提交 cb23623e 编写于 作者: timchen1002's avatar timchen1002

initial commit

上级
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0541bba9596b30844bd298f80ab9eed1, type: 3}
m_Name: Custom RP
m_EditorClassIdentifier:
useDynamicBatching: 0
useGPUInstancing: 1
useSRPBatcher: 1
useLightsPerObject: 0
shadows:
maxDistance: 18.92
distanceFade: 0.1
directional:
atlasSize: 4096
filter: 2
cascadeCount: 4
cascadeRatio1: 0.3
cascadeRatio2: 0.4
cascadeRatio3: 0.5
cascadeFade: 0.1
cascadeBlend: 1
other:
atlasSize: 1024
filter: 0
postFXSettings: {fileID: 11400000, guid: 803d8f754f1bc8c469121e005316f6fa, type: 2}
colorLUTResolution: 64
allowHDR: 1
fileFormatVersion: 2
guid: aedb7cce3445b224592309643d5e4de5
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: b794ab6b110571242b7f151322d2a774
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 41bef6e9187c345828b09960dd1cbfa6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using UnityEditor;
[CanEditMultipleObjects]
[CustomEditorForRenderPipeline(typeof(Light), typeof(CustomRenderPipelineAsset))]
public class CustomLightEditor : LightEditor
{
// 重写灯光Inspector面板
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (!settings.lightType.hasMultipleDifferentValues && (LightType)settings.lightType.enumValueIndex == LightType.Spot)
{
settings.DrawInnerAndOuterSpotAngle();
settings.ApplyModifiedProperties();
}
}
}
fileFormatVersion: 2
guid: 9ecbf1e5ad73cf9408d8f0804dafc43e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
/// <summary>
/// 扩展材质面板
/// </summary>
public class CustomShaderGUI : ShaderGUI
{
MaterialEditor editor;
Object[] materials;
MaterialProperty[] properties;
bool showPresents;
// 投影模式:开启投影、裁剪投影、抖动投影、关闭投影
enum ShadowMode
{
On, Clip, Dither, Off
}
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
EditorGUI.BeginChangeCheck();
base.OnGUI(materialEditor, properties);
editor = materialEditor;
materials = materialEditor.targets;
this.properties = properties;
BakedEmission();
EditorGUILayout.Space();
showPresents = EditorGUILayout.Foldout(showPresents, "Presents", true);
if (showPresents)
{
OpaquePreset();
ClipPreset();
FadePreset();
TransparentPreset();
}
// 如果材质属性有被更改,检查阴影模式的设置状态
if (EditorGUI.EndChangeCheck())
{
SetShadowCasterPass();
CopyLightMappingProperties();
}
}
void CopyLightMappingProperties()
{
MaterialProperty mainTex = FindProperty("_MainTex", properties, false);
MaterialProperty baseMap = FindProperty("_BaseMap", properties, false);
if (mainTex != null && baseMap != null) {
mainTex.textureValue = baseMap.textureValue;
mainTex.textureScaleAndOffset = baseMap.textureScaleAndOffset;
}
MaterialProperty color = FindProperty("_Color", properties, false);
MaterialProperty baseColor = FindProperty("_BaseColor", properties, false);
if (color != null && baseColor != null)
{
color.colorValue = baseColor.colorValue;
}
}
/// <summary>
/// 相关属性存在时可以设置关键字开关
/// </summary>
/// <param name="name"></param>
/// <param name="keyword"></param>
/// <param name="value"></param>
void SetProperty(string name, string keyword, bool value)
{
if (SetProperty(name, value ? 1f : 0f))
{
SetKeyword(keyword, value);
}
}
/// <summary>
/// 设置材质属性
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <returns></returns>
bool SetProperty(string name, float value)
{
MaterialProperty property = FindProperty(name, properties, false);
if (property != null)
{
property.floatValue = value;
return true;
}
return false;
}
/// <summary>
/// 设置关键字状态
/// </summary>
/// <param name="keyword"></param>
/// <param name="enabled"></param>
void SetKeyword(string keyword, bool enabled)
{
if (enabled)
{
foreach (Material m in materials)
{
m.EnableKeyword(keyword);
}
}
else
{
foreach (Material m in materials)
{
m.DisableKeyword(keyword);
}
}
}
bool Clipping
{
set => SetProperty("_Clipping", "_CLIPPING", value);
}
bool PremultiplyAlpha
{
set => SetProperty("_PremulAlpha", "_PREMULTIPLY_ALPHA", value);
}
BlendMode SrcBlend
{
set => SetProperty("_SrcBlend", (float)value);
}
BlendMode DstBlend
{
set => SetProperty("_DstBlend", (float)value);
}
bool ZWrite
{
set => SetProperty("_ZWrite", value ? 1f : 0f);
}
RenderQueue RenderQueue
{
set
{
foreach (Material m in materials)
{
m.renderQueue = (int)value;
}
}
}
// 如果shader的预乘属性不存在,不需要显示该渲染模式的按钮
bool HasProperty(string name) => FindProperty(name, properties, false) != null;
bool HasPremultiplyAlpha => HasProperty("_PremulAlpha");
bool PresetButton(string name)
{
if (GUILayout.Button(name)) {
editor.RegisterPropertyChangeUndo(name);
return true;
}
return false;
}
/// <summary>
/// 烘焙自发光
/// </summary>
void BakedEmission()
{
EditorGUI.BeginChangeCheck();
editor.LightmapEmissionProperty();
if (EditorGUI.EndChangeCheck())
{
foreach (Material m in editor.targets)
{
m.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
}
}
}
/// <summary>
/// 不透明材质默认设置
/// </summary>
void OpaquePreset()
{
if (PresetButton("Opaque"))
{
Clipping = false;
Shadows = ShadowMode.Dither;
PremultiplyAlpha = false;
SrcBlend = BlendMode.One;
DstBlend = BlendMode.Zero;
ZWrite = true;
RenderQueue = RenderQueue.Geometry;
}
}
/// <summary>
/// 裁切材质默认设置
/// </summary>
void ClipPreset()
{
if (PresetButton("Clip"))
{
Clipping = true;
Shadows = ShadowMode.Dither;
PremultiplyAlpha = false;
SrcBlend = BlendMode.One;
DstBlend = BlendMode.Zero;
ZWrite = true;
RenderQueue = RenderQueue.AlphaTest;
}
}
/// <summary>
/// 标准透明材质默认设置
/// </summary>
void FadePreset()
{
if (PresetButton("Fade"))
{
Clipping = false;
Shadows = ShadowMode.Dither;
PremultiplyAlpha = false;
SrcBlend = BlendMode.SrcAlpha;
DstBlend = BlendMode.OneMinusSrcAlpha;
ZWrite = false;
RenderQueue = RenderQueue.Transparent;
}
}
/// <summary>
/// 受光正确的透明材质默认设置
/// </summary>
void TransparentPreset()
{
if (HasPremultiplyAlpha && PresetButton("Transparent"))
{
Clipping = false;
Shadows = ShadowMode.Dither;
PremultiplyAlpha = true;
SrcBlend = BlendMode.One;
DstBlend = BlendMode.OneMinusSrcAlpha;
ZWrite = false;
RenderQueue = RenderQueue.Transparent;
}
}
ShadowMode Shadows
{
set
{
if (SetProperty("_Shadows", (float)value))
{
SetKeyword("_SHADOWS_CLIP", value == ShadowMode.Clip);
SetKeyword("_SHADOWS_DITHER", value == ShadowMode.Dither);
}
}
}
/// <summary>
/// 设置材质的ShadowCaster pass块是否启用
/// </summary>
void SetShadowCasterPass()
{
MaterialProperty shadows = FindProperty("_Shadows", properties, false);
if (shadows == null || shadows.hasMixedValue)
{
return;
}
bool enabled = shadows.floatValue < (float)ShadowMode.Off;
foreach (Material m in materials)
{
m.SetShaderPassEnabled("ShadowCaster", enabled);
}
}
}
fileFormatVersion: 2
guid: 63f209c1640cac74884a5a7d9b8a6bbb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: b08f84cadf408444798120bf37e58218
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using UnityEngine.Rendering;
/// <summary>
/// 生成1023个mesh和小球对象
/// </summary>
public class MeshBall : MonoBehaviour
{
static int baseColorId = Shader.PropertyToID("_BaseColor");
static int metallicId = Shader.PropertyToID("_Metallic");
static int smoothnessId = Shader.PropertyToID("_Smoothness");
[SerializeField]
Mesh mesh = default;
[SerializeField]
Material material = default;
[SerializeField]
LightProbeProxyVolume lightProbeVolume = null;
// 添加金属度和光滑度属性调节参数
Matrix4x4[] matrices = new Matrix4x4[1023];
Vector4[] baseColors = new Vector4[1023];
MaterialPropertyBlock block;
float[] metallic = new float[1023];
float[] smoothness = new float[1023];
void Awake()
{
for (int i = 0; i < matrices.Length; i++)
{
// 创建随机转换矩阵和颜色
matrices[i] = Matrix4x4.TRS(
Random.insideUnitSphere * 10f,
Quaternion.Euler(
Random.value * 360f, Random.value * 360f, Random.value * 360f
),
Vector3.one * Random.Range(0.5f, 1.5f)
);
baseColors[i] = new Vector4(
Random.value, Random.value, Random.value,
Random.Range(0.5f, 1f)
);
// 金属度和光滑度按条件随机
metallic[i] = Random.value < 0.25f ? 1f : 0f;
smoothness[i] = Random.Range(0.05f, 0.95f);
}
}
void Update()
{
if (block == null)
{
// 随机属性发送到着色器
block = new MaterialPropertyBlock();
block.SetVectorArray(baseColorId, baseColors);
block.SetFloatArray(metallicId, metallic);
block.SetFloatArray(smoothnessId, smoothness);
if (!lightProbeVolume)
{
var positions = new Vector3[1023];
for (int i = 0; i < matrices.Length; i++)
{
positions[i] = matrices[i].GetColumn(3);
}
var lightProbes = new SphericalHarmonicsL2[1023];
var occlusionProbes = new Vector4[1023];
LightProbes.CalculateInterpolatedLightAndOcclusionProbes(
positions, lightProbes, occlusionProbes
);
block.CopySHCoefficientArraysFrom(lightProbes);
block.CopyProbeOcclusionArrayFrom(occlusionProbes);
}
}
// 绘制网格实例
Graphics.DrawMeshInstanced(mesh, 0, material, matrices, 1023, block,
ShadowCastingMode.On, true, 0, null, lightProbeVolume ? LightProbeUsage.UseProxyVolume : LightProbeUsage.CustomProvided, lightProbeVolume);
}
}
fileFormatVersion: 2
guid: 2f4e5bddc090f46f8acfc6475bf68617
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
/// <summary>
/// 挂到同材质对象上,可以为每个对象设置不同的属性
/// </summary>
[DisallowMultipleComponent]
public class PerObjectMaterialProperties : MonoBehaviour
{
static int baseColorId = Shader.PropertyToID("_BaseColor");
static int cutoffId = Shader.PropertyToID("_Cutoff");
static int metallicId = Shader.PropertyToID("_Metallic");
static int smoothnessId = Shader.PropertyToID("_Smoothness");
static int emissionColorId = Shader.PropertyToID("_EmissionColor");
[SerializeField]
Color baseColor = Color.white;
[SerializeField, Range(0f, 1f)]
float alphaCutoff = 0.5f, metallic = 0f, smoothness = 0.5f;
[SerializeField, ColorUsage(false, true)]
Color emissionColor = Color.black;
static MaterialPropertyBlock block;
void Awake()
{
OnValidate();
}
void OnValidate()
{
if (block == null)
{
block = new MaterialPropertyBlock();
}
// 设置材质属性
block.SetColor(baseColorId, baseColor);
block.SetFloat(cutoffId, alphaCutoff);
block.SetFloat(metallicId, metallic);
block.SetFloat(smoothnessId, smoothness);
block.SetColor(emissionColorId, emissionColor);
GetComponent<Renderer>().SetPropertyBlock(block);
}
}
fileFormatVersion: 2
guid: 12b34fac330b345eea0c6df7126deddc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 183aea273daae4735ab292ef6f533100
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Profiling;
/// <summary>
/// 相机渲染管理类
/// </summary>
partial class CameraRenderer
{
partial void DrawGizmosBeforeFX();
partial void DrawGizmosAfterFX();
partial void DrawUnsupportedShaders();
#if UNITY_EDITOR
// SRP不支持的着色器标签类型
static ShaderTagId[] legacyShaderTagIds = {
new ShaderTagId("Always"),
new ShaderTagId("ForwardBase"),
new ShaderTagId("PrepassBase"),
new ShaderTagId("Vertex"),
new ShaderTagId("VertexLMRGBM"),
new ShaderTagId("VertexLM"),
};
// 绘制成使用错误材质的粉红色颜色
static Material errorMaterial;
partial void PrepareForSceneWindow();
partial void PrepareBuffer();
string sampleName { get; set; }
/// <summary>
/// 绘制SRP不支持的内置着色器
/// </summary>
partial void DrawUnsupportedShaders()
{
if (errorMaterial == null)
{
errorMaterial = new Material(Shader.Find("Hidden/InternalErrorShader"));
}
var drawingSettings = new DrawingSettings(legacyShaderTagIds[0], new SortingSettings(camera))
{
overrideMaterial = errorMaterial
};
for (int i = 1; i < legacyShaderTagIds.Length; i++)
{
drawingSettings.SetShaderPassName(i, legacyShaderTagIds[i]);
}
var fliteringSettings = FilteringSettings.defaultValue;
// 可以通过 FilteringSettings.defaultValue 属性获得默认的过滤设置
context.DrawRenderers(cullingResults, ref drawingSettings, ref fliteringSettings);
}
/// <summary>
/// 绘制Gizmos
/// </summary>
/// <returns></returns>
partial void DrawGizmosBeforeFX()
{
if (Handles.ShouldRenderGizmos())
{
context.DrawGizmos(camera, GizmoSubset.PreImageEffects);
}
}
/// <summary>
/// 绘制Gizmos
/// </summary>
/// <returns></returns>
partial void DrawGizmosAfterFX()
{
if (Handles.ShouldRenderGizmos())
{
context.DrawGizmos(camera, GizmoSubset.PostImageEffects);
}
}
/// <summary>
/// 在Game视图绘制的几何体也绘制到Scene视图中
/// </summary>
/// <returns></returns>
partial void PrepareForSceneWindow()
{
if (camera.cameraType == CameraType.SceneView)
{
// 如果切换到了Scene视图,调用次方法完成绘制
ScriptableRenderContext.EmitWorldGeometryForSceneView(camera);
}
}
/// <summary>
/// 设置buffer缓冲区的名字
/// </summary>
/// <returns></returns>
partial void PrepareBuffer()
{
// 设置只有在编辑器模式下才分配内存
Profiler.BeginSample("Editor Only");
buffer.name = camera.name;
Profiler.EndSample();
}
#else
const string sampleName = bufferName;
#endif
}
fileFormatVersion: 2
guid: ad3150bd302b9684e9244154722b4d93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using UnityEngine.Rendering;
/// <summary>
/// 相机渲染管理类:单独控制每个相机的渲染
/// </summary>
public partial class CameraRenderer
{
ScriptableRenderContext context;
Camera camera;
const string bufferName = "Render Camera";
// 创建缓冲区
CommandBuffer buffer = new CommandBuffer
{
name = bufferName
};
// 存储相机剔除后的结果
CullingResults cullingResults;
// 着色器标记ID
static ShaderTagId unlitShaderTagId = new ShaderTagId("SRPDefaultUnlit");
static ShaderTagId litShaderTagId = new ShaderTagId("CustomLit");
static int frameBufferId = Shader.PropertyToID("_CameraFrameBuffer");
Lighting lighting = new Lighting();
PostFXStack postFXStack = new PostFXStack();
bool useHDR;
/// <summary>
/// 相机渲染
/// </summary>
/// <param name="context"></param>
/// <param name="camera"></param>
/// <param name="allowHDR"></param>
/// <param name="useDynamicBatching"></param>
/// <param name="useGPUInstancing"></param>
/// <param name="useLightsPerObject"></param>
/// <param name="shadowSettings"></param>
/// <param name="postFXSettings"></param>
/// <param name="colorLUTResolution"></param>
public void Render(ScriptableRenderContext context, Camera camera, bool allowHDR, bool useDynamicBatching, bool useGPUInstancing, bool useLightsPerObject, ShadowSettings shadowSettings, PostFXSettings postFXSettings, int colorLUTResolution)
{
this.context = context;
this.camera = camera;
// 设置buffer缓冲区的名字
PrepareBuffer();
// 在Game视图绘制的几何体也绘制到Scene视图中
PrepareForSceneWindow();
if (!Cull(shadowSettings.maxDistance))
{
return;
}
useHDR = allowHDR && camera.allowHDR;
context.SetupCameraProperties(camera);
// 获得相机的clear flags
CameraClearFlags flags = camera.clearFlags;
buffer.BeginSample(sampleName);
ExecuteBuffer();
lighting.Setup(context, cullingResults, shadowSettings, useLightsPerObject);
postFXStack.Setup(context, camera, postFXSettings, useHDR, colorLUTResolution);
buffer.EndSample(sampleName);
Setup();
// 绘制可见几何体
DrawVisibleGeometry(useDynamicBatching, useGPUInstancing, useLightsPerObject);
// 绘制SRP不支持的内置shader类型
DrawUnsupportedShaders();
// 绘制Gizmos
DrawGizmosBeforeFX();
if (postFXStack.IsActive)
{
if (flags > CameraClearFlags.Color)
{
flags = CameraClearFlags.Color;
}
postFXStack.Render(frameBufferId);
}
DrawGizmosAfterFX();
Cleanup();
// 提交缓冲区
Submit();
}
/// <summary>
/// 剔除
/// </summary>
/// <returns></returns>
bool Cull(float maxShadowDistance)
{
if (camera.TryGetCullingParameters(out ScriptableCullingParameters p))
{
p.shadowDistance = Mathf.Min(maxShadowDistance, camera.farClipPlane);
cullingResults = context.Cull(ref p);
return true;
}
return false;
}
/// <summary>
/// 设置相机的属性和矩阵,在着色器中被称为unity_matrixvp
/// </summary>
void Setup()
{
context.SetupCameraProperties(camera);
// 得到相机的clearflags
CameraClearFlags flags = camera.clearFlags;
if (postFXStack.IsActive)
{
buffer.GetTemporaryRT(frameBufferId, camera.pixelWidth, camera.pixelHeight, 32, FilterMode.Bilinear, useHDR ? RenderTextureFormat.DefaultHDR: RenderTextureFormat.Default);
buffer.SetRenderTarget(frameBufferId, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
}
// 设置相机清除状态
buffer.ClearRenderTarget(flags <= CameraClearFlags.Depth, flags == CameraClearFlags.Color, flags == CameraClearFlags.Color ? camera.backgroundColor.linear : Color.clear);
buffer.BeginSample(sampleName);
ExecuteBuffer();
}
void Cleanup()
{
// 释放申请的RT内存空间
lighting.Cleanup();
if (postFXStack.IsActive)
{
buffer.ReleaseTemporaryRT(frameBufferId);
}
}
/// <summary>
/// 提交缓冲区命令
/// </summary>
void Submit()
{
buffer.EndSample(sampleName);
ExecuteBuffer();
context.Submit();
}
/// <summary>
/// 执行缓冲区命令
/// </summary>
void ExecuteBuffer()
{
context.ExecuteCommandBuffer(buffer);
buffer.Clear();
}
/// <summary>
/// 绘制可见几何体,顺序:不透明物体->天空盒->透明物体
/// </summary>
void DrawVisibleGeometry(bool useDynamicBatching, bool useGPUInstancing, bool useLightsPerObject)
{
PerObjectData lightsPerObjectFlags = useLightsPerObject ? PerObjectData.LightData | PerObjectData.LightIndices : PerObjectData.None;
// 设置绘制顺序和指定渲染相机
var sortingSettings = new SortingSettings(camera)
{
criteria = SortingCriteria.CommonOpaque
};
// 设置渲染的shader pass和渲染顺序
var drawingSettings = new DrawingSettings(unlitShaderTagId, sortingSettings)
{
enableDynamicBatching = useDynamicBatching,
enableInstancing = useGPUInstancing,
perObjectData = PerObjectData.Lightmaps | PerObjectData.ShadowMask | PerObjectData.LightProbe | PerObjectData.OcclusionProbe | PerObjectData.LightProbeProxyVolume | PerObjectData.ReflectionProbes | lightsPerObjectFlags,
};
// 渲染CustomLit表示的pass块
drawingSettings.SetShaderPassName(1, litShaderTagId);
// 只绘制RenderQueue为opaque不透明物体
var filteringSettings = new FilteringSettings(RenderQueueRange.opaque);
// 绘制不透明物体
context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
// 绘制天空盒
context.DrawSkybox(camera);
sortingSettings.criteria = SortingCriteria.CommonTransparent;
drawingSettings.sortingSettings = sortingSettings;
// 只绘制RenderQueue为transparent透明的物体
filteringSettings.renderQueueRange = RenderQueueRange.transparent;
// 绘制透明物体
context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
}
}
fileFormatVersion: 2
guid: a9e70a38f407c0e40bc30bc4ea0ec3f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Collections;
using UnityEngine;
using UnityEngine.Experimental.GlobalIllumination;
using LightType = UnityEngine.LightType;
public partial class CustomRenderPipeline
{
partial void InitializeForEditor();
#if UNITY_EDITOR
partial void InitializeForEditor()
{
Lightmapping.SetDelegate(lightsDelegate);
}
/// <summary>
/// 清理和重置委托
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Lightmapping.ResetDelegate();
}
static Lightmapping.RequestLightsDelegate lightsDelegate =
(Light[] lights, NativeArray<LightDataGI> output) => {
var lightData = new LightDataGI();
for (int i = 0; i < lights.Length; i++)
{
Light light = lights[i];
switch (light.type)
{
case LightType.Directional:
var directionalLight = new DirectionalLight();
LightmapperUtils.Extract(light, ref directionalLight);
lightData.Init(ref directionalLight);
break;
case LightType.Point:
var pointLight = new PointLight();
LightmapperUtils.Extract(light, ref pointLight);
lightData.Init(ref pointLight);
break;
case LightType.Spot:
var spotLight = new SpotLight();
LightmapperUtils.Extract(light, ref spotLight);
lightData.Init(ref spotLight);
break;
case LightType.Area:
var rectangleLight = new RectangleLight();
LightmapperUtils.Extract(light, ref rectangleLight);
rectangleLight.mode = LightMode.Baked;
lightData.Init(ref rectangleLight);
break;
default:
lightData.InitNoBake(light.GetInstanceID());
break;
}
output[i] = lightData;
}
};
#endif
}
fileFormatVersion: 2
guid: 7ba450fb5d4c1a14ba330be01e0f2f62
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using UnityEngine.Rendering;
/// <summary>
/// 自定义渲染管线实例
/// </summary>
public partial class CustomRenderPipeline : RenderPipeline
{
CameraRenderer renderer = new CameraRenderer();
bool allowHDR, useDynamicBatching, useGPUInstancing, useSRPBatcher, useLightsPerObject;
// 阴影的配置
ShadowSettings shadowSettings;
PostFXSettings postFXSettings;
int colorLUTResolution;
public CustomRenderPipeline(bool allowHDR, bool useDynamicBatching, bool useGPUInstancing, bool useSRPBatcher, bool useLightsPerObject, ShadowSettings shadowSettings, PostFXSettings postFXSettings, int colorLUTResolution)
{
this.allowHDR = allowHDR;
this.useDynamicBatching = useDynamicBatching;
this.useGPUInstancing = useGPUInstancing;
this.shadowSettings = shadowSettings;
this.useLightsPerObject = useLightsPerObject;
this.postFXSettings = postFXSettings;
this.colorLUTResolution = colorLUTResolution;
GraphicsSettings.useScriptableRenderPipelineBatching = useSRPBatcher;
// 灯光使用线性强度
GraphicsSettings.lightsUseLinearIntensity = true;
InitializeForEditor();
}
protected override void Render(ScriptableRenderContext context, Camera[] cameras)
{
// 遍历所有相机单独渲染
foreach (Camera camera in cameras)
{
renderer.Render(context, camera, allowHDR, useDynamicBatching, useGPUInstancing, useLightsPerObject, shadowSettings, postFXSettings, colorLUTResolution);
}
}
}
fileFormatVersion: 2
guid: 7801b1ecb6785ac4e879356c5121b295
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using UnityEngine.Rendering;
/// <summary>
/// 自定义渲染管线资产
/// </summary>
[CreateAssetMenu(menuName = "Rendering/Custom Render Pipeline")]
public class CustomRenderPipelineAsset : RenderPipelineAsset
{
[SerializeField]
bool useDynamicBatching = true, useGPUInstancing = true, useSRPBatcher = true;
// 是否使用逐对象光源
[SerializeField]
bool useLightsPerObject = true;
[SerializeField]
ShadowSettings shadows = default;
// 后效资产配置
[SerializeField]
PostFXSettings postFXSettings = default;
public enum ColorLUTResolution { _16 = 16, _32 = 32, _64 = 64 }
// LUT分辨率
[SerializeField]
ColorLUTResolution colorLUTResolution = ColorLUTResolution._32;
// HDR设置
[SerializeField]
bool allowHDR = true;
protected override RenderPipeline CreatePipeline()
{
return new CustomRenderPipeline(allowHDR, useDynamicBatching, useGPUInstancing, useSRPBatcher, useLightsPerObject, shadows, postFXSettings, (int)colorLUTResolution);
}
}
fileFormatVersion: 2
guid: 0541bba9596b30844bd298f80ab9eed1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using UnityEngine.Rendering;
using Unity.Collections;
/// <summary>
/// 灯光类管理
/// </summary>
public class Lighting
{
const string bufferName = "Lighting";
// 存储相机剔除后的结果
CullingResults cullingResults;
CommandBuffer buffer = new CommandBuffer{
name = bufferName
};
// 设置最大可见定向光数量
const int maxDirLightCount = 4;
static int dirLightCountId = Shader.PropertyToID("_DirectionalLightCount");
static int dirLightColorsId = Shader.PropertyToID("_DirectionalLightColors");
static int dirLightDirectionsId = Shader.PropertyToID("_DirectionalLightDirections");
static int dirLightShadowDataId = Shader.PropertyToID("_DirectionalLightShadowData");
// 存储定向光的颜色和方向
static Vector4[] dirLightColors = new Vector4[maxDirLightCount];
static Vector4[] dirLightDirections = new Vector4[maxDirLightCount];
static Vector4[] dirLightShadowData = new Vector4[maxDirLightCount];
// 设置其他类型光源的最大数量
const int maxOtherLightCount = 64;
static int otherLightCountId = Shader.PropertyToID("_OtherLightCount");
static int otherLightColorsId = Shader.PropertyToID("_OtherLightColors");
static int otherLightPositionsId = Shader.PropertyToID("_OtherLightPositions");
static int otherLightDirectionsId = Shader.PropertyToID("_OtherLightDirections");
static int otherLightSpotAnglesId = Shader.PropertyToID("_OtherLightSpotAngles");
static int otherLightShadowDataId = Shader.PropertyToID("_OtherLightShadowData");
// 存储其他类型光源的颜色和位置
static Vector4[] otherLightColors = new Vector4[maxOtherLightCount];
static Vector4[] otherLightPositions = new Vector4[maxOtherLightCount];
static Vector4[] otherLightDirections = new Vector4[maxOtherLightCount];
static Vector4[] otherLightSpotAngles = new Vector4[maxOtherLightCount];
static Vector4[] otherLightShadowData = new Vector4[maxOtherLightCount];
static string lightsPerObjectKeyword = "_LIGHTS_PER_OBJECT";
Shadows shadows = new Shadows();
/// <summary>
/// 初始化设置
/// </summary>
/// <param name="context"></param>
/// <param name="cullingResults"></param>
/// <param name="shadowSettings"></param>
public void Setup(ScriptableRenderContext context, CullingResults cullingResults, ShadowSettings shadowSettings, bool useLightsPerObject)
{
this.cullingResults = cullingResults;
buffer.BeginSample(bufferName);
// 阴影的初始化设置
shadows.Setup(context, cullingResults, shadowSettings);
// 存储并发送所有光源数据
SetupLights(useLightsPerObject);
// 渲染阴影
shadows.Render();
buffer.EndSample(bufferName);
context.ExecuteCommandBuffer(buffer);
buffer.Clear();
}
/// <summary>
/// 存储并发送所有光源数据
/// </summary>
/// <param name="useLightsPerObject"></param>
void SetupLights(bool useLightsPerObject)
{
// 得到光源索引表
NativeArray<int> indexMap = useLightsPerObject ? cullingResults.GetLightIndexMap(Allocator.Temp) : default;
// 得到所有影响相机渲染物体的可见光数据
NativeArray<VisibleLight> visibleLights = cullingResults.visibleLights;
int dirLightCount = 0, otherLightCount = 0;
int i;
for (i = 0; i < visibleLights.Length; i++)
{
int newIndex = -1;
VisibleLight visibleLight = visibleLights[i];
switch (visibleLight.lightType)
{
case LightType.Directional:
if (dirLightCount < maxDirLightCount)
{
// VisibleLight结构很大,我们改为传递引用不是传递值,这样不会生成副本
SetupDirectionalLight(dirLightCount++, i, ref visibleLight);
}
break;
case LightType.Point:
if (otherLightCount < maxOtherLightCount)
{
newIndex = otherLightCount;
SetupPointLight(otherLightCount++, i, ref visibleLight);
}
break;
case LightType.Spot:
if (otherLightCount < maxOtherLightCount)
{
newIndex = otherLightCount;
SetupSpotLight(otherLightCount++, i, ref visibleLight);
}
break;
}
if (useLightsPerObject)
{
indexMap[i] = newIndex;
}
}
// 消除所有不可见光的索引
if (useLightsPerObject)
{
for (; i < indexMap.Length; i++)
{
indexMap[i] = -1;
}
cullingResults.SetLightIndexMap(indexMap);
indexMap.Dispose();
Shader.EnableKeyword(lightsPerObjectKeyword);
}
else
{
Shader.DisableKeyword(lightsPerObjectKeyword);
}
buffer.SetGlobalInt(dirLightCountId, dirLightCount);
if (dirLightCount > 0)
{
buffer.SetGlobalVectorArray(dirLightColorsId, dirLightColors);
buffer.SetGlobalVectorArray(dirLightDirectionsId, dirLightDirections);
buffer.SetGlobalVectorArray(dirLightShadowDataId, dirLightShadowData);
}
buffer.SetGlobalInt(otherLightCountId, otherLightCount);
if (otherLightCount > 0)
{
buffer.SetGlobalVectorArray(otherLightColorsId, otherLightColors);
buffer.SetGlobalVectorArray(otherLightPositionsId, otherLightPositions);
buffer.SetGlobalVectorArray(otherLightDirectionsId, otherLightDirections);
buffer.SetGlobalVectorArray(otherLightSpotAnglesId, otherLightSpotAngles);
buffer.SetGlobalVectorArray(otherLightShadowDataId, otherLightShadowData);
}
}
/// <summary>
/// 存储定向光的数据
/// </summary>
/// <param name="index"></param>
/// <param name="visibleLight"></param>
void SetupDirectionalLight(int index, int visibleIndex, ref VisibleLight visibleLight)
{
dirLightColors[index] = visibleLight.finalColor;
// 通过VisibleLight.localToWorldMatrix属性找到前向矢量,它在矩阵第三列,还要进行取反
dirLightDirections[index] = -visibleLight.localToWorldMatrix.GetColumn(2);
// 存储阴影数据
dirLightShadowData[index] = shadows.ReserveDirectionalShadows(visibleLight.light, visibleIndex);
}
/// <summary>
/// 存储点光源的数据
/// </summary>
/// <param name="index"></param>
/// <param name="visibleLight"></param>
void SetupPointLight(int index, int visibleIndex, ref VisibleLight visibleLight)
{
otherLightColors[index] = visibleLight.finalColor;
// 位置信息在本地到世界的转换矩阵的最后一列
Vector4 position = visibleLight.localToWorldMatrix.GetColumn(3);
// 将光照范围的平方的倒数存储在光源位置的W分量中
position.w = 1f / Mathf.Max(visibleLight.range * visibleLight.range, 0.00001f);
otherLightPositions[index] = position;
otherLightSpotAngles[index] = new Vector4(0f, 1f);
Light light = visibleLight.light;
otherLightShadowData[index] = shadows.ReserveOtherShadows(light, visibleIndex);
}
/// <summary>
/// 存储聚光灯光源的数据
/// </summary>
/// <param name="index"></param>
/// <param name="visibleLight"></param>
void SetupSpotLight(int index, int visibleIndex, ref VisibleLight visibleLight)
{
otherLightColors[index] = visibleLight.finalColor;
Vector4 position = visibleLight.localToWorldMatrix.GetColumn(3);
position.w = 1f / Mathf.Max(visibleLight.range * visibleLight.range, 0.00001f);
otherLightPositions[index] = position;
// 本地到世界的转换矩阵的第三列再求反得到光照方向
otherLightDirections[index] = -visibleLight.localToWorldMatrix.GetColumn(2);
Light light = visibleLight.light;
float innerCos = Mathf.Cos(Mathf.Deg2Rad * 0.5f * light.innerSpotAngle);
float outerCos = Mathf.Cos(Mathf.Deg2Rad * 0.5f * visibleLight.spotAngle);
float angleRangeInv = 1f / Mathf.Max(innerCos - outerCos, 0.001f);
otherLightSpotAngles[index] = new Vector4(
angleRangeInv, -outerCos * angleRangeInv
);
otherLightShadowData[index] = shadows.ReserveOtherShadows(light, visibleIndex);
}
/// <summary>
/// 释放申请的RT内存
/// </summary>
public void Cleanup()
{
shadows.Cleanup();
}
}
fileFormatVersion: 2
guid: aebeb6b4a96844aeb9f722e99b5a394a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using UnityEngine;
[CreateAssetMenu(menuName = "Rendering/Custom Post FX Settings")]
public class PostFXSettings : ScriptableObject
{
[SerializeField]
Shader shader = default;
[Serializable]
public struct ColorAdjustmentsSettings
{
// 后曝光,调整场景的整体曝光度
public float postExposure;
// 对比度,扩大或缩小色调值的总体范围
[Range(-100f, 100f)]
public float contrast;
// 颜色滤镜,通过乘以颜色来给渲染器着色
[ColorUsage(false, true)]
public Color colorFilter;
// 色调偏移,改版所有颜色的色调
[Range(-180f, 180f)]
public float hueShift;
// 饱和度,推动所有颜色的强度
[Range(-100f, 100f)]
public float saturation;
}
[SerializeField]
ColorAdjustmentsSettings colorAdjustments = new ColorAdjustmentsSettings
{
colorFilter = Color.white
};
public ColorAdjustmentsSettings ColorAdjustments => colorAdjustments;
[Serializable]
public struct WhiteBalanceSettings
{
// 色温,调整白平衡的冷暖偏向
[Range(-100f, 100f)]
public float temperature;
// 色调,调整温度变化后的颜色
[Range(-100f, 100f)]
public float tint;
}
[SerializeField]
WhiteBalanceSettings whiteBalance = default;
public WhiteBalanceSettings WhiteBalance => whiteBalance;
[Serializable]
public struct SplitToningSettings
{
// 用于阴影和高光着色
[ColorUsage(false)]
public Color shadows, highlights;
// 设置阴影和高光之间的平滑的滑块
[Range(-100f, 100f)]
public float balance;
}
[SerializeField]
SplitToningSettings splitToning = new SplitToningSettings
{
shadows = Color.gray,
highlights = Color.gray,
};
public SplitToningSettings SplitToning => splitToning;
[Serializable]
public struct ChannelMixerSettings {
public Vector3 red, green, blue;
}
[SerializeField]
ChannelMixerSettings channelMixer = new ChannelMixerSettings {
red = Vector3.right,
green = Vector3.up,
blue = Vector3.forward
};
public ChannelMixerSettings ChannelMixer => channelMixer;
[Serializable]
public struct ShadowsMidtonesHighlightsSettings
{
[ColorUsage(false, true)]
public Color shadows, midtones, highlights;
[Range(0f, 2f)]
public float shadowsStart, shadowsEnd, highlightsStart, highlightsEnd;
}
[SerializeField]
ShadowsMidtonesHighlightsSettings shadowsMidtonesHighlights = new ShadowsMidtonesHighlightsSettings
{
shadows = Color.white,
midtones = Color.white,
highlights = Color.white,
shadowsEnd = 0.3f,
highlightsStart = 0.55f,
highlightsEnd = 1f,
};
public ShadowsMidtonesHighlightsSettings ShadowsMidtonesHighlights => shadowsMidtonesHighlights;
[Serializable]
public struct BloomSettings
{
[Range(0f, 16f)]
public int maxIterations;
[Min(1f)]
public int downscaleLimit;
public bool bicubicUpsampling;
[Min(0f)]
public float threshold;
[Range(0f, 1f)]
public float thresholdKnee;
[Min(0f)]
public float intensity;
// 淡化闪烁
public bool fadeFireflies;
public enum Mode { Additive, Scattering };
public Mode mode;
// 散射
[Range(0.05f, 0.95f)]
public float scatter;
}
[SerializeField]
BloomSettings bloom = new BloomSettings
{
scatter = 0.7f
};
public BloomSettings Bloom => bloom;
[System.Serializable]
public struct ToneMappingSettings
{
public enum Mode
{
None,
ACES,
Neutral,
Reinhard
};
public Mode mode;
}
[SerializeField]
ToneMappingSettings toneMapping = default;
public ToneMappingSettings ToneMapping => toneMapping;
[System.NonSerialized]
Material material;
public Material Material
{
get
{
if (material == null && shader != null)
{
material = new Material(shader);
material.hideFlags = HideFlags.HideAndDontSave;
}
return material;
}
}
}
fileFormatVersion: 2
guid: a4d5e03461da4f346a60224f8a1a6b70
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEditor;
using UnityEngine;
partial class PostFXStack
{
partial void ApplySceneViewState();
#if UNITY_EDITOR
partial void ApplySceneViewState()
{
if (camera.cameraType == CameraType.SceneView && !SceneView.currentDrawingSceneView.sceneViewState.showImageEffects)
{
postFXSettings = null;
}
}
#endif
}
\ No newline at end of file
fileFormatVersion: 2
guid: 896db44226939af439321b458d87770c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using UnityEngine.Rendering;
using static PostFXSettings;
public partial class PostFXStack
{
const string bufferName = "Post FX";
CommandBuffer buffer = new CommandBuffer
{
name = bufferName
};
ScriptableRenderContext context;
Camera camera;
PostFXSettings postFXSettings;
bool useHDR;
public bool IsActive => postFXSettings != null;
int fxSourceId = Shader.PropertyToID("_PostFXSource");
int fxSource2Id = Shader.PropertyToID("_PostFXSource2");
int bloomBucibicUpsamplingId = Shader.PropertyToID("_BloomBicubicUpsampling");
int bloomPrefilterId = Shader.PropertyToID("_BloomPrefilter");
int bloomThresholdId = Shader.PropertyToID("_BloomThreshold");
int bloomIntensityId = Shader.PropertyToID("_BloomIntensity");
int bloomResultId = Shader.PropertyToID("_BloomResult");
int colorAdjustmentsId = Shader.PropertyToID("_ColorAdjustments");
int colorFilterId = Shader.PropertyToID("_ColorFilter");
int whiteBalanceId = Shader.PropertyToID("_WhiteBalance");
int splitToningShadowId = Shader.PropertyToID("_SplitToningShadows");
int splitToningHighlightsId = Shader.PropertyToID("_SplitToningHighlights");
int channelMixerRedId = Shader.PropertyToID("_ChannelMixerRed");
int channelMixerGreenId = Shader.PropertyToID("_ChannelMixerGreen");
int channelMixerBlueId = Shader.PropertyToID("_ChannelMixerBlue");
int smhShadowsId = Shader.PropertyToID("_SMHShadows");
int smhMidtonesId = Shader.PropertyToID("_SMHMidtones");
int smhHighlightsId = Shader.PropertyToID("_SMHHighlights");
int smhRangeId = Shader.PropertyToID("_SMHRange");
int colorGradingLUTId = Shader.PropertyToID("_ColorGradingLUT");
int colorGradingLUTParametersId = Shader.PropertyToID("_ColorGradingLUTParameters");
int colorGradingLUTInLogId = Shader.PropertyToID("_ColorGradingLUTInLogC");
const int maxBloomPyramidLevels = 16;
int colorLUTResolution;
enum Pass
{
BloomAdd,
BloomHorizontal,
BloomPrefilter,
BloomPrefilterFireflies,
BloomScatter,
BloomScatterFinal,
BloomVertical,
Copy,
ColorGradingNone,
ColorGradingACES,
ColorGradingNeutural,
ColorGradingReinhard,
Final,
}
// 纹理标识符
int bloomPyramidId;
public PostFXStack()
{
bloomPyramidId = Shader.PropertyToID("_BloomPyramid0");
for (int i = 1; i < maxBloomPyramidLevels * 2; i++)
{
Shader.PropertyToID("_BloomPyramid" + i);
}
}
public void Setup(ScriptableRenderContext context, Camera camera, PostFXSettings postFXSettings, bool useHDR, int colorLUTResolution)
{
this.context = context;
this.camera = camera;
this.postFXSettings = camera.cameraType <= CameraType.SceneView ? postFXSettings : null;
this.useHDR = useHDR;
this.colorLUTResolution = colorLUTResolution;
ApplySceneViewState();
}
public void Render(int sourceId)
{
if (DoBloom(sourceId))
{
DoColorGradingAndToneMapping(bloomResultId);
buffer.ReleaseTemporaryRT(bloomResultId);
}
else
{
DoColorGradingAndToneMapping(sourceId);
}
context.ExecuteCommandBuffer(buffer);
buffer.Clear();
}
bool DoBloom(int sourceId)
{
PostFXSettings.BloomSettings bloom = postFXSettings.Bloom;
int width = camera.pixelWidth / 2, height = camera.pixelHeight / 2;
if (bloom.maxIterations == 0 || bloom.intensity <= 0f || height < bloom.downscaleLimit * 2 || width < bloom.downscaleLimit * 2)
{
return false;
}
buffer.BeginSample("Bloom");
Vector4 threshold;
threshold.x = Mathf.GammaToLinearSpace(bloom.threshold);
threshold.y = threshold.x * bloom.thresholdKnee;
threshold.z = 2f * threshold.y;
threshold.w = 0.25f / (threshold.y + 0.00001f);
threshold.y -= threshold.x;
buffer.SetGlobalVector(bloomThresholdId, threshold);
RenderTextureFormat format = useHDR ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default;
buffer.GetTemporaryRT(bloomPrefilterId, width, height, 0, FilterMode.Bilinear, format);
Draw(sourceId, bloomPrefilterId, bloom.fadeFireflies ? Pass.BloomPrefilterFireflies : Pass.BloomPrefilter);
width /= 2;
height /= 2;
int fromId = bloomPrefilterId;
int toId = bloomPyramidId + 1;
int i;
for (i = 0; i < bloom.maxIterations; i++)
{
if (height < bloom.downscaleLimit || width < bloom.downscaleLimit)
{
break;
}
int midId = toId - 1;
buffer.GetTemporaryRT(midId, width, height, 0, FilterMode.Bilinear, format);
buffer.GetTemporaryRT(toId, width, height, 0, FilterMode.Bilinear, format);
Draw(fromId, midId, Pass.BloomHorizontal);
Draw(midId, toId, Pass.BloomVertical);
fromId = toId;
toId += 2;
width /= 2;
height /= 2;
}
buffer.ReleaseTemporaryRT(bloomPrefilterId);
buffer.SetGlobalFloat(bloomBucibicUpsamplingId, bloom.bicubicUpsampling ? 1f : 0f);
Pass combinePass, finalPass;
float finalIntensity;
if (bloom.mode == PostFXSettings.BloomSettings.Mode.Additive)
{
combinePass = finalPass = Pass.BloomAdd;
buffer.SetGlobalFloat(bloomIntensityId, 1f);
finalIntensity = bloom.intensity;
}
else
{
combinePass = Pass.BloomScatter;
finalPass = Pass.BloomScatterFinal;
buffer.SetGlobalFloat(bloomIntensityId, bloom.scatter);
finalIntensity = Mathf.Min(bloom.intensity, 1f);
}
if (i > 1)
{
buffer.ReleaseTemporaryRT(fromId - 1);
toId -= 5;
for (i -= 1; i > 0; i--)
{
buffer.SetGlobalTexture(fxSource2Id, toId + 1);
Draw(fromId, toId, combinePass);
buffer.ReleaseTemporaryRT(fromId);
buffer.ReleaseTemporaryRT(toId + 1);
fromId = toId;
toId -= 2;
}
}
else
{
buffer.ReleaseTemporaryRT(bloomPyramidId);
}
buffer.SetGlobalFloat(bloomIntensityId, finalIntensity);
buffer.SetGlobalTexture(fxSource2Id, sourceId);
buffer.GetTemporaryRT(bloomResultId, camera.pixelWidth, camera.pixelHeight, 0, FilterMode.Bilinear, format);
Draw(fromId, bloomResultId, finalPass);
buffer.ReleaseTemporaryRT(fromId);
buffer.EndSample("Bloom");
return true;
}
void ConfigureColorAdjustments()
{
ColorAdjustmentsSettings colorAdjustments = postFXSettings.ColorAdjustments;
buffer.SetGlobalVector(colorAdjustmentsId, new Vector4(
Mathf.Pow(2f, colorAdjustments.postExposure),
colorAdjustments.contrast * 0.01f + 1f,
colorAdjustments.hueShift * (1f / 360f),
colorAdjustments.saturation * 0.01f + 1f
));
buffer.SetGlobalColor(colorFilterId, colorAdjustments.colorFilter.linear);
}
void ConfigureWhiteBalance()
{
WhiteBalanceSettings whiteBalance = postFXSettings.WhiteBalance;
buffer.SetGlobalVector(whiteBalanceId, ColorUtils.ColorBalanceToLMSCoeffs(whiteBalance.temperature, whiteBalance.tint));
}
void ConfigureSplitToning()
{
SplitToningSettings splitToning = postFXSettings.SplitToning;
Color splitColor = splitToning.shadows;
splitColor.a = splitToning.balance * 0.01f;
buffer.SetGlobalColor(splitToningShadowId, splitColor);
buffer.SetGlobalColor(splitToningHighlightsId, splitToning.highlights);
}
void ConfigureChannelMixer()
{
ChannelMixerSettings channelMixer = postFXSettings.ChannelMixer;
buffer.SetGlobalVector(channelMixerRedId, channelMixer.red);
buffer.SetGlobalVector(channelMixerGreenId, channelMixer.green);
buffer.SetGlobalVector(channelMixerBlueId, channelMixer.blue);
}
void ConfigureShadowsMidtonesHighlights()
{
ShadowsMidtonesHighlightsSettings smh = postFXSettings.ShadowsMidtonesHighlights;
buffer.SetGlobalColor(smhShadowsId, smh.shadows.linear);
buffer.SetGlobalColor(smhMidtonesId, smh.midtones.linear);
buffer.SetGlobalColor(smhHighlightsId, smh.highlights.linear);
buffer.SetGlobalVector(smhRangeId, new Vector4(smh.shadowsStart, smh.shadowsEnd, smh.highlightsStart, smh.highlightsEnd));
}
void DoColorGradingAndToneMapping(int sourceId)
{
ConfigureColorAdjustments();
ConfigureWhiteBalance();
ConfigureSplitToning();
ConfigureChannelMixer();
ConfigureShadowsMidtonesHighlights();
int lutHeight = colorLUTResolution;
int lutWidth = lutHeight * lutHeight;
buffer.GetTemporaryRT(colorGradingLUTId, lutWidth, lutHeight, 0, FilterMode.Bilinear, RenderTextureFormat.DefaultHDR);
buffer.SetGlobalVector(colorGradingLUTParametersId, new Vector4(lutHeight, 0.5f / lutWidth, 0.5f / lutHeight, lutHeight / (lutHeight - 1f)));
ToneMappingSettings.Mode mode = postFXSettings.ToneMapping.mode;
Pass pass = Pass.ColorGradingNone + (int)mode;
buffer.SetGlobalFloat(colorGradingLUTInLogId, useHDR && pass != Pass.ColorGradingNone ? 1f : 0f);
Draw(sourceId, colorGradingLUTId, pass);
buffer.SetGlobalVector(colorGradingLUTParametersId, new Vector4(1f / lutWidth, 1f / lutHeight, lutHeight - 1f));
Draw(sourceId, BuiltinRenderTextureType.CameraTarget, Pass.Final);
buffer.ReleaseTemporaryRT(colorGradingLUTId);
}
void Draw(RenderTargetIdentifier from, RenderTargetIdentifier to, Pass pass)
{
buffer.SetGlobalTexture(fxSourceId, from);
buffer.SetRenderTarget(to, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
buffer.DrawProcedural(Matrix4x4.identity, postFXSettings.Material, (int)pass, MeshTopology.Triangles, 3);
}
}
fileFormatVersion: 2
guid: 8af2cec1176e555499e5ce8799244643
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
/// <summary>
/// 渲染管线中的阴影配置
/// </summary>
[System.Serializable]
public class ShadowSettings
{
// 阴影最大距离
[Min(0.001f)]
public float maxDistance = 100f;
// 阴影过渡距离
[Range(0.001f, 1f)]
public float distanceFade = 0.1f;
// 阴影图集大小
public enum MapSize
{
_256 = 256, _512 = 512, _1024 = 1024, _2048 = 2048, _4096 = 4096, _8192 = 8192
}
// PCF滤波模式
public enum FilterMode
{
PCF2x2, PCF3x3, PCF5x5, PCF7x7
}
// 定向光源的阴影配置
[System.Serializable]
public struct Directional
{
public MapSize atlasSize;
public FilterMode filter;
// 级联数量
[Range(1, 4)]
public int cascadeCount;
// 级联比例
[Range(0f, 1f)]
public float cascadeRatio1, cascadeRatio2, cascadeRatio3;
public Vector3 CascadeRatios => new Vector3(cascadeRatio1, cascadeRatio2, cascadeRatio3);
// 级联过渡值
[Range(0.001f, 1f)]
public float cascadeFade;
// 级联混合模式
public enum CascadeBlendMode
{
Hard, Soft, Dither
}
public CascadeBlendMode cascadeBlend;
}
// 设置阴影配置的默认值
public Directional directional = new Directional
{
atlasSize = MapSize._1024,
filter = FilterMode.PCF2x2,
cascadeCount = 4,
cascadeRatio1 = 0.1f,
cascadeRatio2 = 0.25f,
cascadeRatio3 = 0.5f,
cascadeFade = 0.1f,
cascadeBlend = Directional.CascadeBlendMode.Hard
};
// 非定向光源的阴影配置
[System.Serializable]
public struct Other
{
public MapSize atlasSize;
public FilterMode filter;
}
// 设置阴影配置的默认值
public Other other = new Other
{
atlasSize = MapSize._1024,
filter = FilterMode.PCF2x2
};
}
fileFormatVersion: 2
guid: 40207171a73304302b2657aff37fed42
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
此差异已折叠。
fileFormatVersion: 2
guid: b5fd631dc4ef14bdc9ede96162808906
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 2db33945469a2400395335697cbf5a93
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
// BRDF相关库
#ifndef CUSTOM_BRDF_INCLUDED
#define CUSTOM_BRDF_INCLUDED
// BRDF属性
struct BRDF
{
// 漫反射
float3 diffuse;
// 镜面反射
float3 specular;
// 粗糙度
float roughness;
// 感知粗糙度
float perceptualRoughness;
// 菲涅尔反射
float fresnel;
};
// 电介质的反射率平均约0.04
#define MIN_REFLECTIVITY 0.04
// 计算不反射的值,将范围从 0-1 调整到 0-0.96,保持和URP中一样
float OneMinusReflectivity(float metallic)
{
float range = 1.0 - MIN_REFLECTIVITY;
return range - metallic * range;
}
// 获取表面的BRDF数据
BRDF GetBRDF(inout Surface surface, bool applyAlphaToDiffuse = false)
{
BRDF brdf;
float oneMinusReflectivity = OneMinusReflectivity(surface.metallic);
brdf.diffuse = surface.color * oneMinusReflectivity;
// 透明度预乘
if (applyAlphaToDiffuse)
{
brdf.diffuse *= surface.alpha;
}
brdf.specular = lerp(MIN_REFLECTIVITY, surface.color, surface.metallic);
// 光滑度转为实际粗糙度
brdf.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(surface.smoothness);
brdf.roughness = PerceptualRoughnessToRoughness(brdf.perceptualRoughness);
brdf.fresnel = saturate(surface.smoothness + 1.0 - oneMinusReflectivity);
return brdf;
}
// 根据公式得到镜面反射强度
float SpecularStrength(Surface surface, BRDF brdf, Light light)
{
float3 h = SafeNormalize(light.direction + surface.viewDirection);
float nh2 = Square(saturate(dot(surface.normal, h)));
float lh2 = Square(saturate(dot(light.direction, h)));
float r2 = Square(brdf.roughness);
float d2 = Square(nh2 * (r2 - 1.0) + 1.00001);
float normalization = brdf.roughness * 4.0 + 2.0;
return r2 / (d2 * max(0.1, lh2) * normalization);
}
// 获取基于BRDF的直接照明
float3 DirectBRDF (Surface surface, BRDF brdf, Light light)
{
return SpecularStrength(surface, brdf, light) * brdf.specular + brdf.diffuse;
}
// 获取基于BRDF的间接照明
float3 IndirectBRDF(Surface surface, BRDF brdf, float3 diffuse, float3 specular)
{
float fresnelStrength = surface.fresnelStrength * Pow4(1.0 - saturate(dot(surface.normal, surface.viewDirection)));
float3 reflection = specular * lerp(brdf.specular, brdf.fresnel, fresnelStrength);
reflection /= brdf.roughness * brdf.roughness + 1.0;
return (diffuse * brdf.diffuse + reflection) * surface.occlusion;
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: dda9dd1e15e8efa44b7b4c6c80775bd8
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
// 公共方法库
#ifndef CUSTOM_COMMON_INCLUDED
#define CUSTOM_COMMON_INCLUDED
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
#include "UnityInput.hlsl"
// 定义一些宏取代常用的转换矩阵
#define UNITY_MATRIX_M unity_ObjectToWorld
#define UNITY_MATRIX_I_M unity_WorldToObject
#define UNITY_MATRIX_V unity_MatrixV
#define UNITY_MATRIX_VP unity_MatrixVP
#define UNITY_MATRIX_P glstate_matrix_projection
#if defined(_SHADOW_MASK_ALWAYS) || defined(_SHADOW_MASK_DISTANCE)
#define SHADOWS_SHADOWMASK
#endif
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl"
// 获取值的平方
float Square(float x)
{
return x * x;
}
// 计算两点间距离的平方
float DistanceSquared(float3 pA, float3 pB)
{
return dot(pA - pB, pA - pB);
}
// 计算LOD裁剪
void ClipLOD(float2 positionCS, float fade)
{
#if defined(LOD_FADE_CROSSFADE)
float dither = InterleavedGradientNoise(positionCS.xy, 0);
clip(fade + (fade < 0.0 ? dither : -dither));
#endif
}
// 解码法线数据,得到原来的发现向量
float3 DecodeNormal(float4 sample, float scale)
{
#if defined(UNITY_NO_DXT5nm)
return UnpackNormalRGB(sample, scale);
#else
return UnpackNormalmapRGorAG(sample, scale);
#endif
}
// 将发现从切线空间转换到世界空间
float3 NormalTangentToWorld(float3 normalTS, float3 normalWS, float4 tangentWS)
{
// 构建切线到世界空间的转换矩阵,需要世界空间的法线、世界空间的切线的XYZ和W分量
float3x3 tangentToWorld = CreateTangentToWorld(normalWS, tangentWS.xyz, tangentWS.w);
return TransformTangentToWorld(normalTS, tangentToWorld);
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 8affe3d00ecf5d04ebb205a1b24c2dce
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
// 全局照明相关库
#ifndef CUSTOM_GI_INCLUDED
#define CUSTOM_GI_INCLUDED
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl"
TEXTURE2D(unity_Lightmap);
SAMPLER(samplerunity_Lightmap);
TEXTURE3D_FLOAT(unity_ProbeVolumeSH);
SAMPLER(samplerunity_ProbeVolumeSH);
TEXTURE2D(unity_ShadowMask);
SAMPLER(samplerunity_ShadowMask);
TEXTURECUBE(unity_SpecCube0);
SAMPLER(samplerunity_SpecCube0);
// 当需要渲染光照贴图对象时
#if defined(LIGHTMAP_ON)
#define GI_ATTRIBUTE_DATA float2 lightMapUV : TEXCOORD1;
#define GI_VARYINGS_DATA float2 lightMapUV : VAR_LIGHT_MAP_UV;
#define TRANSFER_GI_DATA(input, output) output.lightMapUV = input.lightMapUV * unity_LightmapST.xy + unity_LightmapST.zw;
#define GI_FRAGMENT_DATA(input) input.lightMapUV
#else
// 否则这些宏都为空`
#define GI_ATTRIBUTE_DATA
#define GI_VARYINGS_DATA
#define TRANSFER_GI_DATA(input, output)
#define GI_FRAGMENT_DATA(input) 0.0
#endif
struct GI
{
// 漫反射颜色
float3 diffuse;
// 镜面反射颜色
float3 specular;
ShadowMask shadowMask;
};
// 采样光照贴图
float3 SampleLightMap(float2 lightMapUV)
{
#if defined(LIGHTMAP_ON)
return SampleSingleLightmap(
TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap), lightMapUV,
float4(1.0, 1.0, 0.0, 0.0),
#if defined(UNITY_LIGHTMAP_FULL_HDR)
false,
#else
true,
#endif
float4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0, 0.0)
);
#else
return 0.0;
#endif
}
// 采样光照探针
float3 SampleLightProbe(Surface surfaceWS)
{
#if defined(LIGHTMAP_ON)
return 0.0;
#else
// 判断是否使用LPPV或差值光照探针
if (unity_ProbeVolumeParams.x)
{
return SampleProbeVolumeSH4(
TEXTURE3D_ARGS(unity_ProbeVolumeSH, samplerunity_ProbeVolumeSH),
surfaceWS.position, surfaceWS.normal,
unity_ProbeVolumeWorldToObject,
unity_ProbeVolumeParams.y, unity_ProbeVolumeParams.z,
unity_ProbeVolumeMin.xyz, unity_ProbeVolumeSizeInv.xyz
);
}
else
{
float4 coefficients[7];
coefficients[0] = unity_SHAr;
coefficients[1] = unity_SHAg;
coefficients[2] = unity_SHAb;
coefficients[3] = unity_SHBr;
coefficients[4] = unity_SHBg;
coefficients[5] = unity_SHBb;
coefficients[6] = unity_SHC;
return max(0.0, SampleSH9(coefficients, surfaceWS.normal));
}
#endif
}
// 采样灯光遮挡探针
float4 SampleLightProbeOcclusion()
{
return unity_ProbesOcclusion;
}
// 采样shadowMask得到烘焙阴影数据
float4 SampleBakedShadows(float2 lightMapUV, Surface surfaceWS)
{
#if defined(LIGHTMAP_ON)
return SAMPLE_TEXTURE2D(unity_ShadowMask, samplerunity_ShadowMask, lightMapUV);
#else
if (unity_ProbeVolumeParams.x) {
return SampleProbeOcclusion(
TEXTURE3D_ARGS(unity_ProbeVolumeSH, samplerunity_ProbeVolumeSH),
surfaceWS.position, unity_ProbeVolumeWorldToObject,
unity_ProbeVolumeParams.y, unity_ProbeVolumeParams.z,
unity_ProbeVolumeMin.xyz, unity_ProbeVolumeSizeInv.xyz
);
}
else {
return unity_ProbesOcclusion;
}
#endif
}
// 采样环境立方体纹理
float3 SampleEnvironment(Surface surfaceWS, BRDF brdf)
{
float3 uvw = reflect(-surfaceWS.viewDirection, surfaceWS.normal);
float mip = PerceptualRoughnessToMipmapLevel(brdf.perceptualRoughness);
float4 environment = SAMPLE_TEXTURECUBE_LOD(
unity_SpecCube0, samplerunity_SpecCube0, uvw, mip
);
return DecodeHDREnvironment(environment, unity_SpecCube0_HDR);
}
GI GetGI(float2 lightMapUV, Surface surfaceWS, BRDF brdf)
{
GI gi;
gi.diffuse = SampleLightMap(lightMapUV) + SampleLightProbe(surfaceWS);
gi.specular = SampleEnvironment(surfaceWS, brdf);
gi.shadowMask.always = false;
gi.shadowMask.distance = false;
gi.shadowMask.shadows = 1.0;
#if defined(_SHADOW_MASK_ALWAYS)
gi.shadowMask.always = true;
gi.shadowMask.shadows = SampleBakedShadows(lightMapUV, surfaceWS);
#elif defined(_SHADOW_MASK_DISTANCE)
gi.shadowMask.distance = true;
gi.shadowMask.shadows = SampleBakedShadows(lightMapUV, surfaceWS);
#endif
return gi;
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 172451413b465f34786bae0116837245
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
// 灯光数据相关库
#ifndef CUSTOM_LIGHT_INCLUDED
#define CUSTOM_LIGHT_INCLUDED
#define MAX_DIRECTIONAL_LIGHT_COUNT 4
#define MAX_OTHER_LIGHT_COUNT 64
CBUFFER_START(_CustomLight)
int _DirectionalLightCount;
// 定向光源颜色、方向、阴影等数据
float4 _DirectionalLightColors[MAX_DIRECTIONAL_LIGHT_COUNT];
float4 _DirectionalLightDirections[MAX_DIRECTIONAL_LIGHT_COUNT];
float4 _DirectionalLightShadowData[MAX_DIRECTIONAL_LIGHT_COUNT];
int _OtherLightCount;
// 非定向光源颜色,位置等数据
float4 _OtherLightColors[MAX_OTHER_LIGHT_COUNT];
float4 _OtherLightPositions[MAX_OTHER_LIGHT_COUNT];
float4 _OtherLightDirections[MAX_OTHER_LIGHT_COUNT];
float4 _OtherLightSpotAngles[MAX_OTHER_LIGHT_COUNT];
float4 _OtherLightShadowData[MAX_OTHER_LIGHT_COUNT];
CBUFFER_END
// 灯光的属性
struct Light
{
// 颜色
float3 color;
// 方向
float3 direction;
float attenuation;
};
// 获取方向光源的数量
int GetDirectionalLightCount()
{
return _DirectionalLightCount;
}
int GetOtherLightCount()
{
return _OtherLightCount;
}
// 获取定向光源的阴影数据
DirectionalShadowData GetDirectionalShadowData(int lightIndex, ShadowData shadowData)
{
DirectionalShadowData data;
data.strength = _DirectionalLightShadowData[lightIndex].x;
data.tileIndex = _DirectionalLightShadowData[lightIndex].y + shadowData.cascadeIndex;
data.normalBias = _DirectionalLightShadowData[lightIndex].z;
data.shadowMaskChannel = _DirectionalLightShadowData[lightIndex].w;
return data;
}
// 获取其他光源的阴影数据
OtherShadowData GetOtherShadowData(int lightIndex)
{
OtherShadowData data;
data.strength = _OtherLightShadowData[lightIndex].x;
data.tileIndex = _OtherLightShadowData[lightIndex].y;
data.shadowMaskChannel = _OtherLightShadowData[lightIndex].w;
data.isPoint = _OtherLightShadowData[lightIndex].z == 1.0;
data.lightPositionWS = 0.0;
data.lightDirectionWS = 0.0;
data.spotDirectionWS = 0.0;
return data;
}
// 获取指定索引定向光源数据
Light GetDirectionalLight(int index, Surface surfaceWS, ShadowData shadowData)
{
Light light;
light.color = _DirectionalLightColors[index].rgb;
light.direction = _DirectionalLightDirections[index].xyz;
DirectionalShadowData dirShadowData = GetDirectionalShadowData(index, shadowData);
light.attenuation = GetDirectionalShadowAttenuation(dirShadowData, shadowData, surfaceWS);
return light;
}
// 获取指定索引的非定向光源数据
Light GetOtherLight(int index, Surface surfaceWS, ShadowData shadowData)
{
Light light;
light.color = _OtherLightColors[index].rgb;
float3 position = _OtherLightPositions[index].xyz;
float3 ray = position - surfaceWS.position;
light.direction = normalize(ray);
// 光照强度随距离衰减
float distanceSqr = max(dot(ray, ray), 0.00001);
// 套用公式计算随光照范围衰减
float rangeAttenuation = Square(saturate(1.0 - Square(distanceSqr * _OtherLightPositions[index].w)));
// 获得聚光灯角度
float4 spotAngles = _OtherLightSpotAngles[index];
// 聚光灯方向
float3 spotDirection = _OtherLightDirections[index].xyz;
// 计算聚光灯衰减值
float spotAttenuation = Square(saturate(dot(spotDirection, light.direction) * spotAngles.x + spotAngles.y));
OtherShadowData otherShadowData = GetOtherShadowData(index);
otherShadowData.lightPositionWS = position;
otherShadowData.lightDirectionWS = light.direction;
otherShadowData.spotDirectionWS = spotDirection;
// 光照强度随范围和距离衰减
light.attenuation = GetOtherShadowAttenuation(otherShadowData, shadowData, surfaceWS) * spotAttenuation * rangeAttenuation / distanceSqr;
return light;
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 02fdfa9fa783df346a5e57ca14275e5e
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
// 光照计算相关库
#ifndef CUSTOM_LIGHTING_INCLUDED
#define CUSTOM_LIGHTING_INCLUDED
// 计算入射光照
float3 IncomingLight(Surface surface, Light light)
{
return saturate(dot(surface.normal, light.direction) * light.attenuation) * light.color;
}
// 入射光乘以光照照射到表面的直接照明颜色,得到最终的照明颜色
float3 GetLighting(Surface surface, BRDF brdf, Light light)
{
return IncomingLight(surface, light) * DirectBRDF(surface, brdf, light);
}
// 根据物体的表面信息和灯光属性获取最终光照结果
float3 GetLighting(Surface surfaceWS, BRDF brdf, GI gi)
{
// 得到表面阴影数据
ShadowData shadowData = GetShadowData(surfaceWS);
shadowData.shadowMask = gi.shadowMask;
// 可见光的光照结果进行累加得到最终光照结果
float3 color = IndirectBRDF(surfaceWS, brdf, gi.diffuse, gi.specular);
for (int i = 0; i < GetDirectionalLightCount(); i++)
{
Light light = GetDirectionalLight(i, surfaceWS, shadowData);
color += GetLighting(surfaceWS, brdf, light);
}
#if defined(_LIGHTS_PER_OBJECT)
for (int j = 0; j < min(unity_LightData.y, 8); j++)
{
int lightIndex = unity_LightIndices[(uint)j / 4][(uint)j % 4];
Light light = GetOtherLight(lightIndex, surfaceWS, shadowData);
color += GetLighting(surfaceWS, brdf, light);
}
#else
for (int j = 0; j < GetOtherLightCount(); j++)
{
Light light = GetOtherLight(j, surfaceWS, shadowData);
color += GetLighting(surfaceWS, brdf, light);
}
#endif
return color;
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: a6c7860b1963c2a4983cfc471820dbfd
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
// 阴影采样相关库
#ifndef CUSTOM_SHADOWS_INCLUDED
#define CUSTOM_SHADOWS_INCLUDED
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl"
// 如果使用的是PCF 3X3
#if defined(_DIRECTIONAL_PCF3)
// 需要4个过滤器样本
#define DIRECTIONAL_FILTER_SAMPLES 4
#define DIRECTIONAL_FILTER_SETUP SampleShadow_ComputeSamples_Tent_3x3
#elif defined(_DIRECTIONAL_PCF5)
#define DIRECTIONAL_FILTER_SAMPLES 9
#define DIRECTIONAL_FILTER_SETUP SampleShadow_ComputeSamples_Tent_5x5
#elif defined(_DIRECTIONAL_PCF7)
#define DIRECTIONAL_FILTER_SAMPLES 16
#define DIRECTIONAL_FILTER_SETUP SampleShadow_ComputeSamples_Tent_7x7
#endif
#if defined(_OTHER_PCF3)
#define OTHER_FILTER_SAMPLES 4
#define OTHER_FILTER_SETUP SampleShadow_ComputeSamples_Tent_3x3
#elif defined(_OTHER_PCF5)
#define OTHER_FILTER_SAMPLES 9
#define OTHER_FILTER_SETUP SampleShadow_ComputeSamples_Tent_5x5
#elif defined(_OTHER_PCF7)
#define OTHER_FILTER_SAMPLES 16
#define OTHER_FILTER_SETUP SampleShadow_ComputeSamples_Tent_7x7
#endif
#define MAX_SHADOWED_DIRECTIONAL_LIGHT_COUNT 4
#define MAX_SHADOWED_OTHER_LIGHT_COUNT 16
#define MAX_CASCADE_COUNT 4
// 阴影图集
TEXTURE2D_SHADOW(_DirectionalShadowAtlas);
TEXTURE2D_SHADOW(_OtherShadowAtlas);
#define SHADOW_SAMPLER sampler_linear_clamp_compare
SAMPLER_CMP(SHADOW_SAMPLER);
CBUFFER_START(_CustomShadows)
// 级联数量
int _CascadeCount;
// 级联包围球数据
float4 _CascadeCullingSpheres[MAX_CASCADE_COUNT];
// 级联数据
float4 _CascadeData[MAX_CASCADE_COUNT];
// 定向光阴影转换矩阵
float4x4 _DirectionalShadowMatrices[MAX_SHADOWED_DIRECTIONAL_LIGHT_COUNT * MAX_CASCADE_COUNT];
// 非定向光阴影转换矩阵
float4x4 _OtherShadowMatrices[MAX_SHADOWED_OTHER_LIGHT_COUNT];
float4 _OtherShadowTiles[MAX_SHADOWED_OTHER_LIGHT_COUNT];
// 图集大小
float4 _ShadowAtlasSize;
// 阴影过渡距离
float4 _ShadowDistanceFade;
CBUFFER_END
// 烘焙阴影数据
struct ShadowMask
{
bool always;
bool distance;
float4 shadows;
};
// 获取烘焙阴影的衰减值
float GetBakedShadow(ShadowMask mask, int channel)
{
float shadow = 1.0;
if (mask.always || mask.distance)
{
if (channel > 0)
{
shadow = mask.shadows[channel];
}
}
return shadow;
}
// 获取烘焙阴影的衰减值
float GetBakedShadow(ShadowMask mask, int channel, float strength)
{
if (mask.always || mask.distance)
{
return lerp(1.0, GetBakedShadow(mask, channel), strength);
}
return 1.0;
}
// 表面的阴影数据
struct ShadowData
{
int cascadeIndex;
// 是否采样阴影的标识
float strength;
// 混合级联
float cascadeBlend;
ShadowMask shadowMask;
};
// 混合烘焙和实时阴影
float MixBakedAndRealtimeShadows(ShadowData global, float shadow, int shadowMaskChannel, float strength)
{
float baked = GetBakedShadow(global.shadowMask, shadowMaskChannel);
if (global.shadowMask.always)
{
shadow = lerp(1.0, shadow, global.strength);
shadow = min(baked, shadow);
return lerp(1.0, shadow, strength);
}
if (global.shadowMask.distance)
{
shadow = lerp(baked, shadow, global.strength);
return lerp(1.0, shadow, strength);
}
return lerp(1.0, shadow, strength * global.strength);
}
// 公式计算阴影过渡时的强度
float FadedShadowStrength(float distance, float scale, float fade)
{
return saturate((1.0 - distance * scale) * fade);
}
// 获取世界空间的表面阴影数据
ShadowData GetShadowData(Surface surfaceWS)
{
ShadowData data;
data.shadowMask.always= false;
data.shadowMask.distance = false;
data.shadowMask.shadows = 1.0;
data.cascadeBlend = 1.0;
data.strength = FadedShadowStrength(surfaceWS.depth, _ShadowDistanceFade.x, _ShadowDistanceFade.y);
int i;
// 如果物体表面到球心的平方距离小于球体半径的平方,就说明该物体在这层级联包围球中,得到合适的级联层级索引
for (i = 0; i < _CascadeCount; i++)
{
float4 sphere = _CascadeCullingSpheres[i];
float distanceSqr = DistanceSquared(surfaceWS.position, sphere.xyz);
if (distanceSqr < sphere.w)
{
// 计算级联阴影的过度强度
float fade = FadedShadowStrength(distanceSqr, _CascadeData[i].x, _ShadowDistanceFade.z);
// 如果超出最大级联范围且级联数量大于0,将全局阴影强度设为0(不进行阴影采样)
if (i == _CascadeCount - 1)
{
data.strength *= fade;
}
else
{
data.cascadeBlend = fade;
}
break;
}
}
// 如果超出级联层数,不进行阴影采样
if (i == _CascadeCount && _CascadeCount > 0)
{
data.strength = 0.0;
}
#if defined(_CASCADE_BLEND_DITHER)
else if (data.cascadeBlend < surfaceWS.dither)
{
i += 1;
}
#endif
#if !defined(_CASCADE_BLEND_SOFT)
data.cascadeBlend = 1.0;
#endif
data.cascadeIndex = i;
return data;
}
// 定向光阴影的数据信息
struct DirectionalShadowData
{
float strength;
int tileIndex;
// 法线偏差
float normalBias;
int shadowMaskChannel;
};
// 采样定向光源阴影图集
float SampleDirectionalShadowAtlas(float3 positionSTS)
{
return SAMPLE_TEXTURE2D_SHADOW(_DirectionalShadowAtlas, SHADOW_SAMPLER, positionSTS);
}
// PCF滤波采样定向光阴影
float FilterDirectionalShadow(float3 positionSTS)
{
#if defined(DIRECTIONAL_FILTER_SETUP)
// 样本权重
real weights[DIRECTIONAL_FILTER_SAMPLES];
// 样本位置
real2 positions[DIRECTIONAL_FILTER_SAMPLES];
float4 size = _ShadowAtlasSize.yyxx;
DIRECTIONAL_FILTER_SETUP(size, positionSTS.xy, weights, positions);
float shadow = 0;
for (int i = 0; i < DIRECTIONAL_FILTER_SAMPLES; i++)
{
// 遍历所有样本滤波得到权重和
shadow += weights[i] * SampleDirectionalShadowAtlas(
float3(positions[i].xy, positionSTS.z)
);
}
return shadow;
#else
return SampleDirectionalShadowAtlas(positionSTS);
#endif
}
// 获取级联阴影
float GetCascadedShadow(DirectionalShadowData directional, ShadowData global, Surface surfaceWS)
{
// 计算法线偏移
float3 normalBias = surfaceWS.interpolatedNormal * (directional.normalBias * _CascadeData[global.cascadeIndex].y);
float3 positionSTS = mul(
_DirectionalShadowMatrices[directional.tileIndex],
float4(surfaceWS.position + normalBias, 1.0)
).xyz;
float shadow = FilterDirectionalShadow(positionSTS);
// 如果级联混合小于1代表在级联层级过渡区域中,必须从下一个级联中采样并在两个值之间进行插值
if (global.cascadeBlend < 1.0)
{
normalBias = surfaceWS.interpolatedNormal * (directional.normalBias * _CascadeData[global.cascadeBlend + 1].y);
positionSTS = mul(
_DirectionalShadowMatrices[directional.tileIndex + 1],
float4(surfaceWS.position + normalBias, 1.0)
).xyz;
shadow = lerp(FilterDirectionalShadow(positionSTS), shadow, global.cascadeBlend);
}
return shadow;
}
// 获取定向光阴影的衰减
float GetDirectionalShadowAttenuation(DirectionalShadowData directional, ShadowData global, Surface surfaceWS)
{
// 如果不接受阴影,阴影衰减为1
#if !defined(_RECEIVE_SHADOWS)
return 1.0;
#endif
float shadow;
if (directional.strength * global.strength <= 0.0)
{
shadow = GetBakedShadow(global.shadowMask, directional.shadowMaskChannel, abs(directional.strength));
}
else
{
shadow = GetCascadedShadow(directional, global, surfaceWS);
// 最终衰减结果是阴影强度和采样衰减的线性差值
shadow = MixBakedAndRealtimeShadows(global, shadow, directional.shadowMaskChannel, directional.strength);
}
return shadow;
}
// 非定向光阴影的数据信息
struct OtherShadowData
{
float strength;
int tileIndex;
bool isPoint;
int shadowMaskChannel;
float3 lightPositionWS;
float3 lightDirectionWS;
float3 spotDirectionWS;
};
// 采样非定向光源阴影图集
float SampleOtherShadowAtlas(float3 positionSTS, float3 bounds)
{
positionSTS.xy = clamp(positionSTS.xy, bounds.xy, bounds.xy + bounds.z);
return SAMPLE_TEXTURE2D_SHADOW(_OtherShadowAtlas, SHADOW_SAMPLER, positionSTS);
}
// PCF滤波采样非定向光阴影
float FilterOtherShadow(float3 positionSTS, float3 bonuds)
{
#if defined(OTHER_FILTER_SETUP)
// 样本权重
real weights[OTHER_FILTER_SAMPLES];
// 样本位置
real2 positions[OTHER_FILTER_SAMPLES];
float4 size = _ShadowAtlasSize.wwzz;
OTHER_FILTER_SETUP(size, positionSTS.xy, weights, positions);
float shadow = 0;
for (int i = 0; i < OTHER_FILTER_SAMPLES; i++)
{
// 遍历所有样本滤波得到权重和
shadow += weights[i] * SampleOtherShadowAtlas(
float3(positions[i].xy, positionSTS.z), bonuds
);
}
return shadow;
#else
return SampleOtherShadowAtlas(positionSTS, bonuds);
#endif
}
static const float3 pointShadowPlanes[6] =
{
float3(-1.0, 0.0, 0.0),
float3(1.0, 0.0, 0.0),
float3(0.0, -1.0, 0.0),
float3(0.0, 1.0, 0.0),
float3(0.0, 0.0, -1.0),
float3(0.0, 0.0, 1.0)
};
// 获得非定向光源的阴影强度
float GetOtherShadow(OtherShadowData other, ShadowData global, Surface surfaceWS)
{
float tileIndex = other.tileIndex;
float3 lightPlane = other.spotDirectionWS;
if (other.isPoint)
{
float faceOffset = CubeMapFaceID(-other.lightDirectionWS);
tileIndex += faceOffset;
lightPlane = pointShadowPlanes[faceOffset];
}
float4 tileData = _OtherShadowTiles[tileIndex];
float3 surfaceToLight = other.lightPositionWS - surfaceWS.position;
float distanceToLightPlane = dot(surfaceToLight, lightPlane);
float3 normalBias = surfaceWS.interpolatedNormal * (distanceToLightPlane * tileData.w);
float4 positionSTS = mul(_OtherShadowMatrices[tileIndex], float4(surfaceWS.position + normalBias, 1.0));
return FilterOtherShadow(positionSTS.xyz / positionSTS.w, tileData.xyz);
}
// 获取非定向光源的阴影衰减
float GetOtherShadowAttenuation(OtherShadowData other, ShadowData global, Surface surfaceWS)
{
#if !defined(_RECEIVE_SHADOWS)
return 1.0;
#endif
float shadow;
if (other.strength * global.strength <= 0.0)
{
shadow = GetBakedShadow(global.shadowMask, other.shadowMaskChannel, abs(other.strength));
}
else
{
shadow = GetOtherShadow(other, global, surfaceWS);
shadow = MixBakedAndRealtimeShadows(global, shadow, other.shadowMaskChannel, other.strength);
}
return shadow;
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: c7d5fcbd6bd13b04da4785c60ca22495
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
// 表面信息相关库
#ifndef CUSTOM_SURFACE_INCLUDED
#define CUSTOM_SURFACE_INCLUDED
struct Surface
{
// 表面位置坐标
float3 position;
float3 normal;
float3 interpolatedNormal;
float3 viewDirection;
// 表面深度
float depth;
float3 color;
float alpha;
float metallic;
float smoothness;
// 抖动属性
float dither;
// 菲涅尔反射强度
float fresnelStrength;
// 遮挡数据
float occlusion;
};
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: ab8dce4b88eb72c4897fa48126f98ebd
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
// Unity标准输入库
#ifndef CUSTOM_UNITY_INPUT_INCLUDED
#define CUSTOM_UNITY_INPUT_INCLUDED
CBUFFER_START(UnityPerDraw)
float4x4 unity_ObjectToWorld;
float4x4 unity_WorldToObject;
float4 unity_LODFade;
// 这个矩阵包含一些在这里我们不需要的转换信息
real4 unity_WorldTransformParams;
real4 unity_LightData;
real4 unity_LightIndices[2];
float4 unity_ProbesOcclusion;
float4 unity_SpecCube0_HDR;
float4 unity_LightmapST;
float4 unity_DynamicLightmapST;
float4 unity_SHAr;
float4 unity_SHAg;
float4 unity_SHAb;
float4 unity_SHBr;
float4 unity_SHBg;
float4 unity_SHBb;
float4 unity_SHC;
float4 unity_ProbeVolumeParams;
float4x4 unity_ProbeVolumeWorldToObject;
float4 unity_ProbeVolumeSizeInv;
float4 unity_ProbeVolumeMin;
CBUFFER_END
float4x4 unity_MatrixVP;
float4x4 unity_MatrixV;
float4x4 glstate_matrix_projection;
// 相机位置
float3 _WorldSpaceCameraPos;
float4 _ProjectionParams;
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 963698e3dc3a5284994ab2ea9c2877d1
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 725b9a301060546ae912eb515a7d91c7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Shader "Custom RP/Lit"
{
Properties
{
_BaseMap("Texture", 2D) = "white" {}
_BaseColor("Color", Color) = (0.5, 0.5, 0.5, 1.0)
// 透明度测试的阈值
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
[Toggle(_CLIPPING)] _Clipping ("Alpha Clipping", Float) = 0
// 是否接受投影
[Toggle(_RECEIVE_SHADOWS)] _ReceiveShadows ("Receive Shadows", Float) = 1
// 阴影模式
[KeywordEnum(On, Clip, Dither, Off)] _Shadows ("Shadows", Float) = 0
// 是否使用遮罩纹理
[Toggle(_MASK_MAP)] _MaskMapToggle ("Mask Map", Float) = 0
// 遮罩纹理
[NoScaleOffset] _MaskMap("Mask (MODS)", 2D) = "white" {}
// 金属度
_Metallic("Metallic", Range(0, 1)) = 0
// 遮挡强度
_Occlusion ("Occlusion", Range(0, 1)) = 1
// 光滑度
_Smoothness("Smoothness", Range(0, 1)) = 0.5
// 菲涅尔反射强度
_Fresnel ("Fresnel", Range(0, 1)) = 1
// 是否使用法线纹理
[Toggle(_NORMAL_MAP)] _NormalMapToggle ("Normal Map", Float) = 0
// 法线贴图
[NoScaleOffset] _NormalMap("Normals", 2D) = "bump" {}
_NormalScale("Normal Scale", Range(0, 1)) = 1
// 自发光
[NoScaleOffset] _EmissionMap("Emission", 2D) = "white" {}
[HDR] _EmissionColor("Emission", Color) = (0.0, 0.0, 0.0, 0.0)
// 是否使用细节纹理
[Toggle(_DETAIL_MAP)] _DetailMapToggle ("Detail Maps", Float) = 0
// 细节纹理
_DetailMap("Details", 2D) = "linearGrey" {}
// 细节法线纹理
[NoScaleOffset] _DetailNormalMap("Detail Normals", 2D) = "bump" {}
// 细节反照度
_DetailAlbedo("Detail Albedo", Range(0, 1)) = 1
// 细节光滑度
_DetailSmoothness("Detail Smoothness", Range(0, 1)) = 1
// 细节法线强度
_DetailNormalScale("Detail Normal Scale", Range(0, 1)) = 1
// 透明通道预乘
[Toggle(_PREMULTIPLY_ALPHA)] _PremulAlpha("Premultiply Alpha", Float) = 0
// 设置混合模式
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend", Float) = 1
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Dst Blend", Float) = 0
// 默认写入深度缓冲区
[Enum(Off, 0, On, 1)] _ZWrite ("Z Write", Float) = 1
[HideInInspector] _MainTex("Texture for Lightmap", 2D) = "white" {}
[HideInInspector] _Color("Color for Lightmap", Color) = (0.5, 0.5, 0.5, 1.0)
}
SubShader
{
HLSLINCLUDE
#include "../ShaderLibrary/Common.hlsl"
#include "LitInput.hlsl"
ENDHLSL
Pass
{
Tags
{
"LightMode" = "CustomLit"
}
// 定义混合模式
Blend [_SrcBlend] [_DstBlend]
// 是否写入深度
ZWrite [_ZWrite]
HLSLPROGRAM
#pragma target 3.5
#pragma shader_feature _CLIPPING
#pragma shader_feature _RECEIVE_SHADOWS
// 是否透明通道预乘
#pragma shader_feature _PREMULTIPLY_ALPHA
#pragma shader_feature _MASK_MAP
#pragma shader_feature _NORMAL_MAP
#pragma shader_feature _DETAIL_MAP
#pragma multi_compile _ _DIRECTIONAL_PCF3 _DIRECTIONAL_PCF5 _DIRECTIONAL_PCF7
#pragma multi_compile _ _OTHER_PCF3 _OTHER_PCF5 _OTHER_PCF7
#pragma multi_compile _ _CASCADE_BLEND_SOFT _CASCADE_BLEND_DITHER
#pragma multi_compile _ _SHADOW_MASK_ALWAYS _SHADOW_MASK_DISTANCE
// 是否使用逐对象光源
#pragma multi_compile _ _LIGHTS_PER_OBJECT
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile _ LOD_FADE_CROSSFADE
#pragma multi_compile_instancing
#pragma vertex LitPassVertex
#pragma fragment LitPassFragment
// 插入相关HLSL代码
#include "LitPass.hlsl"
ENDHLSL
}
Pass
{
Tags
{
"LightMode" = "ShadowCaster"
}
ColorMask 0
HLSLPROGRAM
#pragma target 3.5
#pragma shader_feature _ _SHADOWS_CLIP _SHADOWS_DITHER
#pragma multi_compile _ LOD_FADE_CROSSFADE
#pragma multi_compile_instancing
#pragma vertex ShadowCasterPassVertex
#pragma fragment ShadowCasterPassFragment
#include "ShadowCasterPass.hlsl"
ENDHLSL
}
Pass
{
Tags
{
"LightMode" = "Meta"
}
Cull Off
HLSLPROGRAM
#pragma target 3.5
#pragma vertex MetaPassVertex
#pragma fragment MetaPassFragment
#include "MetaPass.hlsl"
ENDHLSL
}
}
CustomEditor "CustomShaderGUI"
}
fileFormatVersion: 2
guid: 6848ac66b88696c4ea2f1389e0877b8e
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
#ifndef CUSTOM_LIT_INPUT_INCLUDED
#define CUSTOM_LIT_INPUT_INCLUDED
TEXTURE2D(_BaseMap);
TEXTURE2D(_MaskMap);
TEXTURE2D(_NormalMap);
TEXTURE2D(_EmissionMap);
SAMPLER(sampler_BaseMap);
TEXTURE2D(_DetailMap);
TEXTURE2D(_DetailNormalMap);
SAMPLER(sampler_DetailMap);
UNITY_INSTANCING_BUFFER_START(UnityPerMaterial)
// 提供纹理的缩放和偏移
UNITY_DEFINE_INSTANCED_PROP(float4, _BaseMap_ST)
UNITY_DEFINE_INSTANCED_PROP(float4, _DetailMap_ST)
UNITY_DEFINE_INSTANCED_PROP(float4, _BaseColor)
UNITY_DEFINE_INSTANCED_PROP(float4, _EmissionColor)
UNITY_DEFINE_INSTANCED_PROP(float, _Cutoff)
UNITY_DEFINE_INSTANCED_PROP(float, _Metallic)
UNITY_DEFINE_INSTANCED_PROP(float, _Occlusion)
UNITY_DEFINE_INSTANCED_PROP(float, _Smoothness)
UNITY_DEFINE_INSTANCED_PROP(float, _Fresnel)
UNITY_DEFINE_INSTANCED_PROP(float, _DetailAlbedo)
UNITY_DEFINE_INSTANCED_PROP(float, _DetailSmoothness)
UNITY_DEFINE_INSTANCED_PROP(float, _DetailNormalScale)
UNITY_DEFINE_INSTANCED_PROP(float, _NormalScale)
UNITY_INSTANCING_BUFFER_END(UnityPerMaterial)
// 通过UNITY_ACCESS_INSTANCED_PROP访问material属性
#define INPUT_PROP(name) UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, name)
struct InputConfig
{
float2 baseUV;
float2 detailUV;
bool useMask;
bool useDetail;
};
InputConfig GetInputConfig(float2 baseUV, float2 detailUV = 0.0)
{
InputConfig c;
c.baseUV = baseUV;
c.detailUV = detailUV;
c.useMask = false;
c.useDetail = false;
return c;
}
// 基本纹理UV变换
float2 TransformBaseUV(float2 baseUV)
{
// 计算缩放和偏移后的UV坐标
float4 baseST = UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, _BaseMap_ST);
return baseUV * baseST.xy + baseST.zw;
}
// 细节纹理UV变换
float2 TransformDetailUV(float2 detailUV)
{
float4 detailST = INPUT_PROP(_DetailMap_ST);
return detailUV * detailST.xy + detailST.zw;
}
float4 GetMask(InputConfig c)
{
if (c.useMask)
{
return SAMPLE_TEXTURE2D(_MaskMap, sampler_BaseMap, c.baseUV);
}
return 1.0;
}
float4 GetDetail(InputConfig c)
{
if (c.useDetail)
{
float map = SAMPLE_TEXTURE2D(_DetailMap, sampler_DetailMap, c.detailUV);
return map * 2.0 - 1.0;
}
return 0.0;
}
float4 GetBase(InputConfig c)
{
float4 map = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, c.baseUV);
float4 color = INPUT_PROP(_BaseColor);
if (c.useDetail)
{
float4 detail = GetDetail(c).r * INPUT_PROP(_DetailAlbedo);
float mask = GetMask(c).b;
map.rgb = lerp(sqrt(map.rgb), detail < 0.0 ? 0.0 : 1.0, abs(detail) * mask);
map.rgb *= map.rgb;
}
return map * color;
}
float3 GetEmission(InputConfig c)
{
float4 map = SAMPLE_TEXTURE2D(_EmissionMap, sampler_BaseMap, c.baseUV);
float4 color = INPUT_PROP(_EmissionColor);
return map.rgb * color.rgb;
}
float GetCutoff(InputConfig c)
{
// 透明度低于阈值的片元进行舍弃
return INPUT_PROP(_Cutoff);
}
float GetMetallic(InputConfig c)
{
float metallic = INPUT_PROP(_Metallic);
metallic *= GetMask(c).r;
return metallic;
}
float GetSmoothness(InputConfig c)
{
float smoothness = INPUT_PROP(_Smoothness);
smoothness *= GetMask(c).a;
if (c.useDetail)
{
float detail = GetDetail(c).b * INPUT_PROP(_DetailSmoothness);
float mask = GetMask(c).b;
smoothness = lerp(smoothness, detail < 0.0 ? 0.0 : 1.0, abs(detail) * mask);
}
return smoothness;
}
float GetFresnel(InputConfig c)
{
return INPUT_PROP(_Fresnel);
}
float GetOcclusion(InputConfig c)
{
float strength = INPUT_PROP(_Occlusion);
float occlusion = GetMask(c).g;
occlusion = lerp(occlusion, 1.0, strength);
return occlusion;
}
// 采样法线并解码法线向量a
float3 GetNormalTS(InputConfig c)
{
float4 map = SAMPLE_TEXTURE2D(_NormalMap, sampler_BaseMap, c.baseUV);
float scale = INPUT_PROP(_NormalScale);
float3 normal = DecodeNormal(map, scale);
if (c.useDetail)
{
map = SAMPLE_TEXTURE2D(_DetailNormalMap, sampler_DetailMap, c.detailUV);
scale = INPUT_PROP(_DetailNormalScale) * GetMask(c).b;
float3 detail = DecodeNormal(map, scale);
normal = BlendNormalRNM(normal, detail);
}
return normal;
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 69d7da49567b5224da7d86aa2f6732e4
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
#ifndef CUSTOM_LIT_PASS_INCLUDED
#define CUSTOM_LIT_PASS_INCLUDED
#include "../ShaderLibrary/Surface.hlsl"
#include "../ShaderLibrary/Shadows.hlsl"
#include "../ShaderLibrary/Light.hlsl"
#include "../ShaderLibrary/BRDF.hlsl"
#include "../ShaderLibrary/GI.hlsl"
#include "../ShaderLibrary/Lighting.hlsl"
// 顶点函数输入结构体
struct Attributes
{
float3 positionOS : POSITION;
float2 baseUV : TEXCOORD0;
// 表面法线
float3 normalOS : NORMAL;
// 对象空间的切线
float4 tangentOS : TANGENT;
GI_ATTRIBUTE_DATA
UNITY_VERTEX_INPUT_INSTANCE_ID
};
// 片元函数输入结构体
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 positionWS: VAR_POSITION;
float2 baseUV : VAR_BASE_UV;
#if defined(_DETAIL_MAP)
float2 detailUV : VAR_DETAIL_UV;
#endif
// 世界法线
float3 normalWS : VAR_NORMAL;
#if defined(_NORMAL_MAP)
// 世界空间的切线
float4 tangentWS : VAR_TANGENT;
#endif
GI_ATTRIBUTE_DATA
UNITY_VERTEX_INPUT_INSTANCE_ID
};
// 顶点函数
Varyings LitPassVertex(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
// 使UnityPassVertex输出位置和索引,并复制索引
UNITY_TRANSFER_INSTANCE_ID(input, output);
TRANSFER_GI_DATA(input, output);
output.positionWS = TransformObjectToWorld(input.positionOS);
output.positionCS = TransformWorldToHClip(output.positionWS);
// 计算世界空间的法线
output.normalWS = TransformObjectToWorldNormal(input.normalOS);
#if defined(_NORMAL_MAP)
// 计算世界空间的切线
output.tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w);
#endif
// 计算缩放和偏移后的UV坐标
output.baseUV = TransformBaseUV(input.baseUV);
#if defined(_DETAIL_MAP)
output.detailUV = TransformDetailUV(input.baseUV);
#endif
return output;
}
// 片元函数
float4 LitPassFragment(Varyings input) : SV_TARGET
{
UNITY_SETUP_INSTANCE_ID(input);
ClipLOD(input.positionCS.xy, unity_LODFade.x);
InputConfig config = GetInputConfig(input.baseUV);
#if defined(_MASK_MAP)
config.useMask = true;
#endif
#if defined(_DETAIL_MAP)
config.detailUV = input.detailUV;
config.useDetail = true;
#endif
float4 base = GetBase(config);
#if defined(_CLIPPING)
// 透明度低于阈值的片元进行舍弃
clip(base.a - GetCutoff(config));
#endif
// 定义一个surface并填充属性
Surface surface;
surface.position = input.positionWS;
#if defined(_NORMAL_MAP)
surface.normal = NormalTangentToWorld(GetNormalTS(config), input.normalWS, input.tangentWS);
surface.interpolatedNormal = input.normalWS;
#else
surface.normal = normalize(input.normalWS);
surface.interpolatedNormal = surface.normal;
#endif
// 得到视角方向
surface.viewDirection = normalize(_WorldSpaceCameraPos - input.positionWS);
surface.depth = -TransformWorldToView(input.positionWS).z;
surface.color = base.rgb;
surface.alpha = base.a;
surface.metallic = GetMetallic(config);
surface.smoothness = GetSmoothness(config);
surface.fresnelStrength = GetFresnel(config);
surface.occlusion = GetOcclusion(config);
// 计算抖动值
surface.dither = InterleavedGradientNoise(input.positionCS.xy, 0);
// 通过表面属性和BRDF计算最终光照结果
#if defined(_PREMULTIPLY_ALPHA)
BRDF brdf = GetBRDF(surface, true);
#else
BRDF brdf = GetBRDF(surface);
#endif
// 获取全局照明数据
GI gi = GetGI(GI_FRAGMENT_DATA(input), surface, brdf);
float3 color = GetLighting(surface, brdf, gi);
color += GetEmission(config);
return float4(color, surface.alpha);
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 0a7dab52c92acc3438e7792caa536224
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
#ifndef CUSTOM_META_PASS_INCLUDED
#define CUSTOM_META_PASS_INCLUDED
#include "../ShaderLibrary/Surface.hlsl"
#include "../ShaderLibrary/Shadows.hlsl"
#include "../ShaderLibrary/Light.hlsl"
#include "../ShaderLibrary/BRDF.hlsl"
bool4 unity_MetaFragmentControl;
float unity_OneOverOutputBoost;
float unity_MaxOutputValue;
struct Attributes {
float3 positionOS : POSITION;
float2 baseUV : TEXCOORD0;
float2 lightMapUV : TEXCOORD1;
};
struct Varyings {
float4 positionCS : SV_POSITION;
float2 baseUV : VAR_BASE_UV;
};
Varyings MetaPassVertex(Attributes input)
{
Varyings output;
input.positionOS.xy = input.lightMapUV * unity_LightmapST.xy + unity_LightmapST.zw;
output.positionCS = TransformWorldToHClip(input.positionOS);
output.baseUV = TransformBaseUV(input.baseUV);
return output;
}
float4 MetaPassFragment(Varyings input) : SV_TARGET
{
InputConfig config = GetInputConfig(input.baseUV);
float4 base = GetBase(config);
Surface surface;
ZERO_INITIALIZE(Surface, surface);
surface.color = base.rgb;
surface.metallic = GetMetallic(config);
surface.smoothness = GetSmoothness(config);
BRDF brdf = GetBRDF(surface);
float4 meta = 0.0;
if (unity_MetaFragmentControl.x)
{
meta = float4(brdf.diffuse, 1.0);
meta.rgb += brdf.specular * brdf.roughness * 0.5;
meta.rgb = min(
PositivePow(meta.rgb, unity_OneOverOutputBoost), unity_MaxOutputValue
);
}
else if (unity_MetaFragmentControl.y)
{
meta = float4(GetEmission(config), 1.0);
}
return meta;
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: cbc7a501efec9804894a575cb1e8d0be
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
Shader "Hidden/Custom RP/Post FX Stack"
{
SubShader
{
Cull Off
ZTest Always
ZWrite Off
HLSLINCLUDE
#include "../ShaderLibrary/Common.hlsl"
#include "PostFXStackPasses.hlsl"
ENDHLSL
Pass
{
Name "Bloom Add"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment BloomAddPassFragment
ENDHLSL
}
Pass
{
Name "Bloom Horizontal"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment BloomHorizontalPassFragment
ENDHLSL
}
Pass
{
Name "Bloom Prefilter"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment BloomPrefilterPassFragment
ENDHLSL
}
Pass
{
Name "Bloom Prefilter Fireflies"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment BloomPrefilterFirefliesPassFragment
ENDHLSL
}
Pass
{
Name "Bloom Scatter"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment BloomScatterPassFragment
ENDHLSL
}
Pass
{
Name "Bloom Scatter Final"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment BloomScatterFinalPassFragment
ENDHLSL
}
Pass
{
Name "Bloom Vertical"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment BloomVerticalPassFragment
ENDHLSL
}
Pass
{
Name "Copy"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment CopyPassFragment
ENDHLSL
}
Pass
{
Name "Color Grading None"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment ColorGradingNonePassFragment
ENDHLSL
}
Pass
{
Name "Color Grading ACES"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment ColorGradingACESPassFragment
ENDHLSL
}
Pass
{
Name "Color Grading Neutral"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment ColorGradingNeutralPassFragment
ENDHLSL
}
Pass
{
Name "Color Grading Reinhard"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment ColorGradingReinhardPassFragment
ENDHLSL
}
Pass {
Name "Final"
HLSLPROGRAM
#pragma target 3.5
#pragma vertex DefaultPassVertex
#pragma fragment FinalPassFragment
ENDHLSL
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: cf43cd85c4d2dc34e8fbe0c95979df18
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
#ifndef CUSTOM_POST_FX_PASSES_INCLUDED
#define CUSTOM_POST_FX_PASSES_INCLUDED
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Filtering.hlsl"
TEXTURE2D(_PostFXSource);
TEXTURE2D(_PostFXSource2);
SAMPLER(sampler_linear_clamp);
float4 _PostFXSource_TexelSize;
bool _BloomBicubicUpsampling;
float4 _BloomThreshold;
float _BloomIntensity;
float4 _ColorAdjustments;
float4 _ColorFilter;
float4 _WhiteBalance;
float4 _SplitToningShadows;
float4 _SplitToningHighlights;
float4 _ChannelMixerRed;
float4 _ChannelMixerGreen;
float4 _ChannelMixerBlue;
float4 _SMHShadows;
float4 _SMHMidtones;
float4 _SMHHighlights;
float4 _SMHRange;
float Luminance(float3 color, bool useACES)
{
return useACES ? AcesLuminance(color) : Luminance(color);
}
// 后曝光
float3 ColorGradePostExposure(float3 color)
{
return color * _ColorAdjustments.x;
}
// 对比度
float3 ColorGradingContrast(float3 color, bool useACES)
{
color = useACES ? ACES_to_ACEScc(unity_to_ACES(color)) : LinearToLogC(color);
color = (color - ACEScc_MIDGRAY) * _ColorAdjustments.y + ACEScc_MIDGRAY;
return useACES ? ACES_to_ACEScg(ACEScc_to_ACES(color)) : LogCToLinear(color);
}
// 颜色滤镜
float3 ColorGradeColorFilter(float3 color)
{
return color * _ColorFilter.rgb;
}
// 色调偏移
float3 ColorGradingHueShift(float3 color)
{
color = RgbToHsv(color);
float hue = color.x + _ColorAdjustments.z;
color.x = RotateHue(hue, 0.0, 1.0);
return HsvToRgb(color);
}
// 饱和度
float3 ColorGradingSaturation(float3 color, bool useACES)
{
float luminance = Luminance(color, useACES);
return (color - luminance) * _ColorAdjustments.w + luminance;
}
// 白平衡
float3 ColorGradeWhiteBalance(float3 color)
{
color = LinearToLMS(color);
color *= _WhiteBalance.rgb;
return LMSToLinear(color);
}
// 色调分离
float3 ColorGradeSplitToning(float3 color, bool useACES)
{
color = PositivePow(color, 1.0 / 2.2);
float t = saturate(Luminance(saturate(color), useACES) + _SplitToningShadows.w);
float3 shadows = lerp(0.5, _SplitToningShadows.rgb, 1.0 - t);
float3 highlights = lerp(0.5, _SplitToningHighlights.rgb, t);
color = SoftLight(color, shadows);
color = SoftLight(color, highlights);
return PositivePow(color, 2.2);
}
float3 ColorGradingChannelMixer(float3 color)
{
return mul(float3x3(_ChannelMixerRed.rgb, _ChannelMixerGreen.rgb, _ChannelMixerBlue.rgb), color);
}
float3 ColorGradingShadowsMidtonesHighlights(float3 color, bool useACES)
{
float luminance = Luminance(color, useACES);
float shadowsWeight = 1.0 - smoothstep(_SMHRange.x, _SMHRange.y, luminance);
float highlightsWeight = smoothstep(_SMHRange.z, _SMHRange.w, luminance);
float midtonesWeight = 1.0 - shadowsWeight - highlightsWeight;
return color * _SMHShadows.rgb * shadowsWeight + color * _SMHMidtones.rgb + color * _SMHHighlights.rgb;
}
// 颜色分级
float3 ColorGrade(float3 color, bool useACES = false)
{
color = ColorGradePostExposure(color);
color = ColorGradeWhiteBalance(color);
color = ColorGradingContrast(color, useACES);
color = ColorGradeColorFilter(color);
// 消除负值
color = max(color, 0.0);
color = ColorGradeSplitToning(color, useACES);
color = ColorGradingChannelMixer(color);
// 消除负值
color = max(color, 0.0);
color = ColorGradingShadowsMidtonesHighlights(color, useACES);
color = ColorGradingHueShift(color);
color = ColorGradingSaturation(color, useACES);
return max(useACES ? ACEScg_to_ACES(color) : color, 0.0);
}
float4 GetSourceTexelSize()
{
return _PostFXSource_TexelSize;
}
float4 GetSource(float2 screenUV)
{
return SAMPLE_TEXTURE2D_LOD(_PostFXSource, sampler_linear_clamp, screenUV, 0);
}
float4 GetSource2(float2 screenUV)
{
return SAMPLE_TEXTURE2D_LOD(_PostFXSource2, sampler_linear_clamp, screenUV, 0);
}
float4 GetSourceBicubic(float2 screenUV)
{
return SampleTexture2DBicubic(TEXTURE2D_ARGS(_PostFXSource, sampler_linear_clamp), screenUV, _PostFXSource_TexelSize.zwxy, 1.0, 0.0);
}
float3 ApplyBloomThreshold(float3 color)
{
float brightness = Max3(color.r, color.g, color.b);
float soft = brightness + _BloomThreshold.y;
soft = clamp(soft, 0.0, _BloomThreshold.z);
soft = soft * soft * _BloomThreshold.w;
float contribution = max(soft, brightness - _BloomThreshold.x);
contribution /= max(brightness, 0.00001);
return color * contribution;
}
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 screenUV : VAR_SCREEN_UV;
};
Varyings DefaultPassVertex(uint vertexID : SV_VertexID)
{
Varyings output;
output.positionCS = float4(
vertexID <= 1 ? -1.0 : 3.0,
vertexID == 1 ? 3.0 : -1.0,
0.0, 1.0
);
output.screenUV = float2(
vertexID <= 1 ? 0.0 : 2.0,
vertexID == 1 ? 2.0 : 0.0
);
if (_ProjectionParams.x < 0.0)
{
output.screenUV.y = 1.0 - output.screenUV.y;
}
return output;
}
float4 BloomAddPassFragment(Varyings input) : SV_TARGET
{
float3 lowRes;
if (_BloomBicubicUpsampling)
{
lowRes = GetSourceBicubic(input.screenUV).rgb;
}
else
{
lowRes = GetSource(input.screenUV).rgb;
}
float3 highRes = GetSource2(input.screenUV).rgb;
return float4(lowRes * _BloomIntensity + highRes, 1.0);
}
float4 BloomHorizontalPassFragment(Varyings input) : SV_TARGET
{
float3 color = 0.0;
float offsets[] = {
-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0
};
float weights[] = {
0.01621622, 0.05405405, 0.12162162, 0.19459459, 0.22702703,
0.19459459, 0.12162162, 0.05405405, 0.01621622
};
for (int i = 0; i < 9; i++)
{
float offset = offsets[i] * 2.0 * GetSourceTexelSize().x;
color += GetSource(input.screenUV + float2(offset, 0.0)).rgb * weights[i];
}
return float4(color, 1.0);
}
float4 BloomVerticalPassFragment(Varyings input) : SV_TARGET
{
float3 color = 0.0;
float offsets[] = {
-3.23076923, -1.38461538, 0.0, 1.38461538, 3.23076923
};
float weights[] = {
0.07027027, 0.31621622, 0.22702703, 0.31621622, 0.07027027
};
for (int i = 0; i < 5; i++)
{
float offset = offsets[i] * 2.0 * GetSourceTexelSize().y;
color += GetSource(input.screenUV + float2(0.0, offset)).rgb * weights[i];
}
return float4(color, 1.0);
}
float4 BloomPrefilterPassFragment(Varyings input) : SV_TARGET
{
float3 color = ApplyBloomThreshold(GetSource(input.screenUV).rgb);
return float4(color, 1.0);
}
float4 BloomPrefilterFirefliesPassFragment(Varyings input) : SV_TARGET
{
float3 color = 0.0;
float weightSum = 0.0;
float2 offsets[] = {
float2(0.0, 0.0),
float2(-1.0, -1.0), float2(-1.0, 1.0), float2(1.0, -1.0), float2(1.0, 1.0)
};
for (int i = 0; i < 5; i++)
{
float3 c = GetSource(input.screenUV + offsets[i] * GetSourceTexelSize().xy * 2.0).rgb;
c = ApplyBloomThreshold(c);
float w = 1.0 / (Luminance(c) + 1.0);
color += c * w;
weightSum += w;
}
color /= weightSum;
return float4(color, 1.0);
}
float4 BloomScatterPassFragment(Varyings input) : SV_TARGET
{
float3 lowRes;
if (_BloomBicubicUpsampling)
{
lowRes = GetSourceBicubic(input.screenUV).rgb;
}
else
{
lowRes = GetSource(input.screenUV).rgb;
}
float3 highRes = GetSource2(input.screenUV).rgb;
return float4(lerp(highRes, lowRes, _BloomIntensity), 1.0);
}
float4 BloomScatterFinalPassFragment(Varyings input) : SV_TARGET
{
float3 lowRes;
if (_BloomBicubicUpsampling) {
lowRes = GetSourceBicubic(input.screenUV).rgb;
}
else {
lowRes = GetSource(input.screenUV).rgb;
}
float3 highRes = GetSource2(input.screenUV).rgb;
lowRes += highRes - ApplyBloomThreshold(highRes);
return float4(lerp(highRes, lowRes, _BloomIntensity), 1.0);
}
float4 CopyPassFragment(Varyings input) : SV_TARGET
{
return GetSource(input.screenUV);
}
float4 _ColorGradingLUTParameters;
bool _ColorGradingLUTInLogC;
float3 GetColorGradedLUT(float2 uv, bool useACES = false)
{
float3 color = GetLutStripValue(uv, _ColorGradingLUTParameters);
return ColorGrade(color, useACES);
}
float4 ColorGradingNonePassFragment(Varyings input) : SV_TARGET
{
float3 color = GetColorGradedLUT(input.screenUV);
return float4(color, 1.0);
}
float4 ColorGradingACESPassFragment(Varyings input) : SV_TARGET
{
float3 color = GetColorGradedLUT(input.screenUV, true);
color = AcesTonemap(color);
return float4(color, 1.0);
}
float4 ColorGradingNeutralPassFragment(Varyings input) : SV_TARGET
{
float3 color = GetColorGradedLUT(input.screenUV);
color = NeutralTonemap(color);
return float4(color, 1.0);
}
float4 ColorGradingReinhardPassFragment(Varyings input) : SV_TARGET
{
float3 color = GetColorGradedLUT(input.screenUV);
color /= color + 1.0;
return float4(color, 1.0);
}
TEXTURE2D(_ColorGradingLUT);
float3 ApplyColorGradingLUT(float3 color)
{
return ApplyLut2D(
TEXTURE2D_ARGS(_ColorGradingLUT, sampler_linear_clamp),
saturate(_ColorGradingLUTInLogC ? LinearToLogC(color) : color),
_ColorGradingLUTParameters.xyz
);
}
float4 FinalPassFragment(Varyings input) :SV_TARGET
{
float4 color = GetSource(input.screenUV);
color.rgb = ApplyColorGradingLUT(color.rgb);
return color;
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 59142aef649f68046ac91afb2ad33311
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
// 阴影投射器
#ifndef CUSTOM_SHADOW_CASTER_PASS_INCLUDED
#define CUSTOM_SHADOW_CASTER_PASS_INCLUDED
// 顶点函数输入结构体
struct Attributes
{
float3 positionOS : POSITION;
float2 baseUV : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
// 片元函数输入结构体
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 baseUV : VAR_BASE_UV;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
bool _ShadowPancaking;
// 顶点函数
Varyings ShadowCasterPassVertex(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
// 使UnityPassVertex输出位置和索引,并复制索引
UNITY_TRANSFER_INSTANCE_ID(input, output);
float3 positionWS = TransformObjectToWorld(input.positionOS);
output.positionCS = TransformWorldToHClip(positionWS);
if (_ShadowPancaking)
{
#if UNITY_REVERSED_Z
output.positionCS.z = min(output.positionCS.z, output.positionCS.w * UNITY_NEAR_CLIP_VALUE);
#else
output.positionCS.z = max(output.positionCS.z, output.positionCS.w * UNITY_NEAR_CLIP_VALUE);
#endif
}
// 计算缩放和偏移后的UV坐标
output.baseUV = TransformBaseUV(input.baseUV);
return output;
}
// 片元函数
void ShadowCasterPassFragment(Varyings input)
{
UNITY_SETUP_INSTANCE_ID(input);
ClipLOD(input.positionCS.xy, unity_LODFade.x);
InputConfig config = GetInputConfig(input.baseUV);
float4 base = GetBase(config);
#if defined(_SHADOWS_CLIP)
// 透明度低于阈值的片元进行舍弃
clip(base.a - GetCutoff(config));
#elif defined(_SHADOWS_DITHER)
// 计算抖动值
float dither = InterleavedGradientNoise(input.positionCS.xy, 0);
clip(base.a - dither);
#endif
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: cf100188a4ff11e4081d3f693d2e2070
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
Shader "Custom RP/Unlit"
{
Properties
{
_BaseMap("Texture", 2D) = "white" {}
[HDR] _BaseColor("Color", Color) = (1.0, 1.0, 1.0, 1.0)
// 透明度测试的阈值
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
[Toggle(_CLIPPING)] _Clipping ("Alpha Clipping", Float) = 0
// 阴影模式
[KeywordEnum(On, Clip, Dither, Off)] _Shadows ("Shadows", Float) = 0
// 设置混合模式
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend", Float) = 1
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Dst Blend", Float) = 0
// 默认写入深度缓冲区
[Enum(Off, 0, On, 1)] _ZWrite ("Z Write", Float) = 1
}
SubShader
{
HLSLINCLUDE
#include "../ShaderLibrary/Common.hlsl"
#include "UnlitInput.hlsl"
ENDHLSL
Pass
{
// 定义混合模式
Blend [_SrcBlend] [_DstBlend]
// 是否写入深度
ZWrite [_ZWrite]
HLSLPROGRAM
#pragma shader_feature _CLIPPING
#pragma multi_compile_instancing
#pragma vertex UnlitPassVertex
#pragma fragment UnlitPassFragment
// 插入相关HLSL代码
#include "UnlitPass.hlsl"
ENDHLSL
}
Pass
{
Tags
{
"LightMode" = "ShadowCaster"
}
ColorMask 0
HLSLPROGRAM
#pragma target 3.5
#pragma shader_feature _ _SHADOWS_CLIP _SHADOWS_DITHER
#pragma multi_compile_instancing
#pragma vertex ShadowCasterPassVertex
#pragma fragment ShadowCasterPassFragment
#include "ShadowCasterPass.hlsl"
ENDHLSL
}
Pass
{
Tags
{
"LightMode" = "Meta"
}
Cull Off
HLSLPROGRAM
#pragma target 3.5
#pragma vertex MetaPassVertex
#pragma fragment MetaPassFragment
#include "MetaPass.hlsl"
ENDHLSL
}
}
CustomEditor "CustomShaderGUI"
}
fileFormatVersion: 2
guid: f9b6d8c713e140648abcabcb6381316f
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
#ifndef CUSTOM_UNLIT_INPUT_INCLUDED
#define CUSTOM_UNLIT_INPUT_INCLUDED
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
UNITY_INSTANCING_BUFFER_START(UnityPerMaterial)
UNITY_DEFINE_INSTANCED_PROP(float4, _BaseMap_ST)
UNITY_DEFINE_INSTANCED_PROP(float4, _BaseColor)
UNITY_DEFINE_INSTANCED_PROP(float, _Cutoff)
UNITY_INSTANCING_BUFFER_END(UnityPerMaterial)
// 通过UNITY_ACCESS_INSTANCED_PROP访问material属性
#define INPUT_PROP(name) UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, name)
struct InputConfig
{
float2 baseUV;
};
InputConfig GetInputConfig(float2 baseUV)
{
InputConfig c;
c.baseUV = baseUV;
return c;
}
float2 TransformBaseUV(float2 baseUV)
{
// 计算缩放和偏移后的UV坐标
float4 baseST = INPUT_PROP(_BaseMap_ST);
return baseUV * baseST.xy + baseST.zw;
}
float2 TransformDetailUV(float2 baseUV)
{
return 0.0;
}
float4 GetMask(InputConfig c)
{
return 1.0;
}
float4 GetDetail(InputConfig c)
{
return 0.0;
}
float4 GetBase(InputConfig c)
{
float4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, c.baseUV);
float4 baseColor = INPUT_PROP(_BaseColor);
return baseMap * baseColor;
}
float3 GetEmission(InputConfig c)
{
return GetBase(c).rgb;
}
float GetCutoff(InputConfig c)
{
return INPUT_PROP(_Cutoff);
}
float GetMetallic(InputConfig c)
{
return 0.0;
}
float GetSmoothness(InputConfig c)
{
return 0.0;
}
float GetFresnel(InputConfig c)
{
return 0.0;
}
float3 GetNormalTS(InputConfig c)
{
return float3(0.0, 0.0, 1.0);
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 526b4f3557307a64ba252a7d6c341b1f
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
#ifndef CUSTOM_UNLIT_PASS_INCLUDED
#define CUSTOM_UNLIT_PASS_INCLUDED
// 顶点函数输入结构体
struct Attributes
{
float3 positionOS : POSITION;
float2 baseUV : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
// 片元函数输入结构体
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 baseUV : VAR_BASE_UV;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
// 顶点函数
Varyings UnlitPassVertex(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
// 使UnityPassVertex输出位置和索引,并复制索引
UNITY_TRANSFER_INSTANCE_ID(input, output);
float3 positionWS = TransformObjectToWorld(input.positionOS);
output.positionCS = TransformWorldToHClip(positionWS);
output.baseUV = TransformBaseUV(input.baseUV);
return output;
}
// 片元函数
float4 UnlitPassFragment(Varyings input) : SV_TARGET
{
UNITY_SETUP_INSTANCE_ID(input);
InputConfig config = GetInputConfig(input.baseUV);
float4 base = GetBase(config);
#if defined(_CLIPPING)
// 透明度低于阈值的片元进行舍弃
clip(base.a - GetCutoff(config));
#endif
return base;
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 4995316860cf375428b5ebb1c0f63386
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a4d5e03461da4f346a60224f8a1a6b70, type: 3}
m_Name: Post FX Settings
m_EditorClassIdentifier:
shader: {fileID: 4800000, guid: cf43cd85c4d2dc34e8fbe0c95979df18, type: 3}
colorAdjustments:
postExposure: 0
contrast: 0
colorFilter: {r: 1, g: 1, b: 1, a: 1}
hueShift: 0
saturation: 0
whiteBalance:
temperature: 0
tint: 0
splitToning:
shadows: {r: 0.0046279924, g: 0.18946211, b: 0.9811321, a: 1}
highlights: {r: 1, g: 0.51841265, b: 0, a: 1}
balance: 0
channelMixer:
red: {x: 1, y: 0, z: 0.33333}
green: {x: 0, y: 0.5, z: 0.33333}
blue: {x: 0, y: 0.5, z: 0.33333}
shadowsMidtonesHighlights:
shadows: {r: 0, g: 1, b: 0.089500666, a: 1}
midtones: {r: 1, g: 1, b: 1, a: 1}
highlights: {r: 1, g: 1, b: 1, a: 1}
shadowsStart: 0
shadowsEnd: 0.3
highlightsStart: 0.55
highlightsEnd: 1
bloom:
maxIterations: 16
downscaleLimit: 2
bicubicUpsampling: 1
threshold: 1
thresholdKnee: 0.5
intensity: 0.88
fadeFireflies: 1
mode: 1
scatter: 0.05
toneMapping:
mode: 0
fileFormatVersion: 2
guid: 803d8f754f1bc8c469121e005316f6fa
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 5105ef07608ce8d46a77e94ee0a6fd8a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 8574b4573e3c34a1ebc1b5d608e35b66
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
此差异已折叠。
fileFormatVersion: 2
guid: 8906592143b104fbdb4c313b4ab8132c
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 4772e383a675c4016a19a76456116c09
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 112000000
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: eb5027765e9124d74aea8517bc5b5ff7
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 1
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 3
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 0
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 6
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
fileFormatVersion: 2
guid: 98c6a8b39fd4c09478f4cbf686a665ef
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 4890085278179872738
userData:
assetBundleName:
assetBundleVariant:
此差异已折叠。
fileFormatVersion: 2
guid: 136e48671e0544d2587a662219697724
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
此差异已折叠。
fileFormatVersion: 2
guid: f83cd4e5c6685ac49a400d07f664abcf
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 4890085278179872738
userData:
assetBundleName:
assetBundleVariant:
此差异已折叠。
fileFormatVersion: 2
guid: 14595156b0dc840aa81a612fd2214d99
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册