【问题标题】:Correctly render semi-transparent sphere in Unity5在 Unity5 中正确渲染半透明球体
【发布时间】:2016-02-05 13:11:20
【问题描述】:

我正在使用 Unity 制作太空探索游戏,但在半透明方面遇到了两个问题。

每个行星都由两个球体组成:一个是地表和云层的组合,另一个(半径稍大)通过剔除正面和向球体外边缘衰减 alpha 来描绘地平线“发光” .这大部分工作正常,但存在以下两个问题:

1) 在我的自定义表面着色器中,当我在#pragma 定义中使用 alpha 关键字时,alpha 会被计入渲染球体,但“发光”球体会在几千个单位的距离处消失。如果我不包含 alpha 关键字,则球体不会向边缘淡化,但会在远处呈现。

2) 尽管尝试了所有 RenderType、Queue、ZWrite 和 ZDepth 选项,但表面球体和“发光”球体是 z-fighting;游戏似乎无法确定哪些多边形更接近 - 尽管事实上应该剔除发光球体上的近面。我什至尝试将发光球体推离玩家相机并将其半径扩大相同的比例,但我仍然莫名其妙地在球体之间进行 z-fighting!

是否有任何我遗漏的设置可以使“发光”球体始终绘制在表面球体后面(鉴于我已经尝试了 ZWrite、ZDepth 的所有组合,如上所述)并且有没有办法启用 alpha 的对象不会在远处消失吗?

我似乎无法弄清楚这一点,因此我们将不胜感激任何帮助!

编辑
这是我的“发光球”的着色器代码。正面被剔除。我什至尝试使用 Offset 关键字将任何绘制的多边形“推”离相机更远。我已经尝试了所有能找到的 Tag、ZWrite 和 ZTest 选项。着色器传递了一个 tint Color、一个大气密度浮点数和一个太阳方向矢量...

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"
}

【问题讨论】:

  • 你使用LOD吗?喜欢 LOD 250?如果是,请将其删除。
  • 不包括细节层次。不过感谢您的指点。
  • 您能在此处包含您的着色器代码吗?我想不出任何会导致这种效果的东西。此外,ZTest Off 是一个有效的选项,尽管官方 Unity 手册中没有列出。
  • 即使添加赏金也没有产生答案。有人有想法吗?我可以提供更多信息吗?

标签: unity3d shader alpha


【解决方案1】:

您是否考虑过在另一台摄像机中以不同比例渲染大型物体以创建动态天空盒?这肯定会解决z-fighting问题。 例如,您可以拥有两台摄像机 - 一台渲染范围为 0.1-1000 的对象,另一台渲染范围为 1000 到 100000 的对象。

额外的优化可以包括从远处渲染环境到立方体天空盒,而不是每一帧都这样做(除非你从远处摧毁一个星球的特殊场合)。

还有另一个优化问题 - 您可以在行星周围渲染一个扁平环,旋转以面向相机,以避免在实际行星表面上过度绘制。但这显然需要更复杂的照明计算。

另外,您是否在没有 Skybox 作为清晰标志的相机上尝试过您的透明着色器?查看this answer 了解如何使用自定义天空盒。

【讨论】:

  • 欢迎来到 StackOverflow!下次,请尝试发布一些示例代码作为您的答案,因为链接可能会失效
【解决方案2】:

我似乎在尝试解决世界空间“抖动”时偶然发现了这个问题的解决方案...... 我正在开发的游戏使用远距离。我改变了远距离物体的定位方式(物体距离相机越远,距离就越小),这已经解决了 z-fighting 和 alpha 消失的问题。 通过使用距离的平方根除以距离并乘以相对 Vector3 和物体的比例,整个太阳系适合 300000 公里。希望这些信息可能对某人有用。

【讨论】:

    【解决方案3】:

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

    我在一个空项目中测试了您的着色器,其中包含正向和延迟渲染。这些调整效果很好。

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

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

    【讨论】:

      猜你喜欢
      • 2014-08-07
      • 1970-01-01
      • 2016-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多