Hey Guys,
Does anyone know how linear sampler works behind the scene? especially when sampling a Texture3D object. Is it fetching 8 texels and interpolate the result? MSDN only says D3D12_FILTER_TYPE_LINEAR will return "the weighter average of a 2x2 area of texels surrounding the desired pixel" which is not super clear to me.
I tried to render a surface by raycasting through a TSDF volume (Texture3D), point sampler and my own linear 'sampler' (point sample 8 nearest voxels then interpolate) gives expected result without artifacts, while LinearSampler and AnisotropicSampler runs faster but generate artifacts(see attachments PointSampler, ManualSampler(trilinear interpolation), LinearSampler).
also here is the most obvious one:
It looks clearly that this artifact related to raycast step size, but why point sampler and manual interpolation don't have this artifact? In fact I double checked, even if I make my ray cast step 10x smaller, the artifact still exist (even worse).
Also another MSDN page at the bottom part states:
During texture sampling, one or more texels are read and combined (this is calling filtering) to produce a single value. Point sampling reads a single texel while linear sampling reads two texels (endpoints) and linearly interpolates a third value between the endpoints.
So it seems samplers will never do 8 texels fetches for correct trilinear interpolation on Texture3D? (anyone?)
in case there are any problems in my manual interpolation I pasted it here:
// f3Idx range (0,0,0) - (resolution.x, resolution.y, resolution.z) float readVolume(float3 f3Idx) { int3 i3Idx000; float3 f3d = modf(f3Idx, i3Idx000) - 0.5f; #if FILTER_READ == 1 float fV000 = tex_srvTSDFVol[BUFFER_INDEX(i3Idx000)]; float fV001 = tex_srvTSDFVol[BUFFER_INDEX(i3Idx000 + uint3(0, 0, 1))]; float fV010 = tex_srvTSDFVol[BUFFER_INDEX(i3Idx000 + uint3(0, 1, 0))]; float fV011 = tex_srvTSDFVol[BUFFER_INDEX(i3Idx000 + uint3(0, 1, 1))]; float fV100 = tex_srvTSDFVol[BUFFER_INDEX(i3Idx000 + uint3(1, 0, 0))]; float fV101 = tex_srvTSDFVol[BUFFER_INDEX(i3Idx000 + uint3(1, 0, 1))]; float fV110 = tex_srvTSDFVol[BUFFER_INDEX(i3Idx000 + uint3(1, 1, 0))]; float fV111 = tex_srvTSDFVol[BUFFER_INDEX(i3Idx000 + uint3(1, 1, 1))]; return fV000 * (1.f - f3d.x) * (1.f - f3d.y) * (1.f - f3d.z) + fV100 * f3d.x * (1.f - f3d.y) * (1.f - f3d.z) + fV010 * (1.f - f3d.x) * f3d.y * (1.f - f3d.z) + fV001 * (1.f - f3d.x) * (1.f - f3d.y) * f3d.z + fV101 * f3d.x * (1.f - f3d.y) * f3d.z + fV011 * (1.f - f3d.x) * f3d.y * f3d.z + fV110 * f3d.x * f3d.y * (1.f - f3d.z) + fV111 * f3d.x * f3d.y * f3d.z; #elif TEX3D_UAV && FILTER_READ == 2 return tex_srvTSDFVol.SampleLevel( samp_Linear, f3Idx / vParam.u3VoxelReso, 0); #elif TEX3D_UAV && FILTER_READ == 3 return tex_srvTSDFVol.SampleLevel( samp_Aniso, f3Idx / vParam.u3VoxelReso, 0); #else return tex_srvTSDFVol[BUFFER_INDEX(i3Idx000)]; #endif // !FILTER_READ }
So I think I probably need more information to dig into it. Also if anyone knows there exist better ways to do Volume interpolated read, please yell at me.
Thanks