diff --git a/CMakeLists.txt b/CMakeLists.txt index 284e47dc75833783a3e08c288a67eba5c0243bef..fb879f27af33a85f6078b1984e1f7a7b00120f80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED NO) set(CMAKE_CXX_EXTENSIONS OFF) # major, minor, patch, and _STAGE_ (0 = alpha, 1 = beta, 2 = gamma/release) -project(radiance_cascades VERSION 0.5.1.1) +project(radiance_cascades VERSION 0.5.2.1) configure_file(src/config.h.in config.h) diff --git a/res/shaders/gi.frag b/res/shaders/gi.frag index 5085da32d5341ba01745731e81bb270d348cc8d8..99a15bb933d21be84a4837f018aeb20b4c46b8ee 100644 --- a/res/shaders/gi.frag +++ b/res/shaders/gi.frag @@ -3,7 +3,7 @@ #define PI 3.141596 #define TWO_PI 6.2831853071795864769252867665590 #define TAU 0.0008 -#define DECAY_RATE 1.3 +#define DECAY_RATE 1.1 out vec4 fragColor; @@ -58,24 +58,24 @@ float noise(vec2 p){ void main() { /* - * To calculate the light value of a pixel we cast `uRaysPerPx` amount of rays in all directions + * To calculate the radiance value of a pixel we cast `uRaysPerPx` amount of rays in all directions * and add all of the resulting samples up, then divide by uRaysPerPx */ vec2 fragCoord = gl_FragCoord.xy/uResolution; float dist = texture(uDistanceField, fragCoord).r; float noise = noise(fragCoord.xy * 2000); - vec3 light = texture(uLastFrame, fragCoord).rgb; + vec3 radiance = texture(uLastFrame, fragCoord).rgb; if (dist >= TAU) { // if we're not already in a wall // cast rays angularly with equal angles between them for (float i = 0.0; i < TWO_PI; i += TWO_PI / uRaysPerPx) { float angle = i + noise; vec3 hitcol = raymarch(fragCoord, vec2(cos(angle) * uResolution.y/uResolution.x, sin(angle))); - light += hitcol; + radiance += hitcol; } - light /= uRaysPerPx; + radiance /= uRaysPerPx; } - fragColor = vec4(light, 1.0); + fragColor = vec4(radiance, 1.0); } diff --git a/res/shaders/rc.frag b/res/shaders/rc.frag new file mode 100644 index 0000000000000000000000000000000000000000..ffa69b0f6003086b8096263afe2db3c2391076c9 --- /dev/null +++ b/res/shaders/rc.frag @@ -0,0 +1,63 @@ +#version 330 core + +#define PI 3.141596 +#define TWO_PI 6.2831853071795864769252867665590 +#define TAU 0.0008 +#define DECAY_RATE 1.3 + +out vec4 fragColor; + +uniform vec2 uResolution; +uniform int uRaysPerPx; +uniform int uMaxSteps; +uniform float uPointA; +uniform float uPointB; +uniform float uLinearResolution; + +uniform sampler2D uDistanceField; +uniform sampler2D uSceneMap; +uniform sampler2D uLastPass; + +// altered raymarching function; only returns coordinates with a distance between a and b +vec2 radiance_interval(vec2 uv, vec2 dir, float a, float b) { + uv += a * dir; + float travelledDist = a; + for (int i = 0; i < uMaxSteps; i++) { + float dist = texture(uDistanceField, uv).r; // sample distance field + uv += (dir * dist); // march our ray (divided by our aspect ratio so no skewed directions) + + // skip UVs outside of the window + if (uv.x != clamp(uv.x, 0.0, 1.0) || uv.y != clamp(uv.y, 0.0, 1.0)) + break; + + // surface hit + if (dist < TAU) + return uv; + + travelledDist += dist; + if (travelledDist >= b) + break; + } + return vec2(0.0); +} + +void main() { + vec2 fragCoord = gl_FragCoord.xy/uResolution; + + float dist = texture(uDistanceField, fragCoord).r; + vec3 radiance = texture(uSceneMap, fragCoord).rgb; + + vec2 uv = floor(gl_FragCoord.xy / uLinearResolution) * uLinearResolution / uResolution; + + if (dist >= TAU) { // if we're not already in a wall + // cast rays angularly with equal angles between them + for (float i = 0.0; i < TWO_PI; i += TWO_PI / uRaysPerPx) { + float angle = i + 0.5; + vec2 hitpos = radiance_interval(uv, vec2(cos(angle) * uResolution.y/uResolution.x, sin(angle)), uPointA, uPointB); + radiance += texture(uSceneMap, hitpos).rgb; + } + radiance /= uRaysPerPx; + } + + fragColor = vec4((radiance + texture(uLastPass, fragCoord).rgb) / 2, 1.0); +} diff --git a/src/demo.cpp b/src/demo.cpp index b9ac30d2cf2047a5f22980824f0195ee3c02a512..a0ceb4194d30308bf4b06b0486eeac296d6958e1 100644 --- a/src/demo.cpp +++ b/src/demo.cpp @@ -14,6 +14,7 @@ Demo::Demo() { pointA = 0.0; pointB = 1.0; orbs = 0.0; + gi = false; user.mode= DRAWING; userSetRandomColor(); @@ -104,6 +105,7 @@ void Demo::render() { ClearBackground(PINK); // const Shader& rcShader = shaders["rc.frag"]; + const Shader& rcShader = shaders["rc.frag"]; const Shader& giShader = shaders["gi.frag"]; const Shader& jfaShader = shaders["jfa.frag"]; const Shader& prepJfaShader = shaders["prepjfa.frag"]; @@ -183,18 +185,49 @@ void Demo::render() { EndShaderMode(); EndTextureMode(); - BeginTextureMode(radianceBufferA); - BeginShaderMode(giShader); - ClearBackground(BLANK); - SetShaderValueTexture(giShader, GetShaderLocation(giShader, "uDistanceField"), distFieldBuf.texture); - SetShaderValueTexture(giShader, GetShaderLocation(giShader, "uSceneMap"), sceneBuf.texture); - SetShaderValueTexture(giShader, GetShaderLocation(giShader, "uLastFrame"), radianceBufferB.texture); - SetShaderValue(giShader, GetShaderLocation(giShader, "uResolution"), &resolution, SHADER_UNIFORM_VEC2); - SetShaderValue(giShader, GetShaderLocation(giShader, "uRaysPerPx"), &raysPerPx, SHADER_UNIFORM_INT); - SetShaderValue(giShader, GetShaderLocation(giShader, "uMaxSteps"), &maxSteps, SHADER_UNIFORM_INT); - DrawRectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, WHITE); - EndShaderMode(); - EndTextureMode(); + if (gi) { + BeginTextureMode(radianceBufferA); + BeginShaderMode(giShader); + ClearBackground(BLANK); + SetShaderValueTexture(giShader, GetShaderLocation(giShader, "uDistanceField"), distFieldBuf.texture); + SetShaderValueTexture(giShader, GetShaderLocation(giShader, "uSceneMap"), sceneBuf.texture); + SetShaderValueTexture(giShader, GetShaderLocation(giShader, "uLastFrame"), radianceBufferB.texture); + SetShaderValue(giShader, GetShaderLocation(giShader, "uResolution"), &resolution, SHADER_UNIFORM_VEC2); + SetShaderValue(giShader, GetShaderLocation(giShader, "uRaysPerPx"), &raysPerPx, SHADER_UNIFORM_INT); + SetShaderValue(giShader, GetShaderLocation(giShader, "uMaxSteps"), &maxSteps, SHADER_UNIFORM_INT); + DrawRectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, WHITE); + EndShaderMode(); + EndTextureMode(); + } else { + for (int i = 0; i < 2; i++) { + radianceBufferC = radianceBufferA; + radianceBufferA = radianceBufferB; + radianceBufferB = radianceBufferC; + + + #define BASE_RAY_COUNT 16 + float intervalStart = i == 0 ? 0.0 : 0.125; + float intervalEnd = i == 0 ? 0.125 : 1.0; + int rayCount = pow(BASE_RAY_COUNT, i+1); // angular resolution + float linearResolution = i == 0 ? 1.0 : 4.0; + + BeginTextureMode(radianceBufferA); + BeginShaderMode(rcShader); + ClearBackground(BLANK); + SetShaderValueTexture(rcShader, GetShaderLocation(rcShader, "uDistanceField"), distFieldBuf.texture); + SetShaderValueTexture(rcShader, GetShaderLocation(rcShader, "uSceneMap"), sceneBuf.texture); + SetShaderValueTexture(rcShader, GetShaderLocation(rcShader, "uLastPass"), radianceBufferC.texture); + SetShaderValue(rcShader, GetShaderLocation(rcShader, "uResolution"), &resolution, SHADER_UNIFORM_VEC2); + SetShaderValue(rcShader, GetShaderLocation(rcShader, "uRaysPerPx"), &rayCount, SHADER_UNIFORM_INT); + SetShaderValue(rcShader, GetShaderLocation(rcShader, "uLinearResolution"), &linearResolution, SHADER_UNIFORM_FLOAT); + SetShaderValue(rcShader, GetShaderLocation(rcShader, "uMaxSteps"), &maxSteps, SHADER_UNIFORM_INT); + SetShaderValue(rcShader, GetShaderLocation(rcShader, "uPointA"), &intervalStart, SHADER_UNIFORM_FLOAT); + SetShaderValue(rcShader, GetShaderLocation(rcShader, "uPointB"), &intervalEnd, SHADER_UNIFORM_FLOAT); + DrawRectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, WHITE); + EndShaderMode(); + EndTextureMode(); + } + } BeginTextureMode(lastFrameBuf); DrawTextureRec(radianceBufferA.texture, {0, 0.0, SCREEN_WIDTH, SCREEN_HEIGHT}, {0.0, 0.0}, WHITE); @@ -263,14 +296,15 @@ void Demo::renderUI() { bool orbsBool = (orbs == 1); ImGui::Checkbox("light orb circle", &orbsBool); orbs = (int)orbsBool; + ImGui::Checkbox("gi", &gi); if (ImGui::SmallButton("show buffers")) debugShowBuffers = !debugShowBuffers; if (debugShowBuffers) { if (ImGui::BeginTable("buffer_table", 2)) { - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - rlImGuiImageSizeV(&emissionMap.tex, {80, 60}); - ImGui::TableSetColumnIndex(1); - rlImGuiImageSizeV(&occlusionMap.tex, {80, 60}); + // ImGui::TableNextRow(); + // ImGui::TableSetColumnIndex(0); + // rlImGuiImageSizeV(&emissionMap.tex, {80, 60}); + // ImGui::TableSetColumnIndex(1); + // rlImGuiImageSizeV(&occlusionMap.tex, {80, 60}); ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); rlImGuiImageSizeV(&sceneBuf.texture, {80, 60}); @@ -283,7 +317,10 @@ void Demo::renderUI() { ImGui::TableSetColumnIndex(0); rlImGuiImageSizeV(&radianceBufferA.texture, {80, 60}); ImGui::TableSetColumnIndex(1); - rlImGuiImageSizeV(&lastFrameBuf.texture, {80, 60}); + rlImGuiImageSizeV(&radianceBufferB.texture, {80, 60}); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + rlImGuiImageSizeV(&radianceBufferC.texture, {80, 60}); ImGui::EndTable(); } } diff --git a/src/demo.h b/src/demo.h index 8f6d4335d15714f002792103fddb1aa80eba634c..20f75ed6af609d07169d9c655dcdf26c546b2cbe 100644 --- a/src/demo.h +++ b/src/demo.h @@ -53,6 +53,7 @@ class Demo { int raysPerPx; bool debug; bool sceneHasChanged; + bool gi; float pointA; float pointB; int orbs; // bool uniform