public static void UpdateAllRaymarchScenes()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("Cannot update all raymarch scenes while playing!");
            }

            Debug.Log("Updating all raymarch scenes");

            string[] guids = AssetDatabase.FindAssets($"t:{nameof(SceneAsset)}", null);

            List <string> scenePaths = new List <string>(guids.Length);

            scenePaths.AddRange(guids.Select(AssetDatabase.GUIDToAssetPath));

            Scene  currentScene     = SceneManager.GetActiveScene();
            string currentScenePath = string.Empty;


            foreach (var path in scenePaths)
            {
                // NOTE(WSWhitehouse): Ignore scenes that are located in the packages
                if (path.StartsWith("Packages/"))
                {
                    continue;
                }

                Scene openScene = EditorSceneManager.OpenScene(path);

                if (openScene.name == currentScene.name)
                {
                    currentScenePath = path;
                }

                if (RaymarchScene.Get() == null)
                {
                    continue;
                }
                RaymarchShaderGen.GenerateRaymarchShader();
            }

            if (!string.IsNullOrEmpty(currentScenePath))
            {
                EditorSceneManager.OpenScene(currentScenePath);
            }
        }
        public static void CreateRaymarchScene()
        {
            var rmScene = RaymarchScene.Get();

            if (rmScene != null)
            {
                Debug.LogError($"There is already an RM Scene in this scene ({SceneManager.GetActiveScene().name})");
                EditorGUIUtility.PingObject(rmScene);
                Selection.SetActiveObjectWithContext(rmScene.gameObject, rmScene.gameObject);
                return;
            }

            var obj = new GameObject("RM Scene");

            rmScene = obj.AddComponent <RaymarchScene>();

            Selection.SetActiveObjectWithContext(obj, obj);
        }
Beispiel #3
0
    public static void GenerateRaymarchShader()
    {
        Debug.Log($"Generating Raymarch Shader in '{SceneManager.GetActiveScene().name}'");

        if (Application.isPlaying)
        {
            Debug.LogError($"{nameof(GenerateRaymarchShader)} called during runtime");
            return;
        }

        RaymarchScene rmScene = RaymarchScene.Get();

        // Raymarch Scene Sanity Checks
        if (rmScene == null)
        {
            Debug.LogError($"{nameof(RaymarchShaderGen)}: There is no {nameof(RaymarchScene)} in the active scene");
            return;
        }

        if (rmScene.templateShader == null)
        {
            Debug.LogError($"{nameof(RaymarchShaderGen)}: There is no template shader in the {nameof(RaymarchScene)}");
            return;
        }

        Scene activeScene   = rmScene.gameObject.scene;
        var   raymarchBases = GenerateRaymarchSceneHierarchy(activeScene);

        string currentDir = Directory.GetCurrentDirectory();

        // Finding path of template
        string templatePath = string.Concat(currentDir, "/", AssetDatabase.GetAssetPath(rmScene.templateShader));

        // Find/Create path for Generated Shader
        string scenePath = string.Concat(currentDir, "/", activeScene.path);
        string sceneName = Path.GetFileNameWithoutExtension(scenePath);

        scenePath = string.Concat(Path.GetDirectoryName(scenePath), "/");

        string shaderName = string.Concat(sceneName, "_RaymarchShader");

        string filePath = string.Concat(scenePath, sceneName);

        Directory.CreateDirectory(filePath);
        filePath = string.Concat(filePath, "/", shaderName, ".shader");

        if (File.Exists(filePath))
        {
            File.Delete(filePath);
        }

        // NOTE(WSWhitehouse): Creating strings to hold shader code that will be inserted into the shader
        int           capacity         = StringCapacityPerObject * raymarchBases.Count;
        StringBuilder raymarchVars     = new StringBuilder(capacity);
        StringBuilder raymarchDistance = new StringBuilder(capacity);
        StringBuilder raymarchLight    = new StringBuilder(capacity);

        raymarchVars.AppendLine("// Raymarch Variables");
        foreach (RaymarchBase raymarchBase in raymarchBases)
        {
            raymarchVars.AppendLine(raymarchBase.GetShaderVariables());
        }

        List <RaymarchOperation> operations = new List <RaymarchOperation>();

        for (int i = 0; i < raymarchBases.Count; i++)
        {
            string guid = raymarchBases[i].GUID.ToShaderSafeString();

            if (raymarchBases[i] is RaymarchOperation rmOperation)
            {
                operations.Add(rmOperation);

                var opGuid = rmOperation.GUID.ToShaderSafeString();

                raymarchDistance.AppendLine($"// Operation Start {rmOperation.operation.ShaderFeatureAsset.FunctionName} {opGuid}");
                raymarchDistance.AppendLine($"float distance{opGuid} = _RenderDistance;");
                raymarchDistance.AppendLine($"float4 colour{opGuid} = float4(1,1,1,1);");
                raymarchDistance.AppendLine();
            }

            if (raymarchBases[i] is RaymarchObject rmObject)
            {
                string positionName           = $"_{nameof(rmObject.Position)}{guid}";
                string rotationName           = $"_{nameof(rmObject.RotationRotor3D)}{guid}";
                string rotation4DName         = $"_{nameof(rmObject.Rotation4D)}{guid}";
                string scaleName              = $"_{nameof(rmObject.Scale)}{guid}";
                string transform4DEnabledName = $"_{nameof(rmObject.Transform4DEnabled)}{guid}";

                string localDistName = $"distance{guid}";
                string localPosName  = $"position{guid}";

                raymarchDistance.AppendLine(
                    $"float4 {localPosName} = (rayPos4D - {positionName}) / {scaleName};");
                raymarchDistance.AppendLine(
                    $"{localPosName} = float4(Rotate3D({localPosName}.xyz, {rotationName}), {localPosName}.w);");

                // raymarchDistance.AppendLine($"if ({transform4DEnabledName} > 0)");
                // raymarchDistance.AppendLine("{");
                // raymarchDistance.AppendLine($"{localPosName} = Rotate4D({localPosName}, {rotation4DName});");
                // raymarchDistance.AppendLine("}");

                raymarchDistance.AppendLine($"int result{transform4DEnabledName} = {transform4DEnabledName} > 0;");
                raymarchDistance.AppendLine($"{localPosName} = Rotate4D({localPosName}, {rotation4DName}) * result{transform4DEnabledName} + " +
                                            $"{localPosName} * !result{transform4DEnabledName};");

                raymarchDistance.AppendLine();
                raymarchDistance.AppendLine($"float {localDistName} = _RenderDistance;");

                raymarchDistance.Append(RaymarchObjectDistanceShaderCode(rmObject));

                raymarchDistance.AppendLine();

                if (operations.Count > 0)
                {
                    var operation = operations[^ 1];