根据上面的代码基本不变:
将verterShaderSource与fragmentShaderSource改为下面的形式。
const char* vertexShaderSource =
"#version 330 core \n"
"out vec4 vertexColor; \n"//out 就是提示要传出参数
"layout(location = 0) in vec3 aPos; \n"
"void main(){ gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
" vertexColor=vec4(1.0f,1.0f,0,0.5f);}\n";
const char* fragmentShaderSource =
"#version 330 core \n"
"out vec4 FragColor; \n"
"in vec4 vertexColor;\n"//in 就是获取前面的参数
"void main() \n"
"{FragColor = vertexColor;} \n";
如果你认真一些的话,你可以看出其实就修改了
“out vec4 vertexColor;“这是在提示我们要传出一个参数vertexColor,
" vertexColor=vec4(1.0f,1.0f,0,0.5f);"这是对我们要传出去的参数vertexColor进行颜色的控制
"in vec4 vertexColor;"获取到前面顶点shader传出的vertexColor参数
“FragColor = vertexColor;”这是赋值,这个逻辑就不用我说了吧!。
然后其中vertexShader需要传出的就是一个位置的四维向量,而gl_Position就是vertexShader默认传出的位置参数,所以不用声明。
而FragColor则不是,所以一开始会宣告fragmentShader要输出一个FrageColor,也就是这句代码
“out vec4 FragColor;”.
当你将代码修改成这样,你就能够得到一个黄色的图像了。
傅老师神笔镇楼:
下面接着做一个随时间渐变的shader吧!
虽然教程里面是绿色,但是作为一名新时代男同胞,对于绿色这种让人不爽的颜色,我表示拒绝,我还是喜欢大红大紫一些。
在此之前记录一点shader的基本知识。首先shader编程语言是针对于GPU编程的,而我们平时用的c++这些是针对的CPU,shader也就是一个GPU小程序。而GPU是没有记录时间的功能的,所以我们就需要借助CPU来帮我们完成记时的功能。于是就有了uniform这个关键字,这就是输入的由CPU控制的变量。
先是shader上的修改:
const char* fragmentShaderSource =
"#version 330 core \n"
"out vec4 FragColor; \n"
"uniform vec4 ourColor;\n"//声明一下这个uniform向量
"void main() \n"
"{FragColor = ourColor;} \n";//赋值操作
然后代码:
while (!glfwWindowShouldClose(window))
{ // 检查事件,调用相应的回调函数,如下文的glfwInput函数
glfwInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
float timeValue = glfwGetTime();//获取CPU的时间
float RedValue = (sin(timeValue)) / 2.0f + 0.5f;//进行一个数值处理,将RedValue的值限定在0到1之间
int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");//获取到本地的uniform
glUseProgram(shaderProgram);//使用本地的材质球,也就是这个渲染程序
glUniform4f(vertexColorLocation, RedValue, 0, 0, 0.5f);//设置颜色,第一个参数是uniform的位置,后面就是color参数
glBindVertexArray(VAO);//每次循环都调用,绑定函数绑定VAO
..........
..........
..........
glfwSwapBuffers(window);
glfwPollEvents();
}
由于篇幅原因,只写了循环以内的,还省略了一些。
讲解一些那里的数值处理问题“float RedValue = (sin(timeValue)) / 2.0f + 0.5f”,这里是先通过sin将数值限定在-1到1之间,然后除以2,就限定到了-0.5到0.5之间,然后在加个0.5,也就到了0到1之间。
放三张效果图:
然后接下来就是五彩斑斓的梯形了
shader与数组的修改如下:
const char* vertexShaderSource =
"#version 330 core \n"
"out vec4 vertexColor; \n"//out 就是提示要传出参数
"layout(location = 3) in vec3 aPos; \n"
"layout(location = 4) in vec3 aCol; \n"
"void main(){ gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
" vertexColor=vec4(aCol,1.0f);}\n";
const char* fragmentShaderSource =
"#version 330 core \n"
"out vec4 FragColor; \n"
"in vec4 vertexColor;\n"//in 就是获取前面的参数
"void main() \n"
"{FragColor = vertexColor;} \n";
float vertices[] = {
-0.5f, -0.5f, 0.0f,1.0f,0,0,//后三个是颜色参数
0.5f, -0.5f, 0.0f,0,1.0f,0,
0.0f, 0.5f, 0.0f,0,0,1.0f,
0.5f, 0.5f, 0.0f,1.0f,1,0,
1.0f, -0.5f, 0, 0,1,1
};
GLuint indices[] = { 0,1,2,1,2,3,1,3,4 };
代码中只要修改一下这个就可以了。
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);//从vao里面在3号索引位起始位上拿取三个值,一次性跳过的是6个值
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 6* sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));//从vao里面在4号索引位上的往右偏三个值后再拿取三个值
glEnableVertexAttribArray(3);//启用属性3,因为默认是禁用的
glEnableVertexAttribArray(4);//启用属性4,因为默认是禁用的
这是解释图,就是说我们拿前面三个做位置向量,后面三个做颜色向量。因此位置向量从第一个开始索引位算起的,然后颜色向量则是要偏三个数,而一个节点是6个float的大小。
上图,五彩斑斓的梯形!好丑!