Jump to content
Unity Insider Forum
Sign in to follow this  
Kojote

Shader Bug

Recommended Posts

Grüße!

Ich habe gerade festgestellt, dass der Standard-Shader von Unity einen kleinen Bug hat. Habe dazu mal ein Bild angehangen. Im Rendering Mode Opaque (rechte Seite) ist alles OK. Stelle ich hingegen auf Fade oder Transparent kommen Fehler hervor (linke Seite). Anscheinend sind das Fragmente des Rückens und des Arms, die da durchscheinen. Da ich Fade nur einen kurzen Augenblick brauche, wenn ich den Alpha nutze, dachte ich, ich lasse den Shader auf Opaque und stelle den Mode per Script um.

material.SetFloat("_Mode", 2f); 

Lustigerweise reagiert er nur auf den Script, wenn ich selber noch einmal im Inspector unten im Shader auf das kleine Dreieck drücke (links ganz unten).

Habt ihr eine Idee?

Grüße von Kojote

Shader Bug.jpg

Share this post


Link to post
Share on other sites

Ich hätte es auch so gemacht, aber noch besser wäre du machst es folgendermaßen, da ich mir auch nicht sicher wäre, wie der Shader auf ein Umschalten im laufenden Betrieb reagiert:

- 1 Material für Charakter normal
- 1 Fade-Material für Charakter

Wenn du nun den Spieler ausblenden willst, tauschst du erst die beiden Materialien aus und blendest dann erst aus. Damit kannst du auch Fehler im Fade-Material bereits während der Entwicklung entdecken und auch ohne das Skript das Material bereits im Editor austauschen.

Wo die Fehler beim Fade-Material herkommen ist schwer zu sagen. Vielleicht eine Art "Z-Fighting", wenn 2 Meshes zu nah aneinander liegen, kann es passieren, daß der Shader die Renderreihenfolge der Meshes nicht korrekt bestimmt. Dadurch wird ein Mesh mal verdeckt und mal nicht.

Zudem kann es auch sein, daß deine Albedo-Charaktertextur bereits einen Alphawert < 1.0 besitzt und damit bereits Teile ausgeblendet werden ...
Um das zu korrigieren müsste man entweder die Texturen überarbeiten oder einen speziellen Fade-Shader verwenden der nur nach "_Color" ausblendet.

Share this post


Link to post
Share on other sites

Ich hab mal schnell einen "Custom-Fade-Shader" gebastelt. Dieser nimmt nur die Alphainformation von "_Color".
Kannst es ja mal damit testen:

Shader "Custom/Fade" {
	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
	    _BumpMap("Bumpmap", 2D) = "bump" {}
		_Glossiness ("Smoothness", Range(0,1)) = 0.5
		_Metallic ("Metallic", Range(0,1)) = 0.0
	}
	SubShader {
	    Tags{ "RenderType" = "Transparent" "Queue" = "Transparent" }
		LOD 200

		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard fullforwardshadows alpha:fade

		// Use shader model 3.0 target, to get nicer looking lighting
		#pragma target 3.0

		sampler2D _MainTex;
		sampler2D _BumpMap;

		struct Input {
			float2 uv_MainTex;
			float2 uv_BumpMap;
		};

		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
		// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
		// #pragma instancing_options assumeuniformscaling
		UNITY_INSTANCING_BUFFER_START(Props)
			// put more per-instance properties here
		UNITY_INSTANCING_BUFFER_END(Props)

		void surf (Input IN, inout SurfaceOutputStandard o) {
			// Albedo comes from a texture tinted by color
			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c.rgb;
			o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
			// Metallic and smoothness come from slider variables
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = _Color.a;
		}
		ENDCG
	}
	FallBack "Diffuse"
}

 

Share this post


Link to post
Share on other sites

Der Spieler wird damit komplett weiß.

Shader error in 'Custom/Fade': Unexpected identifier "UNITY_INSTANCING_BUFFER_START". Expected one of: typedef const void inline uniform nointerpolation extern shared static volatile row_major column_major struct or a user-defined type at line 35

 

Share this post


Link to post
Share on other sites

Nimmt mal diese Zeilen aus dem Shader raus. "Instanzing" brauchen wir gerade nicht...

	// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
	// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
	// #pragma instancing_options assumeuniformscaling
	UNITY_INSTANCING_BUFFER_START(Props)
		// put more per-instance properties here
		UNITY_INSTANCING_BUFFER_END(Props)

 

Share this post


Link to post
Share on other sites
Shader "Custom/Fade" {
	Properties{
		_Color("Color", Color) = (1,1,1,1)
		_MainTex("Albedo (RGB)", 2D) = "white" {}
		_BumpMap("Bumpmap", 2D) = "bump" {}
		_Glossiness("Smoothness", Range(0,1)) = 0.5
		_Metallic("Metallic", Range(0,1)) = 0.0
	}
	
	SubShader{
	Tags{ "RenderType" = "Transparent" "Queue" = "Transparent" }
	LOD 200

	CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard fullforwardshadows alpha:fade

		// Use shader model 3.0 target, to get nicer looking lighting
		#pragma target 3.0

		sampler2D _MainTex;
		sampler2D _BumpMap;

		struct Input {
			float2 uv_MainTex;
			float2 uv_BumpMap;
		};

		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		void surf(Input IN, inout SurfaceOutputStandard o) {
			// Albedo comes from a texture tinted by color
			fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c.rgb;
			o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
			// Metallic and smoothness come from slider variables
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = _Color.a;
		}
	ENDCG
	}
	FallBack "Diffuse"
}

 

