LightPrepass: Split the rendering in 2 phases.

This commit is contained in:
Vincent Lejeune
2014-01-16 01:08:37 +01:00
parent 734f320f75
commit c7fe307a52
11 changed files with 198 additions and 81 deletions

View File

@@ -1,12 +0,0 @@
#version 130
uniform sampler2D texture;
in vec2 uv;
noperspective in vec3 nor;
void main(void)
{
vec4 tex = texture2D(texture, uv);
gl_FragData[0] = vec4(tex.xyz, 1.);
gl_FragData[1] = vec4(0.5 * normalize(nor) + 0.5, gl_FragCoord.z);
gl_FragData[2] = vec4(1. - tex.a);
}

View File

@@ -0,0 +1,7 @@
#version 130
noperspective in vec3 nor;
void main(void)
{
gl_FragColor = vec4(0.5 * normalize(nor) + 0.5, gl_FragCoord.z);
}

View File

@@ -3,14 +3,11 @@ uniform mat4 ModelViewProjectionMatrix;
uniform mat4 TransposeInverseModelView;
in vec3 Position;
in vec2 Texcoord;
in vec3 Normal;
out vec2 uv;
noperspective out vec3 nor;
void main(void)
{
uv = Texcoord;
gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.);
nor = (TransposeInverseModelView * vec4(Normal, 0.)).xyz;
}

View File

@@ -0,0 +1,17 @@
#version 130
uniform sampler2D Albedo;
uniform sampler2D DiffuseMap;
uniform sampler2D SpecularMap;
uniform vec2 screen;
uniform vec3 ambient;
in vec2 uv;
void main(void)
{
vec2 tc = gl_FragCoord.xy / screen;
vec4 color = texture2D(Albedo, uv);
vec3 DiffuseComponent = texture2D(DiffuseMap, tc).xyz;
vec3 SpecularComponent = texture2D(SpecularMap, tc).xyz;
vec3 LightFactor = ambient + DiffuseComponent + SpecularComponent * (1. - color.a);
gl_FragColor = vec4(color.xyz * LightFactor, 1.);
}

View File

@@ -0,0 +1,12 @@
#version 130
uniform mat4 ModelViewProjectionMatrix;
in vec3 Position;
in vec2 Texcoord;
out vec2 uv;
void main(void)
{
uv = Texcoord;
gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.);
}

View File

@@ -1,14 +0,0 @@
#version 130
uniform sampler2D texture;
in vec2 uv;
noperspective in vec3 nor;
void main(void)
{
vec4 tex = texture2D(texture, uv);
if (tex.a < 0.5)
discard;
gl_FragData[0] = vec4(tex.xyz, 1.);
gl_FragData[1] = vec4(0.5 * normalize(nor) + 0.5, gl_FragCoord.z);
gl_FragData[2] = vec4(1. - tex.a);
}

View File

@@ -140,6 +140,21 @@ void IrrDriver::reset()
if (m_glsl) m_post_processing->reset();
} // reset
void IrrDriver::setPhase(unsigned p)
{
phase = p;
}
unsigned IrrDriver::getPhase() const
{
return phase;
}
core::array<video::IRenderTarget> &IrrDriver::getMainSetup()
{
return m_mrt;
}
// ----------------------------------------------------------------------------
#if defined(__linux__) && !defined(ANDROID)

View File

@@ -174,6 +174,8 @@ private:
std::vector<scene::ISceneNode *> m_background;
unsigned phase;
#ifdef DEBUG
/** Used to visualise skeletons. */
std::vector<irr::scene::IAnimatedMeshSceneNode*> m_debug_meshes;
@@ -206,6 +208,9 @@ public:
~IrrDriver();
void initDevice();
void reset();
void setPhase(unsigned);
unsigned getPhase() const;
core::array<video::IRenderTarget> &getMainSetup();
void updateConfigIfRelevant();
void setAllMaterialFlags(scene::IMesh *mesh) const;
scene::IAnimatedMesh *getAnimatedMesh(const std::string &name);

View File

