OpenGLDirectX

OpenGLDirectX 都是计算机图形和游戏开发中常用的图形渲染接口(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)则可能是更好的选择。

1737611317237

HLSLGLSLCg

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
{
float4 pos : POSITION;
float4 color : COLOR;
};

float4 main(PS_INPUT input) : SV_Target
{
return input.color; // 输出颜色
}

2. GLSL (OpenGL Shading Language)

概述

  • GLSLOpenGL 使用的着色器语言,设计目的是为 OpenGL 提供一种高效的、与平台无关的图形编程方式。
  • 它是与 OpenGL 和 OpenGL ES 配套的,支持顶点着色器、片段着色器(即像素着色器)、几何着色器等类型的着色器。

特点

  • 跨平台:GLSL 是 OpenGL 的一部分,因此它可以在支持 OpenGL 的任何平台上运行(如 Windows、Linux、macOS、Android、iOS 等)。
  • 灵活性:GLSL 允许开发者编写高效的图形程序,并且它支持现代图形渲染的多种特性,如 计算着色器光照模型纹理处理 等。
  • 与 OpenGL 紧密结合:GLSL 是 OpenGL 的一部分,它直接操作 OpenGL 渲染管线中的数据,简化了与图形硬件的交互。

应用场景

  • 用于所有支持 OpenGL 和 OpenGL ES 的平台,包括桌面、移动设备以及嵌入式系统。

示例(GLSL)

#version 330 core
in vec4 color;
out vec4 FragColor;

void main()
{
FragColor = color; // 输出颜色
}

3. Cg (C for Graphics)

概述

  • CgNVIDIA 开发的图形着色器语言,旨在提供一种跨平台的着色器编程语言,它的语法类似于 C 语言。
  • Cg 在设计时参考了 HLSL 和 GLSL,试图结合两者的优点。它在早期广泛用于 OpenGLDirectX 环境中,但近年来逐渐被 HLSLGLSL 取代。
  • Cg 提供了丰富的图形编程功能,并且可以生成针对不同平台和图形 API(如 DirectX 和 OpenGL)的代码。

特点

  • 跨平台:Cg 最初被设计为可以在多种图形 API(包括 OpenGL 和 DirectX)中使用,因此它有跨平台的优势。
  • 工具支持:NVIDIA 提供了 Cg 的编译器和工具,帮助开发者生成优化的着色器代码。
  • 已过时:由于 HLSL 和 GLSL 的广泛应用,NVIDIA 已不再积极更新 Cg,目前已经不再作为主流的图形编程语言。

应用场景

  • 以前用于开发跨平台的图形应用,特别是在 OpenGL 和 DirectX 环境下。但如今它的使用逐渐减少,开发者更多使用 HLSL 和 GLSL。

示例(Cg)

struct PS_INPUT
{
float4 pos : POSITION;
float4 color : COLOR;
};

float4 main(PS_INPUT input) : COLOR
{
return input.color; // 输出颜色
}

比较: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 流程

  1. CPU 发出 Draw Call:游戏或应用程序的 CPU 会通过调用 API(如 OpenGL、DirectX 或 Vulkan)发出一个 Draw Call,请求 GPU 渲染指定的几何体。
  2. GPU 执行渲染:GPU 会使用这个指令中包含的数据(如顶点、纹理、着色器等),然后渲染出图形。
  3. 输出图像:GPU 渲染后的图形会被输出到屏幕或渲染目标(如一个纹理)。

1737611739112

如何优化 Draw Call

