diff options
Diffstat (limited to 'gfx/gl/billboardPainter.cpp')
| -rw-r--r-- | gfx/gl/billboardPainter.cpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/gfx/gl/billboardPainter.cpp b/gfx/gl/billboardPainter.cpp new file mode 100644 index 0000000..878e950 --- /dev/null +++ b/gfx/gl/billboardPainter.cpp @@ -0,0 +1,90 @@ +#include "billboardPainter.h" +#include "gldebug.h" +#include "maths.h" +#include <gfx/gl/shaders/billboardPainter-frag.h> +#include <gfx/gl/shaders/billboardPainter-geom.h> +#include <gfx/gl/shaders/billboardPainter-vert.h> +#include <stdexcept> + +const auto VIEWS = []<GLint... Ep>(std::integer_sequence<GLint, Ep...>) { + constexpr float STEP = two_pi / BillboardPainter::VIEW_ANGLES<decltype(two_pi)>; + return std::array {rotate_yaw<4>(Ep * STEP)...}; +}(std::make_integer_sequence<GLint, BillboardPainter::VIEW_ANGLES<GLint>>()); + +BillboardPainter::BillboardPainter() : + program {billboardPainter_vert, billboardPainter_geom, billboardPainter_frag}, angle {}, view {} +{ + glDebugScope _ {fbo}; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + static constexpr std::array<GLenum, 2> ATTACHMENTS {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; + glDrawBuffers(ATTACHMENTS.size(), ATTACHMENTS.data()); + glReadBuffer(GL_NONE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glUseProgram(program); + glUniform(viewLoc, std::span<const glm::mat4> {VIEWS}); +} + +void +BillboardPainter::setView(const Angle newAngle, const glm::mat4 & newView) +{ + angle = newAngle; + view = newView; +} + +Angle +BillboardPainter::getAngle() const +{ + return angle; +} + +void +BillboardPainter::configureBillBoardTextures(glTextures<GL_TEXTURE_2D_ARRAY, 3> & textures, ImageDimensions size) +{ + glDebugScope _ {0}; + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + const auto configuregdata = [size](Impl::glTexture<GL_TEXTURE_2D_ARRAY> & texture, const GLenum iformat) { + texture.storage(1, iformat, size || VIEW_ANGLES<GLsizei>); + texture.parameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR); + texture.parameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR); + texture.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + texture.parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + }; + configuregdata(textures[0], GL_DEPTH_COMPONENT16); + configuregdata(textures[1], GL_RGB8_SNORM); + configuregdata(textures[2], GL_RGB5_A1); +} + +void +BillboardPainter::renderBillBoard(const glTextures<GL_TEXTURE_2D_ARRAY, 3> & billboard, const MeshBase & mesh, + const Texture::AnyPtr texture) const +{ + glDebugScope _ {fbo}; + glEnable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glCullFace(GL_BACK); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glClearColor(0, 0, 0, 0); + fbo.texture(GL_DEPTH_ATTACHMENT, billboard[0]); + fbo.texture(GL_COLOR_ATTACHMENT0, billboard[1]); + fbo.texture(GL_COLOR_ATTACHMENT1, billboard[2]); + fbo.assertComplete(); + if (texture) { + texture->bind(0); + } + glUseProgram(program); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + const TextureDimensions billboardSize = billboard[0].getSize(); + glViewport(0, 0, billboardSize.x, billboardSize.y); + const auto & centre = mesh.getDimensions().centre; + const auto & size = mesh.getDimensions().size; + glUniform(viewProjectionLoc, + std::span<const glm::mat4> {VIEWS * + [extentsMat = glm::translate(glm::ortho(-size, size, -size, size, -size, size), -centre), this]( + const auto & view) { + return this->view * view * extentsMat; + }}); + mesh.draw(); +} |
