Example #1
0
        void UpdateLights()
        {
            SphericalHarmonics lighting = SphericalHarmonics.FromLights(lights
                                                                        .ConvertAll(a => new SHLight {
                directionTo = a.pose.position.Normalized(),
                color       = Color.HSV(a.color) * LightIntensity(a.pose.position)
            })
                                                                        .ToArray());

            Renderer.SkyTex   = Tex.GenCubemap(lighting);
            Renderer.SkyLight = lighting;
        }
Example #2
0
 public static void UpdateSH9FormCubeMap(Cubemap ibl, ref Cubemap curIbl, SH9Struct iblData)
 {
     if (curIbl != ibl)
     {
         if (null == ibl)
         {
             iblData.coefficients = new Vector4[0];
         }
         else
         {
             SH9Helper.ModifyTextureReadable(ibl);
             iblData.coefficients = new Vector4[9];
             if (SphericalHarmonics.CPU_Project_Uniform_9Coeff(ibl, iblData.coefficients))
             {
             }
         }
         curIbl = ibl;
     }
 }
Example #3
0
    public void Initialize()
    {
        oldSkyTex         = Renderer.SkyTex;
        oldSkyLight       = Renderer.SkyLight;
        sphereMesh        = Mesh.GenerateSphere(1, 5);
        Renderer.SkyTex   = Tex.FromCubemapEquirectangular("old_depot.hdr", out SphericalHarmonics lighting);
        Renderer.SkyLight = lighting;

        pbrModel     = Model.FromFile("DamagedHelmet.gltf");
        pbrMaterials = new Material[materialGrid * materialGrid];
        for (int y = 0; y < materialGrid; y++)
        {
            for (int x = 0; x < materialGrid; x++)
            {
                int i = x + y * materialGrid;
                pbrMaterials[i] = new Material(Default.ShaderPbr);
                pbrMaterials[i][MatParamName.ColorTint]       = Color.HSV(0.3f, 0.8f, 0.8f);
                pbrMaterials[i][MatParamName.MetallicAmount]  = x / (float)(materialGrid - 1);
                pbrMaterials[i][MatParamName.RoughnessAmount] = y / (float)(materialGrid - 1);
            }
        }

        /// :CodeSample: Material.GetAllParamInfo Material.GetParamInfo Material.ParamCount MatParamInfo MatParamInfo.name MatParamInfo.type
        /// ### Listing parameters in a Material

        // Iterate using a foreach
        Log.Info("Builtin PBR Materials contain these parameters:");
        foreach (MatParamInfo info in Material.PBR.GetAllParamInfo())
        {
            Log.Info($"- {info.name} : {info.type}");
        }

        // Or with a normal for loop
        Log.Info("Builtin Unlit Materials contain these parameters:");
        for (int i = 0; i < Material.Unlit.ParamCount; i += 1)
        {
            MatParamInfo info = Material.Unlit.GetParamInfo(i);
            Log.Info($"- {info.name} : {info.type}");
        }
        /// :End:
    }
Example #4
0
    public void Initialize()
    {
        oldSkyTex         = Renderer.SkyTex;
        oldSkyLight       = Renderer.SkyLight;
        sphereMesh        = Mesh.GenerateSphere(1, 5);
        Renderer.SkyTex   = Tex.FromCubemapEquirectangular("old_depot.hdr", out SphericalHarmonics lighting);
        Renderer.SkyLight = lighting;

        pbrModel     = Model.FromFile("DamagedHelmet.gltf");
        pbrMaterials = new Material[materialGrid * materialGrid];
        for (int y = 0; y < materialGrid; y++)
        {
            for (int x = 0; x < materialGrid; x++)
            {
                int i = x + y * materialGrid;
                pbrMaterials[i] = new Material(Default.ShaderPbr);
                pbrMaterials[i][MatParamName.ColorTint]       = Color.HSV(0.3f, 0.8f, 0.8f);
                pbrMaterials[i][MatParamName.MetallicAmount]  = x / (float)(materialGrid - 1);
                pbrMaterials[i][MatParamName.RoughnessAmount] = y / (float)(materialGrid - 1);
            }
        }
    }
