【问题标题】:Rendering 3d objects behind 2d Objects unity在 2d 对象统一后渲染 3d 对象
【发布时间】:2019-01-14 08:21:19
【问题描述】:

我正在制作一个结合了 2d 和 3d 元素的等距游戏。我想知道如何让我的玩家和敌人精灵(全部由 2d 元素组成)不会渲染在我的 3d 元素后面或内部。

所以我尝试使用 renderQueue 并将这些岩石等材质的渲染队列设置为较高的值,以便将它们绘制在 2d 元素后面。

但是通过我的搜索,我发现我实际上需要设置对象的 ztest 来纠正这个问题。这让我有点困惑,我不确定该怎么做,因为我并没有真正使用过那么多着色器。我找不到任何体面的参考资料来准确解释如何处理这些假设有this 等先验知识的东西。我尝试下载统一着色器并打开默认精灵之一,但我不确定在哪里更改 ztest 或标记来解决这个问题。

这里是统一的标准精灵着色器:

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

#ifndef UNITY_SPRITES_INCLUDED
#define UNITY_SPRITES_INCLUDED

#include "UnityCG.cginc"

#ifdef UNITY_INSTANCING_ENABLED

UNITY_INSTANCING_BUFFER_START(PerDrawSprite)
    // SpriteRenderer.Color while Non-Batched/Instanced.
    UNITY_DEFINE_INSTANCED_PROP(fixed4, unity_SpriteRendererColorArray)
    // this could be smaller but that's how bit each entry is regardless of type
    UNITY_DEFINE_INSTANCED_PROP(fixed2, unity_SpriteFlipArray)
UNITY_INSTANCING_BUFFER_END(PerDrawSprite)

#define _RendererColor  UNITY_ACCESS_INSTANCED_PROP(PerDrawSprite, unity_SpriteRendererColorArray)
#define _Flip           UNITY_ACCESS_INSTANCED_PROP(PerDrawSprite,    unity_SpriteFlipArray)

#endif // instancing

CBUFFER_START(UnityPerDrawSprite)
#ifndef UNITY_INSTANCING_ENABLED
fixed4 _RendererColor;
fixed2 _Flip;
#endif
float _EnableExternalAlpha;
CBUFFER_END

// Material Color.
fixed4 _Color;

