X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fgraphics%2Frender.cpp;h=9468b68b794b8640558c986870f885c5e171c26d;hb=2e3774eb3f2d5d23a08731175b168566457e2192;hp=f78f9cb6f77fc2b92f1e5e7ad3b137cda65c4aed;hpb=5998b18978bd8e7a0c9deb516474634e1d3521c9;p=blank.git diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index f78f9cb..9468b68 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -1,12 +1,13 @@ -#include "BlendedSprite.hpp" -#include "FixedText.hpp" +#include "ArrayTexture.hpp" +#include "CubeMap.hpp" #include "Font.hpp" #include "Format.hpp" -#include "MessageBox.hpp" -#include "Text.hpp" #include "Texture.hpp" +#include "TextureBase.hpp" #include "Viewport.hpp" +#include "../app/init.hpp" + #include #include #include @@ -104,8 +105,8 @@ bool Font::HasGlyph(Uint16 c) const noexcept { } -glm::tvec2 Font::TextSize(const char *text) const { - glm::tvec2 size; +glm::ivec2 Font::TextSize(const char *text) const { + glm::ivec2 size; if (TTF_SizeUTF8(handle, text, &size.x, &size.y) != 0) { throw std::runtime_error(TTF_GetError()); } @@ -129,8 +130,32 @@ void Font::Render(const char *text, Texture &tex) const { SDL_FreeSurface(srf); } - -void Format::ReadPixelFormat(const SDL_PixelFormat &fmt) { +Format::Format() noexcept +: format(GL_BGRA) +, type(GL_UNSIGNED_INT_8_8_8_8_REV) +, internal(GL_RGBA8) { + sdl_format.format = SDL_PIXELFORMAT_ARGB8888; + sdl_format.palette = nullptr; + sdl_format.BitsPerPixel = 32; + sdl_format.BytesPerPixel = 4; + sdl_format.Rmask = 0x00FF0000; + sdl_format.Gmask = 0x0000FF00; + sdl_format.Bmask = 0x000000FF; + sdl_format.Amask = 0xFF000000; + sdl_format.Rloss = 0; + sdl_format.Gloss = 0; + sdl_format.Bloss = 0; + sdl_format.Aloss = 0; + sdl_format.Rshift = 16; + sdl_format.Gshift = 8; + sdl_format.Bshift = 0; + sdl_format.Ashift = 24; + sdl_format.refcount = 1; + sdl_format.next = nullptr; +} + +Format::Format(const SDL_PixelFormat &fmt) noexcept +: sdl_format(fmt) { if (fmt.BytesPerPixel == 4) { if (fmt.Amask == 0xFF) { if (fmt.Rmask == 0xFF00) { @@ -159,144 +184,59 @@ void Format::ReadPixelFormat(const SDL_PixelFormat &fmt) { } } - -MessageBox::MessageBox(const Font &f) -: font(f) -, lines() -, max_lines(10) -, pos(0.0f) -, adv(0.0f, font.LineSkip(), 0.0f) -, bg(1.0f, 1.0f, 1.0f, 0.0f) -, fg(1.0f, 1.0f, 1.0f, 1.0f) -, grav(Gravity::NORTH_WEST) { - -} - -void MessageBox::Position(const glm::vec3 &p, Gravity g) noexcept { - pos = p; - grav = g; - if (get_y(g) == Align::END) { - adv.y = -font.LineSkip(); - } else { - adv.y = font.LineSkip(); - } - for (Text &txt : lines) { - txt.Pivot(g); - } -} - -void MessageBox::PushLine(const char *text) { - lines.emplace_front(); - Text &txt = lines.front(); - txt.Set(font, text); - txt.Pivot(grav); - - while (lines.size() > max_lines) { - lines.pop_back(); - } -} - -void MessageBox::Render(Viewport &viewport) noexcept { - BlendedSprite &prog = viewport.SpriteProgram(); - prog.SetBG(bg); - prog.SetFG(fg); - viewport.SetCursor(pos, grav); - for (Text &txt : lines) { - prog.SetM(viewport.Cursor()); - txt.Render(viewport); - viewport.MoveCursor(adv); - } -} - - -Text::Text() noexcept -: tex() -, sprite() -, size(0.0f) -, pivot(Gravity::NORTH_WEST) -, dirty(false) { - +bool Format::Compatible(const Format &other) const noexcept { + return format == other.format && type == other.type && internal == other.internal; } -FixedText::FixedText() noexcept -: Text() -, bg(1.0f, 1.0f, 1.0f, 0.0f) -, fg(1.0f, 1.0f, 1.0f, 1.0f) -, pos(0.0f) -, grav(Gravity::NORTH_WEST) -, visible(false) { - -} - -void Text::Set(const Font &font, const char *text) { - font.Render(text, tex); - size = font.TextSize(text); - dirty = true; -} - -namespace { - -SpriteModel::Buffer sprite_buf; +template +TextureBase::TextureBase() { + glGenTextures(COUNT, handle); } -void Text::Update() { - sprite_buf.LoadRect(size.x, size.y, align(pivot, size)); - sprite.Update(sprite_buf); - dirty = false; +template +TextureBase::~TextureBase() { + glDeleteTextures(COUNT, handle); } -void FixedText::Render(Viewport &viewport) noexcept { - BlendedSprite &prog = viewport.SpriteProgram(); - viewport.SetCursor(pos, grav); - prog.SetM(viewport.Cursor()); - prog.SetBG(bg); - prog.SetFG(fg); - Text::Render(viewport); +template +TextureBase::TextureBase(TextureBase &&other) noexcept { + std::memcpy(handle, other.handle, sizeof(handle)); + std::memset(other.handle, 0, sizeof(handle)); } -void Text::Render(Viewport &viewport) noexcept { - if (dirty) { - Update(); - } - BlendedSprite &prog = viewport.SpriteProgram(); - prog.SetTexture(tex); - sprite.Draw(); +template +TextureBase &TextureBase::operator =(TextureBase &&other) noexcept { + std::swap(handle, other.handle); + return *this; } Texture::Texture() -: handle(0) +: TextureBase() , width(0) , height(0) { - glGenTextures(1, &handle); + } Texture::~Texture() { - if (handle != 0) { - glDeleteTextures(1, &handle); - } + } Texture::Texture(Texture &&other) noexcept -: handle(other.handle) { - other.handle = 0; +: TextureBase(std::move(other)) { width = other.width; height = other.height; } Texture &Texture::operator =(Texture &&other) noexcept { - std::swap(handle, other.handle); + TextureBase::operator =(std::move(other)); width = other.width; height = other.height; return *this; } -void Texture::Bind() noexcept { - glBindTexture(GL_TEXTURE_2D, handle); -} - namespace { bool ispow2(unsigned int i) { // don't care about i == 0 here @@ -305,8 +245,7 @@ namespace { } void Texture::Data(const SDL_Surface &srf, bool pad2) noexcept { - Format format; - format.ReadPixelFormat(*srf.format); + Format format(*srf.format); if (!pad2 || (ispow2(srf.w) && ispow2(srf.h))) { int align = UnpackAlignmentFromPitch(srf.pitch); @@ -368,25 +307,6 @@ void Texture::Data(GLsizei w, GLsizei h, const Format &format, GLvoid *data) noe } -void Texture::FilterNearest() noexcept { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); -} - -void Texture::FilterLinear() noexcept { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -} - -void Texture::FilterTrilinear() noexcept { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glGenerateMipmap(GL_TEXTURE_2D); -} - - void Texture::UnpackAlignment(GLint i) noexcept { glPixelStorei(GL_UNPACK_ALIGNMENT, i); } @@ -404,4 +324,140 @@ void Texture::UnpackRowLength(GLint i) noexcept { glPixelStorei(GL_UNPACK_ROW_LENGTH, i); } + +ArrayTexture::ArrayTexture() +: TextureBase() +, width(0) +, height(0) +, depth(0) { + +} + +ArrayTexture::~ArrayTexture() { + +} + +ArrayTexture::ArrayTexture(ArrayTexture &&other) noexcept +: TextureBase(std::move(other)) { + width = other.width; + height = other.height; + depth = other.depth; +} + +ArrayTexture &ArrayTexture::operator =(ArrayTexture &&other) noexcept { + TextureBase::operator =(std::move(other)); + width = other.width; + height = other.height; + depth = other.depth; + return *this; +} + + +void ArrayTexture::Reserve(GLsizei w, GLsizei h, GLsizei d, const Format &f) noexcept { + glTexStorage3D( + GL_TEXTURE_2D_ARRAY, // which + 1, // mipmap count + f.internal, // format + w, h, // dimensions + d // layer count + ); + width = w; + height = h; + depth = d; + format = f; +} + +void ArrayTexture::Data(GLsizei l, const SDL_Surface &srf) { + Format fmt(*srf.format); + if (format.Compatible(fmt)) { + Data(l, fmt, srf.pixels); + } else { + SDL_Surface *converted = SDL_ConvertSurface( + const_cast(&srf), + &format.sdl_format, + 0 + ); + if (!converted) { + throw SDLError("SDL_ConvertSurface"); + } + Format new_fmt(*converted->format); + if (!format.Compatible(new_fmt)) { + SDL_FreeSurface(converted); + throw std::runtime_error("unable to convert texture input"); + } + Data(l, new_fmt, converted->pixels); + SDL_FreeSurface(converted); + } +} + +void ArrayTexture::Data(GLsizei l, const Format &f, GLvoid *data) noexcept { + glTexSubImage3D( + GL_TEXTURE_2D_ARRAY, // which + 0, // mipmap lavel + 0, 0, // dest X and Y offset + l, // layer offset + width, height, + 1, // layer count + f.format, f.type, + data + ); +} + + +CubeMap::CubeMap() +: TextureBase() { + +} + +CubeMap::~CubeMap() { + +} + +CubeMap::CubeMap(CubeMap &&other) noexcept +: TextureBase(std::move(other)) { + +} + +CubeMap &CubeMap::operator =(CubeMap &&other) noexcept { + TextureBase::operator =(std::move(other)); + return *this; +} + + +void CubeMap::Data(Face f, const SDL_Surface &srf) { + Format format; + Format fmt(*srf.format); + if (format.Compatible(fmt)) { + Data(f, srf.w, srf.h, fmt, srf.pixels); + } else { + SDL_Surface *converted = SDL_ConvertSurface( + const_cast(&srf), + &format.sdl_format, + 0 + ); + if (!converted) { + throw SDLError("SDL_ConvertSurface"); + } + Format new_fmt(*converted->format); + if (!format.Compatible(new_fmt)) { + SDL_FreeSurface(converted); + throw std::runtime_error("unable to convert texture input"); + } + Data(f, converted->w, converted->h, new_fmt, converted->pixels); + SDL_FreeSurface(converted); + } +} + +void CubeMap::Data(Face face, GLsizei w, GLsizei h, const Format &f, GLvoid *data) noexcept { + glTexImage2D( + face, // which + 0, // mipmap level + f.internal, // internal format + w, h, // size + 0, // border + f.format, f.type, // pixel format + data // pixel data + ); +} + }