diff --git a/src/frontend/graphics/Skybox.cpp b/src/frontend/graphics/Skybox.cpp index fd98e3d3..2e5d8e06 100644 --- a/src/frontend/graphics/Skybox.cpp +++ b/src/frontend/graphics/Skybox.cpp @@ -9,6 +9,7 @@ #include "../../graphics/Mesh.h" #include "../../graphics/Batch3D.h" #include "../../graphics/Texture.h" +#include "../../graphics/Cubemap.h" #include "../../graphics/Framebuffer.h" #include "../../window/Window.h" #include "../../window/Camera.h" @@ -25,20 +26,11 @@ Skybox::Skybox(uint size, Shader* shader) shader(shader), batch3d(std::make_unique(4096)) { - glGenTextures(1, &cubemap); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - for (uint face = 0; face < 6; face++) { - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - } + auto cubemap = std::make_unique(size, size, ImageFormat::rgb888); uint fboid; glGenFramebuffers(1, &fboid); - fbo = std::make_unique(fboid, 0, (std::unique_ptr)nullptr); + fbo = std::make_unique(fboid, 0, std::move(cubemap)); float vertices[] { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, @@ -63,7 +55,6 @@ Skybox::Skybox(uint size, Shader* shader) } Skybox::~Skybox() { - glDeleteTextures(1, &cubemap); } void Skybox::drawBackground(Camera* camera, Assets* assets, int width, int height) { @@ -150,9 +141,11 @@ void Skybox::refresh(const GfxContext& pctx, float t, float mie, uint quality) { ctx.setFramebuffer(fbo.get()); ctx.setViewport(Viewport(size, size)); + auto cubemap = dynamic_cast(fbo->getTexture()); + ready = true; glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); + cubemap->bind(); shader->use(); const glm::vec3 xaxs[] = { @@ -190,24 +183,24 @@ void Skybox::refresh(const GfxContext& pctx, float t, float mie, uint quality) { shader->uniform1f("u_fog", mie - 1.0f); shader->uniform3f("u_lightDir", glm::normalize(glm::vec3(sin(t), -cos(t), 0.0f))); for (uint face = 0; face < 6; face++) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap->getId(), 0); shader->uniform3f("u_xaxis", xaxs[face]); shader->uniform3f("u_yaxis", yaxs[face]); shader->uniform3f("u_zaxis", zaxs[face]); - mesh->draw(GL_TRIANGLES); + mesh->draw(); } - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + cubemap->unbind(); glActiveTexture(GL_TEXTURE0); } void Skybox::bind() const { glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); + fbo->getTexture()->bind(); glActiveTexture(GL_TEXTURE0); } void Skybox::unbind() const { glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + fbo->getTexture()->unbind(); glActiveTexture(GL_TEXTURE0); } diff --git a/src/frontend/graphics/Skybox.h b/src/frontend/graphics/Skybox.h index 14f2cddd..25e5416e 100644 --- a/src/frontend/graphics/Skybox.h +++ b/src/frontend/graphics/Skybox.h @@ -24,7 +24,6 @@ struct skysprite { class Skybox { std::unique_ptr fbo; - uint cubemap; uint size; Shader* shader; bool ready = false; diff --git a/src/graphics/Batch2D.cpp b/src/graphics/Batch2D.cpp index d576a387..76a8ad31 100644 --- a/src/graphics/Batch2D.cpp +++ b/src/graphics/Batch2D.cpp @@ -19,7 +19,7 @@ Batch2D::Batch2D(size_t capacity) : capacity(capacity), color(1.0f){ ubyte pixels[] = { 0xFF, 0xFF, 0xFF, 0xFF }; - blank = std::make_unique(pixels, 1, 1, GL_RGBA); + blank = std::make_unique(pixels, 1, 1, ImageFormat::rgba8888); _texture = nullptr; } diff --git a/src/graphics/Batch3D.cpp b/src/graphics/Batch3D.cpp index 2def65ef..adacc80e 100644 --- a/src/graphics/Batch3D.cpp +++ b/src/graphics/Batch3D.cpp @@ -19,20 +19,18 @@ Batch3D::Batch3D(size_t capacity) }; buffer = new float[capacity * B3D_VERTEX_SIZE]; - mesh = new Mesh(buffer, 0, attrs); + mesh = std::make_unique(buffer, 0, attrs); index = 0; ubyte pixels[] = { 255, 255, 255, 255, }; - blank = new Texture(pixels, 1, 1, GL_RGBA); + blank = std::make_unique(pixels, 1, 1, ImageFormat::rgba8888); _texture = nullptr; } Batch3D::~Batch3D(){ - delete blank; delete[] buffer; - delete mesh; } void Batch3D::begin(){ diff --git a/src/graphics/Batch3D.h b/src/graphics/Batch3D.h index 771a79ea..dfc3393c 100644 --- a/src/graphics/Batch3D.h +++ b/src/graphics/Batch3D.h @@ -1,21 +1,23 @@ #ifndef GRAPHICS_BATCH3D_H_ #define GRAPHICS_BATCH3D_H_ -#include -#include #include "UVRegion.h" #include "../typedefs.h" +#include +#include +#include + class Mesh; class Texture; class Batch3D { float* buffer; size_t capacity; - Mesh* mesh; + std::unique_ptr mesh; + std::unique_ptr blank; size_t index; - - Texture* blank; + Texture* _texture; void vertex(float x, float y, float z, diff --git a/src/graphics/Cubemap.cpp b/src/graphics/Cubemap.cpp new file mode 100644 index 00000000..f6d0aba1 --- /dev/null +++ b/src/graphics/Cubemap.cpp @@ -0,0 +1,39 @@ +#include "Cubemap.h" +#include "gl_util.h" + +#include + +Cubemap::Cubemap(uint width, uint height, ImageFormat imageFormat) + : Texture(0, width, height) +{ + glGenTextures(1, &id); + glBindTexture(GL_TEXTURE_CUBE_MAP, id); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + uint format = gl::to_gl_format(imageFormat); + for (uint face = 0; face < 6; face++) { + glTexImage2D( + GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, + 0, + format, + width, + height, + 0, + format, + GL_UNSIGNED_BYTE, + NULL + ); + } +} + +void Cubemap::bind(){ + glBindTexture(GL_TEXTURE_CUBE_MAP, id); +} + +void Cubemap::unbind() { + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} diff --git a/src/graphics/Cubemap.h b/src/graphics/Cubemap.h new file mode 100644 index 00000000..7bd41f3c --- /dev/null +++ b/src/graphics/Cubemap.h @@ -0,0 +1,14 @@ +#ifndef GRAPHICS_CUBEMAP_H_ +#define GRAPHICS_CUBEMAP_H_ + +#include "Texture.h" + +class Cubemap : public Texture { +public: + Cubemap(uint width, uint height, ImageFormat format); + + virtual void bind() override; + virtual void unbind() override; +}; + +#endif // GRAPHICS_CUBEMAP_H_ diff --git a/src/graphics/Texture.cpp b/src/graphics/Texture.cpp index 80a45aef..fbebef1f 100644 --- a/src/graphics/Texture.cpp +++ b/src/graphics/Texture.cpp @@ -4,16 +4,19 @@ #include #include "ImageData.h" +#include "gl_util.h" Texture::Texture(uint id, uint width, uint height) : id(id), width(width), height(height) { } -Texture::Texture(ubyte* data, uint width, uint height, uint format) +Texture::Texture(ubyte* data, uint width, uint height, ImageFormat imageFormat) : width(width), height(height) { glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + GLenum format = gl::to_gl_format(imageFormat); glTexImage2D( GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, (GLvoid *) data @@ -33,6 +36,10 @@ void Texture::bind(){ glBindTexture(GL_TEXTURE_2D, id); } +void Texture::unbind() { + glBindTexture(GL_TEXTURE_2D, 0); +} + void Texture::reload(ubyte* data){ glBindTexture(GL_TEXTURE_2D, id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, @@ -58,15 +65,8 @@ void Texture::setNearestFilter() { Texture* Texture::from(const ImageData* image) { uint width = image->getWidth(); uint height = image->getHeight(); - uint format; const void* data = image->getData(); - switch (image->getFormat()) { - case ImageFormat::rgb888: format = GL_RGB; break; - case ImageFormat::rgba8888: format = GL_RGBA; break; - default: - throw std::runtime_error("unsupported image data format"); - } - return new Texture((ubyte*)data, width, height, format); + return new Texture((ubyte*)data, width, height, image->getFormat()); } uint Texture::getWidth() const { diff --git a/src/graphics/Texture.h b/src/graphics/Texture.h index 571463d7..11f8ef6d 100644 --- a/src/graphics/Texture.h +++ b/src/graphics/Texture.h @@ -3,8 +3,7 @@ #include #include "../typedefs.h" - -class ImageData; +#include "ImageData.h" class Texture { protected: @@ -13,10 +12,11 @@ protected: uint height; public: Texture(uint id, uint width, uint height); - Texture(ubyte* data, uint width, uint height, uint format); + Texture(ubyte* data, uint width, uint height, ImageFormat format); virtual ~Texture(); virtual void bind(); + virtual void unbind(); virtual void reload(ubyte* data); void setNearestFilter(); diff --git a/src/graphics/gl_util.h b/src/graphics/gl_util.h new file mode 100644 index 00000000..5e7e7953 --- /dev/null +++ b/src/graphics/gl_util.h @@ -0,0 +1,19 @@ +#ifndef GRAPHICS_GL_UTIL_H_ +#define GRAPHICS_GL_UTIL_H_ + +#include + +#include "ImageData.h" + +namespace gl { + inline GLenum to_gl_format(ImageFormat imageFormat) { + switch (imageFormat) { + case ImageFormat::rgb888: return GL_RGB; + case ImageFormat::rgba8888: return GL_RGBA; + default: + return 0; + } + } +} + +#endif // GRAPHICS_GL_UTIL_H_