Example #5
0
 public static void UpdateSH9FormCubeMap(Cubemap ibl, ref Cubemap curIbl, SH9Struct iblData)
 {
     if (curIbl != ibl)
     {
         if (null == ibl)
         {
             iblData.coefficients = new Vector4[0];
         }
         else
         {
             SH9Helper.ModifyTextureReadable(ibl);
             iblData.coefficients = new Vector4[9];
             if (SphericalHarmonics.CPU_Project_Uniform_9Coeff(ibl, iblData.coefficients))
             {
                 /*g_sph0.xyz * 0.2820947917f +
                  * g_sph1.xyz * 0.4886025119f * v.y;
                  * g_sph2.xyz * 0.4886025119f * v.z;
                  * g_sph3.xyz * 0.4886025119f * v.x;
                  * g_sph4.xyz * 1.0925484306f * v.x * v.y;
                  * g_sph5.xyz * 1.0925484306f * v.y * v.z;
                  * g_sph6.xyz * 0.3153915652f * (3.0f * v.z * v.z - 1.0f);
                  * g_sph7.xyz * 1.0925484306f * v.x * v.z;
                  * g_sph8.xyz * 0.5462742153f * (v.x * v.x - v.y * v.y);
                  */
                 iblData.coefficients[0] = iblData.coefficients[0] * 0.2820947917f;
                 iblData.coefficients[1] = iblData.coefficients[1] * 0.4886025119f;
                 iblData.coefficients[2] = iblData.coefficients[2] * 0.4886025119f;
                 iblData.coefficients[3] = iblData.coefficients[3] * 0.4886025119f;
                 iblData.coefficients[4] = iblData.coefficients[4] * 1.0925484306f;
                 iblData.coefficients[5] = iblData.coefficients[5] * 1.0925484306f;
                 iblData.coefficients[6] = iblData.coefficients[6] * 0.3153915652f;
                 iblData.coefficients[7] = iblData.coefficients[7] * 1.0925484306f;
                 iblData.coefficients[8] = iblData.coefficients[8] * 0.5462742153f;
             }
         }
         curIbl = ibl;
     }
 }
        protected override void DrawCore(RenderContext context)
        {
            var inputTexture = RadianceMap;
            if (inputTexture == null)
                return;
            
            // Gets and checks the input texture
            if (inputTexture.Dimension != TextureDimension.TextureCube)
                throw new NotSupportedException("Only texture cube are currently supported as input of 'LambertianPrefilteringSH' effect.");

            const int FirstPassBlockSize = 4;
            const int FirstPassSumsCount = FirstPassBlockSize * FirstPassBlockSize;

            var faceCount = inputTexture.Dimension == TextureDimension.TextureCube ? 6 : 1;
            var inputSize = new Int2(inputTexture.Width, inputTexture.Height); // (Note: for cube maps width = height)
            var coefficientsCount = harmonicalOrder * harmonicalOrder;

            var sumsToPerfomRemaining = inputSize.X * inputSize.Y * faceCount / FirstPassSumsCount;
            var partialSumBuffer = NewScopedTypedBuffer(coefficientsCount * sumsToPerfomRemaining, PixelFormat.R32G32B32A32_Float, true);


            // Project the radiance on the SH basis and sum up the results along the 4x4 blocks
            firstPassEffect.ThreadNumbers = new Int3(FirstPassBlockSize, FirstPassBlockSize, 1);
            firstPassEffect.ThreadGroupCounts = new Int3(inputSize.X/FirstPassBlockSize, inputSize.Y/FirstPassBlockSize, faceCount);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHParameters.BlockSize, FirstPassBlockSize);
            firstPassEffect.Parameters.Set(SphericalHarmonicsParameters.HarmonicsOrder, harmonicalOrder);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHPass1Keys.RadianceMap, inputTexture);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHPass1Keys.OutputBuffer, partialSumBuffer);
            firstPassEffect.Draw(context);

            // Recursively applies the pass2 (sums the coefficients together) as long as needed. Swap input/output buffer at each iteration.
            var secondPassInputBuffer = partialSumBuffer;
            Buffer secondPassOutputBuffer = null;
            while (sumsToPerfomRemaining % 2 == 0)
            {
                // we are limited in the number of summing threads by the group-shared memory size.
                // determine the number of threads to use and update the number of sums remaining afterward.
                var sumsCount = 1;
                while (sumsCount < (1<<10) && sumsToPerfomRemaining % 2 == 0) // shader can perform only an 2^x number of sums.
                {
                    sumsCount <<= 1;
                    sumsToPerfomRemaining >>= 1;
                }

                // determine the numbers of groups (limited to 65535 groups by dimensions)
                var groupCountX = 1;
                var groupCountY = sumsToPerfomRemaining;
                while (groupCountX >= short.MaxValue)
                {
                    groupCountX <<= 1;
                    groupCountY >>= 1;
                }

                // create the output buffer if not existing yet
                if (secondPassOutputBuffer == null)
                    secondPassOutputBuffer = NewScopedTypedBuffer(coefficientsCount * sumsToPerfomRemaining, PixelFormat.R32G32B32A32_Float, true);

                // draw pass 2
                secondPassEffect.ThreadNumbers = new Int3(sumsCount, 1, 1);
                secondPassEffect.ThreadGroupCounts = new Int3(groupCountX, groupCountY, coefficientsCount);
                secondPassEffect.Parameters.Set(LambertianPrefilteringSHParameters.BlockSize, sumsCount);
                secondPassEffect.Parameters.Set(SphericalHarmonicsParameters.HarmonicsOrder, harmonicalOrder);
                secondPassEffect.Parameters.Set(LambertianPrefilteringSHPass2Keys.InputBuffer, secondPassInputBuffer);
                secondPassEffect.Parameters.Set(LambertianPrefilteringSHPass2Keys.OutputBuffer, secondPassOutputBuffer);
                secondPassEffect.Draw(context);

                // swap second pass input/output buffers.
                var swapTemp = secondPassOutputBuffer;
                secondPassOutputBuffer = secondPassInputBuffer;
                secondPassInputBuffer = swapTemp;
            }

            // create and initialize result SH
            prefilteredLambertianSH = new SphericalHarmonics(HarmonicOrder);

            // Get the data out of the final buffer
            var sizeResult = coefficientsCount * sumsToPerfomRemaining * PixelFormat.R32G32B32A32_Float.SizeInBytes();
            var stagedBuffer = NewScopedBuffer(new BufferDescription(sizeResult, BufferFlags.None, GraphicsResourceUsage.Staging));
            GraphicsDevice.CopyRegion(secondPassInputBuffer, 0, new ResourceRegion(0, 0, 0, sizeResult, 1, 1), stagedBuffer, 0);
            var finalsValues =  stagedBuffer.GetData<Vector4>();    
            
            // performs last possible additions, normalize the result and store it in the SH
            for (var c = 0; c < coefficientsCount; c++)
            {
                var coeff = Vector4.Zero;
                for (var f = 0; f < sumsToPerfomRemaining; ++f)
                {
                    coeff += finalsValues[coefficientsCount * f + c];
                }
                prefilteredLambertianSH.Coefficients[c] = 4 * MathUtil.Pi / coeff.W * new Color3(coeff.X, coeff.Y, coeff.Z);
            }
        }
