public void ensureProperLayerOrdering() { ensureProperNumberLayers(); int numSplatLayers = TerrainGlobals.getTexturing().getActiveTextureCount(); //create N floatN vectors floatN[] layerVecs = new floatN[numSplatLayers]; for (uint k = 0; k < numSplatLayers; k++) { layerVecs[k] = new floatN((uint)numSplatLayers); layerVecs[k][k] = 1; } //now, calculate a VContrib vector for the current layering. floatN vContrib = layerVecs[0].Clone();//start with 100% base layer for (uint k = 1; k < numSplatLayers; k++) { byte b = mLayers[(int)k].mAlphaContrib; int lIdx = mLayers[(int)k].mActiveTextureIndex; float alpha = ((float)b) / 255.0f; vContrib = ( (layerVecs[lIdx] * alpha) + (vContrib * (1 - alpha)) ); } //vContrib now holds at each vector element, the amount the layer is visible to the final pixel //although it's not sorted in the current layer ordering //so, calculate the xF for the new layer ordering, and store it in a temp var floatN vContribSorted = new floatN((uint)numSplatLayers); //back solve to calculate new alpha value. vContribSorted[(uint)(numSplatLayers - 1)] = vContrib[(uint)(numSplatLayers - 1)]; for (int k = (numSplatLayers - 2); k >= 0; k--) { uint invK = (uint)((numSplatLayers - 2) - k); float Vc = vContrib[(uint)(k + 1)]; //vContrib for upper layer float invVc = 1.0f - Vc; //current layer vContrib float cVc = vContrib[(uint)(k)]; float xF = invVc == 0 ? 0 : (cVc / invVc); //move back vContribSorted[(uint)k] = xF; } //now copy back to the unsorted layer index for (int k = 0; k < numSplatLayers; k++) { mLayers[k].mAlphaContrib = (byte)(vContribSorted[(uint)mLayers[k].mActiveTextureIndex] * 255); } //ensure layers are sorted ensureProperSorting(); }
public override bool applyToDstImg(BTerrainQuadNode node, int x, int z, bool selectionMode, bool alternate) { BTerrainLayerContainer layers = node.mLayerContainer; BTerrainActiveDecalContainer decal = TerrainGlobals.getTexturing().getActiveDecal(TerrainGlobals.getTerrainFrontEnd().SelectedDecalIndex); bool changed = false; return(changed); }
public bool init(int decalIndex) { mDecalArrayIndex = decalIndex; BTerrainActiveDecalContainer decal = TerrainGlobals.getTexturing().getActiveDecal(TerrainGlobals.getTerrainFrontEnd().SelectedDecalIndex); SurfaceDescription sd = decal.mTexChannels[0].mTexture.GetLevelDescription(0); mDecalRadius = sd.Width / 2; mDecalWidth = sd.Width; mDecalHeight = sd.Height; return(true); }
public bool mIsSelected; //editor can select a decal instance public void computeBounds() { float vertsToHighResPixelSpaceRatio = BTerrainTexturing.getTextureWidth() / BTerrainQuadNode.cMaxWidth; BTerrainActiveDecalContainer dcl = TerrainGlobals.getTexturing().getActiveDecal(mActiveDecalIndex); int h = (int)(dcl.mWidth * (1.0f / mUScale)); int w = (int)(dcl.mHeight * (1.0f / mVScale)); //rotate our bounds float angleRad = mRotation;// -rotAngle * Math.PI / 180; float angleCos = (float)Math.Cos(angleRad); float angleSin = (float)Math.Sin(angleRad); float halfWidth = w >> 1; float halfHeight = h >> 1; float halfNewWidth, halfNewHeight; int newWidth, newHeight; // rotate corners float cx1 = halfWidth * angleCos; float cy1 = halfWidth * angleSin; float cx2 = halfWidth * angleCos - halfHeight * angleSin; float cy2 = halfWidth * angleSin + halfHeight * angleCos; float cx3 = -halfHeight * angleSin; float cy3 = halfHeight * angleCos; float cx4 = 0; float cy4 = 0; halfNewWidth = Math.Max(Math.Max(cx1, cx2), Math.Max(cx3, cx4)) - Math.Min(Math.Min(cx1, cx2), Math.Min(cx3, cx4)); halfNewHeight = Math.Max(Math.Max(cy1, cy2), Math.Max(cy3, cy4)) - Math.Min(Math.Min(cy1, cy2), Math.Min(cy3, cy4)); newWidth = (int)(halfNewWidth * 2 + 0.5); newHeight = (int)(halfNewHeight * 2 + 0.5); w = newWidth >> 1; h = newHeight >> 1; mTileBoundsMin.X = (int)((mTileCenter.X - (w)) / vertsToHighResPixelSpaceRatio); mTileBoundsMax.X = (int)((mTileCenter.X + (w)) / vertsToHighResPixelSpaceRatio); mTileBoundsMin.Y = (int)((mTileCenter.Y - (h)) / vertsToHighResPixelSpaceRatio); mTileBoundsMax.Y = (int)((mTileCenter.Y + (h)) / vertsToHighResPixelSpaceRatio); }
public int giveLayerIDAtPixel(int x, int y, ref BTerrainTexturingLayer.eLayerType selectedLayerType, bool doSelectDecal) { int index = giveLayerIDAtPixelInternal(x, y, mLayers.Count - 1, ref selectedLayerType); if (index == -1) { return(0); } if (selectedLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Decal && doSelectDecal) { TerrainGlobals.getTexturing().selectActiveDecalInstance(mLayers[index].mActiveTextureIndex); return(mLayers[index].mActiveTextureIndex); } return(index); /* * for (int i = mLayers.Count - 1; i >= 0; i--) * { * * if (mLayers[i].mAlphaLayer[x + BTerrainTexturing.getAlphaTextureWidth() * y] != 0) * { * if (mLayers[i].mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) * { * selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; * return mLayers[i].mActiveTextureIndex; * } * else * { * BTerrainDecalInstance dcli = TerrainGlobals.getTexturing().getActiveDecalInstance(mLayers[i].mActiveTextureIndex); * if (TerrainGlobals.getEditor().mVisTileIntetersectionX <= dcli.mTileBoundsMax.X && TerrainGlobals.getEditor().mVisTileIntetersectionX >= dcli.mTileBoundsMin.X && * TerrainGlobals.getEditor().mVisTileIntetersectionZ <= dcli.mTileBoundsMax.Y && TerrainGlobals.getEditor().mVisTileIntetersectionZ >= dcli.mTileBoundsMin.Y) * { * if (doSelectDecal) * TerrainGlobals.getTexturing().selectActiveDecalInstance(mLayers[i].mActiveTextureIndex); * * selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Decal; * return dcli.mActiveDecalIndex; * } * } * } * } * * selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; * return mLayers[0].mActiveTextureIndex; * */ }
void ensureProperNumberLayers() { bool[] usedTexSlots = new bool[TerrainGlobals.getTexturing().getActiveTextureCount()]; for (int k = 0; k < mLayers.Count; k++) { if (mLayers[k].mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) { usedTexSlots[mLayers[k].mActiveTextureIndex] = true; } } for (int k = 0; k < usedTexSlots.Length; k++) { if (!usedTexSlots[k]) { newSplatLayer(k); } } }
public void unselectActiveDecalInstance(int activeDecalInstanceIndex) { if (activeDecalInstanceIndex < 0 || activeDecalInstanceIndex >= mDecalInstances.Count) { return; } mDecalInstances[activeDecalInstanceIndex].mIsSelected = false; List <BTerrainQuadNode> nodes = TerrainGlobals.getTexturing().giveNodesIntersectingDecalInstance(activeDecalInstanceIndex); for (int i = 0; i < nodes.Count; i++) { //nodes[i].getTextureData().free(); for (int lod = 0; lod < Terrain.BTerrainTexturing.cMaxNumLevels; lod++) { nodes[i].getTextureData(lod).free(); } } nodes.Clear(); nodes = null; }
public void loadTextures() { if (mTexChannels == null) { mTexChannels = new TextureHandle[(int)BTerrainTexturing.eTextureChannels.cSplatChannelCount]; } if (!File.Exists(mFilename)) { mFilename = EditorCore.CoreGlobals.getWorkPaths().mBlankTextureName; mTexChannels[0] = BRenderDevice.getTextureManager().getTexture(mFilename); // = TextureLoader.FromFile(BRenderDevice.getDevice(),mFilename); mTexChannels[1] = BRenderDevice.getTextureManager().getTexture(mFilename); // = TextureLoader.FromFile(BRenderDevice.getDevice(), mFilename); return; } mTexChannels[0] = BRenderDevice.getTextureManager().getTexture(mFilename, TerrainGlobals.getTexturing().activeTextureReloaded);// mTexChannels[0] = TextureLoader.FromFile(BRenderDevice.getDevice(), mFilename); String ext = Path.GetExtension(mFilename); string tName = mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_nm" + ext; mTexChannels[1] = BRenderDevice.getTextureManager().getTexture(tName, TerrainGlobals.getTexturing().activeTextureReloaded);// = TextureLoader.FromFile(BRenderDevice.getDevice(), tName); //gather our information data for the editor mMatHasEmissive = File.Exists(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_em" + ext); mMatHasEnvMask = File.Exists(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_rm" + ext); mMatHasSpecular = File.Exists(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_sp" + ext); mMatHasMask = File.Exists(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_mk" + ".bmp"); //calculate our total memory footprint for this texture m360MemoryFootprint = 0; m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_df.ddx"); m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_nm.ddx"); m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_em.ddx"); m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_rm.ddx"); m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_sp.ddx"); }
public int giveDecalLayerIDAtPixel(int x, int y, bool doSelect) { BTerrainTexturingLayer.eLayerType reftype = BTerrainTexturingLayer.eLayerType.cLayer_Decal; int index = 0; int start = mLayers.Count - 1; while (reftype != BTerrainTexturingLayer.eLayerType.cLayer_Decal) { index = giveLayerIDAtPixelInternal(x, y, start, ref reftype); if (index == -1) { return(0); } } if (doSelect) { TerrainGlobals.getTexturing().selectActiveDecalInstance(mLayers[index].mActiveTextureIndex); } return(index); }
public void removeLayersWithWrongID() { //layer 0 is always a splat if (mLayers.Count == 1 && mLayers[0].mActiveTextureIndex >= TerrainGlobals.getTexturing().getActiveTextureCount()) { mLayers[0].mActiveTextureIndex = 0; return; } for (int i = 0; i < mLayers.Count; i++) { if ((mLayers[i].mActiveTextureIndex >= TerrainGlobals.getTexturing().getActiveTextureCount() && mLayers[i].mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) || (mLayers[i].mActiveTextureIndex >= TerrainGlobals.getTexturing().getActiveDecalInstancesCount() && mLayers[i].mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Decal)) { clearLayerAlpha(i); mLayers.RemoveAt(i); i--; } } fullLayerAlpha(0); }
private int giveLayerIDAtPixelInternal(int x, int y, int startingLayer, ref BTerrainTexturingLayer.eLayerType selectedLayerType) { if (startingLayer > mLayers.Count - 1) { startingLayer = mLayers.Count - 1; } if (startingLayer < 0) { selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; return(0); } for (int i = startingLayer; i >= 0; i--) { if (mLayers[i].mAlphaLayer[x + BTerrainTexturing.getAlphaTextureWidth() * y] != 0) { if (mLayers[i].mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) { selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; return(mLayers[i].mActiveTextureIndex); } else { BTerrainDecalInstance dcli = TerrainGlobals.getTexturing().getActiveDecalInstance(mLayers[i].mActiveTextureIndex); if (TerrainGlobals.getEditor().mVisTileIntetersectionX <= dcli.mTileBoundsMax.X && TerrainGlobals.getEditor().mVisTileIntetersectionX >= dcli.mTileBoundsMin.X && TerrainGlobals.getEditor().mVisTileIntetersectionZ <= dcli.mTileBoundsMax.Y && TerrainGlobals.getEditor().mVisTileIntetersectionZ >= dcli.mTileBoundsMin.Y) { selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Decal; return(i);// dcli.mActiveDecalIndex; } } } } selectedLayerType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; return(-1); }
public void evaluateLOD(Vector3 pt, Vector3 eye, BTerrainLayerContainer layers, BTerrainQuadNode ownerQN)//CLM this is only called on visible nodes { mAgePrediction = mAgePrediction | 0x00000001; int lod = TerrainGlobals.getTexturing().getTextureLODLevel(pt, eye); if (lod != mTextureLODLevel)// || mCompositeTexture==null || mCompositeTexture.mState==eCompositeTextureState.cCS_Free) { mTextureLODLevel = lod; if (mCompositeTexture != null) { mCompositeTexture.free(); mCompositeTexture = null; } /* * mCompositeTexture = TerrainGlobals.getTexturing().getCompositeTexture((int)(BTerrainTexturing.getTextureWidth() >> mTextureLODLevel), (int)(BTerrainTexturing.getTextureHeight() >> mTextureLODLevel)); * if (mCompositeTexture != null) * { * mCompositeTexture.mOwnerNode = ownerQN; * layers.convertToTexturingDataHandle(ref mCompositeTexture); * }*/ } }
public static void MaskCurrentTexture(bool bUseTextureFade) { int totalNumVerts = TerrainGlobals.getTerrain().getNumXVerts(); int i = -1; int selTexIndex = TerrainGlobals.getTerrainFrontEnd().SelectedTextureIndex; BTerrainActiveTextureContainer activeTex = TerrainGlobals.getTexturing().getActiveTexture(TerrainGlobals.getTerrainFrontEnd().SelectedTextureIndex); if (activeTex.mMatHasMask == false) { return; } Image img = Image.FromFile(activeTex.getMaskFileName()); if (img == null) { return; } IMask m = CreateMask(img); if (m == null) { return; } img.Dispose(); for (int x = 0; x < totalNumVerts; x++) { for (int z = 0; z < totalNumVerts; z++) { float baseValue; float factor = 0; if (checkBaseWritePermission(x, z, out baseValue) == false) { continue; } BTerrainTextureVector vec = TerrainGlobals.getEditor().giveTextureDataAtVertex(x, z); if (vec.containsID(selTexIndex, BTerrainTexturingLayer.eLayerType.cLayer_Splat)) { int splatindex = vec.giveLayerIndex(selTexIndex, BTerrainTexturingLayer.eLayerType.cLayer_Splat); float layeralpha = vec.mLayers[splatindex].mAlphaContrib / 255f; float maskAlpha = 0; if (layeralpha == 0) { continue; } maskAlpha = m.GetMaskWeight(((z % 64) * 64) + (x % 64)); //layeralpha = m.GetMaskWeight((( x) * totalNumVerts) + ( z)); if (bUseTextureFade) { maskAlpha = maskAlpha * layeralpha; } if (maskAlpha == 0) { continue; } i++; addSelectedVert(x, z, maskAlpha); } } } }
public void computeDecalLayerAlphaContrib(int layerIndex, int minXVertex, int minZVertex) { if (layerIndex < 0 || layerIndex >= mLayers.Count) { return; } //grab our decal instance if (mLayers[layerIndex].mLayerType != BTerrainTexturingLayer.eLayerType.cLayer_Decal) { return; } float vertsToHighResPixelSpaceRatio = BTerrainTexturing.getTextureWidth() / BTerrainQuadNode.cMaxWidth; BTerrainDecalInstance dcli = TerrainGlobals.getTexturing().getActiveDecalInstance(mLayers[layerIndex].mActiveTextureIndex); BTerrainActiveDecalContainer dcl = TerrainGlobals.getTexturing().getActiveDecal(dcli.mActiveDecalIndex); //scale, rotate, translate us int h = dcl.mHeight; int w = dcl.mWidth; int nW = (int)(w * ((1.0f / dcli.mUScale) / vertsToHighResPixelSpaceRatio)); int nH = (int)(h * ((1.0f / dcli.mVScale) / vertsToHighResPixelSpaceRatio)); int tW = 0; int tH = 0; byte[] tImgResized = null; byte[] tImgRotated = null; byte[] imgDat = new byte[h * w]; imgDat = ImageManipulation.valueGreyScaleImg(imgDat, w, h, ImageManipulation.eValueOperation.cValue_Set, 255); tImgResized = ImageManipulation.resizeGreyScaleImg(imgDat, w, h, nW, nH, ImageManipulation.eFilterType.cFilter_Linear); tImgRotated = ImageManipulation.rotateGreyScaleImg(tImgResized, nW, nH, (float)(-dcli.mRotation * (180.0f / Math.PI)), false, out nW, out nH, ImageManipulation.eFilterType.cFilter_Nearest); byte[] tImg = tImgRotated; int startX = (int)((dcli.mTileCenter.X / vertsToHighResPixelSpaceRatio) - (nW >> 1) - minXVertex); int startY = (int)((dcli.mTileCenter.Y / vertsToHighResPixelSpaceRatio) - (nH >> 1) - minZVertex); clearLayerAlpha(layerIndex); //copy back to masking for (int i = 0; i < nW; i++) { for (int j = 0; j < nH; j++) { int iS = startX + i; if (iS < 0 || iS >= BTerrainTexturing.getAlphaTextureWidth()) { continue; } int jS = startY + j; if (jS < 0 || jS >= BTerrainTexturing.getAlphaTextureHeight()) { continue; } int srcIndex = j + i * nW; int dstIndex = (int)(iS + BTerrainTexturing.getAlphaTextureHeight() * jS); byte val = tImg[srcIndex]; mLayers[layerIndex].mAlphaLayer[dstIndex] = val; } } //also, walk any layers that exist above us, and subtract out their values as well for (int k = layerIndex + 1; k < mLayers.Count; k++) { if (mLayers[k].mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) { for (int i = 0; i < BTerrainTexturing.getAlphaTextureWidth() * BTerrainTexturing.getAlphaTextureHeight(); i++) { mLayers[layerIndex].mAlphaLayer[i] = (byte)BMathLib.Clamp(mLayers[layerIndex].mAlphaLayer[i] - mLayers[k].mAlphaLayer[i], 0, 255); } } } imgDat = null; tImgResized = null; tImgRotated = null; tImg = null; }
public void loadTextures() { if (mTexChannels == null) { mTexChannels = new TextureHandle[(int)BTerrainTexturing.eTextureChannels.cDecalChannelCount + 1]; } if (!File.Exists(mFilename)) { mFilename = EditorCore.CoreGlobals.getWorkPaths().mBlankTextureName; mTexChannels[(int)BTerrainTexturing.eTextureChannels.cAlbedo] = BRenderDevice.getTextureManager().getTexture(mFilename); // = TextureLoader.FromFile(BRenderDevice.getDevice(),mFilename); mTexChannels[(int)BTerrainTexturing.eTextureChannels.cNormal] = BRenderDevice.getTextureManager().getTexture(mFilename); // = TextureLoader.FromFile(BRenderDevice.getDevice(), mFilename); mTexChannels[(int)BTerrainTexturing.eTextureChannels.cOpacity] = BRenderDevice.getTextureManager().getTexture(mFilename); // = TextureLoader.FromFile(BRenderDevice.getDevice(), mFilename); return; } mTexChannels[(int)BTerrainTexturing.eTextureChannels.cAlbedo] = BRenderDevice.getTextureManager().getTexture(mFilename, TerrainGlobals.getTexturing().activeDecalReloaded);// mTexChannels[0] = TextureLoader.FromFile(BRenderDevice.getDevice(), mFilename); String ext = Path.GetExtension(mFilename); string tName = mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_nm" + ext; mTexChannels[(int)BTerrainTexturing.eTextureChannels.cNormal] = BRenderDevice.getTextureManager().getTexture(tName, TerrainGlobals.getTexturing().activeDecalReloaded);// = TextureLoader.FromFile(BRenderDevice.getDevice(), tName); tName = mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_op" + ext; mTexChannels[(int)BTerrainTexturing.eTextureChannels.cOpacity] = BRenderDevice.getTextureManager().getTexture(tName, TerrainGlobals.getTexturing().activeDecalReloaded);// = TextureLoader.FromFile(BRenderDevice.getDevice(), tName); SurfaceDescription sd = mTexChannels[(int)BTerrainTexturing.eTextureChannels.cAlbedo].mTexture.GetLevelDescription(0); mWidth = sd.Width; mHeight = sd.Height; //calculate our total memory footprint for this texture m360MemoryFootprint = 0; //m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_df.ddx"); //m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_nm.ddx"); //m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_em.ddx"); //m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_rm.ddx"); //m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_sp.ddx"); //m360MemoryFootprint += DDXBridge.give360TextureMemFootprint(mFilename.Substring(0, mFilename.LastIndexOf("_df")) + "_op.ddx"); }
public void ensureProperLayerOrdering() { ensureProperNumberLayers(); int numSplatLayers = TerrainGlobals.getTexturing().getActiveTextureCount(); int aWidth = (int)BTerrainTexturing.getAlphaTextureWidth(); int aHeight = (int)BTerrainTexturing.getAlphaTextureHeight(); for (int y = 0; y < aHeight; y++) { for (int x = 0; x < aWidth; x++) { int aIndex = x + aWidth * y; //create N floatN vectors floatN[] layerVecs = new floatN[numSplatLayers]; for (uint k = 0; k < numSplatLayers; k++) { layerVecs[k] = new floatN((uint)numSplatLayers); layerVecs[k][k] = 1; } //quick early out test to make sure we're not screwing up by re-normalizing.. floatN nVal = new floatN((uint)numSplatLayers); for (uint k = 0; k < numSplatLayers; k++) { byte b = mLayers[(int)k].mAlphaLayer[aIndex]; float alpha = ((float)b) / 255.0f; nVal[k] = alpha; } float len = nVal.Length(); if (len == 1.0f) { continue; } //now, calculate a VContrib vector for the current layering. floatN vContrib = layerVecs[0].Clone();//start with 100% base layer for (uint k = 1; k < numSplatLayers; k++) { byte b = mLayers[(int)k].mAlphaLayer[aIndex]; int lIdx = mLayers[(int)k].mActiveTextureIndex; float alpha = ((float)b) / 255.0f; vContrib = ( (layerVecs[lIdx] * alpha) + (vContrib * (1 - alpha)) ); } //vContrib now holds at each vector element, the amount the layer is visible to the final pixel //although it's not sorted in the current layer ordering //so, calculate the xF for the new layer ordering, and store it in a temp var floatN vContribSorted = new floatN((uint)numSplatLayers); floatN vContribSortedInv = new floatN((uint)numSplatLayers); //back solve to calculate new alpha value. vContribSorted[(uint)(numSplatLayers - 1)] = vContrib[(uint)(numSplatLayers - 1)]; vContribSortedInv[(uint)(numSplatLayers - 1)] = 1 - vContribSorted[(uint)(numSplatLayers - 1)]; for (int k = (numSplatLayers - 2); k >= 0; k--) { //multiply the inversions together that we have so far. float mulSoFar = 1; for (uint q = (uint)k + 1; q < numSplatLayers; q++) { mulSoFar *= vContribSortedInv[q]; } vContribSorted[(uint)k] = mulSoFar == 0 ? 0 : vContrib[(uint)(k)] / mulSoFar; vContribSortedInv[(uint)k] = 1 - vContribSorted[(uint)k]; //uint invK = (uint)((numSplatLayers - 2) - k); //float Vc = vContrib[(uint)(k + 1)]; //vContrib for upper layer //float invVc = 1.0f - Vc; ////current layer vContrib //float cVc = vContrib[(uint)(k)]; //float xF = invVc==0?0:(cVc / invVc); ////move back //vContribSorted[(uint)k] = xF; } //now copy back to the unsorted layer index for (int k = 0; k < numSplatLayers; k++) { mLayers[k].mAlphaLayer[aIndex] = (byte)(vContribSorted[(uint)mLayers[k].mActiveTextureIndex] * 255); } } } //ensure layers are sorted ensureProperSorting(); }
//CLM USED FOR EXPORT public unsafe void convertLayersToTexturingDataHandle(BTerrainLayerContainer input, List <Texture> tempAlphaTextures, BTerrainCompositeTexture output, int minXVert, int minZVert, int lod, int channelCount) { // BTerrainLayerContainer input = node.mLayerContainer; // BTerrainCompositeTexture output = node.getTextureData(lod).mCompositeTexture; Viewport vp = new Viewport(); vp.X = output.mXPixelOffset; vp.Y = output.mYPixelOffset; vp.Width = output.mWidth; vp.Height = output.mWidth; vp.MinZ = 0; vp.MaxZ = 1; BRenderDevice.getDevice().Viewport = vp; Microsoft.DirectX.Direct3D.Effect shader = TerrainGlobals.getTexturing().mCompositeShader; shader.Begin(0); shader.BeginPass(0); for (int i = 0; i < channelCount; i++) { for (int k = 0; k < output.mNumMips; k++) { //actually render Surface compositeTarget = null; float scale = 1; try { if (output.UsingAtlas == false) { compositeTarget = output.mTextures[i].GetSurfaceLevel(k); BRenderDevice.getDevice().SetRenderTarget(0, compositeTarget); } else { BTerrainCompositeAtlasTexture atlas = output.mAtlas; if (atlas.mTextures[i].Disposed == true) { atlas.reCreate(); } scale = atlas.mAtlasScale; compositeTarget = atlas.mTextures[i].GetSurfaceLevel(k); BRenderDevice.getDevice().SetRenderTarget(0, compositeTarget); } { BTerrainTexturingLayer.eLayerType lastType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; float layerInc = 1.0f / (float)(cMaxNumBlends - 1);// (float)input.getNumLayers(); for (int j = 0; j < input.getNumLayers(); j++) { // BRenderDevice.getDevice().Clear(ClearFlags.ZBuffer | ClearFlags.Target, unchecked((int)0xFFFF0000), 1.0f, 0); //compose a splat shader.SetValue(mShaderContribOverride, 1); shader.SetValue(mShaderAlphaOverride, 1); if (input.giveLayer(j).mLayerType == BTerrainTexturingLayer.eLayerType.cLayer_Splat) { if (lastType != BTerrainTexturingLayer.eLayerType.cLayer_Splat) { shader.EndPass(); shader.BeginPass(0); lastType = BTerrainTexturingLayer.eLayerType.cLayer_Splat; } if (TerrainGlobals.getEditor().getRenderMode() == BTerrainEditor.eEditorRenderMode.cRenderTextureSelectRender) { if (TerrainGlobals.getEditor().getMode() != BTerrainEditor.eEditorMode.cModeTexEdit) { if (j == 0) { shader.SetValue(mShaderContribOverride, 0); shader.SetValue(mShaderAlphaOverride, 0); } else { continue; } } else { if (input.giveLayer(j).mActiveTextureIndex != TerrainGlobals.getTerrainFrontEnd().SelectedTextureIndex) { shader.SetValue(mShaderContribOverride, 0); } else { shader.SetValue(mShaderContribOverride, 1); } shader.SetValue(mShaderAlphaOverride, 0); } } float targetLayer = (float)(j * layerInc); shader.SetValue(mShaderNumLayersHandle, targetLayer); shader.SetValue(mShaderAlphaTexArrayHandle, tempAlphaTextures[j]); //lock in our target texture BTerrainActiveTextureContainer active = TerrainGlobals.getTexturing().getActiveTexture(input.giveLayer(j).mActiveTextureIndex); if (active == null) { compositeTarget.Dispose(); continue; } shader.SetValue(mShaderTexArrayHandle, active.mTexChannels[i].mTexture); float[] uvs = new float[2]; uvs[0] = active.mUScale; uvs[1] = active.mVScale; shader.SetValue(mShaderLayerUV, uvs); } else //compose a decal { if (lastType != BTerrainTexturingLayer.eLayerType.cLayer_Decal) { shader.EndPass(); shader.BeginPass(1); lastType = BTerrainTexturingLayer.eLayerType.cLayer_Decal; } bool doWhite = false; if (TerrainGlobals.getEditor().getRenderMode() == BTerrainEditor.eEditorRenderMode.cRenderTextureSelectRender) { if (TerrainGlobals.getEditor().getMode() == BTerrainEditor.eEditorMode.cModeTexEdit) { shader.SetValue(mShaderContribOverride, 0); } else if (TerrainGlobals.getEditor().getMode() == BTerrainEditor.eEditorMode.cModeDecalEdit) { doWhite = true; if (TerrainGlobals.getTexturing().getActiveDecalInstance(input.giveLayer(j).mActiveTextureIndex).mActiveDecalIndex != TerrainGlobals.getTerrainFrontEnd().SelectedDecalIndex) { shader.SetValue(mShaderContribOverride, 0); } else { shader.SetValue(mShaderContribOverride, 1); shader.SetValue(mShaderAlphaOverride, 1); } } } //Grab our decal instance BTerrainDecalInstance decal = getActiveDecalInstance(input.giveLayer(j).mActiveTextureIndex); if (decal == null) { compositeTarget.Dispose(); continue; } Vector4 selColor = new Vector4(1, 1, 1, 1); if (decal.mIsSelected) { selColor.Y = 0.75f; selColor.Z = 0.75f; } shader.SetValue(mShaderColorOverload, selColor); //grab the decal we care about BTerrainActiveDecalContainer active = getActiveDecal(decal.mActiveDecalIndex); if (active == null) { compositeTarget.Dispose(); continue; } if (doWhite) { shader.SetValue(mShaderAlphaTexArrayHandle, tempAlphaTextures[0]); } else { shader.SetValue(mShaderAlphaTexArrayHandle, tempAlphaTextures[j]); } shader.SetValue(mShaderAlphaTexDecalHandle, active.mTexChannels[(int)BTerrainTexturing.eTextureChannels.cOpacity].mTexture); shader.SetValue(mShaderTexDecalHandle, active.mTexChannels[i].mTexture); float[] decalDat = new float[4]; decalDat[0] = decal.mRotation; //compute our U and V offset float vertsToHighResPixelSpaceRatio = BTerrainTexturing.getTextureWidth() / BTerrainQuadNode.cMaxWidth; decalDat[1] = (decal.mTileCenter.X - (minXVert * vertsToHighResPixelSpaceRatio)) / BTerrainTexturing.getTextureWidth(); decalDat[2] = (decal.mTileCenter.Y - (minZVert * vertsToHighResPixelSpaceRatio)) / BTerrainTexturing.getTextureHeight(); decalDat[3] = 0; shader.SetValue(mShaderLayerDecalData, decalDat); float[] uvs = new float[2]; uvs[0] = decal.mUScale; uvs[1] = decal.mVScale; shader.SetValue(mShaderLayerUV, uvs); } shader.CommitChanges(); BRenderDevice.getDevice().Viewport = vp; BRenderDevice.getDevice().DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 4, 0, 2); } shader.EndPass(); shader.BeginPass(0); } } catch (Direct3DXException e) { CoreGlobals.getErrorManager().SendToErrorWarningViewer("An error has occured during the compositing process"); } finally { if (compositeTarget != null) { compositeTarget.Dispose(); } } } } shader.EndPass(); shader.End(); }