e5d6a5a22b
* add denoise example /* * Implement SVGF style denoising as bgfx example. Goal is to explore various * options and parameters, not produce an optimized, efficient denoiser. * * Starts with deferred rendering scene with very basic lighting. Lighting is * masked out with a noise pattern to provide something to denoise. There are * two options for the noise pattern. One is a fixed 2x2 dither pattern to * stand-in for lighting at quarter resolution. The other is the common * shadertoy random pattern as a stand-in for some fancier lighting without * enough samples per pixel, like ray tracing. * * First a temporal denoising filter is applied. The temporal filter is only * using normals to reject previous samples. The SVGF paper also describes using * depth comparison to reject samples but that is not implemented here. * * Followed by some number of spatial filters. These are implemented like in the * SVGF paper. As an alternative to the 5x5 Edge-Avoiding A-Trous filter, can * select a 3x3 filter instead. The 3x3 filter takes fewer samples and covers a * smaller area, but takes less time to compute. From a loosely eyeballed * comparison, N 5x5 passes looks similar to N+1 3x3 passes. The wider spatial * filters take a fair chunk of time to compute. I wonder if it would be a good * idea to interleave the input texture before computing, after the first pass * which skips zero pixels. * * I have not implemetened the variance guided part. * * There's also an optional TXAA pass to be applied after. I am not happy with * its implementation yet, so it defaults to off here. */ /* * References: * Spatiotemporal Variance-Guided Filtering: Real-Time Reconstruction for * Path-Traced Global Illumination. by Christoph Schied and more. * - SVGF denoising algorithm * * Streaming G-Buffer Compression for Multi-Sample Anti-Aliasing. * by E. Kerzner and M. Salvi. * - details about history comparison for temporal denoising filter * * Edge-Avoiding À-Trous Wavelet Transform for Fast Global Illumination * Filtering. by Holger Dammertz and more. * - details about a-trous algorithm for spatial denoising filter */ * screen space shadows sample implement screen space shadows. requires deferred rendering or a depth prepass. convert rendered depth to linear depth to skip reconstructing multiple times when doing shadow test. project light into screen space to find direction from each pixel to the light. walk through screen space texture towards light. sample depth to reconstruct position represented by this sample pixel and compare to position along interpolated ray from pixel to light. if position represented by depth is closer to the eye than the light ray, an initial pixel is in shadow. specify distance of shadow ray via world units or pixels in screen space. optionally offset the initial sample position by noise to reduce banding. demonstrate other ways to reduce hard edge of screen space shadow. * clean out denoise sample for pull request... * rename folder to 44- add missing file
84 lines
2.0 KiB
Scala
84 lines
2.0 KiB
Scala
$input v_texcoord0
|
|
|
|
/*
|
|
* Copyright 2021 elven cache. All rights reserved.
|
|
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
|
|
*/
|
|
|
|
#include "../common/common.sh"
|
|
#include "parameters.sh"
|
|
#include "normal_encoding.sh"
|
|
|
|
SAMPLER2D(s_color, 0);
|
|
SAMPLER2D(s_normal, 1);
|
|
SAMPLER2D(s_depth, 2);
|
|
SAMPLER2D(s_shadows, 3);
|
|
|
|
// from assao sample, cs_assao_prepare_depths.sc
|
|
vec3 NDCToViewspace( vec2 pos, float viewspaceDepth )
|
|
{
|
|
vec3 ret;
|
|
|
|
ret.xy = (u_ndcToViewMul * pos.xy + u_ndcToViewAdd) * viewspaceDepth;
|
|
|
|
ret.z = viewspaceDepth;
|
|
|
|
return ret;
|
|
}
|
|
|
|
void main()
|
|
{
|
|
vec2 texCoord = v_texcoord0;
|
|
|
|
vec4 colorId = texture2D(s_color, texCoord);
|
|
vec3 color = toLinear(colorId.xyz);
|
|
float materialId = colorId.w;
|
|
|
|
if (0.0 < materialId)
|
|
{
|
|
vec4 normalRoughness = texture2D(s_normal, texCoord);
|
|
vec3 normal = NormalDecode(normalRoughness.xyz);
|
|
float roughness = normalRoughness.w;
|
|
|
|
// transform normal into view space
|
|
mat4 worldToView = mat4(
|
|
u_worldToView0,
|
|
u_worldToView1,
|
|
u_worldToView2,
|
|
u_worldToView3
|
|
);
|
|
vec3 vsNormal = instMul(worldToView, vec4(normal, 0.0)).xyz;
|
|
|
|
// read depth and recreate position
|
|
float linearDepth = texture2D(s_depth, texCoord).x;
|
|
vec3 viewSpacePosition = NDCToViewspace(texCoord, linearDepth);
|
|
|
|
float shadow = texture2D(s_shadows, texCoord).x;
|
|
|
|
// need to get a valid view vector for any microfacet stuff :(
|
|
float gloss = 1.0-roughness;
|
|
float specPower = 62.0 * gloss + 2.0;
|
|
|
|
vec3 light = (u_lightPosition - viewSpacePosition);
|
|
float lightDistSq = dot(light, light) + 1e-5;
|
|
light = normalize(light);
|
|
float NdotL = saturate(dot(vsNormal, light));
|
|
float diffuse = NdotL * (1.0/lightDistSq);
|
|
float specular = 5.0 * pow(NdotL, specPower);
|
|
|
|
float lightAmount = mix(diffuse, specular, 0.04) * shadow;
|
|
|
|
color = (color * lightAmount);
|
|
color = toGamma(color);
|
|
|
|
// debug display shadows only
|
|
if (0.0 < u_displayShadows)
|
|
{
|
|
color = vec3_splat(shadow);
|
|
}
|
|
}
|
|
// else, assume color is unlit
|
|
|
|
gl_FragColor = vec4(color, 1.0);
|
|
}
|