From 82d7eb746f0e456265326eb2f4a118aa657118f6 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Thu, 18 Feb 2016 15:09:09 +0300 Subject: [PATCH] mesh and vertex buffers, continue development --- src/dlangui/graphics/glsupport.d | 99 ++++++++++++++++++++----------- src/dlangui/graphics/scene/mesh.d | 37 ++++++++++-- 2 files changed, 96 insertions(+), 40 deletions(-) diff --git a/src/dlangui/graphics/glsupport.d b/src/dlangui/graphics/glsupport.d index 957f486a..38ed011e 100644 --- a/src/dlangui/graphics/glsupport.d +++ b/src/dlangui/graphics/glsupport.d @@ -1003,44 +1003,75 @@ alias FBO = GLObject!(GLObjectTypes.Framebuffer, GL_FRAMEBUFFER); import dlangui.graphics.scene.mesh; -class VertexBuffer { - protected GLuint _vertexBuffer; - protected bool _dynamic; - this(Mesh mesh, bool dynamic = false) { - _dynamic = dynamic; - assertgl!glGenBuffers(1, &_vertexBuffer); - assertgl!glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - assertgl!glBufferData(GL_ARRAY_BUFFER, mesh.vertexFormat.vertexSize * mesh.vertexCount, null, _dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); - } - void setVertexData(float[] data) { - assertgl!glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - assertgl!glBufferData(GL_ARRAY_BUFFER, float.sizeof * cast(int)data.length , data.ptr, _dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); - } - ~this() { - if (_vertexBuffer) { - checkgl!glDeleteBuffers(1, &_vertexBuffer); - _vertexBuffer = 0; - } - } +class VertexBufferBase { + /// bind into current context + void bind() {} + /// unbind from current context + void unbind() {} + /// set or change data + void setData(Mesh mesh) { } } -class VertexAttributeBinding { - protected GLuint _handle; - this(Mesh mesh) { +class VertexBuffer : VertexBufferBase { + protected VertexFormat _format; + protected GLuint _vertexBuffer; + protected GLuint _indexBuffer; + protected GLuint _vao; + + this() { + assertgl!glGenBuffers(1, &_vertexBuffer); + assertgl!glGenBuffers(1, &_indexBuffer); + assertgl!glGenVertexArrays(1, &_vao); + } + + ~this() { + checkgl!glDeleteBuffers(1, &_vertexBuffer); + checkgl!glDeleteBuffers(1, &_indexBuffer); + checkgl!glDeleteVertexArrays(1, &_vao); + } + + /// bind into current context + override void bind() { + glBindVertexArray(_vao); + } + + /// unbind from current context + override void unbind() { + checkgl!glBindVertexArray(0); checkgl!glBindBuffer(GL_ARRAY_BUFFER, 0); checkgl!glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - checkgl!glGenVertexArrays(1, &_handle); - if (!_handle) { - Log.e("Cannot generate vertex array id"); - return; - } - checkgl!glBindVertexArray(_handle); - //glBindBuffer(_handle, - checkgl!glBindVertexArray(0); } - ~this() { - if (_handle) { - checkgl!glDeleteVertexArrays(1, &_handle); - } + + void updateVertexFormat() { + // TODO: use vertex attributes from format and shaders + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, _format.vertexSize, cast(char*)(0)); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, _format.vertexSize, cast(char*)(float.sizeof*3)); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, _format.vertexSize, cast(char*)(float.sizeof*6)); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + } + + /// set or change data + override void setData(Mesh mesh) { + _format = mesh.vertexFormat; + // vertex buffer + checkgl!glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + checkgl!glBufferData(GL_ARRAY_BUFFER, _format.vertexSize * mesh.vertexCount, mesh.vertexData.ptr, GL_STATIC_DRAW); + // index buffer + checkgl!glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); + const(ushort[]) indexData = mesh.indexData; + checkgl!glBufferData(GL_ELEMENT_ARRAY_BUFFER, ushort.sizeof * mesh.indexData.length, indexData.ptr, GL_STATIC_DRAW); + // vertex layout + checkgl!glBindVertexArray(_vao); + // specify vertex buffer + checkgl!glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + // set vertex buffer format + updateVertexFormat(); + // specify index buffer + checkgl!glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); + + unbind(); } } diff --git a/src/dlangui/graphics/scene/mesh.d b/src/dlangui/graphics/scene/mesh.d index b8b6ead5..d08c4d48 100644 --- a/src/dlangui/graphics/scene/mesh.d +++ b/src/dlangui/graphics/scene/mesh.d @@ -87,7 +87,7 @@ struct VertexFormat { return false; } /// compare - bool opEquals(immutable ref VertexFormat fmt) { + bool opEquals(immutable ref VertexFormat fmt) const { if (_vertexSize != fmt._vertexSize) return false; for(int i = 0; i < _elements.length; i++) @@ -105,6 +105,9 @@ class Mesh { protected MeshPart[] _parts; @property ref const(VertexFormat) vertexFormat() const { return _vertexFormat; } + + @property VertexFormat vertexFormat() { return _vertexFormat; } + @property void vertexFormat(VertexFormat format) { assert(_vertexCount == 0); _vertexFormat = format; @@ -112,6 +115,28 @@ class Mesh { /// returns vertex count @property int vertexCount() const { return _vertexCount; } + /// returns vertex data array + @property const(float[]) vertexData() const { return _vertexData; } + + /// return index data for all parts + @property const(ushort[]) indexData() const { + if (!_parts) + return null; + if (_parts.length == 1) + return _parts[0].data; + int sz = 0; + foreach(p; _parts) + sz += p.length; + ushort[] res; + res.length = 0; + int pos = 0; + foreach(p; _parts) { + res[pos .. pos + p.length] = p.data[0 .. $]; + pos += p.length; + } + return res; + } + /// mesh part count @property int partCount() const { return cast(int)_parts.length; } /// returns mesh part by index @@ -122,7 +147,7 @@ class Mesh { return meshPart; } - MeshPart addPart(PrimitiveType type, int[] indexes) { + MeshPart addPart(PrimitiveType type, ushort[] indexes) { return addPart(new MeshPart(type, indexes)); } @@ -166,14 +191,14 @@ enum PrimitiveType : int { /// Mesh part - set of vertex indexes with graphics primitive type class MeshPart { protected PrimitiveType _type; - protected int[] _indexData; - this(PrimitiveType type, int[] indexes = null) { + protected ushort[] _indexData; + this(PrimitiveType type, ushort[] indexes = null) { _type = type; _indexData.assumeSafeAppend; add(indexes); } - void add(int[] indexes) { + void add(ushort[] indexes) { if (indexes.length) _indexData ~= indexes; } @@ -188,5 +213,5 @@ class MeshPart { @property int length() const { return cast(int)_indexData.length; } /// index data - @property int[] data() { return _indexData; } + @property const(ushort[]) data() const { return _indexData; } }