Skip to content

Commit

Permalink
RTSS: implement hardware instancing support
Browse files Browse the repository at this point in the history
now works on all RenderSystems
  • Loading branch information
paroj committed Jan 12, 2020
1 parent 9f31033 commit 4263a51
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 206 deletions.
10 changes: 10 additions & 0 deletions Components/RTShaderSystem/include/OgreShaderFFPTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ THE SOFTWARE.
#include "OgreShaderPrerequisites.h"
#ifdef RTSHADER_SYSTEM_BUILD_CORE_SHADERS
#include "OgreShaderSubRenderState.h"
#include "OgreShaderParameter.h"

namespace Ogre {
namespace RTShader {
Expand Down Expand Up @@ -73,9 +74,18 @@ class _OgreRTSSExport FFPTransform : public SubRenderState

bool preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass);

void setInstancingParams(bool enabled, int texCoordIndex)
{
mInstanced = enabled;
mTexCoordIndex = Parameter::Content(Parameter::SPC_TEXTURE_COORDINATE0 + texCoordIndex);
}

static String Type;
protected:
Parameter::Content mTexCoordIndex = Parameter::SPC_TEXTURE_COORDINATE0;
bool mSetPointSize;
bool mInstanced = false;
bool mDoLightCalculations;
};


Expand Down
55 changes: 46 additions & 9 deletions Components/RTShaderSystem/src/OgreShaderFFPTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ int FFPTransform::getExecutionOrder() const
bool FFPTransform::preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass)
{
mSetPointSize = srcPass->getPointSize() != 1.0f || srcPass->isPointAttenuationEnabled();
mDoLightCalculations = srcPass->getLightingEnabled();
return true;
}

Expand All @@ -63,7 +64,7 @@ bool FFPTransform::createCpuSubPrograms(ProgramSet* programSet)

// Resolve World View Projection Matrix.
UniformParameterPtr wvpMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);

// Resolve input position parameter.
ParameterPtr positionIn = vsEntry->resolveInputParameter(Parameter::SPC_POSITION_OBJECT_SPACE);

Expand All @@ -74,10 +75,32 @@ bool FFPTransform::createCpuSubPrograms(ProgramSet* programSet)
// Add dependency.
vsProgram->addDependency(FFP_LIB_TRANSFORM);

bool isHLSL = ShaderGenerator::getSingleton().getTargetLanguage() == "hlsl";

auto stage = vsEntry->getStage(FFP_VS_TRANSFORM);
if(mInstanced)
{
if (isHLSL)
{
// set hlsl shader to use row-major matrices instead of column-major.
// it enables the use of auto-bound 3x4 matrices in generated hlsl shader.
vsProgram->setUseColumnMajorMatrices(false);
}

auto wMatrix = vsEntry->resolveInputParameter(mTexCoordIndex, GCT_MATRIX_3X4);
stage.callFunction(FFP_FUNC_TRANSFORM, wMatrix, positionIn, Out(positionIn).xyz());

if(mDoLightCalculations)
{
auto vsInNormal = vsEntry->resolveInputParameter(Parameter::SPC_NORMAL_OBJECT_SPACE);
stage.callFunction(FFP_FUNC_TRANSFORM, wMatrix, vsInNormal, vsInNormal);
}
// we can end here because the world matrix will be identity with instanced rendering
// so the code below will work as indended
}
stage.callFunction(FFP_FUNC_TRANSFORM, wvpMatrix, positionIn, positionOut);

if(!mSetPointSize || ShaderGenerator::getSingleton().getTargetLanguage() == "hlsl") // not supported with DX11
if(!mSetPointSize || isHLSL) // not supported with DX11
return true;

UniformParameterPtr pointParams = vsProgram->resolveParameter(GpuProgramParameters::ACT_POINT_PARAMS);
Expand All @@ -96,6 +119,8 @@ void FFPTransform::copyFrom(const SubRenderState& rhs)
{
const FFPTransform& rhsTransform = static_cast<const FFPTransform&>(rhs);
mSetPointSize = rhsTransform.mSetPointSize;
mInstanced = rhsTransform.mInstanced;
mTexCoordIndex = rhsTransform.mTexCoordIndex;
}

