From 8a077ca7c421dcea92c9485aa284c6e636f2ddad Mon Sep 17 00:00:00 2001 From: Hunter Kvalevog Date: Sat, 15 Nov 2025 08:48:09 -0600 Subject: gl-vfog: Add more modes --- gl-vfog/fs.glsl | 73 ++++++++++++++++++++++++++++++++++++++++++++++++--------- gl-vfog/main.cc | 14 +++++------ 2 files changed, 69 insertions(+), 18 deletions(-) (limited to 'gl-vfog') diff --git a/gl-vfog/fs.glsl b/gl-vfog/fs.glsl index 00ec9b1..12f32b9 100644 --- a/gl-vfog/fs.glsl +++ b/gl-vfog/fs.glsl @@ -4,13 +4,19 @@ in vec3 f_p; out vec4 f_color; +// ----------------------------------------------------------------------------- +// Uniforms +// ----------------------------------------------------------------------------- uniform vec3 u_cam; uniform float u_time; uniform int u_mode; uniform float u_sigma; +uniform int u_steps; +// ----------------------------------------------------------------------------- // Ray-AABB intersection // ref: https://tavianator.com/2022/ray_box_boundary.html +// ----------------------------------------------------------------------------- bool intersect(vec3 ro, vec3 rd, vec3 bbmin, vec3 bbmax, out float t0, out float t1) { vec3 inv = 1.0f / rd; @@ -23,8 +29,49 @@ bool intersect(vec3 ro, vec3 rd, vec3 bbmin, vec3 bbmax, out float t0, out float return t1 >= max(t0, 0.0f); } -// Mode 0: Basic -void main_0() +// ----------------------------------------------------------------------------- +// Mode 0: Basic volumetric fog +// ----------------------------------------------------------------------------- +float sample_basic(vec3 pos) +{ + return 1.0; +} + +// ----------------------------------------------------------------------------- +// Mode 1: Fade along y axis +// ----------------------------------------------------------------------------- + +float sample_vfade(vec3 pos) +{ + return 1.0f - pos.y; +} + +// ----------------------------------------------------------------------------- +// Mode 2: Some waves +// ----------------------------------------------------------------------------- + +float sample_waves(vec3 pos) +{ + // Fractal sum + // ref: https://thebookofshaders.com/13/ + float h = 0.75f; // baseline + + // Big waves + h += 0.08f * sin(pos.x * 2.0f + u_time); + h += 0.08f * cos(pos.z * 2.0f + u_time * -1.1f); + + // Medium waves + h += 0.05f * sin(pos.x * 5.0f + u_time * 1.7f); + h += 0.05f * cos(pos.z * 4.0f + u_time * -2.0f); + + // Small but choppy waves + h += 0.03f * sin(pos.x * 12.0f + u_time * 3.3f); + h += 0.03f * cos(pos.z * 11.0f + u_time * -2.5f); + + return float(pos.y < h); +} + +void main() { vec3 bbmin = vec3(0.0f, 0.0f, 0.0f); vec3 bbmax = vec3(1.0f, 1.0f, 1.0f); @@ -44,17 +91,21 @@ void main_0() float t_exit = t1; float t_len = max(0.0f, t_exit - t_enter); + float density = 0; + for (int i = 0; i < u_steps; ++i) { + float t = mix(t_enter, t_exit, (float(i) + 0.5f) / float(u_steps)); + vec3 p = ro + rd * t; + switch (u_mode) { + case 0: { density += sample_basic(p); } break; + case 1: { density += sample_vfade(p); } break; + case 2: { density += sample_waves(p); } break; + } + } + density /= float(u_steps); + // Beer-Lambert attenuation // ref: https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law - float a = 1.0f - exp(-u_sigma * t_len); + float a = 1.0f - exp(-u_sigma * t_len * density); f_color = vec4(vec3(1.0f), a); } - -void main() -{ - switch (u_mode) { - case 0: { main_0(); } break; - default: { f_color = vec4(0.0f, 1.0f, 0.0f, 1.0f); } break; - } -} diff --git a/gl-vfog/main.cc b/gl-vfog/main.cc index d14ff38..679d4ec 100644 --- a/gl-vfog/main.cc +++ b/gl-vfog/main.cc @@ -188,6 +188,7 @@ int main(int argc, char* argv[]) GLuint u_time = GL(glGetUniformLocation(prog, "u_time")); GLuint u_mode = GL(glGetUniformLocation(prog, "u_mode")); GLuint u_sigma = GL(glGetUniformLocation(prog, "u_sigma")); + GLuint u_steps = GL(glGetUniformLocation(prog, "u_steps")); bool running = true; while (running) { @@ -213,26 +214,24 @@ int main(int argc, char* argv[]) static int c_mode = 0; static float c_sigma = 4.0f; static float c_zoom = 1.5f; + static int c_steps = 64; ImGui::SetNextWindowPos(ImVec2(15, 15)); ImGui::SetNextWindowSize(ImVec2(150, 768 - 30)); if (ImGui::Begin("Controls", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize)) { ImGui::SeparatorText("Controls"); ImGui::DragFloat("Zoom", &c_zoom, 0.05f, 0.1f, 3.0f); ImGui::SeparatorText("Settings"); - const char* modes[] = { "Basic" }; + const char* modes[] = { "Basic", "Fade", "Waves", }; if (ImGui::BeginCombo("Mode", modes[c_mode])) { for (int i = 0; i < IM_ARRAYSIZE(modes); ++i) { - if (ImGui::Selectable(modes[c_mode], i == c_mode)) { + if (ImGui::Selectable(modes[i], i == c_mode)) { c_mode = i; } } ImGui::EndCombo(); } - switch (c_mode) { - case 0: { - ImGui::DragFloat("Sigma", &c_sigma, 0.05); - } break; - } + ImGui::DragInt("Steps", &c_steps); + ImGui::DragFloat("Sigma", &c_sigma, 0.05); ImGui::End(); } @@ -263,6 +262,7 @@ int main(int argc, char* argv[]) GL(glUniform1f(u_time, t)); GL(glUniform1i(u_mode, c_mode)); GL(glUniform1f(u_sigma, c_sigma)); + GL(glUniform1i(u_steps, c_steps)); GL(glDrawElements(GL_TRIANGLES, 3 * 12, GL_UNSIGNED_SHORT, NULL)); -- cgit v1.2.3