質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

HLSL

HLSLは、米マイクロソフト社によって開発された Direct3D APIで使われるプロプライエタリなシェーディング言語です。

Q&A

解決済

1回答

1815閲覧

Transparentなシェーダに影を受けさせる&ライトプローブを反映させたい

aiueoao

総合スコア146

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

HLSL

HLSLは、米マイクロソフト社によって開発された Direct3D APIで使われるプロプライエタリなシェーディング言語です。

0グッド

0クリップ

投稿2021/06/17 14:20

編集2021/06/18 05:39

前提・実現したいこと

シェーダ初心者です
動くGameObjectを半透明にしたかったので、こちらを参考にさせて頂きシェーダを書いたのですが、リアルタイムの影を受けることが出来ません。ライトプローブの情報は反映されます。
イメージ説明
またこちらのコードでは影を受けることが出来ましたがライトプローブの情報が反映されませんでした。

![イメージ説明

該当のソースコード

HLSL

1Shader "Custom/TestSurfaceShader" 2{ 3 Properties{ 4 _Color("Color", Color) = (1,1,1,1) 5 _MainTex("Albedo (RGB)", 2D) = "white" {} 6 _BumpMap("Normal Map" , 2D) = "bump" {} 7 _BumpScale("Normal Scale", Range(0, 1)) = 1.0 8 } 9 SubShader 10 { 11 Pass 12 { 13 Zwrite On 14 ColorMask 0 15 Lighting OFF 16 } 17 18 Tags {"RenderType" = "Transparent" "Queue" = "Transparent"} 19 Zwrite Off 20 ZTest LEqual 21 22 CGPROGRAM 23 #pragma surface surf Standard fullforwardshadows alpha 24 #pragma target 3.0 25 26 sampler2D _MainTex; 27 28 struct Input { 29 float2 uv_MainTex; 30 }; 31 32 fixed4 _Color; 33 sampler2D _BumpMap; 34 half _BumpScale; 35 36 void surf(Input IN, inout SurfaceOutputStandard o) 37 { 38 // Albedo comes from a texture tinted by color 39 fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; 40 o.Albedo = c.rgb; 41 o.Alpha = c.a; 42 fixed4 n = tex2D(_BumpMap, IN.uv_MainTex); 43 o.Normal = UnpackScaleNormal(n, _BumpScale); 44 } 45 ENDCG 46 } 47 FallBack "Diffuse" 48} 49

試したこと

Unityマニュアルを見てみましたが難しく理解が出来ませんでした。

またこちらの影を受ける箇所をコピペしてみましたがコンパイルエラーが出て解決できませんでした

補足情報

Unity2020.3.11f1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ご提示の「ライトプローブ - 技術的な情報 - Unity マニュアル」の情報は、内部まで分け入ってライティングの動作をカスタマイズしたい場合には取っかかりになるかもしれませんが、たいていの場合は詳細に立ち入らなくてもUnityが用意している簡単な関数やマクロを利用すれば十分だろうと思います。
むしろそうした方が、他のUnityの標準的シェーダーの描画結果とマッチした描画を行えて好ましいんじゃないでしょうか。

※ですが、ご興味がありましたら調べてみるのは大いに結構なことかと思います。要するに、個々のライトプローブやそれらを合成したデータは27個の数値で表現されていて、その割合で9つの基底関数(「球面調和関数 - Wikipedia」の図の上から3段目まで...高校や大学で化学を履修した経験がありましたら、電子の軌道に関する講義であんなへんてこなヒョウタン型を見かけたことがあるかもしれません)を合成することで、大ざっぱながらキューブマップのように全天球から色を取得できる関数を作っているということなんでしょう。離散コサイン変換の球面バージョンの親戚のようなものと言えるかもしれません。

Transparentなunlitシェーダに影を落としたい」の方はUnlitをご希望のようでしたので、あちらに投稿しましたシェーダーは影以外の照明効果は受けないようになっております。もっとご質問者さんの用途に適した形に改修できないかと思いまして、下記のようなシェーダーを作ってみました。

ShaderLab

1Shader "Custom/ShadowReceivableTransparent" 2{ 3 Properties 4 { 5 _MainTex ("Albedo Map", 2D) = "white" {} 6 _Color ("Albedo", Color) = (1.0, 1.0, 1.0, 1.0) 7 [Toggle(_USE_NORMAL_MAP)] _UseNormalMap("Use Normal Map", Float) = 0.0 8 [NoScaleOffset][Normal] _BumpMap ("Normal Map", 2D) = "bump" {} 9 _BumpScale ("Normal Scale", Range(-1.0, 1.0)) = 1.0 10 _Glossiness ("Smoothness", Range(0.0, 1.0)) = 0.5 11 _Metallic ("Metallic", Range(0.0, 1.0)) = 0.0 12 [Toggle(_USE_REFRACTION)] _UseRefraction("Use Refraction", Float) = 0.0 13 _Refraction ("Refraction", Range(1.0, 2.0)) = 1.0 14 _RefractionOffset ("Refraction Offset", Range(0.0, 10.0)) = 1.0 15 [Toggle(_USE_EXTERNAL_GRAB_TEXTURE)] _UseExternalGrabTexture("Use External Grab Texture", Float) = 0.0 16 [NoScaleOffset] _ExternalGrabTexture ("External Grab Texture", 2D) = "white" {} 17 _BlendingRatio ("External Grab Texture Blending Ratio", Range(0.0, 1.0)) = 1.0 18 } 19 20 CGINCLUDE 21 #define UNITY_SETUP_BRDF_INPUT MetallicSetup 22 ENDCG 23 24 SubShader 25 { 26 Tags 27 { 28 "Queue"= "AlphaTest" 29 "RenderType" = "TransparentCutout" 30 } 31 32 // ShadowCasterパスは以前のものを踏襲しつつ、表面のディザリングノイズを防止するよう改修 33 Pass 34 { 35 Name "ShadowCaster" 36 Tags { "LightMode" = "ShadowCaster" } 37 ZWrite On ZTest LEqual Cull Off 38 CGPROGRAM 39 #define UNITY_STANDARD_USE_DITHER_MASK 1 40 #define _ALPHAPREMULTIPLY_ON 1 41 #pragma target 3.0 42 #pragma multi_compile_shadowcaster 43 #pragma vertex vert 44 #pragma fragment frag 45 #include "UnityStandardShadow.cginc" 46 struct VertexOutput 47 { 48 V2F_SHADOW_CASTER_NOPOS 49 float2 tex : TEXCOORD1; 50 }; 51 void vert(VertexInput v, out VertexOutput o, out float4 opos: SV_POSITION) 52 { 53 TRANSFER_SHADOW_CASTER_NOPOS(o, opos) 54 o.tex = TRANSFORM_TEX(v.uv0, _MainTex); 55 } 56 half4 frag(VertexOutput i, UNITY_VPOS_TYPE vpos: VPOS): SV_Target 57 { 58 half alpha = tex2D(_MainTex, i.tex.xy).a * _Color.a; 59 alpha = tex3D(_DitherMaskLOD, float3(vpos.xy * 0.25, alpha * 0.9375)).a; 60 alpha = lerp(1.0, alpha, sign(dot(unity_LightShadowBias, unity_LightShadowBias))); 61 clip(alpha - 0.01); 62 SHADOW_CASTER_FRAGMENT(i) 63 } 64 ENDCG 65 } 66 67 // メインの描画前に、これまでの描画結果をキャプチャーする 68 GrabPass {} 69 70 // メイン部分は不透明サーフェイスシェーダーのスタイルに沿って記述する 71 CGPROGRAM 72 #pragma surface surf Standard fullforwardshadows 73 #pragma multi_compile_local _ _USE_NORMAL_MAP 74 #pragma target 3.0 75 sampler2D _MainTex; 76 struct Input 77 { 78 float2 uv_MainTex; 79 }; 80 #if _USE_NORMAL_MAP 81 sampler2D _BumpMap; 82 half _BumpScale; 83 #endif 84 half _Glossiness; 85 half _Metallic; 86 fixed4 _Color; 87 void surf(Input IN, inout SurfaceOutputStandard o) 88 { 89 fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; 90 o.Albedo = c.rgb; 91 #if _USE_NORMAL_MAP 92 o.Normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale); 93 #endif 94 o.Metallic = _Metallic; 95 o.Smoothness = _Glossiness; 96 o.Alpha = c.a; 97 } 98 ENDCG 99 100 // メイン描画後にキャプチャー結果を重ね描きし、透明になったように見せかける 101 pass 102 { 103 Name "MakeTransparent" 104 Blend SrcAlpha OneMinusSrcAlpha 105 ZWrite Off ZTest LEqual 106 CGPROGRAM 107 #pragma multi_compile_local _ _USE_EXTERNAL_GRAB_TEXTURE 108 #pragma multi_compile_local _ _USE_NORMAL_MAP 109 #pragma multi_compile_local _ _USE_REFRACTION 110 #pragma vertex vert 111 #pragma fragment frag 112 #include "UnityStandardUtils.cginc" 113 sampler2D _GrabTexture; 114 #if _USE_EXTERNAL_GRAB_TEXTURE 115 sampler2D _ExternalGrabTexture; 116 float _BlendingRatio; 117 #endif 118 sampler2D _MainTex; 119 float4 _MainTex_ST; 120 fixed4 _Color; 121 #if _USE_NORMAL_MAP 122 sampler2D _BumpMap; 123 half _BumpScale; 124 #endif 125 #if _USE_REFRACTION 126 float _Refraction; 127 float _RefractionOffset; 128 #endif 129 struct v2f 130 { 131 float4 pos : SV_POSITION; 132 float2 uv : TEXCOORD0; 133 float3 viewPos : TEXCOORD1; 134 #if _USE_REFRACTION 135 float3 viewNormal : TEXCOORD2; 136 #if _USE_NORMAL_MAP 137 float4 viewTangent : TEXCOORD3; 138 #endif 139 #endif 140 }; 141 v2f vert(appdata_tan v) 142 { 143 v2f o; 144 o.pos = UnityObjectToClipPos(v.vertex); 145 o.uv = TRANSFORM_TEX(v.texcoord.xy, _MainTex); 146 o.viewPos = UnityObjectToViewPos(v.vertex); 147 #if _USE_REFRACTION 148 o.viewNormal = mul(UNITY_MATRIX_V, UnityObjectToWorldNormal(v.normal)).xyz; 149 #if _USE_NORMAL_MAP 150 o.viewTangent = float4(mul(UNITY_MATRIX_V, UnityObjectToWorldDir(v.tangent.xyz)).xyz, v.tangent.w); 151 #endif 152 #endif 153 return o; 154 } 155 half4 frag(v2f i): SV_Target 156 { 157 float3 viewPos = i.viewPos; 158 #if _USE_REFRACTION 159 float3 viewDir = any(UNITY_MATRIX_P._41_42_43) ? normalize(i.viewPos) : float3(0.0, 0.0, -1.0); 160 float3 viewNormal = normalize(i.viewNormal); 161 #if _USE_NORMAL_MAP 162 float3 viewTangent = normalize(i.viewTangent.xyz); 163 float3 viewBinormal = cross(viewTangent, viewNormal) * i.viewTangent.w * unity_WorldTransformParams.w; 164 float3 unpackedNormal = UnpackScaleNormal(tex2D(_BumpMap, i.uv), _BumpScale); 165 float3 viewModifiedNormal = mul(unpackedNormal, float3x3(viewTangent, viewBinormal, viewNormal)); 166 #else 167 float3 viewModifiedNormal = viewNormal; 168 #endif 169 viewPos += refract(viewDir, viewModifiedNormal, 1.0 / _Refraction) * _RefractionOffset; 170 #endif 171 float4 clipPos = mul(UNITY_MATRIX_P, float4(viewPos, 1.0)); 172 half3 color = tex2Dproj(_GrabTexture, ComputeGrabScreenPos(clipPos)).rgb; 173 float alpha = 1.0 - (tex2D(_MainTex, i.uv) * _Color).a; 174 #if _USE_EXTERNAL_GRAB_TEXTURE 175 color = lerp(color, tex2Dproj(_ExternalGrabTexture, ComputeScreenPos(clipPos)).rgb, _BlendingRatio); 176 #endif 177 return half4(color, alpha); 178 } 179 ENDCG 180 } 181 } 182} 183

一般的なシェーダーと同様のプロパティを持たせたつもりですので、あらかたの項目はプロパティ名から機能を察していただけるかと思うのですが、特徴的な点として「Use External Grab Texture」のオプションと、テクスチャをセットするための「External Grab Texture」というプロパティを設けてあります。

下図はこのシェーダーを使ったマテリアルを持つ球体をシーンに置き、影を作るための柱を立て、赤色と緑色のライトで2方向から照らしたものです。マテリアルの透明度を変化させてみると、Use External Grab Textureがオフだと完全透明の時でも何もない空間に影だけが落ちた映像になってしまいます。

図1

Unityのレンダリングパイプラインでは、メインのレンダリングに入る前に各ライト毎に下図のような影画像が生成されるようになっています。この時点で球体が存在する前提での影になってしまっており、この影響を取り除くのはちょっと難しいところがあります...

図2

図3

そこでカメラをもう一つ用意し、メインカメラと同じ位置・向きに配置します。球体には専用のレイヤーを割り当て、この背景用カメラのCulling Maskからはそのレイヤーを除外します。

図4

つまり下図のように、球体がない映像を撮影させるわけです。

図5

この映像をレンダーテクスチャ上に描画させ、球体のマテリアルのExternal Grab Textureにそれをセットします。そのような下準備を行った上でUse External Grab Textureをオンにすると、背景映像としてそのテクスチャを使用するようになるため影を消すことができるはずです(微妙な誤差のためか、オブジェクトの縁にわずかなゴミが生じてしまうかもしれませんがご容赦ください...)。

図6

こういった「背景映像を撮影し、それを上乗せすることで透明になったように見せかける」という方式は、普通の透明マテリアルより若干描画コストがかさんでしまう弱点がありますが、背景をテクスチャとして描画時に使用できるというメリットもあるはずです。
ですので、たとえば背景映像をひずませることで、下図のような風変わりなマテリアルを作ることも可能かと思います。

図7

投稿2021/06/19 20:24

Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aiueoao

2021/06/20 01:41

作っていただいたシェーダで目的を果たせました!ありがとうございます! >個々のライトプローブやそれらを合成したデータは27個の数値で表現されていて~ 圧倒的難易度ですね。私の勉強不足ですが...! >特徴的な点として「Use External Grab Texture」のオプションと~ 凄すぎて使いこなせる自信はありませんが、表現の幅をかなり増やせそうですね この度は貴重なお時間を頂きまして、また詳しい説明をして頂き大変ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問