白泽图

  • 文章
    • Unity渲染
    • Unity项目开发
    • 工具
    • 数学
    • 算法
    • 网站搭建
    • 网络&操作系统
蒋程个人博客
互联网技术经验总结&分享
  1. 首页
  2. Unity渲染
  3. 正文

Unity定制Shader GUI优化方案

2020-12-28 2767点热度 0人点赞 0条评论

参考:官方API

写过脚本编译器的同学应该都知道Monobehaivor的脚本可以重画检视面板,这有利我们开发各利插件,方便调试,Shader的面板也可以重画,区别在于,Monobehavior的脚本设置只能在运行时生效,再Shader的面板设置在编译环境下就生效,在运行时无法生效,其实这个很好理解,unity的shader最终还要是编译成各平台对应的shader语言,所以它这里用的控制更多类似于宏,即不同设置会导致最终的编译结果不同

直接上代码:

在Asset中新建文件夹Editor,创建CustomShaderGUI.cs

代码如下:

using UnityEngine;
using UnityEditor;
using System;

public class CustomShaderGUI : ShaderGUI
{
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
        // 渲染默认 GUI
        base.OnGUI(materialEditor, properties);

        Material targetMat = materialEditor.target as Material;

        bool has_sec = Array.IndexOf(targetMat.shaderKeywords, "SEC_ATLAS") != -1;
        EditorGUI.BeginChangeCheck();
        has_sec = EditorGUILayout.Toggle("Sec Texture", has_sec);

        if (EditorGUI.EndChangeCheck())
        {
            if (has_sec)
                targetMat.EnableKeyword("SEC_ATLAS");
            else
                targetMat.DisableKeyword("SEC_ATLAS");
        }
    }
}

Shader代码如下:

Shader "Custom/CustomShader"
{
    Properties
    {
        _Texture1("Texture1", 2D) = "white" {}
        _Texture2("Texture2", 2D) = "white" {}

    }

    SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 200

        Pass
        {
            CGPROGRAM
            #include "UnityCG.cginc"
            #pragma vertex vert
            #pragma fragment frag
            #pragma shader_feature SEC_ATLAS

            sampler2D _Texture1;
            sampler2D _Texture2;

            float4 _Texture1_ST;
            float4 _Texture2_ST;

            struct appdata_t
            {
                float4 vertex : POSITION;
                fixed2 uv : TEXCOORD0;
            };

            struct v2f
            {
                fixed4 vertex : POSITION;
                fixed2 uv : TEXCOORD0;
            };

            v2f vert(appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
#if SEC_ATLAS
                o.uv = v.uv * _Texture2_ST.xy;
#else
                o.uv = v.uv * _Texture1_ST.xy;
#endif
                return o;
            }

            fixed4 frag(v2f i):COLOR
            {
#if SEC_ATLAS
                return tex2D(_Texture2,i.uv);
#endif
                return tex2D(_Texture1,i.uv);
            }
            ENDCG
        }
    }

CustomEditor "CustomShaderGUI"

}

代码很简单,通过Shader的检视面板的SEC_ATLAS选项来决定最终采样第一张图还是第二张图,

shader与C#的关联代码为

#pragma shader_feature SEC_ATLAS  与  CustomEditor "CustomShaderGUI

C#中的控制代码为

targetMat.EnableKeyword("SEC_ATLAS") 与 targetMat.DisableKeyword("SEC_ATLAS")

Shader编译后代码如下(SEC_ATLAS = false的情况):

// Compiled shader for PC, Mac & Linux Standalone

//////////////////////////////////////////////////////////////////////////
// 
// NOTE: This is *not* a valid shader file, the contents are provided just
// for information and for debugging purposes only.
// 
//////////////////////////////////////////////////////////////////////////
// Skipping shader variants that would not be included into build of current scene.

