渲染管线:

- 顶点处理:处理单个顶点。
- 原始装配:连接顶点形成原体。
- 光栅化:将每个原体转换为一组片元。
- 片元处理:处理单个片元。
- 输出合并:将所有原体的片元(在三维空间中)合成显示的二维彩色像素。
片元与像素的区别:
像素是二维的点(x,y)且有颜色值,坐标与二维像素网格对齐。
片元是三维的(x,y,z),x和y与二维像素网格对齐,z轴代表深度。在片元处理阶段会为片元分配颜色和透明度等参数,在输出合并阶段整合。
渲染管线中的顶点处理和片元处理阶段是可以程序编辑的。
Phong反射模型
模型表面光照 = 环境光 + 漫反射 + 高光

\[三角面法线\vec{n} = \frac{\overrightarrow{AB} \times \overrightarrow{AC}}{\| \overrightarrow{AB} \times \overrightarrow{AC} \|}\]
\[光照方向\vec{l} * \vec{n} = cos\alpha
\]
\[\vec{l} * \vec{n}是指\vec{l}在\vec{n}方向上的投影\]
\[反射方向\vec{r} = 2\vec{n}(\vec{l} * \vec{n}) – \vec{l}\]
\[其中2\vec{n}(\vec{l} * \vec{n}) = \vec{l} + \vec{r}\]
\[漫反射强度I_{\text{diff}} = k_d \cdot I_{\text{light}} \cdot \max(0, \vec{n} \cdot \vec{l})\]
\[高光强度I_{\text{spec}} = k_s \cdot I_{\text{light}} \cdot (\max(0, \vec{r} \cdot \vec{v}))^{e}\]
\[k_s和k_d为强度系数;I_{light}为光照强度;e为高光系数\]

struct PhongShader : IShader {
const Model &model;
vec3 l; // light direction in eye coordinates
vec3 tri[3]; // triangle in eye coordinates
PhongShader(const vec3 light, const Model &m) : model(m) {
l = normalized((ModelView*vec4{light.x, light.y, light.z, 0.}).xyz()); // transform the light vector to view coordinates
}
virtual vec4 vertex(const int face, const int vert) {
vec3 v = model.vert(face, vert); // current vertex in object coordinates
vec4 gl_Position = ModelView * vec4{v.x, v.y, v.z, 1.};
tri[vert] = gl_Position.xyz(); // in eye coordinates
return Perspective * gl_Position; // in clip coordinates
}
virtual std::pair<bool,TGAColor> fragment(const vec3 bar) const {
TGAColor gl_FragColor = {255, 255, 255, 255}; // output color of the fragment
//三角面法线
vec3 n = normalized(cross(tri[1]-tri[0], tri[2]-tri[0])); // triangle normal in eye coordinates
//反射向量, n * l 是l在n方向上的投影,2 * n * (n*l) = l + r
vec3 r = normalized(n * (n*l) * 2 - l); // reflected light direction
//环境光
double ambient = .3; // ambient light intensity
//漫反射
double diff = std::max(0., n * l); // diffuse light intensity
double e = 35;
double spec = std::pow(std::max(r.z, 0.), e); // specular intensity, note that the camera lies on the z-axis (in eye coordinates), therefore simple r.z, since (0,0,1)*(r.x, r.y, r.z) = r.z
for (int channel : {0,1,2})
gl_FragColor[channel] *= std::min(1., ambient + .4*diff + .9*spec);
// gl_FragColor[channel] *= std::min(1., ambient + .75*diff);
return {false, gl_FragColor}; // do not discard the pixel
}
};
评论(0)
暂无评论