include shader files in project

This commit is contained in:
WLs50
2025-04-05 12:00:20 +02:00
parent 0882652b2a
commit 671b674f36
30 changed files with 1894 additions and 0 deletions

4
manul/shaders/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
*
!*.hlsl*
!project.manul

View File

@@ -0,0 +1,149 @@
Texture2D<float> g_DepthTexture : register(t0);
RWTexture2D<float> g_Output : register(u0);
sampler g_SamplerLinearClamp : register(s0);
// From https://www.shadertoy.com/view/3tB3z3 - except we're using R2 here
#define XE_HILBERT_LEVEL 6U
#define XE_HILBERT_WIDTH ( (1U << XE_HILBERT_LEVEL) )
#define XE_HILBERT_AREA ( XE_HILBERT_WIDTH * XE_HILBERT_WIDTH )
inline uint HilbertIndex( uint posX, uint posY )
{
uint index = 0U;
for( uint curLevel = XE_HILBERT_WIDTH/2U; curLevel > 0U; curLevel /= 2U )
{
uint regionX = ( posX & curLevel ) > 0U;
uint regionY = ( posY & curLevel ) > 0U;
index += curLevel * curLevel * ( (3U * regionX) ^ regionY);
if( regionY == 0U )
{
if( regionX == 1U )
{
posX = uint( (XE_HILBERT_WIDTH - 1U) ) - posX;
posY = uint( (XE_HILBERT_WIDTH - 1U) ) - posY;
}
uint temp = posX;
posX = posY;
posY = temp;
}
}
return index;
}
// Engine-specific screen & temporal noise loader
float2 SpatioTemporalNoise( uint2 pixCoord, uint temporalIndex ) // without TAA, temporalIndex is always 0
{
float2 noise;
#if 1 // Hilbert curve driving R2 (see https://www.shadertoy.com/view/3tB3z3)
#ifdef XE_GTAO_HILBERT_LUT_AVAILABLE // load from lookup texture...
uint index = g_srcHilbertLUT.Load( uint3( pixCoord % 64, 0 ) ).x;
#else // ...or generate in-place?
uint index = HilbertIndex( pixCoord.x, pixCoord.y );
#endif
index += 288*(temporalIndex%64); // why 288? tried out a few and that's the best so far (with XE_HILBERT_LEVEL 6U) - but there's probably better :)
// R2 sequence - see http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/
return float2( frac( 0.5 + index * float2(0.75487766624669276005, 0.5698402909980532659114) ) );
#else // Pseudo-random (fastest but looks bad - not a good choice)
uint baseHash = Hash32( pixCoord.x + (pixCoord.y << 15) );
baseHash = Hash32Combine( baseHash, temporalIndex );
return float2( Hash32ToFloat( baseHash ), Hash32ToFloat( Hash32( baseHash ) ) );
#endif
}
cbuffer DrawConstants : register(b0) {
float4x4 g_Projection;
float4x4 g_InverseProjection;
float3 g_LightDirView;
float g_NumSamples;
float g_SampleRange;
float g_Thickness;
uint g_FrameIndex;
}
uint2 NdcToPixel(in float2 size, in float4 ndc);
float2 NdcToUv(in float4 ndc);
float4 PixelToNdc(in float2 size, in uint2 pixel, in float depth);
float4 UvToNdc(in float2 uv, in float depth);
uint2 ViewToPixel(in float2 size, in float3 view);
float2 ViewToUv(in float3 view);
float GetPixelDepth(in float2 size, in uint2 pixel);
float GetUvDepth(in float2 uv);
float3 PixelToViewWithDepth(in float2 size, in uint2 pixel);
float3 UvToViewWithDepth(in float2 uv);
[numthreads(8, 8, 1)]
void main(uint3 PixCoord : SV_DispatchThreadID) {
float2 size;
g_DepthTexture.GetDimensions(size.x, size.y);
uint2 pixel = PixCoord.xy;
float occlusion = 0;
g_Output[pixel] = 1.;
float2 noise = SpatioTemporalNoise(PixCoord.xy, g_FrameIndex);
float3 viewPosition = PixelToViewWithDepth(size, pixel);
float3 sample = viewPosition;
float3 step = g_LightDirView * g_SampleRange / g_NumSamples;
sample += noise.x * step;
for(int i = 0; i < g_NumSamples; ++i) {
sample += step;
float2 sample_uv = ViewToUv(sample);
if(all(and(sample_uv > 0, sample_uv < 1.))) {
float depthDelta = sample.z * .998 - GetUvDepth(sample_uv);
if(depthDelta < 0. && depthDelta > -g_Thickness) {
occlusion = 1.;
break;
}
}
}
g_Output[pixel] = 1. - occlusion;
}
uint2 NdcToPixel(in float2 size, in float4 ndc) {
return (uint2)floor(NdcToUv(ndc) * size);
}
float2 NdcToUv(in float4 ndc) {
return ndc.xy * float2(.5, -.5) + .5;
}
float4 PixelToNdc(in float2 size, in uint2 pixel, in float ndc_depth) {
return float4(float2(2., -2.) * ((((float2)pixel + .5) / size) - .5), ndc_depth, 1.);
}
float4 UvToNdc(in float2 uv, in float ndc_depth) {
return float4(float2(2., -2.) * (uv - .5), ndc_depth, 1.);
}
uint2 ViewToPixel(in float2 size, in float3 view) {
float4 ndc = mul(g_Projection, float4(view, 1.));
ndc /= ndc.w;
return NdcToPixel(size, ndc);
}
float2 ViewToUv(in float3 view) {
float4 ndc = mul(g_Projection, float4(view, 1.));
ndc /= ndc.w;
return NdcToUv(ndc);
}
float GetPixelDepth(in float2 size, in uint2 pixel) {
return PixelToViewWithDepth(size, pixel).z;
}
float GetUvDepth(in float2 uv) {
return UvToViewWithDepth(uv).z;
}
float3 PixelToViewWithDepth(in float2 size, in uint2 pixel) {
float4 ndc = PixelToNdc(size, pixel, g_DepthTexture[pixel]);
ndc = mul(g_InverseProjection, ndc);
return ndc.xyz / ndc.w;
}
float3 UvToViewWithDepth(in float2 uv) {
float4 ndc = UvToNdc(uv, g_DepthTexture.SampleLevel(g_SamplerLinearClamp, uv, 0.));
ndc = mul(g_InverseProjection, ndc);
return ndc.xyz / ndc.w;
}

18
manul/shaders/copy.hlsl Normal file
View File

@@ -0,0 +1,18 @@
struct VertexOutput {
float2 m_Position : Position;
float4 m_PositionSV : SV_Position;
};
struct PixelOutput {
float4 m_Output : SV_Target0;
};
sampler source_sampler : register(s0);
Texture2D source : register(t0);
PixelOutput main(VertexOutput ps_in) {
PixelOutput result;
result.m_Output = source.Sample(source_sampler, ps_in.m_Position);
return result;
}

View File

@@ -0,0 +1,52 @@
#define PI 3.1415926535897932384626433832795
#define TWO_PI 6.283185307179586476925286766559
#define ONE_OVER_PI 0.31830988618379067153776752674503
#define TWO_OVER_PI 0.63661977236758134307553505349006
#define ONE_OVER_TWO_PI 0.15915494309189533576888376337251
float3 CalcNormal(in uint3 PixCoord);
float2 EquirectFromNormal(in float3 Normal);
float2 PixCoordToFloat(in uint2 Coord, in uint2 Size);
float2 PixCoordToFloat(in uint2 Coord, in uint2 Size) {
return ((float2)Coord + .5.xx) / (float2)Size;
}
float3 CalcNormal(in uint3 PixCoord) {
static const float3x3 FaceTransform[6] = {
// +X
float3x3( 0., 0., -1.,
0., -1., 0.,
1., 0., 0. ),
// -X
float3x3( 0., 0., 1.,
0., -1., 0.,
-1., 0., 0. ),
// +Y
float3x3( 1., 0., 0.,
0., 0., 1.,
0., 1., 0. ),
// -Y
float3x3( 1., 0., 0.,
0., 0., -1.,
0., -1., 0. ),
// +Z
float3x3( 1., 0., 0.,
0., -1., 0.,
0., 0., 1. ),
// -Z
float3x3( -1., 0., 0.,
0., -1., 0.,
0., 0., -1. )
};
uint2 FaceSize;
uint Elements;
g_OutCubemap.GetDimensions(FaceSize.x, FaceSize.y, Elements);
return normalize(mul(float3(PixCoordToFloat(PixCoord.xy, FaceSize) * 2. - 1., 1.), FaceTransform[PixCoord.z]));
}
float2 EquirectFromNormal(in float3 Normal) {
return float2(atan2(Normal.x, Normal.z) * ONE_OVER_TWO_PI, -asin(Normal.y) * ONE_OVER_PI) + .5.xx;
}

