From 76985c878f5fa14b4485e1bdab69997ed7f878ca Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Wed, 28 Feb 2018 12:39:12 +0100 Subject: [PATCH] Can draw colored stuff using VertexArrayMeshes --- data/shaders/fs_simple.glsl | 7 +- data/shaders/vs_simple.glsl | 10 +- src/SimpleMath/SimpleMathFixed.h | 19 ++++ src/modules/RenderModule.cc | 42 ++++++-- src/modules/RenderUtils.cc | 161 ++++++++++++++++++++++++++++--- src/modules/RenderUtils.h | 60 ++++++++++-- 6 files changed, 264 insertions(+), 35 deletions(-) diff --git a/data/shaders/fs_simple.glsl b/data/shaders/fs_simple.glsl index b83f17d..bac1898 100644 --- a/data/shaders/fs_simple.glsl +++ b/data/shaders/fs_simple.glsl @@ -2,7 +2,7 @@ uniform vec4 uColor; -in vec3 fragmentColor; +in vec4 fragmentColor; out vec3 outColor; @@ -13,6 +13,7 @@ void main() { uColor.b * fragmentColor.b ); - outColor = max(uColor.rgb, fragmentColor); -//outColor = fragmentColor + uColor.rgb - uColor.rgb; + +// outColor = max(uColor.rgb, fragmentColor.rgb); +outColor = fragmentColor.rgb + uColor.rgb - uColor.rgb; } diff --git a/data/shaders/vs_simple.glsl b/data/shaders/vs_simple.glsl index 573f5f8..398d47c 100644 --- a/data/shaders/vs_simple.glsl +++ b/data/shaders/vs_simple.glsl @@ -1,14 +1,16 @@ #version 150 core #extension GL_ARB_explicit_attrib_location : require -in vec3 inCoord; -in vec3 inColor; +in vec4 inCoord; +in vec3 inNormal; +in vec2 inUV; +in vec4 inColor; uniform mat4 uModelViewProj; -out vec3 fragmentColor; +out vec4 fragmentColor; void main() { - gl_Position = uModelViewProj * vec4(inCoord, 1); + gl_Position = uModelViewProj * inCoord; fragmentColor = inColor; } diff --git a/src/SimpleMath/SimpleMathFixed.h b/src/SimpleMath/SimpleMathFixed.h index 2851fcb..0e43713 100644 --- a/src/SimpleMath/SimpleMathFixed.h +++ b/src/SimpleMath/SimpleMathFixed.h @@ -151,6 +151,25 @@ class Matrix { ~Matrix() {}; + Matrix ( + const val_type &v00, const val_type &v01 + ) { + assert (nrows == 2); + assert (ncols == 1); + + mData[0] = v00; + mData[1] = v01; + } + + void set( + const val_type &v00, const val_type &v01 + ) { + COMPILE_ASSERT (nrows * ncols == 2); + + mData[0] = v00; + mData[1] = v01; + } + Matrix ( const val_type &v00, const val_type &v01, const val_type &v02 ) { diff --git a/src/modules/RenderModule.cc b/src/modules/RenderModule.cc index 0d7ca2b..8010949 100644 --- a/src/modules/RenderModule.cc +++ b/src/modules/RenderModule.cc @@ -50,6 +50,9 @@ static const GLfloat g_coordinate_system_vertex_buffer_data[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }; +VertexArray gVertexArray; +VertexArrayMesh gVertexArrayMesh; + // // Module // @@ -180,7 +183,23 @@ void Camera::DrawGui() { // void Renderer::Initialize(int width, int height) { mDefaultTexture.MakeGrid(128, Vector3f (0.8, 0.8f, 0.8f), Vector3f (0.2f, 0.2f, 0.2f)); - + + gVertexArray.Initialize(1000, GL_STATIC_DRAW); + gVertexArrayMesh.Initialize(gVertexArray, 6); + + VertexArray::VertexData vertex_data[] = { + {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 255, 0, 0, 255 }, + {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 255, 0, 0, 255 }, + + {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 255, 0, 255}, + {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 255, 0, 255}, + + {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 255, 255}, + {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 255, 255} + }; + + gVertexArrayMesh.SetData(vertex_data, 6); + // Mesh glGenVertexArrays(1, &mMesh.mVertexArrayId); glBindVertexArray(mMesh.mVertexArrayId); @@ -294,12 +313,7 @@ void Renderer::RenderGl() { ); // glDrawArrays(GL_TRIANGLES, 0, 3); // starting from vertex 0; 3 vertices total - glDisableVertexAttribArray(0); - - glBindAttribLocation(mDefaultProgram.mProgramId, 0, "inCoord"); - glBindAttribLocation(mDefaultProgram.mProgramId, 1, "inColor"); - - // Coordinate system +// // Coordinate system glEnableVertexAttribArray(0); glBindVertexArray(mCoordinateSystem.mVertexArrayId); glUniform4fv(muDefaultColor, 1, Vector4f(0.0f, 0.0f, 0.0f, 1.0f).data()); @@ -324,6 +338,20 @@ void Renderer::RenderGl() { ); glDrawArrays(GL_LINES, 0, 6); + // Coordinate System: VertexArrayMesh + model_view_projection = + TranslateMat44(1.25f, 0.0f, 0.0f) + * mCamera.mViewMatrix + * mCamera.mProjectionMatrix; + glUniformMatrix4fv(muDefaultModelViewProjection, 1, GL_FALSE, model_view_projection.data()); + glUniform4fv(muDefaultColor, 1, Vector4f(1.0f, 0.0f, 0.0f, 1.0f).data()); + glBindAttribLocation(mDefaultProgram.mProgramId, 0, "inCoord"); + glBindAttribLocation(mDefaultProgram.mProgramId, 1, "inNormal"); + glBindAttribLocation(mDefaultProgram.mProgramId, 2, "inUV"); + glBindAttribLocation(mDefaultProgram.mProgramId, 3, "inColor"); + gVertexArray.Bind(); + gVertexArrayMesh.Draw(GL_LINES); + if (mSettings->DrawDepth) { mRenderTarget.RenderToLinearizedDepth(true); glClear(GL_COLOR_BUFFER_BIT); diff --git a/src/modules/RenderUtils.cc b/src/modules/RenderUtils.cc index 0862c84..b1b5b48 100644 --- a/src/modules/RenderUtils.cc +++ b/src/modules/RenderUtils.cc @@ -323,33 +323,172 @@ bool Texture::Load(const char* filename, int num_components) { assert(false); } +VertexArray::~VertexArray() { + if (mVertexArrayId != -1) { + Cleanup(); + } +} + void VertexArray::Initialize(const int& size, GLenum usage) { - mSize = size; - mUsed = 0; + mNumVertices = size; + mNumUsedVertices = 0; glGenVertexArrays (1, &mVertexArrayId); glBindVertexArray(mVertexArrayId); glGenBuffers(1, &mVertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData) * size, NULL, usage); + glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData) * mNumVertices, NULL, usage); +} + +void VertexArray::Cleanup() { + glDeleteBuffers(1, &mVertexBuffer); + mVertexBuffer = -1; + glDeleteVertexArrays(1, &mVertexArrayId); + mVertexArrayId = -1; + + mNumVertices = -1; + mNumUsedVertices = -1; } GLuint VertexArray::AllocateMesh(const int& size) { - GLuint mesh_data_size = size * sizeof(VertexData); - if (mUsed + mesh_data_size > mSize) { + if (mNumUsedVertices + size > mNumVertices) { gLog("Cannot allocate mesh in VertexArray: not enough vertices available"); assert(false); return -1; } - GLuint offset = mUsed; - mUsed += mesh_data_size; - + GLuint offset = mNumUsedVertices; + mNumUsedVertices += size; return offset; } -void VertexArrayMesh::Initialize(VertexArray &array, const int& size) { - mOffset = array.AllocateMesh(size); - assert(mOffset != -1); +void VertexArray::Bind() { + glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); + + // Attribute 0: coords + glEnableVertexAttribArray(0); + glVertexAttribPointer( + 0, + 4, + GL_FLOAT, + GL_FALSE, + (sizeof(VertexData)), + (void*)0 + ); + // Attribute 1: color + glEnableVertexAttribArray(1); + glVertexAttribPointer( + 1, + 4, + GL_UNSIGNED_BYTE, + GL_FALSE, + (sizeof(VertexData)), + (void*)(sizeof(float) * 9) + ); + // Attribute 2: normals + glEnableVertexAttribArray(2); + glVertexAttribPointer( + 2, + 3, + GL_FLOAT, + GL_FALSE, + (sizeof(VertexData)), + (void*)(sizeof(float) * 4) + ); + // Attribute 3: texture coordinates + glEnableVertexAttribArray(3); + glVertexAttribPointer( + 3, + 2, + GL_FLOAT, + GL_FALSE, + (sizeof(VertexData)), + (void*)(sizeof(float) * 7) + ); +} + +bool VertexArray::IsBound() { + GLint bound_vertex_buffer = -1; + glGetIntegerv (GL_ARRAY_BUFFER_BINDING, &bound_vertex_buffer); + return bound_vertex_buffer == mVertexBuffer; +} + +void VertexArrayMesh::Initialize(VertexArray &array, const int& size) { + mVertexArray = &array; + mIndexOffset = mVertexArray->AllocateMesh(size); + mOffsetPtr = (void*) (sizeof(VertexArray::VertexData) * mIndexOffset); +} + +void VertexArrayMesh::SetData( + const VertexArray::VertexData* data, + const int& count + ) { + // upload the data + mVertexCount = count; + glBindBuffer(GL_ARRAY_BUFFER, mVertexArray->mVertexBuffer); + + glBufferSubData( + GL_ARRAY_BUFFER, + (GLintptr) mOffsetPtr, + sizeof(VertexArray::VertexData) * count, + data + ); + + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void VertexArrayMesh::SetData( + const std::vector &coords, + const std::vector &normals, + const std::vector &uvs, + const std::vector &colors, + const std::vector &indices + ) { + assert(mOffsetPtr != (void*) -1); + + int vertex_count = coords.size(); + assert(vertex_count > 0); + + bool have_normals = normals.size() > 0; + bool have_uvs = uvs.size() > 0; + bool have_colors = colors.size() > 0; + + assert(!have_normals || (normals.size() == vertex_count)); + assert(!have_uvs || (uvs.size() == vertex_count)); + assert(!have_colors || (colors.size() == vertex_count)); + + std::vector vertex_data(vertex_count, VertexArray::VertexData()); + + for (int i = 0, n = vertex_count; i < n; ++i) { + memcpy (vertex_data[i].mCoords, coords[i].data(), sizeof(float) * 4); + + if (have_normals) { + memcpy (vertex_data[i].mNormals, normals[i].data(), sizeof(float) * 3); + } else { + memset (vertex_data[i].mNormals, 0, sizeof(float) * 3); + } + + if (have_uvs) { + memcpy (vertex_data[i].mTexCoords, uvs[i].data(), sizeof(float) * 2); + } else { + memset (vertex_data[i].mTexCoords, 0, sizeof(float) * 2); + } + + if (have_colors) { + memcpy (vertex_data[i].mColor, colors[i].data(), sizeof(float) * 4); + } else { + memset (vertex_data[i].mColor, 0, sizeof(float) * 4); + } + } + + SetData( + vertex_data.data(), + vertex_count + ); +} + +void VertexArrayMesh::Draw(GLenum mode) { + assert(mVertexArray->IsBound()); + glDrawArrays(mode, mIndexOffset, mVertexCount); } diff --git a/src/modules/RenderUtils.h b/src/modules/RenderUtils.h index bcd8d4b..051f5da 100644 --- a/src/modules/RenderUtils.h +++ b/src/modules/RenderUtils.h @@ -5,6 +5,8 @@ #include // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. +#include + struct Transform { Quaternion rotation = Quaternion (0.0f, 0.0f, 0.0f, 1.0f); Vector3f translation = Vector3f (0.0f, 0.0f, 0.0f); @@ -199,31 +201,69 @@ struct Mesh { struct VertexArray { GLuint mVertexBuffer = -1; GLuint mVertexArrayId = -1; - GLuint mSize = -1; - GLuint mUsed = -1; + GLuint mNumVertices = -1; + GLuint mNumUsedVertices = -1; struct VertexData { - float mCoords[4]; - float mNormals[4]; - float mTexCoords[2]; - GLubyte mColor[4]; + union { + struct { + float x; + float y; + float z; + float w; + float nx; + float ny; + float nz; + float u; + float v; + GLubyte r; + GLubyte g; + GLubyte b; + GLubyte a; + }; + struct { + float mCoords[4]; + float mNormals[3]; + float mTexCoords[2]; + GLubyte mColor[4]; + }; + }; }; + ~VertexArray(); + void Initialize(const int& size, GLenum usage); + void Cleanup(); GLuint AllocateMesh(const int& size); + void Bind(); + bool IsBound(); }; struct VertexArrayMesh { - GLuint mOffset; + VertexArray* mVertexArray = (VertexArray*) -1; + void* mOffsetPtr = (void*) -1; + GLuint mVertexCount = -1; + + GLuint mIndexOffset = -1; + GLuint mIndexBuffer = -1; + GLuint mIndexCount = -1; void Initialize(VertexArray &array, const int& size); + + void SetData( + const VertexArray::VertexData* data, + const int& count + ); + void SetData( const std::vector &coords, - const std::vector &normals, + const std::vector &normals, const std::vector &uvs, - const std::vector &colors + const std::vector &colors, + const std::vector &indices ); + + void Draw(GLenum mode); }; - #endif