From ceb4f69efcb0d6696992702ad7090f2b7a2a08b3 Mon Sep 17 00:00:00 2001 From: Asuro Date: Wed, 26 Feb 2025 22:52:55 +0100 Subject: [PATCH] magical new dots --- .gitignore | 1 + src/game/Level.cpp | 3 +- src/game/compiled-shaders/dx11/frag.bin | 4 +- src/game/compiled-shaders/glsl/frag.bin | 4 +- src/game/compiled-shaders/spirv/frag.bin | 4 +- src/game/rendering/Rendering.cpp | 46 +++++++++++----- src/game/rendering/Rendering.h | 7 ++- src/game/shaders/frag.sc | 68 +++++++++++++++++------- src/imgui.ini | 21 -------- 9 files changed, 97 insertions(+), 61 deletions(-) delete mode 100644 src/imgui.ini diff --git a/.gitignore b/.gitignore index ea8d5fd..33023d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ # assets *.blend1 tools/remedy-session.rdbg +src/imgui.ini diff --git a/src/game/Level.cpp b/src/game/Level.cpp index ce6307d..22ade74 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -32,7 +32,8 @@ namespace Game float TimeValues[4]{0.0f}; TimeValues[0] = GetInstance().Time.Now; bgfx::setTexture(0, currentMaterial.Textures[0].SamplerHandle, currentMaterial.Textures[0].Handle); - bgfx::setTexture(1, rendering.DitherTextures.Sampler, rendering.DitherTextures.FinalTex); + bgfx::setTexture(1, rendering.DitherTextures.DitherSampler, rendering.DitherTextures.FinalTex); + bgfx::setTexture(2, rendering.DitherTextures.RampSampler, rendering.DitherTextures.RampTex); bgfx::setUniform(currentMaterial.Uniforms[Material::UTime], TimeValues); bgfx::setUniform(currentMaterial.Uniforms[Material::UDotColor], TestColor); diff --git a/src/game/compiled-shaders/dx11/frag.bin b/src/game/compiled-shaders/dx11/frag.bin index d99be2b..3c293c6 100644 --- a/src/game/compiled-shaders/dx11/frag.bin +++ b/src/game/compiled-shaders/dx11/frag.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4f534be349af03c65d024db1a126f6ed229686718f3d409d72d08163b524906 -size 2064 +oid sha256:4b07ca86cc3c0a04e29d60bf55190c93055db86e2c6fe770136fba52bc4c3e17 +size 3578 diff --git a/src/game/compiled-shaders/glsl/frag.bin b/src/game/compiled-shaders/glsl/frag.bin index 5056f82..4bc5a7c 100644 --- a/src/game/compiled-shaders/glsl/frag.bin +++ b/src/game/compiled-shaders/glsl/frag.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8687ed860438b2035627f5a18dcc3909be909dfaf61d86e60a8bfbf374edc409 -size 12332 +oid sha256:f293ceb05aaae9067548cfcf166da78a01d4a6331e1341074c775b9bdc41f837 +size 12985 diff --git a/src/game/compiled-shaders/spirv/frag.bin b/src/game/compiled-shaders/spirv/frag.bin index 6aafbc2..c4d7ef7 100644 --- a/src/game/compiled-shaders/spirv/frag.bin +++ b/src/game/compiled-shaders/spirv/frag.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a11349b7c86ccafb8a6c809dd9b447dbb867e5e345b5e4c1ff4a28985857c830 -size 2860 +oid sha256:e190fcdb299f8d5fa1374c55745404955d758adb14ee6305feab3c7cd00a84a7 +size 3988 diff --git a/src/game/rendering/Rendering.cpp b/src/game/rendering/Rendering.cpp index 2af06e6..ddb5bb8 100644 --- a/src/game/rendering/Rendering.cpp +++ b/src/game/rendering/Rendering.cpp @@ -193,16 +193,17 @@ namespace Game return handle; } - void DitherGen(DitherData& data) + void DitherGen(DitherData& data, int32_t recursion) { - constexpr int32_t MaxRecursion = 1; data.Points[0] = {0.0f, 0.0f}; data.Points[1] = {0.5f, 0.5f}; data.Points[2] = {0.5f, 0.0f}; data.Points[3] = {0.0f, 0.5f}; data.PointCount = 4; + for (int32_t i = 0; i < data.BrightnessBucketCount; ++i) + data.BrightnessBuckets[i] = 0; - for (int32_t recursionLevel = 0; recursionLevel < MaxRecursion; ++recursionLevel) + for (int32_t recursionLevel = 0; recursionLevel < recursion; ++recursionLevel) { int32_t startCount = data.PointCount; float offset = bx::pow(0.5f, recursionLevel + 1); @@ -216,7 +217,7 @@ namespace Game } } - uint64_t dotsPerSide = bx::round(bx::pow(2, MaxRecursion)); + uint64_t dotsPerSide = bx::round(bx::pow(2, recursion)); data.DitherTexDepth = dotsPerSide * dotsPerSide; data.DitherTexWH = 16 * dotsPerSide; uint64_t texPixelCount = data.DitherTexWH * data.DitherTexWH * data.DitherTexDepth; @@ -257,12 +258,20 @@ namespace Game int32_t bucket = bx::clamp(uint32_t(val * DitherData::BrightnessBucketCount), 0, DitherData::BrightnessBucketCount - 1); + data.BrightnessBuckets[bucket] += 1; } } } - // TODO: brightness ramp + // Brightness ramp + int32_t sum = 0; + for (int32_t i = 0; i < data.BrightnessBucketCount; ++i) + { + sum += data.BrightnessBuckets[data.BrightnessBucketCount - 1 - i]; + data.BrightnessRamp[i + 1] = sum / (float)texPixelCount; + } + // Upload textures if (isValid(data.PreviewTex)) { bgfx::destroy(data.PreviewTex); @@ -273,8 +282,14 @@ namespace Game bgfx::destroy(data.FinalTex); data.FinalTex = BGFX_INVALID_HANDLE; } + if (isValid(data.RampTex)) + { + bgfx::destroy(data.RampTex); + data.RampTex = BGFX_INVALID_HANDLE; + } const bgfx::Memory* memPreview = bgfx::makeRef(data.DitherTex, texPixelCount * sizeof(Vec4)); const bgfx::Memory* memFinal = bgfx::makeRef(data.DitherTex, texPixelCount * sizeof(Vec4)); + const bgfx::Memory* memRamp = bgfx::makeRef(data.BrightnessRamp, sizeof(data.BrightnessRamp)); data.PreviewTex = bgfx::createTexture2D(data.DitherTexWH, data.DitherTexWH * data.DitherTexDepth, false, @@ -289,10 +304,16 @@ namespace Game bgfx::TextureFormat::RGBA32F, 0, memFinal); + data.RampTex = bgfx::createTexture2D( + BX_COUNTOF(data.BrightnessRamp), 1, false, 1, bgfx::TextureFormat::R32F, 0, memRamp); - if (!isValid(data.Sampler)) + if (!isValid(data.DitherSampler)) { - data.Sampler = bgfx::createUniform("s_ditherSampler", bgfx::UniformType::Sampler); + data.DitherSampler = bgfx::createUniform("s_ditherSampler", bgfx::UniformType::Sampler); + } + if (!isValid(data.RampSampler)) + { + data.RampSampler = bgfx::createUniform("s_rampSampler", bgfx::UniformType::Sampler); } } @@ -378,7 +399,7 @@ namespace Game { ImGui::LoadIniSettingsFromDisk("imgui.ini"); } - DitherGen(DitherTextures); + DitherGen(DitherTextures, DitherRecursion); } void GameRendering::Update() @@ -460,8 +481,10 @@ namespace Game } if (ImGui::Button("Dithergen")) { - DitherGen(DitherTextures); + DitherGen(DitherTextures, DitherRecursion); } + ImGui::SameLine(); + ImGui::SliderInt("Recursion", &DitherRecursion, 1, 4); ImGui::Text( "%ux%ux%u", DitherTextures.DitherTexWH, DitherTextures.DitherTexWH, DitherTextures.DitherTexDepth); if (!isValid(DitherTextures.PreviewTex)) @@ -474,10 +497,9 @@ namespace Game {(float)DitherTextures.DitherTexWH, (float)DitherTextures.DitherTexWH * DitherTextures.DitherTexDepth}); } - ImGui::Text("Brightness Buckets (TODO)"); - for (int32_t i = 0; i < DitherTextures.BrightnessBucketCount; ++i) + if (isValid(DitherTextures.RampTex)) { - ImGui::Text("%u", DitherTextures.BrightnessBuckets[i]); + ImGui::Image(DitherTextures.RampTex.idx, {BX_COUNTOF(DitherTextures.BrightnessRamp), 1}); } } ImGui::End(); diff --git a/src/game/rendering/Rendering.h b/src/game/rendering/Rendering.h index 89c3690..a281570 100644 --- a/src/game/rendering/Rendering.h +++ b/src/game/rendering/Rendering.h @@ -74,9 +74,13 @@ namespace Game uint32_t DitherTexWH = 0; uint32_t DitherTexDepth = 0; int32_t BrightnessBuckets[BrightnessBucketCount]; + float BrightnessRamp[BrightnessBucketCount + 1]; bgfx::TextureHandle PreviewTex = BGFX_INVALID_HANDLE; bgfx::TextureHandle FinalTex = BGFX_INVALID_HANDLE; - bgfx::UniformHandle Sampler = BGFX_INVALID_HANDLE; + bgfx::TextureHandle RampTex = BGFX_INVALID_HANDLE; + + bgfx::UniformHandle DitherSampler = BGFX_INVALID_HANDLE; + bgfx::UniformHandle RampSampler = BGFX_INVALID_HANDLE; ImTextureID PreviewID = 0; }; @@ -101,6 +105,7 @@ namespace Game uint32_t ResetFlags = BGFX_RESET_VSYNC; uint16_t MainViewID = 10; float LastShaderLoadTime = 0.0f; + int32_t DitherRecursion = 1; public: void Setup(); diff --git a/src/game/shaders/frag.sc b/src/game/shaders/frag.sc index 11b841f..22bdc0e 100644 --- a/src/game/shaders/frag.sc +++ b/src/game/shaders/frag.sc @@ -7,6 +7,7 @@ $input v_wpos SAMPLER2D(s_texColor, 0); SAMPLER3D(s_ditherSampler, 1); +SAMPLER2D(s_rampSampler, 2); uniform vec4 u_time; uniform vec4 u_testColor; @@ -29,19 +30,35 @@ vec3 desaturate(vec3 color) void main() { + // setup + float globalScale = 6.0; float testRadius = 30.0; float testSpeed = 1.0; vec3 testOffset = vec3(0.0, 0.0, 50.0); float3 lightPos = vec3(sin(u_time.x * testSpeed) * testRadius, 5.0, cos(u_time.x * testSpeed) * testRadius); + vec2 inputUv = v_uv0; + vec3 texColor = u_testColor.x > 0.1 ? u_testColor.xyz : texture2D(s_texColor, v_uv0).xyz; + + // lighting // float brightness = calcBrightness(lightPos, v_wpos, v_normal); - float brightness = calcBrightnessDirectional(vec3(0.5, 0.3, 1.0), v_normal); - brightness = 1.0; - // brightness = sin(u_time.x) * 0.5 + 0.5; + float brightness = lerp(0.5, 0.9, calcBrightnessDirectional(vec3(0.5, 0.3, 1.0), v_normal)); + // float brightness = 0.5; + // brightness = lerp(0.2, 1.0, sin(u_time.x) * 0.5 + 0.5); + + // constants + float dotsPerSide = 2; + float dotsTotal = dotsPerSide * dotsPerSide; + float xRes = 32; + float invXRes = 1 / xRes; + float zRes = dotsTotal; + float invZRes = 1 / zRes; + + float2 rampLookupUv = vec2((0.5 * invXRes + (1 - invXRes) * brightness), 0.5); + float brightnessCurve = texture2D(s_rampSampler, rampLookupUv).r; // Magic dot frequency calculation - float baseScale = 8.0; - float2 dx = ddx(v_uv0 * baseScale); - float2 dy = ddy(v_uv0 * baseScale); + float2 dx = ddx(inputUv); + float2 dy = ddy(inputUv); float2x2 mat = float2x2(dx, dy); float4 vectorized = float4(dx, dy); float qq = dot(vectorized, vectorized); @@ -51,23 +68,34 @@ void main() float2 freq = sqrt(float2(qq + discriminant, qq - discriminant) / 2.0); // Figuring out how many dots we want - float spacing = freq.y * exp2(2.0); - spacing = 1.0 / spacing; - spacing *= brightness; // TODO: check reference to see how to calculate this! - float spacingLog = max(log2(spacing), 0.0); + float scaleExp = exp2(globalScale); + float spacing = freq.y * scaleExp; + + float brightnessSpacingMultiplier = pow(brightnessCurve * 2 + 0.001, -(1 - 0.5)); + // float brightnessSpacingMultiplier = 1; + spacing *= brightnessSpacingMultiplier; + + float spacingLog = log2(spacing); int patternScaleLevel = floor(spacingLog); float patternFractional = spacingLog - patternScaleLevel; - vec2 uv = v_uv0 * exp2(patternScaleLevel); - - float dotsTotal = 4; - float subLayer = lerp(0.25 * dotsTotal, dotsTotal, patternFractional); - subLayer = (subLayer - 0.5) / dotsTotal; + vec2 uv = inputUv / exp2(patternScaleLevel); - vec4 circleSample = texture3D(s_ditherSampler, vec3(uv, subLayer)); - float circleVal = circleSample.x < 0.75 ? 0.1 : 0.9; + // patternFractional *= patternFractional; + // patternFractional = smoothstep(0, 1, patternFractional); + float subLayer = lerp(0.25 * dotsTotal, dotsTotal, 1 - patternFractional); + subLayer = (subLayer - 0.5) * invZRes; - // Coloring - vec3 texColor = u_testColor.x > 0.1 ? u_testColor.xyz : texture2D(s_texColor, v_uv0).xyz; - vec3 finalColor = texColor * vec3(circleVal, circleVal, circleVal); + float pattern = texture3D(s_ditherSampler, vec3(uv, subLayer)).r; + + float contrast = 12 * scaleExp * brightnessSpacingMultiplier * 0.1; + contrast *= pow(freq.y / freq.x, 1.0); + float baseVal = lerp(0.5, brightness, saturate(1.05 / (1 + contrast))); + float threshold = 1 - brightnessCurve + 0.6; + + vec3 thresholds = threshold.xxx / texColor; + // vec3 finalColor = saturate((pattern - thresholds) * contrast + baseVal); + vec3 finalColor = saturate((pattern - thresholds) * contrast + baseVal); gl_FragColor = vec4(finalColor, 1.0); + // gl_FragColor = vec4(finalColor * 0.8 + subLayer * 0.2, 1.0); + // gl_FragColor = vec4(finalColor * 0.8 + vec3(uv % 1, 0.0) * 0.2, 1.0); } diff --git a/src/imgui.ini b/src/imgui.ini deleted file mode 100644 index 39ebc3c..0000000 --- a/src/imgui.ini +++ /dev/null @@ -1,21 +0,0 @@ -[Window][WindowOverViewport_11111111] -Pos=0,0 -Size=1920,1080 -Collapsed=0 - -[Window][Rendering] -Pos=1595,0 -Size=325,1080 -Collapsed=0 -DockId=0x00000002,0 - -[Window][Debug##Default] -Pos=60,60 -Size=400,400 -Collapsed=0 - -[Docking][Data] -DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,0 Size=1920,1080 Split=X - DockNode ID=0x00000001 Parent=0x08BD597D SizeRef=1593,1009 CentralNode=1 - DockNode ID=0x00000002 Parent=0x08BD597D SizeRef=325,1009 Selected=0xCEB1220F -