Skip to content

Commit

Permalink
RTSS: implement parallax mapping and use it in respective sample
Browse files Browse the repository at this point in the history
  • Loading branch information
paroj committed Feb 3, 2020
1 parent 2ee2d31 commit 54555e5
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 202 deletions.
21 changes: 14 additions & 7 deletions Components/RTShaderSystem/include/OgreShaderExNormalMapLighting.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,6 @@ class _OgreRTSSExport NormalMapLighting : public PerPixelLighting
/// Normal map space definition.
enum NormalMapSpace
{
/**
Normal map contains normal data in tangent space.
This is the default normal mapping behavior and it requires that the
target mesh will have valid tangents within its vertex data.
*/
NMS_TANGENT,
/**
Normal map contains normal data in object local space.
This normal mapping technique has the advantages of better visualization results,
Expand All @@ -109,7 +103,20 @@ class _OgreRTSSExport NormalMapLighting : public PerPixelLighting
The main drawback of using this kind of normal map is that the target object must be static
in terms of local space rotations and translations.
*/
NMS_OBJECT
NMS_OBJECT = 1,
/**
Normal map contains normal data in tangent space.
This is the default normal mapping behavior and it requires that the
target mesh will have valid tangents within its vertex data.
*/
NMS_TANGENT = 2,
/**
Normal map contains normal data in parallax corrected tangent space
The restrictions of NMS_TANGENT apply. Additionally the alpha
channel of the normal texture is expected to contain height displacement data.
This is used for parallax corrected rendering.
*/
NMS_PARALLAX = 6
};

