summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2024-10-11 18:39:50 -0700
committeryum <yum.food.vr@gmail.com>2024-10-11 18:39:50 -0700
commit0e39a7ef25e7938b84736519057c06c8d84856cc (patch)
tree7af1f8822572aa13747e913fbd8b5ca7d5a82819
parente193c86c869b84dfaaa26465c0e6fb923a27631c (diff)
Fog performance optimizations
* Rename albedo cutoff to alpha cutoff * Add LODs for calculating fog density * Use 3D noise texture to speed up density calculation * Eliminate low impact octaves from density calculation * Add support for multiple emitters
-rw-r--r--Editor/generate_3d_noise.cs67
-rw-r--r--Editor/tooner.cs46
-rw-r--r--cnlohr.cginc26
-rw-r--r--feature_macros.cginc2
-rw-r--r--fog.cginc150
-rw-r--r--globals.cginc27
-rw-r--r--tooner.shader29
7 files changed, 277 insertions, 70 deletions
diff --git a/Editor/generate_3d_noise.cs b/Editor/generate_3d_noise.cs
new file mode 100644
index 0000000..4352d99
--- /dev/null
+++ b/Editor/generate_3d_noise.cs
@@ -0,0 +1,67 @@
+// !! AI ARTIFACT !!
+// This code was originally generated by Claude 3.5 Sonnet.
+using UnityEngine;
+using UnityEditor;
+
+public class WhiteNoiseTextureGenerator : EditorWindow
+{
+ private int textureWidth = 32;
+ private int textureHeight = 32;
+ private int textureDepth = 32;
+ private string textureName = "WhiteNoiseTexture";
+
+ [MenuItem("Tools/yum_food/White Noise Texture Generator")]
+ public static void ShowWindow()
+ {
+ GetWindow<WhiteNoiseTextureGenerator>("White Noise Texture Generator");
+ }
+
+ private void OnGUI()
+ {
+ GUILayout.Label("White Noise Texture Generator", EditorStyles.boldLabel);
+
+ textureWidth = EditorGUILayout.IntField("Texture Width", textureWidth);
+ textureHeight = EditorGUILayout.IntField("Texture Height", textureHeight);
+ textureDepth = EditorGUILayout.IntField("Texture Depth", textureDepth);
+ textureName = EditorGUILayout.TextField("Texture Name", textureName);
+
+ if (GUILayout.Button("Generate Texture"))
+ {
+ if (textureWidth <= 0 || textureHeight <= 0 || textureDepth <= 0)
+ {
+ EditorUtility.DisplayDialog("Error", "Texture dimensions must be greater than zero.", "OK");
+ return;
+ }
+
+ GenerateWhiteNoiseTexture();
+ }
+ }
+
+ private void GenerateWhiteNoiseTexture()
+ {
+ Texture3D texture = new Texture3D(textureWidth, textureHeight, textureDepth, TextureFormat.RGBA32, false);
+ Color[] colors = new Color[textureWidth * textureHeight * textureDepth];
+
+ for (int z = 0; z < textureDepth; z++)
+ {
+ for (int y = 0; y < textureHeight; y++)
+ {
+ for (int x = 0; x < textureWidth; x++)
+ {
+ int index = x + y * textureWidth + z * textureWidth * textureHeight;
+ colors[index] = new Color(Random.value, Random.value, Random.value, 1f);
+ }
+ }
+ }
+
+ texture.SetPixels(colors);
+ texture.Apply();
+
+ string path = $"Assets/{textureName}.asset";
+ AssetDatabase.CreateAsset(texture, path);
+ AssetDatabase.SaveAssets();
+ AssetDatabase.Refresh();
+
+ EditorUtility.DisplayDialog("Success", $"White noise texture generated and saved at {path}", "OK");
+ }
+}
diff --git a/Editor/tooner.cs b/Editor/tooner.cs
index fdcb678..3c0b951 100644
--- a/Editor/tooner.cs
+++ b/Editor/tooner.cs
@@ -2033,10 +2033,16 @@ public class ToonerGUI : ShaderGUI {
FloatProperty(bc, "Noise exponent");
bc = FindProperty("_Gimmick_Fog_00_Normal_Cutoff");
RangeProperty(bc, "Normal cutoff");
- bc = FindProperty("_Gimmick_Fog_00_Albedo_Cutoff");
- RangeProperty(bc, "Albedo cutoff");
+ bc = FindProperty("_Gimmick_Fog_00_Alpha_Cutoff");
+ RangeProperty(bc, "Alpha cutoff");
bc = FindProperty("_Gimmick_Fog_00_Ray_Origin_Randomization");
RangeProperty(bc, "Ray origin randomization");
+ bc = FindProperty("_Gimmick_Fog_00_Lod_Half_Life");
+ FloatProperty(bc, "LOD half life");
+ bc = FindProperty("_Gimmick_Fog_00_Noise");
+ TexturePropertySingleLine(
+ MakeLabel(bc, "Noise"),
+ bc);
bc = FindProperty("_Gimmick_Fog_00_Emitter_Texture");
TexturePropertySingleLine(
@@ -2046,16 +2052,44 @@ public class ToonerGUI : ShaderGUI {
if (bc.textureValue) {
EditorGUI.indentLevel += 1;
- bc = FindProperty("_Gimmick_Fog_00_Emitter_Location");
+ bc = FindProperty("_Gimmick_Fog_00_Emitter0_Location");
VectorProperty(bc, "Location (world)");
- bc = FindProperty("_Gimmick_Fog_00_Emitter_Normal");
+ bc = FindProperty("_Gimmick_Fog_00_Emitter0_Normal");
VectorProperty(bc, "Normal (world)");
- bc = FindProperty("_Gimmick_Fog_00_Emitter_Scale_X");
+ bc = FindProperty("_Gimmick_Fog_00_Emitter0_Scale_X");
FloatProperty(bc, "Scale (x)");
- bc = FindProperty("_Gimmick_Fog_00_Emitter_Scale_Y");
+ bc = FindProperty("_Gimmick_Fog_00_Emitter0_Scale_Y");
FloatProperty(bc, "Scale (y)");
+
bc = FindProperty("_Gimmick_Fog_00_Emitter_Brightness");
FloatProperty(bc, "Brightness");
+ bc = FindProperty("_Gimmick_Fog_00_Emitter_Lod_Half_Life");
+ FloatProperty(bc, "LOD half life");
+
+ for (int i = 0; i < 2; i++) {
+ bc = FindProperty($"_Gimmick_Fog_00_Emitter{i+1}_Enable_Static");
+ enabled = (bc.floatValue != 0.0);
+ EditorGUI.BeginChangeCheck();
+ enabled = Toggle($"Enable emitter {i+1}", enabled);
+ EditorGUI.EndChangeCheck();
+ bc.floatValue = enabled ? 1.0f : 0.0f;
+ SetKeyword($"_GIMMICK_FOG_00_EMITTER_{i+1}", enabled);
+
+ if (enabled) {
+ EditorGUI.indentLevel += 1;
+
+ bc = FindProperty($"_Gimmick_Fog_00_Emitter{i+1}_Location");
+ VectorProperty(bc, "Location (world)");
+ bc = FindProperty($"_Gimmick_Fog_00_Emitter{i+1}_Normal");
+ VectorProperty(bc, "Normal (world)");
+ bc = FindProperty($"_Gimmick_Fog_00_Emitter{i+1}_Scale_X");
+ FloatProperty(bc, "Scale (x)");
+ bc = FindProperty($"_Gimmick_Fog_00_Emitter{i+1}_Scale_Y");
+ FloatProperty(bc, "Scale (y)");
+
+ EditorGUI.indentLevel -= 1;
+ }
+ }
EditorGUI.indentLevel -= 1;
}
diff --git a/cnlohr.cginc b/cnlohr.cginc
index c3163d2..73fb80c 100644
--- a/cnlohr.cginc
+++ b/cnlohr.cginc
@@ -68,14 +68,13 @@ float GetLinearZFromZDepth_WorksWithMirrors(float zDepthFromMap, float2 screenUV
float GetDepthOfWorldPos(float3 worldPos)
{
float3 full_vec_eye_to_geometry = worldPos - _WorldSpaceCameraPos;
- float3 world_dir = normalize(worldPos - _WorldSpaceCameraPos);
float4 objPos = mul(unity_WorldToObject, float4(worldPos, 1));
float4 clipPos = UnityObjectToClipPos(objPos);
float2 suv = clipPos * float2(0.5, 0.5 * _ProjectionParams.x);
float2 screenPos = TransformStereoScreenSpaceTex(suv + 0.5 * clipPos.w, clipPos.w);
- float perspective_divide = 1.0 / clipPos.w;
+ float perspective_divide = rcp(clipPos.w);
float perspective_factor = length(full_vec_eye_to_geometry * perspective_divide);
float2 screen_uv = screenPos.xy * perspective_divide;
float eye_depth_world =
@@ -85,4 +84,27 @@ float GetDepthOfWorldPos(float3 worldPos)
return eye_depth_world;
}
+float GetDepthOfWorldPos(
+ float3 full_vec_eye_to_geometry,
+ float3 worldPos)
+{
+ float4 objPos = mul(unity_WorldToObject, float4(worldPos, 1));
+ float4 clipPos = UnityObjectToClipPos(objPos);
+
+ float2 suv = clipPos * float2(0.5, 0.5 * _ProjectionParams.x);
+ bool suv_in_range =
+ (suv.x >= 0) * (suv.x <= 1) *
+ (suv.y >= 0) * (suv.y <= 1);
+ float2 screenPos = TransformStereoScreenSpaceTex(suv + 0.5 * clipPos.w, clipPos.w);
+
+ float perspective_divide = rcp(clipPos.w);
+ float perspective_factor = length(full_vec_eye_to_geometry * perspective_divide);
+ float2 screen_uv = screenPos.xy * perspective_divide;
+ float eye_depth_world =
+ GetLinearZFromZDepth_WorksWithMirrors(
+ SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screen_uv),
+ screen_uv) * perspective_factor;
+ return suv_in_range ? eye_depth_world : -1E6;
+}
+
#endif // __CNLOHR_INC
diff --git a/feature_macros.cginc b/feature_macros.cginc
index 2a68ff5..fa4e2c9 100644
--- a/feature_macros.cginc
+++ b/feature_macros.cginc
@@ -168,6 +168,8 @@
#pragma shader_feature_local _ SSR_MASK
#pragma shader_feature_local _ _GIMMICK_FOG_00
#pragma shader_feature_local _ _GIMMICK_FOG_00_EMITTER_TEXTURE
+#pragma shader_feature_local _ _GIMMICK_FOG_00_EMITTER_1
+#pragma shader_feature_local _ _GIMMICK_FOG_00_EMITTER_2
#endif // __FEATURE_MACROS_INC
diff --git a/fog.cginc b/fog.cginc
index f31a7d3..f02415f 100644
--- a/fog.cginc
+++ b/fog.cginc
@@ -17,43 +17,77 @@ struct Fog00PBR {
float ao;
};
-float map(float3 p) {
- float density = 0;
- float t = _Time[1] * 0.5;
+float perlin_noise_3d_tex(float3 p)
+{
+ float3 sq = floor(p);
+ float3 sqi = frac(p);
+
+ // 1/256 = 0.00390625
+ float r_lo = _Gimmick_Fog_00_Noise.SampleLevel(linear_repeat_s, p.xyz * 0.00390625, 0);
+
+ return r_lo;
+}
+
+float map(float3 p, float lod) {
+ float3 t = _Time[1] * 0.5;
float radius = saturate(_Gimmick_Fog_00_Radius - length(p));
- float tmp;
- tmp = perlin_noise_3d(p * _Gimmick_Fog_00_Noise_Scale * 3.1 + t) * radius * 0.5;
- density += tmp;
- tmp = perlin_noise_3d(p * _Gimmick_Fog_00_Noise_Scale * 1.7 + t) * radius * 0.5;
- density *= 0.5;
- density += tmp;
- tmp = perlin_noise_3d(p * _Gimmick_Fog_00_Noise_Scale * 1.0 + t) * radius * 0.5;
- density *= 0.5;
- density += tmp;
+
+ float3 pp = p * _Gimmick_Fog_00_Noise_Scale + t;
+ float density = perlin_noise_3d_tex(pp) * radius * 0.7;
density = pow(density, _Gimmick_Fog_00_Noise_Exponent);
- // Note: this term annihilates performance by creating large open areas. Long
- // avgerage view ray = bad perf!
- #if 1
- tmp = perlin_noise_3d(p * _Gimmick_Fog_00_Noise_Scale * 0.167 + t/4) * radius - 0.5;
- tmp *= 0.2;
- density += tmp;
- #endif
+ // This term creates large open areas
+ if (lod < 1) {
+ float tmp = perlin_noise_3d_tex(pp * 0.167 + t/4) * radius - 0.5;
+ // Aggressively dial down this parameter as density increases. We really
+ // need to keep paths short when density is high.
+ float density_performance_fix = rcp(_Gimmick_Fog_00_Density);
+ density_performance_fix *= density_performance_fix;
+ tmp *= 0.5 * density_performance_fix;
+ density += tmp;
+ }
return saturate(density);
}
-float3 get_normal(float3 p, float map_p) {
+float3 get_normal(float3 p, float map_p, float lod) {
float3 e = float3(0.001, 0, 0);
float center = map_p;
// Prevent NaN
float e2 = 1E-9;
return normalize(float3(
- map(p + e.xyz) - center,
- map(p + e.yxz) - center,
- map(p + e.zyx) - center) + e2);
+ map(p + e.xyz, lod) - center,
+ map(p + e.yxz, lod) - center,
+ map(p + e.zyx, lod) - center) + e2);
+}
+
+void getEmitterData(float3 p, float step_size,
+ float3 em_loc, float3 em_normal, float em_scale_x,
+ float em_scale_y, out float3 em_color, out float em_weight,
+ out float3 p_projected)
+{
+ // Project onto plane
+ const float3 p_to_emitter = p - em_loc;
+ const float2 emitter_scale = float2(em_scale_x, em_scale_y);
+ const float t = dot(p_to_emitter, em_normal);
+ float emitter_lod = floor(abs(t) / (_Gimmick_Fog_00_Emitter_Lod_Half_Life * step_size));
+ p_projected = p - t * em_normal;
+
+ p_projected -= em_loc;
+ bool in_range = (abs(p_projected.x) < emitter_scale.x) * (abs(p_projected.y) < emitter_scale.y) * (t > 0);
+
+ float2 emitter_uv = clamp(p_projected.xy, -emitter_scale, emitter_scale) / emitter_scale;
+ emitter_uv /= 2.0;
+ emitter_uv += 0.5;
+ // Go up one LOD every 5 meters
+ // TODO make this tunable
+ em_color = _Gimmick_Fog_00_Emitter_Texture.SampleLevel(linear_repeat_s, emitter_uv, emitter_lod);
+ em_color *= _Gimmick_Fog_00_Emitter_Brightness;
+ float emitter_dist = in_range ? abs(t) : 1000;
+ float emitter_falloff = min(1, rcp(pow(emitter_dist, 1.4)));
+ em_weight = in_range * emitter_falloff;
}
Fog00PBR getFog00(v2f i) {
@@ -108,42 +142,56 @@ Fog00PBR getFog00(v2f i) {
_Gimmick_Fog_00_Max_Ray / step_size,
world_pos_depth_hit_l / step_size));
step_count *= (1 - no_intersection);
+#define FOG_MAX_LOOP 128
+ step_count = min(step_count, FOG_MAX_LOOP);
float3 normal = i.normal;
float ao = 0;
for (uint ii = 0; ii < step_count; ii++) {
- float3 p = ro + (rd * step_size) * ii;
+ const float3 p = ro + (rd * step_size) * ii;
+ const float lod = floor((ii * step_size) / _Gimmick_Fog_00_Lod_Half_Life);
- const float col_gray = 0;
- const float map_p = map(p);
- float4 c = float4(col_gray, col_gray, col_gray, map_p);
+ const float map_p = map(p, lod);
+ float4 c = float4(0, 0, 0, map_p);
c.a = saturate(c.a * _Gimmick_Fog_00_Density * step_size);
#if defined(_GIMMICK_FOG_00_EMITTER_TEXTURE)
- // Project onto plane
- float3 p_to_emitter = p - _Gimmick_Fog_00_Emitter_Location;
- float3 emitter_normal = normalize(_Gimmick_Fog_00_Emitter_Normal);
- float2 emitter_scale = float2(_Gimmick_Fog_00_Emitter_Scale_X, _Gimmick_Fog_00_Emitter_Scale_Y);
-
- float t = dot(p_to_emitter, emitter_normal);
- float3 p_projected = p - t * emitter_normal;
-
- p_projected -= _Gimmick_Fog_00_Emitter_Location;
- bool in_range = (abs(p_projected.x) < emitter_scale.x) * (abs(p_projected.y) < emitter_scale.y) * (t > 0);
-
- float2 emitter_uv = clamp(p_projected.xy, -emitter_scale, emitter_scale) / emitter_scale;
- emitter_uv /= 2.0;
- emitter_uv += 0.5;
- float3 emitter_color = _Gimmick_Fog_00_Emitter_Texture.SampleLevel(linear_repeat_s, emitter_uv, 0);
- emitter_color *= _Gimmick_Fog_00_Emitter_Brightness;
- float emitter_dist = in_range ? abs(t) : 1000;
- // Inverse square is physically accurate, but this looks better.
- float emitter_falloff = min(1, rcp(pow(emitter_dist, 1.0)));
-#if 1
- c.rgb = lerp(c.rgb, emitter_color, in_range * emitter_falloff);
-#else
- c.rgb = emitter_color;
+ {
+ const float3 em_loc = _Gimmick_Fog_00_Emitter0_Location;
+ const float3 em_normal = normalize(_Gimmick_Fog_00_Emitter0_Normal);
+ const float em_scale_x = _Gimmick_Fog_00_Emitter0_Scale_X;
+ const float em_scale_y = _Gimmick_Fog_00_Emitter0_Scale_Y;
+
+ float3 em_color;
+ float em_weight;
+ float3 em_p;
+ getEmitterData(p, step_size, em_loc, em_normal, em_scale_x, em_scale_y, em_color, em_weight, em_p);
+#if defined(_GIMMICK_FOG_00_EMITTER_1)
+ const float3 em1_loc = _Gimmick_Fog_00_Emitter1_Location;
+ const float3 em1_normal = normalize(_Gimmick_Fog_00_Emitter1_Normal);
+ const float em1_scale_x = _Gimmick_Fog_00_Emitter1_Scale_X;
+ const float em1_scale_y = _Gimmick_Fog_00_Emitter1_Scale_Y;
+ float3 em1_color;
+ float em1_weight;
+ float3 em1_p;
+ getEmitterData(p, step_size, em1_loc, em1_normal, em1_scale_x, em1_scale_y, em1_color, em1_weight, em1_p);
+ em_color += em1_color;
+ em_weight += em1_weight;
+#endif
+#if defined(_GIMMICK_FOG_00_EMITTER_2)
+ const float3 em2_loc = _Gimmick_Fog_00_Emitter2_Location;
+ const float3 em2_normal = normalize(_Gimmick_Fog_00_Emitter2_Normal);
+ const float em2_scale_x = _Gimmick_Fog_00_Emitter2_Scale_X;
+ const float em2_scale_y = _Gimmick_Fog_00_Emitter2_Scale_Y;
+ float3 em2_color;
+ float em2_weight;
+ float3 em2_p;
+ getEmitterData(p, step_size, em2_loc, em2_normal, em2_scale_x, em2_scale_y, em2_color, em2_weight, em2_p);
+ em_color += em2_color;
+ em_weight += em2_weight;
#endif
+ c.rgb = lerp(c.rgb, em_color, em_weight);
+ }
#endif
acc += c * (1.0 - acc.a);
@@ -160,7 +208,7 @@ Fog00PBR getFog00(v2f i) {
normal = MY_BLEND_NORMALS(normal, n, n_interp);
}
#endif
- if (acc.a > _Gimmick_Fog_00_Albedo_Cutoff) {
+ if (acc.a > _Gimmick_Fog_00_Alpha_Cutoff) {
acc /= acc.a;
break;
}
diff --git a/globals.cginc b/globals.cginc
index e76cc4f..7c76853 100644
--- a/globals.cginc
+++ b/globals.cginc
@@ -5,6 +5,7 @@
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
+SamplerState point_repeat_s;
SamplerState linear_repeat_s;
SamplerState linear_clamp_s;
SamplerState bilinear_repeat_s;
@@ -713,15 +714,31 @@ float _Gimmick_Fog_00_Noise_Scale;
float _Gimmick_Fog_00_Noise_Exponent;
float _Gimmick_Fog_00_Density;
float _Gimmick_Fog_00_Normal_Cutoff;
-float _Gimmick_Fog_00_Albedo_Cutoff;
+float _Gimmick_Fog_00_Alpha_Cutoff;
float _Gimmick_Fog_00_Ray_Origin_Randomization;
+float _Gimmick_Fog_00_Lod_Half_Life;
+texture3D _Gimmick_Fog_00_Noise;
#if defined(_GIMMICK_FOG_00_EMITTER_TEXTURE)
texture2D _Gimmick_Fog_00_Emitter_Texture;
-float3 _Gimmick_Fog_00_Emitter_Location;
-float3 _Gimmick_Fog_00_Emitter_Normal;
-float _Gimmick_Fog_00_Emitter_Scale_X;
-float _Gimmick_Fog_00_Emitter_Scale_Y;
float _Gimmick_Fog_00_Emitter_Brightness;
+float _Gimmick_Fog_00_Emitter_Lod_Half_Life;
+
+float3 _Gimmick_Fog_00_Emitter0_Location;
+float3 _Gimmick_Fog_00_Emitter0_Normal;
+float _Gimmick_Fog_00_Emitter0_Scale_X;
+float _Gimmick_Fog_00_Emitter0_Scale_Y;
+#if defined(_GIMMICK_FOG_00_EMITTER_1)
+float3 _Gimmick_Fog_00_Emitter1_Location;
+float3 _Gimmick_Fog_00_Emitter1_Normal;
+float _Gimmick_Fog_00_Emitter1_Scale_X;
+float _Gimmick_Fog_00_Emitter1_Scale_Y;
+#endif
+#if defined(_GIMMICK_FOG_00_EMITTER_2)
+float3 _Gimmick_Fog_00_Emitter2_Location;
+float3 _Gimmick_Fog_00_Emitter2_Normal;
+float _Gimmick_Fog_00_Emitter2_Scale_X;
+float _Gimmick_Fog_00_Emitter2_Scale_Y;
+#endif
#endif
#endif
diff --git a/tooner.shader b/tooner.shader
index d3999e9..72567a2 100644
--- a/tooner.shader
+++ b/tooner.shader
@@ -619,21 +619,38 @@ Shader "yum_food/tooner"
_Mochie_UI_Show("UI show", Float) = 0
_Gimmick_Fog_00_Enable_Static("Enable fog 00", Float) = 0
+ _Gimmick_Fog_00_Noise("Noise", 3D) = "black" {}
_Gimmick_Fog_00_Max_Ray("Max ray", Float) = 25
_Gimmick_Fog_00_Radius("Radius", Float) = 25
_Gimmick_Fog_00_Step_Size_Factor("Step size (meters)", Float) = 1
_Gimmick_Fog_00_Noise_Scale("Noise scale", Float) = 1
_Gimmick_Fog_00_Noise_Exponent("Noise exponent", Float) = 2.0
- _Gimmick_Fog_00_Density("Density", Range(0,2)) = 1.0
+ _Gimmick_Fog_00_Density("Density", Range(0,10)) = 1.0
_Gimmick_Fog_00_Normal_Cutoff("Normal cutoff (alpha)", Range(0,1)) = 0.5
- _Gimmick_Fog_00_Albedo_Cutoff("Albedo cutoff (alpha)", Range(0,1)) = 0.9
+ _Gimmick_Fog_00_Alpha_Cutoff("Albedo cutoff (alpha)", Range(0,1)) = 0.9
_Gimmick_Fog_00_Ray_Origin_Randomization("Enable ray origin randomization", Range(0,1)) = 1
+ _Gimmick_Fog_00_Lod_Half_Life("fog", Float) = 5
+
_Gimmick_Fog_00_Emitter_Texture("Emitter texture", 2D) = "black" {}
- _Gimmick_Fog_00_Emitter_Location("fog", Vector) = (0, 0, 0, 0)
- _Gimmick_Fog_00_Emitter_Normal("fog", Vector) = (-1, 0, 0, 0)
- _Gimmick_Fog_00_Emitter_Scale_X("fog", Float) = 1
- _Gimmick_Fog_00_Emitter_Scale_Y("fog", Float) = 1
_Gimmick_Fog_00_Emitter_Brightness("fog", Float) = 1
+ _Gimmick_Fog_00_Emitter_Lod_Half_Life("fog", Float) = 5
+
+ _Gimmick_Fog_00_Emitter0_Location("fog", Vector) = (0, 0, 0, 0)
+ _Gimmick_Fog_00_Emitter0_Normal("fog", Vector) = (-1, 0, 0, 0)
+ _Gimmick_Fog_00_Emitter0_Scale_X("fog", Float) = 1
+ _Gimmick_Fog_00_Emitter0_Scale_Y("fog", Float) = 1
+
+ _Gimmick_Fog_00_Emitter1_Enable_Static("fog", Float) = 0
+ _Gimmick_Fog_00_Emitter1_Location("fog", Vector) = (0, 0, 0, 0)
+ _Gimmick_Fog_00_Emitter1_Normal("fog", Vector) = (-1, 0, 0, 0)
+ _Gimmick_Fog_00_Emitter1_Scale_X("fog", Float) = 1
+ _Gimmick_Fog_00_Emitter1_Scale_Y("fog", Float) = 1
+
+ _Gimmick_Fog_00_Emitter2_Enable_Static("fog", Float) = 0
+ _Gimmick_Fog_00_Emitter2_Location("fog", Vector) = (0, 0, 0, 0)
+ _Gimmick_Fog_00_Emitter2_Normal("fog", Vector) = (-1, 0, 0, 0)
+ _Gimmick_Fog_00_Emitter2_Scale_X("fog", Float) = 1
+ _Gimmick_Fog_00_Emitter2_Scale_Y("fog", Float) = 1
}
SubShader
{