Trying To Blur A Cubemap, But Retain WorldSpace Projection

Hello folks,

I’m trying to blur a cubemap that I’m projecting into the world in a post process material. Projecting the cubemap from a specific position in world space is easy, but I’m struggling to figure out a decent method of blurring it. The cubemap is sourced from a low resolution render target that gets updated every set interval in game.

Here is an example of the world space projection working as intended. The SceneCaptureCube component updates the render target, then I update parameters for it’s location in a post process material to project it in the same location.

I’ve been able to get a modified SpiralBlur custom node working using code found here: Vector Math? Coding?! HLSL! (Cubemap Blur) - Real Time VFX

Code:


float TwoPi = 6.283185; //So pseudo code modifications. This is the principle, if not the exact code. //Take the Reflection vector, or the CameraVector, whichever is more appropriate for your code. //Convert it into to Spherical Coordinates. //Z is unimportant once it is in Spherical Coordinates the radius is unimportant. Infact because you know //the camera vectors or the reflection vectors are normalized you know the the radius is 1, so you can save some caluclations there. //The conversion from normalized cartesian vector to spherical is found here: https://en.wikipedia.org/wiki/Spherical_coordinate_system#Coordinate_system_conversions //Input CameraVector as float3 (or float4, doesn't matter.) //float radius = 1; //Unneeded because we know it will be 1. If you want you can use it. float theta = atan2( CameraVector.y, CameraVector.x ); float phi = acos( CameraVector.z ); //Then almost everything is the same. float3 CurColor; float2 UV = float2( theta, phi ); //So now we are perturbing the spherical coordinates (excluding radius). float2 NewUV = UV; //So now we are perturbing the spherical coordinates (excluding radius). float3 NewCameraVector = 0; //We will use this to store the resultant cameravector for each sample. int i; float StepSize = Distance / (int)DistanceSteps; float CurDistance; float2 CurOffset; float SubOffset = 0; float accumdist = 0; if (DistanceSteps < 1) { return ProcessMaterialColorTextureLookup(TextureCubeSample(Tex, TexSampler, CameraVector)); //Just sample the texCUBE with the camera vector. } else { while (i < (int)DistanceSteps) { CurDistance += StepSize; for (int j = 0; j < (int)RadialSteps; j++) { SubOffset += 1; CurOffset.x = cos(TwoPi * (SubOffset / RadialSteps)); CurOffset.y = sin(TwoPi * (SubOffset / RadialSteps)); NewUV.x = UV.x + CurOffset.x * CurDistance; NewUV.y = UV.y + CurOffset.y * CurDistance; float distpow = pow(CurDistance, KernelPower); //Convert back before sampling. //The conversion can be found here: https://en.wikipedia.org/wiki/Spherical_coordinate_system#Coordinate_system_conversions //Like before since we know the radius is always 1, no need to include it. //NewUV.x stores the offsetted theta, and NewUV.y stores the offsetted phi. NewCameraVector = float3( cos(NewUV.x) * sin(NewUV.y), sin(NewUV.x) * sin(NewUV.y), cos(NewUV.y) ); CurColor += ProcessMaterialColorTextureLookup(TextureCubeSample(Tex, TexSampler, NewCameraVector)) * distpow; accumdist += distpow; } SubOffset += RadialOffset; i++; } CurColor = CurColor; CurColor /= accumdist; return CurColor; }

The issue is that while the spiral blur produces a great result, I lose the world space projection in the process of converting from Cartesian to Spherical coordinates and back.


I’m not well-versed in HLSL, but I did try adding the position offset at the end of the blur steps in the function. The result simply negated the blur effect and left me with what I had originally.
Any ideas on a solution? I thought about sampling the texture with world space offsets and blending them together, but wasn’t sure if that was really the best way to go.

Update: I tried another setup using RotateAboutAxis node with poor quality results and much too high performance cost. But nevertheless this illustrates the general effect I’m trying to mess with.


The SpiralBlur looked much better. I’m basically toying with the idea of using this as some kind of dynamic irradiance map effect.

You are looking for PCF(Percentage Closer Filtering), not blur.

You mean the method used to soften shadowmaps? I’m not very familiar with it. Maybe I’m misunderstanding, but I’m not sure how that would help blur a cubemap texture in a material. Could you elaborate?

Also, I guess I may not have been clear on my end goal with this effect in my post. I’m trying to make a fully dynamic solution for some localized GI in a scene and these cubemaps would be acting like localized, low resolution IBL captures. However the blurring would give me more of an irradiance map look, which is what I am after. All lighting in the scene is dynamic.

https://geeks.ms/waveengineteam/2016…-lighting-ibl/
^^ Here is another example of what I’m doing. Here they blur cubemaps to create irradiance maps for IBL, I’m essentially trying to do this to a cubemap texture sample in the post-process material itself with a function because I can’t use static cubemap textures that are blurred/authored outside of the engine.

This is my first time posting so I apologize if I’m bad at explaining my issue. T w T