Shader "Custom/CustomShader" {
Properties {
 _Texture1 ("Texture1", 2D) = "white" { }
 _Texture2 ("Texture2", 2D) = "white" { }
}
SubShader { 
 LOD 200
 Tags { "RenderType"="Opaque" }


 // Stats for Vertex shader:
 //        d3d11: 9 math
 // Stats for Fragment shader:
 //        d3d11: 0 math, 1 texture
 Pass {
  Tags { "RenderType"="Opaque" }
  //////////////////////////////////
  //                              //
  //      Compiled programs       //
  //                              //
  //////////////////////////////////
//////////////////////////////////////////////////////
Global Keywords: <none>
Local Keywords: <none>
-- Hardware tier variant: Tier 1
-- Vertex shader for "d3d11":
// Stats: 9 math, 2 temp registers
Uses vertex data channel "Vertex"
Uses vertex data channel "TexCoord0"

Constant Buffer "$Globals" (64 bytes) on slot 0 {
  Vector4 _Texture1_ST at 32
}
Constant Buffer "UnityPerDraw" (176 bytes) on slot 1 {
  Matrix4x4 unity_ObjectToWorld at 0
}
Constant Buffer "UnityPerFrame" (368 bytes) on slot 2 {
  Matrix4x4 unity_MatrixVP at 272
}

Shader Disassembly:
//
// Generated by Microsoft (R) D3D Shader Disassembler
//
//
// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// POSITION                 0   xyzw        0     NONE   float   xyz 
// TEXCOORD                 0   xy          1     NONE   float   xy  
//
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Position              0   xyzw        0      POS   float   xyzw
// TEXCOORD                 0   xy          1     NONE   float   xy  
//
      vs_4_0
      dcl_constantbuffer CB0[3], immediateIndexed
      dcl_constantbuffer CB1[4], immediateIndexed
      dcl_constantbuffer CB2[21], immediateIndexed
      dcl_input v0.xyz
      dcl_input v1.xy
      dcl_output_siv o0.xyzw, position
      dcl_output o1.xy
      dcl_temps 2
   0: mul r0.xyzw, v0.yyyy, cb1[1].xyzw
   1: mad r0.xyzw, cb1[0].xyzw, v0.xxxx, r0.xyzw
   2: mad r0.xyzw, cb1[2].xyzw, v0.zzzz, r0.xyzw
   3: add r0.xyzw, r0.xyzw, cb1[3].xyzw
   4: mul r1.xyzw, r0.yyyy, cb2[18].xyzw
   5: mad r1.xyzw, cb2[17].xyzw, r0.xxxx, r1.xyzw
   6: mad r1.xyzw, cb2[19].xyzw, r0.zzzz, r1.xyzw
   7: mad o0.xyzw, cb2[20].xyzw, r0.wwww, r1.xyzw
   8: mul o1.xy, v1.xyxx, cb0[2].xyxx
   9: ret 
// Approximately 0 instruction slots used


-- Hardware tier variant: Tier 1
-- Fragment shader for "d3d11":
// Stats: 0 math, 1 textures
Set 2D Texture "_Texture1" to slot 0

Shader Disassembly:
//
// Generated by Microsoft (R) D3D Shader Disassembler
//
//
// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Position              0   xyzw        0      POS   float       
// TEXCOORD                 0   xy          1     NONE   float   xy  
//
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Target                0   xyzw        0   TARGET   float   xyzw
//
      ps_4_0
      dcl_sampler s0, mode_default
      dcl_resource_texture2d (float,float,float,float) t0
      dcl_input_ps linear v1.xy
      dcl_output o0.xyzw
   0: sample o0.xyzw, v1.xyxx, t0.xyzw, s0
   1: ret 
// Approximately 0 instruction slots used


 }
}
CustomEditor "CustomShaderGUI"
}

上面的代码只生成采样Textrue1的代码

当SEC_ATLAS = true的时:

// Compiled shader for PC, Mac & Linux Standalone

//////////////////////////////////////////////////////////////////////////
// 
// NOTE: This is *not* a valid shader file, the contents are provided just
// for information and for debugging purposes only.
// 
//////////////////////////////////////////////////////////////////////////
// Skipping shader variants that would not be included into build of current scene.

