Add Grass material support for instancing.

This commit is contained in:
vlj 2014-03-24 16:40:40 +01:00
parent d798398478
commit a866b3f416
7 changed files with 202 additions and 4 deletions

View File

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

View File

@ -319,8 +319,10 @@ void Shaders::loadShaders()
MeshShader::ObjectPass1Shader::init(); MeshShader::ObjectPass1Shader::init();
MeshShader::ObjectRefPass1Shader::init(); MeshShader::ObjectRefPass1Shader::init();
MeshShader::InstancedObjectPass1Shader::init(); MeshShader::InstancedObjectPass1Shader::init();
MeshShader::InstancedGrassPass1Shader::init();
MeshShader::ObjectPass2Shader::init(); MeshShader::ObjectPass2Shader::init();
MeshShader::InstancedObjectPass2Shader::init(); MeshShader::InstancedObjectPass2Shader::init();
MeshShader::InstancedGrassPass2Shader::init();
MeshShader::DetailledObjectPass2Shader::init(); MeshShader::DetailledObjectPass2Shader::init();
MeshShader::ObjectRimLimitShader::init(); MeshShader::ObjectRimLimitShader::init();
MeshShader::UntexturedObjectShader::init(); MeshShader::UntexturedObjectShader::init();
@ -528,6 +530,42 @@ namespace MeshShader
glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer()); glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer());
} }
GLuint InstancedGrassPass1Shader::Program;
GLuint InstancedGrassPass1Shader::attrib_position;
GLuint InstancedGrassPass1Shader::attrib_normal;
GLuint InstancedGrassPass1Shader::attrib_origin;
GLuint InstancedGrassPass1Shader::attrib_texcoord;
GLuint InstancedGrassPass1Shader::attrib_color;
GLuint InstancedGrassPass1Shader::uniform_MP;
GLuint InstancedGrassPass1Shader::uniform_VM;
GLuint InstancedGrassPass1Shader::uniform_windDir;
GLuint InstancedGrassPass1Shader::uniform_tex;
void InstancedGrassPass1Shader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_grass.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_position = glGetAttribLocation(Program, "Position");
attrib_normal = glGetAttribLocation(Program, "Normal");
attrib_color = glGetAttribLocation(Program, "Color");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MP = glGetUniformLocation(Program, "ViewProjectionMatrix");
uniform_VM = glGetUniformLocation(Program, "ViewMatrix");
uniform_windDir = glGetUniformLocation(Program, "windDir");
uniform_tex = glGetUniformLocation(Program, "tex");
}
void InstancedGrassPass1Shader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &ViewMatrix, const core::vector3df &windDir, unsigned TU_tex)
{
glUniformMatrix4fv(uniform_MP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer());
glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer());
glUniform3f(uniform_windDir, windDir.X, windDir.Y, windDir.Z);
glUniform1i(uniform_tex, TU_tex);
}
// Solid Lit pass shaders // Solid Lit pass shaders
GLuint ObjectPass2Shader::Program; GLuint ObjectPass2Shader::Program;
@ -871,6 +909,52 @@ namespace MeshShader
glUniform3f(uniform_windDir, windDirection.X, windDirection.Y, windDirection.Z); glUniform3f(uniform_windDir, windDirection.X, windDirection.Y, windDirection.Z);
} }
GLuint InstancedGrassPass2Shader::Program;
GLuint InstancedGrassPass2Shader::attrib_position;
GLuint InstancedGrassPass2Shader::attrib_texcoord;
GLuint InstancedGrassPass2Shader::attrib_color;
GLuint InstancedGrassPass2Shader::uniform_VP;
GLuint InstancedGrassPass2Shader::uniform_screen;
GLuint InstancedGrassPass2Shader::uniform_ambient;
GLuint InstancedGrassPass2Shader::uniform_windDir;
GLuint InstancedGrassPass2Shader::TU_Albedo;
void InstancedGrassPass2Shader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_grass.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_color = glGetAttribLocation(Program, "Color");
uniform_VP = glGetUniformLocation(Program, "ViewProjectionMatrix");
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");
uniform_windDir = glGetUniformLocation(Program, "windDir");
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 InstancedGrassPass2Shader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDirection)
{
glUniformMatrix4fv(uniform_VP, 1, GL_FALSE, ModelViewProjectionMatrix.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);
glUniform3f(uniform_windDir, windDirection.X, windDirection.Y, windDirection.Z);
}
GLuint SphereMapShader::Program; GLuint SphereMapShader::Program;
GLuint SphereMapShader::attrib_position; GLuint SphereMapShader::attrib_position;
GLuint SphereMapShader::attrib_normal; GLuint SphereMapShader::attrib_normal;

