public static Texture2D MakeTexture(Texture2D sourceTexture, RTPGlossBaked[] tilesData) { Texture2D texture2D = new Texture2D(sourceTexture.width, sourceTexture.height, TextureFormat.ARGB32, true); for (int i = 0; i < 4; i++) { int num = sourceTexture.width >> 1; int num2 = i % 2 * num; int num3 = (i % 4 >= 2) ? num : 0; Color[] array = sourceTexture.GetPixels(num2, num3, num, num, 0); for (int j = 0; j < array.Length; j++) { float num4 = Mathf.Clamp01(array[j].a * tilesData[i].gloss_mult); float num5 = num4; float num6 = 1f - num4; num5 = num5 * num5 * num5; num6 = num6 * num6 * num6; float num7 = Mathf.Lerp(num5, 1f - num6, tilesData[i].gloss_shaping); num7 = Mathf.Clamp01(num7); array[j].a = num7; } texture2D.SetPixels(num2, num3, num, num, array, 0); for (int k = 1; k < sourceTexture.mipmapCount - 1; k++) { int num8 = texture2D.width >> k + 1; Color[] array2 = new Color[num8 * num8]; byte[] glossMipLevel = tilesData[i].GetGlossMipLevel(k); int num9 = glossMipLevel.Length; for (int l = 0; l < num9; l++) { int num10 = l % num8; int num11 = l / num8; int num12 = num11 * num8 * 4 + num10 * 2; int num13 = num12 + 1; int num14 = num12 + num8 * 2; int num15 = num14 + 1; array2[l].r = (array[num12].r + array[num13].r + array[num14].r + array[num15].r) / 4f; array2[l].g = (array[num12].g + array[num13].g + array[num14].g + array[num15].g) / 4f; array2[l].b = (array[num12].b + array[num13].b + array[num14].b + array[num15].b) / 4f; array2[l].a = (float)glossMipLevel[l] / 255f; } array = array2; num2 >>= 1; num3 >>= 1; num >>= 1; texture2D.SetPixels(num2, num3, num, num, array2, k); } } texture2D.Apply(false, false); texture2D.Compress(true); texture2D.Apply(false, true); texture2D.wrapMode = sourceTexture.wrapMode; texture2D.anisoLevel = sourceTexture.anisoLevel; texture2D.filterMode = sourceTexture.filterMode; return texture2D; }
// atlas public static Texture2D MakeTexture(Texture2D sourceTexture, RTPGlossBaked[] tilesData) { Texture2D targetTexture=new Texture2D(sourceTexture.width, sourceTexture.height, TextureFormat.ARGB32, true); for(int tile=0; tile<4; tile++) { int halfSize=sourceTexture.width>>1; int bx=(tile%2)*halfSize; int by=((tile%4)<2) ? 0 : halfSize; Color[] prevCols=sourceTexture.GetPixels(bx,by,halfSize,halfSize,0); // use gloss shaping for MIP0 (reszta już przygotowana do skopiowania) for(int i=0; i<prevCols.Length; i++) { float glossiness=Mathf.Clamp01(prevCols[i].a*tilesData[tile].gloss_mult); float gloss_shaped=glossiness; float gloss_shaped_inv=1-glossiness; gloss_shaped=gloss_shaped*gloss_shaped*gloss_shaped; gloss_shaped_inv=gloss_shaped_inv*gloss_shaped_inv*gloss_shaped_inv; float gls=Mathf.Lerp(gloss_shaped, 1-gloss_shaped_inv, tilesData[tile].gloss_shaping); gls=Mathf.Clamp01(gls); prevCols[i].a=gls; } targetTexture.SetPixels(bx,by,halfSize,halfSize,prevCols,0); for(int mip=1; mip<sourceTexture.mipmapCount-1; mip++) { int curSize=(targetTexture.width>>(mip+1)); Color[] cols=new Color[curSize * curSize]; byte[] glossMIPData=tilesData[tile].GetGlossMipLevel(mip); int len=glossMIPData.Length; for(int i=0; i<len; i++) { int ix=i%curSize; int iy=i/curSize; int idx0=iy*curSize*4+ix*2; int idx1=idx0+1; int idx2=idx0+curSize*2; int idx3=idx2+1; // musimy ręcznie obliczyć kolejne MIPmapy koloru, GetPixels(dla miplevel>0) potrafi wywalić Unity (coś z przydziałem pamięci poważnie zaczyna szwankować) cols[i].r=((prevCols[idx0].r+prevCols[idx1].r+prevCols[idx2].r+prevCols[idx3].r)/4); cols[i].g=((prevCols[idx0].g+prevCols[idx1].g+prevCols[idx2].g+prevCols[idx3].g)/4); cols[i].b=((prevCols[idx0].b+prevCols[idx1].b+prevCols[idx2].b+prevCols[idx3].b)/4); cols[i].a=glossMIPData[i]/255.0f; } prevCols=cols; bx=bx>>1; by=by>>1; halfSize=halfSize>>1; targetTexture.SetPixels(bx,by,halfSize,halfSize,cols, mip); } } targetTexture.Apply(false, false); targetTexture.Compress(true); targetTexture.Apply(false, true); targetTexture.wrapMode=sourceTexture.wrapMode; targetTexture.anisoLevel=sourceTexture.anisoLevel; targetTexture.filterMode=sourceTexture.filterMode; return targetTexture; }
public void ApplyGlossBakedAtlas(string shaderParamName, int atlasNum) { if (gloss_baked==null || gloss_baked.Length==0) { gloss_baked=new RTPGlossBaked[12]; } if (atlas_glossBaked[atlasNum]==null) { if (splat_atlases[atlasNum]==null) return; // nie mamy przygotowanego zmodyfikowanego atlasa // if (gloss_baked[i]!=null) { // Debug.Log ("R"+i); // } bool somethings_baked=false; for(int tile=0; tile<4; tile++) { int i=atlasNum*4+tile; if ( (gloss_baked[i]!=null) && gloss_baked[i].used_in_atlas && gloss_baked[i].CheckSize(splats[i]) ) { somethings_baked=true; } } if (somethings_baked) { RTPGlossBaked[] glBakedTMP=new RTPGlossBaked[4]; for(int tile=0; tile<4; tile++) { int i=atlasNum*4+tile; if ( (gloss_baked[i]!=null) && gloss_baked[i].used_in_atlas && gloss_baked[i].CheckSize(splats[i]) ) { glBakedTMP[tile]=gloss_baked[i]; } else { glBakedTMP[tile]=ScriptableObject.CreateInstance(typeof(RTPGlossBaked)) as RTPGlossBaked; glBakedTMP[tile].Init(splats[i].width); glBakedTMP[tile].GetMIPGlossMapsFromAtlas(splat_atlases[atlasNum], tile); // gloss mipmapy bezpośrednio skopiowane z kawałka atlasa glBakedTMP[tile].used_in_atlas=true; } } // połącz elementy atlas_glossBaked[atlasNum]=RTPGlossBaked.MakeTexture(splat_atlases[atlasNum], glBakedTMP); // i zapodaj shaderowi SetShaderParam(shaderParamName, atlas_glossBaked[atlasNum]); } else { // żaden element atlasa nie jest zbake'owany - użyj oryginału SetShaderParam(shaderParamName, splat_atlases[atlasNum]); } } else { SetShaderParam(shaderParamName, atlas_glossBaked[atlasNum]); } }