Example #7
0
    private void OnGUI()
    {
        EditorGUILayout.PropertyField(sp_to_compute);
        so.ApplyModifiedProperties();
        EditorGUILayout.Space();

        if (to_compute != null && GUILayout.Button("Compute Thickness"))
        {
            //create the folder with saved mesh assets
            if (!AssetDatabase.IsValidFolder("Assets/TranslucentMeshes"))
            {
                AssetDatabase.CreateFolder("Assets", "TranslucentMeshes");
            }

            GameObject tmp_camera_object = new GameObject("tmp_camera");
            Camera     tmp_camera        = tmp_camera_object.AddComponent <Camera>();
            tmp_camera.clearFlags      = CameraClearFlags.Color;
            tmp_camera.backgroundColor = Color.black;
            tmp_camera.nearClipPlane   = 0.01f;
            tmp_camera.farClipPlane    = 300;

            GameObject clone    = Instantiate(to_compute.gameObject);
            Mesh       mesh     = Instantiate(to_compute.sharedMesh);
            Vector3[]  vertices = mesh.vertices;
            Vector3[]  normals  = mesh.normals;
            Vector2[]  uv2      = new Vector2[mesh.vertexCount];
            Vector2[]  uv3      = new Vector2[mesh.vertexCount];
            Vector2[]  uv4      = new Vector2[mesh.vertexCount];
            Color[]    colors   = new Color[mesh.vertexCount];

            //temporary storage for the sh coefficients
            Vector4[] coefficients = new Vector4[9];

            //64x64 cubemap should be enough
            Cubemap thickness_cubemap = new Cubemap(128, TextureFormat.RGBA32, false); //TODO: usare formato float

            for (int v = 0; v < mesh.vertexCount; ++v)
            {
                //vertices in the mesh are in local space, transform to world coordinate
                Vector3 vertex_world_position = vertices[v]; // clone.transform.localToWorldMatrix.MultiplyPoint(vertices[v]); //TODO: al posto di lavorare in world space, lavorare in local
                Vector3 world_normal          = normals[v];  // clone.transform.localToWorldMatrix.MultiplyVector(normals[v]);
                tmp_camera.transform.position = vertex_world_position - world_normal * 0.011f;
                tmp_camera.RenderToCubemap(thickness_cubemap);

                //project the cubemap to the spherical harmonic basis
                SphericalHarmonics.GPU_Project_Uniform_9Coeff(thickness_cubemap, coefficients);

                //put 4 coefficients in the vertex color, 2 in the uv2 and 2 in the uv3 and 1 in uv4
                colors[v] = new Color(coefficients[0].x, coefficients[1].x, coefficients[2].x, coefficients[3].x);
                uv2[v]    = new Vector2(coefficients[4].x, coefficients[5].x);
                uv3[v]    = new Vector2(coefficients[6].x, coefficients[7].x);
                uv4[v]    = new Vector2(coefficients[8].x, 0);

                for (int i = 0; i < 9; ++i)
                {
                    coefficients[i] = Vector4.zero;
                }
            }

            mesh.colors = colors;
            mesh.uv2    = uv2;
            mesh.uv3    = uv3;
            mesh.uv4    = uv4;
            mesh.UploadMeshData(true);

            //save the mesh
            AssetDatabase.CreateAsset(mesh, "Assets/TranslucentMeshes/" + to_compute.name + ".asset");

            clone.GetComponent <MeshFilter>().sharedMesh = mesh;

            Object.DestroyImmediate(tmp_camera_object);

            to_compute.gameObject.SetActive(false);
        }
    }
    public void StoreLightmapInfos(int index)
    {
        if (GLog.IsLogInfoEnabled)
        {
            GLog.LogInfo("Storing data for lighting scenario " + index);
        }
        if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.OnDemand)
        {
            if (GLog.IsLogErrorEnabled)
            {
                GLog.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
            }
            return;
        }

        var newLightingScenarioData   = new LightingScenarioData();
        var newRendererInfos          = new List <RendererInfo>();
        var newLightmapsTextures      = new List <Texture2D>();
        var newLightmapsTexturesDir   = new List <Texture2D>();
        var newLightmapsMode          = new LightmapsMode();
        var newSphericalHarmonicsList = new List <SphericalHarmonics>();

        newLightmapsMode = LightmapSettings.lightmapsMode;

        GenerateLightmapInfo(gameObject, newRendererInfos, newLightmapsTextures, newLightmapsTexturesDir, newLightmapsMode);

        newLightingScenarioData.lightmapsMode = newLightmapsMode;

        newLightingScenarioData.lightmaps = newLightmapsTextures.ToArray();

        if (newLightmapsMode != LightmapsMode.NonDirectional)
        {
            newLightingScenarioData.lightmapsDir = newLightmapsTexturesDir.ToArray();
        }

        newLightingScenarioData.rendererInfos = newRendererInfos.ToArray();

        var scene_LightProbes = new SphericalHarmonicsL2[LightmapSettings.lightProbes.bakedProbes.Length];

        scene_LightProbes = LightmapSettings.lightProbes.bakedProbes;

        for (int i = 0; i < scene_LightProbes.Length; i++)
        {
            var SHCoeff = new SphericalHarmonics();

            // j is coefficient
            for (int j = 0; j < 3; j++)
            {
                //k is channel ( r g b )
                for (int k = 0; k < 9; k++)
                {
                    SHCoeff.coefficients[j * 9 + k] = scene_LightProbes[i][j, k];
                }
            }

            newSphericalHarmonicsList.Add(SHCoeff);
        }

        newLightingScenarioData.lightProbes = newSphericalHarmonicsList.ToArray();

        lightingScenariosData = newLightingScenarioData;

        if (lightingScenesNames == null || lightingScenesNames.Count < lightingScenariosCount)
        {
            lightingScenesNames = new List <string>();
            while (lightingScenesNames.Count < lightingScenariosCount)
            {
                lightingScenesNames.Add(null);
            }
        }
    }
    private void OnGUI()
    {
        EditorGUILayout.PropertyField(sp_input_cubemap, new GUIContent("Input Cubemap"));

        so.ApplyModifiedProperties();

        if (input_cubemap != null)
        {
            EditorGUILayout.Space();

            if (GUILayout.Button("CPU Uniform 9 Coefficients"))
            {
                coefficients = new Vector4[9];
                if (SphericalHarmonics.CPU_Project_Uniform_9Coeff(input_cubemap, coefficients))
                {
                    for (int i = 0; i < 9; ++i)
                    {
                        view_mat.SetVector("c" + i.ToString(), coefficients[i]);
                        view_mat.SetTexture("input", input_cubemap);
                    }

                    SceneView.RepaintAll();
                }
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("CPU Monte Carlo 9 Coefficients"))
            {
                coefficients = new Vector4[9];
                if (SphericalHarmonics.CPU_Project_MonteCarlo_9Coeff(input_cubemap, coefficients, 4096))
                {
                    for (int i = 0; i < 9; ++i)
                    {
                        view_mat.SetVector("c" + i.ToString(), coefficients[i]);
                        view_mat.SetTexture("input", input_cubemap);
                    }

                    SceneView.RepaintAll();
                }
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("GPU Uniform 9 Coefficients"))
            {
                coefficients = new Vector4[9];
                if (SphericalHarmonics.GPU_Project_Uniform_9Coeff(input_cubemap, coefficients))
                {
                    for (int i = 0; i < 9; ++i)
                    {
                        view_mat.SetVector("c" + i.ToString(), coefficients[i]);
                        view_mat.SetTexture("input", input_cubemap);
                    }

                    SceneView.RepaintAll();
                }
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("GPU Monte Carlo 9 Coefficients"))
            {
                coefficients = new Vector4[9];

                if (SphericalHarmonics.GPU_Project_MonteCarlo_9Coeff(input_cubemap, coefficients))
                {
                    for (int i = 0; i < 9; ++i)
                    {
                        view_mat.SetVector("c" + i.ToString(), coefficients[i]);
                        view_mat.SetTexture("input", input_cubemap);
                    }
                }
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("Show"))
            {
                RenderSettings.skybox = view_mat;
            }

            view_mode = EditorGUILayout.Slider(view_mode, 0, 1);
            view_mat.SetFloat("_Mode", view_mode);

            EditorGUILayout.Space();

            //print the 9 coefficients
            if (coefficients != null)
            {
                for (int i = 0; i < 9; ++i)
                {
                    EditorGUILayout.LabelField("c_" + i.ToString() + ": " + coefficients[i].ToString("f4"));
                }
            }
        }

        EditorGUILayout.Space();
        if (tmp != null)
        {
            GUILayout.Label(tmp);
        }
    }
    public void StoreLightmapInfos(int index)
    {
        var newLightingScenarioData   = new LightingScenarioData();
        var newRendererInfos          = new List <RendererInfo>();
        var newLightmapsTextures      = new List <Texture2D>();
        var newLightmapsTexturesDir   = new List <Texture2D>();
        var newLightmapsMode          = new LightmapsMode();
        var newSphericalHarmonicsList = new List <SphericalHarmonics>();
        var newLightmapsShadowMasks   = new List <Texture2D>();

        newLightmapsMode = LightmapSettings.lightmapsMode;

        GenerateLightmapInfo(gameObject, newRendererInfos, newLightmapsTextures, newLightmapsTexturesDir, newLightmapsShadowMasks, newLightmapsMode);

        newLightingScenarioData.lightmapsMode = newLightmapsMode;

        newLightingScenarioData.lightmaps = newLightmapsTextures.ToArray();

        if (newLightmapsMode != LightmapsMode.NonDirectional)
        {
            newLightingScenarioData.lightmapsDir = newLightmapsTexturesDir.ToArray();
        }

        //Mixed or realtime support
        newLightingScenarioData.hasRealtimeLights = latestBuildHasReltimeLights;

        newLightingScenarioData.shadowMasks = newLightmapsShadowMasks.ToArray();

        newLightingScenarioData.rendererInfos = newRendererInfos.ToArray();

        var scene_LightProbes = new SphericalHarmonicsL2[LightmapSettings.lightProbes.bakedProbes.Length];

        scene_LightProbes = LightmapSettings.lightProbes.bakedProbes;

        for (int i = 0; i < scene_LightProbes.Length; i++)
        {
            var SHCoeff = new SphericalHarmonics();

            // j is coefficient
            for (int j = 0; j < 3; j++)
            {
                //k is channel ( r g b )
                for (int k = 0; k < 9; k++)
                {
                    SHCoeff.coefficients[j * 9 + k] = scene_LightProbes[i][j, k];
                }
            }

            newSphericalHarmonicsList.Add(SHCoeff);
        }

        newLightingScenarioData.lightProbes = newSphericalHarmonicsList.ToArray();

        if (lightingScenariosData.Count < index + 1)
        {
            lightingScenariosData.Insert(index, newLightingScenarioData);
        }
        else
        {
            lightingScenariosData[index] = newLightingScenarioData;
        }

        lightingScenariosCount = lightingScenariosData.Count;

        if (lightingScenesNames == null || lightingScenesNames.Length < lightingScenariosCount)
        {
            lightingScenesNames = new string[lightingScenariosCount];
        }
    }
