本日はMRTKで提供されているMRTK StandardShaderの調査枠です。
〇これまでの記事
〇Emission
今回はEmission(発光)に関して調査します。
Emissionはオブジェクトをその名の通り発光させることができます。 これはカラーをオーバーレイするような効果を持ちます。
〇 Properties
Properties { // Main maps. _Color("Color", Color) = (1.0, 1.0, 1.0, 1.0) [Toggle(_EMISSION)] _EnableEmission("Enable Emission", Float) = 0.0 [HDR]_EmissiveColor("Emissive Color", Color) = (0.0, 0.0, 0.0, 1.0) // Rendering options. [Toggle(_DIRECTIONAL_LIGHT)] _DirectionalLight("Directional Light", Float) = 1.0 }
ここではMaterialとして使用できる変数を記述します。
今回は_EMISSIONが重要になります。MRTKStandardShaerではこのチェックボックスを有効化すると発光が使用できます。
追加したものは次のようになります。
[Toggle(_EMISSION)] _EnableEmission("Enable Emission", Float) = 0.0 [HDR]_EmissiveColor("Emissive Color", Color) = (0.0, 0.0, 0.0, 1.0)
[HDR]のアトリビュートはハイ・ダイナミック・レンジという手法のカラーで暗明の差が大きく表現できるカラーとして使用できます。
マテリアル側でもこのcolorにはHDRの文字が表示されます。
〇フラグメントシェーダー
フラグメントシェーダーでの変更点は次の通りです。
#if defined(_EMISSION) output.rgb += _EmissiveColor; #endif
影やテクスチャなどのレンダリング結果のoutput.rgb に_EmissiveColorが直接加算されています。
これによって最初に表現したようにオーバーレイが行われています。
〇今回作成したShader
Shader "Custom/MRTKEmission" { Properties { // Main maps. _Color("Color", Color) = (1.0, 1.0, 1.0, 1.0) [Toggle(_EMISSION)] _EnableEmission("Enable Emission", Float) = 0.0 [HDR]_EmissiveColor("Emissive Color", Color) = (0.0, 0.0, 0.0, 1.0) // Rendering options. [Toggle(_DIRECTIONAL_LIGHT)] _DirectionalLight("Directional Light", Float) = 1.0 } SubShader { Pass { Name "Main" Tags{ "RenderType" = "Opaque" "LightMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma shader_feature _EMISSION #pragma shader_feature _DIRECTIONAL_LIGHT #include "UnityCG.cginc" #include "UnityStandardConfig.cginc" #include "UnityStandardUtils.cginc" #include "MixedRealityShaderUtils.cginc" // This define will get commented in by the UpgradeShaderForLightweightRenderPipeline method. //#define _LIGHTWEIGHT_RENDER_PIPELINE #if defined(_DIRECTIONAL_LIGHT) #define _NORMAL #else #undef _NORMAL #endif #if defined(_NORMAL) #define _WORLD_POSITION #else #undef _WORLD_POSITION #endif #if defined(_DIRECTIONAL_LIGHT) #define _FRESNEL #else #undef _FRESNEL #endif #define _UV struct appdata_t { float4 vertex : POSITION; // The default UV channel used for texturing. float2 uv : TEXCOORD0; // Used for smooth normal data (or UGUI scaling data). float4 uv2 : TEXCOORD2; // Used for UGUI scaling data. float2 uv3 : TEXCOORD3; fixed3 normal : NORMAL; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float4 position : SV_POSITION; float2 uv : TEXCOORD0; #if defined(_WORLD_POSITION) float3 worldPosition : TEXCOORD2; #endif fixed3 worldNormal : COLOR3; UNITY_VERTEX_OUTPUT_STEREO }; fixed4 _Color; sampler2D _MainTex; fixed4 _MainTex_ST; fixed _Metallic; fixed _Smoothness; #if defined(_EMISSION) fixed4 _EmissiveColor; #endif #if defined(_DIRECTIONAL_LIGHT) fixed4 _LightColor0; #endif #if defined(_DIRECTIONAL_LIGHT) static const fixed _MinMetallicLightContribution = 0.7; static const fixed _IblContribution = 0.1; #endif #if defined(_FRESNEL) static const float _FresnelPower = 8.0; #endif v2f vert(appdata_t v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); float4 vertexPosition = v.vertex; #if defined(_WORLD_POSITION) float3 worldVertexPosition = mul(unity_ObjectToWorld, vertexPosition).xyz; #endif fixed3 localNormal = v.normal; #if defined(_NORMAL) fixed3 worldNormal = UnityObjectToWorldNormal(localNormal); #endif o.position = UnityObjectToClipPos(vertexPosition); #if defined(_WORLD_POSITION) o.worldPosition.xyz = worldVertexPosition; #endif #if defined(_NORMAL) o.worldNormal = worldNormal; #endif return o; } fixed4 frag(v2f i, fixed facing : VFACE) : SV_Target { // Texturing. fixed4 albedo = tex2D(_MainTex, i.uv); albedo *= _Color; // Normal calculation. #if defined(_NORMAL) fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPosition.xyz)); fixed3 worldNormal; worldNormal = normalize(i.worldNormal) * facing; #endif fixed pointToLight = 1.0; fixed3 fluentLightColor = fixed3(0.0, 0.0, 0.0); // Blinn phong lighting. #if defined(_DIRECTIONAL_LIGHT) float4 directionalLightDirection = _WorldSpaceLightPos0; fixed diffuse = max(0.0, dot(worldNormal, directionalLightDirection)); fixed specular = 0.0; #endif fixed3 ibl = unity_IndirectSpecColor.rgb; // Fresnel lighting. #if defined(_FRESNEL) fixed fresnel = 1.0 - saturate(abs(dot(worldViewDir, worldNormal))); fixed3 fresnelColor = unity_IndirectSpecColor.rgb * (pow(fresnel, _FresnelPower) * max(_Smoothness, 0.5)); #endif // Final lighting mix. fixed4 output = albedo; fixed3 ambient = glstate_lightmodel_ambient + fixed3(0.25, 0.25, 0.25); fixed minProperty = min(_Smoothness, _Metallic); #if defined(_DIRECTIONAL_LIGHT) fixed oneMinusMetallic = (1.0 - _Metallic); output.rgb = lerp(output.rgb, ibl, minProperty); fixed3 directionalLightColor = _LightColor0.rgb; output.rgb *= lerp((ambient + directionalLightColor * diffuse + directionalLightColor * specular) * max(oneMinusMetallic, _MinMetallicLightContribution), albedo, minProperty); output.rgb += (directionalLightColor * albedo * specular) + (directionalLightColor * specular * _Smoothness); output.rgb += ibl * oneMinusMetallic * _IblContribution; #endif #if defined(_FRESNEL) output.rgb += fresnelColor * (1.0 - minProperty); #endif #if defined(_EMISSION) output.rgb += _EmissiveColor; #endif return output; } ENDCG } } Fallback "Hidden/InternalErrorShader" }