OpenGL 4.0 用GLSL实现双面渲染
来源:互联网 发布:three.js画正方形框 编辑:程序博客网 时间:2024/04/30 16:58
当渲染一个完全封闭的 mesh ,如果里面是隐藏的,则不会被渲染。然而 ,如果这个封闭的mesh有个洞,那么里面就可以有一部分是可见的,则需要被渲染出来。在这中情况下,如果不做处理,可能用shader渲染出的光照效果是不正确的(由于mesh表面法线的方向问题)。为了克服这个问题 需要把mesh的表面法线向量反过来,即-normal,然后计算光照模型。
如图
左边的光照模型采用ADS模式(不正确的光照模型),右边的用ADS光照模型和双边光照模型(Two-sided rendering technique)
顶点shader
#version 430layout (location = 0) in vec3 VertexPosition;layout (location = 1) in vec3 VertexNormal;out vec3 FrontColor;out vec3 BackColor;struct LightInfo { vec4 Position; // Light position in eye coords. vec3 La; // Ambient light intensity vec3 Ld; // Diffuse light intensity vec3 Ls; // Specular light intensity};uniform LightInfo Light;struct MaterialInfo { vec3 Ka; // Ambient reflectivity vec3 Kd; // Diffuse reflectivity vec3 Ks; // Specular reflectivity float Shininess; // Specular shininess factor};uniform MaterialInfo Material;uniform mat4 ModelViewMatrix;uniform mat3 NormalMatrix;uniform mat4 ProjectionMatrix;uniform mat4 MVP;vec3 phongModel( vec4 position, vec3 normal ) { vec3 s = normalize(vec3(Light.Position - position)); vec3 v = normalize(-position.xyz); vec3 r = reflect( -s, normal ); vec3 ambient = Light.La * Material.Ka; float sDotN = max( dot(s,normal), 0.0 ); vec3 diffuse = Light.Ld * Material.Kd * sDotN; vec3 spec = vec3(0.0); if( sDotN > 0.0 ) spec = Light.Ls * Material.Ks * pow( max( dot(r,v), 0.0 ), Material.Shininess ); return ambient + diffuse + spec;}void main(){ vec3 tnorm = normalize( NormalMatrix * VertexNormal); vec4 eyeCoords = ModelViewMatrix * vec4(VertexPosition,1.0); FrontColor = phongModel( eyeCoords, tnorm ); BackColor = phongModel( eyeCoords, -tnorm ); gl_Position = MVP * vec4(VertexPosition,1.0);}
片元shader
#version 430in vec3 FrontColor;in vec3 BackColor;layout( location = 0 ) out vec4 FragColor;void main() { if( gl_FrontFacing ) { FragColor = vec4(FrontColor, 1.0); } else { // FragColor = mix( vec4(BackColor, 1.0), vec4(1.0,0.0,0.0,1.0), 0.7 ); FragColor = vec4(BackColor, 1.0); }}
在vertex shader中,ADS光照模型 计算方法放在了phongModel中,这个函数调用了两次,第一次用想模型本身的normal vertor(transformed into eye coordinates ) ,第二次用负normal vector,对应的结果存在Frontcolor 和 Backcolor 中,然后传到片元shader中。
能够优化的地方:
Note that there are a few aspects of the shading model that are independent of the orientation of the normal vector (such as the ambient component). One could optimize this code by rewriting it so that the redundant calculations are only done once. However, in this recipe we compute the entire shading model twice in the interest of making things clear and readable.
注意:在片元shader中,判断是mesh模型的 front 还是back 是通过内置变量gl_FrontFacing判断的,这个判断是基于多边形的环绕方向,而不是法线方向!
A polygon is said to have counter-clockwise winding(逆时针环绕) if the vertices are specified in counter-clockwise order as viewed from the front side of the polygon
默认情况下,如果屏幕上的顶点顺序是逆时针顺序(counter-clockwise order) ,则说明这是一个front facing polygon,然而我们可以通过glFrontFace 来改变。
需要注意的地方
In the vertex shader we determine the front side of the polygon by the direction of the normal vector, and in the fragment shader, the determination is based on the polygon's winding. For this to work properly, the normal vector must be defined appropriately for the face determined by the setting of glFrontFace.
用two-sided rendering 来调试信息
有时候我们想知道哪些是一个mesh的front facing ,哪个是back facing。我们可以用上面的方法,通过在片元shader中中把mesh的back faces 或者 front faces 设置成一个单一颜色来辨认,例如,对于上面的Frag shader ,我们可以在else 中 改为
FragColor = mix( vec4(BackColor,1.0),vec4(1.0,0.0,0.0,1.0), 0.7 );
如下图:
- OpenGL 4.0 用GLSL实现双面渲染
- OpenGL 4.0 用GLSL实现双面渲染
- 【OpenGL】GLSL-双面渲染技术(Two-sided rendering)
- 现代OpenGL+Qt学习笔记之八:GLSL双面渲染
- GLSL-双面渲染技术(Two-sided rendering)
- OpenGL 4.0 GLSL 延迟渲染 Deferred shading
- OpenGL 4.0 GLSL 用单光源 实现逐顶点 漫反射光照模型
- OpenGL 4.0 GLSL 实现 平面着色 Implementing flat shading
- 渲染世界的OPENGL<9>GLSL编程-单位着色器
- OpenGL中GLSL渲染茶壶光照完整程序
- Unity3D双面渲染
- 双面渲染shader
- 双面渲染shader
- OpenGL分片渲染实现
- OpenGL 4.0 GLSL 用 shadow map 算法 生成阴影
- OpenGL/glsl实现bumpmaping的各种细节
- OpenGL GLSL
- opengl实现X射线渲染
- win7中cookie存放的位置以及如何查看
- JVM(Java虚拟机)内存设置
- 最长上升子序列
- 修改母版页内容
- Android开发教程:shape和selector的结合使用
- OpenGL 4.0 用GLSL实现双面渲染
- 游戏行业感悟
- linux 下jsoncpp的安装
- Linux系统文件目录结构图
- BT5 aircrack-ng破解无线密码(wpa/wep)
- 当GROUP BY 与ORDER BY 一起使用时
- 最长公共子序列问题
- .md 文件和 .tex 文件编辑器
- Sql Server中Float格式转换字符串varchar方法(转)