struct appdata_t
{
float4 vertex   : POSITION;
float4 color    : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct v2f
{
float4 vertex   : SV_POSITION;
fixed4 color    : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};

inline float4 UnityFlipSprite(in float3 pos, in fixed2 flip)
{
return float4(pos.xy * flip, pos.z, 1.0);
}

v2f SpriteVert(appdata_t IN)
{
v2f OUT;

UNITY_SETUP_INSTANCE_ID (IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);

OUT.vertex = UnityFlipSprite(IN.vertex, _Flip);
OUT.vertex = UnityObjectToClipPos(OUT.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color * _RendererColor;

#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif

return OUT;
}

sampler2D _MainTex;
sampler2D _AlphaTex;

fixed4 SampleSpriteTexture (float2 uv)
{
fixed4 color = tex2D (_MainTex, uv);

#if ETC1_EXTERNAL_ALPHA
fixed4 alpha = tex2D (_AlphaTex, uv);
color.a = lerp (color.a, alpha.r, _EnableExternalAlpha);
#endif

  return color;
}

fixed4 SpriteFrag(v2f IN) : SV_Target
{
   fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
   c.rgb *= c.a;
   return c;
 }

#endif // UNITY_SPRITES_INCLUDED

更新 1

【问题讨论】:

  • 您是否尝试过将 2D 元素定位在 3D 空间中,就像您的 3D 元素一样,将它们的变换位置放在前面/后面,无论它们需要在前面/后面吗?
  • 就我而言,这不是一个好主意。因为我的相机是等距的,所以它以 41 度角俯视世界。将 2d 元素放置在 3 个元素的“前面”意味着它们被放置在奇怪的角度,这使得 2d 元素的瞄准系统和位置都发生了倾斜,并且使用起来确实变得混乱。我很确定这样做的正确方法是能够告诉某些 3D 元素它们应该简单地呈现在 2D 元素后面。我只是不知道如何编写一个这样做的着色器。更新 1 说明了它在游戏中的外观。 Sprite 在 tile 前面渲染,但不渲染岩石。
  • 你能用别的相机吗?如果可以的话,您可以设置另一个相机剔除遮罩和深度。这可以使图层中的某些内容显示在前面。
  • shader 可以做到这一点,但我认为使用另一个相机会很容易实现。

标签: unity3d rendering shader


【解决方案1】:

如果我正确理解您的问题,我认为您可以尝试使用额外的相机。

正确设置两个相机的剔除蒙版深度清除标志

额外摄像头的深度应该更高,clearflag应该设置为depth only,并且剔除遮罩只设置你想要在前面渲染的层。

并且您的原始相机剔除蒙版应该删除额外相机中的图层渲染。

您可以使特定图层的对象呈现在前面。

昨天Svp告诉我他想要2d和3d对象的细粒度控制绘图顺序。我的旧答案不能很好地做到这一点。所以经过研究,有三种解决方案。

更新:

  1. 将 2d 对象视为 3d。使用 z-pos 对所有对象进行排序。保持少数 3d object z-pos 总是小于或大于 player z-pos (3d object 和 player 的 z-pos 的偏移量需要大于固定值,使整个 3d object 在播放器后面。)。固定值可以选择最大 3d 对象边界。

  2. 将 3d 对象视为 2d。 3d 物体网格渲染使用 2d sprite-default shader。 使用 2d 排序层和层控制 3d 对象渲染中的顺序。但我们需要 自定义网格渲染检查器使用来自 here by uvivagabond 的后续代码复制。

    using System;
    using UnityEngine;
    using UnityEditor;
    using UnityEditorInternal;
    using System.Reflection;
    using UnityEngine.Rendering;
    [CanEditMultipleObjects ()]
    [CustomEditor (typeof(MeshRenderer))]
    public class MeshRendererSortingLayersEditor : Editor
    {
    
        public override void OnInspectorGUI ()
        {
    
            #region Get Serialized Property
            SerializedProperty sortingLayerID = serializedObject.FindProperty (propertyPath: "m_SortingLayerID");
            SerializedProperty sortingOrder = serializedObject.FindProperty ("m_SortingOrder");
    
            SerializedProperty castShadows = serializedObject.FindProperty ("m_CastShadows");
            SerializedProperty receiveShadows = serializedObject.FindProperty ("m_ReceiveShadows");
            SerializedProperty motionVectors = serializedObject.FindProperty ("m_MotionVectors");
            SerializedProperty materials = serializedObject.FindProperty ("m_Materials");
            SerializedProperty lightProbes = serializedObject.FindProperty ("m_LightProbeUsage");
            SerializedProperty reflectionProbes = serializedObject.FindProperty ("m_ReflectionProbeUsage");
            SerializedProperty anchorProbes = serializedObject.FindProperty ("m_ProbeAnchor");
            #endregion
    
            #region Draw Properties
            AddPropertyField (castShadows);
            AddPropertyField (receiveShadows);
            AddPropertyField (motionVectors);
            AddPropertyField (materials);
            AddPopup (ref lightProbes, "Light Probes", typeof(LightProbeUsage));
            AddPopup (ref reflectionProbes, "Reflection Probes", typeof(ReflectionProbeUsage));
            AddPropertyField (anchorProbes, "Anchor Override");
            #endregion
    
    
            GUIStyle style = new GUIStyle (GUI.skin.label);
            style.richText = true;
            EditorGUILayout.Space ();
            EditorGUILayout.LabelField ("<b><color=#EE4035FF>SortingLayers Options:</color></b>", style);
            #region SortingLayer
            Rect firstHoriz = EditorGUILayout.BeginHorizontal ();
            EditorGUI.BeginChangeCheck ();
            //    EditorGUI.PropertyField (mat, new GUIContent ("Materials"));
            EditorGUI.BeginProperty (firstHoriz, GUIContent.none, sortingLayerID);
            string[] layerNames = GetSortingLayerNames ();
            int[] layerID = GetSortingLayerUniqueIDs ();
            int selected = -1;
            int sID = sortingLayerID.intValue;
            for (int i = 0; i < layerID.Length; i++)
                if (sID == layerID [i])
                    selected = i;
            if (selected == -1)
                for (int i = 0; i < layerID.Length; i++)
                    if (layerID [i] == 0)
                        selected = i;
            selected = EditorGUILayout.Popup ("Sorting Layer", selected, layerNames);
    
            sortingLayerID.intValue = layerID [selected];
            EditorGUI.EndProperty ();
            EditorGUILayout.EndHorizontal ();
            #endregion
    
            #region OrderInLayer
            EditorGUILayout.BeginHorizontal ();
            EditorGUI.BeginChangeCheck ();
            EditorGUILayout.PropertyField (sortingOrder, new GUIContent ("Order in Layer"));
            EditorGUILayout.EndHorizontal ();
            serializedObject.ApplyModifiedProperties ();
            #endregion
    
    
        }
    
        void AddPropertyField (SerializedProperty ourSerializedProperty)
        {
            Rect ourRect = EditorGUILayout.BeginHorizontal ();
            EditorGUI.BeginProperty (ourRect, GUIContent.none, ourSerializedProperty);
            EditorGUI.BeginChangeCheck ();
    
            EditorGUILayout.PropertyField (property: ourSerializedProperty, includeChildren: true); //I set includeChildren:true to display material children
    
            EditorGUI.EndProperty ();
            EditorGUILayout.EndHorizontal ();
        }
    
        void AddPropertyField (SerializedProperty ourSerializedProperty, string name)
        {
            Rect ourRect = EditorGUILayout.BeginHorizontal ();
            EditorGUI.BeginProperty (ourRect, GUIContent.none, ourSerializedProperty);
            EditorGUI.BeginChangeCheck ();
    
            EditorGUILayout.PropertyField (ourSerializedProperty, new GUIContent (name), true);
    
            EditorGUI.EndProperty ();
            EditorGUILayout.EndHorizontal ();
        }
    
        void AddPopup (ref SerializedProperty ourSerializedProperty, string nameOfLabel, Type typeOfEnum)
        {
            Rect ourRect = EditorGUILayout.BeginHorizontal ();
            EditorGUI.BeginProperty (ourRect, GUIContent.none, ourSerializedProperty);
            EditorGUI.BeginChangeCheck ();
    
            int actualSelected = 1;  
            int selectionFromInspector = ourSerializedProperty.intValue;
            string[] enumNamesList = System.Enum.GetNames (typeOfEnum);
            actualSelected = EditorGUILayout.Popup (nameOfLabel, selectionFromInspector, enumNamesList);
            ourSerializedProperty.intValue = actualSelected;
    
            EditorGUI.EndProperty ();
            EditorGUILayout.EndHorizontal ();
        }
    
    
        public string[] GetSortingLayerNames ()
        {
            Type internalEditorUtilityType = typeof(InternalEditorUtility);
            PropertyInfo sortingLayersProperty = internalEditorUtilityType.GetProperty ("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic);
            return (string[])sortingLayersProperty.GetValue (null, new object[0]);
        }
    
        public int[] GetSortingLayerUniqueIDs ()
        {
            Type internalEditorUtilityType = typeof(InternalEditorUtility);
            PropertyInfo sortingLayerUniqueIDsProperty = internalEditorUtilityType.GetProperty ("sortingLayerUniqueIDs", BindingFlags.Static | BindingFlags.NonPublic);
            return (int[])sortingLayerUniqueIDsProperty.GetValue (null, new object[0]);
        }
    }
    

在此之后,您的渲染网格检查器视图如下:

  1. 结合 2d 渲染系统和 3d 渲染系统。处理 Z-buffer Z-write 和许多其他问题......我相信这是一个巨大的挑战。Unity 应该做这项工作,而不是我们。

希望对你有帮助。

【讨论】:

  • 啊,我明白了,我当然可以添加我希望在播放器前面绘制的所有图层,需要对元素进行一些重组,但这应该可以。
  • @Svp 额外的相机应该只将剔除蒙版设置为您想要在前面的一个指定图层。其他相机应该在剔除蒙版中删除该图层
  • 是的,但是一旦我决定将玩家展示在石头前面,这意味着玩家现在被展示在所有东西的前面,因为相机的深度更高。这意味着我还需要将所有其他对象放入该相机中。过了一会儿,我在“前置”相机中有很多层,它变得非常混乱。是的,对于我添加到前面的每一层,我都会从后面移除它。事情刚刚开始变得不稳定。
  • 你能做到反向。少放点东西来渲染。@Svp
  • 您的设计似乎有时 A 呈现在前面,有时 A 呈现在后面。所以您在运行时更改图层。
猜你喜欢
  • 2018-06-29
  • 2021-11-14
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 2015-01-12
  • 1970-01-01
  • 1970-01-01
  • 2010-11-04
相关资源
最近更新 更多