TkAstral3D/packages/sdk/public/resource/shaders/water/utils.glsl
2026-04-08 15:34:43 +08:00

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