Как программно разрешить Unity Shader контролировать, какой объект рендерится впереди? - PullRequest
0 голосов
/ 19 сентября 2018

Я только начал изучать Unity, но, поскольку я пришел из среды программирования на C #, я обнаружил, что стандартные сценарии очень быстро изучаются.К сожалению, теперь я столкнулся с проблемой, для которой я считаю, что нужен специальный шейдер, и я полностью потерян, когда дело доходит до шейдеров.

Сценарий: Я использую пользовательский процесс масштабирования расстояния, чтобы действительно большие, удаленные объекты перемещались в разумном диапазоне точности с плавающей запятой от игрока.Это прекрасно работает и управляет масштабированием объектов в зависимости от их скорректированного расстояния, поэтому они на самом деле кажутся очень далекими.Проблема возникает, однако, когда два из этих объектов проходят близко друг к другу в игровом пространстве (это все равно будет миллионы единиц в реальном масштабе), потому что они явно сталкиваются.Пример: https://www.youtube.com/watch?v=KFnuQg4R8NQ

Попытка решения 1: Я рассмотрел выравнивание объектов вдоль оси обзора игрока, и это исправляет столкновение, но это влияет на эффекты затенения и частиц, так чтоХороший вариант

Попытка решения 2: Я пытался изменить RenderOrder, но потому что иногда один объект находится внутри меша другого (хотя центр этого объекта все еще ближе ккамера) это не решает проблему, и эффекты частиц снова проблематичны.

Попытка решения 3: Я попытался переместить сталкивающиеся объекты в их собственный слой, порождая новую камерус большей глубиной в том же положении, что и основная камера, и заставляет камеры видеть элементы только в соответствующих слоях, но это вызывало проблемы с освещением, поскольку некоторые объекты освещают другие, и у меня было только ограниченное количество слоев, поэтому это решение былодовольно ограниченно, так как это заставило меня иметь только небольшое количество объектов, которые могут перекрыватьсяе.ПРИМЕЧАНИЕ: это решение, вероятно, самое близкое к тому, что мне удалось найти.Пример: https://www.youtube.com/watch?v=CyFDgimJ2-8

Попытка решения 4: Я попытался обновить код стандартного шейдера, загрузив его со страницы загрузок Unity и создав свой собственный пользовательский шейдер, который позволяет мне изменятьСвойства ZWrite и ZTest, но поскольку у меня нет реального понимания того, как они работают, я никуда не деться.

Запрос: Я был бы очень признателен за пример кода сценария Shader того, какЯ могу программно заставить один объект, чья сетка либо сталкивается с другой сеткой, либо полностью внутри нее, визуализировать перед этой сеткой.Я надеюсь, что смогу взять этот пример и применить его ко всем шейдерам, которые я сейчас использую (Standard, Particle Additive), чтобы добиться эффекта, который я ищу.Заранее спасибо за помощь.

1 Ответ

0 голосов
/ 20 сентября 2018

В gif ниже оба объекта сталкиваются, и в соответствии с положением камеры куб находится перед сферой, но я могу изменить их видимость с помощью очереди рендеринга:

enter image description here

Если это то, что вам нужно, вам нужно добавить ZWrite Off в свой подшейдер перед запуском CGPROGRAM, ниже приведен стандартный шейдер поверхности, включающий строку:

Shader "Custom/Shader" {
Properties {
    _Color ("Color", Color) = (1,1,1,1)
    _MainTex ("Albedo (RGB)", 2D) = "white" {}
    _Glossiness ("Smoothness", Range(0,1)) = 0.5
    _Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader {
    Tags { "RenderType"="Opaque" }
    LOD 200
    ZWrite Off 
    CGPROGRAM
    // Physically based Standard lighting model, and enable shadows on all light types
    #pragma surface surf Standard fullforwardshadows

    // Use shader model 3.0 target, to get nicer looking lighting
    #pragma target 3.0

    sampler2D _MainTex;

    struct Input {
        float2 uv_MainTex;
    };

    half _Glossiness;
    half _Metallic;
    fixed4 _Color;

    // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    // #pragma instancing_options assumeuniformscaling
    UNITY_INSTANCING_BUFFER_START(Props)
        // put more per-instance properties here
    UNITY_INSTANCING_BUFFER_END(Props)

    void surf (Input IN, inout SurfaceOutputStandard o) {
        // Albedo comes from a texture tinted by color
        fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
        o.Albedo = c.rgb;
        // Metallic and smoothness come from slider variables
        o.Metallic = _Metallic;
        o.Smoothness = _Glossiness;
        o.Alpha = c.a;
    }
    ENDCG
}
FallBack "Diffuse"
}

Теперь сортировкачастицы, посмотрите на тени и как они сталкиваются и как мы можем изменить их видимость независимо от их положения.

enter image description here

Вот шейдер для частиц, яя использую встроенный шейдер Unity, единственное что добавлено это Ztest Always

     Shader "Particles/Alpha Blended Premultiply Custom" {
 Properties {
     _MainTex ("Particle Texture", 2D) = "white" {}
     _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
 }

 Category {
     Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
     ZTest Always
     Blend SrcAlpha OneMinusSrcAlpha
     ColorMask RGB
     Cull Off Lighting Off ZWrite Off

     SubShader {
         Pass {

             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag
             #pragma target 2.0
             #pragma multi_compile_particles
             #pragma multi_compile_fog

             #include "UnityCG.cginc"

             sampler2D _MainTex;
             fixed4 _TintColor;

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

             struct v2f {
                 float4 vertex : SV_POSITION;
                 fixed4 color : COLOR;
                 float2 texcoord : TEXCOORD0;
                 #ifdef SOFTPARTICLES_ON
                 float4 projPos : TEXCOORD1;
                 #endif
                 UNITY_VERTEX_OUTPUT_STEREO
             };

             float4 _MainTex_ST;

             v2f vert (appdata_t v)
             {
                 v2f o;
                 UNITY_SETUP_INSTANCE_ID(v);
                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                 o.vertex = UnityObjectToClipPos(v.vertex);
                 #ifdef SOFTPARTICLES_ON
                 o.projPos = ComputeScreenPos (o.vertex);
                 COMPUTE_EYEDEPTH(o.projPos.z);
                 #endif
                 o.color = v.color;
                 o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
                 return o;
             }

             UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
             float _InvFade;

             fixed4 frag (v2f i) : SV_Target
             {
                 #ifdef SOFTPARTICLES_ON
                 float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
                 float partZ = i.projPos.z;
                 float fade = saturate (_InvFade * (sceneZ-partZ));
                 i.color.a *= fade;
                 #endif

                 return i.color * tex2D(_MainTex, i.texcoord) * i.color.a;
             }
             ENDCG
         }
     }
 }
 } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...