trueno/src/shaders/shader_plane.glsl

160 lines
4.2 KiB
GLSL

@vs vs_plane
in vec4 position;
layout(binding=0) uniform plane_vs_params {
mat4 mvp;
};
out vec4 pos;
out flat int idx;
void main() {
vec3 multisize = vec3(position.xyz * 1000.0);
gl_Position = mvp * vec4(multisize, 1.0);
pos = vec4(multisize, 1.0);
idx = gl_InstanceIndex;
}
@end
@fs fs_plane
in vec4 pos;
in flat int idx;
out vec4 frag_color;
uint murmurHash12(uvec2 src) {
const uint M = 0x5bd1e995u;
uint h = 1190494759u;
src *= M; src ^= src>>24u; src *= M;
h *= M; h ^= src.x; h *= M; h ^= src.y;
h ^= h>>13u; h *= M; h ^= h>>15u;
return h;
}
float hash12(vec2 src) {
uint h = murmurHash12(floatBitsToUint(src));
return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0;
}
layout(binding=1) uniform plane_world_config {
vec3 skyBase;
vec3 skyTop;
vec3 sunDisk;
vec3 horizonHalo;
vec3 sunHalo;
vec3 sunLightColor;
vec3 sunPosition;
float sunIntensity;
float skyIntensity;
int hasClouds;
int hasPlane;
float planeHeight;
int planeType;
float time;
float grassDensity;
};
layout(binding=2) uniform plane_data {
int screen_w;
int screen_h;
int is_reflection_pass;
};
layout(binding = 0) uniform texture2D reftex;
layout(binding = 1) uniform texture2D groundtex;
layout(binding = 2) uniform texture2D shadow;
layout(binding = 0) uniform sampler refsmp;
layout(binding = 1) uniform sampler groundsmp;
layout(binding = 2) uniform sampler shadowsmp;
float random (vec2 st) {
return fract(sin(dot(st.xy,
vec2(12.9898,78.233)))*
43758.5453123);
}
// 2D Noise based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd
float noise (vec2 st) {
vec2 i = floor(st); // Integer part of the coordinate
vec2 f = fract(st); // Fractional part of the coordinate
// Four corners in 2D of a tile
float a = random(i);
float b = random(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0));
// Smoothstep for interpolation
vec2 u = f*f*(3.0-2.0*f);
// Mix (interpolate) the corners
return mix(a, b, u.x) +
(c - a)* u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}
int sign2(float x) {
if(x < 0) return -1;
return 1;
}
vec3 get_ground_sample(vec4 pos, float dirX, float dirY) {
ivec2 plane_coord = ivec2(floor(pos.x + dirX) + 500, floor(pos.z + dirY) + 500);
vec4 reflection = texelFetch(sampler2D(reftex, refsmp), ivec2(gl_FragCoord.x, screen_h - gl_FragCoord.y), 0);
vec4 groundSample = texelFetch(sampler2D(groundtex, groundsmp), plane_coord, 0);
// Calculate all materials so we can blend them.
vec3 water = reflection.xyz * vec3(0.95, 1.0, 0.95);
vec3 sand = vec3(mix(0.8, 1.0, hash12(pos.xz)) * vec3(0.8, 0.7, 0.5));
vec3 grass = vec3(mix(0.8, 1.0, hash12(pos.xz)) * vec3(0.4, 0.8, 0.3));
if(groundSample.b == 1.0) {
return water;
} else if(groundSample.r == 1.0) {
return sand;
} else {
return grass;
}
}
void main() {
vec4 npos = round(pos * 16.0) / 16.0;
vec2 tileCenter = vec2(floor(npos.x) + 0.5, floor(npos.z) + 0.5);
vec2 toCenter = npos.xz - tileCenter;
// Bilinear filtering
float u = smoothstep(0.2, 0.5, abs(toCenter.x)) * 0.5;
float v = smoothstep(0.2, 0.5, abs(toCenter.y)) * 0.5;
// @ToDo: We should implement some sort of fog system and stop doing all this sampling
// stuff if we are far enough from the camera. Currently ground rendering is taking way
// too much time each frame.
vec3 c0 = get_ground_sample(npos, 0.0, 0.0);
vec3 c1 = get_ground_sample(npos, sign2(toCenter.x), 0.0);
vec3 c2 = get_ground_sample(npos, 0.0, sign2(toCenter.y));
vec3 c3 = get_ground_sample(npos, sign2(toCenter.x), sign2(toCenter.y));
float shadowp = texture(sampler2DShadow(shadow, shadowsmp), vec3(0,0,0));
// @ToDo: Consider using cool Inigo Quilez trick here to make it even smoother.
vec3 b01 = mix(c0, c1, u);
vec3 b23 = mix(c2, c3, u);
vec3 bf = mix(b01, b23, v);
if(planeType == 1) {
frag_color = vec4(bf, 1.0);
} else {
frag_color = vec4(vec3(shadowp), 1.0);
}
}
@end
@program plane vs_plane fs_plane