OpenGL学习笔记3——三角形的绘制2 顶点颜色

OpenGL学习笔记3——三角形的绘制2 顶点颜色

  • 1 闪烁的三角形
    • 1.1 Uniforms
  • 2 五彩斑斓的三角形
    • 2.1 修改顶点的颜色
    • 2.2 闪耀的彩色

上次已经画出了三角形,然后在LearnOpenGL最底下还有几个练习和附加内容。这次来把这些东西做一做,加深一下理解。

1 闪烁的三角形

在这里的例子中,后面做了一个颜色会闪烁的三角形,根据他的思路在原来三角形的基础上做一遍。本质就是修改片元着色器,修改所有顶点的颜色。

1.1 Uniforms

Uniforms是一种将数据传输到着色器的方式,本质上是全局变量,所有顶点的数据都是一样的。
将我们片元着色器的改成如下。

const char* fragment_shader_source =
"#version 330 core						  \n"
"uniform vec3 triangleColor;		   	  \n"
"out vec4 FragColor;					  \n"
"void main(){							  \n"
"	FragColor = vec4(triangleColor, 1.0f);\n"
"}									      \n";

就是添加了一个三维向量triangleColor,然后用它代替我们之前写死的RGB三个分量。
然后去到我们渲染循环里面,通过以下代码获取则个triangleColor的位置。

GLint uniColor = glGetUniformLocation(shaderProgram, "triangleColor");

然后通过glUniform3f来修改三个float类型的参数。

glUniform3f(uniColor, 1.0f, 0.0f, 0.0f); // 这样子就是一个红色的

怎么实现闪烁呢?例子中是通过sin计算时间来修改R的值,并且用了一些方法计算时间,但是我发现其实GLFW提供了获取时间的方法。所以就可以把刚才的代码改成如下。

glUniform3f(uniColor, (sin(glfwGetTime() * 10.0f) + 1.0f) / 2.0f, 0, 0);

为什么要时间×10,sin结果再+1再÷2呢?时间×10是修改闪烁的时间,学过三角函数都知道这样会加大频率。然后sin算出来的数值在1到-1之间,然而这里的RGB的值是取值从0到1的,所以就通过加以之后再除以二来映射到0到1之间。运行效果如图(两边的黑白是录频分辨率比窗口分辨率大的问题)。
OpenGL学习笔记3——三角形的绘制2 顶点颜色_第1张图片
我们可以再次的修改,把RGB都改了,乘上不同的速度,效果如下(RGB!)。

		glUniform3f(uniColor, 
			(sin(glfwGetTime() * 0.8f) + 1.0f) / 2.0f,
			(sin(glfwGetTime() * 1.35f) + 1.0f) / 2.0f,
			(sin(glfwGetTime() * 2.0f) + 1.0f) / 2.0f);


(压缩GIF的时候比例有点变了)

2 五彩斑斓的三角形

2.1 修改顶点的颜色

刚才的方法是直接修改了顶点的颜色,但是那样对于所有顶点都是一样的。现在让我们来换一种方法,给顶点加上颜色吧!
我们在顶点中除了位置信息再添加颜色的RGB。

	float vertices[] = {
	-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 前三个是xyz后三个是rgb
	 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
	 0.0f,  0.5f, 0.0f, 0.0f, 0.0f, 1.0f
	};

既然我们在顶点数组中增加了rgb信息,那么我们就要修改VAO中的属性指针的内容,让他理解我们顶点数组中数据的信息。我们再把1属性作为颜色,把偏移量等参数都调一下。

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

小插曲开始
上面是按之前绘制三角形的方法写的,看了看例子里面的代码,发现了一个新写法,如下。

	GLint posAttrib = glGetAttribLocation(shaderProgram, "aPos");
	glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(posAttrib);
	···

直接获取对应变量的位置,通过这个位置来修改属性指针。然后着色器里面这样写就可以了,去掉location。

//layout(location = 0) in vec3 aPos;						 
in vec3 aPos;						 

小插曲结束


然后回到正题。shader源码也要做相应的修改,在顶点着色其中增加在1位置中获取颜色,也是一个vec3变量。然后增加一个输出,然后直接把颜色输出作为下一个着色器的输入。片元着色器把输入的颜色设置为顶点的颜色。

// 顶点着色器源码
const char* vertex_shader_source =
"#version 330 core					 \n"
"layout(location = 0) in vec3 aPos;	 \n"
"layout(location = 1) in vec3 aColor;\n"
"out vec3 Color;					 \n"
"void main(){						 \n"
"	gl_Position = vec4(aPos, 1.0);	 \n"
"	Color = aColor;					 \n"
"}									 \n";

//片元(片段)着色器源码
const char* fragment_shader_source =
"#version 330 core				  \n"
"in vec3 Color;					  \n"
"out vec4 FragColor;			  \n"
"void main(){					  \n"
"	FragColor = vec4(Color, 1.0f);\n"
"}								  \n";

要注意的就是,片元着色器中的in vec3 Color是对应顶点着色器中的out vec3 Color。一开始我编译出错了,就是忘记在顶点着色其中设置输出是Color。
然后我们的结果就是如下啦,渐变的三角形(三个顶点的颜色分别是红绿蓝,顶点之间的颜色OpenGL会自动的帮我们插值运算)。
OpenGL学习笔记3——三角形的绘制2 顶点颜色_第2张图片

2.2 闪耀的彩色

让我们来结合前面颜色的闪烁做一个闪烁的五彩斑斓的三角形吧。
同样是修改片元着色器,上面那一次是直接在外面算好rgb颜色然后传进来的,这次就不了。直接在shader中计算sin。

const char* fragment_shader_source =
"#version 330 core				  \n"
"uniform float time;			  \n"
"in vec3 Color;					  \n"
"out vec4 FragColor;			  \n"
"void main(){					  \n"
"	FragColor = vec4(Color.x * (sin(time) + 1)/2,Color.y * (sin(time) + 1)/2,Color.z * (sin(time) + 1)/2, 1.0f);\n"
"}								  \n";

我本以为glsl有自带time(或许是我的操作不对?),然而没有,那就用一个uniform在外头传一个吧。同样的操作。

/*传入时间*/
		GLint timer = glGetUniformLocation(shaderProgram, "time");
		glUniform1f(timer, glfwGetTime() * 2);

然后试了下发现把背景改为黑色更好看。

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

然后这是结果啦。

也可把再把变换颜色的函数改改,让他更有意思一些。

FragColor = vec4((sin(time*0.5 + Color.x) + 1)/2,(sin(time*1.5+Color.y * 2) + 1)/2,(sin(time*1.23+Color.z * 2.5) + 1)/2, 1.0f);


(有点像我的手机壁纸噢…。本来还想再做几个练习的,但是这次的内容也不少了,就放到下次吧。)

你可能感兴趣的:(#,OpenGL)