基于物理的渲染(PBR)

在前面介绍了BDRF函数,那么具体这个函数是什么样子的我们并不知道。接下来简单介绍常用的BRDF函数。

Phong BRDF

在学习PBR之前,我们最常用的是Phong光照模型,为了使得Phong具有物理意义,定义Phong BRDF:

  • $\alpha$是光线出射方向与入射光线理想镜面反射方向之间的夹角;
  • $k_d$是漫反射率(diffuse reflectivity),即投射到物体表面的能量中发生漫反射的比例;
  • $k_s$是镜面反射率(specular reflectivity),即垂直投射到物体表面的能量中被镜面反射的比例;
  • $n$是镜面指数(specular exponent),更高的值会产生更清晰的镜面反射;
  • 为了满足能量守恒,限制$k_d+k_s\le 1$。

Untitled

Read more

深度重建世界坐标

熟悉MVP流程

MVP变换中,一般是这样得到裁剪坐标:

之后,经过透视除法,得到NDC坐标:

深度重建世界坐标

正常的MVP变换中,一般由如下操作获得裁剪坐标:

然后进行透视除法获得NDC坐标:

现在我们需要将NDC坐标逆推回世界坐标,容易知道:

构造一个新的clipPos:

带入回去,得到:

但注意到$\bf worldPos.w=1$,于是:

所以可以间接求出$\bf clipPos.w$

代入原式,得到:

因此我们不需要$\bf clipPos.w$也是可以得到世界坐标的,因为$\bf ((PV)^{-1}\times (NDCPos, 1)).w$其实就是$\bf worldPos.w$,所以只要算出$\bf (PV)^{-1}\times (NDCPos, 1)$,然后除以自身即可!

代码如下:

1
2
3
4
float depth = texture(depthTex, texcoord);
vec4 ndcPos = vec4(2 * texcoord, 2 * depth - 1, 1.0f);
vec4 worldPos = InverseVP * ndcPos;
worldPos.xyz /= worldPos.w
Read more

辐射度量学与光线追踪原理

辐射度量学

背景

Phong和Blinn-Phong的经验模型过于经验,没有严谨的物理定义,所以计算机图形学急需要一个能够符合物理基本规律的光照知识,这就是辐射度量学提出的背景(基于物理光学)。

概念

  1. 辐射能$Q$,单位是焦耳,是能量,表示穿过一个曲面(类似于电磁学的高斯面)的光能。
  2. 辐射通量$\phi$,表示单位时间内穿过曲面的光能(注意是单位时间,辐射通量等价于功率)

  3. 立体角$\omega$(针对球面坐标系),类比于平面角(针对极坐标系):

    可以得到立体角的公式:

    Untitled

Read more

投影矩阵的具体推导

正交投影

正交投影的步骤是先平移到世界原点,然后进行缩放,把视界体缩放成长度为2的正方体,取值为$[-1,1]^3$:

Untitled

左极端点为$(left,bottom,-near)$,右极端点为$(right,top,-far)$

用矩阵变换描述上述过程:

其中,平移的时候,应当让视见体的中心$\left(
\frac{right+left}{2},
\frac{top+bottom}{2},
-\frac{near+far}{2}
\right)$移动到世界原点,于是平移矩阵如下:

Read more

CG_Final : 2020级计算机图形学期末大作业

截图 2023-03-05 03-09-46

构建

项目地址:https://github.com/InverseDa/CG_Final

Windows

对于Windows用户,需要安装vcpkg:https://vcpkg.io/en/index.html

配置好vcpkg之后可以直接使用

1
vcpkg install glfw assimp

之后使用cmake构建(推荐用Visual Studio的MSVC)

1
cmake -DCMAKE_TOOLCHAIN_FILE=<path\to\vcpkg>\scripts\buildsystems\vcpkg.cmake -B . -G "Visual Studio 17 2022"

构建完毕后打开sln文件即可

Read more

OpenGL教程:13. 深度测试

一般情况下,OpenGL在渲染物体的时候,总是有个“先来后到”的顺序。比如一开始渲染了三角形,后来在三角形的位置上渲染矩形,那么这个矩形就会覆盖三角形。

在三维空间也有类似的情况,比如渲染正方体,如果先渲染前面,然后渲染后面,那么后面就会覆盖前面。一个简单的解决方案就是启用深度测试。

之前,我们渲染了一个3D箱子,并且运用了深度缓冲(Depth Buffer)来防止被阻挡的面渲染到其它面的前面。在这一节中,我们将会更加深入地讨论这些储存在深度缓冲(或z缓冲(z-buffer))中的深度值(Depth Value),以及它们是如何确定一个片段是处于其它片段后方的。

深度缓冲就像颜色缓冲(Color Buffer)(储存所有的片段颜色:视觉输出)一样,在每个片段中储存了信息,并且(通常)和颜色缓冲有着一样的宽度和高度。深度缓冲是由窗口系统自动创建的,它会以16、24或32位float的形式储存它的深度值。在大部分的系统中,深度缓冲的精度都是24位的。

当深度测试(Depth Testing)被启用的时候,OpenGL会将一个片段的深度值与深度缓冲的内容进行对比。OpenGL会执行一个深度测试,如果这个测试通过了的话,深度缓冲将会更新为新的深度值。如果深度测试失败了,片段将会被丢弃。

深度缓冲是在片段着色器(fragment shader)运行之后(以及模板测试(Stencil Testing)运行之后。

屏幕空间坐标与通过OpenGL的glViewport所定义的视口密切相关,并且可以直接使用GLSL内建变量gl_FragCoord从片段着色器中直接访问。gl_FragCoord的x和y分量代表了片段的屏幕空间坐标(其中(0, 0)位于左下角)。gl_FragCoord中也包含了一个z分量,它包含了片段真正的深度值。z值就是需要与深度缓冲内容所对比的那个值。

Read more
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×