mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
Compare commits
3 Commits
75cccf0c4c
...
ab40c2eb34
| Author | SHA1 | Date | |
|---|---|---|---|
| ab40c2eb34 | |||
| 3b5a3b994f | |||
| e1eaf62f09 |
@@ -1,14 +1,75 @@
|
||||
#version 460
|
||||
|
||||
in vec2 TexCoord;
|
||||
in vec3 rayDir;
|
||||
|
||||
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 bool u_underwater;
|
||||
uniform vec3 u_waterColor;
|
||||
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() {
|
||||
vec4 original = texture(u_sceneTexture, TexCoord);
|
||||
@@ -18,6 +79,12 @@ void main() {
|
||||
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;
|
||||
float strength = 0.003;
|
||||
distoredUV.x += sin(TexCoord.y * 15.0 + u_time * 5.0) * strength;
|
||||
@@ -25,11 +92,46 @@ void main() {
|
||||
distoredUV = clamp(distoredUV, 0.001, 0.999);
|
||||
vec4 distorted = texture(u_sceneTexture, distoredUV);
|
||||
|
||||
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 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 fogFactor = clamp(1.0 - (TexCoord.y * u_fogDensity * 10.0), 0.0, 1.0);
|
||||
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 = 1) in vec2 texCoord;
|
||||
|
||||
out vec2 TexCoord;
|
||||
uniform mat4 InverseViewProjection;
|
||||
uniform vec3 cameraPos;
|
||||
|
||||
out vec2 TexCoord;
|
||||
out vec3 rayDir;
|
||||
void main() {
|
||||
gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -237,9 +237,9 @@ void main() {
|
||||
vec3 sceneViewPos = reconstructViewPos(screenUV, sceneDepthRaw);
|
||||
float waterDepth = vert_pos.z - sceneViewPos.z;
|
||||
waterDepth = max(waterDepth, 0.0);
|
||||
// fully deep water
|
||||
const float DEPTH_FADE_DISTANCE = 8.0;
|
||||
float depthFactor = underwater ? 0.0 : clamp(waterDepth / DEPTH_FADE_DISTANCE, 0.0, 1.0);
|
||||
|
||||
const float DEPTH_FADE_DISTANCE = 10;
|
||||
float depthFactor = clamp(waterDepth / DEPTH_FADE_DISTANCE, 0.0, 1.0);
|
||||
|
||||
if (underwater) {
|
||||
reflectColor = vec3(0.0);
|
||||
@@ -287,7 +287,7 @@ void main() {
|
||||
|
||||
if (enableDepthFade) {
|
||||
vec3 shallowColor = vec3(0.4, 0.75, 0.7);
|
||||
vec3 deepColor = vec3(0.0, 0.08, 0.15);
|
||||
vec3 deepColor = vec3(0.0, 0.015, 0.045);
|
||||
|
||||
vec3 waterTint = mix(shallowColor, deepColor, depthFactor);
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ constexpr float CROSS_NORMALS[2][6][3] = {
|
||||
{0.0f, 1.0f, 0.0f}}};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// [-1, 1]
|
||||
constexpr float QUAD_VERTICES[] = {
|
||||
// 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,
|
||||
|
||||
@@ -45,10 +45,12 @@ public:
|
||||
float& cloud_threshold_low();
|
||||
float& cloud_threshold_high();
|
||||
float& refract_strength();
|
||||
float& underwater_fog_density();
|
||||
float& water_density();
|
||||
|
||||
private:
|
||||
struct ParallelLight {
|
||||
glm::vec3 sundir;
|
||||
glm::vec3 sundir; // direction from sun to vertex
|
||||
glm::vec3 lightdir;
|
||||
float sun_height = 0.0f;
|
||||
float day_light = 0.0f;
|
||||
@@ -56,6 +58,7 @@ private:
|
||||
glm::vec3 sun_color;
|
||||
glm::vec3 directional_light_color;
|
||||
glm::vec3 finnal_ambient_color;
|
||||
glm::mat4 light_space_matrix;
|
||||
};
|
||||
|
||||
struct SkyUniform {
|
||||
@@ -115,7 +118,7 @@ private:
|
||||
|
||||
GLuint m_fbo = 0;
|
||||
GLuint m_screen_texture = 0;
|
||||
GLuint m_depth_texture = 0;
|
||||
GLuint m_screen_depth_texture = 0;
|
||||
|
||||
GLuint m_oit_fbo = 0;
|
||||
GLuint m_accum_texture = 0;
|
||||
@@ -152,6 +155,10 @@ private:
|
||||
|
||||
float m_refract_strength = 0.03f;
|
||||
|
||||
float m_underwater_fog_density = 0.08f;
|
||||
|
||||
float m_water_density = 0.12f;
|
||||
|
||||
ParallelLight m_parallel_light;
|
||||
SkyUniform m_sky_uniform;
|
||||
/*
|
||||
|
||||
@@ -662,6 +662,11 @@ void DevPanel::show_shader_tab_item() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ Renderer::~Renderer() {
|
||||
glDeleteVertexArrays(NUM_VAO, m_vao.data());
|
||||
glDeleteFramebuffers(1, &m_fbo);
|
||||
glDeleteTextures(1, &m_screen_texture);
|
||||
glDeleteTextures(1, &m_depth_texture);
|
||||
glDeleteTextures(1, &m_screen_depth_texture);
|
||||
|
||||
glDeleteFramebuffers(1, &m_oit_fbo);
|
||||
glDeleteTextures(1, &m_accum_texture);
|
||||
@@ -443,11 +443,19 @@ void Renderer::render_underwater() {
|
||||
shader.set_loc("u_time", static_cast<float>(glfwGetTime()));
|
||||
shader.set_loc("u_underwater", m_camera.is_under_water());
|
||||
shader.set_loc("u_waterColor", glm::vec3(0.1f, 0.25f, 0.35f));
|
||||
shader.set_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);
|
||||
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);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
@@ -483,7 +491,7 @@ void Renderer::updata_framebuffer(int width, int height) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||
|
||||
glDeleteTextures(1, &m_screen_texture);
|
||||
glDeleteTextures(1, &m_depth_texture);
|
||||
glDeleteTextures(1, &m_screen_depth_texture);
|
||||
|
||||
glGenTextures(1, &m_screen_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_screen_texture);
|
||||
@@ -495,14 +503,14 @@ void Renderer::updata_framebuffer(int width, int height) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
m_screen_texture, 0);
|
||||
|
||||
glGenTextures(1, &m_depth_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_depth_texture);
|
||||
glGenTextures(1, &m_screen_depth_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_screen_depth_texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, width, height, 0,
|
||||
GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
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_depth_texture, 0);
|
||||
m_screen_depth_texture, 0);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
Logger::error("FBO incomplete after resize!");
|
||||
@@ -587,7 +595,7 @@ void Renderer::updata_framebuffer(int width, int height) {
|
||||
#pragma region render_world
|
||||
void Renderer::render_world() {
|
||||
// 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& camera_pos = m_camera.get_camera_pos();
|
||||
float texels_per_unit = 0.0f;
|
||||
@@ -868,7 +876,7 @@ void Renderer::render_world() {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, m_screen_texture);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, m_depth_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_screen_depth_texture);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
for (const auto& snapshot : m_render_snapshots) {
|
||||
@@ -980,4 +988,6 @@ float& Renderer::cloud_speed() { return m_cloud_speed; }
|
||||
float& Renderer::cloud_threshold_low() { return m_cloud_threshold_low; }
|
||||
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
|
||||
Reference in New Issue
Block a user