Envmap improvements

This commit is contained in:
Turánszki János
2023-08-30 09:21:42 +02:00
committed by GitHub
parent af4175a775
commit 41f29e2a1d
7 changed files with 98 additions and 59 deletions
@@ -70,7 +70,7 @@ float4 main(VertextoPixel input) : SV_TARGET
Surface surface;
surface.init();
surface.create(material, color, 0);
surface.create(material, color, surfacemap_simple);
surface.P = input.P;
surface.N = N;
surface.V = 0;
+26 -11
View File
@@ -3,7 +3,8 @@
PUSHCONSTANT(push, FilterEnvmapPushConstants);
// From "Real Shading in UnrealEngine 4" by Brian Karis
// From "Real Shading in UnrealEngine 4" by Brian Karis, page 4
// https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
float3 ImportanceSampleGGX(float2 Xi, float Roughness, float3 N)
{
float a = Roughness * Roughness;
@@ -14,7 +15,11 @@ float3 ImportanceSampleGGX(float2 Xi, float Roughness, float3 N)
H.x = SinTheta * cos(Phi);
H.y = SinTheta * sin(Phi);
H.z = CosTheta;
return H;
float3 UpVector = abs(N.z) < 0.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 TangentX * H.x + TangentY * H.y + N * H.z;
}
[numthreads(GENERATEMIPCHAIN_2D_BLOCK_SIZE, GENERATEMIPCHAIN_2D_BLOCK_SIZE, 1)]
@@ -27,20 +32,30 @@ void main(uint3 DTid : SV_DispatchThreadID)
float2 uv = (DTid.xy + 0.5f) * push.filterResolution_rcp.xy;
float3 N = uv_to_cubemap(uv, DTid.z);
float3x3 tangentSpace = get_tangentspace(N);
float3 V = N;
float4 col = 0;
float Roughness = push.filterRoughness;
for (uint i = 0; i < push.filterRayCount; ++i)
uint rayCount = push.filterRayCount;
for (uint i = 0; i < rayCount; ++i)
{
float2 hamm = hammersley2d(i, push.filterRayCount);
float3 hemisphere = ImportanceSampleGGX(hamm, push.filterRoughness, N);
float3 cone = mul(hemisphere, tangentSpace);
col += input.SampleLevel(sampler_linear_clamp, cone, 0);
float2 Xi = hammersley2d(i, rayCount);
float3 H = ImportanceSampleGGX(Xi, Roughness, N);
float3 L = 2 * dot(V, H) * H - V;
float NoL = saturate(dot(N, L));
if (NoL > 0)
{
col += input.SampleLevel(sampler_linear_clamp, L, 0) * NoL;
}
}
if(col.a > 0)
{
col /= col.a;
}
col /= (float)push.filterRayCount;
output[uint3(DTid.xy, DTid.z)] = col;
}
+1 -1
View File
@@ -29,7 +29,7 @@ float4 main(VertexToPixel input) : SV_Target
Surface surface;
surface.init();
surface.create(material, color, 0);
surface.create(material, color, surfacemap_simple);
surface.P = input.pos3D;
surface.N = input.nor;
surface.V = V;
+1 -1
View File
@@ -379,7 +379,7 @@ inline float3 EnvironmentReflection_Global(in Surface surface)
GetDynamicSkyColor(float3(0, 1, 0), false, false, true),
saturate(surface.R.y * 0.5 + 0.5));
envColor = lerp(skycolor_real, skycolor_rough, saturate(surface.roughness)) * surface.F;
envColor = lerp(skycolor_real, skycolor_rough, surface.roughness) * surface.F;
#else
+40 -10
View File
@@ -4,12 +4,32 @@
#define max3(v) max(max(v.x, v.y), v.z)
// hard coded value for surfaces with simplified lighting:
// occlusion = 1
// roughness = 1
// metalness = 0
// reflectance = 0
static const float4 surfacemap_simple = float4(1, 1, 0, 0);
static const float roughness_min = 0.045f;
float3 F_Schlick(const float3 f0, float f90, float VoH)
{
// Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"
return f0 + (f90 - f0) * pow5(1.0 - VoH);
}
// https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
half3 EnvBRDFApprox(half3 SpecularColor, half Roughness, half NoV)
{
const half4 c0 = { -1, -0.0275, -0.572, 0.022 };
const half4 c1 = { 1, 0.0425, 1.04, -0.04 };
half4 r = Roughness * c0 + c1;
half a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
half2 AB = half2(-1.04, 1.04) * a004 + r.zw;
return SpecularColor * AB.x + AB.y;
}
struct SheenSurface
{
float3 color;
@@ -222,26 +242,31 @@ struct Surface
create(material);
}
inline void update()
{
roughness = clamp(roughness, 0.045, 1);
roughnessBRDF = roughness * roughness;
roughness = saturate(roughness);
roughnessBRDF = sqr(max(roughness, roughness_min)); // only clamp min for BRDF!
#ifdef SHEEN
sheen.roughness = clamp(sheen.roughness, 0.045, 1);
sheen.roughnessBRDF = sheen.roughness * sheen.roughness;
sheen.roughness = saturate(sheen.roughness);
sheen.roughnessBRDF = sqr(max(sheen.roughness, roughness_min)); // only clamp min for BRDF!
#endif // SHEEN
#ifdef CLEARCOAT
clearcoat.roughness = clamp(clearcoat.roughness, 0.045, 1);
clearcoat.roughnessBRDF = clearcoat.roughness * clearcoat.roughness;
clearcoat.roughness = saturate(clearcoat.roughness);
clearcoat.roughnessBRDF = sqr(max(clearcoat.roughness, roughness_min)); // only clamp min for BRDF!
#endif // CLEARCOAT
NdotV = saturate(dot(N, V) + 1e-5);
f90 = saturate(50.0 * dot(f0, 0.33));
#ifdef CARTOON
F = F_Schlick(f0, f90, NdotV);
#else
F = EnvBRDFApprox(f0, roughness, NdotV);
#endif // CARTOON
R = -reflect(V, N);
@@ -252,7 +277,12 @@ struct Surface
#endif // SHEEN
#ifdef CLEARCOAT
clearcoat.F = F_Schlick(f0, f90, saturate(dot(clearcoat.N, V) + 1e-5));
float clearcoatNdotV = saturate(dot(clearcoat.N, V) + 1e-5);
#ifdef CARTOON
clearcoat.F = F_Schlick(f0, f90, clearcoatNdotV);
#else
clearcoat.F = EnvBRDFApprox(f0, clearcoat.roughness, clearcoatNdotV);
#endif // CARTOON
clearcoat.F *= clearcoat.factor;
clearcoat.R = -reflect(V, clearcoat.N);
#endif // CLEARCOAT
@@ -544,7 +574,7 @@ struct Surface
if (simple_lighting)
{
surfaceMap = 0;
surfaceMap = surfacemap_simple;
}
#ifdef SURFACE_LOAD_QUAD_DERIVATIVES
+28 -34
View File
@@ -7642,9 +7642,10 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd)
device->BindComputeShader(&shaders[CSTYPE_FILTERENVMAP], cmd);
desc.width = std::max(1u, desc.width >> (desc.mip_levels - 1));
desc.height = std::max(1u, desc.height >> (desc.mip_levels - 1));
for (uint32_t i = desc.mip_levels - 1; i > 0; --i)
int mip_start = desc.mip_levels - 1;
desc.width = std::max(1u, desc.width >> mip_start);
desc.height = std::max(1u, desc.height >> mip_start);
for (int i = mip_start; i > 0; --i)
{
{
GPUBarrier barriers[] = {
@@ -7664,8 +7665,15 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd)
push.filterResolution_rcp.x = 1.0f / push.filterResolution.x;
push.filterResolution_rcp.y = 1.0f / push.filterResolution.y;
push.filterRoughness = (float)i / (float)desc.mip_levels;
push.filterRayCount = 128;
push.texture_input = device->GetDescriptorIndex(&vis.scene->envrenderingColorBuffer, SubresourceType::SRV, std::max(0, (int)i - 2));
if (probe.IsRealTime())
{
push.filterRayCount = 128;
}
else
{
push.filterRayCount = 1024;
}
push.texture_input = device->GetDescriptorIndex(&vis.scene->envrenderingColorBuffer, SubresourceType::SRV, std::max(0, (int)i - 1));
push.texture_output = device->GetDescriptorIndex(&vis.scene->envrenderingColorBuffer, SubresourceType::UAV, i);
device->PushConstants(&push, sizeof(push), cmd);
@@ -7703,6 +7711,7 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd)
EnvironmentProbeComponent probe;
probe.textureIndex = 0;
probe.position = vis.camera->Eye;
probe.SetRealTime(true);
AABB probe_aabb;
probe_aabb.layerMask = 0;
@@ -8728,7 +8737,6 @@ void BlockCompress(const Texture& texture_src, const Texture& texture_bc, Comman
desc.height = std::max(1u, texture_bc.desc.height / block_size);
desc.bind_flags = BindFlag::UNORDERED_ACCESS;
desc.layout = ResourceState::UNORDERED_ACCESS;
desc.mip_levels = GetMipCount(desc.width, desc.height);
Texture bc_raw_dest;
{
@@ -8797,22 +8805,14 @@ void BlockCompress(const Texture& texture_src, const Texture& texture_bc, Comman
bc_raw_desc.height = std::max(bc_raw->desc.height, bc_raw_desc.height);
bc_raw_desc.width = wi::math::GetNextPowerOfTwo(bc_raw_desc.width);
bc_raw_desc.height = wi::math::GetNextPowerOfTwo(bc_raw_desc.height);
bc_raw_desc.mip_levels = GetMipCount(bc_raw_desc.width, bc_raw_desc.height);
device->CreateTexture(&bc_raw_desc, nullptr, bc_raw);
device->SetName(bc_raw, "bc_raw");
for (uint32_t i = 0; i < bc_raw->desc.mip_levels; ++i)
{
int subresource_index = device->CreateSubresource(bc_raw, SubresourceType::UAV, 0, bc_raw_desc.array_size, i, 1);
assert(subresource_index == i);
}
std::string info;
info += "BlockCompress created a new raw block texture to fit request: " + std::string(GetFormatString(texture_bc.desc.format)) + " (" + std::to_string(texture_bc.desc.width) + ", " + std::to_string(texture_bc.desc.height) + ")";
info += "\n\tFormat = ";
info += GetFormatString(bc_raw_desc.format);
info += "\n\tResolution = " + std::to_string(bc_raw_desc.width) + " * " + std::to_string(bc_raw_desc.height);
info += "\n\tMip Levels = " + std::to_string(bc_raw_desc.mip_levels);
info += "\n\tArray Size = " + std::to_string(bc_raw_desc.array_size);
size_t total_size = 0;
total_size += ComputeTextureMemorySizeInBytes(bc_raw_desc);
@@ -8823,28 +8823,22 @@ void BlockCompress(const Texture& texture_src, const Texture& texture_bc, Comman
bc_raw_dest = *bc_raw;
}
const uint32_t mip_levels = std::min(desc.mip_levels, std::min(texture_src.desc.mip_levels, texture_bc.desc.mip_levels));
for (uint32_t mip = 0; mip < mip_levels; ++mip)
for (uint32_t mip = 0; mip < texture_bc.desc.mip_levels; ++mip)
{
const uint32_t width = std::max(1u, desc.width >> mip);
const uint32_t height = std::max(1u, desc.height >> mip);
device->BindResource(&texture_src, 0, cmd, texture_src.desc.mip_levels == 1 ? -1 : mip);
device->BindUAV(&bc_raw_dest, 0, cmd, mip);
device->BindUAV(&bc_raw_dest, 0, cmd);
device->Dispatch((width + 7u) / 8u, (height + 7u) / 8u, desc.array_size, cmd);
}
GPUBarrier barriers[] = {
GPUBarrier::Image(&bc_raw_dest, ResourceState::UNORDERED_ACCESS, ResourceState::COPY_SRC),
GPUBarrier::Image(&texture_bc, texture_bc.desc.layout, ResourceState::COPY_DST),
};
device->Barrier(barriers, arraysize(barriers), cmd);
GPUBarrier barriers[] = {
GPUBarrier::Image(&bc_raw_dest, ResourceState::UNORDERED_ACCESS, ResourceState::COPY_SRC),
GPUBarrier::Image(&texture_bc, texture_bc.desc.layout, ResourceState::COPY_DST),
};
device->Barrier(barriers, arraysize(barriers), cmd);
for (uint32_t slice = 0; slice < desc.array_size; ++slice)
{
for (uint32_t mip = 0; mip < texture_bc.desc.mip_levels; ++mip)
for (uint32_t slice = 0; slice < desc.array_size; ++slice)
{
const uint32_t width = std::max(1u, desc.width >> mip);
const uint32_t height = std::max(1u, desc.height >> mip);
Box box;
box.left = 0;
box.right = width;
@@ -8855,18 +8849,18 @@ void BlockCompress(const Texture& texture_src, const Texture& texture_bc, Comman
device->CopyTexture(
&texture_bc, 0, 0, 0, mip, dst_slice_offset + slice,
&bc_raw_dest, std::min(mip, bc_raw_dest.desc.mip_levels - 1), slice,
&bc_raw_dest, 0, slice,
cmd,
&box
);
}
}
for (int i = 0; i < arraysize(barriers); ++i)
{
std::swap(barriers[i].image.layout_before, barriers[i].image.layout_after);
for (int i = 0; i < arraysize(barriers); ++i)
{
std::swap(barriers[i].image.layout_before, barriers[i].image.layout_after);
}
device->Barrier(barriers, arraysize(barriers), cmd);
}
device->Barrier(barriers, arraysize(barriers), cmd);
device->EventEnd(cmd);
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wi::version
// minor features, major updates, breaking compatibility changes
const int minor = 71;
// minor bug fixes, alterations, refactors, updates
const int revision = 280;
const int revision = 281;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);