图形学基础概念梳理以及OpenGL初识------计算机图形学高质量实时渲染(一)

图形学基础概念梳理以及OpenGL初识

在这里插入图片描述

本节课目录:

1.复习计算机图形学基础
2.复习GPU渲染管线
3.OpenGL 和GLSL
4.渲染方程
5.相关微积分知识

图形渲染管线

先对渲染管线进行一个复习
我们知道物体在最开始是3D的模型,经过渲染后会最终得到一张图,而这中间经过了一些系列的操作,这个过程我们称其为渲染管线(渲染流水线)

渲染管线的一系列操作是现代GPU上完成的,因为GPU完成或者说是计算的快,因为GPU的并行度比较高。
在这里插入图片描述
3D物体在空间中以一堆点和点的连接关系来表示,每个点都会经过第一个步骤顶点处理,也就是经过一系列的变换,如MVP变换,ViewPoint变换,从而变换成屏幕上的一个点。
在这里插入图片描述
经过这一些系列的变换之后,各点之间的连接关系是不会变换的,只是点被投影到了屏幕上,因此变换前的三个点所组成的三角形在变换后仍由这三个点组成三角形。

三角形投影到屏幕上后我们要进行光栅化操作来将三角形离散成一堆像素(或者是fragment)
在这里插入图片描述
在打散成像素的过程中我们要使用深度缓存来处理解决遮挡问题。
在这里插入图片描述
接着我们进行着色处理,这就是计算它应该长什么样子,比如布林冯着色模型。

布林冯是一个经验式模型,因此它并不是完美的,它对全局或者是间接光照是一个近似的做法,它对全局的一些现象处理的不好,比如阴影,光线的多次弹射。
在这里插入图片描述
在着色过程中,我们可以在三角形内部或者是整个物体上的任意一个地方得到一个纹理的坐标,从而把一张图给贴在上面,或者根据它的纹理坐标,任一个位置我们都可以知道在纹理的哪个地方去查询。
同时我们还提到了一个叫插值的概念,也就是说我们知道三角形三个顶点对应的纹理坐标,我们可以通过插值来在三角形内部的任一位置得到一个平滑的纹理过度。
最终我们得到一张成图。

OpenGL

首先什么是OpenGL:
OpenGL是一系列在cpu端上负责调动GPU的API,也就是在CPU端写的,我们可以知道OpenGL用什么语言写是没有关系的。
我们更关心的是GPU怎么去执行,而不是CPU如何让GPU去执行。
在这里插入图片描述
OpenGL的一个特点:
可以跨平台。
OpenGL的一个缺点:
1.版本过于碎片化。
2.C风格语言,不是很好用。
OpenGL就像画油画
我们要渲染一个3D场景,我们类比画油画的各个步骤:

1.摆好物体和模型

在这里插入图片描述
在摆好物体和模型之前我们会有两个问题:
a)我们需要告诉GPU我们要用什么样的模型
在OpenGL中我们通过VBO我们可以把需要渲染的图元的顶点信息,直接上传存储在GPU的显存中。
VBO就是GPU中一块用来存储你的模型的区域。模型的存储方式与存储三角形的.obj方式相似,存储一堆vertices,normal,texture coords等以一定的格式组织了一个物体应该放在GPU何处。
b)模型应该如何摆放
在101中我们需要自己手写各种矩阵来进行物体的运动,而在OpenGL当中内置了这些函数,我们只需要调动函数写入参数即可,不用再自己去写函数。

2.架好画架

在这里插入图片描述
架好画架也会遇到两件事:
a)view transformation(视图变换)
首先放置相机,在101中仍然是我们自己去推导和写的矩阵,而opengl的api简化了摄像机的视图变化,让一切变得简单了很多。
我们只需要规定相机的一些属性就可以了,比如说:
fov(可视角度),aspect(长宽比),zNear(近平面),zFar(远平面)

b)create/use a framebuffer(建立画架)
要建立opengl画架,就是framebuffer,为了要使用一个画架,我们一定要在上面贴(attach)一块画布(buffer或者是texture)的,因此到第三步。

3.在画架上贴上一块画布

在这里插入图片描述
framebuffer对场景渲染一次,可以用渲染出好几张不同性质的纹理,(这也解释了第5点画好一张后换画布可以继续画),最后由fragment shader告诉你要写到哪一个纹理上去。

也就是你从一个角度看过去渲染一次场景可以输出好几张不同的图,可能有一张是shading的结果,有一张是深度。

例如这几张图就是通过MRT在对场景渲染一次后得到的四张不同性质的图:
在这里插入图片描述
在这里插入图片描述
我们也是可以直接把framebuffer渲染的结果显示到屏幕上的,但是直接把framebuffer的渲染结果放在屏幕上会造成屏幕撕裂,因为你这一帧还渲染下一半,下一帧就开始渲染覆盖你这一帧所看到的的内容,从而导致了屏幕撕裂。

在游戏中常有一个叫做垂直同步的设置能解决这个问题,或者先把渲染好的结果存储在一个纹理或者缓冲区内,确定没问题再放在屏幕上,这种方法叫做双缓冲,更复杂的还有三缓冲。

4.在画布上绘画

我们要把场景给画在画布上,那么无论如何我们肯定要进行shading,那么:
如何做shading呢?(我们在101中已经讲的很清楚了)
课程中只会用到顶点着色和像素着色。
顶点着色的话,每个顶点的要在顶点着色器操作,首先要进行mvp的投影,到达裁剪坐标系,齐次裁剪后经过透视除法,到达NDC,之后再通过视口变换到屏幕坐标系中。之后我们将需要做插值的值进行插值得到结果后,再将结果传递到像素着色器。
那么像素得到的输入就是顶点着色器的输出在上一个顶点的属性,接着就会被插值到任何一个像素的属性上。

