Unity中Shader的ShaderLOD

文章目录

  • 前言
  • 一、ShaderLOD的使用步骤
    • 1、ShaderLOD使用在不同的SubShader中,用于区分SubShader所对应的配置
    • 2、在 C# 中使用 Shader.globalMaximumLOD 赋值来选择不同的 SubShader,以达到修改配置对应Shader的效果
    • 3、在设置LOD时,是需要和程序讨论统一 LOD 对应的数值所对应的配置
  • 二、ShaderLOD实现不同配置对应不同SubShader
    • 1、我们基于之前的文章代码,继续测试该功能
    • 2、编写C#脚本来控制选择不同的ShaderLOD,并且把该脚本挂载在摄像机上
    • 3、在用来测试的SubShader中添加 LOD 600 对应高配,并且添加一个只有空Pass的SubShader设置LOD 400 对应中配。(一般来说,SubShader的顺序按LOD从大到小来排序最合适,不容易出错)


前言

Unity中Shader的ShaderLOD,这个功能用于让游戏支持 高配、中配、低配不同效果之间切换时使用。


一、ShaderLOD的使用步骤

1、ShaderLOD使用在不同的SubShader中,用于区分SubShader所对应的配置

LOD 100;

2、在 C# 中使用 Shader.globalMaximumLOD 赋值来选择不同的 SubShader,以达到修改配置对应Shader的效果

Shader.globalMaximumLOD = 100;

3、在设置LOD时,是需要和程序讨论统一 LOD 对应的数值所对应的配置

二、ShaderLOD实现不同配置对应不同SubShader

1、我们基于之前的文章代码,继续测试该功能

因为需要使用LOD来区分不同的配置,所以不能使用上一篇的Fallback了

  • Unity中Shader的Fallback

我们使用没实现Fallback的Shader来继续测试

  • Unity中Shader阴影的接收

2、编写C#脚本来控制选择不同的ShaderLOD,并且把该脚本挂载在摄像机上

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

[ExecuteInEditMode]
public class ShaderLOD : MonoBehaviour
{
    public enum Quality
    {
        High,Medium,Low
    }

    public Quality theQuality = Quality.High;
    
    void Update()
    {
        switch (theQuality)
        {
            case Quality.High:
                Shader.globalMaximumLOD = 600; 
                break;
            case Quality.Medium:
                Shader.globalMaximumLOD = 400;
                break;
            case Quality.Low:
                Shader.globalMaximumLOD = 200;
                break;
        }
    }
}


3、在用来测试的SubShader中添加 LOD 600 对应高配,并且添加一个只有空Pass的SubShader设置LOD 400 对应中配。(一般来说,SubShader的顺序按LOD从大到小来排序最合适,不容易出错)

Shader代码:

//ShaderLOD
Shader "MyShader/P1_7_5"
{
    Properties
    {
        [Enum(Off,0,On,1)]_ZWrite("ZWrite",int) = 0
        [Enum(UnityEngine.Rendering.CompareFunction)]_ZTest("ZTest",int) = 0
        //使用这个标签,可以使外部暴露属性,有标题
        [Header(Base)]
        [NoScaleOffset]_MainTex ("Texture", 2D) = "white" {}
        _Clip("Clip",Range(0,1)) = 0
        //使用这个标签可以 在两行暴露属性之间加 间隙
        [Space(10)]
        [Header(Dissolve)]
        _DissolveTex("DissolveTex",2D) = "black"{}

        [NoScaleOffset]_RampTex("RampTex(RGB)",2D) = "black" {}
        
    }
    SubShader
    {
        Tags{"Queue" = "Geometry"}
        LOD 600
        
        Blend Off
        Cull Back
        /*ZWrite [_ZWrite]
        
        ZTest [_ZTest]*/
        
        Offset -1,-1
        
        UsePass "MyShader/P1_6_4/XRay"
        
        Pass
        {
            //Tags{"LightMode"="ForwardBase"}
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            //#pragma multi_compile_fwdbase
            //剔除无用的变体
            //#pragma skip_variants DIRLIGHTMAP_COMBINED DYNAMICLIGHTMAP_ON LIGHTMAP_ON LIGHTMAP_SHADOW_MIXING LIGHTPROBE_SH SHADOWS_SHADOWMASK VERTEXLIGHT_ON
            //自己定义,阴影需要使用的变体
            #pragma multi_compile DIRECTIONAL SHADOWS_SCREEN
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            
            sampler2D _MainTex;
            float _Clip;
            sampler2D _DissolveTex; 
            //这个四维向量,xyzw分别表示 Tilling 和 Offset 的 xy ,命名方式 在纹理名 后加 _ST
            float4 _DissolveTex_ST;


            //因为 在使用渐变纹理时,只使用了 渐变纹理的 u 坐标,所以把  sampler2D 换为 sampler
            sampler _RampTex;

            struct appdata
            {
                float4 vertex : POSITION;
                float4 uv : TEXCOORD0;
            };
            
            //1.在v2f中添加UNITY_SHADOW_COORDS(idx),unity会自动声明一个叫_ShadowCoord的float4变量,用作阴影的采样坐标.
            struct v2f
            {
                float4 uv : TEXCOORD0;
                float4 pos : SV_POSITION;
                UNITY_SHADOW_COORDS(1)
                float4 worldPos :TEXCOORD2;
            };
            //2.在顶点着色器中添加TRANSFER_SHADOW(o),用于将上面定义的_ShadowCoord纹理采样坐标变换到相应的屏幕空间纹理坐标,为采样阴影纹理使用.
            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                
                //为了减少传入的值 ,所以就不创建新变量来存储,而是把 uv 改为  四维向量 来用
                //使用 o.uv 的 xy 来存放 原人物贴图
                //使用 o.uv 的 zw 来存放 噪波贴图缩放 和 偏移 后的值
                o.uv.xy = v.uv.xy;
                //o.uv.zw = v.uv * _DissolveTex_ST.xy + _DissolveTex_ST.zw;
                o.uv.zw = TRANSFORM_TEX(v.uv,_DissolveTex);

                TRANSFER_SHADOW(o)
                //把顶点转化到世界空间下
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);
                
                return o;
            }
            //3.在片断着色器中添加UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos),其中atten即存储了采样后的阴影.
            fixed4 frag (v2f i) : SV_Target
            {

                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos)
                
                fixed4 col = tex2D(_MainTex, i.uv.xy);

                //把阴影 和 纹理相乘
                col *= atten;
                
                //外部获取的 纹理 ,使用前都需要采样
                fixed4 dissolveTex = tex2D(_DissolveTex,i.uv.zw);
                
                //片段的取舍
                clip(dissolveTex.r -  _Clip);

                //进行归一化
                fixed4 dissolveValue = saturate((dissolveTex.r - _Clip) / (_Clip + 0.1 - _Clip));

                fixed4 rampTex = tex1D(_RampTex,dissolveValue.r);

                //col += rampTex;
                return col;
            }
            ENDCG
        }
        //阴影的投射
        Pass
        {
            //1、设置 "LightMode" = "ShadowCaster"
            Tags{"LightMode" = "ShadowCaster"}
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag
            //需要添加一个 Unity变体
            #pragma multi_compile_shadowcaster

            
            #include "UnityCG.cginc"

            //声明消融使用的变量
            float _Clip;
            sampler2D _DissolveTex;
            float4 _DissolveTex_ST;
            
            //2、appdata中声明float4 vertex:POSITION;和half3 normal:NORMAL;这是生成阴影所需要的语义.
            //注意:在appdata部分,我们几乎不要去修改名字 和 对应的类型。
            //因为,在Unity中封装好的很多方法都是使用这些标准的名字
            struct appdata
            {
                float4 vertex:POSITION;
                half3 normal:NORMAL;
                float4 uv:TEXCOORD;
            };
            //3、v2f中添加V2F_SHADOW_CASTER;用于声明需要传送到片断的数据.
            struct v2f
            {
                float4 uv : TEXCOORD;
                V2F_SHADOW_CASTER;
            };
            //4、在顶点着色器中添加TRANSFER_SHADOW_CASTER_NORMALOFFSET(o),主要是计算阴影的偏移以解决不正确的Shadow Acne和Peter Panning现象.
            v2f vert(appdata v)
            {
                v2f o;
                o.uv.zw = TRANSFORM_TEX(v.uv,_DissolveTex);
                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
                return o;
            }
            //5、在片断着色器中添加SHADOW_CASTER_FRAGMENT(i)
            
            fixed4 frag(v2f i) : SV_Target
            {
                //外部获取的 纹理 ,使用前都需要采样
                fixed4 dissolveTex = tex2D(_DissolveTex,i.uv.zw);
                
                //片段的取舍
                clip(dissolveTex.r -  _Clip);
                
                SHADOW_CASTER_FRAGMENT(i);
            }
            ENDCG
        }
    }
    SubShader
    {
        LOD 400
        Pass
        {
            
        }
        
    }
}