Example #11
0
    public void StoreLightmapInfos(int index)
    {
        Debug.Log("Storing data for lighting scenario " + index);
        if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.OnDemand)
        {
            Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
            return;
        }

        var newLightingScenarioData   = new LightingScenarioData();
        var newRendererInfos          = new List <RendererInfo>();
        var newLightmapsTextures      = new List <Texture2D>();
        var newLightmapsTexturesDir   = new List <Texture2D>();
        var newLightmapsMode          = new LightmapsMode();
        var newSphericalHarmonicsList = new List <SphericalHarmonics>();
        var newLightmapsShadowMasks   = new List <Texture2D>();

        newLightmapsMode = LightmapSettings.lightmapsMode;

        GenerateLightmapInfo(gameObject, newRendererInfos, newLightmapsTextures, newLightmapsTexturesDir, newLightmapsShadowMasks, newLightmapsMode);

        newLightingScenarioData.lightmapsMode = newLightmapsMode;

        newLightingScenarioData.lightmaps = newLightmapsTextures.ToArray();

        if (newLightmapsMode != LightmapsMode.NonDirectional)
        {
            newLightingScenarioData.lightmapsDir = newLightmapsTexturesDir.ToArray();
        }

        //Mixed or realtime support
        newLightingScenarioData.hasRealtimeLights = latestBuildHasReltimeLights;

        newLightingScenarioData.shadowMasks = newLightmapsShadowMasks.ToArray();

        newLightingScenarioData.rendererInfos = newRendererInfos.ToArray();

        var scene_LightProbes = new SphericalHarmonicsL2[LightmapSettings.lightProbes.bakedProbes.Length];

        scene_LightProbes = LightmapSettings.lightProbes.bakedProbes;

        for (int i = 0; i < scene_LightProbes.Length; i++)
        {
            var SHCoeff = new SphericalHarmonics();

            // j is coefficient
            for (int j = 0; j < 3; j++)
            {
                //k is channel ( r g b )
                for (int k = 0; k < 9; k++)
                {
                    SHCoeff.coefficients[j * 9 + k] = scene_LightProbes[i][j, k];
                }
            }

            newSphericalHarmonicsList.Add(SHCoeff);
        }

        newLightingScenarioData.lightProbes = newSphericalHarmonicsList.ToArray();

        if (lightingScenariosData.Count < index + 1)
        {
            lightingScenariosData.Insert(index, newLightingScenarioData);
        }
        else
        {
            lightingScenariosData[index] = newLightingScenarioData;
        }

        lightingScenariosCount = lightingScenariosData.Count;

        if (lightingScenesNames == null || lightingScenesNames.Length < lightingScenariosCount)
        {
            lightingScenesNames = new string[lightingScenariosCount];
        }
        if (latestBuildHasReltimeLights && lightingScenesNames[index] != null)
        {
            lightingScenesNames[index] = lightingScenariosScenes[index].name;
        }
    }
Example #12
0
    public void SaveLightMaps()
    {
        LightingScenarioData newLightingScenario = new LightingScenarioData();
        var newRendererInfos           = new List <RendererInfo>();
        var newLightmapsTextures       = new List <Texture2D>();
        var newLightmapsTexturesDir    = new List <Texture2D>();
        var newLightmapsTexturesShadow = new List <Texture2D>();
        var newLightmapsMode           = new LightmapsMode();
        var newSphericalHarmonicsList  = new List <SphericalHarmonics>();

        newLightmapsMode = LightmapSettings.lightmapsMode;

        var renderers = FindObjectsOfType(typeof(MeshRenderer));

        Debug.Log("stored info for " + renderers.Length + " meshrenderers");
        foreach (MeshRenderer renderer in renderers)
        {
            if (renderer.lightmapIndex != -1)
            {
                RendererInfo info = new RendererInfo();
                info.renderer            = renderer;
                info.lightmapOffsetScale = renderer.lightmapScaleOffset;

                Texture2D lightmaplight = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapColor;
                info.lightmapIndex = newLightmapsTextures.IndexOf(lightmaplight);
                if (info.lightmapIndex == -1)
                {
                    info.lightmapIndex = newLightmapsTextures.Count;
                    newLightmapsTextures.Add(lightmaplight);
                }

                if (newLightmapsMode != LightmapsMode.NonDirectional)
                {
                    //first directional lighting
                    Texture2D lightmapdir = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapDir;
                    info.lightmapIndex = newLightmapsTexturesDir.IndexOf(lightmapdir);
                    if (info.lightmapIndex == -1)
                    {
                        info.lightmapIndex = newLightmapsTexturesDir.Count;
                        newLightmapsTexturesDir.Add(lightmapdir);
                    }
                    LightmapData lmd = LightmapSettings.lightmaps[0];
                    //now the shadowmask
                    Texture2D lightmapshadow = LightmapSettings.lightmaps[renderer.lightmapIndex].shadowMask;
                    if (lightmapshadow != null)
                    {
                        info.lightmapIndex = newLightmapsTexturesShadow.IndexOf(lightmapshadow);
                        if (info.lightmapIndex == -1)
                        {
                            info.lightmapIndex = newLightmapsTexturesShadow.Count;
                            newLightmapsTexturesShadow.Add(lightmapshadow);
                        }
                    }
                }
                newRendererInfos.Add(info);
            }
        }


        newLightingScenario.lightmapsMode = newLightmapsMode;
        newLightingScenario.lightmaps     = newLightmapsTextures.ToArray();

        if (newLightmapsMode != LightmapsMode.NonDirectional)
        {
            newLightingScenario.lightmapsDir    = newLightmapsTexturesDir.ToArray();
            newLightingScenario.lightmapsShadow = newLightmapsTexturesShadow.ToArray();
        }

        newLightingScenario.rendererInfos = newRendererInfos.ToArray();

        var scene_LightProbes = new SphericalHarmonicsL2[LightmapSettings.lightProbes.bakedProbes.Length];

        scene_LightProbes = LightmapSettings.lightProbes.bakedProbes;

        for (int i = 0; i < scene_LightProbes.Length; i++)
        {
            var SHCoeff = new SphericalHarmonics();

            // j is coefficient
            for (int j = 0; j < 3; j++)
            {
                //k is channel ( r g b )
                for (int k = 0; k < 9; k++)
                {
                    SHCoeff.coefficients[j * 9 + k] = scene_LightProbes[i][j, k];
                }
            }

            newSphericalHarmonicsList.Add(SHCoeff);
        }

        newLightingScenario.lightProbes = newSphericalHarmonicsList.ToArray();

        // write the files and map config data.
        CreateResourcesDirectory(m_currentLightScenario);

        string resourcesDir = GetResourcesDirectory(m_currentLightScenario);

        CopyTextureToResources(resourcesDir, newLightingScenario.lightmaps);
        CopyTextureToResources(resourcesDir, newLightingScenario.lightmapsDir);
        CopyTextureToResources(resourcesDir, newLightingScenario.lightmapsShadow);

        newLightingScenario.name = m_currentLightScenario;
        SaveLightScenarioData(newLightingScenario);

        UnityEditor.EditorUtility.SetDirty(this.gameObject);
    }
        protected override void DrawCore(RenderDrawContext context)
        {
            var inputTexture = RadianceMap;
            if (inputTexture == null)
                return;

            var coefficientsCount = harmonicalOrder * harmonicalOrder;
            var faceCount = inputTexture.Dimension == TextureDimension.TextureCube ? 6 : 1;
            if (faceCount == 1)
            {
                throw new NotSupportedException("Only texture cube are currently supported as input of 'LambertianPrefilteringNoCompute' effect.");
            }
            firstPassEffect.Parameters.Set(SphericalHarmonicsParameters.HarmonicsOrder, harmonicalOrder);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHNoComputePass1Keys.RadianceMap, inputTexture);

            // Create a tree of power-of-two textures for summing up coefficients
            var intermediateSize = new Int2(MathUtil.NextPowerOfTwo(inputTexture.Width), MathUtil.NextPowerOfTwo(inputTexture.Height));
            var intermediateTextures = new List<Texture>();

            intermediateTextures.Add(NewScopedRenderTarget2D(intermediateSize.X, intermediateSize.Y, PixelFormat.R32G32B32A32_Float));
            while (intermediateSize.X > 1 || intermediateSize.Y > 1)
            {
                if (intermediateSize.X > 1)
                    intermediateSize.X >>= 1;
                if (intermediateSize.Y > 1)
                    intermediateSize.Y >>= 1;

                intermediateTextures.Add(NewScopedRenderTarget2D(intermediateSize.X, intermediateSize.Y, PixelFormat.R32G32B32A32_Float));
            }

            // Create a staging texture for each coefficient
            var stagingTextures = new Texture[coefficientsCount];
            var stagingDescription = intermediateTextures[intermediateTextures.Count - 1].Description.ToStagingDescription();
            for (var c = 0; c < coefficientsCount; c++)
                stagingTextures[c] = Texture.New(GraphicsDevice, stagingDescription);

            // Calculate one coefficient at a time
            for (var c = 0; c < coefficientsCount; c++)
            {
                // Project the radiance on the SH basis and sum up the results for all faces
                firstPassEffect.Parameters.Set(LambertianPrefilteringSHNoComputePass1Keys.CoefficientIndex, c);
                firstPassEffect.Parameters.Set(LambertianPrefilteringSHNoComputePass1Keys.RadianceMap, RadianceMap);
                firstPassEffect.SetOutput(intermediateTextures[0]);
                ((RendererBase)firstPassEffect).Draw(context);

                // Recursive summation
                for (var i = 1; i < intermediateTextures.Count; i++)
                {
                    secondPassEffect.SetInput(intermediateTextures[i - 1]);
                    secondPassEffect.SetOutput(intermediateTextures[i]);
                    ((RendererBase)secondPassEffect).Draw(context);
                }

                context.CommandList.Copy(intermediateTextures[intermediateTextures.Count - 1], stagingTextures[c]);
            }

            // Create and initialize result SH
            PrefilteredLambertianSH = new SphericalHarmonics(HarmonicOrder);

            // Read back coefficients and store it in the SH
            for (var c = 0; c < coefficientsCount; c++)
            {
                var value = stagingTextures[c].GetData<Vector4>(context.CommandList)[0];
                PrefilteredLambertianSH.Coefficients[c] = 4 * MathUtil.Pi / value.W * new Color3(value.X, value.Y, value.Z);
            }
        }