优化 Draw Call 的目的是减少每帧中发出的 Draw Call 数量,这可以通过以下方式实现:

  1. 合并绘制操作
    • 批量渲染:将多个物体的渲染合并为一次 Draw Call。例如,多个静态物体可以放入同一个批次,使用相同的材质和纹理来减少 Draw Call。
    • 实例化渲染(Instancing):当多个物体具有相同的几何体结构但不同的位置、缩放或旋转时,可以使用实例化渲染,将所有实例的绘制合并为一个 Draw Call。这样,只需发送一次 Draw Call,就能渲染多个相同物体。
  2. 减少状态切换
    • GPU 渲染时需要设置各种状态(如纹理、着色器等)。频繁地切换这些状态(例如更换纹理或着色器)会增加开销。优化时,尽量保持状态的一致性,减少不必要的切换。
  3. 合并多个小物体
    • 如果场景中有很多小物体,可以将它们合并成更大的几何体,减少每个物体的独立 Draw Call。
  4. 使用合适的渲染 API
    • 一些现代的渲染 API(如 VulkanDirectX 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 和硬件):

  1. 模型变换(Model Transformation)
    • 将物体的顶点从物体坐标系变换到世界坐标系。这是通过一个变换矩阵完成的,通常是物体位置、旋转和缩放的组合。
  2. 视图变换(View Transformation)
    • 将物体从世界坐标系变换到观察者的视图坐标系(也叫视图空间或相机坐标系)。这个变换是为了模拟观察者的视角。
  3. 投影变换(Projection Transformation)
    • 将视图空间中的顶点投影到二维视口上(屏幕上的坐标)。常见的投影方式包括透视投影(模拟现实世界的视角)和正交投影(无透视效果,常用于技术绘图或2D应用)。
  4. 裁剪(Clipping)
    • 剔除那些不在视锥体内的物体,这样就避免了绘制不在视野中的物体,提高了渲染效率。
  5. 光栅化(Rasterization)
    • 将三维场景中的几何体(通常是三角形)转换为二维图像的像素或片元。每个像素或片元都会有颜色、深度等属性。
  6. 纹理映射(Texture Mapping)
    • 在光栅化后的片元上应用纹理图像,赋予物体更多的细节和真实感。
  7. 光照(Lighting)
    • 根据物体的表面特性、光源的位置和方向,计算每个片元的光照值。固定管线的光照模型通常比较简单,只有一些基本的光照模型(如环境光、漫反射和镜面反射)。
  8. 颜色混合和输出(Blending and Output)
    • 在最终的颜色输出阶段,应用颜色混合(例如透明度效果)并将最终的像素颜色输出到帧缓冲中,准备显示在屏幕上。

固定管线渲染的特点

  1. 不可定制
    • 固定管线的渲染过程是预定义的,开发者无法控制渲染的每个步骤或添加新的步骤。例如,光照、纹理映射和着色等过程都有固定的实现方式,无法改变。
  2. 简单易用
    • 由于渲染过程已经预定义好,开发者不需要关心复杂的图形编程细节,使用固定管线的开发工作量较少。适合于那些不需要高度自定义渲染的应用场景。
  3. 硬件加速
    • 在早期的图形硬件上,固定管线的操作往往是由硬件直接加速的,这使得渲染过程非常高效和快速。
  4. 局限性
    • 固定管线的局限性在于它的灵活性差。由于所有操作都是固定的,开发者无法根据需要定制或优化渲染管线。例如,光照模型和材质处理等都没有办法像现代的 可编程管线 那样进行自定义。

固定管线渲染的历史和发展

在图形硬件发展早期,所有的图形操作都通过固定管线来完成。随着 GPU 技术的不断进步,特别是可编程 GPU 的出现,渲染管线逐步变得更加灵活和可定制。

  • OpenGL 2.x 和 DirectX 9 时代,固定管线仍然是主流,但引入了 着色器(Shader)的概念,使得部分渲染过程(如光照、纹理等)可以通过编程来进行定制,但仍保留了固定管线的部分功能。
  • OpenGL 3.x 和 DirectX 10 及之后版本,固定管线逐渐被 可编程管线 取代,允许开发者编写顶点着色器、片段着色器等程序来完全控制渲染过程。这种方式提供了更高的灵活性,但也需要开发者具备更多的图形编程知识。

固定管线与可编程管线的比较

特性 固定管线渲染 可编程管线渲染
灵活性 低,渲染过程不可定制 高,开发者可以自定义顶点着色器、片段着色器等
性能 由于是固定的硬件加速,通常性能较好 更灵活但可能需要更多的优化与调整
开发难度 较低,开发者只需调用 API 较高,开发者需要编写着色器程序
可控性 不可控制,API 完全固定 完全控制渲染管线,可以实现复杂效果
适用场景 简单的渲染任务,较早的硬件或简单应用 需要高自定义的复杂渲染任务,如现代游戏

总结

固定管线渲染 是早期图形硬件和渲染 API 的标准渲染方式,具有简单易用、硬件加速等特点,但缺乏灵活性,无法提供复杂的自定义渲染控制。随着图形硬件和渲染 API 的发展,固定管线逐渐被 可编程管线 替代,使得开发者能够编写着色器程序来完全控制渲染过程,提供了更高的灵活性和功能,适应了现代图形和游戏的需求。如果不是为了对较旧的设备进行兼容,不建议继续使用固定管线的渲染方式。