Skip to content

Commit

Permalink
#5584: Each Shader is now maintaining VBOs to store the surface data
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Nov 2, 2021
1 parent b2fd9ab commit 3c324a5
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 69 deletions.
40 changes: 39 additions & 1 deletion libs/render/IndexedVertexBuffer.h
@@ -1,6 +1,8 @@
#pragma once

#include "render.h"
#include <GL/glew.h>
#include "render/VBO.h"

#include "GLProgramAttributes.h"

Expand All @@ -17,7 +19,7 @@ namespace render
* raw vertex geometry.
*/
template<typename Vertex_T>
class IndexedVertexBuffer
class IndexedVertexBuffer final
{
public:
typedef std::vector<Vertex_T> Vertices;
Expand Down Expand Up @@ -80,6 +82,11 @@ class IndexedVertexBuffer
std::copy(begin, end, std::back_inserter(_vertices));
}

typename Vertices::size_type getNumVertices() const
{
return _vertices.size();
}

/// Add a batch of indices
template<typename Iter_T>
void addIndexBatch(Iter_T begin, std::size_t count)
Expand All @@ -101,6 +108,37 @@ class IndexedVertexBuffer
}
}

/// Add a batch of indices
template<typename Iter_T>
void addIndicesToLastBatch(Iter_T begin, std::size_t count, Indices::value_type offset = 0)
{
if (_batches.empty())
{
addIndexBatch(begin, count);
return;
}

if (count < 1)
{
throw std::logic_error("Batch must contain at least one index");
}

auto& batch = *_batches.rbegin();
batch.size += count;

// Append the indices
_indices.reserve(_indices.size() + count);

for (Iter_T i = begin; i < begin + count; ++i)
{
_indices.push_back(*i + offset);
}

// Invalidate the vertex and index buffers
deleteVBO(_vertexVBO);
deleteVBO(_indexVBO);
}