Example #14
0
    public void Initialize()
    {
        oldSkyTex   = Renderer.SkyTex;
        oldSkyLight = Renderer.SkyLight;

        /// :CodeSample: Renderer.SkyTex Renderer.SkyLight Tex.FromCubemapEquirectangular
        /// ## Setting lighting to an equirect cubemap
        /// Changing the environment's lighting based on an image is a really
        /// great way to instantly get a particular feel to your scene! A neat
        /// place to find compatible equirectangular images for this is
        /// [Poly Haven](https://polyhaven.com/hdris)
        Renderer.SkyTex   = Tex.FromCubemapEquirectangular("old_depot.hdr", out SphericalHarmonics lighting);
        Renderer.SkyLight = lighting;
        /// And here's what it looks like applied to the default Material!
        /// ![Default Material example]({{site.screen_url}}/MaterialDefault.jpg)
        /// :End:

        meshSphere = Mesh.GenerateSphere(1, 8);

        /// :CodeSample: Default.Material
        /// If you want to modify the default material, it's recommended to
        /// copy it first!
        matDefault = Default.Material.Copy();
        /// And here's what it looks like:
        /// ![Default Material example]({{site.screen_url}}/MaterialDefault.jpg)
        /// :End:

        /// :CodeSample: Default.MaterialUI
        /// This Material is basically the same as Default.Material, except it
        /// also adds some glow to the surface near the user's fingers. It
        /// works best on flat surfaces, and in StereoKit's design language,
        /// can be used to indicate that something is interactive.
        matUI = Default.MaterialUI.Copy();
        /// And here's what it looks like:
        /// ![UI Material example]({{site.screen_url}}/MaterialUI.jpg)
        /// :End:

        /// :CodeSample: Material.Wireframe
        /// Here's creating a simple wireframe material!
        matWireframe           = Default.Material.Copy();
        matWireframe.Wireframe = true;
        /// Which looks like this:
        /// ![Wireframe material example]({{site.screen_url}}/MaterialWireframe.jpg)
        /// :End:

        /// :CodeSample: Material.FaceCull Cull.Front
        /// Here's setting FaceCull to Front, which is the opposite of the
        /// default behavior. On a sphere, this is a little hard to see, but
        /// you might notice here that the lighting is for the back side of
        /// the sphere!
        matCull          = Default.Material.Copy();
        matCull.FaceCull = Cull.Front;
        /// ![FaceCull material example]({{site.screen_url}}/MaterialCull.jpg)
        /// :End:

        /// :CodeSample: Material.Transparency Transparency.Add
        /// ## Additive Transparency
        /// Here's an example material with additive transparency.
        /// Transparent materials typically don't write to the depth buffer,
        /// but this may vary from case to case. Note that the material's
        /// alpha does not play any role in additive transparency! Instead,
        /// you could make the material's tint darker.
        matAlphaAdd = Default.Material.Copy();
        matAlphaAdd.Transparency = Transparency.Add;
        matAlphaAdd.DepthWrite   = false;
        /// ![Additive transparency example]({{site.screen_url}}/MaterialAlphaAdd.jpg)
        /// :End:

        /// :CodeSample: Material.Transparency Transparency.Blend
        /// ## Alpha Blending
        /// Here's an example material with an alpha blend transparency.
        /// Transparent materials typically don't write to the depth buffer,
        /// but this may vary from case to case. Here we're setting the alpha
        /// through the material's Tint value, but the diffuse texture's
        /// alpha and the instance render color's alpha may also play a part
        /// in the final alpha value.
        matAlphaBlend = Default.Material.Copy();
        matAlphaBlend.Transparency            = Transparency.Blend;
        matAlphaBlend.DepthWrite              = false;
        matAlphaBlend[MatParamName.ColorTint] = new Color(1, 1, 1, 0.75f);
        /// ![Alpha blend example]({{site.screen_url}}/MaterialAlphaBlend.jpg)
        /// :End:

        matTextured = Default.Material.Copy();
        matTextured[MatParamName.DiffuseTex] = Tex.FromFile("floor.png");

        /// :CodeSample: Default.MaterialUnlit
        matUnlit = Default.MaterialUnlit.Copy();
        matUnlit[MatParamName.DiffuseTex] = Tex.FromFile("floor.png");
        /// ![Unlit material example]({{site.screen_url}}/MaterialUnlit.jpg)
        /// :End:

        /// :CodeSample: Default.MaterialPBR
        /// Occlusion (R), Roughness (G), and Metal (B) are stored
        /// respectively in the R, G and B channels of their texture.
        /// Occlusion can be separated out into a different texture as per
        /// the GLTF spec, so you do need to assign it separately from the
        /// Metal texture.
        matPBR = Default.MaterialPBR.Copy();
        matPBR[MatParamName.DiffuseTex]   = Tex.FromFile("metal_plate_diff.jpg");
        matPBR[MatParamName.MetalTex]     = Tex.FromFile("metal_plate_metal.jpg", false);
        matPBR[MatParamName.OcclusionTex] = Tex.FromFile("metal_plate_metal.jpg", false);
        /// ![PBR material example]({{site.screen_url}}/MaterialPBR.jpg)
        /// :End:

        /// :CodeSample: Default.MaterialUIBox
        /// The UI Box material has 3 parameters to control how the box wires
        /// are rendered. The initial size in meters is 'border_size', and
        /// can grow by 'border_size_grow' meters based on distance to the
        /// user's hand. That distance can be configured via the
        /// 'border_affect_radius' property of the shader, which is also in
        /// meters.
        matUIBox = Default.MaterialUIBox.Copy();
        matUIBox["border_size"]          = 0.005f;
        matUIBox["border_size_grow"]     = 0.01f;
        matUIBox["border_affect_radius"] = 0.2f;
        /// ![UI box material example]({{site.screen_url}}/MaterialUIBox.jpg)
        /// :End:

        matParameters = Default.Material.Copy();
        matParameters[MatParamName.DiffuseTex] = Tex.FromFile("floor.png");
        matParameters[MatParamName.ColorTint]  = Color.HSV(0.6f, 0.7f, 1f);
        matParameters[MatParamName.TexScale]   = 2;
    }
