杰瑞科技汇

CG教程,可编程实时权威指南如何入门?

由于这本书是英文原版,且年代稍早,我会为您提供一个结合了该书核心思想与现代实践的、系统化的 CG 教程和学习路径,这不仅仅是一本“书”的解读,更是一份从零到一的实战指南。

CG教程,可编程实时权威指南如何入门?-图1
(图片来源网络,侵删)

CG 教程:可编程实时渲染权威指南(实战版)

这份指南将分为以下几个部分:

  1. 核心思想:从固定功能到可编程管线
  2. 图形渲染管线:你的“Hello World”在哪里?
  3. 着色器语言:GLSL vs. HLSL
  4. 第一块积木:顶点着色器
  5. 魔法发生的地方:片元着色器
  6. 现代渲染进阶:从 Shader Model 5 到现代 API
  7. 学习资源与实战项目推荐

核心思想:从固定功能到可编程管线

在学习代码之前,必须理解这个根本性的转变。

  • 固定功能管线:在早期(如 DirectX 7/8),GPU 内部有固定的处理流程,你告诉 GPU “用这个光源”、“用这个纹理”、“开启这个混合模式”,GPU 就会按照预设的公式去执行,这就像一个只能做特定菜品的厨师,你点菜,他照着菜谱做。

  • 可编程管线:从 DirectX 9 / OpenGL 2.0 开始,程序员可以直接编写小程序(即 着色器 - Shader)上传到 GPU,让 GPU 在特定阶段执行这些自定义程序,这就像给了厨师一个完整的厨房和菜谱,你可以让他用任意食材、任意方法创造全新的菜品。

    CG教程,可编程实时权威指南如何入门?-图2
    (图片来源网络,侵删)

着色器就是运行在 GPU 上的小程序,它们是可编程管线的灵魂。


图形渲染管线:你的“Hello World”在哪里?

想象一下,你如何告诉 GPU 画一个彩色的三角形?这个过程就是渲染管线,虽然现代管线非常复杂,但其核心阶段与《可编程实时权威指南》中描述的概念一脉相承。

一个简化的可编程管线流程如下:

  1. 应用阶段:你的游戏主程序在 CPU 上运行,它负责准备数据:顶点坐标、颜色、纹理坐标、模型变换矩阵等,然后将这些数据发送给 GPU。
  2. 几何阶段
    • 输入装配:GPU 收集 CPU 发来的顶点数据。
    • 顶点着色器(可编程) 对每个顶点执行一次,它的主要工作是:
      • 坐标变换:将顶点从模型空间 -> 世界空间 -> 观察空间 -> 裁剪空间,这是“画在哪里”的关键。
      • 计算其他属性:如法线、光照等。
    • 曲面细分 & 几何着色器:(可选,更高级)用于增加模型细节或动态生成几何体。
    • 裁剪 & 光栅化:将屏幕外的顶点裁剪掉,然后将三角形“像素化”,确定哪些像素被这个三角形覆盖,并为每个像素生成一个片元
  3. 光栅化阶段
    • 片元着色器(可编程) 对每个片元执行一次,它的主要工作是:
      • 纹理采样:根据片元的纹理坐标,从纹理图像中获取颜色。
      • 光照计算:根据光源和法线计算最终颜色。
      • 颜色输出:输出该片元的最终颜色值。
  4. 输出合并阶段:将片元着色器输出的颜色与屏幕上已有的颜色进行混合、深度测试等,最终写入帧缓冲区,显示在屏幕上。

你的第一个“Hello World”程序,就是编写一个最简单的顶点着色器,把一个三角形的三个顶点画在屏幕上。

CG教程,可编程实时权威指南如何入门?-图3
(图片来源网络,侵删)

着色器语言:GLSL vs. HLSL

《可编程实时权威指南》主要基于 HLSL (High-Level Shading Language),它是 DirectX 的一部分,而在跨平台领域,GLSL (OpenGL Shading Language) 是标准。

  • HLSL:主要用于 Windows 平台的 DirectX 应用,语法上与 C/C++/C# 更相似。
  • GLSL:主要用于跨平台的 OpenGL/Vulkan/Metal 应用,语法上更像 C,但有一些独特的特性。

核心概念几乎完全相同:变量、数据类型(vec3, mat4)、函数、in/outuniformattribute/varying(旧版GLSL)等。

现代选择

  • Vulkan / Metal:使用一种名为 SPIR-V 的中间语言,可以由 HLSL 或 GLSL 编译而来,这提供了更好的跨平台兼容性。
  • OpenGL:继续使用 GLSL。
  • DirectX 12:继续使用 HLSL。

建议:初学者可以先选择一种深入学习,GLSL(配合 OpenGL),因为它在学术和跨平台领域应用更广,理解一种后,另一种的语法转换非常容易。


第一块积木:顶点着色器

顶点着色器是处理单个顶点的“工人”,它的基本任务是位置变换

一个最简单的 GLSL 顶点着色器示例:

// 声明从应用阶段传入的变量
// 'layout' 指定了顶点属性的位置索引
layout (location = 0) in vec3 aPos; // aPos = 顶点位置
// 声明传递给片元着色器的变量(可选)
// out vec3 ourColor;
// 声明全局的、所有顶点共享的变量(如变换矩阵)
uniform mat4 model;      // 模型矩阵
uniform mat4 view;       // 观察矩阵
uniform mat4 projection; // 投影矩阵
void main()
{
    // 核心计算:将顶点位置从模型空间转换到裁剪空间
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    // 如果需要,可以传递其他数据给片元着色器
    // ourColor = aColor; 
}

