zoukankan      html  css  js  c++  java
  • ShadowMap

    ShadowMap

      一个物体之所以会处在阴影当中,是由于在它和光源之间存在着遮蔽物,或者说遮蔽物离光源的距离比物体要近,这就是 shadow mapping 算法的基本原理。

      Pass1: 以光源为视点,或者说在光源坐标系下面对整个场景进行渲染,目的是要得到一副所有物体相对于光源的 depth map (也就是我们所说的shadow map),也就是这副图像中每个象素的值代表着场景里面离光源最近的 fragment 的深度值。由于这个pass中我们感兴趣的只是象素的深度值,所以可以把所有的光照计算关掉,打开 z-test 和 z-write 的 render state 。

      Pass2: 将视点恢复到原来的正常位置,渲染整个场景,对每个象素计算它和光源的距离,然后将这个值和 depth map中相应的值比较,以确定这个象素点是否处在阴影当中。然后根据比较的结果,对 shadowed fragment 和 lighted fragment 分别进行不同的光照计算,这样就可以得到阴影的效果了。 

      从上面的分析可以看出来,depth map的渲染只和光源的位置以及场景中物体的位置有关,无论视点怎么运动,只要光源和物体的相互位置关系不变,shadow map就可以被重复使用,因此对于没有动态光源的场景,shadow mapping 是很明智的一种选择。

      Shadows add a great deal of realism to a lighted scene and make it easier for a viewer to observe spatial relationships between objects.

      

        

        

        

      Vetex Shader:

    #version 330 core
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 aNormal;
    layout (location = 2) in vec2 aTexCoords;
    
    out VS_OUT {
        vec3 FragPos;
        vec3 Normal;
        vec2 TexCoords;
        vec4 FragPosLightSpace;
    } vs_out;
    
    uniform mat4 projection;
    uniform mat4 view;
    uniform mat4 model;
    uniform mat4 lightSpaceMatrix;
    
    void main()
    {    
        vs_out.FragPos = vec3(model * vec4(aPos, 1.0));
        vs_out.Normal = transpose(inverse(mat3(model))) * aNormal;
        vs_out.TexCoords = aTexCoords;
        vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
        gl_Position = projection * view * model * vec4(aPos, 1.0);
    }
    View Code

      Pixel Shader中的深度比较函数:

    float ShadowCalculation(vec4 fragPosLightSpace)
    {
        // perform perspective divide
        vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
        // transform to [0,1] range
        projCoords = projCoords * 0.5 + 0.5;
        // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
        float closestDepth = texture(shadowMap, projCoords.xy).r; 
        // get depth of current fragment from light's perspective
        float currentDepth = projCoords.z;
        // check whether current frag pos is in shadow
        float shadow = currentDepth > closestDepth  ? 1.0 : 0.0;
    
        return shadow;
    }  
    View Code

         

    Shadow acne

      上面的渲染结果中会有黑色的条纹。

        

      Because the shadow map is limited by resolution, multiple fragments can sample the same value from the depth map when they're relatively far away from the light source. The image shows the floor where each tilted panel represents a single texel of the depth map. As you can see, several fragments sample the same depth sample.

        

        

    Peter panning

        

      This shadow artifact is called peter panning since objects seem slightly detached from their shadows. We can use a little trick to solve most of the peter panning issue by using front face culling when rendering the depth map.

    Over sampling

        问题:depth-map以外的部分都黑了。

        

        深度大于1.0,直接无shadow即可。

        

        改进后的效果。

        

     【PCF

        生成的阴影有锯齿。

        

      solution to these jagged edges is called PCF or percentage-closer filtering which is a term that hosts many different filtering functions that produce softer shadows, making them appear less blocky or hard. The idea is to sample more than once from the depth map, each time with slightly different texture coordinates. For each individual sample we check whether it is in shadow or not. All the sub-results are then combined and averaged and we get a nice soft looking shadow.

      

    参考:https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping

  • 相关阅读:
    c++实现单例
    shell查看并修复网络连接
    shell检测interface是否已分配ip,qt调用shell脚本
    ubuntu, Debian, CentOS
    Makefile 中:= ?= += =的区别
    我开新博客了
    soft lockup和hard lockup介绍
    linux系统奔溃之vmcore:kdump 的亲密战友 crash
    布局文件中的sp、dp还有px的区别
    kvmalloc函数
  • 原文地址:https://www.cnblogs.com/tekkaman/p/9066505.html
Copyright © 2011-2022 走看看