Skip to content

Commit

Permalink
Alternate hash function using pcg3d
Browse files Browse the repository at this point in the history
  • Loading branch information
a-e-k committed Jul 23, 2024
1 parent 9ec1d89 commit 4258fec
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 28 deletions.
11 changes: 8 additions & 3 deletions src/ImageCanvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,9 +560,14 @@ Vector3f ImageCanvas::applyTonemap(const Vector3f& value, float gamma, ETonemap
}
case ETonemap::Hash:
{
static const auto fract = [](float x){ return x - floor(x); };
Vector3f mixed = abs(fract(dot(value, Vector3f{115.191742f, 64.0546951f, 124.512291f})) - 0.5f) * Vector3f{1368.46143f, 1523.2019f, 1034.50476f};
result = {2.0f * abs(fract(mixed.x()) - 0.5f), 2.0f * abs(fract(mixed.y()) - 0.5f), 2.0f * abs(fract(mixed.z()) - 0.5f)};
// See 'Hash Functions for GPU Rendering' (https://jcgt.org/published/0009/03/02/)
uint32_t vX = std::bit_cast<uint32_t>(value.x()) * 1664525u + 1013904223u;
uint32_t vY = std::bit_cast<uint32_t>(value.y()) * 1664525u + 1013904223u;
uint32_t vZ = std::bit_cast<uint32_t>(value.z()) * 1664525u + 1013904223u;
vX += vY * vZ; vY += vZ * vX; vZ += vX * vY;
vX ^= vX >> 16u; vY ^= vY >> 16u; vZ ^= vZ >> 16u;
vX += vY * vZ; vY += vZ * vX; vZ += vX * vY;
result = {vX * (1.0f / 4294967295.0f), vY * (1.0f / 4294967295.0f), vZ * (1.0f / 4294967295.0f)};
break;
}
default:
Expand Down
70 changes: 45 additions & 25 deletions src/UberShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ UberShader::UberShader(RenderPass* renderPass) {
#if defined(NANOGUI_USE_OPENGL) || defined(NANOGUI_USE_GLES)
# if defined(NANOGUI_USE_OPENGL)
std::string preamble =
R"(#version 110)";
R"(#version 330)";
# elif defined(NANOGUI_USE_GLES)
std::string preamble =
R"(#version 100
precision highp float;)";
R"(#version 300 es
precision highp float;
precision highp int;)";
# endif
auto vertexShader = preamble +
R"glsl(
Expand All @@ -31,11 +32,11 @@ UberShader::UberShader(RenderPass* renderPass) {
uniform vec2 referenceScale;
uniform vec2 referenceOffset;
attribute vec2 position;
in vec2 position;
varying vec2 checkerUv;
varying vec2 imageUv;
varying vec2 referenceUv;
out vec2 checkerUv;
out vec2 imageUv;
out vec2 referenceUv;
void main() {
checkerUv = position / (pixelSize * checkerSize);
Expand Down Expand Up @@ -79,9 +80,11 @@ UberShader::UberShader(RenderPass* renderPass) {
uniform vec4 bgColor;
varying vec2 checkerUv;
varying vec2 imageUv;
varying vec2 referenceUv;
in vec2 checkerUv;
in vec2 imageUv;
in vec2 referenceUv;
layout(location = 0) out vec4 fragColor;
float average(vec3 col) {
return (col.r + col.g + col.b) / 3.0;
Expand Down Expand Up @@ -118,8 +121,19 @@ UberShader::UberShader(RenderPass* renderPass) {
}
}
vec3 hash(vec3 co){
return 2.0 * abs(fract(abs(fract(dot(co, vec3(115.191742, 64.0546951, 124.512291))) - 0.5) * vec3(1368.46143, 1523.2019, 1034.50476)) - 0.5);
vec3 hash(vec3 col) {
uvec3 v = floatBitsToUint(col);
// See 'Hash Functions for GPU Rendering' (https://jcgt.org/published/0009/03/02/)
// pcg3d is MIT licensed (https://github.com/markjarzynski/PCG3D/commit/684c5da):
// Copyright 2020 Mark Jarzynski & Marc Olano
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
v = v * 1664525u + 1013904223u;
v.x += v.y * v.z; v.y += v.z * v.x; v.z += v.x * v.y;
v ^= v >> 16u;
v.x += v.y * v.z; v.y += v.z * v.x; v.z += v.x * v.y;
return vec3(v) * vec3(1.0 / 4294967295.0);
}
vec3 applyTonemap(vec3 col, vec4 background) {
Expand Down Expand Up @@ -155,7 +169,7 @@ UberShader::UberShader(RenderPass* renderPass) {
return vec3(0.0);
}
vec4 sample(sampler2D sampler, vec2 uv) {
vec4 sampleImage(sampler2D sampler, vec2 uv) {
vec4 color = texture2D(sampler, uv);
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
color = vec4(0.0);
Expand All @@ -170,35 +184,35 @@ UberShader::UberShader(RenderPass* renderPass) {
vec3 checker = abs(mod(floor(checkerUv.x) + floor(checkerUv.y), 2.0)) < 0.5 ? darkGray : lightGray;
checker = bgColor.rgb * bgColor.a + checker * (1.0 - bgColor.a);
if (!hasImage) {
gl_FragColor = vec4(checker, 1.0);
fragColor = vec4(checker, 1.0);
return;
}
float cropAlpha =
imageUv.x < cropMin.x || imageUv.x > cropMax.x || imageUv.y < cropMin.y || imageUv.y > cropMax.y ? 0.3 : 1.0;
vec4 imageVal = sample(image, imageUv);
vec4 imageVal = sampleImage(image, imageUv);
imageVal.a *= cropAlpha;
if (!hasReference) {
gl_FragColor = vec4(
fragColor = vec4(
applyTonemap(applyExposureAndOffset(imageVal.rgb), vec4(checker, 1.0 - imageVal.a)),
1.0
);
gl_FragColor.rgb = clamp(gl_FragColor.rgb, clipToLdr ? 0.0 : -64.0, clipToLdr ? 1.0 : 64.0);
fragColor.rgb = clamp(fragColor.rgb, clipToLdr ? 0.0 : -64.0, clipToLdr ? 1.0 : 64.0);
return;
}
vec4 referenceVal = sample(reference, referenceUv);
vec4 referenceVal = sampleImage(reference, referenceUv);
referenceVal.a *= cropAlpha;
vec3 difference = imageVal.rgb - referenceVal.rgb;
float alpha = (imageVal.a + referenceVal.a) * 0.5;
gl_FragColor = vec4(
fragColor = vec4(
applyTonemap(applyExposureAndOffset(applyMetric(difference, referenceVal.rgb)), vec4(checker, 1.0 - alpha)),
1.0
);
gl_FragColor.rgb = clamp(gl_FragColor.rgb, clipToLdr ? 0.0 : -64.0, clipToLdr ? 1.0 : 64.0);
fragColor.rgb = clamp(fragColor.rgb, clipToLdr ? 0.0 : -64.0, clipToLdr ? 1.0 : 64.0);
})glsl";
#elif defined(NANOGUI_USE_METAL)
auto vertexShader =
Expand Down Expand Up @@ -280,8 +294,14 @@ UberShader::UberShader(RenderPass* renderPass) {
}
}
float3 hash(float3 co){
return 2.0f * abs(fract(abs(fract(dot(co.xyz, float3(115.191742f, 64.0546951f, 124.512291f))) - 0.5f) * float3(1368.46143f, 1523.2019f, 1034.50476f)) - 0.5f);
float3 hash(float3 col) {
uint3 v = as_type<uint3>(col);
// See 'Hash Functions for GPU Rendering' (https://jcgt.org/published/0009/03/02/)
v = v * 1664525u + 1013904223u;
v.x += v.y * v.z; v.y += v.z * v.x; v.z += v.x * v.y;
v ^= v >> 16u;
v.x += v.y * v.z; v.y += v.z * v.x; v.z += v.x * v.y;
return float3(v) * float3(1.0f / 4294967295.0f);
}
float3 applyTonemap(float3 col, float4 background, int tonemap, float offset, float gamma, texture2d<float, access::sample> colormap, sampler colormapSampler) {
Expand Down Expand Up @@ -315,7 +335,7 @@ UberShader::UberShader(RenderPass* renderPass) {
return float3(0.0f);
}
float4 sample(texture2d<float, access::sample> texture, sampler textureSampler, float2 uv) {
float4 sampleImage(texture2d<float, access::sample> texture, sampler textureSampler, float2 uv) {
float4 color = texture.sample(textureSampler, uv);
if (uv.x < 0.0f || uv.x > 1.0f || uv.y < 0.0f || uv.y > 1.0f) {
return float4(0.0f);
Expand Down Expand Up @@ -361,7 +381,7 @@ UberShader::UberShader(RenderPass* renderPass) {
float cropAlpha = vert.imageUv.x < cropMin.x || vert.imageUv.x > cropMax.x || vert.imageUv.y < cropMin.y || vert.imageUv.y > cropMax.y ? 0.3f : 1.0f;
float4 imageVal = sample(image, image_sampler, vert.imageUv);
float4 imageVal = sampleImage(image, image_sampler, vert.imageUv);
imageVal.a *= cropAlpha;
if (!hasReference) {
float4 color = float4(
Expand All @@ -380,7 +400,7 @@ UberShader::UberShader(RenderPass* renderPass) {
return color;
}
float4 referenceVal = sample(reference, reference_sampler, vert.referenceUv);
float4 referenceVal = sampleImage(reference, reference_sampler, vert.referenceUv);
referenceVal.a *= cropAlpha;
float3 difference = imageVal.rgb - referenceVal.rgb;
Expand Down

0 comments on commit 4258fec

Please sign in to comment.