Shader "Custom/CustomShader" {
Properties {
 _Texture1 ("Texture1", 2D) = "white" { }
 _Texture2 ("Texture2", 2D) = "white" { }
}
SubShader { 
 LOD 200
 Tags { "RenderType"="Opaque" }


 // Stats for Vertex shader:
 //        d3d11: 9 math
 // Stats for Fragment shader:
 //        d3d11: 0 math, 1 texture
 Pass {
  Tags { "RenderType"="Opaque" }
  //////////////////////////////////
  //                              //
  //      Compiled programs       //
  //                              //
  //////////////////////////////////
//////////////////////////////////////////////////////
Global Keywords: <none>
Local Keywords: <none>
-- Hardware tier variant: Tier 1
-- Vertex shader for "d3d11":
// Stats: 9 math, 2 temp registers
Uses vertex data channel "Vertex"
Uses vertex data channel "TexCoord0"

Constant Buffer "$Globals" (64 bytes) on slot 0 {
  Vector4 _Texture1_ST at 32
}
Constant Buffer "UnityPerDraw" (176 bytes) on slot 1 {
  Matrix4x4 unity_ObjectToWorld at 0
}
Constant Buffer "UnityPerFrame" (368 bytes) on slot 2 {
  Matrix4x4 unity_MatrixVP at 272
}

Shader Disassembly:
//
// Generated by Microsoft (R) D3D Shader Disassembler
//
//
// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// POSITION                 0   xyzw        0     NONE   float   xyz 
// TEXCOORD                 0   xy          1     NONE   float   xy  
//
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Position              0   xyzw        0      POS   float   xyzw
// TEXCOORD                 0   xy          1     NONE   float   xy  
//
      vs_4_0
      dcl_constantbuffer CB0[3], immediateIndexed
      dcl_constantbuffer CB1[4], immediateIndexed
      dcl_constantbuffer CB2[21], immediateIndexed
      dcl_input v0.xyz
      dcl_input v1.xy
      dcl_output_siv o0.xyzw, position
      dcl_output o1.xy
      dcl_temps 2
   0: mul r0.xyzw, v0.yyyy, cb1[1].xyzw
   1: mad r0.xyzw, cb1[0].xyzw, v0.xxxx, r0.xyzw
   2: mad r0.xyzw, cb1[2].xyzw, v0.zzzz, r0.xyzw
   3: add r0.xyzw, r0.xyzw, cb1[3].xyzw
   4: mul r1.xyzw, r0.yyyy, cb2[18].xyzw
   5: mad r1.xyzw, cb2[17].xyzw, r0.xxxx, r1.xyzw
   6: mad r1.xyzw, cb2[19].xyzw, r0.zzzz, r1.xyzw
   7: mad o0.xyzw, cb2[20].xyzw, r0.wwww, r1.xyzw
   8: mul o1.xy, v1.xyxx, cb0[2].xyxx
   9: ret 
// Approximately 0 instruction slots used


-- Hardware tier variant: Tier 1
-- Fragment shader for "d3d11":
// Stats: 0 math, 1 textures
Set 2D Texture "_Texture1" to slot 0

Shader Disassembly:
//
// Generated by Microsoft (R) D3D Shader Disassembler
//
//
// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Position              0   xyzw        0      POS   float       
// TEXCOORD                 0   xy          1     NONE   float   xy  
//
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Target                0   xyzw        0   TARGET   float   xyzw
//
      ps_4_0
      dcl_sampler s0, mode_default
      dcl_resource_texture2d (float,float,float,float) t0
      dcl_input_ps linear v1.xy
      dcl_output o0.xyzw
   0: sample o0.xyzw, v1.xyxx, t0.xyzw, s0
   1: ret 
// Approximately 0 instruction slots used


//////////////////////////////////////////////////////
Global Keywords: SEC_ATLAS 
Local Keywords: <none>
-- Hardware tier variant: Tier 1
-- Vertex shader for "d3d11":
// Stats: 9 math, 2 temp registers
Uses vertex data channel "Vertex"
Uses vertex data channel "TexCoord0"

Constant Buffer "$Globals" (64 bytes) on slot 0 {
  Vector4 _Texture2_ST at 48
}
Constant Buffer "UnityPerDraw" (176 bytes) on slot 1 {
  Matrix4x4 unity_ObjectToWorld at 0
}
Constant Buffer "UnityPerFrame" (368 bytes) on slot 2 {
  Matrix4x4 unity_MatrixVP at 272
}

Shader Disassembly:
//
// Generated by Microsoft (R) D3D Shader Disassembler
//
//
// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// POSITION                 0   xyzw        0     NONE   float   xyz 
// TEXCOORD                 0   xy          1     NONE   float   xy  
//
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Position              0   xyzw        0      POS   float   xyzw
// TEXCOORD                 0   xy          1     NONE   float   xy  
//
      vs_4_0
      dcl_constantbuffer CB0[4], immediateIndexed
      dcl_constantbuffer CB1[4], immediateIndexed
      dcl_constantbuffer CB2[21], immediateIndexed
      dcl_input v0.xyz
      dcl_input v1.xy
      dcl_output_siv o0.xyzw, position
      dcl_output o1.xy
      dcl_temps 2
   0: mul r0.xyzw, v0.yyyy, cb1[1].xyzw
   1: mad r0.xyzw, cb1[0].xyzw, v0.xxxx, r0.xyzw
   2: mad r0.xyzw, cb1[2].xyzw, v0.zzzz, r0.xyzw
   3: add r0.xyzw, r0.xyzw, cb1[3].xyzw
   4: mul r1.xyzw, r0.yyyy, cb2[18].xyzw
   5: mad r1.xyzw, cb2[17].xyzw, r0.xxxx, r1.xyzw
   6: mad r1.xyzw, cb2[19].xyzw, r0.zzzz, r1.xyzw
   7: mad o0.xyzw, cb2[20].xyzw, r0.wwww, r1.xyzw
   8: mul o1.xy, v1.xyxx, cb0[3].xyxx
   9: ret 
// Approximately 0 instruction slots used


-- Hardware tier variant: Tier 1
-- Fragment shader for "d3d11":
// Stats: 0 math, 1 textures
Set 2D Texture "_Texture2" to slot 0

Shader Disassembly:
//
// Generated by Microsoft (R) D3D Shader Disassembler
//
//
// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Position              0   xyzw        0      POS   float       
// TEXCOORD                 0   xy          1     NONE   float   xy  
//
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Target                0   xyzw        0   TARGET   float   xyzw
//
      ps_4_0
      dcl_sampler s0, mode_default
      dcl_resource_texture2d (float,float,float,float) t0
      dcl_input_ps linear v1.xy
      dcl_output o0.xyzw
   0: sample o0.xyzw, v1.xyxx, t0.xyzw, s0
   1: ret 
// Approximately 0 instruction slots used


 }
}
CustomEditor "CustomShaderGUI"
}

只生成了采样Texture2的代码,所以当Shader代码可以高度定制时,推荐使用此方法可以有效提升效率,缺点为不可在运行环境的动态修改,测试如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FloatMesh;

public class Test : MonoBehaviour
{
    public MeshRenderer mRender;

    void OnGUI()
    {
        if (GUI.Button(new Rect(0, 0, 150, 50),"BUTTON"))
        {
            mRender.material.EnableKeyword("SEC_ATLAS");
        }
    }
} 

报错如下:

UnassignedReferenceException: The variable mRender of Test has not been assigned.
You probably need to assign the mRender variable of the Test script in the inspector.
UnityEngine.Renderer.get_material () (at <2feaf16e80004e0cadae3f2e05f2a3fa>:0)
Test.OnGUI () (at Assets/Script/Test.cs:14)

标签: 暂无
最后更新:2020-12-28

蒋程

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

COPYRIGHT © 2023 白泽图. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

登录
注册|忘记密码?