zoukankan      html  css  js  c++  java
  • 让我们好好聊聊Unity Shader中的multi_complie

    https://zhuanlan.zhihu.com/p/77043332

    一,multi_complie 还是 shader_feature

    shader_feature 和 multi_complie 是两个很相似的预编译指令,在Editor模式下,他们是几乎没有区别的。

    共同点是:

    • 声明Keyword,用来产生Shader的变体(Variant)
    #pragma multi_compile A B
    //OR #pragma shader_feature A B
    
    //-----------------------A模块----------------------
    #if A
      return fixed4(1,1,1,1); 
    #endif 
    //---------------------------------------------------
    
    //-----------------------B模块-----------------------
    #if B
      return fixed4(0,0,0,1); 
    #endif
    //---------------------------------------------------
    • 这个Shader会被编译成两个变体:一是只包含A模块代码的变体A;二是只包含B模块代码的变体B;
    • 指定的第一个关键字是默认生效的,即默认使用变体A;
    • 在脚本里用Material.EnableKeyword或Shader.EnableKeyword来控制运行时具体使用变体A还是变体B;
    • 它们声明的Keyword是全局的,可以对全局的包含该Keyword的不同Shader起作用;
    • 全局最多只能声明256个这样的Keyword;
    • 请注意Keyword的数量和变体的数量之间的关系,并可能由此导致的性能开销,比如声明#pragma multi_compile A B和#pragma multi_compile D E 这样的两组Keyword会产生 2x2=4 个Shader变体,但若声明10组这样的keyword,则该Shader会产生1024个变体;

    区别在于:

    如果使用shader_feature,build时没有用到的变体会被删除,不会打出来。也就是说,在build以后环境里,运行代码Material.EnableKeyword("B")可能不起作用,因为没有Material在使用变体B,所以变体B没有被build出来,运行时也找不到变体B。

    如果想解决这个问题,可以采取以下办法中的其中一种:

    1. 使用multi_complie 代替 shader_feature,multi_complie 会把所有变体build出来;
    2. 把这个Shader加入“always included shaders”中 (Project Settings -> Graphic);
    3. 创造一个使用变体B的Material,强行说明变体B有用;

    二,__

    上文已经提到了,最多声明256个全局Keyword,因此我们要尽量节省Keyword的使用数量。其中一个技巧是使用 __(两条下划线),如:

    #pragma multi_compile __ A
    //OR #pragma shader_feature __ A
    
    //-----------------------A模块----------------------
    #if A
      return fixed4(1,1,1,1); 
    #endif 
    //---------------------------------------------------
    
    return fixed4(0,0,0,1);
    
    • 此方式相比#pragma multi_compile A B 的方式,我们可以减少使用一个Keyword。
    • 此方式仍会编译成两个变体:一是不包含A模块代码的变体非A;二是包含A模块代码的变体A;
    • 默认为 __ ,即变体非A生效。

    三,multi_complie_local

    全局的Keyword只能有256个,这或许会最终对我们造成限制,而且大部分Keyword并不需要进行全局声明。

    因此,我们可以使用multi_complie_local来声明局部的、只在该Shader内部起作用的Keyword,用法相似:

    #pragma multi_compile_local __ A
    //OR #pragma shader_feature_local __ A
    
    //-----------------------A模块----------------------
    #if A
      return fixed4(1,1,1,1); 
    #endif 
    //---------------------------------------------------
    
    return fixed4(0,0,0,1);

    但需要注意:

    • local Keyword仍有数量限制,每个Shader最多可以包含64个local Keyword
    • 因为这种Keyword是局部的,Material.EnableKeyword仍是有效的,但对Shader.EnableKeyword或CommandBuffer.EnableShaderKeyword这种全局开关说拜拜
    • 当你既声明了一个全局的Keyword A ,同时又声明了一个同名的、局部的Keyword A,那么优先认为Keyword A是局部的。
  • 相关阅读:
    Linux基础——硬盘分区、格式化及文件系统的管理
    Linux基础——系统监控
    Centos7安装并配置mysql5.6完美教程
    lr常用函数
    Python3中使用urllib的方法详解(header,代理,超时,认证,异常处理)
    cmd批处理常用符号详解
    Java 和 JSP 实现网站访问量统计 (刷新过滤)
    JAVA 导出 Excel, 将Excel下载到本地
    JAVA 导出 Excel, JS 导出 Excel
    windows server服务器上部署java+tomcat网站域名配置
  • 原文地址:https://www.cnblogs.com/nafio/p/12805697.html
Copyright © 2011-2022 走看看