Пытаюсь объединить два шейдера (двухсторонний и поперечное сечение), но получаю синтаксическую ошибку

Я пытаюсь "объединить" код двух шейдеров:

Первый — двусторонний шейдер для Hololens из Microsoft Holotoolkit:

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

Shader "MixedRealityToolkit/Obsolete/Fast Configurable 2 Sided"
{
    Properties
    {
        _Mode("Rendering Mode", Float) = 0.0

        [Toggle] _UseVertexColor("Vertex Color Enabled?", Float) = 0
        [Toggle] _UseMainColor("Main Color Enabled?", Float) = 0
        _Color("Main Color", Color) = (1,1,1,1)
        [Toggle] _UseMainTex("Main Texture Enabled?", Float) = 0
        [NoScaleOffset]_MainTex("Main Texture", 2D) = "red" {}

        [Toggle] _UseOcclusionMap("Occlusion/Detail Texture Enabled?", Float) = 0
        [NoScaleOffset]_OcclusionMap("Occlusion/Detail Texture", 2D) = "blue" {}

        [Toggle] _UseAmbient("Ambient Lighting Enabled?", Float) = 1
        [Toggle] _UseDiffuse("Diffuse Lighting Enabled?", Float) = 1

        [Toggle] _SpecularHighlights("Specular Lighting Enabled?", Float) = 0
        [Toggle] _Shade4("Use additional lighting data? (Expensive!)", Float) = 0

        [Toggle] _ForcePerPixel("Light per-pixel (always on if a map is set)", Float) = 0

        _SpecColor("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
        [PowerSlider(5.0)]_Specular("Specular (Specular Power)", Range(1.0, 100.0)) = 10.0
        [Toggle] _UseSpecularMap("Use Specular Map? (per-pixel)", Float) = 0
        [NoScaleOffset]_SpecularMap("Specular Map", 2D) = "white" {}

        _Gloss("Gloss (Specular Scale)", Range(0.1, 10.0)) = 1.0
        [Toggle] _UseGlossMap("Use Gloss Map? (per-pixel)", Float) = 0
        [NoScaleOffset]_GlossMap("Gloss Map", 2D) = "white" {}

        [Toggle] _UseBumpMap("Normal Map Enabled? (per-pixel)", Float) = 0
        [NoScaleOffset][Normal] _BumpMap("Normal Map", 2D) = "bump" {}

        [Toggle] _UseReflections("Reflections Enabled?", Float) = 0
        [NoScaleOffset]_CubeMap("CubeMap", Cube) = "" {}
        _ReflectionScale("Reflection Scale", Range(0.01, 3.0)) = 2.0
        [Toggle]_CalibrationSpaceReflections("Reflect in calibration space?", Float) = 0

        [Toggle] _UseRimLighting("Rim Lighting Enabled?", Float) = 0
        [PowerSlider(.6)]_RimPower("Power", Range(0.1, 1.0)) = 0.7
        _RimColor("Color", Color) = (1,1,1,1)

        [Toggle] _UseEmissionColor("Emission Color Enabled?", Float) = 0
        _EmissionColor("Emission Color", Color) = (1,1,1,1)
        [Toggle] _UseEmissionMap("Emission Map Enabled?", Float) = 0
        [NoScaleOffset] _EmissionMap("Emission Map", 2D) = "blue" {}

        _TextureScaleOffset("Texture Scale (XY) and Offset (ZW)", Vector) = (1, 1, 0, 0)

        [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("SrcBlend", Float) = 1 //"One"
        [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("DestBlend", Float) = 0 //"Zero"
        [Enum(UnityEngine.Rendering.BlendOp)] _BlendOp("BlendOp", Float) = 0 //"Add"

        [Toggle] _AlphaTest("Alpha test enabled?", Float) = 0
        _Cutoff("Alpha Cutoff", Range(-0.1, 1.0)) = -0.1

        [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4 //"LessEqual"
        [Enum(Off,0,On,1)] _ZWrite("ZWrite", Float) = 1 //"On"
        [Enum(UnityEngine.Rendering.ColorWriteMask)] _ColorWriteMask("ColorWriteMask", Float) = 15 //"All"
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
        LOD 100
        Blend[_SrcBlend][_DstBlend]
        BlendOp[_BlendOp]
        ZTest[_ZTest]
        ZWrite[_ZWrite]

        Pass
        {
            Name "FRONT"
            Tags { "LightMode" = "ForwardBase" }
            Cull Back
            ColorMask[_ColorWriteMask]

            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                //compiles all variants needed by ForwardBase (forward rendering base) pass type. The variants deal with different lightmap types and main directional light having shadows on or off.
                #pragma multi_compile_fwdbase

                //expands to several variants to handle different fog types
                #pragma multi_compile_fog

                //We only target the HoloLens (and the Unity editor), so take advantage of shader model 5.
                #pragma target 5.0
                #pragma only_renderers d3d11

                //shader features are only compiled if a material uses them
                #pragma shader_feature _USEVERTEXCOLOR_ON
                #pragma shader_feature _USEMAINCOLOR_ON
                #pragma shader_feature _USEMAINTEX_ON
                #pragma shader_feature _USESOCCLUSIONMAP_ON
                #pragma shader_feature _USEBUMPMAP_ON
                #pragma shader_feature _USEAMBIENT_ON
                #pragma shader_feature _USEDIFFUSE_ON
                #pragma shader_feature _USESPECULAR_ON
                #pragma shader_feature _USEGLOSSMAP_ON
                #pragma shader_feature _SHADE4_ON
                #pragma shader_feature _USEREFLECTIONS_ON
                #pragma shader_feature _USERIMLIGHTING_ON
                #pragma shader_feature _USEEMISSIONCOLOR_ON
                #pragma shader_feature _USEEMISSIONTEX_ON
                #pragma shader_feature _ALPHATEST_ON

                //scale and offset will apply to all
                #pragma shader_feature _MainTex_SCALE_ON
                #pragma shader_feature _MainTex_OFFSET_ON

                //may be set from script so generate both paths
                #pragma multi_compile __ _NEAR_PLANE_FADE_ON

                #include "FastConfigurable.cginc"           
            ENDCG
        }

        Pass
        {
            Name "BACK"
            Tags{ "LightMode" = "ForwardBase" }
            Cull Front
            ColorMask[_ColorWriteMask]

            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                //compiles all variants needed by ForwardBase (forward rendering base) pass type. The variants deal with different lightmap types and main directional light having shadows on or off.
                #pragma multi_compile_fwdbase

                //expands to several variants to handle different fog types
                #pragma multi_compile_fog

                //We only target the HoloLens (and the Unity editor), so take advantage of shader model 5.
                #pragma target 5.0
                #pragma only_renderers d3d11

                //shader features are only compiled if a material uses them
                #pragma shader_feature _USEMAINCOLOR_ON
                #pragma shader_feature _USEMAINTEX_ON
                #pragma shader_feature _USESOCCLUSIONMAP_ON
                #pragma shader_feature _USEBUMPMAP_ON
                #pragma shader_feature _USEAMBIENT_ON
                #pragma shader_feature _USEDIFFUSE_ON
                #pragma shader_feature _USESPECULAR_ON
                #pragma shader_feature _USEGLOSSMAP_ON
                #pragma shader_feature _SHADE4_ON
                #pragma shader_feature _USEEMISSIONCOLOR_ON
                #pragma shader_feature _USEEMISSIONTEX_ON

                //scale and offset will apply to all
                #pragma shader_feature _MainTex_SCALE_ON
                #pragma shader_feature _MainTex_OFFSET_ON

                //may be set from script so generate both paths
                #pragma multi_compile __ _NEAR_PLANE_FADE_ON

                #define FLIP_NORMALS 1
                #include "FastConfigurable.cginc"
            ENDCG
        }
    } 

    CustomEditor "HoloToolkit.Unity.FastConfigurable2SidedGUI"
    Fallback "VertexLit" //for shadows
}

Второй — это шейдер поперечного сечения из магазина ресурсов Unity:

Shader "CrossSection/OnePlaneBSP" {
    Properties{
        _Color("Color", Color) = (1,1,1,1)
        _CrossColor("Cross Section 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
        _PlaneNormal("PlaneNormal",Vector) = (0,1,0,0)
        _PlanePosition("PlanePosition",Vector) = (0,0,0,1)
        _StencilMask("Stencil Mask", Range(0, 255)) = 255
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        //LOD 200
        Stencil
        {
            Ref [_StencilMask]
            CompBack Always
            PassBack Replace

            CompFront Always
            PassFront Zero
        }
        Cull Back
            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;

            float3 worldPos;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
        fixed4 _CrossColor;
        fixed3 _PlaneNormal;
        fixed3 _PlanePosition;
        bool checkVisability(fixed3 worldPos)
        {
            float dotProd1 = dot(worldPos - _PlanePosition, _PlaneNormal);
            return dotProd1 > 0  ;
        }
        void surf(Input IN, inout SurfaceOutputStandard o) {
            if (checkVisability(IN.worldPos))discard;
            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

            Cull Front
            CGPROGRAM
#pragma surface surf NoLighting  noambient

        struct Input {
            half2 uv_MainTex;
            float3 worldPos;

        };
        sampler2D _MainTex;
        fixed4 _Color;
        fixed4 _CrossColor;
        fixed3 _PlaneNormal;
        fixed3 _PlanePosition;
        bool checkVisability(fixed3 worldPos)
        {
            float dotProd1 = dot(worldPos - _PlanePosition, _PlaneNormal);
            return dotProd1 >0 ;
        }
        fixed4 LightingNoLighting(SurfaceOutput s, fixed3 lightDir, fixed atten)
        {
            fixed4 c;
            c.rgb = s.Albedo;
            c.a = s.Alpha;
            return c;
        }

        void surf(Input IN, inout SurfaceOutput o)
        {
            if (checkVisability(IN.worldPos))discard;
            o.Albedo = _CrossColor;

        }
            ENDCG

    }
    //FallBack "Diffuse"
}

Я попытался начать с двухстороннего шейдера и добавить поверхность прагмы для серфинга из второго в конце первого ПРОХОДА следующим образом:

...
//End of the first PASS from the first shader


        #include "FastConfigurable.cginc"       



#pragma surface surf NoLighting  noambient


        struct Input {
            half2 uv_MainTex;
            float3 worldPos;

        };
        fixed4 _CrossColor;
        fixed3 _PlaneNormal;
        fixed3 _PlanePosition;
        bool checkVisability(fixed3 worldPos)
        {
            float dotProd1 = dot(worldPos - _PlanePosition, _PlaneNormal);
            return dotProd1 > 0;
        }
        fixed4 LightingNoLighting(SurfaceOutput s, fixed3 lightDir, fixed atten)
        {
            fixed4 c;
            c.rgb = s.Albedo;
            c.a = s.Alpha;
            return c;
        }

        void surf(Input IN, inout SurfaceOutput o)
        {
            if (checkVisability(IN.worldPos))discard;
            o.Albedo = _CrossColor;

        }
            ENDCG
        }


        Pass
        {
            Name "BACK"
            Tags{ "LightMode" = "ForwardBase" }
            Cull Front
            ColorMask[_ColorWriteMask]

            CGPROGRAM
//Next of the second PASS of the first shader
...

Но я получаю следующие ошибки:

Shader Compiler Socket Exception: Terminating shader compiler process

Shader compiler: Preprocess DoubleSidedStandardCrossCut.shader: Internal error communicating with the shader compiler process. Please report a bug including this shader and the editor log.

Shader error in 'DoubleSidedStandardCrossCut': Parse error: syntax error, unexpected $end, expecting TOK_SHADER at line 1

Если у вас есть какие-либо советы или предложения, я был бы очень признателен, спасибо!

Комбинировать шейдеры сложно, особенно если один из них — поверхностный, а другой — фрагментный.

Draco18s no longer trusts SE 22.05.2019 17:00

Хорошо, спасибо за ваш ответ. Однако я не вижу фрагментный шейдер в коде Microsoft, он есть в одном из файлов cginc?

elpha01 22.05.2019 17:05

Плохо, я думал, что файлы cginc были скомпилированным кодом, но это обычный текст, я посмотрю на это.

elpha01 22.05.2019 17:07
#pragma fragment frag в двустороннем шейдере MRTK указывает, что это фрагментный шейдер, тогда как другой имеет #pragma surface surf. Кроме того, МРТК на самом деле не включает в себя собственный код, а ссылается на внешний код: #include "FastConfigurable.cginc"
Draco18s no longer trusts SE 22.05.2019 19:33

Похоже, проблема заключается в ошибке синтаксического анализа в строке 1 вашего шейдера: «Ошибка шейдера в« DoubleSidedStandardCrossCut »: ошибка синтаксического анализа: синтаксическая ошибка, неожиданный конец $, ожидание TOK_SHADER в строке 1». Но Draco18s прав, что объединение этих двух шейдеров может быть изрядная работа. Какого эффекта вы пытаетесь достичь? Возможно, это уже возможно с шейдером MRTK/Standard. Вы можете увидеть несколько уже доступных эффектов, если откроете сцену Unity MaterialGallery.

Cameron-Micka 22.05.2019 17:14

Я стараюсь иметь двухстороннее и поперечное сечение одновременно. Я протестировал новые шейдеры MRTK, но двухсторонний эффект не очень красивый, задние грани плохо реагируют на освещение. Однако я мог бы получить желаемое поведение с этой проблемой, используя только второй шейдер и отключив Cull. Я продолжу расследование, и если я не найду решение, я опубликую то, что я сейчас использую. Спасибо.

elpha01 22.05.2019 17:30
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
6
675
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как часто это сводится к тому, чего вы хотите достичь, и к пониманию того, какая часть какого шейдера делает то, что вы хотите в конечном результате.

Это не очень понятно, и я могу только делать предположения. Кажется, у вас есть заданная сетка; вы хотите, чтобы это могло быть (1) вырезанный на основе Плана, учитывая его положение и нормаль; и хотите, чтобы (2) поверхности лицом вперед (F) и лицом назад (B) имели разные свойства рендеринга.

Написание многопроходных шейдеров часто является просто сокращением того, что вы можете сделать с помощью простой настройки, хотя, возможно, и с немного большими накладными расходами: каждый проход — это, по сути, еще один вызов отрисовки, он также может быть другим объектом.

Опции:

  1. Написать многопроходный шейдер
  2. Имейте 2 объекта, вложенных в общее преобразование, или объект F или B, вложенный в другой.
  3. Если у вашей сетки нет подмешей, назначьте 2 материала компоненту MeshRenderer. В этом списке обычно назначаются разные материалы для каждой подсетки, но если ни один из них не присутствует, он просто снова отрисует сетку.

В любом случае 2 и 3 вам нужен 2 материала. Они оба могут использовать один и тот же шейдер, или для простоты вы можете сначала создать 2 шейдера с запеченными свойствами:

  • Материал B(ack) имеет более низкую очередь рендеринга (возможно Geometry-1), так как его всегда нужно покрывать F(ront). (см. https://docs.unity3d.com/Manual/SL-SubShaderTags.html)
  • Материал B использует флаг Cull Front, а материал F использует флаг Cull Back (по умолчанию).
  • Оба они используют checkVisibility(IN.worldPos) для отбрасывания вырезанных пикселей.

На заметку: это должно быть быстро, так как вы, кажется, делаете VR, поэтому я бы рекомендовал использовать инструкцию clip() hlsl и иметь checkVisibility для возврата числа с плавающей запятой, чтобы полностью избавиться от условного ветвления.

Другие вопросы по теме