More seperate cc files, font & overlay rendering
This commit is contained in:
BIN
DejaVuSans.ttf
Normal file
BIN
DejaVuSans.ttf
Normal file
Binary file not shown.
8
Makefile
8
Makefile
@@ -1,8 +1,8 @@
|
|||||||
CXX=g++
|
CXX=g++
|
||||||
CXXOPTS=-Og -ggdb -Wall -Wextra -pedantic -Wno-unused-function -Wno-unused-parameter -Wno-sign-compare -std=c++11 -flto
|
CXXOPTS=-O2 -ggdb -Wall -Wextra -pedantic -Wno-unused-function -Wno-unused-parameter -Wno-sign-compare -std=c++14 -flto
|
||||||
LDOPTS=-flto
|
LDOPTS=
|
||||||
LIBS=-lglbinding -lSDL2 -lSDL2_image -lobj
|
LIBS=-lglbinding -lSDL2 -lSDL2_image -lobj -lSDL2_ttf
|
||||||
CXXSRCS=main.cc objectParser.cc
|
CXXSRCS=main.cc objectParser.cc shaders.cc Object.cc VBOManager.cc texture.cc font.cc Overlay.cc
|
||||||
OBJS=$(addprefix objs/,$(CXXSRCS:.cc=.o))
|
OBJS=$(addprefix objs/,$(CXXSRCS:.cc=.o))
|
||||||
|
|
||||||
objs/%.o: %.cc
|
objs/%.o: %.cc
|
||||||
|
|||||||
77
Object.cc
Normal file
77
Object.cc
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#include <vector>
|
||||||
|
#include <glbinding/gl/gl.h>
|
||||||
|
|
||||||
|
#define GLM_FORCE_RADIANS
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
|
#include "shaders.hh"
|
||||||
|
#include "Object.hh"
|
||||||
|
|
||||||
|
using namespace gl;
|
||||||
|
|
||||||
|
Object::Object(VBOManager& vboManager, std::vector<objVertexAttribs> const& vas,
|
||||||
|
std::vector<uint16_t> indices, Program& prog)
|
||||||
|
: _vboManager(vboManager), _prog(prog), _indices(std::move(indices)), _vaID(0)
|
||||||
|
{
|
||||||
|
construct(vas);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::Object(VBOManager& vboManager, std::string const& filename,
|
||||||
|
Program& prog)
|
||||||
|
: _vboManager(vboManager), _prog(prog), _vaID(0)
|
||||||
|
{
|
||||||
|
auto tmp = readObject(filename);
|
||||||
|
_indices = std::get<1>(tmp);
|
||||||
|
construct(std::get<0>(tmp));
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::~Object()
|
||||||
|
{
|
||||||
|
glDeleteVertexArrays(1, &_vaID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::draw(glm::mat4 const& modelview, Program *override) const
|
||||||
|
{
|
||||||
|
glBindVertexArray(_vaID);
|
||||||
|
if (override)
|
||||||
|
override->use();
|
||||||
|
else
|
||||||
|
_prog.use();
|
||||||
|
glUniformMatrix4fv(_prog.getUniformLocation("model_matrix"), 1, GL_FALSE,
|
||||||
|
glm::value_ptr(modelview));
|
||||||
|
glDrawElements(GL_TRIANGLES, _indices.size(), GL_UNSIGNED_SHORT,
|
||||||
|
_indices.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::construct(std::vector<objVertexAttribs> const& vas)
|
||||||
|
{
|
||||||
|
_vbo = _vboManager.alloc(sizeof(objVertexAttribs)*vas.size());
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, _vbo.getVBOId());
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, _vbo.getOfs(),
|
||||||
|
sizeof(objVertexAttribs)*vas.size(), (void*)vas.data());
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &_vaID);
|
||||||
|
glBindVertexArray(_vaID);
|
||||||
|
|
||||||
|
GLint al;
|
||||||
|
if((al = _prog.getAttribLocation("vertex")) != -1) {
|
||||||
|
glEnableVertexAttribArray(al);
|
||||||
|
glVertexAttribPointer(al, 3, GL_FLOAT, GL_FALSE, sizeof(objVertexAttribs),
|
||||||
|
(void*)(_vbo.getOfs()+offsetof(objVertexAttribs, vertex)));
|
||||||
|
}
|
||||||
|
if((al = _prog.getAttribLocation("vertexTC")) != -1) {
|
||||||
|
glEnableVertexAttribArray(al);
|
||||||
|
glVertexAttribPointer(al, 2, GL_UNSIGNED_SHORT, GL_TRUE,
|
||||||
|
sizeof(objVertexAttribs),
|
||||||
|
(void*)(_vbo.getOfs()+offsetof(objVertexAttribs, texCoords)));
|
||||||
|
}
|
||||||
|
if((al = _prog.getAttribLocation("vertexNorm")) != -1) {
|
||||||
|
glEnableVertexAttribArray(al);
|
||||||
|
glVertexAttribPointer(al, 4, GL_INT_2_10_10_10_REV, GL_TRUE,
|
||||||
|
sizeof(objVertexAttribs),
|
||||||
|
(void*)(_vbo.getOfs()+offsetof(objVertexAttribs, normal)));
|
||||||
|
}
|
||||||
|
}
|
||||||
63
Object.hh
63
Object.hh
@@ -1,78 +1,37 @@
|
|||||||
#ifndef __OPENGLPLAYGROUND_OBJECT_HH__
|
#ifndef __OPENGLPLAYGROUND_OBJECT_HH__
|
||||||
#define __OPENGLPLAYGROUND_OBJECT_HH__
|
#define __OPENGLPLAYGROUND_OBJECT_HH__
|
||||||
|
|
||||||
#include <memory>
|
#include <vector>
|
||||||
|
#include <glbinding/gl/types.h>
|
||||||
|
|
||||||
#include "objectParser.hh"
|
#include "objectParser.hh"
|
||||||
#include "VBOManager.hh"
|
#include "VBOManager.hh"
|
||||||
|
|
||||||
|
class Program;
|
||||||
|
|
||||||
class Object {
|
class Object {
|
||||||
public:
|
public:
|
||||||
Object(VBOManager& vboManager, std::vector<objVertexAttribs> const& vas, std::vector<uint16_t> const& indices,
|
Object(VBOManager& vboManager, std::vector<objVertexAttribs> const& vas,
|
||||||
Program& prog)
|
std::vector<uint16_t> indices, Program& prog);
|
||||||
: _vboManager(vboManager), _prog(prog), _indices(indices), _vaID(0) {
|
|
||||||
construct(vas);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object(VBOManager& vboManager, std::string const& filename, Program& prog)
|
Object(VBOManager& vboManager, std::string const& filename, Program& prog);
|
||||||
: _vboManager(vboManager), _prog(prog), _vaID(0) {
|
|
||||||
auto tmp = readObject(filename);
|
|
||||||
_indices = std::get<1>(tmp);
|
|
||||||
construct(std::get<0>(tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
Object(Object const& copy) = delete;
|
Object(Object const& copy) = delete;
|
||||||
|
|
||||||
~Object() {
|
~Object();
|
||||||
glDeleteVertexArrays(1, &_vaID);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object& operator=(Object const& copy) = delete;
|
Object& operator=(Object const& copy) = delete;
|
||||||
|
|
||||||
void draw(glm::mat4 const& modelview, Program *override = nullptr) const {
|
void draw(glm::mat4 const& modelview, Program *override = nullptr) const;
|
||||||
glBindVertexArray(_vaID);
|
|
||||||
if (override)
|
|
||||||
override->use();
|
|
||||||
else
|
|
||||||
_prog.use();
|
|
||||||
glUniformMatrix4fv(_prog.getUniformLocation("model_matrix"), 1, GL_FALSE,
|
|
||||||
glm::value_ptr(modelview));
|
|
||||||
glDrawElements(GL_TRIANGLES, _indices.size(), GL_UNSIGNED_SHORT, _indices.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void construct(std::vector<objVertexAttribs> const& vas) {
|
void construct(std::vector<objVertexAttribs> const& vas);
|
||||||
_vbo = _vboManager.alloc(sizeof(objVertexAttribs)*vas.size());
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo.getVBOId());
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, _vbo.getOfs(), sizeof(objVertexAttribs)*vas.size(),
|
|
||||||
(void*)vas.data());
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &_vaID);
|
|
||||||
glBindVertexArray(_vaID);
|
|
||||||
|
|
||||||
GLint al;
|
|
||||||
if((al = _prog.getAttribLocation("vertex")) != -1) {
|
|
||||||
glEnableVertexAttribArray(al);
|
|
||||||
glVertexAttribPointer(al, 3, GL_FLOAT, GL_FALSE, sizeof(objVertexAttribs),
|
|
||||||
(void*)(_vbo.getOfs()+offsetof(objVertexAttribs, vertex)));
|
|
||||||
}
|
|
||||||
if((al = _prog.getAttribLocation("vertexTC")) != -1) {
|
|
||||||
glEnableVertexAttribArray(al);
|
|
||||||
glVertexAttribPointer(al, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(objVertexAttribs),
|
|
||||||
(void*)(_vbo.getOfs()+offsetof(objVertexAttribs, texCoords)));
|
|
||||||
}
|
|
||||||
if((al = _prog.getAttribLocation("vertexNorm")) != -1) {
|
|
||||||
glEnableVertexAttribArray(al);
|
|
||||||
glVertexAttribPointer(al, 4, GL_INT_2_10_10_10_REV, GL_TRUE, sizeof(objVertexAttribs),
|
|
||||||
(void*)(_vbo.getOfs()+offsetof(objVertexAttribs, normal)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VBOManager& _vboManager;
|
VBOManager& _vboManager;
|
||||||
VBOManager::VBOAlloc _vbo;
|
VBOManager::VBOAlloc _vbo;
|
||||||
Program& _prog;
|
Program& _prog;
|
||||||
std::vector<uint16_t> _indices;
|
std::vector<uint16_t> _indices;
|
||||||
GLuint _vaID;
|
gl::GLuint _vaID;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
53
Overlay.cc
Normal file
53
Overlay.cc
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include <vector>
|
||||||
|
#include <glbinding/gl/gl.h>
|
||||||
|
|
||||||
|
#include "shaders.hh"
|
||||||
|
#include "Overlay.hh"
|
||||||
|
|
||||||
|
using namespace gl;
|
||||||
|
|
||||||
|
Overlay::Overlay(VBOManager& vboManager, std::vector<ovlVertexAttribs> const& vas,
|
||||||
|
Program& prog)
|
||||||
|
: vboManager_(vboManager), vbo_(vboManager_.alloc(sizeof(ovlVertexAttribs)*vas.size())),
|
||||||
|
prog_(prog), vaID_(0), vertices_(vas.size())
|
||||||
|
{
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId());
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, vbo_.getOfs(),
|
||||||
|
sizeof(ovlVertexAttribs)*vas.size(),
|
||||||
|
static_cast<void const*>(vas.data()));
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &vaID_);
|
||||||
|
try {
|
||||||
|
glBindVertexArray(vaID_);
|
||||||
|
GLint al;
|
||||||
|
if((al = prog_.getAttribLocation("vertex")) != -1) {
|
||||||
|
glEnableVertexAttribArray(al);
|
||||||
|
glVertexAttribPointer(al, 2, GL_SHORT, GL_TRUE, sizeof(ovlVertexAttribs),
|
||||||
|
(void*)(vbo_.getOfs()+offsetof(ovlVertexAttribs, vertex)));
|
||||||
|
}
|
||||||
|
if((al = prog_.getAttribLocation("vertexTC")) != -1) {
|
||||||
|
glEnableVertexAttribArray(al);
|
||||||
|
glVertexAttribPointer(al, 2, GL_UNSIGNED_SHORT, GL_TRUE,
|
||||||
|
sizeof(ovlVertexAttribs),
|
||||||
|
(void*)(vbo_.getOfs()+offsetof(ovlVertexAttribs, texCoords)));
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
glDeleteVertexArrays(1, &vaID_);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Overlay::~Overlay()
|
||||||
|
{
|
||||||
|
glDeleteVertexArrays(1, &vaID_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlay::draw(Program *override) const
|
||||||
|
{
|
||||||
|
glBindVertexArray(vaID_);
|
||||||
|
if (override)
|
||||||
|
override->use();
|
||||||
|
else
|
||||||
|
prog_.use();
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, vertices_);
|
||||||
|
}
|
||||||
36
Overlay.hh
Normal file
36
Overlay.hh
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef __OPENGLPLAYGROUND_OVERLAY_HH__
|
||||||
|
#define __OPENGLPLAYGROUND_OVERLAY_HH__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <glbinding/gl/types.h>
|
||||||
|
|
||||||
|
#include "VBOManager.hh"
|
||||||
|
|
||||||
|
class Program;
|
||||||
|
|
||||||
|
struct ovlVertexAttribs {
|
||||||
|
uint16_t vertex[2];
|
||||||
|
uint16_t texCoords[2];
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
class Overlay {
|
||||||
|
public:
|
||||||
|
Overlay(VBOManager& vboManager, std::vector<ovlVertexAttribs> const& vas,
|
||||||
|
Program& prog);
|
||||||
|
|
||||||
|
Overlay(Overlay const& copy) = delete;
|
||||||
|
Overlay& operator=(Overlay const& copy) = delete;
|
||||||
|
|
||||||
|
~Overlay();
|
||||||
|
|
||||||
|
void draw(Program *override = nullptr) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VBOManager& vboManager_;
|
||||||
|
VBOManager::VBOAlloc vbo_;
|
||||||
|
Program& prog_;
|
||||||
|
gl::GLuint vaID_;
|
||||||
|
size_t vertices_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
145
VBOManager.cc
Normal file
145
VBOManager.cc
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
#include <glbinding/gl/gl.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "VBOManager.hh"
|
||||||
|
|
||||||
|
using namespace gl;
|
||||||
|
|
||||||
|
VBOManager::VBOManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::~VBOManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBOAlloc::~VBOAlloc()
|
||||||
|
{
|
||||||
|
if(_vbo)
|
||||||
|
_vbo->free(*this);
|
||||||
|
_vbo = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBOAlloc::VBOAlloc(VBOAlloc&& move)
|
||||||
|
: _vbo(move._vbo), _ofs(move._ofs), _size(move._size)
|
||||||
|
{
|
||||||
|
move._vbo = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBOAlloc& VBOManager::VBOAlloc::operator=(VBOAlloc&& move)
|
||||||
|
{
|
||||||
|
_vbo = move._vbo;
|
||||||
|
_ofs = move._ofs;
|
||||||
|
_size = move._size;
|
||||||
|
move._vbo = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBOAlloc::VBOAlloc()
|
||||||
|
: _vbo(nullptr), _ofs(0), _size(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBOAlloc::VBOAlloc(VBO &vbo, size_t ofs, size_t size)
|
||||||
|
: _vbo(&vbo), _ofs(ofs), _size(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBOAlloc VBOManager::alloc(size_t size, GLenum type)
|
||||||
|
{
|
||||||
|
for(auto& vbo : _vbos[type]) {
|
||||||
|
try {
|
||||||
|
return vbo.alloc(size);
|
||||||
|
} catch (AllocFailed &ex) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_vbos[type].emplace_back((size>default_size)?size:default_size, type);
|
||||||
|
|
||||||
|
return _vbos[type].back().alloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBO::VBO(size_t size, GLenum type)
|
||||||
|
: _bufID(0)
|
||||||
|
{
|
||||||
|
glGenBuffers(1, &_bufID);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, _bufID);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, size, NULL, type);
|
||||||
|
_allocs.emplace_back(_Entry{size, false});
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBO::VBO(VBO&& move)
|
||||||
|
: _bufID(move._bufID), _allocs(std::move(move._allocs))
|
||||||
|
{
|
||||||
|
move._bufID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBO& VBOManager::VBO::operator=(VBO&& move)
|
||||||
|
{
|
||||||
|
for (auto ent : _allocs) {
|
||||||
|
assert(!ent.used);
|
||||||
|
}
|
||||||
|
if (_bufID)
|
||||||
|
glDeleteBuffers(1, &_bufID);
|
||||||
|
_bufID = move._bufID;
|
||||||
|
move._bufID = 0;
|
||||||
|
_allocs = std::move(move._allocs);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBO::~VBO()
|
||||||
|
{
|
||||||
|
for (auto ent : _allocs) {
|
||||||
|
assert(!ent.used);
|
||||||
|
}
|
||||||
|
if (_bufID)
|
||||||
|
glDeleteBuffers(1, &_bufID);
|
||||||
|
_bufID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBOManager::VBOAlloc VBOManager::VBO::alloc(size_t size)
|
||||||
|
{
|
||||||
|
if (size%alignment != 0)
|
||||||
|
size += (alignment - (size%alignment));
|
||||||
|
|
||||||
|
size_t pos = 0;
|
||||||
|
for (auto it = _allocs.begin();it != _allocs.end();++it) {
|
||||||
|
if (!it->used && (it->size >= size)) {
|
||||||
|
size_t leftover = it->size - size;
|
||||||
|
it->used = true;
|
||||||
|
it->size = size;
|
||||||
|
if (leftover > 0)
|
||||||
|
_allocs.insert(++it, _Entry{leftover, false});
|
||||||
|
printf("DEBUG: VBO: Allocated %lu @ %lu in %u\n", size, pos, _bufID);
|
||||||
|
return VBOAlloc(*this, pos, size);
|
||||||
|
}
|
||||||
|
pos += it->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw AllocFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VBOManager::VBO::free(VBOAlloc& alloc)
|
||||||
|
{
|
||||||
|
size_t pos = 0;
|
||||||
|
for (auto it = _allocs.begin();it != _allocs.end();++it) {
|
||||||
|
if (pos == alloc._ofs) {
|
||||||
|
assert(it->size == alloc._size);
|
||||||
|
printf("DEBUG: VBO: Freed %lu @ %lu in %u\n", alloc._size, pos, _bufID);
|
||||||
|
it->used = false;
|
||||||
|
if ((std::next(it) != _allocs.end()) &&
|
||||||
|
!std::next(it)->used) {
|
||||||
|
it->size += std::next(it)->size;
|
||||||
|
_allocs.erase(std::next(it));
|
||||||
|
}
|
||||||
|
if ((it != _allocs.begin()) &&
|
||||||
|
!std::prev(it)->used) {
|
||||||
|
it->size += std::prev(it)->size;
|
||||||
|
_allocs.erase(std::prev(it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos += it->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
132
VBOManager.hh
132
VBOManager.hh
@@ -5,18 +5,15 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include <glbinding/gl/gl.h>
|
#include <glbinding/gl/types.h>
|
||||||
|
|
||||||
using namespace gl;
|
|
||||||
|
|
||||||
class VBOManager {
|
class VBOManager {
|
||||||
public:
|
public:
|
||||||
VBOManager() {
|
VBOManager();
|
||||||
}
|
|
||||||
|
|
||||||
~VBOManager() {
|
~VBOManager();
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -24,35 +21,23 @@ private:
|
|||||||
|
|
||||||
static const size_t default_size = 1048576;
|
static const size_t default_size = 1048576;
|
||||||
static const size_t alignment = 8;
|
static const size_t alignment = 8;
|
||||||
|
static const gl::GLenum default_type = gl::GL_STATIC_DRAW;
|
||||||
|
|
||||||
class AllocFailed {};
|
class AllocFailed {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class VBOAlloc {
|
class VBOAlloc {
|
||||||
public:
|
public:
|
||||||
~VBOAlloc() {
|
~VBOAlloc();
|
||||||
if(_vbo)
|
|
||||||
_vbo->free(*this);
|
|
||||||
_vbo = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
VBOAlloc(VBOAlloc&& move) : _vbo(move._vbo), _ofs(move._ofs), _size(move._size) {
|
VBOAlloc(VBOAlloc&& move);
|
||||||
move._vbo = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
VBOAlloc(VBOAlloc const& copy) = delete;
|
VBOAlloc(VBOAlloc const& copy) = delete;
|
||||||
VBOAlloc& operator=(VBOAlloc const& copy) = delete;
|
VBOAlloc& operator=(VBOAlloc const& copy) = delete;
|
||||||
|
|
||||||
VBOAlloc& operator=(VBOAlloc&& move) {
|
VBOAlloc& operator=(VBOAlloc&& move);
|
||||||
_vbo = move._vbo;
|
|
||||||
_ofs = move._ofs;
|
|
||||||
_size = move._size;
|
|
||||||
move._vbo = nullptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
VBOAlloc() : _vbo(nullptr), _ofs(0), _size(0) {
|
VBOAlloc();
|
||||||
}
|
|
||||||
|
|
||||||
size_t getOfs() const {
|
size_t getOfs() const {
|
||||||
assert(_vbo);
|
assert(_vbo);
|
||||||
@@ -64,14 +49,13 @@ public:
|
|||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint getVBOId() const {
|
gl::GLuint getVBOId() const {
|
||||||
assert(_vbo);
|
assert(_vbo);
|
||||||
return _vbo->getID();
|
return _vbo->getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VBOAlloc(VBO &vbo, size_t ofs, size_t size) : _vbo(&vbo), _ofs(ofs), _size(size) {
|
VBOAlloc(VBO &vbo, size_t ofs, size_t size);
|
||||||
}
|
|
||||||
|
|
||||||
friend class VBOManager;
|
friend class VBOManager;
|
||||||
friend class VBO;
|
friend class VBO;
|
||||||
@@ -80,107 +64,33 @@ public:
|
|||||||
size_t _ofs, _size;
|
size_t _ofs, _size;
|
||||||
};
|
};
|
||||||
|
|
||||||
VBOAlloc alloc(size_t size, GLenum type = GL_STATIC_DRAW) {
|
VBOAlloc alloc(size_t size, gl::GLenum type = default_type);
|
||||||
for(auto& vbo : _vbos[type]) {
|
|
||||||
try {
|
|
||||||
return vbo.alloc(size);
|
|
||||||
} catch (AllocFailed &ex) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_vbos[type].emplace_back((size>default_size)?size:default_size, type);
|
|
||||||
|
|
||||||
return _vbos[type].back().alloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
class VBO {
|
class VBO {
|
||||||
public:
|
public:
|
||||||
VBO(size_t size = default_size, GLenum type = GL_STATIC_DRAW) : _bufID(0) {
|
VBO(size_t size = default_size, gl::GLenum type = default_type);
|
||||||
glGenBuffers(1, &_bufID);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _bufID);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, size, NULL, type);
|
|
||||||
_allocs.emplace_back(_Entry{size, false});
|
|
||||||
}
|
|
||||||
|
|
||||||
VBO(VBO const& copy) = delete;
|
VBO(VBO const& copy) = delete;
|
||||||
VBO& operator=(VBO const& copy) = delete;
|
VBO& operator=(VBO const& copy) = delete;
|
||||||
|
|
||||||
VBO(VBO&& move) : _bufID(move._bufID), _allocs(std::move(move._allocs)) {
|
VBO(VBO&& move);
|
||||||
move._bufID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
VBO& operator=(VBO&& move) {
|
VBO& operator=(VBO&& move);
|
||||||
for (auto ent : _allocs) {
|
|
||||||
assert(!ent.used);
|
|
||||||
}
|
|
||||||
if (_bufID)
|
|
||||||
glDeleteBuffers(1, &_bufID);
|
|
||||||
_bufID = move._bufID;
|
|
||||||
move._bufID = 0;
|
|
||||||
_allocs = std::move(move._allocs);
|
|
||||||
}
|
|
||||||
|
|
||||||
~VBO() {
|
~VBO();
|
||||||
for (auto ent : _allocs) {
|
|
||||||
assert(!ent.used);
|
|
||||||
}
|
|
||||||
if (_bufID)
|
|
||||||
glDeleteBuffers(1, &_bufID);
|
|
||||||
_bufID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
VBOAlloc alloc(size_t size) {
|
VBOAlloc alloc(size_t size);
|
||||||
if (size%alignment != 0)
|
|
||||||
size += (alignment - (size%alignment));
|
|
||||||
|
|
||||||
size_t pos = 0;
|
void free(VBOAlloc& alloc);
|
||||||
for (auto it = _allocs.begin();it != _allocs.end();++it) {
|
|
||||||
if (!it->used && (it->size >= size)) {
|
|
||||||
size_t leftover = it->size - size;
|
|
||||||
it->used = true;
|
|
||||||
it->size = size;
|
|
||||||
if (leftover > 0)
|
|
||||||
_allocs.insert(++it, _Entry{leftover, false});
|
|
||||||
printf("DEBUG: VBO: Allocated %lu @ %lu in %u\n", size, pos, _bufID);
|
|
||||||
return VBOAlloc(*this, pos, size);
|
|
||||||
}
|
|
||||||
pos += it->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw AllocFailed();
|
gl::GLuint getID() const {
|
||||||
}
|
|
||||||
|
|
||||||
void free(VBOAlloc& alloc) {
|
|
||||||
size_t pos = 0;
|
|
||||||
for (auto it = _allocs.begin();it != _allocs.end();++it) {
|
|
||||||
if (pos == alloc._ofs) {
|
|
||||||
assert(it->size == alloc._size);
|
|
||||||
printf("DEBUG: VBO: Freed %lu @ %lu in %u\n", alloc._size, pos, _bufID);
|
|
||||||
it->used = false;
|
|
||||||
if ((std::next(it) != _allocs.end()) &&
|
|
||||||
!std::next(it)->used) {
|
|
||||||
it->size += std::next(it)->size;
|
|
||||||
_allocs.erase(std::next(it));
|
|
||||||
}
|
|
||||||
if ((it != _allocs.begin()) &&
|
|
||||||
!std::prev(it)->used) {
|
|
||||||
it->size += std::prev(it)->size;
|
|
||||||
_allocs.erase(std::prev(it));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pos += it->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint getID() const {
|
|
||||||
return _bufID;
|
return _bufID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint _bufID;
|
gl::GLuint _bufID;
|
||||||
|
|
||||||
struct _Entry {
|
struct _Entry {
|
||||||
size_t size;
|
size_t size;
|
||||||
@@ -190,7 +100,7 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<GLenum, std::vector<VBO> > _vbos;
|
std::map<gl::GLenum, std::vector<VBO> > _vbos;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
64
common.hh
64
common.hh
@@ -9,6 +9,7 @@
|
|||||||
#include <glbinding/gl/gl.h>
|
#include <glbinding/gl/gl.h>
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
|
||||||
using namespace gl;
|
using namespace gl;
|
||||||
|
|
||||||
@@ -24,71 +25,78 @@ public:
|
|||||||
|
|
||||||
class POSIXException : public Exception {
|
class POSIXException : public Exception {
|
||||||
public:
|
public:
|
||||||
POSIXException(int err): Exception(), _err(err) {
|
POSIXException(int err): Exception(), err_(err) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~POSIXException() {}
|
int getErr() const {return err_;}
|
||||||
|
|
||||||
int getErr() const {return _err;}
|
|
||||||
|
|
||||||
virtual std::string toString() const {
|
std::string toString() const override {
|
||||||
return std::string("POSIXException: ") + std::strerror(_err);
|
return std::string("POSIXException: ") + std::strerror(err_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _err;
|
int err_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GLException : public Exception {
|
class GLException : public Exception {
|
||||||
public:
|
public:
|
||||||
GLException(GLenum err) : Exception(), _err(err) {
|
GLException(GLenum err) : Exception(), err_(err) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~GLException() {}
|
GLenum getErr() const {return err_;}
|
||||||
|
|
||||||
GLenum getErr() const {return _err;}
|
|
||||||
|
|
||||||
std::string errToString() const {
|
std::string errToString() const {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
if (_err == GL_INVALID_ENUM)
|
if (err_ == GL_INVALID_ENUM)
|
||||||
ret += "GL_INVALID_ENUM ";
|
ret += "GL_INVALID_ENUM ";
|
||||||
if (_err == GL_INVALID_VALUE)
|
if (err_ == GL_INVALID_VALUE)
|
||||||
ret += "GL_INVALID_VALUE ";
|
ret += "GL_INVALID_VALUE ";
|
||||||
if (_err == GL_INVALID_OPERATION)
|
if (err_ == GL_INVALID_OPERATION)
|
||||||
ret += "GL_INVALID_OPERATION ";
|
ret += "GL_INVALID_OPERATION ";
|
||||||
if (_err == GL_INVALID_FRAMEBUFFER_OPERATION)
|
if (err_ == GL_INVALID_FRAMEBUFFER_OPERATION)
|
||||||
ret += "GL_INVALID_FRAMEBUFFER_OPERATION ";
|
ret += "GL_INVALID_FRAMEBUFFER_OPERATION ";
|
||||||
if (_err == GL_OUT_OF_MEMORY)
|
if (err_ == GL_OUT_OF_MEMORY)
|
||||||
ret += "GL_OUT_OF_MEMORY ";
|
ret += "GL_OUT_OF_MEMORY ";
|
||||||
if (_err == GL_STACK_UNDERFLOW)
|
if (err_ == GL_STACK_UNDERFLOW)
|
||||||
ret += "GL_STACK_UNDERFLOW ";
|
ret += "GL_STACK_UNDERFLOW ";
|
||||||
if (_err == GL_STACK_OVERFLOW)
|
if (err_ == GL_STACK_OVERFLOW)
|
||||||
ret += "GL_STACK_OVERFLOW ";
|
ret += "GL_STACK_OVERFLOW ";
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string toString() const {
|
std::string toString() const override {
|
||||||
return "GLException: " + errToString() + "(" + std::to_string(static_cast<int>(_err)) + ")";
|
return "GLException: " + errToString() + "(" + std::to_string(static_cast<int>(err_)) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLenum _err;
|
GLenum err_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SDLException : public Exception {
|
class SDLException : public Exception {
|
||||||
public:
|
public:
|
||||||
SDLException() : Exception(), _msg(SDL_GetError()) {
|
SDLException() : Exception(), msg_(SDL_GetError()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~SDLException() {}
|
std::string toString() const override {
|
||||||
|
return "SDLException: " + msg_;
|
||||||
virtual std::string toString() const {
|
|
||||||
return "SDLException: " + _msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _msg;
|
std::string msg_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TTFException : public Exception {
|
||||||
|
public:
|
||||||
|
TTFException() : Exception(), msg_(TTF_GetError()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string toString() const override {
|
||||||
|
return "TTFException: " + msg_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string msg_;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void checkGlError() {
|
static void checkGlError() {
|
||||||
|
|||||||
41
font.cc
Normal file
41
font.cc
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <cassert>
|
||||||
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
|
||||||
|
#include "common.hh"
|
||||||
|
#include "texture.hh"
|
||||||
|
#include "font.hh"
|
||||||
|
|
||||||
|
Font::Font(std::string const& filename, unsigned ptsize)
|
||||||
|
: font_{nullptr}
|
||||||
|
{
|
||||||
|
assert(TTF_WasInit());
|
||||||
|
font_ = TTF_OpenFont(filename.c_str(), ptsize);
|
||||||
|
if(!font_)
|
||||||
|
throw TTFException{};
|
||||||
|
}
|
||||||
|
|
||||||
|
Font::~Font()
|
||||||
|
{
|
||||||
|
if(font_)
|
||||||
|
TTF_CloseFont(font_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D Font::render(std::string const& text, bool fast) const {
|
||||||
|
SDL_Surface *surf;
|
||||||
|
if(fast)
|
||||||
|
surf = TTF_RenderUTF8_Solid(font_, text.c_str(), SDL_Color{255, 255, 255, 255});
|
||||||
|
else
|
||||||
|
surf = TTF_RenderUTF8_Blended(font_, text.c_str(), SDL_Color{255, 255, 255, 255});
|
||||||
|
|
||||||
|
if(!surf)
|
||||||
|
throw TTFException{};
|
||||||
|
|
||||||
|
try {
|
||||||
|
Texture2D ret{surf};
|
||||||
|
SDL_FreeSurface(surf);
|
||||||
|
return ret;
|
||||||
|
} catch(...) {
|
||||||
|
SDL_FreeSurface(surf);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
font.hh
Normal file
26
font.hh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __OPENGLPLAYGROUND_FONT_HH__
|
||||||
|
#define __OPENGLPLAYGROUND_FONT_HH__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct _TTF_Font;
|
||||||
|
typedef struct _TTF_Font TTF_Font;
|
||||||
|
class Texture2D;
|
||||||
|
|
||||||
|
class Font {
|
||||||
|
public:
|
||||||
|
Font(std::string const& filename, unsigned ptsize);
|
||||||
|
Font(Font const& copy) = delete;
|
||||||
|
|
||||||
|
Font& operator=(Font const& copy) = delete;
|
||||||
|
|
||||||
|
~Font();
|
||||||
|
|
||||||
|
Texture2D render(std::string const& text, bool fast = false) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TTF_Font* font_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
60
main.cc
60
main.cc
@@ -4,6 +4,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_image.h>
|
#include <SDL2/SDL_image.h>
|
||||||
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
|
||||||
#include <glbinding/gl/gl.h>
|
#include <glbinding/gl/gl.h>
|
||||||
#include <glbinding/Binding.h>
|
#include <glbinding/Binding.h>
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
|
#include <glm/gtc/packing.hpp>
|
||||||
|
|
||||||
#include "common.hh"
|
#include "common.hh"
|
||||||
#include "shaders.hh"
|
#include "shaders.hh"
|
||||||
@@ -21,6 +23,8 @@
|
|||||||
#include "VBOManager.hh"
|
#include "VBOManager.hh"
|
||||||
#include "objectParser.hh"
|
#include "objectParser.hh"
|
||||||
#include "Object.hh"
|
#include "Object.hh"
|
||||||
|
#include "font.hh"
|
||||||
|
#include "Overlay.hh"
|
||||||
|
|
||||||
using namespace gl;
|
using namespace gl;
|
||||||
|
|
||||||
@@ -50,6 +54,13 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(TTF_Init() == -1) {
|
||||||
|
printf("Could not init SDL_ttf: %s\n", TTF_GetError());
|
||||||
|
IMG_Quit();
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
||||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||||
@@ -106,7 +117,10 @@ int main(int argc, char *argv[])
|
|||||||
0.1f, 100.0f);
|
0.1f, 100.0f);
|
||||||
glm::mat4 view = glm::lookAt(glm::vec3(2.0f, 2.0f, 10),
|
glm::mat4 view = glm::lookAt(glm::vec3(2.0f, 2.0f, 10),
|
||||||
glm::vec3(0.0f, 0.0f, 0),
|
glm::vec3(0.0f, 0.0f, 0),
|
||||||
glm::vec3(0, 1, 0));
|
glm::vec3(0, 1, 0));
|
||||||
|
|
||||||
|
Font font{"DejaVuSans.ttf", 12};
|
||||||
|
|
||||||
// sf::Font font;
|
// sf::Font font;
|
||||||
// if (!font.loadFromFile("DejaVuSans.ttf")) {
|
// if (!font.loadFromFile("DejaVuSans.ttf")) {
|
||||||
// std::printf("Error loading font\n");
|
// std::printf("Error loading font\n");
|
||||||
@@ -120,7 +134,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// sf::Clock clock;
|
// sf::Clock clock;
|
||||||
// sf::Time last = clock.getElapsedTime();
|
// sf::Time last = clock.getElapsedTime();
|
||||||
|
auto last = SDL_GetTicks();
|
||||||
|
|
||||||
VBOManager vboManager;
|
VBOManager vboManager;
|
||||||
|
|
||||||
Texture2D cubeTex("textures/Wood_Box_Texture.jpg");
|
Texture2D cubeTex("textures/Wood_Box_Texture.jpg");
|
||||||
@@ -135,7 +150,8 @@ int main(int argc, char *argv[])
|
|||||||
const unsigned lights = 2;
|
const unsigned lights = 2;
|
||||||
const unsigned shadowMapSize = 512;
|
const unsigned shadowMapSize = 512;
|
||||||
glm::mat4 shadowProj = glm::perspectiveFov(90.0f, static_cast<float>(shadowMapSize),
|
glm::mat4 shadowProj = glm::perspectiveFov(90.0f, static_cast<float>(shadowMapSize),
|
||||||
static_cast<float>(shadowMapSize), 1.0f, 128.0f);
|
static_cast<float>(shadowMapSize), 1.0f, 128.0f);
|
||||||
|
//glm::mat4 shadowProj = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 1.0f, 128.0f);
|
||||||
std::vector<TextureCubeMap> shadowMaps;
|
std::vector<TextureCubeMap> shadowMaps;
|
||||||
for(unsigned i = 0;i < lights;++i) {
|
for(unsigned i = 0;i < lights;++i) {
|
||||||
shadowMaps.emplace_back(shadowMapSize);
|
shadowMaps.emplace_back(shadowMapSize);
|
||||||
@@ -160,6 +176,10 @@ int main(int argc, char *argv[])
|
|||||||
FragmentShader shadowFs{fileToString("shaders/shadow.fs")};
|
FragmentShader shadowFs{fileToString("shaders/shadow.fs")};
|
||||||
Program shadowProg{shadowVs, shadowFs};
|
Program shadowProg{shadowVs, shadowFs};
|
||||||
|
|
||||||
|
VertexShader ovlVs{fileToString("shaders/overlay.vs")};
|
||||||
|
FragmentShader ovlFs{fileToString("shaders/overlay.fs")};
|
||||||
|
Program ovlProg{ovlVs, ovlFs};
|
||||||
|
|
||||||
prog.use();
|
prog.use();
|
||||||
glUniformMatrix4fv(prog.getUniformLocation("projection_matrix"), 1, GL_FALSE,
|
glUniformMatrix4fv(prog.getUniformLocation("projection_matrix"), 1, GL_FALSE,
|
||||||
glm::value_ptr(proj));
|
glm::value_ptr(proj));
|
||||||
@@ -171,12 +191,28 @@ int main(int argc, char *argv[])
|
|||||||
glUniform1iv(prog.getUniformLocation("texShadowMaps"), 2, shadowMapTUs);
|
glUniform1iv(prog.getUniformLocation("texShadowMaps"), 2, shadowMapTUs);
|
||||||
|
|
||||||
shadowProg.use();
|
shadowProg.use();
|
||||||
glUniformMatrix4fv(prog.getUniformLocation("projection_matrix"), 1, GL_FALSE,
|
glUniformMatrix4fv(shadowProg.getUniformLocation("projection_matrix"), 1, GL_FALSE,
|
||||||
glm::value_ptr(shadowProj));
|
glm::value_ptr(shadowProj));
|
||||||
|
|
||||||
|
ovlProg.use();
|
||||||
|
glUniform1i(ovlProg.getUniformLocation("texBase"), 0);
|
||||||
|
|
||||||
Object box(vboManager, "objects/woodbox.obj", prog);
|
Object box(vboManager, "objects/woodbox.obj", prog);
|
||||||
Object pyramid(vboManager, "objects/pyramid.obj", prog);
|
Object pyramid(vboManager, "objects/pyramid.obj", prog);
|
||||||
Object plane(vboManager, "objects/plane.obj", prog);
|
Object plane(vboManager, "objects/plane.obj", prog);
|
||||||
|
|
||||||
|
float px20_width = 2.0f*(20.0f/width);
|
||||||
|
float px20_height = 2.0f*(20.0f/height);
|
||||||
|
|
||||||
|
std::vector<ovlVertexAttribs> ovlAttribs{
|
||||||
|
{{glm::packSnorm1x16(1.0-px20_width), glm::packSnorm1x16(1.0)}, {0, 0}},
|
||||||
|
{{glm::packSnorm1x16(1.0), glm::packSnorm1x16(1.0-px20_height)}, {65535u, 65535u}},
|
||||||
|
{{glm::packSnorm1x16(1.0), glm::packSnorm1x16(1.0)}, {65535u, 0}},
|
||||||
|
{{glm::packSnorm1x16(1.0-px20_width), glm::packSnorm1x16(1.0)}, {0, 0}},
|
||||||
|
{{glm::packSnorm1x16(1.0-px20_width), glm::packSnorm1x16(1.0-px20_height)}, {0, 65535u}},
|
||||||
|
{{glm::packSnorm1x16(1.0), glm::packSnorm1x16(1.0-px20_height)}, {65535u, 65535u}}};
|
||||||
|
|
||||||
|
Overlay ovl{vboManager, ovlAttribs, ovlProg};
|
||||||
|
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
@@ -288,6 +324,20 @@ int main(int argc, char *argv[])
|
|||||||
// fpsText.setPosition({1680-fpsText.getLocalBounds().width, 0});
|
// fpsText.setPosition({1680-fpsText.getLocalBounds().width, 0});
|
||||||
// window.draw(fpsText);
|
// window.draw(fpsText);
|
||||||
|
|
||||||
|
auto now = SDL_GetTicks();
|
||||||
|
auto elapsed = now - last;
|
||||||
|
last = now;
|
||||||
|
std::string fpsText = std::to_string(static_cast<unsigned>(1000.0/elapsed));
|
||||||
|
auto fpsTex = font.render(fpsText);
|
||||||
|
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
fpsTex.bind();
|
||||||
|
//redTex.bind();
|
||||||
|
ovl.draw();
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
SDL_GL_SwapWindow(window);
|
SDL_GL_SwapWindow(window);
|
||||||
}
|
}
|
||||||
}catch(Exception &ex) {
|
}catch(Exception &ex) {
|
||||||
|
|||||||
134
shaders.cc
Normal file
134
shaders.cc
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
#include <glbinding/gl/gl.h>
|
||||||
|
|
||||||
|
#include "shaders.hh"
|
||||||
|
|
||||||
|
using namespace gl;
|
||||||
|
|
||||||
|
ShaderException::ShaderException(std::string const& msg)
|
||||||
|
: GLException(glGetError()), _msg(msg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader::Shader(std::string const& program, GLenum type)
|
||||||
|
: _shaderID(glCreateShader(type))
|
||||||
|
{
|
||||||
|
const char* const arr[] = {program.c_str()};
|
||||||
|
glShaderSource(_shaderID, 1, arr, NULL);
|
||||||
|
glCompileShader(_shaderID);
|
||||||
|
|
||||||
|
int state;
|
||||||
|
glGetShaderiv(_shaderID, GL_COMPILE_STATUS, &state);
|
||||||
|
|
||||||
|
if (state == 0) {
|
||||||
|
int logLength;
|
||||||
|
glGetShaderiv(_shaderID, GL_INFO_LOG_LENGTH, &logLength);
|
||||||
|
|
||||||
|
char *log = new char[logLength];
|
||||||
|
glGetShaderInfoLog(_shaderID, logLength, NULL, log);
|
||||||
|
std::string msg(log);
|
||||||
|
delete[] log;
|
||||||
|
|
||||||
|
glDeleteShader(_shaderID);
|
||||||
|
|
||||||
|
throw ShaderException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader::~Shader()
|
||||||
|
{
|
||||||
|
glDeleteShader(_shaderID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Program::Program(VertexShader& vertex, FragmentShader& frag)
|
||||||
|
: _geom(nullptr), _vertex(vertex), _frag(frag), _progID(glCreateProgram())
|
||||||
|
{
|
||||||
|
glAttachShader(_progID, _vertex.getID());
|
||||||
|
glAttachShader(_progID, _frag.getID());
|
||||||
|
|
||||||
|
glLinkProgram(_progID);
|
||||||
|
|
||||||
|
int state;
|
||||||
|
glGetProgramiv(_progID, GL_LINK_STATUS, &state);
|
||||||
|
|
||||||
|
if (state == 0) {
|
||||||
|
int logLength;
|
||||||
|
glGetProgramiv(_progID, GL_INFO_LOG_LENGTH, &logLength);
|
||||||
|
|
||||||
|
char *log = new char[logLength];
|
||||||
|
glGetProgramInfoLog(_progID, logLength, NULL, log);
|
||||||
|
std::string msg(log);
|
||||||
|
delete[] log;
|
||||||
|
|
||||||
|
glDeleteProgram(_progID);
|
||||||
|
|
||||||
|
throw ShaderException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
glDetachShader(_progID, _vertex.getID());
|
||||||
|
glDetachShader(_progID, _frag.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
Program::Program(GeometryShader& geom, VertexShader& vertex, FragmentShader& frag)
|
||||||
|
: _geom(&geom), _vertex(vertex), _frag(frag), _progID(glCreateProgram())
|
||||||
|
{
|
||||||
|
glAttachShader(_progID, _geom->getID());
|
||||||
|
glAttachShader(_progID, _vertex.getID());
|
||||||
|
glAttachShader(_progID, _frag.getID());
|
||||||
|
|
||||||
|
glLinkProgram(_progID);
|
||||||
|
|
||||||
|
int state;
|
||||||
|
glGetProgramiv(_progID, GL_LINK_STATUS, &state);
|
||||||
|
|
||||||
|
if (!state) {
|
||||||
|
int logLength;
|
||||||
|
glGetProgramiv(_progID, GL_INFO_LOG_LENGTH, &logLength);
|
||||||
|
|
||||||
|
char *log = new char[logLength];
|
||||||
|
glGetProgramInfoLog(_progID, logLength, NULL, log);
|
||||||
|
std::string msg(log);
|
||||||
|
delete[] log;
|
||||||
|
|
||||||
|
glDeleteProgram(_progID);
|
||||||
|
|
||||||
|
throw ShaderException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
glDetachShader(_progID, _geom->getID());
|
||||||
|
glDetachShader(_progID, _vertex.getID());
|
||||||
|
glDetachShader(_progID, _frag.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
Program::~Program()
|
||||||
|
{
|
||||||
|
glDeleteProgram(_progID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::use() const
|
||||||
|
{
|
||||||
|
glUseProgram(_progID);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint Program::getUniformLocation(std::string const& name) const
|
||||||
|
{
|
||||||
|
auto search = _uniformLocCache.find(name);
|
||||||
|
if (search != _uniformLocCache.end())
|
||||||
|
return search->second;
|
||||||
|
|
||||||
|
GLint ret = glGetUniformLocation(_progID, name.c_str());
|
||||||
|
if (ret != -1)
|
||||||
|
_uniformLocCache.emplace(name, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint Program::getAttribLocation(std::string const& name) const
|
||||||
|
{
|
||||||
|
auto search = _attribLocCache.find(name);
|
||||||
|
if (search != _attribLocCache.end())
|
||||||
|
return search->second;
|
||||||
|
|
||||||
|
GLint ret = glGetAttribLocation(_progID, name.c_str());
|
||||||
|
if (ret != -1)
|
||||||
|
_attribLocCache.emplace(name, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
142
shaders.hh
142
shaders.hh
@@ -4,22 +4,20 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <glbinding/gl/gl.h>
|
#include <glbinding/gl/types.h>
|
||||||
|
|
||||||
#include "common.hh"
|
#include "common.hh"
|
||||||
|
|
||||||
using namespace gl;
|
|
||||||
|
|
||||||
class ShaderException : public GLException {
|
class ShaderException : public GLException {
|
||||||
public:
|
public:
|
||||||
ShaderException(std::string const& msg) : GLException(glGetError()), _msg(msg) {
|
ShaderException(std::string const& msg);
|
||||||
}
|
|
||||||
|
//~ShaderException() {}
|
||||||
virtual ~ShaderException() {}
|
|
||||||
|
|
||||||
std::string const& getMsg() const {return _msg;}
|
std::string const& getMsg() const {return _msg;}
|
||||||
|
|
||||||
virtual std::string toString() const {
|
std::string toString() const override {
|
||||||
return "ShaderException: " + _msg;
|
return "ShaderException: " + _msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,33 +31,12 @@ class Shader {
|
|||||||
public:
|
public:
|
||||||
Shader() : _shaderID(0) {
|
Shader() : _shaderID(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader(std::string const& program, GLenum type) : _shaderID(glCreateShader(type)) {
|
|
||||||
const char* const arr[] = {program.c_str()};
|
|
||||||
glShaderSource(_shaderID, 1, arr, NULL);
|
|
||||||
glCompileShader(_shaderID);
|
|
||||||
|
|
||||||
int state;
|
|
||||||
glGetShaderiv(_shaderID, GL_COMPILE_STATUS, &state);
|
|
||||||
|
|
||||||
if (!state) {
|
|
||||||
int logLength;
|
|
||||||
glGetShaderiv(_shaderID, GL_INFO_LOG_LENGTH, &logLength);
|
|
||||||
|
|
||||||
char *log = new char[logLength];
|
|
||||||
glGetShaderInfoLog(_shaderID, logLength, NULL, log);
|
|
||||||
std::string msg(log);
|
|
||||||
delete[] log;
|
|
||||||
|
|
||||||
glDeleteShader(_shaderID);
|
|
||||||
|
|
||||||
throw ShaderException(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~Shader() {
|
protected:
|
||||||
glDeleteShader(_shaderID);
|
Shader(std::string const& program, gl::GLenum type);
|
||||||
}
|
|
||||||
|
public:
|
||||||
|
virtual ~Shader();
|
||||||
|
|
||||||
unsigned getID() const {
|
unsigned getID() const {
|
||||||
return _shaderID;
|
return _shaderID;
|
||||||
@@ -75,118 +52,33 @@ class VertexShader : public Shader {
|
|||||||
public:
|
public:
|
||||||
VertexShader(std::string const& program) : Shader(program, GL_VERTEX_SHADER) {
|
VertexShader(std::string const& program) : Shader(program, GL_VERTEX_SHADER) {
|
||||||
}
|
}
|
||||||
|
|
||||||
~VertexShader() override {
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FragmentShader : public Shader {
|
class FragmentShader : public Shader {
|
||||||
public:
|
public:
|
||||||
FragmentShader(std::string const& program) : Shader(program, GL_FRAGMENT_SHADER) {
|
FragmentShader(std::string const& program) : Shader(program, GL_FRAGMENT_SHADER) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~FragmentShader() {
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GeometryShader : public Shader {
|
class GeometryShader : public Shader {
|
||||||
public:
|
public:
|
||||||
GeometryShader(std::string const& program) : Shader(program, GL_GEOMETRY_SHADER) {
|
GeometryShader(std::string const& program) : Shader(program, GL_GEOMETRY_SHADER) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~GeometryShader() {
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Program {
|
class Program {
|
||||||
public:
|
public:
|
||||||
Program(VertexShader& vertex, FragmentShader& frag)
|
Program(VertexShader& vertex, FragmentShader& frag);
|
||||||
: _geom(nullptr), _vertex(vertex), _frag(frag), _progID(glCreateProgram()) {
|
|
||||||
glAttachShader(_progID, _vertex.getID());
|
|
||||||
glAttachShader(_progID, _frag.getID());
|
|
||||||
|
|
||||||
glLinkProgram(_progID);
|
Program(GeometryShader& geom, VertexShader& vertex, FragmentShader& frag);
|
||||||
|
|
||||||
int state;
|
|
||||||
glGetProgramiv(_progID, GL_LINK_STATUS, &state);
|
|
||||||
|
|
||||||
if (!state) {
|
|
||||||
int logLength;
|
|
||||||
glGetProgramiv(_progID, GL_INFO_LOG_LENGTH, &logLength);
|
|
||||||
|
|
||||||
char *log = new char[logLength];
|
|
||||||
glGetProgramInfoLog(_progID, logLength, NULL, log);
|
|
||||||
std::string msg(log);
|
|
||||||
delete[] log;
|
|
||||||
|
|
||||||
glDeleteProgram(_progID);
|
|
||||||
|
|
||||||
throw ShaderException(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
glDetachShader(_progID, _vertex.getID());
|
|
||||||
glDetachShader(_progID, _frag.getID());
|
|
||||||
}
|
|
||||||
|
|
||||||
Program(GeometryShader& geom, VertexShader& vertex, FragmentShader& frag)
|
|
||||||
: _geom(&geom), _vertex(vertex), _frag(frag), _progID(glCreateProgram()) {
|
|
||||||
glAttachShader(_progID, _geom->getID());
|
|
||||||
glAttachShader(_progID, _vertex.getID());
|
|
||||||
glAttachShader(_progID, _frag.getID());
|
|
||||||
|
|
||||||
glLinkProgram(_progID);
|
|
||||||
|
|
||||||
int state;
|
|
||||||
glGetProgramiv(_progID, GL_LINK_STATUS, &state);
|
|
||||||
|
|
||||||
if (!state) {
|
|
||||||
int logLength;
|
|
||||||
glGetProgramiv(_progID, GL_INFO_LOG_LENGTH, &logLength);
|
|
||||||
|
|
||||||
char *log = new char[logLength];
|
|
||||||
glGetProgramInfoLog(_progID, logLength, NULL, log);
|
|
||||||
std::string msg(log);
|
|
||||||
delete[] log;
|
|
||||||
|
|
||||||
glDeleteProgram(_progID);
|
|
||||||
|
|
||||||
throw ShaderException(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
glDetachShader(_progID, _geom->getID());
|
|
||||||
glDetachShader(_progID, _vertex.getID());
|
|
||||||
glDetachShader(_progID, _frag.getID());
|
|
||||||
}
|
|
||||||
|
|
||||||
~Program() {
|
~Program();
|
||||||
glDeleteProgram(_progID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void use() const {
|
void use() const;
|
||||||
glUseProgram(_progID);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLint getUniformLocation(std::string const& name) const {
|
gl::GLint getUniformLocation(std::string const& name) const;
|
||||||
auto search = _uniformLocCache.find(name);
|
|
||||||
if (search != _uniformLocCache.end())
|
|
||||||
return search->second;
|
|
||||||
|
|
||||||
GLint ret = glGetUniformLocation(_progID, name.c_str());
|
|
||||||
if (ret != -1)
|
|
||||||
_uniformLocCache.emplace(name, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLint getAttribLocation(std::string const& name) const {
|
gl::GLint getAttribLocation(std::string const& name) const;
|
||||||
auto search = _attribLocCache.find(name);
|
|
||||||
if (search != _attribLocCache.end())
|
|
||||||
return search->second;
|
|
||||||
|
|
||||||
GLint ret = glGetAttribLocation(_progID, name.c_str());
|
|
||||||
if (ret != -1)
|
|
||||||
_attribLocCache.emplace(name, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GeometryShader* _geom;
|
GeometryShader* _geom;
|
||||||
@@ -194,7 +86,7 @@ private:
|
|||||||
FragmentShader& _frag;
|
FragmentShader& _frag;
|
||||||
unsigned _progID;
|
unsigned _progID;
|
||||||
|
|
||||||
mutable std::unordered_map<std::string, GLint> _uniformLocCache, _attribLocCache;
|
mutable std::unordered_map<std::string, gl::GLint> _uniformLocCache, _attribLocCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
11
shaders/overlay.fs
Normal file
11
shaders/overlay.fs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
uniform sampler2D texBase;
|
||||||
|
|
||||||
|
in vec2 fragTC;
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
color = texture(texBase, fragTC);
|
||||||
|
}
|
||||||
13
shaders/overlay.vs
Normal file
13
shaders/overlay.vs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#version 330 core
|
||||||
|
#extension GL_ARB_shading_language_420pack : enable
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 vertex;
|
||||||
|
layout(location = 1) in vec2 vertexTC;
|
||||||
|
|
||||||
|
out vec2 fragTC;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 pos = vec4(vertex, 0.0, 1.0);
|
||||||
|
gl_Position = pos;
|
||||||
|
fragTC = vertexTC;
|
||||||
|
}
|
||||||
@@ -8,15 +8,17 @@ uniform samplerCubeShadow texShadowMaps[lights];
|
|||||||
float VectorToDepth (vec3 Vec)
|
float VectorToDepth (vec3 Vec)
|
||||||
{
|
{
|
||||||
vec3 AbsVec = abs(Vec);
|
vec3 AbsVec = abs(Vec);
|
||||||
float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));
|
//float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));
|
||||||
|
float LocalZcomp = length(AbsVec);
|
||||||
|
|
||||||
// Replace f and n with the far and near plane values you used when
|
// Replace f and n with the far and near plane values you used when
|
||||||
// you drew your cube map.
|
// you drew your cube map.
|
||||||
const float f = 128.0;
|
const float f = 128.0;
|
||||||
const float n = 1.0;
|
const float n = 1.0;
|
||||||
|
|
||||||
float NormZComp = (f+n) / (f-n) - (2*f*n)/(f-n)/LocalZcomp;
|
// float NormZComp = (f+n) / (f-n) - (2*f*n)/(f-n)/LocalZcomp;
|
||||||
return (NormZComp + 1.0) * 0.5;
|
return (f/(f-n))+(f*n/(n-f))/LocalZcomp;
|
||||||
|
//return (NormZComp + 1.0) * 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
in vec2 fragTC;
|
in vec2 fragTC;
|
||||||
@@ -27,7 +29,7 @@ in vec3 lightVecs[lights];
|
|||||||
|
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|
||||||
const float bias = 0.00;
|
const float bias = 0.0;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 texColor = texture(texBase, fragTC);
|
vec4 texColor = texture(texBase, fragTC);
|
||||||
|
|||||||
214
texture.cc
Normal file
214
texture.cc
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
#include <glbinding/gl/gl.h>
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
|
||||||
|
#include "texture.hh"
|
||||||
|
|
||||||
|
using namespace gl;
|
||||||
|
|
||||||
|
static unsigned ilog2(unsigned in)
|
||||||
|
{
|
||||||
|
unsigned ret = 0u, orig = in;
|
||||||
|
while (in >>= 1) ++ret;
|
||||||
|
// if ((1<<ret) < orig) ++ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Framebuffer::Framebuffer()
|
||||||
|
: _fbID(0)
|
||||||
|
{
|
||||||
|
glGenFramebuffers(1, &_fbID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Framebuffer::~Framebuffer()
|
||||||
|
{
|
||||||
|
glDeleteFramebuffers(1, &_fbID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Framebuffer::bind() const
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Framebuffer::attachTexture(GLenum textarget, GLuint texID)
|
||||||
|
{
|
||||||
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||||
|
textarget, texID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TextureCubeMap::TextureCubeMap(unsigned size)
|
||||||
|
: _texID(0)
|
||||||
|
{
|
||||||
|
glGenTextures(1, &_texID);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, _texID);
|
||||||
|
|
||||||
|
if(SDL_GL_ExtensionSupported("GL_ARB_texture_storage"))
|
||||||
|
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT24,
|
||||||
|
size, size);
|
||||||
|
else {
|
||||||
|
std::printf("Warning: extension GL_ARB_texture_storage not supported!\n");
|
||||||
|
for (unsigned i = 0;i < 6;++i) {
|
||||||
|
GLenum const face[6] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
|
||||||
|
glTexImage2D(face[i], 0, static_cast<GLint>(GL_DEPTH_COMPONENT16), size, size, 0,
|
||||||
|
GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, static_cast<GLint>(GL_LINEAR));
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, static_cast<GLint>(GL_LINEAR));
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureCubeMap::~TextureCubeMap()
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &_texID);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureCubeMap::TextureCubeMap(TextureCubeMap && move)
|
||||||
|
: _texID(move._texID)
|
||||||
|
{
|
||||||
|
move._texID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureCubeMap& TextureCubeMap::operator=(TextureCubeMap && move)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &_texID);
|
||||||
|
_texID = move._texID;
|
||||||
|
move._texID = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureCubeMap::bind() const
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, _texID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Texture2D::Texture2D(unsigned width, unsigned height)
|
||||||
|
: _texID(0)
|
||||||
|
{
|
||||||
|
_glCreate(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D::Texture2D(std::string const& file)
|
||||||
|
: _texID(0)
|
||||||
|
{
|
||||||
|
SDL_Surface *surf = IMG_Load(file.c_str());
|
||||||
|
if (!surf)
|
||||||
|
throw SDLException();
|
||||||
|
|
||||||
|
try {
|
||||||
|
_glCreate(surf->w, surf->h);
|
||||||
|
try {
|
||||||
|
assert(surf->format->format == SDL_PIXELFORMAT_RGB24); // TODO: Proper support of many formats
|
||||||
|
if (SDL_MUSTLOCK(surf))
|
||||||
|
SDL_LockSurface(surf);
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGB, GL_UNSIGNED_BYTE, surf->pixels);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
} catch(...) {
|
||||||
|
glDeleteTextures(1, &_texID);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...) {
|
||||||
|
SDL_FreeSurface(surf);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
SDL_FreeSurface(surf);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D::Texture2D(SDL_Surface *surface)
|
||||||
|
: _texID(0)
|
||||||
|
{
|
||||||
|
if(surface->format->Amask == 0)
|
||||||
|
_glCreate(surface->w, surface->h);
|
||||||
|
else
|
||||||
|
_glCreate(surface->w, surface->h, true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
SDL_Surface *surf;
|
||||||
|
if((surface->format->format != SDL_PIXELFORMAT_RGB24) &&
|
||||||
|
(surface->format->format != SDL_PIXELFORMAT_RGBA8888)) {
|
||||||
|
if(surface->format->Amask == 0) {
|
||||||
|
surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGB24, 0);
|
||||||
|
} else {
|
||||||
|
surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
|
||||||
|
}
|
||||||
|
if(!surf)
|
||||||
|
throw SDLException{};
|
||||||
|
} else {
|
||||||
|
surf = surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_MUSTLOCK(surf))
|
||||||
|
SDL_LockSurface(surf);
|
||||||
|
try {
|
||||||
|
if(surface->format->Amask == 0)
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGB, GL_UNSIGNED_BYTE, surf->pixels);
|
||||||
|
else
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
} catch(...) {
|
||||||
|
if (surf != surface)
|
||||||
|
SDL_FreeSurface(surf);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
SDL_FreeSurface(surf);
|
||||||
|
} catch(...) {
|
||||||
|
glDeleteTextures(1, &_texID);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D::Texture2D(Texture2D&& move)
|
||||||
|
: _texID(move._texID)
|
||||||
|
{
|
||||||
|
move._texID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D& Texture2D::operator=(Texture2D&& move)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &_texID);
|
||||||
|
_texID = move._texID;
|
||||||
|
move._texID = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D::~Texture2D()
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &_texID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture2D::bind() const
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _texID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture2D::_glCreate(unsigned width, unsigned height, bool alpha)
|
||||||
|
{
|
||||||
|
glGenTextures(1, &_texID);
|
||||||
|
try {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _texID);
|
||||||
|
unsigned logWidth = ilog2(width), logHeight = ilog2(height);
|
||||||
|
unsigned levels = std::max(logWidth,logHeight)+1u;
|
||||||
|
if(SDL_GL_ExtensionSupported("GL_ARB_texture_storage"))
|
||||||
|
glTexStorage2D(GL_TEXTURE_2D, levels, alpha?GL_RGBA8:GL_RGB8, width, height);
|
||||||
|
else {
|
||||||
|
std::printf("Warning: extension GL_ARB_texture_storage not supported!\n");
|
||||||
|
for (unsigned i = 0u; i < levels; ++i)
|
||||||
|
{
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, i, static_cast<const int>(alpha?GL_RGBA8:GL_RGB8), width, height, 0,
|
||||||
|
alpha?GL_RGBA8:GL_RGB8, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
width = std::max(1u, (width / 2u));
|
||||||
|
height = std::max(1u, (height / 2u));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
glDeleteTextures(1, &_texID);
|
||||||
|
}
|
||||||
|
}
|
||||||
145
texture.hh
145
texture.hh
@@ -6,168 +6,73 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <glbinding/gl/types.h>
|
||||||
#include <SDL2/SDL_image.h>
|
|
||||||
|
|
||||||
#include <glbinding/gl/gl.h>
|
|
||||||
|
|
||||||
#include "common.hh"
|
#include "common.hh"
|
||||||
|
|
||||||
using namespace gl;
|
|
||||||
|
|
||||||
static unsigned ilog2(unsigned in)
|
|
||||||
{
|
|
||||||
unsigned ret = 0u;
|
|
||||||
while (in >>= 1) ++ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Framebuffer {
|
class Framebuffer {
|
||||||
public:
|
public:
|
||||||
Framebuffer() : _fbID(0) {
|
Framebuffer();
|
||||||
glGenFramebuffers(1, &_fbID);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Framebuffer() {
|
~Framebuffer();
|
||||||
glDeleteFramebuffers(1, &_fbID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bind() const {
|
void bind() const;
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbID);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint getID() const {
|
gl::GLuint getID() const {
|
||||||
return _fbID;
|
return _fbID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void attachTexture(GLenum textarget, GLuint texID) {
|
void attachTexture(GLenum textarget, gl::GLuint texID);
|
||||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
|
||||||
textarget, texID, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint _fbID;
|
gl::GLuint _fbID;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureCubeMap {
|
class TextureCubeMap {
|
||||||
public:
|
public:
|
||||||
TextureCubeMap(unsigned size) : _texID(0) {
|
TextureCubeMap(unsigned size);
|
||||||
glGenTextures(1, &_texID);
|
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, _texID);
|
|
||||||
|
|
||||||
if(SDL_GL_ExtensionSupported("GL_ARB_texture_storage"))
|
|
||||||
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT24,
|
|
||||||
size, size);
|
|
||||||
else {
|
|
||||||
std::printf("Warning: extension GL_ARB_texture_storage not supported!\n");
|
|
||||||
for (unsigned i = 0;i < 6;++i) {
|
|
||||||
GLenum const face[6] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
|
|
||||||
glTexImage2D(face[i], 0, static_cast<GLint>(GL_DEPTH_COMPONENT16), size, size, 0,
|
|
||||||
GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, static_cast<GLint>(GL_LINEAR));
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, static_cast<GLint>(GL_LINEAR));
|
|
||||||
}
|
|
||||||
|
|
||||||
~TextureCubeMap() {
|
~TextureCubeMap();
|
||||||
glDeleteTextures(1, &_texID);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureCubeMap(TextureCubeMap const& copy) = delete;
|
TextureCubeMap(TextureCubeMap const& copy) = delete;
|
||||||
TextureCubeMap& operator=(TextureCubeMap const& copy) = delete;
|
TextureCubeMap& operator=(TextureCubeMap const& copy) = delete;
|
||||||
|
|
||||||
TextureCubeMap(TextureCubeMap && move) : _texID(move._texID) {
|
TextureCubeMap(TextureCubeMap && move);
|
||||||
move._texID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureCubeMap& operator=(TextureCubeMap && move) {
|
TextureCubeMap& operator=(TextureCubeMap && move);
|
||||||
glDeleteTextures(1, &_texID);
|
|
||||||
_texID = move._texID;
|
|
||||||
move._texID = 0;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bind() const {
|
void bind() const;
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, _texID);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint getID() const {
|
gl::GLuint getID() const {
|
||||||
return _texID;
|
return _texID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint _texID;
|
gl::GLuint _texID;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Texture2D {
|
class Texture2D {
|
||||||
public:
|
public:
|
||||||
Texture2D(unsigned width, unsigned height) : _texID(0) {
|
Texture2D(unsigned width, unsigned height);
|
||||||
_glCreate(width, height);
|
Texture2D(std::string const& file);
|
||||||
}
|
Texture2D(SDL_Surface *surface);
|
||||||
|
|
||||||
Texture2D(std::string const& file) : _texID(0) {
|
Texture2D(Texture2D const& copy) = delete;
|
||||||
SDL_Surface *surf = IMG_Load(file.c_str());
|
Texture2D& operator=(Texture2D const& copy) = delete;
|
||||||
if (!surf)
|
|
||||||
throw SDLException();
|
|
||||||
|
|
||||||
try {
|
Texture2D(Texture2D&& move);
|
||||||
_glCreate(surf->w, surf->h);
|
Texture2D& operator=(Texture2D&& move);
|
||||||
try {
|
|
||||||
assert(surf->format->format == SDL_PIXELFORMAT_RGB24); // TODO: Proper support of many formats
|
|
||||||
if (SDL_MUSTLOCK(surf))
|
|
||||||
SDL_LockSurface(surf);
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGB, GL_UNSIGNED_BYTE, surf->pixels);
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
|
||||||
} catch(...) {
|
|
||||||
glDeleteTextures(1, &_texID);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(...) {
|
|
||||||
SDL_FreeSurface(surf);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
SDL_FreeSurface(surf);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Texture2D() {
|
~Texture2D();
|
||||||
glDeleteTextures(1, &_texID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bind() {
|
void bind() const;
|
||||||
glBindTexture(GL_TEXTURE_2D, _texID);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void _glCreate(unsigned width, unsigned height) {
|
void _glCreate(unsigned width, unsigned height, bool alpha = false);
|
||||||
glGenTextures(1, &_texID);
|
|
||||||
try {
|
|
||||||
glBindTexture(GL_TEXTURE_2D, _texID);
|
|
||||||
unsigned logWidth = ilog2(width), logHeight = ilog2(height);
|
|
||||||
unsigned levels = std::max(logWidth,logHeight)+1u;
|
|
||||||
if(SDL_GL_ExtensionSupported("GL_ARB_texture_storage"))
|
|
||||||
glTexStorage2D(GL_TEXTURE_2D, levels, GL_RGB8, width, height);
|
|
||||||
else {
|
|
||||||
std::printf("Warning: extension GL_ARB_texture_storage not supported!\n");
|
|
||||||
for (unsigned i = 0u; i < levels; ++i)
|
|
||||||
{
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, i, static_cast<const int>(GL_RGB8), width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
width = std::max(1u, (width / 2u));
|
|
||||||
height = std::max(1u, (height / 2u));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(...) {
|
|
||||||
glDeleteTextures(1, &_texID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint _texID;
|
gl::GLuint _texID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user