@@ -193,6 +193,7 @@ void IrrDriver::renderGLSL(float dt)
m_video_driver->setRenderTarget(m_mrt, false, false);
m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_SOLID;
irr_driver->setPhase(0);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, ~0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
@@ -227,6 +228,13 @@ void IrrDriver::renderGLSL(float dt)
// Lights
renderLights(cambox, camnode, overridemat, cam, dt);
irr_driver->setPhase(1);
m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_SOLID;
glStencilFunc(GL_EQUAL, 0, ~0);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glEnable(GL_STENCIL_TEST);
m_scene_manager->drawAll(m_renderpass);
glDisable(GL_STENCIL_TEST);
if (!bgnodes)
{

View File

@@ -2,6 +2,7 @@
#include "graphics/irr_driver.hpp"
#include <ISceneManager.h>
#include <IMaterialRenderer.h>
#include "config/user_config.hpp"
static
GLuint createVAO(GLuint vbo, GLuint idx, GLuint attrib_position, GLuint attrib_texcoord, GLuint attrib_normal, size_t stride)
@@ -11,39 +12,72 @@ GLuint createVAO(GLuint vbo, GLuint idx, GLuint attrib_position, GLuint attrib_t
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(attrib_position);
glEnableVertexAttribArray(attrib_texcoord);
glEnableVertexAttribArray(attrib_normal);
if ((GLint)attrib_texcoord != -1)
glEnableVertexAttribArray(attrib_texcoord);
if ((GLint)attrib_normal != -1)
glEnableVertexAttribArray(attrib_normal);
glVertexAttribPointer(attrib_position, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(attrib_texcoord, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*) 28);
glVertexAttribPointer(attrib_normal, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*) 12);
if ((GLint)attrib_texcoord != -1)
glVertexAttribPointer(attrib_texcoord, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*) 28);
if ((GLint)attrib_normal != -1)
glVertexAttribPointer(attrib_normal, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*) 12);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idx);
glBindVertexArray(0);
return vao;
}
namespace ObjectShader
namespace ObjectPass1Shader
{
GLuint Program;
GLuint attrib_position, attrib_texcoord, attrib_normal;
GLuint uniform_MVP, uniform_TIMV, uniform_texture;
GLuint attrib_position, attrib_normal;
GLuint uniform_MVP, uniform_TIMV;
void init()
{
initGL();
Program = LoadProgram(file_manager->getAsset("shaders/object.vert").c_str(), file_manager->getAsset("shaders/object.frag").c_str());
Program = LoadProgram(file_manager->getAsset("shaders/object_pass1.vert").c_str(), file_manager->getAsset("shaders/object_pass1.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_normal = glGetAttribLocation(Program, "Normal");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
uniform_TIMV = glGetUniformLocation(Program, "TransposeInverseModelView");
uniform_texture = glGetUniformLocation(Program, "texture");
uniform_TIMV = glGetUniformLocation(Program, "TransposeInverseModelView");;
}
void setProgramAndUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, unsigned TU_texture)
void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView)
{
glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer());
glUniformMatrix4fv(uniform_TIMV, 1, GL_FALSE, TransposeInverseModelView.pointer());
glUniform1i(uniform_texture, TU_texture);
}
}
namespace ObjectPass2Shader
{
GLuint Program;
GLuint attrib_position, attrib_texcoord;
GLuint uniform_MVP, uniform_TIMV, uniform_Albedo, uniform_DiffuseMap, uniform_SpecularMap, uniform_screen, uniform_ambient;
void init()
{
initGL();
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/object_pass2.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
uniform_Albedo = glGetUniformLocation(Program, "Albedo");
uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap");
uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap");
uniform_screen = glGetUniformLocation(Program, "screen");
uniform_ambient = glGetUniformLocation(Program, "ambient");
}
void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, unsigned TU_Albedo, unsigned TU_DiffuseMap, unsigned TU_SpecularMap)
{
glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer());
glUniform1i(uniform_Albedo, TU_Albedo);
glUniform1i(uniform_DiffuseMap, TU_DiffuseMap);
glUniform1i(uniform_SpecularMap, TU_SpecularMap);
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);
}
}
@@ -123,7 +157,6 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb)
result.textures = static_cast<irr::video::COpenGLTexture*>(tex)->getOpenGLTextureName();
else
result.textures = 0;
result.vao = 0;
return result;
}
@@ -139,9 +172,10 @@ STKMesh::STKMesh(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::IScene
GLmeshes.push_back(allocateMeshBuffer(mb));
}
if (ObjectShader::Program)
if (ObjectPass1Shader::Program && ObjectPass2Shader::Program)
return;
ObjectShader::init();
ObjectPass1Shader::init();
ObjectPass2Shader::init();
}
STKMesh::~STKMesh()
@@ -150,43 +184,87 @@ STKMesh::~STKMesh()
// glDeleteBuffers(index_buffer.size(), index_buffer.data());
}
static
void drawFirstPass(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
{
irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH), false, false);
glStencilFunc(GL_ALWAYS, 0, ~0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
core::matrix4 ModelViewProjectionMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
core::matrix4 TransposeInverseModelView = irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
TransposeInverseModelView *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
TransposeInverseModelView.makeInverse();
TransposeInverseModelView = TransposeInverseModelView.getTransposed();
glUseProgram(ObjectPass1Shader::Program);
ObjectPass1Shader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView);
glBindVertexArray(mesh.vao_first_pass);
glDrawElements(ptype, count, itype, 0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glStencilFunc(GL_ALWAYS, 1, ~0);
irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getMainSetup(), false, false);
}
static
void drawSecondPass(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
{
irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_COLOR), false, false);
glEnable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_BLEND);
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
core::matrix4 ModelViewProjectionMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mesh.textures);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, static_cast<irr::video::COpenGLTexture*>(irr_driver->getRTT(RTT_TMP1))->getOpenGLTextureName());
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, static_cast<irr::video::COpenGLTexture*>(irr_driver->getRTT(RTT_TMP2))->getOpenGLTextureName());
glUseProgram(ObjectPass2Shader::Program);
ObjectPass2Shader::setUniforms(ModelViewProjectionMatrix, 0, 1, 2);
glBindVertexArray(mesh.vao_second_pass);
glDrawElements(ptype, count, itype, 0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_COLOR), false, false);
}
static
void draw(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
{
if (!mesh.textures)
return;
glStencilFunc(GL_ALWAYS, 0, ~0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
core::matrix4 ModelViewProjectionMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
core::matrix4 TransposeInverseModelView = irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
TransposeInverseModelView *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
TransposeInverseModelView.makeInverse();
TransposeInverseModelView = TransposeInverseModelView.getTransposed();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mesh.textures);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glUseProgram(ObjectShader::Program);
ObjectShader::setProgramAndUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, 0);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glStencilFunc(GL_ALWAYS, 1, ~0);
if (irr_driver->getPhase() == 0)
drawFirstPass(mesh, type);
else
drawSecondPass(mesh, type);
video::SMaterial material;
material.MaterialType = irr_driver->getShader(ES_RAIN);
@@ -206,11 +284,14 @@ static bool isObject(video::E_MATERIAL_TYPE type)
static void initvaostate(GLMesh &mesh, video::E_MATERIAL_TYPE type)
{
if (mesh.vao)
if (mesh.vao_first_pass)
return;
mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer,
ObjectShader::attrib_position, ObjectShader::attrib_texcoord, ObjectShader::attrib_normal,
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
ObjectPass1Shader::attrib_position, -1, ObjectPass1Shader::attrib_normal,
mesh.Stride);
mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
ObjectPass2Shader::attrib_position, ObjectPass2Shader::attrib_texcoord, -1,
mesh.Stride);
}

View File

@@ -9,7 +9,8 @@
#include <vector>
struct GLMesh {
GLuint vao;
GLuint vao_first_pass;
GLuint vao_second_pass;
GLuint vertex_buffer;
GLuint index_buffer;
GLuint textures;