Skip to content

Commit

Permalink
Add Grass material support for instancing.
Browse files Browse the repository at this point in the history
  • Loading branch information
vlj committed Mar 24, 2014
1 parent d798398 commit a866b3f
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 4 deletions.
25 changes: 25 additions & 0 deletions data/shaders/instanced_grass.vert
@@ -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;
}
84 changes: 84 additions & 0 deletions src/graphics/shaders.cpp
Expand Up @@ -319,8 +319,10 @@ void Shaders::loadShaders()
MeshShader::ObjectPass1Shader::init();
MeshShader::ObjectRefPass1Shader::init();
MeshShader::InstancedObjectPass1Shader::init();
MeshShader::InstancedGrassPass1Shader::init();
MeshShader::ObjectPass2Shader::init();
MeshShader::InstancedObjectPass2Shader::init();
MeshShader::InstancedGrassPass2Shader::init();
MeshShader::DetailledObjectPass2Shader::init();
MeshShader::ObjectRimLimitShader::init();
MeshShader::UntexturedObjectShader::init();
Expand Down Expand Up @@ -528,6 +530,42 @@ namespace MeshShader
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

GLuint ObjectPass2Shader::Program;
Expand Down Expand Up @@ -871,6 +909,52 @@ namespace MeshShader
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::attrib_position;
GLuint SphereMapShader::attrib_normal;
Expand Down
23 changes: 23 additions & 0 deletions src/graphics/shaders.hpp
Expand Up @@ -88,6 +88,17 @@ class InstancedObjectPass1Shader
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
{
public:
Expand Down Expand Up @@ -183,6 +194,18 @@ class GrassPass2Shader
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
{
public:
Expand Down
56 changes: 52 additions & 4 deletions src/graphics/stkinstancedscenenode.cpp
Expand Up @@ -29,6 +29,10 @@ void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMateria
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);
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:
return;
}
Expand All @@ -46,6 +50,10 @@ void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMateria
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);
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:
return;
}
Expand Down Expand Up @@ -97,11 +105,24 @@ static void drawFSPMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjecti

MeshShader::InstancedObjectPass1Shader::setUniforms(ModelViewProjectionMatrix, irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));

printf("instance count is %d\n", instance_count);
glBindVertexArray(mesh.vao_first_pass);
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)
{
irr_driver->IncreaseObjectCount();
Expand All @@ -113,11 +134,25 @@ static void drawSMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjection

MeshShader::InstancedObjectPass2Shader::setUniforms(ModelViewProjectionMatrix, core::matrix4::EM4CONST_IDENTITY);

assert(mesh.vao_second_pass);
glBindVertexArray(mesh.vao_second_pass);
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()
{
setFirstTimeMaterial();
Expand All @@ -127,17 +162,30 @@ void STKInstancedSceneNode::render()
ModelViewProjectionMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION);
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++)
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;
}

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++)
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;
}
}
1 change: 1 addition & 0 deletions src/graphics/stkinstancedscenenode.hpp
Expand Up @@ -16,6 +16,7 @@ class STKInstancedSceneNode : public irr::scene::CMeshSceneNode
bool isMaterialInitialized;
void setFirstTimeMaterial();
void initinstancedvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat);
core::vector3df windDir;
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),
Expand Down
15 changes: 15 additions & 0 deletions src/graphics/stkmesh.cpp
Expand Up @@ -205,6 +205,21 @@ void computeTIMV(core::matrix4 &TransposeInverseModelView)
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)
{
irr_driver->IncreaseObjectCount();
Expand Down
2 changes: 2 additions & 0 deletions src/graphics/stkmesh.hpp
Expand Up @@ -64,6 +64,8 @@ void computeMVP(core::matrix4 &ModelViewProjectionMatrix);
void computeTIMV(core::matrix4 &TransposeInverseModelView);
bool isObject(video::E_MATERIAL_TYPE type);

core::vector3df getWind();

// Pass 1 shader (ie shaders that outputs normals and depth)
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);
Expand Down

0 comments on commit a866b3f

Please sign in to comment.