xxxkxxx

Members
  • Content count

    0
  • Joined

  • Last visited

Community Reputation

138 Neutral

About xxxkxxx

  • Rank
    Newbie
  1. Specular convolution problem.

    Problem was solved by changing float texelSolidAngle = (4.0 * PI) / (6.0 * currentResolution * currentResolution); float environmentMapMipLevel = clamp(0.5 * log2(sampleSolidAngle / texelSolidAngle), 0.0, activeMipsCountZeroBased); to float texelSolidAngle = (4.0 * PI) / (6.0 * Mip0Resolution * Mip0Resolution); float environmentMapMipLevel = max(0.5 * log2(sampleSolidAngle / texelSolidAngle) + 1.0, 0.0);
  2. Hello guys! Another IBL / convolution topic here. I was doing specular-ibl-ggx-convolution and had encountered following artefact. It happens on +Z and -Z faces. This is -Z cubemap face viewed in Renderdoc (resolutions are 256x256, 128x128, 64x64, cubemap is little bit washed out because it is in float16 hdr format, so I had changed range to better visualize artefact): [attachment=35679:bug.png] In final rendered image looks like that: [attachment=35680:bug1.PNG] Looks like it "swirls" at poles along Z axis. Diameter of the "dot" in the middle depends on 0.999 number from: float3 tangentY = ((abs(N.z) < 0.999) ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0)); Code for convolution is pretty standard:   uint ReverseBits(in uint bits) { bits = (bits << 16u) | (bits >> 16u); bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); return bits; } float2 Hammersley(in uint i, in uint N) { return float2(float(i) / float(N), float(ReverseBits(i)) * 2.3283064365386963e-10); } float3 ImportanceSampleGGX(in float roughness, in float2 eta) { float phi = 2.0 * PI * eta.x; float cosTheta = sqrt((1.0 - eta.y) / ((roughness * roughness - 1.0) * eta.y + 1.0)); float sinTheta = sqrt(1.0 - cosTheta * cosTheta); float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); return H; } float TrowbridgeReitzGGX(in float roughness, in float NdotH) { float a2 = roughness * roughness; float denominator = (a2 * NdotH - NdotH) * NdotH + 1.0; return a2 / (PI * denominator * denominator); } float3 ConvolveEnvironmentMap(in float linearRoughness, in float3 V, in SamplerState trilinearSampler, in TextureCube<float4> environmentMap, in float currentResolution, in float activeMipsCountZeroBased, in uint currentMip) { float3 N = V; float3 tangentY = ((abs(N.z) < 0.999) ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0)); float3 tangentX = normalize(cross(tangentY, N)); tangentY = cross(N, tangentX); float3x3 W = float3x3(tangentX, tangentY, N); float roughness = linearRoughness * linearRoughness; float3 Integral = float3(0.0, 0.0, 0.0); float Weight = 0.0; const uint samplesCount = 32; for (uint i = 0; i < samplesCount; i++) { float2 eta = Hammersley(i, samplesCount); float3 H = mul(ImportanceSampleGGX(roughness, eta), W); float3 L = 2.0 * dot(V, H) * H - V; float NdotL = saturate(dot(N, L)); float NdotH = saturate(dot(N, H)); float LdotH = saturate(dot(L, H)); float pdf = DTrowbridgeReitzGGX(roughness, NdotH) * 0.25; float sampleSolidAngle = 1.0 / (float(samplesCount0) * pdf); float texelSolidAngle = (4.0 * PI) / (6.0 * currentResolution * currentResolution); float environmentMapMipLevel = clamp(0.5 * log2(sampleSolidAngle / texelSolidAngle), 0.0, activeMipsCountZeroBased); float3 Li = environmentMap.SampleLevel(trilinearSampler, L, environmentMapMipLevel).rgb; Integral += Li * NdotL; Weight += NdotL; } return Integral / Weight; } Here's calling compute shader: cbuffer ConvolutionData : register(b0) { ... } SamplerState LinearClampSampler : register(s0); TextureCube Input : register(t0); RWTexture2DArray<float4> CurrentMipSlice : register(u0); [numthreads(16, 16, 1)] void cs_main( uint3 groupID : SV_GroupID, uint3 dispatchThreadID : SV_DispatchThreadID, uint3 groupThreadID : SV_GroupThreadID, uint groupIndex : SV_GroupIndex) { const float2 uv = ((float2(dispatchThreadID.xy) + 0.5) * InvCubemapResolution) * 2.0 - 1.0; const float3 V0 = normalize(float3(1.0, -uv.y, -uv.x)); const float3 V1 = normalize(float3(-1.0, -uv.y, uv.x)); const float3 V2 = normalize(float3(uv.x, 1.0, uv.y)); const float3 V3 = normalize(float3(uv.x, -1.0, -uv.y)); const float3 V4 = normalize(float3(uv.x, -uv.y, 1.0)); const float3 V5 = normalize(float3(-uv.x, -uv.y, -1.0)); CurrentMipSlice[uint3(dispatchThreadID.xy, 0)] = float4(ConvolveEnvironmentMap(V0, ...), 1.0); CurrentMipSlice[uint3(dispatchThreadID.xy, 1)] = float4(ConvolveEnvironmentMap(V1, ...), 1.0); CurrentMipSlice[uint3(dispatchThreadID.xy, 2)] = float4(ConvolveEnvironmentMap(V2, ...), 1.0); CurrentMipSlice[uint3(dispatchThreadID.xy, 3)] = float4(ConvolveEnvironmentMap(V3, ...), 1.0); CurrentMipSlice[uint3(dispatchThreadID.xy, 4)] = float4(ConvolveEnvironmentMap(V4, ...), 1.0); CurrentMipSlice[uint3(dispatchThreadID.xy, 5)] = float4(ConvolveEnvironmentMap(V5, ...), 1.0); } Sample count is pretty low (32), but changing it to 64 doesn't really help. Also because I'm using FIS approach, it should look better than that, I think. [attachment=35681:bug2.PNG] Appreciate any help, thanks!