GLSL-双面渲染技术(Two-sided rendering)

来源:互联网 发布:eclipse java mars 编辑:程序博客网 时间:2024/04/30 22:24

http://blog.csdn.net/xiajun07061225/article/details/7729871

 

 

当我们渲染一个完全封闭的物体的时候,多边形的背面都是隐藏的,我们无法看见。但是如果这个物体有一些空洞,那么一些背面就可以被看见了。然而因为这些多边形的法向量的方向在这个时候不是正确的,所以会渲染出错误的结果。为了合理的渲染这些背面,我们必须反转法向量,然后基于这些反转的法向量来计算光照。

下图显示了一个采用Phong光照模型绘制茶壶使用双面渲染与否的结果对比:


图一 使用双面渲染与不使用的效果对比

一、固定管线OpenGL实现双面渲染

在固定管线中,我们需要用一个函数来启用双面光照:

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);

这样,OpenGL将会反转表面的法线的方向,表示背面多边形的法线。

实例:

[cpp] view plaincopyprint?
  1. void GLWidget::initLight()  
  2. {  
  3.     GLfloat light_ambient[]={0.7,0.8,0.9,1.0};     
  4.     GLfloat light_diffuse[]={1.0,1.0,1.0,1.0};     
  5.     GLfloat light_specular[]={1.0,1.0,1.0,1.0};     
  6.     GLfloat light_position[]={2.0,2.0,2.0,0.0};  
  7.     GLfloat mat_diffuse[]={0.8,0.8,0.8,1.0};   
  8.   
  9.     glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);     
  10.     glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);     
  11.     glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);     
  12.     glLightfv(GL_LIGHT0,GL_POSITION,light_position);   
  13.   
  14.     glEnable(GL_LIGHTING);  
  15.     glEnable(GL_LIGHT0);  
  16.     glEnable(GL_AUTO_NORMAL);  
  17.     glEnable(GL_NORMALIZE);  
  18.     //glEnable(GL_CULL_FACE);   
  19.     //启用双面光照   
  20.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);  
  21.     glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mat_diffuse);    
  22. }  
效果:



二、可编程管线OpenGL实现双面渲染

假设我们的光照(采用Phong光照模型)计算是基于顶点的。在顶点着色器中,我们需要为每个顶点分别计算两次:front face和back face。两次计算采用的法向量不同。

[cpp] view plaincopyprint?
  1. #version 400   
  2.   
  3. layout (location = 0) in vec3 VertexPosition;  
  4. layout (location = 1) in vec3 VertexNormal;  
  5.   
  6. out vec3 FrontColor;  
  7. out vec3 BackColor;  
  8.   
  9. struct LightInfo{  
  10.     vec4 Position;  
  11.     vec3 La;  
  12.     vec3 Ld;  
  13.     vec3 Ls;  
  14. };  
  15. uniform LightInfo Light;  
  16.   
  17. struct MaterialInfo{  
  18.     vec3 Ka;  
  19.     vec3 Kd;  
  20.     vec3 Ks;  
  21.     float Shininess;  
  22. };  
  23. uniform MaterialInfo Material;  
  24.   
  25. uniform mat4 ModelViewMatrix;  
  26. uniform mat3 NormalMatrix;  
  27. uniform mat4 ProjectionMatrix;  
  28. uniform mat4 MVP;  
  29.   
  30. //转化到视空间   
  31. void getEyeSpace(out vec3 tnorm,out vec4 eyeCoords)  
  32. {  
  33.     //convert normal and position to eye coords  
  34.     tnorm = normalize(NormalMatrix * VertexNormal);  
  35.     eyeCoords = ModelViewMatrix * vec4(VertexPosition,1.0);  
  36. }  
  37.   
  38. //计算Phong光照模型   
  39. vec3 phongModel(vec4 eyeCoords,vec3 tnorm)  
  40. {  
  41.     vec3 s = normalize(vec3(Light.Position - eyeCoords));  
  42.     vec3 v = normalize(-eyeCoords.xyz);  
  43.     vec3 r = reflect(-s,tnorm);  
  44.   
  45.     vec3 ambient = Light.La * Material.Ka;  
  46.   
  47.     float sDotN = max(dot(s,tnorm),0.0);  
  48.     vec3 diffuse = Light.Ld * Material.Kd * sDotN;  
  49.   
  50.     vec3 specular = vec3(0.0);  
  51.     if(sDotN > 0)  
  52.         specular = Light.Ls * Material.Ks *   
  53.                     pow(max(dot(r,v),0.0),Material.Shininess);  
  54.   
  55.     return (ambient + diffuse + specular);  
  56. }  
  57.   
  58. void main()  
  59. {  
  60.     vec3 tnorm;  
  61.     vec4 eyeCoords;  
  62.     getEyeSpace(tnorm,eyeCoords);  
  63.     FrontColor = phongModel(eyeCoords,tnorm);  
  64.     BackColor = phongModel(eyeCoords,-tnorm);  
  65.   
  66.     gl_Position = MVP * vec4(VertexPosition,1.0);  
  67. }  
在片断着色器中,我们根据关键字gl_FrontFacing的值来为片断赋予颜色值。

gl_FrontFacing是GLSL内置的关键字,它代表图元是面向光源还是背向光源。

片断着色器 twosided.frag:

[cpp] view plaincopyprint?
  1. #version 400   
  2.   
  3. in vec3 FrontColor;  
  4. in vec3 BackColor;  
  5.   
  6. layout (location = 0) out vec4 FragColor;  
  7.   
  8. void main()  
  9. {  
  10.     if(gl_FrontFacing)  
  11.     {  
  12.         FragColor = vec4(FrontColor,1.0);  
  13.     }  
  14.     else  
  15.     {  
  16.         FragColor = vec4(BackColor,1.0);  
  17.     }  
  18. }  


原创粉丝点击