Example #15
0
    private void OnGUI()
    {
        modle = EditorGUILayout.Toggle("CubeMap", modle);
        if (modle)
        {
            input_cubemap = EditorGUILayout.ObjectField("Input Cubemap", input_cubemap, typeof(Cubemap), true) as Cubemap;
            isCopyNew     = EditorGUILayout.Toggle("从环境球获取", isCopyNew);
            if (input_cubemap != null)
            {
                EditorGUILayout.Space();

                if (GUILayout.Button("CPU Uniform 9 Coefficients"))
                {
                    Cubemap cm = input_cubemap;
                    if (isCopyNew)
                    {
                        test = cm = CopyFromEnvMap();
                    }

                    ModifyTextureReadable();
                    coefficients = new Vector4[9];
                    if (SphericalHarmonics.CPU_Project_Uniform_9Coeff(cm, coefficients))
                    {
                        setSH9Global();
                    }
                    if (isCopyNew)
                    {
                        GameObject.DestroyImmediate(cm, true);
                    }
                }

                EditorGUILayout.Space();

                if (GUILayout.Button("CPU Monte Carlo 9 Coefficients"))
                {
                    Cubemap cm = input_cubemap;
                    if (isCopyNew)
                    {
                        cm = CopyFromEnvMap();
                    }
                    ModifyTextureReadable();
                    coefficients = new Vector4[9];
                    if (SphericalHarmonics.CPU_Project_MonteCarlo_9Coeff(cm, coefficients, 4096))
                    {
                        setSH9Global();
                    }
                    if (isCopyNew)
                    {
                        GameObject.DestroyImmediate(cm, true);
                    }
                }

                EditorGUILayout.Space();

                if (GUILayout.Button("GPU Uniform 9 Coefficients"))
                {
                    Cubemap cm = input_cubemap;
                    if (isCopyNew)
                    {
                        input_cubemap = cm = CopyFromEnvMap();
                    }
                    ModifyTextureReadable();
                    coefficients = new Vector4[9];
                    if (SphericalHarmonics.GPU_Project_Uniform_9Coeff(cm, coefficients))
                    {
                        setSH9Global();
                    }
                    if (isCopyNew)
                    {
                        GameObject.DestroyImmediate(cm, true);
                    }
                }

                EditorGUILayout.Space();

                if (GUILayout.Button("GPU Monte Carlo 9 Coefficients"))
                {
                    Cubemap cm = input_cubemap;
                    if (isCopyNew)
                    {
                        cm = CopyFromEnvMap();
                    }
                    ModifyTextureReadable();
                    coefficients = new Vector4[9];
                    if (SphericalHarmonics.GPU_Project_MonteCarlo_9Coeff(cm, coefficients))
                    {
                        setSH9Global();
                    }
                    if (isCopyNew)
                    {
                        GameObject.DestroyImmediate(cm, true);
                    }
                }

                EditorGUILayout.Space();
            }
        }
        else
        {
            env_map = EditorGUILayout.ObjectField("360环境球", env_map, typeof(Texture2D), true) as Texture2D;

            if (env_map)
            {
                sun = EditorGUILayout.Toggle("太阳", sun);
            }

            enableLight = EditorGUILayout.Toggle("灯光", enableLight);

            if (enableLight)
            {
                GUILayout.BeginHorizontal();
                if (GUILayout.Button("+"))
                {
                    lights.Add(null);
                }
                if (GUILayout.Button("-"))
                {
                    if (lights.Count > 0)
                    {
                        lights.RemoveAt(lights.Count - 1);
                    }
                }


                GUILayout.EndHorizontal();
                for (int i = 0; i < lights.Count; i++)
                {
                    lights[i] = EditorGUILayout.ObjectField("360环境球", lights[i], typeof(Light), true) as Light;
                }
            }
            bool hasLight = false;
            for (int i = 0; i < lights.Count; i++)
            {
                if (lights [i] != null)
                {
                    hasLight = true;
                    break;
                }
            }
            //lights
            if (hasLight || env_map != null)
            {
                EditorGUILayout.Space();

                if (GUILayout.Button("CPU Uniform 9 Coefficients"))
                {
                    ModifyTextureReadable(env_map);
                    List <Light> ls = new List <Light> ();
                    foreach (Light l in lights)
                    {
                        if (l != null)
                        {
                            ls.Add(l);
                        }
                    }

                    coefficients = new Vector4[9];
                    if (SphericalHarmonics.CPU_Project_360HJQ(env_map, coefficients, 4096, sun, ls.ToArray()))
                    {
                        setSH9Global();
                    }
                }
            }
        }



        if (coefficients != null && coefficients.Length == 9)
        {
            if (GUILayout.Button("保存"))
            {
                SH9Data data = SH9Data.CreateInstance <SH9Data> ();
                data.coefficients = coefficients;

                string path = EditorUtility.SaveFilePanelInProject("Save SH9 Data", "ibl.asset", "asset",
                                                                   "Please enter a file name to save the texture to");
                if (path.Length != 0)
                {
                    if (System.IO.File.Exists(path))
                    {
                        /*if (EditorUtility.DisplayDialog("目标已存在", "替换", "取消"))
                         *      {
                         *
                         *      }*/

                        data.test         = new Vector4(1, 0, 0, 1);
                        data              = AssetDatabase.LoadAssetAtPath <SH9Data> (path);
                        data.coefficients = coefficients;
                        AssetDatabase.SaveAssets();
                    }
                    else
                    {
                        data.test = Vector4.one;
                        AssetDatabase.CreateAsset(data, path);
                        AssetDatabase.ImportAsset(path);
                    }
                }
            }
            EditorGUILayout.Space();
            for (int i = 0; i < 9; ++i)
            {
                EditorGUILayout.LabelField("c_" + i.ToString() + ": " + coefficients[i].ToString("f4"));
            }
        }


        EditorGUILayout.Space();
        if (tmp != null)
        {
            GUILayout.Label(tmp);
        }
    }