//-----------------------------------------------------------------------
Expand All @@ -110,21 +135,33 @@ SubRenderState* FFPTransformFactory::createInstance(ScriptCompiler* compiler,
{
if (prop->name == "transform_stage")
{
if(prop->values.size() == 1)
if(prop->values.size() > 0)
{
bool hasError = false;
String modelType;
int texCoordSlot = 1;

if(false == SGScriptTranslator::getString(prop->values.front(), &modelType))
auto it = prop->values.begin();

if(!SGScriptTranslator::getString(*it, &modelType))
{
compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
return NULL;
hasError = true;
}

if (modelType == "ffp")
if(++it != prop->values.end() && !SGScriptTranslator::getInt(*++it, &texCoordSlot))
hasError = true;

if(hasError)
{
return createOrRetrieveInstance(translator);
compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
return NULL;
}
}

auto ret = static_cast<FFPTransform*>(createOrRetrieveInstance(translator));
ret->setInstancingParams(modelType == "instanced", texCoordSlot);

return ret;
}
}

return NULL;
Expand Down
16 changes: 16 additions & 0 deletions Docs/src/rtss.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ To modify the default lighting stage [see below](@ref rtss_custom_api). For more

Here are the attributes you can use in a `rtshader_system` block of a .material script:

- [transform_stage](#transform_stage)
- [lighting_stage](#lighting_stage)
- [fog_stage](#fog_stage)
- [light_count](#light_count)
Expand All @@ -26,6 +27,21 @@ Here are the attributes you can use in a `rtshader_system` block of a .material
- [layered_blend](#layered_blend)
- [source_modifier](#source_modifier)

<a name="transform_stage"></a>

## transform_stage

Force a specific transform calculation
@par
Format: `transform_stage <type> [attrIndex]`
@par
Example: `transform_stage instanced 1`

@param type either `ffp` or `instanced`
@param coordinateIndex the start texcoord attribute index to read the instanced world matrix from

@note `instanced` is supposed to be used with Ogre::InstanceManager::HWInstancingBasic

<a name="lighting_stage"></a>

## lighting_stage
Expand Down
42 changes: 2 additions & 40 deletions Samples/Media/materials/programs/GLSL120/HWBasicInstancing.vert
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,19 @@

//Vertex input
attribute vec4 vertex;
attribute vec3 normal;
attribute vec4 uv0;
attribute vec4 uv1;
attribute vec4 uv2;
attribute vec4 uv3;
attribute vec3 tangent;
attribute mat3x4 uv1;

//Parameters
uniform mat4 viewProjMatrix;

#if (DEPTH_SHADOWCASTER || DEPTH_SHADOWRECEIVER)
uniform vec4 depthRange;
#endif

#if DEPTH_SHADOWRECEIVER
uniform mat4 texViewProjMatrix;
#endif

//Output
#if DEPTH_SHADOWCASTER
varying vec2 depth;
#else
varying vec2 _uv0;
varying vec3 oNormal;
varying vec3 oVPos;
#if DEPTH_SHADOWRECEIVER
varying vec4 oLightSpacePos;
#endif
#endif

//---------------------------------------------
//Main Vertex Shader
//---------------------------------------------
void main(void)
{
mat3x4 worldMatrix = mat3x4(uv1, uv2, uv3);
mat3x4 worldMatrix = uv1;
vec4 worldPos = vec4(vertex * worldMatrix, 1);
vec3 worldNorm = normal * mat3(worldMatrix);

//Transform the position
gl_Position = viewProjMatrix * worldPos;

#if DEPTH_SHADOWCASTER
depth = gl_Position.zw;
#else
_uv0 = uv0.xy;
oNormal = worldNorm;
oVPos = worldPos.xyz;

#if DEPTH_SHADOWRECEIVER
oLightSpacePos = texViewProjMatrix * worldPos;
#endif
#endif
}
53 changes: 4 additions & 49 deletions Samples/Media/materials/programs/GLSLES/HWBasicInstancing.vert
Original file line number Diff line number Diff line change
Expand Up @@ -8,64 +8,19 @@ precision mediump float;

//Vertex input
in vec4 vertex;
in vec3 normal;
in vec4 uv0;
in vec4 uv1;
in vec4 uv2;
in vec4 uv3;
in vec3 tangent;
in mat3x4 uv1;

//Parameters
uniform mat4 viewProjMatrix;

#if (DEPTH_SHADOWCASTER || DEPTH_SHADOWRECEIVER)
uniform vec4 depthRange;
#endif

#if DEPTH_SHADOWRECEIVER
uniform mat4 texViewProjMatrix;
#endif

//Output
#if DEPTH_SHADOWCASTER
out vec2 depth;
#else
out vec2 _uv0;
out vec3 oNormal;
out vec3 oVPos;
#if DEPTH_SHADOWRECEIVER
out vec4 oLightSpacePos;
#endif
#endif

//---------------------------------------------
//Main Vertex Shader
//---------------------------------------------
void main(void)
{
mat4 worldMatrix;
worldMatrix[0] = uv1;
worldMatrix[1] = uv2;
worldMatrix[2] = uv3;
worldMatrix[3] = vec4( 0, 0, 0, 1 );

vec4 worldPos = vertex * worldMatrix;
vec3 worldNorm = normal * mat3(worldMatrix);
mat3x4 worldMatrix = uv1;
vec3 worldPos = vertex * worldMatrix;

//Transform the position
gl_Position = viewProjMatrix * worldPos;

#if DEPTH_SHADOWCASTER
depth.x = (gl_Position.z - depthRange.x) * depthRange.w;
depth.y = depthRange.w;
#else
_uv0 = uv0.xy;
oNormal = worldNorm;
oVPos = worldPos.xyz;

#if DEPTH_SHADOWRECEIVER
oLightSpacePos = texViewProjMatrix * worldPos;
oLightSpacePos.z = (oLightSpacePos.z - depthRange.x) * depthRange.w;
#endif
#endif
gl_Position = viewProjMatrix * vec4(worldPos, 1);
}
40 changes: 4 additions & 36 deletions Samples/Media/materials/programs/HLSL_Cg/HWBasicInstancing.cg
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@
struct VS_INPUT
{
float4 Position : POSITION;
float3 Normal : NORMAL;
float2 uv0 : TEXCOORD0;

float4 mat14 : TEXCOORD1;
float4 mat24 : TEXCOORD2;
float4 mat34 : TEXCOORD3;
float3x4 mat : TEXCOORD1;
};

#include "InstancingVertexInterpolators.cg"
Expand All @@ -24,45 +19,18 @@ struct VS_INPUT
//---------------------------------------------
VS_OUTPUT main_vs( in VS_INPUT input,
uniform float4x4 viewProjMatrix

#if defined( DEPTH_SHADOWCASTER ) || defined( DEPTH_SHADOWRECEIVER )
, uniform float4 depthRange
#endif
#ifdef DEPTH_SHADOWRECEIVER
, uniform float4x4 texViewProjMatrix
#endif
)
{
VS_OUTPUT output;

float3x4 worldMatrix;
worldMatrix[0] = input.mat14;
worldMatrix[1] = input.mat24;
worldMatrix[2] = input.mat34;
float3x4 worldMatrix = input.mat;

float4 worldPos = float4( mul( worldMatrix, input.Position ).xyz, 1.0f );
float3 worldNorm= mul( (float3x3)(worldMatrix), input.Normal );

//Transform the position
output.Position = mul( viewProjMatrix, worldPos );

#ifdef DEPTH_SHADOWCASTER
output.ps.unused = float3( 0, 0, 0 );
output.ps.depth = (output.Position.z - depthRange.x + SHADOW_BIAS) * depthRange.w;
#else
output.ps.uv0 = input.uv0;

//Pass Normal and position for Blinn Phong lighting
output.ps.Normal = normalize(worldNorm);
output.ps.vPos = worldPos.xyz;

#ifdef DEPTH_SHADOWRECEIVER
// Calculate the position of vertex in light space to do shadows
output.ps.lightSpacePos = mul( texViewProjMatrix, worldPos );
// make linear
output.ps.lightSpacePos.z = (output.ps.lightSpacePos.z - depthRange.x) * depthRange.w;
#endif
#endif
output.ps.unused = float3( output.Position.zw, 0 );
output.ps.depth = output.Position.z;

return output;
}
Loading

0 comments on commit 4263a51

Please sign in to comment.