예제 #1
0
            /// <summary>
            /// Create the texture, using this technique.
            /// </summary>
            /// <param name="ctx">
            /// A <see cref="GraphicsContext"/> used for allocating resources.
            /// </param>
            public override void Create(GraphicsContext ctx)
            {
                // Define storage
                InternalFormat internalFormat = _PixelFormat.ToInternalFormat();

                if (!IsImmutableSupported(ctx))
                {
                    PixelFormat format = _PixelFormat.ToDataFormat();

                    for (uint level = 0, w = _Width, h = _Height; level < _MipmapLevels; level++, w = Math.Max(1, w / 2), h = Math.Max(1, h / 2))
                    {
                        Gl.TexImage2D(_Target, (int)level, internalFormat, (int)w, (int)h, 0, format, /* Unused */ PixelType.UnsignedByte, IntPtr.Zero);

                        // Always check for errors
                        Gl.CheckErrors();
                    }
                }
                else
                {
                    Gl.TexStorage2D(_Target, (int)_MipmapLevels, internalFormat, (int)_Width, (int)_Height);

                    // Always check for errors
                    Gl.CheckErrors();
                }

                // Define mipmap array
                for (uint level = 0, w = _Width, h = _Height; level < _MipmapLevels; level++, w = Math.Max(1, w / 2), h = Math.Max(1, h / 2))
                {
                    _Texture2d.SetMipmap(_PixelFormat, w, h, 1, level);
                }
            }
예제 #2
0
            /// <summary>
            /// Update the reference Buffer, using this technique.
            /// </summary>
            /// <param name="ctx">
            /// A <see cref="GraphicsContext"/> used for allocating resources.
            /// </param>
            public override void Create(GraphicsContext ctx)
            {
                if (ctx.Extensions.DirectStateAccess_ARB || ctx.Version.IsCompatible(Gl.Version_450))
                {
                    if (!ctx.Extensions.BufferStorage_ARB || !Buffer.Immutable)
                    {
                        // Emulates glBufferStorage error checking (only for size)
                        if (Buffer.Immutable && Buffer.Size != 0)
                        {
                            throw new GlException(ErrorCode.InvalidOperation);
                        }

                        Gl.NamedBufferData(Buffer.ObjectName, _Size, _Array, Buffer.Hint);
                    }
                    else
                    {
                        if (Buffer.Immutable)
                        {
                            Gl.NamedBufferStorage(Buffer.ObjectName, _Size, _Array, Buffer.UsageMask);
                        }
                        else
                        {
                            Gl.NamedBufferData(Buffer.ObjectName, _Size, _Array, Buffer.Hint);
                        }
                    }
                }
                else
                {
                    if (!ctx.Extensions.BufferStorage_ARB || !Buffer.Immutable)
                    {
                        // Emulates glBufferStorage error checking (only for size)
                        if (Buffer.Immutable && Buffer.Size != 0)
                        {
                            throw new GlException(ErrorCode.InvalidOperation);
                        }

                        Gl.BufferData(Buffer.Target, _Size, _Array, Buffer.Hint);
                    }
                    else
                    {
                        if (Buffer.Immutable)
                        {
                            Gl.BufferStorage(Buffer.Target, _Size, _Array, Buffer.UsageMask);
                        }
                        else
                        {
                            Gl.BufferData(Buffer.Target, _Size, _Array, Buffer.Hint);
                        }
                    }
                }

                // Explictly check for errors
                Gl.CheckErrors();

                Buffer.Size = _Size;
            }
예제 #3
0
 public static void Check()
 {
     try
     {
         Gl.CheckErrors();
     }
     catch (Exception e)
     {
         StaticLogger.Logger.Error(e);
     }
 }
예제 #4
0
            /// <summary>
            /// Update the reference Buffer, using this technique.
            /// </summary>
            /// <param name="ctx">
            /// A <see cref="GraphicsContext"/> used for allocating resources.
            /// </param>
            public override void Create(GraphicsContext ctx)
            {
                if (ctx.Extensions.DirectStateAccess_ARB || ctx.Version.IsCompatible(Gl.Version_450))
                {
                    CreateDSA(ctx);
                }
                else
                {
                    CreateCompatible(ctx);
                }

                // Explictly check for errors
                Gl.CheckErrors();

                Buffer.Size = _Size;
            }
            /// <summary>
            /// Construct an UniformBlockBinding.
            /// </summary>
            /// <param name="program">
            /// The <see cref="ShaderProgram"/> defining this uniform block.
            /// </param>
            /// <param name="uniformBlockIndex">
            /// A <see cref="UInt32"/> that specifies the index used for identifying the uniform block.
            /// </param>
            public UniformBlockBinding(ShaderProgram program, uint uniformBlockIndex)
            {
                if (program == null)
                {
                    throw new ArgumentNullException("program");
                }

                int[] uniformBlockParams;

                // Index
                Index = uniformBlockIndex;

                // Name length
                int uniformBlockNameLength;

                uniformBlockParams = new int[1];
                Gl.GetActiveUniformBlock(program.ObjectName, Index, Gl.UNIFORM_BLOCK_NAME_LENGTH, uniformBlockParams);
                uniformBlockNameLength = uniformBlockParams[0];

                // Name
                StringBuilder uniformBlockNameBuffer = new StringBuilder(uniformBlockNameLength);
                int           nameLength;

                Gl.GetActiveUniformBlockName(program.ObjectName, Index, uniformBlockNameBuffer.Capacity, out nameLength, uniformBlockNameBuffer);
                Gl.CheckErrors();

                Name = uniformBlockNameBuffer.ToString();

                // Data size
                uniformBlockParams = new int[1];
                Gl.GetActiveUniformBlock(program.ObjectName, Index, Gl.UNIFORM_BLOCK_DATA_SIZE, uniformBlockParams);

                DataSize = (uint)uniformBlockParams[0];

                // Active uniforms
                uniformBlockParams = new int[1];
                Gl.GetActiveUniformBlock(program.ObjectName, Index, Gl.UNIFORM_BLOCK_ACTIVE_UNIFORMS, uniformBlockParams);

                ActiveUniforms = (uint)uniformBlockParams[0];

                // Uniform indices
                uniformBlockParams = new int[ActiveUniforms];
                Gl.GetActiveUniformBlock(program.ObjectName, Index, Gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, uniformBlockParams);

                UniformIndices = uniformBlockParams;
            }
예제 #6
0
            /// <summary>
            /// Construct an UniformBlockBinding.
            /// </summary>
            /// <param name="program">
            /// The <see cref="ShaderProgram"/> defining this uniform block.
            /// </param>
            /// <param name="uniformBlockIndex">
            /// A <see cref="UInt32"/> that specifies the index used for identifying the uniform block.
            /// </param>
            public UniformBlockBinding(ShaderProgram program, uint uniformBlockIndex)
            {
                if (program == null)
                {
                    throw new ArgumentNullException("program");
                }

                int[] uniformBlockParams;

                // Index
                Index = uniformBlockIndex;

                // Name length
                int uniformBlockNameLength;

                uniformBlockParams = new int[1];
                Gl.GetActiveUniformBlock(program.ObjectName, Index, UniformBlockPName.UniformBlockNameLength, uniformBlockParams);
                uniformBlockNameLength = uniformBlockParams[0];

                // Name
                StringBuilder uniformBlockNameBuffer = new StringBuilder(uniformBlockNameLength);
                int           nameLength;

                Gl.GetActiveUniformBlockName(program.ObjectName, Index, uniformBlockNameBuffer.Capacity, out nameLength, uniformBlockNameBuffer);
                Gl.CheckErrors();

                Name = uniformBlockNameBuffer.ToString();

                // Data size
                uniformBlockParams = new int[1];
                Gl.GetActiveUniformBlock(program.ObjectName, Index, UniformBlockPName.UniformBlockDataSize, uniformBlockParams);

                DataSize = (uint)uniformBlockParams[0];

                // Active uniforms
                uniformBlockParams = new int[1];
                Gl.GetActiveUniformBlock(program.ObjectName, Index, UniformBlockPName.UniformBlockActiveUniforms, uniformBlockParams);

                ActiveUniforms = (uint)uniformBlockParams[0];

                // Uniform indices
                uniformBlockParams = new int[ActiveUniforms];
                Gl.GetActiveUniformBlock(program.ObjectName, Index, UniformBlockPName.UniformBlockActiveUniformIndices, uniformBlockParams);

                UniformIndices = Array.ConvertAll(uniformBlockParams, delegate(int item) { return((uint)item); });
            }
예제 #7
0
        /// <summary>
        /// Invalidate a range of the content of this Buffer.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> that created this Buffer.
        /// </param>
        public void Invalidate(GraphicsContext ctx, IntPtr offset, uint length)
        {
            if (ctx.Extensions.InvalidateSubdata_ARB || ctx.Version.IsCompatible(Gl.Version_430))
            {
                Gl.InvalidateBufferSubData(ObjectName, offset, length);
            }
            else
            {
                if (!Immutable && RequiresName(ctx))
                {
                    ctx.Bind(this);
                    Gl.BufferSubData(Target, offset, length, IntPtr.Zero);
                }
            }

            Gl.CheckErrors();
        }
예제 #8
0
        /// <summary>
        /// Invalidate the content of this Buffer.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> that created this Buffer.
        /// </param>
        public void Invalidate(GraphicsContext ctx)
        {
            if (ctx.Extensions.InvalidateSubdata_ARB || ctx.Version.IsCompatible(Gl.Version_430))
            {
                Gl.InvalidateBufferData(ObjectName);
            }
            else
            {
                if (!Immutable && RequiresName(ctx))
                {
                    ctx.Bind(this);
                    Gl.BufferData(Target, Size, IntPtr.Zero, Hint);
                }
            }

            Gl.CheckErrors();
        }
예제 #9
0
        /// <summary>
        /// Map the GPU buffer allocated by this Buffer.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> required for mapping this Buffer.
        /// </param>
        /// <param name="mask">
        /// A <see cref="BufferAccess"/> that specify the map access.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown if this Buffer is already mapped.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown if this Buffer does not exist for <paramref name="ctx"/>.
        /// </exception>
        public void Map(GraphicsContext ctx, BufferAccess mask)
        {
            CheckThisExistence(ctx);

            if (IsMapSupported(ctx))
            {
#if !MONODROID
                if (ctx.Extensions.DirectStateAccess_ARB || ctx.Version.IsCompatible(Gl.Version_450))
                {
                    if ((MappedBuffer = Gl.MapNamedBuffer(ObjectName, mask)) == IntPtr.Zero)
                    {
                        Gl.CheckErrors();
                    }
                }
                else
                {
#endif
                ctx.Bind(this);

                if ((MappedBuffer = Gl.MapBuffer(Target, mask)) == IntPtr.Zero)
                {
                    Gl.CheckErrors();
                }
#if !MONODROID
            }
#endif
            }
            else
            {
                if (GpuBuffer == null)
                {
                    throw new GlException(ErrorCode.InvalidOperation);
                }
                if ((MappedBuffer = GpuBuffer.AlignedBuffer) == IntPtr.Zero)
                {
                    throw new GlException(ErrorCode.InvalidOperation);
                }
            }

            Debug.Assert(MappedBuffer != IntPtr.Zero);

            MapOffset = IntPtr.Zero;
            MapSize   = Size;
            _Access   = mask;
        }
예제 #10
0
        /// <summary>
        /// Reset the allocated GPU buffer for this Buffer.
        /// </summary>
        /// <param name="ctx">
        ///
        /// </param>
        /// <param name="size">
        /// A <see cref="UInt32"/> that determine the size of the buffer object GPU buffer, in bytes.
        /// </param>
        /// <param name="data">
        ///
        /// </param>
        protected void CreateGpuBuffer(GraphicsContext ctx, uint size, IntPtr data)
        {
            if (Immutable && _GpuBufferSize > 0)
            {
                throw new InvalidOperationException("buffer is immutable");
            }

            if (Immutable && ctx.Extensions.BufferStorage_ARB)
            {
                Gl.BufferStorage(Target, size, data, (uint)_UsageMask);
                Gl.CheckErrors();
            }
            else
            {
                Gl.BufferData(Target, size, data, Hint);
                if (CpuBufferAddress != IntPtr.Zero)
                {
                    Gl.BufferSubData(Target, IntPtr.Zero, _GpuBufferSize, CpuBufferAddress);
                }
            }

            // Store GPU buffer size
            _GpuBufferSize = size;
        }
예제 #11
0
        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();
                }
            }
        }
예제 #12
0
        /// <summary>
        /// Map a range of the GPU buffer allocated by this Buffer.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> required for mapping this Buffer.
        /// </param>
        /// <param name="mask">
        /// A <see cref="BufferAccessMask"/> that specify the map access.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown if this Buffer is already mapped.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown if this Buffer does not exist for <paramref name="ctx"/>.
        /// </exception>
        public void Map(GraphicsContext ctx, BufferAccessMask mask, IntPtr offset = default(IntPtr), uint size = 0)
        {
            CheckThisExistence(ctx);

            uint mapSize = size != 0 ? size : Size;

            if (IsMapRangeSupported(ctx))
            {
#if !MONODROID
                if (ctx.Extensions.DirectStateAccess_ARB || ctx.Version.IsCompatible(Gl.Version_450))
                {
                    if ((MappedBuffer = Gl.MapNamedBufferRange(ObjectName, offset, mapSize, mask)) == IntPtr.Zero)
                    {
                        Gl.CheckErrors();
                    }
                }
                else
                {
#endif
                ctx.Bind(this);

                if ((MappedBuffer = Gl.MapBufferRange(Target, offset, mapSize, mask)) == IntPtr.Zero)
                {
                    Gl.CheckErrors();
                }
#if !MONODROID
            }
#endif
            }
            else
            {
                if (GpuBuffer == null)
                {
                    throw new GlException(ErrorCode.InvalidOperation);
                }
                if (GpuBuffer.AlignedBuffer == IntPtr.Zero)
                {
                    throw new GlException(ErrorCode.InvalidOperation);
                }

                MappedBuffer = new IntPtr(GpuBuffer.AlignedBuffer.ToInt64() + offset.ToInt64());
            }

            // Determine map access
            if (mask.HasFlag(BufferAccessMask.MapReadBit) && mask.HasFlag(BufferAccessMask.MapWriteBit))
            {
                _Access = BufferAccess.ReadWrite;
            }
            else if (mask.HasFlag(BufferAccessMask.MapReadBit))
            {
                _Access = BufferAccess.ReadOnly;
            }
            else if (mask.HasFlag(BufferAccessMask.MapWriteBit))
            {
                _Access = BufferAccess.WriteOnly;
            }
            else
            {
                _Access = 0;
            }

            Debug.Assert(MappedBuffer != IntPtr.Zero);

            MapOffset   = offset;
            MapSize     = mapSize;
            _AccessMask = mask;
        }