power_play/res/sh/shade.hlsl

118 lines
3.9 KiB
HLSL

#include "sh/common.hlsl"
/* ========================== *
* Root signature
* ========================== */
#define ROOTSIG \
"RootConstants(num32BitConstants = 16, b0), " \
"DescriptorTable(SRV(t0, space = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \
"DescriptorTable(SRV(t0, space = 1, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \
"DescriptorTable(SRV(t0, space = 2, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \
"DescriptorTable(UAV(u0, space = 3, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), "
ConstantBuffer<struct sh_shade_constants> g_constants : register(b0);
Texture2D<float4> g_textures_float4[] : register(t0, space0);
Texture2D<uint2> g_textures_uint2[] : register(t0, space1);
Texture3D<uint> g_noise_textures[] : register(t0, space2);
RWTexture2D<float4> g_target_textures[]: register(u0, space3);
struct cs_input {
DECLS(uint3, SV_DispatchThreadID);
};
/* ========================== *
* Lighting
* ========================== */
#define SAMPLES 16
#define MARCHES 16
#define AMBIENT float3(0, 0, 0)
float rand_angle(uint2 pos, uint ray_index) {
Texture3D<uint> noise_tex = g_noise_textures[SH_BLUE_NOISE_TEX_ID];
int3 noise_coord = int3(1, 1, 1);
noise_coord += int3(pos.xy, ray_index);
// noise_coord.xyz += g_constants.frame_seed.xyz;
noise_coord.xy -= g_constants.camera_offset;
uint noise = noise_tex[noise_coord % uint3(SH_BLUE_NOISE_TEX_WIDTH, SH_BLUE_NOISE_TEX_HEIGHT, SH_BLUE_NOISE_TEX_DEPTH)];
return ((float)noise / (float)0xFFFF) * TAU;
}
INLINE float3 get_light_in_dir(uint2 ray_start, float2 ray_dir)
{
Texture2D<uint2> flood_tex = g_textures_uint2[g_constants.emittance_flood_tex_urid];
Texture2D<float4> emittance_tex = g_textures_float4[g_constants.emittance_tex_urid];
float3 result = AMBIENT;
float2 at_float = ray_start;
uint2 at_uint = ray_start;
for (uint i = 0; i < MARCHES; ++i) {
uint2 flood = flood_tex[at_uint];
float2 dist_vec = at_float - (float2)flood;
float dist = length(dist_vec);
if (dist < 1) {
result = emittance_tex[flood].rgb;
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;
}
INLINE float3 get_light_at_pos(uint2 pos)
{
float3 result = 0;
for (uint i = 0; i < SAMPLES; ++i) {
float angle = rand_angle(pos, i);
float2 dir = float2(cos(angle), sin(angle));
float3 light_in_dir = get_light_in_dir(pos, dir);
result += light_in_dir;
}
result /= SAMPLES;
return result;
}
/* ========================== *
* 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) {
Texture2D<float4> albedo_tex = g_textures_float4[g_constants.albedo_tex_urid];
Texture2D<float4> read_tex = g_textures_float4[g_constants.read_tex_urid];
RWTexture2D<float4> target_tex = g_target_textures[g_constants.target_tex_urid];
float4 color = float4(1, 1, 1, 1);
/* Apply albedo */
color *= albedo_tex[id];
/* Apply lighting */
if (g_constants.flags & SH_SHADE_FLAG_LIGHTING_ENABLED) {
color.rgb *= get_light_at_pos(id);
}
/* Apply temporal accumulation */
float hysterisis = 0;
// hysterisis = 0.2;
// hysterisis = 0.4;
// hysterisis = 0.5;
// hysterisis = 0.9;
color.rgb = lerp(color.rgb, read_tex[id].rgb, hysterisis);
target_tex[id] = color;
}
}