From c77ffb1882c09d3a932dd74f763f33ff11a61313 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Sat, 25 Jan 2014 21:33:21 +0100 Subject: [PATCH] STKBillboard: Create new SceneNode wrapper. --- data/shaders/billboard.frag | 10 ++++ data/shaders/billboard.vert | 16 ++++++ .../source/Irrlicht/CBillboardSceneNode.h | 2 +- sources.cmake | 2 + src/graphics/irr_driver.cpp | 14 ++++- src/graphics/shaders.cpp | 32 +++++++++++ src/graphics/shaders.hpp | 11 ++++ src/graphics/stkbillboard.cpp | 56 +++++++++++++++++++ src/graphics/stkbillboard.hpp | 19 +++++++ 9 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 data/shaders/billboard.frag create mode 100644 data/shaders/billboard.vert create mode 100644 src/graphics/stkbillboard.cpp create mode 100644 src/graphics/stkbillboard.hpp diff --git a/data/shaders/billboard.frag b/data/shaders/billboard.frag new file mode 100644 index 000000000..d43518c6f --- /dev/null +++ b/data/shaders/billboard.frag @@ -0,0 +1,10 @@ +#version 130 +uniform sampler2D tex; + +in vec2 uv; +out vec4 FragColor; + +void main(void) +{ + FragColor = texture(tex, uv); +} diff --git a/data/shaders/billboard.vert b/data/shaders/billboard.vert new file mode 100644 index 000000000..9a9f34d28 --- /dev/null +++ b/data/shaders/billboard.vert @@ -0,0 +1,16 @@ +#version 130 +uniform mat4 ModelViewMatrix; +uniform mat4 ProjectionMatrix; +uniform vec3 Position; +uniform vec2 Size; + +in vec2 Corner; +in vec2 Texcoord; +out vec2 uv; + +void main(void) +{ + uv = Texcoord; + vec4 Center = ModelViewMatrix * vec4(Position, 1.); + gl_Position = ProjectionMatrix * (Center + vec4(Size * Corner, 0., 0.)); +} diff --git a/lib/irrlicht/source/Irrlicht/CBillboardSceneNode.h b/lib/irrlicht/source/Irrlicht/CBillboardSceneNode.h index 416b6ffe4..42f1f69a1 100644 --- a/lib/irrlicht/source/Irrlicht/CBillboardSceneNode.h +++ b/lib/irrlicht/source/Irrlicht/CBillboardSceneNode.h @@ -79,7 +79,7 @@ public: //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); -private: +protected: //! Size.Width is the bottom edge width core::dimension2d Size; diff --git a/sources.cmake b/sources.cmake index e479a3074..71097b569 100644 --- a/sources.cmake +++ b/sources.cmake @@ -61,6 +61,7 @@ src/graphics/skid_marks.cpp src/graphics/slip_stream.cpp src/graphics/stars.cpp src/graphics/stkanimatedmesh.cpp +src/graphics/stkbillboard.cpp src/graphics/stkmesh.cpp src/graphics/sun.cpp src/graphics/water.cpp @@ -389,6 +390,7 @@ src/graphics/skid_marks.hpp src/graphics/slip_stream.hpp src/graphics/stars.hpp src/graphics/stkanimatedmesh.hpp +src/graphics/stkbillboard.hpp src/graphics/stkmesh.hpp src/graphics/sun.hpp src/graphics/water.hpp diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 6e97fb69e..266335ef0 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -33,6 +33,7 @@ #include "graphics/shaders.hpp" #include "graphics/shadow_importance.hpp" #include "graphics/stkanimatedmesh.hpp" +#include "graphics/stkbillboard.hpp" #include "graphics/stkmesh.hpp" #include "graphics/sun.hpp" #include "graphics/rtts.hpp" @@ -968,8 +969,17 @@ scene::ISceneNode *IrrDriver::addBillboard(const core::dimension2d< f32 > size, video::ITexture *texture, scene::ISceneNode* parent, bool alphaTesting) { - scene::IBillboardSceneNode* node = - m_scene_manager->addBillboardSceneNode(parent, size); + scene::IBillboardSceneNode* node; + if (isGLSL()) + { + if (!parent) + parent = m_scene_manager->getRootSceneNode(); + + node = new STKBillboard(parent, m_scene_manager, -1, vector3df(0., 0., 0.), size); + node->drop(); + } + else + node = m_scene_manager->addBillboardSceneNode(parent, size); assert(node->getMaterialCount() > 0); node->setMaterialTexture(0, texture); if(alphaTesting) diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 9f9f0c649..9a6f29b01 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -255,6 +255,7 @@ void Shaders::loadShaders() MeshShader::GrassPass2Shader::init(); MeshShader::BubbleShader::init(); MeshShader::TransparentShader::init(); + MeshShader::BillboardShader::init(); MeshShader::DisplaceShader::init(); ParticleShader::FlipParticleRender::init(); ParticleShader::HeightmapSimulationShader::init(); @@ -774,6 +775,37 @@ namespace MeshShader glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer()); glUniform1i(uniform_tex, TU_tex); } + + GLuint BillboardShader::Program; + GLuint BillboardShader::attrib_corner; + GLuint BillboardShader::attrib_texcoord; + GLuint BillboardShader::uniform_MV; + GLuint BillboardShader::uniform_P; + GLuint BillboardShader::uniform_tex; + GLuint BillboardShader::uniform_Position; + GLuint BillboardShader::uniform_Size; + + void BillboardShader::init() + { + Program = LoadProgram(file_manager->getAsset("shaders/billboard.vert").c_str(), file_manager->getAsset("shaders/billboard.frag").c_str()); + attrib_corner = glGetAttribLocation(Program, "Corner"); + attrib_texcoord = glGetAttribLocation(Program, "Texcoord"); + uniform_MV = glGetUniformLocation(Program, "ModelViewMatrix"); + uniform_P = glGetUniformLocation(Program, "ProjectionMatrix"); + uniform_Position = glGetUniformLocation(Program, "Position"); + uniform_Size = glGetUniformLocation(Program, "Size"); + uniform_tex = glGetUniformLocation(Program, "tex"); + printf("TUTex is %d, Texcoord is %d\n", uniform_tex, attrib_texcoord); + } + + void BillboardShader::setUniforms(const core::matrix4 &ModelViewMatrix, const core::matrix4 &ProjectionMatrix, const core::vector3df &Position, const core::dimension2d &size, unsigned TU_tex) + { + glUniformMatrix4fv(uniform_MV, 1, GL_FALSE, ModelViewMatrix.pointer()); + glUniformMatrix4fv(uniform_P, 1, GL_FALSE, ProjectionMatrix.pointer()); + glUniform3f(uniform_Position, Position.X, Position.Y, Position.Z); + glUniform2f(uniform_Size, size.Width, size.Height); + glUniform1i(uniform_tex, TU_tex); + } GLuint ColorizeShader::Program; GLuint ColorizeShader::attrib_position; diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index cc1b242d0..d2b847ac2 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -191,6 +191,17 @@ public: static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, unsigned TU_tex); }; +class BillboardShader +{ +public: + static GLuint Program; + static GLuint attrib_corner, attrib_texcoord; + static GLuint uniform_MV, uniform_P, uniform_tex, uniform_Position, uniform_Size; + + static void init(); + static void setUniforms(const core::matrix4 &ModelViewMatrix, const core::matrix4 &ProjectionMatrix, const core::vector3df &Position, const core::dimension2d &size, unsigned TU_tex); +}; + class ColorizeShader { diff --git a/src/graphics/stkbillboard.cpp b/src/graphics/stkbillboard.cpp new file mode 100644 index 000000000..02a0a7e43 --- /dev/null +++ b/src/graphics/stkbillboard.cpp @@ -0,0 +1,56 @@ +#include "graphics/stkbillboard.hpp" +#include "graphics/glwrap.hpp" +#include "graphics/shaders.hpp" +#include "graphics/irr_driver.hpp" + +using namespace irr; + +static GLuint billboardvbo; +static GLuint billboardvao = 0; + +static void createbillboardvao() +{ + float quad[] = { + -.5, -.5, 0., 1., + -.5, .5, 0., 0., + .5, -.5, 1., 1., + .5, .5, 1., 0., + }; + + glGenBuffers(1, &billboardvbo); + glGenVertexArrays(1, &billboardvao); + glBindVertexArray(billboardvao); + glBindBuffer(GL_ARRAY_BUFFER, billboardvbo); + glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), quad, GL_STATIC_DRAW); + glEnableVertexAttribArray(MeshShader::BillboardShader::attrib_corner); + glEnableVertexAttribArray(MeshShader::BillboardShader::attrib_texcoord); + glVertexAttribPointer(MeshShader::BillboardShader::attrib_corner, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); + glVertexAttribPointer(MeshShader::BillboardShader::attrib_texcoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid*) (2 * sizeof(float))); + glBindVertexArray(0); +} + +STKBillboard::STKBillboard(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id, + const irr::core::vector3df& position, const irr::core::dimension2d& size, + irr::video::SColor colorTop, irr::video::SColor colorBottom) : + CBillboardSceneNode(parent, mgr, id, position, size, colorTop, colorBottom), IBillboardSceneNode(parent, mgr, id, position) +{ + if (!billboardvao) + createbillboardvao(); +} + +void STKBillboard::render() +{ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + glDepthFunc(GL_FALSE); + core::vector3df pos = getAbsolutePosition(); + glBindVertexArray(billboardvao); + GLuint texid = static_cast(Material.getTexture(0))->getOpenGLTextureName(); + setTexture(0, texid, GL_LINEAR, GL_LINEAR); + glUseProgram(MeshShader::BillboardShader::Program); + MeshShader::BillboardShader::setUniforms(irr_driver->getViewMatrix(), irr_driver->getProjMatrix(), pos, Size, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); + return; +} diff --git a/src/graphics/stkbillboard.hpp b/src/graphics/stkbillboard.hpp new file mode 100644 index 000000000..cae618e05 --- /dev/null +++ b/src/graphics/stkbillboard.hpp @@ -0,0 +1,19 @@ +#ifndef STKBILLBOARD_HPP +#define STKBILLBOARD_HPP + +#include "../lib/irrlicht/source/Irrlicht/CBillboardSceneNode.h" +#include +#include + +class STKBillboard : public irr::scene::CBillboardSceneNode +{ +public: + STKBillboard(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id, + const irr::core::vector3df& position, const irr::core::dimension2d& size, + irr::video::SColor colorTop = irr::video::SColor(0xFFFFFFFF), + irr::video::SColor colorBottom = irr::video::SColor(0xFFFFFFFF)); + + virtual void render(); +}; + +#endif \ No newline at end of file