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;
}