Files
wc3re/render/Overlay.cc

115 lines
3.8 KiB
C++

#include <glbinding/gl/gl.h>
#include <SDL2/SDL.h>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Overlay.hh"
#include "renderutil.hh"
#include "VBOManager.hh"
#include "ProgramProvider.hh"
#include "Renderer.hh"
using namespace gl;
namespace render {
namespace {
struct VertexAttribs {
int16_t vertex[2];
uint16_t texCoords[2];
};
}
Overlay::Overlay(Renderer& renderer, int width, int height, int left, int top, int intWidth, int intHeight)
: Drawable(renderer), texture_(create2DTexture(intWidth, intHeight, true, 1)),
vbo_(VBOManager::getInstance().alloc(sizeof(VertexAttribs)*6)),
width_(width), height_(height), top_(top), left_(left), intWidth_(intWidth), intHeight_(intHeight)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, static_cast<int>(GL_LINEAR));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<int>(GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast<int>(GL_CLAMP_TO_EDGE));
program_ = ProgramProvider::getInstance().getProgram("overlay", "overlay");
glGenVertexArrays(1, &vertexArray_.get());
short int t = top_, l = left_, b = height+top_, r = width+left_;
std::vector<VertexAttribs> vertexAttribs{
{{l, t}, {0, 0}},
{{r, b}, {65535u, 65535u}},
{{r, t}, {65535u, 0}},
{{l, t}, {0, 0}},
{{l, b}, {0, 65535u}},
{{r, b}, {65535u, 65535u}}};
glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId());
glBindVertexArray(vertexArray_);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE, sizeof(VertexAttribs),
vbo_.getOfs(offsetof(VertexAttribs, vertex)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(VertexAttribs),
vbo_.getOfs(offsetof(VertexAttribs, texCoords)));
glBufferSubData(GL_ARRAY_BUFFER, vbo_.getBase(),
sizeof(VertexAttribs)*6,
vertexAttribs.data());
ovlProj_ = glm::ortho(0.0f, static_cast<float>(renderer_.getWidth()),
static_cast<float>(renderer_.getHeight()), 0.0f);
}
void Overlay::draw()
{
glDisable(GL_DEPTH_TEST);
useProgram(program_);
glUniformMatrix4fv(0, 1, GL_FALSE, glm::value_ptr(ovlProj_));
glUniform1i(1, 0);
glBindTexture(GL_TEXTURE_2D, texture_);
glBindVertexArray(vertexArray_);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
// void Overlay::clear()
// {
// if (SDL_GL_ExtensionSupported("GL_ARB_clear_texture"))
// glClearTexImage(texture_, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
// else {
// std::vector<uint8_t> zeros(intWidth_*intHeight_*4, 0u);
// setContentBGRA8(zeros.data());
// }
// }
void Overlay::setContent(SDL_Surface *content)
{
if (!content ||
(content->h > intHeight_) ||
(content->w > intWidth_))
throw Exception{"null or mismatched surface"};
glBindTexture(GL_TEXTURE_2D, texture_);
if (content->format->format != SDL_PIXELFORMAT_ARGB8888) {
printf("Warning: Format conversion in Overlay::setContent\n");
SDLSurfaceUPtr tmpSurf(SDL_ConvertSurfaceFormat(content, SDL_PIXELFORMAT_ARGB8888, 0));
if (!tmpSurf)
throw SDLException{};
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tmpSurf->w, tmpSurf->h, GL_BGRA, GL_UNSIGNED_BYTE, tmpSurf->pixels);
} else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, content->w, content->h, GL_BGRA, GL_UNSIGNED_BYTE, content->pixels);
}
void Overlay::setContentRGB8(void *data)
{
glBindTexture(GL_TEXTURE_2D, texture_);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, intWidth_, intHeight_, GL_RGB, GL_UNSIGNED_BYTE, data);
}
void Overlay::setContentBGRA8(void *data)
{
glBindTexture(GL_TEXTURE_2D, texture_);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, intWidth_, intHeight_, GL_BGRA, GL_UNSIGNED_BYTE, data);
}
}