View File

@ -88,6 +88,17 @@ public:
static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &ViewMatrix); static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &ViewMatrix);
}; };
class InstancedGrassPass1Shader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_normal, attrib_origin, attrib_color, attrib_texcoord;
static GLuint uniform_MP, uniform_VM, uniform_windDir, uniform_tex;
static void init();
static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &ViewMatrix, const core::vector3df &windDir, unsigned TU_tex);
};
class ObjectPass2Shader class ObjectPass2Shader
{ {
public: public:
@ -183,6 +194,18 @@ public:
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDirection); static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDirection);
}; };
class InstancedGrassPass2Shader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_texcoord, attrib_color, attrib_origin;
static GLuint uniform_VP, uniform_TM, uniform_screen, uniform_ambient, uniform_windDir;
static GLuint TU_Albedo;
static void init();
static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::vector3df &windDirection);
};
class SphereMapShader class SphereMapShader
{ {
public: public:

View File

@ -29,6 +29,10 @@ void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMateria
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::InstancedObjectPass1Shader::attrib_position, -1, -1, MeshShader::InstancedObjectPass1Shader::attrib_normal, -1, -1, -1, mesh.Stride); MeshShader::InstancedObjectPass1Shader::attrib_position, -1, -1, MeshShader::InstancedObjectPass1Shader::attrib_normal, -1, -1, -1, mesh.Stride);
break; break;
case FPSM_GRASS:
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::InstancedGrassPass1Shader::attrib_position, MeshShader::InstancedGrassPass1Shader::attrib_texcoord, -1, MeshShader::InstancedGrassPass1Shader::attrib_normal, -1, -1, MeshShader::InstancedGrassPass1Shader::attrib_color, mesh.Stride);
break;
default: default:
return; return;
} }
@ -46,6 +50,10 @@ void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMateria
mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, 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); MeshShader::InstancedObjectPass2Shader::attrib_position, MeshShader::InstancedObjectPass2Shader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
break; 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);
break;
default: default:
return; return;
} }
@ -97,11 +105,24 @@ static void drawFSPMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjecti
MeshShader::InstancedObjectPass1Shader::setUniforms(ModelViewProjectionMatrix, irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW)); MeshShader::InstancedObjectPass1Shader::setUniforms(ModelViewProjectionMatrix, irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
printf("instance count is %d\n", instance_count);
glBindVertexArray(mesh.vao_first_pass); glBindVertexArray(mesh.vao_first_pass);
glDrawElementsInstanced(ptype, count, itype, 0, instance_count); 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();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::InstancedGrassPass1Shader::setUniforms(ModelViewProjectionMatrix, irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW), windDir, 0);
glBindVertexArray(mesh.vao_first_pass);
glDrawElementsInstanced(ptype, count, itype, 0, instance_count);
}
static void drawSMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, size_t instance_count) static void drawSMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, size_t instance_count)
{ {
irr_driver->IncreaseObjectCount(); irr_driver->IncreaseObjectCount();
@ -113,11 +134,25 @@ static void drawSMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjection
MeshShader::InstancedObjectPass2Shader::setUniforms(ModelViewProjectionMatrix, core::matrix4::EM4CONST_IDENTITY); MeshShader::InstancedObjectPass2Shader::setUniforms(ModelViewProjectionMatrix, core::matrix4::EM4CONST_IDENTITY);
assert(mesh.vao_second_pass);
glBindVertexArray(mesh.vao_second_pass); glBindVertexArray(mesh.vao_second_pass);
glDrawElementsInstanced(ptype, count, itype, 0, instance_count); 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();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
setTexture(MeshShader::InstancedGrassPass2Shader::TU_Albedo, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::InstancedGrassPass2Shader::setUniforms(ModelViewProjectionMatrix, windDir);
glBindVertexArray(mesh.vao_second_pass);
glDrawElementsInstanced(ptype, count, itype, 0, instance_count);
}
void STKInstancedSceneNode::render() void STKInstancedSceneNode::render()
{ {
setFirstTimeMaterial(); setFirstTimeMaterial();
@ -127,17 +162,30 @@ void STKInstancedSceneNode::render()
ModelViewProjectionMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION); ModelViewProjectionMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW); ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
glUseProgram(MeshShader::InstancedObjectPass1Shader::Program); if (!GeometricMesh[FPSM_DEFAULT].empty())
glUseProgram(MeshShader::InstancedObjectPass1Shader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++) for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 3); drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 3);
windDir = getWind();
if (!GeometricMesh[FPSM_GRASS].empty())
glUseProgram(MeshShader::InstancedGrassPass1Shader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_GRASS].size(); i++)
drawFSPMGrass(*GeometricMesh[FPSM_GRASS][i], ModelViewProjectionMatrix, windDir, instance_pos.size() / 3);
return; return;
} }
if (irr_driver->getPhase() == SOLID_LIT_PASS) if (irr_driver->getPhase() == SOLID_LIT_PASS)
{ {
glUseProgram(MeshShader::InstancedObjectPass2Shader::Program); if (!ShadedMesh[SM_DEFAULT].empty())
glUseProgram(MeshShader::InstancedObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[FPSM_DEFAULT].size(); i++) for (unsigned i = 0; i < ShadedMesh[FPSM_DEFAULT].size(); i++)
drawSMDefault(*ShadedMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 3); drawSMDefault(*ShadedMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 3);
if (!ShadedMesh[SM_GRASS].empty())
glUseProgram(MeshShader::InstancedGrassPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_GRASS].size(); i++)
drawSMGrass(*ShadedMesh[SM_GRASS][i], ModelViewProjectionMatrix, windDir, instance_pos.size() / 3);
return; return;
} }
} }

