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

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

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

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

Unity

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

Q&A

解決済

2回答

2110閲覧

SkyboxをCubemapに設定すると太陽が表示されなくなる

Yukirr4_

総合スコア728

Unity3D

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

Unity

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

0グッド

0クリップ

投稿2020/07/15 09:50

編集2020/07/15 10:15

Skyboxを作ったものに変更したところ(シェーダはSkybox/Cubemap)、
ゲームカメラに太陽が表示されなくなってしまいました。

その場でSkyboxをデフォルトのものに戻すと太陽が表示されるので、
他の環境は関係ないと思います。

このSkyboxで太陽を表示させたいのですが、
どなたかSkyboxについて詳しい方回答お願いします。

####追記
https://www.reddit.com/r/Unity3D/comments/721ctv/standard_skybox_directional_light_results_in_an/
このSkyboxは太陽を描写する処理が含まれていないようなのですが、代わりに良いものがあれば教えていただければ嬉しいです。
スカイボックスのテクスチャはpng1枚です。

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

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

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

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

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

guest

回答2

0

パート2

ShaderLab

1 float far = 0.0; 2 half3 cIn, cOut; 3 4 if(eyeRay.y >= 0.0) 5 { 6 // Sky 7 // Calculate the length of the "atmosphere" 8 far = sqrt(kOuterRadius2 + kInnerRadius2 * eyeRay.y * eyeRay.y - kInnerRadius2) - kInnerRadius * eyeRay.y; 9 10 float3 pos = cameraPos + far * eyeRay; 11 12 // Calculate the ray's starting position, then calculate its scattering offset 13 float height = kInnerRadius + kCameraHeight; 14 float depth = exp(kScaleOverScaleDepth * (-kCameraHeight)); 15 float startAngle = dot(eyeRay, cameraPos) / height; 16 float startOffset = depth*scale(startAngle); 17 18 // Initialize the scattering loop variables 19 float sampleLength = far / kSamples; 20 float scaledLength = sampleLength * kScale; 21 float3 sampleRay = eyeRay * sampleLength; 22 float3 samplePoint = cameraPos + sampleRay * 0.5; 23 24 // Now loop through the sample rays 25 float3 frontColor = float3(0.0, 0.0, 0.0); 26 // Weird workaround: WP8 and desktop FL_9_3 do not like the for loop here 27 // (but an almost identical loop is perfectly fine in the ground calculations below) 28 // Just unrolling this manually seems to make everything fine again. 29 //for(int i=0; i<int(kSamples); i++) 30 { 31 float height = length(samplePoint); 32 float depth = exp(kScaleOverScaleDepth * (kInnerRadius - height)); 33 float lightAngle = dot(_WorldSpaceLightPos0.xyz, samplePoint) / height; 34 float cameraAngle = dot(eyeRay, samplePoint) / height; 35 float scatter = (startOffset + depth*(scale(lightAngle) - scale(cameraAngle))); 36 float3 attenuate = exp(-clamp(scatter, 0.0, kMAX_SCATTER) * (kInvWavelength * kKr4PI + kKm4PI)); 37 frontColor += attenuate * (depth * scaledLength); 38 samplePoint += sampleRay; 39 } 40 { 41 float height = length(samplePoint); 42 float depth = exp(kScaleOverScaleDepth * (kInnerRadius - height)); 43 float lightAngle = dot(_WorldSpaceLightPos0.xyz, samplePoint) / height; 44 float cameraAngle = dot(eyeRay, samplePoint) / height; 45 float scatter = (startOffset + depth*(scale(lightAngle) - scale(cameraAngle))); 46 float3 attenuate = exp(-clamp(scatter, 0.0, kMAX_SCATTER) * (kInvWavelength * kKr4PI + kKm4PI)); 47 frontColor += attenuate * (depth * scaledLength); 48 samplePoint += sampleRay; 49 } 50 51 // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader 52 cIn = frontColor * (kInvWavelength * kKrESun); 53 cOut = frontColor * kKmESun; 54 } 55 else 56 { 57 // Ground 58 far = (-kCameraHeight) / (min(-0.001, eyeRay.y)); 59 60 float3 pos = cameraPos + far * eyeRay; 61 62 // Calculate the ray's starting position, then calculate its scattering offset 63 float depth = exp((-kCameraHeight) * (1.0/kScaleDepth)); 64 float cameraAngle = dot(-eyeRay, pos); 65 float lightAngle = dot(_WorldSpaceLightPos0.xyz, pos); 66 float cameraScale = scale(cameraAngle); 67 float lightScale = scale(lightAngle); 68 float cameraOffset = depth*cameraScale; 69 float temp = (lightScale + cameraScale); 70 71 // Initialize the scattering loop variables 72 float sampleLength = far / kSamples; 73 float scaledLength = sampleLength * kScale; 74 float3 sampleRay = eyeRay * sampleLength; 75 float3 samplePoint = cameraPos + sampleRay * 0.5; 76 77 // Now loop through the sample rays 78 float3 frontColor = float3(0.0, 0.0, 0.0); 79 float3 attenuate; 80 //for(int i=0; i<int(kSamples); i++) // Loop removed because we kept hitting SM2.0 temp variable limits. Doesn't affect the image too much. 81 { 82 float height = length(samplePoint); 83 float depth = exp(kScaleOverScaleDepth * (kInnerRadius - height)); 84 float scatter = depth*temp - cameraOffset; 85 attenuate = exp(-clamp(scatter, 0.0, kMAX_SCATTER) * (kInvWavelength * kKr4PI + kKm4PI)); 86 frontColor += attenuate * (depth * scaledLength); 87 samplePoint += sampleRay; 88 } 89 90 cIn = frontColor * (kInvWavelength * kKrESun + kKmESun); 91 cOut = clamp(attenuate, 0.0, 1.0); 92 } 93 94 #if SKYBOX_SUNDISK == SKYBOX_SUNDISK_HQ 95 o.vertexForSun = -eyeRay; 96 #elif SKYBOX_SUNDISK == SKYBOX_SUNDISK_SIMPLE 97 o.rayDir = half3(-eyeRay); 98 #else 99 o.skyGroundFactor = -eyeRay.y / SKY_GROUND_THRESHOLD; 100 #endif 101 102 #if SKYBOX_SUNDISK != SKYBOX_SUNDISK_NONE 103 // The sun should have a stable intensity in its course in the sky. Moreover it should match the highlight of a purely specular material. 104 // This matching was done using the standard shader BRDF1 on the 5/31/2017 105 // Finally we want the sun to be always bright even in LDR thus the normalization of the lightColor for low intensity. 106 half lightColorIntensity = clamp(length(_LightColor0.xyz), 0.25, 1); 107 #if SKYBOX_SUNDISK == SKYBOX_SUNDISK_SIMPLE 108 o.sunColor = kSimpleSundiskIntensityFactor * saturate(cOut * kSunScale) * _LightColor0.xyz / lightColorIntensity; 109 #else // SKYBOX_SUNDISK_HQ 110 o.sunColor = kHDSundiskIntensityFactor * saturate(cOut) * _LightColor0.xyz / lightColorIntensity; 111 #endif 112 #endif 113 114 #if defined(UNITY_COLORSPACE_GAMMA) && SKYBOX_COLOR_IN_TARGET_COLOR_SPACE 115 #if SKYBOX_SUNDISK != SKYBOX_SUNDISK_NONE 116 o.sunColor = sqrt(o.sunColor); 117 #endif 118 #endif 119 120 return o; 121 } 122 123 // Calculates the Mie phase function 124 half getMiePhase(half eyeCos, half eyeCos2) 125 { 126 half temp = 1.0 + MIE_G2 - 2.0 * MIE_G * eyeCos; 127 temp = pow(temp, pow(_SunSize,0.65) * 10); 128 temp = max(temp,1.0e-4); // prevent division by zero, esp. in half precision 129 temp = 1.5 * ((1.0 - MIE_G2) / (2.0 + MIE_G2)) * (1.0 + eyeCos2) / temp; 130 #if defined(UNITY_COLORSPACE_GAMMA) && SKYBOX_COLOR_IN_TARGET_COLOR_SPACE 131 temp = pow(temp, .454545); 132 #endif 133 return temp; 134 } 135 136 // Calculates the sun shape 137 half calcSunAttenuation(half3 lightPos, half3 ray) 138 { 139 #if SKYBOX_SUNDISK == SKYBOX_SUNDISK_SIMPLE 140 half3 delta = lightPos - ray; 141 half dist = length(delta); 142 half spot = 1.0 - smoothstep(0.0, _SunSize, dist); 143 return spot * spot; 144 #else // SKYBOX_SUNDISK_HQ 145 half focusedEyeCos = pow(saturate(dot(lightPos, ray)), _SunSizeConvergence); 146 return getMiePhase(-focusedEyeCos, focusedEyeCos * focusedEyeCos); 147 #endif 148 } 149 150 fixed4 frag (v2f i) : SV_Target 151 { 152 // if y > 1 [eyeRay.y < -SKY_GROUND_THRESHOLD] - ground 153 // if y >= 0 and < 1 [eyeRay.y <= 0 and > -SKY_GROUND_THRESHOLD] - horizon 154 // if y < 0 [eyeRay.y > 0] - sky 155 #if SKYBOX_SUNDISK == SKYBOX_SUNDISK_HQ 156 half3 ray = normalize(i.vertexForSun.xyz); 157 half y = ray.y / SKY_GROUND_THRESHOLD; 158 #elif SKYBOX_SUNDISK == SKYBOX_SUNDISK_SIMPLE 159 half3 ray = i.rayDir.xyz; 160 half y = ray.y / SKY_GROUND_THRESHOLD; 161 #else 162 half y = i.skyGroundFactor; 163 #endif 164 165 half4 tex = texCUBE (_Tex, i.texcoord); 166 half3 c = DecodeHDR (tex, _Tex_HDR); 167 c = c * _Tint.rgb * unity_ColorSpaceDouble.rgb; 168 c *= _Exposure; 169 170 #if SKYBOX_SUNDISK != SKYBOX_SUNDISK_NONE 171 if(y < 0.0) 172 { 173 c += i.sunColor * calcSunAttenuation(_WorldSpaceLightPos0.xyz, -ray); 174 } 175 #endif 176 177 return half4(c, 1); 178 } 179 ENDCG 180 } 181 } 182 Fallback Off 183}

実験用の背景としては下図のような画像を使用したところ...

図1

下図のように、太陽の方角に光が描かれました。GIFにつき階調が十分表現できていませんが、実際の見た目はちょっと試した限りでは問題なさそうに見えました。

図2

投稿2020/07/15 20:16

Bongo

総合スコア10807

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

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

0

ベストアンサー

ご提示のStandard skybox + directional light results in an actual sun. When changing the skybox, the sun is behind the skybox. Is there a workaround to actually see it? : Unity3Dで言及されているように、デフォルトのスカイボックスの太陽はSkybox/Proceduralシェーダーが描いているものであり、Skybox/Cubemapには太陽を描く機能はないでしょう。

Skybox/Cubemapを改造した(というかSkybox/Proceduralの記述をペタペタ貼り付けただけです...やっつけ仕事ですみません)下記のようなSkybox/Cubemap (Sun Disk)を作り、

ShaderLab

1// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 3Shader "Skybox/Cubemap (Sun Disk)" { 4 Properties { 5 _Tint ("Tint Color", Color) = (.5, .5, .5, .5) 6 [Gamma] _Exposure ("Exposure", Range(0, 8)) = 1.0 7 _Rotation ("Rotation", Range(0, 360)) = 0 8 [NoScaleOffset] _Tex ("Cubemap (HDR)", Cube) = "grey" {} 9 10 [KeywordEnum(None, Simple, High Quality)] _SunDisk ("Sun", Int) = 2 11 _SunSize ("Sun Size", Range(0,1)) = 0.04 12 _SunSizeConvergence("Sun Size Convergence", Range(1,10)) = 5 13 _AtmosphereThickness ("Atmosphere Thickness", Range(0,5)) = 1.0 14 } 15 16 SubShader { 17 Tags { "Queue"="Background" "RenderType"="Background" "PreviewType"="Skybox" } 18 Cull Off ZWrite Off 19 20 Pass { 21 22 CGPROGRAM 23 #pragma vertex vert 24 #pragma fragment frag 25 #pragma target 2.0 26 27 #pragma multi_compile_local _SUNDISK_NONE _SUNDISK_SIMPLE _SUNDISK_HIGH_QUALITY 28 29 #include "UnityCG.cginc" 30 #include "Lighting.cginc" 31 32 samplerCUBE _Tex; 33 half4 _Tex_HDR; 34 half4 _Tint; 35 half _Exposure; 36 float _Rotation; 37 38 half _SunSize; 39 half _SunSizeConvergence; 40 half _AtmosphereThickness; 41 42 #if defined(UNITY_COLORSPACE_GAMMA) 43 #define GAMMA 2 44 #define COLOR_2_GAMMA(color) color 45 #define COLOR_2_LINEAR(color) color*color 46 #define LINEAR_2_OUTPUT(color) sqrt(color) 47 #else 48 #define GAMMA 2.2 49 // HACK: to get gfx-tests in Gamma mode to agree until UNITY_ACTIVE_COLORSPACE_IS_GAMMA is working properly 50 #define COLOR_2_GAMMA(color) ((unity_ColorSpaceDouble.r>2.0) ? pow(color,1.0/GAMMA) : color) 51 #define COLOR_2_LINEAR(color) color 52 #define LINEAR_2_LINEAR(color) color 53 #endif 54 55 // RGB wavelengths 56 // .35 (.62=158), .43 (.68=174), .525 (.75=190) 57 static const float3 kDefaultScatteringWavelength = float3(.65, .57, .475); 58 static const float3 kVariableRangeForScatteringWavelength = float3(.15, .15, .15); 59 60 #define OUTER_RADIUS 1.025 61 static const float kOuterRadius = OUTER_RADIUS; 62 static const float kOuterRadius2 = OUTER_RADIUS*OUTER_RADIUS; 63 static const float kInnerRadius = 1.0; 64 static const float kInnerRadius2 = 1.0; 65 66 static const float kCameraHeight = 0.0001; 67 68 #define kRAYLEIGH (lerp(0.0, 0.0025, pow(_AtmosphereThickness,2.5))) // Rayleigh constant 69 #define kMIE 0.0010 // Mie constant 70 #define kSUN_BRIGHTNESS 20.0 // Sun brightness 71 72 #define kMAX_SCATTER 50.0 // Maximum scattering value, to prevent math overflows on Adrenos 73 74 static const half kHDSundiskIntensityFactor = 15.0; 75 static const half kSimpleSundiskIntensityFactor = 27.0; 76 77 static const half kSunScale = 400.0 * kSUN_BRIGHTNESS; 78 static const float kKmESun = kMIE * kSUN_BRIGHTNESS; 79 static const float kKm4PI = kMIE * 4.0 * 3.14159265; 80 static const float kScale = 1.0 / (OUTER_RADIUS - 1.0); 81 static const float kScaleDepth = 0.25; 82 static const float kScaleOverScaleDepth = (1.0 / (OUTER_RADIUS - 1.0)) / 0.25; 83 static const float kSamples = 2.0; // THIS IS UNROLLED MANUALLY, DON'T TOUCH 84 85 #define MIE_G (-0.990) 86 #define MIE_G2 0.9801 87 88 #define SKY_GROUND_THRESHOLD 0.02 89 90 // sun disk rendering: 91 // no sun disk - the fastest option 92 #define SKYBOX_SUNDISK_NONE 0 93 // simplistic sun disk - without mie phase function 94 #define SKYBOX_SUNDISK_SIMPLE 1 95 // full calculation - uses mie phase function 96 #define SKYBOX_SUNDISK_HQ 2 97 98 // uncomment this line and change SKYBOX_SUNDISK_SIMPLE to override material settings 99 // #define SKYBOX_SUNDISK SKYBOX_SUNDISK_SIMPLE 100 101 #ifndef SKYBOX_SUNDISK 102 #if defined(_SUNDISK_NONE) 103 #define SKYBOX_SUNDISK SKYBOX_SUNDISK_NONE 104 #elif defined(_SUNDISK_SIMPLE) 105 #define SKYBOX_SUNDISK SKYBOX_SUNDISK_SIMPLE 106 #else 107 #define SKYBOX_SUNDISK SKYBOX_SUNDISK_HQ 108 #endif 109 #endif 110 111 #ifndef SKYBOX_COLOR_IN_TARGET_COLOR_SPACE 112 #if defined(SHADER_API_MOBILE) 113 #define SKYBOX_COLOR_IN_TARGET_COLOR_SPACE 1 114 #else 115 #define SKYBOX_COLOR_IN_TARGET_COLOR_SPACE 0 116 #endif 117 #endif 118 119 float3 RotateAroundYInDegrees (float3 vertex, float degrees) 120 { 121 float alpha = degrees * UNITY_PI / 180.0; 122 float sina, cosa; 123 sincos(alpha, sina, cosa); 124 float2x2 m = float2x2(cosa, -sina, sina, cosa); 125 return float3(mul(m, vertex.xz), vertex.y).xzy; 126 } 127 128 struct appdata_t { 129 float4 vertex : POSITION; 130 UNITY_VERTEX_INPUT_INSTANCE_ID 131 }; 132 133 struct v2f { 134 float4 vertex : SV_POSITION; 135 float3 texcoord : TEXCOORD0; 136 137 #if SKYBOX_SUNDISK == SKYBOX_SUNDISK_HQ 138 // for HQ sun disk, we need vertex itself to calculate ray-dir per-pixel 139 float3 vertexForSun : TEXCOORD1; 140 #elif SKYBOX_SUNDISK == SKYBOX_SUNDISK_SIMPLE 141 half3 rayDir : TEXCOORD1; 142 #else 143 // as we dont need sun disk we need just rayDir.y (sky/ground threshold) 144 half skyGroundFactor : TEXCOORD1; 145 #endif 146 147 #if SKYBOX_SUNDISK != SKYBOX_SUNDISK_NONE 148 half3 sunColor : TEXCOORD3; 149 #endif 150 151 UNITY_VERTEX_OUTPUT_STEREO 152 }; 153 154 float scale(float inCos) 155 { 156 float x = 1.0 - inCos; 157 return 0.25 * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); 158 } 159 160 v2f vert (appdata_t v) 161 { 162 v2f o; 163 UNITY_SETUP_INSTANCE_ID(v); 164 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); 165 float3 rotated = RotateAroundYInDegrees(v.vertex, _Rotation); 166 o.vertex = UnityObjectToClipPos(rotated); 167 o.texcoord = v.vertex.xyz; 168 169 float3 kSkyTintInGammaSpace = COLOR_2_GAMMA(_Tint); // convert tint from Linear back to Gamma 170 float3 kScatteringWavelength = lerp ( 171 kDefaultScatteringWavelength-kVariableRangeForScatteringWavelength, 172 kDefaultScatteringWavelength+kVariableRangeForScatteringWavelength, 173 half3(1,1,1) - kSkyTintInGammaSpace); // using Tint in sRGB gamma allows for more visually linear interpolation and to keep (.5) at (128, gray in sRGB) point 174 float3 kInvWavelength = 1.0 / pow(kScatteringWavelength, 4); 175 176 float kKrESun = kRAYLEIGH * kSUN_BRIGHTNESS; 177 float kKr4PI = kRAYLEIGH * 4.0 * 3.14159265; 178 179 float3 cameraPos = float3(0,kInnerRadius + kCameraHeight,0); // The camera's current position 180 181 float3 eyeRay = normalize(mul((float3x3)unity_ObjectToWorld, v.vertex.xyz));

(コードの途中ですが、長すぎて別回答に分断します...パート2へ続く)

投稿2020/07/15 20:15

Bongo

総合スコア10807

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

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

Yukirr4_

2020/07/16 11:02 編集

回答ありがとうございます! 本当に助かりました!太陽を表示するのにもこれほどのコードが必要なのですね... 勉強になりました。これからもよろしくお願いいたしますmm
Bongo

2020/07/16 12:09

実際のところ、光源の方角に太陽っぽい円を描くだけならもっとシンプルにできると思います。 Skybox/Proceduralの場合は大気散乱をシミュレートして空の色を決める仕掛けになっており(光源の角度が水平に近づくと夕焼けのように空がオレンジ色になったりしますよね)、コードがだいぶ複雑になっているようです。せっかくなのでSkybox/Proceduralと同じような品質の太陽を描けた方がいいかな...と思ってSkybox/Proceduralのコードを流用することにしたのですが、いざやってみると太陽を描く部分も散乱の計算過程に密接に関連していたため、結局ほとんどのコードを写し込むことになってしまいました...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問