openGL CG 系列教程3-Pixel Lighting
2010-04-30 18:36
465 查看
*原创文章,转载请注明出处*
openGL CG 系列教程3-Pixel Lighting
在上一篇教程中介绍了phong model下的一般光照,并且用Cg着色语言实现了固定渲染管线中gouraud shading光照效果。由于是基于vertex的光照,虽然采用gouraud shading要比flat shading效果好的多,但是和phong shading的效果相差很大。这里大家要注意的是,phong model和phong shading的区别。上一篇教程所讲的光照模型叫phong model,而这篇教程要介绍的一种着色方法叫phong shading,必须要使用shader才能实现。下面的图中对比了采用flat shading,gouraud shading和phong shading技术渲染的一个圆环。
有了上一篇教程的基础,用Cg来实现基于pixel lighing的phong shading光照就容易多了。绝大部分的Cg shader代码都是一样的,主要的改变就是这次不是在vertex shader里光照,而是在fragment shader里计算光照。所以整个vertex shader的代码很简单,将要渲染的物体的顶点位置,顶点法线传入fragment shader就是vertex shader的全部工作。整个vertex shader的代码如下。
03vs.cg
上面的代码的输出结构体中有三个成员。Position是传入的物体的顶点,该顶点将用ModelViewProjection矩阵转换成剪裁坐标系中的坐标供光栅化使用。一旦将坐标转换后,我们就无法在fragment shader中使用物体的顶点坐标了。由于要在fragment shader中计算光照,所以我们要将物体的顶点位置,顶点法线都传入到fragment shader中。这里物体转换前的顶点和法线分别使用了语义TEXCOORD0和TEXCOORD1,代表将它们作为纹理坐标后传入fragment shader。这样GPU会把顶点和法线信息当做纹理坐标来处理,在贴图的时候,GPU会根据纹理自动插值计算每个像素对应的颜色,而现在GPU插值计算出来的就是每个像素对应的坐标和法线信息了。有了这些数据就可以进行phong shading的计算了。光照计算的公式和方法和上一个教程介绍的一模一样。下面是fragment shader的代码。
03fs.cg
*原创文章,转载请注明出处*
openGL CG 系列教程3-Pixel Lighting
在上一篇教程中介绍了phong model下的一般光照,并且用Cg着色语言实现了固定渲染管线中gouraud shading光照效果。由于是基于vertex的光照,虽然采用gouraud shading要比flat shading效果好的多,但是和phong shading的效果相差很大。这里大家要注意的是,phong model和phong shading的区别。上一篇教程所讲的光照模型叫phong model,而这篇教程要介绍的一种着色方法叫phong shading,必须要使用shader才能实现。下面的图中对比了采用flat shading,gouraud shading和phong shading技术渲染的一个圆环。
Flat shading | Gouraud shading | Phong shading |
有了上一篇教程的基础,用Cg来实现基于pixel lighing的phong shading光照就容易多了。绝大部分的Cg shader代码都是一样的,主要的改变就是这次不是在vertex shader里光照,而是在fragment shader里计算光照。所以整个vertex shader的代码很简单,将要渲染的物体的顶点位置,顶点法线传入fragment shader就是vertex shader的全部工作。整个vertex shader的代码如下。
03vs.cg
struct output { float4 position : POSITION; float3 objectPos : TEXCOORD0; float3 normal : TEXCOORD1; }; output vs_main( float4 position : POSITION, float3 normal : NORMAL, uniform float4x4 MV, uniform float4x4 MVP ) { output OUT; OUT.position = mul(MVP, position); OUT.objectPos = mul(MV, position).xyz; OUT.normal = mul(MV, float4(normal,0.0)).xyz; return OUT; } |
上面的代码的输出结构体中有三个成员。Position是传入的物体的顶点,该顶点将用ModelViewProjection矩阵转换成剪裁坐标系中的坐标供光栅化使用。一旦将坐标转换后,我们就无法在fragment shader中使用物体的顶点坐标了。由于要在fragment shader中计算光照,所以我们要将物体的顶点位置,顶点法线都传入到fragment shader中。这里物体转换前的顶点和法线分别使用了语义TEXCOORD0和TEXCOORD1,代表将它们作为纹理坐标后传入fragment shader。这样GPU会把顶点和法线信息当做纹理坐标来处理,在贴图的时候,GPU会根据纹理自动插值计算每个像素对应的颜色,而现在GPU插值计算出来的就是每个像素对应的坐标和法线信息了。有了这些数据就可以进行phong shading的计算了。光照计算的公式和方法和上一个教程介绍的一模一样。下面是fragment shader的代码。
03fs.cg
uniform float3 LightPosition; uniform float3 eyePosition; uniform float3 I; uniform float3 Ka; uniform float3 Kd; uniform float3 Ks; uniform float shininess; struct input{ float3 objectPos: TEXCOORD0; float3 normal : TEXCOORD1; }; struct output{ float4 color : COLOR; }; output fs_main( in input IN ) { output OUT; float3 N = normalize(IN.normal); float3 P = IN.objectPos; float3 L = normalize(LightPosition - P); float NdotL = max(dot(N,L),0); float3 ambient = Ka * I; float3 diffuse = Kd * I * NdotL; float3 V = normalize(eyePosition - P); float3 H = normalize(L+V); float NdotH = pow(max(dot(N,H), 0), shininess); if(NdotL<=0) NdotH = 0.0; float3 specular = Ks*I*NdotH; float3 color = ambient + diffuse + specular; OUT.color.xyz= color; OUT.color.w = 1.0; return OUT; } |
*原创文章,转载请注明出处*
相关文章推荐
- openGL CG 系列教程4 - Lighting + Texture
- OpenGL CG 系列教程1 - Hello CG
- openGL CG 系列教程5 – Environment Mapping ( 环境贴图 )
- openGL CG 系列教程5 – Environment Mapping ( 环境贴图 )
- 【转】OpenGL CG系列教程2,vertex lighting
- openGL CG 系列教程
- 【转】OpenGL CG系列教程1 - Hello CG
- OPENGL CG 系列教程1-HelloVCG
- openGL CG 系列教程06 – Normal Mapping (法线贴图)
- openGL CG 系列教程07 – Toon Shader
- openGL CG 系列教程2 - Vertex Lighting
- openGL CG 系列教程1 - Hello CG
- NeHe OpenGL系列教程(中英文版附带VC++源码)中英文系列
- OpenGL系列教程之三:OpenGL渲染管线
- OpenGL系列教程之十:OpenGL帧缓冲区对象(FBO)
- 国外入门级Opengl系列教程网站
- OpenGL系列教程之八:OpenGL顶点缓冲区对象(VBO)
- OpenGL系列教程之四:OpenGL 变换
- OpenGL系列教程之一:OpenGL
- OpenGL系列教程之九:OpenGL像素缓冲区对象(PBO)