mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-06-21 18:17:03 +08:00
feat: water effects (#19)
* feat(shaders): add lighting to block accumulation OIT shaders * feat(renderer): add water rendering with OIT and new shaders * feat(water): implement screen-space reflection and refraction for water with depth fade and perturbation * refactor(shader): replace glUniform calls with generic set_loc and remove cached locations * feat(water): add noise-based caustics and configurable fog density * fix(water shader): update depth fade and remove underwater check - Increase DEPTH_FADE_DISTANCE from 8 to 10 - Remove conditional so depth fade always applies - Darken deepColor from (0, 0.08, 0.15) to (0, 0.015, 0.045) * feat(underwater): add volume scattering and shadow mapping for light shafts
This commit is contained in:
@@ -4,10 +4,21 @@ layout (location = 0) out vec4 accum;
|
|||||||
layout (location = 1) out float reveal;
|
layout (location = 1) out float reveal;
|
||||||
|
|
||||||
in vec2 tc;
|
in vec2 tc;
|
||||||
|
in vec3 normal;
|
||||||
|
in vec3 vert_pos;
|
||||||
|
in float roughness;
|
||||||
flat in int tex_layer;
|
flat in int tex_layer;
|
||||||
in float v_depth;
|
in float v_depth;
|
||||||
layout (binding = 0) uniform sampler2DArray samp;
|
layout (binding = 0) uniform sampler2DArray samp;
|
||||||
|
|
||||||
|
uniform float ambientStrength;
|
||||||
|
uniform vec3 sunlightColor;
|
||||||
|
uniform vec3 ambientColor;
|
||||||
|
uniform vec3 sunlightDir;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform bool shader_on;
|
||||||
|
uniform float specularStrength;
|
||||||
|
|
||||||
float weight(float z, float a) {
|
float weight(float z, float a) {
|
||||||
float intermediate = 0.03 / (1e-5 + pow(z / 200.0, 4.0));
|
float intermediate = 0.03 / (1e-5 + pow(z / 200.0, 4.0));
|
||||||
|
|
||||||
@@ -15,7 +26,71 @@ float weight(float z, float a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 color = texture(samp, vec3(tc, tex_layer));
|
|
||||||
|
vec4 objectColor = texture(samp, vec3(tc, tex_layer));
|
||||||
|
|
||||||
|
if (!shader_on) {
|
||||||
|
vec4 color = objectColor;
|
||||||
|
float alpha = color.a;
|
||||||
|
if (alpha < 1e-4) discard;
|
||||||
|
|
||||||
|
|
||||||
|
float w = weight(v_depth, alpha);
|
||||||
|
|
||||||
|
accum = vec4(color.rgb * alpha * w, alpha * w);
|
||||||
|
|
||||||
|
reveal = alpha;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 lightDir = normalize(-sunlightDir);
|
||||||
|
|
||||||
|
vec3 norm = normalize(normal);
|
||||||
|
|
||||||
|
vec3 V =
|
||||||
|
normalize(cameraPos - vert_pos);
|
||||||
|
|
||||||
|
vec3 H =
|
||||||
|
normalize(lightDir + V);
|
||||||
|
|
||||||
|
vec3 ambient = ambientStrength * ambientColor;
|
||||||
|
|
||||||
|
float diff = max(dot(norm, lightDir), 0.0);
|
||||||
|
|
||||||
|
vec3 diffuse = diff * sunlightColor;
|
||||||
|
|
||||||
|
float r =
|
||||||
|
clamp(roughness, 0.0, 1.0);
|
||||||
|
|
||||||
|
float shininess =
|
||||||
|
mix(
|
||||||
|
512.0,
|
||||||
|
4.0,
|
||||||
|
r
|
||||||
|
);
|
||||||
|
float ks =
|
||||||
|
mix(
|
||||||
|
0.8,
|
||||||
|
0.02,
|
||||||
|
r
|
||||||
|
);
|
||||||
|
|
||||||
|
float spec = 0.0;
|
||||||
|
|
||||||
|
if(diff > 0.0)
|
||||||
|
{
|
||||||
|
spec =
|
||||||
|
ks *
|
||||||
|
pow(
|
||||||
|
max(dot(norm,H),0.0),
|
||||||
|
shininess
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 specular = spec * sunlightColor * specularStrength;
|
||||||
|
|
||||||
|
vec4 color = vec4((ambient + diffuse) * objectColor.rgb + specular, objectColor.a);
|
||||||
|
|
||||||
float alpha = color.a;
|
float alpha = color.a;
|
||||||
if (alpha < 1e-4) discard;
|
if (alpha < 1e-4) discard;
|
||||||
|
|
||||||
|
|||||||
@@ -3,19 +3,28 @@
|
|||||||
layout (location = 0) in vec3 pos;
|
layout (location = 0) in vec3 pos;
|
||||||
layout (location = 1) in vec2 texCoord;
|
layout (location = 1) in vec2 texCoord;
|
||||||
layout (location = 2) in float layer;
|
layout (location = 2) in float layer;
|
||||||
|
layout (location = 3) in vec3 aNormal;
|
||||||
|
layout (location = 4) in float Roughness;
|
||||||
|
|
||||||
out vec2 tc;
|
out vec2 tc;
|
||||||
|
out vec3 normal;
|
||||||
|
out vec3 vert_pos;
|
||||||
flat out int tex_layer;
|
flat out int tex_layer;
|
||||||
|
out float roughness;
|
||||||
out float v_depth;
|
out float v_depth;
|
||||||
|
|
||||||
uniform mat4 mv_matrix;
|
uniform mat4 mv_matrix;
|
||||||
uniform mat4 proj_matrix;
|
uniform mat4 proj_matrix;
|
||||||
|
uniform mat4 norm_matrix;
|
||||||
|
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 view_pos = mv_matrix * vec4(pos, 1.0);
|
vec4 view_pos = mv_matrix * vec4(pos, 1.0);
|
||||||
gl_Position = proj_matrix * view_pos;
|
vert_pos = pos;
|
||||||
|
roughness = Roughness;
|
||||||
tc = texCoord;
|
tc = texCoord;
|
||||||
tex_layer = int(layer);
|
tex_layer = int(layer);
|
||||||
v_depth = -view_pos.z;
|
v_depth = -view_pos.z;
|
||||||
|
normal = mat3(norm_matrix) * aNormal;
|
||||||
|
gl_Position = proj_matrix * view_pos;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ float fbm(vec2 p) {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void) {
|
vec3 computeSkyColor(vec3 dir) {
|
||||||
vec3 sund = normalize(sunDir);
|
vec3 sund = normalize(sunDir);
|
||||||
|
|
||||||
float t =
|
float t =
|
||||||
@@ -88,6 +88,13 @@ void main(void) {
|
|||||||
|
|
||||||
sky += glow * sunColor;
|
sky += glow * sunColor;
|
||||||
|
|
||||||
|
return sky;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
|
||||||
|
vec3 sky = computeSkyColor(dir);
|
||||||
|
|
||||||
frag_color = vec4(sky, 1.0);
|
frag_color = vec4(sky, 1.0);
|
||||||
//frag_color = vec4(vec3(sunAmount), 1.0);
|
//frag_color = vec4(vec3(sunAmount), 1.0);
|
||||||
//frag_color = vec4(t,0,0,1);
|
//frag_color = vec4(t,0,0,1);
|
||||||
|
|||||||
@@ -1,35 +1,137 @@
|
|||||||
#version 460
|
#version 460
|
||||||
|
|
||||||
in vec2 TexCoord;
|
in vec2 TexCoord;
|
||||||
|
in vec3 rayDir;
|
||||||
|
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
|
||||||
uniform sampler2D u_sceneTexture;
|
layout (binding = 0) uniform sampler2D u_sceneTexture;
|
||||||
|
layout (binding = 1) uniform sampler2D u_depthTexture;
|
||||||
|
layout (binding = 2) uniform sampler2D u_shadowMap;
|
||||||
|
uniform mat4 u_lightSpaceMatrix;
|
||||||
uniform float u_time;
|
uniform float u_time;
|
||||||
uniform bool u_underwater;
|
uniform bool u_underwater;
|
||||||
uniform vec3 u_waterColor;
|
uniform vec3 u_waterColor;
|
||||||
uniform float u_fogDensity;
|
uniform float u_fogDensity;
|
||||||
|
uniform mat4 InverseViewProjection;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform vec3 sunDir;
|
||||||
|
uniform vec3 sunColor;
|
||||||
|
uniform float waterDensity;
|
||||||
|
|
||||||
|
float hash(vec2 p) {
|
||||||
|
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
||||||
|
}
|
||||||
|
|
||||||
|
float noise(vec2 p) {
|
||||||
|
vec2 i = floor(p);
|
||||||
|
vec2 f = fract(p);
|
||||||
|
f = f * f * (3.0 - 2.0 * f);
|
||||||
|
|
||||||
|
return mix(
|
||||||
|
mix(hash(i), hash(i + vec2(1.0, 0.0)), f.x),
|
||||||
|
mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), f.x),
|
||||||
|
f.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
float fbm(vec2 p) {
|
||||||
|
float value = 0.0;
|
||||||
|
float amp = 0.5;
|
||||||
|
float freq = 1.0;
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
value += amp * noise(p * freq);
|
||||||
|
freq *= 2.0;
|
||||||
|
amp *= 0.5;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getCausticValue(float x, float y, float z) {
|
||||||
|
float w = 8.0;
|
||||||
|
float strength = 4.0;
|
||||||
|
vec2 coord = vec2(x, y) * w + z * 0.5;
|
||||||
|
|
||||||
|
float n = fbm(coord);
|
||||||
|
|
||||||
|
float caustic = pow(n, 3.0) * strength;
|
||||||
|
return caustic;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getShadow(vec3 worldPos) {
|
||||||
|
vec4 posLightSpace = u_lightSpaceMatrix * vec4(worldPos, 1.0);
|
||||||
|
vec3 projCoords = posLightSpace.xyz / posLightSpace.w;
|
||||||
|
projCoords = projCoords * 0.5 + 0.5;
|
||||||
|
|
||||||
|
if (projCoords.z > 1.0) return 1.0;
|
||||||
|
|
||||||
|
float closestDepth = texture(u_shadowMap, projCoords.xy).r;
|
||||||
|
float currentDepth = projCoords.z;
|
||||||
|
|
||||||
|
return currentDepth - 0.005 > closestDepth ? 0.0 : 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 original = texture(u_sceneTexture, TexCoord);
|
vec4 original = texture(u_sceneTexture, TexCoord);
|
||||||
|
|
||||||
if (!u_underwater) {
|
if (!u_underwater) {
|
||||||
FragColor = original;
|
FragColor = original;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float rawDepth = texture(u_depthTexture, TexCoord).r;
|
||||||
|
vec3 ndc = vec3(TexCoord * 2.0 - 1.0, rawDepth * 2.0 - 1.0);
|
||||||
|
vec4 worldPosH = InverseViewProjection * vec4(ndc, 1.0);
|
||||||
|
vec3 worldPos = worldPosH.xyz / worldPosH.w;
|
||||||
|
float sceneDistance = distance(cameraPos, worldPos);
|
||||||
|
|
||||||
vec2 distoredUV = TexCoord;
|
vec2 distoredUV = TexCoord;
|
||||||
float strength = 0.003;
|
float strength = 0.003;
|
||||||
distoredUV.x += sin(TexCoord.y * 15.0 + u_time * 5.0) * strength;
|
distoredUV.x += sin(TexCoord.y * 15.0 + u_time * 5.0) * strength;
|
||||||
distoredUV.y += cos(TexCoord.x * 15.0 + u_time * 4.3) * strength;
|
distoredUV.y += cos(TexCoord.x * 15.0 + u_time * 4.3) * strength;
|
||||||
distoredUV = clamp(distoredUV, 0.001, 0.999);
|
distoredUV = clamp(distoredUV, 0.001, 0.999);
|
||||||
vec4 distorted = texture(u_sceneTexture, distoredUV);
|
vec4 distorted = texture(u_sceneTexture, distoredUV);
|
||||||
|
|
||||||
|
float rawCaustic = getCausticValue(TexCoord.x, TexCoord.y, u_time * 0.3);
|
||||||
|
float caustic = 0.5 + rawCaustic * 0.5;
|
||||||
|
vec3 causticLight = vec3(caustic * 0.9, caustic, caustic * 0.7);
|
||||||
|
|
||||||
float caustic = 0.9 + 0.1 * sin(TexCoord.x * 20.0 + u_time) * cos(TexCoord.y * 20.0 + u_time * 1.2);
|
|
||||||
vec3 causticLight = vec3(caustic, caustic * 0.95, caustic * 0.9);
|
|
||||||
//vec3 causticLight = vec3(1.0);
|
|
||||||
float fogFactor = clamp(1.0 - (TexCoord.y * u_fogDensity * 10.0), 0.0, 1.0);
|
float fogFactor = clamp(1.0 - (TexCoord.y * u_fogDensity * 10.0), 0.0, 1.0);
|
||||||
vec3 mixed = mix(u_waterColor, distorted.rgb * causticLight, fogFactor);
|
vec3 mixed = mix(u_waterColor, distorted.rgb * causticLight, fogFactor);
|
||||||
|
// Volume Scattering
|
||||||
|
vec3 rayOrigin = cameraPos;
|
||||||
|
vec3 rayDirection = normalize(rayDir);
|
||||||
|
|
||||||
FragColor = vec4(mixed, 1.0);
|
float maxDist = 10.0; // Maximum visible distance
|
||||||
|
float stepSize = 0.4;
|
||||||
|
float phasePower = 8.0; // Beam Sharpness
|
||||||
|
|
||||||
|
vec3 scattering = vec3(0.0);
|
||||||
|
float transmittance = 1.0;
|
||||||
|
|
||||||
|
float cosTheta = dot(rayDirection, sunDir);
|
||||||
|
float phase = pow(max(cosTheta, 0.0), phasePower);
|
||||||
|
|
||||||
|
for (float t = 0.0; t < maxDist; t += stepSize) {
|
||||||
|
|
||||||
|
if (t > sceneDistance) break;
|
||||||
|
vec3 pos = rayOrigin + rayDirection * t;
|
||||||
|
|
||||||
|
float shadow = getShadow(pos);
|
||||||
|
|
||||||
|
float density = waterDensity;
|
||||||
|
|
||||||
|
|
||||||
|
vec3 absorption = vec3(0.3, 0.08, 0.02); // Absorption coefficient per meter
|
||||||
|
vec3 sunLightAtPos = sunColor * exp(-absorption * t);
|
||||||
|
|
||||||
|
scattering += density * phase * sunLightAtPos * transmittance * stepSize * shadow;
|
||||||
|
|
||||||
|
float extinction = waterDensity * 1.5; // Extinction coefficient, tunable
|
||||||
|
transmittance *= exp(-extinction * stepSize);
|
||||||
|
if (transmittance < 0.01) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FragColor.rgb = mixed + scattering;
|
||||||
|
FragColor.a = 1.0;
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,18 @@
|
|||||||
layout (location = 0) in vec2 pos;
|
layout (location = 0) in vec2 pos;
|
||||||
layout (location = 1) in vec2 texCoord;
|
layout (location = 1) in vec2 texCoord;
|
||||||
|
|
||||||
out vec2 TexCoord;
|
uniform mat4 InverseViewProjection;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
|
||||||
|
out vec2 TexCoord;
|
||||||
|
out vec3 rayDir;
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
|
|
||||||
TexCoord = texCoord;
|
TexCoord = texCoord;
|
||||||
|
vec4 clipPos = vec4(pos, 1.0, 1.0);
|
||||||
|
vec4 worldPosH = InverseViewProjection * clipPos;
|
||||||
|
vec3 worldPos = worldPosH.xyz / worldPosH.w;
|
||||||
|
vec3 RayDir = worldPos - cameraPos;
|
||||||
|
rayDir = normalize(RayDir);
|
||||||
|
gl_Position = clipPos;
|
||||||
|
|
||||||
}
|
}
|
||||||
316
assets/shaders/water_f_shader.glsl
Normal file
316
assets/shaders/water_f_shader.glsl
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
layout (location = 0) out vec4 accum;
|
||||||
|
layout (location = 1) out float reveal;
|
||||||
|
|
||||||
|
in vec2 tc;
|
||||||
|
in vec3 normal;
|
||||||
|
in vec3 vert_pos;
|
||||||
|
in vec3 world_pos;
|
||||||
|
in float roughness;
|
||||||
|
flat in int tex_layer;
|
||||||
|
in float v_depth;
|
||||||
|
layout (binding = 0) uniform sampler2DArray samp;
|
||||||
|
uniform sampler2D sceneColorTex; // binding 1
|
||||||
|
uniform sampler2D sceneDepthTex; // binding 2
|
||||||
|
|
||||||
|
uniform mat4 proj_matrix;
|
||||||
|
uniform mat4 inv_proj_matrix;
|
||||||
|
uniform mat4 inv_view_matrix;
|
||||||
|
|
||||||
|
uniform float ambientStrength;
|
||||||
|
uniform vec3 sunlightColor;
|
||||||
|
uniform vec3 ambientColor;
|
||||||
|
uniform vec3 sunlightDir;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform bool shader_on;
|
||||||
|
uniform float specularStrength;
|
||||||
|
|
||||||
|
uniform vec3 skyTop;
|
||||||
|
uniform vec3 skyBottom;
|
||||||
|
uniform vec3 sunColor;
|
||||||
|
uniform float horizonSharpness;
|
||||||
|
uniform float cloudWhiteMix;
|
||||||
|
uniform float cloudThresholdLow;
|
||||||
|
uniform float cloudThresholdHigh;
|
||||||
|
uniform float time;
|
||||||
|
|
||||||
|
uniform vec3 sunDir; // world!
|
||||||
|
|
||||||
|
uniform bool underwater;
|
||||||
|
|
||||||
|
uniform float refractStrength;
|
||||||
|
|
||||||
|
uniform bool enablePerturb;
|
||||||
|
uniform bool enableDepthFade;
|
||||||
|
float weight(float z, float a) {
|
||||||
|
float intermediate = 0.03 / (1e-5 + pow(z / 200.0, 4.0));
|
||||||
|
|
||||||
|
return a * clamp(intermediate, 1e-2, 3e2);
|
||||||
|
}
|
||||||
|
|
||||||
|
float hash(vec2 p) {
|
||||||
|
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
|
||||||
|
}
|
||||||
|
|
||||||
|
float noise(vec2 p) {
|
||||||
|
vec2 i = floor(p);
|
||||||
|
vec2 f = fract(p);
|
||||||
|
f = f * f * (3.0 - 2.0 * f);
|
||||||
|
float a = hash(i);
|
||||||
|
float b = hash(i + vec2(1.0, 0.0));
|
||||||
|
float c = hash(i + vec2(0.0, 1.0));
|
||||||
|
float d = hash(i + vec2(1.0, 1.0));
|
||||||
|
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float fbm(vec2 p) {
|
||||||
|
float v = 0.0;
|
||||||
|
float amp = 0.5;
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
v += amp * noise(p);
|
||||||
|
p *= 2.0;
|
||||||
|
amp *= 0.5;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 computeSkyColor(vec3 dir) {
|
||||||
|
vec3 sund = normalize(sunDir);
|
||||||
|
|
||||||
|
float t =
|
||||||
|
clamp(
|
||||||
|
dir.y * 0.5 + 0.5,
|
||||||
|
0.0,
|
||||||
|
1.0
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
vec3 sky =
|
||||||
|
mix(
|
||||||
|
skyBottom,
|
||||||
|
skyTop,
|
||||||
|
pow(t, horizonSharpness)
|
||||||
|
);
|
||||||
|
|
||||||
|
// cloud
|
||||||
|
if (dir.y > 0.0) {
|
||||||
|
vec2 cloud_uv = dir.xz / (dir.y + 0.15) * 0.5 + vec2(time * 0.005, time * 0.002);
|
||||||
|
float cloud_density = fbm(cloud_uv * 2.0);
|
||||||
|
float safeLow = cloudThresholdLow;
|
||||||
|
float safeHigh = max(cloudThresholdHigh, cloudThresholdLow + 0.001);
|
||||||
|
cloud_density = smoothstep(safeLow,safeHigh, cloud_density);
|
||||||
|
|
||||||
|
|
||||||
|
float fade = smoothstep(0.0, 0.3, dir.y) * (1.0 - smoothstep(0.85, 1.0, dir.y));
|
||||||
|
cloud_density *= fade;
|
||||||
|
|
||||||
|
vec3 cloud_color = mix(skyBottom, vec3(1.0), cloudWhiteMix);
|
||||||
|
sky = mix(sky, cloud_color, cloud_density * 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sunAmount = max(dot(dir, sund), 0.0);
|
||||||
|
|
||||||
|
//float glow = pow(sunAmount, 8.0) * 0.15;
|
||||||
|
|
||||||
|
float glow = pow(sunAmount, 8.0) * 0.15 + pow(sunAmount, 32.0) * 0.3;
|
||||||
|
|
||||||
|
sky += glow * sunColor;
|
||||||
|
|
||||||
|
return sky;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconstruct eye-space coordinates from screen UV and depth buffer value
|
||||||
|
vec3 reconstructViewPos(vec2 uv, float depth) {
|
||||||
|
vec4 clip = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||||
|
vec4 view = inv_proj_matrix * clip;
|
||||||
|
return view.xyz / view.w;
|
||||||
|
}
|
||||||
|
// Screen-space ray marching, origin/dir are in eye space
|
||||||
|
bool traceSSR(vec3 origin, vec3 dir, out vec2 hitUV) {
|
||||||
|
const int COARSE_STEPS = 32;
|
||||||
|
const float COARSE_STEP = 0.6;
|
||||||
|
const int REFINE_STEPS = 8;
|
||||||
|
const float THICKNESS = 0.3;
|
||||||
|
|
||||||
|
vec3 pos = origin;
|
||||||
|
vec3 prevPos = origin;
|
||||||
|
bool foundCoarse = false;
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < COARSE_STEPS; ++i) {
|
||||||
|
prevPos = pos;
|
||||||
|
pos += dir * COARSE_STEP;
|
||||||
|
|
||||||
|
vec4 clip = proj_matrix * vec4(pos, 1.0);
|
||||||
|
if (clip.w <= 0.0) return false;
|
||||||
|
vec3 ndc = clip.xyz / clip.w;
|
||||||
|
if (abs(ndc.x) > 1.0 || abs(ndc.y) > 1.0) return false;
|
||||||
|
|
||||||
|
vec2 uv = ndc.xy * 0.5 + 0.5;
|
||||||
|
float sceneDepth = texture(sceneDepthTex, uv).r;
|
||||||
|
vec3 scenePos = reconstructViewPos(uv, sceneDepth);
|
||||||
|
|
||||||
|
if (pos.z - scenePos.z < 0.0) {
|
||||||
|
foundCoarse = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundCoarse) return false;
|
||||||
|
|
||||||
|
|
||||||
|
vec3 lo = prevPos;
|
||||||
|
vec3 hi = pos;
|
||||||
|
|
||||||
|
for (int i = 0; i < REFINE_STEPS; ++i) {
|
||||||
|
vec3 mid = (lo + hi) * 0.5;
|
||||||
|
|
||||||
|
vec4 clip = proj_matrix * vec4(mid, 1.0);
|
||||||
|
vec3 ndc = clip.xyz / clip.w;
|
||||||
|
vec2 uv = ndc.xy * 0.5 + 0.5;
|
||||||
|
float sceneDepth = texture(sceneDepthTex, uv).r;
|
||||||
|
vec3 scenePos = reconstructViewPos(uv, sceneDepth);
|
||||||
|
|
||||||
|
if (mid.z - scenePos.z < 0.0) {
|
||||||
|
hi = mid;
|
||||||
|
} else {
|
||||||
|
lo = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 finalClip = proj_matrix * vec4(hi, 1.0);
|
||||||
|
vec3 finalNdc = finalClip.xyz / finalClip.w;
|
||||||
|
vec2 finalUV = finalNdc.xy * 0.5 + 0.5;
|
||||||
|
|
||||||
|
float finalDepth = texture(sceneDepthTex, finalUV).r;
|
||||||
|
vec3 finalScenePos = reconstructViewPos(finalUV, finalDepth);
|
||||||
|
|
||||||
|
if (abs(hi.z - finalScenePos.z) > THICKNESS) return false;
|
||||||
|
|
||||||
|
hitUV = finalUV;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
vec4 objectColor = texture(samp, vec3(tc, tex_layer));
|
||||||
|
|
||||||
|
if (!shader_on) {
|
||||||
|
vec4 color = objectColor;
|
||||||
|
float alpha = color.a;
|
||||||
|
if (alpha < 1e-4) discard;
|
||||||
|
|
||||||
|
|
||||||
|
float w = weight(v_depth, alpha);
|
||||||
|
|
||||||
|
accum = vec4(color.rgb * alpha * w, alpha * w);
|
||||||
|
|
||||||
|
reveal = alpha;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Normal perturbation
|
||||||
|
vec3 N;
|
||||||
|
if (enablePerturb) {
|
||||||
|
const float wave_speed_scale = 40.0;
|
||||||
|
vec2 waveUV1 = world_pos.xz * 8.0 + vec2(time * 0.05 * wave_speed_scale, time * 0.03 * wave_speed_scale);
|
||||||
|
vec2 waveUV2 = world_pos.xz * 13.0 + vec2(-time * 0.04 * wave_speed_scale, time * 0.06 * wave_speed_scale);
|
||||||
|
|
||||||
|
float wave1 = noise(waveUV1);
|
||||||
|
float wave2 = noise(waveUV2);
|
||||||
|
|
||||||
|
vec2 normalPerturb = vec2(wave1 - 0.5, wave2 - 0.5) * 0.1;
|
||||||
|
N = normalize(normal + vec3(normalPerturb.x, 0.0, normalPerturb.y));
|
||||||
|
} else {
|
||||||
|
N = normalize(normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 V = normalize(-vert_pos);
|
||||||
|
|
||||||
|
vec3 reflectColor;
|
||||||
|
vec3 refractColor;
|
||||||
|
float fresnel;
|
||||||
|
|
||||||
|
vec2 screenUV = gl_FragCoord.xy / vec2(textureSize(sceneDepthTex, 0));
|
||||||
|
|
||||||
|
// water depth
|
||||||
|
float sceneDepthRaw = texture(sceneDepthTex, screenUV).r;
|
||||||
|
vec3 sceneViewPos = reconstructViewPos(screenUV, sceneDepthRaw);
|
||||||
|
float waterDepth = vert_pos.z - sceneViewPos.z;
|
||||||
|
waterDepth = max(waterDepth, 0.0);
|
||||||
|
|
||||||
|
const float DEPTH_FADE_DISTANCE = 10;
|
||||||
|
float depthFactor = clamp(waterDepth / DEPTH_FADE_DISTANCE, 0.0, 1.0);
|
||||||
|
|
||||||
|
if (underwater) {
|
||||||
|
reflectColor = vec3(0.0);
|
||||||
|
refractColor = objectColor.rgb;
|
||||||
|
fresnel = 0.0;
|
||||||
|
} else {
|
||||||
|
vec3 R = reflect(-V, N);
|
||||||
|
vec3 origin = vert_pos + N * 0.05;
|
||||||
|
vec2 hitUV;
|
||||||
|
|
||||||
|
if (traceSSR(origin, R, hitUV)) {
|
||||||
|
reflectColor = texture(sceneColorTex, hitUV).rgb;
|
||||||
|
} else {
|
||||||
|
vec3 worldR = mat3(inv_view_matrix) * R;
|
||||||
|
reflectColor = computeSkyColor(worldR);
|
||||||
|
}
|
||||||
|
|
||||||
|
float effectiveRefractStrength = refractStrength * (1.0 - depthFactor * 0.5);
|
||||||
|
vec2 refractOffset = N.xz * effectiveRefractStrength;
|
||||||
|
vec2 refractUV = clamp(screenUV + refractOffset, vec2(0.001), vec2(0.999));
|
||||||
|
|
||||||
|
refractColor = texture(sceneColorTex, refractUV).rgb;
|
||||||
|
|
||||||
|
fresnel = pow(1.0 - max(dot(N, V), 0.0), 5.0);
|
||||||
|
fresnel = mix(0.02, 1.0, fresnel);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 lightDir = normalize(-sunlightDir);
|
||||||
|
vec3 H = normalize(lightDir + V);
|
||||||
|
vec3 ambient = ambientStrength * ambientColor;
|
||||||
|
float diff = max(dot(N, lightDir), 0.0);
|
||||||
|
vec3 diffuse = diff * sunlightColor;
|
||||||
|
|
||||||
|
float r = clamp(roughness, 0.0, 1.0);
|
||||||
|
float shininess = mix(512.0, 4.0, r);
|
||||||
|
float ks = mix(0.8, 0.02, r);
|
||||||
|
|
||||||
|
float spec = 0.0;
|
||||||
|
if (diff > 0.0) {
|
||||||
|
spec = ks * pow(max(dot(N, H), 0.0), shininess);
|
||||||
|
}
|
||||||
|
vec3 specular = spec * sunlightColor * specularStrength;
|
||||||
|
|
||||||
|
vec3 tintedRefract;
|
||||||
|
|
||||||
|
if (enableDepthFade) {
|
||||||
|
vec3 shallowColor = vec3(0.4, 0.75, 0.7);
|
||||||
|
vec3 deepColor = vec3(0.0, 0.015, 0.045);
|
||||||
|
|
||||||
|
vec3 waterTint = mix(shallowColor, deepColor, depthFactor);
|
||||||
|
|
||||||
|
tintedRefract = mix(refractColor, refractColor * waterTint, depthFactor);
|
||||||
|
tintedRefract = mix(tintedRefract, objectColor.rgb, 0.4); // Forcefully blend 40% texture color, independent of depth
|
||||||
|
} else {
|
||||||
|
tintedRefract = mix(refractColor, objectColor.rgb, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
//vec3 baseWaterColor = (ambient + diffuse) * objectColor.rgb + specular;
|
||||||
|
vec3 baseWaterColor = (ambient + diffuse) * tintedRefract + specular;
|
||||||
|
|
||||||
|
vec3 finalColor = mix(baseWaterColor, reflectColor, fresnel);
|
||||||
|
|
||||||
|
float alpha = objectColor.a;
|
||||||
|
if (alpha < 1e-4) discard;
|
||||||
|
|
||||||
|
|
||||||
|
float w = weight(v_depth, alpha);
|
||||||
|
|
||||||
|
accum = vec4(finalColor * alpha * w, alpha * w);
|
||||||
|
|
||||||
|
reveal = alpha;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
32
assets/shaders/water_v_shader.glsl
Normal file
32
assets/shaders/water_v_shader.glsl
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 pos;
|
||||||
|
layout (location = 1) in vec2 texCoord;
|
||||||
|
layout (location = 2) in float layer;
|
||||||
|
layout (location = 3) in vec3 aNormal;
|
||||||
|
layout (location = 4) in float Roughness;
|
||||||
|
|
||||||
|
out vec2 tc;
|
||||||
|
out vec3 normal;
|
||||||
|
out vec3 vert_pos;
|
||||||
|
out vec3 world_pos;
|
||||||
|
flat out int tex_layer;
|
||||||
|
out float roughness;
|
||||||
|
out float v_depth;
|
||||||
|
|
||||||
|
uniform mat4 mv_matrix;
|
||||||
|
uniform mat4 proj_matrix;
|
||||||
|
uniform mat4 norm_matrix;
|
||||||
|
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 view_pos = mv_matrix * vec4(pos, 1.0);
|
||||||
|
world_pos = pos;
|
||||||
|
vert_pos = view_pos.xyz;
|
||||||
|
normal = mat3(norm_matrix) * aNormal;
|
||||||
|
roughness = Roughness;
|
||||||
|
tc = texCoord;
|
||||||
|
tex_layer = int(layer);
|
||||||
|
v_depth = -view_pos.z;
|
||||||
|
gl_Position = proj_matrix * view_pos;
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ private:
|
|||||||
static constexpr int SIZE_X = CHUNK_SIZE;
|
static constexpr int SIZE_X = CHUNK_SIZE;
|
||||||
static constexpr int SIZE_Y = WORLD_SIZE_Y;
|
static constexpr int SIZE_Y = WORLD_SIZE_Y;
|
||||||
static constexpr int SIZE_Z = CHUNK_SIZE;
|
static constexpr int SIZE_Z = CHUNK_SIZE;
|
||||||
static constexpr int VERTEX_DATA_SUM = 4;
|
static constexpr int VERTEX_DATA_SUM = 5;
|
||||||
std::atomic<bool> m_dirty{false};
|
std::atomic<bool> m_dirty{false};
|
||||||
std::atomic<bool> m_need_upload{true};
|
std::atomic<bool> m_need_upload{true};
|
||||||
std::atomic<bool> m_is_on_gen_vertex_data{false};
|
std::atomic<bool> m_is_on_gen_vertex_data{false};
|
||||||
@@ -39,6 +39,7 @@ private:
|
|||||||
1 - cross_plane
|
1 - cross_plane
|
||||||
2 - normal_discard
|
2 - normal_discard
|
||||||
3 - transparent and blend
|
3 - transparent and blend
|
||||||
|
4 - water
|
||||||
*/
|
*/
|
||||||
std::vector<VertexData> m_vertex_data;
|
std::vector<VertexData> m_vertex_data;
|
||||||
float frequency = 0.01f;
|
float frequency = 0.01f;
|
||||||
@@ -113,6 +114,9 @@ public:
|
|||||||
GLuint get_normal_blend_vao() const;
|
GLuint get_normal_blend_vao() const;
|
||||||
size_t get_normal_blend_vertices_sum() const;
|
size_t get_normal_blend_vertices_sum() const;
|
||||||
|
|
||||||
|
GLuint get_water_vao() const;
|
||||||
|
size_t get_water_vertices_sum() const;
|
||||||
|
|
||||||
bool is_dirty() const;
|
bool is_dirty() const;
|
||||||
void mark_dirty();
|
void mark_dirty();
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ struct ChunkRenderSnapshot {
|
|||||||
size_t normal_discard_vertices_count;
|
size_t normal_discard_vertices_count;
|
||||||
GLuint normal_blend_vao;
|
GLuint normal_blend_vao;
|
||||||
size_t normal_blend_vertices_count;
|
size_t normal_blend_vertices_count;
|
||||||
|
GLuint water_vao;
|
||||||
|
size_t water_vertices_count;
|
||||||
glm::vec3 center;
|
glm::vec3 center;
|
||||||
glm::vec3 half_extents;
|
glm::vec3 half_extents;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ constexpr float CROSS_NORMALS[2][6][3] = {
|
|||||||
{0.0f, 1.0f, 0.0f}}};
|
{0.0f, 1.0f, 0.0f}}};
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
// [-1, 1]
|
||||||
constexpr float QUAD_VERTICES[] = {
|
constexpr float QUAD_VERTICES[] = {
|
||||||
// postion // texcoorlds
|
// postion // texcoorlds
|
||||||
-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f,
|
-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f,
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ public:
|
|||||||
|
|
||||||
bool& discard_transparent();
|
bool& discard_transparent();
|
||||||
bool& shader_on();
|
bool& shader_on();
|
||||||
|
bool& water_perturb();
|
||||||
|
bool& water_depth_fade();
|
||||||
int& shadow_mode();
|
int& shadow_mode();
|
||||||
int& light_cull_face();
|
int& light_cull_face();
|
||||||
int& light_size_uv();
|
int& light_size_uv();
|
||||||
@@ -42,10 +44,13 @@ public:
|
|||||||
float& cloud_speed();
|
float& cloud_speed();
|
||||||
float& cloud_threshold_low();
|
float& cloud_threshold_low();
|
||||||
float& cloud_threshold_high();
|
float& cloud_threshold_high();
|
||||||
|
float& refract_strength();
|
||||||
|
float& underwater_fog_density();
|
||||||
|
float& water_density();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ParallelLight {
|
struct ParallelLight {
|
||||||
glm::vec3 sundir;
|
glm::vec3 sundir; // direction from sun to vertex
|
||||||
glm::vec3 lightdir;
|
glm::vec3 lightdir;
|
||||||
float sun_height = 0.0f;
|
float sun_height = 0.0f;
|
||||||
float day_light = 0.0f;
|
float day_light = 0.0f;
|
||||||
@@ -53,6 +58,15 @@ private:
|
|||||||
glm::vec3 sun_color;
|
glm::vec3 sun_color;
|
||||||
glm::vec3 directional_light_color;
|
glm::vec3 directional_light_color;
|
||||||
glm::vec3 finnal_ambient_color;
|
glm::vec3 finnal_ambient_color;
|
||||||
|
glm::mat4 light_space_matrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SkyUniform {
|
||||||
|
glm::vec3 sky_top;
|
||||||
|
glm::vec3 sky_bottom;
|
||||||
|
glm::vec3 sun_dir_view;
|
||||||
|
float horizon_sharpness;
|
||||||
|
float cloud_white_mix;
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr glm::vec3 SUN_COLOR{1.00f, 0.95f, 0.80f};
|
static constexpr glm::vec3 SUN_COLOR{1.00f, 0.95f, 0.80f};
|
||||||
@@ -79,6 +93,8 @@ private:
|
|||||||
|
|
||||||
bool m_discard_tranparent = true;
|
bool m_discard_tranparent = true;
|
||||||
bool m_shader_on = true;
|
bool m_shader_on = true;
|
||||||
|
bool m_water_perturb = true;
|
||||||
|
bool m_water_depth_fade = true;
|
||||||
int m_shadow_mode = 0;
|
int m_shadow_mode = 0;
|
||||||
int m_light_cull_face = 0;
|
int m_light_cull_face = 0;
|
||||||
float m_aspect = 0.0f;
|
float m_aspect = 0.0f;
|
||||||
@@ -94,9 +110,6 @@ private:
|
|||||||
|
|
||||||
glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat, m_norm_mat;
|
glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat, m_norm_mat;
|
||||||
|
|
||||||
GLuint m_mv_loc = 0;
|
|
||||||
GLuint m_proj_loc = 0;
|
|
||||||
|
|
||||||
GLuint m_sky_vbo = 0;
|
GLuint m_sky_vbo = 0;
|
||||||
GLuint m_text_vbo = 0;
|
GLuint m_text_vbo = 0;
|
||||||
GLuint m_outline_indices_vbo = 0;
|
GLuint m_outline_indices_vbo = 0;
|
||||||
@@ -105,12 +118,12 @@ private:
|
|||||||
|
|
||||||
GLuint m_fbo = 0;
|
GLuint m_fbo = 0;
|
||||||
GLuint m_screen_texture = 0;
|
GLuint m_screen_texture = 0;
|
||||||
GLuint m_depth_render_buffer = 0;
|
GLuint m_screen_depth_texture = 0;
|
||||||
|
|
||||||
GLuint m_oit_fbo = 0;
|
GLuint m_oit_fbo = 0;
|
||||||
GLuint m_accum_texture = 0;
|
GLuint m_accum_texture = 0;
|
||||||
GLuint m_reveal_texture = 0;
|
GLuint m_reveal_texture = 0;
|
||||||
GLuint m_oit_depth_render_buffer = 0;
|
GLuint m_oit_depth_texture = 0;
|
||||||
|
|
||||||
GLuint m_depth_map_fbo = 0;
|
GLuint m_depth_map_fbo = 0;
|
||||||
GLuint m_depth_map_texture = 0;
|
GLuint m_depth_map_texture = 0;
|
||||||
@@ -140,7 +153,14 @@ private:
|
|||||||
float m_cloud_threshold_low = 0.5f;
|
float m_cloud_threshold_low = 0.5f;
|
||||||
float m_cloud_threshold_high = 0.75f;
|
float m_cloud_threshold_high = 0.75f;
|
||||||
|
|
||||||
|
float m_refract_strength = 0.03f;
|
||||||
|
|
||||||
|
float m_underwater_fog_density = 0.08f;
|
||||||
|
|
||||||
|
float m_water_density = 0.12f;
|
||||||
|
|
||||||
ParallelLight m_parallel_light;
|
ParallelLight m_parallel_light;
|
||||||
|
SkyUniform m_sky_uniform;
|
||||||
/*
|
/*
|
||||||
0 - quad vao
|
0 - quad vao
|
||||||
1 - sky vao
|
1 - sky vao
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "glm/ext/vector_float3.hpp"
|
||||||
|
#include "glm/gtc/type_ptr.hpp"
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -21,6 +24,26 @@ public:
|
|||||||
GLuint loc(const std::string& loc) const;
|
GLuint loc(const std::string& loc) const;
|
||||||
const std::string& name() const;
|
const std::string& name() const;
|
||||||
void use() const;
|
void use() const;
|
||||||
|
template <typename> struct always_false : std::false_type {}; // NOLINT
|
||||||
|
template <typename T>
|
||||||
|
void set_loc(const std::string& location, T&& value) const {
|
||||||
|
using std::is_same_v;
|
||||||
|
using dT = std::decay_t<T>;
|
||||||
|
if constexpr (is_same_v<dT, int> || is_same_v<dT, bool>) {
|
||||||
|
glUniform1i(loc(location), value);
|
||||||
|
} else if constexpr (is_same_v<dT, float>) {
|
||||||
|
glUniform1f(loc(location), value);
|
||||||
|
} else if constexpr (is_same_v<dT, double>) {
|
||||||
|
glUniform1f(loc(location), static_cast<float>(value));
|
||||||
|
} else if constexpr (is_same_v<dT, glm::vec3>) {
|
||||||
|
glUniform3fv(loc(location), 1, glm::value_ptr(value));
|
||||||
|
} else if constexpr (is_same_v<dT, glm::mat4>) {
|
||||||
|
glUniformMatrix4fv(loc(location), 1, GL_FALSE,
|
||||||
|
glm::value_ptr(value));
|
||||||
|
} else {
|
||||||
|
static_assert(always_false<dT>::value, "Unknown Type");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint m_program = 0;
|
GLuint m_program = 0;
|
||||||
|
|||||||
@@ -657,6 +657,16 @@ void DevPanel::show_shader_tab_item() {
|
|||||||
ImGui::SliderFloat("Cloud Threshold High",
|
ImGui::SliderFloat("Cloud Threshold High",
|
||||||
&m_app.renderer().cloud_threshold_high(), 0.0f,
|
&m_app.renderer().cloud_threshold_high(), 0.0f,
|
||||||
1.0f);
|
1.0f);
|
||||||
|
ImGui::SliderFloat("Water Refract Strength",
|
||||||
|
&m_app.renderer().refract_strength(), 0.0f, 1.0f);
|
||||||
|
ImGui::Checkbox("Water Perturb", &m_app.renderer().water_perturb());
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Checkbox("WaterDepthFade", &m_app.renderer().water_depth_fade());
|
||||||
|
ImGui::SliderFloat("Underwater Fog Density",
|
||||||
|
&m_app.renderer().underwater_fog_density(), 0.0f,
|
||||||
|
1.0f);
|
||||||
|
ImGui::SliderFloat("Water Density", &m_app.renderer().water_density(),
|
||||||
|
0.0f, 1.0f);
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,6 +146,11 @@ size_t Chunk::get_normal_blend_vertices_sum() const {
|
|||||||
return m_vertex_data[3].m_sum.load();
|
return m_vertex_data[3].m_sum.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint Chunk::get_water_vao() const { return m_vertex_data[4].m_vao; }
|
||||||
|
size_t Chunk::get_water_vertices_sum() const {
|
||||||
|
return m_vertex_data[4].m_sum.load();
|
||||||
|
}
|
||||||
|
|
||||||
void Chunk::gen_phase_one() {
|
void Chunk::gen_phase_one() {
|
||||||
m_generator = std::make_unique<ChunkGenerator>(*this);
|
m_generator = std::make_unique<ChunkGenerator>(*this);
|
||||||
if (!m_generator) {
|
if (!m_generator) {
|
||||||
@@ -392,7 +397,14 @@ void Chunk::gen_vertices(const OptionalBlockVectorArray& neighbor_block) {
|
|||||||
if (BlockManager::is_discard(cur_id)) {
|
if (BlockManager::is_discard(cur_id)) {
|
||||||
m_vertex_data[2].m_vertices.emplace_back(vex);
|
m_vertex_data[2].m_vertices.emplace_back(vex);
|
||||||
} else if (BlockManager::is_blend(cur_id)) {
|
} else if (BlockManager::is_blend(cur_id)) {
|
||||||
m_vertex_data[3].m_vertices.emplace_back(vex);
|
if (cur_id == 7) {
|
||||||
|
m_vertex_data[4].m_vertices.emplace_back(
|
||||||
|
vex);
|
||||||
|
} else {
|
||||||
|
m_vertex_data[3].m_vertices.emplace_back(
|
||||||
|
vex);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Logger::warn("Id {} is transparent but not "
|
Logger::warn("Id {} is transparent but not "
|
||||||
"discard or blend",
|
"discard or blend",
|
||||||
|
|||||||
@@ -971,6 +971,7 @@ void World::update(float delta_time) {
|
|||||||
chunk.get_normal_discard_vertices_sum(),
|
chunk.get_normal_discard_vertices_sum(),
|
||||||
chunk.get_normal_blend_vao(),
|
chunk.get_normal_blend_vao(),
|
||||||
chunk.get_normal_blend_vertices_sum(),
|
chunk.get_normal_blend_vertices_sum(),
|
||||||
|
chunk.get_water_vao(), chunk.get_water_vertices_sum(),
|
||||||
glm::vec3(static_cast<float>(pos.x * CHUNK_SIZE) +
|
glm::vec3(static_cast<float>(pos.x * CHUNK_SIZE) +
|
||||||
static_cast<float>(CHUNK_SIZE / 2),
|
static_cast<float>(CHUNK_SIZE / 2),
|
||||||
static_cast<float>(WORLD_SIZE_Y / 2),
|
static_cast<float>(WORLD_SIZE_Y / 2),
|
||||||
|
|||||||
273
src/renderer.cpp
273
src/renderer.cpp
@@ -37,12 +37,12 @@ Renderer::~Renderer() {
|
|||||||
glDeleteVertexArrays(NUM_VAO, m_vao.data());
|
glDeleteVertexArrays(NUM_VAO, m_vao.data());
|
||||||
glDeleteFramebuffers(1, &m_fbo);
|
glDeleteFramebuffers(1, &m_fbo);
|
||||||
glDeleteTextures(1, &m_screen_texture);
|
glDeleteTextures(1, &m_screen_texture);
|
||||||
glDeleteRenderbuffers(1, &m_depth_render_buffer);
|
glDeleteTextures(1, &m_screen_depth_texture);
|
||||||
|
|
||||||
glDeleteFramebuffers(1, &m_oit_fbo);
|
glDeleteFramebuffers(1, &m_oit_fbo);
|
||||||
glDeleteTextures(1, &m_accum_texture);
|
glDeleteTextures(1, &m_accum_texture);
|
||||||
glDeleteTextures(1, &m_reveal_texture);
|
glDeleteTextures(1, &m_reveal_texture);
|
||||||
glDeleteRenderbuffers(1, &m_oit_depth_render_buffer);
|
glDeleteTextures(1, &m_oit_depth_texture);
|
||||||
|
|
||||||
glDeleteFramebuffers(1, &m_depth_map_fbo);
|
glDeleteFramebuffers(1, &m_depth_map_fbo);
|
||||||
glDeleteTextures(1, &m_depth_map_texture);
|
glDeleteTextures(1, &m_depth_map_texture);
|
||||||
@@ -84,6 +84,9 @@ void Renderer::init() {
|
|||||||
"shaders/depth_fragment_shader.glsl"};
|
"shaders/depth_fragment_shader.glsl"};
|
||||||
Shader billboard{"billboard", "shaders/billboard_v_shader.glsl",
|
Shader billboard{"billboard", "shaders/billboard_v_shader.glsl",
|
||||||
"shaders/billboard_f_shader.glsl"};
|
"shaders/billboard_f_shader.glsl"};
|
||||||
|
Shader water_shader{"water", "shaders/water_v_shader.glsl",
|
||||||
|
"shaders/water_f_shader.glsl"};
|
||||||
|
|
||||||
m_shaders.insert({world_shader.hash(), std::move(world_shader)});
|
m_shaders.insert({world_shader.hash(), std::move(world_shader)});
|
||||||
m_shaders.insert({outline_shader.hash(), std::move(outline_shader)});
|
m_shaders.insert({outline_shader.hash(), std::move(outline_shader)});
|
||||||
m_shaders.insert({sky_shdaer.hash(), std::move(sky_shdaer)});
|
m_shaders.insert({sky_shdaer.hash(), std::move(sky_shdaer)});
|
||||||
@@ -96,6 +99,7 @@ void Renderer::init() {
|
|||||||
{composite_block_shader.hash(), std::move(composite_block_shader)});
|
{composite_block_shader.hash(), std::move(composite_block_shader)});
|
||||||
m_shaders.insert({depth_shader.hash(), std::move(depth_shader)});
|
m_shaders.insert({depth_shader.hash(), std::move(depth_shader)});
|
||||||
m_shaders.insert({billboard.hash(), std::move(billboard)});
|
m_shaders.insert({billboard.hash(), std::move(billboard)});
|
||||||
|
m_shaders.insert({water_shader.hash(), std::move(water_shader)});
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
||||||
@@ -260,17 +264,14 @@ void Renderer::render_outline() {
|
|||||||
|
|
||||||
if (block_pos != std::nullopt) {
|
if (block_pos != std::nullopt) {
|
||||||
|
|
||||||
m_mv_loc = shader.loc("mv_matrix");
|
|
||||||
m_proj_loc = shader.loc("proj_matrix");
|
|
||||||
|
|
||||||
m_m_mat =
|
m_m_mat =
|
||||||
glm::translate(glm::mat4(1.0f), glm::vec3(block_pos.value().pos));
|
glm::translate(glm::mat4(1.0f), glm::vec3(block_pos.value().pos));
|
||||||
|
|
||||||
m_v_mat = m_camera.get_camera_lookat();
|
m_v_mat = m_camera.get_camera_lookat();
|
||||||
m_mv_mat = m_v_mat * m_m_mat;
|
m_mv_mat = m_v_mat * m_m_mat;
|
||||||
|
|
||||||
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
shader.set_loc("mv_matrix", m_mv_mat);
|
||||||
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
shader.set_loc("proj_matrix", m_p_mat);
|
||||||
|
|
||||||
glBindVertexArray(m_vao[2]);
|
glBindVertexArray(m_vao[2]);
|
||||||
|
|
||||||
@@ -306,19 +307,20 @@ void Renderer::render_sky() {
|
|||||||
glm::vec3 day_bottom =
|
glm::vec3 day_bottom =
|
||||||
mix(sunset_horizon, horizon, m_parallel_light.day_light);
|
mix(sunset_horizon, horizon, m_parallel_light.day_light);
|
||||||
|
|
||||||
glm::vec3 sky_top = mix(night_zenith, day_top, m_parallel_light.day_factor);
|
m_sky_uniform.sky_top =
|
||||||
glm::vec3 sky_bottom =
|
mix(night_zenith, day_top, m_parallel_light.day_factor);
|
||||||
|
m_sky_uniform.sky_bottom =
|
||||||
mix(night_horizon, day_bottom, m_parallel_light.day_factor);
|
mix(night_horizon, day_bottom, m_parallel_light.day_factor);
|
||||||
|
|
||||||
float day_sharpness =
|
float day_sharpness =
|
||||||
glm::mix(SUNSET_SHARPNESS, NOON_SHARPNESS, m_parallel_light.day_light);
|
glm::mix(SUNSET_SHARPNESS, NOON_SHARPNESS, m_parallel_light.day_light);
|
||||||
|
|
||||||
float horizon_sharpness =
|
m_sky_uniform.horizon_sharpness =
|
||||||
glm::mix(NIGHT_SHARPNESS, day_sharpness, m_parallel_light.day_factor);
|
glm::mix(NIGHT_SHARPNESS, day_sharpness, m_parallel_light.day_factor);
|
||||||
|
|
||||||
float day_cloud_mix =
|
float day_cloud_mix =
|
||||||
glm::mix(SUNSET_CLOUD_MIX, NOON_CLOUD_MIX, m_parallel_light.day_light);
|
glm::mix(SUNSET_CLOUD_MIX, NOON_CLOUD_MIX, m_parallel_light.day_light);
|
||||||
float cloud_white_mix =
|
m_sky_uniform.cloud_white_mix =
|
||||||
glm::mix(NIGHT_CLOUD_MIX, day_cloud_mix, m_parallel_light.day_factor);
|
glm::mix(NIGHT_CLOUD_MIX, day_cloud_mix, m_parallel_light.day_factor);
|
||||||
|
|
||||||
m_cloud_time += m_delta_time * m_cloud_speed;
|
m_cloud_time += m_delta_time * m_cloud_speed;
|
||||||
@@ -326,28 +328,24 @@ void Renderer::render_sky() {
|
|||||||
const auto& sky_shader = get_shader("sky");
|
const auto& sky_shader = get_shader("sky");
|
||||||
|
|
||||||
sky_shader.use();
|
sky_shader.use();
|
||||||
m_mv_loc = sky_shader.loc("mv_matrix");
|
|
||||||
m_proj_loc = sky_shader.loc("proj_matrix");
|
|
||||||
|
|
||||||
m_m_mat = glm::translate(glm::mat4(1.0f), m_camera.get_camera_pos() -
|
m_m_mat = glm::translate(glm::mat4(1.0f), m_camera.get_camera_pos() -
|
||||||
glm::vec3(0.5f, 0.5f, 0.5f));
|
glm::vec3(0.5f, 0.5f, 0.5f));
|
||||||
m_v_mat = m_camera.get_camera_lookat();
|
m_v_mat = m_camera.get_camera_lookat();
|
||||||
m_mv_mat = m_v_mat * m_m_mat;
|
m_mv_mat = m_v_mat * m_m_mat;
|
||||||
|
|
||||||
glm::vec3 sun_dir_view = (-m_parallel_light.sundir);
|
m_sky_uniform.sun_dir_view = (-m_parallel_light.sundir);
|
||||||
|
sky_shader.set_loc("mv_matrix", m_mv_mat);
|
||||||
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
sky_shader.set_loc("proj_matrix", m_p_mat);
|
||||||
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
sky_shader.set_loc("skyTop", m_sky_uniform.sky_top);
|
||||||
glUniform3fv(sky_shader.loc("skyTop"), 1, glm::value_ptr(sky_top));
|
sky_shader.set_loc("skyBottom", m_sky_uniform.sky_bottom);
|
||||||
glUniform3fv(sky_shader.loc("skyBottom"), 1, glm::value_ptr(sky_bottom));
|
sky_shader.set_loc("sunDir", m_sky_uniform.sun_dir_view);
|
||||||
glUniform3fv(sky_shader.loc("sunDir"), 1, glm::value_ptr(sun_dir_view));
|
sky_shader.set_loc("sunColor", m_parallel_light.directional_light_color);
|
||||||
glUniform3fv(sky_shader.loc("sunColor"), 1,
|
sky_shader.set_loc("horizonSharpness", m_sky_uniform.horizon_sharpness);
|
||||||
glm::value_ptr(m_parallel_light.directional_light_color));
|
sky_shader.set_loc("time", m_cloud_time);
|
||||||
glUniform1f(sky_shader.loc("horizonSharpness"), horizon_sharpness);
|
sky_shader.set_loc("cloudWhiteMix", m_sky_uniform.cloud_white_mix);
|
||||||
glUniform1f(sky_shader.loc("time"), m_cloud_time);
|
sky_shader.set_loc("cloudThresholdLow", m_cloud_threshold_low);
|
||||||
glUniform1f(sky_shader.loc("cloudWhiteMix"), cloud_white_mix);
|
sky_shader.set_loc("cloudThresholdHigh", m_cloud_threshold_high);
|
||||||
glUniform1f(sky_shader.loc("cloudThresholdLow"), m_cloud_threshold_low);
|
|
||||||
glUniform1f(sky_shader.loc("cloudThresholdHigh"), m_cloud_threshold_high);
|
|
||||||
glBindVertexArray(m_vao[1]);
|
glBindVertexArray(m_vao[1]);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
@@ -369,12 +367,9 @@ void Renderer::render_sky() {
|
|||||||
glm::scale(glm::mat4(1.0f), glm::vec3(SUN_SIZE)) *
|
glm::scale(glm::mat4(1.0f), glm::vec3(SUN_SIZE)) *
|
||||||
glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, -0.5f, 0.0f));
|
glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, -0.5f, 0.0f));
|
||||||
|
|
||||||
m_mv_loc = billboard.loc("mv_matrix");
|
billboard.set_loc("mv_matrix", m_mv_mat);
|
||||||
m_proj_loc = billboard.loc("proj_matrix");
|
billboard.set_loc("proj_matrix", m_p_mat);
|
||||||
|
billboard.set_loc("color", SUN_COLOR);
|
||||||
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
|
||||||
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
|
||||||
glUniform3fv(billboard.loc("color"), 1, glm::value_ptr(SUN_COLOR));
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
@@ -384,9 +379,9 @@ void Renderer::render_sky() {
|
|||||||
m_mv_mat = glm::translate(glm::mat4(1.0f), moon_view_pos) *
|
m_mv_mat = glm::translate(glm::mat4(1.0f), moon_view_pos) *
|
||||||
glm::scale(glm::mat4(1.0f), glm::vec3(MOON_SIZE)) *
|
glm::scale(glm::mat4(1.0f), glm::vec3(MOON_SIZE)) *
|
||||||
glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, -0.5f, 0.0f));
|
glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, -0.5f, 0.0f));
|
||||||
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
billboard.set_loc("mv_matrix", m_mv_mat);
|
||||||
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
billboard.set_loc("proj_matrix", m_p_mat);
|
||||||
glUniform3fv(billboard.loc("color"), 1, glm::value_ptr(MOON_COLOR));
|
billboard.set_loc("color", MOON_COLOR);
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
@@ -406,9 +401,7 @@ void Renderer::render_text() {
|
|||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
m_proj_loc = shader.loc("projection");
|
shader.set_loc("projection", m_ui_proj);
|
||||||
|
|
||||||
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_ui_proj));
|
|
||||||
|
|
||||||
auto& texts = DebugCollector::get().all_texts();
|
auto& texts = DebugCollector::get().all_texts();
|
||||||
for (auto& t : texts) {
|
for (auto& t : texts) {
|
||||||
@@ -425,11 +418,9 @@ void Renderer::render_ui() {
|
|||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
m_mv_loc = shader.loc("m_matrix");
|
|
||||||
m_proj_loc = shader.loc("proj_matrix");
|
|
||||||
|
|
||||||
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_ui_m_matrix));
|
shader.set_loc("mv_matrix", m_ui_m_matrix);
|
||||||
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_ui_proj));
|
shader.set_loc("proj_matrix", m_ui_proj);
|
||||||
|
|
||||||
glBindVertexArray(m_vao[3]);
|
glBindVertexArray(m_vao[3]);
|
||||||
|
|
||||||
@@ -448,15 +439,23 @@ void Renderer::render_underwater() {
|
|||||||
|
|
||||||
glBindVertexArray(m_vao[0]);
|
glBindVertexArray(m_vao[0]);
|
||||||
|
|
||||||
glUniform1i(shader.loc("u_sceneTexture"), 0);
|
shader.set_loc("u_sceneTexture", 0);
|
||||||
glUniform1f(shader.loc("u_time"), glfwGetTime());
|
shader.set_loc("u_time", static_cast<float>(glfwGetTime()));
|
||||||
glUniform1i(shader.loc("u_underwater"), m_camera.is_under_water());
|
shader.set_loc("u_underwater", m_camera.is_under_water());
|
||||||
glUniform3f(shader.loc("u_waterColor"), 0.1f, 0.25f, 0.35f);
|
shader.set_loc("u_waterColor", glm::vec3(0.1f, 0.25f, 0.35f));
|
||||||
glUniform1f(shader.loc("u_fogDensity"), 0.08f);
|
shader.set_loc("u_fogDensity", m_underwater_fog_density);
|
||||||
|
shader.set_loc("cameraPos", m_camera.get_camera_pos());
|
||||||
|
shader.set_loc("sunDir", -m_parallel_light.sundir);
|
||||||
|
shader.set_loc("waterDensity", m_water_density);
|
||||||
|
shader.set_loc("InverseViewProjection", glm::inverse(m_p_mat * m_v_mat));
|
||||||
|
shader.set_loc("sunColor", m_parallel_light.sun_color);
|
||||||
|
shader.set_loc("u_lightSpaceMatrix", m_parallel_light.light_space_matrix);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_screen_texture);
|
glBindTexture(GL_TEXTURE_2D, m_screen_texture);
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_screen_depth_texture);
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_depth_map_texture);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
@@ -492,7 +491,7 @@ void Renderer::updata_framebuffer(int width, int height) {
|
|||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||||
|
|
||||||
glDeleteTextures(1, &m_screen_texture);
|
glDeleteTextures(1, &m_screen_texture);
|
||||||
glDeleteRenderbuffers(1, &m_depth_render_buffer);
|
glDeleteTextures(1, &m_screen_depth_texture);
|
||||||
|
|
||||||
glGenTextures(1, &m_screen_texture);
|
glGenTextures(1, &m_screen_texture);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_screen_texture);
|
glBindTexture(GL_TEXTURE_2D, m_screen_texture);
|
||||||
@@ -504,11 +503,14 @@ void Renderer::updata_framebuffer(int width, int height) {
|
|||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||||
m_screen_texture, 0);
|
m_screen_texture, 0);
|
||||||
|
|
||||||
glGenRenderbuffers(1, &m_depth_render_buffer);
|
glGenTextures(1, &m_screen_depth_texture);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, m_depth_render_buffer);
|
glBindTexture(GL_TEXTURE_2D, m_screen_depth_texture);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, width, height, 0,
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||||
GL_RENDERBUFFER, m_depth_render_buffer);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
|
||||||
|
m_screen_depth_texture, 0);
|
||||||
|
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
Logger::error("FBO incomplete after resize!");
|
Logger::error("FBO incomplete after resize!");
|
||||||
@@ -520,7 +522,7 @@ void Renderer::updata_framebuffer(int width, int height) {
|
|||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_oit_fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, m_oit_fbo);
|
||||||
glDeleteTextures(1, &m_accum_texture);
|
glDeleteTextures(1, &m_accum_texture);
|
||||||
glDeleteTextures(1, &m_reveal_texture);
|
glDeleteTextures(1, &m_reveal_texture);
|
||||||
glDeleteRenderbuffers(1, &m_oit_depth_render_buffer);
|
glDeleteTextures(1, &m_oit_depth_texture);
|
||||||
glGenTextures(1, &m_accum_texture);
|
glGenTextures(1, &m_accum_texture);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_accum_texture);
|
glBindTexture(GL_TEXTURE_2D, m_accum_texture);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA,
|
||||||
@@ -537,11 +539,14 @@ void Renderer::updata_framebuffer(int width, int height) {
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
|
||||||
m_reveal_texture, 0);
|
m_reveal_texture, 0);
|
||||||
glGenRenderbuffers(1, &m_oit_depth_render_buffer);
|
glGenTextures(1, &m_oit_depth_texture);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, m_oit_depth_render_buffer);
|
glBindTexture(GL_TEXTURE_2D, m_oit_depth_texture);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, width, height, 0,
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||||
GL_RENDERBUFFER, m_oit_depth_render_buffer);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
|
||||||
|
m_oit_depth_texture, 0);
|
||||||
GLenum draw_buffer[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
|
GLenum draw_buffer[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
|
||||||
glDrawBuffers(2, draw_buffer);
|
glDrawBuffers(2, draw_buffer);
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
@@ -590,7 +595,7 @@ void Renderer::updata_framebuffer(int width, int height) {
|
|||||||
#pragma region render_world
|
#pragma region render_world
|
||||||
void Renderer::render_world() {
|
void Renderer::render_world() {
|
||||||
// shader map
|
// shader map
|
||||||
glm::mat4 light_space_matrix;
|
glm::mat4& light_space_matrix = m_parallel_light.light_space_matrix;
|
||||||
auto& m_render_snapshots = m_world.render_snapshots();
|
auto& m_render_snapshots = m_world.render_snapshots();
|
||||||
auto& camera_pos = m_camera.get_camera_pos();
|
auto& camera_pos = m_camera.get_camera_pos();
|
||||||
float texels_per_unit = 0.0f;
|
float texels_per_unit = 0.0f;
|
||||||
@@ -635,10 +640,9 @@ void Renderer::render_world() {
|
|||||||
near_plane, far_plane);
|
near_plane, far_plane);
|
||||||
|
|
||||||
light_space_matrix = light_projection * light_view;
|
light_space_matrix = light_projection * light_view;
|
||||||
glUniformMatrix4fv(depth_shader.loc("lightSpaceMatrix"), 1, GL_FALSE,
|
depth_shader.set_loc("lightSpaceMatrix", light_space_matrix);
|
||||||
glm::value_ptr(light_space_matrix));
|
depth_shader.set_loc("is_discard_tranparent", m_discard_tranparent);
|
||||||
glUniform1i(depth_shader.loc("is_discard_tranparent"),
|
|
||||||
m_discard_tranparent);
|
|
||||||
glViewport(0, 0, DEPTH_MAP_SIZE, DEPTH_MAP_SIZE);
|
glViewport(0, 0, DEPTH_MAP_SIZE, DEPTH_MAP_SIZE);
|
||||||
if (m_light_cull_face == 0) {
|
if (m_light_cull_face == 0) {
|
||||||
glCullFace(GL_FRONT);
|
glCullFace(GL_FRONT);
|
||||||
@@ -698,9 +702,6 @@ void Renderer::render_world() {
|
|||||||
const auto& normal_block_shader = get_shader("normal_block");
|
const auto& normal_block_shader = get_shader("normal_block");
|
||||||
normal_block_shader.use();
|
normal_block_shader.use();
|
||||||
|
|
||||||
m_mv_loc = normal_block_shader.loc("mv_matrix");
|
|
||||||
m_proj_loc = normal_block_shader.loc("proj_matrix");
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_depth_map_texture);
|
glBindTexture(GL_TEXTURE_2D, m_depth_map_texture);
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
@@ -711,31 +712,27 @@ void Renderer::render_world() {
|
|||||||
m_norm_mat = glm::transpose(glm::inverse(m_mv_mat));
|
m_norm_mat = glm::transpose(glm::inverse(m_mv_mat));
|
||||||
glm::vec3 light_dir_view = glm::normalize(glm::mat3(m_v_mat) * lightdir);
|
glm::vec3 light_dir_view = glm::normalize(glm::mat3(m_v_mat) * lightdir);
|
||||||
|
|
||||||
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
normal_block_shader.set_loc("mv_matrix", m_mv_mat);
|
||||||
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
normal_block_shader.set_loc("proj_matrix", m_p_mat);
|
||||||
glUniformMatrix4fv(normal_block_shader.loc("norm_matrix"), 1, GL_FALSE,
|
normal_block_shader.set_loc("norm_matrix", m_norm_mat);
|
||||||
glm::value_ptr(m_norm_mat));
|
normal_block_shader.set_loc("lightSpaceMatrix", light_space_matrix);
|
||||||
glUniformMatrix4fv(normal_block_shader.loc("lightSpaceMatrix"), 1, GL_FALSE,
|
normal_block_shader.set_loc("ambientStrength", m_ambient_strength);
|
||||||
glm::value_ptr(light_space_matrix));
|
normal_block_shader.set_loc("sunlightColor",
|
||||||
glUniform1f(normal_block_shader.loc("ambientStrength"), m_ambient_strength);
|
m_parallel_light.directional_light_color);
|
||||||
glUniform3fv(normal_block_shader.loc("sunlightColor"), 1,
|
normal_block_shader.set_loc("ambientColor",
|
||||||
glm::value_ptr(m_parallel_light.directional_light_color));
|
m_parallel_light.finnal_ambient_color);
|
||||||
glUniform3fv(normal_block_shader.loc("ambientColor"), 1,
|
normal_block_shader.set_loc("sunlightDir", light_dir_view);
|
||||||
glm::value_ptr(m_parallel_light.finnal_ambient_color));
|
normal_block_shader.set_loc("shadowMode", m_shadow_mode);
|
||||||
glUniform3fv(normal_block_shader.loc("sunlightDir"), 1,
|
normal_block_shader.set_loc("shader_on", m_shader_on);
|
||||||
glm::value_ptr(light_dir_view));
|
normal_block_shader.set_loc("texelsPerUnit", texels_per_unit);
|
||||||
glUniform1i(normal_block_shader.loc("shadowMode"), m_shadow_mode);
|
normal_block_shader.set_loc("lightSizeUV",
|
||||||
glUniform1i(normal_block_shader.loc("shader_on"), m_shader_on);
|
static_cast<float>(m_light_size_uv));
|
||||||
glUniform1f(normal_block_shader.loc("texelsPerUnit"), texels_per_unit);
|
normal_block_shader.set_loc("minRadius", m_min_radius);
|
||||||
glUniform1f(normal_block_shader.loc("lightSizeUV"),
|
normal_block_shader.set_loc("maxRadius", m_max_radius);
|
||||||
static_cast<GLfloat>(m_light_size_uv));
|
normal_block_shader.set_loc("samples", m_samples);
|
||||||
glUniform1f(normal_block_shader.loc("minRadius"), m_min_radius);
|
normal_block_shader.set_loc("specularStrength", m_specular_strength);
|
||||||
glUniform1f(normal_block_shader.loc("maxRadius"), m_max_radius);
|
normal_block_shader.set_loc("cameraPos", m_camera.get_camera_pos());
|
||||||
glUniform1i(normal_block_shader.loc("samples"), m_samples);
|
|
||||||
glUniform1f(normal_block_shader.loc("specularStrength"),
|
|
||||||
m_specular_strength);
|
|
||||||
glUniform3fv(normal_block_shader.loc("cameraPos"), 1,
|
|
||||||
glm::value_ptr(m_camera.get_camera_pos()));
|
|
||||||
m_mvp_mat = m_p_mat * m_mv_mat;
|
m_mvp_mat = m_p_mat * m_mv_mat;
|
||||||
|
|
||||||
auto& m_planes = m_world.planes();
|
auto& m_planes = m_world.planes();
|
||||||
@@ -797,15 +794,6 @@ void Renderer::render_world() {
|
|||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_oit_fbo);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_oit_fbo);
|
||||||
|
|
||||||
// pass one accumulate
|
// pass one accumulate
|
||||||
auto& accum_shader = get_shader("accum");
|
|
||||||
accum_shader.use();
|
|
||||||
|
|
||||||
GLint mv_loc = accum_shader.loc("mv_matrix");
|
|
||||||
GLint proj_loc = accum_shader.loc("proj_matrix");
|
|
||||||
|
|
||||||
glUniformMatrix4fv(mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
|
||||||
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_oit_fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, m_oit_fbo);
|
||||||
|
|
||||||
glClearBufferfv(GL_COLOR, 0, glm::value_ptr(glm::vec4(0.0f)));
|
glClearBufferfv(GL_COLOR, 0, glm::value_ptr(glm::vec4(0.0f)));
|
||||||
@@ -819,6 +807,28 @@ void Renderer::render_world() {
|
|||||||
glBlendFunci(0, GL_ONE, GL_ONE);
|
glBlendFunci(0, GL_ONE, GL_ONE);
|
||||||
|
|
||||||
glBlendFunci(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
glBlendFunci(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
||||||
|
|
||||||
|
auto set_accum_loc = [&](const Shader& accum_shader) {
|
||||||
|
accum_shader.set_loc("mv_matrix", m_mv_mat);
|
||||||
|
accum_shader.set_loc("proj_matrix", m_p_mat);
|
||||||
|
accum_shader.set_loc("norm_matrix", m_norm_mat);
|
||||||
|
accum_shader.set_loc("lightSpaceMatrix", light_space_matrix);
|
||||||
|
accum_shader.set_loc("ambientStrength", m_ambient_strength);
|
||||||
|
accum_shader.set_loc("sunlightColor",
|
||||||
|
m_parallel_light.directional_light_color);
|
||||||
|
accum_shader.set_loc("ambientColor",
|
||||||
|
m_parallel_light.finnal_ambient_color);
|
||||||
|
accum_shader.set_loc("sunlightDir", light_dir_view);
|
||||||
|
accum_shader.set_loc("shader_on", m_shader_on);
|
||||||
|
accum_shader.set_loc("specularStrength", m_specular_strength);
|
||||||
|
accum_shader.set_loc("cameraPos", m_camera.get_camera_pos());
|
||||||
|
};
|
||||||
|
|
||||||
|
auto& accum_shader = get_shader("accum");
|
||||||
|
accum_shader.use();
|
||||||
|
|
||||||
|
set_accum_loc(accum_shader);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
for (const auto& snapshot : m_render_snapshots) {
|
for (const auto& snapshot : m_render_snapshots) {
|
||||||
if (!Math::is_aabb_in_frustum(snapshot.center, snapshot.half_extents,
|
if (!Math::is_aabb_in_frustum(snapshot.center, snapshot.half_extents,
|
||||||
@@ -834,6 +844,56 @@ void Renderer::render_world() {
|
|||||||
glDrawArrays(GL_TRIANGLES, 0, snapshot.normal_blend_vertices_count);
|
glDrawArrays(GL_TRIANGLES, 0, snapshot.normal_blend_vertices_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use SSR
|
||||||
|
|
||||||
|
auto& water_shader = get_shader("water");
|
||||||
|
water_shader.use();
|
||||||
|
|
||||||
|
set_accum_loc(water_shader);
|
||||||
|
|
||||||
|
water_shader.set_loc("sceneColorTex", 1);
|
||||||
|
water_shader.set_loc("sceneDepthTex", 2);
|
||||||
|
water_shader.set_loc("inv_proj_matrix", glm::inverse(m_p_mat));
|
||||||
|
water_shader.set_loc("inv_view_matrix", glm::inverse(m_v_mat));
|
||||||
|
|
||||||
|
// sky loc
|
||||||
|
|
||||||
|
water_shader.set_loc("skyTop", m_sky_uniform.sky_top);
|
||||||
|
water_shader.set_loc("skyBottom", m_sky_uniform.sky_bottom);
|
||||||
|
water_shader.set_loc("sunDir", m_sky_uniform.sun_dir_view);
|
||||||
|
water_shader.set_loc("sunColor", m_parallel_light.directional_light_color);
|
||||||
|
water_shader.set_loc("horizonSharpness", m_sky_uniform.horizon_sharpness);
|
||||||
|
water_shader.set_loc("time", glfwGetTime());
|
||||||
|
water_shader.set_loc("cloudWhiteMix", m_sky_uniform.cloud_white_mix);
|
||||||
|
water_shader.set_loc("cloudThresholdLow", m_cloud_threshold_low);
|
||||||
|
water_shader.set_loc("cloudThresholdHigh", m_cloud_threshold_high);
|
||||||
|
water_shader.set_loc("underwater", m_camera.is_under_water());
|
||||||
|
water_shader.set_loc("refractStrength", m_refract_strength);
|
||||||
|
water_shader.set_loc("enablePerturb", m_water_perturb);
|
||||||
|
water_shader.set_loc("enableDepthFade", m_water_depth_fade);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_screen_texture);
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_screen_depth_texture);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
for (const auto& snapshot : m_render_snapshots) {
|
||||||
|
if (!Math::is_aabb_in_frustum(snapshot.center, snapshot.half_extents,
|
||||||
|
m_planes)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot.water_vertices_count != 0) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY,
|
||||||
|
m_texture_manager.get_texture_array());
|
||||||
|
glBindVertexArray(snapshot.water_vao);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, snapshot.water_vertices_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto& composite_shader = get_shader("composite");
|
auto& composite_shader = get_shader("composite");
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
composite_shader.use();
|
composite_shader.use();
|
||||||
@@ -915,6 +975,8 @@ Renderer::get_smoothed_shadow_lightdir(const glm::vec3& raw_shadow_lightdir,
|
|||||||
float& Renderer::ambient_strength() { return m_ambient_strength; }
|
float& Renderer::ambient_strength() { return m_ambient_strength; }
|
||||||
bool& Renderer::discard_transparent() { return m_discard_tranparent; }
|
bool& Renderer::discard_transparent() { return m_discard_tranparent; }
|
||||||
bool& Renderer::shader_on() { return m_shader_on; }
|
bool& Renderer::shader_on() { return m_shader_on; }
|
||||||
|
bool& Renderer::water_perturb() { return m_water_perturb; }
|
||||||
|
bool& Renderer::water_depth_fade() { return m_water_depth_fade; }
|
||||||
int& Renderer::shadow_mode() { return m_shadow_mode; }
|
int& Renderer::shadow_mode() { return m_shadow_mode; }
|
||||||
int& Renderer::light_cull_face() { return m_light_cull_face; }
|
int& Renderer::light_cull_face() { return m_light_cull_face; }
|
||||||
int& Renderer::light_size_uv() { return m_light_size_uv; }
|
int& Renderer::light_size_uv() { return m_light_size_uv; }
|
||||||
@@ -925,4 +987,7 @@ float& Renderer::specular_strength() { return m_specular_strength; }
|
|||||||
float& Renderer::cloud_speed() { return m_cloud_speed; }
|
float& Renderer::cloud_speed() { return m_cloud_speed; }
|
||||||
float& Renderer::cloud_threshold_low() { return m_cloud_threshold_low; }
|
float& Renderer::cloud_threshold_low() { return m_cloud_threshold_low; }
|
||||||
float& Renderer::cloud_threshold_high() { return m_cloud_threshold_high; }
|
float& Renderer::cloud_threshold_high() { return m_cloud_threshold_high; }
|
||||||
|
float& Renderer::refract_strength() { return m_refract_strength; }
|
||||||
|
float& Renderer::underwater_fog_density() { return m_underwater_fog_density; }
|
||||||
|
float& Renderer::water_density() { return m_water_density; }
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
Reference in New Issue
Block a user