OpenGL会将三角形打成一堆像素,然后对每个像素着色。
这门课程最重要的就是我们如何去写顶点着色器和片段着色器。

我们来做一个简单的总结:
在这里插入图片描述
opengl就是告诉GPU在每一趟渲染中需要:
1.指定物体,相机,mvp矩阵等
2.指定framebuffer和输出纹理
3.指定vertex,fragment shader
4.(当在gpu里确定了一切)渲染

5.在画新画时可以采用或者参考旧画上的内容

之前渲染的纹理可以给之后渲染参考(多pass渲染)
那么为什么场景要渲染多次?
我们以shadow map为例,它是一个典型的两趟做法,从light和camera分别去看场景,因此在light得到的深度这个一个纹理,我们可以在camera时候再去用它。
同样类似的还有延迟渲染,pre-z这些多pass算法。(一般为2-pass)。

OpenGL Shading Language(GLSL)

顾名思义,就是着色器怎么操作的语言就是着色语言,着色语言风格偏C语言。

怎么使用shader?

首先要写shader,然后让opengl去编译shader,但是你可能会比编译fragment shader或者是vertex shader,因此可以建立program集合了你写的所有自定义shader,再做一个链接,最后使用链接好的program渲染。
写shader可以近似于在cpu上编程,两者十分相似。
在这里插入图片描述

Vertex Shader

attribute(顶点属性关键字只在vertex shader出现)
vec3(3维向量)
aVertexPosition(获取顶点位置)
vec4(aVertexPosition,1.0)定义一个4维向量只要3维向量后面跟一个数。
varying(需要传递fragment shader)
high(定义计算精度)
vec2 vNormal;
uniform(全局变量)
在这里插入图片描述

Fragment Shader

实例这个片段着色器是一个blinn-phong像素着色器。
color= pow(texture2D(uSampler,vTextureCoord).rgb,vec3(2.2)(伽马矫正))。
gl_FragColor(输出颜色) = …
在这里插入图片描述
在这里插入图片描述

Debug

早年debug只有Nvida NSight能调试glsl,hlsl只能在软件上运行来debug
现在,对于N卡,可以用nsight graphics跨平台,但是只支持nvidia
强推renderdoc,对显卡品牌没什么要求
RGB调试法

The Rendering Equation(渲染方程)

在games101中,我们整个path tracing的体系是建立在rendering equation上的,因为他是一个正确的用来描述光线传播的一个方法。
在这里插入图片描述
Rendering Equation是一个正确的用来描述光线传播的等式,讲的是:
看到的任何一个点p反射到眼中的radiance = 这个点P本身发出的radiance+其他打到这个点的radiance 乘以brdf乘以cos。
在这里插入图片描述
我们在指brdf时候可能指原始brdf,也可能指cosine-weighted brdf
visibility是在实时渲染中我们需要考虑到物体会不会被光源照射到,比如在一点P往一方向去看,我们知道这一方向有光源发出光线的,但是光线能否打到p上,因此引出了visibility的概念。

RealTime Rendering会显式的考虑visibility,他与原先的理解是等价的,之所以这么理解是为了能够更好的理解环境光照,要比不写visibility项更加的直观。
在这里插入图片描述
任一方向过来的光的强度只能由一张图来决定,可以一个是立方体贴图(cubemap)也可以是定义在球上的一张图(sphere map)。
这两种表示都有不同的问题,在本课程中会介绍一种新的表示,以八面体来表示。

此时只需要考虑说,从任何一个shading point往那个方向看去,看这个visibility是否可见,等于将实际上的光源和能否看到他,把这两项拆开考虑了,就很方便。

间接光照

光线会进行弹射,形成间接光照,将间接光照加到直接光照上就是全局光照,实现全局光照就是要解决间接光照。

全局光照 = 直接光照+间接光照。只看直接光照也被成为局部光照模型。
在这里插入图片描述
在这里插入图片描述
我们可以看出,图像越亮越NB.

课堂答疑整理

  • 1.问:怎么定义哪些点连接成三角形?
    答:比如obj格式是先给一系列点进行编号,再去定义面,每个面都带着三个点的编号的下标。
  • 2.问:有无适合全局光照的管线?
    答:无,但光线追踪渲染管线很完善。
  • 3.问:纹理坐标怎么进行参数化?
    答:可以理解为物体外面有个盒子,把盒子挤压到物体上,盒子上的uv是比较好进行确定的。
  • 4.问:几个光源就需要几个shadowmap吗?光源也需要深度测试吗?
    答:是
  • 5.问:纹理是不是是个buffer?
    答:opengl里两者的定义不一样,但也可以这样理解,理解为显存里面的一块缓存区域。
  • 6.问:opengl支持optix吗?
    答:可以,但不要指望shader能调用一个光线一个场景怎么运作。
    PS:OptiX,是Nvidia的一个光线追踪引擎。
    用于在 GPU 上实现出色光线追踪性能的应用框架。提供简单、递归式的灵活工作流,用于加速光线追踪算法。它包含可编程相交、光线生成和着色功能,可将 NVIDIA GPU 的强大功能引入光线追踪应用。
  • 7.问:一个pass就是一个fragmentbuffer渲染一次吗?
    答:一个场景渲染一次。
  • 8.问:不同shader里定义里的变量会通用吗?答:不是。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值