Search code examples
unity-game-engineshader

Unity using shader for water effect but I need the normal and location of the shader triangle not the mesh


I am working on a game and I bought a water shader, I am just to time strapped to learn it right now. I am making a game with water and ships. I need the ships to respond to the water shader vertex normal at the ray cast hit position. Frankly I just don't know what I am doing and I would appreciate any help. Shader

Shader "StylizedWater/Mobile"
{
    Properties
    {
        [HDR]_WaterColor("Water Color", Color) = (0.1176471,0.6348885,1,0)
        [HDR]_WaterShallowColor("WaterShallowColor", Color) = (0.4191176,0.7596349,1,0)
        _Wavetint("Wave tint", Range( -1 , 1)) = 0
        [HDR]_RimColor("Rim Color", Color) = (1,1,1,0.5019608)
        _NormalStrength("NormalStrength", Range( 0 , 1)) = 0.25
        _Transparency("Transparency", Range( 0 , 1)) = 0.75
        _Glossiness("Glossiness", Range( 0 , 1)) = 0.85
        [Toggle]_Worldspacetiling("Worldspace tiling", Float) = 1
        _NormalTiling("NormalTiling", Range( 0 , 1)) = 0.9
        _EdgeFade("EdgeFade", Range( 0.01 , 3)) = 0.2448298
        _RimSize("Rim Size", Range( 0 , 20)) = 5
        _Rimfalloff("Rim falloff", Range( 0.1 , 50)) = 3
        _Rimtiling("Rim tiling", Float) = 0.5
        _FoamOpacity("FoamOpacity", Range( -1 , 1)) = 0.05
        _FoamSpeed("FoamSpeed", Range( 0 , 1)) = 0.1
        _FoamSize("FoamSize", Float) = 0
        _FoamTiling("FoamTiling", Float) = 0.05
        _Depth("Depth", Range( 0 , 100)) = 30
        _Wavesspeed("Waves speed", Range( 0 , 10)) = 0.75
        _WaveHeight("Wave Height", Range( 0 , 1)) = 0.5366272
        _WaveFoam("Wave Foam", Range( 0 , 10)) = 0
        _WaveSize("Wave Size", Range( 0 , 10)) = 0.1
        _WaveDirection("WaveDirection", Vector) = (1,0,0,0)
        [NoScaleOffset][Normal]_Normals("Normals", 2D) = "bump" {}
        [NoScaleOffset]_Shadermap("Shadermap", 2D) = "black" {}
        [Toggle(_USEINTERSECTIONFOAM_ON)] _UseIntersectionFoam("UseIntersectionFoam", Float) = 0
        [Toggle]_ENABLE_VC("ENABLE_VC", Float) = 0
        [Toggle(_LIGHTING_ON)] _LIGHTING("LIGHTING", Float) = 0
        [Toggle]_Unlit("Unlit", Float) = 0
        _Metallicness("Metallicness", Range( 0 , 1)) = 0
        [Toggle(_NORMAL_MAP_ON)] _NORMAL_MAP("NORMAL_MAP", Float) = 0
        [Toggle]_USE_VC_INTERSECTION("USE_VC_INTERSECTION", Float) = 0
        [Toggle]_EnableDepthTexture("EnableDepthTexture", Float) = 1
        [HideInInspector] __dirty( "", Int ) = 1
    }

    SubShader
    {
        Tags{ "RenderType" = "Transparent"  "Queue" = "Transparent+0" "IgnoreProjector" = "True" "ForceNoShadowCasting" = "True" }
        LOD 200
        Cull Back
        CGPROGRAM
        #include "UnityPBSLighting.cginc"
        #include "UnityShaderVariables.cginc"
        #include "UnityCG.cginc"
        #pragma target 3.0
        #pragma multi_compile __ _LIGHTING_ON
        #pragma multi_compile __ _NORMAL_MAP_ON
        #pragma shader_feature _USEINTERSECTIONFOAM_ON
        #pragma fragmentoption ARB_precision_hint_fastest
        #pragma exclude_renderers xbox360 psp2 n3ds wiiu 
        #pragma surface surf StandardCustomLighting alpha:fade keepalpha noshadow nolightmap  nodynlightmap nodirlightmap nometa noforwardadd vertex:vertexDataFunc 
        struct Input
        {
            float3 worldPos;
            float4 screenPos;
            float4 vertexColor : COLOR;
            float2 vertexToFrag713;
            float2 vertexToFrag714;
            float3 worldRefl;
            INTERNAL_DATA
            float3 vertexToFrag746;
            float3 worldNormal;
        };

        struct SurfaceOutputCustomLightingCustom
        {
            half3 Albedo;
            half3 Normal;
            half3 Emission;
            half Metallic;
            half Smoothness;
            half Occlusion;
            half Alpha;
            Input SurfInput;
            UnityGIInput GIData;
        };

        uniform sampler2D _Normals;
        uniform sampler2D _Shadermap;
        uniform half _WaveHeight;
        uniform float _ENABLE_VC;
        uniform float _Worldspacetiling;
        uniform float _WaveSize;
        uniform float _Wavesspeed;
        uniform float4 _WaveDirection;
        uniform float _EnableDepthTexture;
        uniform sampler2D_float _CameraDepthTexture;
        uniform half _EdgeFade;
        uniform half _Transparency;
        uniform float _Depth;
        uniform half4 _WaterShallowColor;
        uniform float4 _RimColor;
        uniform float _USE_VC_INTERSECTION;
        uniform half _Rimfalloff;
        uniform float _Rimtiling;
        uniform half _RimSize;
        uniform float _NormalTiling;
        uniform half _NormalStrength;
        uniform half _Glossiness;
    

uniform float _Unlit;
        uniform half4 _WaterColor;
        uniform half _Wavetint;
        uniform half _FoamOpacity;
        uniform float _FoamTiling;
        uniform float _FoamSpeed;
        uniform half _FoamSize;
        uniform float _WaveFoam;
        uniform float _Metallicness;

        void vertexDataFunc( inout appdata_full v, out Input o )
        {
            UNITY_INITIALIZE_OUTPUT( Input, o );
            float3 ase_vertexNormal = v.normal.xyz;
            float4 VertexColors729 = lerp(float4( 0,0,0,0 ),v.color,_ENABLE_VC);
            float3 ase_worldPos = mul( unity_ObjectToWorld, v.vertex );
            float2 Tiling21 = lerp(( -20.0 * v.texcoord.xy ),( (ase_worldPos).xz * float2( 0.1,0.1 ) ),_Worldspacetiling);
            float2 appendResult500 = (float2(_WaveDirection.x , _WaveDirection.z));
            float2 WaveSpeed40 = ( ( _Wavesspeed * _Time.x ) * appendResult500 );
            float2 HeightmapUV581 = ( ( ( Tiling21 * _WaveSize ) * float2( 0.1,0.1 ) ) + ( WaveSpeed40 * float2( 0.5,0.5 ) ) );
            float4 tex2DNode94 = tex2Dlod( _Shadermap, float4( HeightmapUV581, 0, 1.0) );
            float temp_output_95_0 = ( saturate( ( _WaveHeight - (VertexColors729).b ) ) * tex2DNode94.g );
            float3 Displacement100 = ( ase_vertexNormal * temp_output_95_0 );
            v.vertex.xyz += Displacement100;
            o.vertexToFrag713 = lerp(( -20.0 * v.texcoord.xy ),( (ase_worldPos).xz * float2( 0.1,0.1 ) ),_Worldspacetiling);
            o.vertexToFrag714 = ( ( _Wavesspeed * _Time.x ) * appendResult500 );
            #if defined(LIGHTMAP_ON) && ( UNITY_VERSION < 560 || ( defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) ) )//aselc
            float4 ase_lightColor = 0;
            #else //aselc
            float4 ase_lightColor = _LightColor0;
            #endif //aselc
            o.vertexToFrag746 = ase_lightColor.rgb;
            
        }

        inline half4 LightingStandardCustomLighting( inout SurfaceOutputCustomLightingCustom s, half3 viewDir, UnityGI gi )
        {
            UnityGIInput data = s.GIData;
            Input i = s.SurfInput;
            half4 c = 0;
            //Start - Stylized Water custom depth
            float4 ase_screenPos = float4( i.screenPos.xyz , i.screenPos.w + 0.00000000001 );
            float4 ase_screenPosNorm = ase_screenPos / ase_screenPos.w;
            ase_screenPosNorm.z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? ase_screenPosNorm.z : ase_screenPosNorm.z * 0.5 + 0.5;
            float screenDepth795 = LinearEyeDepth(UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture,UNITY_PROJ_COORD(ase_screenPos))));
            float distanceDepth795 =  ( screenDepth795 - LinearEyeDepth( ase_screenPosNorm.z ) ) / (  lerp( 1.0 , ( 1.0 / _ProjectionParams.z ) , unity_OrthoParams.w) );
            #if SHADER_API_MOBILE && UNITY_VERSION >= 20183 //Build only, abs() function causes offset in depth on mobile in 2018.3
            #else
            distanceDepth795 = abs(distanceDepth795);
            #endif
            //End - Stylized Water custom depth
            float DepthTexture494 = distanceDepth795;
            float ColorDepth479 = lerp(1.0,saturate( ( DepthTexture494 / _Depth ) ),_EnableDepthTexture);
            float4 VertexColors729 = lerp(float4( 0,0,0,0 ),i.vertexColor,_ENABLE_VC);
            float2 Tiling21 = i.vertexToFrag713;
            float2 temp_output_24_0 = ( Tiling21 * _Rimtiling );
            float2 WaveSpeed40 = i.vertexToFrag714;
            float temp_output_30_0 = ( tex2D( _Shadermap, ( ( 0.5 * temp_output_24_0 ) + WaveSpeed40 ) ).b * tex2D( _Shadermap, ( temp_output_24_0 + ( 1.0 - WaveSpeed40 ) ) ).b );
            float Intersection42 = saturate( ( _RimColor.a * ( 1.0 - ( ( ( lerp(lerp(1.0,DepthTexture494,_EnableDepthTexture),( 1.0 - (VertexColors729).r ),_USE_VC_INTERSECTION) / _Rimfalloff ) * temp_output_30_0 ) + ( lerp(lerp(1.0,DepthTexture494,_EnableDepthTexture),( 1.0 - (VertexColors729).r ),_USE_VC_INTERSECTION) / _RimSize ) ) ) ) );
            float Opacity121 = saturate( ( ( lerp(1.0,saturate( ( DepthTexture494 / _EdgeFade ) ),_EnableDepthTexture) * saturate( ( ( _Transparency * saturate( ( ColorDepth479 + _WaterShallowColor.a ) ) ) + Intersection42 ) ) ) - (VertexColors729).g ) );
            float3 ase_worldPos = i.worldPos;
            #if defined(LIGHTMAP_ON) && UNITY_VERSION < 560 //aseld
            float3 ase_worldlightDir = 0;
            #else //aseld
            float3 ase_worldlightDir = normalize( UnityWorldSpaceLightDir( ase_worldPos ) );
            #endif //aseld
            half3 _BlankNormal = half3(0,0,1);
            float2 temp_output_705_0 = ( _NormalTiling * Tiling21 );
            #ifdef _NORMAL_MAP_ON
                float2 staticSwitch760 = ( ( float2( 0.25,0.25 ) * temp_output_705_0 ) + WaveSpeed40 );
            #else
                float2 staticSwitch760 = float2( 0,0 );
            #endif
            #ifdef _NORMAL_MAP_ON
                float2 staticSwitch761 = ( temp_output_705_0 + ( 1.0 - WaveSpeed40 ) );
            #else
                float2 staticSwitch761 = float2( 0,0 );
            #endif
            #ifdef _NORMAL_MAP_ON
                float3 staticSwitch763 = ( ( UnpackNormal( tex2D( _Normals, staticSwitch760 ) ) + UnpackNormal( tex2D( _Normals, staticSwitch761 ) ) ) / float3( 2,2,2 ) );
            #else
                float3 staticSwitch763 = _BlankNormal;
            #endif
            float3 lerpResult621 = lerp( _BlankNormal , staticSwitch763 , _NormalStrength);
            float3 NormalMap52 = lerpResult621;
            float dotResult741 = dot( ase_worldlightDir , normalize( WorldReflectionVector( i , NormalMap52 ) ) );
            float GlossParam754 = _Glossiness;
            float3 lerpResult478 = lerp( (_WaterShallowColor).rgb , (_WaterColor).rgb , ColorDepth479);
            float3 WaterColor350 = lerpResult478;
            float2 HeightmapUV581 = ( ( ( Tiling21 * _WaveSize ) * float2( 0.1,0.1 ) ) + ( WaveSpeed40 * float2( 0.5,0.5 ) ) );
            float4 tex2DNode94 = tex2D( _Shadermap, HeightmapUV581 );
            float Heightmap99 = tex2DNode94.g;
            float3 temp_cast_0 = (( Heightmap99 * _Wavetint )).xxx;
            float3 RimColor102 = (_RimColor).rgb;
            float3 lerpResult61 = lerp( ( WaterColor350 - temp_cast_0 ) , ( RimColor102 * 3.0 ) , Intersection42);
            float2 temp_output_634_0 = ( WaveSpeed40 * _FoamSpeed );
            float4 tex2DNode67 = tex2D( _Shadermap, ( ( _FoamTiling * Tiling21 ) + temp_output_634_0 + ( Heightmap99 * 0.1 ) ) );
            #ifdef _USEINTERSECTIONFOAM_ON
                float staticSwitch725 = ( 1.0 - tex2DNode67.b );
            #else
                float staticSwitch725 = saturate( ( 1000.0 * ( ( tex2D( _Shadermap, ( ( _FoamTiling * ( Tiling21 * float2( 0.5,0.5 ) ) ) + temp_output_634_0 ) ).r - tex2DNode67.r ) - _FoamSize ) ) );
            #endif
            float Foam73 = ( _FoamOpacity * staticSwitch725 );
            float3 temp_cast_1 = (2.0).xxx;
            float FoamTex244 = staticSwitch725;
            float WaveFoam221 = saturate( ( pow( ( tex2DNode94.g * _WaveFoam ) , 2.0 ) * FoamTex244 ) );
            float3 lerpResult223 = lerp( ( lerpResult61 + Foam73 ) , temp_cast_1 , WaveFoam221);
            float3 FinalColor114 = lerpResult223;
            #ifdef _LIGHTING_ON
                float3 staticSwitch769 = float3( 0,0,0 );
            #else
                float3 staticSwitch769 = ( saturate( ( pow( max( 0.0 , dotResult741 ) , ( GlossParam754 * 128.0 ) ) * GlossParam754 ) ) + lerp(( i.vertexToFrag746 * FinalColor114 ),FinalColor114,_Unlit) );
            #endif
            float3 CustomLighting753 = staticSwitch769;
            SurfaceOutputStandard s733 = (SurfaceOutputStandard ) 0;
            s733.Albedo = FinalColor114;
            s733.Normal = WorldNormalVector( i , NormalMap52 );
            s733.Emission = float3( 0,0,0 );
            s733.Metallic = _Metallicness;
            s733.Smoothness = GlossParam754;
            s733.Occlusion = 1.0;

            data.light = gi.light;

            UnityGI gi733 = gi;
            #ifdef UNITY_PASS_FORWARDBASE
            Unity_GlossyEnvironmentData g733 = UnityGlossyEnvironmentSetup( s733.Smoothness, data.worldViewDir, s733.Normal, float3(0,0,0));
            gi733 = UnityGlobalIllumination( data, s733.Occlusion, s733.Normal, g733 );
            #endif

            float3 surfResult733 = LightingStandard ( s733, viewDir, gi733 ).rgb;
            surfResult733 += s733.Emission;

            #ifdef UNITY_PASS_FORWARDADD//733
            surfResult733 -= s733.Emission;
            #endif//733
            #ifdef _LIGHTING_ON
                float3 staticSwitch734 = surfResult733;
            #else
                float3 staticSwitch734 = CustomLighting753;
            #endif
            c.rgb = staticSwitch734;
            c.a = Opacity121;
            return c;
        }

        inline void LightingStandardCustomLighting_GI( inout SurfaceOutputCustomLightingCustom s, UnityGIInput data, inout UnityGI gi )
        {
            s.GIData = data;
        }

        void surf( Input i , inout SurfaceOutputCustomLightingCustom o )
        {
            o.SurfInput = i;
            o.Normal = float3(0,0,1);
        }

        ENDCG
    }
}

