Start working on instancing library node

This commit is contained in:
Vincent Lejeune 2014-03-16 16:26:38 +01:00
parent 4af050e1c0
commit dd5997d277
10 changed files with 318 additions and 2 deletions

View File

@ -0,0 +1,18 @@
uniform mat4 ViewProjectionMatrix;
uniform mat4 ViewMatrix;
in vec3 Origin;
in vec3 Orientation;
in vec3 Position;
in vec3 Normal;
out vec3 nor;
void main(void)
{
mat4 ModelMatrix = mat4(1.);
ModelMatrix[3].xyz += Origin;
mat4 TransposeInverseModelView = transpose(inverse(ViewMatrix * ModelMatrix));
gl_Position = ViewProjectionMatrix * ModelMatrix * vec4(Position, 1.);
nor = (TransposeInverseModelView * vec4(Normal, 0.)).xyz;
}

View File

@ -0,0 +1,23 @@
uniform mat4 ViewProjectionMatrix;
uniform mat4 TextureMatrix =
mat4(1., 0., 0., 0.,
0., 1., 0., 0.,
0., 0., 1., 0.,
0., 0., 0., 1.);
in vec3 Origin;
in vec3 Position;
in vec2 Texcoord;
out vec2 uv;
void main(void)
{
mat4 ModelMatrix = mat4(1.);
ModelMatrix[3].xyz += Origin;
uv = (TextureMatrix * vec4(Texcoord, 1., 1.)).xy;
gl_Position = ViewProjectionMatrix * ModelMatrix * vec4(Position, 1.);
}

View File

@ -63,6 +63,7 @@ src/graphics/slip_stream.cpp
src/graphics/stars.cpp
src/graphics/stkanimatedmesh.cpp
src/graphics/stkbillboard.cpp
src/graphics/stkinstancedscenenode.cpp
src/graphics/stkmesh.cpp
src/graphics/stkmeshscenenode.cpp
src/graphics/sun.cpp
@ -395,6 +396,7 @@ src/graphics/slip_stream.hpp
src/graphics/stars.hpp
src/graphics/stkanimatedmesh.hpp
src/graphics/stkbillboard.hpp
src/graphics/stkinstancedscenenode.hpp
src/graphics/stkmesh.hpp
src/graphics/stkmeshscenenode.hpp
src/graphics/sun.hpp

View File

