【发布时间】:2020-03-13 05:45:14
【问题描述】:
我对着色器真的很陌生。我在不同的论坛上搜索了类似的问题,但没有一个能帮助我解决我正在努力解决的问题。
基本上,我必须制作一个将 6 个纹理合并为一个的着色器。我有6层。每一层都是一个纹理,所有这些层都必须相互叠加显示。每层纹理大小相同。
这是我现在的代码:
Shader "TileShaders/Chunk"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_SecondLayer ("Second Layer", 2D) = "white" {}
_ThirdLayer ("Third Layer", 2D) = "white" {}
_FourthLayer ("Fourth Layer", 2D) = "white" {}
_FifthLayer ("Fifth Layer", 2D) = "white" {}
_SixthLayer ("Sixth Layer", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Cull Off
Lighting Off
ZWrite Off
Blend One OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ PIXELSNAP_ON
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
fixed4 _Color;
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = UnityObjectToClipPos(IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color;
#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif
return OUT;
}
sampler2D _MainTex;
sampler2D _AlphaTex;
float _AlphaSplitEnabled;
fixed4 SampleSpriteTexture (float2 uv)
{
fixed4 color = tex2D (_MainTex, uv);
#if UNITY_TEXTURE_ALPHASPLIT_ALLOWED
if (_AlphaSplitEnabled)
color.a = tex2D (_AlphaTex, uv).r;
#endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWED
return color;
}
fixed4 frag(v2f IN) : SV_Target
{
fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
c.rgb *= c.a;
return c;
}
ENDCG
}
}
}
它是 Sprites/Default unity shader,我只是添加了这几个变量,因为我知道我需要这些数据来将其显示为一个纹理:
_SecondLayer ("Second Layer", 2D) = "white" {}
_ThirdLayer ("Third Layer", 2D) = "white" {}
_FourthLayer ("Fourth Layer", 2D) = "white" {}
_FifthLayer ("Fifth Layer", 2D) = "white" {}
_SixthLayer ("Sixth Layer", 2D) = "white" {}
这就是我所做的一切。我真的不知道如何开始。这是我第一次用着色器做一些事情
编辑
感谢您的回复! lerp() 帮了我很多,没有它,所有层都同时可见,看起来真的很奇怪。
现在一切看起来都很棒。但是有一个小问题。只要所有图层都包含纹理,它看起来就很棒。但是如果只有一层分配了纹理而其余的没有分配,则整个结果纹理是白色的。
这就是代码现在的样子:
fixed4 c = tex2D(_MainTex, IN.texcoord);
fixed4 c2 = tex2D(_SecondLayer, IN.texcoord);
fixed4 returnTexture = c;
returnTexture.rgba = lerp(c, c2, c2.a).rgba;
return returnTexture;
为了避免这个问题,我正在考虑 if 语句将检查每一层上的纹理是否存在,但我听说如果可能的话我应该随时避免它。有没有更好的处理方法?
编辑 2 由于我对帖子删除的最新回答,我不知道最终帮助我的答案是否仍然可见,但这是来自:trojanfoe 的解决方案
请编辑您的原始问题,而不是创建答案来扩展您的问题。不要使用 if 语句;相反,您可能想要使用着色器功能并使用#if HAVE_TEXTURE_2 等。这样统一将生成着色器的多个版本,每个版本都针对“打开”的纹理量身定制。此外,您不需要 .rgba swizzles,因为这是默认设置。
编辑 3
所以我尝试将所有这些层叠加显示,但 lerp() 存在一些问题。
fixed4 c1 = tex2D(_MainTex, IN.texcoord);
fixed4 c2 = tex2D(_SecondLayer, IN.texcoord);
fixed4 c3 = tex2D(_ThirdLayer, IN.texcoord);
fixed4 c4 = tex2D(_FourthLayer, IN.texcoord);
fixed4 c5 = tex2D(_FifthLayer, IN.texcoord);
fixed4 c6 = tex2D(_SixthLayer, IN.texcoord);
fixed4 returnTexture1 = c1;
fixed4 returnTexture2 = c2;
fixed4 returnTexture3 = c3;
fixed4 returnTexture4 = c4;
fixed4 returnTexture5 = c5;
fixed4 returnTexture6 = c6;
returnTexture1 = lerp(c1, c2, c2.a);
returnTexture2 = lerp(c3, c4, c4.a);
returnTexture3 = lerp(c5, c6, c6.a);
fixed4 returnAlmostFinalTexture = lerp(returnTexture1, returnTexture2, returnTexture2.a);
fixed4 returnFinalTexture = lerp(returnTexture2, returnTexture3, returnTexture3.a);
return returnFinalTexture;
'returnAlmostFinalTexture' 可以正常工作,但 'returnFinalTexture' 会中断。 现在我有 4 个工作层,但我无法让所有 6 个工作层都工作。但我很确定如果我总共有 8 层,它就可以完成工作。
我可以更轻松地处理超过 2 个纹理吗?
编辑 4
好吧,我得到了这个工作,这就是现在的样子:
fixed4 c1 = tex2D(_MainTex, IN.texcoord);
fixed4 c2 = tex2D(_SecondLayer, IN.texcoord);
fixed4 c3 = tex2D(_ThirdLayer, IN.texcoord);
fixed4 c4 = tex2D(_FourthLayer, IN.texcoord);
fixed4 c5 = tex2D(_FifthLayer, IN.texcoord);
fixed4 c6 = tex2D(_SixthLayer, IN.texcoord);
fixed4 returnTexture1 = lerp(c1, c2, c2.a);
fixed4 returnTexture2 = lerp(c3, c4, c4.a);
fixed4 returnTexture3 = lerp(c5, c6, c6.a);
fixed4 returnAlmostFinalTexture = lerp(returnTexture1, returnTexture2, returnTexture2.a);
fixed4 returnFinalTexture = lerp(returnAlmostFinalTexture, returnTexture3, returnTexture3.a);
return returnFinalTexture;
这是我能做到的最好方法吗?或者我可以以某种方式更轻松/更优化地处理所有这些纹理?
【问题讨论】: