本日はHoloLensの表現実験枠です。
昨日開発したSpatialMeshのシェーダーを改造していきます。
〇HoloLens 2022年アドベントカレンダー
HoloLens 2022年アドベントカレンダーはQiita上で私の師であるがち本さんが開催している企画です。
クリスマスまで毎日記事を埋めていくことが目的で本日は18日目の記事になります。
〇SpatialMeshに影を落とす
昨日はSpatialMeshに影を落とす表現を実装しました。
今回はこれを改造して影の見た目を変えれるようにしていきます。
〇TriplanerMapping
SpatialMeshはテクスチャを張るためのUVを持ち合わせていません。
そのため普通にサンプリングを行うことができないためTriplanerMappingと呼ばれる手法を使用します。
TriplanerMapingはUVを無視してUnityのワールド座標ベースにサンプリングを行うことができる手法です。
TriplanerMapingの詳細は本記事では省きますので前述の過去の記事を参考にしてください。
float4 col= tex2D(_CyberTex,uvX)*triplanarBlend.x + tex2D(_CyberTex,uvY)* triplanarBlend.y+tex2D(_CyberTex,uvZ)*triplanarBlend.z;
colはのちに影以外が0(黒)になります。最後に掛け合わせることで影部分のみにテクスチャが反映されるようになります。

〇実機で確認
今回はラメ上のテクスチャでcyberな雰囲気を再現しました。
〇ソースコード
Shader "Unlit/SpatialShadow"
{
Properties
{
_CyberTex("CyberTex",2D) = "white"{}
_ShadowColor("ShadowColor",color) = (1,1,1,1)
}
SubShader
{
Tags
{
"RenderType"="Opaque"
"Queue"="Geometry-1"
}
// ColorMask R
ZWrite On
ZTest LEqual
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct appdata
{
float4 vertex : POSITION;
half3 normal: NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 position : SV_POSITION;
float3 normalWS : TEXCOORD1;
float4 shadowCoord : TEXCOORD3;
float3 worldNormal:COLOR3;
float3 triplanaerNormal : COLOR4;
float4 triplanaerPosition : TEXCOORD6;
UNITY_VERTEX_OUTPUT_STEREO
};
float4 _MainColor;
float4 _ShadowColor;
sampler2D _CyberTex;
float4 _CyberTex_ST;
v2f vert(appdata input)
{
v2f output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
output.position = TransformObjectToHClip(input.vertex);;
VertexNormalInputs normal = GetVertexNormalInputs(input.normal);
output.normalWS = normal.normalWS;
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.vertex.xyz);//追加
output.shadowCoord = GetShadowCoord(vertexInput);//追加
output.triplanaerNormal = normal.normalWS;
output.triplanaerPosition = mul(unity_ObjectToWorld, input.vertex).xyzw;
return output;
}
float4 frag(v2f input) : SV_Target
{
//TriplanaerSettings
float3 triplanarBlend = pow(abs(input.normalWS),1);
triplanarBlend/=dot(triplanarBlend,half3(1,1,1));
float2 uvX = input.triplanaerPosition.zy * _CyberTex_ST.xy+_CyberTex_ST.zw;
float2 uvY = input.triplanaerPosition.xz * _CyberTex_ST.xy+_CyberTex_ST.zw;
float2 uvZ = input.triplanaerPosition.xy *_CyberTex_ST.xy+_CyberTex_ST.zw;
float3 axisSign = input.normalWS <0? -1 : 1;
uvX*=axisSign.x;
uvY*=axisSign.y;
uvZ*=axisSign.z;
float4 col= tex2D(_CyberTex,uvX)*triplanarBlend.x + tex2D(_CyberTex,uvY)* triplanarBlend.y+tex2D(_CyberTex,uvZ)*triplanarBlend.z;
//Light.hlslで提供されるUnityのライトを取得する関数
Light lt = GetMainLight(input.shadowCoord);
float4 lightColor = float4(lt.color, 1)*(lt.distanceAttenuation * lt.shadowAttenuation);
col *= abs(1-saturate(lightColor.r));
return col;
}
ENDHLSL
}
}
}