View File

@@ -0,0 +1,39 @@
#pragma pack_matrix(column_major)
struct VertexInput {
float3 m_Position : Position;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
};
struct VertexOutput {
float3 m_Position : Position;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_PositionSV : SV_Position;
float4 m_PositionCS : PositionCS;
float4 m_HistoryPositionCS : HistoryPositionCS;
};
cbuffer VertexConstants : register(b0) {
float4x4 g_FaceProjection;
};
#include "manul/draw_constants.hlsli"
VertexOutput main(in VertexInput vs_in) {
VertexOutput result;
float4x3 model_view = GetModelView();
result.m_Position = mul(float4(vs_in.m_Position, 1.), model_view).xyz;
result.m_Normal = mul(float4(vs_in.m_Normal, 0.), model_view).xyz;
result.m_Normal = vs_in.m_Normal;
result.m_TexCoord = vs_in.m_TexCoord;
result.m_Tangent.xyz = vs_in.m_Tangent.xyz;
result.m_Tangent.w = vs_in.m_Tangent.w;
result.m_PositionSV = mul(g_FaceProjection, float4(result.m_Position, 1.));
result.m_PositionCS = result.m_PositionSV;
result.m_HistoryPositionCS = result.m_PositionSV;
return result;
}

View File

@@ -0,0 +1,43 @@
StructuredBuffer<float4x3> g_InTransforms : register(t0);
RWStructuredBuffer<float4x3> g_OutCulledTransforms : register(u0);
struct CommandBuffer {
uint g_IndexCountPerInstance;
uint g_InstanceCount;
uint g_StartIndexLocation;
int g_BaseVertexLocation;
uint g_StartInstanceLocation;
};
RWStructuredBuffer<CommandBuffer> g_CommandBuffer : register(u1);
cbuffer ViewData : register(b0) {
float4 g_FrustumPlanes[6];
float4x4 g_Projection;
}
cbuffer PushConstants : register(b1) {
float3 g_Origin;
float g_InstanceRadius;
float g_MinRadius;
float g_MaxRadius;
uint g_NumInstances;
}
[numthreads(64, 1, 1)]
void main(uint3 DispatchId : SV_DispatchThreadID) {
if(DispatchId.x >= g_NumInstances) return;
float4x3 instance = g_InTransforms[DispatchId.x];
//float3 position = mul(float4(0., 0., 0., 1.), instance) + g_Origin;
//for(int i = 0; i < 6; ++i) {
// if(dot(float4(position, 1.), g_FrustumPlanes[i]) < -g_InstanceRadius) return;
//}
//float4 ndc = mul(g_Projection, float4(0., g_InstanceRadius, -length(position), 1.));
//float radius = ndc.y / ndc.w;
//if(radius > g_MinRadius && radius <= g_MaxRadius) {
uint index;
InterlockedAdd(g_CommandBuffer[0].g_InstanceCount, 1, index);
g_OutCulledTransforms[index] = instance;
//}
}

View File

@@ -0,0 +1,42 @@
#pragma pack_matrix(column_major)
struct VertexInput {
float3 m_Position : Position;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
};
struct VertexOutput {
float3 m_Position : Position;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_PositionSV : SV_Position;
float4 m_PositionCS : PositionCS;
float4 m_HistoryPositionCS : HistoryPositionCS;
};
cbuffer VertexConstants : register(b0) {
float4x4 g_JitteredProjection;
float4x4 g_Projection;
float4x4 g_ProjectionHistory;
};
#include "manul/draw_constants.hlsli"
VertexOutput main(in VertexInput vs_in) {
VertexOutput result;
float4x3 model_view = GetModelView();
float4x3 model_view_history = GetModelViewHistory();
result.m_Position = mul(float4(vs_in.m_Position, 1.), model_view).xyz;
result.m_Normal = mul(float4(vs_in.m_Normal, 0.), model_view).xyz;
result.m_TexCoord = vs_in.m_TexCoord;
result.m_Tangent.xyz = mul(float4(vs_in.m_Tangent.xyz, 0.), model_view).xyz;
result.m_Tangent.w = vs_in.m_Tangent.w;
result.m_PositionSV = mul(g_JitteredProjection, float4(result.m_Position, 1.));
result.m_PositionCS = mul(g_Projection, float4(result.m_Position, 1.));
float3 history_position = mul(float4(vs_in.m_Position, 1.), model_view_history);
result.m_HistoryPositionCS = mul(g_ProjectionHistory, float4(history_position, 1.));
return result;
}

213
manul/shaders/envmap.hlsl Normal file
View File

