diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 0e2f13528..ef9fa7ea3 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -320,9 +320,11 @@ void Shaders::loadShaders() MeshShader::ObjectPass1Shader::init(); MeshShader::ObjectRefPass1Shader::init(); MeshShader::InstancedObjectPass1Shader::init(); + MeshShader::InstancedObjectRefPass1Shader::init(); MeshShader::InstancedGrassPass1Shader::init(); MeshShader::ObjectPass2Shader::init(); MeshShader::InstancedObjectPass2Shader::init(); + MeshShader::InstancedObjectRefPass2Shader::init(); MeshShader::InstancedGrassPass2Shader::init(); MeshShader::DetailledObjectPass2Shader::init(); MeshShader::ObjectRimLimitShader::init(); @@ -537,6 +539,42 @@ namespace MeshShader glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer()); } + GLuint InstancedObjectRefPass1Shader::Program; + GLuint InstancedObjectRefPass1Shader::attrib_position; + GLuint InstancedObjectRefPass1Shader::attrib_normal; + GLuint InstancedObjectRefPass1Shader::attrib_texcoord; + GLuint InstancedObjectRefPass1Shader::attrib_orientation; + GLuint InstancedObjectRefPass1Shader::attrib_origin; + GLuint InstancedObjectRefPass1Shader::attrib_scale; + GLuint InstancedObjectRefPass1Shader::uniform_MP; + GLuint InstancedObjectRefPass1Shader::uniform_VM; + GLuint InstancedObjectRefPass1Shader::uniform_tex; + + void InstancedObjectRefPass1Shader::init() + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), + GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str()); + attrib_origin = glGetAttribLocation(Program, "Origin"); + attrib_orientation = glGetAttribLocation(Program, "Orientation"); + attrib_position = glGetAttribLocation(Program, "Position"); + attrib_scale = glGetAttribLocation(Program, "Scale"); + attrib_normal = glGetAttribLocation(Program, "Normal"); + attrib_texcoord = glGetAttribLocation(Program, "Texcoord"); + uniform_MP = glGetUniformLocation(Program, "ViewProjectionMatrix"); + uniform_VM = glGetUniformLocation(Program, "InverseViewMatrix"); + uniform_tex = glGetUniformLocation(Program, "tex"); + } + + void InstancedObjectRefPass1Shader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &ViewMatrix, unsigned TU_tex) + { + glUniformMatrix4fv(uniform_MP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer()); + glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer()); + glUniform1i(uniform_tex, TU_tex); + } + GLuint InstancedGrassPass1Shader::Program; GLuint InstancedGrassPass1Shader::attrib_position; GLuint InstancedGrassPass1Shader::attrib_normal; @@ -667,6 +705,57 @@ namespace MeshShader } void InstancedObjectPass2Shader::setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &TextureMatrix) + { + glUniformMatrix4fv(uniform_VP, 1, GL_FALSE, ViewProjectionMatrix.pointer()); + glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer()); + glUniform2f(uniform_screen, UserConfigParams::m_width, UserConfigParams::m_height); + const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight(); + glUniform3f(uniform_ambient, s.r, s.g, s.b); + } + + GLuint InstancedObjectRefPass2Shader::Program; + GLuint InstancedObjectRefPass2Shader::attrib_position; + GLuint InstancedObjectRefPass2Shader::attrib_texcoord; + GLuint InstancedObjectRefPass2Shader::attrib_origin; + GLuint InstancedObjectRefPass2Shader::attrib_orientation; + GLuint InstancedObjectRefPass2Shader::attrib_scale; + GLuint InstancedObjectRefPass2Shader::uniform_VP; + GLuint InstancedObjectRefPass2Shader::uniform_TM; + GLuint InstancedObjectRefPass2Shader::uniform_screen; + GLuint InstancedObjectRefPass2Shader::uniform_ambient; + GLuint InstancedObjectRefPass2Shader::TU_Albedo; + + void InstancedObjectRefPass2Shader::init() + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), + GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.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"); + uniform_TM = glGetUniformLocation(Program, "TextureMatrix"); + GLuint uniform_Albedo = glGetUniformLocation(Program, "Albedo"); + GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); + GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); + GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); + uniform_screen = glGetUniformLocation(Program, "screen"); + uniform_ambient = glGetUniformLocation(Program, "ambient"); + TU_Albedo = 3; + + glUseProgram(Program); + glUniform1i(uniform_DiffuseMap, 0); + glUniform1i(uniform_SpecularMap, 1); + glUniform1i(uniform_SSAO, 2); + glUniform1i(uniform_Albedo, TU_Albedo); + glUseProgram(0); + } + + void InstancedObjectRefPass2Shader::setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &TextureMatrix) { glUniformMatrix4fv(uniform_VP, 1, GL_FALSE, ViewProjectionMatrix.pointer()); glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer()); diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 86cf4435b..1bc18b7eb 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -88,6 +88,17 @@ public: static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &ViewMatrix); }; +class InstancedObjectRefPass1Shader +{ +public: + static GLuint Program; + static GLuint attrib_position, attrib_normal, attrib_texcoord, attrib_origin, attrib_orientation, attrib_scale; + static GLuint uniform_MP, uniform_VM, uniform_tex; + + static void init(); + static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &ViewMatrix, unsigned TU_tex); +}; + class InstancedGrassPass1Shader { public: @@ -123,6 +134,18 @@ public: static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &TextureMatrix); }; +class InstancedObjectRefPass2Shader +{ +public: + static GLuint Program; + static GLuint attrib_position, attrib_texcoord, attrib_origin, attrib_orientation, attrib_scale; + static GLuint uniform_VP, uniform_TM, uniform_screen, uniform_ambient; + static GLuint TU_Albedo; + + static void init(); + static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &TextureMatrix); +}; + class DetailledObjectPass2Shader { public: diff --git a/src/graphics/stkinstancedscenenode.cpp b/src/graphics/stkinstancedscenenode.cpp index 87541d951..e080a2a52 100644 --- a/src/graphics/stkinstancedscenenode.cpp +++ b/src/graphics/stkinstancedscenenode.cpp @@ -51,6 +51,20 @@ void STKInstancedSceneNode::createGLMeshes() isMaterialInitialized = false; } +template +void setInstanceAttribPointer() +{ + glEnableVertexAttribArray(T::attrib_origin); + glVertexAttribPointer(T::attrib_origin, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0); + glVertexAttribDivisor(T::attrib_origin, 1); + glEnableVertexAttribArray(T::attrib_orientation); + glVertexAttribPointer(T::attrib_orientation, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(3 * sizeof(float))); + glVertexAttribDivisor(T::attrib_orientation, 1); + glEnableVertexAttribArray(T::attrib_scale); + glVertexAttribPointer(T::attrib_scale, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(6 * sizeof(float))); + glVertexAttribDivisor(T::attrib_scale, 1); +} + void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat) { switch (GeoMat) @@ -61,15 +75,15 @@ void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMateria glGenBuffers(1, &instances_vbo); glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); glBufferData(GL_ARRAY_BUFFER, instance_pos.size() * sizeof(float), instance_pos.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(MeshShader::InstancedObjectPass1Shader::attrib_origin); - glVertexAttribPointer(MeshShader::InstancedObjectPass1Shader::attrib_origin, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0); - glVertexAttribDivisor(MeshShader::InstancedObjectPass1Shader::attrib_origin, 1); - glEnableVertexAttribArray(MeshShader::InstancedObjectPass1Shader::attrib_orientation); - glVertexAttribPointer(MeshShader::InstancedObjectPass1Shader::attrib_orientation, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(3 * sizeof(float))); - glVertexAttribDivisor(MeshShader::InstancedObjectPass1Shader::attrib_orientation, 1); - glEnableVertexAttribArray(MeshShader::InstancedObjectPass1Shader::attrib_scale); - glVertexAttribPointer(MeshShader::InstancedObjectPass1Shader::attrib_scale, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(6 * sizeof(float))); - glVertexAttribDivisor(MeshShader::InstancedObjectPass1Shader::attrib_scale, 1); + setInstanceAttribPointer(); + break; + case FPSM_ALPHA_REF_TEXTURE: + mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, + MeshShader::InstancedObjectRefPass1Shader::attrib_position, MeshShader::InstancedObjectRefPass1Shader::attrib_texcoord, -1, MeshShader::InstancedObjectRefPass1Shader::attrib_normal, -1, -1, -1, mesh.Stride); + glGenBuffers(1, &instances_vbo); + glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); + glBufferData(GL_ARRAY_BUFFER, instance_pos.size() * sizeof(float), instance_pos.data(), GL_STATIC_DRAW); + setInstanceAttribPointer(); break; case FPSM_GRASS: mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, @@ -77,15 +91,7 @@ void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMateria glGenBuffers(1, &instances_vbo); glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); glBufferData(GL_ARRAY_BUFFER, instance_pos.size() * sizeof(float), instance_pos.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(MeshShader::InstancedGrassPass1Shader::attrib_origin); - glVertexAttribPointer(MeshShader::InstancedGrassPass1Shader::attrib_origin, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0); - glVertexAttribDivisor(MeshShader::InstancedGrassPass1Shader::attrib_origin, 1); - glEnableVertexAttribArray(MeshShader::InstancedGrassPass1Shader::attrib_orientation); - glVertexAttribPointer(MeshShader::InstancedGrassPass1Shader::attrib_orientation, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(3 * sizeof(float))); - glVertexAttribDivisor(MeshShader::InstancedGrassPass1Shader::attrib_orientation, 1); - glEnableVertexAttribArray(MeshShader::InstancedGrassPass1Shader::attrib_scale); - glVertexAttribPointer(MeshShader::InstancedGrassPass1Shader::attrib_scale, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(6 * sizeof(float))); - glVertexAttribDivisor(MeshShader::InstancedGrassPass1Shader::attrib_scale, 1); + setInstanceAttribPointer(); break; default: return; @@ -99,29 +105,19 @@ void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMateria mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::InstancedObjectPass2Shader::attrib_position, MeshShader::InstancedObjectPass2Shader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride); glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); - glEnableVertexAttribArray(MeshShader::InstancedObjectPass2Shader::attrib_origin); - glVertexAttribPointer(MeshShader::InstancedObjectPass2Shader::attrib_origin, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0); - glVertexAttribDivisor(MeshShader::InstancedObjectPass2Shader::attrib_origin, 1); - glEnableVertexAttribArray(MeshShader::InstancedObjectPass2Shader::attrib_orientation); - glVertexAttribPointer(MeshShader::InstancedObjectPass2Shader::attrib_orientation, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(3 * sizeof(float))); - glVertexAttribDivisor(MeshShader::InstancedObjectPass2Shader::attrib_orientation, 1); - glEnableVertexAttribArray(MeshShader::InstancedObjectPass2Shader::attrib_scale); - glVertexAttribPointer(MeshShader::InstancedObjectPass2Shader::attrib_scale, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(6 * sizeof(float))); - glVertexAttribDivisor(MeshShader::InstancedObjectPass2Shader::attrib_scale, 1); + setInstanceAttribPointer(); + break; + case SM_ALPHA_REF_TEXTURE: + mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, + MeshShader::InstancedObjectRefPass2Shader::attrib_position, MeshShader::InstancedObjectRefPass2Shader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride); + glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); + setInstanceAttribPointer(); break; case SM_GRASS: mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::InstancedGrassPass2Shader::attrib_position, MeshShader::InstancedGrassPass2Shader::attrib_texcoord, -1, -1, -1, -1, MeshShader::InstancedGrassPass2Shader::attrib_color, mesh.Stride); glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); - glEnableVertexAttribArray(MeshShader::InstancedGrassPass2Shader::attrib_origin); - glVertexAttribPointer(MeshShader::InstancedGrassPass2Shader::attrib_origin, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0); - glVertexAttribDivisor(MeshShader::InstancedGrassPass2Shader::attrib_origin, 1); - glEnableVertexAttribArray(MeshShader::InstancedGrassPass2Shader::attrib_orientation); - glVertexAttribPointer(MeshShader::InstancedGrassPass2Shader::attrib_orientation, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*) (3 * sizeof(float))); - glVertexAttribDivisor(MeshShader::InstancedGrassPass2Shader::attrib_orientation, 1); - glEnableVertexAttribArray(MeshShader::InstancedGrassPass2Shader::attrib_scale); - glVertexAttribPointer(MeshShader::InstancedGrassPass2Shader::attrib_scale, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(6 * sizeof(float))); - glVertexAttribDivisor(MeshShader::InstancedGrassPass2Shader::attrib_scale, 1); + setInstanceAttribPointer(); break; default: return; @@ -182,6 +178,23 @@ static void drawFSPMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjecti glDrawElementsInstanced(ptype, count, itype, 0, instance_count); } +static void drawFSPMAlphaRefTexture(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, size_t instance_count) +{ + irr_driver->IncreaseObjectCount(); + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + core::matrix4 InverseViewMatrix; + irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW).getInverse(InverseViewMatrix); + + setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + MeshShader::InstancedObjectRefPass1Shader::setUniforms(ModelViewProjectionMatrix, InverseViewMatrix, 0); + + glBindVertexArray(mesh.vao_first_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(); @@ -214,6 +227,21 @@ static void drawSMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjection glDrawElementsInstanced(ptype, count, itype, 0, instance_count); } +static void drawSMAlphaRefTexture(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, size_t instance_count) +{ + irr_driver->IncreaseObjectCount(); + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + setTexture(MeshShader::InstancedObjectRefPass2Shader::TU_Albedo, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + + MeshShader::InstancedObjectRefPass2Shader::setUniforms(ModelViewProjectionMatrix, core::matrix4::EM4CONST_IDENTITY); + + glBindVertexArray(mesh.vao_second_pass); + glDrawElementsInstanced(ptype, count, itype, 0, instance_count); +} + static void drawSMGrass(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDir, size_t instance_count) { irr_driver->IncreaseObjectCount(); @@ -243,6 +271,11 @@ void STKInstancedSceneNode::render() for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++) drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 9); + if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty()) + glUseProgram(MeshShader::InstancedObjectRefPass1Shader::Program); + for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++) + drawFSPMAlphaRefTexture(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i], ModelViewProjectionMatrix, instance_pos.size() / 9); + windDir = getWind(); if (!GeometricMesh[FPSM_GRASS].empty()) glUseProgram(MeshShader::InstancedGrassPass1Shader::Program); @@ -258,6 +291,11 @@ void STKInstancedSceneNode::render() for (unsigned i = 0; i < ShadedMesh[FPSM_DEFAULT].size(); i++) drawSMDefault(*ShadedMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 9); + if (!ShadedMesh[SM_ALPHA_REF_TEXTURE].empty()) + glUseProgram(MeshShader::InstancedObjectRefPass2Shader::Program); + for (unsigned i = 0; i < ShadedMesh[SM_ALPHA_REF_TEXTURE].size(); i++) + drawSMAlphaRefTexture(*ShadedMesh[SM_ALPHA_REF_TEXTURE][i], ModelViewProjectionMatrix, instance_pos.size() / 9); + if (!ShadedMesh[SM_GRASS].empty()) glUseProgram(MeshShader::InstancedGrassPass2Shader::Program); for (unsigned i = 0; i < ShadedMesh[SM_GRASS].size(); i++)