Example #16
0
        protected override void DrawCore(RenderDrawContext context)
        {
            var inputTexture = RadianceMap;

            if (inputTexture == null)
            {
                return;
            }

            const int FirstPassBlockSize = 4;
            const int FirstPassSumsCount = FirstPassBlockSize * FirstPassBlockSize;

            var faceCount = inputTexture.ViewDimension == TextureDimension.TextureCube ? 6 : 1;

            if (faceCount == 1)
            {
                throw new NotSupportedException("Only texture cube are currently supported as input of 'LambertianPrefilteringSH' effect.");
            }
            var inputSize         = new Int2(inputTexture.Width, inputTexture.Height); // (Note: for cube maps width = height)
            var coefficientsCount = harmonicalOrder * harmonicalOrder;

            var sumsToPerfomRemaining = inputSize.X * inputSize.Y * faceCount / FirstPassSumsCount;
            var partialSumBuffer      = NewScopedTypedBuffer(coefficientsCount * sumsToPerfomRemaining, PixelFormat.R32G32B32A32_Float, true);

            // Project the radiance on the SH basis and sum up the results along the 4x4 blocks
            firstPassEffect.ThreadNumbers     = new Int3(FirstPassBlockSize, FirstPassBlockSize, 1);
            firstPassEffect.ThreadGroupCounts = new Int3(inputSize.X / FirstPassBlockSize, inputSize.Y / FirstPassBlockSize, faceCount);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHParameters.BlockSize, FirstPassBlockSize);
            firstPassEffect.Parameters.Set(SphericalHarmonicsParameters.HarmonicsOrder, harmonicalOrder);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHPass1Keys.RadianceMap, inputTexture);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHPass1Keys.OutputBuffer, partialSumBuffer);
            ((RendererBase)firstPassEffect).Draw(context);

            // Recursively applies the pass2 (sums the coefficients together) as long as needed. Swap input/output buffer at each iteration.
            var    secondPassInputBuffer  = partialSumBuffer;
            Buffer secondPassOutputBuffer = null;

            while (sumsToPerfomRemaining % 2 == 0)
            {
                // we are limited in the number of summing threads by the group-shared memory size.
                // determine the number of threads to use and update the number of sums remaining afterward.
                var sumsCount = 1;
                while (sumsCount < (1 << 10) && sumsToPerfomRemaining % 2 == 0) // shader can perform only an 2^x number of sums.
                {
                    sumsCount             <<= 1;
                    sumsToPerfomRemaining >>= 1;
                }

                // determine the numbers of groups (limited to 65535 groups by dimensions)
                var groupCountX = 1;
                var groupCountY = sumsToPerfomRemaining;
                while (groupCountX >= short.MaxValue)
                {
                    groupCountX <<= 1;
                    groupCountY >>= 1;
                }

                // create the output buffer if not existing yet
                if (secondPassOutputBuffer == null)
                {
                    secondPassOutputBuffer = NewScopedTypedBuffer(coefficientsCount * sumsToPerfomRemaining, PixelFormat.R32G32B32A32_Float, true);
                }

                // draw pass 2
                secondPassEffect.ThreadNumbers     = new Int3(sumsCount, 1, 1);
                secondPassEffect.ThreadGroupCounts = new Int3(groupCountX, groupCountY, coefficientsCount);
                secondPassEffect.Parameters.Set(LambertianPrefilteringSHParameters.BlockSize, sumsCount);
                secondPassEffect.Parameters.Set(SphericalHarmonicsParameters.HarmonicsOrder, harmonicalOrder);
                secondPassEffect.Parameters.Set(LambertianPrefilteringSHPass2Keys.InputBuffer, secondPassInputBuffer);
                secondPassEffect.Parameters.Set(LambertianPrefilteringSHPass2Keys.OutputBuffer, secondPassOutputBuffer);
                ((RendererBase)secondPassEffect).Draw(context);

                // swap second pass input/output buffers.
                var swapTemp = secondPassOutputBuffer;
                secondPassOutputBuffer = secondPassInputBuffer;
                secondPassInputBuffer  = swapTemp;
            }

            // create and initialize result SH
            prefilteredLambertianSH = new SphericalHarmonics(HarmonicOrder);

            // Get the data out of the final buffer
            var sizeResult   = coefficientsCount * sumsToPerfomRemaining * PixelFormat.R32G32B32A32_Float.SizeInBytes();
            var stagedBuffer = NewScopedBuffer(new BufferDescription(sizeResult, BufferFlags.None, GraphicsResourceUsage.Staging));

            context.CommandList.CopyRegion(secondPassInputBuffer, 0, new ResourceRegion(0, 0, 0, sizeResult, 1, 1), stagedBuffer, 0);
            var finalsValues = stagedBuffer.GetData <Vector4>(context.CommandList);

            // performs last possible additions, normalize the result and store it in the SH
            for (var c = 0; c < coefficientsCount; c++)
            {
                var coeff = Vector4.Zero;
                for (var f = 0; f < sumsToPerfomRemaining; ++f)
                {
                    coeff += finalsValues[coefficientsCount * f + c];
                }
                prefilteredLambertianSH.Coefficients[c] = 4 * MathUtil.Pi / coeff.W * new Color3(coeff.X, coeff.Y, coeff.Z);
            }
        }