/**
* \brief
* Replace all data with that from another IndexedVertexBuffer
Expand Down
18 changes: 9 additions & 9 deletions radiantcore/patch/PatchRenderables.cpp
Expand Up @@ -171,8 +171,8 @@ void RenderablePatchTesselation::update()
_needsUpdate = false;

// Load all the vertices into the target vector
_vertices = _tess.vertices;
_indices.reserve((_tess.height - 1) * (_tess.width - 1) * 6); // 6 => 2 triangles per quad
std::vector<unsigned int> indices;
indices.reserve((_tess.height - 1) * (_tess.width - 1) * 6); // 6 => 2 triangles per quad

// Generate the indices to define the triangles in clockwise order
for (std::size_t h = 0; h < _tess.height - 1; ++h)
Expand All @@ -181,15 +181,15 @@ void RenderablePatchTesselation::update()

for (std::size_t w = 0; w < _tess.width - 1; ++w)
{
_indices.push_back(static_cast<unsigned int>(rowOffset + w + _tess.width));
_indices.push_back(static_cast<unsigned int>(rowOffset + w + 1));
_indices.push_back(static_cast<unsigned int>(rowOffset + w));
indices.push_back(static_cast<unsigned int>(rowOffset + w + _tess.width));
indices.push_back(static_cast<unsigned int>(rowOffset + w + 1));
indices.push_back(static_cast<unsigned int>(rowOffset + w));

_indices.push_back(static_cast<unsigned int>(rowOffset + w + _tess.width));
_indices.push_back(static_cast<unsigned int>(rowOffset + w + _tess.width + 1));
_indices.push_back(static_cast<unsigned int>(rowOffset + w + 1));
indices.push_back(static_cast<unsigned int>(rowOffset + w + _tess.width));
indices.push_back(static_cast<unsigned int>(rowOffset + w + _tess.width + 1));
indices.push_back(static_cast<unsigned int>(rowOffset + w + 1));
}
}

_shader->addSurface(_vertices, _indices);
_shader->addSurface(_tess.vertices, indices);
}
13 changes: 0 additions & 13 deletions radiantcore/patch/PatchRenderables.h
Expand Up @@ -100,9 +100,6 @@ class RenderablePatchTesselation
bool _needsUpdate;
ShaderPtr _shader;

std::vector<ArbitraryMeshVertex> _vertices;
std::vector<unsigned int> _indices;

public:
RenderablePatchTesselation(const PatchTesselation& tess) :
_tess(tess),
Expand All @@ -111,14 +108,4 @@ class RenderablePatchTesselation

void update();
void setShader(const ShaderPtr& shader);

const std::vector<ArbitraryMeshVertex>& getVertexArray() const
{
return _vertices;
}

const std::vector<unsigned int>& getIndexArray() const
{
return _indices;
}
};
56 changes: 42 additions & 14 deletions radiantcore/rendersystem/backend/OpenGLShader.cpp
Expand Up @@ -75,6 +75,7 @@ OpenGLRenderSystem& OpenGLShader::getRenderSystem()

void OpenGLShader::destroy()
{
_vertexBuffer.reset();
_materialChanged.disconnect();
_material.reset();
_shaderPasses.clear();
Expand Down Expand Up @@ -112,28 +113,55 @@ void OpenGLShader::addRenderable(const OpenGLRenderable& renderable,

void OpenGLShader::addSurface(const std::vector<ArbitraryMeshVertex>& vertices, const std::vector<unsigned int>& indices)
{
// Offset all incoming vertices with a given offset
auto indexOffset = static_cast<unsigned int>(_vertices.size());

_vertices.reserve(_vertices.size() + vertices.size());
_indices.reserve(_indices.size() + indices.size());

_vertices.insert(_vertices.end(), vertices.begin(), vertices.end());

for (const auto index : indices)
if (!_vertexBuffer)
{
_indices.push_back(indexOffset + index);
_vertexBuffer = std::make_unique<IndexedVertexBuffer<ArbitraryMeshVertex>>();
}

// Offset all incoming vertices with a given offset
auto indexOffset = static_cast<unsigned int>(_vertexBuffer->getNumVertices());

// Pump the data to the VBO
_vertexBuffer->addVertices(vertices.begin(), vertices.end());
_vertexBuffer->addIndicesToLastBatch(indices.begin(), indices.size(), indexOffset);
}

const std::vector<ArbitraryMeshVertex>& OpenGLShader::getVertices() const
void OpenGLShader::drawSurfaces()
{
return _vertices;
if (hasSurfaces())
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

_vertexBuffer->renderAllBatches(GL_TRIANGLES, false);
#if 0
// Render all triangles

glBindBuffer(GL_VERTEX_ARRAY, _vbo);

// Set the vertex pointer first
glVertexPointer(3, GL_DOUBLE, sizeof(ArbitraryMeshVertex), &_vertices.front().vertex);
glNormalPointer(GL_DOUBLE, sizeof(ArbitraryMeshVertex), &_vertices.front().normal);
glTexCoordPointer(2, GL_DOUBLE, sizeof(ArbitraryMeshVertex), &_vertices.front().texcoord);
//glVertexAttribPointer(ATTR_TEXCOORD, 2, GL_DOUBLE, 0, sizeof(ArbitraryMeshVertex), &vertices.front().texcoord);
//glVertexAttribPointer(ATTR_TANGENT, 3, GL_DOUBLE, 0, sizeof(ArbitraryMeshVertex), &vertices.front().tangent);
//glVertexAttribPointer(ATTR_BITANGENT, 3, GL_DOUBLE, 0, sizeof(ArbitraryMeshVertex), &vertices.front().bitangent);

glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(_indices.size()), GL_UNSIGNED_INT, _indices.data());

//glDisableClientState(GL_NORMAL_ARRAY);
//glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//glDisableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_VERTEX_ARRAY, 0);
#endif
}
}

const std::vector<unsigned int> OpenGLShader::getIndices() const
bool OpenGLShader::hasSurfaces() const
{
return _indices;
return _vertexBuffer && _vertexBuffer->getNumVertices() > 0;
}

void OpenGLShader::setVisible(bool visible)
Expand Down
10 changes: 4 additions & 6 deletions radiantcore/rendersystem/backend/OpenGLShader.h
Expand Up @@ -5,6 +5,7 @@
#include "irender.h"
#include "ishaders.h"
#include "string/string.h"
#include "render/IndexedVertexBuffer.h"

#include <list>
#include <sigc++/connection.h>
Expand Down Expand Up @@ -44,9 +45,7 @@ class OpenGLShader final :
typedef std::set<Observer*> Observers;
Observers _observers;

// Hacky triangle soup
std::vector<ArbitraryMeshVertex> _vertices;
std::vector<unsigned int> _indices;
std::unique_ptr<render::IndexedVertexBuffer<ArbitraryMeshVertex>> _vertexBuffer;

private:

Expand Down Expand Up @@ -101,9 +100,8 @@ class OpenGLShader final :
const IRenderEntity* entity) override;

void addSurface(const std::vector<ArbitraryMeshVertex>& vertices, const std::vector<unsigned int>& indices) override;

const std::vector<ArbitraryMeshVertex>& getVertices() const;
const std::vector<unsigned int> getIndices() const;
bool hasSurfaces() const;
void drawSurfaces();

void setVisible(bool visible) override;
bool isVisible() const override;
Expand Down
28 changes: 2 additions & 26 deletions radiantcore/rendersystem/backend/OpenGLShaderPass.cpp
Expand Up @@ -576,31 +576,7 @@ void OpenGLShaderPass::render(OpenGLState& current,
// Apply our state to the current state object
applyState(current, flagsMask, viewer, time, NULL);

#if 1
if (!_owner.getVertices().empty())
{
// Render all triangles
const auto& vertices = _owner.getVertices();
const auto& indices = _owner.getIndices();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

// Set the vertex pointer first
glVertexPointer(3, GL_DOUBLE, sizeof(ArbitraryMeshVertex), &vertices.front().vertex);
glNormalPointer(GL_DOUBLE, sizeof(ArbitraryMeshVertex), &vertices.front().normal);
glTexCoordPointer(2, GL_DOUBLE, sizeof(ArbitraryMeshVertex), &vertices.front().texcoord);
//glVertexAttribPointer(ATTR_TEXCOORD, 2, GL_DOUBLE, 0, sizeof(ArbitraryMeshVertex), &vertices.front().texcoord);
//glVertexAttribPointer(ATTR_TANGENT, 3, GL_DOUBLE, 0, sizeof(ArbitraryMeshVertex), &vertices.front().tangent);
//glVertexAttribPointer(ATTR_BITANGENT, 3, GL_DOUBLE, 0, sizeof(ArbitraryMeshVertex), &vertices.front().bitangent);

glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_INT, indices.data());

//glDisableClientState(GL_NORMAL_ARRAY);
//glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//glDisableClientState(GL_VERTEX_ARRAY);
}
#endif
_owner.drawSurfaces();

if (!_renderablesWithoutEntity.empty())
{
Expand Down Expand Up @@ -628,7 +604,7 @@ void OpenGLShaderPass::render(OpenGLState& current,

bool OpenGLShaderPass::empty()
{
return _renderables.empty() && _renderablesWithoutEntity.empty() && _owner.getVertices().empty();
return _renderables.empty() && _renderablesWithoutEntity.empty() && _owner.hasSurfaces();
}

bool OpenGLShaderPass::stateIsActive()
Expand Down

0 comments on commit 3c324a5

Please sign in to comment.