Add Grass material support for instancing.
This commit is contained in:
parent
d798398478
commit
a866b3f416
25
data/shaders/instanced_grass.vert
Normal file
25
data/shaders/instanced_grass.vert
Normal 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;
|
||||
}
|
@ -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();
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
@ -88,6 +88,17 @@ public:
|
||||
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:
|
||||
@ -183,6 +194,18 @@ public:
|
||||
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:
|
||||
|
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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();
|
||||
@ -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();
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ protected:
|
||||
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),
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user