@@ -0,0 +1,213 @@
RWTexture2DArray<float4> g_OutCubemap : register(u0);
RWTexture2D<float2> g_OutBRDF : register(u1);
Texture2D<float3> g_SourceEquirect : register(t0);
TextureCube<float3> g_SourceCube : register(t1);
Texture1D<float2> g_SampleKernel : register(t2);
SamplerState g_SamplerLinearClampV : register(s0);
SamplerState g_SamplerLinearClamp : register(s1);
#include "cubemap_utils.hlsli"
float DistributionGGX(float NdotH, float roughness);
float GeometrySchlickGGX(float NdotV, float roughness);
float GeometrySmith(float roughness, float NdotV, float NdotL);
float3 ImportanceSampleGGX(in float2 Xi,in float Roughness , in float3 N);
void ImportanceSampleCosDir(in float2 u, in float3 N, out float3 L, out float NdotL, out float pdf);
float2 GetSample(uint sample, uint sampleCount);
struct FilterParameters {
float m_PreExposureMul;
float m_Roughness;
float m_SampleCount;
float m_SourceWidth;
float m_MipBias;
uint3 m_Offset;
};
#ifdef SPIRV
[[vk::push_constant]] ConstantBuffer<FilterParameters> g_FilterParams;
#else
cbuffer g_Const : register(b0) { FilterParameters g_FilterParams; }
#endif
#include "manul/sky.hlsli"
[numthreads(32, 32, 1)]
void CSSampleEquirectangular(uint3 PixCoord : SV_DispatchThreadID) {
//Sky(g_OutCubemap[PixCoord + g_FilterParams.m_Offset], CalcNormal(PixCoord + g_FilterParams.m_Offset), normalize(float3(0., .1, 1.)), 0.);
g_OutCubemap[PixCoord + g_FilterParams.m_Offset].rgb = clamp(g_SourceEquirect.SampleLevel(g_SamplerLinearClampV, EquirectFromNormal(CalcNormal(PixCoord)), 0.) * g_FilterParams.m_PreExposureMul, 0., 65535.);
}
[numthreads(32, 32, 1)]
void CSDiffuseIBL(uint3 PixCoord : SV_DispatchThreadID) {
float3 N = CalcNormal(PixCoord + g_FilterParams.m_Offset);
float sampleCount = g_FilterParams.m_SampleCount;
float width = g_FilterParams.m_SourceWidth;
float mipBias = g_FilterParams.m_MipBias;
float3 accBrdf = 0;
for ( uint i =0; i < sampleCount ; ++ i ) {
float2 eta = GetSample (i , sampleCount ) ;
float3 L ;
float NdotL ;
float pdf ;
ImportanceSampleCosDir ( eta , N , L , NdotL , pdf ) ;
if ( NdotL >0) {
float omegaS = 1. / ( sampleCount * pdf );
float omegaP = 4. * PI / (6. * width * width );
float mipLevel = max(0., mipBias + .5 * log2 ( omegaS / omegaP ));
accBrdf += g_SourceCube . SampleLevel ( g_SamplerLinearClamp , L, mipLevel ) ;
}
}
g_OutCubemap[PixCoord + g_FilterParams.m_Offset].rgb = accBrdf * (1. / sampleCount);
}
[numthreads(32, 32, 1)]
void CSSpecularIBL(uint3 PixCoord : SV_DispatchThreadID) {
float3 N = CalcNormal(PixCoord + g_FilterParams.m_Offset);
float roughness = g_FilterParams.m_Roughness;
float width = g_FilterParams.m_SourceWidth;
float sampleCount = g_FilterParams.m_SampleCount;
float mipBias = g_FilterParams.m_MipBias;
float3 accBrdf = 0;
float accWeight = 0;
for ( uint i =0; i < sampleCount ; ++ i ) {
float2 eta = GetSample (i , sampleCount ) ;
float pdf ;
float3 H = ImportanceSampleGGX(eta, roughness, N);
float3 L = normalize(2 * dot( N, H ) * H - N);
float NdotL = dot(N, L);
float NdotH = dot(N, H);
if(NdotL > 0) {
float D = DistributionGGX(NdotH, roughness);
float pdf = D / 4.;
float omegaS = 1. / ( sampleCount * pdf );
float omegaP = 4. * PI / (6. * width * width );
float mipLevel = roughness == 0. ? mipBias : max(0., mipBias + .5 * log2 ( omegaS / omegaP ));
accBrdf += g_SourceCube . SampleLevel ( g_SamplerLinearClamp , L, mipLevel ) * NdotL;
accWeight += NdotL;
}
}
g_OutCubemap[PixCoord + g_FilterParams.m_Offset].rgb = accBrdf * (1. / accWeight);
}
[numthreads(32, 32, 1)]
void CSIntegrateBRDF(uint3 PixCoord : SV_DispatchThreadID) {
uint2 FaceSize;
g_OutBRDF.GetDimensions(FaceSize.x, FaceSize.y);
float NoV = ((float)PixCoord.x + .5) / (float)FaceSize.x;
float Roughness = ((float)PixCoord.y + .5) / (float)FaceSize.y;
float3 N = float3(0., 0., 1.);
float3 V;
V.x = sqrt( 1. - NoV * NoV ); // sin
V.y = 0.;
V.z = NoV; // cos
float A = 0.;
float B = 0.;
float sampleCount = 1024.;
for( uint i = 0; i < sampleCount; i++ )
{
float2 Xi = GetSample (i , sampleCount );
float3 H = ImportanceSampleGGX(Xi, Roughness, N);
float3 L = normalize(2. * dot( V, H ) * H - V);
float NoL = saturate( L.z );
float NoH = saturate( H.z );
float VoH = saturate( dot( V, H ) );
if( NoL > 0. )
{
float G = GeometrySmith( Roughness, NoV, NoL );
float G_Vis = G * VoH / (NoH * NoV);
float Fc = pow( 1. - VoH, 5. );
A += (1. - Fc) * G_Vis;
B += Fc * G_Vis;
}
}
g_OutBRDF[PixCoord.xy] = float2( A, B ) / sampleCount;
}
[numthreads(32, 32, 1)]
void CSGenerateCubeMip(uint3 PixCoord : SV_DispatchThreadID) {
g_OutCubemap[PixCoord + g_FilterParams.m_Offset].rgb = g_SourceCube.SampleLevel(g_SamplerLinearClamp, CalcNormal(PixCoord + g_FilterParams.m_Offset), 0.);
}
float GeometrySchlickGGX(float NdotV, float roughness)
{
// note that we use a different k for IBL
float a = roughness;
float k = (a * a) / 2.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float GeometrySmith(float roughness, float NdotV, float NdotL)
{
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
float DistributionGGX(float NdotH, float roughness)
{
float a = roughness*roughness;
float a2 = a*a;
float nom = a2;
float denom = (NdotH*NdotH * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return nom / denom;
}
void ImportanceSampleCosDir (in float2 Xi, in float3 N, out float3 L, out float NdotL, out float pdf) {
// Local referencial
float3 upVector = abs (N.z) < .999 ? float3 (0., 0., 1.) : float3 (1., 0., 0.) ;
float3 tangentX = normalize ( cross ( upVector , N ) ) ;
float3 tangentY = cross ( N , tangentX ) ;
float r = sqrt ( Xi.x ) ;
float phi = Xi.y * TWO_PI;
L = float3 ( r * cos ( phi ) , r * sin ( phi ) , sqrt ( max (0. ,1. - Xi.x ) ) ) ;
L = normalize ( tangentX * L . y + tangentY * L . x + N * L . z ) ;
NdotL = dot (L , N ) ;
pdf = NdotL * ONE_OVER_PI ;
}
float3 ImportanceSampleGGX(in float2 Xi,in float Roughness , in float3 N)
{
double a = Roughness * Roughness;
float Phi = TWO_PI * Xi.x;
float CosTheta = sqrt( (float)((1. - Xi.y) / ( 1. + (a*a - 1.) * Xi.y ) ));
float SinTheta = sqrt( 1. - CosTheta * CosTheta );
float3 H = float3( SinTheta * cos( Phi ), SinTheta * sin( Phi ), CosTheta);
float3 UpVector = abs(N.z) < .999 ? float3(0.,0.,1.) : float3(1.,0.,0.);
float3 TangentX = normalize( cross( UpVector , N ) );
float3 TangentY = cross( N, TangentX );
// Tangent to world space
return normalize( TangentX * H.x + TangentY * H.y + N * H.z );
}
float RadicalInverse_VdC(uint bits)
{
return float(reversebits(bits)) * 2.3283064365386963e-10; // / 0x100000000
}
float2 GetSample(uint i, uint N) {
return float2((float)i/(float)N, RadicalInverse_VdC(i));
}

View File

@@ -0,0 +1,16 @@
struct VertexInput {
float2 m_Position : Position;
};
struct VertexOutput {
float2 m_Position : Position;
float4 m_PositionSV : SV_Position;
};
VertexOutput main(in VertexInput vs_in) {
VertexOutput result;
result.m_Position = vs_in.m_Position;
result.m_PositionSV = float4(vs_in.m_Position * float2(2., -2.) + float2(-1., 1.), 0., 1.);
return result;
}

View File

@@ -0,0 +1,69 @@
#define PI 3.1415926535897932384626433832795
#define TWO_PI 6.283185307179586476925286766559
#define ONE_OVER_PI 0.31830988618379067153776752674503
#define TWO_OVER_PI 0.63661977236758134307553505349006
#define ONE_OVER_TWO_PI 0.15915494309189533576888376337251
RWTexture2DArray<float4> g_OutCubemap : register(u0);
TextureCube<float3> g_Skybox : register(t0);
TextureCube<float3> g_Diffuse : register(t1);
TextureCube<float3> g_Normal : register(t2);
TextureCube<float4> g_Params : register(t3);
TextureCube<float> g_Depth : register(t4);
TextureCube<float3> g_DiffuseIBL : register(t5);
SamplerState g_SamplerLinearClamp : register(s0);
SamplerState g_SamplerPointClamp : register(s1);
#include "cubemap_utils.hlsli"
#include "manul/sky.hlsli"
struct FilterParameters {
uint3 m_Offset;
uint unused;
float3 m_LightVector;
float m_Altitude;
float3 m_LightColor;
};
#ifdef SPIRV
[[vk::push_constant]] ConstantBuffer<FilterParameters> g_FilterParams;
#else
cbuffer g_Const : register(b0) { FilterParameters g_FilterParams; }
#endif
cbuffer FilterConstants : register(b1) {
float4x4 g_InverseProjection;
};
[numthreads(32, 32, 1)]
void main(uint3 PixCoord : SV_DispatchThreadID) {
float3 normal = CalcNormal(PixCoord + g_FilterParams.m_Offset);
float3 size;
g_OutCubemap.GetDimensions(size.x, size.y, size.z);
//g_OutCubemap[PixCoord + g_Offset] = g_Skybox.SampleLevel(g_SamplerLinearClamp, normal, 0.);
float3 color = 1.e-7;
CalcAtmosphere(color, normal, g_FilterParams.m_LightVector);
//CalcAtmosphere(g_OutCubemap[PixCoord + g_Offset], 1., normal, g_LightVector, g_Altitude, SKY_INF, g_LightColor.rgb, 10);
float3 normal_flipped = normal * float3(-1., 1., 1.);
float depth = g_Depth.SampleLevel(g_SamplerPointClamp, normal_flipped, 0.);
float linear_depth = 2500.;
if(depth > 0.) {
float3 material_albedo = g_Diffuse.SampleLevel(g_SamplerPointClamp, normal_flipped, 0.);
float4 material_params = g_Params.SampleLevel(g_SamplerPointClamp, normal_flipped, 0.);
float3 material_normal = (g_Normal.SampleLevel(g_SamplerPointClamp, normal_flipped, 0.) - .5) * 2.;
float NdotL = max(dot(material_normal, g_FilterParams.m_LightVector), 0.);
color = material_albedo * (g_DiffuseIBL.SampleLevel(g_SamplerPointClamp, material_normal, 0.) + ONE_OVER_PI * NdotL * g_FilterParams.m_LightColor.rgb) * material_params.b;
float4 position_ndc = mul(g_InverseProjection, float4(PixCoordToFloat(PixCoord.xy + g_FilterParams.m_Offset.xy, size.xy) * 2. - 1., depth, 1.));
position_ndc /= position_ndc.w;
linear_depth = length(position_ndc.xyz);
}
ApplyAerialPerspective(color, 1., normal, g_FilterParams.m_LightVector, linear_depth/2500.);
g_OutCubemap[PixCoord + g_FilterParams.m_Offset].rgb = color;
}

View File

@@ -0,0 +1,118 @@
#include "manul/math.hlsli"
struct VertexOutput {
float2 m_Position : Position;
float4 m_PositionSV : SV_Position;
};
struct PixelOutput {
float4 m_Color : SV_Target0;
};
Texture2D<float3> gbuffer_diffuse : register(t0);
Texture2D<float3> gbuffer_emission : register(t1);
Texture2D<float4> gbuffer_params : register(t2);
Texture2D<float3> gbuffer_normal : register(t3);
Texture2D<float> gbuffer_depth : register(t4);
RWTexture2D<float4> output : register(u0);
#define DEFERRED_LIGHTING_PASS
#include "manul/gbuffer_ssao.hlsli"
//#include "manul/gbuffer_contact_shadows.hlsli"
#include "manul/shadow.hlsli"
#include "manul/lighting.hlsli"
#include "manul/sky.hlsli"
#define BLOCK_SIZE 8
#define TILE_BORDER 1
#define TILE_SIZE (BLOCK_SIZE + 2 * TILE_BORDER)
groupshared float2 tile_XY[TILE_SIZE*TILE_SIZE];
groupshared float tile_Z[TILE_SIZE*TILE_SIZE];
uint2 unflatten2D(uint idx, uint2 dim)
{
return uint2(idx % dim.x, idx / dim.x);
}
uint flatten2D(uint2 coord, uint2 dim)
{
return coord.x + coord.y * dim.x;
}
[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
void main(uint3 PixCoord : SV_DispatchThreadID, uint3 GroupID : SV_GroupID, uint GroupIndex : SV_GroupIndex) {
uint2 gbuffer_dimensions;
gbuffer_depth.GetDimensions(gbuffer_dimensions.x, gbuffer_dimensions.y);
const int2 tile_upperleft = GroupID.xy * BLOCK_SIZE - TILE_BORDER;
for (uint t = GroupIndex; t < TILE_SIZE * TILE_SIZE; t += BLOCK_SIZE * BLOCK_SIZE)
{
const uint2 pixel = tile_upperleft + unflatten2D(t, TILE_SIZE);
const float depth = gbuffer_depth[pixel];
const float3 position = ReconstructPos(PixelToCS(pixel, gbuffer_dimensions), depth);
tile_XY[t] = position.xy;
tile_Z[t] = position.z;
}
GroupMemoryBarrierWithGroupSync();
// Decode material data
MaterialData material;
material.m_PixelCoord = PixCoord.xy;
float2 uv = ( material.m_PixelCoord + .5) / gbuffer_dimensions;
uint2 tile_co = material.m_PixelCoord - tile_upperleft;
//float depth = gbuffer_depth[ material.m_PixelCoord];
uint co = flatten2D(tile_co, TILE_SIZE);
uint co_px = flatten2D(tile_co + int2(1, 0), TILE_SIZE);
uint co_nx = flatten2D(tile_co + int2(-1, 0), TILE_SIZE);
uint co_py = flatten2D(tile_co + int2(0, 1), TILE_SIZE);
uint co_ny = flatten2D(tile_co + int2(0, -1), TILE_SIZE);
float depth = tile_Z[co];
float depth_px = tile_Z[co_px];
float depth_nx = tile_Z[co_nx];
float depth_py = tile_Z[co_py];
float depth_ny = tile_Z[co_ny];
material.m_Position = float3(tile_XY[co], depth);
if(abs(depth_px - depth) < abs(depth_nx - depth)) {
material.m_PositionDDX.xy = tile_XY[co_px];
material.m_PositionDDX.z = depth_px;
}
else{
material.m_PositionDDX.xy = tile_XY[co_nx];
material.m_PositionDDX.z = depth_nx;
}
if(abs(depth_py - depth) < abs(depth_ny - depth)) {
material.m_PositionDDY.xy = tile_XY[co_py];
material.m_PositionDDY.z = depth_py;
}
else{
material.m_PositionDDY.xy = tile_XY[co_ny];
material.m_PositionDDY.z = depth_ny;
}
material.m_MaterialAlbedoAlpha.rgb = gbuffer_diffuse[ material.m_PixelCoord];
material.m_MaterialAlbedoAlpha.a = 1.;
material.m_MaterialEmission = gbuffer_emission[ material.m_PixelCoord];
material.m_MaterialParams = gbuffer_params[ material.m_PixelCoord];
material.m_MaterialNormal = UnpackNormalXYZ(gbuffer_normal[ material.m_PixelCoord]);
PixelOutput ps_out;
#if LIGHTING_NEEDS_PIXELPOSITION
ApplyMaterialLighting(output[material.m_PixelCoord], material, material.m_PixelCoord);
#else
ApplyMaterialLighting(output[material.m_PixelCoord], material);
#endif
float3 view_world = mul((float3x3)g_InverseModelView, material.m_Position);
ApplyAerialPerspective(output[material.m_PixelCoord].rgb, 1., normalize(view_world), g_LightDir, length(view_world)/2500.);
//if(depth < 1.){
// CalcAtmosphere(ps_out.m_Color.rgb, 1., normalize(mul((float3x3) g_InverseModelView, material.m_Position)), g_LightDir.xyz, g_Altitude, length(view.xyz), g_LightColor.rgb, 10);
//}
//return ps_out;
}

View File

@@ -0,0 +1,46 @@
#pragma pack_matrix(column_major)
struct VertexInput {
float3 m_Position : Position;
float4 m_PositionCS : PositionCS;
float4 m_HistoryPositionCS : HistoryPositionCS;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_PositionSV : SV_Position;
};
struct VertexOutput {
float3 m_Position : Position;
float4 m_PositionCS : PositionCS;
float4 m_HistoryPositionCS : HistoryPositionCS;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_PositionSV : SV_Position;
uint m_ViewportIndex : SV_RenderTargetArrayIndex;
};
cbuffer CubeDrawConstants : register(b0) {
float4x4 g_FaceProjections[6];
};
[maxvertexcount(18)]
void main(triangle in VertexInput gs_in[3], inout TriangleStream<VertexOutput> gs_out) {
for(uint vp = 0; vp < 6; ++vp) {
for(uint vertex = 0; vertex < 3; ++vertex) {
VertexOutput output;
VertexInput input = gs_in[2 - vertex];
output.m_Position = input.m_Position;
output.m_PositionCS = mul(g_FaceProjections[vp], float4(output.m_Position * float3(-1., 1., 1.), 1.));
output.m_HistoryPositionCS = output.m_PositionCS;
output.m_PositionSV = output.m_PositionCS;
output.m_Normal = input.m_Normal;
output.m_TexCoord = input.m_TexCoord;
output.m_Tangent = input.m_Tangent;
output.m_ViewportIndex = vp;
gs_out.Append(output);
}
gs_out.RestartStrip();
}
}

View File

@@ -0,0 +1,48 @@
#pragma pack_matrix(column_major)
struct VertexInput {
float3 m_Position : Position;
float4 m_PositionCS : PositionCS;
float4 m_HistoryPositionCS : HistoryPositionCS;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_PositionSV : SV_Position;
};
struct VertexOutput {
float3 m_Position : Position;
float4 m_PositionCS : PositionCS;
float4 m_HistoryPositionCS : HistoryPositionCS;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_PositionSV : SV_Position;
uint m_ViewportIndex : SV_RenderTargetArrayIndex;
};
#define CASCADE_COUNT 4
cbuffer CubeDrawConstants : register(b0) {
float4x4 g_CascadeProjections[CASCADE_COUNT];
};
[maxvertexcount(CASCADE_COUNT*3)]
void main(triangle in VertexInput gs_in[3], inout TriangleStream<VertexOutput> gs_out) {
for(uint vp = 0; vp < CASCADE_COUNT; ++vp) {
for(uint vertex = 0; vertex < 3; ++vertex) {
VertexOutput output;
VertexInput input = gs_in[vertex];
output.m_Position = input.m_Position;
output.m_PositionCS = mul(g_CascadeProjections[vp], float4(output.m_Position, 1.));
output.m_HistoryPositionCS = output.m_PositionCS;
output.m_PositionSV = output.m_PositionCS;
output.m_Normal = input.m_Normal;
output.m_TexCoord = input.m_TexCoord;
output.m_Tangent = input.m_Tangent;
output.m_ViewportIndex = vp;
gs_out.Append(output);
}
gs_out.RestartStrip();
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2014-2021, NVIDIA CORPORATION. All rights reserved.
*
* 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.
*/
#define MA_TONEMAP_SRGB_REC709 0
#define MA_TONEMAP_LINEAR_REC2020 1
struct Constants
{
float2 invDisplaySize;
float outputNits;
int m_TonemapFunction;
};
#ifdef SPIRV
[[vk::push_constant]] ConstantBuffer<Constants> g_Const;
#else
cbuffer g_Const : register(b0) { Constants g_Const; }
#endif
struct PS_INPUT
{
float4 pos : SV_POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
float3 LinearToSRGB(float3 color)
{
// Approximately pow(color, 1.0 / 2.2)
return select(color < 0.0031308, 12.92 * color, 1.055 * pow(abs(color), 1.0 / 2.4) - 0.055);
}
float3 SRGBToLinear(float3 color)
{
// Approximately pow(color, 2.2)
return select(color < 0.04045, color / 12.92, pow(abs(color + 0.055) / 1.055, 2.4));
}
float3 Rec709ToRec2020(float3 color)
{
static const float3x3 conversion =
{
0.627402, 0.329292, 0.043306,
0.069095, 0.919544, 0.011360,
0.016394, 0.088028, 0.895578
};
return mul(conversion, color);
}
float3 LinearToST2084(float3 color)
{
float m1 = 2610.0 / 4096.0 / 4;
float m2 = 2523.0 / 4096.0 * 128;
float c1 = 3424.0 / 4096.0;
float c2 = 2413.0 / 4096.0 * 32;
float c3 = 2392.0 / 4096.0 * 32;
float3 cp = pow(abs(color), m1);
return pow((c1 + c2 * cp) / (1 + c3 * cp), m2);
}
sampler sampler0 : register(s0);
Texture2D texture0 : register(t0);
float4 main(PS_INPUT input) : SV_Target
{
float4 tex_col = texture0.Sample(sampler0, input.uv);
float4 input_col = input.col;
switch(g_Const.m_TonemapFunction) {
case MA_TONEMAP_LINEAR_REC2020:
{
input_col.rgb = SRGBToLinear(input_col.rgb);
float4 out_col = input_col * tex_col;
const float st2084max = 10000.;
const float hdrScalar = g_Const.outputNits / st2084max;
//out_col.rgb = Rec709ToRec2020(out_col.rgb);
out_col.rgb *= hdrScalar;
out_col.rgb = LinearToST2084(out_col.rgb);
return out_col;
}
default:
{
tex_col.rgb = LinearToSRGB(tex_col.rgb);
return input_col * tex_col;
}
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2014-2021, NVIDIA CORPORATION. All rights reserved.
*
* 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.
*/
struct Constants
{
float2 invDisplaySize;
float outputNits;
};
#ifdef SPIRV
[[vk::push_constant]] ConstantBuffer<Constants> g_Const;
#else
cbuffer g_Const : register(b0) { Constants g_Const; }
#endif
struct VS_INPUT
{
float2 pos : POSITION;
float2 uv : TEXCOORD0;
float4 col : COLOR0;
};
struct PS_INPUT
{
float4 out_pos : SV_POSITION;
float4 out_col : COLOR0;
float2 out_uv : TEXCOORD0;
};
PS_INPUT main(VS_INPUT input)
{
PS_INPUT output;
output.out_pos.xy = input.pos.xy * g_Const.invDisplaySize * float2(2.0, -2.0) + float2(-1.0, 1.0);
output.out_pos.zw = float2(0, 1);
output.out_col = input.col;
output.out_uv = input.uv;
return output;
}

View File

@@ -0,0 +1,41 @@
#pragma pack_matrix(column_major)
struct VertexInput {
float3 m_Position : Position;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_InstanceTransform[3] : InstanceTransform;
};
struct VertexOutput {
float3 m_Position : Position;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_PositionSV : SV_Position;
float4 m_PositionCS : PositionCS;
float4 m_HistoryPositionCS : HistoryPositionCS;
};
cbuffer VertexConstants : register(b0) {
float4x4 g_FaceProjection;
};
#include "manul/draw_constants.hlsli"
VertexOutput main(in VertexInput vs_in) {
VertexOutput result;
float4x3 model_view = GetModelView();
float4x4 instance_transform = transpose(float4x4(vs_in.m_InstanceTransform[0], vs_in.m_InstanceTransform[1], vs_in.m_InstanceTransform[2], float4(0., 0., 0., 1.)));
float3 position = mul(float4(vs_in.m_Position, 1.), instance_transform).xyz;
result.m_Position = mul(float4(position, 1.), model_view).xyz;
result.m_Normal = mul(float4(mul(float4(vs_in.m_Normal, 0.), instance_transform)), model_view).xyz;
result.m_TexCoord = vs_in.m_TexCoord;
result.m_Tangent.xyz = mul(float4(mul(float4(vs_in.m_Tangent.xyz, 0.), instance_transform)), model_view).xyz;
result.m_Tangent.w = vs_in.m_Tangent.w;
result.m_PositionSV = mul(g_FaceProjection, float4(result.m_Position, 1.));
result.m_PositionCS = result.m_PositionSV;
result.m_HistoryPositionCS = result.m_PositionSV;
return result;
}

View File

@@ -0,0 +1,25 @@
#pragma pack_matrix(column_major)
struct VertexInput {
float3 m_Position : Position;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_InstanceTransform[3] : InstanceTransform;
};
struct VertexOutput {
float2 m_TexCoord : TexCoord;
float4 m_PositionSV : SV_Position;
};
#include "manul/draw_constants_shadow.hlsli"
VertexOutput main(in VertexInput vs_in) {
VertexOutput result;
float4x4 instance_transform = transpose(float4x4(vs_in.m_InstanceTransform[0], vs_in.m_InstanceTransform[1], vs_in.m_InstanceTransform[2], float4(0., 0., 0., 1.)));
float3 position = mul(float4(vs_in.m_Position, 1.), instance_transform);
result.m_TexCoord = vs_in.m_TexCoord;
result.m_PositionSV = mul(g_DrawConstants.m_ModelViewProjection, float4(position, 1.));
return result;
}

View File

@@ -0,0 +1,45 @@
#pragma pack_matrix(column_major)
struct VertexInput {
float3 m_Position : Position;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_InstanceTransform[3] : InstanceTransform;
};
struct VertexOutput {
float3 m_Position : Position;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
float4 m_PositionSV : SV_Position;
float4 m_PositionCS : PositionCS;
float4 m_HistoryPositionCS : HistoryPositionCS;
};
cbuffer VertexConstants : register(b0) {
float4x4 g_JitteredProjection;
float4x4 g_Projection;
float4x4 g_ProjectionHistory;
};
#include "manul/draw_constants.hlsli"
VertexOutput main(in VertexInput vs_in) {
VertexOutput result;
float4x3 model_view = GetModelView();
float4x3 model_view_history = GetModelViewHistory();
float4x4 instance_transform = transpose(float4x4(vs_in.m_InstanceTransform[0], vs_in.m_InstanceTransform[1], vs_in.m_InstanceTransform[2], float4(0., 0., 0., 1.)));
float3 position = mul(float4(vs_in.m_Position, 1.), instance_transform).xyz;
result.m_Position = mul(float4(position, 1.), model_view).xyz;
result.m_Normal = mul(mul(float4(vs_in.m_Normal, 0.), instance_transform), model_view);
result.m_TexCoord = vs_in.m_TexCoord;
result.m_Tangent.xyz = mul(mul(float4(vs_in.m_Tangent.xyz, 0.), instance_transform), model_view);
result.m_Tangent.w = vs_in.m_Tangent.w;
result.m_PositionSV = mul(g_JitteredProjection, float4(result.m_Position, 1.));
result.m_PositionCS = mul(g_Projection, float4(result.m_Position, 1.));
float3 history_position = mul(float4(position, 1.), model_view_history).xyz;
result.m_HistoryPositionCS = mul(g_ProjectionHistory, float4(history_position, 1.));
return result;
}

309
manul/shaders/project.manul Normal file
View File

@@ -0,0 +1,309 @@
templates:
# Partially pre-filled containers to avoid excessive copypasta
XeGTAO:
source: XeGTAO/GTAO
target: compute
definitions: # TODO (mostly) move to shader file I guess
VA_COMPILED_AS_SHADER_CODE: 1
VA_DIRECTX: 12
VA_DXC: 1
XE_GTAO_USE_DEFAULT_CONSTANTS: 1
XE_GTAO_FP32_DEPTHS: 1
XE_GTAO_USE_HALF_FLOAT_PRECISION: 0
VA_COMPILED_AS_SHADER_CODE: 1
VA_SATURATE: saturate
envmap:
source: envmap
target: compute
precomputed_sky:
source: manul/sky_aerial_lut
target: compute
bloom:
source: manul/bloom
target: compute
gbuffer_lights:
source: manul/gbuffer_lights
target: compute
shaders:
materials:
# Material shaders
# are compiled for all the rendering passes at once
# Binding layout will also be defined here (though ignored by compiler for now)
default_lit:
textures:
albedo:
binding: 0
hint: linear # so that texture will be marked as sRGB
default: white
# We split the normal map into two textures to drastically improve compression quality when compressed using standard of "Paczka całościowa"
# (so that we use the best of two 5.6.5 RGB compression blocks for hopefully less gradient-like parameters and two interpolated alphas for normal)
params: # Metalness.Roughness.Occlusion.Specular
binding: 1
hint: linear
default: legacy_params
normal:
binding: 2
hint: normalmap
default: normalmap
# paramx: # Metalness.Roughness.[UNUSED].Normal[X]
# binding: 1
# hint: linear
# default: legacy_params
# paramy: # Specular.Occlusion.[UNUSED].Normal[Y]
# binding: 2
# hint: linear
# default: legacy_params
# selfillum:
# binding: 3
# hint: color
# default: black
masked_shadow_texture: albedo
source: ps_default_lit
legacy:
textures:
diffuse:
binding: 0
hint: color # so that texture will be marked as sRGB
default: white
masked_shadow_texture: diffuse
source: ps_legacy
legacy_reflection:
textures:
diffuse:
binding: 0
hint: color # so that texture will be marked as sRGB
default: white
normal:
binding: 1
hint: normalmap
default: normalmap
masked_shadow_texture: diffuse
source: ps_legacy_reflection
legacy_normalmap:
textures:
diffuse:
binding: 0
hint: color # so that texture will be marked as sRGB
default: white
normal:
binding: 1
hint: normalmap
default: normalmap
masked_shadow_texture: diffuse
source: ps_legacy_normalmap
legacy_specgloss:
textures:
diffuse:
binding: 0
hint: color # so that texture will be marked as sRGB
default: white
specgloss:
binding: 1
hint: linear
default: white
masked_shadow_texture: diffuse
source: ps_legacy_specgloss
legacy_normalmap_specgloss:
textures:
diffuse:
binding: 0
hint: color # so that texture will be marked as sRGB
default: white
specgloss:
binding: 1
hint: linear
default: white
normal:
binding: 2
hint: normalmap
default: normalmap
masked_shadow_texture: diffuse
source: ps_legacy_normalmap_specgloss
legacy_water:
textures:
diffuse:
binding: 0
hint: color # so that texture will be marked as sRGB
default: white
normal:
binding: 1
hint: normalmap
default: normalmap
dudvmap:
binding: 2
hint: normalmap
default: normalmap
masked_shadow_texture: diffuse
source: ps_legacy_water
utility:
# Everything that does not belong to scene graph rendering
# ImGui shaders
imgui_pixel:
source: imgui_pixel
target: pixel
entrypoint: main
imgui_vertex:
source: imgui_vertex
target: vertex
entrypoint: main
# Shadow material
shadow_masked:
source: ps_shadow_masked
target: pixel
entrypoint: main
# Contact shadows
contact_shadows:
source: contact_shadows
target: compute
entrypoint: main
# Gbuffer lighting
gbuffer_lighting:
source: gbufferblit
target: compute
entrypoint: main
# Vertex shaders
default_vertex:
source: default_vertex
target: vertex
entrypoint: main
shadow_vertex:
source: shadow_vertex
target: vertex
entrypoint: main
cubemap_vertex:
source: cubemap_vertex
target: vertex
entrypoint: main
instanced_vertex:
source: instanced_vertex
target: vertex
entrypoint: main
instanced_shadow_vertex:
source: instanced_shadow_vertex
target: vertex
entrypoint: main
instanced_cubemap_vertex:
source: instanced_cubemap_vertex
target: vertex
entrypoint: main
# Fullscreen Fx shaders
fx_vertex:
source: fx_vertex
target: vertex
entrypoint: main
copy:
source: copy
target: pixel
entrypoint: main
skybox:
source: skybox
target: pixel
entrypoint: main
tonemap:
source: tonemap
target: pixel
entrypoint: main
# Envmap compute shaders
gbuffer_cube_lighting:
source: gbuffer_cube_lighting
target: compute
entrypoint: main
envmap_CSSampleEquirectangular:
use_template: envmap
entrypoint: CSSampleEquirectangular
envmap_CSDiffuseIBL:
use_template: envmap
entrypoint: CSDiffuseIBL
envmap_CSSpecularIBL:
use_template: envmap
entrypoint: CSSpecularIBL
envmap_CSGenerateCubeMip:
use_template: envmap
entrypoint: CSGenerateCubeMip
envmap_CSIntegrateBRDF:
use_template: envmap
entrypoint: CSIntegrateBRDF
# XeGTAO
gtao_CSPrefilterDepths16x16:
use_template: XeGTAO
entrypoint: CSPrefilterDepths16x16
gtao_CSGTAOLow:
use_template: XeGTAO
entrypoint: CSGTAOLow
gtao_CSGTAOMedium:
use_template: XeGTAO
entrypoint: CSGTAOMedium
gtao_CSGTAOHigh:
use_template: XeGTAO
entrypoint: CSGTAOHigh
gtao_CSGTAOUltra:
use_template: XeGTAO
entrypoint: CSGTAOUltra
gtao_CSDenoisePass:
use_template: XeGTAO
entrypoint: CSDenoisePass
gtao_CSDenoiseLastPass:
use_template: XeGTAO
entrypoint: CSDenoiseLastPass
# Atmospheric transmitance LUT
sky_transmittance:
source: manul/sky_transmittance
target: pixel
entrypoint: main
sky_aerial_lut:
use_template: precomputed_sky
entrypoint: CS_AerialLUT
sky:
use_template: precomputed_sky
entrypoint: CS_Sky
# Blóm
bloom_prefilter:
use_template: bloom
entrypoint: CS_BloomPrefilter
bloom_downsample:
use_template: bloom
entrypoint: CS_BloomDownsample
bloom_upsample:
use_template: bloom
entrypoint: CS_BloomUpsample
bloom_apply:
use_template: bloom
entrypoint: CS_BloomApply
# Wire geometry shader
vtx_line:
source: manul/line
target: vertex
entrypoint: vtx_main
geo_line:
source: manul/line
target: geometry
entrypoint: geo_main
pix_line:
source: manul/line
target: pixel
entrypoint: pix_main
# Deferred light primitives
gbuffer_light_clear:
use_template: gbuffer_lights
entrypoint: CS_Clear
gbuffer_light_spot:
use_template: gbuffer_lights
entrypoint: CS_Spotlight
# Forward+ light culling
forwardplus_compute_frustums:
source: manul/forward_plus/forward_plus
target: compute
entrypoint: CS_ComputeFrustums
forwardplus_cull_lights:
source: manul/forward_plus/forward_plus
target: compute
entrypoint: CS_CullLights
# Auto exposure
autoexp_compute_avg_luminance:
source: manul/comp_luminance
target: compute
entrypoint: CS_ComputeAvgLuminance
autoexp_apply:
source: manul/apply_auto_exposure
target: compute
entrypoint: CS_ApplyAutoExposure

View File

@@ -0,0 +1,30 @@
#include "manul/math.hlsli"
#include "manul/color_transform.hlsli"
#include "manul/material.hlsli"
sampler diffuse_sampler : register(s0);
Texture2D<float4> tex_albedo : register(t0);
Texture2D<float4> tex_params : register(t1);
Texture2D<float2> tex_normal : register(t2);
//Texture2D<float4> tex_paramx : register(t1);
//Texture2D<float4> tex_paramy : register(t2);
#include "manul/alpha_mask.hlsli"
void MaterialPass(inout MaterialData material) {
material.m_MaterialAlbedoAlpha = tex_albedo.Sample(diffuse_sampler, material.m_TexCoord);
material.m_MaterialAlbedoAlpha.rgb = saturate(ACEScg_to_XYZ(material.m_MaterialAlbedoAlpha.rgb));
AlphaMask(material.m_MaterialAlbedoAlpha.a);
material.m_MaterialEmission = float3(0., 0., 0.);
//float4 params_nx = tex_paramx.Sample(diffuse_sampler, material.m_TexCoord);
//float4 params_ny = tex_paramy.Sample(diffuse_sampler, material.m_TexCoord);
//material.m_MaterialParams = float4(params_nx.xy, params_ny.yx);
//float3 normal = UnpackNormalXY(float2(params_nx.a, params_ny.a));
material.m_MaterialParams = tex_params.Sample(diffuse_sampler, material.m_TexCoord);
float3 normal = UnpackNormalXY(tex_normal.Sample(diffuse_sampler, material.m_TexCoord));
material.m_MaterialNormal = normalize(normal.x * material.m_Tangent + normal.y * material.m_Bitangent + normal.z * material.m_Normal);
//#if PASS & FORWARD_LIGHTING
// float NdotV = saturate(dot(material.m_MaterialNormal, -normalize(material.m_Position)));
// material.m_MaterialAlbedoAlpha.a = lerp(pow(1. - NdotV, 5.), 1., material.m_MaterialAlbedoAlpha.a);
//#endif
}

View File

@@ -0,0 +1,16 @@
#include "manul/material.hlsli"
#include "manul/color_transform.hlsli"
sampler diffuse_sampler : register(s0);
Texture2D diffuse : register(t0);
#include "manul/alpha_mask.hlsli"
void MaterialPass(inout MaterialData material) {
material.m_MaterialAlbedoAlpha = diffuse.Sample(diffuse_sampler, material.m_TexCoord);
material.m_MaterialAlbedoAlpha.rgb = saturate(REC709_to_XYZ(material.m_MaterialAlbedoAlpha.rgb * g_DrawConstants.m_Diffuse));
AlphaMask(material.m_MaterialAlbedoAlpha.a);
material.m_MaterialEmission = g_DrawConstants.m_SelfIllum * material.m_MaterialAlbedoAlpha.rgb;
material.m_MaterialParams = float4(0., 1., 1., 0.);
material.m_MaterialNormal = material.m_Normal;
}

View File

@@ -0,0 +1,22 @@
#include "manul/math.hlsli"
#include "manul/material.hlsli"
#include "manul/color_transform.hlsli"
sampler diffuse_sampler : register(s0);
Texture2D diffuse : register(t0);
Texture2D<float4> normalmap : register(t1);
#include "manul/alpha_mask.hlsli"
void MaterialPass(inout MaterialData material) {
material.m_MaterialAlbedoAlpha = diffuse.Sample(diffuse_sampler, material.m_TexCoord);
material.m_MaterialAlbedoAlpha.rgb = saturate(REC709_to_XYZ(material.m_MaterialAlbedoAlpha.rgb * g_DrawConstants.m_Diffuse));
AlphaMask(material.m_MaterialAlbedoAlpha.a);
material.m_MaterialEmission = g_DrawConstants.m_SelfIllum * material.m_MaterialAlbedoAlpha.rgb;
float4 normal_refl = normalmap.Sample(diffuse_sampler, material.m_TexCoord);
material.m_MaterialParams = float4(0., (1. - normal_refl.a) * (1. - normal_refl.a), 1., 0.);
float3 normal = UnpackNormalXY(normal_refl.xy);
material.m_MaterialNormal = normalize(normal.x * material.m_Tangent + normal.y * material.m_Bitangent + normal.z * material.m_Normal);
}

View File

@@ -0,0 +1,23 @@
#include "manul/math.hlsli"
#include "manul/material.hlsli"
#include "manul/color_transform.hlsli"
sampler diffuse_sampler : register(s0);
Texture2D diffuse : register(t0);
Texture2D<float3> specgloss : register(t1);
Texture2D<float2> normalmap : register(t2);
#include "manul/alpha_mask.hlsli"
void MaterialPass(inout MaterialData material) {
material.m_MaterialAlbedoAlpha = diffuse.Sample(diffuse_sampler, material.m_TexCoord);
material.m_MaterialAlbedoAlpha.rgb = saturate(REC709_to_XYZ(material.m_MaterialAlbedoAlpha.rgb * g_DrawConstants.m_Diffuse));
AlphaMask(material.m_MaterialAlbedoAlpha.a);
material.m_MaterialEmission = g_DrawConstants.m_SelfIllum * material.m_MaterialAlbedoAlpha.rgb;
float3 params = specgloss.Sample(diffuse_sampler, material.m_TexCoord);
material.m_MaterialParams = float4(params.b, 1. - params.g, 1., .5);
float3 normal = UnpackNormalXY(normalmap.Sample(diffuse_sampler, material.m_TexCoord));
material.m_MaterialNormal = normalize(normal.x * material.m_Tangent + normal.y * material.m_Bitangent + normal.z * material.m_Normal);
}

View File

@@ -0,0 +1,22 @@
#include "manul/math.hlsli"
#include "manul/material.hlsli"
#include "manul/color_transform.hlsli"
sampler diffuse_sampler : register(s0);
Texture2D diffuse : register(t0);
Texture2D<float4> normalmap : register(t1);
#include "manul/alpha_mask.hlsli"
void MaterialPass(inout MaterialData material) {
material.m_MaterialAlbedoAlpha = diffuse.Sample(diffuse_sampler, material.m_TexCoord);
material.m_MaterialAlbedoAlpha.rgb = saturate(REC709_to_XYZ(material.m_MaterialAlbedoAlpha.rgb * g_DrawConstants.m_Diffuse));
AlphaMask(material.m_MaterialAlbedoAlpha.a);
material.m_MaterialEmission = g_DrawConstants.m_SelfIllum * material.m_MaterialAlbedoAlpha.rgb;
float4 normal_refl = normalmap.Sample(diffuse_sampler, material.m_TexCoord);
material.m_MaterialParams = float4(0., (1. - normal_refl.a) * (1. - normal_refl.a), 1., 0.);
float3 normal = UnpackNormalXY(normal_refl.xy);
material.m_MaterialNormal = material.m_Normal;
}

View File

@@ -0,0 +1,21 @@
#include "manul/math.hlsli"
#include "manul/material.hlsli"
#include "manul/color_transform.hlsli"
sampler diffuse_sampler : register(s0);
Texture2D diffuse : register(t0);
Texture2D<float3> specgloss : register(t1);
#include "manul/alpha_mask.hlsli"
void MaterialPass(inout MaterialData material) {
material.m_MaterialAlbedoAlpha = diffuse.Sample(diffuse_sampler, material.m_TexCoord);
material.m_MaterialAlbedoAlpha.rgb = saturate(REC709_to_XYZ(material.m_MaterialAlbedoAlpha.rgb * g_DrawConstants.m_Diffuse));
AlphaMask(material.m_MaterialAlbedoAlpha.a);
material.m_MaterialEmission = g_DrawConstants.m_SelfIllum * material.m_MaterialAlbedoAlpha.rgb;
float3 params = specgloss.Sample(diffuse_sampler, material.m_TexCoord);
material.m_MaterialParams = float4(params.b, 1. - params.g, 1., .5);
material.m_MaterialNormal = material.m_Normal;
}

View File

@@ -0,0 +1,37 @@
#include "manul/math.hlsli"
#include "manul/material.hlsli"
#include "manul/color_transform.hlsli"
sampler diffuse_sampler : register(s0);
Texture2D<float3> diffuse : register(t0);
Texture2D<float2> normalmap : register(t1);
Texture2D<float2> dudvmap : register(t2);
void MaterialPass(inout MaterialData material) {
float2 tex_coord = material.m_TexCoord;
float move_factor = 0.;
#if PASS & FORWARD_LIGHTING
move_factor += (.02 * g_Time);
#endif
move_factor %= 1.;
float2 distorted_tex_coord = dudvmap.Sample(diffuse_sampler, float2(tex_coord.x + move_factor, tex_coord.y)) * .1;
distorted_tex_coord = tex_coord + float2(distorted_tex_coord.x , distorted_tex_coord.y + move_factor);
float2 total_distorted_tex_coord = (dudvmap.Sample(diffuse_sampler, distorted_tex_coord) * 2. - 1. ) * .05;
tex_coord += total_distorted_tex_coord;
material.m_MaterialAlbedoAlpha.rgb = diffuse.Sample(diffuse_sampler, tex_coord);
material.m_MaterialAlbedoAlpha.rgb = saturate(REC709_to_XYZ(material.m_MaterialAlbedoAlpha.rgb));
material.m_MaterialAlbedoAlpha.a = 1.;
material.m_MaterialEmission = 0;
material.m_MaterialParams = float4(0., .04, 1., .5);
#if PASS & FORWARD_LIGHTING
float4 fragment_ndc = float4(material.m_PositionNDC.xy, g_GbufferDepth[material.m_PixelCoord], 1.);
fragment_ndc = mul(g_InverseProjection, fragment_ndc);
fragment_ndc /= fragment_ndc.w;
float depth = min(0., (fragment_ndc.z - material.m_Position.z));
material.m_MaterialAlbedoAlpha.a = 1. - exp(depth * 2.5);
#endif
float3 normal = UnpackNormalXY(normalmap.Sample(diffuse_sampler, tex_coord));
material.m_MaterialNormal = normalize(normal.x * material.m_Tangent + normal.y * material.m_Bitangent + normal.z * material.m_Normal);
}

View File

@@ -0,0 +1,17 @@
#pragma pack_matrix(column_major)
sampler diffuse_sampler : register(s0);
Texture2D diffuse : register(t0);
#include "manul/draw_constants_shadow.hlsli"
#include "manul/alpha_mask.hlsli"
struct VertexOutput {
float2 m_TexCoord : TexCoord;
};
void main(in VertexOutput ps_in) {
float4 color = diffuse.Sample(diffuse_sampler, ps_in.m_TexCoord);
AlphaMask(color.a);
}

View File

@@ -0,0 +1,22 @@
#pragma pack_matrix(column_major)
struct VertexInput {
float3 m_Position : Position;
float3 m_Normal : Normal;
float2 m_TexCoord : TexCoord;
float4 m_Tangent : Tangent;
};
struct VertexOutput {
float2 m_TexCoord : TexCoord;
float4 m_PositionSV : SV_Position;
};
#include "manul/draw_constants_shadow.hlsli"
VertexOutput main(in VertexInput vs_in) {
VertexOutput result;
result.m_TexCoord = vs_in.m_TexCoord;
result.m_PositionSV = mul(g_DrawConstants.m_ModelViewProjection, float4(vs_in.m_Position, 1.));
return result;
}

49
manul/shaders/skybox.hlsl Normal file
View File

@@ -0,0 +1,49 @@
struct VertexOutput {
float2 m_Position : Position;
float4 m_PositionSV : SV_Position;
};
struct PixelOutput {
float3 m_Color : SV_Target0;
float3 m_Emission : SV_Target1;
float4 m_Params : SV_Target2;
float3 m_Normal : SV_Target3;
float3 m_Motion : SV_Target4;
};
cbuffer SkyboxPixelConstants : register(b0) {
float4x4 g_InverseViewProjection;
float4x4 g_HistoryReproject;
float3 g_SunDirection;
float g_Altitude;
float3 g_MoonDirection;
}
sampler g_SkyboxSampler : register(s0);
TextureCube g_Skybox : register(t0);
#include "manul/sky.hlsli"
PixelOutput main(VertexOutput ps_in) {
PixelOutput result;
result.m_Color = 0..xxx;
result.m_Emission = 1..xxx;
result.m_Params = 0..xxxx;
result.m_Normal = 0..xxx;
result.m_Motion = 0..xxx;
float4 positionNdc = float4((ps_in.m_Position - .5.xx) * float2(2., -2.), 1., 1.);
float3 viewDir = normalize(mul(g_InverseViewProjection, positionNdc).xyz);
result.m_Emission = 1.e-7;
CalcSun(result.m_Emission, viewDir, g_SunDirection, g_Altitude);
CalcMoon(result.m_Emission, viewDir, g_MoonDirection, g_SunDirection, g_Altitude);
CalcAtmosphere(result.m_Emission, viewDir, g_SunDirection);
//result.m_Emission = g_Skybox.Sample(g_SkyboxSampler, normalize(mul(g_InverseViewProjection, positionNdc).xyz)).rgb;
//result.m_Emission = 0.; //Sky(normalize(mul(g_InverseViewProjection, positionNdc).xyz), g_SunDirection, g_Altitude);
float4 positionReproject = mul(g_HistoryReproject, positionNdc);
positionReproject.xyz /= positionReproject.w;
result.m_Motion = (positionNdc - positionReproject).xyz;
result.m_Motion.xy = result.m_Motion.xy * .5.xx;
//result.m_Output = source.Sample(source_sampler, ps_in.m_Position);
return result;
}

187
manul/shaders/tonemap.hlsl Normal file
View File

@@ -0,0 +1,187 @@
#include "manul/color_transform.hlsli"
#define MA_TONEMAP_SRGB_REC709 0
#define MA_TONEMAP_LINEAR_REC2020 1
struct TonemapConstants {
int m_TonemapFunction;
float m_SceneExposure;
float m_SceneNits;
float m_SceneGamma;
};
#ifdef SPIRV
[[vk::push_constant]] ConstantBuffer<TonemapConstants> g_TonemapConstants;
#else
cbuffer g_Const : register(b0) { TonemapConstants g_TonemapConstants; }
#endif
struct VertexOutput {
float2 m_Position : Position;
float4 m_PositionSV : SV_Position;
};
struct PixelOutput {
float4 m_Output : SV_Target0;
};
sampler source_sampler : register(s0);
Texture2D source : register(t0);
Texture2D<float3> noise : register(t1);
float3 ACESFilm(float3 x)
{
float a = 2.51f;
float b = 0.03f;
float c = 2.43f;
float d = 0.59f;
float e = 0.14f;
return (x*(a*x+b))/(x*(c*x+d)+e);
}
float luminance(float3 v)
{
return dot(v, float3(0.2126f, 0.7152f, 0.0722f));
}
float3 reinhard_jodie(float3 v)
{
float l = luminance(v);
float3 tv = v / (1.0f + v);
return lerp(v / (1.0f + l), tv, tv);
}
float3 reinhard_extended_luminance(float3 v, float max_white_l)
{
float l_old = luminance(v);
float numerator = l_old * (1.0f + (l_old / (max_white_l * max_white_l)));
float l_new = numerator / (1.0f + l_old);
return v * l_new / l_old;
}
float3 ApplySRGBCurve( float3 x )
{
// Approximately pow(x, 1.0 / 2.2)
return select(x < 0.0031308, 12.92 * x, 1.055 * pow(x, 1.0 / 2.4) - 0.055);
}
float3 Rec709ToRec2020(float3 color)
{
static const float3x3 conversion =
{
0.627402, 0.329292, 0.043306,
0.069095, 0.919544, 0.011360,
0.016394, 0.088028, 0.895578
};
return mul(conversion, color);
}
float3 LinearToST2084(float3 color)
{
float m1 = 2610.0 / 4096.0 / 4;
float m2 = 2523.0 / 4096.0 * 128;
float c1 = 3424.0 / 4096.0;
float c2 = 2413.0 / 4096.0 * 32;
float c3 = 2392.0 / 4096.0 * 32;
float3 cp = pow(abs(color), m1);
return pow((c1 + c2 * cp) / (1 + c3 * cp), m2);
}
float3 filmicF(float3 x)
{
float A = 0.22f;
float B = 0.30f;
float C = 0.10f;
float D = 0.20f;
float E = 0.01f;
float F = 0.30f;
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F)) - E/F;
}
float3 filmic(float3 x)
{
return filmicF(x) / filmicF(11.2);
}
static const float3x3 ACESInputMat =
{
{0.59719, 0.35458, 0.04823},
{0.07600, 0.90834, 0.01566},
{0.02840, 0.13383, 0.83777}
};
// ODT_SAT => XYZ => D60_2_D65 => sRGB
static const float3x3 ACESOutputMat =
{
{ 1.60475, -0.53108, -0.07367},
{-0.10208, 1.10813, -0.00605},
{-0.00327, -0.07276, 1.07602}
};
float3 RRTAndODTFit(float3 v)
{
float3 a = v * (v + 0.0245786f) - 0.000090537f;
float3 b = v * (0.983729f * v + 0.4329510f) + 0.238081f;
return a / b;
}
float3 ACESFitted(float3 color)
{
color = mul(ACESInputMat, color);
// Apply RRT and ODT
color = RRTAndODTFit(color);
color = mul(ACESOutputMat, color);
// Clamp to [0, 1]
//color = saturate(color);
return color;
}
PixelOutput main(VertexOutput ps_in) {
PixelOutput result;
//result.m_Output.rgb = pow(ACESFilm(source.Sample(source_sampler, ps_in.m_Position).rgb), 1./2.2);
result.m_Output.rgb = source[(uint2)ps_in.m_PositionSV.xy].rgb;
result.m_Output.rgb = pow(result.m_Output.rgb*g_TonemapConstants.m_SceneExposure, g_TonemapConstants.m_SceneGamma);
switch(g_TonemapConstants.m_TonemapFunction) {
case MA_TONEMAP_SRGB_REC709:
{
uint2 noise_size;
noise.GetDimensions(noise_size.x, noise_size.y);
float3 noise_sample = noise[ps_in.m_PositionSV.xy % noise_size];
result.m_Output.rgb = XYZ_to_REC709(result.m_Output.rgb);
result.m_Output.rgb = saturate(reinhard_jodie(result.m_Output.rgb));
//result.m_Output.rgb = saturate(XYZ_to_REC2020(result.m_Output.rgb));
ApplySRGBCurve(result.m_Output.rgb);
result.m_Output.rgb = floor(result.m_Output.rgb * 256. + noise_sample) / 255.;
}
break;
case MA_TONEMAP_LINEAR_REC2020:
{
const float st2084max = 10000.;
const float hdrScalar = g_TonemapConstants.m_SceneNits / st2084max;
//result.m_Output.rgb = XYZ_to_REC2020(result.m_Output.rgb);
//result.m_Output.rgb = ACESFilm(result.m_Output.rgb);
//const float3 LuminanceWeights = float3(0.299,0.587,0.114);
//float luminance = dot(LuminanceWeights, result.m_Output.rgb);
//result.m_Output.rgb = lerp(luminance.xxx, result.m_Output.rgb, 2.2);
result.m_Output.rgb = XYZ_to_REC709(result.m_Output.rgb);
result.m_Output.rgb = ACESFilm(result.m_Output.rgb);
result.m_Output.rgb = Rec709ToRec2020(result.m_Output.rgb);
result.m_Output.rgb = saturate(result.m_Output.rgb);
result.m_Output.rgb *= hdrScalar;
result.m_Output.rgb = LinearToST2084(result.m_Output.rgb);
}
break;
}
result.m_Output.a = 1.;
return result;
}