在图形编程中,通过顶点属性可以为网格添加额外数据,如颜色,从而实现丰富的视觉效果。本文将引导你为三角形网格的每个顶点指定不同颜色(红、绿、蓝),并通过片元插值在片元着色器中混合这些颜色,最终渲染出彩虹三角形。这将帮助你理解顶点属性的添加和传递过程。
什么是顶点属性?
到目前为止,我们的网格顶点只包含位置信息。但在真实的3D图形应用中,顶点可以携带更多类型的数据:
-
颜色属性:为每个顶点指定独特的颜色
-
纹理坐标:用于纹理映射的UV坐标
-
法向量:用于光照计算的表面法线
-
自定义数据:任何你需要的额外信息
💡 顶点属性是附加到每个顶点的额外数据,这些数据会在渲染管线中传递给着色器进行处理。
顶点颜色属性的优势:
-
通过插值自动生成平滑的颜色过渡
-
比纹理采样更高效的着色方式
-
对每个顶点的颜色有完全控制权
-
相比纹理贴图占用更少显存
添加顶点颜色
将信息从 C++ 代码传递到渲染管线的两种方式中,通过网格顶点数据是唯一能逐顶点变化的方法。目前网格仅包含位置数据,但我们可以扩展为每个顶点添加颜色属性。在 openFrameworks 中,使用 addColor() 方法轻松实现。
在 ofApp.cpp 的 setup() 函数中,添加顶点颜色:
void ofApp::setup(){
// 创建三角形网格
triangle.addVertex(glm::vec3(-1.0, -1.0, 0.0)); // 左下角
triangle.addVertex(glm::vec3( 1.0, -1.0, 0.0)); // 右下角
triangle.addVertex(glm::vec3( 0.0, 1.0, 0.0)); // 顶部
// 为每个顶点添加不同颜色
triangle.addColor(ofFloatColor(1.0, 0.0, 0.0)); // 红色
triangle.addColor(ofFloatColor(0.0, 1.0, 0.0)); // 绿色
triangle.addColor(ofFloatColor(0.0, 0.0, 1.0)); // 蓝色
// 加载着色器
shader.load("vertex_color.vert", "vertex_color.frag");
}
注意:
-
顶点和颜色的添加顺序必须一致
-
第1个顶点对应第1个颜色,第2个顶点对应第2个颜色,以此类推
-
使用
ofFloatColor确保颜色值在0.0-1.0范围内
颜色数据的存储格式
在GPU中,颜色通常以RGBA格式存储:
-
R (Red):红色分量 (0.0 - 1.0)
-
G (Green):绿色分量 (0.0 - 1.0)
-
B (Blue):蓝色分量 (0.0 - 1.0)
-
A (Alpha):透明度分量 (0.0 - 1.0)
更新顶点着色器
网格现在包含多个顶点属性(位置 + 颜色),需在顶点着色器中使用布局限定符(layout qualifier)指定数据顺序,以便正确解析。创建新的顶点着色器 vertex_color.vert:
#version 410
// 布局限定符:指定顶点属性的输入位置
layout(location = 0) in vec3 position; // 位置属性
layout(location = 1) in vec4 color; // 颜色属性
// 输出变量:传递给片元着色器
out vec4 vertex_color; // 将颜色传递给下一阶段
void main()
{
// 变换顶点位置
gl_Position = vec4(position, 1.0);
// 传递颜色数据
vertex_color = color;
}
布局限定符 (Layout Qualifiers)
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
-
作用:明确指定顶点属性在GPU中的存储位置
-
location = 0:位置属性固定在索引0
-
location = 1:颜色属性分配到索引1
-
类型匹配:vec3对应位置(x,y,z),vec4对应颜色(r,g,b,a)
输出变量
out vec4 vertex_color;
-
out关键字:声明输出到下一个着色器阶段的变量
-
命名规范:使用描述性名称,便于在片元着色器中识别
-
数据传递:顶点着色器的输出自动成为片元着色器的输入
更新片元着色器
片元着色器需从顶点着色器接收颜色数据,使用 in 关键字声明匹配的输入变量。创建新的片元着色器 vertex_color.frag:
#version 410
// 输入变量:接收来自顶点着色器的数据
in vec4 vertex_color; // 插值后的颜色
// 输出变量:最终像素颜色
out vec4 output_color;
void main()
{
// 直接使用插值后的颜色
output_color = vertex_color;
}
变量名匹配
-
顶点着色器的
out vec4 vertex_color -
片元着色器的
in vec4 vertex_color -
变量名必须完全相同,类型也必须匹配
片元插值
运行程序后,你将看到一个彩虹三角形。尽管仅为三个顶点指定了颜色,但屏幕显示多种渐变色。这是因为渲染管线在光栅化阶段自动进行片元插值:根据片元与顶点的距离,混合顶点颜色,实现平滑过渡。

953

被折叠的 条评论
为什么被折叠?



