赞
踩
1.复习计算机图形学基础
2.复习GPU渲染管线
3.OpenGL 和GLSL
4.渲染方程
5.相关微积分知识
先对渲染管线进行一个复习
我们知道物体在最开始是3D的模型,经过渲染后会最终得到一张图,而这中间经过了一些系列的操作,这个过程我们称其为渲染管线(渲染流水线)
渲染管线的一系列操作是现代GPU上完成的,因为GPU完成或者说是计算的快,因为GPU的并行度比较高。
3D物体在空间中以一堆点和点的连接关系来表示,每个点都会经过第一个步骤顶点处理,也就是经过一系列的变换,如MVP变换,ViewPoint变换,从而变换成屏幕上的一个点。
经过这一些系列的变换之后,各点之间的连接关系是不会变换的,只是点被投影到了屏幕上,因此变换前的三个点所组成的三角形在变换后仍由这三个点组成三角形。
三角形投影到屏幕上后我们要进行光栅化操作来将三角形离散成一堆像素(或者是fragment)
在打散成像素的过程中我们要使用深度缓存来处理解决遮挡问题。
接着我们进行着色处理,这就是计算它应该长什么样子,比如布林冯着色模型。
布林冯是一个经验式模型,因此它并不是完美的,它对全局或者是间接光照是一个近似的做法,它对全局的一些现象处理的不好,比如阴影,光线的多次弹射。
在着色过程中,我们可以在三角形内部或者是整个物体上的任意一个地方得到一个纹理的坐标,从而把一张图给贴在上面,或者根据它的纹理坐标,任一个位置我们都可以知道在纹理的哪个地方去查询。
同时我们还提到了一个叫插值的概念,也就是说我们知道三角形三个顶点对应的纹理坐标,我们可以通过插值来在三角形内部的任一位置得到一个平滑的纹理过度。
最终我们得到一张成图。
首先什么是OpenGL:
OpenGL是一系列在cpu端上负责调动GPU的API,也就是在CPU端写的,我们可以知道OpenGL用什么语言写是没有关系的。
我们更关心的是GPU怎么去执行,而不是CPU如何让GPU去执行。
OpenGL的一个特点:
可以跨平台。
OpenGL的一个缺点:
1.版本过于碎片化。
2.C风格语言,不是很好用。
OpenGL就像画油画
我们要渲染一个3D场景,我们类比画油画的各个步骤:
在摆好物体和模型之前我们会有两个问题:
a)我们需要告诉GPU我们要用什么样的模型
在OpenGL中我们通过VBO我们可以把需要渲染的图元的顶点信息,直接上传存储在GPU的显存中。
VBO就是GPU中一块用来存储你的模型的区域。模型的存储方式与存储三角形的.obj方式相似,存储一堆vertices,normal,texture coords等以一定的格式组织了一个物体应该放在GPU何处。
b)模型应该如何摆放
在101中我们需要自己手写各种矩阵来进行物体的运动,而在OpenGL当中内置了这些函数,我们只需要调动函数写入参数即可,不用再自己去写函数。
架好画架也会遇到两件事:
a)view transformation(视图变换)
首先放置相机,在101中仍然是我们自己去推导和写的矩阵,而opengl的api简化了摄像机的视图变化,让一切变得简单了很多。
我们只需要规定相机的一些属性就可以了,比如说:
fov(可视角度),aspect(长宽比),zNear(近平面),zFar(远平面)
b)create/use a framebuffer(建立画架)
要建立opengl画架,就是framebuffer,为了要使用一个画架,我们一定要在上面贴(attach)一块画布(buffer或者是texture)的,因此到第三步。
framebuffer对场景渲染一次,可以用渲染出好几张不同性质的纹理,(这也解释了第5点画好一张后换画布可以继续画),最后由fragment shader告诉你要写到哪一个纹理上去。
也就是你从一个角度看过去渲染一次场景可以输出好几张不同的图,可能有一张是shading的结果,有一张是深度。
例如这几张图就是通过MRT在对场景渲染一次后得到的四张不同性质的图:
我们也是可以直接把framebuffer渲染的结果显示到屏幕上的,但是直接把framebuffer的渲染结果放在屏幕上会造成屏幕撕裂,因为你这一帧还渲染下一半,下一帧就开始渲染覆盖你这一帧所看到的的内容,从而导致了屏幕撕裂。
在游戏中常有一个叫做垂直同步的设置能解决这个问题,或者先把渲染好的结果存储在一个纹理或者缓冲区内,确定没问题再放在屏幕上,这种方法叫做双缓冲,更复杂的还有三缓冲。
我们要把场景给画在画布上,那么无论如何我们肯定要进行shading,那么:
如何做shading呢?(我们在101中已经讲的很清楚了)
课程中只会用到顶点着色和像素着色。
顶点着色的话,每个顶点的要在顶点着色器操作,首先要进行mvp的投影,到达裁剪坐标系,齐次裁剪后经过透视除法,到达NDC,之后再通过视口变换到屏幕坐标系中。之后我们将需要做插值的值进行插值得到结果后,再将结果传递到像素着色器。
那么像素得到的输入就是顶点着色器的输出在上一个顶点的属性,接着就会被插值到任何一个像素的属性上。
OpenGL会将三角形打成一堆像素,然后对每个像素着色。
这门课程最重要的就是我们如何去写顶点着色器和片段着色器。
我们来做一个简单的总结:
opengl就是告诉GPU在每一趟渲染中需要:
1.指定物体,相机,mvp矩阵等
2.指定framebuffer和输出纹理
3.指定vertex,fragment shader
4.(当在gpu里确定了一切)渲染
之前渲染的纹理可以给之后渲染参考(多pass渲染)
那么为什么场景要渲染多次?
我们以shadow map为例,它是一个典型的两趟做法,从light和camera分别去看场景,因此在light得到的深度这个一个纹理,我们可以在camera时候再去用它。
同样类似的还有延迟渲染,pre-z这些多pass算法。(一般为2-pass)。
顾名思义,就是着色器怎么操作的语言就是着色语言,着色语言风格偏C语言。
首先要写shader,然后让opengl去编译shader,但是你可能会比编译fragment shader或者是vertex shader,因此可以建立program集合了你写的所有自定义shader,再做一个链接,最后使用链接好的program渲染。
写shader可以近似于在cpu上编程,两者十分相似。
attribute(顶点属性关键字只在vertex shader出现)
vec3(3维向量)
aVertexPosition(获取顶点位置)
vec4(aVertexPosition,1.0)定义一个4维向量只要3维向量后面跟一个数。
varying(需要传递fragment shader)
high(定义计算精度)
vec2 vNormal;
uniform(全局变量)
实例这个片段着色器是一个blinn-phong像素着色器。
color= pow(texture2D(uSampler,vTextureCoord).rgb,vec3(2.2)(伽马矫正))。
gl_FragColor(输出颜色) = …
早年debug只有Nvida NSight能调试glsl,hlsl只能在软件上运行来debug
现在,对于N卡,可以用nsight graphics跨平台,但是只支持nvidia
强推renderdoc,对显卡品牌没什么要求
RGB调试法
在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.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。