OpenGL 渲染管线与显卡可执行程序

news/2024/5/2 5:21:54/文章来源:https://blog.csdn.net/MldXTieJiang/article/details/129143854

渲染管线的六个步骤

OpenGL 渲染管线的六个步骤,从指定几何图元到帧缓冲区写入像素,图像就被 OpenGL 引擎一步步地渲染到屏幕(FBO)上去了。

指定几何对象

OpenGL 引擎会根据开发者的指令去绘制几何图元。OpenGL(ES)提供给开发者的绘制方法 glDrawArrays 的第一个参数 mode,就是指定绘制方式。绘制方式的可选值有点、线、三角形三种,分别应用于不同的场景中。
粒子效果的场景中,我们一般用点(GL_POINTS)来绘制;直线的场景中,我们主要用线(GL_LINES)来绘制;所有二维图形图像的渲染,都用三角形(GL_TRIANGLE_STRIP)来绘制。
我们根据不同的场景选择的绘制方式,就决定了 OpenGL(ES)渲染管线的第一阶段怎么去绘制几何图元。

顶点变换

不论阶段一指定的是哪种几何对象,所有的几何数据都要来到顶点处理阶段,顶点处理阶段的操作就是变换顶点的位置:一是根据模型视图和投影矩阵的计算来改变物体(顶点)坐标的位置;二是根据纹理坐标与纹理矩阵来改变纹理坐标的位置。这里的输出是用 gl_Position 来表示具体的顶点位置的,如果是用点(GL_POINTS)来绘制几何图元的话,还应该输出 gl_PointSize。

图元组装

在阶段二的时候,我们已经确定了物体坐标和顶点坐标,然后到这个阶段进行图元组装。这里我们根据应用程序送往图元的规则(如 GL_POINTS 、GL_TRIANGLES 等)以及具体的纹理坐标,把纹理组装成图元。

栅格化操作

由上一阶段传递过来的图元数据,在这里会被分解成更小的单元并对应帧缓冲区的各个像素。这些单元叫做“片元”,一个片元可能包含窗口颜色、纹理坐标等属性。片元的属性则是图元上顶点数据经过插值而确定的,这其实就是栅格化操作,这个操作能够确定每一个片元是什么。

片元处理

通过纹理坐标取得纹理中相对应的片元像素值,根据自己的需要改变这个片元,比如调节饱和度、锐化等,最终输出的是一个四维向量 gl_FragColor,我们用它来表示修改之后的片元像素。

帧缓冲操作

帧缓冲操作是渲染管线的最后一个阶段,执行帧缓冲的写入等操作,OpenGL 引擎负责把最终的像素值写入到帧缓冲区中。

创建显卡执行程序

把 Shader 扔给 OpenGL 的渲染管线,这一部分叫做接口程序部分,就是利用 OpenGL 提供的接口来驱动 OpenGL 进行渲染。

在这里插入图片描述

创建 Shader

第一步是调用 glCreateShader 方法创建一个对象,作为 Shader 的容器,这个函数返回一个容器的句柄,函数原型如下:

GLuint glCreateShader(GLenum shaderType); 

函数原型中的参数 shaderType 有两种类型:

  • 一是 GL_VERTEX_SHADER,创建顶点着色器时开发者应传入的类型;
  • 二是 GL_FRAGMENT_SHADER,创建片元着色器时开发者应传入的类型。

第二步就是给创建的这个 Shader 添加源代码,对应图片最右边的两个 Shader Content,它们就是根据 GLSL 语法和内嵌函数书写出来的两个着色器程序,都是字符串类型。这个函数的作用就是把开发者的着色器程序加载到着色器句柄所关联的内存中,函数原型如下:

void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lenOfStrings)

最后一步就是来编译这个 Shader,编译 Shader 的函数原型如下:

void glCompileShader(GLuint shader);

编译完成之后,怎么知道这个 Shader 被编译成功了呢?我们可以使用下面这个函数来验证。

void glGetShaderiv (GLuint shader, GLenum pname, GLint* params);

其中,第一个参数 GLuint shader 就是我们要验证的 Shader 句柄;第二个参数 GLenum pname 是我们要验证的这个 Shader 的状态值,我们一般在这里验证是否编译成功,这个状态值选择 GL_COMPILE_STATUS。第三个参数 GLint* params 就是返回值,当返回值是 1 的时候,说明这个 Shader 编译成功了;如果是 0,就说明这个 shader 没有被编译成功。
这个时候,我们就需要知道着色器代码中的哪一行出了问题,所以还需要开发者再次调用这个函数,只不过是获取这个 Shader 的另外一种状态,这个时候状态值应该选择 GL_INFO_LOG_LENGTH,那么返回值返回的就是错误原因字符串的长度,我们可以利用这个长度分配出一个 buffer,然后调用获取出 Shader 的 InfoLog 函数,原型如下:

void glGetShaderInfoLog(GLuint object, int maxLen, int *len, char *log);

