diff --git a/data/shaders/bubble.vert b/data/shaders/bubble.vert index f216f4f4e..f26f0a246 100644 --- a/data/shaders/bubble.vert +++ b/data/shaders/bubble.vert @@ -20,14 +20,17 @@ #version 130 uniform mat4 ModelViewProjectionMatrix; uniform float time; + +in vec3 Position; +in vec2 Texcoord; out vec2 uv; void main() { - gl_Position = ModelViewProjectionMatrix * gl_Vertex; + gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.); - float delta_x = cos(time*3.0) * sin( 4.0 * gl_TexCoord[0].st.s * 6.28318531 ); - float delta_y = cos(time*2.0) * sin( 3.0 * gl_TexCoord[0].st.t * 6.28318531 ); + float delta_x = cos(time*3.0) * sin( 4.0 * Texcoord.x * 6.28318531 ); + float delta_y = cos(time*2.0) * sin( 3.0 * Texcoord.y * 6.28318531 ); - uv = gl_MultiTexCoord0.st + vec2(0.02*delta_x, 0.02*delta_y); + uv = Texcoord + vec2(0.02*delta_x, 0.02*delta_y); } diff --git a/data/shaders/object_pass2.frag b/data/shaders/object_pass2.frag index bb4f42dec..4ccb2ceea 100644 --- a/data/shaders/object_pass2.frag +++ b/data/shaders/object_pass2.frag @@ -16,5 +16,5 @@ void main(void) vec3 SpecularComponent = texture(SpecularMap, tc).xyz; float ao = texture(SSAO, tc).x; vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent * (1. - color.a); - FragColor = vec4(color.xyz * LightFactor, color.a); + FragColor = vec4(color.xyz * LightFactor, 1.); } diff --git a/data/shaders/objectref_pass2.frag b/data/shaders/objectref_pass2.frag index aaf7e66e4..5c1589f98 100644 --- a/data/shaders/objectref_pass2.frag +++ b/data/shaders/objectref_pass2.frag @@ -17,5 +17,5 @@ void main(void) vec3 SpecularComponent = texture(SpecularMap, tc).xyz; float ao = texture(SSAO, tc).x; vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent; - FragColor = vec4(color.xyz * LightFactor, color.a); + FragColor = vec4(color.xyz * LightFactor, 1.); } diff --git a/data/shaders/transparent.frag b/data/shaders/transparent.frag new file mode 100644 index 000000000..b891b6f92 --- /dev/null +++ b/data/shaders/transparent.frag @@ -0,0 +1,10 @@ +#version 130 +uniform sampler2D tex; + +in vec2 uv; +out vec4 FragColor; + +void main() +{ + FragColor = texture(tex, uv); +} diff --git a/data/shaders/transparent.vert b/data/shaders/transparent.vert new file mode 100644 index 000000000..9b841a47f --- /dev/null +++ b/data/shaders/transparent.vert @@ -0,0 +1,12 @@ +#version 130 +uniform mat4 ModelViewProjectionMatrix; + +in vec3 Position; +in vec2 Texcoord; +out vec2 uv; + +void main() +{ + uv = Texcoord; + gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.); +} diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 75c20d135..3258b8f66 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -301,18 +301,11 @@ void IrrDriver::renderGLSL(float dt) } // We need to re-render camera due to the per-cam-node hack. - PROFILER_PUSH_CPU_MARKER("- Transparent Pass 1", 0xFF, 0x00, 0x00); - irr_driver->setPhase(0); + PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00); m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_TRANSPARENT; m_scene_manager->drawAll(m_renderpass); PROFILER_POP_CPU_MARKER(); - PROFILER_PUSH_CPU_MARKER("- Transparent Pass 2", 0xFF, 0x00, 0x00); - irr_driver->setPhase(1); - m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_TRANSPARENT; - m_scene_manager->drawAll(m_renderpass); - PROFILER_POP_CPU_MARKER(); - PROFILER_PUSH_CPU_MARKER("- Particles", 0xFF, 0x00, 0x00); m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_TRANSPARENT_EFFECT; m_scene_manager->drawAll(m_renderpass); diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index e24389b6b..03f87e920 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -246,6 +246,8 @@ void Shaders::loadShaders() MeshShader::SplattingShader::init(); MeshShader::GrassPass1Shader::init(); MeshShader::GrassPass2Shader::init(); + MeshShader::BubbleShader::init(); + MeshShader::TransparentShader::init(); } Shaders::~Shaders() @@ -574,6 +576,53 @@ namespace MeshShader glUniform3f(uniform_ambient, s.r, s.g, s.b); } + GLuint BubbleShader::Program; + GLuint BubbleShader::attrib_position; + GLuint BubbleShader::attrib_texcoord; + GLuint BubbleShader::uniform_MVP; + GLuint BubbleShader::uniform_tex; + GLuint BubbleShader::uniform_time; + GLuint BubbleShader::uniform_transparency; + + void BubbleShader::init() + { + Program = LoadProgram(file_manager->getAsset("shaders/bubble.vert").c_str(), file_manager->getAsset("shaders/bubble.frag").c_str()); + attrib_position = glGetAttribLocation(Program, "Position"); + attrib_texcoord = glGetAttribLocation(Program, "Texcoord"); + uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix"); + uniform_tex = glGetUniformLocation(Program, "tex"); + uniform_time = glGetUniformLocation(Program, "time"); + uniform_transparency = glGetUniformLocation(Program, "transparency"); + } + void BubbleShader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, unsigned TU_tex, float time, float transparency) + { + glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer()); + glUniform1i(uniform_tex, TU_tex); + glUniform1f(uniform_time, time); + glUniform1f(uniform_transparency, transparency); + } + + GLuint TransparentShader::Program; + GLuint TransparentShader::attrib_position; + GLuint TransparentShader::attrib_texcoord; + GLuint TransparentShader::uniform_MVP; + GLuint TransparentShader::uniform_tex; + + void TransparentShader::init() + { + Program = LoadProgram(file_manager->getAsset("shaders/transparent.vert").c_str(), file_manager->getAsset("shaders/transparent.frag").c_str()); + attrib_position = glGetAttribLocation(Program, "Position"); + attrib_texcoord = glGetAttribLocation(Program, "Texcoord"); + uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix"); + uniform_tex = glGetUniformLocation(Program, "tex"); + } + + void TransparentShader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, unsigned TU_tex) + { + glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer()); + glUniform1i(uniform_tex, TU_tex); + } + GLuint ColorizeShader::Program; GLuint ColorizeShader::attrib_position; GLuint ColorizeShader::uniform_MVP; diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 9f0f0fecd..0cd98f4e3 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -125,6 +125,29 @@ public: static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, unsigned TU_tex_layout, unsigned TU_tex_detail0, unsigned TU_tex_detail1, unsigned TU_tex_detail2, unsigned TU_tex_detail3, unsigned TU_DiffuseMap, unsigned TU_SpecularMap, unsigned TU_SSAO); }; +class BubbleShader +{ +public: + static GLuint Program; + static GLuint attrib_position, attrib_texcoord; + static GLuint uniform_MVP, uniform_tex, uniform_time, uniform_transparency; + + static void init(); + static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, unsigned TU_tex, float time, float transparency); +}; + +class TransparentShader +{ +public: + static GLuint Program; + static GLuint attrib_position, attrib_texcoord; + static GLuint uniform_MVP, uniform_tex; + + static void init(); + static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, unsigned TU_tex); +}; + + class ColorizeShader { public: diff --git a/src/graphics/stkmesh.cpp b/src/graphics/stkmesh.cpp index e531d1eb8..8a00648df 100644 --- a/src/graphics/stkmesh.cpp +++ b/src/graphics/stkmesh.cpp @@ -415,7 +415,59 @@ void STKMesh::drawGlow(const GLMesh &mesh, float r, float g, float b) glBindBuffer(GL_ARRAY_BUFFER, 0); } -void STKMesh::draw(const GLMesh &mesh, video::E_MATERIAL_TYPE type, bool isTransparent) +void STKMesh::drawTransparentObject(const GLMesh &mesh) +{ + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + computeMVP(ModelViewProjectionMatrix); + setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR); + + glUseProgram(MeshShader::TransparentShader::Program); + MeshShader::TransparentShader::setUniforms(ModelViewProjectionMatrix, 0); + + glBindVertexArray(mesh.vao_first_pass); + glDrawElements(ptype, count, itype, 0); +} + +void STKMesh::drawBubble(const GLMesh &mesh) +{ + const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f; + float transparency = 1.; + + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + computeMVP(ModelViewProjectionMatrix); + setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR); + + glUseProgram(MeshShader::BubbleShader::Program); + MeshShader::BubbleShader::setUniforms(ModelViewProjectionMatrix, 0, time, transparency); + + glBindVertexArray(mesh.vao_first_pass); + glDrawElements(ptype, count, itype, 0); +} + +void STKMesh::drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type) +{ + glEnable(GL_DEPTH_TEST); + glDisable(GL_ALPHA_TEST); + glDepthMask(GL_FALSE); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + + if (type == video::EMT_TRANSPARENT_ALPHA_CHANNEL) + drawTransparentObject(mesh); + if (type == irr_driver->getShader(ES_BUBBLES)) + drawBubble(mesh); + return; +} + +void STKMesh::drawSolid(const GLMesh &mesh, video::E_MATERIAL_TYPE type) { if (!mesh.textures[0]) @@ -440,9 +492,6 @@ void STKMesh::draw(const GLMesh &mesh, video::E_MATERIAL_TYPE type, bool isTrans drawGrassPass1(mesh); else drawObjectPass1(mesh); - - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); glStencilFunc(GL_ALWAYS, 1, ~0); irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getMainSetup(), false, false); break; @@ -451,23 +500,11 @@ void STKMesh::draw(const GLMesh &mesh, video::E_MATERIAL_TYPE type, bool isTrans { irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_COLOR), false, false); - if (isTransparent) - { - glEnable(GL_DEPTH_TEST); - glDisable(GL_ALPHA_TEST); - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - else - { - glEnable(GL_DEPTH_TEST); - glDisable(GL_ALPHA_TEST); - glDepthMask(GL_FALSE); - glDisable(GL_BLEND); - } - + glEnable(GL_DEPTH_TEST); + glDisable(GL_ALPHA_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_BLEND); + if (type == irr_driver->getShader(ES_SPHERE_MAP)) drawSphereMap(mesh); else if (type == irr_driver->getShader(ES_SPLATTING)) @@ -478,9 +515,6 @@ void STKMesh::draw(const GLMesh &mesh, video::E_MATERIAL_TYPE type, bool isTrans drawGrassPass2(mesh); else drawObjectPass2(mesh); - - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); break; } case 2: @@ -490,14 +524,6 @@ void STKMesh::draw(const GLMesh &mesh, video::E_MATERIAL_TYPE type, bool isTrans break; } } - - video::SMaterial material; - material.MaterialType = irr_driver->getShader(ES_RAIN); - material.BlendOperation = video::EBO_NONE; - material.ZWriteEnable = true; - material.Lighting = false; - irr_driver->getVideoDriver()->setMaterial(material); - static_cast(irr_driver->getVideoDriver())->setRenderStates3DMode(); } static bool isObject(video::E_MATERIAL_TYPE type) @@ -516,6 +542,8 @@ static bool isObject(video::E_MATERIAL_TYPE type) return true; if (type == irr_driver->getShader(ES_GRASS_REF)) return true; + if (type == irr_driver->getShader(ES_BUBBLES)) + return true; if (type == video::EMT_TRANSPARENT_ALPHA_CHANNEL) return true; return false; @@ -540,6 +568,16 @@ static void initvaostate(GLMesh &mesh, video::E_MATERIAL_TYPE type) mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::GrassPass1Shader::attrib_position, MeshShader::GrassPass1Shader::attrib_texcoord, -1, MeshShader::GrassPass1Shader::attrib_normal, -1, -1, MeshShader::GrassPass1Shader::attrib_color, mesh.Stride); } + else if (type == irr_driver->getShader(ES_BUBBLES)) + { + mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, + MeshShader::BubbleShader::attrib_position, MeshShader::BubbleShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride); + } + else if (type == video::EMT_TRANSPARENT_ALPHA_CHANNEL) + { + mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, + MeshShader::TransparentShader::attrib_position, MeshShader::TransparentShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride); + } else { mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, @@ -604,7 +642,19 @@ void STKMesh::render() if (isObject(material.MaterialType) && isTransparentPass == transparent) { initvaostate(GLmeshes[i], material.MaterialType); - draw(GLmeshes[i], material.MaterialType, transparent); + if (transparent) + drawTransparent(GLmeshes[i], material.MaterialType); + else + drawSolid(GLmeshes[i], material.MaterialType); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + video::SMaterial material; + material.MaterialType = irr_driver->getShader(ES_RAIN); + material.BlendOperation = video::EBO_NONE; + material.ZWriteEnable = true; + material.Lighting = false; + irr_driver->getVideoDriver()->setMaterial(material); + static_cast(irr_driver->getVideoDriver())->setRenderStates3DMode(); } else if (transparent == isTransparentPass) { diff --git a/src/graphics/stkmesh.hpp b/src/graphics/stkmesh.hpp index 3aca6de16..010ea673f 100644 --- a/src/graphics/stkmesh.hpp +++ b/src/graphics/stkmesh.hpp @@ -27,7 +27,8 @@ protected: std::vector GLmeshes; core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView; core::vector3df windDir; - void draw(const GLMesh &mesh, video::E_MATERIAL_TYPE type, bool isTransparent); + void drawSolid(const GLMesh &mesh, video::E_MATERIAL_TYPE type); + void drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type); // Pass 1 shader (ie shaders that outputs normals and depth) void drawObjectPass1(const GLMesh &mesh); @@ -42,6 +43,10 @@ protected: void drawObjectRefPass2(const GLMesh &mesh); void drawGrassPass2(const GLMesh &mesh); + // Forward pass (for transparents meshes) + void drawTransparentObject(const GLMesh &mesh); + void drawBubble(const GLMesh &mesh); + // Pass 3 shader (glow) void drawGlow(const GLMesh &mesh, float r, float g, float b); public: