#include "billboardPainter.h" #include "gldebug.h" #include "maths.h" #include #include #include #include const auto VIEWS = [](std::integer_sequence) { constexpr float STEP = two_pi / BillboardPainter::VIEW_ANGLES; return std::array {rotate_yaw<4>(Ep * STEP)...}; }(std::make_integer_sequence>()); BillboardPainter::BillboardPainter() : program {billboardPainter_vert, billboardPainter_geom, billboardPainter_frag}, angle {}, view {} { glDebugScope _ {fbo}; glBindFramebuffer(GL_FRAMEBUFFER, fbo); static constexpr std::array 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 {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 & textures, ImageDimensions size) { glDebugScope _ {0}; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const auto configuregdata = [size](Impl::glTexture & texture, const GLenum iformat) { texture.storage(1, iformat, size || VIEW_ANGLES); 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 & 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 {VIEWS * [extentsMat = glm::translate(glm::ortho(-size, size, -size, size, -size, size), -centre), this]( const auto & view) { return this->view * view * extentsMat; }}); mesh.draw(); }