关键点

  • in / in vec3 aPos:输入变量,代表顶点的某个属性(位置、颜色等)。
  • uniform:全局常量,对于所有顶点都是相同的,如矩阵、时间、光源位置。
  • gl_Position:一个内置的输出变量,必须被赋值,它代表顶点在裁剪空间中的最终位置。
  • 矩阵乘法顺序projection * view * model * vertex,记住矩阵乘法不满足交换律,顺序至关重要。

魔法发生的地方:片元着色器

片元着色器决定屏幕上每个像素最终呈现什么颜色,它是实现光照、纹理、后期效果的核心。

一个简单的 GLSL 片元着色器示例(带颜色):

// 从顶点着色器接收的数据(需要和 VS 中的 'out' 变量名和类型匹配)
// in vec3 ourColor;
// 声明一个纹理采样器
uniform sampler2D ourTexture;
// 输出变量,最终的颜色值
out vec4 FragColor;
void main()
{
    // 方式1:使用从顶点着色器插值得到的颜色
    // FragColor = vec4(ourColor, 1.0);
    // 方式2:从纹理中采样颜色(更常见)
    FragColor = texture(ourTexture, vec2(0.5, 0.5)); // 采样纹理的中心点
}

进阶:Phong 光照模型(经典示例)

这是《可编程实时权威指南》中的核心内容之一,片元着色器需要计算环境光、漫反射和镜面反射。

in vec3 FragPos;  // 从顶点着色器传递过来的片元位置(世界坐标)
in vec3 Normal;   // 从顶点着色器传递过来的片元法线
uniform vec3 lightPos;   // 光源位置
uniform vec3 viewPos;    // 观察者位置(摄像机)
uniform vec3 lightColor; // 光源颜色
out vec4 FragColor;
void main()
{
    // 1. 环境光
    float ambientStrength = 0.1;
    vec3 ambient = ambientStrength * lightColor;
    // 2. 漫反射
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;
    // 3. 镜面反射
    float specularStrength = 0.5;
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); // 32是高光系数
    vec3 specular = specularStrength * spec * lightColor;
    // 组合所有光照
    vec3 result = (ambient + diffuse + specular) * vec4(1.0, 1.0, 1.0, 1.0).xyz; // 假设物体是白色的
    FragColor = vec4(result, 1.0);
}

现代渲染进阶:从 Shader Model 5 到现代 API

《可编程实时权威指南》的时代是 DirectX 9/10/11,现在我们已经进入了 DirectX 12, Vulkan, Metal 的时代。

  • 可编程管线对象:现代 API(如 DX12, Vulkan)要求你显式地创建和绑定整个管线的状态,包括所有着色器、混合状态、光栅化状态等,这比旧的“设置一个着色器”更底层、更强大,也更复杂。
  • GPU Driven Rendering:一种新的渲染范式,利用计算着色器来高效地驱动渲染流程,例如进行大规模的可见性剔除、动态批处理等。
  • 物理渲染:基于物理的材质和工作流,着色器需要更精确地模拟光线与材质的交互(微表面模型)。
  • Ray Tracing(光线追踪):通过硬件加速光线追踪,着色器可以编写“光线着色器”,实现全局光照、反射、折射等过去难以实现的效果。

不变的核心:无论 API 如何变化,顶点着色器负责位置变换,片元着色器负责颜色计算这一核心逻辑从未改变,理解了基础,才能驾驭现代的复杂技术。


学习资源与实战项目推荐

  1. 书籍(理论基石)

    • 《Programming Vertex, Geometry, and Pixel Shaders》:必读,深入理解管线和着色器编程。
    • 《Real-Time Rendering, 4th Edition》:实时渲染的“百科全书”,涵盖了从管线到光照、到现代技术的方方面面。
    • 《OpenGL SuperBible》:学习 OpenGL 和 GLSL 的绝佳入门书籍。
  2. 在线教程(动手实践)

    • LearnOpenGL (CN)强烈推荐! 从零开始,使用现代 OpenGL(3.3+)和 GLSL,讲解清晰,代码完整,覆盖了所有基础和进阶主题,它的结构几乎就是一份完美的实战教程。
    • Bilibili / YouTube:搜索“OpenGL教程”、“Shader Toy教程”、“HLSL教程”,有大量优秀的视频课程。The ChernoSebastian LagueJohnnysson 等博主的视频质量非常高。
  3. 工具与社区

    • Shader Toy:一个在线的 GLSL 片元着色器“游乐场”,你可以看到别人的炫酷效果,并学习他们的代码,是学习视觉特效的绝佳平台。
    • RenderHub:提供大量高质量的 3D 模型和材质,方便你专注于编写着色器。
    • GitHub:寻找开源的图形学项目,阅读源码是提升最快的方式之一。
  4. 实战项目路径

    • 项目 1:渲染一个彩色三角形:学习设置 OpenGL 上下文,编译和链接着色器,传递顶点数据。
    • 项目 2:加载并显示一个纹理:学习纹理坐标和纹理采样。
    • 项目 3:实现 Phong 光照模型:将上面提到的 Phong 着色器代码应用到你的模型上。
    • 项目 4:实现一个简单的后处理效果:如灰度、反色、模糊等,这需要你将渲染结果作为纹理再次输入。
    • 项目 5:学习并使用 PBR:尝试实现一个基于物理的渲染材质。
    • 项目 6(终极挑战):实现一个简单的延迟渲染器:这是现代游戏引擎普遍使用的技术,能让你深入理解 G-Buffer 和光照计算。

学习 CG 和可编程实时渲染是一个理论与实践紧密结合的过程,以《可编程实时权威指南》的思想为骨架,以现代教程(如 LearnOpenGL)为血肉,通过不断动手实践,才能真正掌握这门强大的技术,祝你学习顺利!

分享:
扫描分享到社交APP
上一篇
下一篇