2026-06-09 룸 프로토타입 디자인 (진행중)
This commit is contained in:
145
Assets/Stylized Water 3/Editor/Shader/FogIntegration.cs
Normal file
145
Assets/Stylized Water 3/Editor/Shader/FogIntegration.cs
Normal file
File diff suppressed because one or more lines are too long
10
Assets/Stylized Water 3/Editor/Shader/FogIntegration.cs.meta
Normal file
10
Assets/Stylized Water 3/Editor/Shader/FogIntegration.cs.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a3be5417b7946088b3cbec887cf0dfe
|
||||
timeCreated: 1729855911
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 287769
|
||||
packageName: Stylized Water 3
|
||||
packageVersion: 3.2.7
|
||||
assetPath: Assets/Stylized Water 3/Editor/Shader/FogIntegration.cs
|
||||
uploadId: 927372
|
||||
1740
Assets/Stylized Water 3/Editor/Shader/MaterialUI.cs
Normal file
1740
Assets/Stylized Water 3/Editor/Shader/MaterialUI.cs
Normal file
File diff suppressed because it is too large
Load Diff
18
Assets/Stylized Water 3/Editor/Shader/MaterialUI.cs.meta
Normal file
18
Assets/Stylized Water 3/Editor/Shader/MaterialUI.cs.meta
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6df0d541f8b14642985c92afdb9f538
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 287769
|
||||
packageName: Stylized Water 3
|
||||
packageVersion: 3.2.7
|
||||
assetPath: Assets/Stylized Water 3/Editor/Shader/MaterialUI.cs
|
||||
uploadId: 927372
|
||||
327
Assets/Stylized Water 3/Editor/Shader/ShaderConfigurator.cs
Normal file
327
Assets/Stylized Water 3/Editor/Shader/ShaderConfigurator.cs
Normal file
@@ -0,0 +1,327 @@
|
||||
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
|
||||
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
|
||||
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
|
||||
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
|
||||
|
||||
#if SWS_DEV
|
||||
#define ENABLE_SHADER_STRIPPING_LOG
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Serialization;
|
||||
using Debug = UnityEngine.Debug;
|
||||
using Object = UnityEngine.Object;
|
||||
using Random = UnityEngine.Random;
|
||||
#if URP
|
||||
using UnityEngine.Rendering.Universal;
|
||||
#endif
|
||||
|
||||
namespace StylizedWater3
|
||||
{
|
||||
public static class ShaderConfigurator
|
||||
{
|
||||
public const string DEFAULT_SHADER_GUID = "823f6b206953b674a9a64f9e3ec57752";
|
||||
|
||||
public static Shader GetDefaultShader()
|
||||
{
|
||||
string defaultShaderPath = AssetDatabase.GUIDToAssetPath(DEFAULT_SHADER_GUID);
|
||||
Shader defaultShader = AssetDatabase.LoadAssetAtPath<Shader>(defaultShaderPath);
|
||||
|
||||
return defaultShader;
|
||||
}
|
||||
|
||||
public static ShaderMessage[] GetErrorMessages(Shader shader)
|
||||
{
|
||||
ShaderMessage[] messages = null;
|
||||
|
||||
int n = ShaderUtil.GetShaderMessageCount(shader);
|
||||
|
||||
if (n < 1) return messages;
|
||||
|
||||
messages = ShaderUtil.GetShaderMessages(shader);
|
||||
|
||||
//Filter for errors
|
||||
messages = messages.Where(x => x.severity == ShaderCompilerMessageSeverity.Error).ToArray();
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
#if URP
|
||||
//Strips keywords from the shader for features belonging to newer URP versions.
|
||||
private class KeywordStripper : IPreprocessShaders
|
||||
{
|
||||
private const string LOG_FILEPATH = "Logs/Stylized Water 3 Compilation.log";
|
||||
|
||||
#if ENABLE_SHADER_STRIPPING_LOG
|
||||
private System.Diagnostics.Stopwatch m_stripTimer = new System.Diagnostics.Stopwatch();
|
||||
#endif
|
||||
|
||||
private List<ShaderKeyword> StrippedKeywords = new List<ShaderKeyword>();
|
||||
|
||||
//URP 18+
|
||||
private readonly ShaderKeyword _TEST = new ShaderKeyword("_TEST");
|
||||
|
||||
private readonly bool heightPrePassEnabled;
|
||||
|
||||
#if SWS_DEV
|
||||
[MenuItem("SWS/Debug/HeightPrePassEnabled")]
|
||||
#endif
|
||||
private static bool HeightPrePassEnabled()
|
||||
{
|
||||
bool state = false;
|
||||
|
||||
if (StylizedWaterRenderFeature.RequireHeightPrePass) return true;
|
||||
|
||||
//Check if the displacement pre-pass is enabled anywhere
|
||||
for (int i = 0; i < GraphicsSettings.allConfiguredRenderPipelines.Length; i++)
|
||||
{
|
||||
UniversalRenderPipelineAsset pipeline = (UniversalRenderPipelineAsset)GraphicsSettings.allConfiguredRenderPipelines[i];
|
||||
|
||||
ScriptableRendererData[] renderers = PipelineUtilities.GetRenderDataList(pipeline);
|
||||
|
||||
for (int j = 0; j < renderers.Length; j++)
|
||||
{
|
||||
StylizedWaterRenderFeature renderFeature = (StylizedWaterRenderFeature)PipelineUtilities.GetRenderFeature<StylizedWaterRenderFeature>(renderers[j]);
|
||||
|
||||
if (renderFeature)
|
||||
{
|
||||
state |= renderFeature.heightPrePassSettings.enable;
|
||||
|
||||
#if SWS_DEV
|
||||
//Debug.Log($"{renderers[j].name}. Enable?:{renderFeature.heightPrePassSettings.enable}");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if SWS_DEV
|
||||
//Debug.Log("Height pre-pass enabled somewhere: " + state);
|
||||
#endif
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
//Note: Constructor is called once, when building starts
|
||||
public KeywordStripper()
|
||||
{
|
||||
if (PlayerSettings.GetGraphicsAPIs(EditorUserBuildSettings.activeBuildTarget)[0] == GraphicsDeviceType.OpenGLES3)
|
||||
{
|
||||
if (UniversalRenderPipeline.asset.msaaSampleCount > 1)
|
||||
{
|
||||
Debug.LogWarning("[Stylized Water 3] You are deploying a build using the OpenGLES 3.0 graphics API with MSAA enabled (in your URP pipeline asset). Due to a bug in some graphics chips, transparent materials (including the water) will not render. " +
|
||||
"Disable MSAA, or use the Vulkan graphics API", UniversalRenderPipeline.asset);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_6000_1_OR_NEWER
|
||||
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WebGL && UniversalRenderPipeline.asset.lightProbeSystem == LightProbeSystem.ProbeVolumes)
|
||||
{
|
||||
if (PlayerSettings.GetGraphicsAPIs(EditorUserBuildSettings.activeBuildTarget)[0] ==
|
||||
GraphicsDeviceType.WebGPU)
|
||||
{
|
||||
Debug.LogWarning("[Stylized Water 3] WebGL builds using the WebGPU graphics API do not support Adaptive Probe Volumes. Shader will fall back to standard SH/Light Probes.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//Check if the displacement pre-pass is enabled anywhere
|
||||
heightPrePassEnabled = HeightPrePassEnabled();
|
||||
|
||||
StrippedKeywords.Clear();
|
||||
|
||||
if (!heightPrePassEnabled)
|
||||
{
|
||||
StrippedKeywords.Add(new ShaderKeyword(ShaderParams.Keywords.WaterHeightPass));
|
||||
}
|
||||
|
||||
//Note: Keywords for extensions are only injected through the shader generator. Hence they don't need to be stripped
|
||||
|
||||
#if !UNITY_6000_0_OR_NEWER
|
||||
StrippedKeywords.Add(_TEST);
|
||||
#endif
|
||||
|
||||
LogInitialization();
|
||||
}
|
||||
|
||||
public int callbackOrder => 0;
|
||||
|
||||
public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> compilerDataList)
|
||||
{
|
||||
#if URP
|
||||
if (UniversalRenderPipeline.asset == null || compilerDataList == null || compilerDataList.Count == 0) return;
|
||||
|
||||
//Only run for specific shaders
|
||||
if (shader.name.Contains("Stylized Water 3") == false) return;
|
||||
|
||||
LogStart(shader, snippet, compilerDataList);
|
||||
|
||||
var inputShaderVariantCount = compilerDataList.Count;
|
||||
for (int i = 0; i < inputShaderVariantCount;)
|
||||
{
|
||||
//If any of the excluded keywords are enabled in this variant, strip it
|
||||
bool removeInput = StripUnused(shader, compilerDataList[i], snippet);
|
||||
|
||||
// Remove at swap back
|
||||
if (removeInput)
|
||||
compilerDataList[i] = compilerDataList[--inputShaderVariantCount];
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
if (compilerDataList is List<ShaderCompilerData> inputDataList)
|
||||
{
|
||||
inputDataList.RemoveRange(inputShaderVariantCount, inputDataList.Count - inputShaderVariantCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = compilerDataList.Count - 1; i >= inputShaderVariantCount; --i)
|
||||
compilerDataList.RemoveAt(i);
|
||||
}
|
||||
|
||||
LogStrippingEnd(compilerDataList.Count);
|
||||
#endif
|
||||
}
|
||||
|
||||
private bool StripUnused(Shader shader, ShaderCompilerData compilerData, ShaderSnippetData snippet)
|
||||
{
|
||||
if (StripPass(shader, snippet))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (var keyword in StrippedKeywords)
|
||||
{
|
||||
if (StripKeyword(shader, keyword, compilerData, snippet))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool StripPass(Shader shader, ShaderSnippetData snippet)
|
||||
{
|
||||
if (heightPrePassEnabled == false && snippet.passName == ShaderParams.Passes.HeightPrePass)
|
||||
{
|
||||
Log($"- Stripped Pass {snippet.passName} ({shader.name}) (Stage: {snippet.shaderType})");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool StripKeyword(Shader shader, ShaderKeyword keyword, ShaderCompilerData compilerData, ShaderSnippetData snippet)
|
||||
{
|
||||
if (compilerData.shaderKeywordSet.IsEnabled(keyword))
|
||||
{
|
||||
LogStripping(shader, keyword, snippet);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#region Logging
|
||||
struct StrippingLog
|
||||
{
|
||||
public Shader shader;
|
||||
public ShaderKeyword keyword;
|
||||
public string passName;
|
||||
public ShaderType shaderType;
|
||||
}
|
||||
|
||||
private void LogInitialization()
|
||||
{
|
||||
#if ENABLE_SHADER_STRIPPING_LOG
|
||||
//Clear log file first
|
||||
File.WriteAllLines(LOG_FILEPATH, new string[] {});
|
||||
|
||||
Log("KeywordStripper initialized...", true);
|
||||
|
||||
Log(string.Empty);
|
||||
|
||||
Log($"Displacement Pre-pass enabled in build: {heightPrePassEnabled}", true);
|
||||
|
||||
Log(string.Empty);
|
||||
|
||||
for (int i = 0; i < StrippedKeywords.Count; i++)
|
||||
{
|
||||
Log($"• {StrippedKeywords[i].name} keyword to be stripped");
|
||||
}
|
||||
|
||||
Log($"{StrippedKeywords.Count} total keywords to be stripped");
|
||||
#endif
|
||||
}
|
||||
|
||||
private void LogStart(Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> compilerDataList)
|
||||
{
|
||||
#if ENABLE_SHADER_STRIPPING_LOG
|
||||
m_stripTimer.Start();
|
||||
|
||||
var text = $"OnProcessShader running for {shader.name}. (Pass: {snippet.passName}) (Stage: {snippet.shaderType}). Num variants: {compilerDataList.Count}";
|
||||
|
||||
Log(text, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
StrippingLog prevLog;
|
||||
|
||||
private void LogStripping(Shader shader, ShaderKeyword keyword, ShaderSnippetData snippet)
|
||||
{
|
||||
#if ENABLE_SHADER_STRIPPING_LOG
|
||||
|
||||
//Try to avoid spamming the log with duplicates, this otherwise slows down compilation to a crawl
|
||||
if (prevLog.keyword.index == keyword.index && prevLog.shader == shader && prevLog.passName == snippet.passName && prevLog.shaderType == snippet.shaderType)
|
||||
{
|
||||
//File.AppendAllText(LOG_FILEPATH, "- Skipping log!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
prevLog.shader = shader;
|
||||
prevLog.keyword = keyword;
|
||||
prevLog.passName = snippet.passName;
|
||||
prevLog.shaderType = snippet.shaderType;
|
||||
|
||||
var text = $"- Stripped {keyword.name} ({shader.name}) variant. (Pass {snippet.passName}) (Stage: {snippet.shaderType})";
|
||||
|
||||
Log(text);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void LogStrippingEnd(int count)
|
||||
{
|
||||
#if ENABLE_SHADER_STRIPPING_LOG
|
||||
m_stripTimer.Stop();
|
||||
System.TimeSpan stripTimespan = m_stripTimer.Elapsed;
|
||||
|
||||
var text = $"Stripping took {stripTimespan.Minutes}m{stripTimespan.Seconds}s ({stripTimespan.Milliseconds}ms). Remaining variants to compile: {count}";
|
||||
|
||||
Log(text);
|
||||
|
||||
m_stripTimer.Reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void Log(string text, bool newLine = false)
|
||||
{
|
||||
#if ENABLE_SHADER_STRIPPING_LOG
|
||||
File.AppendAllText(LOG_FILEPATH, (newLine ? "\n" : "") + text + "\n");
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c05c2f42980e1b649a1c2cd783b30b58
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 287769
|
||||
packageName: Stylized Water 3
|
||||
packageVersion: 3.2.7
|
||||
assetPath: Assets/Stylized Water 3/Editor/Shader/ShaderConfigurator.cs
|
||||
uploadId: 927372
|
||||
497
Assets/Stylized Water 3/Editor/Shader/TemplateParser.cs
Normal file
497
Assets/Stylized Water 3/Editor/Shader/TemplateParser.cs
Normal file
@@ -0,0 +1,497 @@
|
||||
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
|
||||
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
|
||||
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
|
||||
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace StylizedWater3
|
||||
{
|
||||
public static class TemplateParser
|
||||
{
|
||||
public const int SHADER_GENERATOR_VERSION_MAJOR = 5;
|
||||
public const int SHADER_GENERATOR_MINOR = 1;
|
||||
public const int SHADER_GENERATOR_PATCH = 3;
|
||||
|
||||
//Stencil mask used by water shader. Currently used for underwater rendering
|
||||
//Values 1-65 are used by deferred rendering
|
||||
public const int STENCIL_REF = 65;
|
||||
|
||||
//Converts relative include paths such as (../../Libraries/File.hlsl) to an absolute path
|
||||
//Supports the source file being part of a package
|
||||
public static string RelativeToAbsoluteIncludePath(string filePath, string relativePath)
|
||||
{
|
||||
string fileDir = Path.GetDirectoryName(filePath);
|
||||
|
||||
//Count how many folders should be traversed up
|
||||
int levels = relativePath.Split(new[]
|
||||
{
|
||||
".."
|
||||
}, StringSplitOptions.None).Length - 1;
|
||||
|
||||
string traveledPath = fileDir;
|
||||
if (levels > 0)
|
||||
{
|
||||
for (int i = 0; i < levels; i++)
|
||||
{
|
||||
//Remove the number of needed sub-directories needed to reach the destination
|
||||
int strimStart = traveledPath.LastIndexOf(Path.DirectorySeparatorChar);
|
||||
traveledPath = traveledPath.Remove(strimStart);
|
||||
}
|
||||
}
|
||||
|
||||
//The directory without the "up" navigators
|
||||
string relativeFolder = relativePath.Replace("../", string.Empty);
|
||||
|
||||
//Concatenate them together
|
||||
string absolutePath = traveledPath + "/" + relativeFolder;
|
||||
|
||||
//Convert back- to forward slashes
|
||||
absolutePath = absolutePath.Replace("\\", "/");
|
||||
|
||||
return absolutePath;
|
||||
}
|
||||
|
||||
//Pre-process the template to inject additional template contents into it
|
||||
private static void ModifyTemplate(ref string[] lines, WaterShaderImporter importer)
|
||||
{
|
||||
StringBuilder templateBuilder = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string line = lines[i];
|
||||
|
||||
//Inject additional passes into template
|
||||
if (line.Contains("%passes%"))
|
||||
{
|
||||
List<Object> passes = new List<Object>(importer.settings.additionalPasses);
|
||||
|
||||
if (StylizedWaterEditor.UnderwaterRenderingInstalled())
|
||||
{
|
||||
string maskPassGUID = "46c22cecd601401a875ca4554695986f";
|
||||
string maskPassPath = AssetDatabase.GUIDToAssetPath(maskPassGUID);;
|
||||
|
||||
Object underwaterMaskPass = AssetDatabase.LoadAssetAtPath<Object>(maskPassPath);
|
||||
|
||||
passes.Add(underwaterMaskPass);
|
||||
}
|
||||
|
||||
int passCount = passes.Count;
|
||||
for (int j = 0; j < passCount; j++)
|
||||
{
|
||||
if (passes[j] != null)
|
||||
{
|
||||
string filePath = AssetDatabase.GetAssetPath(passes[j]);
|
||||
|
||||
importer.RegisterDependency(filePath);
|
||||
|
||||
string[] passContexts = File.ReadAllLines(filePath);
|
||||
|
||||
for (int k = 0; k < passContexts.Length; k++)
|
||||
{
|
||||
templateBuilder.AppendLine(passContexts[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
templateBuilder.AppendLine(lines[i]);
|
||||
}
|
||||
lines = templateBuilder.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None);
|
||||
}
|
||||
|
||||
public static string CreateShaderCode(string templatePath, ref string[] lines, WaterShaderImporter importer, bool tessellation = false)
|
||||
{
|
||||
if (importer == null)
|
||||
{
|
||||
throw new Exception("Failed to compile shader from template code. The importer is invalid, this should not even be possible. Whatever you did, undo it...");
|
||||
}
|
||||
|
||||
//Extension installation states
|
||||
var underwaterInstalled = StylizedWaterEditor.UnderwaterRenderingInstalled();
|
||||
var dynamicEffectsInstalled = StylizedWaterEditor.DynamicEffectsInstalled();
|
||||
|
||||
FogIntegration.Integration fogIntegration = importer.GetFogIntegration();
|
||||
|
||||
AssetInfo.VersionChecking.CheckUnityVersion();
|
||||
|
||||
//Shader name
|
||||
string prefix = importer.settings.hidden ? "Hidden/" : string.Empty;
|
||||
string suffix = tessellation ? ShaderParams.ShaderNames.TESSELLATION_NAME_SUFFIX : string.Empty;
|
||||
string shaderName = $"{prefix}{AssetInfo.ASSET_NAME}/{importer.settings.shaderName}";
|
||||
|
||||
string shaderPath = importer.assetPath;
|
||||
|
||||
ModifyTemplate(ref lines, importer);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
//Ignore blank lines and comments for analysis
|
||||
if (string.IsNullOrWhiteSpace(lines[i]) || lines[i].StartsWith("//"))
|
||||
{
|
||||
sb.AppendLine(lines[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
//First non-space character
|
||||
int indent = System.Text.RegularExpressions.Regex.Match(lines[i], "[^-\\s]").Index;
|
||||
|
||||
string whitespace = lines[i].Replace(lines[i].Substring(indent), "");
|
||||
|
||||
//AppendLine using previous line's white spacing
|
||||
void AddLine(string source)
|
||||
{
|
||||
sb.AppendLine(source.Insert(0, whitespace));
|
||||
}
|
||||
|
||||
//Remove whitespaces
|
||||
string line = lines[i].Remove(0, indent);
|
||||
|
||||
bool Matches(string source) { return string.CompareOrdinal(source, line) == 0; }
|
||||
|
||||
if (Matches("%asset_version%"))
|
||||
{
|
||||
AddLine($"//Asset version {AssetInfo.INSTALLED_VERSION}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%compiler_version%"))
|
||||
{
|
||||
AddLine($"//Shader generator version: {new Version(SHADER_GENERATOR_VERSION_MAJOR, SHADER_GENERATOR_MINOR, SHADER_GENERATOR_PATCH)}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%unity_version%"))
|
||||
{
|
||||
AddLine($"//Unity version: {AssetInfo.VersionChecking.GetUnityVersion()}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%shader_name%"))
|
||||
{
|
||||
AddLine($"Shader \"{shaderName}{suffix}\"");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%custom_directives%"))
|
||||
{
|
||||
foreach (WaterShaderImporter.Directive directive in importer.settings.customIncludeDirectives)
|
||||
{
|
||||
if(directive.enabled == false) continue;
|
||||
|
||||
string directivePrefix = string.Empty;
|
||||
|
||||
switch (directive.type)
|
||||
{
|
||||
case WaterShaderImporter.Directive.Type.define:
|
||||
directivePrefix = "#define ";
|
||||
break;
|
||||
case WaterShaderImporter.Directive.Type.include:
|
||||
directivePrefix = "#include ";
|
||||
break;
|
||||
case WaterShaderImporter.Directive.Type.include_with_pragmas:
|
||||
directivePrefix = "#include_with_pragmas ";
|
||||
break;
|
||||
case WaterShaderImporter.Directive.Type.pragma:
|
||||
directivePrefix = "#pragma ";
|
||||
break;
|
||||
}
|
||||
|
||||
if (directive.value != string.Empty) AddLine($"{directivePrefix}{directive.value}");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%global_defines%"))
|
||||
{
|
||||
if (importer.settings.singleCausticsLayer)
|
||||
{
|
||||
AddLine("#define CAUSTICS_SINGLE_LAYER");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%pragma_target%"))
|
||||
{
|
||||
if (tessellation)
|
||||
{
|
||||
AddLine("#pragma target 4.6");
|
||||
}
|
||||
else
|
||||
{
|
||||
AddLine("#pragma target 3.0");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%pragma_renderers%"))
|
||||
{
|
||||
if (tessellation)
|
||||
{
|
||||
AddLine("#pragma exclude_renderers gles");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith("Fallback"))
|
||||
{
|
||||
if (tessellation)
|
||||
{
|
||||
//Fallback to non-tessellation variant (with without suffix)
|
||||
AddLine($"Fallback \"{shaderName}\"");
|
||||
//Test, disable fallback
|
||||
//AddLine(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Leave as is
|
||||
AddLine(line);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%tessellation_properties%"))
|
||||
{
|
||||
if (tessellation)
|
||||
{
|
||||
AddLine("_TessValue(\"Max subdivisions\", Range(1, 64)) = 16");
|
||||
AddLine("_TessMin(\"Start Distance\", Float) = 0");
|
||||
AddLine("_TessMax(\"End Distance\", Float) = 15");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%tessellation_directives%"))
|
||||
{
|
||||
if (tessellation)
|
||||
{
|
||||
AddLine("#define TESSELLATION_ON");
|
||||
AddLine("#pragma require tessellation tessHW");
|
||||
AddLine("#pragma hull Hull");
|
||||
AddLine("#pragma domain Domain");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.Contains("%stencilID%"))
|
||||
{
|
||||
int stencilID = STENCIL_REF;
|
||||
|
||||
if (importer.settings.fogIntegration == FogIntegration.Assets.COZY)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
line = line.Replace("%stencilID%", stencilID.ToString());
|
||||
AddLine(line);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%stencil%"))
|
||||
{
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%multi_compile_light_cookies%"))
|
||||
{
|
||||
if (importer.settings.lightCookies)
|
||||
{
|
||||
AddLine("#pragma multi_compile_fragment _ _LIGHT_COOKIES");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.Contains("%render_queue_offset%"))
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
switch (fogIntegration.asset)
|
||||
{
|
||||
//case FogIntegration.Assets.COZY: offset = 2;
|
||||
//break;
|
||||
//case Fog.Assets.AtmosphericHeightFog : offset = 2; //Should actually render after the fog sphere, but asset inherently relies on double fog shading it seems?
|
||||
//break;
|
||||
default: offset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
line = line.Replace("%render_queue_offset%", offset.ToString());
|
||||
AddLine(line);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%defines%"))
|
||||
{
|
||||
if (importer.settings.additionalLightCaustics)
|
||||
{
|
||||
AddLine("#define _ADDITIONAL_LIGHT_CAUSTICS");
|
||||
}
|
||||
if (importer.settings.additionalLightTranslucency)
|
||||
{
|
||||
AddLine("#define _ADDITIONAL_LIGHT_TRANSLUCENCY");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%multi_compile underwater rendering%"))
|
||||
{
|
||||
if (underwaterInstalled)
|
||||
{
|
||||
importer.configurationState.underwaterRendering = true;
|
||||
|
||||
AddLine($"#pragma multi_compile_fragment _ {ShaderParams.Keywords.UnderwaterRendering}");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%multi_compile_vertex dynamic effects%"))
|
||||
{
|
||||
if (dynamicEffectsInstalled)
|
||||
{
|
||||
importer.configurationState.dynamicEffects = true;
|
||||
|
||||
AddLine($"#pragma multi_compile_vertex _ {ShaderParams.Keywords.DynamicEffects}");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%multi_compile dynamic effects%"))
|
||||
{
|
||||
if (dynamicEffectsInstalled)
|
||||
{
|
||||
importer.configurationState.dynamicEffects = true;
|
||||
|
||||
AddLine($"#pragma multi_compile _ {ShaderParams.Keywords.DynamicEffects}");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Matches("%mobile_keyword_modifiers%"))
|
||||
{
|
||||
if (importer.settings.forceSimpleShadingOnMobile)
|
||||
{
|
||||
AddLine("#if defined(SHADER_API_MOBILE) || defined(SHADER_API_SWITCH) || defined(SHADER_API_SWITCH2)");
|
||||
AddLine("#undef _ADVANCED_SHADING");
|
||||
AddLine("#define _ADVANCED_SHADING 0");
|
||||
AddLine("#endif");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith("#include "))
|
||||
{
|
||||
string includePath = line.Replace("#include ", string.Empty);
|
||||
//Remove parenthesis
|
||||
includePath = includePath.Replace("\"", string.Empty);
|
||||
|
||||
importer.RegisterDependency(includePath);
|
||||
}
|
||||
|
||||
if (importer.settings.type == WaterShaderImporter.WaterShaderSettings.ShaderType.WaterSurface)
|
||||
{
|
||||
if (Matches("%define_fog_integration%"))
|
||||
{
|
||||
AddLine($"#define {fogIntegration.asset.ToString()}");
|
||||
|
||||
if (fogIntegration.asset == FogIntegration.Assets.UnityFog)
|
||||
{
|
||||
AddLine("#pragma multi_compile_fog");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* include FogLibrary */
|
||||
if (Matches("%include_fog_integration_library%"))
|
||||
{
|
||||
//Default until otherwise valid
|
||||
line = string.Empty;
|
||||
|
||||
//Mark the asset integration as being compiled in
|
||||
importer.configurationState.fogIntegration = fogIntegration;
|
||||
|
||||
if (fogIntegration.asset != FogIntegration.Assets.None && fogIntegration.asset != FogIntegration.Assets.UnityFog)
|
||||
{
|
||||
string includePath = AssetDatabase.GUIDToAssetPath(fogIntegration.libraryGUID);
|
||||
|
||||
importer.RegisterDependency(includePath);
|
||||
|
||||
//Not found error
|
||||
if (includePath == string.Empty)
|
||||
{
|
||||
if (EditorUtility.DisplayDialog(AssetInfo.ASSET_NAME,
|
||||
fogIntegration.name + " fog shader library could not be found with the GUID \"" + fogIntegration.libraryGUID + "\".\n\n" +
|
||||
"This means it was changed by the author (rare!), you deleted the \".meta\" file at some point, or the asset simply isn't installed.", "Ok"))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var pragma = fogIntegration.includeWithPragmas ? "include_with_pragmas" : "include";
|
||||
line = $"#{pragma} \"{includePath}\"";
|
||||
|
||||
AddLine(line);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Shaders created using "ShaderUtil.CreateShaderAsset" don't exist in a literal sense. Hence any relative file paths are invalid
|
||||
//Convert them to absolute file paths
|
||||
//Bonus: moving a shader file (or its folder) triggers it to re-import, thus always keeping the file path up-to-date
|
||||
if (line.StartsWith("#include_library"))
|
||||
{
|
||||
string relativePath = line.Replace("#include_library ", string.Empty);
|
||||
//Remove parenthesis
|
||||
relativePath = relativePath.Replace("\"", string.Empty);
|
||||
|
||||
string includePath = RelativeToAbsoluteIncludePath(shaderPath, relativePath);
|
||||
|
||||
line = $"#include \"{includePath}\"";
|
||||
|
||||
importer.RegisterDependency(includePath);
|
||||
|
||||
AddLine(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
//Insert whitespace back in
|
||||
line = line.Insert(0, whitespace);
|
||||
|
||||
//Nothing special, keep whatever line this is
|
||||
sb.AppendLine(line);
|
||||
}
|
||||
|
||||
//Convert to separate lines again
|
||||
lines = sb.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None);
|
||||
|
||||
//Convert to single string, respecting line breaks and spacing.
|
||||
return String.Join(Environment.NewLine, lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Assets/Stylized Water 3/Editor/Shader/TemplateParser.cs.meta
Normal file
10
Assets/Stylized Water 3/Editor/Shader/TemplateParser.cs.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14c82c38120d418bbd44cd7c0df0778d
|
||||
timeCreated: 1729855802
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 287769
|
||||
packageName: Stylized Water 3
|
||||
packageVersion: 3.2.7
|
||||
assetPath: Assets/Stylized Water 3/Editor/Shader/TemplateParser.cs
|
||||
uploadId: 927372
|
||||
373
Assets/Stylized Water 3/Editor/Shader/WaterShaderImporter.cs
Normal file
373
Assets/Stylized Water 3/Editor/Shader/WaterShaderImporter.cs
Normal file
@@ -0,0 +1,373 @@
|
||||
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
|
||||
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
|
||||
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
|
||||
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
|
||||
|
||||
using UnityEditor.AssetImporters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.Serialization;
|
||||
using Debug = UnityEngine.Debug;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace StylizedWater3
|
||||
{
|
||||
[ScriptedImporter(TemplateParser.SHADER_GENERATOR_VERSION_MAJOR + TemplateParser.SHADER_GENERATOR_MINOR + TemplateParser.SHADER_GENERATOR_PATCH, TARGET_FILE_EXTENSION, 0)]
|
||||
public class WaterShaderImporter : ScriptedImporter
|
||||
{
|
||||
private const string TARGET_FILE_EXTENSION = "watershader3";
|
||||
private const string ICON_NAME = "water-shader-icon";
|
||||
|
||||
[Tooltip("Rather than storing the template in this file, it can be sourced from an external text file" +
|
||||
"\nUse this if you intent to duplicate this asset, and need only minor modifications to its import settings")]
|
||||
[SerializeField] public LazyLoadReference<Object> template;
|
||||
|
||||
[Space]
|
||||
|
||||
public WaterShaderSettings settings = new WaterShaderSettings();
|
||||
|
||||
/// <summary>
|
||||
/// File paths of any file this shader depends on. This list will be populated with any "#include" paths present in the template
|
||||
/// Registering these as dependencies is required to trigger the shader to recompile when these files are changed
|
||||
/// </summary>
|
||||
//[NonSerialized] //Want to keep these serialized. Will differ per-project, which also causes the file to appear as changed for every project when updating the asset (this triggers a re-import)
|
||||
public List<string> dependencies = new List<string>();
|
||||
|
||||
[Serializable]
|
||||
//Keep track of what was being compiled in
|
||||
//Used to detect discrepencies between the project state, and the compiled shader
|
||||
public class ConfigurationState
|
||||
{
|
||||
public bool underwaterRendering;
|
||||
public bool dynamicEffects;
|
||||
public FogIntegration.Integration fogIntegration;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
underwaterRendering = false;
|
||||
dynamicEffects = false;
|
||||
fogIntegration = FogIntegration.GetIntegration(FogIntegration.Assets.None);
|
||||
}
|
||||
}
|
||||
public ConfigurationState configurationState = new ConfigurationState();
|
||||
|
||||
public string GetTemplatePath()
|
||||
{
|
||||
return template.isSet ? AssetDatabase.GetAssetPath(template.asset) : assetPath;
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
if(settings.shaderName == string.Empty) settings.shaderName = $"{Application.productName} ({DateTime.Now.Ticks})";
|
||||
}
|
||||
|
||||
public override void OnImportAsset(AssetImportContext context)
|
||||
{
|
||||
Shader shader = AssetDatabase.LoadAssetAtPath<Shader>(context.assetPath);
|
||||
//if (shader != null) ShaderUtil.ClearShaderMessages(shader);
|
||||
|
||||
string templatePath = GetTemplatePath();
|
||||
|
||||
if (templatePath == string.Empty)
|
||||
{
|
||||
Debug.LogError("Failed to import water shader, template file path is null. It possibly hasn't been imported first?", shader);
|
||||
return;
|
||||
}
|
||||
|
||||
#if SWS_DEV
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
#endif
|
||||
|
||||
string[] lines = File.ReadAllLines(templatePath);
|
||||
|
||||
if (lines.Length == 0)
|
||||
{
|
||||
Debug.LogError("Failed to generated water shader. Template or file content is empty (or wasn't yet imported)...");
|
||||
return;
|
||||
}
|
||||
|
||||
dependencies.Clear();
|
||||
|
||||
configurationState.Reset();
|
||||
|
||||
string shaderLab = TemplateParser.CreateShaderCode(context.assetPath, ref lines, this, false);
|
||||
|
||||
Shader shaderAsset = ShaderUtil.CreateShaderAsset(shaderLab, true);
|
||||
|
||||
int passCount = shaderAsset.passCount;
|
||||
|
||||
ShaderInfo shaderInfo = ShaderUtil.GetShaderInfo(shaderAsset);
|
||||
ShaderData shaderData = ShaderUtil.GetShaderData(shaderAsset);
|
||||
|
||||
//Unity will always create 3 base passes: Unnamed, DepthNormalsOnly & DepthOnly
|
||||
if (shaderInfo.hasErrors && shaderData.GetSubshader(0).GetPass(0).Name.Contains("Unnamed"))
|
||||
{
|
||||
Debug.LogError($"Failed to compile water shader at {context.assetPath}. It contains no passes. " +
|
||||
$"This may happen if the shader file was imported while one or more script compile errors were present, or moving the Stylized Water 3 folder, or the meta-file was deleted. Resulting in all configurations getting wiped. To resolve this, re-import the file from the Package Manager.");
|
||||
return;
|
||||
}
|
||||
ShaderUtil.RegisterShader(shaderAsset);
|
||||
|
||||
Texture2D thumbnail = Resources.Load<Texture2D>(ICON_NAME);
|
||||
if(!thumbnail) thumbnail = EditorGUIUtility.IconContent("ShaderImporter Icon").image as Texture2D;
|
||||
|
||||
context.AddObjectToAsset("MainAsset", shaderAsset, thumbnail);
|
||||
context.SetMainObject(shaderAsset);
|
||||
|
||||
//Do not attempt to create a tessellation variant for the underwater post-effect shaders
|
||||
if (settings.type == WaterShaderSettings.ShaderType.WaterSurface)
|
||||
{
|
||||
//Re-read the original template again
|
||||
lines = File.ReadAllLines(templatePath);
|
||||
shaderLab = TemplateParser.CreateShaderCode(context.assetPath, ref lines, this, true);
|
||||
|
||||
Shader tessellation = ShaderUtil.CreateShaderAsset(shaderLab, true);
|
||||
//ShaderUtil.RegisterShader(tessellation);
|
||||
|
||||
context.AddObjectToAsset("Tessellation", (Object)tessellation, thumbnail);
|
||||
}
|
||||
|
||||
//Set up dependency, so that changes to the template triggers shaders to regenerate
|
||||
if (template.isSet && AssetDatabase.TryGetGUIDAndLocalFileIdentifier(template, out var guid, out long _))
|
||||
{
|
||||
//Note: this strictly only works when adding the file path!
|
||||
//context.DependsOnArtifact(guid);
|
||||
|
||||
dependencies.Insert(0, AssetDatabase.GUIDToAssetPath(guid));
|
||||
}
|
||||
|
||||
//Dependencies are populated during the template parsing phase.
|
||||
foreach (string dependency in dependencies)
|
||||
{
|
||||
context.DependsOnSourceAsset(dependency);
|
||||
}
|
||||
|
||||
#if SWS_DEV
|
||||
sw.Stop();
|
||||
//Debug.Log($"Imported \"{Path.GetFileNameWithoutExtension(assetPath)}\" water shader in {sw.Elapsed.Milliseconds}ms. With {dependencies.Count} dependencies.", shader);
|
||||
#endif
|
||||
}
|
||||
|
||||
public bool RequiresRecompilation(out string message)
|
||||
{
|
||||
bool isValid = true;
|
||||
|
||||
var underwaterInstalled = configurationState.underwaterRendering == StylizedWaterEditor.UnderwaterRenderingInstalled();
|
||||
var dynamicEffectsInstalled = configurationState.dynamicEffects == StylizedWaterEditor.DynamicEffectsInstalled();
|
||||
var fogIntegration = configurationState.fogIntegration.asset == GetFogIntegration().asset;
|
||||
|
||||
isValid = underwaterInstalled & dynamicEffectsInstalled & fogIntegration;
|
||||
|
||||
message = string.Empty;
|
||||
|
||||
if (isValid == false)
|
||||
{
|
||||
if (!underwaterInstalled) message += "\nUnderwater Rendering extension installed, but not activated";
|
||||
if (!dynamicEffectsInstalled) message += "\nDynamic Effects extension installed, but not activated";
|
||||
if (!fogIntegration) message += $"\nFog integration does not match.\nInstalled: {configurationState.fogIntegration.name} - Detected in project: {GetFogIntegration().name}";
|
||||
}
|
||||
|
||||
return !isValid;
|
||||
}
|
||||
|
||||
public void Reimport()
|
||||
{
|
||||
this.SaveAndReimport();
|
||||
}
|
||||
|
||||
public void ClearCache(bool recompile = false)
|
||||
{
|
||||
var objs = AssetDatabase.LoadAllAssetsAtPath(assetPath);
|
||||
|
||||
foreach (var obj in objs)
|
||||
{
|
||||
if (obj is Shader)
|
||||
{
|
||||
ShaderUtil.ClearShaderMessages((Shader)obj);
|
||||
ShaderUtil.ClearCachedData((Shader)obj);
|
||||
|
||||
if(recompile) AssetDatabase.ImportAsset(assetPath);
|
||||
|
||||
#if SWS_DEV
|
||||
Debug.Log($"Cleared cache for {obj.name}");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
public void RegisterDependency(string dependencyAssetPath)
|
||||
{
|
||||
if (dependencyAssetPath.StartsWith("Packages/") == false)
|
||||
{
|
||||
string guid = AssetDatabase.AssetPathToGUID(dependencyAssetPath);
|
||||
|
||||
if (guid == string.Empty)
|
||||
{
|
||||
//Also throws an error for things like '#include_library "SurfaceModifiers/SurfaceModifiers.hlsl"', which are wrapped in an #ifdef. That's a false positive
|
||||
//Debug.LogException(new Exception($"Tried to import \"{this.assetPath}\" with an missing dependency, supposedly at path: {dependencyAssetPath}."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Tessellation variant pass may run, causing the same dependencies to be registered twice, hence check first
|
||||
if(dependencies.Contains(dependencyAssetPath) == false) dependencies.Add(dependencyAssetPath);
|
||||
}
|
||||
|
||||
//Handles correct behaviour when double-clicking a .watershader asset. Should open in the IDE
|
||||
[UnityEditor.Callbacks.OnOpenAsset]
|
||||
#if UNITY_6000_4_OR_NEWER
|
||||
public static bool OnOpenAsset(EntityId instanceID, int line)
|
||||
#else
|
||||
public static bool OnOpenAsset(int instanceID, int line)
|
||||
#endif
|
||||
{
|
||||
#if UNITY_6000_3_OR_NEWER
|
||||
Object target = EditorUtility.EntityIdToObject(instanceID);
|
||||
EntityId id = (EntityId)instanceID;
|
||||
#else
|
||||
Object target = EditorUtility.InstanceIDToObject(instanceID);
|
||||
int id = instanceID;
|
||||
#endif
|
||||
|
||||
if (target is Shader)
|
||||
{
|
||||
var path = AssetDatabase.GetAssetPath(id);
|
||||
|
||||
if (Path.GetExtension(path) != "." + TARGET_FILE_EXTENSION) return false;
|
||||
|
||||
string externalScriptEditor = ScriptEditorUtility.GetExternalScriptEditor();
|
||||
|
||||
if (externalScriptEditor != "internal" && externalScriptEditor != string.Empty)
|
||||
{
|
||||
InternalEditorUtility.OpenFileAtLineExternal(path, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.OpenURL("file://" + path);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static WaterShaderImporter GetForShader(Shader shader)
|
||||
{
|
||||
return AssetImporter.GetAtPath(AssetDatabase.GetAssetOrScenePath(shader)) as WaterShaderImporter;
|
||||
}
|
||||
|
||||
public Shader GetShader()
|
||||
{
|
||||
return AssetDatabase.LoadAssetAtPath<Shader>(assetPath);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Directive
|
||||
{
|
||||
public enum Type
|
||||
{
|
||||
[InspectorName("(no prefix)")]
|
||||
custom,
|
||||
[InspectorName("#include")]
|
||||
include,
|
||||
[InspectorName("#pragma")]
|
||||
pragma,
|
||||
[InspectorName("#include_with_pragmas")]
|
||||
include_with_pragmas,
|
||||
[InspectorName("#define")]
|
||||
define
|
||||
}
|
||||
public bool enabled = true;
|
||||
public Type type;
|
||||
public string value;
|
||||
|
||||
public Directive(Type _type, string _value)
|
||||
{
|
||||
this.type = _type;
|
||||
this.value = _value;
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] FindAllAssets()
|
||||
{
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(Application.dataPath);
|
||||
|
||||
FileInfo[] fileInfos = directoryInfo.GetFiles("*." + TARGET_FILE_EXTENSION, SearchOption.AllDirectories);
|
||||
|
||||
#if SWS_DEV
|
||||
//Debug.Log($"{fileInfos.Length} .{TARGET_FILE_EXTENSION} assets found");
|
||||
#endif
|
||||
|
||||
string[] filePaths = new string[fileInfos.Length];
|
||||
|
||||
for (int i = 0; i < filePaths.Length; i++)
|
||||
{
|
||||
filePaths[i] = fileInfos[i].FullName.Replace(@"\", "/").Replace(Application.dataPath, "Assets");
|
||||
}
|
||||
|
||||
return filePaths;
|
||||
}
|
||||
|
||||
#if SWS_DEV
|
||||
[MenuItem("SWS/Reimport water shaders")]
|
||||
#endif
|
||||
public static void ReimportAll()
|
||||
{
|
||||
string[] filePaths = FindAllAssets();
|
||||
foreach (var filePath in filePaths)
|
||||
{
|
||||
#if SWS_DEV
|
||||
//Debug.Log($"Reimporting: {filePath}");
|
||||
#endif
|
||||
AssetDatabase.ImportAsset(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
public FogIntegration.Integration GetFogIntegration()
|
||||
{
|
||||
return settings != null && settings.autoIntegration ? FogIntegration.GetFirstInstalled() : FogIntegration.GetIntegration(settings.fogIntegration);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class WaterShaderSettings
|
||||
{
|
||||
[Tooltip("How it will appear in the selection menu")]
|
||||
public string shaderName;
|
||||
[Tooltip("Hide the shader in the selection menu. Yet still make it findable with Shader.Find()")]
|
||||
public bool hidden;
|
||||
public enum ShaderType
|
||||
{
|
||||
WaterSurface,
|
||||
PostProcessing
|
||||
}
|
||||
public ShaderType type;
|
||||
[Tooltip("Enable to disable the Advanced Shading mode on mobile platforms (including Nintendo Switch 1 & 2). Unity internally decides which platforms that is!")]
|
||||
public bool forceSimpleShadingOnMobile = true;
|
||||
|
||||
[Tooltip("Before compiling the shader, check whichever asset is present in the project and activate its integration")]
|
||||
public bool autoIntegration = true;
|
||||
public FogIntegration.Assets fogIntegration = FogIntegration.Assets.UnityFog;
|
||||
|
||||
[Tooltip("Add support for native light cookies. Disabled by default to allow for cookies to act as caustics projectors that ignore the water surface")]
|
||||
public bool lightCookies = false;
|
||||
[Tooltip("Point and spot lights add caustics")]
|
||||
public bool additionalLightCaustics = false;
|
||||
public bool additionalLightTranslucency = true;
|
||||
[Tooltip("When disabled, two caustics textures are cross-animated. Disable this when using a flipbook caustics texture!")]
|
||||
public bool singleCausticsLayer;
|
||||
|
||||
public List<Directive> customIncludeDirectives = new List<Directive>();
|
||||
[FormerlySerializedAs("passes")]
|
||||
[Tooltip("Pass blocks that are to be added to the shader template")]
|
||||
public Object[] additionalPasses = new Object[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb104378e2fbf2942ae8b66abb7a1d57
|
||||
timeCreated: 1678979614
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 287769
|
||||
packageName: Stylized Water 3
|
||||
packageVersion: 3.2.7
|
||||
assetPath: Assets/Stylized Water 3/Editor/Shader/WaterShaderImporter.cs
|
||||
uploadId: 927372
|
||||
Reference in New Issue
Block a user