Example #17
0
        protected override void DrawCore(RenderDrawContext context)
        {
            var inputTexture = RadianceMap;

            if (inputTexture == null)
            {
                return;
            }

            var coefficientsCount = harmonicalOrder * harmonicalOrder;
            var faceCount         = inputTexture.ViewDimension == TextureDimension.TextureCube ? 6 : 1;

            if (faceCount == 1)
            {
                throw new NotSupportedException("Only texture cube are currently supported as input of 'LambertianPrefilteringNoCompute' effect.");
            }
            firstPassEffect.Parameters.Set(SphericalHarmonicsParameters.HarmonicsOrder, harmonicalOrder);
            firstPassEffect.Parameters.Set(LambertianPrefilteringSHNoComputePass1Keys.RadianceMap, inputTexture);

            // Create a tree of power-of-two textures for summing up coefficients
            var intermediateSize     = new Int2(MathUtil.NextPowerOfTwo(inputTexture.Width), MathUtil.NextPowerOfTwo(inputTexture.Height));
            var intermediateTextures = new List <Texture>();

            intermediateTextures.Add(NewScopedRenderTarget2D(intermediateSize.X, intermediateSize.Y, PixelFormat.R32G32B32A32_Float));
            while (intermediateSize.X > 1 || intermediateSize.Y > 1)
            {
                if (intermediateSize.X > 1)
                {
                    intermediateSize.X >>= 1;
                }
                if (intermediateSize.Y > 1)
                {
                    intermediateSize.Y >>= 1;
                }

                intermediateTextures.Add(NewScopedRenderTarget2D(intermediateSize.X, intermediateSize.Y, PixelFormat.R32G32B32A32_Float));
            }

            // Create a staging texture for each coefficient
            var stagingTextures    = new Texture[coefficientsCount];
            var stagingDescription = intermediateTextures[intermediateTextures.Count - 1].Description.ToStagingDescription();

            for (var c = 0; c < coefficientsCount; c++)
            {
                stagingTextures[c] = Texture.New(GraphicsDevice, stagingDescription);
            }

            // Calculate one coefficient at a time
            for (var c = 0; c < coefficientsCount; c++)
            {
                // Project the radiance on the SH basis and sum up the results for all faces
                firstPassEffect.Parameters.Set(LambertianPrefilteringSHNoComputePass1Keys.CoefficientIndex, c);
                firstPassEffect.Parameters.Set(LambertianPrefilteringSHNoComputePass1Keys.RadianceMap, RadianceMap);
                firstPassEffect.SetOutput(intermediateTextures[0]);
                ((RendererBase)firstPassEffect).Draw(context);

                // Recursive summation
                for (var i = 1; i < intermediateTextures.Count; i++)
                {
                    secondPassEffect.SetInput(intermediateTextures[i - 1]);
                    secondPassEffect.SetOutput(intermediateTextures[i]);
                    ((RendererBase)secondPassEffect).Draw(context);
                }

                context.CommandList.Copy(intermediateTextures[intermediateTextures.Count - 1], stagingTextures[c]);
            }

            // Create and initialize result SH
            PrefilteredLambertianSH = new SphericalHarmonics(HarmonicOrder);

            // Read back coefficients and store it in the SH
            for (var c = 0; c < coefficientsCount; c++)
            {
                var value = stagingTextures[c].GetData <Vector4>(context.CommandList)[0];
                PrefilteredLambertianSH.Coefficients[c] = 4 * MathUtil.Pi / value.W * new Color3(value.X, value.Y, value.Z);
            }
        }
Example #18
0
    public void Compute()
    {
        Material old_skybox    = RenderSettings.skybox;
        Material cosine_skybox = new Material(Shader.Find("SH/CosineSkybox"));

        RenderSettings.skybox = cosine_skybox;

        //create the folder with saved mesh assets
        if (!AssetDatabase.IsValidFolder("Assets/ComputedMeshes"))
        {
            AssetDatabase.CreateFolder("Assets", "ComputedMeshes");
        }

        //don't modify the original objects but make a copy
        GameObject parent = new GameObject("computed");

        parent.SetActive(false);

        GameObject tmp_camera_object = new GameObject("tmp_camera");
        Camera     tmp_camera        = tmp_camera_object.AddComponent <Camera>();

        tmp_camera.clearFlags    = CameraClearFlags.Skybox;
        tmp_camera.nearClipPlane = 0.01f;
        tmp_camera.farClipPlane  = 300;

        //temporary storage for the sh coefficients
        Vector4[] coefficients = new Vector4[9];

        //64x64 cubemap should be enough
        Cubemap visibility_cubemap = new Cubemap(64, TextureFormat.RGBA32, false);

        //cycle the children renderers
        MeshRenderer[] to_compute = gameObject.GetComponentsInChildren <MeshRenderer>();

        //get the total number of vertex to compute
        int total_vertex     = 0;
        int completed_vertex = 0;

        foreach (MeshRenderer mr in to_compute)
        {
            if (mr.gameObject.isStatic)
            {
                total_vertex = mr.gameObject.GetComponent <MeshFilter>().sharedMesh.vertexCount;
            }
        }

        //shader for rendering the visibility (black = occluded)
        Shader black_shader = Shader.Find("SH/BlackShader");

        foreach (MeshRenderer mr in to_compute)
        {
            if (mr.gameObject.isStatic) //compute only static objects
            {
                //clone the original
                GameObject clone = Instantiate(mr.gameObject);
                clone.name = mr.gameObject.name;
                clone.transform.SetParent(parent.transform);

                Mesh      mesh     = Instantiate(mr.gameObject.GetComponent <MeshFilter>().sharedMesh);
                Vector3[] vertices = mesh.vertices;
                Vector3[] normals  = mesh.normals;
                Vector2[] uv2      = new Vector2[mesh.vertexCount];
                Vector2[] uv3      = new Vector2[mesh.vertexCount];
                Vector2[] uv4      = new Vector2[mesh.vertexCount];
                Color[]   colors   = new Color[mesh.vertexCount];

                for (int v = 0; v < mesh.vertexCount; ++v)
                {
                    //vertices in the mesh are in local space, transform to world coordinate
                    Vector3 vertex_world_position = clone.transform.localToWorldMatrix.MultiplyPoint(vertices[v]);
                    Vector3 world_normal          = clone.transform.localToWorldMatrix.MultiplyVector(normals[v]);
                    tmp_camera.transform.position = vertex_world_position + world_normal * 0.011f;  //offset the camera a little in the normal direction
                    cosine_skybox.SetVector("N", world_normal);

                    tmp_camera.SetReplacementShader(black_shader, "");
                    tmp_camera.RenderToCubemap(visibility_cubemap);
                    tmp_camera.ResetReplacementShader();

                    //project the cubemap to the spherical harmonic basis
                    SphericalHarmonics.GPU_Project_Uniform_9Coeff(visibility_cubemap, coefficients);

                    //put 4 coefficients in the vertex color, 2 in the uv2 and 2 in the uv3 and 1 in uv4
                    colors[v] = new Color(coefficients[0].x, coefficients[1].x, coefficients[2].x, coefficients[3].x);
                    uv2[v]    = new Vector2(coefficients[4].x, coefficients[5].x);
                    uv3[v]    = new Vector2(coefficients[6].x, coefficients[7].x);
                    uv4[v]    = new Vector2(coefficients[8].x, 0);

                    for (int i = 0; i < 9; ++i)
                    {
                        coefficients[i] = Vector4.zero;
                    }

                    completed_vertex++;
                }

                mesh.colors = colors;
                mesh.uv2    = uv2;
                mesh.uv3    = uv3;
                mesh.uv4    = uv4;
                mesh.UploadMeshData(true);

                //save the mesh
                AssetDatabase.CreateAsset(mesh, "Assets/ComputedMeshes/" + mr.name + ".asset");

                clone.GetComponent <MeshFilter>().sharedMesh = mesh;

                Material mat = new Material(Shader.Find("SH/SH_Shader"));
                clone.GetComponent <MeshRenderer>().material = mat;
            }
        }

        Object.DestroyImmediate(tmp_camera_object);

        gameObject.SetActive(false);
        parent.SetActive(true);

        RenderSettings.skybox = old_skybox;
    }