From 0fb6515bcaae252add43ec427b85974d794dd09d Mon Sep 17 00:00:00 2001 From: vlj Date: Mon, 31 Mar 2014 22:06:37 +0200 Subject: [PATCH] Instancing: Support for alpha ref shadow. --- data/shaders/instanciedshadow.vert | 4 ++ src/graphics/shaders.cpp | 60 +++++++++++++++++++++++--- src/graphics/shaders.hpp | 13 +++++- src/graphics/stkinstancedscenenode.cpp | 25 +++++++++++ src/graphics/stkmesh.cpp | 4 +- 5 files changed, 96 insertions(+), 10 deletions(-) diff --git a/data/shaders/instanciedshadow.vert b/data/shaders/instanciedshadow.vert index 64cefb5c8..0c2377b93 100644 --- a/data/shaders/instanciedshadow.vert +++ b/data/shaders/instanciedshadow.vert @@ -3,6 +3,9 @@ in vec3 Orientation; in vec3 Scale; in vec3 Position; +in vec2 Texcoord; + +out vec2 tc; mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale); mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation, vec3 scale); @@ -11,4 +14,5 @@ void main(void) { mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale); gl_Position = ModelMatrix * vec4(Position, 1.); + tc = Texcoord; } \ No newline at end of file diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 62f632a33..7aa89c0d6 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -346,6 +346,7 @@ void Shaders::loadShaders() MeshShader::ShadowShader::init(); MeshShader::InstancedShadowShader::init(); MeshShader::RefShadowShader::init(); + MeshShader::InstancedRefShadowShader::init(); MeshShader::GrassShadowShader::init(); MeshShader::SkyboxShader::init(); ParticleShader::FlipParticleRender::init(); @@ -1453,7 +1454,8 @@ namespace MeshShader GLuint RefShadowShader::Program; GLuint RefShadowShader::attrib_position; GLuint RefShadowShader::attrib_texcoord; - GLuint RefShadowShader::uniform_MVP; + GLuint RefShadowShader::uniform_VP; + GLuint RefShadowShader::uniform_MM; GLuint RefShadowShader::uniform_tex; void RefShadowShader::init() @@ -1471,18 +1473,64 @@ namespace MeshShader GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str()); attrib_position = glGetAttribLocation(Program, "Position"); attrib_texcoord = glGetAttribLocation(Program, "Texcoord"); - uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix"); + uniform_VP = glGetUniformLocation(Program, "ViewProjectionMatrix[0]"); + uniform_tex = glGetUniformLocation(Program, "tex"); + uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); + } + + void RefShadowShader::setUniforms(const core::matrix4 &ModelMatrix, const std::vector &ViewProjectionMatrix, unsigned TU_tex) + { + size_t size = ViewProjectionMatrix.size(); + float *tmp = new float[16 * size]; + for (unsigned i = 0; i < size; i++) { + memcpy(&tmp[16 * i], ViewProjectionMatrix[i].pointer(), 16 * sizeof(float)); + } + glUniformMatrix4fv(uniform_VP, size, GL_FALSE, tmp); + glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); + glUniform1i(uniform_tex, TU_tex); + delete[] tmp; + } + + GLuint InstancedRefShadowShader::Program; + GLuint InstancedRefShadowShader::attrib_position; + GLuint InstancedRefShadowShader::attrib_texcoord; + GLuint InstancedRefShadowShader::attrib_origin; + GLuint InstancedRefShadowShader::attrib_orientation; + GLuint InstancedRefShadowShader::attrib_scale; + GLuint InstancedRefShadowShader::uniform_VP; + GLuint InstancedRefShadowShader::uniform_tex; + + void InstancedRefShadowShader::init() + { + // Geometry shader needed + if (irr_driver->getGLSLVersion() < 150) + { + attrib_position = -1; + attrib_texcoord = -1; + return; + } + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), + GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedshadow.vert").c_str(), + GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str()); + attrib_position = glGetAttribLocation(Program, "Position"); + attrib_texcoord = glGetAttribLocation(Program, "Texcoord"); + attrib_origin = glGetAttribLocation(Program, "Origin"); + attrib_orientation = glGetAttribLocation(Program, "Orientation"); + attrib_scale = glGetAttribLocation(Program, "Scale"); + uniform_VP = glGetUniformLocation(Program, "ViewProjectionMatrix[0]"); uniform_tex = glGetUniformLocation(Program, "tex"); } - void RefShadowShader::setUniforms(const std::vector &ModelViewProjectionMatrix, unsigned TU_tex) + void InstancedRefShadowShader::setUniforms(const std::vector &ViewProjectionMatrix, unsigned TU_tex) { - size_t size = ModelViewProjectionMatrix.size(); + size_t size = ViewProjectionMatrix.size(); float *tmp = new float[16 * size]; for (unsigned i = 0; i < size; i++) { - memcpy(&tmp[16 * i], ModelViewProjectionMatrix[i].pointer(), 16 * sizeof(float)); + memcpy(&tmp[16 * i], ViewProjectionMatrix[i].pointer(), 16 * sizeof(float)); } - glUniformMatrix4fv(uniform_MVP, size, GL_FALSE, tmp); + glUniformMatrix4fv(uniform_VP, size, GL_FALSE, tmp); glUniform1i(uniform_tex, TU_tex); delete[] tmp; } diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 2803edaee..a77a87d74 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -348,7 +348,18 @@ class RefShadowShader public: static GLuint Program; static GLuint attrib_position, attrib_texcoord; - static GLuint uniform_MVP, uniform_tex; + static GLuint uniform_VP, uniform_MM, uniform_tex; + + static void init(); + static void setUniforms(const core::matrix4 &ModelMatrix, const std::vector &ModelViewProjectionMatrix, unsigned TU_tex); +}; + +class InstancedRefShadowShader +{ +public: + static GLuint Program; + static GLuint attrib_position, attrib_texcoord, attrib_origin, attrib_orientation, attrib_scale; + static GLuint uniform_VP, uniform_tex; static void init(); static void setUniforms(const std::vector &ModelViewProjectionMatrix, unsigned TU_tex); diff --git a/src/graphics/stkinstancedscenenode.cpp b/src/graphics/stkinstancedscenenode.cpp index 72cb76f82..635a36196 100644 --- a/src/graphics/stkinstancedscenenode.cpp +++ b/src/graphics/stkinstancedscenenode.cpp @@ -87,6 +87,9 @@ void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMateria glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); glBufferData(GL_ARRAY_BUFFER, instance_pos.size() * sizeof(float), instance_pos.data(), GL_STATIC_DRAW); setInstanceAttribPointer(); + mesh.vao_shadow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::InstancedRefShadowShader::attrib_position, MeshShader::InstancedRefShadowShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride); + glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); + setInstanceAttribPointer(); break; case FPSM_GRASS: mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, @@ -213,6 +216,23 @@ static void drawFSPMAlphaRefTexture(GLMesh &mesh, const core::matrix4 &ModelView glDrawElementsInstanced(ptype, count, itype, 0, instance_count); } +static void drawShadowAlphaRefTexture(GLMesh &mesh, size_t instance_count) +{ + irr_driver->IncreaseObjectCount(); + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + std::vector ShadowMVP(irr_driver->getShadowViewProj()); + + setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + MeshShader::InstancedRefShadowShader::setUniforms(ShadowMVP, 0); + + assert(mesh.vao_shadow_pass); + glBindVertexArray(mesh.vao_shadow_pass); + glDrawElementsInstanced(ptype, count, itype, 0, instance_count); +} + static void drawFSPMGrass(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDir, size_t instance_count) { irr_driver->IncreaseObjectCount(); @@ -327,6 +347,11 @@ void STKInstancedSceneNode::render() glUseProgram(MeshShader::InstancedShadowShader::Program); for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++) drawShadowDefault(*GeometricMesh[FPSM_DEFAULT][i], instance_pos.size() / 9); + + if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty()) + glUseProgram(MeshShader::InstancedRefShadowShader::Program); + for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++) + drawShadowAlphaRefTexture(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i], instance_pos.size() / 9); return; } } diff --git a/src/graphics/stkmesh.cpp b/src/graphics/stkmesh.cpp index f9646269a..80a3398d1 100644 --- a/src/graphics/stkmesh.cpp +++ b/src/graphics/stkmesh.cpp @@ -666,11 +666,9 @@ void drawShadowRef(const GLMesh &mesh) size_t count = mesh.IndexCount; std::vector ShadowMVP(irr_driver->getShadowViewProj()); - for (unsigned i = 0; i < ShadowMVP.size(); i++) - ShadowMVP[i] *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD); setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - MeshShader::RefShadowShader::setUniforms(ShadowMVP, 0); + MeshShader::RefShadowShader::setUniforms(irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD), ShadowMVP, 0); assert(mesh.vao_shadow_pass); glBindVertexArray(mesh.vao_shadow_pass);