mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
support specular occlusion using bent normals
This commit is contained in:
@@ -78,7 +78,7 @@ void NvSsao::Init() {
|
||||
.setWidth(m_width)
|
||||
.setHeight(m_height)
|
||||
.setIsUAV(true)
|
||||
.setFormat(Format::R8_UINT)
|
||||
.setFormat(Format::R32_UINT)
|
||||
.setInitialState(ResourceStates::ShaderResource)
|
||||
.setKeepInitialState(true));
|
||||
|
||||
@@ -88,7 +88,7 @@ void NvSsao::Init() {
|
||||
.setWidth(m_width)
|
||||
.setHeight(m_height)
|
||||
.setIsUAV(true)
|
||||
.setFormat(Format::R8_UINT)
|
||||
.setFormat(Format::R32_UINT)
|
||||
.setInitialState(ResourceStates::ShaderResource)
|
||||
.setKeepInitialState(true));
|
||||
|
||||
@@ -98,7 +98,7 @@ void NvSsao::Init() {
|
||||
.setWidth(m_width)
|
||||
.setHeight(m_height)
|
||||
.setIsUAV(true)
|
||||
.setFormat(Format::R8_UNORM)
|
||||
.setFormat(Format::RGBA8_UNORM)
|
||||
.setIsTypeless(true)
|
||||
.setInitialState(ResourceStates::ShaderResource)
|
||||
.setKeepInitialState(true));
|
||||
@@ -129,27 +129,6 @@ void NvSsao::Init() {
|
||||
.addBindingLayout(blPrefilterDepths));
|
||||
}
|
||||
|
||||
{
|
||||
BindingLayoutHandle blPrefilterDepths;
|
||||
BindingSetDesc bsDescPrefilter =
|
||||
BindingSetDesc()
|
||||
.addItem(BindingSetItem::ConstantBuffer(0, m_constantBuffer))
|
||||
.addItem(BindingSetItem::Texture_SRV(0, m_gbuffer->m_gbuffer_depth))
|
||||
.addItem(BindingSetItem::Sampler(0, sampler_point));
|
||||
for (int i = 0; i < XE_GTAO_DEPTH_MIP_LEVELS; ++i) {
|
||||
bsDescPrefilter.addItem(
|
||||
BindingSetItem::Texture_UAV(i, m_workingDepths, Format::UNKNOWN,
|
||||
TextureSubresourceSet(i, 1, 0, 1)));
|
||||
}
|
||||
utils::CreateBindingSetAndLayout(m_backend->GetDevice(),
|
||||
ShaderType::Compute, 0, bsDescPrefilter,
|
||||
blPrefilterDepths, m_BSPrefilterDepths);
|
||||
m_PSOPrefilterDepths = m_backend->GetDevice()->createComputePipeline(
|
||||
ComputePipelineDesc()
|
||||
.setComputeShader(m_CSPrefilterDepths16x16)
|
||||
.addBindingLayout(blPrefilterDepths));
|
||||
}
|
||||
|
||||
{
|
||||
BindingLayoutHandle blGTAO;
|
||||
utils::CreateBindingSetAndLayout(
|
||||
@@ -157,8 +136,6 @@ void NvSsao::Init() {
|
||||
BindingSetDesc()
|
||||
.addItem(BindingSetItem::ConstantBuffer(0, m_constantBuffer))
|
||||
.addItem(BindingSetItem ::Texture_SRV(0, m_workingDepths))
|
||||
.addItem(
|
||||
BindingSetItem::Texture_SRV(1, m_gbuffer->m_gbuffer_normal))
|
||||
.addItem(BindingSetItem::Texture_UAV(0, m_workingAOTerm))
|
||||
.addItem(BindingSetItem::Texture_UAV(1, m_workingEdges))
|
||||
.addItem(BindingSetItem::Texture_UAV(2, m_debugImage))
|
||||
@@ -251,10 +228,10 @@ void NvSsao::Render(nvrhi::ICommandList* command_list,
|
||||
nvrhi::BindingSetItem::ConstantBuffer(0, m_constantBuffer))
|
||||
.addItem(nvrhi::BindingSetItem::Texture_SRV(0, ping))
|
||||
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
||||
1, m_gbuffer->m_gbuffer_normal))
|
||||
1, m_workingEdges))
|
||||
.addItem(nvrhi::BindingSetItem::Texture_UAV(
|
||||
0, last_pass ? m_outputAO.Get() : pong,
|
||||
nvrhi::Format::R8_UINT))
|
||||
nvrhi::Format::R32_UINT))
|
||||
.addItem(nvrhi::BindingSetItem::Texture_UAV(1, m_workingEdges))
|
||||
.addItem(nvrhi::BindingSetItem::Texture_UAV(2, m_debugImage))
|
||||
.addItem(nvrhi::BindingSetItem::Sampler(0, m_SamplerPoint)),
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
#include "math.hlsli"
|
||||
|
||||
#include "lighting_functions.hlsli"
|
||||
|
||||
#include "color_transform.hlsli"
|
||||
|
||||
#include "manul/gbuffer_ssao.hlsli"
|
||||
|
||||
struct ViewConstants {
|
||||
float4x4 m_inverse_model_view;
|
||||
float4x4 m_inverse_projection;
|
||||
};
|
||||
|
||||
struct PushConstantsSpotLight {
|
||||
float3 m_origin;
|
||||
float m_radius_sqr;
|
||||
float3 m_direction;
|
||||
float m_cos_inner_cone;
|
||||
float3 m_color;
|
||||
float m_cos_outer_cone;
|
||||
};
|
||||
|
||||
cbuffer g_ViewConst : register(b0) { ViewConstants g_View; }
|
||||
|
||||
#ifdef SPIRV
|
||||
[[vk::push_constant]] ConstantBuffer<PushConstantsSpotLight> g_SpotLight;
|
||||
#else
|
||||
cbuffer g_SpotLightConst : register(b1) { PushConstantsSpotLight g_SpotLight; }
|
||||
#endif
|
||||
|
||||
RWTexture2D<float4> g_OutDiffuse : register(u0);
|
||||
|
||||
Texture2D<float> g_GbufferDepth : register(t0);
|
||||
Texture2D<float3> g_GbufferNormal : register(t1);
|
||||
Texture2D<float4> g_GbufferParams : register(t2);
|
||||
Texture2D<float3> g_GbufferColor : register(t3);
|
||||
|
||||
float2 PixelToCS(in float2 pixel, in float2 size) {
|
||||
return ((pixel + .5) / size - .5) * float2(2., -2.);
|
||||
}
|
||||
|
||||
float3 ReconstructPos(in float2 cs, in float depth) {
|
||||
float4 ndc = float4(cs, depth, 1.);
|
||||
ndc = mul(g_View.m_inverse_projection, ndc);
|
||||
return ndc.xyz / ndc.w;
|
||||
}
|
||||
|
||||
[numthreads(8, 8, 1)]
|
||||
void CS_Clear(uint3 PixCoord : SV_DispatchThreadID, uint3 GroupID : SV_GroupID, uint GroupIndex : SV_GroupIndex) {
|
||||
uint2 pixel = PixCoord.xy;
|
||||
g_OutDiffuse[pixel].rgb = 0.;
|
||||
}
|
||||
|
||||
[numthreads(8, 8, 1)]
|
||||
void CS_Spotlight(uint3 PixCoord : SV_DispatchThreadID, uint3 GroupID : SV_GroupID, uint GroupIndex : SV_GroupIndex) {
|
||||
uint2 gbuffer_dimensions;
|
||||
uint2 pixel = PixCoord.xy;
|
||||
|
||||
g_OutDiffuse.GetDimensions(gbuffer_dimensions.x, gbuffer_dimensions.y);
|
||||
float3 position = ReconstructPos(PixelToCS(PixCoord.xy, gbuffer_dimensions), g_GbufferDepth[pixel]);
|
||||
float3 view = mul((float3x3)g_View.m_inverse_model_view, position);
|
||||
|
||||
float3 L_offset = g_SpotLight.m_origin - view;
|
||||
float3 L = normalize(L_offset);
|
||||
if(dot(L_offset, L_offset) > g_SpotLight.m_radius_sqr) return;
|
||||
|
||||
float3 albedo = g_GbufferColor[pixel];
|
||||
float4 params = g_GbufferParams[pixel];
|
||||
float3 normal = UnpackNormalXYZ(g_GbufferNormal[pixel]);
|
||||
|
||||
SurfaceData surface_data;
|
||||
surface_data.m_Albedo = albedo;
|
||||
surface_data.m_Alpha = 1.;
|
||||
surface_data.m_Metalness = params.r;
|
||||
surface_data.m_Roughness = params.g;
|
||||
#ifdef GBUFFER_SSAO_HLSLI
|
||||
surface_data.m_DiffuseOcclusion = min(params.b, GetSSAO(pixel));
|
||||
#else
|
||||
surface_data.m_DiffuseOcclusion = params.b;
|
||||
#endif
|
||||
surface_data.m_Normal = mul((float3x3)g_View.m_inverse_model_view, normal);
|
||||
surface_data.m_View = -normalize(view);
|
||||
surface_data.m_Reflect = reflect(-surface_data.m_View, surface_data.m_Normal);
|
||||
surface_data.m_NdotV = max(dot(surface_data.m_Normal, surface_data.m_View), 0.);
|
||||
surface_data.m_SpecularF0 = float3(.04, .04, .04) * params.a * 2.;
|
||||
surface_data.m_SpecularF0 = lerp(surface_data.m_SpecularF0, surface_data.m_Albedo, surface_data.m_Metalness);
|
||||
surface_data.m_SpecularF = FresnelSchlickRoughness(surface_data.m_NdotV, surface_data.m_SpecularF0, surface_data.m_Roughness);
|
||||
surface_data.m_HorizonFading = 1.6;
|
||||
surface_data.m_SpecularOcclusion = ComputeSpecOcclusion(surface_data.m_NdotV, surface_data.m_DiffuseOcclusion, surface_data.m_Roughness);
|
||||
|
||||
float3 lit = float3(0., 0., 0.);
|
||||
|
||||
DirectionalLight directionalLight;
|
||||
directionalLight.m_LightVector = L;
|
||||
directionalLight.m_Color = max(REC709_to_XYZ(g_SpotLight.m_color), 0.);
|
||||
ApplyDirectionalLight(lit, directionalLight, surface_data, 1.);
|
||||
|
||||
|
||||
float cone = saturate((dot(L, -g_SpotLight.m_direction) - g_SpotLight.m_cos_inner_cone) / (g_SpotLight.m_cos_outer_cone - g_SpotLight.m_cos_inner_cone));
|
||||
float attenuation = 1. / dot(L_offset, L_offset) * (1. - cone);
|
||||
|
||||
g_OutDiffuse[pixel].rgb += lit * attenuation;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef GBUFFER_SSAO_HLSLI
|
||||
#define GBUFFER_SSAO_HLSLI
|
||||
Texture2D<float> g_SSAO : register(t5);
|
||||
Texture2D<float4> g_SSAO : register(t5);
|
||||
|
||||
float4 R8G8B8A8_UNORM_to_FLOAT4( uint packedInput )
|
||||
{
|
||||
@@ -19,8 +19,11 @@ void DecodeVisibilityBentNormal( const uint packedValue, out float visibility, o
|
||||
visibility = decoded.w;
|
||||
}
|
||||
|
||||
float GetSSAO(in uint2 pixel_position) {
|
||||
return g_SSAO[pixel_position];
|
||||
float4 GetBentNormal(in uint2 pixel_position) {
|
||||
float4 bent_normal = g_SSAO[pixel_position];
|
||||
bent_normal.xyz = 2. * bent_normal.xyz - 1.;
|
||||
bent_normal.z *= -1.;
|
||||
return bent_normal;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,6 +40,12 @@ void ApplyMaterialLighting(out float4 lit, in MaterialData material)
|
||||
// Camera-centric world position
|
||||
float3 view = mul((float3x3)g_InverseModelView, material.m_Position);
|
||||
|
||||
#ifdef GBUFFER_SSAO_HLSLI
|
||||
float4 bent_normal = GetBentNormal(pixel_position);
|
||||
bent_normal.a = min(material.m_MaterialParams.b, bent_normal.a);
|
||||
bent_normal.xyz = mul((float3x3)g_InverseModelView, bent_normal.xyz);
|
||||
#endif
|
||||
|
||||
// Convert material to surface data
|
||||
SurfaceData surface_data;
|
||||
surface_data.m_Albedo = clamp(material.m_MaterialAlbedoAlpha.rgb, .02, .9);
|
||||
@@ -47,7 +53,7 @@ void ApplyMaterialLighting(out float4 lit, in MaterialData material)
|
||||
surface_data.m_Metalness = material.m_MaterialParams.r;
|
||||
surface_data.m_Roughness = material.m_MaterialParams.g;
|
||||
#ifdef GBUFFER_SSAO_HLSLI
|
||||
surface_data.m_DiffuseOcclusion = min(material.m_MaterialParams.b, GetSSAO(pixel_position));
|
||||
surface_data.m_DiffuseOcclusion = bent_normal.a;
|
||||
#else
|
||||
surface_data.m_DiffuseOcclusion = material.m_MaterialParams.b;
|
||||
#endif
|
||||
@@ -59,7 +65,12 @@ void ApplyMaterialLighting(out float4 lit, in MaterialData material)
|
||||
surface_data.m_SpecularF0 = lerp(surface_data.m_SpecularF0, surface_data.m_Albedo, surface_data.m_Metalness);
|
||||
surface_data.m_SpecularF = FresnelSchlickRoughness(surface_data.m_NdotV, surface_data.m_SpecularF0, surface_data.m_Roughness);
|
||||
surface_data.m_HorizonFading = 1.6;
|
||||
#ifdef GBUFFER_SSAO_HLSLI
|
||||
float BNdotR = max(0., dot(surface_data.m_Reflect, bent_normal.xyz));
|
||||
surface_data.m_SpecularOcclusion = ComputeSpecOcclusion(BNdotR, surface_data.m_DiffuseOcclusion, surface_data.m_Roughness);
|
||||
#else
|
||||
surface_data.m_SpecularOcclusion = ComputeSpecOcclusion(surface_data.m_NdotV, surface_data.m_DiffuseOcclusion, surface_data.m_Roughness);
|
||||
#endif
|
||||
|
||||
lit.rgb = material.m_MaterialEmission * surface_data.m_Alpha;
|
||||
lit.a = 1. - (saturate((1. - surface_data.m_Alpha) * lerp(1. - dot(surface_data.m_SpecularF, 1./3.), 0., surface_data.m_Metalness)));
|
||||
|
||||
@@ -13,6 +13,7 @@ templates:
|
||||
VA_COMPILED_AS_SHADER_CODE: 1
|
||||
VA_SATURATE: saturate
|
||||
XE_GTAO_GENERATE_NORMALS_INPLACE: 1
|
||||
XE_GTAO_COMPUTE_BENT_NORMALS: 1
|
||||
envmap:
|
||||
source: envmap
|
||||
target: compute
|
||||
@@ -22,9 +23,6 @@ templates:
|
||||
bloom:
|
||||
source: manul/bloom
|
||||
target: compute
|
||||
gbuffer_lights:
|
||||
source: manul/gbuffer_lights
|
||||
target: compute
|
||||
shaders:
|
||||
materials:
|
||||
# Material shaders
|
||||
@@ -327,13 +325,6 @@ shaders:
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user