c语言 uniform

99ANYc3cd6
预计阅读时长 13 分钟
位置: 首页 C语言 正文

在标准的 C 语言(C89, C99, C11, C17, C23)中,并没有一个叫做 uniform 的关键字或者内置的数据类型。

c语言 uniform
(图片来源网络,侵删)

uniform 这个词在计算机科学中,尤其是在图形学和游戏开发领域,通常与 “一致变量” (Uniform Variable) 概念紧密相关,这个概念主要出现在 着色器语言 中,OpenGL 的 GLSL、Vulkan 的 GLSL、DirectX 的 HLSL 等。

C 语言可以通过特定的库(主要是图形 API)来间接使用和管理这些 uniform 变量,下面我将分两部分来解释:

  1. uniform 的核心概念是什么? (主要在图形学上下文中)
  2. C 语言如何与 uniform 交互? (通过 OpenGL 等库)

第一部分:uniform 的核心概念

在图形学编程中,我们使用着色器来告诉 GPU 如何渲染一个物体,着色器运行在 GPU 上,它们有自己的执行环境。

uniform 变量是着色器中的一种特殊变量,它的作用是:

c语言 uniform
(图片来源网络,侵删)

从 CPU(你的 C 程序)向 GPU(正在运行的着色器)传递数据。

uniform 的主要特点:

  1. 只读: 着色器程序只能读取 uniform 变量的值,而不能修改它,数据是单向流动的,从 CPU 到 GPU。
  2. 全局作用域: 一个 uniform 变量在单个着色器程序(可以包含顶点着色器和片段着色器)中是全局可见的,顶点着色器和片段着色器可以访问同一个 uniform 变量。
  3. 值在图元间保持一致: 这就是 "uniform"(一致、统一)这个名字的由来,当你绘制一个由多个顶点组成的三角形时,这个三角形的每个顶点在执行顶点着色器时,看到的同一个 uniform 变量的值是完全相同的,它不会像顶点属性(如顶点坐标、颜色)那样在每个顶点上变化。
  4. 用于传递“全局”信息: uniform 变量通常用于传递那些影响整个渲染对象或整个场景的数据,
    • 变换矩阵: 模型、视图、投影矩阵。
    • 颜色: 全局光照颜色、物体颜色。
    • 光源信息: 光源位置、颜色、强度。
    • 时间: 用于实现动画效果的时间值。
    • 采样器: 用于访问纹理的句柄。

一个简单的 GLSL 示例

这是一个 GLSL 片段着色器,它使用了一个 uniform 变量 uColor 来设置所有像素的颜色。

// 片段着色器
#version 330 core
// 声明一个 uniform 变量来接收颜色
// vec4 是一个包含4个浮点数的向量,代表 RGBA
uniform vec4 uColor; 
// 这个函数会为每个被渲染的像素调用一次
out vec4 FragColor;
void main()
{
    // 直接使用从 CPU 传递过来的 uniform 颜色值
    FragColor = uColor; 
}

在这个例子中,uColor 就是一个 uniform,无论这个片段属于哪个像素,只要这个着色器程序在运行,uColor 的值都是固定的,直到 CPU 通过 OpenGL API 更新它。


第二部分:C 语言如何与 uniform 交互

既然 uniform 是着色器语言里的概念,C 语言本身并不能直接定义它,C 语言的角色是 “CPU 端的管理者”,它通过图形 API(如 OpenGL)来获取 uniform 变量的位置,并向其传递数据。

c语言 uniform
(图片来源网络,侵删)

下面是一个使用 C 语言和 OpenGL 库来设置 uniform 变量的典型流程。

步骤 1: 编译并链接着色器程序

你需要在 C 程序中加载并编译你的着色器代码(如上面的 GLSL 代码),然后将它们链接成一个完整的着色器程序,这个过程完成后,GPU 就知道这个程序里有哪些 uniform 变量了。

// 假设 shaderProgram 是已经成功链接好的 OpenGL 着色器程序ID
GLuint shaderProgram = glCreateProgram();
// ... 加载、编译顶点和片段着色器,然后链接 ...

步骤 2: 获取 uniform 变量的位置

在 CPU 端,你需要获取着色器程序中 uniform 变量的“位置”或“索引”,这个位置是一个整数,OpenGL 用它来唯一标识这个 uniform 变量。

使用 glGetUniformLocation 函数:

// 获取名为 "uColor" 的 uniform 变量的位置
GLuint uColorLocation = glGetUniformLocation(shaderProgram, "uColor");
// 检查是否获取成功
if (uColorLocation == -1) {
    printf("Warning: uColor uniform not found or not active!\n");
}

重要提示: 在调用 glGetUniformLocation 之前,必须确保着色器程序已经被激活glUseProgram(shaderProgram)),或者在使用 glGetUniformLocation 之后在使用 uniform 函数之前激活程序。

步骤 3: 向 uniform 变量传递数据

获取到位置后,你就可以使用一系列 glUniform* 函数来向其传递数据,函数名的前缀 glUniform 后面会跟着数据类型和维度的信息。

要向我们的 vec4 uColor 传递数据:

// 假设我们想设置颜色为红色 (1.0, 0.0, 0.0, 1.0)
float redColor[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
// 在渲染循环中,每次绘制前设置 uniform 值
glUseProgram(shaderProgram); // 1. 激活着色器程序
// 2. 使用 glUniform4fv 函数传递数据
// 参数1: uniform 的位置 (uColorLocation)
// 参数2: 要设置的向量的数量 (我们只设置一个)
// 参数3: 指向颜色数据的指针
glUniform4fv(uColorLocation, 1, redColor); 

其他常用的 glUniform* 函数:

函数 用途 示例
glUniform1i(location, v0) 设置一个整型或采样器 glUniform1i(uTextureLocation, 0); (绑定到纹理单元 0)
glUniform1f(location, v0) 设置一个浮点数 glUniform1f(uTimeLocation, currentTime);
glUniform2f(location, v0, v1) 设置一个包含2个浮点数的向量 glUniform2f(uResolutionLocation, screenWidth, screenHeight);
glUniformMatrix4fv(...) 设置一个 4x4 矩阵 glUniformMatrix4fv(uMVPMatrixLocation, 1, GL_FALSE, &matrix[0][0]);

  1. C 语言没有 uniform 关键字uniform 是着色器语言(如 GLSL)中的概念,不是标准 C 的一部分。
  2. uniform 的作用:是 CPU 向 GPU 着色器传递只读全局一致数据的一种机制。
  3. C 语言的交互方式:C 程序通过图形 API(如 OpenGL)来管理 uniform
    • glGetUniformLocation: 获取 uniform 在着色器程序中的位置。
    • glUseProgram: 激活包含 uniform 的着色器程序。
    • glUniform* 系列函数:根据 uniform 的数据类型(如 int, float, vec2, mat4)向其传递数据。

当你在 C 语言中听到或看到 "uniform" 时,可以立刻联想到它是在通过一个图形库(如 OpenGL)来与 GPU 着色器进行通信。

-- 展开阅读全文 --
头像
C语言如何高效实现compute计算功能?
« 上一篇 04-22
dede图片上传失败怎么办?
下一篇 » 04-22

相关文章

取消
微信二维码
支付宝二维码

目录[+]