自己紹介
HLSLシェーダーの魔導書を誕生日プレゼントにもらってシェーダーに入門した大学生。
今回の記事の背景
Build-in RenderPipeline時代のUnityは「CG言語」というものでシェーダーを書いていたそうです。
しかし、SRP(URP / HDRPの基盤)となってからは「HLSL言語」が推奨されています。
こちらのほうが最適化されているそうです。
詳しくは以下のQiitaをご覧ください。
一方で、ネットには今でもCG言語でかかれたものが多く、HLSL言語で書かれたものは比較的少ないです。
今回はHLSL言語を学ぶ過程で、せっかくならHLSL言語の記事を増やそうというノリで書いています。
本題
鏡面反射の実装でUnityではReflection Probeを使うことが多いと思います。(知らんけど)
ということで、それをHLSLで実装する方法です。
CG言語版はCAの矢野さんが書かれています。
Unityの環境
Unity : 2023.2.3f1
URP : 16.0.4
URPもうすぐRender Graphってやつで作り直されるらしいけどそれでも使えるよ…ね?
コード
Shader "Custom/Reflection"
{
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#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;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 WorldPos : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
float3 pos : TEXCOORD2;
};
v2f vert (appdata v)
{
v2f o = (v2f) 0;
o.vertex = TransformObjectToHClip(v.vertex.xyz);
o.worldNormal = TransformObjectToWorldNormal(v.normal, true);
return o;
}
half4 frag (v2f i) : SV_Target
{
half3 worldViewDir = normalize(_WorldSpaceCameraPos - i.WorldPos);
half3 reflectDir = normalize(reflect(-worldViewDir, i.worldNormal));
half4 envCol = SAMPLE_TEXTURECUBE(unity_SpecCube0, samplerunity_SpecCube0, reflectDir);
envCol.rgb = DecodeHDREnvironment(envCol, unity_SpecCube0_HDR);
return envCol;
}
ENDHLSL
}
}
}
こちらのコードは実はほぼコピペではあるのですが、ところどころ改良しています。
ポイント
ここからは上記で挙げた矢野さんの記事を参考にCG言語との差を見ていきたいと思います。
オブジェクト空間からスクリーン空間へ
ここは組み込み関数がUnityObjectToClipPos
からTransformObjectToHClip
に変更されています。
この関数はPackages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl
の中でincludeされている、Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl
でincludeされているPackages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl
で定義されています。
遠すぎです。
同様にUnityObjectToWorldNormal
もTransformObjectToWorldNormal
に変更されています。
Reflection Probeのサンプリングの方法
ここが一番情報なくて困りました…
正直コードの通りとしかいいようがないです!
またDecodeHDREnviroment
は、Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl
でincludeされているPackages/com.unity.render-pipelines.universal/ShaderLibrary/GlobalIllumination.hlsl
でincludeされているPackages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl
で実装されています。
とおおおおおおおおおおおおおいのよ全部
結果
このようにレンダリングされます。
(矢野さんに見習ってSceneビューで)
まとめ
組み込み関数のリファレンスが本当になくて、めちゃめちゃ大変。。。
これからもHLSLの記事を少しずつ世に増やして行ければと思ってます。
ではまた…!
参考にした記事