计算机图形学速通指南笔记(0)

计算机图形学速通指南笔记(0)

前言

如果你已经有用计算机绘图的经验,你就会知道在这个过程中你会先画一个圆,然后是一个矩形、一条线、一些三角形,直到你构成你想要的图像。这个过程和手写一封信或一本书非常相似------它是一系列逐步执行任务的指令。

着色器也是一组指令,但这些指令会同时作用于屏幕上的每一个像素。这意味着你编写的代码必须根据像素在屏幕上的位置表现不同。就像印刷机一样,你的程序将作为一个函数工作,接收一个位置并返回一个颜色,并且当它被编译时,它会运行得非常快。

自然的承接下来,我们就要回答:怎么就快了?答案是------并行计算,或者说,并行处理。

并行处理并不是一个陌生的话题,我们都知道,单个CPU处理器,不管怎么说,都是只能串行的做事情。

可能会有人问我:不对啊,我的单核的电脑,怎么看起来同时在做很多事情呢?答案是操作系统对您的电脑进行了进程调度,让CPU看起来很万能,但实际上不过是在一个极短的时间内来回切换多个任务

现代计算机通常由多个处理器组成,换而言之,咱们真的有并行能力了,它们就像这些管道一样工作,依次完成任务,从而保持系统流畅运行。

在这个领域,也许我们真的要好好聊一下,认识理解并行编程的必要性。这是因为游戏,或者是视频,显然处理了极大量的像素计算

视频游戏和其他图形应用程序比其他程序需要更多的处理能力。由于它们包含大量图形内容,因此必须进行大量的逐像素运算。屏幕上的每一个像素都需要计算,在 3D 游戏中,还需要计算几何形状和透视效果。

您可能没有概念,我们需要强调下,我们要对每一个像素进行计算。举个例子,就拿800x600的屏幕来唠------每帧需要处理 48 万个像素 ,也就是每秒 1440 万次计算!没错!这足以让微处理器过载。

在现代 2880x1800 分辨率的 Retina 显示屏上,以每秒 60 帧的速度运行,这种计算每秒需要进行 311,040,000 次。您可以想想,要是塞给CPU来做,他只会直接罢工了。

所以,GPU应运而生,他比CPU更加简单,但是兄弟们,她算的快,特别擅长浮点类和批量的计算。因为他会真正并行的同时处理一大堆像素而且返回运算的结果。

既然 GPU 是一个拥有成千上万个小核心的"计算工厂",那咱们总得给这些工人发一份统一的"施工指南"吧?这个指南,就是着色器(Shader)。简单来说,着色器就是一段运行在 GPU 上的小程序。它不再像 CPU 那样擅长处理复杂的逻辑判断,而是极其专注于一件事:计算。我的意思是------你可以把它想象成一个高效的"涂色配方":它告诉 GPU 每一个微小的核心,在处理特定像素时,光影该怎么变、颜色该怎么调。正是有了这些脚本,GPU 才能让数万核心齐头并进,完成天文数字般的运算。

所以,在我们的旅途中,需要学习跟 GPU 相关的内容,也要学习类似 OpenGL 的东西。换而言之------就是学习如何编写这些着色器,指挥它们操作我们的硬件,一笔一画地勾勒出我们想要的世界。"

什么是 GLSL?

GLSL 代表 OpenGL 着色语言,它是着色器程序的特定标准。但是这里我们点到为止。

为什么图形学难?

一方面是算法的难度,以及------并行计算。

为了并行运行,每个管道或线程都必须独立于其他线程。我们说线程之间相互"盲",不知道其他线程在做什么。这条限制意味着所有数据必须沿同一方向流动。因此,不可能检查另一个线程的结果、修改输入数据,或者将一个线程的输出传递给另一个线程。允许线程间通信会危及数据的完整性。

此外,GPU 会使并行微处理器(管道)始终处于繁忙状态;一旦空闲,它们就会接收新的信息进行处理。线程不可能知道它前一刻在做什么。它可能正在绘制操作系统用户界面中的一个按钮,然后在游戏中渲染一部分天空,最后显示电子邮件的文本。每个线程不仅是盲的,而且是无记忆的。除了需要对根据位置逐像素改变结果的通用函数进行抽象之外,盲性和无记忆的限制使得着色器在初级程序员中并不受欢迎。

上代码

