opengl中的阴影瑕疵

时间:2015-11-08 15:07:24

标签: opengl-es webgl shadow-mapping

我正在尝试渲染一个物体和两个灯光,其中一个灯光投射阴影。一切正常但我注意到有一些明显的瑕疵,如下图所示,有些阴影似乎溢出到明亮的区域。

shadow overflows to bright areas

下面是将深度信息渲染到帧缓冲区的着色器

    <script id="shadow-shader-vertex" type="x-shader/x-vertex">
        attribute vec4 aVertexPosition;
        uniform mat4 uObjMVP;

        void main() {
            gl_Position = uObjMVP * aVertexPosition;
        }
    </script>

    <script id="shadow-shader-fragment" type="x-shader/x-vertex">
        precision mediump float;

        void main() {
            //pack gl_FragCoord.z
            const vec4 bitShift = vec4(1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0);
            const vec4 bitMask = vec4(1.0/256.0, 1.0/256.0, 1.0/256.0, 0.0);
            vec4 rgbaDepth = fract(gl_FragCoord.z * bitShift);
            rgbaDepth -= rgbaDepth.gbaa * bitMask;

            gl_FragColor = rgbaDepth;
        }
    </script>

在上面的着色器中,uObjMVP是从投射阴影的光的位置(温暖的光线,冷光不投射阴影)中使用的MVP矩阵

以下是绘制所有内容的着色器:

   <script id="shader-vertex" type="x-shader/x-vertex">
        //position of a vertex.
        attribute vec4 aVertexPosition; 
        //vertex normal.
        attribute vec3 aNormal; 

        //mvp matrix
        uniform mat4 uObjMVP; 

        uniform mat3 uNormalMV; 

        //shadow mvp matrix
        uniform mat4 uShadowMVP;

        //interplate normals
        varying vec3 vNormal;

        //for shadow calculation
        varying vec4 vShadowPositionFromLight;

        void main() {       
            gl_Position = uObjMVP * aVertexPosition;

            //convert normal direction from object space to view space
            vNormal = uNormalMV * aNormal;

            vShadowPositionFromLight = uShadowMVP * aVertexPosition;
        }
    </script>

    <script id="shader-fragment" type="x-shader/x-fragment">
        precision mediump float;

        uniform sampler2D uShadowMap;

        varying vec3 vNormal;
        varying vec4 vShadowPositionFromLight;

        struct baseColor {
            vec3 ambient;
            vec3 diffuse;
        };

        struct directLight {
            vec3 direction;
            vec3 color;
        };

        baseColor mysObjBaseColor = baseColor(
            vec3(1.0, 1.0, 1.0),
            vec3(1.0, 1.0, 1.0)
        );

        directLight warmLight = directLight(
            normalize(vec3(-83.064, -1.99, -173.467)),
            vec3(0.831, 0.976, 0.243)
        );

        directLight coldLight = directLight(
            normalize(vec3(37.889, 47.864, -207.187)),
            vec3(0.196, 0.361, 0.608)
        );

        vec3 ambientLightColor = vec3(0.3, 0.3, 0.3);

        float unpackDepth(const in vec4 rgbaDepth) {
            const vec4 bitShift = vec4(1.0, 1.0/256.0, 1.0/(256.0*256.0), 1.0/(256.0*256.0*256.0));
            float depth = dot(rgbaDepth, bitShift);
            return depth;
        }

        float calVisibility() {
            vec3 shadowCoord = (vShadowPositionFromLight.xyz/vShadowPositionFromLight.w)/2.0 + 0.5;
            float depth = unpackDepth(texture2D(uShadowMap, shadowCoord.xy));
            return (shadowCoord.z > depth + 0.005) ? 0.4 : 1.0;
        }

        vec3 calAmbientLight(){
            return ambientLightColor * mysObjBaseColor.ambient;
        }

        vec3 calDiffuseLight(const in directLight light, const in float visibility){
            vec3 inverseLightDir = light.direction * -1.0;
            float dot = max(dot(inverseLightDir, normalize(vNormal)), 0.0);
            return light.color * mysObjBaseColor.diffuse * dot * visibility;
        }

        void main() {
            vec3 ambientLight = calAmbientLight();
            float visibility = calVisibility();
            vec3 warmDiffuseLight = calDiffuseLight(warmLight, visibility);
            // cold light does not cast shadow and hence visilibility is always 1.0
            vec3 coldDiffuseLight = calDiffuseLight(coldLight, 1.0);
            gl_FragColor = vec4(coldDiffuseLight + warmDiffuseLight + ambientLight, 1.0);
        }
    </script>

如果我只是将深度信息绘制到画布上,

        void main() {
            // vec3 ambientLight = calAmbientLight();
            // float visibility = calVisibility();
            // vec3 warmDiffuseLight = calDiffuseLight(warmLight, visibility);
            // // cold light does not cast shadow and hence visilibility is always 1.0
            // vec3 coldDiffuseLight = calDiffuseLight(coldLight, 1.0);
            // gl_FragColor = vec4(coldDiffuseLight + warmDiffuseLight + ambientLight, 1.0);

            vec3 shadowCoord = (vShadowPositionFromLight.xyz/vShadowPositionFromLight.w)/2.0 + 0.5;
            gl_FragColor = vec4(unpackDepth(texture2D(uShadowMap, shadowCoord.xy)), 0.0, 0.0, 1.0);
        }

我会得到这张照片 It seems that some fragments does not have corresponded depth value recorded in the first pass 提前谢谢。

0 个答案:

没有答案