OpenGL 4.0 GLSL 用立方体贴图和 环境贴图 模拟反射效果
来源:互联网 发布:程序员和美工谁收入高 编辑:程序博客网 时间:2024/06/06 20:48
我们可以用纹理代表物体周围的环境,然后把纹理贴到物体上,实现映射周围的场景目的,这项技术也被乘坐环境贴图(EnvironmentMapping)。环境贴图通常来模拟反射或者折射效果。
最常见的环境贴图(Environment Mapping)是立方体cube map。
立方体贴图(cube map texture)通常由六个分开的图像组成,在设置环绕方式时采用GL_CLAMP_TO_EDGE,这样可以避免在cubeedge中避免边框颜色。
一个反射效果如下图:
vertex shader
#version 430layout (location = 0) in vec3 VertexPosition;layout (location = 1) in vec3 VertexNormal;layout (location = 2) in vec2 VertexTexCoord;out vec3 ReflectDir;uniform bool DrawSkyBox;uniform vec3 WorldCameraPosition;uniform mat4 ModelViewMatrix;uniform mat4 ModelMatrix;uniform mat3 NormalMatrix;uniform mat4 ProjectionMatrix;uniform mat4 MVP;void main(){ if( DrawSkyBox ) { ReflectDir = VertexPosition; } else { vec3 worldPos = vec3( ModelMatrix * vec4(VertexPosition,1.0) ); vec3 worldNorm = vec3(ModelMatrix * vec4(VertexNormal, 0.0)); vec3 worldView = normalize( WorldCameraPosition - worldPos ); ReflectDir = reflect(-worldView, worldNorm ); } gl_Position = MVP * vec4(VertexPosition,1.0);}
片元shader
#version 430in vec3 ReflectDir;layout(binding=0) uniform samplerCube CubeMapTex;uniform bool DrawSkyBox;uniform float ReflectFactor;uniform vec4 MaterialColor;layout( location = 0 ) out vec4 FragColor;void main() { // Access the cube map texture vec4 cubeMapColor = texture(CubeMapTex, ReflectDir); if( DrawSkyBox ) FragColor = cubeMapColor; else FragColor = mix( MaterialColor, cubeMapColor, ReflectFactor);}
在顶点shader中,主要计算反射方向(ReflectDir),然后在片元shader中通过ReflectDir来获取cubemap。
在片元shader中如果不绘制天空盒(DrawSkyBox是false),则我们可以在世界坐标系中计算viewer的反射方向。即通过 reflect(-worldView, worldNorm ) 来计算ReflectDir。
之所以在世界坐标系中计算是因为:如果在相机坐标系的话,当相机移动了反射方向也不会改变。
在vertexshader中,我们转化position到世界坐标系中存储到worldPos,我们用同样方法转换法线normal。注意:用 ModelMatrix转化normal时其第四个分量一定是0(避免ModelMatrix转换分量的影响),还有,模型矩阵一定不能包含任何非均匀缩放元素(anynon-uniform scaling component)。否则,法线的转换不正确。见:http://blog.csdn.net/zhuyingqingfen/article/details/19335427
在fragmentshader将会用ReflectDir访问立方体贴图。可以想象成这样:一束光线从viewer开始,射到物体表面然后反射,最终射到cubemap上(最终的片元颜色就是射到cubemap上那点的颜色 值);
如果我们渲染skybox(DrawSkyBoxis true),那么我们用顶点位置作为反射方向。为什么?,因为当天空盒被渲染的时候,我们想要天空盒上的位置(对应于cubemap上的位置,天空盒确实是cubemap 渲染出来的)。在片元shader中,ReflectDir将会用作访问cubemap 的纹理坐标。因此,如果我们想访问cubemap上的位置(对应于中心在原点的一个cube的位置),我们需要这个指向这个位置的向量,我们需要的这个向量就是这个点减去原点位置(0,0,0),因而我们只需要这个点的位置。
天空盒经常被渲染成viewer在天空盒的中心位置,天空盒会随着viewer移动(所以,viewer总会在天空盒的中心位置)
在这篇教程中有两点需要注意:
1. 渲染的物体(如茶壶)只会反射环境贴图的场景,而不会反射任何场景中其他的物体。如果想反射其他物体,我们需要产生一个环境贴图(通过把相机放到物体的位置上,然后让相机朝向各个坐标抽方向(正负),渲染六次),然后用这个环境贴图反射到物体上。当然如果场景中的任何一个物体发生移动,我们需要重新生成环境贴图。(这在实时交互程序中一般不可取)。
2. 在上面的shader中,我们计算的反射方向是取的cube map上的点作为反射方向(DrawSkyBox为true即认为物体(上面的茶壶)在原点,cube map 上的一点减去原点即为反射方向,但实际上是相机在原点而不是茶壶),这就意味着我们忽略了物体的位置,认为环境贴图在无穷远处。
- OpenGL 4.0 GLSL 用立方体贴图和 环境贴图 模拟反射效果
- OpenGL立方体贴图
- WinCE OpenGL绘制立方体和纹理贴图
- OpenGL显示中文和旋转立方体贴图
- DirectX11 使用Cube Mapping 立方体环境贴图实现天空、物体反射效果
- OpenGL 核心技术之立方体贴图
- 立方体环境贴图(Cube Mapping)之OpenGL原理
- (149)环境立方体贴图
- 立方体贴图
- OpenGL纹理贴图 旋转的立方体
- OpenGL 4.0 GLSL 模拟 雾效果
- opengl 贴图
- 立方体纹理贴图代码
- 简单立方体纹理贴图
- 立方体贴图(Cubemap)
- opengles立方体贴图
- OPENGL 纹理贴图 旋转立方体(Nehe glut版)
- OpenGL学习记录——旋转立方体+文件贴图
- MFC 中 删除一个非空文件夹
- ELF动态链接原理分析
- C++对象模型
- jquery ui实现弹窗效果
- mongodb:在mongo终端上操作将数据从一个字段复制到另一个字段上。
- OpenGL 4.0 GLSL 用立方体贴图和 环境贴图 模拟反射效果
- 用html5开发随机生成的大树的代码
- day24
- tftp 在ubuntu12.04, busyBox上的配置和使用
- ORA-12052: cannot fast refresh materialized view DCS_BIZ.MV_TMP_16
- UITextView
- 邮箱自动填充js
- c++ 产生随机数
- Oracle索引原理