OpenGL学习笔记3——三角形的绘制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之间。运行效果如图(两边的黑白是录频分辨率比窗口分辨率大的问题)。
在这里插入图片描述
我们可以再次的修改,把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会自动的帮我们插值运算)。
在这里插入图片描述

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);

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

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenGL 中设置颜色有多种方法,以下是其中两种: 1. 使用 glColor* 函数设置当前颜色 glColor* 函数可以设置当前的颜色,从而在绘制图形时使用该颜色。* 可以是以下任意一种:3f、4f、3fv、4fv、3d、4d、3dv、4dv。例如,glColor3f(1.0f, 0.0f, 0.0f) 可以设置当前颜色为红色。 示例代码: ```c++ glColor3f(1.0f, 0.0f, 0.0f); // 设置当前颜色为红色 glBegin(GL_TRIANGLES); glVertex3f(-0.5f, -0.5f, 0.0f); glVertex3f(0.5f, -0.5f, 0.0f); glVertex3f(0.0f, 0.5f, 0.0f); glEnd(); ``` 2. 在顶点数据中指定颜色 可以在顶点数据中指定每个顶点颜色,然后在绘制图形时使用这些颜色。在这种情况下,需要使用 glVertex* 和 glColor* 函数分别指定顶点的位置和颜色。 示例代码: ```c++ GLfloat vertices[] = { -0.5f, -0.5f, 0.0f, // 左下角顶点 1.0f, 0.0f, 0.0f, // 红色 0.5f, -0.5f, 0.0f, // 右下角顶点 0.0f, 1.0f, 0.0f, // 绿色 0.0f, 0.5f, 0.0f, // 中间顶点 0.0f, 0.0f, 1.0f // 蓝色 }; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), vertices); glColorPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), vertices + 3); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); ``` 这里使用了 glVertexPointer 和 glColorPointer 函数来指定顶点的位置和颜色。在绘制时,使用 glDrawArrays 函数来绘制三角形。注意,需要使用 glEnableClientState 和 glDisableClientState 函数来启用和禁用顶点数组。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值