I’m trying to use a compute shader to modify a 3D render texture. I want to keep the existing contents, but additively paint into the texture in a specific location. However, while I could use a compute shader to fill everything with a constant colour, I couldn’t get it to do any modifications on top of existing state. I’ve been banging my head against this for a while and can’t find any useful documentation on the subject.
My compute shader:
#pragma kernel CSMain
Texture3D<float4> texIn;
RWTexture3D<float4> texOut;
float3 boundsDimensions;
float3 boundsCenter;
float3 paintCenter;
float paintRadius;
float paintMult;
float paintPower;
float4 paintColor;
[numthreads(8,8,8)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
float3 texSize;
texIn.GetDimensions(texSize.x, texSize.y, texSize.z);
float3 unitsPerTexel = (boundsDimensions/texSize);
float3 diff = (id.xyz*unitsPerTexel + boundsCenter - paintCenter);
float dist = length(diff);
float amount = saturate(1-dist/paintRadius);
amount = pow(amount,paintPower) * paintMult;
float4 finalPaint = saturate(texIn[id.xyz] + amount * paintColor);
texOut[id.xyz] = finalPaint;
}
The calling code:
ComputeShader paintShader = Resources.Load<ComputeShader>("ComputeShaders/PaintSphere");
paintShader.SetTexture(0, "texIn", paintVolume.Volume);
paintShader.SetTexture(0, "texOut", paintVolume.Volume);
paintShader.SetVector("boundsDimensions", paintVolume.BoundsSize);
paintShader.SetVector("boundsCenter", paintVolume.BoundsCenter);
paintShader.SetVector("paintCenter", transform.InverseTransformPoint(worldPosition));
paintShader.SetFloat("paintRadius", radius);
paintShader.SetFloat("paintMult", mult);
paintShader.SetFloat("paintPower", power);
paintShader.SetVector("paintColor", color);
paintShader.Dispatch(0, paintVolume.Volume.width / 8, paintVolume.Volume.height / 8, paintVolume.Volume.volumeDepth / 8);
…And, for good measure, the render texture creation:
volume = new RenderTexture(volumeDimensions, volumeDimensions, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
volume.isVolume = true;
volume.volumeDepth = volumeDimensions;
volume.enableRandomWrite = true;
As far as I can tell, the questionable bit is that I’m feeding the same texture into the shader as both an input and an output variable. However, I don’t know another way to approach this. Does anyone know what I’m doing wrong, or what I could do as an alternative approach?