计算机图形学 | 可编程渲染管线
创始人
2025-06-01 02:43:25
0

计算机图形学 | 可编程渲染管线

  • 计算机图形学 | 可编程渲染管线
    • 3.1 从固定到可编程
      • 图形编程的发展
      • GPU渲染管线
        • 渲染管线的功能
        • 流水线中的三个概念阶段
    • 3.2 探秘GPU渲染管线
      • GPU渲染管线
      • 几何阶段
      • 光栅化阶段
    • 3.3 着色器编程
      • 着色器语言
      • GLSL
      • EBO、VBO和VAO
      • 例程

华中科技大学《计算机图形学》课程

MOOC地址:计算机图形学(HUST)

计算机图形学 | 可编程渲染管线

3.1 从固定到可编程

图形编程的发展

早期的图形编程

在这里插入图片描述

那些用来绘制图元及其属性的对应函数库不存在或非常低级;

不具体硬件相关,不具备可移植性。

程序员有很大的控制权,耗费时间。

图形标准的产生

在这里插入图片描述

  • 图形核心系统(Graphical Kernel System,GKS)
  • 程序员层次式交互图形系统(Programmer’s Hierarchical Interactive Graphics System,PHIGS)
  • 开放的图形库( Open Graphics LibraryOpenGL )

它们都与设备无关。

固定管线

图形API提供了一个对硬件进行操作的标准接口;从内部实现上来说,API对程序员提出的各种绘制图元或属性的请求都采用固定的方式来处理。

这种内部实现方式通常称为固定功能渲染流水线

对程序员来说,控制权减少,非常方便。

典型的光栅扫描图形显示子系统:

在这里插入图片描述

流水线的概念:

在这里插入图片描述

在这里插入图片描述

固定到可编程:钩函数hooks的出现突破固定功能流水线的限制,使用可编程着色器修改流水线中某些特定步骤的行为。

在这里插入图片描述

GPU渲染管线

渲染管线的功能

决定在给定虚拟相机、三维物体、光源、照明模式,以及纹理等诸多条件的情况下生成或绘制一幅二维图像的过程。

在这里插入图片描述

流水线中的三个概念阶段

应用阶段

将需要在屏幕上显示出来绘制的几何体,也就是绘制图元,比如点、线、矩形等输入到绘制管线的下一个阶段。

具体包括图元的顶点数据、摄像机位置、光照纹理等参数。

几何阶段

几何阶段需要将顶点数据最终进行屏幕映射。

这其中需要:

  • 将各个图元放入到世界坐标系中,也就是进行模型变换;
  • 根据光照纹理等计算顶点处材质的光照着色效果;
  • 根据摄像机的位置、取景范围进行观察变换和裁剪;
  • 最后进行屏幕映射,也就是把三维模型转换到屏幕坐标系中

光栅化阶段

光栅化部分的输入是经过变换和投影后的顶点、颜色以及纹理坐标,它的工作是给每个像素正确配色,以便绘制整幅图形。

由于输入的是三角形顶点,所以需要根据三角形表面的差异,逐个遍历三角形计算各个像素的颜色值。之后根据其可见性等进行合并得到最后的输出。

在这里插入图片描述

实例:

在这里插入图片描述

3.2 探秘GPU渲染管线

GPU渲染管线

在这里插入图片描述

几何阶段

在这里插入图片描述

在这里插入图片描述

光栅化阶段

在这里插入图片描述

片元操作:

在这里插入图片描述

3.3 着色器编程

着色器语言

在这里插入图片描述

在这里插入图片描述

Phong光照明模型的综合表述:

由物体表面上一点P反射到视点的光强I为环境光的反射光强、理想漫反射光强和镜面反射光强的总和。

I=IaKa+IpKd(L×N)+IpKs(R×V)nI=I_aK_a+I_pK_d(L×N)+I_pK_s(R×V)^nI=Ia​Ka​+Ip​Kd​(L×N)+Ip​Ks​(R×V)n

在这里插入图片描述

GLSL