My Code

private void FixedUpdate()
    {
        RaycastHit hit;
        LayerMask mask = LayerMask.GetMask("ignore");
        Physics.Raycast(transform.position, Vector3.down, out hit, Mathf.Infinity, mask);
        MeshCollider meshCollider = hit.collider as MeshCollider;
        if (!(meshCollider == null || meshCollider.sharedMesh == null))
        {
            Mesh mesh = meshCollider.sharedMesh;
            mesh.RecalculateNormals();
            Vector3[] normals = mesh.normals;
            int[] triangles = mesh.triangles;

            // Extract local space normals of the triangle we hit
            Vector3 n0 = normals[triangles[hit.triangleIndex * 3 + 0]];
            Vector3 n1 = normals[triangles[hit.triangleIndex * 3 + 1]];
            Vector3 n2 = normals[triangles[hit.triangleIndex * 3 + 2]];

            // interpolate using the barycentric coordinate of the hitpoint
            Vector3 baryCenter = hit.barycentricCoordinate;

            // Use barycentric coordinate to interpolate normal
            Vector3 interpolatedNormal = n0 * baryCenter.x + n1 * baryCenter.y + n2 * baryCenter.z;
            // normalize the interpolated normal
            interpolatedNormal = interpolatedNormal.normalized;

            // Transform local space normals to world space
            Transform hitTransform = hit.collider.transform;
            interpolatedNormal = hitTransform.TransformDirection(interpolatedNormal);

            // Display with Debug.DrawLine
            Debug.DrawRay(gameObject.transform.position, interpolatedNormal * 10f, Color.black);
        }
        //0-1 on max speed
        currentShipScalar = ((shipSpeed - (shipSpeed - Body.velocity.magnitude)) / (shipSpeed));

this only returns the mesh normal not the shader. I used this enter link description here

and this enter link description here

as my code source. I feel dumb I am just exhausted. I don't like that I have not yet understood whats going on but I have a dead line of one week. any help would be apreciated.


Solution

  • The asset you are using is just a shader. Changes in the vertex position inside a shader are just on the GPU and can not be accessed by the CPU. The asset also states, it does not support Buoyancy, so it really just is a visual thing.

    To be able to access the wave distortion you either need to have a compute shader or some other preprocessing step that calculates your changes for you, which are used afterwards inside you wave shader.

    More information on the same problem

    Might be worth taking a look at another solution (maybe the boat attack repo would be a good fit), but I don't know your target device and scope of the project (I guess you're on builtin renderer right now).