magical new dots
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
# assets
|
# assets
|
||||||
*.blend1
|
*.blend1
|
||||||
tools/remedy-session.rdbg
|
tools/remedy-session.rdbg
|
||||||
|
src/imgui.ini
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ namespace Game
|
|||||||
float TimeValues[4]{0.0f};
|
float TimeValues[4]{0.0f};
|
||||||
TimeValues[0] = GetInstance().Time.Now;
|
TimeValues[0] = GetInstance().Time.Now;
|
||||||
bgfx::setTexture(0, currentMaterial.Textures[0].SamplerHandle, currentMaterial.Textures[0].Handle);
|
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::UTime], TimeValues);
|
||||||
bgfx::setUniform(currentMaterial.Uniforms[Material::UDotColor], TestColor);
|
bgfx::setUniform(currentMaterial.Uniforms[Material::UDotColor], TestColor);
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -193,16 +193,17 @@ namespace Game
|
|||||||
return handle;
|
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[0] = {0.0f, 0.0f};
|
||||||
data.Points[1] = {0.5f, 0.5f};
|
data.Points[1] = {0.5f, 0.5f};
|
||||||
data.Points[2] = {0.5f, 0.0f};
|
data.Points[2] = {0.5f, 0.0f};
|
||||||
data.Points[3] = {0.0f, 0.5f};
|
data.Points[3] = {0.0f, 0.5f};
|
||||||
data.PointCount = 4;
|
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;
|
int32_t startCount = data.PointCount;
|
||||||
float offset = bx::pow(0.5f, recursionLevel + 1);
|
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.DitherTexDepth = dotsPerSide * dotsPerSide;
|
||||||
data.DitherTexWH = 16 * dotsPerSide;
|
data.DitherTexWH = 16 * dotsPerSide;
|
||||||
uint64_t texPixelCount = data.DitherTexWH * data.DitherTexWH * data.DitherTexDepth;
|
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),
|
int32_t bucket = bx::clamp(uint32_t(val * DitherData::BrightnessBucketCount),
|
||||||
0,
|
0,
|
||||||
DitherData::BrightnessBucketCount - 1);
|
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))
|
if (isValid(data.PreviewTex))
|
||||||
{
|
{
|
||||||
bgfx::destroy(data.PreviewTex);
|
bgfx::destroy(data.PreviewTex);
|
||||||
@@ -273,8 +282,14 @@ namespace Game
|
|||||||
bgfx::destroy(data.FinalTex);
|
bgfx::destroy(data.FinalTex);
|
||||||
data.FinalTex = BGFX_INVALID_HANDLE;
|
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* memPreview = bgfx::makeRef(data.DitherTex, texPixelCount * sizeof(Vec4));
|
||||||
const bgfx::Memory* memFinal = 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.PreviewTex = bgfx::createTexture2D(data.DitherTexWH,
|
||||||
data.DitherTexWH * data.DitherTexDepth,
|
data.DitherTexWH * data.DitherTexDepth,
|
||||||
false,
|
false,
|
||||||
@@ -289,10 +304,16 @@ namespace Game
|
|||||||
bgfx::TextureFormat::RGBA32F,
|
bgfx::TextureFormat::RGBA32F,
|
||||||
0,
|
0,
|
||||||
memFinal);
|
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");
|
ImGui::LoadIniSettingsFromDisk("imgui.ini");
|
||||||
}
|
}
|
||||||
DitherGen(DitherTextures);
|
DitherGen(DitherTextures, DitherRecursion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRendering::Update()
|
void GameRendering::Update()
|
||||||
@@ -460,8 +481,10 @@ namespace Game
|
|||||||
}
|
}
|
||||||
if (ImGui::Button("Dithergen"))
|
if (ImGui::Button("Dithergen"))
|
||||||
{
|
{
|
||||||
DitherGen(DitherTextures);
|
DitherGen(DitherTextures, DitherRecursion);
|
||||||
}
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SliderInt("Recursion", &DitherRecursion, 1, 4);
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%ux%ux%u", DitherTextures.DitherTexWH, DitherTextures.DitherTexWH, DitherTextures.DitherTexDepth);
|
"%ux%ux%u", DitherTextures.DitherTexWH, DitherTextures.DitherTexWH, DitherTextures.DitherTexDepth);
|
||||||
if (!isValid(DitherTextures.PreviewTex))
|
if (!isValid(DitherTextures.PreviewTex))
|
||||||
@@ -474,10 +497,9 @@ namespace Game
|
|||||||
{(float)DitherTextures.DitherTexWH,
|
{(float)DitherTextures.DitherTexWH,
|
||||||
(float)DitherTextures.DitherTexWH * DitherTextures.DitherTexDepth});
|
(float)DitherTextures.DitherTexWH * DitherTextures.DitherTexDepth});
|
||||||
}
|
}
|
||||||
ImGui::Text("Brightness Buckets (TODO)");
|
if (isValid(DitherTextures.RampTex))
|
||||||
for (int32_t i = 0; i < DitherTextures.BrightnessBucketCount; ++i)
|
|
||||||
{
|
{
|
||||||
ImGui::Text("%u", DitherTextures.BrightnessBuckets[i]);
|
ImGui::Image(DitherTextures.RampTex.idx, {BX_COUNTOF(DitherTextures.BrightnessRamp), 1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|||||||
@@ -74,9 +74,13 @@ namespace Game
|
|||||||
uint32_t DitherTexWH = 0;
|
uint32_t DitherTexWH = 0;
|
||||||
uint32_t DitherTexDepth = 0;
|
uint32_t DitherTexDepth = 0;
|
||||||
int32_t BrightnessBuckets[BrightnessBucketCount];
|
int32_t BrightnessBuckets[BrightnessBucketCount];
|
||||||
|
float BrightnessRamp[BrightnessBucketCount + 1];
|
||||||
bgfx::TextureHandle PreviewTex = BGFX_INVALID_HANDLE;
|
bgfx::TextureHandle PreviewTex = BGFX_INVALID_HANDLE;
|
||||||
bgfx::TextureHandle FinalTex = 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;
|
ImTextureID PreviewID = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -101,6 +105,7 @@ namespace Game
|
|||||||
uint32_t ResetFlags = BGFX_RESET_VSYNC;
|
uint32_t ResetFlags = BGFX_RESET_VSYNC;
|
||||||
uint16_t MainViewID = 10;
|
uint16_t MainViewID = 10;
|
||||||
float LastShaderLoadTime = 0.0f;
|
float LastShaderLoadTime = 0.0f;
|
||||||
|
int32_t DitherRecursion = 1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Setup();
|
void Setup();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ $input v_wpos
|
|||||||
|
|
||||||
SAMPLER2D(s_texColor, 0);
|
SAMPLER2D(s_texColor, 0);
|
||||||
SAMPLER3D(s_ditherSampler, 1);
|
SAMPLER3D(s_ditherSampler, 1);
|
||||||
|
SAMPLER2D(s_rampSampler, 2);
|
||||||
uniform vec4 u_time;
|
uniform vec4 u_time;
|
||||||
uniform vec4 u_testColor;
|
uniform vec4 u_testColor;
|
||||||
|
|
||||||
@@ -29,19 +30,35 @@ vec3 desaturate(vec3 color)
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
// setup
|
||||||
|
float globalScale = 6.0;
|
||||||
float testRadius = 30.0;
|
float testRadius = 30.0;
|
||||||
float testSpeed = 1.0;
|
float testSpeed = 1.0;
|
||||||
vec3 testOffset = vec3(0.0, 0.0, 50.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);
|
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 = calcBrightness(lightPos, v_wpos, v_normal);
|
||||||
float brightness = calcBrightnessDirectional(vec3(0.5, 0.3, 1.0), v_normal);
|
float brightness = lerp(0.5, 0.9, calcBrightnessDirectional(vec3(0.5, 0.3, 1.0), v_normal));
|
||||||
brightness = 1.0;
|
// float brightness = 0.5;
|
||||||
// brightness = sin(u_time.x) * 0.5 + 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
|
// Magic dot frequency calculation
|
||||||
float baseScale = 8.0;
|
float2 dx = ddx(inputUv);
|
||||||
float2 dx = ddx(v_uv0 * baseScale);
|
float2 dy = ddy(inputUv);
|
||||||
float2 dy = ddy(v_uv0 * baseScale);
|
|
||||||
float2x2 mat = float2x2(dx, dy);
|
float2x2 mat = float2x2(dx, dy);
|
||||||
float4 vectorized = float4(dx, dy);
|
float4 vectorized = float4(dx, dy);
|
||||||
float qq = dot(vectorized, vectorized);
|
float qq = dot(vectorized, vectorized);
|
||||||
@@ -51,23 +68,34 @@ void main()
|
|||||||
float2 freq = sqrt(float2(qq + discriminant, qq - discriminant) / 2.0);
|
float2 freq = sqrt(float2(qq + discriminant, qq - discriminant) / 2.0);
|
||||||
|
|
||||||
// Figuring out how many dots we want
|
// Figuring out how many dots we want
|
||||||
float spacing = freq.y * exp2(2.0);
|
float scaleExp = exp2(globalScale);
|
||||||
spacing = 1.0 / spacing;
|
float spacing = freq.y * scaleExp;
|
||||||
spacing *= brightness; // TODO: check reference to see how to calculate this!
|
|
||||||
float spacingLog = max(log2(spacing), 0.0);
|
float brightnessSpacingMultiplier = pow(brightnessCurve * 2 + 0.001, -(1 - 0.5));
|
||||||
|
// float brightnessSpacingMultiplier = 1;
|
||||||
|
spacing *= brightnessSpacingMultiplier;
|
||||||
|
|
||||||
|
float spacingLog = log2(spacing);
|
||||||
int patternScaleLevel = floor(spacingLog);
|
int patternScaleLevel = floor(spacingLog);
|
||||||
float patternFractional = spacingLog - patternScaleLevel;
|
float patternFractional = spacingLog - patternScaleLevel;
|
||||||
vec2 uv = v_uv0 * exp2(patternScaleLevel);
|
vec2 uv = inputUv / exp2(patternScaleLevel);
|
||||||
|
|
||||||
float dotsTotal = 4;
|
|
||||||
float subLayer = lerp(0.25 * dotsTotal, dotsTotal, patternFractional);
|
|
||||||
subLayer = (subLayer - 0.5) / dotsTotal;
|
|
||||||
|
|
||||||
vec4 circleSample = texture3D(s_ditherSampler, vec3(uv, subLayer));
|
// patternFractional *= patternFractional;
|
||||||
float circleVal = circleSample.x < 0.75 ? 0.1 : 0.9;
|
// patternFractional = smoothstep(0, 1, patternFractional);
|
||||||
|
float subLayer = lerp(0.25 * dotsTotal, dotsTotal, 1 - patternFractional);
|
||||||
|
subLayer = (subLayer - 0.5) * invZRes;
|
||||||
|
|
||||||
// Coloring
|
float pattern = texture3D(s_ditherSampler, vec3(uv, subLayer)).r;
|
||||||
vec3 texColor = u_testColor.x > 0.1 ? u_testColor.xyz : texture2D(s_texColor, v_uv0).xyz;
|
|
||||||
vec3 finalColor = texColor * vec3(circleVal, circleVal, circleVal);
|
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, 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user