【Shader进阶】Shader的Lod

43 篇文章 30 订阅
24 篇文章 3 订阅

目录

官方说明

Shader Level of Detail(简称Lod)

中文版说明

着色器细节级别

一、实战

编辑器功能,快速创建CubeMap


官方说明

Shader Level of Detail(简称Lod)

Shader Level of Detail (LOD) works by only using shaders or subshaders that have their LOD value less than a given number.

By default, allowed LOD level is infinite, that is, all shaders that are supported by the user’s hardware can be used. However, in some cases you might want to drop shader details, even if the hardware can support them. For example, some cheap graphics cards might support all the features, but are too slow to use them. So you may want to not use parallax normal mapping on them.

Shader LOD can be either set per individual shader (using Shader.maximumLOD), or globally for all shaders (using Shader.globalMaximumLOD).

In your custom shaders, use LOD command to set up LOD value for any subshader.

Built-in shaders in Unity have their LODs set up this way:

  • VertexLit kind of shaders = 100
  • Decal, Reflective VertexLit = 150
  • Diffuse = 200
  • Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
  • Bumped, Specular = 300
  • Bumped Specular = 400
  • Parallax = 500
  • Parallax Specular = 600

中文版说明

着色器细节级别

 

着色器细节级别(LOD)仅通过使用其LOD值小于给定数字的着色器或子着色器来工作。

默认情况下,允许的LOD级别是无限的,也就是说,可以使用用户硬件支持的所有着色器。但是,在某些情况下,即使硬件可以支持着色器详细信息,也可能要删除它们。例如,某些便宜的图形卡可能支持所有功能,但使用它们的速度太慢。因此,您可能不希望对它们使用视差法线贴图。

可以为每个着色器设置Shader LOD(使用Shader.maximumLOD),也可以为所有着色器全局设置(使用Shader.globalMaximumLOD)。

在您的自定义着色器中,使用LOD命令为任何子着色器设置LOD值。

Unity中的内置着色器通过以下方式设置其LOD:

  • VertexLit着色器= 100
  • 贴花,反射性顶点光= 150
  • 漫射= 200
  • 漫反射细节,反射凹凸未照明,反射凹凸VertexLit = 250
  • 凹凸,镜面反射= 300
  • 凹凸镜面反射= 400
  • 视差= 500
  • 视差镜面反射= 600

看完后,感觉还是很懵逼,实测一下吧

一、实战

漫反射 (LOD为100)、半兰伯特漫反射(LOD为200)、环境反射(LOD为300)

效果图:

 

 

Shader "Unlit/LoadTest"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
		_Color("Color", Color) = (1,1,1,1)
		_CubeMap("CubeMap", Cube) = "_Skybox"{}

		[Space(5)]
		_FValue("FValue", Range(0,1)) = 0.5		
	}
	SubShader
	{

		Tags { "RenderType" = "Opaque" }
		LOD 300 //默认为100 
		//实现一个环境反射+漫反射+菲涅尔系数
		Pass
		{
			Tags
			{
				"LightMode" = "ForwardBase"
			}
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fwdbase

			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
				fixed3 normal : NORMAL;
				float4 pos : TEXCOORD1;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Color;
			samplerCUBE _CubeMap;
			fixed _FValue;

			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				o.normal = UnityObjectToWorldNormal(v.normal);
				o.pos = mul(unity_ObjectToWorld, v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.pos));
				fixed3 normal = normalize(i.normal);
				fixed d = max(0, dot(lightDir, normal) * 0.5 + 0.5);
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.pos));				
				fixed3 reflectDir = reflect(normal, viewDir);
				fixed4 reflectCol = texCUBE(_CubeMap, reflectDir);
				col.rgb = col.rgb * d * _LightColor0.rgb;
				half feinier = _FValue + pow(dot(normal, viewDir), 5); //菲尼尔系数
				return col * reflectCol * feinier;
			}
			ENDCG
		}
	}

	SubShader
	{
		Tags { "RenderType" = "Opaque" }
		LOD 200 //默认为100 
		//实现一个半兰伯特漫反射
		Pass
		{
			Tags{
				"LightMode" = "ForwardBase"
			}
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fwdbase

			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
				fixed3 normal : NORMAL;
				float4 pos : TEXCOORD1;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Color;

			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				o.normal = UnityObjectToWorldNormal(v.normal);
				o.pos = mul(unity_ObjectToWorld, v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.pos));
				fixed3 normal = normalize(i.normal);
				fixed d = max(0, dot(lightDir, normal) * 0.5 + 0.5);
				col.rgb = col.rgb * d * _LightColor0.rgb;
				return col * _Color;
			}
			ENDCG
		}
	}

	SubShader
	{
		Tags { "RenderType" = "Opaque" }
		LOD 100 //默认为100 
		//实现一个兰伯特漫反射
		Pass
		{
			Tags{
				"LightMode" = "ForwardBase"
			}
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fwdbase

			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
				fixed3 normal : NORMAL;
				float4 pos : TEXCOORD1;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Color;

			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				o.normal = UnityObjectToWorldNormal(v.normal);
				o.pos = mul(unity_ObjectToWorld, v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.pos));
				fixed3 normal = normalize(i.normal);
				fixed d = max(0, dot(lightDir, normal));
				col.rgb = col.rgb * d * _LightColor0.rgb;
				return col * _Color;
			}
			ENDCG
		}
	}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LodTest : MonoBehaviour {

    public int lod;
    Shader shader;
	void Start () {
        //Shader.globalMaximumLOD = 500; //设置全局Lod, 比它小的Shader能够渲染
        shader = gameObject.GetComponent<MeshRenderer>().material.shader;

	}
		
	void Update () {
        shader.maximumLOD = lod;
    }
}

编辑器功能,快速创建CubeMap

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class AutoCreateCubeMap : EditorWindow
{

    static EditorWindow window;
    [MenuItem("Milk/AutoCreateCubemap")]
    public static void Create()
    {
        window = EditorWindow.GetWindowWithRect(typeof(AutoCreateCubeMap), new Rect(200, 200, 300, 400));
        window.Show();
    }

    private GameObject obj;
    private Cubemap cubemap;
    private void OnGUI()
    {
        GUILayout.BeginVertical();
        EditorGUI.indentLevel++;
        GUILayout.BeginHorizontal();
        EditorGUI.indentLevel++;
        obj = (GameObject)EditorGUILayout.ObjectField("Render From Position", obj, typeof(GameObject), true);
        EditorGUI.indentLevel--;
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        EditorGUI.indentLevel++;
        cubemap = (Cubemap)EditorGUILayout.ObjectField("Cubemap", cubemap, typeof(Cubemap), true);
        EditorGUI.indentLevel--;
        GUILayout.EndHorizontal();
        EditorGUI.indentLevel--;
        if (GUILayout.Button("Create"))
        {
            GameObject go = new GameObject("CameraObject");
            Camera camera = go.AddComponent<Camera>();
            go.transform.position = obj.transform.position;
            camera.RenderToCubemap(cubemap);
            DestroyImmediate(go);
        }
        GUILayout.EndVertical();
    }
}

 

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值