首页 > 解决方案 > Graphics.Blit() 似乎与我在 Android 构建上的自定义着色器混合得不好

问题描述

我在 2019.4.14f1 中有一个简单的项目,它在编辑器中运行良好,但在我为 Android 构建和运行时却没有。

我正在尝试在透明平面上“绘画”。为此,我使用了一个着色器,它采用纹理并在某些坐标处打印另一个纹理。着色器未应用于平面,但我将它与 2 Blit() 一起使用以更新平面的纹理。

我得到的错误是,在编辑器上,alpha 似乎是正常的,但在 android 上,Plane 是黑色的,我绘制的纹理没有平滑的边缘。

在飞机上,我使用的材质是Unlit/Transparent,我改为_MainTex。

着色器 DrawPaint.shader :

Shader "Unlit/DrawPaint"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
        _Coordinates("BrushCoordinates", Vector) = (0,0,0,0)
        _Color("BrushColor", Color) = (0,0,0,0)
        _SizeX("BrushSizeX", Float) = 50
        _SizeY("BrushSizeY", Float) = 50
        _BrushTex("BrushTex", 2D) = "white" {}
        _Strength("Strength", Float) = 1
    }
        SubShader
        {
            Tags {"RenderType"="Transparent" }
            LOD 100

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

                #include "UnityCG.cginc"

                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };

                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                };

                sampler2D _MainTex, _BrushTex;
                float4 _MainTex_ST;
                fixed4 _Color, _Coordinates;
                float _Strength, _SizeX, _SizeY;

                v2f vert(appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                    return o;
                }

                fixed4 frag(v2f i) : SV_Target
                {
                    half4 col = tex2D(_MainTex, i.uv);
                    half2 diff = _Coordinates.xy - i.uv;
                    half2 scaledDiff = diff * half2(_SizeX,_SizeY);
                    if (abs(scaledDiff.x) < 0.5 && abs(scaledDiff.y) < 0.5)
                    {
                        half4 texVal = tex2D(_BrushTex, scaledDiff + half2(0.5, 0.5));
                        return saturate(texVal.w > 0.01 ? _Color * texVal * _Strength + col : col);
                    }
                    else
                    {
                        return col;
                    }
                }
                ENDCG
            }
        }
}

以及飞机上的脚本:

public class DrawableSurface : MonoBehaviour
{
    [SerializeField]
    private Shader _drawShader;

    [SerializeField]
    private Texture2D _brushTex;

    private RenderTexture _paintTex;
    private Material _mat, _drawMat;

    [SerializeField]
    private float startSize = 8f;

    private void Awake() 
    {

        _drawMat = new Material(_drawShader);
        _drawMat.SetColor("_Color", Color.red);
        _drawMat.SetFloat("_SizeX", startSize);
        _drawMat.SetFloat("_SizeY", startSize);
        _drawMat.SetFloat("_Strength", 0.1f);
        _drawMat.SetTexture("_MainTex", Texture2D.whiteTexture);
        _drawMat.SetTexture("_BrushTex", _brushTex);

        _mat = GetComponent<MeshRenderer>().material;
        _paintTex = new RenderTexture(1024, 1024, 0);
        _mat.SetTexture("_MainTex", _paintTex);
    }

    public void OnHit(Vector2 texCoord)
    {
        Debug.Log("Hit at " + texCoord);
        _drawMat.SetVector("_Coordinates", new Vector4(texCoord.x, texCoord.y, 0, 0));
        RenderTexture tmp = RenderTexture.GetTemporary(_paintTex.width, _paintTex.height, 0);
        Graphics.Blit(_paintTex, tmp);
        Graphics.Blit(tmp, _paintTex, _drawMat);
        RenderTexture.ReleaseTemporary(tmp);
    }
}

然后我只是用 and 进行光线投射Physics.RaycastscreenPointToRay通过hit.texCoord

在编辑器中:
在编辑器中,一切看起来都很完美

在安卓上:
在 Android 上,背景是黑色的,而且 alpha 似乎不起作用

如果我在平面上添加具有透明度的纹理并评论_mat.SetTexture("_MainTex", _paintTex);透明度工作的线(但绘画部分显然没有:))Android 支持平面上的材料。

所以我指出错误出现在 RenderTexture 上,我怀疑 Blit,因为我已经读到它在 Android 上存在问题,添加ZTest Always到我的着色器应该可以解决它,但它不会改变任何东西。我花了一天的时间寻找答案,但找不到答案,我需要为这个项目使用 2019.4。

标签: unity3dshader

解决方案


似乎添加_paintTex.Create();解决了我的问题。我仍然不明白为什么它在编辑器中有效,但在 Android 上无效。也许渲染纹理不是在 Android 上自动创建的。


推荐阅读