计算机图形学 | 可编程渲染管线
创始人
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);

相关内容

热门资讯

安卓9系统怎样应用分身,轻松实... 你有没有发现,手机里的APP越来越多,有时候一个APP里还要处理好多任务,分身功能简直就是救星啊!今...
获取安卓系统的ip地址,轻松获... 你有没有想过,你的安卓手机里隐藏着一个神秘的IP地址?没错,就是那个能让你在网络世界里找到自己的小秘...
LG彩电安卓系统升级,畅享智能... 你家的LG彩电是不是最近有点儿“闹别扭”,屏幕上时不时地跳出个升级提示?别急,今天就来给你详细说说这...
阴阳师安卓苹果系统,安卓与苹果... 亲爱的玩家们,你是否曾在深夜里,手握手机,沉浸在阴阳师的神秘世界?今天,就让我带你一起探索这款风靡全...
华为安卓系统区别在哪,独特创新... 你知道吗?最近手机圈里可是热闹非凡,尤其是华为的新动作,让很多人眼睛都瞪大了。没错,我说的就是华为自...
怎么重新刷安卓手机系统,深度解... 手机用久了,是不是感觉卡顿得厉害?别急,今天就来教你怎么重新刷安卓手机系统,让你的手机焕然一新,速度...
刷正版安卓系统教程,刷正版安卓... 你有没有想过,让你的安卓手机焕然一新,体验一把正版系统的魅力呢?别急,今天就来手把手教你如何刷正版安...
移动支撑系统安卓版,助力移动办... 你有没有发现,现在的生活越来越离不开手机了?无论是工作还是娱乐,手机几乎成了我们生活的必需品。而今天...
安卓怎么进win系统界面,安卓... 亲爱的安卓用户,你是否曾幻想过在安卓设备上直接体验Windows系统的魅力?别再羡慕那些Window...
incall可以升级安卓系统吗... 你有没有想过,你的手机是不是也能像电脑一样,时不时地来个系统升级呢?今天,咱们就来聊聊这个话题——i...
安卓系统带农历软件,尽享传统节... 你知道吗?现在智能手机上有个特别实用的功能,那就是农历显示。对于咱们中国人来说,农历可是有着深厚的历...
安卓系统资源占用高,揭秘原因与... 你有没有发现,你的安卓手机最近变得越来越慢了?是不是觉得打开一个应用都要等半天,甚至有时候还会卡死?...
安卓10的系统有哪些,功能升级... 你有没有发现,你的安卓手机最近是不是变得有点不一样了?没错,就是那个神秘的安卓10系统!它就像一位魔...
固态硬盘系统迁移到安卓,固态硬... 你有没有想过,把你的固态硬盘系统迁移到安卓设备上,是不是能让你在移动办公或者娱乐时更加得心应手呢?想...
平板电脑能玩安卓系统吗,畅享丰... 你有没有想过,平板电脑竟然也能玩安卓系统?这可不是天方夜谭,而是科技发展的新趋势。想象你手中的平板瞬...
安卓刷精简系统下载,轻松打造高... 你有没有想过,你的安卓手机是不是有点儿“臃肿”了呢?运行速度慢,电池续航短,有时候还卡得要命。别急,...
安卓子系统windows11,... 你知道吗?最近科技圈可是炸开了锅,因为安卓子系统在Windows 11上的兼容性成了大家热议的话题。...
电脑里怎么下载安卓系统,电脑端... 你有没有想过,你的电脑里也能装上安卓系统呢?没错,就是那个让你手机不离手的安卓!今天,就让我来带你一...
索尼相机魔改安卓系统,魔改系统... 你知道吗?最近在摄影圈里掀起了一股热潮,那就是索尼相机魔改安卓系统。这可不是一般的改装,而是让这些专...
安卓系统哪家的最流畅,安卓系统... 你有没有想过,为什么你的手机有时候像蜗牛一样慢吞吞的,而别人的手机却能像风一样快?这背后,其实就是安...