@ -46,6 +46,7 @@ PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
PFNGLBLENDEQUATIONPROC glBlendEquation;
PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
PFNGLDELETEBUFFERSPROC glDeleteBuffers;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
@ -181,6 +182,7 @@ void initGL()
glBlendEquation = (PFNGLBLENDEQUATIONPROC)IRR_OGL_LOAD_EXTENSION("glBlendEquation");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)IRR_OGL_LOAD_EXTENSION("glVertexAttribDivisor");
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawArraysInstanced");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsInstanced");
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)IRR_OGL_LOAD_EXTENSION("glDeleteBuffers");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)IRR_OGL_LOAD_EXTENSION("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)IRR_OGL_LOAD_EXTENSION("glBindVertexArray");

View File

@ -68,6 +68,7 @@ extern PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
extern PFNGLBLENDEQUATIONPROC glBlendEquation;
extern PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
extern PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
extern PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;

View File

@ -36,6 +36,7 @@
#include "graphics/shaders.hpp"
#include "graphics/shadow_importance.hpp"
#include "graphics/stkmeshscenenode.hpp"
#include "graphics/stkinstancedscenenode.hpp"
#include "graphics/wind.hpp"
#include "io/file_manager.hpp"
#include "items/item.hpp"
@ -50,6 +51,8 @@
#include <algorithm>
STKInstancedSceneNode *InstancedBox = 0;
void IrrDriver::renderGLSL(float dt)
{
World *world = World::getWorld(); // Never NULL.
@ -132,6 +135,15 @@ void IrrDriver::renderGLSL(float dt)
transparent_glow_nodes.push_back(repnode);
}
if (!InstancedBox)
{
InstancedBox = new STKInstancedSceneNode(items->getItemModel(items->getItem(0)->getType()), m_scene_manager->getRootSceneNode(), m_scene_manager, -1);
InstancedBox->addWorldMatrix(core::vector3df(0, 0, 0));
InstancedBox->addWorldMatrix(core::vector3df(1., 0, 0));
InstancedBox->addWorldMatrix(core::vector3df(0, 1., 0));
InstancedBox->addWorldMatrix(core::vector3df(0, 0, 1.));
}
// Start the RTT for post-processing.
// We do this before beginScene() because we want to capture the glClear()
// because of tracks that do not have skyboxes (generally add-on tracks)
@ -203,7 +215,7 @@ void IrrDriver::renderGLSL(float dt)
irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
irr_driver->genProjViewMatrix();
InstancedBox->render();
PROFILER_POP_CPU_MARKER();
// Todo : reenable glow and shadows
@ -245,7 +257,7 @@ void IrrDriver::renderGLSL(float dt)
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
m_scene_manager->drawAll(m_renderpass);
InstancedBox->render();
PROFILER_POP_CPU_MARKER();
if (World::getWorld()->getTrack()->isFogEnabled())

View File

@ -255,7 +255,9 @@ void Shaders::loadShaders()
MeshShader::NormalMapShader::init();
MeshShader::ObjectPass1Shader::init();
MeshShader::ObjectRefPass1Shader::init();
MeshShader::InstancedObjectPass1Shader::init();
MeshShader::ObjectPass2Shader::init();
MeshShader::InstancedObjectPass2Shader::init();
MeshShader::DetailledObjectPass2Shader::init();
MeshShader::ObjectRimLimitShader::init();
MeshShader::UntexturedObjectShader::init();
@ -425,6 +427,29 @@ namespace MeshShader
glUniform1i(uniform_normalMap, TU_normalMap);
}
GLuint InstancedObjectPass1Shader::Program;
GLuint InstancedObjectPass1Shader::attrib_position;
GLuint InstancedObjectPass1Shader::attrib_normal;
GLuint InstancedObjectPass1Shader::attrib_origin;
GLuint InstancedObjectPass1Shader::uniform_MP;
GLuint InstancedObjectPass1Shader::uniform_VM;
void InstancedObjectPass1Shader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/instanced_object_pass1.vert").c_str(), file_manager->getAsset("shaders/object_pass1.frag").c_str());
attrib_origin = glGetAttribLocation(Program, "Origin");
attrib_position = glGetAttribLocation(Program, "Position");
attrib_normal = glGetAttribLocation(Program, "Normal");
uniform_MP = glGetUniformLocation(Program, "ViewProjectionMatrix");
uniform_VM = glGetUniformLocation(Program, "ViewMatrix");
}
void InstancedObjectPass1Shader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &ViewMatrix)
{
glUniformMatrix4fv(uniform_MP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer());
glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer());
}
// Solid Lit pass shaders
GLuint ObjectPass2Shader::Program;
@ -468,6 +493,49 @@ namespace MeshShader
glUniform3f(uniform_ambient, s.r, s.g, s.b);
}
GLuint InstancedObjectPass2Shader::Program;
GLuint InstancedObjectPass2Shader::attrib_position;
GLuint InstancedObjectPass2Shader::attrib_texcoord;
GLuint InstancedObjectPass2Shader::attrib_origin;
GLuint InstancedObjectPass2Shader::uniform_VP;
GLuint InstancedObjectPass2Shader::uniform_TM;
GLuint InstancedObjectPass2Shader::uniform_screen;
GLuint InstancedObjectPass2Shader::uniform_ambient;
GLuint InstancedObjectPass2Shader::TU_Albedo;
void InstancedObjectPass2Shader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/instanced_object_pass2.vert").c_str(), file_manager->getAsset("shaders/object_pass2.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_origin = glGetAttribLocation(Program, "Origin");
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 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 DetailledObjectPass2Shader::Program;
GLuint DetailledObjectPass2Shader::attrib_position;
GLuint DetailledObjectPass2Shader::attrib_texcoord;

View File

@ -76,6 +76,17 @@ public:
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, unsigned TU_normalMap);
};
class InstancedObjectPass1Shader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_normal, attrib_origin;
static GLuint uniform_MP, uniform_VM;
static void init();
static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &ViewMatrix);
};
class ObjectPass2Shader
{
public:
@ -88,6 +99,18 @@ public:
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix);
};
class InstancedObjectPass2Shader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_texcoord, attrib_origin;
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:

View File