View File

@ -16,6 +16,7 @@ protected:
bool isMaterialInitialized; bool isMaterialInitialized;
void setFirstTimeMaterial(); void setFirstTimeMaterial();
void initinstancedvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat); void initinstancedvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat);
core::vector3df windDir;
public: public:
STKInstancedSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id, 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& position = irr::core::vector3df(0, 0, 0),

View File

@ -205,6 +205,21 @@ void computeTIMV(core::matrix4 &TransposeInverseModelView)
TransposeInverseModelView = TransposeInverseModelView.getTransposed(); TransposeInverseModelView = TransposeInverseModelView.getTransposed();
} }
core::vector3df getWind()
{
const core::vector3df pos = irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD).getTranslation();
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
GrassShaderProvider *gsp = (GrassShaderProvider *)irr_driver->getCallback(ES_GRASS);
float m_speed = gsp->getSpeed(), m_amplitude = gsp->getAmplitude();
float strength = (pos.X + pos.Y + pos.Z) * 1.2f + time * m_speed;
strength = noise2d(strength / 10.0f) * m_amplitude * 5;
// * 5 is to work with the existing amplitude values.
// Pre-multiply on the cpu
return irr_driver->getWind() * strength;
}
void drawObjectPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView) void drawObjectPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView)
{ {
irr_driver->IncreaseObjectCount(); irr_driver->IncreaseObjectCount();

View File

@ -64,6 +64,8 @@ void computeMVP(core::matrix4 &ModelViewProjectionMatrix);
void computeTIMV(core::matrix4 &TransposeInverseModelView); void computeTIMV(core::matrix4 &TransposeInverseModelView);
bool isObject(video::E_MATERIAL_TYPE type); bool isObject(video::E_MATERIAL_TYPE type);
core::vector3df getWind();
// Pass 1 shader (ie shaders that outputs normals and depth) // Pass 1 shader (ie shaders that outputs normals and depth)
void drawObjectPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView); void drawObjectPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView);
void drawNormalPass(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView); void drawNormalPass(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView);