From be3a81656b8493010d2329fa00da617e24293438 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Wed, 23 Sep 2015 11:41:39 +0200 Subject: [PATCH] cube map textures --- src/app/Assets.hpp | 2 + src/app/app.cpp | 40 +++++++++++ src/graphics/ArrayTexture.hpp | 12 +--- src/graphics/CubeMap.hpp | 45 ++++++++++++ src/graphics/Format.hpp | 4 +- src/graphics/Texture.hpp | 13 ++-- src/graphics/TextureBase.hpp | 69 +++++++++++++++++++ src/graphics/render.cpp | 125 ++++++++++++++++++---------------- 8 files changed, 232 insertions(+), 78 deletions(-) create mode 100644 src/graphics/CubeMap.hpp create mode 100644 src/graphics/TextureBase.hpp diff --git a/src/app/Assets.hpp b/src/app/Assets.hpp index d1a4ae7..db0933f 100644 --- a/src/app/Assets.hpp +++ b/src/app/Assets.hpp @@ -10,6 +10,7 @@ namespace blank { class ArrayTexture; class BlockTypeRegistry; +class CubeMap; class Sound; class Texture; class TextureIndex; @@ -20,6 +21,7 @@ public: explicit AssetLoader(const std::string &base); void LoadBlockTypes(const std::string &set_name, BlockTypeRegistry &, TextureIndex &) const; + CubeMap LoadCubeMap(const std::string &name) const; Font LoadFont(const std::string &name, int size) const; Sound LoadSound(const std::string &name) const; Texture LoadTexture(const std::string &name) const; diff --git a/src/app/app.cpp b/src/app/app.cpp index 4368022..6e7201a 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -9,6 +9,7 @@ #include "init.hpp" #include "../audio/Sound.hpp" #include "../graphics/ArrayTexture.hpp" +#include "../graphics/CubeMap.hpp" #include "../graphics/Font.hpp" #include "../graphics/Texture.hpp" #include "../io/TokenStreamReader.hpp" @@ -374,6 +375,45 @@ void AssetLoader::LoadBlockTypes(const std::string &set_name, BlockTypeRegistry } } +CubeMap AssetLoader::LoadCubeMap(const string &name) const { + string full = textures + name; + string right = full + "-right.png"; + string left = full + "-left.png"; + string top = full + "-top.png"; + string bottom = full + "-bottom.png"; + string back = full + "-back.png"; + string front = full + "-front.png"; + + CubeMap cm; + SDL_Surface *srf; + + if (!(srf = IMG_Load(right.c_str()))) throw SDLError("IMG_Load"); + cm.Data(CubeMap::RIGHT, *srf); + SDL_FreeSurface(srf); + + if (!(srf = IMG_Load(left.c_str()))) throw SDLError("IMG_Load"); + cm.Data(CubeMap::LEFT, *srf); + SDL_FreeSurface(srf); + + if (!(srf = IMG_Load(top.c_str()))) throw SDLError("IMG_Load"); + cm.Data(CubeMap::TOP, *srf); + SDL_FreeSurface(srf); + + if (!(srf = IMG_Load(bottom.c_str()))) throw SDLError("IMG_Load"); + cm.Data(CubeMap::BOTTOM, *srf); + SDL_FreeSurface(srf); + + if (!(srf = IMG_Load(back.c_str()))) throw SDLError("IMG_Load"); + cm.Data(CubeMap::BACK, *srf); + SDL_FreeSurface(srf); + + if (!(srf = IMG_Load(front.c_str()))) throw SDLError("IMG_Load"); + cm.Data(CubeMap::FRONT, *srf); + SDL_FreeSurface(srf); + + return cm; +} + Font AssetLoader::LoadFont(const string &name, int size) const { string full = fonts + name + ".ttf"; return Font(full.c_str(), size); diff --git a/src/graphics/ArrayTexture.hpp b/src/graphics/ArrayTexture.hpp index 93b560e..3adb44e 100644 --- a/src/graphics/ArrayTexture.hpp +++ b/src/graphics/ArrayTexture.hpp @@ -2,6 +2,7 @@ #define BLANK_GRAPHICS_ARRAYTEXTURE_HPP_ #include "Format.hpp" +#include "TextureBase.hpp" #include @@ -10,7 +11,8 @@ struct SDL_Surface; namespace blank { -class ArrayTexture { +class ArrayTexture +: public TextureBase { public: ArrayTexture(); @@ -27,19 +29,11 @@ public: GLsizei Height() const noexcept { return height; } GLsizei Depth() const noexcept { return depth; } - void Bind() noexcept; - void Reserve(GLsizei w, GLsizei h, GLsizei d, const Format &) noexcept; void Data(GLsizei l, const SDL_Surface &); void Data(GLsizei l, const Format &, GLvoid *data) noexcept; - void FilterNearest() noexcept; - void FilterLinear() noexcept; - void FilterTrilinear() noexcept; - private: - GLuint handle; - GLsizei width, height, depth; Format format; diff --git a/src/graphics/CubeMap.hpp b/src/graphics/CubeMap.hpp new file mode 100644 index 0000000..b328196 --- /dev/null +++ b/src/graphics/CubeMap.hpp @@ -0,0 +1,45 @@ +#ifndef BLANK_GRAPHICS_CUBEMAP_HPP_ +#define BLANK_GRAPHICS_CUBEMAP_HPP_ + +#include "Format.hpp" +#include "TextureBase.hpp" + +#include + +struct SDL_Surface; + + +namespace blank { + +class CubeMap +: public TextureBase { + +public: + enum Face { + RIGHT = GL_TEXTURE_CUBE_MAP_POSITIVE_X, + LEFT = GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + TOP = GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + BOTTOM = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + BACK = GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + FRONT = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + }; + +public: + CubeMap(); + ~CubeMap(); + + CubeMap(CubeMap &&) noexcept; + CubeMap &operator =(CubeMap &&) noexcept; + + CubeMap(const CubeMap &) = delete; + CubeMap &operator =(const CubeMap &) = delete; + +public: + void Data(Face, const SDL_Surface &) noexcept; + void Data(Face, GLsizei w, GLsizei h, const Format &, GLvoid *data) noexcept; + +}; + +} + +#endif diff --git a/src/graphics/Format.hpp b/src/graphics/Format.hpp index 5762aab..194cc1c 100644 --- a/src/graphics/Format.hpp +++ b/src/graphics/Format.hpp @@ -15,8 +15,8 @@ struct Format { SDL_PixelFormat sdl_format; - Format(); - explicit Format(const SDL_PixelFormat &); + Format() noexcept; + explicit Format(const SDL_PixelFormat &) noexcept; bool Compatible(const Format &other) const noexcept; diff --git a/src/graphics/Texture.hpp b/src/graphics/Texture.hpp index 9e24a8d..f838808 100644 --- a/src/graphics/Texture.hpp +++ b/src/graphics/Texture.hpp @@ -1,6 +1,8 @@ #ifndef BLANK_GRAPHICS_TEXTURE_HPP_ #define BLANK_GRAPHICS_TEXTURE_HPP_ +#include "TextureBase.hpp" + #include struct SDL_Surface; @@ -10,7 +12,8 @@ namespace blank { struct Format; -class Texture { +class Texture +: public TextureBase { public: Texture(); @@ -26,22 +29,14 @@ public: GLsizei Width() const noexcept { return width; } GLsizei Height() const noexcept { return height; } - void Bind() noexcept; - void Data(const SDL_Surface &, bool pad2 = true) noexcept; void Data(GLsizei w, GLsizei h, const Format &, GLvoid *data) noexcept; - void FilterNearest() noexcept; - void FilterLinear() noexcept; - void FilterTrilinear() noexcept; - static void UnpackAlignment(GLint) noexcept; static int UnpackAlignmentFromPitch(int) noexcept; static void UnpackRowLength(GLint) noexcept; private: - GLuint handle; - GLsizei width, height; }; diff --git a/src/graphics/TextureBase.hpp b/src/graphics/TextureBase.hpp new file mode 100644 index 0000000..4c3e8a8 --- /dev/null +++ b/src/graphics/TextureBase.hpp @@ -0,0 +1,69 @@ +#ifndef BLANK_GRAPHICS_TEXTUREBASE_HPP_ +#define BLANK_GRAPHICS_TEXTUREBASE_HPP_ + +#include + + +namespace blank { + +template +class TextureBase { + +public: + TextureBase(); + ~TextureBase(); + + TextureBase(TextureBase &&other) noexcept; + TextureBase &operator =(TextureBase &&) noexcept; + + TextureBase(const TextureBase &) = delete; + TextureBase &operator =(const TextureBase &) = delete; + +public: + void Bind(GLsizei which = 0) noexcept { + glBindTexture(TARGET, handle[which]); + } + + void FilterNearest() noexcept { + glTexParameteri(TARGET, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(TARGET, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + void FilterLinear() noexcept { + glTexParameteri(TARGET, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(TARGET, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + void FilterTrilinear() noexcept { + glTexParameteri(TARGET, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(TARGET, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glGenerateMipmap(TARGET); + } + + void WrapEdge() noexcept { + glTexParameteri(TARGET, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + void WrapBorder() noexcept { + glTexParameteri(TARGET, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER); + glTexParameteri(TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + } + void WrapRepeat() noexcept { + glTexParameteri(TARGET, GL_TEXTURE_WRAP_R, GL_REPEAT); + glTexParameteri(TARGET, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(TARGET, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + void WrapMirror() noexcept { + glTexParameteri(TARGET, GL_TEXTURE_WRAP_R, GL_MIRRORED_REPEAT); + glTexParameteri(TARGET, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameteri(TARGET, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + } + +private: + GLuint handle[COUNT]; + +}; + +} + +#endif diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 470cb19..fdf751e 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -1,7 +1,9 @@ #include "ArrayTexture.hpp" +#include "CubeMap.hpp" #include "Font.hpp" #include "Format.hpp" #include "Texture.hpp" +#include "TextureBase.hpp" #include "Viewport.hpp" #include "../app/init.hpp" @@ -128,7 +130,7 @@ void Font::Render(const char *text, Texture &tex) const { SDL_FreeSurface(srf); } -Format::Format() +Format::Format() noexcept : format(GL_BGRA) , type(GL_UNSIGNED_INT_8_8_8_8_REV) , internal(GL_RGBA8) { @@ -152,7 +154,7 @@ Format::Format() sdl_format.next = nullptr; } -Format::Format(const SDL_PixelFormat &fmt) +Format::Format(const SDL_PixelFormat &fmt) noexcept : sdl_format(fmt) { if (fmt.BytesPerPixel == 4) { if (fmt.Amask == 0xFF) { @@ -187,38 +189,54 @@ bool Format::Compatible(const Format &other) const noexcept { } +template +TextureBase::TextureBase() { + glGenTextures(COUNT, handle); +} + +template +TextureBase::~TextureBase() { + glDeleteTextures(COUNT, handle); +} + +template +TextureBase::TextureBase(TextureBase &&other) noexcept { + std::memcpy(handle, other.handle, sizeof(handle)); + std::memset(other.handle, 0, sizeof(handle)); +} + +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 @@ -289,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); } @@ -327,29 +326,26 @@ void Texture::UnpackRowLength(GLint i) noexcept { ArrayTexture::ArrayTexture() -: handle(0) +: TextureBase() , width(0) , height(0) , depth(0) { - glGenTextures(1, &handle); + } ArrayTexture::~ArrayTexture() { - if (handle != 0) { - glDeleteTextures(1, &handle); - } + } ArrayTexture::ArrayTexture(ArrayTexture &&other) noexcept -: handle(other.handle) { - other.handle = 0; +: TextureBase(std::move(other)) { width = other.width; height = other.height; depth = other.depth; } ArrayTexture &ArrayTexture::operator =(ArrayTexture &&other) noexcept { - std::swap(handle, other.handle); + TextureBase::operator =(std::move(other)); width = other.width; height = other.height; depth = other.depth; @@ -357,11 +353,6 @@ ArrayTexture &ArrayTexture::operator =(ArrayTexture &&other) noexcept { } -void ArrayTexture::Bind() noexcept { - glBindTexture(GL_TEXTURE_2D_ARRAY, handle); -} - - void ArrayTexture::Reserve(GLsizei w, GLsizei h, GLsizei d, const Format &f) noexcept { glTexStorage3D( GL_TEXTURE_2D_ARRAY, // which @@ -413,22 +404,40 @@ void ArrayTexture::Data(GLsizei l, const Format &f, GLvoid *data) noexcept { } -void ArrayTexture::FilterNearest() noexcept { - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); +CubeMap::CubeMap() +: TextureBase() { + } -void ArrayTexture::FilterLinear() noexcept { - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +CubeMap::~CubeMap() { + } -void ArrayTexture::FilterTrilinear() noexcept { - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glGenerateMipmap(GL_TEXTURE_2D_ARRAY); +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) noexcept { + Data(f, srf.w, srf.h, Format(*srf.format), srf.pixels); +} + +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 + ); } } -- 2.39.2