opengl40glsl用shadowmap算法生成阴影_第1页
opengl40glsl用shadowmap算法生成阴影_第2页
opengl40glsl用shadowmap算法生成阴影_第3页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、OpenGL 4.0 GLSL用 shadow map 算法生成阴影shadow map 其实把场景渲染了两次,第一次是从灯光的角度(把相机放到灯光位置)渲染场景,然后存储渲染的深度信息到一张纹理上即渲染一张shadow map(用 FBO技术)。第二次再从观察者的角度来渲染。在第二次渲染时才渲染阴影,生成阴影的过程是这样的:对于每个片元的深度信息和第一次从灯光角度渲染的深度信息比较,如果当前深度值大于第一次渲染的深度值,则肯定有物体在当前片元和灯光之间,那么当前片元在阴影区。如图:左边是灯光和其对应的透视截锥, 右边是对应渲染出来的 shadow map。在阴影图的灰度强度对应 shadow

2、 map 中德深度值(越黑说明越近)这个算法的关键之处在于片元三维坐标系的转换这样可以在 shadow map 中寻找正确的纹理坐标。因为shadowmap 只是一个 2D 的纹理,我们需要在灯光的 frustum 中德点映射到从 0-1 之间。 light view matrix 可以把 world 中的点转换到灯光坐标系下的点。light's projection matrix光坐标系下的点(within the light's frustum) 转换到可以灯其次裁剪坐标系( homogeneous clip coordinates.) These are called c

3、lip coordinates because the built-in clipping functionality takes place when the position is defined in these coordinates. Points within the perspective (or orthographic) frustum are transformedby the projection matrix to the (homogeneous) space that is contained within a cube centered at the origin

4、, with side length of 2. This space is called the canonical viewing volume. The term "homogeneous" means that these coordinates should not necessarily be considered to be true Cartesian positions until they are divided by their fourth coordinate. For full details about homogeneous coordina

5、tes, refer to your favorite textbook on computer graphics. 在裁剪坐标系中,点的 x 和 y 分量大体上可以作为访问纹理的坐标。而z 分量存储了深度信息,我们可以和 shadow map 中的值作比较。不过在用之前,我们有两件事要做: 1. 我们需要一个偏转矩阵把他们映射到0-1( instead of -1 to 1) 之间 ,2. 我们需要应用透视除法( perspective division )。Of course, the x and y components also need to be biased between ze

6、ro and one because that is the appropriate range for texture access.We can use the following "bias" matrix to alter our clipcoordinates. 顶点 shadercpp view plain copy print?#version400layout (location=0) in vec3 VertexPosition;layout(location=1) in vec3 VertexNormal;out vec3 Normal;outvec3

7、Position;out vec4 ShadowCoord;uniform mat4ModelViewMatrix;uniform mat3 NormalMatrix;uniformmat4 MVP;uniform mat4 ShadowMatrix;void main()Position = (ModelViewMatrix *vec4(VertexPosition,1.0).xyz;Normal =normalize( NormalMatrix * VertexNormal );ShadowCoord = ShadowMatrix * vec4(VertexPosition,1.0);gl

8、_Position = MVP * vec4(VertexPosition,1.0);片元shadercpp view plain copy print?#version 400uniformstruct LightInfo vec4 Position;vec3 Intensity; Light;uniform struct MaterialInfo vec3 Ka;vec3 Kd;vec3 Ks;float Shininess; Material;uniform sampler2DShadow ShadowMap;in vec3 Position;in vec3 Normal;in vec4

9、 ShadowCoord;layout (location =0) out vec4 FragColor;vec3 phongModelDiffAndSpec()vec3 n = Normal;if( !gl_FrontFacing ) n = -n;vec3 s = normalize(vec3(Light.Position) - Position);vec3v = normalize(-Position.xyz);vec3 r = reflect( -s, n );float sDotN = max( dot(s,n), 0.0 );vec3 diffuse =Light.Intensit

10、y * Material.Kd * sDotN;vec3 spec =vec3(0.0);if( sDotN > 0.0 )spec =Light.Intensity * Material.Ks *pow( max( dot(r,v), 0.0 ), Material.Shininess );returndiffuse + spec;subroutine void RenderPassType();subroutine uniform RenderPassType RenderPass;subroutine (RenderPassType)void shadeWithShadow

11、()vec3 ambient = Light.Intensity * Material.Ka;vec3 diffAndSpec = phongModelDiffAndSpec();floatshadow = textureProj(ShadowMap, ShadowCoord);/If the fragment is in shadow, use ambient light only.FragColor = vec4(diffAndSpec * shadow + ambient,1.0);/shadow 为 1则不在阴影区,为0 则在阴影区,只用环境光 ambient/ Gamma corre

12、ctFragColor =pow( FragColor, vec4(1.0 / 2.2) );subroutine(RenderPassType)void recordDepth()/ Do nothing,depth will be written automaticallyvoid main()/ This will call either shadeWithShadow orrecordDepthRenderPass();设置 FBOcpp viewplain copy print?void SceneShadowMap:setupFBO()GLfloat border = 1.0f,

13、0.0f,0.0f,0.0f ;/ Thedepth buffer textureGLuint depthTex;glGenTextures(1, &depthTex);glBindTexture(GL_TEXTURE_2D, depthTex);glTexStorage2D(GL_TEXTURE_2D, 1,GL_DEPTH_COMPONENT24, shadowMapWidth,shadowMapHeight);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameteri(G

14、L_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR, border);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_M

15、ODE,GL_COMPARE_REF_TO_TEXTURE);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_FUNC, GL_LESS);/ Assign the depth buffer texture to texture channel 0 glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, depthTex);Create and set up the FBOglGenFramebuffers(1,&shadowFBO);/glBindFramebuffe

