internal MyTextureArray(TexId[] mergeList, string debugName) { m_mergeList = mergeList; m_debugName = debugName; Init(); }
internal MyTextureArray(TexId[] mergeList) { var srcDesc = MyTextures.GetView(mergeList[0]).Description; Size = MyTextures.GetSize(mergeList[0]); ArrayLen = mergeList.Length; Texture2DDescription desc = new Texture2DDescription(); desc.ArraySize = ArrayLen; desc.BindFlags = BindFlags.ShaderResource; desc.CpuAccessFlags = CpuAccessFlags.None; desc.Format = srcDesc.Format; desc.Height = (int)Size.Y; desc.Width = (int)Size.X; desc.MipLevels = 0; desc.SampleDescription.Count = 1; desc.SampleDescription.Quality = 0; desc.Usage = ResourceUsage.Default; m_resource = new Texture2D(MyRender11.Device, desc); // foreach mip var mipmaps = (int)Math.Log(Size.X, 2) + 1; for (int a = 0; a < ArrayLen; a++) { for (int m = 0; m < mipmaps; m++) { MyRender11.Context.CopySubresourceRegion(MyTextures.Textures.Data[mergeList[a].Index].Resource, Resource.CalculateSubResourceIndex(m, 0, mipmaps), null, Resource, Resource.CalculateSubResourceIndex(m, a, mipmaps)); } } ShaderView = new ShaderResourceView(MyRender11.Device, Resource); }
internal static MyTextureArray FromStringArray(string[] mergeList, MyTextureEnum type, string debugName) { if (mergeList == null) { return null; } TexId[] ids = new TexId[mergeList.Length]; for (int i = 0; i < ids.Length; i++) { ids[i] = MyTextures.GetTexture(mergeList[i], type, true); } return new MyTextureArray(ids, debugName); }
internal static Vector2 GetSize(TexId texId) { return Textures.Data[texId.Index].Size; }
static unsafe void CreateCommonTextures() { { var desc = new Texture2DDescription(); desc.ArraySize = 1; desc.BindFlags = BindFlags.ShaderResource; desc.Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm; desc.Height = 1; desc.Width = 1; desc.Usage = ResourceUsage.Immutable; desc.MipLevels = 1; desc.SampleDescription.Count = 1; desc.SampleDescription.Quality = 0; DataBox[] databox = new DataBox[1]; uint data = 0; void* ptr = &data; databox[0].DataPointer = new IntPtr(ptr); databox[0].RowPitch = 4; ZeroTexId = RegisterTexture("EMPTY", null, MyTextureEnum.SYSTEM, new Texture2D(MyRender11.Device, desc, databox), new Vector2(1, 1)); data = (255 << 16) | (127 << 8) | 127; MissingNormalGlossTexId = RegisterTexture("MISSING_NORMAL_GLOSS", null, MyTextureEnum.SYSTEM, new Texture2D(MyRender11.Device, desc, databox), new Vector2(1, 1)); data = 255; MissingExtensionTexId = RegisterTexture("MISSING_EXTENSIONS", null, MyTextureEnum.SYSTEM, new Texture2D(MyRender11.Device, desc, databox), new Vector2(1, 1)); data = (127 << 16) | (0 << 8) | 255; DebugPinkTexId = RegisterTexture("Pink", null, MyTextureEnum.SYSTEM, new Texture2D(MyRender11.Device, desc, databox), new Vector2(1, 1)); } { var desc = new Texture2DDescription(); desc.ArraySize = 6; desc.BindFlags = BindFlags.ShaderResource; desc.Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm; desc.Height = 1; desc.Width = 1; desc.Usage = ResourceUsage.Immutable; desc.MipLevels = 1; desc.SampleDescription.Count = 1; desc.SampleDescription.Quality = 0; desc.OptionFlags = ResourceOptionFlags.TextureCube; DataBox[] databox = new DataBox[6]; uint data = 0; void* ptr = &data; for (int i = 0; i < 6; i++) { databox[i].DataPointer = new IntPtr(ptr); databox[i].RowPitch = 4; } MissingCubeTexId = RegisterTexture("MISSING_CUBEMAP", null, MyTextureEnum.SYSTEM, new Texture2D(MyRender11.Device, desc, databox), new Vector2(1, 1)); } { byte[] ditherData = new byte[] { 0, 32, 8, 40, 2, 34, 10, 42, 48, 16, 56, 24, 50, 18, 58, 26, 12, 44, 4, 36, 14, 46, 6, 38, 60, 28, 52, 20, 62, 30, 54, 22, 3, 35, 11, 43, 1, 33, 9, 41, 51, 19, 59, 27, 49, 17, 57, 25, 15, 47, 7, 39, 13, 45, 5, 37, 63, 31, 55, 23, 61, 29, 53, 21 }; for (int i = 0; i < 64; i++) { ditherData[i] *= 4; } var desc = new Texture2DDescription(); desc.ArraySize = 1; desc.BindFlags = BindFlags.ShaderResource; desc.Format = SharpDX.DXGI.Format.R8_UNorm; desc.Height = 8; desc.Width = 8; desc.Usage = ResourceUsage.Immutable; desc.MipLevels = 1; desc.SampleDescription.Count = 1; desc.SampleDescription.Quality = 0; DataBox[] databox = new DataBox[1]; fixed (byte* dptr = ditherData) { databox[0].DataPointer = new IntPtr(dptr); databox[0].RowPitch = 8; Dithering8x8TexId = RegisterTexture("DITHER_8x8", null, MyTextureEnum.SYSTEM, new Texture2D(MyRender11.Device, desc, databox), new Vector2(8, 8)); } byte bdata = 255; void *ptr = &bdata; databox[0].DataPointer = new IntPtr(ptr); databox[0].RowPitch = 1; desc.Height = 1; desc.Width = 1; MissingAlphamaskTexId = RegisterTexture("MISSING_ALPHAMASK", null, MyTextureEnum.SYSTEM, new Texture2D(MyRender11.Device, desc, databox), new Vector2(1, 1)); } }
internal static void AddSingleSprite(TexId texId, Color color, Vector2 origin, Vector2 tangent, Rectangle? sourceRect, RectangleF destinationRect) { AddSingleSprite(MyTextures.Views[texId.Index], MyTextures.GetSize(texId), color, origin, tangent, sourceRect, destinationRect); }
static void UnloadResources(TexId texId) { //Debug.Assert(CheckState(texId, MyTextureState.LOADED)); if (Textures.Data[texId.Index].OwnsData) { if (Textures.Data[texId.Index].Resource != null) { Textures.Data[texId.Index].Resource.Dispose(); Textures.Data[texId.Index].Resource = null; } if (Views[texId.Index] != null) { Views[texId.Index].Dispose(); Views[texId.Index] = null; } } else { Textures.Data[texId.Index].Resource = null; Views[texId.Index] = null; } Textures.Data[texId.Index].FileExists = false; Textures.Data[texId.Index].Size = Vector2.Zero; Textures.Data[texId.Index].SkippedMipmaps = 0; MoveState(texId, MyTextureState.LOADED, MyTextureState.WAITING); }
static TexId RegisterTexture(string name, string contentPath, MyTextureEnum type, Resource resource, Vector2 size) { var nameKey = MyStringId.GetOrCompute(name); if (!NameIndex.ContainsKey(nameKey)) { var texId = NameIndex[nameKey] = new TexId { Index = Textures.Allocate() }; Textures.Data[texId.Index] = new MyTextureInfo { Name = name, ContentPath = contentPath, Type = type, Resource = resource, Size = size }; resource.DebugName = name; Views[texId.Index] = new ShaderResourceView(MyRender11.Device, resource); Views[texId.Index].DebugName = name; } else // reregistered after device reset { var id = NameIndex[nameKey]; if(Textures.Data[id.Index].Resource == null) { Textures.Data[id.Index].Resource = resource; resource.DebugName = name; Views[id.Index] = new ShaderResourceView(MyRender11.Device, resource); Views[id.Index].DebugName = name; } } return NameIndex[nameKey]; }
internal static ShaderResourceView GetView(TexId tex) { return tex != TexId.NULL ? Views[tex.Index] : null; }
internal static TexId GetTexture(MyStringId nameId, string contentPath, MyTextureEnum type, bool waitTillLoaded = false) { if(nameId == MyStringId.NullOrEmpty) { switch (type) { case MyTextureEnum.NORMALMAP_GLOSS: return MissingNormalGlossTexId; case MyTextureEnum.EXTENSIONS: return MissingExtensionTexId; case MyTextureEnum.ALPHAMASK: return MissingAlphamaskTexId; case MyTextureEnum.CUBEMAP: return MissingCubeTexId; case MyTextureEnum.COLOR_METAL: return MyRender11.DebugMode ? DebugPinkTexId : ZeroTexId; } return ZeroTexId; } var nameKey = nameId; if (!NameIndex.ContainsKey(nameKey)) { //Debug.Assert(type != MyTextureEnum.SYSTEM); var texId = NameIndex[nameKey] = new TexId{ Index = Textures.Allocate() }; InitState(texId, MyTextureState.WAITING); Textures.Data[texId.Index] = new MyTextureInfo { Name = nameId.ToString(), ContentPath = contentPath, Type = type, OwnsData = true }; MyArrayHelpers.Reserve(ref Views, texId.Index + 1); Views[texId.Index] = null; if (waitTillLoaded) { LoadTexture(texId); MoveState(texId, MyTextureState.WAITING, MyTextureState.LOADED); } } return NameIndex[nameKey]; }
static void LoadTexture(TexId texId) { var contentPath = Textures.Data[texId.Index].ContentPath; string path; if (string.IsNullOrEmpty(contentPath)) path = Path.Combine(MyFileSystem.ContentPath, Textures.Data[texId.Index].Name); else path = Path.Combine(contentPath, Textures.Data[texId.Index].Name); Debug.Assert(Textures.Data[texId.Index].Resource == null); Debug.Assert(GetView(texId) == null, "Texture " + Textures.Data[texId.Index].Name + " in invalid state"); Image img = null; if (MyFileSystem.FileExists(path)) { try { using (var s = MyFileSystem.OpenRead(path)) { img = Image.Load(s); } } catch(Exception e) { MyRender11.Log.WriteLine("Could not load texture: " + path + ", exception: " + e); } } if(img != null) { int skipMipmaps = (Textures.Data[texId.Index].Type != MyTextureEnum.GUI && img.Description.MipLevels > 1) ? MyRender11.RenderSettings.TextureQuality.MipmapsToSkip(img.Description.Width, img.Description.Height) : 0; int targetMipmaps = img.Description.MipLevels - skipMipmaps; var mipmapsData = new DataBox[(img.Description.MipLevels - skipMipmaps) * img.Description.ArraySize]; for(int z = 0; z<img.Description.ArraySize; z++) { for (int i = 0; i < targetMipmaps; i++) { var pixels = img.GetPixelBuffer(z, i + skipMipmaps); mipmapsData[Resource.CalculateSubResourceIndex(i, z, targetMipmaps)] = new DataBox { DataPointer = pixels.DataPointer, RowPitch = pixels.RowStride }; } } var targetWidth = img.Description.Width >> skipMipmaps; var targetHeight = img.Description.Height >> skipMipmaps; var desc = new Texture2DDescription { MipLevels = targetMipmaps, Format = img.Description.Format, Height = targetHeight, Width = targetWidth, ArraySize = img.Description.ArraySize, BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.None, Usage = ResourceUsage.Immutable, SampleDescription = new SharpDX.DXGI.SampleDescription { Count = 1, Quality = 0 }, OptionFlags = img.Description.Dimension == TextureDimension.TextureCube ? ResourceOptionFlags.TextureCube : ResourceOptionFlags.None }; var resource = new Texture2D(MyRender11.Device, desc, mipmapsData); Textures.Data[texId.Index].Resource = resource; Textures.Data[texId.Index].Size = new Vector2(targetWidth, targetHeight); Textures.Data[texId.Index].SkippedMipmaps = skipMipmaps; Textures.Data[texId.Index].FileExists = true; Views[texId.Index] = new ShaderResourceView(MyRender11.Device, resource); resource.DebugName = path; Views[texId.Index].DebugName = path; img.Dispose(); } else { // set data to some crap TexId replacingId = ZeroTexId; switch(Textures.Data[texId.Index].Type) { case MyTextureEnum.NORMALMAP_GLOSS: replacingId = MissingNormalGlossTexId; break; case MyTextureEnum.EXTENSIONS: replacingId = MissingExtensionTexId; break; case MyTextureEnum.ALPHAMASK: replacingId = MissingAlphamaskTexId; break; case MyTextureEnum.CUBEMAP: replacingId = MissingCubeTexId; break; case MyTextureEnum.COLOR_METAL: replacingId = MyRender11.DebugMode ? DebugPinkTexId : ZeroTexId; break; } Views[texId.Index] = Views[replacingId.Index]; Textures.Data[texId.Index].Resource = Textures.Data[replacingId.Index].Resource; Textures.Data[texId.Index].Size = Textures.Data[replacingId.Index].Size; Textures.Data[texId.Index].OwnsData = false; } }
internal static void UpdateSpotlight(LightId light, bool enabled, Vector3 direction, float range, float apertureCos, Vector3 up, Vector3 color, float falloff, TexId reflectorTexture) { var info = Spotlights[light.Index]; var gid = light.ParentGID; if (gid != -1 && MyIDTracker<MyActor>.FindByID((uint)gid) != null) { var matrix = MyIDTracker<MyActor>.FindByID((uint)gid).WorldMatrix; Vector3.TransformNormal(ref direction, ref matrix, out direction); Vector3.TransformNormal(ref up, ref matrix, out up); } bool aabbChanged = info.Direction != direction || info.Range != range || info.ApertureCos != apertureCos || info.Up != up; Spotlights[light.Index].Enabled = enabled; Spotlights[light.Index].Direction = direction; Spotlights[light.Index].Range = range; Spotlights[light.Index].ApertureCos = apertureCos; Spotlights[light.Index].Up = up; Spotlights[light.Index].Falloff = falloff; Spotlights[light.Index].Color = color; Spotlights[light.Index].ReflectorTexture = reflectorTexture; var proxy = Spotlights[light.Index].BvhProxyId; var positionDifference = Vector3D.RectangularDistance(ref Spotlights[light.Index].LastBvhUpdatePosition, ref Lights.Data[light.Index].PositionWithOffset); bool dirty = (enabled && ((proxy == -1) || (positionDifference > MOVE_TOLERANCE || aabbChanged))) || (!enabled && proxy != -1); if (dirty) { DirtySpotlights.Add(light); } else { DirtySpotlights.Remove(light); } }
internal static void ClearState(TexId texId) { for(int i=0; i<State.Length; i++) { State[i].Remove(texId); } }
internal static bool CheckState(TexId texId, MyTextureState state) { return State[(int)state].Contains(texId); }
internal static void MoveState(TexId texId, MyTextureState from, MyTextureState to) { State[(int)from].Remove(texId); State[(int)to].Add(texId); }
internal static void InitState(TexId texId, MyTextureState state) { Debug.Assert(!CheckState(texId, MyTextureState.LOADED)); Debug.Assert(!CheckState(texId, MyTextureState.WAITING)); State[(int)state].Add(texId); }
private static void UpdateTextureArray() { if (m_textureArrayDirty) { if (m_textureArray != null) m_textureArray.Dispose(); m_textureArray = null; Resources.TexId[] textIds = new Resources.TexId[m_textureArrayIndices.Count]; foreach (var item in m_textureArrayIndices) textIds[item.Value.Index] = item.Key; if (textIds.Length > 0) m_textureArray = new Resources.MyTextureArray(textIds, "gpuParticles"); m_textureArrayDirty = false; } }
internal static ShaderResourceView GetView(TexId tex) { return Views[tex.Index]; }
static void AddBatch(int counter, int offset, TexId prevTexture, MyTransparentMaterial prevMaterial) { MyBillboardRendererBatch batch = new MyBillboardRendererBatch(); batch.Offset = offset; batch.Num = counter - offset; batch.Texture = prevTexture; batch.Lit = prevMaterial.CanBeAffectedByOtherLights; batch.AlphaCutout = prevMaterial.AlphaCutout; m_batches.Add(batch); }