celestia/src/celengine/vertexobject.cpp

188 lines
5.6 KiB
C++

// vertexobject.cpp
//
// Copyright (C) 2019, the Celestia Development Team
//
// VBO/VAO wrappper class. Currently GL2/GL2+VAO only.
//
// 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 2
// of the License, or (at your option) any later version.
#include "shadermanager.h"
#include "vertexobject.h"
using namespace celestia;
namespace celgl
{
VertexObject::VertexObject(GLenum bufferType) :
m_bufferType(bufferType)
{
}
VertexObject::VertexObject(GLenum bufferType, GLsizeiptr bufferSize, GLenum streamType) :
m_bufferSize(bufferSize),
m_bufferType(bufferType),
m_streamType(streamType)
{
}
VertexObject::~VertexObject()
{
if (m_vaoId != 0 && isVAOSupported())
glDeleteVertexArrays(1, &m_vaoId);
if (m_vboId != 0)
glDeleteBuffers(1, &m_vboId);
}
void VertexObject::bind(AttributesType attributes) noexcept
{
m_currentAttributes = attributes;
if ((m_state & State::Initialize) != 0)
{
if (isVAOSupported())
{
glGenVertexArrays(1, &m_vaoId);
glBindVertexArray(m_vaoId);
}
glGenBuffers(1, &m_vboId);
glBindBuffer(m_bufferType, m_vboId);
}
else
{
if (isVAOSupported())
{
glBindVertexArray(m_vaoId);
if ((m_state & State::Update) != 0)
glBindBuffer(m_bufferType, m_vboId);
}
else
{
glBindBuffer(m_bufferType, m_vboId);
enableAttribArrays();
}
}
}
void VertexObject::bindWritable(AttributesType attributes) noexcept
{
m_state |= State::Update;
bind(attributes);
}
void VertexObject::unbind() noexcept
{
if (isVAOSupported())
{
if ((m_state & (State::Initialize | State::Update)) != 0)
glBindBuffer(m_bufferType, 0);
glBindVertexArray(0);
}
else
{
disableAttribArrays();
glBindBuffer(m_bufferType, 0);
}
m_state = State::NormalState;
m_currentAttributes = AttributesType::Invalid;
}
bool VertexObject::allocate(const void* data) noexcept
{
glBufferData(m_bufferType, m_bufferSize, data, m_streamType);
return glGetError() != GL_NO_ERROR;
}
bool VertexObject::allocate(GLsizeiptr bufferSize, const void* data) noexcept
{
m_bufferSize = bufferSize;
return allocate(data);
}
bool VertexObject::allocate(GLenum bufferType, GLsizeiptr bufferSize, const void* data, GLenum streamType) noexcept
{
m_bufferType = bufferType;
m_bufferSize = bufferSize;
m_streamType = streamType;
return allocate(data);
}
bool VertexObject::setBufferData(const void* data, GLintptr offset, GLsizeiptr size) noexcept
{
glBufferSubData(m_bufferType, offset, size == 0 ? m_bufferSize : size, data);
return glGetError() == GL_NO_ERROR;
}
void VertexObject::draw(GLenum primitive, GLsizei count, GLint first) noexcept
{
if ((m_state & State::Initialize) != 0)
enableAttribArrays();
glDrawArrays(primitive, first, count);
}
void VertexObject::enableAttribArrays() noexcept
{
glBindBuffer(m_bufferType, m_vboId);
for (const auto& t : m_attribParams[(unsigned int)m_currentAttributes])
{
auto n = t.first;
auto& p = t.second;
glEnableVertexAttribArray(n);
glVertexAttribPointer(n, p.count, p.type, p.normalized, p.stride, (GLvoid*) (size_t) p.offset);
}
}
void VertexObject::disableAttribArrays() noexcept
{
if (m_currentAttributes == AttributesType::Invalid)
return;
for (const auto& t : m_attribParams[(unsigned int)m_currentAttributes])
glDisableVertexAttribArray(t.first);
glBindBuffer(m_bufferType, 0);
}
void VertexObject::setVertices(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset, AttributesType attributes) noexcept
{
setVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex, count, type, normalized, stride, offset, attributes);
}
void VertexObject::setNormals(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset, AttributesType attributes) noexcept
{
setVertexAttribArray(CelestiaGLProgram::NormalAttributeIndex, count, type, normalized, stride, offset, attributes);
}
void VertexObject::setColors(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset, AttributesType attributes) noexcept
{
setVertexAttribArray(CelestiaGLProgram::ColorAttributeIndex, count, type, normalized, stride, offset, attributes);
}
void VertexObject::setTextureCoords(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset, AttributesType attributes) noexcept
{
setVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex, count, type, normalized, stride, offset, attributes);
}
void VertexObject::setTangents(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset, AttributesType attributes) noexcept
{
setVertexAttribArray(CelestiaGLProgram::TangentAttributeIndex, count, type, normalized, stride, offset, attributes);
}
void VertexObject::setPointSizes(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset, AttributesType attributes) noexcept
{
setVertexAttribArray(CelestiaGLProgram::PointSizeAttributeIndex, count, type, normalized, offset, stride, attributes);
}
void VertexObject::setVertexAttribArray(GLint location, GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset, AttributesType attributes)
{
if (location < 0)
return;
PtrParams p = { offset, stride, count, type, normalized };
m_attribParams[(unsigned int)attributes][location] = p;
}
} // namespace