public static void TestDDS() { Image gradient = gradientImage(); DDS.DDS dds = gradient; if (dds.width != (uint)(Math.Ceiling(gradient.width / 4f) * 4)) { Console.WriteLine("DDS file has an incorrent width!"); } if (dds.height != (uint)(Math.Ceiling(gradient.height / 4f) * 4)) { Console.WriteLine("DDS file has an incorrent height!"); } Image image2 = dds; Image.Color color0 = image2[5, 4]; Image.Color color1 = gradient[5, 4]; if (!color0.Equals(color1)) { Console.WriteLine("Image -> DDS -> Image fails pixel data!"); } }
public static void TestDDS2() { Image image = null; DDS.DDS dss = null; BMP.BMP bmp = null; // Read BMP using (var fileStream = new FileStream("forest4.bmp", FileMode.Open)) { image = BMP.BMP.read(fileStream); fileStream.Close(); } // Write DDS File.Delete("forest4.dds"); using (var fileStream = new FileStream("forest4.dds", FileMode.OpenOrCreate)) { dss = image; dss.write(fileStream); fileStream.Close(); } // Read DDS using (var fileStream = new FileStream("forest4.dds", FileMode.OpenOrCreate)) { image = DDS.DDS.read(fileStream); fileStream.Close(); } // See what happened in a BMP File.Delete("forest5.bmp"); using (var fileStream = new FileStream("forest5.bmp", FileMode.OpenOrCreate)) { bmp = image; bmp.write(fileStream); fileStream.Close(); } }
private void ContextCreated(object sender, NativeWindowEventArgs e) { AttributeId[] attributes = null; _vao = new VertexArrayObject(true); { var texture = new TQTexture(File.ReadAllBytes("texture.tex")); _texture = new Texture(TextureTarget.Texture2d); _texture.Parameteri(TextureParameterName.TextureWrapS, TextureWrapMode.Repeat); _texture.Parameteri(TextureParameterName.TextureWrapT, TextureWrapMode.Repeat); _texture.Parameteri(TextureParameterName.TextureMinFilter, TextureMinFilter.Linear); _texture.Parameteri(TextureParameterName.TextureMagFilter, TextureMagFilter.Linear); foreach (var frame in texture) { var dds = new DDS.DDS(frame.Data); InternalFormat internalFormat; if (dds.Header.Capabilities.HasFlag(Capabilities.Complex)) { switch (dds.Header.PixelFormat.FourCC) { case "DXT5": internalFormat = InternalFormat.CompressedRgbaS3tcDxt5Ext; break; default: throw new NotImplementedException(); } } else { throw new NotImplementedException(); } _texture.Storage2D((int)dds.Header.MipmapCount, internalFormat, (int)dds.Header.Width, (int)dds.Header.Height); foreach (var layer in dds) { int level = 0; foreach (var mip in layer) { unsafe { fixed(byte *ptr = mip.Data) { _texture.CompressedSubImage2D( level++, internalFormat, xOffset: 0, yOffset: 0, width: (int)Math.Max(1, (dds.Header.Width * 2) >> level), height: (int)Math.Max(1, (dds.Header.Height * 2) >> level), data: mip.Data); Gl.CheckErrors(); } } } break; //TODO: Further layers. } break; //TODO: Further frames. } } var mesh = new Mesh.Mesh(File.ReadAllBytes("mesh.msh")); foreach (var part in mesh) { if (part.Is(out VertexBuffer vertexBuffer)) { Console.Write("Loading VBO..."); var vbo = new Buffer(true); vbo.BufferData(vertexBuffer.Buffer, BufferUsage.StaticDraw); _vao.VertexBuffer(0, vbo, IntPtr.Zero, vertexBuffer.Header.Stride); Console.Write(" OK!"); attributes = vertexBuffer.Attributes.ToArray(); Console.Write($" (also got {attributes.Length} attributes)"); _vertexCount = vertexBuffer.Header.VertexCount; Console.WriteLine($" (also got vertex count {_vertexCount})"); } else if (part.Is(out Shaders shaders)) { foreach (var shader in shaders) { { Console.Write($"Sort of loading {shader.FileName}..."); using (var vertexShader = new Shader(ShaderType.VertexShader, File.ReadAllText($"{shader.FileName}.vertex.glsl"))) using (var fragmentShader = new Shader(ShaderType.FragmentShader, File.ReadAllText($"{shader.FileName}.fragment.glsl"))) { _program = new ShaderProgram(vertexShader, fragmentShader); } _program.Link(); Console.WriteLine(" OK!"); } { Console.Write($"Setting up attibutes..."); var offset = 0u; foreach (var attribute in attributes) { switch (attribute) { case AttributeId.Position: SetUpAttribute(_vao, _program, "position", 3, VertexAttribType.Float, normalized: false, offset, bindingIndex: 0); break; case AttributeId.Normal: SetUpAttribute(_vao, _program, "normal", 3, VertexAttribType.Float, normalized: true, offset, bindingIndex: 0); break; case AttributeId.Tangent: SetUpAttribute(_vao, _program, "tangent", 3, VertexAttribType.Float, normalized: true, offset, bindingIndex: 0); break; case AttributeId.Bitangent: SetUpAttribute(_vao, _program, "bitangent", 3, VertexAttribType.Float, normalized: true, offset, bindingIndex: 0); break; case AttributeId.UV: SetUpAttribute(_vao, _program, "uv", 2, VertexAttribType.Float, normalized: false, offset, bindingIndex: 0); break; case AttributeId.Weights: SetUpAttribute(_vao, _program, "weights", 4, VertexAttribType.Float, normalized: false, offset, bindingIndex: 0); break; case AttributeId.Bones: SetUpAttribute(_vao, _program, "bones", 4, VertexAttribType.Byte, normalized: false, offset, bindingIndex: 0); break; case AttributeId.Bytes: SetUpAttribute(_vao, _program, "bytes", 4, VertexAttribType.UnsignedByte, normalized: false, offset, bindingIndex: 0); break; } offset += GetAttributeSize(attribute); } Console.WriteLine(" OK!"); } { Console.Write($"Setting up uniforms..."); if (_program.TryGetUniformLocation("transformation", out var transformationUniform)) { var matrix = new Matrix4x4( .5f, 0, 0, 0, 0, .5f, 0, 0, 0, 0, .5f, 0, 0, -.7f, 0, 1 ); _program.UniformMatrix4f(transformationUniform, transpose: false, in matrix); } else { throw new NotImplementedException(); } Console.WriteLine(" OK!"); } } } else if (part.Is(out IndexBuffer indexBuffer)) { Console.Write("Loading IBO..."); var ibo = new Buffer(true); ibo.BufferData(indexBuffer.TriangleIndices, BufferUsage.StaticDraw); _vao.ElementBuffer(ibo); Console.WriteLine(" OK!"); var drawRanges = new List <(int, int)>(); foreach (var drawCall in indexBuffer) { drawRanges.Add((drawCall.Common.StartFaceIndex, drawCall.Common.FaceCount)); } _drawRanges = drawRanges.ToArray(); } else if (part.Is(out Bones bones)) { _boneVao = new VertexArrayObject(true); Console.Write("Loading Bones..."); _boneMatrices = new Matrix4x4[bones.Count]; _bonePositions = new Vector3[bones.Count]; for (int i = 0; i < _boneMatrices.Length; i++) { _boneMatrices[i] = Matrix4x4.Identity; } foreach (var bone in bones) { var i = bone.Index; var position = new Vector4(bone.Position, 1); var bonePosition = Vector4.Transform(position, _boneMatrices[i]); _bonePositions[i] = new Vector3(bonePosition.X, bonePosition.Y, bonePosition.Z); var boneMatrix = new Matrix4x4( bone.Axes[0], bone.Axes[1], bone.Axes[2], 0, bone.Axes[3], bone.Axes[4], bone.Axes[5], 0, bone.Axes[6], bone.Axes[7], bone.Axes[8], 0, bone.Position.X, bone.Position.Y, bone.Position.Z, 1 ); _boneMatrices[i] = boneMatrix * _boneMatrices[i]; foreach (var childBone in bone) { _boneMatrices[childBone.Index] = _boneMatrices[i]; } } var boneVbo = new Buffer(true); Span <Vector3> boneVboData = (from p in _bonePositions select new Vector3(p.X / 2, p.Y / 2 - .7f, p.Z / 2)).ToArray().AsSpan(); _boneVao.VertexBuffer(0, boneVbo, IntPtr.Zero, 3 * sizeof(float)); Gl.CheckErrors(); boneVbo.BufferData(boneVboData, BufferUsage.StaticDraw); Gl.CheckErrors(); //TODO: LINQ it! var boneIbo = new Buffer(true); Gl.CheckErrors(); var boneIboEntries = new List <(int, int)>(); foreach (var parent in bones) { foreach (var child in parent) { boneIboEntries.Add((parent.Index, child.Index)); } } boneIbo.BufferData(boneIboEntries.SelectMany(x => new[] { (ushort)x.Item1, (ushort)x.Item2 }).ToArray().AsSpan(), BufferUsage.StaticDraw); _boneVao.ElementBuffer(boneIbo); Gl.CheckErrors(); _boneLinkCount = boneIboEntries.Count; using (var vertexShader = new Shader(ShaderType.VertexShader, File.ReadAllText("bones.vertex.glsl"))) using (var fragmentShader = new Shader(ShaderType.FragmentShader, File.ReadAllText("bones.fragment.glsl"))) { _boneProgram = new ShaderProgram(vertexShader, fragmentShader); } _boneProgram.Link(); Console.WriteLine(" OK!"); SetUpAttribute(_boneVao, _boneProgram, "position", 3, VertexAttribType.Float, normalized: false, relativeOffset: 0, bindingIndex: 0); Gl.CheckErrors(); } } }
public static void TestDDSBlock() { // R5G6B5 lossless color var color = new Image.Color(248, 252, 248); // Image with a single block Image image = new Image(4, 4, color); // Image -> DDS DDS.DDS dds = image; if (dds.horizontalBlocks != 1 || dds.verticalBlocks != 1) { Console.WriteLine("DDS file has an incorrent number of blocks!"); } if (!dds[0][0].Equals(color) || !dds[0][0].Equals(color)) { Console.WriteLine("DDS block has an incorrent color!"); } // Get serialized block struct DDS_DXT1Block structBlock = dds[0]; Image.Color color2 = structBlock.color0; if (!color2.Equals(color) || (structBlock.indices & 0x3) != 0) { Console.WriteLine("StructBlock contains incorrect colors!"); } // Set some colors to black and get the block again image[7] = Image.Color.Black; image[15] = Image.Color.Black; // image -> dds -> block -> struct block -> block dds = image; structBlock = dds[0]; DXT1Block block = structBlock; var color3 = block[0]; var color4 = block[7]; var color5 = block[15]; if (!color3.Equals(color) || !color4.Equals(Image.Color.Black) || !color5.Equals(Image.Color.Black)) { Console.WriteLine("DDS failed saving/restoring 2 colors!"); } // Let's save the file and see what happens File.Delete("block.dds"); using (var fileStream = new FileStream("block.dds", FileMode.OpenOrCreate)) { dds.write(fileStream); fileStream.Close(); } DDS.DDS dds2; using (var fileStream = new FileStream("block.dds", FileMode.OpenOrCreate)) { dds2 = DDS.DDS.read(fileStream); fileStream.Close(); } block = dds2[0]; color3 = block[0]; color4 = block[7]; color5 = block[15]; if (!color3.Equals(color) || !color4.Equals(Image.Color.Black) || !color5.Equals(Image.Color.Black)) { Console.WriteLine("DDS failed saving/restoring 2 colors!"); } }