一个顶点数据可能会包含多个属性,比如2维坐标和4维的颜色,那么一个顶点数据就有6个维度了。通过顶点着色器,将每个顶点的颜色传递到片段着色器中。
传递颜色时,现在顶点着色器中声明一个输出颜色变量,然后再在片段着色器中声明一个输入颜色变量,这两个颜色变量的类型要一致,变量名也要相同,这样着色器程序就能够默认将这两个变量认为是同一个变量,就可以进行不同着色器之间的通信了。
值得注意的是,在增加了顶点数组中的颜色属性的数据后,在后面创建vbo对象后复制顶点数据时,需要修改复制顶点数据的大小,同时在启用顶点属性指针时,要多启用一个颜色属性的指针(id = 1),同时要在最后修改初始位置指针的偏移量。示意图如下:
代码:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(640, 480, "Rectangle", nullptr, nullptr);
glfwMakeContextCurrent(window);
std::cout << glGetString(GL_VERSION) << std::endl;
glewInit();
unsigned int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
std::vector<float> vertices = {
-0.5f, -0.5f, 1.0f, 0.0f, 0.0f,// 0
0.5f, -0.5f, 0.0f, 1.0f, 0.0f,// 1
0.5f, 0.5f, 0.0f, 0.0f, 1.0f,// 2
-0.5f, 0.5f, 1.0f, 1.0f, 0.0f // 3
};
unsigned int vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*) (2 * sizeof(float))); //颜色指针的初始位置为跳过第一个位置数据的指针,即要往后移2个float大小
std::vector<int> indices = {
0, 1, 2,
2, 3, 0
};
unsigned int ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
const char* vertexShaderSource = "#version 330 core\n"
"layout(location = 0) in vec4 pos;\n"
"layout(location = 1) in vec4 color;\n"
"out vec4 our_color;\n"
"void main()\n"
"{\n"
" gl_Position = pos;\n"
" our_color = color;\n"
"}\0";
unsigned int vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertexShaderSource, nullptr);
glCompileShader(vs);
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"in vec4 our_color;\n"
"void main()\n"
"{\n"
" color = our_color;\n"
"}\0";
unsigned int fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragmentShaderSource, nullptr);
glCompileShader(fs);
unsigned int program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glBindVertexArray(0);
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
while (!glfwWindowShouldClose(window))
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glUseProgram(program);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteProgram(program);
glfwTerminate();
return 0;
}
效果: