unity3d - 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.Raycast
并screenPointToRay
通过hit.texCoord
如果我在平面上添加具有透明度的纹理并评论_mat.SetTexture("_MainTex", _paintTex);
透明度工作的线(但绘画部分显然没有:))Android 支持平面上的材料。
所以我指出错误出现在 RenderTexture 上,我怀疑 Blit,因为我已经读到它在 Android 上存在问题,添加ZTest Always
到我的着色器应该可以解决它,但它不会改变任何东西。我花了一天的时间寻找答案,但找不到答案,我需要为这个项目使用 2019.4。
解决方案
似乎添加_paintTex.Create();
解决了我的问题。我仍然不明白为什么它在编辑器中有效,但在 Android 上无效。也许渲染纹理不是在 Android 上自动创建的。
推荐阅读
- firebase - 如何迁移到散列的 Firebase 密码?
- c# - Linq 采取不同的方式
- sql - 为什么放置 sum(case...) 会改变我的答案?
- reactjs - 更改页面时是否在 Reactjs 中重新加载应用程序会删除所有已保存的状态
- c++ - 为什么 vs code 中的默认构建任务在 powershell 中运行,而不是在选择的默认终端中运行?
- django - 如何在 Django 中检索货币并在反应前端显示它们?
- amazon-web-services - AWS Route 53 - 如何将流量路由到负载均衡器,包括上下文路径?
- laravel - 使用数据表中的一个下拉过滤器进行多表搜索
- terraform - 如果我可以更改目录,terraform 1.0.6 找不到提供者
- python - 使用python从字符串中提取数据(将字符串字典转换为字典)