121 lines
3.8 KiB
HLSL
121 lines
3.8 KiB
HLSL
#include "sh/common.hlsl"
|
|
|
|
/* ========================== *
|
|
* Root signature
|
|
* ========================== */
|
|
|
|
#define ROOTSIG \
|
|
"RootConstants(num32BitConstants = 9, b0), " \
|
|
"DescriptorTable(SRV(t0, space = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \
|
|
"DescriptorTable(SRV(t0, space = 1, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \
|
|
"DescriptorTable(UAV(u0, space = 2, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \
|
|
\
|
|
\
|
|
"StaticSampler(s0, " \
|
|
"filter = FILTER_MIN_MAG_MIP_POINT, " \
|
|
"addressU = TEXTURE_ADDRESS_CLAMP, " \
|
|
"addressV = TEXTURE_ADDRESS_CLAMP, " \
|
|
"addressW = TEXTURE_ADDRESS_CLAMP, " \
|
|
"maxAnisotropy = 1)"
|
|
|
|
ConstantBuffer<struct sh_shade_constants> g_constants : register(b0);
|
|
Texture2D<float4> g_gbuff_textures[] : register(t0, space0);
|
|
Texture2D<uint2> g_emittance_flood_textures[] : register(t0, space1);
|
|
RWTexture2D<float4> g_write_textures[]: register(u0, space2);
|
|
|
|
SamplerState g_sampler : register(s0);
|
|
|
|
struct cs_input {
|
|
DECLS(uint3, SV_DispatchThreadID);
|
|
};
|
|
|
|
#define SAMPLES 4
|
|
#define MARCHES 16
|
|
|
|
/* ========================== *
|
|
* Lighting
|
|
* ========================== */
|
|
|
|
#define AMBIENT float4(1, 1, 1, 1)
|
|
|
|
INLINE float4 get_light_in_dir(uint2 ray_start, float2 ray_dir)
|
|
{
|
|
float4 result = AMBIENT;
|
|
float2 at_float = ray_start;
|
|
uint2 at_uint = ray_start;
|
|
for (uint i = 0; i < MARCHES; ++i) {
|
|
uint2 flood = g_emittance_flood_textures[g_constants.emittance_flood_tex_urid][at_uint];
|
|
float2 dist_vec = at_float - (float2)flood;
|
|
float dist = length(dist_vec);
|
|
if (dist <= 1) {
|
|
result = g_gbuff_textures[g_constants.emittance_tex_urid][flood];
|
|
break;
|
|
} else {
|
|
at_float += ray_dir * dist;
|
|
at_uint = round(at_float);
|
|
if (at_uint.x < 0 || at_uint.x >= g_constants.tex_width || at_uint.y < 0 || at_uint.y >= g_constants.tex_height) {
|
|
/* Ambient lighting (ray hit edge of screen) */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
float rand_float_from_float2(float2 pos) {
|
|
return frac(sin(dot(pos.xy, float2(12.9898,78.233))) * 43758.5453123);
|
|
}
|
|
|
|
INLINE float4 get_light_at_pos(uint2 pos)
|
|
{
|
|
float4 result = 0;
|
|
for (int i = 0; i < SAMPLES; ++i) {
|
|
float angle = TAU * (((float)i + rand_float_from_float2(pos + (float)i + sin(g_constants.time))) / ((float)SAMPLES - 1));
|
|
float2 dir = float2(cos(angle), sin(angle));
|
|
float4 light_in_dir = get_light_in_dir(pos, dir);
|
|
result += light_in_dir;
|
|
}
|
|
result /= SAMPLES;
|
|
|
|
return result;
|
|
}
|
|
|
|
/* ========================== *
|
|
* Tone map
|
|
* ========================== */
|
|
|
|
/* ACES approximation by Krzysztof Narkowicz
|
|
* https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ */
|
|
INLINE float3 tone_map(float3 v)
|
|
{
|
|
return saturate((v * (2.51f * v + 0.03f)) / (v * (2.43f * v + 0.59f) + 0.14f));
|
|
}
|
|
|
|
/* ========================== *
|
|
* Entry point
|
|
* ========================== */
|
|
|
|
[numthreads(8, 8, 1)]
|
|
SH_ENTRY(ROOTSIG) void cs(struct cs_input input)
|
|
{
|
|
uint2 id = input.SV_DispatchThreadID.xy;
|
|
if (id.x >= g_constants.tex_width || id.y >= g_constants.tex_height) {
|
|
return; /* Overflow */
|
|
}
|
|
float4 albedo = g_gbuff_textures[g_constants.albedo_tex_urid][id];
|
|
float4 lighting = get_light_at_pos(id);
|
|
|
|
float4 color = albedo * lighting;
|
|
// float4 color = albedo + lighting;
|
|
|
|
/* Tonemap */
|
|
/* TODO: Dynamic exposure based on average scene luminance */
|
|
color *= g_constants.exposure;
|
|
color.rgb = tone_map(color.rgb);
|
|
|
|
/* Gamma correct */
|
|
color = pow(abs(color), 1/g_constants.gamma);
|
|
|
|
g_write_textures[g_constants.write_tex_urid][id] = color;
|
|
}
|