Search Unity

Mesh rotation and ray marching

Discussion in 'Shaders' started by forteller, Jul 17, 2019.

  1. forteller

    forteller

    Joined:
    Jun 15, 2019
    Posts:
    55
    I've written a simple ray marcher in ShaderLab to visualize some 3D textures. Right now I'm applying the material to a cube and everything looks fine when the cube is at euler angles (0,0,0) but the more the cube is rotated the less predictable changes resulting from small movements in camera perspective become and the more two-dimensional the shader appears.

    I'm wondering how I would I best go about rotating 3D textures used in a ray marching shader, optimally I could just rotate the mesh itself and the shader would rotate intuitively along with it. I've tried rotating the uvw's in the shader itself but nothing seems to be working so I assume the problem lies in how i'm setting up my uvw's but I don't really know.

    At the moment here is how i'm setting my UVW's:
    Code (CSharp):
    1.     void Calculate3DTexUVW()
    2.     {
    3.         List<Vector3> UVWs = new List<Vector3>();
    4.  
    5.         for (int i = 0; i < meshFilter.sharedMesh.vertices.Length; i++)
    6.         {
    7.             UVWs.Add(new Vector3(meshFilter.sharedMesh.vertices[i].x,
    8.                 meshFilter.mesh.vertices[i].y,
    9.                 meshFilter.mesh.vertices[i].z));
    10.             if (UVWInWorldCoordinates) //toggle to make uvw's independant of mesh vertices
    11.             {
    12.                 UVWs[i] = transform.TransformPoint(UVWs[i]);
    13.             }
    14.         }
    15.  
    16.         meshFilter.sharedMesh.SetUVs(0, UVWs);
    17.     }
    Here is a version of the ray marcher:
    Code (CSharp):
    1. Shader "Custom/SpecieShaderPlane"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex3D("MainTex 3D", 3D) = "red" {}
    6.         _Color("Specie Color", Color) = (1,1,1,1)
    7.         _Intensity("Intensity", Range(0,1)) = 0.1
    8.         _Threshold("Min Threshold", Range(0,1)) = 0.5 //cut off alpha
    9.         _StepSize("Penetration Step Size", Range(0,0.1)) = 0.05
    10.         _StepNumber("Step Number (times to propogate ray)", Range(0,512)) = 64
    11.     }
    12.         SubShader
    13.         {
    14.             Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }
    15.             Blend SrcAlpha OneMinusSrcAlpha
    16.             ZWrite On
    17.             Cull Back
    18.             Pass
    19.             {
    20.                 CGPROGRAM
    21.                 #pragma vertex vert
    22.                 #pragma fragment frag
    23.  
    24.                 #include "UnityCG.cginc"
    25.                 #include "UnityShaderVariables.cginc"
    26.  
    27.                 struct appdata
    28.                 {
    29.                     float4 mVert : POSITION; //model vertex position
    30.                     float3 UVW : TEXCOORD0;
    31.                 };
    32.  
    33.                 struct v2f
    34.                 {
    35.                     float3 UVWTransformed : TEXCOORD0;
    36.                     float4 cVert : SV_POSITION; //clip vertex position
    37.                     float4 wVert : POSITION1; //world vertex position
    38.                     float3 camToFragDir : POSITION2; //unit vector representing direction
    39.                 };
    40.  
    41.                 sampler3D _MainTex3D;
    42.                 float4x4 _UVWTransform; //set in c# script
    43.                 v2f vert(appdata input)
    44.                 {
    45.                     v2f o;
    46.                     o.cVert = UnityObjectToClipPos(input.mVert); //model-clip transform
    47.                     o.wVert = mul(unity_ObjectToWorld, input.mVert); //model-world transform
    48.  
    49.  
    50.                     o.UVWTransformed = mul(_UVWTransform, float4(input.UVW, 1)).xyz; //transform uvw
    51.                     o.camToFragDir = normalize(o.wVert - _WorldSpaceCameraPos);
    52.  
    53.                     return o;
    54.                 }
    55.  
    56.                 fixed4 _Color;
    57.                 float _Intensity;
    58.                 float _Threshold;
    59.                 float _StepSize;
    60.                 float _StepNumber;
    61.  
    62.                 fixed4 frag(v2f input) : SV_Target
    63.                 {
    64.                         float3 ray = { 0,0,0 }; //offset from surface to sample from
    65.                         fixed4 col = { 0,0,0,0 };
    66.  
    67.                         //ray marching loop where a ray penetrates into a 3D texture and samples as it propagates
    68.                         for (int i = 0; i < _StepNumber; i++) {
    69.                             fixed4 currentSample = tex3D(_MainTex3D, input.UVWTransformed + ray);
    70.                             if (currentSample.r < _Threshold) {
    71.                                 currentSample.rgb = 0;
    72.                             }
    73.                            
    74.                             col.a += (1 - col.a) * currentSample * _Intensity; // asymptotic transfer function
    75.                             ray += input.camToFragDir * _StepSize; //propogate ray
    76.                         }
    77.                      
    78.                         col.rgb = _Color.rgb;
    79.                     return col;
    80.                 }
    81.                 ENDCG
    82.             }
    83.         }
    84. }
    85.  
    And here is how I was setting my uvw transform matrix in c#
    Code (CSharp):
    1.     private void Transform(Vector3 pos, Vector3 rot, float sclInverse)
    2.     {
    3.         float t = Time.time;
    4.         float scl = 1 / sclInverse;
    5.  
    6.         Quaternion rotQ = Quaternion.Euler(t * rot.x, t * rot.y, t * rot.z);
    7.         Vector3 sclV = new Vector3(scl, scl, scl);
    8.  
    9.         Matrix4x4 mat = Matrix4x4.TRS(pos, rotQ, sclV);
    10.         GetComponent<Renderer>().sharedMaterial.SetMatrix("_UVWTransform", mat);
    11.     }
    Thanks!