2016-02-05 43 views
12

我在Unity中制作了一个太空探索游戏,我遇到了半透明问题。在Unity5中正确渲染半透明球体

每个行星都由两个球体组成:一个是组合表面和云层,另一个(半径稍大)通过剔除正面和衰落alpha到外边缘来描述地平线'发光'领域。这主要是做工精细,但有以下两个问题:

1)在我定制的表面材质,当我使用Alpha关键字在#pragma定义,阿尔法被计入呈现球面,但“光晕”球体在几千个单位的距离消失。如果我不包含alpha关键字,则球体不会向边缘褪色,但会在距离处呈现。 2)尽管尝试所有的RenderType,Queue,ZWrite和ZDepth选项,表面球体和'发光'球体是z战斗;游戏似乎无法确定哪个多边形更近 - 尽管事实上发光球面上的近面应该被淘汰。我甚至试图将发光球从球员相机中推开,并以相同的比例扩大其半径,但我仍然莫名其妙地获得了球体之间的z战斗!

有没有办法,我失踪,这将使该“光晕”领域的任何设置总是被画后面的表面球(因为我已经试过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" 
} 
+0

你使用LOD吗?像LOD 250一样?如果是删除它。 –

+0

不包含LOD。感谢指针,但。 – moosefetcher

+0

你可以在这里包含着色器的代码吗?我想不出任何会导致这种影响的事情。另外,ZTest Off是一个有效的选择,尽管没有在官方的Unity手册中列出。 – HalpPlz

回答

0

我似乎在解决这个问题都有所涉猎,而试图解决世界空间“抖动” .. 我正在开发的游戏使用很远的距离。我改变了长距离物体的定位方式(距离越来越近,物体距离相机越远),这就解决了z战斗和alpha消失。 整个太阳系通过使用距离除以距离的平方根,乘以相对的Vector3和物体的比例尺,可以拟合成300000公里的距离。希望这些信息可能对某人有用。

0

如果您使用的是alpha,那么您需要更改标签以在透明度传递中呈现alpha。同时关闭ZWrite。并删除偏移量。

我在一个空的项目中使用Forward和Deferred渲染测试了你的着色器。这些调整效果很好。

首先绘制所有不透明的几何图形,然后完成alpha通道并渲染场景中所有对象的TOP都具有透明度的所有对象。它需要这样做,否则它将无法混合alpha的颜色。

Tags { "RenderType" = "Transparent" "Queue" = "Transparent" } 
ZWrite Off 
0

你有没有想过在其他相机不同的比例绘制大型对象来创建动态天空体?这肯定会解决z战斗问题。 例如,您可以拥有两个摄像头 - 一个渲染范围为0.1-1000的对象,另一个摄像头的范围从1000到100000.

附加优化可以包括从远处渲染环境到立方体天空框,然后执行此操作不是每一帧(除非你在远方摧毁一颗行星时的特殊场合除外)。

另外还有一个优化问题 - 您可以在地球周围绘制一个平坦的环,旋转以面对相机,以避免在实际行星表面上透支。但显然,这需要更复杂的照明计算。

另外,你有没有试过你的透明着色器没有Skybox作为清除标志的相机?请检查this answer如何使用自定义天空盒。

+0

欢迎来到StackOverflow!下次尝试发布一些示例代码作为您的答案,因为链接可能会失效 – cdomination

+0

Skybox代码与此答案无关。 – mcfrei