绘制三个顶点颜色不同的三角形
//#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
#include <iostream>
const GLuint WIDTH = 800, HEIGHT = 600;
#define ARR_LEN 512
const GLchar * vShaderSource = "#version 330 core\n"
"layout(location = 0) in vec3 position;\n"
"layout(location = 1) in vec3 testColor;\n"
"out vec4 ourColor;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"ourColor = vec4(testColor.r, testColor.g, testColor.b, 1.0);\n"
"}\0";
//定义location=0的变量position 用来确定三角形顶点的位置
//定义location=1的变量testColor用来确定三角形顶点的颜色
//用户自己写的程序向顶点着色器传参时 是通过location标识来确定变量
const GLchar* fShaderSource = "#version 330 core\n"
"in vec4 ourColor;\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = ourColor;\n"
"}\n\0";
//ourColor接收顶点着色器传递过来的颜色参数
void key_callback(GLFWwindow *window, int key, int scancode, int action, int mode);
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//使用opengl核心模式(实时渲染)
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "first opengl test", nullptr, nullptr);
//创建window
if (!window)
{
std::cout<<"failed to create window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
//设置当前工作窗口
glfwSetKeyCallback(window, key_callback);
//设置监听键盘时间
glewExperimental = true;
//采用核心模式 在glewInit(0调用之前 必须将glewExperimental 置为true
auto err = glewInit();
if (err!=GLEW_OK)
{
auto str=glewGetErrorString(err);
std::cout << "failed to init glew" << std::endl;
return -1;
}
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
//编译顶点着色器
GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vShader, 1, &vShaderSource, nullptr);
glCompileShader(vShader);
//监测编译是否有错误
GLint success;
GLchar infoLog[ARR_LEN];
glGetShaderiv(vShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vShader, ARR_LEN, nullptr, infoLog);
std::cout << "error::shader::vertex::compilation_failed" << infoLog << std::endl;
}
//编译片段着色器
GLuint64 fShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fShader, 1, &fShaderSource, nullptr);
glCompileShader(fShader);
//监测编译是否有错误
glGetShaderiv(fShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vShader, ARR_LEN, nullptr, infoLog);
std::cout << "error::shader::fragment::compilation_failed" << infoLog << std::endl;
}
//创建shaderprogram
GLuint shaderProgram = glCreateProgram();
//将shader与shaderprogram链接
glAttachShader(shaderProgram, vShader);
glAttachShader(shaderProgram, fShader);
//link shaderprogram
glLinkProgram(shaderProgram);
//监测链接是否有错误
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderProgram, ARR_LEN, nullptr, infoLog);
std::cout << "link error :" << infoLog << std::endl;
}
glDeleteShader(vShader);//
glDeleteShader(fShader);//着色器 对象链接到程序对象后 删除着色器
//定义 绘制三角形需要的数据
GLfloat arr[] = {
//position //color
0.f, 0.5f, 0.0f, 1.0f,0.0f,0.0f,
0.5f, -0.5f, 0.0f, 0.0f,1.0f,0.0f,
-0.5f, -0.5f, 0.0f, 0.0f,0.0f,1.0f
};
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(arr), arr, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)0);
//将数组中的每组数据的前三个数据 传到顶点着色器中location为0变量(即此例的position)
//由于是前三个数据 位置数据在缓冲中的起始位置偏移量为0
glEnableVertexAttribArray(0);
//将 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)0) 绑定
//数据设置为激活状态 待opengl绘制时使用
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)(3*sizeof(GLfloat)));
//将数组中的每组数据的后三个数据 传到顶点着色器中location为1变量(即此例的testColor)
//由于起始数据前面有三个数据 因此位置数据在缓冲中的起始位置偏移量为(GLvoid *)(3*sizeof(GLfloat))
glEnableVertexAttribArray(1);
/将 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)(3*sizeof(GLfloat)));
/绑定数据设置成激活状态 待opengl绘制时使用
glBindBuffer(GL_ARRAY_BUFFER, 0);
//解绑vbo
glBindVertexArray(0);
//解绑vao
//设置模式
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
//render
//clear the colorbuffer
glClearColor(0.0, 0, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
//绑定vao
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
//swap the sreen buffers
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &VAO);
//删除vao
glDeleteBuffers(1, &VBO);
//删除vbo
glfwTerminate();
return 0;
}
void key_callback(GLFWwindow *window, int key, int scancode, int action, int mode)
{
if (key==GLFW_KEY_ESCAPE&&action==GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
效果图: