计算机图形学理论(3):着色器编程

本系列根据国外一个图形小哥的讲解为本,整合互联网的一些资料,结合自己的一些理解。

CPU vs GPU

CPU支持:

  • 快速缓存
  • 分支适应性
  • 高性能

GPU支持:

  • 多个 ALU
  • 快速板载内存
  • 并行任务的高吞吐量(在每个片段、顶点上执行着色器程序)

CPU 是更复杂的计算单元,因为它具有大量指令来支持各种功能。而GPU以SIMD方式工作(单指令多数据),它擅长使用数千个核心以并行方式处理大量数据。综上所述,CPU 非常适合任务并行性,GPU 非常适合数据并行。

渲染管线比较

固定管线可编程管线
左侧的固定管线提供了固定的渲染管道,光栅化后有固定的方式处理顶点和片段。而可编程管道使我们能够灵活地控制顶点和片段处理器。

顶点处理器的输入/输出

作为输入数据,每个顶点中存储有颜色、法线、位置、纹理坐标和其他数据。

纹理数据是着色器变量,通常尺寸较大且速度较慢。

模型视图矩阵、材质和光照都是uniform变量,这些由所有顶点共享。
image.png

片段处理器的输入/输出

大多数输入数据来自顶点处理器。

例如,当我们想要使用 Gouraud 着色渲染场景时,我们应该在顶点着色器中为每个片段插入颜色因子。然后,在片段着色器中,我们只需将计算出的颜色分配给每个片段。
image.png

着色器如何通信?

  • uniform参数:在整个执行过程中设置。
  • attribute参数:为每个顶点设置。
  • varying参数:从顶点着色器传递到片段着色器(例如逆转换法线)。对于不同的参数,两个处理器中使用相同的变量名称。

image.png

如何编写着色器

在现代openGL中,我们应该在着色器程序中编写光照处理逻辑。与简单着色方法相关,有两种着色方式:

  • 逐顶点着色(gouraud 着色)

通过这种方式,我们计算顶点着色器内部的照明,然后将varying参数传递给片段着色器。

  • 逐片段着色(phong 着色)

在片段着色中,对每个顶点的法线进行插值,然后通过将发现作为varying参数在片段着色器中计算照明。

归一化

照明计算可以使用法线向量和光方向向量的点积来计算。

我们可以采用单位向量来简化计算,因为两个向量归一化后点积的结果等于余弦项。

由于经过各种变换,向量的长度并不总是相同。所以在这种情况下我们需要不断地对向量进行归一化。
image.pngimage.png
在右侧图像中,解释了如何获取三角形的法向量。

假设我们知道组成三角形的三个点,我们可以通过点相减得到三角形边的两个向量。然后,如果我们对顺时针方向的两个边向量进行叉积,我们可以得到一个与三角形表面正交的向量。经过归一化,最终我们得到了三角形的法向量。

2. 指定光源(静态)

对于每个光源,我们可以设置一个RGBA。

vec4 diffuse0 = vec4(1.0, 0.0, 0.0, 1.0);
vec4 ambient0 = vec4(1.0, 0.0, 0.0, 1.0);
vec4 specular0= vec4(1.0, 0.0, 0.0, 1.0);
vec4 light_pos = vec4(1.0, 2.0, 3.0, 1.0);

image.png
局部 BRDF 照明模型遵循此方程。

根据光源的类型,我们需要不同地计算照度。
image.png

3. 移动光源

光源是其位置或方向受模型视图矩阵影响的几何对象。

如果我们将灯安装在汽车上,光源就会随着汽车移动。 (需要更新位置)
image.png

4. 材质属性

根据材质属性,相同的照明可以以不同的方式表示。

5. 背面可见性

大多数情况下,物体是不透明的,无法看到物体的背面。

但是,如果一个物体具有像镜子一样的透明面,则背面的法线向量将变得与正面的方向相似。也就是说,它是可见的。

我们也可以在着色器中处理这个问题。
image.png

Shader程序示例(Gouraud着色)

  • 顶点着色器
in vec4 vPosition; 
in vec3 vNormal;
//using vPosition & vNormal attribute, we calculate this
out vec4 color; // vertex shade// light and material properties
uniform vec4 ambientProduct, diffuseProduct, specularProduct
uniform mat4 modelView
uniform mat4 projection;
uniform vec4 lightPos;
uniform float shininess;void main() 
{// Transform vertex position into eye coordinates.vec3 pos = (modelView * vPosition).xyz; // swizzling component;vec3 L = normalize(lightPos.xyz - pos);vec3 E = normalize(-pos);vec3 H = normalize(L+E);// Transform vertex normal into eye coordinatesvec3 N = normalize(ModelView * vec4(vNormal, 0.0).xyz);// compute terms in illumination equation.// assume no atteunationfloat kd = max(dot(N,L), 0.0);vec4 diffuse = kd * diffuseProduct;float ks = pow(max(dot(N,H),0.0), shininess); // simplified phong modelvec4 specular = ks * specularProduct;if(dot(L,N) < 0.0) specular = vec4(0.0,0.0,0.0, 1.0);// gl_Position is built-in uniform variablegl_Position = projection * modelView * vPosition;// output.color = ambientProduct + diffuse + specular;color.a = 1.0;}
  • 片段着色器
in vec4 color;void main()
{gl_FragColor = color;
}

着色器中的纹理映射

应用纹理的三个基本步骤:

  1. 在应用程序中指定纹理
  • 读取或生成图像(例如读取png文件,自己生成深度图)
  • 将其分配给纹理(此处应用最近邻/线性插值/MipMap 算法)
  • 启用纹理
  1. 给顶点指定纹理坐标

image.png

  1. 指定纹理参数(包裹wrapping、过滤filtering)

纹理如何映射到对象?

在 UV 坐标中,每个颜色信息都是针对每个位置定义的。

根据我们设置的纹理坐标,映射到相应的UV坐标并得到它的颜色。
image.png

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

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

相关文章

反激式开关电源电路的测试记录(一)

反激式开关电源电路的测试记录&#xff08;一&#xff09; Chapter1 反激式开关电源电路的测试记录&#xff08;一&#xff09;一、测前准备二、测试总结 Chapter2 反激式开关电源电路测试记录&#xff08;二&#xff09;Chapter3 UC3842电源管理芯片详细解读一、管脚描述&…

蓝桥杯2020年5月青少组Python程序设计国赛真题

1、 上边是一个算法流程图,最后输出的b的值是() A.377 B.987 C.1597 D.2584 2、 3、如果整个整数X本身是完全平方数,同时它的每一位数字也都是完全平方数我们就称X 是完美平方数。前几个完美平方数是0、1、4、9、49、100、144......即第1个完美平方数是0,第2个是 1,第3个…

TypeScript学习笔记归纳(持续更新ing)

文章目录 前言 二、TypeScript的优势体现在哪里&#xff1f; 1、执行时间上的区别 2、基础数据类型区别 3、TS优势 三、TypeScript的关键特性 四、TypeScript的类型系统 1、什么是类型注释&#xff1f; 2、类型系统核心 - 常用类型 1&#xff09; 基本类型&#xff0…

Verilog RAM/ROM的数据初始化

文章目录 一、初始化方式二、测试 FPGA设计中RAM和ROM作为存储器用来存储可变或不可变类型的数据。 ROM初始化一般是加载固定数据&#xff0c;RAM声明时默认为不定态数据&#xff0c;初始化时可以让数据为全1或者全0。 一、初始化方式 复位时按地址写入初值always (posedge cl…

基于阿里云服务网格流量泳道的全链路流量管理(二):宽松模式流量泳道

作者&#xff1a;尹航 在前文基于阿里云服务网格流量泳道的全链路流量管理&#xff08;一&#xff09;&#xff1a;严格模式流量泳道中&#xff0c;我们介绍了使用服务网格 ASM 的严格模式流量泳道进行全链路灰度管理的使用场景。该模式对于应用程序无任何要求&#xff0c;只需…

Linux poll 和 select 机制

poll select 介绍 使用非阻塞 I/O 的应用程序常常使用 poll, select, 和 epoll 系统调用. poll, select 和 epoll 本质上有相同的功能: 每个允许一个进程来决定它是否可读或者写一个 或多个文件而不阻塞. 这些调用也可阻塞进程直到任何一个给定集合的文件描述符可用来 读或写.…

Linux 宝塔mysql莫名其妙数据库不见了恢复数据库

起因&#xff1a;宝塔安装的mysql 线上运行突然表包括库都不见了&#xff0c;想办法恢复数据库 登陆mysql cd /www/server/mysql/binmysql -u root -p查看binlog日志是否打开 show variables like log_%;log_bin如果为 ON 则为开启状态&#xff0c;如果开启了才可以进行下一…

C# WPF上位机开发(从demo编写到项目开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 C# WPF编程&#xff0c;特别是控件部分&#xff0c;其实学起来特别快。只是后面多了多线程、锁、数据库、网络这部分稍微复杂一点&#xff0c;不过…

【贪心】单源最短路径Python实现

文章目录 [toc]问题描述Dijkstra算法Dijkstra算法应用示例时间复杂性Python实现 个人主页&#xff1a;丷从心 系列专栏&#xff1a;贪心算法 问题描述 给定一个带权有向图 G ( V , E ) G (V , E) G(V,E)&#xff0c;其中每条边的权是非负实数&#xff0c;给定 V V V中的一个…

计算机网络-网络层

计算机网络-网络层 以下笔记整理为哔哩哔哩湖科大教书匠的《计算机网络微课堂》的教学视频。 链接&#xff1a;计算机网络微课堂 1. 网络层概述 1.1 网络层的主要任务是实现网络互联&#xff0c;进而实现数据包在各网络之间的传输。 1.2 要实现网络层任务&#xff0c;需要解决…

nodejs+vue+微信小程序+python+PHP计算机网络在线考试系统-计算机毕业设计推荐

信息数据的处理完全依赖人工进行操作&#xff0c; 所以电子化信息管理的出现就能缓解以及改变传统人工方式面临的处境&#xff0c;一方面可以确保信息数据在短时间被高效处理&#xff0c;还能节省人力成本&#xff0c;另一方面可以确保信息数据的安全性&#xff0c;可靠性&…

python实现批量替换目录下多个后缀为docx文档内容

批量替换目录下多个后缀为docx文档内容 摘要&#xff1a; 本文将介绍如何使用Python实现批量替换目录下多个后缀为docx文档内容。通过使用Python的os和glob模块&#xff0c;我们可以轻松地遍历目录下的所有文件&#xff0c;并对每个文件进行操作。此外&#xff0c;我们还将使用…