74 lines
2.3 KiB
GLSL
74 lines
2.3 KiB
GLSL
vec2 intersectCylinder(vec3 origin, vec3 ray, float radius, float yMin, float yMax) {
|
|
float a = ray.x * ray.x + ray.z * ray.z;
|
|
float b = 2.0 * (origin.x * ray.x + origin.z * ray.z);
|
|
float c = origin.x * origin.x + origin.z * origin.z - radius * radius;
|
|
|
|
float tNear = -1e10;
|
|
float tFar = 1e10;
|
|
|
|
if (a > 1e-6) {
|
|
float discriminant = b * b - 4.0 * a * c;
|
|
if (discriminant < 0.0) return vec2(1e10, -1e10);
|
|
float sqrtDisc = sqrt(discriminant);
|
|
tNear = (-b - sqrtDisc) / (2.0 * a);
|
|
tFar = (-b + sqrtDisc) / (2.0 * a);
|
|
}
|
|
|
|
if (abs(ray.y) > 1e-6) {
|
|
float tBottom = (yMin - origin.y) / ray.y;
|
|
float tTop = (yMax - origin.y) / ray.y;
|
|
float tCapNear = min(tBottom, tTop);
|
|
float tCapFar = max(tBottom, tTop);
|
|
tNear = max(tNear, tCapNear);
|
|
tFar = min(tFar, tCapFar);
|
|
} else {
|
|
if (origin.y < yMin || origin.y > yMax) return vec2(1e10, -1e10);
|
|
}
|
|
|
|
return vec2(tNear, tFar);
|
|
}
|
|
|
|
|
|
vec3 getCylinderWallColor(vec3 point) {
|
|
float scale = 0.5;
|
|
|
|
vec3 wallColor = tilesColor;
|
|
vec3 normal;
|
|
float r = length(point.xz);
|
|
|
|
float edge = poolRadius - 0.001;
|
|
|
|
if (r > edge) {
|
|
float angle = atan(point.z, point.x);
|
|
vec2 uv = vec2(angle / 3.14159 * 0.5 + 0.5, point.y / poolHeight * 0.5 + 0.5);
|
|
if (useTiles > 0.5) {
|
|
wallColor = texture(tiles, uv).rgb;
|
|
}
|
|
normal = vec3(-point.x / r, 0.0, -point.z / r);
|
|
} else {
|
|
vec2 uv = point.xz / (poolRadius * 2.0) + 0.5;
|
|
if (useTiles > 0.5) {
|
|
wallColor = texture(tiles, uv).rgb;
|
|
}
|
|
normal = vec3(0.0, 1.0, 0.0);
|
|
}
|
|
|
|
scale /= length(point);
|
|
|
|
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 = point.xz / (poolRadius * 2.0) + 0.5;
|
|
vec4 info = texture(water, waterCoord);
|
|
if (point.y < info.r) {
|
|
vec2 causticCoord = (point.xz - point.y * refractedLight.xz / refractedLight.y) / (poolRadius * 2.0);
|
|
vec4 caustic = texture(causticTex, 0.75 * causticCoord + 0.5);
|
|
scale += diffuse * caustic.r * 2.0 * caustic.g;
|
|
} else {
|
|
vec2 t = intersectCylinder(point, refractedLight, poolRadius, -poolHeight, poolHeight * 2.0);
|
|
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;
|
|
}
|