UnityShader常见术语
OpenGL 和 DirectX
OpenGL 和 DirectX 都是计算机图形和游戏开发中常用的图形渲染接口(API),它们提供了一组工具和规范,允许开发者控制硬件来创建图形和处理多媒体内容。虽然它们的核心功能相似,但它们有不同的历史背景、平台支持和设计哲学。
1. OpenGL(Open Graphics Library)
概述
- 开放标准:OpenGL 是一个跨平台的图形渲染 API,最初由硅图形(SGI)公司于 1992 年开发,现在由非盈利组织 Khronos Group 维护。它是一个开放标准,意味着任何公司或开发者都可以免费使用和实现它。
- 跨平台支持:OpenGL 主要支持跨平台操作系统,如 Windows、Linux、macOS(虽然 Apple 现在推崇 Metal)以及一些移动平台(通过 OpenGL ES)。
- 灵活性:OpenGL 是一个比较低层次的 API,提供了大量的可配置选项,可以允许开发者非常精细地控制图形渲染过程。
优点
- 跨平台:OpenGL 可以在多种操作系统上运行,因此,基于 OpenGL 的应用程序可以更容易地在不同平台间移植。
- 开放性:作为一个开放标准,OpenGL 的文档和规范可以免费访问,且得到了广泛的支持。
- 成熟的社区支持:OpenGL 拥有丰富的教程、开发工具和开源项目,有庞大的开发者社区支持。
缺点
- 性能问题:由于其抽象层较高,OpenGL 相比 DirectX 可能在一些平台上的性能较差。
- 较为复杂:OpenGL 对开发者的要求较高,提供了大量的自由度,这可能会导致开发变得复杂。
应用领域
- OpenGL 主要用于游戏、3D 图形、科学计算(如计算机辅助设计 CAD)、虚拟现实、图像处理等领域。
2. DirectX
概述
- 微软的专有技术:DirectX 是由微软开发并为 Windows 平台量身定制的多媒体接口,首次发布于 1995 年。它包括多个子组件,其中 Direct3D 是专门用于图形渲染的部分,类似于 OpenGL。
- Windows 专用:与 OpenGL 的跨平台支持不同,DirectX 只适用于 Windows 操作系统和 Xbox 游戏机。虽然 DirectX 的某些功能(如 DirectCompute)也能在其他平台上运行,但 Direct3D 主要用于 Windows 平台。
优点
- 优化的性能:由于 DirectX 是专为 Windows 平台设计的,微软能够在操作系统层面对其进行优化,因此它在 Windows 上的性能通常优于 OpenGL。
- 紧密集成:DirectX 与 Windows 操作系统和硬件的集成更为紧密,因此它能够更好地利用 Windows 系统提供的功能和硬件加速。
- 更易上手:与 OpenGL 相比,DirectX 的 API 在一些情况下设计得更加简洁易用,尤其是在开发游戏时,微软为 DirectX 提供了丰富的工具和库,帮助开发者更快上手。
缺点
- 平台限制:DirectX 仅限于 Windows 和 Xbox 系统,这使得它在跨平台开发时受限。虽然通过工具如 Wine 可以在 Linux 上运行 DirectX 应用,但这并不是一个完美的解决方案。
- 封闭性:作为一个专有技术,DirectX 不是开放标准,微软控制着其更新和发展,某些方面的文档和实现并不如 OpenGL 那样透明。
应用领域
- DirectX 是 Windows 上最常用的图形 API,尤其在游戏开发领域。许多 Windows 游戏和基于 Xbox 的游戏都依赖 Direct3D(DirectX 的一部分)来进行图形渲染。
OpenGL vs DirectX 的比较
特性 | OpenGL | DirectX |
---|---|---|
平台支持 | 跨平台(Windows、Linux、macOS、移动设备等) | 主要支持 Windows 和 Xbox |
开源与闭源 | 开源,开发者可以自由使用和修改 | 封闭,微软控制开发和更新 |
性能 | 在跨平台应用中有时不如 DirectX 高效 | 在 Windows 上经过优化,通常性能更好 |
API 复杂度 | 较为复杂,提供更多灵活性和控制 | 相对较简洁,易于上手 |
文档和支持 | 文档和社区支持广泛,跨平台开发社区活跃 | 主要针对 Windows 平台,文档和工具完善 |
开发工具支持 | 可以在多种平台上使用各类开发工具 | 紧密集成于 Visual Studio 等工具 |
总结
- OpenGL 适合那些需要跨平台支持的应用程序和开发者,尤其是那些需要灵活控制渲染细节的场景,如学术研究、跨平台游戏开发等。
- DirectX 则更加适合 Windows 平台的开发,尤其是在游戏和图形密集型应用中,由于其对 Windows 系统和硬件的优化,通常提供更高的性能和更好的支持。
对于游戏开发者来说,DirectX 通常是 Windows 游戏开发的首选,而对于跨平台应用或者需要支持多种操作系统的开发者来说,OpenGL(或其衍生的 Vulkan)则可能是更好的选择。
HLSL、GLSL 和Cg
HLSL(High-Level Shading Language)、GLSL(OpenGL Shading Language)和 Cg(C for Graphics)都是用于编写图形着色器(shaders)的编程语言。它们的主要用途是为图形处理单元(GPU)编写程序,以执行特定的图形计算任务,比如渲染、光照、纹理映射等。这些着色器程序会在图形渲染管线中运行,以实现复杂的视觉效果。
下面是这三种语言的详细介绍:
1. HLSL (High-Level Shading Language)
概述
- HLSL 是微软为 DirectX 提供的着色器语言,用于在 Direct3D 环境中编写着色器程序。
- 它是 高层次的着色器语言,语法类似于 C,且专为 GPU 编程设计。
- 通过 HLSL,开发者可以编写各种类型的着色器,如 顶点着色器、像素着色器、几何着色器、计算着色器 等。
特点
- 平台依赖:HLSL 仅在 Windows 和 Xbox 平台上使用,因为它与 DirectX(特别是 Direct3D)紧密集成。
- 强大的功能:提供了大量的图形编程功能,允许开发者控制渲染管线的各个阶段。
- 语法简洁:类似于 C/C++,这使得它对大多数熟悉 C 语言的程序员更易于上手。
应用场景
- 用于 Windows 和 Xbox 平台的游戏和图形应用开发,特别是 DirectX 环境下的图形渲染编程。
示例(HLSL)
struct PS_INPUT |
2. GLSL (OpenGL Shading Language)
概述
- GLSL 是 OpenGL 使用的着色器语言,设计目的是为 OpenGL 提供一种高效的、与平台无关的图形编程方式。
- 它是与 OpenGL 和 OpenGL ES 配套的,支持顶点着色器、片段着色器(即像素着色器)、几何着色器等类型的着色器。
特点
- 跨平台:GLSL 是 OpenGL 的一部分,因此它可以在支持 OpenGL 的任何平台上运行(如 Windows、Linux、macOS、Android、iOS 等)。
- 灵活性:GLSL 允许开发者编写高效的图形程序,并且它支持现代图形渲染的多种特性,如 计算着色器、光照模型、纹理处理 等。
- 与 OpenGL 紧密结合:GLSL 是 OpenGL 的一部分,它直接操作 OpenGL 渲染管线中的数据,简化了与图形硬件的交互。
应用场景
- 用于所有支持 OpenGL 和 OpenGL ES 的平台,包括桌面、移动设备以及嵌入式系统。
示例(GLSL)
|
3. Cg (C for Graphics)
概述
- Cg 是 NVIDIA 开发的图形着色器语言,旨在提供一种跨平台的着色器编程语言,它的语法类似于 C 语言。
- Cg 在设计时参考了 HLSL 和 GLSL,试图结合两者的优点。它在早期广泛用于 OpenGL 和 DirectX 环境中,但近年来逐渐被 HLSL 和 GLSL 取代。
- Cg 提供了丰富的图形编程功能,并且可以生成针对不同平台和图形 API(如 DirectX 和 OpenGL)的代码。
特点
- 跨平台:Cg 最初被设计为可以在多种图形 API(包括 OpenGL 和 DirectX)中使用,因此它有跨平台的优势。
- 工具支持:NVIDIA 提供了 Cg 的编译器和工具,帮助开发者生成优化的着色器代码。
- 已过时:由于 HLSL 和 GLSL 的广泛应用,NVIDIA 已不再积极更新 Cg,目前已经不再作为主流的图形编程语言。
应用场景
- 以前用于开发跨平台的图形应用,特别是在 OpenGL 和 DirectX 环境下。但如今它的使用逐渐减少,开发者更多使用 HLSL 和 GLSL。
示例(Cg)
struct PS_INPUT |
比较:HLSL、GLSL、Cg
特性 | HLSL | GLSL | Cg |
---|---|---|---|
平台支持 | 主要用于 Windows 和 Xbox(DirectX) | 跨平台支持(Windows、Linux、macOS 等) | 跨平台支持(OpenGL 和 DirectX) |
语言风格 | 类似 C/C++,语法清晰简洁 | 类似 C,易于理解,接近硬件编程 | 类似 C,融合了 HLSL 和 GLSL 的优点 |
功能性 | 强大,特别是在 Direct3D 环境下 | 强大,专为 OpenGL 环境设计 | 早期强大,但现在逐渐被 HLSL 和 GLSL 取代 |
主流使用 | 游戏、图形开发,特别是在 Windows 平台 | 游戏开发、图形应用,支持广泛平台 | 过去用于跨平台开发,但现已过时 |
未来前景 | 强大且继续更新,尤其在 DirectX 中 | 广泛使用,特别是在跨平台应用中 | 已不再更新,逐渐被淘汰 |
总结
- HLSL:专为 DirectX 环境设计,主要用于 Windows 和 Xbox 游戏开发,性能优化较好,功能强大。
- GLSL:与 OpenGL 紧密集成,支持跨平台应用,适用于桌面、移动和嵌入式平台的图形开发。
- Cg:早期为跨平台图形开发设计,但现在被 HLSL 和 GLSL 取代,逐渐过时。
如今,开发者通常根据所选平台和图形 API 来选择合适的着色器语言:如果是 Windows 和 Xbox 平台,使用 HLSL;如果是跨平台应用,使用 GLSL。Cg 曾经有一定的影响力,但现在已不再是主流选择。对于Unity平台,我们同样可以选择使用哪种语言。在Unity Shader中,我们可以选择使用 “CG/HLSL”或者“GLSL”。带引号是因为Unity里的这些着色语言并不是真正意义上的对应的着色语言,尽管它们的语法几乎一样。以Unity CG为例,你有时会发现有些CG语法在Unity Shader中是不支持的。
Draw Call
Draw Call 是计算机图形学中的一个术语,指的是向图形处理单元(GPU)发出的一次请求,要求它渲染(绘制)一个或多个图形元素(如三角形、纹理、顶点等)。每个 Draw Call 通常代表一次对 GPU 的操作,它告诉 GPU 需要渲染的内容以及如何渲染。
详细解释
在现代的图形渲染中,GPU 执行渲染操作时,会接收来自 CPU 的一系列指令(这些指令包括顶点数据、材质、纹理、光照等信息)。每个 Draw Call 就是这种指令的一个集合,包含了关于如何绘制某个图形的详细信息。通常情况下,一个 Draw Call 可能会涉及到以下内容:
- 顶点数据:比如一个三角形的三个顶点的坐标。
- 纹理数据:图像或纹理应用到图形表面的方式。
- 着色器:控制渲染效果的程序(如顶点着色器和片段着色器)。
- 渲染目标:要渲染到的帧缓冲或图像。
简单的 Draw Call 流程
- CPU 发出 Draw Call:游戏或应用程序的 CPU 会通过调用 API(如 OpenGL、DirectX 或 Vulkan)发出一个 Draw Call,请求 GPU 渲染指定的几何体。
- GPU 执行渲染:GPU 会使用这个指令中包含的数据(如顶点、纹理、着色器等),然后渲染出图形。
- 输出图像:GPU 渲染后的图形会被输出到屏幕或渲染目标(如一个纹理)。
如何优化 Draw Call
优化 Draw Call 的目的是减少每帧中发出的 Draw Call 数量,这可以通过以下方式实现:
- 合并绘制操作:
- 批量渲染:将多个物体的渲染合并为一次 Draw Call。例如,多个静态物体可以放入同一个批次,使用相同的材质和纹理来减少 Draw Call。
- 实例化渲染(Instancing):当多个物体具有相同的几何体结构但不同的位置、缩放或旋转时,可以使用实例化渲染,将所有实例的绘制合并为一个 Draw Call。这样,只需发送一次 Draw Call,就能渲染多个相同物体。
- 减少状态切换:
- GPU 渲染时需要设置各种状态(如纹理、着色器等)。频繁地切换这些状态(例如更换纹理或着色器)会增加开销。优化时,尽量保持状态的一致性,减少不必要的切换。
- 合并多个小物体:
- 如果场景中有很多小物体,可以将它们合并成更大的几何体,减少每个物体的独立 Draw Call。
- 使用合适的渲染 API:
- 一些现代的渲染 API(如 Vulkan 和 DirectX 12)允许开发者更细粒度地控制 GPU 和 CPU 之间的交互,优化 Draw Call 的发出时机,从而减轻性能负担。
Draw Call 示例
假设我们要渲染一个简单的场景,包含一个立方体和一个球体。每个物体都有自己的纹理和着色器。如果我们分别为每个物体发出一个 Draw Call,那么会有两个 Draw Call:一个用于渲染立方体,另一个用于渲染球体。
- 高效的做法:如果立方体和球体使用相同的材质和纹理,可以将它们合并成一个 Draw Call,通过批量渲染或者实例化渲染来减少 Draw Call 数量。
固定管线渲染
固定管线渲染(Fixed-Function Pipeline Rendering)是指在计算机图形学中,一种由图形 API 提供的预定义的、不可定制的渲染管线,它以固定的顺序执行一系列图形处理步骤。也就是说,渲染过程中的各个步骤已经被硬件或 API 固定下来,开发者无法修改或控制这些步骤的执行顺序或具体实现。
在早期的图形硬件(GPU)中,固定管线渲染是最常用的方式,开发者通过调用图形 API(如 OpenGL 或 DirectX)中的固定功能,来完成图形的渲染任务。这些功能包括光照、纹理映射、颜色混合、裁剪等。
固定管线渲染的工作原理
固定管线渲染通常遵循以下几个主要阶段(顺序可能略有不同,取决于具体的 API 和硬件):
- 模型变换(Model Transformation):
- 将物体的顶点从物体坐标系变换到世界坐标系。这是通过一个变换矩阵完成的,通常是物体位置、旋转和缩放的组合。
- 视图变换(View Transformation):
- 将物体从世界坐标系变换到观察者的视图坐标系(也叫视图空间或相机坐标系)。这个变换是为了模拟观察者的视角。
- 投影变换(Projection Transformation):
- 将视图空间中的顶点投影到二维视口上(屏幕上的坐标)。常见的投影方式包括透视投影(模拟现实世界的视角)和正交投影(无透视效果,常用于技术绘图或2D应用)。
- 裁剪(Clipping):
- 剔除那些不在视锥体内的物体,这样就避免了绘制不在视野中的物体,提高了渲染效率。
- 光栅化(Rasterization):
- 将三维场景中的几何体(通常是三角形)转换为二维图像的像素或片元。每个像素或片元都会有颜色、深度等属性。
- 纹理映射(Texture Mapping):
- 在光栅化后的片元上应用纹理图像,赋予物体更多的细节和真实感。
- 光照(Lighting):
- 根据物体的表面特性、光源的位置和方向,计算每个片元的光照值。固定管线的光照模型通常比较简单,只有一些基本的光照模型(如环境光、漫反射和镜面反射)。
- 颜色混合和输出(Blending and Output):
- 在最终的颜色输出阶段,应用颜色混合(例如透明度效果)并将最终的像素颜色输出到帧缓冲中,准备显示在屏幕上。
固定管线渲染的特点
- 不可定制:
- 固定管线的渲染过程是预定义的,开发者无法控制渲染的每个步骤或添加新的步骤。例如,光照、纹理映射和着色等过程都有固定的实现方式,无法改变。
- 简单易用:
- 由于渲染过程已经预定义好,开发者不需要关心复杂的图形编程细节,使用固定管线的开发工作量较少。适合于那些不需要高度自定义渲染的应用场景。
- 硬件加速:
- 在早期的图形硬件上,固定管线的操作往往是由硬件直接加速的,这使得渲染过程非常高效和快速。
- 局限性:
- 固定管线的局限性在于它的灵活性差。由于所有操作都是固定的,开发者无法根据需要定制或优化渲染管线。例如,光照模型和材质处理等都没有办法像现代的 可编程管线 那样进行自定义。
固定管线渲染的历史和发展
在图形硬件发展早期,所有的图形操作都通过固定管线来完成。随着 GPU 技术的不断进步,特别是可编程 GPU 的出现,渲染管线逐步变得更加灵活和可定制。
- OpenGL 2.x 和 DirectX 9 时代,固定管线仍然是主流,但引入了 着色器(Shader)的概念,使得部分渲染过程(如光照、纹理等)可以通过编程来进行定制,但仍保留了固定管线的部分功能。
- OpenGL 3.x 和 DirectX 10 及之后版本,固定管线逐渐被 可编程管线 取代,允许开发者编写顶点着色器、片段着色器等程序来完全控制渲染过程。这种方式提供了更高的灵活性,但也需要开发者具备更多的图形编程知识。
固定管线与可编程管线的比较
特性 | 固定管线渲染 | 可编程管线渲染 |
---|---|---|
灵活性 | 低,渲染过程不可定制 | 高,开发者可以自定义顶点着色器、片段着色器等 |
性能 | 由于是固定的硬件加速,通常性能较好 | 更灵活但可能需要更多的优化与调整 |
开发难度 | 较低,开发者只需调用 API | 较高,开发者需要编写着色器程序 |
可控性 | 不可控制,API 完全固定 | 完全控制渲染管线,可以实现复杂效果 |
适用场景 | 简单的渲染任务,较早的硬件或简单应用 | 需要高自定义的复杂渲染任务,如现代游戏 |
总结
固定管线渲染 是早期图形硬件和渲染 API 的标准渲染方式,具有简单易用、硬件加速等特点,但缺乏灵活性,无法提供复杂的自定义渲染控制。随着图形硬件和渲染 API 的发展,固定管线逐渐被 可编程管线 替代,使得开发者能够编写着色器程序来完全控制渲染过程,提供了更高的灵活性和功能,适应了现代图形和游戏的需求。如果不是为了对较旧的设备进行兼容,不建议继续使用固定管线的渲染方式。