


版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 聘用ktv员工合同范本
- 污水委托处理协议合同书
- 游泳健身培训合同协议书
- 物业与万达合作协议合同
- 食品事故赔偿协议书范本
- 电厂采购密封件合同范本
- 结石科合作协议合同范本
- 村道维修承包合同协议书
- 离职协议代签协议书范本
- 物业的车位买卖合同协议
- 医共体人事编制管理办法
- 小儿肛周脓肿护理
- 医院法律法规培训内容
- 山东畜牧兽医单招考试题及答案
- 玉米杂交种子质量控制与高效制种技术的应用探索
- 2025年 北京海淀区招聘社区工作者考试笔试试卷附答案
- 商户安全生产培训课件
- 【扶臂式挡土墙迎水坡和背水坡堤防整体抗滑稳定计算案例1200字】
- 四川省广元市2024-2025学年第二学期八年级期末考试数学试卷(无答案)
- 死亡病例讨论制度落实与质控优化
- 痛经的中医护理
评论
0/150
提交评论