Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Resolved Rotate Sampler3d UVs

Discussion in 'General Graphics' started by RendergonPolygons, Mar 1, 2022.

  1. RendergonPolygons

    RendergonPolygons

    Joined:
    Oct 9, 2019
    Posts:
    97
    Hi ! I'm trying to rotate a volume I raymarch from its UVs in the unlit shader. I don't rotate the cube object where I raymarch because I intend sampling several 3d textures via raymarching, rotate them as necessary and finally blend the colors:

    I tried this rotation around X with function by keijiro for a 3d texture but the results don't work, see result below:

    Code (CSharp):
    1.  
    2. float sample_volume(float3 uv, float3 p)
    3. {
    4.     //float3 uv2 = mul(uv - 0.5, Rot(_Angle)) + 0.5;//error because its float2
    5.     uv = mul(uv - 0.5, AngleAxis3x3(_Angle, uv.x)) + 0.5;
    6.     float v = tex3D(_MainTex, uv).r * _Intensity;
    7.     return v;
    8. }
    9.  
    Code (CSharp):
    1. // Rotation with angle (in radians) and axis
    2. float3x3 AngleAxis3x3(float angle, float3 axis)
    3. {
    4.     float c, s;
    5.     sincos(angle, s, c);
    6.  
    7.     float t = 1 - c;
    8.     float x = axis.x;
    9.     float y = axis.y;
    10.     float z = axis.z;
    11.  
    12.     return float3x3(
    13.         t * x * x + c,      t * x * y - s * z,  t * x * z + s * y,
    14.         t * x * y + s * z,  t * y * y + c,      t * y * z - s * x,
    15.         t * x * z - s * y,  t * y * z + s * x,  t * z * z + c
    16.     );
    17. }
    This is what the above code looks like - the video captures slowly rotating from 0 to 90 degrees both in-game and in scene. It breaks the raymarched volume.

    What is the 3d function to rotate the UVs like in 2d below or this other post ?
    Code (CSharp):
    1. float s = sin ( radians );
    2. float c = cos ( radians );
    3. float2x2 rotationMatrix = float2x2( c, -s, s, c);
    4. uv = mul ( uv - 0.5, rotationMatrix ) + 0.5;
    this is the shader code:
    Code (CSharp):
    1. #include "UnityCG.cginc"
    2.  
    3. #define ITERATIONS 100
    4. #define PI2 6.28318530718
    5.  
    6. half4 _Color;
    7. sampler3D _MainTex;
    8. half _Intensity, _Threshold;
    9. half3 _SliceMin, _SliceMax;
    10. float4x4 _AxisRotationMatrix;
    11. float _Angle;
    12.  
    13. struct Ray {
    14.     float3 origin;
    15.     float3 dir;
    16. };
    17.  
    18. struct AABB {
    19.     float3 min;
    20.     float3 max;
    21. };
    22.  
    23. // https http.download.nvidia.com/developer/presentations/2005/GDC/Audio_and_Slides/VolumeRendering_files/GDC_2_files/GDC_2005_VolumeRenderingForGames_files/Slide0073.htm
    24. bool intersect(Ray r, AABB aabb, out float t0, out float t1)
    25. {
    26.     float3 invR = 1.0 / r.dir;
    27.     float3 tbot = invR * (aabb.min - r.origin);
    28.     float3 ttop = invR * (aabb.max - r.origin);
    29.     float3 tmin = min(ttop, tbot);
    30.     float3 tmax = max(ttop, tbot);
    31.     float2 t = max(tmin.xx, tmin.yz);
    32.     t0 = max(t.x, t.y);
    33.     t = min(tmax.xx, tmax.yz);
    34.     t1 = min(t.x, t.y);
    35.     return t0 <= t1;
    36. }
    37.  
    38. float3 get_uv(float3 p) {
    39.     return (p + 0.5);
    40. }
    41.  
    42. //https forum.unity.com/threads/moving-uvs-of-a-texture-by-an-angle-0-360.486045/
    43. float2x2 Rot(float angleDegrees)
    44. {
    45.     float rad = angleDegrees * PI2 / 360;
    46.     float cosAngle = cos(rad);
    47.     float sinAngle = sin(rad);
    48.     float2x2 rot = float2x2(cosAngle, -sinAngle, sinAngle, cosAngle);
    49.     return rot;
    50. }
    51.  
    52. // Rotation with angle (in radians) and axis
    53. //https gist.github.com/keijiro/ee439d5e7388f3aafc5296005c8c3f33
    54. float3x3 AngleAxis3x3(float angleDegrees, float3 axis)
    55. {
    56.     float rad = angleDegrees * PI2 / 360;
    57.  
    58.     float c, s;
    59.     sincos(rad, s, c);
    60.  
    61.     float t = 1 - c;
    62.     float x = axis.x;
    63.     float y = axis.y;
    64.     float z = axis.z;
    65.  
    66.     return float3x3(
    67.         t * x * x + c, t * x * y - s * z, t * x * z + s * y,
    68.         t * x * y + s * z, t * y * y + c, t * y * z - s * x,
    69.         t * x * z - s * y, t * y * z + s * x, t * z * z + c
    70.         );
    71. }
    72.  
    73. float sample_volume(float3 uv, float3 p)
    74. {
    75.     //float3 uv2 = mul(uv - 0.5, Rot(_Angle)) + 0.5;//error because its float2
    76.     uv = mul(uv - 0.5, AngleAxis3x3(_Angle, uv.x)) + 0.5;
    77.  
    78.     float v = tex3D(_MainTex, uv).r * _Intensity;
    79.  
    80.     return v;
    81. }
    82.  
    83. struct appdata
    84. {
    85.     float4 vertex : POSITION;
    86.     float2 uv : TEXCOORD0;
    87. };
    88.  
    89. struct v2f
    90. {
    91.     float4 vertex : SV_POSITION;
    92.     float2 uv : TEXCOORD0;
    93.     float3 world : TEXCOORD1;
    94.     float3 local : TEXCOORD2;
    95. };
    96.  
    97. v2f vert(appdata v)
    98. {
    99.     v2f o;
    100.  
    101.     o.vertex = UnityObjectToClipPos(v.vertex);
    102.     o.uv = v.uv;
    103.     o.world = mul(unity_ObjectToWorld, v.vertex).xyz;
    104.     o.local = v.vertex.xyz;
    105.     return o;
    106. }
    107.  
    108. fixed4 frag(v2f i) : SV_Target
    109. {
    110.   Ray ray;
    111.     ray.origin = i.local;
    112.  
    113.     // world space direction to object space
    114.     float3 dir = (i.world - _WorldSpaceCameraPos);
    115.     ray.dir = normalize(mul(unity_WorldToObject, dir));
    116.  
    117.     AABB aabb;
    118.     aabb.min = float3(-0.5, -0.5, -0.5);
    119.     aabb.max = float3(0.5, 0.5, 0.5);
    120.  
    121.     float tnear;
    122.     float tfar;
    123.     intersect(ray, aabb, tnear, tfar);
    124.  
    125.     tnear = max(0.0, tnear);
    126.  
    127.     // float3 start = ray.origin + ray.dir * tnear;
    128.     float3 start = ray.origin;
    129.     float3 end = ray.origin + ray.dir * tfar;
    130.     float dist = abs(tfar - tnear);
    131.     float step_size = dist / float(ITERATIONS);
    132.     float3 ds = normalize(end - start) * step_size;
    133.  
    134.     float4 dst = float4(0, 0, 0, 0);
    135.     float3 p = start;
    136.  
    137.     [unroll]
    138.     for (int iter = 0; iter < ITERATIONS; iter++)
    139.     {
    140.       float3 uv = get_uv(p);
    141.  
    142.       float v = sample_volume(uv, p);
    143.       float4 src = float4(v, v, v, v);
    144.       src.a *= 0.5;
    145.       src.rgb *= src.a;
    146.  
    147.       // blend
    148.       dst = (1.0 - dst.a) * src + dst;
    149.       p += ds;
    150.  
    151.       if (dst.a > _Threshold) break;
    152. }
    153.  
    154. return saturate(dst) * _Color;
    155. }
    156.  
    157. #endif
     
    Last edited: Mar 1, 2022
  2. joshuacwilde

    joshuacwilde

    Joined:
    Feb 4, 2018
    Posts:
    643
    I assume on line 5 you meant this?

    Code (CSharp):
    1. uv = mul(uv - 0.5, AngleAxis3x3(_Angle, float3(1,0,0))) + 0.5;
    2.  
     
    RendergonPolygons likes this.
  3. RendergonPolygons

    RendergonPolygons

    Joined:
    Oct 9, 2019
    Posts:
    97
    Thanks a bunch @joshuacwilde , that works ! I had not understood what was going into the parameter !
     
    joshuacwilde likes this.