OpenGL的着色器语言GLSL,也就是OpenGL Shading Language。

  • 顶点着色器(Vertex Shader)
  • 几何着色器(Geometry Shader)
  • 曲面细分着色器(Tessellation Shader)
  • 片元着色器(Fragment Shader)

在OpenGL中使用着色器的流程:

  1. 创建着色器对象
  2. 源码关联到着色器对象
  3. 编译着色器
  4. 创建一个程序对象
  5. 创建一个程序对象

与OpenGL的通信:

在这里插入图片描述

数据类型:

  • 标量:整数(int)、无符号整数(uint)、布尔类型(bool)及浮点数(float)
  • 矢量:一个矢量可以有2、3、4个分量
  • 矩阵
  • 结构和数组:结构体的成员或者数组的基类型可以为任意的数据类型

控制结构:

  • 循环结构:for、while和do-while
  • 选择结构:if-then、if-then-else,Glsl3.0版本引入了switch结构

EBO、VBO和VAO

EBO(Element Buffer Object,也叫IBO:Index Buffer Object):索引缓冲区对象,这个缓冲区主要用来存储顶点的索引信息。

在这里插入图片描述

VBO(Vertex Buffer Object):顶点缓冲区对象,主要用来存储顶点的各种信息。

好处:模型的顶点信息放进VBO,这样每次画模型时,数据丌用再从CPU的势力范围内存里取,而是直接从GPU的显存里取,从而提高效率。

VAO(Vertex Arrary Object):顶点数组对象

VAO是一个保存了所有顶点数据属性的状态结合,它存储了顶点数据的格式以及顶点数据所需的VBO对象的引用。VAO本身并没有存储顶点的相关属性数据,这些信息是存储在VBO中的,VAO相当于是对很多个VBO的引用,把一些VBO组合在一起作为一个对象统一管理。

VAO和VBO之间的关系:

在这里插入图片描述

例程

方法一:VAO+VBO绘制四边形

// 渲染之前VAO/VBO的绑定生成  
// 顶点数据  
float vertices[] = {  
// 第一个三角形  
0.5f, 0.5f, 0.0f, // 右上  
0.5f, -0.5f, 0.0f, // 右下  
-0.5f, -0.5f, 0.0f, // 左下  
// 第二个三角形  
-0.5f, -0.5f, 0.0f, // 左下  
0.5f, 0.5f, 0.0f, // 右上  
-0.5f, 0.5f, 0.0f // 左上  
};  
// 生成立方体的VAO、VBO  
unsigned int VBO, VAO;  
glGenVertexArrays(1, &VAO);  
glGenBuffers(1, &VBO);  
// 绑定VAO  
glBindVertexArray(VAO);  
// 绑定VBO并传入顶点数据  
glBindBuffer(GL_ARRAY_BUFFER, VBO);  
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);  
// 设置顶点属性指针  
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);  
glEnableVertexAttribArray(0);  
// 解绑VBO  
glBindBuffer(GL_ARRAY_BUFFER, 0);  
// 解绑VAO  
glBindVertexArray(0);  
// 渲染时  
// 使用之前链接好的着色器程序  
glUseProgram(shaderProgram);  
// 绑定VAO  
glBindVertexArray(VAO);  
// 用VAO绘制四边形  
glDrawArrays(GL_TRIANGLES, 0, 6);

方法二:VAO+VBO+EBO绘制四边形

// 渲染之前VAO/VBO/EBO的绑定生成
// 顶点数据
float vertices[] = {
0.5f, 0.5f, 0.0f, // 右上
0.5f, -0.5f, 0.0f, // 右下
-0.5f, -0.5f, 0.0f, // 左下
-0.5f, 0.5f, 0.0f // 左上
};
// 索引数据(注意这里是从0开始的)
unsigned int indices[] = {
0, 1, 3, // 第一个三角形
1, 2, 3 // 第二个三角形
};
// 生成立方体的VAO、VBO和EBO
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
// 绑定VAO
glBindVertexArray(VAO);
// 绑定VBO并传入顶点数据
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 绑定EBO并传入索引数据
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 设置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 解绑VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 注意丌要解绑EBO,因为EBO存储在VAO中
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// 解绑VAO
glBindVertexArray(0);
// 渲染时
// 使用之前链接好的着色器程序
glUseProgram(shaderProgram);
// 绑定VAO(实际上丌需要每次绑定)
glBindVertexArray(VAO);
// 用EBO绘制四边形
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

