public override TexturePageHandle createTexturePageHandle(VTexPage page, IndirectionTexture indirectionTexture, int padding, int padding2, int textelsPerPage, int mipOffset) { PixelBox sourceBox; int mipCount = image.NumMipmaps; if (mipCount == 0) //We always have to take from the largest size { sourceBox = image.getPixelBox(0, 0); } else { sourceBox = image.getPixelBox(0, (uint)(page.mip - mipOffset)); } IntSize2 largestSupportedPageIndex = indirectionTexture.NumPages; largestSupportedPageIndex.Width >>= page.mip; largestSupportedPageIndex.Height >>= page.mip; if (page.x != 0 && page.y != 0 && page.x + 1 != largestSupportedPageIndex.Width && page.y + 1 != largestSupportedPageIndex.Height) { //Can grab a complete page from the texture sourceBox.Rect = new IntRect(page.x * textelsPerPage - padding, page.y * textelsPerPage - padding, textelsPerPage + padding2, textelsPerPage + padding2); } else { //Have to get a partial page sourceBox.Rect = new IntRect(page.x * textelsPerPage, page.y * textelsPerPage, textelsPerPage, textelsPerPage); } return(new TexturePageHandle(sourceBox, this)); }
public override TexturePageHandle createTexturePageHandle(VTexPage page, IndirectionTexture indirectionTexture, int padding, int padding2, int textelsPerPage, int mipOffset) { int mip = page.mip; int x = page.x; int y = page.y; bool halfSizePages = textelsPerPage != pagedImage.PageSize; if (halfSizePages) { x /= 2; y /= 2; } var image = pagedImage.getImage(x, y, mip - mipOffset); var pixelBox = image.getPixelBox(); if (halfSizePages && image.Width == pagedImage.PageSize + padding2) { int subpageX = page.x % 2; int subpageY = page.y % 2; int offsetMultiple = (int)image.Width / 2 - padding; int halfSize = textelsPerPage + padding2; pixelBox.Rect = new Engine.IntRect(offsetMultiple * subpageX, offsetMultiple * subpageY, halfSize, halfSize); } return(new TexturePageHandle(pixelBox, this, image)); }
private bool copyToStaging(VTexPage page, StagingBufferSet buffers, IndirectionTexture indirectionTexture, OriginalTextureInfo textureUnit) { bool usedPhysicalPage = false; try { if (page.mip >= textureUnit.MipOffset) { //Load or grab from cache using (var pageHandle = textureCache.getImage(page, indirectionTexture, textureUnit, textelsPerPage, padding, padding2)) { buffers.setPhysicalPage(pageHandle.PixelBox, virtualTextureManager.getPhysicalTexture(textureUnit.TextureUnit), padding); usedPhysicalPage = true; } } else { Logging.Log.Warning("Unable to load mip map level {0} for texture {1}", page.mip - textureUnit.MipOffset, textureUnit.TextureFileName); } } catch (Exception ex) { Logging.Log.Error("{0} loading image {1}. Message: {2}", ex.GetType().Name, textureUnit.TextureFileName, ex.Message); } return(usedPhysicalPage); }
public void destroyIndirectionTexture(IndirectionTexture indirectionTex) { lock (newIndirectionTextures) { //Make sure we aren't waiting to be activated as a new texture newIndirectionTextures.Remove(indirectionTex); } lock (retiredIndirectionTextures) { retiredIndirectionTextures.Add(indirectionTex); indirectionTextures.Remove(indirectionTex.MaterialSetKey); } }
/// <summary> /// Create or retrieve an indirection texture, will return true if the texture was just created. Useful /// for filling out other info on the texture if needed. /// </summary> /// <param name="materialSetKey">The key to use to search for this texture.</param> /// <param name="textureSize">The size of the virtual texture this indirection texture needs to remap.</param> /// <param name="indirectionTex">An out variable for the results.</param> /// <returns>True if the texture was just created, false if not.</returns> public bool createOrRetrieveIndirectionTexture(String materialSetKey, IntSize2 textureSize, bool keepHighestMip, out IndirectionTexture indirectionTex) { if (!indirectionTextures.TryGetValue(materialSetKey, out indirectionTex)) { indirectionTex = new IndirectionTexture(materialSetKey, textureSize, texelsPerPage, this, keepHighestMip); indirectionTextures.Add(indirectionTex.MaterialSetKey, indirectionTex); lock (newIndirectionTextures) { newIndirectionTextures.Add(indirectionTex); } return(true); } return(false); }
public void setIndirectionTextures(IndirectionTexture oldIndirectionTexture, IndirectionTexture newIndirectionTexture) { updateOldIndirectionTexture = oldIndirectionTexture != null; updateNewIndirectionTexture = oldIndirectionTexture != newIndirectionTexture; if (updateOldIndirectionTexture) { oldIndirectionTextureStaging.setData(oldIndirectionTexture); oldIndirectionId = oldIndirectionTexture.Id; } if (updateNewIndirectionTexture) { newIndirectionTextureStaging.setData(newIndirectionTexture); newIndirectionId = newIndirectionTexture.Id; } }
private bool loadPage(VTexPage page, StagingBufferSet stagingBuffers) { bool added = false; try { //First see if we still have that page in our virtual texture pool, possible optimization to sort these to the front of the list if (physicalPageQueue.Count > 0) //Do we have pages available { PTexPage pTexPage = physicalPageQueue[0]; //The physical page candidate, do not modify before usedPhysicalPages if statement below if (loadImages(page, pTexPage, stagingBuffers)) { //Alert old texture of removal if there was one, Do not modify pTexPage above this if block, we need the old data IndirectionTexture oldIndirectionTexture = null; if (pTexPage.VirtualTexturePage != null) { if (virtualTextureManager.getIndirectionTexture(pTexPage.VirtualTexturePage.indirectionTexId, out oldIndirectionTexture)) { oldIndirectionTexture.removePhysicalPage(pTexPage); } physicalPagePool.Remove(pTexPage.VirtualTexturePage); //Be sure to remove the page from the pool if it was used previously } physicalPageQueue.RemoveAt(0); pTexPage.VirtualTexturePage = page; usedPhysicalPages.Add(page, pTexPage); //Add to new indirection texture IndirectionTexture newIndirectionTex; if (virtualTextureManager.getIndirectionTexture(page.indirectionTexId, out newIndirectionTex)) { newIndirectionTex.addPhysicalPage(pTexPage); stagingBuffers.setIndirectionTextures(oldIndirectionTexture, newIndirectionTex); } added = true; } } } catch (Exception ex) { Logging.Log.Debug("{0} loading page {1}. Message: {2}", ex.GetType().Name, page.ToString(), ex.Message); } return(added); }
internal TexturePageHandle getImage(VTexPage page, IndirectionTexture indirectionTexture, OriginalTextureInfo textureUnit, int textelsPerPage, int padding, int padding2) { String textureName; if (texturesArePaged) { textureName = textureUnit.TextureFileName; } else { textureName = String.Format("{0}_{1}", textureUnit.TextureFileName, indirectionTexture.RealTextureSize.Width >> page.mip); } TextureCacheHandle cacheHandle; if (!this.TryGetValue(textureName, out cacheHandle)) { String file = textureUnit.TextureFileName; if (texturesArePaged) //Paged Images { //using (var perfMon = new LogPerformanceBlock(String.Format("Loaded image {0} in {{0}} ms", file), Logging.LogLevel.Info, "TextureCache")) //{ PagedImage pagedImage = new PagedImage(); pagedImage.load(() => VirtualFileSystem.Instance.openStream(file, Engine.Resources.FileMode.Open, Engine.Resources.FileAccess.Read)); cacheHandle = this.Add(textureName, pagedImage); //} } else //Normal Images { String extension = Path.GetExtension(file); String directFile = textureUnit.TextureFileName.Substring(0, file.Length - extension.Length); directFile = String.Format("{0}_{1}{2}", directFile, indirectionTexture.RealTextureSize.Width >> page.mip, extension); if (VirtualFileSystem.Instance.exists(directFile)) { var image = doLoadImage(extension, directFile); cacheHandle = this.Add(textureName, image); } else { //Not using cache for full size images, this is a rare case that we are not really supporting right now Image image = doLoadImage(extension, textureUnit.TextureFileName); //If we aren't mip 0 resize accordingly if (page.mip > image.NumMipmaps && page.mip != 0) { using (Image original = image) { image = new Image(original.Width >> page.mip, original.Height >> page.mip, original.Depth, original.Format, original.NumFaces, original.NumMipmaps); using (var src = original.getPixelBox()) { using (var dest = image.getPixelBox()) { Image.Scale(src, dest, Image.Filter.FILTER_BILINEAR); } } } } cacheHandle = this.Add(textureName, image); } } } return(cacheHandle.createTexturePageHandle(page, indirectionTexture, padding, padding2, textelsPerPage, textureUnit.MipOffset)); }
public void setupVirtualTextureFragmentParams(GpuProgramParametersSharedPtr gpuParams, IndirectionTexture indirectionTexture) { if (gpuParams.Value.hasNamedConstant("physicalSizeRecip")) { gpuParams.Value.setNamedConstant("physicalSizeRecip", PhysicalSizeRecrip); var realSize = indirectionTexture.RealTextureSize; gpuParams.Value.setNamedConstant("mipBiasSize", new Vector2(realSize.Width, realSize.Height)); gpuParams.Value.setNamedConstant("pagePaddingScale", TextureLoader.PagePaddingScale); gpuParams.Value.setNamedConstant("pagePaddingOffset", TextureLoader.PagePaddingOffset); if (gpuParams.Value.hasNamedConstant("pageSizeLog2")) { gpuParams.Value.setNamedConstant("pageSizeLog2", pageSizeLog2); } } else { Logging.Log.Error("physicalSizeRecip varaible missing"); } }
internal bool getIndirectionTexture(int id, out IndirectionTexture tex) { return(indirectionTexturesById.TryGetValue(id, out tex)); }
public void setData(IndirectionTexture indirectionTexture) { this.indirectionTexture = indirectionTexture; indirectionTexture.copyToStaging(pixelBox); }
private Task <bool> fireCopyToStaging(VTexPage page, StagingBufferSet buffers, IndirectionTexture indirectionTexture, OriginalTextureInfo textureUnit) { return(Task.Run(() => copyToStaging(page, buffers, indirectionTexture, textureUnit))); }
/// <summary> /// Create a texture page handle for this cache handle, the page will be selected from the given info. /// You must dispose the handle that is returned. /// </summary> /// <param name="page"></param> /// <param name="indirectionTexture"></param> /// <param name="padding"></param> /// <param name="padding2"></param> /// <param name="textelsPerPage"></param> /// <returns></returns> public abstract TexturePageHandle createTexturePageHandle(VTexPage page, IndirectionTexture indirectionTexture, int padding, int padding2, int textelsPerPage, int mipOffset);