可能有点快,但是,我们干程序的都喜欢上代码说话。好,那就上代码。从Unix C搞出来的Hello World经典步骤,我们也搞一个。这是一个简单的单行程序,输出热情洋溢的欢迎信息,并预示着未来的机遇。

在GPU领域,渲染文本对于第一步来说过于复杂,因此我们将选择一种明亮的欢迎颜色来表达我们的热情!

c 复制代码
#ifdef GL_ES
precision mediump float;
#endif

void main() {
	gl_FragColor = vec4(1.0,0.0,1.0,1.0);
}

虽然这些简单的代码看起来并不复杂,但我们可以从中推断出大量的知识:

  1. 着色器语言只有一个主函数,该函数会在最后返回一个颜色值。这类似于 C 语言。

  2. 最终的像素颜色被赋值给保留的全局变量 gl_FragColor。

  3. 这种类似 C 语言的语言内置了变量(例如 gl_FragColor)、函数和类型。在本例中,我们刚刚接触到了 vec4,它代表一个四维浮点精度向量。稍后我们将看到更多类型,例如 vec3 和 vec2,以及常用的 float、int 和 bool。

  4. 如果我们仔细观察 vec4 类型,我们可以推断出它的四个参数分别对应红色、绿色、蓝色和 Alpha 通道。我们还可以看到这些值是归一化的,也就是说它们的取值范围是 0.0 到 1.0。稍后,我们将学习归一化值如何使变量之间的值映射更加容易。

  5. 在这个例子中,我们可以看到另一个重要的 C 语言特性:预处理器宏。宏是预编译步骤的一部分。使用宏可以定义全局变量并执行一些基本的条件操作(例如使用 #ifdef#endif)。所有宏命令都以井号 (#) 开头。预编译发生在编译之前,它会复制所有对 #define 的调用,并检查 #ifdef(已定义)和 #ifndef(未定义)条件语句。在上面的"Hello World!"示例中,我们仅在定义了 GL_ES 时才插入第 2 行,这通常发生在代码在移动设备和浏览器上编译时。

  6. 浮点类型在着色器中至关重要,因此精度级别也至关重要。较低的精度意味着更快的渲染速度,但会牺牲图像质量。您可以仔细指定每个使用浮点数的变量的精度。在第一行代码中(precision mediump float;),我们将所有浮点数设置为中等精度。但我们也可以选择将其设置为低精度(precision lowp float;)或高精度(precision highp float;)。

  7. 最后,也许也是最重要的一点是,GLSL 规范并不保证变量会自动转换。这意味着什么?制造商采用不同的方法来加速显卡处理,但他们必须保证最低规格。自动转换并不在其中。在我们的"Hello World!"程序中......例如,vec4 具有浮点精度,因此它期望赋值为浮点数。如果您想编写高质量且一致的代码,而不是花费数小时调试白屏,请习惯在浮点数前加上小数点 (.)。

这是笔者在看Book Of Shader的时候注意的,非常感谢GPT,他告诉我(虽然我的确也发现了,这不是一个标准的C语言程序)这不是一个可以运行的C语言程序,在下一篇博客里,我们将会讲解如何在WSL中配置OpenGL学习环境,进一步学习OpenGL!

相关推荐
带土12 小时前
2. C++ private、protected、public
开发语言·c++
百***78753 小时前
Sora Video2 API国内接入避坑与场景落地:开发者实战笔记
人工智能·笔记·gpt
日更嵌入式的打工仔3 小时前
RS-485通讯协议
笔记·嵌入式硬件
数据轨迹0013 小时前
ICCV MK-UNet:多核深度可分离卷积医学分割
经验分享·笔记·facebook·oneapi·twitter
星火开发设计4 小时前
二维数组:矩阵存储与多维数组的内存布局
开发语言·c++·人工智能·算法·矩阵·函数·知识
夜勤月4 小时前
彻底终结内存泄漏与悬挂指针:深度实战 C++ 智能指针底层原理与自定义内存池,打造稳如泰山的系统基石
开发语言·c++
Fcy6484 小时前
⽤哈希表封装unordered_map和unordered_set(C++模拟实现)
数据结构·c++·散列表
CSDN_RTKLIB4 小时前
右值引用一个误区
c++
一分之二~5 小时前
二叉树--层序遍历(迭代和递归)
数据结构·c++·算法·leetcode