16、r(GL_FRAMEBUFFER, shadowFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D, depthTex, 0);GLenumdrawBuffers = GL_NONE;glDrawBuffers(1,drawBuffers);GLenum result =glCheckFramebufferStatus(GL_FRAMEBUFFER);if( result = GL_FRAMEBUFFER_COMPLETE)printf("Framebuffer is compl

17、ete.n");printf("Framebuffer is not complete.n"); elseglBindFramebuffer(GL_FRAMEBUFFER,0);FBO只包含一个单一纹理附加到深度buffer上。GL_TEXTURE_WRAP_*环绕模式设置成GL_CLAMP_TO_BORDER. 当一个片元处于 shadow map 的外边( outside of the lights' frutum), 那么这个片元的纹理坐标可能超出 1 或者小于 0。在这种情况下,我们需要把这些点置于阴影之外(不在阴影中)。当用了GL_CLAMP_T

18、O_BORDER,在这种情况下将返回边缘的值(the value that is returned from a texture lookup will the bordervalue).默认的边缘值是 ( 0,0,0,0)。当纹理包含深度分量,第一个分量被当作深度值。因此我们设置边缘颜色值为(1,0,0,0)( 1 对应最大深度值) 。这样在比较时, 所有处于light s frutum 之外的片元,将不会在阴影中。接下来两行 cpp view plain copyprint?glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE,GL_C

19、OMPARE_REF_TO_TEXTURE);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_FUNC, GL_LESS);这样设置之后,访问纹理的结果将是一个比较的结果,而不是从纹理中取出的颜色值。 纹理坐标 ShadowCoord 的第三个分量( r 分量)将会和和纹理坐标为(s,t)的值作比较。比较结果是一个float 型值。 GL_TEXTURE_COMPARE_FUNC设置成GL_LESS(Other options include GL_LEQUAL,GL_ALWAYS,GL_GEQUAL, and so on.), 意思是如果纹理

20、坐标ShadowCoord 的 r 值 (第三分量)小于纹理坐标为(s,t)(ShadowCoord 的前两个分量)的值结果将返回1.0The next step is the key to the shadow mapping algorithm. We use the built-in texture access function textureProj to access the shadow map texture ShadowMap. Before using the texture coordinate to access the texture, the textureProj

21、 function will divide the first three coordinates of the texture coordinate by the fourth coordinate. Remember that this is exactly what is needed to convert the homogeneous position (ShadowCoord) to a true Cartesian position( 笛卡尔坐标位置) . After this perspective division, the textureProj function will

22、 use the result to access the texture. As this texture's type is sampler2DShadow, it is treatedas texture containing depth values, and rather than returning avalue from the texture, it returns the result of a comparison. Thefirst two coordinates of ShadowCoord are used to access a depthvalue wit

23、hin the texture. That value is then compared against thevalue of the third component of ShadowCoord. WhenGL_NEAREST is the interpolation mode (as it is in our case)the result will be 1.0 or 0.0. As we set the comparison functionto GL_LESS, this will return 1.0, if the value of the thirdcomponent of ShadowCoord is less than the

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论