之后我们可以把 InfoLog 打印出来,帮助我们来调试实际的 Shader 中的错误。按照上面的步骤我们可以创建出 Vertex Shader 和 Fragment Shader,那么接下来我们看图片中的左半部分,也就是如何通过这两个 Shader 来创建 Program。

创建 Program

首先我们创建一个程序的实例作为程序的容器,这个函数返回程序的句柄。函数原型如下:

GLuint glCreateProgram(void);

紧接着将把上面部分编译的 shader 附加(Attach)到刚刚创建的程序中,调用的函数名称如下:

void glAttachShader(GLuint program, GLuint shader);

其中,第一个参数 GLuint program 就是传入在上面一步返回的程序容器的句柄,第二个参数 GLuint shader 就是编译的 Shader 的句柄,当然要为每一个 shader 都调用一次这个方法才能把两个 Shader 都关联到 Program 中去。
当顶点着色器和片元着色器都被附加到程序中之后,最后一步就是链接程序,链接函数原型如下:

void glLinkProgram(GLuint program);

传入参数就是程序容器的句柄,那么具体这个程序到底有没有链接成功呢?OpenGL 也提供了一个函数用来检查这个程序的状态,函数原型如下:

glGetProgramiv (GLuint program, GLenum pname, GLint* params);

第一个参数就是传入程序容器的句柄,第二个参数代表我们要检查这个程序的哪一个状态,这里面我们传入 GL_LINK_STATUS,最后一个参数就是返回值。返回值是 1 则代表链接成功,如果返回值是 0 则代表链接失败。类似于编译 Shader 的操作,如果链接失败了,可以获取错误信息,以便修改程序。
获取错误信息时,也得先调用这个函数,但是第二个参数我们传递的是 GL_INFO_LOG_LENGTH,代表获取出这个程序的 InfoLog 的长度,拿到长度之后我们分配出一个 char* 的内存空间以获取出 InfoLog,函数原型如下:

void glGetProgramInfoLog(GLuint object, int maxLen, int *len, char *log);

调用这个函数返回的 InfoLog,可以作为 Log 打印出来,以便定位问题。

到这里我们就创建出了一个 Program。回顾一下整个过程和 C 语言的编译和链接阶段非常相似,对比构造 OpenGL Program,编译阶段做了编译顶点着色器和片元着色器,并且把两个着色器 Attach 到 Program 中,链接阶段就是链接这个 Program。

创建显卡执行程序之后就是如何使用这个程序,其实使用这个构建出来的程序也很简单,调用 glUseProgram 这个方法即可,然后将一些内存中的数据与指令传递给这个程序,让这个程序运行起来。但是要想完全运行到手机上,还需要为 OpenGL ES 的运行提供一个上下文环境。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_72320.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IMX6ULL学习笔记(17)——工程管理

一、简介 之前我们把所有源码文件放在一个文件夹下。 这样做存在两个主要问题,第一,代码存放混乱不易阅读。第二,程序可移植性差。如果工程源文件达到几十、甚至数百个的时候,这样一股脑全部放到根目录下就会使工程显得混乱不堪。…

[JavaEE系列] 详解面试中HTTP协议HTTPS协议

文章目录HTTP不安全HTTPS中的加密算法对称加密非对称加密混合加密HTTPS中的摘要算法HTTPS中的数字证书SSL /TLS握手TCP建立连接(三次握手)三次握手中常见的面试题:TCP断开连接(四次挥手)四次挥手中常见的面试题&#x…

前端页面开发模块组织结构

模块组织 任何超过 1000 行的 CSS 代码,你都曾经历过这样的体验: 这个 class 到底是什么意思呢?这个 class 在哪里被使用呢?如果我创建一个 xxoo class,会造成冲突吗?Reasonable System for CSS Stylesheet Structure 的目标就是解决以上问题,它不是一个框架,而是通过…

2.5|1.3 操作系统与嵌入式操作系统概述

CPU是计算机系统的心脏,操作系统是计算机系统的大脑。半个世纪以来操作系统这门软件科学吸引了世界上一大群最热情、最有智慧的杰出人材,集中了人类现代创造性思维活动的精髓。操作系统是软件世界的万花筒、世博会,是软件王国中的一顶璀璨的皇…

十二、Django表单

表单 在之前的案例中,每次我们需要提交表单数据的时候。我们都需要去手动编辑html表单,根据不同的字段,字段名,进行编码。做了很多重复的部分,所以django提供了一个专门用来处理表单的类,django.forms.For…

代码随想录算法训练营第六天 |哈希表理论基础、242.有效的字母异位词、349. 两个数组的交集 、202. 快乐数、 1. 两数之和

打卡第六天,补昨天的卡 今日任务 哈希表理论基础242.有效的字母异位词349.两个数组的交集202.快乐数1.两数之和 哈希表理论基础 哈希表是根据关键码的值而直接进行访问的数据结构。 哈希表能解决什么问题呢? 一般哈希表都是用来快速判断一个元素是否出现集合里。 …

Tr0ll1靶机训练

