我正在使用Unity制作太空探索游戏,但是在半透明方面遇到了两个问题。
每个星球由两个球体组成:一个是表面和云层的结合体,另一个(半径略大)通过剔除前面的面并向球体外缘淡化alpha来描绘地平线“光晕”。这基本上还算正常,但以下两个问题:
1)在我的自定义表面着色器中,当我在#pragma定义中使用alpha关键字时,alpha会计入渲染的球体中,但是“光晕”球体在几千个单位的距离处消失。如果我不包含alpha关键字,则球体不会朝边缘褪色,但是它会在远处渲染。
2)尽管尝试了所有RenderType、Queue、ZWrite和ZDepth选项,表面球体和“光晕”球体仍然存在z-fighting;游戏似乎无法确定哪些多边形更接近-尽管“光晕”球体上的近面应该被剔除。我甚至尝试将“光晕”球体从玩家相机推开,并以相同比例扩展其半径,但是我仍然无法解释为什么球体之间发生z-fighting!
是否有任何设置我错过了,可以使“光晕”球体始终在表面球体的后面绘制(假设我已尝试所有ZWrite、ZDepth组合,如上所述),并且有没有方法使启用alpha的对象不会在远处消失?
我似乎无法解决这个问题,所以任何帮助都将不胜感激!
编辑
这是我的“光晕球”的着色器代码。剔除前面的面。我甚至尝试使用Offset关键字将任何绘制的多边形推离相机。我尝试了所有我能找到的Tag、ZWrite和ZTest选项。该着色器传递了一个色调颜色、大气密度浮点数和一个太阳方向向量...
Shader "Custom/planet glow" {
Properties {
_glowTint ("Glow Tint", Color) = (0.5,0.8,1,1)
_atmosphereMix ("Atmosphere Mix", float) = 0
_sunDirection ("Sun Direction", Vector) = (0, 0, 0, 0)
}
SubShader {
Tags { "RenderType" = "Opaque" "Queue" = "Geometry" }
Cull Front // I want only the far faces to render (behind the actual planet surface)
Offset 10000, 10000
ZWrite On // Off also tried
ZTest LEqual // I have tried various other options here, incombination with changing this setting in the planet surface shader
CGPROGRAM
#pragma surface surf Lambert alpha
#pragma target 4.0
struct Input {
float3 viewDir;
};
fixed4 _glowTint;
float _atmosphereMix;
float4 _sunDirection;
void surf (Input IN, inout SurfaceOutput o) {
_sunDirection = normalize(_sunDirection);
o.Albedo = _glowTint;
float cameraNormalDP = saturate(dot( normalize(IN.viewDir), -o.Normal ) * 4.5);
float sunNormalDP = saturate(dot( normalize(-_sunDirection), -o.Normal ) * 2);
o.Alpha = _atmosphereMix * sunNormalDP * (cameraNormalDP * cameraNormalDP * cameraNormalDP); // makes the edge fade 'faster'
o.Emission = _glowTint;
}
ENDCG
}
FallBack "Diffuse"
}