/**
Expand Down
51 changes: 37 additions & 14 deletions Components/RTShaderSystem/src/OgreShaderExNormalMapLighting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ bool NormalMapLighting::resolveGlobalParameters(ProgramSet* programSet)
auto posContent = Parameter::SPC_POSTOCAMERA_OBJECT_SPACE;

// Resolve input vertex shader tangent.
if (mNormalMapSpace == NMS_TANGENT)
if (mNormalMapSpace & NMS_TANGENT)
{
mVSInTangent = vsMain->resolveInputParameter(Parameter::SPC_TANGENT_OBJECT_SPACE);

Expand Down Expand Up @@ -241,11 +241,11 @@ bool NormalMapLighting::resolvePerLightParameters(ProgramSet* programSet)
if(mLightParamsList.size() > 8)
mLightParamsList.resize(8);

bool needViewPos = false;
bool needViewPos = mNormalMapSpace == NMS_PARALLAX;

auto lightDirContent = mNormalMapSpace == NMS_TANGENT ? Parameter::SPC_LIGHTDIRECTION_TANGENT_SPACE0
auto lightDirContent = mNormalMapSpace & NMS_TANGENT ? Parameter::SPC_LIGHTDIRECTION_TANGENT_SPACE0
: Parameter::SPC_LIGHTDIRECTION_OBJECT_SPACE0;
auto lightPosContent = mNormalMapSpace == NMS_TANGENT ? Parameter::SPC_POSTOLIGHT_TANGENT_SPACE0
auto lightPosContent = mNormalMapSpace & NMS_TANGENT ? Parameter::SPC_POSTOLIGHT_TANGENT_SPACE0
: Parameter::SPC_POSITION_OBJECT_SPACE;

// Resolve per light parameters.
Expand All @@ -263,7 +263,7 @@ bool NormalMapLighting::resolvePerLightParameters(ProgramSet* programSet)
case Light::LT_POINT:
mLightParamsList[i].mPosition = vsProgram->resolveParameter(GpuProgramParameters::ACT_LIGHT_POSITION, i);
mLightParamsList[i].mVSOutToLightDir =
vsMain->resolveOutputParameter(Parameter::Content(lightPosContent + i));
vsMain->resolveOutputParameter(Parameter::Content(lightPosContent + i), GCT_FLOAT3);
mLightParamsList[i].mToLight = psMain->resolveInputParameter(mLightParamsList[i].mVSOutToLightDir);

mLightParamsList[i].mAttenuatParams = psProgram->resolveParameter(GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
Expand All @@ -275,7 +275,7 @@ bool NormalMapLighting::resolvePerLightParameters(ProgramSet* programSet)

mLightParamsList[i].mPosition = vsProgram->resolveParameter(GpuProgramParameters::ACT_LIGHT_POSITION, i);
mLightParamsList[i].mVSOutToLightDir =
vsMain->resolveOutputParameter(Parameter::Content(lightPosContent + i));
vsMain->resolveOutputParameter(Parameter::Content(lightPosContent + i), GCT_FLOAT3);
mLightParamsList[i].mToLight = psMain->resolveInputParameter(mLightParamsList[i].mVSOutToLightDir);

mLightParamsList[i].mDirection = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_LIGHTS|GPV_PER_OBJECT, "light_direction_obj_space");
Expand Down Expand Up @@ -341,6 +341,7 @@ bool NormalMapLighting::resolveDependencies(ProgramSet* programSet)

psProgram->addDependency(FFP_LIB_TEXTURING);
psProgram->addDependency(SGX_LIB_PERPIXELLIGHTING);
psProgram->addDependency(SGX_LIB_NORMALMAP);

return true;
}
Expand All @@ -358,10 +359,24 @@ bool NormalMapLighting::addFunctionInvocations(ProgramSet* programSet)

auto stage = psMain->getStage(FFP_PS_COLOUR_BEGIN + 1);

if (mNormalMapSpace == NMS_PARALLAX)
{
// TODO: use specificed scale and bias
stage.callFunction("SGX_Generate_Parallax_Texcoord", {In(mPSNormalMapSampler), In(mPSInTexcoord), In(mToView),
In(Vector2(0.04, -0.02)), Out(mPSInTexcoord)});

// overwrite texcoord0 unconditionally, only one texcoord set is supported with parallax mapping
// we are before FFP_PS_TEXTURING, so the new value will be used
auto texcoord0 = psMain->resolveInputParameter(Parameter::SPC_TEXTURE_COORDINATE0, GCT_FLOAT2);
stage.assign(mPSInTexcoord, texcoord0);
}

// Add the normal fetch function invocation
if(!mLightParamsList.empty())
{
stage.callFunction(SGX_FUNC_FETCHNORMAL, mPSNormalMapSampler, mPSInTexcoord, mViewNormal);

}

// Add the global illumination functions.
addPSGlobalIlluminationInvocation(stage);

Expand All @@ -381,7 +396,7 @@ bool NormalMapLighting::addFunctionInvocations(ProgramSet* programSet)
void NormalMapLighting::addVSInvocation(const FunctionStageRef& stage)
{
// Construct TNB matrix.
if (mNormalMapSpace == NMS_TANGENT)
if (mNormalMapSpace & NMS_TANGENT)
{
stage.callFunction(SGX_FUNC_CONSTRUCT_TBNMATRIX, mVSInNormal, mVSInTangent, mVSTBNMatrix);
}
Expand All @@ -407,13 +422,13 @@ void NormalMapLighting::addVSInvocation(const FunctionStageRef& stage)
stage.callFunction(FFP_FUNC_TRANSFORM, mWorldInvRotMatrix, mVSLocalDir, mVSLocalDir);

// Transform to tangent space.
if (mNormalMapSpace == NMS_TANGENT)
if (mNormalMapSpace & NMS_TANGENT)
{
stage.callFunction(FFP_FUNC_TRANSFORM, mVSTBNMatrix, mVSLocalDir, mVSOutViewPos);
}

// Output object space.
else if (mNormalMapSpace == NMS_OBJECT)
else if (mNormalMapSpace & NMS_OBJECT)
{
stage.assign(mVSLocalDir, mVSOutViewPos);
}
Expand All @@ -434,13 +449,13 @@ void NormalMapLighting::addVSIlluminationInvocation(const LightParams* curLightP
curLightParams->mVSOutDirection.get() != NULL)
{
// Transform to texture space.
if (mNormalMapSpace == NMS_TANGENT)
if (mNormalMapSpace & NMS_TANGENT)
{
stage.callFunction(FFP_FUNC_TRANSFORM, mVSTBNMatrix, In(curLightParams->mDirection).xyz(),
curLightParams->mVSOutDirection);
}
// Output object space.
else if (mNormalMapSpace == NMS_OBJECT)
else if (mNormalMapSpace & NMS_OBJECT)
{
stage.assign(In(curLightParams->mDirection).xyz(), curLightParams->mVSOutDirection);
}
Expand All @@ -457,14 +472,14 @@ void NormalMapLighting::addVSIlluminationInvocation(const LightParams* curLightP
stage.callFunction(FFP_FUNC_TRANSFORM, mWorldInvRotMatrix, mVSLocalDir, mVSLocalDir);

// Transform to tangent space.
if (mNormalMapSpace == NMS_TANGENT)
if (mNormalMapSpace & NMS_TANGENT)
{
stage.callFunction(FFP_FUNC_TRANSFORM, mVSTBNMatrix, mVSLocalDir,
curLightParams->mVSOutToLightDir);
}

// Output object space.
else if (mNormalMapSpace == NMS_OBJECT)
else if (mNormalMapSpace & NMS_OBJECT)
{
stage.assign(mVSLocalDir, curLightParams->mVSOutToLightDir);
}
Expand Down Expand Up @@ -497,6 +512,9 @@ bool NormalMapLighting::preAddToRenderState(const RenderState* renderState, Pass
normalMapTexture->setSampler(mNormalMapSampler);
mNormalMapSamplerIndex = dstPass->getNumTextureUnitStates() - 1;

if(mNormalMapSpace == NMS_PARALLAX)
mSpecularEnable = true;

return true;
}

Expand Down Expand Up @@ -562,6 +580,11 @@ SubRenderState* NormalMapLightingFactory::createInstance(ScriptCompiler* compile
{
normalMapSubRenderState->setNormalMapSpace(NormalMapLighting::NMS_OBJECT);
}

if (strValue == "parallax")
{
normalMapSubRenderState->setNormalMapSpace(NormalMapLighting::NMS_PARALLAX);
}
}

// Read texture coordinate index.
Expand Down
2 changes: 1 addition & 1 deletion Docs/src/rtss.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Force a specific lighting model.
@par
Format: `lighting_stage <ffp|per_pixel|normal_map|gbuffer> [normalised]`
@par
Format2: `lighting_stage normal_map <texturename> [tangent_space|object_space] [coordinateIndex] [samplerName]`
Format2: `lighting_stage normal_map <texturename> [tangent_space|object_space|parallax] [coordinateIndex] [samplerName]`
@par
Format3: `lighting_stage gbuffer <target_layout> [target_layout]`
@par
Expand Down
4 changes: 2 additions & 2 deletions Media/RTShaderLib/GLSL/SGXLib_NormalMap.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@ void SGX_Generate_Parallax_Texcoord(in sampler2D normalHeightMap,
eyeVec = normalize(eyeVec);
float height = texture2D(normalHeightMap, texCoord).a;
float displacement = (height * scaleBias.x) + scaleBias.y;
vec3 scaledEyeDir = eyeVec * displacement;
newTexCoord = (scaledEyeDir + vec3(texCoord, 1.0)).xy;
vec2 scaledEyeDir = eyeVec.xy * displacement;
newTexCoord = scaledEyeDir + texCoord;
}
4 changes: 2 additions & 2 deletions Media/RTShaderLib/HLSL_Cg/SGXLib_NormalMap.cg
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ void SGX_Generate_Parallax_Texcoord(in sampler2D normalHeightMap,
eyeVec = normalize(eyeVec);
float height = tex2D(normalHeightMap, texCoord).a;
float displacement = (height * scaleBias.x) + scaleBias.y;
float3 scaledEyeDir = eyeVec * displacement;
newTexCoord = (scaledEyeDir + float3(texCoord, 1.0)).xy;
float2 scaledEyeDir = eyeVec.xy * displacement;
newTexCoord = scaledEyeDir + texCoord;
}
39 changes: 0 additions & 39 deletions Samples/Media/materials/programs/GLSL/OffsetMappingFp.glsl

This file was deleted.

45 changes: 0 additions & 45 deletions Samples/Media/materials/programs/GLSL/OffsetMappingVp.glsl

This file was deleted.

Loading

0 comments on commit 54555e5

Please sign in to comment.