mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 16:36:15 +03:00
216 lines
7.1 KiB
GLSL
216 lines
7.1 KiB
GLSL
#version 460
|
|
|
|
/*
|
|
** Physical based render code, develop by engineer: qiutanguu.
|
|
*/
|
|
|
|
#extension GL_EXT_samplerless_texture_functions : enable
|
|
#extension GL_ARB_separate_shader_objects : enable
|
|
#extension GL_ARB_shading_language_420pack : enable
|
|
#extension GL_ARB_gpu_shader_fp64 : enable
|
|
|
|
layout (set = 0, binding = 0) uniform texture2D inHDRSceneColor;
|
|
layout (set = 0, binding = 1, rgba8) uniform writeonly image2D outLdrColor;
|
|
layout (set = 0, binding = 2) uniform texture2D inBloomTexture;
|
|
layout (set = 0, binding = 3) uniform texture2D inAdaptedLumTex;
|
|
|
|
#define COMMON_SAMPLER_SET 1
|
|
#include "CommonSamplerSet.glsl"
|
|
#include "Common.glsl"
|
|
|
|
layout (set = 2, binding = 0) uniform UniformView { ViewData viewData; };
|
|
layout (set = 3, binding = 0) uniform UniformFrame { FrameData frameData; };
|
|
|
|
// Temporal blue noise jitter is hard to stable resolve. :(
|
|
// Maybe simple blue noise is better.
|
|
#define BLUE_NOISE_TEXTURE_SET 4
|
|
#define BLUE_NOISE_BUFFER_SET 5
|
|
#include "BlueNoiseCommon.glsl"
|
|
#include "Deband16.glsl"
|
|
|
|
layout (push_constant) uniform PushConsts
|
|
{
|
|
vec4 prefilterFactor;
|
|
float bloomIntensity;
|
|
float bloomBlur;
|
|
|
|
float tonemapper_P; // Max brightness.
|
|
float tonemapper_a; // contrast
|
|
float tonemapper_m; // linear section start
|
|
float tonemapper_l; // linear section length
|
|
float tonemapper_c; // black
|
|
float tonemapper_b; // pedestal
|
|
float tonemmaper_s; // scale
|
|
uint bDisplayHDR_rec2020_PQ; // HDR display?
|
|
float saturation;
|
|
};
|
|
|
|
#include "TonemapperFunction.glsl"
|
|
#include "BasicBloomCommon.glsl"
|
|
#include "ColorSpace.glsl"
|
|
|
|
// Gamma curve encode to srgb.
|
|
vec3 encodeSRGB(vec3 linearRGB)
|
|
{
|
|
// Most PC Monitor is 2.2 Gamma, this function is enough.
|
|
return pow(linearRGB, vec3(1.0 / 2.2));
|
|
|
|
// TV encode Rec709 encode.
|
|
vec3 a = 12.92 * linearRGB;
|
|
vec3 b = 1.055 * pow(linearRGB, vec3(1.0 / 2.4)) - 0.055;
|
|
vec3 c = step(vec3(0.0031308), linearRGB);
|
|
return mix(a, b, c);
|
|
}
|
|
|
|
// PQ curve encode to ST2084.
|
|
vec3 encodeST2084(vec3 linearRGB)
|
|
{
|
|
const float m1 = 2610. / 4096. * .25;
|
|
const float m2 = 2523. / 4096. * 128;
|
|
const float c1 = 2392. / 4096. * 32 - 2413. / 4096. * 32 + 1;
|
|
const float c2 = 2413. / 4096. * 32;
|
|
const float c3 = 2392. / 4096. * 32;
|
|
|
|
// Standard encode 10000 nit, same with standard DaVinci Resolve nit.
|
|
float C = 10000.0;
|
|
|
|
vec3 L = linearRGB / C;
|
|
// vec3 L = linearRGB;
|
|
|
|
vec3 Lm = pow(L, vec3(m1));
|
|
vec3 N1 = (c1 + c2 * Lm);
|
|
vec3 N2 = (1.0 + c3 * Lm);
|
|
vec3 N = N1 / N2;
|
|
|
|
vec3 P = pow(N, vec3(m2));
|
|
return P;
|
|
}
|
|
|
|
|
|
|
|
vec3 applySaturationSRGB(vec3 c, float saturation)
|
|
{
|
|
return mix(vec3(lumaSRGB(c)), c, saturation);
|
|
}
|
|
|
|
layout (local_size_x = 8, local_size_y = 8) in;
|
|
void main()
|
|
{
|
|
ivec2 colorSize = imageSize(outLdrColor);
|
|
|
|
uvec2 groupThreadId = remap8x8(gl_LocalInvocationIndex);
|
|
uvec2 dispatchId = groupThreadId + gl_WorkGroupID.xy * 8;
|
|
ivec2 workPos = ivec2(dispatchId);
|
|
|
|
if(workPos.x >= colorSize.x || workPos.y >= colorSize.y)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Compute uv basic on out ldr color.
|
|
const vec2 uv = (vec2(workPos) + vec2(0.5f)) / vec2(colorSize);
|
|
|
|
// load color.
|
|
vec4 hdrColor = texture(sampler2D(inHDRSceneColor, pointClampEdgeSampler), uv);
|
|
|
|
|
|
// Build bloom color.
|
|
vec3 bloomColor = texture(sampler2D(inBloomTexture, linearClampEdgeSampler), uv).rgb;
|
|
|
|
// Auto exposure.
|
|
#if 1
|
|
{
|
|
float adaptiveLum = texelFetch(inAdaptedLumTex, ivec2(0, 0), 0).r;
|
|
hdrColor.xyz *= adaptiveLum, viewData.evCompensation;
|
|
//
|
|
}
|
|
#elif 0
|
|
{
|
|
hdrColor.xyz *= viewData.exposure;
|
|
}
|
|
#endif
|
|
|
|
// Add bloom feed if mix output.
|
|
#if MIX_BLOOM_OUTPUT
|
|
bloomColor += hdrColor.xyz - prefilter(hdrColor.xyz, prefilterFactor);
|
|
#endif
|
|
|
|
|
|
// Bloom composition.
|
|
#if MIX_BLOOM_OUTPUT
|
|
hdrColor.xyz = mix(hdrColor.xyz, bloomColor, bloomIntensity);
|
|
#else
|
|
hdrColor.xyz += bloomColor * bloomIntensity;
|
|
#endif
|
|
|
|
// Linear srgb color space.
|
|
vec3 colorSrgb = max(hdrColor.xyz, vec3(0.0));
|
|
|
|
|
|
|
|
// TODO: Maybe use ACES color space in the future. then we can do some hdr color gradient in aces color space.
|
|
//
|
|
|
|
const bool bSrgb = bDisplayHDR_rec2020_PQ == 0;
|
|
|
|
const float P = bSrgb ? min(1.0, tonemapper_P) : tonemapper_P; // max display brightness.
|
|
const float a = tonemapper_a; // contrast
|
|
const float m = tonemapper_m; // linear section start
|
|
const float l = tonemapper_l; // linear section length
|
|
const float c = tonemapper_c; // black
|
|
const float b = tonemapper_b; // pedestal
|
|
|
|
// Tonemapper in srgb color space.
|
|
colorSrgb.x = uchimuraTonemapper(colorSrgb.x, P, a, m, l, c, b);
|
|
colorSrgb.y = uchimuraTonemapper(colorSrgb.y, P, a, m, l, c, b);
|
|
colorSrgb.z = uchimuraTonemapper(colorSrgb.z, P, a, m, l, c, b);
|
|
|
|
// apply saturation in srgb space.
|
|
colorSrgb = applySaturationSRGB(colorSrgb, saturation);
|
|
|
|
vec3 mappingColor;
|
|
if(bSrgb) // Gamma encode srgb
|
|
{
|
|
// OETF = gamma(1.0/2.2)
|
|
mappingColor.xyz = encodeSRGB(colorSrgb.xyz);
|
|
}
|
|
else // PQ encode BT2020.
|
|
{
|
|
// Scale factor for converting pixel values to nits.
|
|
// This value is required for PQ (ST2084) conversions, because PQ linear values are in nits.
|
|
// The purpose is to make good use of PQ lut entries. A scale factor of 100 conveniently places
|
|
// about half of the PQ lut indexing below 1.0, with the other half for input values over 1.0.
|
|
// Also, 100nits is the expected monitor brightness for a 1.0 pixel value without a tone curve.
|
|
const float LinearToNitsScale = 100.0 * tonemmaper_s;
|
|
const float LinearToNitsScaleInverse = 1.0 / LinearToNitsScale;
|
|
|
|
vec3 colorRec2020 = sRGB_2_Rec2020 * colorSrgb;
|
|
//
|
|
// OETF = inverse pq
|
|
mappingColor.xyz = encodeST2084(colorRec2020.xyz * LinearToNitsScale);
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Need jitter in R11G10B11 when in HDR display mode, but current looks good, so just use blue noise 8bit jitter.
|
|
// mappingColor.xyz = quantise(mappingColor.xyz, vec2(workPos), frameData);
|
|
|
|
// Offset retarget for new seeds each frame
|
|
uvec2 offset = uvec2(vec2(0.754877669, 0.569840296) * frameData.frameIndex.x * uvec2(colorSize));
|
|
uvec2 offsetId = dispatchId.xy + offset;
|
|
offsetId.x = offsetId.x % colorSize.x;
|
|
offsetId.y = offsetId.y % colorSize.y;
|
|
|
|
// Display is 8bit, so jitter with blue noise with [-1, 1] / 255.0.
|
|
// Current also looks good in hdr display even it under 11bit.
|
|
mappingColor.x += 1.0 / 255.0 * (-1.0 + 2.0 * samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d(offsetId.x, offsetId.y, 0, 0u));
|
|
mappingColor.y += 1.0 / 255.0 * (-1.0 + 2.0 * samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d(offsetId.x, offsetId.y, 0, 1u));
|
|
mappingColor.z += 1.0 / 255.0 * (-1.0 + 2.0 * samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d(offsetId.x, offsetId.y, 0, 2u));
|
|
|
|
mappingColor.xyz = max(mappingColor.xyz, vec3(0.0));
|
|
imageStore(outLdrColor, workPos, vec4(mappingColor, 1.0));
|
|
}
|
|
|
|
// NOTE: if want to output hdr to DaVinci Resolve.
|
|
// you need to add one ACES tonemapper fx, and input transform is ST2048. ouput tramsform is Rec709. |