結果
影が黒色の場合
影が水色の場合
二つの画像の影を比較すると,黒色と水色の影をを確認することができます.
コード
ReceiveShadowOnly.shader
Shader "Universal Render Pipeline/Simple Lit"
{
Properties
{
// 影の色をここで指定
_ShadowColor("Shadow Color", Color) = (0, 0, 0, 0)
}
SubShader
{
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "UniversalMaterialType" = "SimpleLit" "IgnoreProjector" = "True" "ShaderModel"="4.5"}
LOD 300
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
HLSLPROGRAM
#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _RECEIVE_SHADOWS_OFF
// -------------------------------------
// Universal Pipeline keywords
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
//--------------------------------------
#pragma vertex LitPassVertexSimple
#pragma fragment LitPassFragmentSimple
#include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float2 texcoord : TEXCOORD0;
};
struct Varyings
{
float2 uv : TEXCOORD0;
float3 positionWS : TEXCOORD2;
float4 positionCS : SV_POSITION;
};
half4 _ShadowColor;
Varyings LitPassVertexSimple(Attributes input)
{
Varyings output = (Varyings)0;
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.positionWS.xyz = vertexInput.positionWS;
output.positionCS = vertexInput.positionCS;
return output;
}
Light MyGetMainLight(float4 shadowCoord)
{
Light light = GetMainLight();
/// RealTimeShadowの計算 ///
half4 shadowParams = GetMainLightShadowParams();
half shadowStrength = shadowParams.x;
ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
half attenuation;
attenuation = SAMPLE_TEXTURE2D_SHADOW(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture, shadowCoord.xyz);
attenuation = SampleShadowmapFiltered(TEXTURE2D_SHADOW_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowCoord, shadowSamplingData);;
attenuation = LerpWhiteTo(attenuation, shadowStrength);
half shadowAttenuation = BEYOND_SHADOW_FAR(shadowCoord) ? 1.0 : attenuation;
///
light.shadowAttenuation = shadowAttenuation;
return light;
}
half4 LitPassFragmentSimple(Varyings input) : SV_Target
{
half4 shadowCoord = TransformWorldToShadowCoord(input.positionWS);
Light mainLight = MyGetMainLight(shadowCoord);
half3 white = half3(1, 1, 1);
half3 finalColor = lerp(_ShadowColor.rgb, white, mainLight.shadowAttenuation);
return half4(finalColor, 1);
}
ENDHLSL
}
}
}
影を受けとるオブジェクトにこのシェーダーを用いたマテリアルを貼りつけることで,色付影を付けられます.
SimpleLit.shaderを参考にし,必要な部分だけ抽出しました.
方法
Unityでは,リアルタイムの影をレンダリングするためにシャドウマッピングと呼ばれる技術を使用しています.
影を付けるにはシャドウマップをサンプリングして,ライトがオブジェクトに遮られているかどうかを判別します.
フラグメントシェーダー内では次のように処理をします.
- ワールド座標からShadowMapをサンプリングする際に使用するshadowCoordを得る
- メインライト(Directional Light)から,影が付くかどうかを表すshadowAttenuationを求める
- shadowAttenuationを影が付いているかどうかを表すマスクであると考え,lerpを使って影の部分は影の色,影出ない部分は白色にする
おわりに
影に模様とか付けてみたいですね
参考
SimpleLit.shader内のForward部分のFragmentPassが書かれてあります.
SimpleLitForwardPass.hlsl