Sample Volume Texture (Custom HLSL)

Howdy,

There are some great resources for HLSL and materials out there BUT for volume textures things seem pretty sparse (except for sparse volume textures :stuck_out_tongue: which seem to have some more popularity due to VDB ).

Question:

How can I sample a volume texture to do ray marching in the Materials editor?

Notes:

  • Using UE 5.5
  • Open to Volumetrics plugin if there is something in there.
  • I currently generate my volume textures from c++ similar to the great TBRaymarch Plugin
  • Is that plugin now part of the Volumetrics plugin…?

Tried:

I followed this awesome tutorial and got it working just find for a 2D texture (PseudoVolumeTexture). However, tried to switch a volume texture causes the Sampler to never be found.

Example custom hlsl code. Neither sampling mode below worked.

float accumdens = 0;LocalCamVec = normalize(mul(Parameters.CameraVector, (float3x3)LWCToFloat(GetPrimitiveData(Parameters).WorldToLocal)));

for (int i = 0; i < MaxSteps; i++) {// Use Texture3DSample or VolumeTexture.Sample instead of PseudoVolumeTexture

//float cursample = Texture3DSample (VolumeTexture, VolumeTextureSampler, saturate(CurPos)).r;float cursample = VolumeTexture.Sample(VolumeTextureSampler, saturate(CurPos)).r;accumdens += cursample * StepSize;CurPos += -LocalCamVec * StepSize;}

CurPos -= -LocalCamVec * StepSize;CurPos += -LocalCamVec * StepSize * FinalStepSize;

// Final sample with adjusted step size

//float cursample = Texture3DSample (VolumeTexture, VolumeTextureSampler, saturate(CurPos)).r;float cursample = VolumeTexture.Sample(VolumeTextureSampler, saturate(CurPos)).r;accumdens += cursample * StepSize * FinalStepSize;

return accumdens;

voltex_sortof
Here is an image using a VolumeTexture but manually sweeping through the Z axis (no HLSL just a time + sine node on the Texture UV)… :frowning:

Trying to find examples in the Engine code, found:

Engine\Shaders\Private\BasePassPixelShader.usf

which uses it like this:

float4 Vector0 = Texture3DSample(IndirectLightingCache.IndirectLightingCacheTexture0, IndirectLightingCache.IndirectLightingCacheTextureSampler0, VolumeUVs);

So the function exists… hmm…

If a VolumeTexture render method is already implemented I would love to just use that and avoid this whole custom HLSL black voodoo magic.

Some progress made…

  • The input texture had to switch to a TextureObject and not a TextureSampler
  • Use SampleLevel and add the mimap value.
float accumdens = 0;
LocalCamVec = normalize(mul(Parameters.CameraVector, (float3x3)LWCToFloat(GetPrimitiveData(Parameters).WorldToLocal)));

for (int i = 0; i < MaxSteps; i++) {
    // Use Texture3DSample instead of PseudoVolumeTexture
    float cursample = VolumeTexture.SampleLevel(VolumeTextureSampler, saturate(CurPos),0).r;
 
    accumdens += cursample * StepSize;
    CurPos += -LocalCamVec * StepSize;
}

CurPos -= -LocalCamVec * StepSize;
CurPos += -LocalCamVec * StepSize * FinalStepSize;

// Final sample with adjusted step size
float cursample = VolumeTexture.SampleLevel(VolumeTextureSampler, saturate(CurPos),0).r;
accumdens += cursample * StepSize * FinalStepSize;

return accumdens;

Maybe you already know this, just in case:

The syntax for the Texture2DSampler in HLSL for Unreal is:

Texture2DSample([TextureObject], [TextureObject]Sampler, [UV]);

If you name your TextureObject “InTex”, the automatically created sampler would be named “InTexSampler”.
So for example:

Texture2DSample(InTex, InTexSampler, float2(0.f, 0.f));

I guess it is the same for the 3D/volume sampler. But maybe you already have a better way to sample.
————————————————————————————————-
Unreal materials always generate HLSL code:

  • MaterialEditor → Window → Shader Code → HLSL Code
  • contents of Custom nodes get parsed into a function, search for the comment “// uniform_material_expressions” the function should be called something like MaterialFloat3 CustomExpression0(FMaterialPixelParameters Parameters)

I got to know it from from this article:

1 Like

I didn’t know you could view the HLSL code. Thanks for that tip and the link. With all these things combined, I have achieved what I desired.

Voila!