public static int LoadTexture(string filename, CacheStorage cache) { GL.ActiveTexture(TextureUnit.Texture0); filename = filename.ToLower(); if (cache.materials.ContainsKey(filename)) { // Console.WriteLine("[CACHE HIT] " + filename); return cache.materials[filename]; } //Console.WriteLine("[CACHE MISS] " + filename); int textureId = GL.GenTexture(); var blp = new BLPReader(); blp.LoadBLP(filename); if (blp.bmp == null) { throw new Exception("BMP is null!"); } else { GL.BindTexture(TextureTarget.Texture2D, textureId); cache.materials.Add(filename, textureId); System.Drawing.Imaging.BitmapData bmp_data = blp.bmp.LockBits(new System.Drawing.Rectangle(0, 0, blp.bmp.Width, blp.bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp_data.Width, bmp_data.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); blp.bmp.UnlockBits(bmp_data); } // Console.WriteLine("[CACHE ADD] " + filename); return textureId; }
private void LoadTile(string basedir, int[] tile) { var x = tile[0]; var y = tile[1]; string _SelectedMapName = ((KeyValuePair<int, string>)MapListBox.SelectedValue).Value; Rectangle rect = new Rectangle(); rect.Name = _SelectedMapName.Replace("'", string.Empty).Replace(" ", string.Empty) + x.ToString("D2") + "_" + y.ToString("D2"); //leading zeros just like adts, this breaks when the mapname has special characters (zg)D: rect.Width = WDTGrid.Width / 64; rect.Height = WDTGrid.Height / 64; rect.VerticalAlignment = VerticalAlignment.Top; rect.HorizontalAlignment = HorizontalAlignment.Left; if (File.Exists(basedir + "World\\Minimaps\\" + _SelectedMapName + "\\map" + x.ToString("D2") + "_" + y.ToString("D2") + ".blp")) { rect.MouseLeftButtonDown += new MouseButtonEventHandler(Rectangle_Mousedown); var xmargin = x * rect.Width; var ymargin = y * rect.Height; rect.Margin = new Thickness(xmargin, ymargin, 0, 0); var blp = new BLPReader(basedir); //Kalimdor takes a few seconds to load, and takes up about ~4xxMB of memory after its loaded, this can be much improved blp.LoadBLP("World\\Minimaps\\" + _SelectedMapName + "\\map" + x.ToString("D2") + "_" + y.ToString("D2") + ".blp"); BitmapImage bitmapImage = new BitmapImage(); using (MemoryStream bitmap = blp.asBitmapStream()) { bitmapImage.BeginInit(); bitmapImage.StreamSource = bitmap; bitmapImage.DecodePixelHeight = Convert.ToInt32(rect.Width); bitmapImage.DecodePixelWidth = Convert.ToInt32(rect.Height); bitmapImage.CacheOption = BitmapCacheOption.OnLoad; bitmapImage.EndInit(); } ImageBrush imgBrush = new ImageBrush(bitmapImage); rect.Fill = imgBrush; } else { rect.Fill = new SolidColorBrush(Color.FromRgb(0, 111, 0)); Console.WriteLine(basedir + "World\\Minimaps\\" + _SelectedMapName + "\\map" + x.ToString("D2") + "_" + y.ToString("D2") + ".blp"); } WDTGrid.Children.Add(rect); }
public void LoadM2() { //Load model M2Reader reader = new M2Reader(basedir); string filename = modelPath; reader.LoadM2(filename); //Load vertices List<float> verticelist = new List<float>(); for (int i = 0; i < reader.model.vertices.Count(); i++) { verticelist.Add(reader.model.vertices[i].position.X); verticelist.Add(reader.model.vertices[i].position.Z * -1); verticelist.Add(reader.model.vertices[i].position.Y); verticelist.Add(1.0f); verticelist.Add(reader.model.vertices[i].normal.X); verticelist.Add(reader.model.vertices[i].normal.Z * -1); verticelist.Add(reader.model.vertices[i].normal.Y); verticelist.Add(reader.model.vertices[i].textureCoordX); verticelist.Add(reader.model.vertices[i].textureCoordY); } //Load indices List<ushort> indicelist = new List<ushort>(); for (int i = 0; i < reader.model.skins[0].triangles.Count(); i++) { indicelist.Add(reader.model.skins[0].triangles[i].pt1); indicelist.Add(reader.model.skins[0].triangles[i].pt2); indicelist.Add(reader.model.skins[0].triangles[i].pt3); } //Convert to array ushort[] indices = indicelist.ToArray(); float[] vertices = verticelist.ToArray(); //Get texture, what a mess this could be much better M2Material[] materials = new M2Material[reader.model.textures.Count()]; for (int i = 0; i < reader.model.textures.Count(); i++) { materials[i].flags = reader.model.textures[i].flags; var blp = new BLPReader(basedir); if (File.Exists(Path.Combine(basedir, reader.model.filename.Replace("M2", "blp")))) { blp.LoadBLP(reader.model.filename.Replace("M2", "blp")); } else { blp.LoadBLP(reader.model.textures[i].filename); } if (blp.bmp == null) { materials[i].texture = Texture2D.FromFile<Texture2D>(device, "missingtexture.jpg"); } else { MemoryStream s = new MemoryStream(); blp.bmp.Save(s, System.Drawing.Imaging.ImageFormat.Png); s.Seek(0, SeekOrigin.Begin); materials[i].texture = Texture2D.FromMemory<Texture2D>(device, s.ToArray()); } } M2RenderBatch[] renderbatches = new M2RenderBatch[reader.model.skins[0].submeshes.Count()]; for (int i = 0; i < reader.model.skins[0].submeshes.Count(); i++) { renderbatches[i].firstFace = reader.model.skins[0].submeshes[i].startTriangle; renderbatches[i].numFaces = reader.model.skins[0].submeshes[i].nTriangles; for (int tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++) { if (reader.model.skins[0].textureunit[tu].submeshIndex == i) { renderbatches[i].materialID = reader.model.skins[0].textureunit[tu].texture; } } } m2.indices = indices; m2.vertices = vertices; m2.materials = materials; m2.renderBatches = renderbatches; }
public static void exportWMO(string file, BackgroundWorker exportworker = null) { if(exportworker == null) { exportworker = new BackgroundWorker(); } Console.WriteLine("Loading WMO file.."); exportworker.ReportProgress(5, "Reading WMO.."); var outdir = ConfigurationManager.AppSettings["outdir"]; WMOReader reader = new WMOReader(); reader.LoadWMO(file); // TODO: Support doodads! for (int i = 0; i < reader.wmofile.doodadNames.Count(); i++) { //Console.WriteLine(reader.wmofile.doodadNames[i].filename); //reader.wmofile.doodadDefinitions[i]. //reader.wmofile.doodadDefinitions[i]. } exportworker.ReportProgress(30, "Reading WMO.."); uint totalVertices = 0; var groups = new Structs.WMOGroup[reader.wmofile.group.Count()]; for (int g = 0; g < reader.wmofile.group.Count(); g++) { if (reader.wmofile.group[g].mogp.vertices == null) { continue; } for (int i = 0; i < reader.wmofile.groupNames.Count(); i++) { if (reader.wmofile.group[g].mogp.nameOffset == reader.wmofile.groupNames[i].offset) { groups[g].name = reader.wmofile.groupNames[i].name.Replace(" ", "_"); } } if (groups[g].name == "antiportal") { continue; } groups[g].verticeOffset = totalVertices; groups[g].vertices = new Structs.Vertex[reader.wmofile.group[g].mogp.vertices.Count()]; for (int i = 0; i < reader.wmofile.group[g].mogp.vertices.Count(); i++) { groups[g].vertices[i].Position = new Vector3(reader.wmofile.group[g].mogp.vertices[i].vector.X * -1, reader.wmofile.group[g].mogp.vertices[i].vector.Z, reader.wmofile.group[g].mogp.vertices[i].vector.Y); groups[g].vertices[i].Normal = new Vector3(reader.wmofile.group[g].mogp.normals[i].normal.X, reader.wmofile.group[g].mogp.normals[i].normal.Z, reader.wmofile.group[g].mogp.normals[i].normal.Y); groups[g].vertices[i].TexCoord = new Vector2(reader.wmofile.group[g].mogp.textureCoords[0][i].X, reader.wmofile.group[g].mogp.textureCoords[0][i].Y); totalVertices++; } var indicelist = new List<uint>(); for (int i = 0; i < reader.wmofile.group[g].mogp.indices.Count(); i++) { indicelist.Add(reader.wmofile.group[g].mogp.indices[i].indice); } groups[g].indices = indicelist.ToArray(); } exportworker.ReportProgress(55, "Exporting textures.."); // Create output directory if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file)))) { Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file))); } var mtlsb = new StringBuilder(); var textureID = 0; var materials = new Structs.Material[reader.wmofile.materials.Count()]; for (int i = 0; i < reader.wmofile.materials.Count(); i++) { for (int ti = 0; ti < reader.wmofile.textures.Count(); ti++) { if (reader.wmofile.textures[ti].startOffset == reader.wmofile.materials[i].texture1) { //materials[i].textureID = BLPLoader.LoadTexture(reader.wmofile.textures[ti].filename, cache); materials[i].textureID = textureID + i; materials[i].filename = Path.GetFileNameWithoutExtension(reader.wmofile.textures[ti].filename); if (reader.wmofile.materials[i].blendMode == 0) { materials[i].transparent = false; } else { materials[i].transparent = true; } var blpreader = new BLPReader(); blpreader.LoadBLP(reader.wmofile.textures[ti].filename); try { blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file), materials[i].filename + ".png")); } catch (Exception e) { Console.WriteLine(e.Message); } textureID++; } } } //No idea how MTL files really work yet. Needs more investigation. foreach (var material in materials) { mtlsb.Append("newmtl " + material.filename + "\n"); mtlsb.Append("Ns 96.078431\n"); mtlsb.Append("Ka 1.000000 1.000000 1.000000\n"); mtlsb.Append("Kd 0.640000 0.640000 0.640000\n"); mtlsb.Append("Ks 0.000000 0.000000 0.000000\n"); mtlsb.Append("Ke 0.000000 0.000000 0.000000\n"); mtlsb.Append("Ni 1.000000\n"); mtlsb.Append("d 1.000000\n"); mtlsb.Append("illum 2\n"); mtlsb.Append("map_Kd " + material.filename + ".png\n"); if (material.transparent) { mtlsb.Append("map_d " + material.filename + ".png\n"); } } File.WriteAllText(Path.Combine(outdir, file.Replace(".wmo", ".mtl")), mtlsb.ToString()); exportworker.ReportProgress(75, "Exporting model.."); int numRenderbatches = 0; //Get total amount of render batches for (int i = 0; i < reader.wmofile.group.Count(); i++) { if (reader.wmofile.group[i].mogp.renderBatches == null) { continue; } numRenderbatches = numRenderbatches + reader.wmofile.group[i].mogp.renderBatches.Count(); } int rb = 0; for (int g = 0; g < reader.wmofile.group.Count(); g++) { groups[g].renderBatches = new Structs.RenderBatch[numRenderbatches]; var group = reader.wmofile.group[g]; if (group.mogp.renderBatches == null) { continue; } for (int i = 0; i < group.mogp.renderBatches.Count(); i++) { var batch = group.mogp.renderBatches[i]; groups[g].renderBatches[rb].firstFace = batch.firstFace; groups[g].renderBatches[rb].numFaces = batch.numFaces; if (batch.flags == 2) { groups[g].renderBatches[rb].materialID = (uint)batch.possibleBox2_3; } else { groups[g].renderBatches[rb].materialID = batch.materialID; } groups[g].renderBatches[rb].blendType = reader.wmofile.materials[batch.materialID].blendMode; groups[g].renderBatches[rb].groupID = (uint)g; rb++; } } exportworker.ReportProgress(95, "Writing files.."); var objsw = new StreamWriter(Path.Combine(outdir, file.Replace(".wmo", ".obj"))); objsw.WriteLine("# Written by Marlamin's WoW OBJExporter. Original file: " + file); objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(file) + ".mtl"); foreach (var group in groups) { if (group.vertices == null) { continue; } objsw.WriteLine("g " + group.name); foreach (var vertex in group.vertices) { objsw.WriteLine("v " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Position.Z); objsw.WriteLine("vt " + vertex.TexCoord.X + " " + -vertex.TexCoord.Y); objsw.WriteLine("vn " + vertex.Normal.X + " " + vertex.Normal.Y + " " + vertex.Normal.Z); } var indices = group.indices; foreach (var renderbatch in group.renderBatches) { var i = renderbatch.firstFace; if (renderbatch.numFaces > 0) { objsw.WriteLine("usemtl " + materials[renderbatch.materialID].filename); objsw.WriteLine("s 1"); while (i < (renderbatch.firstFace + renderbatch.numFaces)) { objsw.WriteLine("f " + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + " " + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + " " + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1)); i = i + 3; } } } } objsw.Close(); Console.WriteLine("Done loading WMO file!"); }
public Render() { using (var dg = new DisposeGroup()) { //Load Shaders var pVSBlob = dg.Add(ShaderBytecode.CompileFromFile("RenderWithCam.fx", "VS", "vs_4_0")); var inputSignature = dg.Add(ShaderSignature.GetInputSignature(pVSBlob)); m_pVertexShader = new VertexShader(Device, pVSBlob); var pPSBlob = dg.Add(ShaderBytecode.CompileFromFile("RenderWithCam.fx", "PS", "ps_4_0")); m_pPixelShader = new PixelShader(Device, pPSBlob); //Define layout var layout = dg.Add(new InputLayout(Device, inputSignature, new[]{ new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0) })); //Load model M2Reader reader = new M2Reader("Z:\\18566_full\\"); reader.LoadM2(@"World\ArtTest\Boxtest\xyz.m2"); //Load vertices List<float> verticelist = new List<float>(); for (int i = 0; i < reader.model.vertices.Count(); i++) { verticelist.Add(reader.model.vertices[i].position.X); verticelist.Add(reader.model.vertices[i].position.Z * -1); verticelist.Add(reader.model.vertices[i].position.Y); verticelist.Add(1.0f); verticelist.Add(reader.model.vertices[i].textureCoordX); verticelist.Add(reader.model.vertices[i].textureCoordY); } //Load indices List<ushort> indicelist = new List<ushort>(); for (int i = 0; i < reader.model.skins[0].triangles.Count(); i++) { indicelist.Add(reader.model.skins[0].triangles[i].pt1); indicelist.Add(reader.model.skins[0].triangles[i].pt2); indicelist.Add(reader.model.skins[0].triangles[i].pt3); } //Convert to array ushort[] indices = indicelist.ToArray(); float[] vertices = verticelist.ToArray(); //Set count for use in draw later on indicecount = indices.Count(); //Create buffers var vertexBuffer = dg.Add(Buffer.Create(Device, BindFlags.VertexBuffer, vertices)); var vertexBufferBinding = new VertexBufferBinding(vertexBuffer, Utilities.SizeOf<Vector4>() + Utilities.SizeOf<Vector2>(), 0); var indexBuffer = dg.Add(Buffer.Create(Device, BindFlags.IndexBuffer, indices)); Device.ImmediateContext.InputAssembler.InputLayout = (layout); Device.ImmediateContext.InputAssembler.SetVertexBuffers(0, vertexBufferBinding); Device.ImmediateContext.InputAssembler.SetIndexBuffer(indexBuffer, Format.R16_UInt, 0); Device.ImmediateContext.InputAssembler.PrimitiveTopology = (PrimitiveTopology.TriangleList); //Get texture, what a mess this could be much better var blp = new BLPReader("Z:\\18566_full\\"); if (File.Exists(Path.Combine("Z:\\18566_full\\", reader.model.filename.Replace("M2", "blp")))) { blp.LoadBLP(reader.model.filename.Replace("M2", "blp")); } else { if (reader.model.textures.Count() > 0) { blp.LoadBLP(reader.model.textures[0]); } else { throw new Exception("No forking textures, mate."); } } MemoryStream s = new MemoryStream(); blp.bmp.Save(s, System.Drawing.Imaging.ImageFormat.Png); s.Seek(0, SeekOrigin.Begin); Texture2D texture = Texture2D.FromMemory<Texture2D>(Device, s.ToArray()); var textureView = new ShaderResourceView(Device, texture); var sampler = new SamplerState(Device, new SamplerStateDescription() { Filter = Filter.MinMagMipLinear, AddressU = TextureAddressMode.Wrap, AddressV = TextureAddressMode.Wrap, AddressW = TextureAddressMode.Wrap, BorderColor = SharpDX.Color.Black, ComparisonFunction = Comparison.Never, MaximumAnisotropy = 16, MipLodBias = 0, MinimumLod = 0, MaximumLod = 16, }); Device.ImmediateContext.PixelShader.SetSampler(0, sampler); Device.ImmediateContext.PixelShader.SetShaderResource(0, textureView); //End of texture stuff, Set(ref m_pConstantBuffer, new ConstantBuffer<Projections>(Device)); Device.ImmediateContext.VertexShader.SetConstantBuffer(0, m_pConstantBuffer.Buffer); } //Make camera Camera = new FirstPersonCamera(); Camera.SetProjParams((float)Math.PI / 2, 1, 0.01f, 100.0f); Camera.SetViewParams(new Vector3(0.0f, 0.0f, -5.0f), new Vector3(0.0f, 1.0f, 0.0f)); }
public void LoadWMO() { WMOReader reader = new WMOReader(basedir); reader.LoadWMO(modelPath); WMOMaterial[] materials = new WMOMaterial[reader.wmofile.materials.Count()]; for (int i = 0; i < reader.wmofile.materials.Count(); i++) { for (int ti = 0; ti < reader.wmofile.textures.Count(); ti++) { if (reader.wmofile.textures[ti].startOffset == reader.wmofile.materials[i].texture1) { Texture2D texture; var blp = new BLPReader(basedir); blp.LoadBLP(reader.wmofile.textures[ti].filename); if (blp.bmp == null) { texture = Texture2D.FromFile<Texture2D>(device, "missingtexture.jpg"); } else { MemoryStream s = new MemoryStream(); blp.bmp.Save(s, System.Drawing.Imaging.ImageFormat.Png); s.Seek(0, SeekOrigin.Begin); texture = Texture2D.FromMemory<Texture2D>(device, s.ToArray()); s.Dispose(); } materials[i].materialID = (uint)i; materials[i].filename = reader.wmofile.textures[ti].filename; materials[i].texture = texture; } } } WoWWMOGroup[] groups = new WoWWMOGroup[reader.wmofile.header.nGroups]; for (int i = 0; i < reader.wmofile.header.nGroups; i++) { groups[i] = LoadGroupWMO(reader.wmofile.group[i]); } wmo.materials = materials; wmo.groups = groups; }
public static void exportADT(string file, BackgroundWorker exportworker = null) { if (exportworker == null) { exportworker = new BackgroundWorker(); } var outdir = ConfigurationManager.AppSettings["outdir"]; float TileSize = 1600.0f / 3.0f; //533.333 float ChunkSize = TileSize / 16.0f; //33.333 float UnitSize = ChunkSize / 8.0f; //4.166666 // ~~fun fact time with marlamin~~ this /2 ends up being pixelspercoord on minimap float MapMidPoint = 32.0f / ChunkSize; var mapname = file.Replace("world\\maps\\", "").Substring(0, file.Replace("world\\maps\\", "").IndexOf("\\")); var coord = file.Replace("world\\maps\\" + mapname + "\\" + mapname, "").Replace(".adt", "").Split('_'); var centerx = int.Parse(coord[1]); var centery = int.Parse(coord[2]); List<Structs.RenderBatch> renderBatches = new List<Structs.RenderBatch>(); List<Structs.Vertex> verticelist = new List<Structs.Vertex>(); List<int> indicelist = new List<Int32>(); Dictionary<int, string> materials = new Dictionary<int, string>(); var distance = 1; // Create output directory if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file)))) { Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file))); } for (int y = centery; y < centery + distance; y++) { for (int x = centerx; x < centerx + distance; x++) { var curfile = "world\\maps\\" + mapname + "\\" + mapname + "_" + x + "_" + y + ".adt"; if (!CASC.FileExists(file)) { Console.WriteLine("File " + file + " does not exist"); continue; } exportworker.ReportProgress(0, "Loading ADT " + curfile); ADTReader reader = new ADTReader(); reader.LoadADT(curfile); // No chunks? Let's get the hell out of here if (reader.adtfile.chunks == null) { continue; } if (CASC.FileExists("world\\maptextures\\" + mapname + "\\" + mapname + "_" + y + "_" + x + ".blp")) { materials.Add(materials.Count() + 1, "mat" + y.ToString() + x.ToString()); var blpreader = new BLPReader(); blpreader.LoadBLP(curfile.Replace("maps", "maptextures").Replace(".adt", ".blp")); try { blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file), "mat" + y.ToString() + x.ToString() + ".png")); } catch (Exception e) { Console.WriteLine(e.Message); } } //List<Material> materials = new List<Material>(); //for (int ti = 0; ti < reader.adtfile.textures.filenames.Count(); ti++) //{ // Material material = new Material(); // material.filename = reader.adtfile.textures.filenames[ti]; // //if (!WoWFormatLib.Utils.CASC.FileExists(material.filename)) { continue; } // material.textureID = BLPLoader.LoadTexture(reader.adtfile.textures.filenames[ti], cache); // materials.Add(material); //} var initialChunkY = reader.adtfile.chunks[0].header.position.Y; var initialChunkX = reader.adtfile.chunks[0].header.position.X; for (uint c = 0; c < reader.adtfile.chunks.Count(); c++) { var chunk = reader.adtfile.chunks[c]; int off = verticelist.Count(); Structs.RenderBatch batch = new Structs.RenderBatch(); for (int i = 0, idx = 0; i < 17; i++) { for (int j = 0; j < (((i % 2) != 0) ? 8 : 9); j++) { Structs.Vertex v = new Structs.Vertex(); v.Normal = new OpenTK.Vector3(chunk.normals.normal_2[idx] / 127f, chunk.normals.normal_0[idx] / 127f, chunk.normals.normal_1[idx] / 127f); v.Position = new OpenTK.Vector3(chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z, chunk.header.position.X - (i * UnitSize * 0.5f)); if ((i % 2) != 0) v.Position.X -= 0.5f * UnitSize; v.TexCoord = new Vector2(-(v.Position.X - initialChunkX) / TileSize, -(v.Position.Z - initialChunkY) / TileSize); verticelist.Add(v); } } batch.firstFace = (uint)indicelist.Count(); for (int j = 9; j < 145; j++) { indicelist.AddRange(new Int32[] { off + j + 8, off + j - 9, off + j }); indicelist.AddRange(new Int32[] { off + j - 9, off + j - 8, off + j }); indicelist.AddRange(new Int32[] { off + j - 8, off + j + 9, off + j }); indicelist.AddRange(new Int32[] { off + j + 9, off + j + 8, off + j }); if ((j + 1) % (9 + 8) == 0) j += 9; } batch.materialID = (uint)materials.Count(); batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace; //var layermats = new List<uint>(); //var alphalayermats = new List<int>(); //for (int li = 0; li < reader.adtfile.texChunks[c].layers.Count(); li++) //{ // if (reader.adtfile.texChunks[c].alphaLayer != null) // { // alphalayermats.Add(BLPLoader.GenerateAlphaTexture(reader.adtfile.texChunks[c].alphaLayer[li].layer)); // } // layermats.Add((uint)cache.materials[reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[li].textureId].ToLower()]); //} //batch.materialID = layermats.ToArray(); //batch.alphaMaterialID = alphalayermats.ToArray(); renderBatches.Add(batch); } } } var mtlsw = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl")); //No idea how MTL files really work yet. Needs more investigation. foreach (var material in materials) { mtlsw.WriteLine("newmtl " + material.Value); mtlsw.WriteLine("Ka 1.000000 1.000000 1.000000"); mtlsw.WriteLine("Kd 0.640000 0.640000 0.640000"); mtlsw.WriteLine("map_Ka " + material.Value + ".png"); mtlsw.WriteLine("map_Kd " + material.Value + ".png"); } mtlsw.Close(); var indices = indicelist.ToArray(); var adtname = Path.GetFileNameWithoutExtension(file); var objsw = new StreamWriter(Path.Combine(outdir, file.Replace(".adt", ".obj"))); objsw.WriteLine("# Written by Marlamin's WoW OBJExporter. Original file: " + file); objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl"); objsw.WriteLine("g " + adtname); foreach (var vertex in verticelist) { objsw.WriteLine("v " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Position.Z); objsw.WriteLine("vt " + vertex.TexCoord.X + " " + -vertex.TexCoord.Y); objsw.WriteLine("vn " + vertex.Normal.X + " " + vertex.Normal.Y + " " + vertex.Normal.Z); } foreach (var renderBatch in renderBatches) { var i = renderBatch.firstFace; if (materials.ContainsKey((int)renderBatch.materialID)) { objsw.WriteLine("usemtl " + materials[(int)renderBatch.materialID]); objsw.WriteLine("s 1"); } while (i < (renderBatch.firstFace + renderBatch.numFaces)) { objsw.WriteLine("f " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1)); i = i + 3; } } objsw.Close(); }
private Bitmap CompileGroup(string wmoname, string groupid) { Console.WriteLine(" group " + groupid); int min_x = 64; int min_y = 64; int max_x = 0; int max_y = 0; int x = 0; int y = 0; string wmoonlyname = Path.GetFileNameWithoutExtension(wmoname); string wmodir = Path.GetDirectoryName(wmoname).Replace("World\\", "World\\Minimaps\\"); List<string> filePaths = new List<string>(); string lastpath = ""; for (int cur_x = 0; cur_x < 64; cur_x++) { for (int cur_y = 0; cur_y < 64; cur_y++) { string wmogroupfilename = wmodir + "\\" + wmoonlyname + "_" + groupid + "_" + cur_x.ToString().PadLeft(2, '0') + "_" + cur_y.ToString().PadLeft(2, '0') + ".blp"; //wmogroupfilename = wmogroupfilename.Replace("\\", "\\\\"); if (wmogroupfilename.Contains("000_00_00")) { Console.WriteLine("CHECKING " + wmogroupfilename); } if (CASC.FileExists(wmogroupfilename)) { Console.WriteLine(wmogroupfilename + " exists!"); filePaths.Add(wmogroupfilename); } } } foreach (string path in filePaths) { Console.WriteLine(path); x = int.Parse(path.Substring(path.Length - 9, 2)); y = int.Parse(path.Substring(path.Length - 6, 2)); if (x > max_x) { max_x = x; } if (y > max_y) { max_y = y; } if (x < min_x) { min_x = x; } if (y < min_y) { min_y = y; } // Console.WriteLine("[" + groupid + "] MIN: " + min_x + " " + min_y); // Console.WriteLine("[" + groupid + "] MAX: " + max_x + " " + max_y); lastpath = path; } var res_x = 0; var res_y = 0; if (min_x == 0 && max_x == 0 && min_y == 0 && max_y == 0) { var blpreader = new BLPReader(); blpreader.LoadBLP(lastpath); res_x = blpreader.bmp.Width; res_y = blpreader.bmp.Height; } else { res_x = (((max_x - min_x) * 256) + 256); res_y = (((max_y - min_y) * 256) + 256); } //Console.WriteLine("[" + groupid + "] " + "Creating new image of " + res_x + "x" + res_y + " for " + wmoname); if (res_x < 0) { res_x = 1; } if (res_y < 0) { res_y = 1; } Bitmap bmp = new Bitmap(res_x, res_y); Graphics g = Graphics.FromImage(bmp); foreach (string path in filePaths) { x = int.Parse(path.Substring(path.Length - 9, 2)); y = int.Parse(path.Substring(path.Length - 6, 2)); var blpreader = new BLPReader(); blpreader.LoadBLP(path); // Console.WriteLine("BLP Width: " + blpreader.bmp.Width); // Console.WriteLine("BLP Height: " + blpreader.bmp.Height); var draw_x = (x - min_x) * 256; var draw_y = (max_y - (y - min_y)) * 256; //Console.WriteLine("Drawing tile at " + draw_x + " & " + draw_y); g.DrawImage(blpreader.bmp, draw_x, draw_y, new Rectangle(0, 0, blpreader.bmp.Width, blpreader.bmp.Height), GraphicsUnit.Pixel); } g.Dispose(); return bmp; }
public static void exportM2(string file, BackgroundWorker exportworker = null) { if (exportworker == null) { exportworker = new BackgroundWorker(); } var outdir = ConfigurationManager.AppSettings["outdir"]; var reader = new M2Reader(); exportworker.ReportProgress(15, "Reading M2.."); if (!CASC.FileExists(file)) { throw new Exception("404 M2 not found!"); } reader.LoadM2(file); Structs.Vertex[] vertices = new Structs.Vertex[reader.model.vertices.Count()]; for (int i = 0; i < reader.model.vertices.Count(); i++) { vertices[i].Position = new OpenTK.Vector3(reader.model.vertices[i].position.X, reader.model.vertices[i].position.Z, reader.model.vertices[i].position.Y * -1); vertices[i].Normal = new OpenTK.Vector3(reader.model.vertices[i].normal.X, reader.model.vertices[i].normal.Z, reader.model.vertices[i].normal.Y); vertices[i].TexCoord = new Vector2(reader.model.vertices[i].textureCoordX, reader.model.vertices[i].textureCoordY); } // Create output directory if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file)))) { Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file))); } var objsw = new StreamWriter(Path.Combine(outdir, file.Replace(".m2", ".obj"))); objsw.WriteLine("# Written by Marlamin's WoW OBJExporter. Original file: " + file); objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(file) + ".mtl"); foreach (var vertex in vertices) { objsw.WriteLine("v " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Position.Z); objsw.WriteLine("vt " + vertex.TexCoord.X + " " + -vertex.TexCoord.Y); objsw.WriteLine("vn " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Normal.Z); } List<uint> indicelist = new List<uint>(); for (int i = 0; i < reader.model.skins[0].triangles.Count(); i++) { var t = reader.model.skins[0].triangles[i]; indicelist.Add(t.pt1); indicelist.Add(t.pt2); indicelist.Add(t.pt3); } var indices = indicelist.ToArray(); exportworker.ReportProgress(35, "Writing files.."); var renderbatches = new Structs.RenderBatch[reader.model.skins[0].submeshes.Count()]; for (int i = 0; i < reader.model.skins[0].submeshes.Count(); i++) { if (file.StartsWith("character", StringComparison.CurrentCultureIgnoreCase)) { if (reader.model.skins[0].submeshes[i].submeshID != 0) { if (!reader.model.skins[0].submeshes[i].submeshID.ToString().EndsWith("01")) { continue; } } } renderbatches[i].firstFace = reader.model.skins[0].submeshes[i].startTriangle; renderbatches[i].numFaces = reader.model.skins[0].submeshes[i].nTriangles; renderbatches[i].groupID = (uint)i; for (int tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++) { if (reader.model.skins[0].textureunit[tu].submeshIndex == i) { renderbatches[i].blendType = reader.model.renderflags[reader.model.skins[0].textureunit[tu].renderFlags].blendingMode; renderbatches[i].materialID = reader.model.texlookup[reader.model.skins[0].textureunit[tu].texture].textureID; } } } exportworker.ReportProgress(65, "Exporting textures.."); var mtlsb = new StreamWriter(Path.Combine(outdir, file.Replace(".m2", ".mtl"))); var textureID = 0; var materials = new Structs.Material[reader.model.textures.Count()]; for (int i = 0; i < reader.model.textures.Count(); i++) { string texturefilename = "Dungeons\\Textures\\testing\\COLOR_13.blp"; materials[i].flags = reader.model.textures[i].flags; switch (reader.model.textures[i].type) { case 0: //Console.WriteLine(" Texture given in file!"); texturefilename = reader.model.textures[i].filename; break; case 1: string[] csfilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(file, (int)reader.model.textures[i].type, i); if (csfilenames.Count() > 0) { texturefilename = csfilenames[0]; } else { //Console.WriteLine(" No type 1 texture found, falling back to placeholder texture"); } break; case 2: if (WoWFormatLib.Utils.CASC.FileExists(Path.ChangeExtension(file, ".blp"))) { //Console.WriteLine(" BLP exists!"); texturefilename = Path.ChangeExtension(file, ".blp"); } else { //Console.WriteLine(" Type 2 does not exist!"); //needs lookup? } break; case 11: string[] cdifilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(file, (int)reader.model.textures[i].type); for (int ti = 0; ti < cdifilenames.Count(); ti++) { if (WoWFormatLib.Utils.CASC.FileExists(file.Replace(reader.model.name + ".M2", cdifilenames[ti] + ".blp"))) { texturefilename = file.Replace(reader.model.name + ".M2", cdifilenames[ti] + ".blp"); } } break; default: // Console.WriteLine(" Falling back to placeholder texture"); break; } //Console.WriteLine(" Eventual filename is " + texturefilename); materials[i].textureID = textureID + i; materials[i].filename = Path.GetFileNameWithoutExtension(texturefilename); var blpreader = new BLPReader(); blpreader.LoadBLP(texturefilename); try { blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file), materials[i].filename + ".png")); } catch (Exception e) { Console.WriteLine(e.Message); } } exportworker.ReportProgress(85, "Writing files.."); foreach (var material in materials) { mtlsb.WriteLine("newmtl " + material.filename); mtlsb.WriteLine("illum 2"); mtlsb.WriteLine("map_Ka " + material.filename + ".png"); mtlsb.WriteLine("map_Kd " + material.filename + ".png"); } mtlsb.Close(); objsw.WriteLine("g " + Path.GetFileNameWithoutExtension(file)); foreach (var renderbatch in renderbatches) { var i = renderbatch.firstFace; objsw.WriteLine("o " + Path.GetFileNameWithoutExtension(file) + renderbatch.groupID); objsw.WriteLine("usemtl " + materials[renderbatch.materialID].filename); objsw.WriteLine("s 1"); while (i < (renderbatch.firstFace + renderbatch.numFaces)) { objsw.WriteLine("f " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1)); i = i + 3; } } objsw.Close(); // https://en.wikipedia.org/wiki/Wavefront_.obj_file#Basic_materials // http://wiki.unity3d.com/index.php?title=ExportOBJ // http://web.cse.ohio-state.edu/~hwshen/581/Site/Lab3_files/Labhelp_Obj_parser.htm Console.WriteLine("Done loading model!"); }
private static void Main(string[] args) { string mapname = ""; string basedir = ConfigurationManager.AppSettings["basedir"]; bool buildmaps = Boolean.Parse(ConfigurationManager.AppSettings["buildmaps"]); bool buildWMOmaps = Boolean.Parse(ConfigurationManager.AppSettings["buildwmomaps"]); Console.WriteLine("Initializing CASC.."); if(basedir != String.Empty){ CASC.InitCasc(null, basedir); }else{ CASC.InitCasc(null, @"D:\Games\World of Warcraft Public Test", "wow_beta"); // Use beta for now } Console.WriteLine("CASC initialized!"); Console.WriteLine("Current patch: " + CASC.cascHandler.Config.BuildName); if (buildmaps == true) { DBCReader<MapRecord> reader = new DBCReader<MapRecord>("DBFilesClient\\Map.dbc"); for (int i = 0; i < reader.recordCount; i++) { //I used to check if WDT existed, but sometimes minimaps for maps without WDTs slip through the cracks mapname = reader[i].Directory; if (reader[i].expansionID < 6) { Console.WriteLine("Skipping map " + mapname + " WoD and below!"); continue; } var min_x = 64; var min_y = 64; var max_x = 0; var max_y = 0; for (int cur_x = 0; cur_x < 64; cur_x++) { for (int cur_y = 0; cur_y < 64; cur_y++) { if (CASC.FileExists("World\\Minimaps\\" + mapname + "\\map" + cur_x + "_" + cur_y + ".blp")) { if (cur_x > max_x) { max_x = cur_x; } if (cur_y > max_y) { max_y = cur_y; } if (cur_x < min_x) { min_x = cur_x; } if (cur_y < min_y) { min_y = cur_y; } } } } Console.WriteLine("[" + mapname + "] MIN: (" + min_x + " " + min_y + ") MAX: (" + max_x + " " + max_y + ")"); var res_x = (((max_x - min_x) * 256) + 256); var res_y = (((max_y - min_y) * 256) + 256); if (res_x < 0 || res_y < 0) { Console.WriteLine("[" + mapname + "] " + "Skipping map, has no minimap tiles"); continue; } Console.WriteLine("[" + mapname + "] " + "Creating new image of " + res_x + "x" + res_y); Bitmap bmp = new Bitmap(res_x, res_y); Graphics g = Graphics.FromImage(bmp); Font drawFont = new Font("Arial", 16); for (int cur_x = 0; cur_x < 64; cur_x++) { for (int cur_y = 0; cur_y < 64; cur_y++) { if (CASC.FileExists("World\\Minimaps\\" + mapname + "\\map" + cur_x + "_" + cur_y + ".blp")) { var blpreader = new BLPReader(); blpreader.LoadBLP("World\\Minimaps\\" + mapname + "\\map" + cur_x + "_" + cur_y + ".blp"); g.DrawImage(blpreader.bmp, (cur_x - min_x) * 256, (cur_y - min_y) * 256, new Rectangle(0, 0, 256, 256), GraphicsUnit.Pixel); } } } g.Dispose(); if (!Directory.Exists("done")) { Directory.CreateDirectory("done"); } bmp.Save("done/" + mapname + ".png"); // SUPER MINIMAP COMPILER TIME!!!!!!!!!!!!!!! var super_res_x = (((max_x - min_x) * 512) + 512); var super_res_y = (((max_y - min_y) * 512) + 512); if (super_res_x < 0 || super_res_y < 0) { Console.WriteLine("[SUPER " + mapname + "] " + "Skipping map, has no minimap tiles"); continue; } Console.WriteLine("[SUPER " + mapname + "] " + "Creating new image of " + super_res_x + "x" + super_res_y); Bitmap super_bmp = new Bitmap(super_res_x, super_res_y); Graphics super_g = Graphics.FromImage(super_bmp); for (int cur_x = 0; cur_x < 64; cur_x++) { for (int cur_y = 0; cur_y < 64; cur_y++) { if (CASC.FileExists("World\\Minimaps\\" + mapname + "\\map" + cur_x + "_" + cur_y + ".blp")) { var blpreader = new BLPReader(); blpreader.LoadBLP("World\\Minimaps\\" + mapname + "\\map" + cur_x + "_" + cur_y + ".blp"); super_g.DrawImage(blpreader.bmp, (cur_x - min_x) * 512, (cur_y - min_y) * 512, new Rectangle(0, 0, 512, 512), GraphicsUnit.Pixel); } } } super_g.Dispose(); if (!Directory.Exists("done")) { Directory.CreateDirectory("done"); } super_bmp.Save("done/SUPER_" + mapname + ".png"); } } if (buildWMOmaps == true) { //List<string> listfile = CASC.GenerateListfile(); var listfile = File.ReadAllLines(@"listfile.txt"); DBCReader<MapRecord> reader = new DBCReader<MapRecord>("DBFilesClient\\Map.dbc"); string[] unwantedExtensions = new string[513]; for (int i = 0; i < 512; i++) { unwantedExtensions[i] = "_" + i.ToString().PadLeft(3, '0') + ".wmo"; } unwantedExtensions[512] = "LOD1.wmo"; foreach (string s in listfile) { if (!unwantedExtensions.Contains(s.Substring(s.Length - 8, 8))) { if (!s.Contains("LOD") && s.EndsWith(".wmo", StringComparison.CurrentCultureIgnoreCase)) { Console.WriteLine(s); WMO wmocompiler = new WMO(); wmocompiler.Compile(s); } } } Console.ReadLine(); } }
protected override void OnLoad(EventArgs e) { // Get OpenGL version Console.WriteLine("OpenGL version: " + GL.GetString(StringName.Version)); Console.WriteLine("OpenGL vendor: " + GL.GetString(StringName.Vendor)); this.CursorVisible = false; // Set up camera ActiveCamera = new OldCamera(Width, Height, new Vector3(0, 0, -1), new Vector3(0, 0, 1), Vector3.UnitY); // Vertex Attribute Object vertexAttribObject = GL.GenVertexArray(); GL.BindVertexArray(vertexAttribObject); // Vertices float[] vertices = new float[] { -1.0f, -1.0f, -10f, 0.0f, 0.0f, // Top-left 1.0f, -1.0f, -10f, 1.0f, 0.0f, // Top-right 1.0f, 1.0f, -10f, 1.0f, 1.0f, // Bottom-right -1.0f, 1.0f, -10f, 0.0f, 1.0f // Bottom-left }; vertexBuffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer); GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (vertices.Count() * sizeof(float)), vertices, BufferUsageHint.StaticDraw); int verticeBufferSize = 0; GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer); GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out verticeBufferSize); Console.WriteLine("Vertices in buffer: " + verticeBufferSize / 5 / sizeof(float)); // Elements int[] elements = new int[] { 0, 1, 2, 2, 3, 0 }; elementBuffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, elementBuffer); GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(elements.Count() * sizeof(int)), elements, BufferUsageHint.StaticDraw); // Vertex shader vertexShader = GL.CreateShader(ShaderType.VertexShader); string vertexSource = File.ReadAllText("Shaders/vertex.shader"); Console.WriteLine(vertexSource); GL.ShaderSource(vertexShader, vertexSource); GL.CompileShader(vertexShader); int vertexShaderStatus; GL.GetShader(vertexShader, ShaderParameter.CompileStatus, out vertexShaderStatus); Console.WriteLine("[VERTEX] Shader compile status: " + vertexShaderStatus); string vertexShaderLog; GL.GetShaderInfoLog(vertexShader, out vertexShaderLog); Console.Write(vertexShaderLog); // Fragment shader fragmentShader = GL.CreateShader(ShaderType.FragmentShader); string fragmentSource = File.ReadAllText("Shaders/fragment.shader"); Console.WriteLine(fragmentSource); GL.ShaderSource(fragmentShader, fragmentSource); GL.CompileShader(fragmentShader); int fragmentShaderStatus; GL.GetShader(fragmentShader, ShaderParameter.CompileStatus, out fragmentShaderStatus); Console.WriteLine("[FRAGMENT] Shader compile status: " + fragmentShaderStatus); string fragmentShaderLog; GL.GetShaderInfoLog(fragmentShader, out fragmentShaderLog); Console.Write(fragmentShaderLog); // Shader program shaderProgram = GL.CreateProgram(); GL.AttachShader(shaderProgram, vertexShader); GL.AttachShader(shaderProgram, fragmentShader); GL.BindFragDataLocation(shaderProgram, 0, "outColor"); GL.LinkProgram(shaderProgram); string programInfoLog = GL.GetProgramInfoLog(shaderProgram); Console.Write(programInfoLog); int programStatus; GL.GetProgram(shaderProgram, GetProgramParameterName.LinkStatus, out programStatus); Console.WriteLine("[FRAGMENT] Program link status: " + programStatus); GL.UseProgram(shaderProgram); GL.ValidateProgram(shaderProgram); GL.DetachShader(shaderProgram, vertexShader); GL.DeleteShader(vertexShader); GL.DetachShader(shaderProgram, fragmentShader); GL.DeleteShader(fragmentShader); // Set up matrix ActiveCamera.setupGLRenderMatrix(shaderProgram); // Shader settings int posAttrib = GL.GetAttribLocation(shaderProgram, "position"); GL.EnableVertexAttribArray(posAttrib); GL.VertexAttribPointer(posAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 5, 0); int texCoordAttrib = GL.GetAttribLocation(shaderProgram, "texCoord"); GL.EnableVertexAttribArray(texCoordAttrib); GL.VertexAttribPointer(texCoordAttrib, 2, VertexAttribPointerType.Float, false, sizeof(float) * 5, sizeof(float) * 3); // Clear GL.ClearColor(Color.Black); // Uniforms int uniColor = GL.GetUniformLocation(shaderProgram, "triangleColor"); Vector3 uniCol3 = new Vector3(1.0f, 0.0f, 0.0f); GL.Uniform3(uniColor, uniCol3); // Textures int[] textureIds = new int[2]; GL.GenTextures(2, textureIds); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, textureIds[0]); var blp = new BLPReader(); blp.LoadBLP(File.OpenRead(@"Z:\WoW extracts\20363_full\Textures\ShaneCube.blp")); System.Drawing.Imaging.BitmapData bmp_data = blp.bmp.LockBits(new System.Drawing.Rectangle(0, 0, blp.bmp.Width, blp.bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp_data.Width, bmp_data.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); blp.bmp.UnlockBits(bmp_data); GL.Uniform1(GL.GetUniformLocation(shaderProgram, "tex"), 0); GL.ActiveTexture(TextureUnit.Texture1); GL.BindTexture(TextureTarget.Texture2D, textureIds[1]); }