stevenarella/src/render/shaders/clouds_geo.glsl

123 lines
3.5 KiB
GLSL

layout(points) in;
layout(triangle_strip, max_vertices = 24) out;
uniform mat4 perspectiveMatrix;
uniform mat4 cameraMatrix;
uniform vec3 offset;
uniform float cloudOffset;
uniform vec4 textureInfo;
uniform float atlas;
uniform sampler2DArray textures;
uniform sampler2D cloudMap;
in vec3 vLighting[];
out vec3 fLighting;
out vec4 fColor;
void setVertex(vec3 base, vec3 off, float color) {
gl_Position = perspectiveMatrix * cameraMatrix * vec4(base + off*vec3(1.0,-1.0,1.0), 1.0);
fColor = vec4(color, color, color, 1.0);
fLighting = vLighting[0];
EmitVertex();
}
float coffset = cloudOffset;
const float invAtlasSize = 1.0 / 1024.0;
vec4 atlasTexture(vec2 tPos) {
tPos.y += floor(coffset);
tPos = mod(tPos, textureInfo.zw);
tPos += textureInfo.xy;
tPos *= invAtlasSize;
return texture(textures, vec3(tPos, atlas));
}
ivec2 texP = ivec2(0, 0);
ivec2 heightP = ivec2(0, 0);
bool isSolid(ivec2 pos) {
float height = texelFetch(cloudMap, ivec2(mod(heightP + pos, 512)), 0).r;
if (height >= 127.0/255.0) return false;
return atlasTexture(vec2(texP + pos)).r + height > (250.0 / 255.0);
}
bool isFutureSolid(ivec2 pos) {
// Sneak a peak into the future
coffset += 1.0;
bool ret = isSolid(pos);
coffset -= 1.0;
return ret;
}
void main() {
vec3 base = floor(offset) + gl_in[0].gl_Position.xyz;
texP = ivec2(gl_in[0].gl_Position.xz + 160.0 + offset.xz) - ivec2(0.0, -1.0);
heightP = ivec2(mod(base.xz, 512));
if (!isSolid(ivec2(0))) return;
float backOffset = 1.0 - fract(cloudOffset);
float frontOffset = -fract(cloudOffset);
if (!isFutureSolid(ivec2(0, -1))) {
frontOffset = 0.0;
}
// Top
setVertex(base, vec3(0.0, 1.0, frontOffset), 1.0);
setVertex(base, vec3(1.0, 1.0, frontOffset), 1.0);
setVertex(base, vec3(0.0, 1.0, backOffset), 1.0);
setVertex(base, vec3(1.0, 1.0, backOffset), 1.0);
EndPrimitive();
// Bottom
setVertex(base, vec3(0.0, 0.0, frontOffset), 0.7);
setVertex(base, vec3(0.0, 0.0, backOffset), 0.7);
setVertex(base, vec3(1.0, 0.0, frontOffset), 0.7);
setVertex(base, vec3(1.0, 0.0, backOffset), 0.7);
EndPrimitive();
if (!isSolid(ivec2(-1, 0)) || !isFutureSolid(ivec2(-1, -1))) {
float sideOffset = backOffset;
if (isSolid(ivec2(-1, 1)) && !isFutureSolid(ivec2(-1, 0))) {
sideOffset = 1.0;
}
// -X
setVertex(base, vec3(0.0, 0.0, frontOffset), 0.8);
setVertex(base, vec3(0.0, 1.0, frontOffset), 0.8);
setVertex(base, vec3(0.0, 0.0, sideOffset), 0.8);
setVertex(base, vec3(0.0, 1.0, sideOffset), 0.8);
EndPrimitive();
}
if (!isSolid(ivec2(1, 0)) || !isFutureSolid(ivec2(1, -1))) {
float sideOffset = backOffset;
if (isSolid(ivec2(1, 1)) && !isFutureSolid(ivec2(1, 0))) {
sideOffset = 1.0;
}
// +X
setVertex(base, vec3(1.0, 0.0, frontOffset), 0.8);
setVertex(base, vec3(1.0, 0.0, sideOffset), 0.8);
setVertex(base, vec3(1.0, 1.0, frontOffset), 0.8);
setVertex(base, vec3(1.0, 1.0, sideOffset), 0.8);
EndPrimitive();
}
if (!isSolid(ivec2(0, 1)) || !isFutureSolid(ivec2(0, 0))) {
// -Z
setVertex(base, vec3(0.0, 0.0, backOffset), 0.8);
setVertex(base, vec3(0.0, 1.0, backOffset), 0.8);
setVertex(base, vec3(1.0, 0.0, backOffset), 0.8);
setVertex(base, vec3(1.0, 1.0, backOffset), 0.8);
EndPrimitive();
}
if (!isSolid(ivec2(0, -1)) || !isFutureSolid(ivec2(0, -2))) {
// +Z
setVertex(base, vec3(0.0, 0.0, frontOffset), 0.8);
setVertex(base, vec3(1.0, 0.0, frontOffset), 0.8);
setVertex(base, vec3(0.0, 1.0, frontOffset), 0.8);
setVertex(base, vec3(1.0, 1.0, frontOffset), 0.8);
EndPrimitive();
}
}