@ -0,0 +1,141 @@
#include "stkinstancedscenenode.hpp"
#include "graphics/irr_driver.hpp"
STKInstancedSceneNode::STKInstancedSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
const irr::core::vector3df& position,
const irr::core::vector3df& rotation,
const irr::core::vector3df& scale) :
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
{
createGLMeshes();
}
void STKInstancedSceneNode::createGLMeshes()
{
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
GLmeshes.push_back(allocateMeshBuffer(mb));
}
isMaterialInitialized = false;
}
void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat)
{
glGenVertexArrays(1, &mesh.vao_first_pass);
glBindVertexArray(mesh.vao_first_pass);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_buffer);
glEnableVertexAttribArray(MeshShader::InstancedObjectPass1Shader::attrib_position);
glEnableVertexAttribArray(MeshShader::InstancedObjectPass1Shader::attrib_normal);
glVertexAttribPointer(MeshShader::InstancedObjectPass1Shader::attrib_position, 3, GL_FLOAT, GL_FALSE, mesh.Stride, 0);
glVertexAttribPointer(MeshShader::InstancedObjectPass1Shader::attrib_normal, 3, GL_FLOAT, GL_FALSE, mesh.Stride, (GLvoid*)12);
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, 3 * sizeof(float), 0);
glVertexAttribDivisor(MeshShader::InstancedObjectPass1Shader::attrib_origin, 1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_buffer);
glGenVertexArrays(1, &mesh.vao_second_pass);
glBindVertexArray(mesh.vao_second_pass);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_buffer);
glEnableVertexAttribArray(MeshShader::InstancedObjectPass2Shader::attrib_position);
glEnableVertexAttribArray(MeshShader::InstancedObjectPass2Shader::attrib_texcoord);
glVertexAttribPointer(MeshShader::InstancedObjectPass2Shader::attrib_position, 3, GL_FLOAT, GL_FALSE, mesh.Stride, 0);
glVertexAttribPointer(MeshShader::InstancedObjectPass2Shader::attrib_texcoord, 3, GL_FLOAT, GL_FALSE, mesh.Stride, (GLvoid*)28);
glBindBuffer(GL_ARRAY_BUFFER, instances_vbo);
glEnableVertexAttribArray(MeshShader::InstancedObjectPass2Shader::attrib_origin);
glVertexAttribPointer(MeshShader::InstancedObjectPass2Shader::attrib_origin, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glVertexAttribDivisor(MeshShader::InstancedObjectPass2Shader::attrib_origin, 1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_buffer);
}
void STKInstancedSceneNode::setFirstTimeMaterial()
{
if (isMaterialInitialized)
return;
irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
if (!mb)
continue;
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
GLMesh &mesh = GLmeshes[i];
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type);
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures);
initinstancedvaostate(mesh, GeometricType, ShadedType);
}
isMaterialInitialized = true;
printf("instance count : %d\n", instance_pos.size() / 3);
}
void STKInstancedSceneNode::addWorldMatrix(const core::vector3df &v)
{
instance_pos.push_back(v.X);
instance_pos.push_back(v.Y);
instance_pos.push_back(v.Z);
}
void STKInstancedSceneNode::render()
{
irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();
setFirstTimeMaterial();
// AbsoluteTransformation.setTranslation(vector3df(0., 0., 10.));
// driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
{
ModelViewProjectionMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
glUseProgram(MeshShader::InstancedObjectPass1Shader::Program);
for (unsigned i = 0; i < GLmeshes.size(); i++)
{
GLMesh &mesh = GLmeshes[i];
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
MeshShader::InstancedObjectPass1Shader::setUniforms(ModelViewProjectionMatrix, irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
glBindVertexArray(mesh.vao_first_pass);
glDrawElementsInstanced(ptype, count, itype, 0, instance_pos.size() / 3);
}
return;
}
if (irr_driver->getPhase() == SOLID_LIT_PASS)
{
glUseProgram(MeshShader::InstancedObjectPass2Shader::Program);
for (unsigned i = 0; i < GLmeshes.size(); i++)
{
GLMesh &mesh = GLmeshes[i];
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
setTexture(MeshShader::InstancedObjectPass2Shader::TU_Albedo, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::InstancedObjectPass2Shader::setUniforms(ModelViewProjectionMatrix, core::matrix4::EM4CONST_IDENTITY);
assert(mesh.vao_second_pass);
glBindVertexArray(mesh.vao_second_pass);
glDrawElementsInstanced(ptype, count, itype, 0, instance_pos.size() / 3);
}
return;
}
}

View File

@ -0,0 +1,26 @@
#ifndef STKINSTANCEDSCENENODE_HPP
#define STKINSTANCEDSCENENODE_HPP
#include "stkmesh.hpp"
class STKInstancedSceneNode : public irr::scene::CMeshSceneNode
{
protected:
std::vector<GLMesh> GLmeshes;
std::vector<float> instance_pos;
core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView;
GLuint instances_vbo;
void createGLMeshes();
bool isMaterialInitialized;
void setFirstTimeMaterial();
void initinstancedvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat);
public:
STKInstancedSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
const irr::core::vector3df& position = irr::core::vector3df(0, 0, 0),
const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0),
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f));
virtual void render();
void addWorldMatrix(const core::vector3df &);
};
#endif