当前位置:网站首页>Unity Shader 常规光照模型代码整理
Unity Shader 常规光照模型代码整理
2022-08-01 21:24:00 【Mr.QSheng】
Unity Shader 常规光照模型代码整理
本次整理在Unity中几种常见的光照模型,包含
1.BlinnPhong(常规光照模型)
2.ForwardRender(多灯光带有衰弱前向渲染)
3.AttenuationAndShadow(多灯光添加阴影,衰弱的前向渲染)
4.Stander(unity 官方标准光照模型PBR)
5.CustonStander(手动实现Unity PBR,代码来自catlike Coding)
文章目录
前言
本次整理在Unity中几种常见的光照模型,包含BlinnPhong,ForwardRender,AttenuationAndShadow,Stander,CustonStander.本次章节分享的主要目的也是为了自己往后方便直接上来copy,也方便其他人直接copy直接用。
一、demo效果展示
二、各种光照模型
1.BlinnPhong
代码如下(示例):
Shader "Unlit/BlinnPhong"
{
Properties
{
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
_Specular ("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(1.0, 500)) = 20
}
SubShader
{
Tags {
"LightMode"="ForwardBase" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float4 worldPos : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
return fixed4(ambient + diffuse + specular, 1.0);
}
ENDCG
}
}
}
2.ForwardRender
代码如下(示例):
Shader "Unlit/ForwardRender"
{
Properties
{
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
_Specular ("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
SubShader
{
Tags {
"RenderType"="Opaque" }
LOD 100
Pass
{
Tags {
"LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "Lighting.cginc"
#include "AutoLight.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
fixed atten = 1.0;
return fixed4(ambient + (diffuse + specular) * atten, 1.0);
}
ENDCG
}
Pass
{
Tags {
"LightMode"="ForwardAdd" }
Blend One One
CGPROGRAM
#pragma multi_compile_fwdadd
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "AutoLight.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
#ifdef USING_DIRECTIONAL_LIGHT
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
#else
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
#endif
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
#ifdef USING_DIRECTIONAL_LIGHT
fixed atten = 1.0;
#elif defined (SPOT)
float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#else
fixed atten = 1.0;
#endif
return fixed4((diffuse + specular) * atten, 1.0);
}
ENDCG
}
}
}
3.AttenuationAndShadow
代码如下(示例):
Shader "Unlit/AttenuationAndShadow"
{
Properties
{
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
_Specular ("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
SubShader
{
Tags {
"RenderType"="Opaque" }
LOD 100
Pass
{
Tags {
"LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "Lighting.cginc"
#include "AutoLight.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
SHADOW_COORDS(2)
};
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
return fixed4(ambient + (diffuse + specular) * atten, 1.0);
}
ENDCG
}
Pass {
Tags {
"LightMode"="ForwardAdd" }
Blend One One
CGPROGRAM
#pragma multi_compile_fwdadd
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "AutoLight.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
SHADOW_COORDS(2)
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
return fixed4((diffuse + specular) * atten, 1.0);
}
ENDCG
}
}
FallBack "Specular"
}
4.Stander
直接创建一个表面着色器即可
2.CustonStander
shader代码如下所示:
Shader "Unlit/CustonStander"
{
Properties
{
_Color ("Tint", Color) = (1, 1, 1, 1)
_MainTex ("Albedo", 2D) = "white" {
}
[NoScaleOffset] _NormalMap ("Normals", 2D) = "bump" {
}
_BumpScale ("Bump Scale", Float) = 1
[NoScaleOffset] _MetallicMap ("Metallic", 2D) = "white" {
}
[Gamma] _Metallic ("Metallic", Range(0, 1)) = 0
_Smoothness ("Smoothness", Range(0, 1)) = 0.1
[NoScaleOffset] _OcclusionMap ("Occlusion", 2D) = "white" {
}
_OcclusionStrength ("Occlusion Strength", Range(0, 1)) = 1
[NoScaleOffset] _EmissionMap ("Emission", 2D) = "black" {
}
_Emission ("Emission", Color) = (0, 0, 0)
[NoScaleOffset] _DetailMask ("Detail Mask", 2D) = "white" {
}
_DetailTex ("Detail Albedo", 2D) = "gray" {
}
[NoScaleOffset] _DetailNormalMap ("Detail Normals", 2D) = "bump" {
}
_DetailBumpScale ("Detail Bump Scale", Float) = 1
_Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5
_WireframeColor ("Wireframe Color", Color) = (0, 0, 0)
_WireframeSmoothing ("Wireframe Smoothing", Range(0, 10)) = 1
_WireframeThickness ("Wireframe Thickness", Range(0, 10)) = 1
[HideInInspector] _SrcBlend ("_SrcBlend", Float) = 1
[HideInInspector] _DstBlend ("_DstBlend", Float) = 0
[HideInInspector] _ZWrite ("_ZWrite", Float) = 1
}
SubShader
{
Pass
{
Tags {
"LightMode" = "ForwardBase"
}
Blend [_SrcBlend][_DstBlend]
ZWrite [_ZWrite]
CGPROGRAM
#pragma target 4.0
#pragma shader_feature _ _RENDERING_CUTOUT _RENDERING_FADE _RENDERING_TRANSPARENT
#pragma shader_feature _METALLIC_MAP
#pragma shader_feature _ _SMOOTHNESS_ALBEDO _SMOOTHNESS_METALLIC
#pragma shader_feature _NORMAL_MAP
#pragma shader_feature _PARALLAX_MAP
#pragma shader_feature _OCCLUSION_MAP
#pragma shader_feature _EMISSION_MAP
#pragma shader_feature _DETAIL_MASK
#pragma shader_feature _DETAIL_ALBEDO_MAP
#pragma shader_feature _DETAIL_NORMAL_MAP
#pragma multi_compile _ LOD_FADE_CROSSFADE
#pragma multi_compile_fwdbase
#pragma multi_compile_fog
#pragma multi_compile_instancing
#pragma instancing_options lodfade force_same_maxcount_for_gl
#define FORWARD_BASE_PASS
#include "My Lighting.cginc"
#pragma vertex MyVertexProgram
#pragma fragment MyFragmentProgram
ENDCG
}
Pass {
Tags {
"LightMode" = "ForwardAdd"
}
Blend [_SrcBlend] One
ZWrite Off
CGPROGRAM
#pragma target 3.0
#pragma shader_feature _ _RENDERING_CUTOUT _RENDERING_FADE _RENDERING_TRANSPARENT
#pragma shader_feature _METALLIC_MAP
#pragma shader_feature _ _SMOOTHNESS_ALBEDO _SMOOTHNESS_METALLIC
#pragma shader_feature _NORMAL_MAP
#pragma shader_feature _PARALLAX_MAP
#pragma shader_feature _DETAIL_MASK
#pragma shader_feature _DETAIL_ALBEDO_MAP
#pragma shader_feature _DETAIL_NORMAL_MAP
#pragma shader_feature UNITY_PBS_USE_BRDF1
#pragma multi_compile _ LOD_FADE_CROSSFADE
#pragma multi_compile_fwdadd_fullshadows
#pragma multi_compile_fog
#pragma vertex MyVertexProgram
#pragma fragment MyFragmentProgram
#include "My Lighting.cginc"
ENDCG
}
}
CustomEditor "MyLightingShaderGUI"
}
Shader GUI代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
public class MyLightingShaderGUI : ShaderGUI
{
enum SmoothnessSource
{
Uniform, Albedo, Metallic
}
enum RenderingMode
{
Opaque, Cutout, Fade, Transparent
}
struct RenderingSettings
{
public RenderQueue queue;
public string renderType;
public BlendMode srcBlend, dstBlend;
public bool zWrite;
public static RenderingSettings[] modes = {
new RenderingSettings() {
queue = RenderQueue.Geometry,
renderType = "",
srcBlend = BlendMode.One,
dstBlend = BlendMode.Zero,
zWrite = true
},
new RenderingSettings() {
queue = RenderQueue.AlphaTest,
renderType = "TransparentCutout",
srcBlend = BlendMode.One,
dstBlend = BlendMode.Zero,
zWrite = true
},
new RenderingSettings() {
queue = RenderQueue.Transparent,
renderType = "Transparent",
srcBlend = BlendMode.SrcAlpha,
dstBlend = BlendMode.OneMinusSrcAlpha,
zWrite = false
},
new RenderingSettings() {
queue = RenderQueue.Transparent,
renderType = "Transparent",
srcBlend = BlendMode.One,
dstBlend = BlendMode.OneMinusSrcAlpha,
zWrite = false
}
};
}
static GUIContent staticLabel = new GUIContent();
static ColorPickerHDRConfig emissionConfig =
new ColorPickerHDRConfig(0f, 99f, 1f / 99f, 3f);
Material target;
MaterialEditor editor;
MaterialProperty[] properties;
bool shouldShowAlphaCutoff;
public override void OnGUI(
MaterialEditor editor, MaterialProperty[] properties
)
{
this.target = editor.target as Material;
this.editor = editor;
this.properties = properties;
DoRenderingMode();
DoMain();
DoSecondary();
DoAdvanced();
}
void DoRenderingMode()
{
RenderingMode mode = RenderingMode.Opaque;
shouldShowAlphaCutoff = false;
if (IsKeywordEnabled("_RENDERING_CUTOUT"))
{
mode = RenderingMode.Cutout;
shouldShowAlphaCutoff = true;
}
else if (IsKeywordEnabled("_RENDERING_FADE"))
{
mode = RenderingMode.Fade;
}
else if (IsKeywordEnabled("_RENDERING_TRANSPARENT"))
{
mode = RenderingMode.Transparent;
}
EditorGUI.BeginChangeCheck();
mode = (RenderingMode)EditorGUILayout.EnumPopup(
MakeLabel("Rendering Mode"), mode
);
if (EditorGUI.EndChangeCheck())
{
RecordAction("Rendering Mode");
SetKeyword("_RENDERING_CUTOUT", mode == RenderingMode.Cutout);
SetKeyword("_RENDERING_FADE", mode == RenderingMode.Fade);
SetKeyword(
"_RENDERING_TRANSPARENT", mode == RenderingMode.Transparent
);
RenderingSettings settings = RenderingSettings.modes[(int)mode];
foreach (Material m in editor.targets)
{
m.renderQueue = (int)settings.queue;
m.SetOverrideTag("RenderType", settings.renderType);
m.SetInt("_SrcBlend", (int)settings.srcBlend);
m.SetInt("_DstBlend", (int)settings.dstBlend);
m.SetInt("_ZWrite", settings.zWrite ? 1 : 0);
}
}
if (mode == RenderingMode.Fade || mode == RenderingMode.Transparent)
{
DoSemitransparentShadows();
}
}
void DoSemitransparentShadows()
{
EditorGUI.BeginChangeCheck();
bool semitransparentShadows =
EditorGUILayout.Toggle(
MakeLabel("Semitransp. Shadows", "Semitransparent Shadows"),
IsKeywordEnabled("_SEMITRANSPARENT_SHADOWS")
);
if (EditorGUI.EndChangeCheck())
{
SetKeyword("_SEMITRANSPARENT_SHADOWS", semitransparentShadows);
}
if (!semitransparentShadows)
{
shouldShowAlphaCutoff = true;
}
}
void DoMain()
{
GUILayout.Label("Main Maps", EditorStyles.boldLabel);
MaterialProperty mainTex = FindProperty("_MainTex");
editor.TexturePropertySingleLine(
MakeLabel(mainTex, "Albedo (RGB)"), mainTex, FindProperty("_Color")
);
if (shouldShowAlphaCutoff)
{
DoAlphaCutoff();
}
DoMetallic();
DoSmoothness();
DoNormals();
DoOcclusion();
DoEmission();
DoDetailMask();
editor.TextureScaleOffsetProperty(mainTex);
}
void DoAlphaCutoff()
{
MaterialProperty slider = FindProperty("_Cutoff");
EditorGUI.indentLevel += 2;
editor.ShaderProperty(slider, MakeLabel(slider));
EditorGUI.indentLevel -= 2;
}
void DoNormals()
{
MaterialProperty map = FindProperty("_NormalMap");
Texture tex = map.textureValue;
EditorGUI.BeginChangeCheck();
editor.TexturePropertySingleLine(
MakeLabel(map), map,
tex ? FindProperty("_BumpScale") : null
);
if (EditorGUI.EndChangeCheck() && tex != map.textureValue)
{
SetKeyword("_NORMAL_MAP", map.textureValue);
}
}
void DoMetallic()
{
MaterialProperty map = FindProperty("_MetallicMap");
Texture tex = map.textureValue;
EditorGUI.BeginChangeCheck();
editor.TexturePropertySingleLine(
MakeLabel(map, "Metallic (R)"), map,
tex ? null : FindProperty("_Metallic")
);
if (EditorGUI.EndChangeCheck() && tex != map.textureValue)
{
SetKeyword("_METALLIC_MAP", map.textureValue);
}
}
void DoSmoothness()
{
SmoothnessSource source = SmoothnessSource.Uniform;
if (IsKeywordEnabled("_SMOOTHNESS_ALBEDO"))
{
source = SmoothnessSource.Albedo;
}
else if (IsKeywordEnabled("_SMOOTHNESS_METALLIC"))
{
source = SmoothnessSource.Metallic;
}
MaterialProperty slider = FindProperty("_Smoothness");
EditorGUI.indentLevel += 2;
editor.ShaderProperty(slider, MakeLabel(slider));
EditorGUI.indentLevel += 1;
EditorGUI.BeginChangeCheck();
source = (SmoothnessSource)EditorGUILayout.EnumPopup(
MakeLabel("Source"), source
);
if (EditorGUI.EndChangeCheck())
{
RecordAction("Smoothness Source");
SetKeyword("_SMOOTHNESS_ALBEDO", source == SmoothnessSource.Albedo);
SetKeyword(
"_SMOOTHNESS_METALLIC", source == SmoothnessSource.Metallic
);
}
EditorGUI.indentLevel -= 3;
}
void DoOcclusion()
{
MaterialProperty map = FindProperty("_OcclusionMap");
Texture tex = map.textureValue;
EditorGUI.BeginChangeCheck();
editor.TexturePropertySingleLine(
MakeLabel(map, "Occlusion (G)"), map,
tex ? FindProperty("_OcclusionStrength") : null
);
if (EditorGUI.EndChangeCheck() && tex != map.textureValue)
{
SetKeyword("_OCCLUSION_MAP", map.textureValue);
}
}
void DoEmission()
{
MaterialProperty map = FindProperty("_EmissionMap");
Texture tex = map.textureValue;
EditorGUI.BeginChangeCheck();
editor.TexturePropertyWithHDRColor(
MakeLabel(map, "Emission (RGB)"), map, FindProperty("_Emission"),
emissionConfig, false
);
editor.LightmapEmissionProperty(2);
if (EditorGUI.EndChangeCheck())
{
if (tex != map.textureValue)
{
SetKeyword("_EMISSION_MAP", map.textureValue);
}
foreach (Material m in editor.targets)
{
m.globalIlluminationFlags &=
~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
}
}
}
void DoDetailMask()
{
MaterialProperty mask = FindProperty("_DetailMask");
EditorGUI.BeginChangeCheck();
editor.TexturePropertySingleLine(
MakeLabel(mask, "Detail Mask (A)"), mask
);
if (EditorGUI.EndChangeCheck())
{
SetKeyword("_DETAIL_MASK", mask.textureValue);
}
}
void DoSecondary()
{
GUILayout.Label("Secondary Maps", EditorStyles.boldLabel);
MaterialProperty detailTex = FindProperty("_DetailTex");
EditorGUI.BeginChangeCheck();
editor.TexturePropertySingleLine(
MakeLabel(detailTex, "Albedo (RGB) multiplied by 2"), detailTex
);
if (EditorGUI.EndChangeCheck())
{
SetKeyword("_DETAIL_ALBEDO_MAP", detailTex.textureValue);
}
DoSecondaryNormals();
editor.TextureScaleOffsetProperty(detailTex);
}
void DoSecondaryNormals()
{
MaterialProperty map = FindProperty("_DetailNormalMap");
Texture tex = map.textureValue;
EditorGUI.BeginChangeCheck();
editor.TexturePropertySingleLine(
MakeLabel(map), map,
tex ? FindProperty("_DetailBumpScale") : null
);
if (EditorGUI.EndChangeCheck() && tex != map.textureValue)
{
SetKeyword("_DETAIL_NORMAL_MAP", map.textureValue);
}
}
void DoAdvanced()
{
GUILayout.Label("Advanced Options", EditorStyles.boldLabel);
editor.EnableInstancingField();
}
MaterialProperty FindProperty(string name)
{
return FindProperty(name, properties);
}
static GUIContent MakeLabel(string text, string tooltip = null)
{
staticLabel.text = text;
staticLabel.tooltip = tooltip;
return staticLabel;
}
static GUIContent MakeLabel(
MaterialProperty property, string tooltip = null
)
{
staticLabel.text = property.displayName;
staticLabel.tooltip = tooltip;
return staticLabel;
}
void SetKeyword(string keyword, bool state)
{
if (state)
{
foreach (Material m in editor.targets)
{
m.EnableKeyword(keyword);
}
}
else
{
foreach (Material m in editor.targets)
{
m.DisableKeyword(keyword);
}
}
}
bool IsKeywordEnabled(string keyword)
{
return target.IsKeywordEnabled(keyword);
}
void RecordAction(string label)
{
editor.RegisterPropertyChangeUndo(label);
}
}
My Lighting.cginc代码如下:
#if !defined(MY_LIGHT_INCLUDED)
#define MY_LIGHT_INCLUDED
#include "My Lighting Input.cginc"
#if !defined(ALBEDO_FUNCTION)
#define ALBEDO_FUNCTION GetAlbedo
#endif
void InitializeFragmentNormal(inout Interpolators i){
float3 tangentSpaceNormal = GetTangentSpaceNormal(i);
}
float FadeShadows(Interpolators i, float attenuation){
#if HANDLE_SHADOWS_BLENDING_IN_GI || ADDITIONAL_MASKED_DIRECTIONAL_SHADOWS
#if ADDITIONAL_MASKED_DIRECTIONAL_SHADOWS
attenuation = SHADOW_ATTENUATION(i);
#endif
float viewZ = dot(_WorldSpaceCameraPos - i.worldPos, UNITY_MATRIX_V[2].xyz);
float shadowFadeDistance = UnityComputeShadowFadeDistance(i.worldPos, viewZ);
float shadowFade = UnityComputeShadowFade(shadowFadeDistance);
float bakedAttenuation = UnitySampleBakedOcclusion(i.lightmapUV, i.worldPos);
attenuation = UnityMixRealtimeAndBakedShadows(attenuation, bakedAttenuation, shadowFade);
#endif
return attenuation;
}
UnityLight CreateLight(Interpolators i){
UnityLight light;
#if defined(DEFFRRED_PASS) || SUBTRACTIVE_LIGHTING
light.dir = float3(0, 1, 0);
light.color = 0;
#else
#if defined(POINT) || defined(POINT_COKKIE) || defined(SPOT)
light.dir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
#else
light.dir = _WorldSpaceLightPos0.xyz;
#endif
UNITY_LIGHT_ATTENUATION(attenuation, i, i.worldPos.xyz);
attenuation = FadeShadows(i, attenuation);
light.color = _LightColor0.rgb * attenuation;
#endif
return light;
}
void ApplySubtractiveLighting(Interpolators i, inout UnityIndirect indirectLight)
{
#if SUBTRACTIVE_LIGHTING
UNITY_LIGHT_ATTENUATION(attenuation, i, i.worldPos.xyz);
attenuation = FadeShadows(i, attenuation);
float ndotl = saturate(dot(i.normal, _WorldSpaceCameraPos0.xyz));
float3 shadowedLightEstimate =
ndotl * (1 - attenuation) * _LightColor0.rgb;
float3 subtractedLight = indirectLight.diffuse - shadowedLightEstimate;
subtractedLight = max(subtractedLight, unity_ShadowColor.rgb);
subtractedLight = lerp(subtractedLight, indirectLight.diffuse, _LightShadowData.x);
indirectLight.diffuse = min(subtractedLight, indirectLight.diffuse);
#endif
}
float3 Boxprojection(float3 direction, float3 position, float4 cubemapPosition,
float3 boxMin, float3 boxMax){
#if UNITY_SPECCUBE_BOX_PROJECTION
UNITY_BRANCH
if (cubemapPosition.w > 0){
float3 factors = ((direction > 0 ? boxMax : boxMin) - position) / direction;
float scalar = min(min(factors.x, factors.y), factors.z);
direction = direction * scalar + (position - cubemapPosition);
}
#endif
return direction;
}
UnityIndirect CreateIndirectLight(Interpolators i, float3 viewDir){
UnityIndirect indirectLight;
indirectLight.diffuse = 0;
indirectLight.specular = 0;
#if defined(VERTEXLIGHT_ON)
indirectLight.diffuse = i.vertexLightColor;
#endif
#if defined(FORWARD_BASE_PASS) || defined(DEFFRRED_PASS)
#if defined(LIGHTMAP_ON)
indirectLight.diffuse =
DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.lighmapUV));
#if defined(DIRLIGHTMAP_COMBINED)
float4 lightmapDirection = UNITY_SAMPLE_TEX2D_SAMPLER(
unity_LightmapInd, unity_Lightmap, i.lightmapUV);
indirectLight.diffuse = DecodeDirectionalLightmap(indirectLight.diffuse,
lightmapDirection, i.normal);
#endif
ApplySubtractiveLighting(i, indirectLight);
#endif
#if defined(DYNAMICLIGHTMAP_ON)
float3 dynamicLightDiffuse = DecodeRealtimeLightmap(
UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, i.dynamicLightmapUV));
#if defined(DIRLIGHTMAP_COMBINED)
float4 dynamicLightmapDirection = UNITY_SAMPLE_TEX2D_SAMPLER(
unity_DynamicDirectionality, unity_DynamicLightmap, i.dynamicLightmapUV);
indirectLight.diffuse += DecodeDirectionalLightmap(dynamicLightDiffuse,
dynamicLightmapDirection, i.normal);
#else
indirectLight.diffuse += dynamicLightDiffuse;
#endif
#endif
#if !defined(LIGHTMAP_ON) && !defined(DYNAMICLIGHTMAP_ON)
#if UNITY_LIGHT_PROBE_PROXY_VOLUME
if (unity_ProbeVolumeParams.x == 1){
indirectLight.diffuse = SHEvalLinearL0L1_SampleProbeVolume(
float4(i.normal, 1), i.worldPos
);
indirectLight.diffuse = max(0, indirectLight.diffuse);
#if defined(UNITY_COLORSPACE_GAMMA)
indirectLight.diffuse = LinearToGammaSpace(indirectLight.diffuse);
#endif
}
else {
indirectLight.diffuse = max(0, ShadeSH9(float4(i.normal, 1)));
}
#else
indirectLight.diffuse += max(0, ShadeSH9(float4(i.normal, 1)));
#endif
#endif
float3 reflectionDir = reflect(-viewDir, i.normal);
Unity_GlossyEnvironmentData envData;
envData.roughness = 1 - GetSmoothness(i);
envData.reflUVW = Boxprojection(
reflectionDir, i.worldPos.xyz,
unity_SpecCube0_ProbePosition,
unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
float3 probe0 = Unity_GlossyEnvironment(
UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, envData);
envData.reflUVW = Boxprojection(
reflectionDir, i.worldPos.xyz,
unity_SpecCube1_ProbePosition,
unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
#if UNITY_SPECCUBE_BLENDING
float interpolator = unity_SpecCube0_BoxMin.w;
UNITY_BRANCH
if (interpolator < 0.99999){
float3 probe1 = Unity_GlossyEnvironment(
UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1, unity_SpecCube0),
unity_SpecCube0_HDR, envData);
indirectLight.specular = lerp(probe1, probe0, interpolator);
}
else{
indirectLight.specular = probe0;
}
#else
indirectLight.specular = probe0;
#endif
float occlusion = GetOcclusion(i);
indirectLight.diffuse *= occlusion;
indirectLight.specular *= occlusion;
#if defined(DEFERRED_PASS) && UNITY_ENANLE_REFLECTION_BUFFERS
indirectLight.specular = 0;
#endif
#endif
return indirectLight;
}
float4 ApplyFog(float4 color, Interpolators i){
#if FOG_ON
float viewDistance = length(_WorldSpaceCameraPos - i.worldPos);
#if FOG_DEPTH
viewDistance = UNITY_Z_0_FAR_FROM_CLIPSPACE(i.worldPos.w);
#endif
UNITY_CALC_FOG_FACTOR_RAW(viewDistance);
float3 fogColor = 0;
#if defined(FORWARD_BASE_PASS)
fogColor = unity_FogColor.rgb;
#endif
color.rgb = lerp(fogColor, color.rgb, saturate(unityFogFactor));
#endif
return color;
}
float3 CreateBinormal(float3 normal, float3 tangent, float binormalSign){
return cross(normal, tangent.xyz) * (binormalSign * unity_WorldTransformParams.w);
}
void ComputeVertexLightColor(inout InterpolatorsVertex i){
#if defined(VERTEXLIGHT_ON)
i.vertexLightColor = Shade4PointLights(
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
unity_LightColor[0].rgb, unity_LightColor[1].rgb,
unity_LightColor[2].rgb, unity_LightColor[3].rgb,
unity_4LightAtten0, i.worldPos.xyz, i.normal);
#endif
}
InterpolatorsVertex MyVertexProgram(VertexData v){
InterpolatorsVertex i;
UNITY_INITIALIZE_OUTPUT(InterpolatorsVertex, i);
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, i);
i.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
i.uv.zw = TRANSFORM_TEX(v.uv, _DetailTex);
#if VERTEX_DISPLACEMENT
float displacement = tex2Dlod(_DisplacementMap, float4(i.uv.xy, 0, 0)).g;
displacement = (displacement - 0.5) * _DisplacementStrength;
v.normal = normalize(v.normal);
v.vertex.xyz += v.normal * displacement;
#endif
i.pos = UnityObjectToClipPos(v.vertex);
i.worldPos.xyz = mul(unity_ObjectToWorld, v.vertex);
#if FOG_DEPTH
i.worldPos.w = i.pos.z;
#endif
i.normal = UnityObjectToWorldNormal(v.normal);
#if defined(BINORMAL_PER_FRAGMENT)
i.tangent = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
#else
i.tangent = UnityObjectToWorldDir(v.tangent.xyz);
i.binormal = CreateBinormal(i.normal, i.tangent, v.tangent.w);
#endif
#if defined(DYNAMICLIGHTMAP_ON)
i.dynamicLightmapUV = v.uv2 * unity_DynamicLightmapST.xy +
unity_DynamicLightmap.zw;
#endif
UNITY_TRANSFER_SHADOW(i, v.uv1);
ComputeVertexLightColor(i);
return i;
}
struct FragmentOutput{
#if defined(DEFERRED_PASS)
float4 gBuffer0 : SV_Target0;
float4 gBuffer1 : SV_Target1;
float4 gBuffer2 : SV_Target2;
float4 gBuffer3 : SV_Target3;
#if defined(SHADPWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4)
float4 gBuffer4 : SV_Target4;
#endif
#else
float4 color : SV_Target;
#endif
};
FragmentOutput MyFragmentProgram(Interpolators i){
UNITY_SETUP_INSTANCE_ID(i);
float alpha = GetAlpha(i);
#if defined(_RENDERING_CUTOUT)
clip(alpha - _Cutoff);
#endif
InitializeFragmentNormal(i);
float3 viewDir = normalize(_WorldSpaceCameraPos - i.worldPos.xyz);
float3 specularTint;
float oneMinusReflectivity;
float3 albedo = DiffuseAndSpecularFromMetallic(
ALBEDO_FUNCTION(i), GetMetallic(i), specularTint, oneMinusReflectivity
);
#if defined(_RENDERING_TRANSPARENT)
albedo *= alpha
alpha = 1 - oneMinusReflectivity + alpha * oneMinusReflectivity;
#endif
float4 color = UNITY_BRDF_PBS(
albedo, specularTint, oneMinusReflectivity,
GetSmoothness(i), i.normal, viewDir, CreateLight(i),
CreateIndirectLight(i, viewDir)
);
color.rgb += GetEmission(i);
#if defined(_RENDERING_FADE) || defined(_RENDERING_TRANSPARENT)
color.a = alpha;
#endif
FragmentOutput output;
#if defined(DEFERRED_PASS)
#if !defined(UNITY_HDR_ON)
color.rgb = exp2(-color.rgb);
#endif
output.gBuffer0.rgb = albedo;
output.gBuffer0.a = GetOcclusion(i);
output.gBuffer1.rgb = specularTint;
output.gBuffer1.a = GetSmoothness(i);
output.gBuffer2 = float4(i.normal * 0.5 + 0.5, 1);
output.gBuffer3 = color;
#if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4)
float2 shadowUV = 0;
#if defined(LIGHTMAP_ON)
shadowUV = i.lightmapUV;
#endif
output.gBuffer4 = UnityGetRawBakedOcclusions(shadowUV, i.worldPos.xyz);
#endif
#else
output.color = ApplyFog(color, i);
#endif
return output;
}
#endif
My Lighting Input.cginc代码如下:
#if !defined(MY_LIGHTING_INPUT_INCLUDED)
#define MY_LIGHTING_INPUT_INCLUDED
#include "UnityPBSLighting.cginc"
#include "AutoLight.cginc"
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
#if !defined(FOG_DISTANCE)
#define FOG_DEPTH 1
#endif
#define FOG_ON 1
#endif
#if !defined(LIGHTMAP_ON) && defined(SHADOWS_SCREEN)
#if defined(SHADOWS_SHADOWMASK) && !defined(UNITY_NO_SCREENSPACE_SHADOWS)
#define ADDITIONAL_MASKED_DIRECTIONAL_SHADOWS 1
#endif
#endif
#if defined(LIGHTMAP_ON) && defined(SHADOWS_SCREEN)
#if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK)
#define SUBTRACTIVE_LIGHTING 1
#endif
#endif
UNITY_INSTANCING_BUFFER_START(InstanceProperties)
UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
#define _Color_arr InstanceProperties
UNITY_INSTANCING_BUFFER_END(InstanceProperties)
struct VertexData {
UNITY_VERTEX_INPUT_INSTANCE_ID
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 uv : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float2 uv2 : TEXCOORD2;
};
struct InterpolatorsVertex
{
UNITY_VERTEX_INPUT_INSTANCE_ID
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
#if defined(BINORMAL_PER_FRAGMENT)
float4 tangent : TEXCOORD2;
#else
float3 tangent : TEXCOORD2;
float3 binormal : TEXCOORD3;
#endif
#if FOG_DEPTH
float4 worldPos : TEXCOORD4;
#else
float3 worldPos : TEXCOORD4;
#endif
UNITY_SHADOW_COORDS(5)
#if defined(VERTEXLIGHT_ON)
float3 vertexLightColor : TEXCOORD6;
#endif
#if defined(LIGHTMAP_ON) || ADDITIONAL_MASKED_DIRECTIONAL_SHADOWS
float2 lightmapUV : TEXCOORD6;
#endif
#if defined(DYNAMICLIGHTMAP_ON)
float2 dynamicLightmapUV : TEXCOORD7;
#endif
};
struct Interpolators {
UNITY_VERTEX_INPUT_INSTANCE_ID
float4 pos :SV_POSITION;
float4 uv: TEXCOORD0;
float3 normal : TEXCOORD1;
float3 tangent : TEXCOORD2;
float3 binormal : TEXCOORD3;
#if FOG_DEPTH
float4 worldPos : TEXCOORD4;
#else
float3 worldPos : TEXCOORD4;
#endif
UNITY_SHADOW_COORDS(5)
#if defined(VERTEXLIGHT_ON)
float3 vertexLightColor : TEXCOORD6;
#endif
#if defined(LIGHTMAP_ON) || ADDITIONAL_MASKED_DIRECTIONAL_SHADOWS
float2 lightmapUV:TEXCOORD6;
#endif
#if defined(DYNAMICLIGHTMAP_ON)
float2 dynamicLightmapUV: TEXCOORD7;
#endif
#if defined(CUSTOM_GEOMETRY_INTENRPOLATORS)
CUSTOM_GEOMETRY_INTERPOLATORS
#endif
};
sampler2D _MainTex, _DetailTex, _DetailMask;
float4 _MainTex_ST, _DetailTex_ST;
sampler2D _NormalMap, _DetailNormalMap;
float _BumpScale, _DetailBumpScale;
sampler2D _MetallicMap;
float _Metallic;
float _Smoothness;
sampler2D _OcclusionMap;
float _OcclusionStrength;
sampler2D _EmissionMap;
float3 _Emission;
float _Cutoff;
float GetAlpha(Interpolators i){
float alpha = UNITY_ACCESS_INSTANCED_PROP(_Color_arr, _Color).a;
#if !defined(_SMOOTHNESS_ALBEDO)
alpha *= tex2D(_MainTex, i.uv.xy).a;
#endif
return alpha;
}
float GetDetailMask(Interpolators i){
#if defined(_DETAIL_MASK)
return tex2D(_DetaiMask, i.uv.xy);
#else
return 1;
#endif
}
float3 GetAlbedo(Interpolators i){
float3 albedo = tex2D(_MainTex, i.uv.xy).rgb * UNITY_ACCESS_INSTANCED_PROP(_Color_arr, _Color).rgb;
#if defined(_DETAIL_ALBEDO_MAP)
float3 details = tex2D(_DetailTex, i.uv.zw) * unity_ColorSpaceDouble;
albedo = lerp(albedo, albedo * details, GetDetailMask(i));
#endif
return albedo;
}
float GetMetallic(Interpolators i){
#if defined(_METALLIC_MAP)
return tex2D(_MetallicMap, i.uv.xy).r;
#else
return _Metallic;
#endif
}
float GetSmoothness(Interpolators i){
float smoothness = 1;
#if defined(_SMOOTHNESS_ALBEDO)
smoothness = tex2D(_MainTex, i.uv.xy).a;
#elif defined(_SMOOTHNESS_METALLIC) && defined(_METALLIC_MAP)
smoothness = tex2D(_METALLIC_MAP, i.uv.xy).a;
#endif
return smoothness * _Smoothness;
}
float3 GetEmission(Interpolators i){
#if defined(FORWARD_BASE_PASS) || defined(DEFERRED_PASS)
#if defined(_EMISSION_MAP)
return tex2D(_EmissionMap, i.uv.xy) * _Emission;
#else
return _Emission;
#endif
#else
return 0;
#endif
}
float GetOcclusion(Interpolators i){
#if defined(_OCCLUSION_MAP)
return lerp(1, tex2D(_OCCLUSION_MAP, i.uv.xy).g, _OcclusionStrength);
#else
return 1;
#endif
}
float3 GetTangentSpaceNormal(Interpolators i){
float3 normal = float3(0, 0 , 1);
#if defined(_NORMAL_MAP)
normal = UnpackScaleNormal(tex2D(_NormalMap, i.uv.xy), _BumpScale);
#endif
#if defined(_DETAIL_NORMAL_MAP)
float3 detailNormal =
UnpackScaleNormal(
tex2D(_DetailNormalMap, i.uv.zw), _DetailBumpScale
);
detailNormal = lerp(float3(0 ,0 , 1), detailNormal, GetDetailMask(i));
normal = BlendNormals(normal , detailNormal);
#endif
return normal;
}
#endif
总结
以上就是今天要讲的内容。
边栏推荐
- ISC2022 HackingClub white hat summit countdown 1 day!Most comprehensive agenda formally announced!Yuan universe, wonderful!
- Pytorch学习记录(八):生成对抗网络GAN
- 方舟生存进化是什么游戏?好不好玩
- 数据库练习
- 记录第一次给开源项目提 PR
- shell脚本
- 回收租凭系统100%开源无加密 商城+回收+租赁
- 一个关于操作数据库的建议—用户密码
- C语言_联合体共用体引入
- C Pitfalls and Defects Chapter 7 Portability Defects 7.7 Truncation During Division
猜你喜欢
随机推荐
LeetCode·32.最长有效括号·栈·动态规划
宝塔应用使用心得
C陷阱与缺陷 附录B Koenig和Moo夫妇访谈
LeetCode·每日一题·1374.生成每种字符都是奇数个的字符串·模拟
Realize the superposition display analysis of DWG drawing with CAD in Cesium
对C语言结构体内存对齐的理解
记录第一次给开源项目提 PR
深拷贝浅拷贝
相亲模型与有限状态机
Review Set/Map basics with these two hooks
Get started with Grafana in 15 minutes
sizeof的详细解说和与strlen的区别
【力扣】字符串相乘
TP5-NPs负载噻吩类化合物TP5白蛋白纳米粒/阿魏酸钠新糖牛血清蛋白纳米粒
2022-08-01 第五小组 顾祥全 学习笔记 day25-枚举与泛型
【Jmeter常用断言组件】
C专家编程 第1章 C:穿越时空的迷雾 1.2 C语言的早期体验
AIDL通信
二分法中等 LeetCode6133. 分组的最大数量
property语法