/// <summary> /// Creates a 3D texture. /// </summary> public static Texture3D CreateTexture3DFromResources(string texturePathFromResources, int slices) { Texture3D texture3D = null; Texture2D texture2D = Resources.Load<Texture2D>(texturePathFromResources); if (texture2D != null) { int height = texture2D.height; int width = texture2D.width / slices; Color[] pixels2D = texture2D.GetPixels(); Color[] pixels3D = new Color[pixels2D.Length]; for (int z = 0; z < slices; ++z) for (int y = 0; y < height; ++y) for (int x = 0; x < width; ++x) pixels3D[x + (y * width) + (z * (width * height))] = pixels2D[x + (z * width) + (((width - y) - 1) * width * height)]; texture3D = new Texture3D(width, height, slices, TextureFormat.ARGB32, false); texture3D.SetPixels(pixels3D); texture3D.Apply(); texture3D.filterMode = FilterMode.Trilinear; texture3D.wrapMode = TextureWrapMode.Clamp; texture3D.anisoLevel = 1; } else Debug.LogWarning(string.Format("Texture '{0}' not found in 'Resources/Textures' folder.", texturePathFromResources)); return texture3D; }
/*****/ private void CreateDistanceField() { var size = 128; var pdbName = "MA_matrix_G1"; string path = "Assets/Resources/3D Textures/" + pdbName + ".asset"; Texture3D tmp = (Texture3D)AssetDatabase.LoadAssetAtPath(path, typeof(Texture3D)); if (tmp) { _volumeTexture = tmp; } else { RenderTexture _distanceFieldRT; _distanceFieldRT = new RenderTexture(size, size, 0, RenderTextureFormat.R8); _distanceFieldRT.volumeDepth = size; _distanceFieldRT.isVolume = true; _distanceFieldRT.isPowerOfTwo = true; _distanceFieldRT.enableRandomWrite = true; _distanceFieldRT.filterMode = FilterMode.Trilinear; _distanceFieldRT.name = pdbName; _distanceFieldRT.hideFlags = HideFlags.HideAndDontSave; _distanceFieldRT.generateMips = true; _distanceFieldRT.useMipMap = true; _distanceFieldRT.Create(); var atomSpheres = PdbLoader.LoadAtomSpheres(pdbName); var atomSphereGPUBuffer = new ComputeBuffer(atomSpheres.Count, sizeof(float) * 4, ComputeBufferType.Default); atomSphereGPUBuffer.SetData(atomSpheres.ToArray()); Graphics.SetRenderTarget(_distanceFieldRT); GL.Clear(true, true, new Color(0, 0, 0)); var createDistanceFieldCS = Resources.Load("Compute Shaders/CreateDistanceField") as ComputeShader; createDistanceFieldCS.SetInt("_GridSize", size); createDistanceFieldCS.SetInt("_NumAtoms", atomSpheres.Count); createDistanceFieldCS.SetBuffer(0, "_SpherePositions", atomSphereGPUBuffer); createDistanceFieldCS.SetTexture(0, "_VolumeTexture", _distanceFieldRT); createDistanceFieldCS.Dispatch(0, Mathf.CeilToInt(size / 10.0f), Mathf.CeilToInt(size / 10.0f), Mathf.CeilToInt(size / 10.0f)); atomSphereGPUBuffer.Release(); //**** var flatSize = size * size * size; var voxelGPUBuffer = new ComputeBuffer(flatSize, sizeof(float)); var readVoxelsCS = Resources.Load("Compute Shaders/ReadVoxels") as ComputeShader; readVoxelsCS.SetInt("_VolumeSize", size); readVoxelsCS.SetBuffer(0, "_VoxelBuffer", voxelGPUBuffer); readVoxelsCS.SetTexture(0, "_VolumeTexture", _distanceFieldRT); readVoxelsCS.Dispatch(0, size, size, size); var voxelCPUBuffer = new float[flatSize]; voxelGPUBuffer.GetData(voxelCPUBuffer); var volumeColors = new Color[flatSize]; for (int i = 0; i < flatSize; i++) { volumeColors[i] = new Color(0, 0, 0, voxelCPUBuffer[i]); } var texture3D = new Texture3D(size, size, size, TextureFormat.Alpha8, true); texture3D.SetPixels(volumeColors); texture3D.wrapMode = TextureWrapMode.Clamp; texture3D.anisoLevel = 0; texture3D.Apply(); AssetDatabase.CreateAsset(texture3D, path); AssetDatabase.SaveAssets(); // Print the path of the created asset Debug.Log(AssetDatabase.GetAssetPath(texture3D)); voxelGPUBuffer.Release(); _distanceFieldRT.Release(); DestroyImmediate(_distanceFieldRT); _volumeTexture = texture3D; } }
protected void SetIdentityLut() { int dim = 16; Color[] newC = new Color[dim * dim * dim]; float oneOverDim = 1.0f / (1.0f * dim - 1.0f); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { for (int k = 0; k < dim; k++) { newC[i + (j * dim) + (k * dim * dim)] = new Color((i * 1.0f) * oneOverDim, (j * 1.0f) * oneOverDim, (k * 1.0f) * oneOverDim, 1.0f); } } } if (m_Lut3D) DestroyImmediate(m_Lut3D); m_Lut3D = new Texture3D(dim, dim, dim, TextureFormat.ARGB32, false); m_Lut3D.hideFlags = HideFlags.HideAndDontSave; m_Lut3D.SetPixels(newC); m_Lut3D.Apply(); m_BaseTextureName = ""; }
public void Generate() { tex = new Texture3D(size, size, size, TextureFormat.RGB24, true); var cols = new Color[size * size * size]; // float mul = 1.0f / (size-1); int idx = 0; Color c = Color.black; for (int z = 0; z < size; ++z) { for (int y = 0; y < size; ++y) { for (int x = 0; x < size; ++x, ++idx) { c.r = fbm(x, y, z); c.g = c.r; c.b = c.r; cols[idx] = c; } } } tex.SetPixels(cols); tex.Apply(); Shader.SetGlobalTexture("_3DTex", tex); }
static public int SetPixels(IntPtr l) { try { int argc = LuaDLL.lua_gettop(l); if (argc == 2) { UnityEngine.Texture3D self = (UnityEngine.Texture3D)checkSelf(l); UnityEngine.Color[] a1; checkArray(l, 2, out a1); self.SetPixels(a1); pushValue(l, true); return(1); } else if (argc == 3) { UnityEngine.Texture3D self = (UnityEngine.Texture3D)checkSelf(l); UnityEngine.Color[] a1; checkArray(l, 2, out a1); System.Int32 a2; checkType(l, 3, out a2); self.SetPixels(a1, a2); pushValue(l, true); return(1); } pushValue(l, false); LuaDLL.lua_pushstring(l, "No matched override function to call"); return(2); } catch (Exception e) { return(error(l, e)); } }
void Create3DTexture() { int iTexSizeX = m_pClouds2DTex.width; int iTexSizeY = m_pClouds2DTex.height; int iTextureDepth = iTexSizeX / m_iLayersSquaredSize; int iLayerSize = m_iLayersSquaredSize * m_iLayersSquaredSize; m_pClouds3D = new Texture3D(m_iLayersSquaredSize, m_iLayersSquaredSize, iTextureDepth, TextureFormat.ARGB32, true); Color[] pTexColor = new Color[iTexSizeX * iTexSizeY]; for (int x = 0; x < iTexSizeX; x++) { for (int y = 0; y < iTexSizeY; y++) { int iLayer = x / m_iLayersSquaredSize; int iLayerIndex = (y * m_iLayersSquaredSize) + (x % m_iLayersSquaredSize); int iIndex = (iLayer * iLayerSize) + iLayerIndex; Color tColor = m_pClouds2DTex.GetPixel(x, y); pTexColor[iIndex] = tColor; } } m_pClouds3D.SetPixels(pTexColor); m_pClouds3D.Apply(true); Shader.SetGlobalTexture("_CloudTex", m_pClouds3D); UpdateProperties(); }
public static Texture3D LoadVolumeFromFile(string fileName, TextureFormat format, int elementSize ,int width, int height, int depth) { BinaryReader br = new BinaryReader(File.Open(fileName, FileMode.Open, FileAccess.Read)); Texture3D noiseTex = new Texture3D(width, height, depth, TextureFormat.RGBA32, false); noiseTex.filterMode = FilterMode.Bilinear; noiseTex.wrapMode = TextureWrapMode.Repeat; int numElements = width * height * depth; List<Color> colors = new List<Color>(numElements); // Get pixels from 2d texture for each slize in z direction for (int z = 0; z < depth; z++) { Texture2D tex2d = LoadTexture2DRaw(br, width, height, format, elementSize); colors.AddRange(tex2d.GetPixels()); } //colors should now be filled with all pixels noiseTex.SetPixels(colors.ToArray()); noiseTex.Apply(false); br.Close(); return noiseTex; }
static public int SetPixels(IntPtr l) { try{ if (matchType(l, 2, typeof(UnityEngine.Color), typeof(System.Int32))) { UnityEngine.Texture3D self = (UnityEngine.Texture3D)checkSelf(l); UnityEngine.Color[] a1; checkType(l, 2, out a1); System.Int32 a2; checkType(l, 3, out a2); self.SetPixels(a1, a2); return(0); } else if (matchType(l, 2, typeof(UnityEngine.Color))) { UnityEngine.Texture3D self = (UnityEngine.Texture3D)checkSelf(l); UnityEngine.Color[] a1; checkType(l, 2, out a1); self.SetPixels(a1); return(0); } LuaDLL.luaL_error(l, "No matched override function to call"); return(0); } catch (Exception e) { LuaDLL.luaL_error(l, e.ToString()); return(0); } }
public void SetIdentityLut() { int dim = 16; Color[] newC = new Color[dim*dim*dim]; float oneOverDim = 1.0f/(1.0f*dim - 1.0f); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { for (int k = 0; k < dim; k++) { newC[i + (j*dim) + (k*dim*dim)] = new Color((i*1.0f)*oneOverDim, (j*1.0f)*oneOverDim, (k*1.0f)*oneOverDim, 1.0f); } } } if (converted3DLut) DestroyImmediate(converted3DLut); converted3DLut = new Texture3D(dim, dim, dim, TextureFormat.ARGB32, false); converted3DLut.SetPixels(newC); converted3DLut.Apply(); basedOnTempTex = ""; }
static public int SetPixels(IntPtr l) { try { #if DEBUG var method = System.Reflection.MethodBase.GetCurrentMethod(); string methodName = GetMethodName(method); #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.BeginSample(methodName); #else Profiler.BeginSample(methodName); #endif #endif int argc = LuaDLL.lua_gettop(l); if (argc == 2) { UnityEngine.Texture3D self = (UnityEngine.Texture3D)checkSelf(l); UnityEngine.Color[] a1; checkArray(l, 2, out a1); self.SetPixels(a1); pushValue(l, true); return(1); } else if (argc == 3) { UnityEngine.Texture3D self = (UnityEngine.Texture3D)checkSelf(l); UnityEngine.Color[] a1; checkArray(l, 2, out a1); System.Int32 a2; checkType(l, 3, out a2); self.SetPixels(a1, a2); pushValue(l, true); return(1); } pushValue(l, false); LuaDLL.lua_pushstring(l, "No matched override function SetPixels to call"); return(2); } catch (Exception e) { return(error(l, e)); } #if DEBUG finally { #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.EndSample(); #else Profiler.EndSample(); #endif } #endif }
static public int SetPixels__A_Color(IntPtr l) { try { UnityEngine.Texture3D self = (UnityEngine.Texture3D)checkSelf(l); UnityEngine.Color[] a1; checkArray(l, 2, out a1); self.SetPixels(a1); pushValue(l, true); return(1); } catch (Exception e) { return(error(l, e)); } }
public Texture3D Generate3DTexture() { float r = 0.3f; Texture3D texture3D = new Texture3D(n, n, n, TextureFormat.ARGB32, true); int size = n * n * n; Color[] cols = new Color[size]; int idx = 0; Color c = Color.white; float frequency = 0.01f / n; float center = n / 2.0f + 0.5f; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < n; k++, ++idx) { float dx = center - i; float dy = center - j; float dz = center - k; float off = Mathf.Abs(Perlin.Turbulence(i * frequency, j * frequency, k * frequency, 6)); float d = Mathf.Sqrt(dx * dx + dy * dy + dz * dz) / (n); //c.r = c.g = c.b = c.a = ((d-off) < r)?1.0f:0.0f; float p = d - off; c.r = c.g = c.b = c.a = Mathf.Clamp01(r - p); cols[idx] = c; } } } //for(int i = 0; i < size; i++) // Debug.Log (newC[i]); texture3D.SetPixels(cols); texture3D.Apply(); renderer.material.SetTexture("g_densityTex", texture3D); texture3D.filterMode = FilterMode.Trilinear; texture3D.wrapMode = TextureWrapMode.Clamp; texture3D.anisoLevel = 1; //Color[] cs = texture3D.GetPixels(); //for(int i = 0; i < 10; i++) // Debug.Log (cs[i]); return texture3D; }
public void Convert(Texture2D temp2DTex, string path) { // conversion fun: the given 2D texture needs to be of the format // w * h, wheras h is the 'depth' (or 3d dimension 'dim') and w = dim * dim if (temp2DTex) { int dim = temp2DTex.width * temp2DTex.height; dim = temp2DTex.height; if (!ValidDimensions(temp2DTex)) { Debug.LogWarning("The given 2D texture " + temp2DTex.name + " cannot be used as a 3D LUT."); basedOnTempTex = ""; return; } Color[] c = temp2DTex.GetPixels(); Color[] newC = new Color[c.Length]; for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { for (int k = 0; k < dim; k++) { int j_ = dim - j - 1; newC[i + (j * dim) + (k * dim * dim)] = c[k * dim + i + j_ * dim * dim]; } } } if (converted3DLut) DestroyImmediate(converted3DLut); converted3DLut = new Texture3D(dim, dim, dim, TextureFormat.ARGB32, false); converted3DLut.SetPixels(newC); converted3DLut.Apply(); basedOnTempTex = path; } else { // error, something went terribly wrong Debug.LogError("Couldn't color correct with 3D LUT texture. Image Effect will be disabled."); } }
public static void Generate3DTexture(ref Texture3D texture3D, int n) { float r = 0.3f; int size = n * n * n; Color[] cols = new Color[size]; int idx = 0; Color c = Color.white; float frequency = 0.01f / n; float center = n / 2.0f + 0.5f; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < n; k++, ++idx) { float dx = center - i; float dy = center - j; float dz = center - k; float off = Mathf.Abs(Perlin.Turbulence(i * frequency, j * frequency, k * frequency, 6)); float d = Mathf.Sqrt(dx * dx + dy * dy + dz * dz) / (n); //c.r = c.g = c.b = c.a = ((d-off) < r)?1.0f:0.0f; float p = d - off; c.r = c.g = c.b = c.a = Mathf.Clamp01(r - p); cols[idx] = c; } } } //for(int i = 0; i < size; i++) // Debug.Log (newC[i]); texture3D.SetPixels(cols); texture3D.Apply(); texture3D.filterMode = FilterMode.Trilinear; texture3D.wrapMode = TextureWrapMode.Clamp; texture3D.anisoLevel = 1; }
void Start() { tex = new Texture3D (size, size, size, TextureFormat.ARGB32, true); var cols = new Color[size * size * size]; float mul = 1.0f / (size - 1); int idx = 0; Color c = Color.white; for (int z = 0; z < size; ++z) { for (int y = 0; y < size; ++y) { for (int x = 0; x < size; ++x, ++idx) { c.r = 1f - (Mathf.Abs(x-size * .5f) * 2f * mul); c.g = 1f - (Mathf.Abs(y-size * .5f) * 2f * mul); c.b = 1f - (Mathf.Abs(z-size * .5f) * 2f * mul); cols [idx] = c; } } } tex.SetPixels (cols); tex.Apply (); renderer.material.SetTexture ("_Volume", tex); }
public static Texture3D LoadVolumeFromFile(string fileName) { int x, y, z; x = y = z = 16; // int numElementsTotal = 16*16*16 + 8*8*8 + 4*4*4 + 2*2*2 + 1; // all mip levels BinaryReader br = new BinaryReader(File.Open(fileName, FileMode.Open, FileAccess.Read)); int headerSize = 5 * sizeof(int); br.ReadBytes(headerSize); // skip header info Texture3D noiseTex = new Texture3D(x, y, z, TextureFormat.RGBA32, true); noiseTex.filterMode = FilterMode.Bilinear; noiseTex.wrapMode = TextureWrapMode.Repeat; int maxMipLevel = 16; for (int mipLevel = 0; mipLevel < 5; mipLevel++) { ////int dimMipLevel = Mathf.Pow(2,(float)(4-mipLevel)); // dimension of miplevel 16, 8, 4, 2, 1 int dimMipLevel = maxMipLevel >> mipLevel; int numElMip = dimMipLevel * dimMipLevel * dimMipLevel; //Color[] colors = new Color[numElMip]; List<Color> colors = new List<Color>(numElMip); // Get pixels from 2d texture for each slize in z direction for (z = 0; z < dimMipLevel; z++) { Texture2D tex2d = LoadTexture2DRaw(br, dimMipLevel, dimMipLevel); colors.AddRange(tex2d.GetPixels()); } //colors should now be filled with all pixels noiseTex.SetPixels(colors.ToArray(), mipLevel); noiseTex.Apply(false); } br.Close(); return noiseTex; }
internal bool Convert(Texture2D lookupTexture) { if (!SystemInfo.supports3DTextures) { Debug.LogError("System does not support 3D textures"); return false; } else if (lookupTexture == null) { SetIdentityLut(); } else { if (converted3DLut != null) { DestroyImmediate(converted3DLut); } if (lookupTexture.mipmapCount > 1) { Debug.LogError("Lookup texture must not have mipmaps"); return false; } try { int dim = lookupTexture.width * lookupTexture.height; dim = lookupTexture.height; if (!ValidDimensions(lookupTexture)) { Debug.LogError("Lookup texture dimensions must be a power of two. The height must equal the square root of the width."); return false; } var c = lookupTexture.GetPixels(); var newC = new Color[c.Length]; for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { for (int k = 0; k < dim; k++) { int j_ = dim - j - 1; newC[i + (j * dim) + (k * dim * dim)] = c[k * dim + i + j_ * dim * dim]; } } } converted3DLut = new Texture3D(dim, dim, dim, TextureFormat.ARGB32, false); converted3DLut.SetPixels(newC); converted3DLut.Apply(); lutSize = converted3DLut.width; converted3DLut.wrapMode = TextureWrapMode.Clamp; } catch (Exception ex) { Debug.LogError("Unable to convert texture to LUT texture, make sure it is read/write. Error: " + ex); } } return true; }
public void SetIdentityLut() { if (!SystemInfo.supports3DTextures) { return; } else if (converted3DLut != null) { DestroyImmediate(converted3DLut); } int dim = 16; var newC = new Color[dim * dim * dim]; float oneOverDim = 1.0f / (1.0f * dim - 1.0f); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { for (int k = 0; k < dim; k++) { newC[i + (j * dim) + (k * dim * dim)] = new Color((i * 1.0f) * oneOverDim, (j * 1.0f) * oneOverDim, (k * 1.0f) * oneOverDim, 1.0f); } } } converted3DLut = new Texture3D(dim, dim, dim, TextureFormat.ARGB32, false); converted3DLut.SetPixels(newC); converted3DLut.Apply(); lutSize = converted3DLut.width; converted3DLut.wrapMode = TextureWrapMode.Clamp; }
public Texture3D Create3DTexture(int width, int height, int depth, int frame) { MegaFlowFrame f = frames[frame]; if ( width == 0 || height == 0 || depth == 0 ) return null; width = Mathf.ClosestPowerOfTwo(width); height = Mathf.ClosestPowerOfTwo(height); depth = Mathf.ClosestPowerOfTwo(depth); Texture3D tex = new Texture3D(width, height, depth, TextureFormat.RGB24, false); tex.wrapMode = TextureWrapMode.Repeat; tex.anisoLevel = 0; Color[] cols = new Color[width * height * depth]; float max = 0.0f; for ( int i = 0; i < f.vel.Count; i++ ) { float m = f.vel[i].sqrMagnitude; if ( m > max ) max = m; } float len = Mathf.Sqrt(max); Vector3 p; Color c = Color.white; bool inbounds = false; #if false for ( int x = 0; x < width; x++ ) { p.x = ((float)x / (float)width) * f.size.x; for ( int y = 0; y < height; y++ ) { p.y = ((float)y / (float)height) * f.size.y; for ( int z = 0; z < depth; z++ ) { p.z = ((float)z / (float)depth) * f.size.z; Vector3 vel = f.GetGridVel(p, ref inbounds); vel /= len; c.r = (vel.x * 0.5f) + 0.5f; c.g = (vel.y * 0.5f) + 0.5f; c.b = (vel.z * 0.5f) + 0.5f; cols[(x * depth * height) + (z * height) + y] = c; } } } #endif int ix = 0; for ( int z = 0; z < depth; z++ ) { p.z = ((float)z / (float)depth) * f.size.z; for ( int y = 0; y < height; y++ ) { p.y = ((float)y / (float)height) * f.size.y; for ( int x = 0; x < width; x++ ) { p.x = ((float)x / (float)width) * f.size.x; Vector3 vel = f.GetGridVel(p, ref inbounds); vel /= len; c.r = (vel.x * 0.5f) + 0.5f; c.g = (vel.y * 0.5f) + 0.5f; c.b = (vel.z * 0.5f) + 0.5f; cols[ix++] = c; } } } tex.SetPixels(cols); tex.Apply(); return tex; }
/** * Return a volume texture containing a representation of this distance field. */ public Texture3D GetVolumeTexture(int size) { if (Root == null) return null; // upper bound of the distance from any point inside the bounds to the surface. float maxDist = Mathf.Max(Root.bounds.size.x,Root.bounds.size.y,Root.bounds.size.z); float spacingX = Root.bounds.size.x / (float)size; float spacingY = Root.bounds.size.y / (float)size; float spacingZ = Root.bounds.size.z / (float)size; Texture3D tex = new Texture3D (size, size, size, TextureFormat.ARGB32, false); var cols = new Color[size*size*size]; int idx = 0; Color c = Color.black; Vector3 gradient; for (int z = 0; z < size; ++z) { for (int y = 0; y < size; ++y) { for (int x = 0; x < size; ++x, ++idx) { Vector3 samplePoint = Root.bounds.min + new Vector3(spacingX * x + spacingX*0.5f, spacingY * y + spacingY*0.5f, spacingZ * z + spacingZ*0.5f); float distance = DistanceAndGradientAt(samplePoint,out gradient); if (distance >= 0) c.r = distance.Remap(0,maxDist*0.1f,0.5f,1); else c.r = distance.Remap(-maxDist*0.1f,0,0,0.5f); cols[idx] = c; } } } tex.SetPixels (cols); tex.Apply (); return tex; }
void UpdateLut() { UpdateUserLut(); UpdateCurve(); float lutA = GetLutA(); SimplePolyFunc polyToe; SimplePolyFunc polyLinear; SimplePolyFunc polyShoulder; float gammaSpace = 2.2f; float x0 = Mathf.Pow(1.0f/3.0f, gammaSpace); float shoulderBase = .7f; float x1 = Mathf.Pow(shoulderBase, gammaSpace); float gammaHighY = Mathf.Pow(shoulderBase, 1.0f + (lutShoulder) * 1.0f); float y1 = Mathf.Pow(gammaHighY, gammaSpace); float y0 = 0.0f; { float t = x0 / x1; float lin = t * y1; float low = lin * (1.0f-lutToe*.5f); y0 = low; } float dx = x1 - x0; float dy = y1 - y0; float m = 0.0f; if (dx > 0 && dy > 0) m = dy / dx; // linear section, power is 1, slope is m polyLinear.x0 = x0; polyLinear.y0 = y0; polyLinear.A = m; polyLinear.B = 1.0f; polyLinear.signX = 1.0f; polyLinear.signY = 1.0f; polyLinear.logA = Mathf.Log(m); // toe polyToe = polyLinear; polyToe.Initialize(x0, y0, m); float linearW = GetWhitePoint(); { // shoulder, first think about it "backwards" float offsetX = linearW - x1; float offsetY = 1.0f - y1; polyShoulder = polyLinear; polyShoulder.Initialize(offsetX, offsetY, m); // flip horizontal polyShoulder.signX = -1.0f; polyShoulder.x0 = -linearW; // flip vertical polyShoulder.signY = -1.0f; polyShoulder.y0 = 1.0f; } int dim = 32; Color[] newC = new Color[dim * dim * dim]; float oneOverDim = 1.0f / (1.0f * dim - 1.0f); Color normS = NormalizeColor(lutShadows); Color normM = NormalizeColor(lutMidtones); Color normH = NormalizeColor(lutHighlights); float avgS = (normS.r + normS.g + normS.b) / 3.0f; float avgM = (normM.r + normM.g + normM.b) / 3.0f; float avgH = (normH.r + normH.g + normH.b) / 3.0f; // these are magic numbers float liftScale = .1f; float gammaScale = .5f; float gainScale = .5f; float liftR = (normS.r - avgS) * liftScale; float liftG = (normS.g - avgS) * liftScale; float liftB = (normS.b - avgS) * liftScale; float gammaR = Mathf.Pow(2.0f, (normM.r - avgM) * gammaScale); float gammaG = Mathf.Pow(2.0f, (normM.g - avgM) * gammaScale); float gammaB = Mathf.Pow(2.0f, (normM.b - avgM) * gammaScale); float gainR = Mathf.Pow(2.0f, (normH.r - avgH) * gainScale); float gainG = Mathf.Pow(2.0f, (normH.g - avgH) * gainScale); float gainB = Mathf.Pow(2.0f, (normH.b - avgH) * gainScale); float minGamma = .01f; float invGammaR = 1.0f / Mathf.Max(minGamma, gammaR); float invGammaG = 1.0f / Mathf.Max(minGamma, gammaG); float invGammaB = 1.0f / Mathf.Max(minGamma, gammaB); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { for (int k = 0; k < dim; k++) { float srcR = (i * 1.0f) * oneOverDim; float srcG = (j * 1.0f) * oneOverDim; float srcB = (k * 1.0f) * oneOverDim; float dstR = EvalFilmicHelper(srcR, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); float dstG = EvalFilmicHelper(srcG, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); float dstB = EvalFilmicHelper(srcB, lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW); // enable lut if (enableUserLut) { Color c = SampleLutLinear(dstR, dstG, dstB); dstR = c.r; dstG = c.g; dstB = c.b; } dstR = EvalCurveGradingHelper(dstR, liftR, invGammaR, gainR); dstG = EvalCurveGradingHelper(dstG, liftG, invGammaG, gainG); dstB = EvalCurveGradingHelper(dstB, liftB, invGammaB, gainB); if (enableColorGrading) { // saturation float midVal = (dstR + dstG + dstB) / 3.0f; dstR = midVal + (dstR - midVal) * lutSaturation; dstG = midVal + (dstG - midVal) * lutSaturation; dstB = midVal + (dstB - midVal) * lutSaturation; } newC[i + (j * dim) + (k * dim * dim)] = new Color(dstR, dstG, dstB, 1.0f); } } } if (lutTex) DestroyImmediate(lutTex); lutTex = new Texture3D(dim, dim, dim, TextureFormat.ARGB32, false); lutTex.filterMode = FilterMode.Bilinear; lutTex.wrapMode = TextureWrapMode.Clamp; lutTex.hideFlags = HideFlags.DontSave; lutTex.SetPixels(newC); lutTex.Apply(); #if false if (false) { // Instad of doing a single 3D lut, I tried doing this as 3x 1D luts. Or rather, // a single lut with separate curves baked into RGB channels. It wasn't actually faster // do it's disabled. But there are two reasons why in the future it might be useful: // 1. If it turns out that 3x 1D luts are faster on some hardware, it might be worth it. // 2. Updating the 3D LUT is quite slow so you can't change it every frame. If the // parameters need to lerp than the 1D version might be worthwhile. CreateFilmicCurveHelper(lutA, polyToe, polyLinear, polyShoulder, x0, x1, linearW, liftR, invGammaR, gainR, liftG, invGammaG, gainG, liftB, invGammaB, gainB); } #endif }
private static void DecodeFloat3D(int w, int h, int d, int c, float min, float max, RenderTexture tex, Color[] map, ComputeShader shader) { Color[] array = new Color[w * h * d]; Color[] array2 = new Color[w * h * d]; Color[] array3 = new Color[w * h * d]; Color[] array4 = new Color[w * h * d]; for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { for (int k = 0; k < d; k++) { array[i + j * w + k * w * h] = new Color(0f, 0f, 0f, 0f); array2[i + j * w + k * w * h] = new Color(0f, 0f, 0f, 0f); array3[i + j * w + k * w * h] = new Color(0f, 0f, 0f, 0f); array4[i + j * w + k * w * h] = new Color(0f, 0f, 0f, 0f); if (c > 0) { array[i + j * w + k * w * h] = map[(i + j * w + k * w * h) * c]; } if (c > 1) { array2[i + j * w + k * w * h] = map[(i + j * w + k * w * h) * c + 1]; } if (c > 2) { array3[i + j * w + k * w * h] = map[(i + j * w + k * w * h) * c + 2]; } if (c > 3) { array4[i + j * w + k * w * h] = map[(i + j * w + k * w * h) * c + 3]; } } } } Texture3D texture3D = new Texture3D(w, h, d, TextureFormat.ARGB32, false); texture3D.hideFlags = HideFlags.HideAndDontSave; texture3D.filterMode = FilterMode.Point; texture3D.wrapMode = TextureWrapMode.Clamp; texture3D.SetPixels(array); texture3D.Apply(); Texture3D texture3D2 = new Texture3D(w, h, d, TextureFormat.ARGB32, false); texture3D2.hideFlags = HideFlags.HideAndDontSave; texture3D2.filterMode = FilterMode.Point; texture3D2.wrapMode = TextureWrapMode.Clamp; texture3D2.SetPixels(array2); texture3D2.Apply(); Texture3D texture3D3 = new Texture3D(w, h, d, TextureFormat.ARGB32, false); texture3D3.hideFlags = HideFlags.HideAndDontSave; texture3D3.filterMode = FilterMode.Point; texture3D3.wrapMode = TextureWrapMode.Clamp; texture3D3.SetPixels(array3); texture3D3.Apply(); Texture3D texture3D4 = new Texture3D(w, h, d, TextureFormat.ARGB32, false); texture3D4.hideFlags = HideFlags.HideAndDontSave; texture3D4.filterMode = FilterMode.Point; texture3D4.wrapMode = TextureWrapMode.Clamp; texture3D4.SetPixels(array4); texture3D4.Apply(); shader.SetFloat("_Min", min); shader.SetFloat("_Max", max); shader.SetTexture(0, "_TexR", texture3D); shader.SetTexture(0, "_TexG", texture3D2); shader.SetTexture(0, "_TexB", texture3D3); shader.SetTexture(0, "_TexA", texture3D4); shader.SetTexture(0, "des", tex); shader.Dispatch(0, w, h, d); UnityEngine.Object.Destroy(texture3D); UnityEngine.Object.Destroy(texture3D2); UnityEngine.Object.Destroy(texture3D3); UnityEngine.Object.Destroy(texture3D4); }
protected void ConvertBaseTexture() { if (!ValidDimensions(LookupTexture)) { Debug.LogWarning("The given 2D texture " + LookupTexture.name + " cannot be used as a 3D LUT. Pick another texture or adjust dimension to e.g. 256x16."); return; } m_BaseTextureName = LookupTexture.name; int dim = LookupTexture.height; Color[] c = LookupTexture.GetPixels(); Color[] newC = new Color[c.Length]; for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { for (int k = 0; k < dim; k++) { int j_ = dim - j - 1; newC[i + (j * dim) + (k * dim * dim)] = c[k * dim + i + j_ * dim * dim]; } } } if (m_Lut3D) DestroyImmediate(m_Lut3D); m_Lut3D = new Texture3D(dim, dim, dim, TextureFormat.ARGB32, false); m_Lut3D.hideFlags = HideFlags.HideAndDontSave; m_Lut3D.wrapMode = TextureWrapMode.Clamp; m_Lut3D.SetPixels(newC); m_Lut3D.Apply(); }
public void GenerateVolumeTexture() { // sort //System.Array.Sort(slices, (x, y) => x.name.CompareTo(y.name)); // use a bunch of memory! _volumeBuffer = new Texture3D(volumeWidth, volumeHeight, volumeDepth, TextureFormat.ARGB32, false); var w = _volumeBuffer.width; var h = _volumeBuffer.height; var d = _volumeBuffer.depth; // skip some slices if we can't fit it all in var countOffset = (slices.Length - 1) / (float)d; var volumeColors = new Color[w * h * d]; var sliceCount = 0; var sliceCountFloat = 0f; for(int z = 0; z < d; z++) { sliceCountFloat += countOffset; sliceCount = Mathf.FloorToInt(sliceCountFloat); for(int x = 0; x < w; x++) { for(int y = 0; y < h; y++) { var idx = x + (y * w) + (z * (w * h)); volumeColors[idx] = slices[sliceCount].GetPixelBilinear(x / (float)w, y / (float)h); if(increaseVisiblity) { volumeColors[idx].a *= volumeColors[idx].r; } } } } _volumeBuffer.SetPixels(volumeColors); _volumeBuffer.Apply(); _rayMarchMaterial.SetTexture("_VolumeTex", _volumeBuffer); }
// Build voxel object public virtual float Build(Storage voxels, Bounds bounds) { // Check for given array if (voxels != null) { //if (colorAssignments != null) { // Check for non-empty array if (voxels.Count > 0) { // Get iterator if (iterator == null) { iterator = voxels.GetIterator(); currentProgress = 0; } if (texture == null) { if (superSamplingCount <= 0) { superSamplingCount = 1; } // Calculate target resolution int textureWidth = (voxels.Width + superSamplingCount - 1) / superSamplingCount; int textureHeight = (voxels.Height + superSamplingCount - 1) / superSamplingCount; int textureDepth = (voxels.Depth + superSamplingCount - 1) / superSamplingCount; // Make resolution 2^n, if flag is set if (powerOfTwo) { textureWidth = (int)Math.Pow(2, Math.Ceiling(Math.Log((float)textureWidth) / Math.Log(2))); textureHeight = (int)Math.Pow(2, Math.Ceiling(Math.Log((float)textureHeight) / Math.Log(2))); textureDepth = (int)Math.Pow(2, Math.Ceiling(Math.Log((float)textureDepth) / Math.Log(2))); } if (textureWidth != 0 && textureHeight != 0 && textureDepth != 0) { texels = new Color[textureWidth * textureHeight * textureDepth]; counts = new float[textureWidth * textureHeight * textureDepth]; hdr |= voxels.HasHDR(); // Create new texture instance texture = new UnityEngine.Texture3D(textureWidth, textureHeight, textureDepth, hdr ? TextureFormat.RGBAHalf : TextureFormat.RGBA32, 4); if (texture != null) { //texture.filterMode = FilterMode.Point; texture.wrapMode = TextureWrapMode.Clamp; } } } if (texture != null) { // Process voxels in steps for (int number = 0; number < 10; ++number) { // Retrieve color and coordinate for current cell int x, y, z; Color color = iterator.GetNextColor(out x, out y, out z); // Check for valid voxel if (color.a > 0) { var index = x / superSamplingCount + (y / superSamplingCount + z / superSamplingCount * texture.height) * texture.width; // Store color to texels array texels[index] += color; ++counts[index]; } else { iterator = null; break; } } // Return current progress when building has not been finished if (iterator != null) { return(currentProgress = (float)iterator.Number / (float)(voxels.Count + 1)); } else { // Calculate weight factor for every source cell var samplingFactor = 1f / (superSamplingCount * superSamplingCount * superSamplingCount); // Normalize colors and expand edges or blend with background for (int index = 0; index < texels.Length; ++index) { if (counts[index] > 0) { if (expandEdges) { texels[index].r /= counts[index]; texels[index].g /= counts[index]; texels[index].b /= counts[index]; texels[index].a *= samplingFactor; } else { texels[index] /= counts[index]; texels[index] += backgroundColor * (1 - texels[index].a); } } else { if (!expandEdges) { texels[index] = backgroundColor; } } } if (expandEdges) { bool repeat; do { repeat = false; // Process all cells for (int index = 0; index < texels.Length; ++index) { // Check if current cell is empty if (counts[index] == 0) { var column = index % texture.width; var row = index / texture.width % texture.height; var slice = index / texture.width / texture.height; var color = new Color(0, 0, 0, 0); var count = 0f; // Sum up all colors of direct neighbor cells for (int offset = 0; offset < 6; ++offset) { // Get offset by current index var offsetX = offset == 0 ? -1 : offset == 1 ? 1 : 0; var offsetY = offset == 2 ? -1 : offset == 3 ? 1 : 0; var offsetZ = offset == 4 ? -1 : offset == 5 ? 1 : 0; var offsetColumn = column + offsetX; if (offsetColumn >= 0 && offsetColumn < texture.width) { var offsetRow = row + offsetY; if (offsetRow >= 0 && offsetRow < texture.height) { var offsetSlice = slice + offsetZ; if (offsetSlice >= 0 && offsetSlice < texture.depth) { var offsetIndex = offsetColumn + (offsetRow + offsetSlice * texture.height) * texture.width; // Check if neighbor includes an original color or one that has been set in a previous iteration if (counts[offsetIndex] > 0) { // Sum color components and increase quantity counter for later normalization color += texels[offsetIndex]; ++count; } } } } } if (count > 0) { // Normalize target color but set full transparency texels[index].r = color.r / count; texels[index].g = color.g / count; texels[index].b = color.b / count; texels[index].a = 0; // Flag index as processed in this loop and enable next one counts[index] = -count; repeat = true; } } } // Unset processing flags for next iteration for (int index = 0; index < texels.Length; ++index) { if (counts[index] < 0) { counts[index] = -counts[index]; } } }while (repeat); } // Transfer all texel colors to the texture texture.SetPixels(texels); } } } } } // Check for texture and color array if (texture != null) { // Apply color changes on texture texture.Apply(); } // Reset current processing data iterator = null; return(currentProgress = 1); }