Skip to content
【转载】cesium 实现体积光 (Volumetric Light) 圣光 (Godrays)

介绍:

体积光,也被称作神光(Godrays)、阳光尘或光束效果(crepuscular rays),是一种视觉效果,经常被用于增强3D渲染图、视频游戏和电影中的自然光照效果。体积光效果通过模拟光线在三维空间中传播时遇到各种障碍(如云、尘埃或水雾等)而产生的散射现象,来产生一种戏剧性和真实感十足的视觉体验。

常用的webgl框架均有实现:

three.js 实现:

babylon 实现:

cesium 实现:

获取一帧只有太阳,径向模糊的画面

获取一帧只有太阳,径向模糊的画面

获取一帧正常的画面

两个画面融合

附上实现代码:(使用cesium最新的版本1.106) 如有问题可以私信我

第一步:使用后处理,对画面进行径向模糊

javascript
const blurShader = `
        uniform sampler2D UserMapSampler;
        uniform vec2 lightPositionOnScreen;
        uniform float decay;
        uniform float exposure;
        uniform float density;
        uniform float weight;
        in vec2 v_textureCoordinates; 
        bool isSunVisible(vec2 position) {
            return position.x > 0.0 && position.x < 1.0 && position.y > 0.0 && position.y < 1.0;
        }
        void main()
        {   
            vec2 tc = v_textureCoordinates; 
            int NUM_SAMPLES = 100;
            vec2 deltaTexCoord = (tc - lightPositionOnScreen.xy);
            deltaTexCoord *= 1.0 / float(NUM_SAMPLES) * density;
            float illuminationDecay = 1.0;
            vec4 color =texture(UserMapSampler, tc)*0.4;
            for(int i=0; i < NUM_SAMPLES ; i++)
            {
                tc -= deltaTexCoord;
                vec4 mysample = texture(UserMapSampler, tc)*0.4;
                mysample *= illuminationDecay * weight;
                color += mysample;
                illuminationDecay *= decay;
            }
            out_FragColor = vec4(color.rgb * exposure, 1.0);
        }
      `;

第二步:对遮挡太阳的进行遮挡,得到一个只有阳光的图

javascript
    `
          #version 300 es
          uniform sampler2D passTexture;
          uniform sampler2D depthTexture; // 场景深度纹理
          uniform bool isSkyAtmosphereVisible; // 大气是否显示
          in vec2 v_textureCoordinates; // 来自顶点着色器的纹理坐标
          float getDepth(in vec4 depth) {
                float z_window = czm_unpackDepth(depth);
                z_window = czm_reverseLogDepth(z_window);
                float n_range = czm_depthRange.near;
                float f_range = czm_depthRange.far;
                return (2.0 * z_window - n_range - f_range) / (f_range - n_range);
          }
          void main() {
              vec4 color;
              vec4 depthColor = texture(depthTexture, v_textureCoordinates);
              float depth = getDepth(depthColor);
              if (depth >= 1.0) {
                color = texture(passTexture, v_textureCoordinates);
              } else {
                color = vec4(0.0, 0.0, 0.0, 1.0);
              }
              out_FragColor = color;
          }
        `

第三步、对获取到的两张图进行融合

javascript
`
              uniform sampler2D baseTexture;
              uniform sampler2D blendTexture;
              in vec2 v_textureCoordinates;
              float blendScreen(float base, float blend) {
                return 1.0-((1.0-base)*(1.0-blend));
              }
              vec3 blendScreen(vec3 base, vec3 blend) {
                return vec3(blendScreen(base.r,blend.r),blendScreen(base.g,blend.g),blendScreen(base.b,blend.b));
              }
              void main()
              {           
                  vec4 base = texture(baseTexture, v_textureCoordinates);
                  vec4 blend = texture(blendTexture, v_textureCoordinates);
                  vec3 sceneColor = blend.xyz;
                  sceneColor = czm_RGBToHSB(sceneColor);
                  if (sceneColor.z > 0.8) {
                    sceneColor.z -= 0.2; // 降低亮度
                    // 限制亮度值在0到1之间
                    sceneColor.z = max(sceneColor.z, 0.0);
                  }
                  sceneColor = czm_HSBToRGB(sceneColor);
                  float opacity = 1.0;
                  vec3 blendColorDodge = (blendScreen(vec3(base.rgb), sceneColor)) * opacity + vec3((base.rgb) * (1.0 - opacity));
                  out_FragColor = vec4(blendColorDodge, base.a);
              }
            `

本文转自 https://blog.csdn.net/baidu_38716385/article/details/138141421?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-4-138141421-blog-131343531.235^v43^pc_blog_bottom_relevance_base2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-4-138141421-blog-131343531.235^v43^pc_blog_bottom_relevance_base2&utm_relevant_index=8,如有侵权,请联系删除。

Updated at: