diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 78a12211..117648f3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -165,6 +165,7 @@ set(BASE_SOURCES graphics/core/nulldevice.cpp graphics/core/nulldevice.h graphics/core/texture.h + graphics/core/type.cpp graphics/core/type.h graphics/core/vertex.h graphics/engine/camera.cpp diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index b4e897db..f2aae7d3 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -26,6 +26,7 @@ #include "graphics/core/color.h" #include "graphics/core/texture.h" +#include "graphics/core/vertex.h" #include "math/intpoint.h" @@ -267,8 +268,10 @@ enum PrimitiveType PRIMITIVE_POINTS, PRIMITIVE_LINES, PRIMITIVE_LINE_STRIP, + PRIMITIVE_LINE_LOOP, PRIMITIVE_TRIANGLES, - PRIMITIVE_TRIANGLE_STRIP + PRIMITIVE_TRIANGLE_STRIP, + PRIMITIVE_TRIANGLE_FAN }; /** @@ -413,6 +416,14 @@ public: //! Sets only the texture wrap modes (for faster than thru stage params) virtual void SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wrapT) = 0; + //! Renders primitive composed of generic vertices + virtual void DrawPrimitive(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int vertexCount) = 0; + + //! Renders multiple primitives composed of generic vertices + virtual void DrawPrimitives(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int first[], int count[], int drawCount) = 0; + //! Renders primitive composed of vertices with single texture virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount, Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) = 0; diff --git a/src/graphics/core/nulldevice.cpp b/src/graphics/core/nulldevice.cpp index aba9f800..9abdb156 100644 --- a/src/graphics/core/nulldevice.cpp +++ b/src/graphics/core/nulldevice.cpp @@ -168,6 +168,16 @@ void CNullDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, i { } +void CNullDevice::DrawPrimitive(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int vertexCount) +{ +} + +void CNullDevice::DrawPrimitives(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int first[], int count[], int drawCount) +{ +} + void CNullDevice::DrawPrimitives(PrimitiveType type, const Vertex *vertices, int first[], int count[], int drawCount, Color color) { diff --git a/src/graphics/core/nulldevice.h b/src/graphics/core/nulldevice.h index 5721d920..39e3f995 100644 --- a/src/graphics/core/nulldevice.h +++ b/src/graphics/core/nulldevice.h @@ -81,6 +81,11 @@ public: void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT) override; + void DrawPrimitive(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int vertexCount) override; + void DrawPrimitives(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int first[], int count[], int drawCount) override; + void DrawPrimitive(PrimitiveType type, const Vertex* vertices, int vertexCount, Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override; void DrawPrimitive(PrimitiveType type, const VertexTex2* vertices, int vertexCount, Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override; void DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount) override; diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h index 1ec8ef99..e092abb9 100644 --- a/src/graphics/core/texture.h +++ b/src/graphics/core/texture.h @@ -205,47 +205,6 @@ struct TextureStageParams } }; -/** -* \struct TexGenMode -* \brief Texture generation mode -*/ -enum TexGenMode -{ - //! No texture generation - TEX_GEN_NONE, - //! Object linear mode - TEX_GEN_OBJECT_LINEAR, - //! Eye linear mode - TEX_GEN_EYE_LINEAR, - //! Spherical mapping mode - TEX_GEN_SPHERE_MAP, - //! Normal mapping mode - TEX_GEN_NORMAL_MAP, - //! Reflection mapping mode - TEX_GEN_REFLECTION_MAP -}; - -/** -* \struct TextureGenerationParams -* \brief Parameters for texture coordinate generation -* -* These params define the generation of texture coordinate for given texture unit. -*/ -struct TextureGenerationParams -{ - struct Coord - { - TexGenMode mode = TEX_GEN_NONE; - float plane[4] = {}; - }; - Coord coords[4]; - - void LoadDefault() - { - *this = TextureGenerationParams(); - } -}; - /** * \struct Texture * \brief Info about a texture diff --git a/src/graphics/core/type.cpp b/src/graphics/core/type.cpp new file mode 100644 index 00000000..ddcd343d --- /dev/null +++ b/src/graphics/core/type.cpp @@ -0,0 +1,56 @@ +/* +* This file is part of the Colobot: Gold Edition source code +* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam +* http://epsitec.ch; http://colobot.info; http://github.com/colobot +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see http://gnu.org/licenses +*/ + +/** +* \file graphics/core/type.cpp +* \brief Type support and conversion +*/ + +#include "graphics/core/type.h" + +#include + +// Graphics module namespace +namespace Gfx +{ + +//! Returns size in bytes of given type +int GetTypeSize(Type type) +{ + switch (type) + { + case Type::BYTE: + case Type::UBYTE: + return 1; + case Type::SHORT: + case Type::USHORT: + case Type::HALF: + return 2; + case Type::INT: + case Type::UINT: + case Type::FLOAT: + return 4; + case Type::DOUBLE: + return 8; + default: + return 0; + } +} + +} // namespace Gfx diff --git a/src/graphics/core/type.h b/src/graphics/core/type.h index 0c04747d..4a49f582 100644 --- a/src/graphics/core/type.h +++ b/src/graphics/core/type.h @@ -54,6 +54,9 @@ enum class Type : unsigned char DOUBLE, }; +//! Returns size in bytes of given type +int GetTypeSize(Type type); + // TODO: functions for conversion between types } // namespace Gfx diff --git a/src/graphics/opengl/gl14device.cpp b/src/graphics/opengl/gl14device.cpp index 7b93aaff..35a7f0bc 100644 --- a/src/graphics/opengl/gl14device.cpp +++ b/src/graphics/opengl/gl14device.cpp @@ -1379,6 +1379,168 @@ void CGL14Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, i glDisableClientState(GL_COLOR_ARRAY); } +void CGL14Device::DrawPrimitive(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int vertexCount) +{ + const char *ptr = reinterpret_cast(vertices); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(format.vertex.size, + TransformType(format.vertex.type), + format.vertex.stride, + ptr + format.vertex.offset); + + if (format.color.enabled) + { + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(format.color.size, + TransformType(format.color.type), + format.color.stride, + ptr + format.color.offset); + } + else + glColor4fv(format.color.values); + + if (format.normal.enabled) + { + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(TransformType(format.normal.type), + format.normal.stride, + ptr + format.normal.offset); + } + else + glNormal3fv(format.normal.values); + + glClientActiveTexture(GL_TEXTURE0 + m_remap[0]); + if (format.tex1.enabled) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(format.tex1.size, + TransformType(format.tex1.type), + format.tex1.stride, + ptr + format.tex1.offset); + } + else + glTexCoord2fv(format.tex1.values); + + glClientActiveTexture(GL_TEXTURE0 + m_remap[1]); + if (format.tex2.enabled) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(format.tex2.size, + TransformType(format.tex2.type), + format.tex2.stride, + ptr + format.tex2.offset); + } + else + glTexCoord2fv(format.tex2.values); + + glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount); + + glDisableClientState(GL_VERTEX_ARRAY); + + if (format.color.enabled) glDisableClientState(GL_COLOR_ARRAY); + if (format.normal.enabled) glDisableClientState(GL_NORMAL_ARRAY); + + if (format.tex1.enabled) + { + glClientActiveTexture(GL_TEXTURE0 + m_remap[0]); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + + if (format.tex2.enabled) + { + glClientActiveTexture(GL_TEXTURE0 + m_remap[1]); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } +} + +void CGL14Device::DrawPrimitives(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int first[], int count[], int drawCount) +{ + const char *ptr = reinterpret_cast(vertices); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(format.vertex.size, + TransformType(format.vertex.type), + format.vertex.stride, + ptr + format.vertex.offset); + + if (format.color.enabled) + { + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(format.color.size, + TransformType(format.color.type), + format.color.stride, + ptr + format.color.offset); + } + else + glColor4fv(format.color.values); + + if (format.normal.enabled) + { + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(TransformType(format.normal.type), + format.normal.stride, + ptr + format.normal.offset); + } + else + glNormal3fv(format.normal.values); + + glClientActiveTexture(GL_TEXTURE0 + m_remap[0]); + if (format.tex1.enabled) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(format.tex1.size, + TransformType(format.tex1.type), + format.tex1.stride, + ptr + format.tex1.offset); + } + else + glTexCoord2fv(format.tex1.values); + + glClientActiveTexture(GL_TEXTURE0 + m_remap[1]); + if (format.tex2.enabled) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(format.tex2.size, + TransformType(format.tex2.type), + format.tex2.stride, + ptr + format.tex2.offset); + } + else + glTexCoord2fv(format.tex2.values); + + GLenum t = TranslateGfxPrimitive(type); + + if (m_multiDrawArrays) + { + glMultiDrawArrays(t, first, count, drawCount); + } + else + { + for (int i = 0; i < drawCount; i++) + glDrawArrays(t, first[i], count[i]); + } + + glDisableClientState(GL_VERTEX_ARRAY); + + if (format.color.enabled) glDisableClientState(GL_COLOR_ARRAY); + if (format.normal.enabled) glDisableClientState(GL_NORMAL_ARRAY); + + if (format.tex1.enabled) + { + glClientActiveTexture(GL_TEXTURE0 + m_remap[0]); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + + if (format.tex2.enabled) + { + glClientActiveTexture(GL_TEXTURE0 + m_remap[1]); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } +} + void CGL14Device::DrawPrimitives(PrimitiveType type, const Vertex *vertices, int first[], int count[], int drawCount, Color color) { diff --git a/src/graphics/opengl/gl14device.h b/src/graphics/opengl/gl14device.h index 96190394..39b4a122 100644 --- a/src/graphics/opengl/gl14device.h +++ b/src/graphics/opengl/gl14device.h @@ -119,6 +119,11 @@ public: void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT) override; + virtual void DrawPrimitive(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int vertexCount) override; + virtual void DrawPrimitives(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int first[], int count[], int drawCount) override; + virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount, Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override; virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount, diff --git a/src/graphics/opengl/gl21device.cpp b/src/graphics/opengl/gl21device.cpp index e1a96dbe..b38f6387 100644 --- a/src/graphics/opengl/gl21device.cpp +++ b/src/graphics/opengl/gl21device.cpp @@ -1196,6 +1196,162 @@ void CGL21Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, i glDisableClientState(GL_COLOR_ARRAY); } +void CGL21Device::DrawPrimitive(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int vertexCount) +{ + BindVBO(0); + + const char *ptr = reinterpret_cast(vertices); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(format.vertex.size, + TransformType(format.vertex.type), + format.vertex.stride, + ptr + format.vertex.offset); + + if (format.color.enabled) + { + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(format.color.size, + TransformType(format.color.type), + format.color.stride, + ptr + format.color.offset); + } + else + glColor4fv(format.color.values); + + if (format.normal.enabled) + { + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(TransformType(format.normal.type), + format.normal.stride, + ptr + format.normal.offset); + } + else + glNormal3fv(format.normal.values); + + glClientActiveTexture(GL_TEXTURE0); + if (format.tex1.enabled) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(format.tex1.size, + TransformType(format.tex1.type), + format.tex1.stride, + ptr + format.tex1.offset); + } + else + glTexCoord2fv(format.tex1.values); + + glClientActiveTexture(GL_TEXTURE1); + if (format.tex2.enabled) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(format.tex2.size, + TransformType(format.tex2.type), + format.tex2.stride, + ptr + format.tex2.offset); + } + else + glTexCoord2fv(format.tex2.values); + + glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount); + + glDisableClientState(GL_VERTEX_ARRAY); + + if (format.color.enabled) glDisableClientState(GL_COLOR_ARRAY); + if (format.normal.enabled) glDisableClientState(GL_NORMAL_ARRAY); + + if (format.tex1.enabled) + { + glClientActiveTexture(GL_TEXTURE0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + + if (format.tex2.enabled) + { + glClientActiveTexture(GL_TEXTURE1); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } +} + +void CGL21Device::DrawPrimitives(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int first[], int count[], int drawCount) +{ + BindVBO(0); + + const char *ptr = reinterpret_cast(vertices); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(format.vertex.size, + TransformType(format.vertex.type), + format.vertex.stride, + ptr + format.vertex.offset); + + if (format.color.enabled) + { + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(format.color.size, + TransformType(format.color.type), + format.color.stride, + ptr + format.color.offset); + } + else + glColor4fv(format.color.values); + + if (format.normal.enabled) + { + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(TransformType(format.normal.type), + format.normal.stride, + ptr + format.normal.offset); + } + else + glNormal3fv(format.normal.values); + + glClientActiveTexture(GL_TEXTURE0); + if (format.tex1.enabled) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(format.tex1.size, + TransformType(format.tex1.type), + format.tex1.stride, + ptr + format.tex1.offset); + } + else + glTexCoord2fv(format.tex1.values); + + glClientActiveTexture(GL_TEXTURE1); + if (format.tex2.enabled) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(format.tex2.size, + TransformType(format.tex2.type), + format.tex2.stride, + ptr + format.tex2.offset); + } + else + glTexCoord2fv(format.tex2.values); + + glMultiDrawArrays(TranslateGfxPrimitive(type), first, count, drawCount); + + glDisableClientState(GL_VERTEX_ARRAY); + + if (format.color.enabled) glDisableClientState(GL_COLOR_ARRAY); + if (format.normal.enabled) glDisableClientState(GL_NORMAL_ARRAY); + + if (format.tex1.enabled) + { + glClientActiveTexture(GL_TEXTURE0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + + if (format.tex2.enabled) + { + glClientActiveTexture(GL_TEXTURE1); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } +} + void CGL21Device::DrawPrimitives(PrimitiveType type, const Vertex *vertices, int first[], int count[], int drawCount, Color color) { diff --git a/src/graphics/opengl/gl21device.h b/src/graphics/opengl/gl21device.h index 20cf2156..e70d66c6 100644 --- a/src/graphics/opengl/gl21device.h +++ b/src/graphics/opengl/gl21device.h @@ -100,6 +100,11 @@ public: void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT) override; + virtual void DrawPrimitive(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int vertexCount) override; + virtual void DrawPrimitives(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int first[], int count[], int drawCount) override; + virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount, Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override; virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount, diff --git a/src/graphics/opengl/gl33device.cpp b/src/graphics/opengl/gl33device.cpp index df67e5c1..3d5ae713 100644 --- a/src/graphics/opengl/gl33device.cpp +++ b/src/graphics/opengl/gl33device.cpp @@ -523,21 +523,18 @@ bool CGL33Device::Create() m_framebuffers["default"] = MakeUnique(framebufferParams); - // create dynamic buffers - for (int i = 0; i < 3; i++) - { - glGenVertexArrays(1, &m_dynamicBuffers[i].vao); + // create dynamic buffer + glGenVertexArrays(1, &m_dynamicBuffer.vao); - m_dynamicBuffers[i].size = 4 * 1024 * 1024; - m_dynamicBuffers[i].offset = 0; + m_dynamicBuffer.size = 4 * 1024 * 1024; + m_dynamicBuffer.offset = 0; - glGenBuffers(1, &m_dynamicBuffers[i].vbo); - glBindBuffer(GL_ARRAY_BUFFER, m_dynamicBuffers[i].vbo); - glBufferData(GL_ARRAY_BUFFER, m_dynamicBuffers[i].size, nullptr, GL_STREAM_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glGenBuffers(1, &m_dynamicBuffer.vbo); + glBindBuffer(GL_ARRAY_BUFFER, m_dynamicBuffer.vbo); + glBufferData(GL_ARRAY_BUFFER, m_dynamicBuffer.size, nullptr, GL_STREAM_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); - m_vboMemory += m_dynamicBuffers[i].size; - } + m_vboMemory += m_dynamicBuffer.size; GetLogger()->Info("CDevice created successfully\n"); @@ -563,13 +560,10 @@ void CGL33Device::Destroy() DestroyAllTextures(); // delete dynamic buffer - for (int i = 0; i < 3; i++) - { - glDeleteVertexArrays(1, &m_dynamicBuffers[i].vao); - glDeleteBuffers(1, &m_dynamicBuffers[i].vbo); + glDeleteVertexArrays(1, &m_dynamicBuffer.vao); + glDeleteBuffers(1, &m_dynamicBuffer.vbo); - m_vboMemory -= m_dynamicBuffers[i].size; - } + m_vboMemory -= m_dynamicBuffer.size; m_lights.clear(); m_lightsEnabled.clear(); @@ -1075,46 +1069,39 @@ void CGL33Device::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int unsigned int size = vertexCount * sizeof(Vertex); - DynamicBuffer& buffer = m_dynamicBuffers[0]; + DynamicBuffer& buffer = m_dynamicBuffer; BindVAO(buffer.vao); BindVBO(buffer.vbo); unsigned int offset = UploadVertexData(buffer, vs, size); - // Start of the buffer, reinitialize binding state - if (offset == 0) - { - // Vertex coordinate - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, coord))); + // Vertex coordinate + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), + reinterpret_cast(offset + offsetof(Vertex, coord))); - // Normal - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, normal))); - - // Color - glDisableVertexAttribArray(2); - - // Texture coordinate 0 - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, texCoord))); - - // Texture coordinate 1 - glDisableVertexAttribArray(4); - glVertexAttrib2f(4, 0.0f, 0.0f); - } + // Normal + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), + reinterpret_cast(offset + offsetof(Vertex, normal))); + // Color + glDisableVertexAttribArray(2); glVertexAttrib4fv(2, color.Array()); + // Texture coordinate 0 + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), + reinterpret_cast(offset + offsetof(Vertex, texCoord))); + + // Texture coordinate 1 + glDisableVertexAttribArray(4); + glVertexAttrib2f(4, 0.0f, 0.0f); + UpdateRenderingMode(); - int first = offset / sizeof(Vertex); - - glDrawArrays(TranslateGfxPrimitive(type), first, vertexCount); + glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount); } void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount, Color color) @@ -1123,46 +1110,40 @@ void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, unsigned int size = vertexCount * sizeof(VertexTex2); - DynamicBuffer& buffer = m_dynamicBuffers[1]; + DynamicBuffer& buffer = m_dynamicBuffer; BindVAO(buffer.vao); BindVBO(buffer.vbo); unsigned int offset = UploadVertexData(buffer, vs, size); - if (offset == 0) - { - // Vertex coordinate - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), - reinterpret_cast(offsetof(VertexTex2, coord))); + // Vertex coordinate + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), + reinterpret_cast(offset + offsetof(VertexTex2, coord))); - // Normal - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), - reinterpret_cast(offsetof(VertexTex2, normal))); - - // Color - glDisableVertexAttribArray(2); - - // Texture coordinate 0 - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), - reinterpret_cast(offsetof(VertexTex2, texCoord))); - - // Texture coordinate 1 - glEnableVertexAttribArray(4); - glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), - reinterpret_cast(offsetof(VertexTex2, texCoord2))); - } + // Normal + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), + reinterpret_cast(offset + offsetof(VertexTex2, normal))); + // Color + glDisableVertexAttribArray(2); glVertexAttrib4fv(2, color.Array()); + // Texture coordinate 0 + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), + reinterpret_cast(offset + offsetof(VertexTex2, texCoord))); + + // Texture coordinate 1 + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), + reinterpret_cast(offset + offsetof(VertexTex2, texCoord2))); + UpdateRenderingMode(); - int first = offset / sizeof(VertexTex2); - - glDrawArrays(TranslateGfxPrimitive(type), first, vertexCount); + glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount); } void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount) @@ -1171,43 +1152,82 @@ void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, i unsigned int size = vertexCount * sizeof(VertexCol); - DynamicBuffer& buffer = m_dynamicBuffers[2]; + DynamicBuffer& buffer = m_dynamicBuffer; BindVAO(buffer.vao); BindVBO(buffer.vbo); unsigned int offset = UploadVertexData(buffer, vs, size); - if (offset == 0) - { - // Vertex coordinate - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexCol), - reinterpret_cast(offsetof(VertexCol, coord))); + // Vertex coordinate + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexCol), + reinterpret_cast(offset + offsetof(VertexCol, coord))); - // Normal - glDisableVertexAttribArray(1); - glVertexAttrib3f(1, 0.0f, 0.0f, 1.0f); + // Normal + glDisableVertexAttribArray(1); + glVertexAttrib3f(1, 0.0f, 0.0f, 1.0f); - // Color - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(VertexCol), - reinterpret_cast(offsetof(VertexCol, color))); + // Color + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(VertexCol), + reinterpret_cast(offset + offsetof(VertexCol, color))); - // Texture coordinate 0 - glDisableVertexAttribArray(3); - glVertexAttrib2f(3, 0.0f, 0.0f); + // Texture coordinate 0 + glDisableVertexAttribArray(3); + glVertexAttrib2f(3, 0.0f, 0.0f); - // Texture coordinate 1 - glDisableVertexAttribArray(4); - glVertexAttrib2f(4, 0.0f, 0.0f); - } + // Texture coordinate 1 + glDisableVertexAttribArray(4); + glVertexAttrib2f(4, 0.0f, 0.0f); UpdateRenderingMode(); - int first = offset / sizeof(VertexCol); + glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount); +} - glDrawArrays(TranslateGfxPrimitive(type), first, vertexCount); +void CGL33Device::DrawPrimitive(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int vertexCount) +{ + DynamicBuffer& buffer = m_dynamicBuffer; + + BindVAO(buffer.vao); + BindVBO(buffer.vbo); + + unsigned int offset = UploadVertexData(buffer, vertices, size); + + // Update vertex attribute bindings + UpdateVertexAttribute(0, format.vertex, offset); + UpdateVertexAttribute(1, format.normal, offset); + UpdateVertexAttribute(2, format.color, offset); + UpdateVertexAttribute(3, format.tex1, offset); + UpdateVertexAttribute(4, format.tex2, offset); + + UpdateRenderingMode(); + + glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount); +} + +void CGL33Device::DrawPrimitives(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int first[], int count[], int drawCount) +{ + DynamicBuffer& buffer = m_dynamicBuffer; + + BindVAO(buffer.vao); + BindVBO(buffer.vbo); + + unsigned int offset = UploadVertexData(buffer, vertices, size); + + // Update vertex attribute bindings + UpdateVertexAttribute(0, format.vertex, offset); + UpdateVertexAttribute(1, format.normal, offset); + UpdateVertexAttribute(2, format.color, offset); + UpdateVertexAttribute(3, format.tex1, offset); + UpdateVertexAttribute(4, format.tex2, offset); + + UpdateRenderingMode(); + + glMultiDrawArrays(TranslateGfxPrimitive(type), first, count, drawCount); } void CGL33Device::DrawPrimitives(PrimitiveType type, const Vertex *vertices, @@ -1227,51 +1247,39 @@ void CGL33Device::DrawPrimitives(PrimitiveType type, const Vertex *vertices, unsigned int size = vertexCount * sizeof(Vertex); - DynamicBuffer& buffer = m_dynamicBuffers[0]; + DynamicBuffer& buffer = m_dynamicBuffer; BindVAO(buffer.vao); BindVBO(buffer.vbo); unsigned int offset = UploadVertexData(buffer, vs, size); - if (offset == 0) - { - // Vertex coordinate - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, coord))); + // Vertex coordinate + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), + reinterpret_cast(offset + offsetof(Vertex, coord))); - // Normal - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, normal))); - - // Color - glDisableVertexAttribArray(2); - - // Texture coordinate 0 - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, texCoord))); - - // Texture coordinate 1 - glDisableVertexAttribArray(4); - glVertexAttrib2f(4, 0.0f, 0.0f); - } + // Normal + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), + reinterpret_cast(offset + offsetof(Vertex, normal))); + // Color + glDisableVertexAttribArray(2); glVertexAttrib4fv(2, color.Array()); + // Texture coordinate 0 + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), + reinterpret_cast(offset + offsetof(Vertex, texCoord))); + + // Texture coordinate 1 + glDisableVertexAttribArray(4); + glVertexAttrib2f(4, 0.0f, 0.0f); + UpdateRenderingMode(); - int firstOffset = offset / sizeof(Vertex); - - for (int i = 0; i < drawCount; i++) - first[i] += firstOffset; - glMultiDrawArrays(TranslateGfxPrimitive(type), first, count, drawCount); - - for (int i = 0; i < drawCount; i++) - first[i] -= firstOffset; } void CGL33Device::DrawPrimitives(PrimitiveType type, const VertexTex2 *vertices, @@ -1291,52 +1299,40 @@ void CGL33Device::DrawPrimitives(PrimitiveType type, const VertexTex2 *vertices, unsigned int size = vertexCount * sizeof(VertexTex2); - DynamicBuffer& buffer = m_dynamicBuffers[1]; + DynamicBuffer& buffer = m_dynamicBuffer; BindVAO(buffer.vao); BindVBO(buffer.vbo); unsigned int offset = UploadVertexData(buffer, vs, size); - if (offset == 0) - { - // Vertex coordinate - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), - reinterpret_cast(offsetof(VertexTex2, coord))); + // Vertex coordinate + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), + reinterpret_cast(offset + offsetof(VertexTex2, coord))); - // Normal - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), - reinterpret_cast(offsetof(VertexTex2, normal))); - - // Color - glDisableVertexAttribArray(2); - - // Texture coordinate 0 - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), - reinterpret_cast(offsetof(VertexTex2, texCoord))); - - // Texture coordinate 1 - glEnableVertexAttribArray(4); - glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), - reinterpret_cast(offsetof(VertexTex2, texCoord2))); - } + // Normal + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), + reinterpret_cast(offset + offsetof(VertexTex2, normal))); + // Color + glDisableVertexAttribArray(2); glVertexAttrib4fv(2, color.Array()); + // Texture coordinate 0 + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), + reinterpret_cast(offset + offsetof(VertexTex2, texCoord))); + + // Texture coordinate 1 + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), + reinterpret_cast(offset + offsetof(VertexTex2, texCoord2))); + UpdateRenderingMode(); - int firstOffset = offset / sizeof(VertexTex2); - - for (int i = 0; i < drawCount; i++) - first[i] += firstOffset; - glMultiDrawArrays(TranslateGfxPrimitive(type), first, count, drawCount); - - for (int i = 0; i < drawCount; i++) - first[i] -= firstOffset; } void CGL33Device::DrawPrimitives(PrimitiveType type, const VertexCol *vertices, @@ -1356,49 +1352,38 @@ void CGL33Device::DrawPrimitives(PrimitiveType type, const VertexCol *vertices, unsigned int size = vertexCount * sizeof(VertexCol); - DynamicBuffer& buffer = m_dynamicBuffers[2]; + DynamicBuffer& buffer = m_dynamicBuffer; BindVAO(buffer.vao); BindVBO(buffer.vbo); unsigned int offset = UploadVertexData(buffer, vs, size); - if (offset == 0) - { - // Vertex coordinate - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexCol), - reinterpret_cast(offsetof(VertexCol, coord))); + // Vertex coordinate + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexCol), + reinterpret_cast(offset + offsetof(VertexCol, coord))); - // Normal - glDisableVertexAttribArray(1); - glVertexAttrib3f(1, 0.0f, 0.0f, 1.0f); + // Normal + glDisableVertexAttribArray(1); + glVertexAttrib3f(1, 0.0f, 0.0f, 1.0f); - // Color - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(VertexCol), - reinterpret_cast(offsetof(VertexCol, color))); + // Color + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(VertexCol), + reinterpret_cast(offset + offsetof(VertexCol, color))); - // Texture coordinate 0 - glDisableVertexAttribArray(3); - glVertexAttrib2f(3, 0.0f, 0.0f); + // Texture coordinate 0 + glDisableVertexAttribArray(3); + glVertexAttrib2f(3, 0.0f, 0.0f); - // Texture coordinate 1 - glDisableVertexAttribArray(4); - glVertexAttrib2f(4, 0.0f, 0.0f); - } + // Texture coordinate 1 + glDisableVertexAttribArray(4); + glVertexAttrib2f(4, 0.0f, 0.0f); UpdateRenderingMode(); - int firstOffset = offset / sizeof(VertexCol); - - for (int i = 0; i < drawCount; i++) - first[i] += firstOffset; - glMultiDrawArrays(TranslateGfxPrimitive(type), first, count, drawCount); - - for (int i = 0; i < drawCount; i++) - first[i] -= firstOffset; } unsigned int CGL33Device::CreateStaticBuffer(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) @@ -2057,7 +2042,7 @@ inline void CGL33Device::BindVAO(GLuint vao) m_currentVAO = vao; } -unsigned int CGL33Device::UploadVertexData(DynamicBuffer& buffer, void* data, unsigned int size) +unsigned int CGL33Device::UploadVertexData(DynamicBuffer& buffer, const void* data, unsigned int size) { unsigned int nextOffset = buffer.offset + size; @@ -2080,7 +2065,7 @@ unsigned int CGL33Device::UploadVertexData(DynamicBuffer& buffer, void* data, un if (ptr != nullptr) { memcpy(ptr, data, size); - + glUnmapBuffer(GL_ARRAY_BUFFER); } // mapping failed, we must upload data with glBufferSubData @@ -2095,6 +2080,25 @@ unsigned int CGL33Device::UploadVertexData(DynamicBuffer& buffer, void* data, un return currentOffset; } +void CGL33Device::UpdateVertexAttribute(int index, const VertexAttribute &attribute, int offset) +{ + if (attribute.enabled) + { + glEnableVertexAttribArray(index); + glVertexAttribPointer(index, + attribute.size, + TranslateType(attribute.type), + attribute.normalized ? GL_TRUE : GL_FALSE, + attribute.stride, + reinterpret_cast(offset + attribute.offset)); + } + else + { + glDisableVertexAttribArray(index); + glVertexAttrib4fv(index, attribute.values); + } +} + bool CGL33Device::IsAnisotropySupported() { return m_capabilities.anisotropySupported; diff --git a/src/graphics/opengl/gl33device.h b/src/graphics/opengl/gl33device.h index a47fb999..dc17e98f 100644 --- a/src/graphics/opengl/gl33device.h +++ b/src/graphics/opengl/gl33device.h @@ -115,6 +115,11 @@ public: void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT) override; + virtual void DrawPrimitive(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int vertexCount) override; + virtual void DrawPrimitives(PrimitiveType type, const void *vertices, + int size, const VertexFormat &format, int first[], int count[], int drawCount) override; + virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount, Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override; virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount, @@ -202,7 +207,9 @@ private: inline void BindVAO(GLuint vao); //! Uploads data to dynamic buffer and returns offset to it - unsigned int UploadVertexData(DynamicBuffer& buffer, void* data, unsigned int size); + unsigned int UploadVertexData(DynamicBuffer& buffer, const void* data, unsigned int size); + + inline void UpdateVertexAttribute(int index, const VertexAttribute &attribute, int offset); private: //! Current config @@ -283,7 +290,7 @@ private: //! Shader program for shadow rendering GLuint m_shadowProgram = 0; - DynamicBuffer m_dynamicBuffers[3]; + DynamicBuffer m_dynamicBuffer; //! Current mode unsigned int m_mode = 0; diff --git a/src/graphics/opengl/glutil.cpp b/src/graphics/opengl/glutil.cpp index bd6ae886..66018213 100644 --- a/src/graphics/opengl/glutil.cpp +++ b/src/graphics/opengl/glutil.cpp @@ -335,8 +335,10 @@ GLenum TranslateGfxPrimitive(PrimitiveType type) case PRIMITIVE_POINTS: flag = GL_POINTS; break; case PRIMITIVE_LINES: flag = GL_LINES; break; case PRIMITIVE_LINE_STRIP: flag = GL_LINE_STRIP; break; + case PRIMITIVE_LINE_LOOP: flag = GL_LINE_LOOP; break; case PRIMITIVE_TRIANGLES: flag = GL_TRIANGLES; break; case PRIMITIVE_TRIANGLE_STRIP: flag = GL_TRIANGLE_STRIP; break; + case PRIMITIVE_TRIANGLE_FAN: flag = GL_TRIANGLE_FAN; break; default: assert(false); break; } return flag; @@ -441,6 +443,23 @@ GLenum TranslateTextureCoordinateGen(int index) return textureCoordGen[index]; } +GLenum TranslateType(Type type) +{ + switch (type) + { + case Type::BYTE: return GL_BYTE; + case Type::UBYTE: return GL_UNSIGNED_BYTE; + case Type::SHORT: return GL_SHORT; + case Type::USHORT: return GL_UNSIGNED_SHORT; + case Type::INT: return GL_INT; + case Type::UINT: return GL_UNSIGNED_INT; + case Type::HALF: return GL_HALF_FLOAT; + case Type::FLOAT: return GL_FLOAT; + case Type::DOUBLE: return GL_DOUBLE; + default: return 0; + } +} + std::string lastShaderError; std::string GetLastShaderError() diff --git a/src/graphics/opengl/glutil.h b/src/graphics/opengl/glutil.h index 2da4cf20..03450cad 100644 --- a/src/graphics/opengl/glutil.h +++ b/src/graphics/opengl/glutil.h @@ -93,6 +93,8 @@ GLenum TranslateTextureCoordinate(int index); GLenum TranslateTextureCoordinateGen(int index); +GLenum TranslateType(Type type); + std::string GetLastShaderError(); GLint LoadShader(GLint type, const char* filename);