使用自定义着色器调用Material.setPass会破坏GL - Unity

时间:2015-05-10 06:56:07

标签: opengl unity3d

这是我的着色器,它将一种颜色替换为另一种颜色:

Shader "Custom/SwapColors" 
{ 
    Properties
    {
        _MainTex("Texture",2D)="white"{}
        swap_from("Swap From",COLOR)=(1,1,1,1)
        swap_to("Swap To",COLOR)=(1,1,1,1)
        threshold("Threshold",Float)=0.00001
    }
    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
        }
        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            sampler2D _MainTex;
            float4 swap_from;
            float4 swap_to;
            float threshold;

            struct VertexInput
            {
                float4 pos:POSITION;
                float2 uv:TEXCOORD0;
            };
            struct FragmentInput
            {
                float4 pos:SV_POSITION;
                float2 uv:TEXCOORD0;
            };

            FragmentInput vert(VertexInput data)
            {
                FragmentInput res;
                res.pos=mul(UNITY_MATRIX_MVP,data.pos);
                res.uv=data.uv;
                return res;
            }
            bool eq(fixed f,fixed s)
            {
                return abs(f-s)<threshold;
            }
            float4 frag(FragmentInput data):COLOR
            {
                float4 res=tex2D(_MainTex,data.uv.xy).rgba;
                if(eq(res.r,swap_from.r)&&eq(res.g,swap_from.g)&&eq(res.b,swap_from.b))
                    res.rgb=swap_to.rgb;
                return res;
            }
            ENDCG
        }
    }
    Fallback "Diffuse"
}

这是一个附加到gameobject的测试脚本,其中包含主摄像头。在其中我尝试渲染一条线和纹理四边形。

mat分配了带有纹理的SwapColors

sprite_mat分配了具有相同纹理的默认精灵着色器。

using UnityEngine;
using System.Collections; 

public class Test : MonoBehaviour 
{
    [SerializeField]
    Material mat;
    [SerializeField]
    Material sprite_mat;
    void OnPostRender()
    {


        GL.PushMatrix();
        GL.LoadProjectionMatrix(Camera.main.projectionMatrix);
        GL.modelview=Camera.main.worldToCameraMatrix;

        GL.Begin(GL.LINES);
        sprite_mat.SetPass(0);
        GL.Vertex(new Vector3(0,0));
        GL.Vertex(new Vector3(5,0));
        GL.End();


        GL.Begin(GL.QUADS);
        sprite_mat.SetPass(0);

        mat.SetPass(0);//<------------------------------------ PROBLEM

        GL.TexCoord(new Vector3(0,0));
        GL.Vertex(new Vector2(0,0));

        GL.TexCoord(new Vector3(1,0));
        GL.Vertex(new Vector2(1,0));

        GL.TexCoord(new Vector3(1,1));
        GL.Vertex(new Vector2(1,1));

        GL.TexCoord(new Vector3(0,1));
        GL.Vertex(new Vector2(0,1));
        GL.End();


        GL.PopMatrix();
    }
}

当我用sprite_mat渲染四边形时,一切正常。

当我使用mat时,不仅四边形消失,,但线条,尽管它是用sprite_mat渲染的。

如果我在编辑器中创建另一个四边形并将其材质设置为mat,则会正确渲染它。

我的主要问题是setPass如何影响在另一个不相关的setPass之后呈现的几何体。

示例项目: forum.unity3d.com/attachments/errorgl-7z.138105 /

编辑:我找到了一个默认的Unity精灵着色器并将其与我的相比较。四边形消失了,因为它面向相机的相反方向。它由Cull Off修正。

如果我添加行

float4 color:COLOR;

VertexInput结构,使用我的着色器的材质会停止使用其他材质影响几何体。我不明白发生了什么。

1 个答案:

答案 0 :(得分:0)

我认为您SetPass(0)GL.Begin(..)之间GL.End(..)两次不能{。}}。

您可以使用SetPass(0); [..] SetPass(1);设置各种通行证,但查看着色器我认为这不是您想要做的。

所以你试图通过2次传球来制作四边形吗?一个使用默认的Sprite材质,另一个使用自定义材质?或者只画两次?

我不完全明白你想在这做什么。