信息收集 主机探测 端口扫描 21,22,80端口开放通过浏览器访问并进行指纹识别,并没没有发现什么有用信息 测试 观察发现21端口开放(ftp)尝试进行匿名登录发现其中存在一个流量文件将其下载 并将文件用wirwshark打开,追踪其TCP流(…

BEV感知:DETR3D

3D检测:DETR3D前言MethodImage Feature Extracting2D-to-3D Feature TransformationLoss实验结果前言 在这篇paper,作者提出了一个更优雅的2D与3D之间转换的算法在自动驾驶领域,它不依赖于深度信息的预测,这个框架被称之为DETR3D…

【C进阶】数据的存储

文章目录:star:1. 数据类型:star:2. 整形在内存中的存储2.1 存储规则2.2 存储模式2.3 验证大小端模式:star:3. 数据范围3.1 整形溢出3.2 数据范围的求解3.3 练习:star:4. 浮点型在内存中的存储4.1 浮点数的存储规则4.2 练习5. :star::star:总结(思维导图)⭐️1. 数据类型 在了…

Android - 代码生成远程依赖库(阿里云)

一、注册 没有注册过阿里云且没有实名认证的点这里:阿里云官网 二、查看库 阿里云制品仓库Packages (注:如果没有创建企业或个人使用,按照提示,选个人使用) 三、选择类型 选择其中一个(两…

传统巨头生“变”,中国毫米波雷达市场战火再升级

进入2023年,中国车载毫米波雷达市场战火明显升级。 一方面,愈演愈烈的份额抢夺战不仅仅存在于几大传统巨头之间,也快速转移到与国产供应商之间;随着部分外资巨头的本土化战略深入落地,同时对国产供应商造成了压力。 …

ur3+robotiq ft sensor+robotiq 2f 140配置gazebo仿真环境

ur3robotiq ft sensorrobotiq 2f 140配置gazebo仿真环境 搭建环境: ubuntu: 20.04 ros: Nonetic sensor: robotiq_ft300 gripper: robotiq_2f_140_gripper UR: UR3 通过上一篇博客配置好ur3、力传感器和robotiq夹爪的rviz仿真环境后,现在来配置一下对…

MySQL数据库————MVCC

MySQL的脏读、幻读、不可重复读 脏读 现在有两个事务在操作table表,事务B修改了id2的name字段为李老四,但是没有提交,事务A查询id2的数据,得到name为李老四;事务B发生回滚,id2的数据的name又变回李四&…

性能测试知多少?怎样开展性能测试

看到好多新手,在性能需求模糊的情况下,随便找一个性能测试工具,然后就开始进行性能测试了,在这种情况下得到的性能测试结果很难体现系统真实的能力,或者可能与系统真实的性能相距甚远。 与功能测试相比,性能…

【Spring Boot 原理分析】- 自动配置

【Spring Boot 原理分析】- 自动配置 Condition 注解 Condition 是 Spring 4.0 增加的条件判断功能,通过这个功能可以实现选择的创建 Bean 操作 👑 我们在使用 Spring 的时候,只需导入某个依赖的坐标,就可以直接通过 Autwired 注…

堆,堆构建,堆排序,PriorityQueue和TopN问题

零. 前言 堆作为一种重要的数据结构,在面笔试中经常出现,排序问题中,堆排序作为一种重要的排序算法经常被问道,大顶堆小顶堆的应用经常出现,经典的问题TopN问题也是堆的重要应用,因此,了解并掌握…

Mac - Spotlight(聚焦)

文章目录一、Mac 中 Spotlight 的使用1、调用/打开 Spotlight2、执行搜索3、Spotlight 设置二、Mac 上的 Spotlight 开发1、关于 Spotlight2、使用 NSMetadataQuery 搜索示例三、mds 和 fsevents四、命令行访问 Spotlight五、Core Spotlight Framework六、Spotlight 插件相关资…

CSS预处理器sass和less

文章目录CSS预处理器什么是CSS预处理器Sass和LESS背景介绍Sass背景介绍LESS的背景介绍Sass安装Sass下载Ruby安装文件安装Ruby安装Sass编译Sass命令行编译命令行编译配置选项四种编译排版演示nested 编译排版格式expanded 编译排版格式compact 编译排版格式compressed 编译排版格…

登录逻辑漏洞整理集合

目录一、任意用户注册1.未验证邮箱/手机号2、不安全验证邮箱/手机号3.批量注册4.个人信息伪造5.前端验证审核绕过6.用户名覆盖二、任意用户登录1、万能密码2、验证码、密码回显3、登录检测不安全三、任意账号重置1、重置账号名2、验证码3、MVC数据对象自动绑定4、Unicode字符处…

独立产品灵感周刊 DecoHack #048 - 优秀独立开发产品推荐

如果有关注我的 Twitter 的朋友应该看到了,我上周末研究了两天 AI 画图,现在用 Ai 做图太强了,上周又升级 Stable Diffusion 玩了一下,和我去年试的时候相比强大了好多,而且插件LoRA模型玩法都还在快速迭代&#xff0c…