选择高配效果:

在这里插入图片描述

选择中配效果:(因为是空Pass,所以返回白色)
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/103876.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Git简明教程

1.Git的定位 在我们自己开发项目的过程中,经常会遇到这样的情况,为了防止代码丢失,或者新变更的代码影响到原有的代码功能,为了在失误后能恢复到原来的版本,不得不复制出一个副本,比如:“坦克大战1.0”“坦…

创建 Edge 浏览器扩展教程(下)

创建 Edge 浏览器扩展教程(下) 创建扩展教程,第 2 部分1:更新弹出窗口.html以包含按钮2:更新弹出窗口.html在浏览器选项卡顶部显示图像3:创建弹出式 JavaScript 以发送消息4:从任何浏览器选项卡…

react createElement 和 cloneElement 有什么区别?

前言 什么是react React是一个用于构建用户界面的JavaScript库。它旨在帮助开发人员构建可维护、高性能的应用程序界面。React的核心思想是组件化,它允许开发人员将用户界面划分为小块组件,每个组件负责自己的渲染和行为。这种组件化的方法使得代码更容易…

k8s集群镜像下载加gradana监控加elk日志收集加devops加秒杀项目

展示 1.配套资料2.devops 3.elk日志收集 4.grafana监控 5.dashboard![在这里插入图片描述](https://img-blog.csdnimg.cn/bf294f9fd98e4c038858a6bf5c34dbdc.png 目的 学习k8s来来回回折腾很久了,光搭个环境就能折腾几天。这次工作需要终于静下心来好好学习了一…

经管博士科研基础【26】海塞矩阵

1. 海塞矩阵 海塞矩阵是一个由多变量实值函数的所有二阶偏导数组成的方块矩阵。 一元函数就是二阶导,多元函数就是二阶偏导组成的矩阵。求向量函数最小值时可以使用,矩阵正定是最小值存在的充分条件。经济学中常常遇到求最优的问题,目标函数是多元非线性函数的极值问题,尚…

Warning: ‘Destination Folder‘ contains 1 space.【Anaconda安装】

报错内容如下: 意思就是说你的安装路径下不要有空格哈哈,有空格就不行,比如: "D:\Program Files\Anaconda3"中间就有空格,Program与Files之间。 换个路径,例如: 就可以了。

【技能树笔记】网络篇——练习题解析(九)

目录 前言 一、OSPF双栈 1.1 OSPFv3 LSA 1.2 OSPFv3 二、ISIS双栈 2.1 ISISv6 2.2 ISIS高级特性 三、BGP双栈 四、PIM双栈 总结 🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。 💡本文由Filot…

python—openpyxl操作excel详解

前言 openpyxl属于第三方模块,在python中用来处理excel文件。 可以对excel进行的操作有:读写、修改、调整样式及插入图片等。 但只能用来处理【 .xlsx】 后缀的excel文件。 使用前需要先安装,安装方法: pip install openpyxl…

Hadoop3教程(二十七):(生产调优篇)HDFS读写压测

文章目录 (146)HDFS压测环境准备(147)HDFS读写压测写压测读压测 参考文献 (146)HDFS压测环境准备 对开发人员来讲,压测这个技能很重要。 假设你刚搭建好一个集群,就可以直接投入生…

华为数通方向HCIP-DataCom H12-831题库(多选题:61-80)

第61题 在MPLS VPN中,为了区分使用相同地址空间的IPV4前缀,将IPV4的地址增加了RD值,下列选项描述正确的是: A、在PE设备上,每一个VPN实例都对应一个RD值,同一PE设备上,必须保证RD值唯一 B、RD可用于来控制VPN路由信息的发布 C、RD在传递过程中作为BGP的扩展团体性封装在…

Docker镜像仓库

Docker镜像仓库 一、Docker镜像的创建1.1、基于已有镜像创建1.2、基于本地模板创建1.3、基于Dockerfile创建(使用最广泛)1.3.1、联合文件系统(UnionFS)1.3.2、镜像加载原理1.3.3、Dockerfile1.3.4、Docker 镜像结构的分层 二、如何…

【JavaScript】深入浅出理解事件循环

1. 浏览器的进程模型 1.1 进程 程序运行需要有它自己专属的内存空间,可以把这块内存空间简单的理解为进程。 每个应用至少有一个进程,进程之间相互独立,即使要通信,也需要双方同意。 1.2 线程 有了进程后,就可以运…

uniapp: 本应用使用HBuilderX x.x.xx 或对应的cli版本编译,而手机端SDK版本是 x.x.xx。不匹配的版本可能造成应用异常。

文章目录 前言一、原因分析二、解决方案2.1、方案一:更新HbuilderX版本2.2、方案二:设置固定的版本2.3、方案三:忽略版本(不推荐) 三、总结四、感谢 前言 项目场景:示例:通过使用HbuilderX打包…

idea 设置serlvet 类模板(快捷生成servlet类)

我的版本是idea2020.3.4,博客中有相应安装教程,其他版本设置类似: 1.选择文件-->设置 2.选择编辑器-->文件和代码模板-->其他 3.选择Web-->Servlet Annotated Class.java-->复制相应模板,下面顺便设置了注释模板 …

成集云 | 成销云-移动订货集成用友NC | 解决方案

方案介绍 成销云移动订货系统支持多终端下单、业务员代下单、分级定价、数据分析、财务结算、对接ERP等功能,帮助客户解决、订货困难、错单漏单、价格体系混乱等问题,为商家提供更精准的营销和库存管理手段。 用友NC是用友NC产品的全新系列&#xff0c…

【JAVA学习笔记】44 - 注解,元注解

项目代码 一、注解的引入 1)注解(Annotation)也被称为元数据(Metadata),用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息。 2)和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。 3)在Ja…

GLIP,FLIP论文阅读

Scaling Language-Image Pre-training via Masking(FLIP,2023)👍 贡献: 1.图像端引入MAE的随机MASK,image encoder只处理未mask的patches(和之前的MAE方法一致),减少了输…

一、python基础语法

文章目录 1.Python介绍1)发明者龟叔2)python特点3)python缺点4)Python版本 2.Python解释器1)编译型和解释型2)常见的python解释器3)下载Python解释器4)安装Python解释器5&#xff09…

网络流探索:解决网络最大流问题的算法集锦

1.初识网络流 网络流一直是初学者心中很难过去的一道坎,很多人说它是一个不像DFS/BFS那么直观的算法,同时网上也有各种参差不齐的材料,让人感到一知半解。 如果你也有这样的感觉,那么不要灰心,坚持住,因为…

redis 主从复制

1 . redis主从复制 – 配置文件方式实现 1.1简介 : 主机更新后根据配置和策略,自动同步到备机的master/slave机制,Master以写为主,Slave以读为主 1.2 具体作用 读写分离,性能扩展,降低主服务器的压力容灾&#xff0c…
最新文章