相关内容

热门资讯

安卓系统苹果手机识别,跨界融合... 你知道吗?在科技飞速发展的今天,手机已经成为了我们生活中不可或缺的一部分。而说到手机,安卓系统和苹果...
harmonyos系统是不是安... 亲爱的读者,你是否曾好奇过HarmonyOS系统与安卓系统之间的关系?是不是安卓的“亲戚”?今天,就...
手机怎么装系统安卓,安卓系统安... 手机卡顿了?想给安卓系统来个大变身?别急,跟着我一步步来,保证让你的手机焕然一新!一、准备工作在开始...
安卓Linux系统内网穿透,A... 你有没有想过,你的安卓手机里那些看似普通的APP,其实可能正在悄悄地帮你打通网络世界的任督二脉呢?没...
win怎么安装安卓系统,Win... 亲爱的读者,你是不是对Win系统上的安卓应用垂涎已久,但又苦于不知道如何安装安卓系统呢?别急,今天我...
升级小米平板安卓系统,畅享全新... 你有没有发现,你的小米平板用久了,是不是感觉有点卡呢?别急,今天就来教你怎么给它来个系统升级,让它焕...
捷豹安卓系统车载,捷豹安卓系统... 哇,你有没有想过,当你的手机和汽车融为一体,会是怎样的体验呢?想象你正驾驶着你的捷豹,车窗外的风景如...
安卓1到10系统,安卓1.0至... 你有没有想过,手机里的安卓系统就像是我们生活中的好朋友,从青涩的少年成长为稳重的青年呢?从安卓1.0...
安卓8.0停用系统应用,提升使... 你知道吗?最近安卓系统又来了一次大动作,那就是安卓8.0系统开始停用一些系统应用了。这可真是让人有点...
安卓系统修改mtu值,轻松提升... 你有没有想过,你的安卓手机其实是个小小的电脑呢?它里面藏着许多可以自定义的秘密功能,就像修改MTU值...
安卓平板改window系统,探... 你有没有想过,你的安卓平板其实可以摇身一变,变成一个Windows系统的电脑呢?没错,就是那种可以运...
时空猎人安卓苹果系统,探索无尽... 你知道吗?最近在手机游戏圈里,有一款叫做《时空猎人》的游戏可是火得一塌糊涂呢!不管是安卓用户还是苹果...
安卓9.0系统的电视,新一代电... 亲爱的读者们,你是否也像我一样,对科技新玩意儿充满好奇?今天,我要和你聊聊一个让人眼前一亮的话题——...
小pc安装安卓系统,轻松安装安... 你有没有想过,你的小PC也能变身成为安卓系统的超级玩家呢?没错,就是那个平时默默无闻的小家伙,现在也...
高通备份安卓系统,全方位数据安... 你知道吗?在这个科技飞速发展的时代,手机备份可是个不得不提的话题。尤其是对于安卓用户来说,选择一个靠...
谷歌安卓系统有多少,从诞生到全... 你有没有想过,那个无处不在的谷歌安卓系统,究竟在全球有多少用户呢?它就像一个神秘的数字,每天都在悄悄...
fc黄金传说安卓系统,畅享复古... 你有没有听说最近安卓系统上的一款超酷的游戏——《FC黄金传说》?这款游戏可是让不少玩家都沉迷其中,今...
变小的我安卓系统,安卓系统演变... 你有没有发现,最近你的手机好像变轻了?没错,说的就是你,那个陪伴你多年的安卓系统。它悄无声息地进行了...
vivo安卓系统小彩蛋,体验科... 你知道吗?在vivo的安卓系统中,竟然隐藏着一些超有趣的小彩蛋!这些小彩蛋就像是在手机里埋下的宝藏,...
安卓系统如何强制重启,安卓系统... 手机突然卡壳了,是不是又该给它来个“大保健”了?没错,今天就来聊聊安卓系统如何强制重启。别小看这个看...