void CubemapToEnvMap() { Texture2D resultTex = new Texture2D(m_DstTexSize, m_DstTexSize, TextureFormat.RGB24, false); float invTexRes = 1.0f / (resultTex.height - 1); //bool topHemisphere = true; for (int y = 0; y < resultTex.height; y++) { for (int x = 0; x < resultTex.width; x++) { Vector3 dir; float xf = (float)x * invTexRes; float yf = (float)y * invTexRes; xf = xf * 2 - 1; yf = yf * 2 - 1; float p = 0.5f - 0.5f * (xf * xf + yf * yf); dir.x = xf; dir.y = p; dir.z = yf; dir.Normalize(); // float theta = 2 * Mathf.Acos(Mathf.Sqrt(1 - xf)); // float phi = topHemisphere ? (Mathf.PI * yf) : (2 * Mathf.PI * yf); // dir.x = Mathf.Sin(theta) * Mathf.Cos(phi); // dir.y = Mathf.Sin(theta) * Mathf.Sin(phi); // dir.z = Mathf.Cos(theta); CubemapFace face; float u, v; DirToUV(dir, out face, out u, out v); Color col = m_Cubemap.GetPixel(face, (int)(u * m_Cubemap.width), (int)(v * m_Cubemap.height)); resultTex.SetPixel(x, y, col); } } resultTex.Apply(); SaveTex(resultTex, "Assets/GeneratedTextures/envmap.png"); }
Vector4 GetCubeColor(Vector3 pos) { Color col = new Color(); //可以使用正态分布 float xabs = pos.x; float yabs = pos.y; float zabs = pos.z; int faceIndex = -1; Vector2 uv = new Vector2(); if (xabs >= yabs && xabs >= zabs) { //x faceIndex = pos.x > 0 ? 0 : 1; uv.x = pos.y / xabs; uv.y = pos.z / xabs; } else if (yabs >= xabs && yabs >= zabs) { //y faceIndex = pos.y > 0 ? 2 : 3; uv.x = pos.x / yabs; uv.y = pos.z / yabs; } else { //z faceIndex = pos.z > 0 ? 4 : 5; uv.x = pos.x / zabs; uv.y = pos.y / zabs; } //[0,1.0] uv.x = (uv.x + 1.0f) / 2.0f; uv.y = (uv.y + 1.0f) / 2.0f; int w = cubeMap.width - 1; int x = (int)(w * uv.x); int y = (int)(w * uv.y); //Debug.Log("random face:" + faceIndex.ToString()); if (faceCalculate.ContainsKey(faceIndex)) { faceCalculate[faceIndex]++; } col = cubeMap.GetPixel((CubemapFace)faceIndex, x, y); Vector4 colVec4 = new Vector4(col.r, col.g, col.b, col.a); return(colVec4); }
/// <summary> ///保存单张图片 /// </summary> private void SaveSingelTexture() { Texture2D screenShot = new Texture2D(renderCubeMap.width, renderCubeMap.height, TextureFormat.ARGB32, false); for (int i = 0; i < renderCubeMap.width; i++) { for (int j = 0; j < renderCubeMap.height; j++) { screenShot.SetPixel(i, j, renderCubeMap.GetPixel(offcialFaces, renderCubeMap.width - i, renderCubeMap.height - j)); } } screenShot.Apply(); byte[] bytes = screenShot.EncodeToPNG(); string path = EditorUtility.SaveFilePanel("图片保存", Application.dataPath, faces.ToString(), "png"); System.IO.File.WriteAllBytes(path, bytes); AssetDatabase.Refresh(); }
void BackUpAndScaleAndFormatAndSizeAndCopyCubeTexture(List <Cubemap> cubeMapGroup, int maxSize) { for (int i = 0; i < cubeMapGroup.Count; i++) { string fileName = CopyTextureToFolder(cubeMapGroup[i].GetInstanceID(), tempTextureFolderFinal, true); AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); TextureImporter textureImporter = (TextureImporter)TextureImporter.GetAtPath(fileName); textureImporter.textureShape = TextureImporterShape.TextureCube; textureImporter.isReadable = true; textureImporter.maxTextureSize = maxSize; textureImporter.mipmapEnabled = false; textureImporter.wrapMode = TextureWrapMode.Clamp; textureImporter.filterMode = FilterMode.Point; textureImporter.textureCompression = TextureImporterCompression.Uncompressed; AssetDatabase.ImportAsset(fileName); Cubemap loadTex = (Cubemap)AssetDatabase.LoadAssetAtPath(fileName, typeof(Cubemap)); Texture2D exportSaveTex; exportSaveTex = new Texture2D(loadTex.width, loadTex.height, TextureFormat.RGB24, false, false); for (int j = 0; j < 6; j++) { for (int k = 0; k < exportSaveTex.width; k++) { for (int z = 0; z < exportSaveTex.height; z++) { exportSaveTex.SetPixel(k, exportSaveTex.height - z - 1, loadTex.GetPixel((CubemapFace)j, k, z)); } } // exportSaveTex.SetPixels(loadTex.GetPixels((CubemapFace)j)); exportSaveTex.Apply(); var bytes = exportSaveTex.EncodeToJPG(95); File.WriteAllBytes(textureFolderFinal + "/" + loadTex.name + "_" + j + ".jpg", bytes); } } }
public static int GetPixel(IntPtr l) { int result; try { Cubemap cubemap = (Cubemap)LuaObject.checkSelf(l); CubemapFace face; LuaObject.checkEnum <CubemapFace>(l, 2, out face); int x; LuaObject.checkType(l, 3, out x); int y; LuaObject.checkType(l, 4, out y); Color pixel = cubemap.GetPixel(face, x, y); LuaObject.pushValue(l, true); LuaObject.pushValue(l, pixel); result = 2; } catch (Exception e) { result = LuaObject.error(l, e); } return(result); }
// Start is called before the first frame update void Start() { query = new KDQuery(); VPLVector = new Vector3[InitVPLCount]; VPLPoints = new Vector3[InitVPLCount]; SpotAngle = GetComponent <Light>().spotAngle; if (type == "Point Light") { Vector3 org = this.transform.position; RaycastHit hit; parent = new GameObject(); for (int i = 0; i < InitVPLCount; i++) { float Rx = Random48.Get(); float Ry = Random48.Get(); float Rz = Random48.Get(); Rx = halton(seedCount, 2); Ry = halton(seedCount, 3); Rz = halton(seedCount++, 4); seedCount = seedCount % (maxSeed * 3); Vector3 tempDir = new Vector3(Rx * 2.0f - 1.0f, Ry * 2.0f - 1.0f, Rz * 2.0f - 1.0f); //tempDir.Normalize(); //tempDir -= new Vector3(0.5f,0.5f,0.5f); VPLVector[i] = (tempDir); Vector3 B = tempDir; Vector3 dir = this.transform.right * B.x + this.transform.up * B.y - this.transform.forward * B.z; if (Physics.Raycast(org, dir, out hit, 1000)) { VPLPoints[i] = (hit.point); } GameObject temp = new GameObject(); temp.transform.parent = parent.transform; temp.transform.position = VPLPoints[i]; temp.AddComponent <Light>(); temp.GetComponent <Light>().shadows = LightShadows.Hard; temp.GetComponent <Light>().shadowBias = 0; temp.GetComponent <Light>().shadowNormalBias = 0; temp.GetComponent <Light>().shadowNearPlane = 0.2f; Vector3 CubeUV = convert_xyz_to_cube_uv(B); if (CubeUV.x == 0.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveX, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 1.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeX, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 2.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveY, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 3.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeY, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 4.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveZ, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 5.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeZ, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } VPL.Add(temp); } } else { int PassCount = 0; Vector3 org = this.transform.position; RaycastHit hit; Texture2D tempTex = new Texture2D(1024, 1024); RenderTexture.active = rendertexture; tempTex.ReadPixels(new UnityEngine.Rect(0, 0, 1024, 1024), 0, 0); parent = new GameObject(); Debug.DrawLine(transform.position + transform.forward * 10, this.transform.position); while (PassCount != InitVPLCount) { //float Rx = ((float)Random.Range(0, 1024)) / 1024.0f; //float Ry = ((float)Random.Range(0, 1024)) / 1024.0f; float Rx = Random48.Get(); float Ry = Random48.Get(); Rx = halton(seedCount, 2); Ry = halton(seedCount++, 3); seedCount = seedCount % (maxSeed * 2); if (Mathf.Sqrt((Rx - 0.5f) * (Rx - 0.5f) + (Ry - 0.5f) * (Ry - 0.5f)) <= radius) { Vector3 B = new Vector2(Rx, Ry); B.x -= 0.5f; B.y -= 0.5f; VPLVector[PassCount] = B; // float l = Vector3.Dot(B, B); float z; z = -Mathf.Tan((Fov / 2.0f) / 180.0f * 3.1415926f); Vector3 dir = this.transform.right * B.x + this.transform.up * B.y - this.transform.forward * z; if (Physics.Raycast(org, dir, out hit, 1000)) { Vector3 p; p.x = B.x * 1024.0f; p.y = B.y * 1024.0f; GameObject temp = new GameObject(); temp.transform.parent = parent.transform; temp.transform.position = hit.point; temp.AddComponent <Light>(); temp.GetComponent <Light>().color = (tempTex.GetPixel((int)p.x, (int)p.y)); temp.GetComponent <Light>().shadows = LightShadows.Hard; VPL.Add(temp); VPLPoints[PassCount] = hit.point; PassCount++; } else { continue; } } } int a = 1; tree = new KDTree(VPLPoints, 16); } }
void Update() { if (cubemapType == CubemapType.SkyboxCubemap) { messageSkybox = true; messageClouds = false; } else { messageSkybox = false; messageClouds = true; } if (generateCubemap) { var cam = GetComponent <Camera>(); var path = "Assets/Generated Skybox Cubemap.png"; if (cubemapType == CubemapType.CloudsCubemap) { path = "Assets/Generated Clouds Cubemap.png"; } Cubemap cubemap = new Cubemap((int)cubemapSize, UnityEngine.Experimental.Rendering.GraphicsFormat.R32G32B32A32_SFloat, 0); cam.RenderToCubemap(cubemap); cubemap.Apply(); Texture2D img = new Texture2D((int)cubemapSize * 6, (int)cubemapSize, TextureFormat.RGBAFloat, false); for (int i = 0; i < (int)cubemapSize; i++) { for (int j = 0; j < (int)cubemapSize; j++) { var pixelColor = cubemap.GetPixel(CubemapFace.PositiveX, i, (int)cubemapSize - j); var pixelValue = 1.0f; if (cubemapType == CubemapType.CloudsCubemap) { pixelValue = pixelColor.r + pixelColor.g + pixelColor.b; } img.SetPixel(i, j, new Color(pixelColor.r, pixelColor.g, pixelColor.b, pixelValue)); } } for (int i = 0; i < (int)cubemapSize; i++) { for (int j = 0; j < (int)cubemapSize; j++) { var pixelColor = cubemap.GetPixel(CubemapFace.NegativeX, i, (int)cubemapSize - j); var pixelValue = 1.0f; if (cubemapType == CubemapType.CloudsCubemap) { pixelValue = pixelColor.r + pixelColor.g + pixelColor.b; } img.SetPixel(i + (int)cubemapSize, j, new Color(pixelColor.r, pixelColor.g, pixelColor.b, pixelValue)); } } for (int i = 0; i < (int)cubemapSize; i++) { for (int j = 0; j < (int)cubemapSize; j++) { var pixelColor = cubemap.GetPixel(CubemapFace.PositiveY, i, (int)cubemapSize - j); var pixelValue = 1.0f; if (cubemapType == CubemapType.CloudsCubemap) { pixelValue = pixelColor.r + pixelColor.g + pixelColor.b; } img.SetPixel(i + (int)cubemapSize * 2, j, new Color(pixelColor.r, pixelColor.g, pixelColor.b, pixelValue)); } } for (int i = 0; i < (int)cubemapSize; i++) { for (int j = 0; j < (int)cubemapSize; j++) { var pixelColor = cubemap.GetPixel(CubemapFace.NegativeY, i, (int)cubemapSize - j); var pixelValue = 1.0f; if (cubemapType == CubemapType.CloudsCubemap) { pixelValue = pixelColor.r + pixelColor.g + pixelColor.b; } img.SetPixel(i + (int)cubemapSize * 3, j, new Color(pixelColor.r, pixelColor.g, pixelColor.b, pixelValue)); } } for (int i = 0; i < (int)cubemapSize; i++) { for (int j = 0; j < (int)cubemapSize; j++) { var pixelColor = cubemap.GetPixel(CubemapFace.PositiveZ, i, (int)cubemapSize - j); var pixelValue = 1.0f; if (cubemapType == CubemapType.CloudsCubemap) { pixelValue = pixelColor.r + pixelColor.g + pixelColor.b; } img.SetPixel(i + (int)cubemapSize * 4, j, new Color(pixelColor.r, pixelColor.g, pixelColor.b, pixelValue)); } } for (int i = 0; i < (int)cubemapSize; i++) { for (int j = 0; j < (int)cubemapSize; j++) { var pixelColor = cubemap.GetPixel(CubemapFace.NegativeZ, i, (int)cubemapSize - j); var pixelValue = 1.0f; if (cubemapType == CubemapType.CloudsCubemap) { pixelValue = pixelColor.r + pixelColor.g + pixelColor.b; } img.SetPixel(i + (int)cubemapSize * 5, j, new Color(pixelColor.r, pixelColor.g, pixelColor.b, pixelValue)); } } img.Apply(); byte[] imgBytes = img.EncodeToPNG(); File.WriteAllBytes(path, imgBytes); AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); TextureImporter texImporter = AssetImporter.GetAtPath(path) as TextureImporter; texImporter.textureShape = TextureImporterShape.TextureCube; texImporter.textureCompression = TextureImporterCompression.CompressedHQ; texImporter.mipmapEnabled = false; texImporter.sRGBTexture = false; texImporter.SaveAndReimport(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); if (cubemapType == CubemapType.CloudsCubemap) { RenderSettings.skybox.SetTexture("_CloudsCubemap", AssetDatabase.LoadAssetAtPath <Cubemap>(path)); } Debug.Log("[Polyverse Skies] The Generated Cubemap is saved to the Assets folder!"); generateCubemap = false; } }
// This function computes a diffuse environment map in // "filteredCubemap" of the same dimensions as "originalCubemap" // by integrating -- for each texel of "filteredCubemap" -- // the diffuse illumination from all texels of "originalCubemap" // for the surface normal vector corresponding to the direction // of each texel of "filteredCubemap". private Cubemap computeFilteredCubeMap() { Cubemap filteredCubeMap = new Cubemap(originalCubeMap.width, originalCubeMap.format, true); int filteredSize = filteredCubeMap.width; int originalSize = originalCubeMap.width; // Compute all texels of the diffuse environment cube map // by itterating over all of them for (int filteredFace = 0; filteredFace < 6; filteredFace++) // the six sides of the cube { for (int filteredI = 0; filteredI < filteredSize; filteredI++) { for (int filteredJ = 0; filteredJ < filteredSize; filteredJ++) { Vector3 filteredDirection = getDirection(filteredFace, filteredI, filteredJ, filteredSize).normalized; float totalWeight = 0.0f; Vector3 originalDirection; Vector3 originalFaceDirection; float weight; Color filteredColor = new Color(0.0f, 0.0f, 0.0f); // sum (i.e. integrate) the diffuse illumination // by all texels in the original environment map for (int originalFace = 0; originalFace < 6; originalFace++) { originalFaceDirection = getDirection( originalFace, 1, 1, 3).normalized; //the normal vector of the face for (int originalI = 0; originalI < originalSize; originalI++) { for (int originalJ = 0; originalJ < originalSize; originalJ++) { originalDirection = getDirection( originalFace, originalI, originalJ, originalSize); // direction to the texel // (i.e. light source) weight = 1.0f / originalDirection.sqrMagnitude; // take smaller size of more // distant texels into account originalDirection = originalDirection.normalized; weight = weight * Vector3.Dot( originalFaceDirection, originalDirection); // take tilt of texel compared // to face into account weight = weight * Mathf.Max(0.0f, Vector3.Dot(filteredDirection, originalDirection)); // directional filter // for diffuse illumination totalWeight = totalWeight + weight; // instead of analytically // normalization, we just normalize // to the potential max illumination filteredColor = filteredColor + weight * originalCubeMap.GetPixel( (CubemapFace)originalFace, originalI, originalJ); // add the // illumination by this texel } } } filteredCubeMap.SetPixel( (CubemapFace)filteredFace, filteredI, filteredJ, filteredColor / totalWeight); // store the diffuse illumination of this texel } } } // Avoid seams between cube faces: average edge texels // to the same color on each side of the seam int maxI = filteredCubeMap.width - 1; for (int i = 0; i < maxI; i++) { setFaceAverage(ref filteredCubeMap, 0, i, 0, 2, maxI, maxI - i); setFaceAverage(ref filteredCubeMap, 0, 0, i, 4, maxI, i); setFaceAverage(ref filteredCubeMap, 0, i, maxI, 3, maxI, i); setFaceAverage(ref filteredCubeMap, 0, maxI, i, 5, 0, i); setFaceAverage(ref filteredCubeMap, 1, i, 0, 2, 0, i); setFaceAverage(ref filteredCubeMap, 1, 0, i, 5, maxI, i); setFaceAverage(ref filteredCubeMap, 1, i, maxI, 3, 0, maxI - i); setFaceAverage(ref filteredCubeMap, 1, maxI, i, 4, 0, i); setFaceAverage(ref filteredCubeMap, 2, i, 0, 5, maxI - i, 0); setFaceAverage(ref filteredCubeMap, 2, i, maxI, 4, i, 0); setFaceAverage(ref filteredCubeMap, 3, i, 0, 4, i, maxI); setFaceAverage(ref filteredCubeMap, 3, i, maxI, 5, maxI - i, maxI); } // Avoid seams between cube faces: // average corner texels to the same color // on all three faces meeting in one corner setCornerAverage(ref filteredCubeMap, 0, 0, 0, 2, maxI, maxI, 4, maxI, 0); setCornerAverage(ref filteredCubeMap, 0, maxI, 0, 2, maxI, 0, 5, 0, 0); setCornerAverage(ref filteredCubeMap, 0, 0, maxI, 3, maxI, 0, 4, maxI, maxI); setCornerAverage(ref filteredCubeMap, 0, maxI, maxI, 3, maxI, maxI, 5, 0, maxI); setCornerAverage(ref filteredCubeMap, 1, 0, 0, 2, 0, 0, 5, maxI, 0); setCornerAverage(ref filteredCubeMap, 1, maxI, 0, 2, 0, maxI, 4, 0, 0); setCornerAverage(ref filteredCubeMap, 1, 0, maxI, 3, 0, maxI, 5, maxI, maxI); setCornerAverage(ref filteredCubeMap, 1, maxI, maxI, 3, 0, 0, 4, 0, maxI); filteredCubeMap.Apply(); //apply all SetPixel(..) commands return(filteredCubeMap); }
public static Color GetColorInDirection(this Cubemap cubemap, Vector3 dir) { // this could be faster, save some of the calculations to be reused float x = 0; float y = 0; Ray ray = new Ray(Vector3.zero, dir); float d; Plane p; Vector3 pos; CubemapFace face = CubemapUtils.GetFace(dir); switch (face) { case CubemapFace.PositiveX: p = new Plane(-Vector3.right, 1); p.Raycast(ray, out d); pos = ray.GetPoint(d); x = -0.5f * pos.z + 0.5f; y = -0.5f * pos.y + 0.5f; break; case CubemapFace.NegativeX: p = new Plane(Vector3.right, 1); p.Raycast(ray, out d); pos = ray.GetPoint(d); x = 0.5f * pos.z + 0.5f; y = -0.5f * pos.y + 0.5f; break; case CubemapFace.PositiveY: p = new Plane(-Vector3.up, 1); p.Raycast(ray, out d); pos = ray.GetPoint(d); x = 0.5f * pos.x + 0.5f; y = 0.5f * pos.z + 0.5f; break; case CubemapFace.NegativeY: p = new Plane(Vector3.up, 1); p.Raycast(ray, out d); pos = ray.GetPoint(d); x = 0.5f * pos.x + 0.5f; y = -0.5f * pos.z + 0.5f; break; case CubemapFace.PositiveZ: p = new Plane(-Vector3.forward, 1); p.Raycast(ray, out d); pos = ray.GetPoint(d); x = 0.5f * pos.x + 0.5f; y = -0.5f * pos.y + 0.5f; break; case CubemapFace.NegativeZ: p = new Plane(Vector3.forward, 1); p.Raycast(ray, out d); pos = ray.GetPoint(d); x = -0.5f * pos.x + 0.5f; y = -0.5f * pos.y + 0.5f; break; } return(cubemap.GetPixel(face, (int)(x * cubemap.width), (int)(y * cubemap.height))); }