88 lines
2.6 KiB
GLSL
88 lines
2.6 KiB
GLSL
const float IOR_AIR = 1.0;
|
|
const float IOR_WATER = 1.333;
|
|
|
|
const vec3 abovewaterColor = vec3(0.25, 1.0, 1.25);
|
|
const vec3 underwaterColor = vec3(0.4, 0.9, 1.0);
|
|
|
|
uniform float poolHeight;
|
|
uniform vec2 poolHalfSize;
|
|
uniform float poolRadius;
|
|
|
|
uniform vec3 light;
|
|
uniform sampler2D tiles;
|
|
uniform sampler2D causticTex;
|
|
uniform sampler2D water;
|
|
uniform float useTiles;
|
|
uniform vec3 tilesColor;
|
|
|
|
|
|
vec2 intersectCube(vec3 origin, vec3 ray, vec3 cubeMin, vec3 cubeMax) {
|
|
vec3 tMin = (cubeMin - origin) / ray;
|
|
vec3 tMax = (cubeMax - origin) / ray;
|
|
vec3 t1 = min(tMin, tMax);
|
|
vec3 t2 = max(tMin, tMax);
|
|
float tNear = max(max(t1.x, t1.y), t1.z);
|
|
float tFar = min(min(t2.x, t2.y), t2.z);
|
|
return vec2(tNear, tFar);
|
|
}
|
|
|
|
|
|
vec3 getWallColor(vec3 point) {
|
|
float scale = 0.5;
|
|
|
|
vec3 wallColor = tilesColor;
|
|
vec3 normal;
|
|
float edgeX = poolHalfSize.x - 0.001;
|
|
float edgeZ = poolHalfSize.y - 0.001;
|
|
|
|
if (abs(point.x) > edgeX) {
|
|
vec2 uv = vec2(point.y / poolHeight, point.z / poolHalfSize.y);
|
|
if (useTiles > 0.5) {
|
|
wallColor = texture(tiles, uv * 0.5 + vec2(1.0, 0.5)).rgb;
|
|
}
|
|
normal = vec3(-sign(point.x), 0.0, 0.0);
|
|
} else if (abs(point.z) > edgeZ) {
|
|
vec2 uv = vec2(point.y / poolHeight, point.x / poolHalfSize.x);
|
|
if (useTiles > 0.5) {
|
|
wallColor = texture(tiles, uv * 0.5 + vec2(1.0, 0.5)).rgb;
|
|
}
|
|
normal = vec3(0.0, 0.0, -sign(point.z));
|
|
} else {
|
|
vec2 uv = vec2(point.x / poolHalfSize.x, point.z / poolHalfSize.y);
|
|
if (useTiles > 0.5) {
|
|
wallColor = texture(tiles, uv * 0.5 + 0.5).rgb;
|
|
}
|
|
normal = vec3(0.0, 1.0, 0.0);
|
|
}
|
|
|
|
scale /= length(point); /* pool ambient occlusion */
|
|
|
|
/* caustics */
|
|
vec3 refractedLight = -refract(-light, vec3(0.0, 1.0, 0.0), IOR_AIR / IOR_WATER);
|
|
float diffuse = max(0.0, dot(refractedLight, normal));
|
|
vec2 waterCoord = vec2(
|
|
point.x / (poolHalfSize.x * 2.0) + 0.5,
|
|
point.z / (poolHalfSize.y * 2.0) + 0.5
|
|
);
|
|
vec4 info = texture(water, waterCoord);
|
|
if (point.y < info.r) {
|
|
vec2 poolScale = poolHalfSize * 2.0;
|
|
vec2 causticCoord = (point.xz - point.y * refractedLight.xz / refractedLight.y) / poolScale;
|
|
vec4 caustic = texture(causticTex, 0.75 * causticCoord + 0.5);
|
|
scale += diffuse * caustic.r * 2.0 * caustic.g;
|
|
} else {
|
|
/* shadow for the rim of the pool */
|
|
vec2 t = intersectCube(
|
|
point,
|
|
refractedLight,
|
|
vec3(-poolHalfSize.x, -poolHeight, -poolHalfSize.y),
|
|
vec3(poolHalfSize.x, poolHeight * 2.0, poolHalfSize.y)
|
|
);
|
|
diffuse *= 1.0 / (1.0 + exp(-200.0 / (1.0 + 10.0 * (t.y - t.x)) * (point.y + refractedLight.y * t.y - poolHeight * 2.0 / 12.0)));
|
|
|
|
scale += diffuse * 0.5;
|
|
}
|
|
|
|
return wallColor * scale;
|
|
}
|