Share this post


Link to post
Share on other sites

Jetzt scheint es zu funktionieren. Und dieser Shader ist jetzt wie der Standardshader?

EDIT: Gleiches Problem wie beim Standardshader. Habs gerade heraus gefunden, ist genauer gesagt der Hals, der das Problem macht. 

Edited by Kojote

Share this post


Link to post
Share on other sites

Ja, ist ein Surfaceshader der auf dem Unitystandardshader basiert ....

Dann liegt es wohl nicht am Alphawert der Textur ...

Haben wirklich alle Materialien des Charakter das gleiche Material, also z.b. "Custom/Fade" ?? 
Wenn man Materialien mischt entstehen häufig solche Probleme.

Share this post


Link to post
Share on other sites

Das Material tauschen hat auch nichts gebracht. Er reagiert trotzdem nicht auf einen neuen Rendering Mode bis ich im Inspector wieder das kleine Dreieck drücke.

Mal sehen ob das hilft: https://sassybot.com/blog/swapping-rendering-mode-in-unity-5-0/

EDIT:

Jap, dass Hilft! Mal als Hilfestellung, wenn wer das selbe machen will, hier der Code.

Initialisierung:

SkinnedMeshRenderer smr = this.gameObject.GetComponentInChildren<SkinnedMeshRenderer>();
Material material = smr.material;
Color32 col = material.GetColor("_Color");

Methoden:

    private void WechselMaterialStandard() {
        material.SetFloat("_Mode", 0);
        material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
        material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
        material.SetInt("_ZWrite", 1);
        material.DisableKeyword("_ALPHATEST_ON");
        material.DisableKeyword("_ALPHABLEND_ON");
        material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
        material.renderQueue = -1;
    }

    private void WechselMaterialFade() {
        material.SetFloat("_Mode", 2);
        material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
        material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
        material.SetInt("_ZWrite", 0);
        material.DisableKeyword("_ALPHATEST_ON");
        material.DisableKeyword("_ALPHABLEND_ON");
        material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
        material.renderQueue = 3000;
    }

Kann man zum Beispiel in eine Corouine packen:

    private IEnumerator LuftkollisionCoroutine() {
        WechselMaterialFade();
        while (col.a >= 10) {
            col.a -= 10;
            material.SetColor("_Color", col);
            yield return new WaitForFixedUpdate();
        }
        col.a = 0;
    }

Und halt wann man will wieder zurück ändern:

WechselMaterialStandard();
col.a = 255;
material.SetColor("_Color", col);

@Sascha - wäre vielleicht auch was für den Snipped bzw. Tutorial Bereich?

Share this post


Link to post
Share on other sites

Also ein Austauschen des Materials sollte eigentlich funktionieren. Warum sollte das Fadematerial versagen, du stellst ja hier nichts zur Laufzeit um. Wenn man zur Laufzeit den Shader "manipuliert" kann deine obere Methode natürlich notwendig sein. Aber wie gesagt, wenn du ein Material mit "Opaque" definierst und ein anderes Material mit "Fade" und das Material beim Renderer zur Laufzeit austauschst sollte man an den Materialien eigentlich nichts "drehen" müssen. Aber trotzdem interessant wie man zur Laufzeit einen Shader ändert.

So gleich noch in die Tat umgesetzt (wollte es doch mal überprüfen). "F1" - Ausblenden "F2" - Einblenden
So hast du auch gleich noch ein "Fade In". Das kann man verwenden, wenn der Spieler wieder spawnt.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SwapMaterial : MonoBehaviour {

    public Material m_Normal;
    public Material m_Fade;

    private Renderer m_Renderer;
    private Material m_Current;

    // Use this for initialization
    void Start () {
        m_Renderer = GetComponent<Renderer>();
        m_Current = m_Normal;
    }
	
	// Update is called once per frame
	void Update () {
		if (Input.GetKeyDown(KeyCode.F1))
        {
            StartCoroutine(FadeOut());
        }

        if (Input.GetKeyDown(KeyCode.F2))
        {
            StartCoroutine(FadeIn());
        }
    }

    private IEnumerator FadeIn()
    {
        SwitchMaterial(m_Fade);

        Color32 col = m_Current.GetColor("_Color");
        col.a = 0;
        m_Current.SetColor("_Color", col);

        while (col.a <= 245)
        {
            col.a += 10;
            m_Current.SetColor("_Color", col);
            yield return 0;
        }
        col.a = 255;

        SwitchMaterial(m_Normal);
    }

    private IEnumerator FadeOut()
    {
        SwitchMaterial(m_Fade);

        Color32 col = m_Current.GetColor("_Color");
        col.a = 255;
        m_Current.SetColor("_Color", col);

        while (col.a >= 10)
        {
            col.a -= 10;
            m_Current.SetColor("_Color", col);
            yield return 0;
        }
        col.a = 0;
    }

    void SwitchMaterial(Material material)
    {
       m_Current = material;
       m_Renderer.material = m_Current;
    }
}

 

Share this post


Link to post
Share on other sites

Tja keine Ahnung warum er den Rendering Mode nicht ändert. Hatte zwei Texturen, eine Opaque, eine Fade. Habe die Textur geändert, aber der Rendering Mode wurde nicht aktualisiert. Fand ich auch komisch, eigentlich sollte er es doch übernehmen.

Share this post


Link to post
Share on other sites
vor 6 Stunden schrieb Kojote:

wäre vielleicht auch was für den Snipped bzw. Tutorial Bereich?

Schaden tut sowas selten ;)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×