overte-lubosz/interface/resources/shaders/ambient_occlusion.frag
2014-11-03 17:36:10 -08:00

79 lines
2.4 KiB
GLSL

#version 120
//
// ambient_occlusion.frag
// fragment shader
//
// Created by Andrzej Kapolka on 7/5/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the depth texture
uniform sampler2D depthTexture;
// the random rotation texture
uniform sampler2D rotationTexture;
// the sample kernel containing the unit offset vectors
const int SAMPLE_KERNEL_SIZE = 16;
uniform vec3 sampleKernel[SAMPLE_KERNEL_SIZE];
// the distance to the near clip plane
uniform float near;
// the distance to the far clip plane
uniform float far;
// the left and bottom edges of the view window
uniform vec2 leftBottom;
// the right and top edges of the view window
uniform vec2 rightTop;
// an offset value to apply to the texture coordinates
uniform vec2 texCoordOffset;
// a scale value to apply to the texture coordinates
uniform vec2 texCoordScale;
// the radius of the effect
uniform float radius;
// the scale for the noise texture
uniform vec2 noiseScale;
// given a texture coordinate, returns the 3D view space z coordinate
float texCoordToViewSpaceZ(vec2 texCoord) {
return (far * near) / (texture2D(depthTexture, texCoord * texCoordScale + texCoordOffset).r * (far - near) - far);
}
// given a texture coordinate, returns the 3D view space coordinate
vec3 texCoordToViewSpace(vec2 texCoord) {
float z = texCoordToViewSpaceZ(texCoord);
return vec3((leftBottom + texCoord * (rightTop - leftBottom)) * (-z / near), z);
}
void main(void) {
vec3 rotationX = texture2D(rotationTexture, gl_TexCoord[0].st * noiseScale).rgb;
vec3 rotationY = normalize(cross(rotationX, vec3(0.0, 0.0, 1.0)));
mat3 rotation = mat3(rotationX, rotationY, cross(rotationX, rotationY));
vec3 center = texCoordToViewSpace(gl_TexCoord[0].st);
vec2 rdenominator = 1.0 / (rightTop - leftBottom);
vec2 xyFactor = 2.0 * near * rdenominator;
vec2 zFactor = (rightTop + leftBottom) * rdenominator;
float occlusion = 4.0;
for (int i = 0; i < SAMPLE_KERNEL_SIZE; i++) {
vec3 offset = center + rotation * (radius * sampleKernel[i]);
vec2 projected = offset.xy * xyFactor + offset.z * zFactor;
float depth = texCoordToViewSpaceZ(projected * -0.5 / offset.z + vec2(0.5, 0.5));
occlusion += 1.0 - step(offset.z, depth);
}
gl_FragColor = vec4(occlusion, occlusion, occlusion, 0.0) / 16.0;
}