着色
模型-投影变换:物体变为标准立方体中
视口变换:3D物体变为2D平面
光栅化:绘制物体在2D平面上
着色:对物体应用材质 -- apply a material to an object
材质在光照作用下表现出来的颜色
Bling-Phone模型光照会出现的情况:漫反射 + 高光 + 环境光照
Shading Point
考虑的光照最简模型。一个接受光照的平面,其主要有4个参数
法线:n
观测方向:v
光照方向:l
表面属性:(材质)
着色的局部性 着色不会产生阴影,他只考虑物体自己,当在考虑时,会在空间中去掉其他物体
漫反射
光照方向与Shading Point 法线的夹角余弦\(cos\theta = l \cdot n\)决定了光源的吸收情况
点光源的能量在距离上的衰减
点光源周围可以看作为一圈一圈的等势线,距离光源r的点能够接受到的能量为\(I =\frac{I_0}{r^2}\)
Lambertian Diffuse Shading -- 漫反射的计算结果
\[L_d = k_d \cdot \frac{I_0}{r^2} \cdot max(0,n \cdot l) \]\(max(0,n \cdot l)\)表示Shading Point 能够接受到的能量,与0比大小,为了避免余弦为负值带来的无意义情况
\(\frac{I_0}{r^2}\)表示能够到达Shading Point 的能量大小,随着距离衰减
\(k_d\) diffuse coefficient 主要由物体材质决定
可以看出在漫反射计算公式中,并没有考虑观测向量v对结果的影响,因为对于漫反射来说从四面八方看到的结果应该是一样的
高光
观测方向接近镜面反射方向
光照方向在Shading Point 上存在一个镜面反射向量,当该向量与观测方向接近时,将表现出高光
等价于
Shading Point的法线向量与入射向量和观测向量的半程向量(两个向量组成的角的角平分线)接近
p次幂让高光范围减小
环境光照
假设任何点接受到的环境光照是相同的\(I_a\)
\[L_a = k_a \cdot I_a \]Blinn-Phone 着色模型
\[L = L_d + L_s + L_a\\ = k_d \cdot \frac{I_0}{r^2} \cdot max(0,n \cdot l) + k_s \cdot \frac{I_0}{r^2} \cdot max(0,n \cdot h)^p + k_a \cdot I_a \]着色频率
flat shading
利用一个三角形面的法线来计算着色
Gouraud Shading
利用一个三角形的三个顶点法线计算顶点颜色,然后插值计算三角形内部的颜色
for(每个三角形)
{
color P0;
color P1;
color P2;
for(三角形中的每个像素)
{
//计算该像素在三角形中的重心坐标
color pixelc = P0*x + P1*y + P2*z;
setcolor(pixel,pixelc);
}
}
根据三角形面求解顶点法线
一个顶点会被多个三角形面共用,所以该顶点法线就为 每个面法线的平均
\[N_v = \frac{\sum_iN_i}{||\sum_iN_i||} \]Phone Shading
对每个像素通过三角形的三个顶点插值计算法线,然后利用该法线计算每个像素的颜色
for(每个三角形)
{
normal P0;
normal P1;
normal P2;
for(三角形中的每个像素)
{
//计算该像素在三角形中的重心坐标
normal pixeln = P0*x + P1*y + P2*z;
setcolor(pixel,getcolor(pixeln));
}
}
实时渲染管线
- 输入3D空间中的点
- MVP变换 + 视口变换 3D点变到2D平面上
- 点连接为三角形 obj文件有相应的定义
- 光栅化--离散三角形为像素块
- 对像素块着色
- 输出
纹理映射
定义任何一个点的属性,一般存在一个纹理贴图
以obj文件来说,obj文件内可能会定义给出每个顶点的uv坐标,可以通过读取uv坐标值,从而在纹理贴图中寻找到该点的属性
一般来说,纹理贴图的坐标是由RGB来表示的即其坐标范围在(0,255)之间,而经过变换后的物体坐标在(-1,1)之间,所以为了对应,需要对纹理坐标进行处理
此时再根据之前求得的重心坐标,利用三角形的三个顶点求得每个像素点的纹理值,即可
重心坐标
用于插值计算。对于与一个三角形处于同一平面的点(x,y)都可以由三角形的三个顶点线性组合得到
\[(x,y) = \alpha A + \beta B + \gamma C \alpha + \beta + \gamma = 1 \]\(\alpha \beta \gamma\) 就是点(x,y)对于这个三角形的重心坐标
对于在三角形内部的一点,\(\alpha \beta \gamma\) 全为非负的
求解重心坐标
//_v为三角形三个顶点组成的数组,x,y为点
Vector3f a (_v[1].x()-_v[0].x(),_v[2].x()-_v[0].x(),_v[0].x()-x);
Vector3f b (_v[1].y()-_v[0].y(),_v[2].y()-_v[0].y(),_v[0].y()-y);
//叉乘
Vector3f c (a.y()*b.z()-a.z()*b.y(),a.z()*b.x()-a.x()*b.z(),a.x()*b.y()-a.y()*b.x());
//点(x,y)的重心坐标
Vector3f res (1.f-(c.x()+c.y())/c.z(),c.y()/c.z(),c.x()/c.z());
重心坐标的应用
对于三角形内部任何一个点的属性(颜色,法线等)都可以通过重心坐标与三角形的三个顶点对应属性相乘得到
重心坐标在投影变换下的属性会发生改变,对于待渲染物体的重心坐标,应当在3D空间中求得
如何应用纹理
for(每一个像素)
{
//根据插值计算出该像素的纹理坐标u,v
(u,v) = cal(pixel);
//根据uv在贴图上查询颜色
color = get_(u,v);
//设置该像素的颜色
set_(pixel,color);
}
纹理贴图过小-- 放大
纹理贴图较小 --> 拉伸纹理贴图至物体图像大小
--> 一个texel 对应 多个pixel --> 导致一个pixel在求取颜色时,(u,v)坐标不是整数 --> 而采用四舍五入的方法,导致图像精度的降低
解决办法:双线性插值
利用包围该pixel的4个texel进行插值求解颜色。相当于是二维平面的重心坐标。假设有当前pixel坐标为\((x_0,y_0)\),可以求得
//小于x0,y0的最大整数, 大于x0,y0的最小整数
int minx;
int miny;
int maxx;
int many;
float s = x0-minx;
float t = y0-miny;
//对于在x方向可以插值
color c1 = lerp(s,cminx_miny,cmaxx_miny);
color c2 = lerp(s,cminx_maxy,cmaxx_maxy);
//然后利用c1 和 c2 在 y方向上插值
color res = lerp(t,c1,c2);
纹理贴图过大 -- 压缩
导致一个pixel 对应 多个 texel -> pixel中心求得的颜色不能代替多个texel的颜色
解决办法1:MSAA
将一个pixel划分为多个采样块
解决办法2:MipMap
将点查询变为范围查询,MipMap -- 快 不准确,方形
原理:将纹理先行处理,即不断降低1倍的分辨率,存储纹理值,得到\(log_2(n)\)张图片。对于每个pixel映射到纹理贴图上的面积选择对应的MipMap那么就可以直接查询获得当前pixel的纹理值。
如何确定选择哪一张图片
对于pixel p0其上方和右方有pixel p1和p2,三点映射到纹理贴图上,可以求得u1u0 和 u2u0的距离两者距离最大值L,选择\(log_2L\)的图片纹理即为当前p0的纹理。
比如当前L=4说明当前映射覆盖了4×4的texel,需要经过2次降低,才会得到1块texel,那么选择该mipmap即为平均值。
对于非整数层的MipMap
通过双线性插值求解
首先在上下两个整数层求解对于pixel的纹理,然后再通过层与层之间的重心坐标求解非整数层的纹理
MipMap问题
过度模糊
- 解决方法:各向异性过滤
Mipmap是纹理长宽同比缩小,考虑一个矩阵,相当于只存储了对角线的元素,而再添加其余的缩小样本,将解决只能处理正方形区域的问题。
但仍然不能解决斜着的映射图像。
凹凸贴图 Bump Texture
对法线的扰动实现渲染出凹凸的现象。凹凸贴图存储的是每个pixel的高度信息,使得可以通过相邻两个pixel的高度差计算得到当前pixel的法线
考虑2D平面
原始点P的法线n(p) = (0,1)
对于点P在凹凸贴图上可以求得其切线 dp = c*[h(p+1)-h(p)]
利用该条切线求得凹凸贴图影响下的 法线变换 n(p) = (-dp,1).normal;
考虑3D空间
原始点P的法线n(p) = (0,0,1)
切线有2个方向:u,v
然后再根据该切线求得P点的法线 n(p) = \((-\frac{dp}{du},-\frac{dp}{dv},1)\).normal;
真实的法线
定义的原始法线都为(0,0,1),而实际法线并不是这个数值
在一个微元上,可以认为法线是(0,0,1)在求得由凹凸贴图更改的法线后,再利用原始法线的向量值进行矩阵变换求得真实改动后的法线
位移贴图 Displayment Texture
实际改变点的位置
标签:贴图,法线,cdot,纹理,着色,三角形,pixel From: https://www.cnblogs.com/XTG111/p/18062868