OpenGL 着色器语言特性

一、GLSL 内置变量(Built-in Variables)

GLSL 提供以 gl_ 前缀的预定义内置变量,作为 Shader 中数据交互的额外方式。

1.1 顶点着色器内置变量

变量 类型 作用
gl_Position vec4 输出裁剪空间顶点位置(必设)
gl_PointSize float 设置点的大小(像素),用于 GL_POINTS 图元
gl_VertexID int 当前顶点 ID(只读)

关键代码示例:

glsl 复制代码
void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);    
    gl_PointSize = gl_Position.z;  // 距离越远,点越大
}

使用前需启用:glEnable(GL_PROGRAM_POINT_SIZE);

1.2 片元着色器内置变量

变量 类型 作用
gl_FragCoord vec3 片元窗口坐标 (x, y) + 深度值 (z)
gl_FrontFacing bool 判断片元是否面向观察者
gl_FragDepth float 输出变量,可手动修改深度值
gl_PointCoord vec2 点图元的局部坐标

gl_FragCoord 示例:

glsl 复制代码
void main()
{             
    if(gl_FragCoord.x < 400)
        FragColor = vec4(1.0, 0.0, 0.0, 1.0);  // 红色 - 左侧
    else
        FragColor = vec4(0.0, 1.0, 0.0, 1.0);         // 绿色 - 右侧        
}

gl_FrontFacing 应用:内外纹理切换

glsl 复制代码
void main()
{
    if(gl_FrontFacing)
        FragColor = vec4(1.0, 0.0, 0.0, 1.0);  // 正面用红色
    else
        FragColor = vec4(0.0, 1.0, 0.0, 1.0);  // 背面用绿色
}

二、接口块(Interface Blocks)

用于组织着色器间的输入输出数据,使代码更清晰。

2.1 基本语法

glsl 复制代码
#version 330 core

// 输出到下一个着色器
out VS_OUT
{
    vec3 textCoord;
} vs_out;

// 输入来自上一个着色器
in VS_OUT
{
    vec3 textCoord;
} fs_in;

void main()
{
    vs_out.textCoord = aTexCoord;
    // ...
}

2.2 与 Uniform 对比

  • 普通 Uniformin float someValue;
  • 接口块in BlockName { type varName; } instanceName;

接口块更易管理大量相关数据,适合传递变换矩阵、材质属性等结构化数据。


三、统一缓冲区对象(UBO - Uniform Buffer Objects)

3.1 为什么需要 UBO?

传统方式每个 shader 都要单独绑定 Uniform,UBO 允许:

  • 一次绑定,多个 Shader 共享
  • 高效更新:减少 CPU-GPU 数据传输
  • 符合标准布局:便于多项目复用

3.2 定义与使用

1. C++ 端定义 Uniform 块:

cpp 复制代码
// 定义 Uniform 块结构
#version 330 core
layout(std140) uniform MatrixBlock
{
    mat4 projection;
    mat4 view;
    mat4 model;
};

2. GLSL 访问:

glsl 复制代码
uniform MatrixBlock matrices;

void main()
{
    gl_Position = matrices.projection * matrices.view * matrices.model * vec4(aPos, 1.0);
}

3. C++ 端创建与绑定:

cpp 复制代码
unsigned int uboExample;
glGenBuffers(1, &uboExample);
glBindBuffer(GL_UNIFORM_BUFFER, uboExample);
glBufferData(GL_UNIFORM_BUFFER, sizeof(matrices), &matrices, GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboExample);  // 绑定到索引 0

3.3 布局限定符

限定符 说明
shared 不同程序共享,需手动设置 offset
packed 运行时优化,需查询 offset
std140 最常用,显式定义内存布局
std430 更紧凑的布局(不常用)

四、实用技巧

4.1 gl_PointCoord 制作点精灵

glsl 复制代码
void main()
{
    vec2 uv = gl_PointCoord;  // 0.0 ~ 1.0
    if(length(uv - vec2(0.5)) > 0.5)
        discard;  // 裁剪圆形外的像素
    FragColor = texture(spriteTexture, uv);
}

4.2 gl_FragDepth 性能注意

使用 gl_FragDepth禁用 Early-Z 测试,可能影响渲染性能,仅在必要时使用。


五、要点总结

类别 要点
内置变量 顶点用 gl_Position/PoinSize/VertexID,片元用 gl_FragCoord/FrontFacing/FragDepth
接口块 in/out BlockName {} instance 组织输入输出
UBO glBindBufferBase + layout(std140) 实现高效 Uniform 管理
相关推荐
GISer_Jing3 天前
Three.js着色器编译机制深度解析
javascript·webgl·着色器
threelab9 天前
Three.js 加载 3D Tiles 瓦片数据 | 三维可视化 / AI 提示词
开发语言·前端·javascript·人工智能·3d·着色器
threelab9 天前
Three.js 黑洞引力效果着色器 | 三维可视化 / AI 提示词
开发语言·javascript·着色器
threelab10 天前
Three.js 抽象艺术着色器效果 | 三维可视化 / AI 提示词
前端·javascript·人工智能·3d·着色器
♡すぎ♡10 天前
ShaderLab:PBR+IBL(ShaderToy Translation)
算法·计算机图形学·着色器·pbr·ibl
threelab11 天前
Three.js 3D 地图可视化 | 三维可视化 / AI 提示词
前端·javascript·人工智能·3d·着色器
♡すぎ♡12 天前
现代实时渲染管线
计算机图形学·opengl·着色器·渲染管线
threelab12 天前
Three.js 数学函数着色器 | 三维可视化 / AI 提示词
javascript·人工智能·着色器
threelab13 天前
Three.js 3D 热力图效果 | 三维可视化 / AI 提示词
开发语言·前端·javascript·人工智能·3d·着色器
XX風13 天前
OpenGL中 为什么RBO 不能被着色器采样?
着色器