WebGL Dof

168 阅读1分钟

WebGL Depth of Field (nutty.ca)

原文

attribute vec3 Vertex;
attribute vec2 Uv;
uniform mat4 ProjectionMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ModelMatrix;
varying vec2 vUv;
void main () {
    gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(Vertex, 1.0);
    vUv = Uv;
}
#ifdef GL_ES
    precision highp float;
#endif

#define PI 3.141592

varying vec2 vUv;
uniform sampler2D Sample0;
uniform sampler2D Sample1;
const float near = 0.94;
const float far = 0.975;
float unpack (vec4 colour) {
    const vec4 bitShifts = vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0);
    return dot(colour, bitShifts);
}
void main () {
    float depth = unpack(texture2D(Sample0, vUv));
    vec3 colour = vec3(0, 0, 0);
    float texelSize = 0.0;
    // 非中间段 根据距离都乘以一个系数
    if ( depth > far )
        texelSize = (depth - far) * 0.2;
    else if ( depth < near )
        texelSize = (near - depth) * 0.2;
    // 设置最大的texelsize
    if ( texelSize > (1.0 / 256.0) )
        texelSize = 1.0 / 256.0;
    //开始计算 4x4中 非中间深度 就会融合再除以 否则就是原来颜色
    float neighbourDepth;
    int count = 0;
    for (int y = -2; y <= 2; ++y) { //上下 相邻 5x5 
        for (int x = -2; x <= 2; ++x) {
            vec2 offset = vUv + vec2(float(x) * texelSize, float(y) * texelSize);
            if ( (offset.x >= 0.0) && (offset.x <= 1.0) && (offset.y >= 0.0) && (offset.y <= 1.0) ) {
                neighbourDepth = unpack(texture2D(Sample0, offset));
                if ( (neighbourDepth < near) || (neighbourDepth > far) ) { //深度
                    colour += texture2D(Sample1, offset).xyz; //颜色
                    ++count;
                }
            }
        }
    }
    if ( count > 0 )
        colour /= float(count); //除以
    else
        colour = texture2D(Sample1, vUv).xyz;
    gl_FragColor.xyz = colour.xyz;
    gl_FragColor.w = 1.0;
}

image.png

image.png