Unity URP 2D Light の設定について、毎回忘れてしまうので自分用覚書です。
-
Project Settings > Graphics Default Render Pipeline を URP-2D のものにする
-
Sprite > Open Sprite Editor > 左上 > Secondaly Textures に _NormalMap と _MaskMap を追加する
-
CompositeShadowCaster2D をアタッチしたGameObjectの下にスプライト群を置くと影が統合される
統合前 | 統合後 |
---|---|
![]() |
![]() |
おまけ
normalの反転/強度を変更できるようにしたSprite-Lit-Default
効果小 | 効果大 |
---|---|
![]() |
![]() |
ソースコード(Unity6)
Shader "Universal Render Pipeline/2D/Sprite-Lit-DefaultEx(Unity6)"
{
Properties
{
_MainTex("Diffuse", 2D) = "white" {}
_MaskTex("Mask", 2D) = "white" {}
_NormalMap("Normal Map", 2D) = "bump" {}
_NormalIntensity("Normal Intensity", Range(-2,2)) = 1
_ZWrite("ZWrite", Float) = 0
// Legacy properties. They're here so that materials using this shader can gracefully fallback to the legacy sprite shader.
[HideInInspector] _Color("Tint", Color) = (1,1,1,1)
[HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1)
[HideInInspector] _AlphaTex("External Alpha", 2D) = "white" {}
[HideInInspector] _EnableExternalAlpha("Enable External Alpha", Float) = 0
}
SubShader
{
Tags {"Queue" = "Transparent" "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" }
Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha
Cull Off
ZWrite [_ZWrite]
ZTest Off
Pass
{
Tags { "LightMode" = "Universal2D" }
HLSLPROGRAM
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/Core2D.hlsl"
#pragma vertex CombinedShapeLightVertex
#pragma fragment CombinedShapeLightFragment
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/ShapeLightShared.hlsl"
#pragma multi_compile _ DEBUG_DISPLAY SKINNED_SPRITE
struct Attributes
{
float3 positionOS : POSITION;
float4 color : COLOR;
float2 uv : TEXCOORD0;
UNITY_SKINNED_VERTEX_INPUTS
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
half4 color : COLOR;
float2 uv : TEXCOORD0;
half2 lightingUV : TEXCOORD1;
#if defined(DEBUG_DISPLAY)
float3 positionWS : TEXCOORD2;
#endif
UNITY_VERTEX_OUTPUT_STEREO
};
#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/LightingUtility.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/DebugMipmapStreamingMacros.hlsl"
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
UNITY_TEXTURE_STREAMING_DEBUG_VARS_FOR_TEX(_MainTex);
TEXTURE2D(_MaskTex);
SAMPLER(sampler_MaskTex);
// NOTE: Do not ifdef the properties here as SRP batcher can not handle different layouts.
CBUFFER_START(UnityPerMaterial)
half4 _Color;
CBUFFER_END
#if USE_SHAPE_LIGHT_TYPE_0
SHAPE_LIGHT(0)
#endif
#if USE_SHAPE_LIGHT_TYPE_1
SHAPE_LIGHT(1)
#endif
#if USE_SHAPE_LIGHT_TYPE_2
SHAPE_LIGHT(2)
#endif
#if USE_SHAPE_LIGHT_TYPE_3
SHAPE_LIGHT(3)
#endif
Varyings CombinedShapeLightVertex(Attributes v)
{
Varyings o = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
UNITY_SKINNED_VERTEX_COMPUTE(v);
v.positionOS = UnityFlipSprite(v.positionOS, unity_SpriteProps.xy);
o.positionCS = TransformObjectToHClip(v.positionOS);
#if defined(DEBUG_DISPLAY)
o.positionWS = TransformObjectToWorld(v.positionOS);
#endif
o.uv = v.uv;
o.lightingUV = half2(ComputeScreenPos(o.positionCS / o.positionCS.w).xy);
o.color = v.color * _Color * unity_SpriteColor;
return o;
}
#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/CombinedShapeLightShared.hlsl"
half4 CombinedShapeLightFragment(Varyings i) : SV_Target
{
const half4 main = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
const half4 mask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, i.uv);
SurfaceData2D surfaceData;
InputData2D inputData;
InitializeSurfaceData(main.rgb, main.a, mask, surfaceData);
InitializeInputData(i.uv, i.lightingUV, inputData);
SETUP_DEBUG_TEXTURE_DATA_2D_NO_TS(inputData, i.positionWS, i.positionCS, _MainTex);
return CombinedShapeLightShared(surfaceData, inputData);
}
ENDHLSL
}
Pass
{
ZWrite Off
Tags { "LightMode" = "NormalsRendering"}
HLSLPROGRAM
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/Core2D.hlsl"
#pragma vertex NormalsRenderingVertex
#pragma fragment NormalsRenderingFragment
#pragma multi_compile _ SKINNED_SPRITE
struct Attributes
{
float3 positionOS : POSITION;
float4 color : COLOR;
float2 uv : TEXCOORD0;
float4 tangent : TANGENT;
UNITY_SKINNED_VERTEX_INPUTS
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
half4 color : COLOR;
float2 uv : TEXCOORD0;
half4 normalWS : TEXCOORD1;
half3 tangentWS : TEXCOORD2;
half3 bitangentWS : TEXCOORD3;
UNITY_VERTEX_OUTPUT_STEREO
};
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
TEXTURE2D(_NormalMap);
SAMPLER(sampler_NormalMap);
half _NormalIntensity;
// NOTE: Do not ifdef the properties here as SRP batcher can not handle different layouts.
CBUFFER_START( UnityPerMaterial )
half4 _Color;
CBUFFER_END
Varyings NormalsRenderingVertex(Attributes attributes)
{
Varyings o = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(attributes);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
UNITY_SKINNED_VERTEX_COMPUTE(attributes);
attributes.positionOS = UnityFlipSprite(attributes.positionOS, unity_SpriteProps.xy);
o.positionCS = TransformObjectToHClip(attributes.positionOS);
o.uv = attributes.uv;
o.color = attributes.color;
o.normalWS.xyz = -GetViewForwardDir();
o.normalWS.w = _NormalIntensity;
o.tangentWS = TransformObjectToWorldDir(attributes.tangent.xyz);
o.bitangentWS = cross(o.normalWS.xyz, o.tangentWS) * attributes.tangent.w;
return o;
}
#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/NormalsRenderingShared.hlsl"
half4 NormalsRenderingFragment(Varyings i) : SV_Target
{
const half4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
half3 normalTS = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, i.uv));
normalTS = normalize(half3(normalTS.x * i.normalWS.w, normalTS.y * i.normalWS.w, normalTS.z));
half4 ret = NormalsRenderingShared(mainTex, normalTS, i.tangentWS.xyz, i.bitangentWS.xyz, i.normalWS.xyz);
return ret;
}
ENDHLSL
}
Pass
{
Tags { "LightMode" = "UniversalForward" "Queue"="Transparent" "RenderType"="Transparent"}
HLSLPROGRAM
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/Core2D.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/DebugMipmapStreamingMacros.hlsl"
#if defined(DEBUG_DISPLAY)
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/Debugging2D.hlsl"
#endif
#pragma vertex UnlitVertex
#pragma fragment UnlitFragment
#pragma multi_compile _ DEBUG_DISPLAY SKINNED_SPRITE
struct Attributes
{
float3 positionOS : POSITION;
float4 color : COLOR;
float2 uv : TEXCOORD0;
UNITY_SKINNED_VERTEX_INPUTS
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float4 color : COLOR;
float2 uv : TEXCOORD0;
#if defined(DEBUG_DISPLAY)
float3 positionWS : TEXCOORD2;
#endif
UNITY_VERTEX_OUTPUT_STEREO
};
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
UNITY_TEXTURE_STREAMING_DEBUG_VARS_FOR_TEX(_MainTex);
// NOTE: Do not ifdef the properties here as SRP batcher can not handle different layouts.
CBUFFER_START( UnityPerMaterial )
half4 _Color;
CBUFFER_END
Varyings UnlitVertex(Attributes attributes)
{
Varyings o = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(attributes);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
UNITY_SKINNED_VERTEX_COMPUTE(attributes);
attributes.positionOS = UnityFlipSprite( attributes.positionOS, unity_SpriteProps.xy);
o.positionCS = TransformObjectToHClip(attributes.positionOS);
#if defined(DEBUG_DISPLAY)
o.positionWS = TransformObjectToWorld(attributes.positionOS);
#endif
o.uv = attributes.uv;
o.color = attributes.color * _Color * unity_SpriteColor;
return o;
}
float4 UnlitFragment(Varyings i) : SV_Target
{
float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
#if defined(DEBUG_DISPLAY)
SurfaceData2D surfaceData;
InputData2D inputData;
half4 debugColor = 0;
InitializeSurfaceData(mainTex.rgb, mainTex.a, surfaceData);
InitializeInputData(i.uv, inputData);
SETUP_DEBUG_TEXTURE_DATA_2D_NO_TS(inputData, i.positionWS, i.positionCS, _MainTex);
if(CanDebugOverrideOutputColor(surfaceData, inputData, debugColor))
{
return debugColor;
}
#endif
return mainTex;
}
ENDHLSL
}
}
Fallback "Sprites/Default"
}
ソースコード(Unity2022)
using UnityEngine;
using UnityEngine.Rendering;
namespace ModelToBump
{
//https://docs.unity3d.com/ja/2021.3/Manual/srp-setting-render-pipeline-asset.html
public class ActiveRenderPipelineExample : MonoBehaviour
{
// In the Inspector, assign a Render Pipeline Asset to each of these fields
public RenderPipelineAsset defaultRenderPipelineAsset;
public RenderPipelineAsset overrideRenderPipelineAsset;
void Start()
{
GraphicsSettings.defaultRenderPipeline = defaultRenderPipelineAsset;
QualitySettings.renderPipeline = overrideRenderPipelineAsset;
DisplayCurrentRenderPipeline();
}
void Update()
{
// When the user presses the left shift key, switch the default render pipeline
if (Input.GetKeyDown(KeyCode.LeftShift))
{
SwitchDefaultRenderPipeline();
DisplayCurrentRenderPipeline();
}
// When the user presses the right shift key, switch the override render pipeline
else if (Input.GetKeyDown(KeyCode.RightShift))
{
SwitchOverrideRenderPipeline();
DisplayCurrentRenderPipeline();
}
}
// Switch the default render pipeline between null,
// and the render pipeline defined in defaultRenderPipelineAsset
void SwitchDefaultRenderPipeline()
{
if (GraphicsSettings.defaultRenderPipeline == defaultRenderPipelineAsset)
{
GraphicsSettings.defaultRenderPipeline = null;
}
else
{
GraphicsSettings.defaultRenderPipeline = defaultRenderPipelineAsset;
}
}
// Switch the override render pipeline between null,
// and the render pipeline defined in overrideRenderPipelineAsset
void SwitchOverrideRenderPipeline()
{
if (QualitySettings.renderPipeline == overrideRenderPipelineAsset)
{
QualitySettings.renderPipeline = null;
}
else
{
QualitySettings.renderPipeline = overrideRenderPipelineAsset;
}
}
// Print the current render pipeline information to the console
void DisplayCurrentRenderPipeline()
{
// GraphicsSettings.defaultRenderPipeline determines the default render pipeline
// If it is null, the default is the Built-in Render Pipeline
if (GraphicsSettings.defaultRenderPipeline != null)
{
Debug.Log("The default render pipeline is defined by " + GraphicsSettings.defaultRenderPipeline.name);
}
else
{
Debug.Log("The default render pipeline is the Built-in Render Pipeline");
}
// QualitySettings.renderPipeline determines the override render pipeline for the current quality level
// If it is null, no override exists for the current quality level
if (QualitySettings.renderPipeline != null)
{
Debug.Log("The override render pipeline for the current quality level is defined by " + QualitySettings.renderPipeline.name);
}
else
{
Debug.Log("No override render pipeline exists for the current quality level");
}
// If an override render pipeline is defined, Unity uses that
// Otherwise, it falls back to the default value
if (QualitySettings.renderPipeline != null)
{
Debug.Log("The active render pipeline is the override render pipeline");
}
else
{
Debug.Log("The active render pipeline is the default render pipeline");
}
// To get a reference to the Render Pipeline Asset that defines the active render pipeline,
// without knowing if it is the default or an override, use GraphicsSettings.currentRenderPipeline
if (GraphicsSettings.currentRenderPipeline != null)
{
Debug.Log("The active render pipeline is defined by " + GraphicsSettings.currentRenderPipeline.name);
}
else
{
Debug.Log("The active render pipeline is the Built-in Render Pipeline");
}
}
}
}
以上です。