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); } }
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); } }
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 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; }