GAMES101_notes_02
GAMES101: 现代计算机图形学入门
笔记02:Shading
Lesson 07 Shading 1(Illumination, Shading and Graphics Pipeline)
本讲内容:
- Visibility/ occlusion
- Z-buffering
- Shading
- Illumination & Shading
- Graphics Pipeline
Visibility 可见性
Painter’s Algorithm
受油画绘画技术的启发,作画时应当先画远处的物体,再画近处的物体,从而保证物体遮挡的结果是正确的
问题是如何判断哪个物体远,哪个物体近?相同远近的物体,绘画顺序怎么样确定?
需要首先对三角形进行排序,需要$O(n\log n)$的时间,但是不能完全解决问题
Z-buffer 深度缓存
用于解决上述提到的问题
Idea:
- Store current min. z-value for each sample(pixel)
- Needs an additional buffer for depth values
- frame buffer stores color values
- depth buffer (z-buffer) stores depth
Important: For simplicity we suppose $z$ is always positive(smaller $z$ -> closer, larger $z$ -> further)
算法流程
- Initialize depth buffer to $\infty$
- During rasterization:
for(each triangle T)
for(each sample(x, y, z) in T)
if(z < zbuffer[x, y]) // closest sample so far
framebuffer[x, y] = rgb; // update color
zbuffer[x, y] = z; // update depth
else
; // do nothing, this sample is occluded
(目前只是说明在已知深度的情况下如何处理遮挡关系,还未介绍如何确定物体深度)
正确性和复杂度
复杂度
- 对于$n$个三角形只需要花费$O(n)$的时间
- 并不是排序算法,所以时间消耗是线性的
不同三角形处理顺序不改变结果(但是会被舍入误差影响)
Most important visibility algorithm
- Implemented in hardware for all GPUs
对于MSAA的影响
当采用MSAA时,深度缓存应当是对每个采样点,而不是对每个像素进行采样
Shading 着色
目前已经学过的内容:
- Position objects and the camera in the world 空间中的模型和摄像机
- Compute position of objects relative to the camera 计算模型位置
- Project objects onto the screen 投影
- Sample triangle coverage 光栅化
下一步的操作:着色(Shading)
Definition of Shading
- The definition in the dictionary: The darkening or coloring of an illustration or diagram with parallel lines or a block of color.
- The definition in this course: The process of applying a material to an object.
A Simple Shading Model(Blinn-Phong Reflectance Model)
Perceptual Observations
- Specular highlights 高光
- Diffuse reflection 漫反射
- Ambient lighting 环境光照
Shading is Local
Compute light reflected toward camera at specific shading point
Input:
- Viewer direction, $v$
- Surface normal, $n$
- Light direction(for each of many lights), $l$
- Surfaces parameters(colors, shininess, …)
注意:着色并不是添加阴影!(shading $\ne$ shadow)
Diffuse Reflection
- Light is scattered uniformly in all directions
- Surface color is the same for all viewing directions
- But how much light(energy) is received?
- Lambert’s cosine law:随着光线和平面法线夹角$\theta$的不断扩大,单位面积接收到的光线能量逐渐变小,比例满足$\cos \theta = l \cdot n$
Light Falloff 能量耗散
将光源视为一个持续释放能量的点,则随着传播距离的增加,能量的大小应当与距离的平方成反比。
Lambertian(Diffuse) Shading
Shading independent of view direction
\[L_d = k_d(I/r^2)\max(0, \mathbf{n} \cdot \mathbf{l})\]其中
- $L_d$: diffusely reflected light
- $k_d$: diffuse coefficient (color)
- $(I/r^2)$: energy arrived at the shading point
- $\max(0, \mathbf{n}\cdot \mathbf{l})$: energy received by the shading point
Lesson 08 Shading 2(Shading, Pipeline and Texture Mapping)
本讲内容:
- Blinn-Phong reflectance model
- Specular and ambient terms
- Shading frequencies
- Graphics pipeline
- Texture mapping
Blinn-Phong reflectance model
回忆上讲的漫反射项(Lambertian/Diffuse Term),可以发现漫反射项和观测方向$v$没有关系,对任意方向的反射光强度都是相同的。
Specular Term(Blinn-Phong)
Intensity depends on view direction
- Bright near mirror reflection direction
$v$ close to mirror direction $\Leftrightarrow$ half vector near normal
- Measure “near” by dot product of unit vectors
引入半程向量$\mathbf{h}$,可以避免计算反射向量$r$的困难,半程向量的计算公式如下:
\[\begin{align*} \mathbf{h} &= bisector(\mathbf{v}, \mathbf{l})\\ &= \frac{\mathbf{v}+\mathbf{l}}{\|\mathbf{v}+\mathbf{v}\|} \end{align*}\]则Blinn-Phong公式给出的镜面反射项为
\[\begin{align*} L_s &= k_s(I/r^2)\max(0, \cos \alpha)^p\\ &= k_s(I/r^2)\max(0, \mathbf{n} \cdot \mathbf{h})^p \end{align*}\]其中
- $L_s$: Specularly reflected light
- $k_s$: specular coefficient
- 余弦值添加指数参数$p$的原因:能够使高光得到加窄,使得只有最接近镜面反射的部分高光明显。一般$p$取$100-200$
Ambient Term(Blinn-Phong)
Shading that does not depend on anything
- Add constant color to account for disregarded illumination and fill in black shadows
- This is approximate / fake!
环境光项计算公式如下:
\[L_a = k_a I_a\]其中
- $L_a$: Reflected ambient light
- $k_a$: Ambient coefficient
综合上述内容,可得到Blinn-Phong反射模型:
\[\begin{align*} L &= L_a + L_d + L_s\\ &= k_aI_a + k_d(I/r^2)\max(0, \mathbf{n} \cdot \mathbf{l}) + k_s(I/r^2)\max(0, \mathbf{n} \cdot \mathbf{h})^p \end{align*}\]Shading Frequencies 着色频率
对每个平面上多少个点进行Shading,将会影响着色的结果
三种常见的着色方式:
- Flat Shading 逐面着色
- Triangle face is flat - one normal vector
- Not good for smooth surfaces
- Gouraud shading 逐顶点着色
- Interpolate colors from vertices across triangle
- Each vertex has a normal vector(how?)
- Phong shading 逐像素着色
- Interpolate normal vectors across each triangle
- Compute full shading model at each pixel
- Not the Blinn-Phong Reflectance Model
当几何体足够复杂的时候,逐面着色和逐顶点着色与逐像素着色的区别会变小。
Define Per-Vertex Normal Vectors
Best to get vertex normals from the underlying geometry. Otherwise have to infer vertex normal from triangle faces
- Simple scheme: Average surrounding face normals
Define Per-Pixel Normal Vectors
Barycentric interpolation (introducing soon) of vertex normals.
Don’t forget to normalize the interpolated directions
Graphics(Real-time Rendering) Pipeline
管线:从Input到Output的过程:
- Input: Vertices in 3D space
- Application:
- Vertex Processing: Vertices positioned in screen space
- Triangle Processing: Triangles positioned in screen space
- Rasterization: Fragments(one per covered sample)
- Fragment Processing: Shaded fragments
- Framebuffer Operations: Display
- Output: images(pixels)
过去学习的内容对应到pipeline中:
- MVP transforms: 1
- Sampling triangle coverage: 3
- Z-Buffer Visibility Tests: 4
- Shading: 1, 4(考虑不同的着色频率,着色发生的环节会不同)
- Texture mapping(introducing soon): 1, 4
Shader Programs
- Program vertex and fragment processing stages(分别称为vertex-shader和fragment-shader/pixel-shader)
- Describe operation on a single vertex(or fragment)
Example GLSL fragment shader program
uniform sampler2D my Texture; // program parameter
uniform vec3 lightDir; // program parameter
varying vec2 uv; // per fragment value(interp. by rasterizer)
varying vec3 norm; // per fragment value(interp. by rasterizer)
void(diffuseShader)()
{
vec3 kd;
kd = texture2d(myTexture, uv); // material color from texture
kd *= clamp(dot(-lightDir, norm), 0.0, 1.0); // Lambertian shading model
gl_FragColor = vec4(kd, 1.0); // Output fragment color
}
Remark:
- Shader function executes once per fragment;
- Outputs color of surface at the current fragment’s screen sample position;
- This shader performs a texture lookup to obtain the surfaces’s material color at this point, then performs a diffuse lighting calculation.
Modern development in CG
(省略该部分内容)
Texture Mapping
本质:在物体不同位置定义不同属性
Surfaces are 2D
Surface lives in 3D world space. Every 3D surface point also has a place where it goes in the 2D image(texture).
需要考虑物体平面和纹理空间的映射关系,纹理空间坐标系通过$u-v$坐标系表示,通过映射关系可以实现从$[0,1]^2$纹理空间到物体表面的映射
Textures can be used multiple times
通过设计纹理图样,可以实现同样纹理贴图的无缝衔接
Interpolation Across Triangles: Barycentric Coordinates(next lesson)
Lesson 09 Shading 3(Texture Mapping Cont.)
本讲内容:
- Barycentric coordinates 重心坐标
- Texture queries 添加纹理的流程
- Applications of textures 纹理相关应用
Interpolation Across Triangles: Barycentric Coordinates
为什么要进行插值?
- 在每个顶点定义固定值
- 我们希望能够在三角形中每点上平滑获得合适的值
对哪些内容进行插值?
- Texture coordinates, colors, normal vector, …
怎么做插值?
- Barycentric Coordinates
Barycentric Coordinates
三角形所在平面中的任一点,都可以用顶点坐标的线性组合来表示:
\[\mathbf{x} = \alpha A + \beta B + \gamma C\]其中三个系数需要满足
\[\alpha + \beta + \gamma = 1\]如果还满足$\alpha, \beta, \gamma \ge 0$,那么该点一定在三角形内。我们称$(\alpha, \beta, \gamma)$为该点关于三角形$ABC$的 重心坐标。
由上述定义,可知$A, B, C$三点的重心坐标分别是$(1,0,0), (0,1,0), (0,0,1)$;对于三角形内任意一点$\mathbf{X}$其重心坐标的三个分量$\alpha, \beta, \gamma$可以由如下公式得到:
\[\alpha = \frac{S_{\triangle XBC}}{S_{\triangle ABC}},\quad \beta = \frac{S_{\triangle XCA}}{S_{\triangle ABC}},\quad \gamma = \frac{S_{\triangle XAB}}{S_{\triangle ABC}}\]即三个分量的比等于其对应三个三角形的面积比。
三角形的重心,其重心坐标为$(\frac{1}{3}, \frac{1}{3}, \frac{1}{3})$
对于$x-y$平面上的三角形$ABC$与其中的一点$(x, y)$,利用上述的定义及叉乘的相关知识可以得到其重心坐标分量为
\[\alpha = \frac{-(x - x_B)(y_C - y_B) + (y - y_B)(x_C - x_B)}{-(x_A - x_B)(y_C - y_B) + (y_A - y_B)(x_C - x_B)},\\ \beta = \frac{-(x - x_C)(y_A - y_C) + (y - y_C)(x_A - x_C)}{-(x_B - x_C)(y_A - y_C) + (y_B - y_C)(x_A - x_C)},\\ \gamma = 1 - \alpha - \beta.\]Using Barycentric Coordinates
当给定三角形顶点的信息,我们就可以通过重心坐标计算得到相应的三角形中对赢点的信息
\[V = \alpha V_A + \beta V_B + \gamma V_C\]However, barycentric coordinates are not invariant under projection!
Applying Textures
Simple Texture Mapping: Diffuse Color
- For each rasterized screen sample $(x, y)$:
- $(u, v)$ = evaluate texture coordinate at $(x, y)$(using barycentric coordinates)
- texcolor = texture.sample $(u, v)$;
- set sample’s color to texcolor;
Texture Magnification(easy case)
当像素数量大于纹理贴图元素数量的时候,需要采用双线性插值(Bilinear Interpolation),来避免小纹理贴到大图上的时候过于失真的情况。
对于一个映射到纹理上坐标非整数的像素点,可以利用与其最近的四个纹理元素进行双线性插值,得到一个结果值
- Linear interpolation: $lerp(x, v_0, v_1) = v_0 + x(v_1 - v_0)$
- Two helper lerps: \(u_0 = lerp(s, u_{00}, u_{10})\\ u_1 = lerp(s, u_{10}, u_{11})\)
- Final vertical lerp, to get result: $f(x, y) = lerp(t, u_0, u_1)$
进一步,可以采取更高精度的多项式插值(双向三次样条插值)
Texture Magnification(hard case)
当纹理贴图元素数量大于像素数量的时候,结果会比之前更糟糕(走样:摩尔纹和锯齿)
如果此时用超采样,那么可以对抗走样问题,得到很好的结果,但是花费过于昂贵了。
为了能够保证采样频率满足纹理的频率,除了增加采样的频率以外,也可以通过处理纹理频率(即降低纹理频率)的方法来解决问题。
Mipmap: Allowing(fast, approx., square) range queries
通过将纹理不停取平均,每次将纹理分辨率降低1/4,得到一个 纹理金字塔。对于分辨率为$n$的纹理,得到的纹理金字塔的分辨率综合是$\frac{4}{3}n$,即$O(n)$。
通过计算采样点与相邻采样点映射到纹理上的点构成的四边形面积,即可确定应该利用纹理金字塔中哪层的结果进行映射。
但是实际贴图中,如果用离散的层进行贴图,可能导致最后的图像存在纹理的不连续现象,则将实数的层数其上下的整数层,在两个整数层进行双线性插值,得到纹理贴图结果,再根据实际层数进行插值,便可以得到一个相对连续的结果(三线性插值)
但是Mipmap只能应用于方形结构,对于一些长宽比不相同的结构,可能会出现过模糊的现象(overblur)。
Anisotropic Filtering 各向异性过滤
Ripmaps and summed area tables
- 对于矩形区域查询可以得到很好的结果。
- 但是对于沿对角线方向延伸的形状,计算结果仍然很差。
效果更加优秀的过滤方法:EWA filtering
Application of Textures(第十讲内容)
In modern GPUs, texture = memory + range query(filtering)
- General method to bring data to fragment calculations
Many applications:
- Environment lighting 环境光照(环境贴图)
- Store microgeometry
- Procedural textures
- Solid modeling
- Volume rendering
- …