0

I am trying to apply a raymarching shader to my Unity VR project. It is supposed to apply a shader to particles that represent a fluid using Smooth Particle Hydrodynamics. However, I am running into this error:

Compute shader (Raymarching): Property (_DepthTexture) at kernel index (0) is not set
UnityEngine.StackTraceUtility:ExtractStackTrace ()
FluidRayMarching:OnRenderImage (UnityEngine.RenderTexture,UnityEngine.RenderTexture) (at Assets/Scripts/FluidRayMarching.cs:90)
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

And the Unity VR scene fails to start beyond the Unity Logo at the beginning. In the Unity Game window, all I get is a black screen. enter image description here

I am new to shaders and am still trying to learn but I am not making good sense of it. I appreciate any help with this.

Thank you.

This is the script that I have, called FluidRayMarching.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FluidRayMarching : MonoBehaviour
{
    public ComputeShader raymarching;
    public Camera cam;
    
    List<ComputeBuffer> buffersToDispose = new List<ComputeBuffer>();
    
    public SPH sph;

    RenderTexture target;

    [Header("Params")]
    public float viewRadius;
    public float blendStrength;
    public Color waterColor;

    public Color ambientLight;

    public Light lightSource;


    void InitRenderTexture () {
        if (target == null || target.width != cam.pixelWidth || target.height != cam.pixelHeight) {
            if (target != null) {
                target.Release ();
            }
            
            cam.depthTextureMode = DepthTextureMode.Depth;

            target = new RenderTexture (cam.pixelWidth, cam.pixelHeight, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
            target.enableRandomWrite = true;
            target.Create ();
        }
    }


    private bool render = false;

    public ComputeBuffer _particlesBuffer;

    private void SpawnParticlesInBox()
    {
       _particlesBuffer = new ComputeBuffer(1, 44);
       _particlesBuffer.SetData(new Particle[] {
        new Particle {
        position = new Vector3(0,0,0)
       }});

    }

    public void Begin() {
        // SpawnParticlesInBox();
        InitRenderTexture();
        raymarching.SetBuffer(0,"particles",sph._particlesBuffer);
        raymarching.SetInt("numParticles",sph.particles.Length);
        raymarching.SetFloat("particleRadius", viewRadius);
        raymarching.SetFloat("blendStrength", blendStrength);
        raymarching.SetVector("waterColor", waterColor);
        raymarching.SetVector("_AmbientLight", ambientLight);
        raymarching.SetTextureFromGlobal(0, "_DepthTexture", "_CameraDepthTexture");
        render = true;
    }


    void OnRenderImage (RenderTexture source, RenderTexture destination) {
        
        // InitRenderTexture();

        if (!render) {
            Begin();
        }

        if (render) {

            raymarching.SetVector ("_Light", lightSource.transform.forward);

            raymarching.SetTexture (0, "Source", source);
            raymarching.SetTexture (0, "Destination", target);
            raymarching.SetVector("_CameraPos", cam.transform.position);
            raymarching.SetMatrix ("_CameraToWorld", cam.cameraToWorldMatrix);
            raymarching.SetMatrix ("_CameraInverseProjection", cam.projectionMatrix.inverse);

            int threadGroupsX = Mathf.CeilToInt (cam.pixelWidth / 8.0f);
            int threadGroupsY = Mathf.CeilToInt (cam.pixelHeight / 8.0f);

            raymarching.Dispatch (0, threadGroupsX, threadGroupsY, 1);

            Graphics.Blit (target, destination);
        }
    }

}

And this is the shader, called Raymarching.compute:

#pragma kernel CSMain

Texture2D<float4> Source;
RWTexture2D<float4> Destination;
Texture2D<float4> _DepthTexture;

float4x4 _CameraToWorld;
float4x4 _CameraInverseProjection;

static const float maxDst = 80;
static const float epsilon = 0.001f;
static const float shadowBias = epsilon * 50;

struct Particle
{
    float pressure;
    float density;
    float3 currentForce;
    float3 velocity;
    float3 position;
};

StructuredBuffer<Particle> particles;
int numParticles;
float particleRadius;
float blendStrength;
float3 waterColor;
float3 _Light;
float3 _AmbientLight;
float3 _CameraPos;

struct Ray {
    float3 origin;
    float3 direction;
};

float SphereDistance(float3 eye, float3 centre, float radius) {
    return distance(eye, centre) - radius;
}

Ray CreateRay(float3 origin, float3 direction) {
    Ray ray;
    ray.origin = origin;
    ray.direction = direction;
    return ray;
}

Ray CreateCameraRay(float2 uv) {
    float3 origin = mul(_CameraToWorld, float4(0,0,0,1)).xyz;
    float3 direction = mul(_CameraInverseProjection, float4(uv,0,1)).xyz;
    direction = mul(_CameraToWorld, float4(direction,0)).xyz;
    direction = normalize(direction);
    return CreateRay(origin,direction);
}

// polynomial smooth min (k = 0.1);
// from https://www.iquilezles.org/www/articles/smin/smin.htm
float4 Blend( float a, float b, float3 colA, float3 colB, float k )
{
    float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
    float blendDst = lerp( b, a, h ) - k*h*(1.0-h);
    float3 blendCol = lerp(colB,colA,h);
    return float4(blendCol, blendDst);
}

float4 Combine(float dstA, float dstB, float3 colourA, float3 colourB) {
    float dst = dstA;
    float3 colour = colourA;
    float4 blend = Blend(dstA,dstB,colourA,colourB, blendStrength);
    dst = blend.w;
    colour = blend.xyz;
    return float4(colour,dst);
}

float GetShapeDistance(Particle particle, float3 eye) {
   
    return SphereDistance(eye, particle.position, particleRadius);
    return maxDst;
}


float4 SceneInfo(float3 eye) {
    float globalDst = maxDst;
    float3 globalColour = waterColor;
    
    for (int i = 0; i < numParticles; i ++) {
        Particle particle = particles[i];

        float localDst = GetShapeDistance(particle,eye);
        float3 localColour = waterColor;


        float4 globalCombined = Combine(globalDst, localDst, globalColour, localColour);
        globalColour = globalCombined.xyz;
        globalDst = globalCombined.w;        
    }

    return float4(globalColour, globalDst);
}

float3 EstimateNormal(float3 p) {
    float x = SceneInfo(float3(p.x+epsilon,p.y,p.z)).w - SceneInfo(float3(p.x-epsilon,p.y,p.z)).w;
    float y = SceneInfo(float3(p.x,p.y+epsilon,p.z)).w - SceneInfo(float3(p.x,p.y-epsilon,p.z)).w;
    float z = SceneInfo(float3(p.x,p.y,p.z+epsilon)).w - SceneInfo(float3(p.x,p.y,p.z-epsilon)).w;
    return normalize(float3(x,y,z));
}

float CalculateShadow(Ray ray, float dstToShadePoint) {
    float rayDst = 0;
    int marchSteps = 0;
    float shadowIntensity = .2;
    float brightness = 1;

    while (rayDst < dstToShadePoint) {
        marchSteps ++;
        float4 sceneInfo = SceneInfo(ray.origin);
        float dst = sceneInfo.w;
        
        if (dst <= epsilon) {
            return shadowIntensity;
        }

        brightness = min(brightness,dst*200);

        ray.origin += ray.direction * dst;
        rayDst += dst;
    }
    return shadowIntensity + (1-shadowIntensity) * brightness;
}

float LinearEyeDepth( float rawdepth )
{
    float _NearClip = 0.3;
    float FarClip = 1000;
    float x, y, z, w;
    #if SHADER_API_GLES3 // insted of UNITY_REVERSED_Z
        x = -1.0 + _NearClip/ FarClip;
        y = 1;
        z = x / _NearClip;
        w = 1 / _NearClip;
    #else
        x = 1.0 - _NearClip/ FarClip;
        y = _NearClip / FarClip;
        z = x / _NearClip;
        w = y / _NearClip;
    #endif
    
    return 1.0 / (z * rawdepth + w);
}

[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    uint width,height;
    Destination.GetDimensions(width, height);

    Destination[id.xy] = Source[id.xy];

    float2 uv = id.xy / float2(width,height) * 2 - 1;
    float rayDst = 0;

    Ray ray = CreateCameraRay(uv);
    int marchSteps = 0;

    float depth = LinearEyeDepth(_DepthTexture[id.xy]);

    

    while (rayDst < maxDst) {
        marchSteps ++;
        float4 sceneInfo = SceneInfo(ray.origin);
        float dst = sceneInfo.w;

        if (rayDst >= depth) {
            Destination[id.xy] = Source[id.xy];
            break;
        }
        
        if (dst <= epsilon) {
            float3 pointOnSurface = ray.origin + ray.direction * dst;
            float3 normal = EstimateNormal(pointOnSurface - ray.direction * epsilon);
            float3 lightDir = -_Light;
            float lighting = saturate(saturate(dot(normal,lightDir))) ;

            float3 reflectDir = reflect(-lightDir, normal);
            float spec = pow(max(dot(ray.direction, reflectDir), 0.0), 32);
            float3 specular = 0.7 * spec * float3(1,1,1);

            float3 col = sceneInfo.xyz;

            float3 t1 = cross(normal, float3(0,0,1));
            float3 t2 = cross(normal, float3(0,1,0));
            float3 tangent = float3(0,0,0);
            if (length(t1) > length(t2)) {
                tangent = normalize(t1);
            }
            else {
                tangent = normalize(t2);
            }

            float3x3 tangentMatrix = float3x3(tangent,cross(tangent, normal),normal);

            float3 viewDir = normalize(pointOnSurface-_CameraPos);

            float3 refracted = mul(tangentMatrix, refract(viewDir, normal,1));
            

            Destination[id.xy] = float4(lerp(col, Source[id.xy+(refracted.xy)], 0.8) * (specular + _AmbientLight + lighting * 0.01),1);
           

            break;
        }

        ray.origin += ray.direction * dst;
        rayDst += dst;
    }
}

1 Answer 1

0

Your approach seems fine and assigning the texture in OnRenderImage sounds reasonable. I don't know exactly why but for me using SetTextureFromGlobal(0, "_DepthTexture", "_CameraDepthTexture"); in the first update loop solved it.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your comment. I will try your suggestion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.