Shader开发(十二)用顶点属性添加颜色

在图形编程中,通过顶点属性可以为网格添加额外数据,如颜色,从而实现丰富的视觉效果。本文将引导你为三角形网格的每个顶点指定不同颜色(红、绿、蓝),并通过片元插值在片元着色器中混合这些颜色,最终渲染出彩虹三角形。这将帮助你理解顶点属性的添加和传递过程。


什么是顶点属性?

到目前为止,我们的网格顶点只包含位置信息。但在真实的3D图形应用中,顶点可以携带更多类型的数据:

  • 颜色属性:为每个顶点指定独特的颜色

  • 纹理坐标:用于纹理映射的UV坐标

  • 法向量:用于光照计算的表面法线

  • 自定义数据:任何你需要的额外信息

💡 顶点属性是附加到每个顶点的额外数据,这些数据会在渲染管线中传递给着色器进行处理。

顶点颜色属性的优势:

  • 通过插值自动生成平滑的颜色过渡

  • 比纹理采样更高效的着色方式

  • 对每个顶点的颜色有完全控制权

  • 相比纹理贴图占用更少显存


添加顶点颜色

将信息从 C++ 代码传递到渲染管线的两种方式中,通过网格顶点数据是唯一能逐顶点变化的方法。目前网格仅包含位置数据,但我们可以扩展为每个顶点添加颜色属性。在 openFrameworks 中,使用 addColor() 方法轻松实现。

ofApp.cppsetup() 函数中,添加顶点颜色:

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

  • 变量名必须完全相同,类型也必须匹配


片元插值

运行程序后,你将看到一个彩虹三角形。尽管仅为三个顶点指定了颜色,但屏幕显示多种渐变色。这是因为渲染管线在光栅化阶段自动进行片元插值:根据片元与顶点的距离,混合顶点颜色,实现平滑过渡。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值