2
\$\begingroup\$

I get this really strange effect in my builds, and only in builds, when particles intersect with/go under the water:

enter image description here enter image description here

Supposed to look like:

enter image description here

I have no idea what to search for or what to look for, any clues?

EDIT:

Water shader causing issues (purchased asset, I've written the seller):

enter image description here

Particle used:

enter image description here enter image description here

I've tried messing around with render queues and settings on the particle system, but no real luck.

EDIT: It seems if I disable the depth effects on the component in the editor, the issue dissapears. Here is code from the class "LPWDepthEffect"

    using System.Collections.Generic;
using UnityEngine;

namespace LPWAsset {
    [ExecuteInEditMode]
    public class LPWDepthEffect : MonoBehaviour {

        static Dictionary<Camera, Camera> depthCams = new Dictionary<Camera, Camera>();
        static Dictionary<Camera, float> camState = new Dictionary<Camera, float>();
        static RenderTexture depthTex = null;

        static Shader depthShader = null;
        bool receiveShadows;
        static bool recursiveGuard;

        static bool hideObjects = true;

        public void Init(bool receiveShadows) {
            this.receiveShadows = receiveShadows;
        }

        public void OnWillRenderObject() {
            var act = gameObject.activeInHierarchy && enabled;
            if (!act || !GetComponent<Renderer>()) return;

            var material = GetComponent<Renderer>().sharedMaterial;
            if (!material || !material.HasProperty("_EdgeBlend")) return;

            Camera cam = Camera.current;
            if (!cam) return;

            bool hasDepth = material.GetFloat("_EdgeBlend") > 0.5f ||
                (material.HasProperty("_LightAbs") && material.GetFloat("_LightAbs") > 0.5f);

            if (hasDepth) cam.depthTextureMode |= DepthTextureMode.Depth;

            if (!receiveShadows || !hasDepth) return; // only when both depth + shadows

            // Render only once per camera
            float lastRender;
            if (camState.TryGetValue(cam, out lastRender)) {
                if (Mathf.Approximately(Time.time, lastRender) && Application.isPlaying) return;
                camState[cam] = Time.time;
            } else {
                camState.Add(cam, Time.time);
            }

            // Safeguard from recursive 
            if (recursiveGuard) return;
            recursiveGuard = true;

            // Rendertexture
            if (!depthTex) {
                depthTex = new RenderTexture(cam.pixelWidth, cam.pixelHeight, 24, RenderTextureFormat.Depth);
                depthTex.name = "__DepthTex" + GetInstanceID();
                depthTex.hideFlags = HideFlags.DontSave;
            }

            // Camera
            Camera depthCam = null;
            depthCams.TryGetValue(cam, out depthCam);
            if (!depthCam) { // catch both not-in-dictionary and in-dictionary-but-deleted-GO
                GameObject go = new GameObject("Water Depth Camera id" + GetInstanceID() + " for " + cam.GetInstanceID(), typeof(Camera));
                depthCam = go.GetComponent<Camera>();
                depthCam.enabled = false;
                depthCam.transform.position = transform.position;
                depthCam.transform.rotation = transform.rotation;
                go.hideFlags = hideObjects ? HideFlags.HideAndDontSave : HideFlags.DontSave;
                depthCams[cam] = depthCam;
                depthCam.clearFlags = CameraClearFlags.Depth;
            }

            int oldPixelLightCount = QualitySettings.pixelLightCount;
            QualitySettings.pixelLightCount = 0;
            float oldShadowDistance = QualitySettings.shadowDistance;
            QualitySettings.shadowDistance = 0;

            if (depthCam != null) {
                depthCam.farClipPlane = cam.farClipPlane;
                depthCam.nearClipPlane = cam.nearClipPlane;
                depthCam.orthographic = cam.orthographic;
                depthCam.fieldOfView = cam.fieldOfView;
                depthCam.aspect = cam.aspect;
                depthCam.orthographicSize = cam.orthographicSize;
                depthCam.depth = cam.depth - 0.1f;

                //Render
                depthCam.worldToCameraMatrix = cam.worldToCameraMatrix;
                depthCam.projectionMatrix = cam.projectionMatrix;
                depthCam.cullingMask = ~(1 << 4) & cam.cullingMask; // without water
                depthCam.targetTexture = depthTex;
                depthCam.transform.position = cam.transform.position;
                depthCam.transform.rotation = cam.transform.rotation;
                if(depthShader == null) {
                    depthShader = Shader.Find("Hidden/LPWRenderDepth");
                }
                depthCam.renderingPath = RenderingPath.VertexLit;
                depthCam.RenderWithShader(depthShader, "RenderType");
                GetComponent<Renderer>().sharedMaterial.SetTexture("_DepthTexture", depthTex);
            }

            QualitySettings.pixelLightCount = oldPixelLightCount;
            QualitySettings.shadowDistance = oldShadowDistance;
            recursiveGuard = false;

        }

        // Cleanup all the objects we possibly have created
        void OnDisable() {
            if (depthTex) {
                Destroy_(depthTex);
                depthTex = null;
            }
            foreach (var kvp in depthCams) {
                Destroy_((kvp.Value).gameObject);
            }
            depthCams.Clear();
            camState.Clear();
        }

        public void Destroy_(Object o) {
            if (Application.isPlaying) Destroy(o);
            else DestroyImmediate(o);
        }

    }
}

And here is the DepthShader:

Shader "Hidden/LPWRenderDepth" {

    SubShader {
        Tags { "RenderType"="Opaque" }
        Pass {
            ZWrite On
            Lighting Off
            ColorMask 0

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0

            #include "UnityCG.cginc"

            struct appdata {
              float3 pos : POSITION;
            };

            struct v2f {
              float4 pos : SV_POSITION;
            };

            v2f vert (appdata IN) {
              v2f o;
              o.pos = UnityObjectToClipPos(IN.pos);
              return o;
            }

            fixed4 frag (v2f IN) : SV_Target {
              return fixed4(0,0,0,0);
            }
            ENDCG
        }
    }

    SubShader {
        Tags { "RenderType"="Transparent" }

        Pass {
            ZWrite Off
            Lighting Off
            ColorMask 0

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0

            #include "UnityCG.cginc"

            float4 vert () : SV_POSITION {
              return float4(0,0,0,0);
            }

            fixed4 frag () : SV_Target {
              return fixed4(0,0,0,0);
            }
            ENDCG
        }
    }

    SubShader {
        Tags { "RenderType"="TransparentCutout" }

        Pass {
            ZWrite Off
            Lighting Off
            ColorMask 0

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0

            #include "UnityCG.cginc"

            float4 vert () : SV_POSITION {
              return float4(0,0,0,0);
            }

            fixed4 frag () : SV_Target {
              return fixed4(0,0,0,0);
            }
            ENDCG
        }
    }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ Are you using particles in your project? How did you make the water/character? Is there a chance you are using particles for a "splashing" effect which just doesn't work on builds? \$\endgroup\$ – TomTsagk Aug 3 '19 at 18:31
  • 1
    \$\begingroup\$ Can you please include enough details of your terrain, water, and particle setup (materials, shaders, etc) so that we can reproduce this effect in a new empty project? This will let us test solutions to be sure they work for your case. For starters, suspect #1 for squares around transparent objects is writing to the depth buffer when you shouldn't, so be sure to pay attention to where you're using transparent shaders, and what queue/order you're drawing in. \$\endgroup\$ – DMGregory Aug 3 '19 at 23:40
  • \$\begingroup\$ @DMGregory Thanks I realize I didnt provide much info. I tried to update with what I think is relevant. Please let me know if something important is missing. \$\endgroup\$ – Majs Aug 4 '19 at 10:37
  • \$\begingroup\$ I realize now that the cause is the water shader, and since that is a purchased asset that I cannot share, it will be hard to debug this. I can only hope someone ran into something similar. \$\endgroup\$ – Majs Aug 6 '19 at 20:50
  • 1
    \$\begingroup\$ @SeyedMortezaKamali Could it be caused by the Shader.Find("...")? I think I stumbled upon that during my research earlier, that it might cause issues in builds. \$\endgroup\$ – Majs Aug 7 '19 at 20:56
1
+200
\$\begingroup\$

This was solved by moving the shaders to the "Assets/Resources" folder, since the scripts use Shader.Find("...")

\$\endgroup\$
-1
\$\begingroup\$

Observing the problem, I believe the random quad projections in the water are actually the quads of the particles without their texture rendering correctly. i imagine that Shader.Find("...") was previously unable to find the texture to render onto each quad(if you don't know, a particle is an actual image, usually a blurry circle, mapped to a texture2D, mapped to a simple quad for performance speed), but would still render the quad and their respective color filters. I hope that sheds some light on the problem even though it was already solved.

\$\endgroup\$
  • 1
    \$\begingroup\$ I already added this as an answer 6 hours ago? \$\endgroup\$ – Majs Aug 8 '19 at 7:04
  • \$\begingroup\$ While shader.Find(...) Was mentioned as an answer, no reason was given. Comments in the question seemed to end at "maybe its the buffer". Stack exchange seeks to educate users rather than simply provide solutions. I offered my answer with elaboration on what was likely appearing, how it might be fixed, and why it appeared that way to begin with. Sorry if i missed that information somewhere else \$\endgroup\$ – Jody Sowald Aug 9 '19 at 4:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.