STKMesh: Use forward rendering for transparent

Transparent objects may be double sided (like bubble),
it doesn't make sense to use a deferred renderer.
This commit is contained in:
Vincent Lejeune 2014-01-20 21:42:38 +01:00
parent f3a9b24880
commit a67f5bf511
10 changed files with 193 additions and 48 deletions

View File

@ -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);
}

View File

@ -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.);
}

View File

@ -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.);
}

View File

@ -0,0 +1,10 @@
#version 130
uniform sampler2D tex;
in vec2 uv;
out vec4 FragColor;
void main()
{
FragColor = texture(tex, uv);
}

View File

@ -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.);
}

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

@ -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::video::COpenGLDriver*>(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::video::COpenGLDriver*>(irr_driver->getVideoDriver())->setRenderStates3DMode();
}
else if (transparent == isTransparentPass)
{

View File

@ -27,7 +27,8 @@ protected:
std::vector<GLMesh> 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: