0
\$\begingroup\$

What I want is to swipe any curve into a plane, axis aligned. I made 2d intersection of the cross section then the 2d hieght extruded: - first I want to compute ex: the xz intersections - then using the computed z, intersect again in the yz

To test it I tried with swiping a simple line as a validation, however all I get is garbage.

    Shader "Unlit/Raytraced Rows"
{
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _Rows ("Number of Rows", Float) = 1
        _HalfDepth ("Half Depth", Float) = 0.2
    }

    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _Rows;
            float _HalfDepth;

            struct v2f {
                float4 pos : SV_Position;
                float2 uv : TEXCOORD0;
                float3 objectViewDir : TEXCOORD1;
                float3x3 objectToTangent : TEXCOORD2;
            };

            v2f vert (appdata_full v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

                float3 normal = normalize(v.normal.xyz);
                float3 tangent = normalize(v.tangent.xyz);
                float3 bitangent = normalize(cross(normal, tangent) * v.tangent.w);
                o.objectToTangent = float3x3(tangent, bitangent, normal);

                o.objectViewDir = ObjSpaceViewDir(v.vertex);

                return o;
            }

            float rayPlaneIntersection( float3 rayDir, float3 rayPos, float3 planeNormal, float3 planePos)
            {
                float denom = dot(planeNormal, rayDir);
                denom = max(denom, 0.000001); // avoid divide by zero
                float3 diff = planePos - rayPos;
                return -dot(diff, planeNormal) / denom;
            }

            float line2dIntersection(float2 rayDir, float2 rayPos,  float2 planeDir, float2 planePos)
            {
                return (rayPos - planePos) / (max( 0.000001, (planeDir - rayDir) ) );
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // calculate tangent space view direction
                float3 tangentViewDir = mul(i.objectToTangent, i.objectViewDir);

                // build ray direction scaled to fit into a "row" space
                float3 rayDir = tangentViewDir;
                rayDir.x *= _Rows; // scale x based on number of rows
                rayDir.y *= _MainTex_ST.y / _MainTex_ST.x; // correct for texture scale aspect
                rayDir.z /= _HalfDepth; // scale z by inverse half depth
                rayDir = normalize(rayDir);

                // get row space uv
                float2 scaledUV = i.uv * float2(_Rows, 1);
                float2 fracUV = frac(scaledUV);

                // plane normals
                float cosine = 0.70710678; // 45 degrees
                float3 p0Normal = float3(cosine, 0, cosine);
                float3 p1Normal = float3(-cosine, 0, cosine);

                // get ray plane intersection distances
                float pt0 = rayPlaneIntersection(
                    rayDir, float3(fracUV.xy, 0), // ray
                    p0Normal, float3(0,0,0) // plane, starting at left edge of row space
                );
                float pt1 = rayPlaneIntersection(
                    rayDir, float3(fracUV.xy, 0), // ray
                    p1Normal, float3(1,0,0) // plane, starting at right edge of row space
                );

                float al1 = line2dIntersection(rayDir.xz, float2(fracUV.x, 0),normalize(float2(1,1)),float2(0,0));
                float3 rayDir2 = rayDir;
                rayDir2.xz = float3( rayDir.xz * al1,0);
                float al2 = line2dIntersection(rayDir2.yz, float2(fracUV.y, 0),normalize(float2(1,0)),float2(0,rayDir2.z));
                rayDir2.y = rayDir2.y * al2;

                // calculate and apply uv offset
                float ptMin =  min(pt0, pt1);
                // scale ray back to unscaled tangent space and apply min range
                float2 uvOffset = rayDir.xy * float2(1 / _Rows, 1) * ptMin;
                float2 uv =  i.uv - uvOffset ;


                // use derivates from the original uv to avoid sampling artifacts on the peaks
                // -- not actually correct, but way easier than calculating the proper derivates --
                float2 uv_ddx = ddx(i.uv);
                float2 uv_ddy = ddy(i.uv);
                fixed4 col = tex2Dgrad(_MainTex, uv, uv_ddx, uv_ddy);
                return col;
            }

            ENDCG
        }
    }
}

Relevant part is in the frag shader, if you run the code above it should work for the plane intersection.

this part is the line intersection:

        float line2dIntersection(float2 rayDir, float2 rayPos,  float2 planeDir, float2 planePos)
        {
            return (rayPos - planePos) / (max( 0.000001, (planeDir - rayDir) ) );
        }

applied:

float al1 = line2dIntersection(rayDir.xz, float2(fracUV.x, 0),normalize(float2(1,1)),float2(0,0));
            float3 rayDir2 = rayDir;
            rayDir2.xz = float3( rayDir.xz * al1,0);
            float al2 = line2dIntersection(rayDir2.yz, float2(fracUV.y, 0),normalize(float2(1,0)),float2(0,rayDir2.z));
            rayDir2.y = rayDir2.y * al2;

TO try to get the line intersection working we have to change:

 // calculate and apply uv offset
            float ptMin =  min(pt0, pt1);
            // scale ray back to unscaled tangent space and apply min range
            float2 uvOffset = rayDir.xy * float2(1 / _Rows, 1) * ptMin;
            float2 uv =  i.uv - uvOffset ;

into

// calculate and apply uv offset

                float2 uv =  i.uv - rayDir2.xy;

Obviously that doesn't work I don't know why. Where did I got wrong?

\$\endgroup\$
  • 1
    \$\begingroup\$ can you add Image to your question? because Images better show the problem! \$\endgroup\$ – Seyed Morteza Kamali Oct 4 '18 at 21:56

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.