Skip to content

Commit

Permalink
RTSS: implement GBuffer output SubRenderState
Browse files Browse the repository at this point in the history
supporting any two of DEPTH, DEPTH_NORMAL, DIFFUSE_SPECULAR outputs
  • Loading branch information
paroj committed Jan 18, 2020
1 parent 5168a6a commit d622b71
Show file tree
Hide file tree
Showing 13 changed files with 380 additions and 553 deletions.
133 changes: 133 additions & 0 deletions Components/RTShaderSystem/include/OgreShaderExGBuffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org
Copyright (c) 2000-2014 Torus Knot Software Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#ifndef _ShaderGBuffer_
#define _ShaderGBuffer_

#include "OgreShaderPrerequisites.h"
#ifdef RTSHADER_SYSTEM_BUILD_CORE_SHADERS
#include "OgreShaderParameter.h"
#include "OgreShaderSubRenderState.h"

namespace Ogre
{
namespace RTShader
{

/** \addtogroup Optional
* @{
*/
/** \addtogroup RTShader
* @{
*/

/** Transform sub render state implementation of writing to GBuffers
*/
class _OgreRTSSExport GBuffer : public SubRenderState
{

// Interface.
public:
enum TargetLayout
{
TL_DEPTH,
TL_DEPTH_NORMAL,
TL_DIFFUSE_SPECULAR,
};
typedef std::vector<TargetLayout> TargetBuffers;

/**
@see SubRenderState::getType.
*/
virtual const String& getType() const;

/**
@see SubRenderState::getExecutionOrder.
*/
virtual int getExecutionOrder() const;

/**
@see SubRenderState::copyFrom.
*/
virtual void copyFrom(const SubRenderState& rhs);

/**
@see SubRenderState::createCpuSubPrograms.
*/
virtual bool createCpuSubPrograms(ProgramSet* programSet);

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

void setOutBuffers(const TargetBuffers& buffers) { mOutBuffers = buffers; }

static String Type;

private:
void addDepthInvocations(ProgramSet* programSet, const ParameterPtr& out) const;
void addNormalInvocations(ProgramSet* programSet, const ParameterPtr& out) const ;
void addDiffuseSpecularInvocations(ProgramSet* programSet, const ParameterPtr& out) const;

TargetBuffers mOutBuffers;
};

/**
A factory that enables creation of GBuffer instances.
@remarks Sub class of SubRenderStateFactory
*/
class _OgreRTSSExport GBufferFactory : public SubRenderStateFactory
{
public:
/**
@see SubRenderStateFactory::getType.
*/
virtual const String& getType() const;

/**
@see SubRenderStateFactory::createInstance.
*/
virtual SubRenderState* createInstance(ScriptCompiler* compiler, PropertyAbstractNode* prop, Pass* pass,
SGScriptTranslator* translator);

/**
@see SubRenderStateFactory::writeInstance.
*/
virtual void writeInstance(MaterialSerializer* ser, SubRenderState* subRenderState, Pass* srcPass, Pass* dstPass);

protected:
/**
@see SubRenderStateFactory::createInstanceImpl.
*/
virtual SubRenderState* createInstanceImpl();
};

/** @} */
/** @} */

} // namespace RTShader
} // namespace Ogre

#endif
#endif
224 changes: 224 additions & 0 deletions Components/RTShaderSystem/src/OgreShaderExGBuffer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org
Copyright (c) 2000-2014 Torus Knot Software Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreShaderPrecompiledHeaders.h"
#ifdef RTSHADER_SYSTEM_BUILD_CORE_SHADERS

namespace Ogre
{
namespace RTShader
{

/************************************************************************/
/* */
/************************************************************************/
String GBuffer::Type = "GBuffer";

//-----------------------------------------------------------------------
const String& GBuffer::getType() const { return Type; }

//-----------------------------------------------------------------------
int GBuffer::getExecutionOrder() const { return FFP_LIGHTING; }

bool GBuffer::preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass)
{
srcPass->setLightingEnabled(false); // disable receiving shadows
return true;
}

//-----------------------------------------------------------------------
bool GBuffer::createCpuSubPrograms(ProgramSet* programSet)
{
Function* psMain = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM)->getMain();

for(size_t i = 0; i < mOutBuffers.size(); i++)
{
auto out =
psMain->resolveOutputParameter(i == 0 ? Parameter::SPC_COLOR_DIFFUSE : Parameter::SPC_COLOR_SPECULAR);

switch(mOutBuffers[i])
{
case TL_DEPTH_NORMAL:
addNormalInvocations(programSet, out);
OGRE_FALLTHROUGH;
case TL_DEPTH:
addDepthInvocations(programSet, out);
break;
case TL_DIFFUSE_SPECULAR:
addDiffuseSpecularInvocations(programSet, out);
break;
default:
OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "unsupported TargetLayout");
}
}

return true;
}

void GBuffer::addDepthInvocations(ProgramSet* programSet, const ParameterPtr& out) const
{
Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
Function* vsMain = vsProgram->getMain();
Function* psMain = psProgram->getMain();

// vertex shader
auto vsOutPos = vsMain->resolveOutputParameter(Parameter::SPC_POSITION_PROJECTIVE_SPACE);

bool isD3D9 = ShaderGenerator::getSingleton().getTargetLanguage() == "hlsl" &&
!GpuProgramManager::getSingleton().isSyntaxSupported("vs_4_0_level_9_1");

if (isD3D9)
{
auto vstage = vsMain->getStage(FFP_VS_POST_PROCESS);
auto vsPos = vsMain->resolveOutputParameter(Parameter::SPC_UNKNOWN, GCT_FLOAT4);
vstage.assign(vsOutPos, vsPos);
std::swap(vsOutPos, vsPos);
}

// fragment shader
auto fstage = psMain->getStage(FFP_PS_COLOUR_END);
auto viewPos = psMain->resolveInputParameter(vsOutPos);

fstage.assign(In(viewPos).z(), Out(out).x());

if (isD3D9)
{
fstage.div(In(out).x(), In(viewPos).w(), Out(out).x());
}
}

void GBuffer::addNormalInvocations(ProgramSet* programSet, const ParameterPtr& out) const
{
Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
Function* vsMain = vsProgram->getMain();
Function* psMain = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM)->getMain();

// compute vertex shader normal
auto vstage = vsMain->getStage(FFP_VS_LIGHTING);
auto vsInNormal = vsMain->resolveInputParameter(Parameter::SPC_NORMAL_OBJECT_SPACE);
auto vsOutNormal = vsMain->resolveOutputParameter(Parameter::SPC_NORMAL_VIEW_SPACE);
auto worldViewITMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_NORMAL_MATRIX);
vstage.callFunction(FFP_FUNC_TRANSFORM, worldViewITMatrix, vsInNormal, vsOutNormal);

// pass through
auto fstage = psMain->getStage(FFP_PS_COLOUR_END);
fstage.assign(psMain->resolveInputParameter(vsOutNormal), Out(out).mask(Operand::OPM_YZW));
}

void GBuffer::addDiffuseSpecularInvocations(ProgramSet* programSet, const ParameterPtr& out) const
{
Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
Function* psMain = psProgram->getMain();

// set diffuse - TODO vertex color tracking
auto diffuse = psProgram->resolveParameter(GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
psMain->getStage(FFP_PS_COLOUR_BEGIN + 1).assign(diffuse, out);

// set shininess
auto surfaceShininess = psProgram->resolveParameter(GpuProgramParameters::ACT_SURFACE_SHININESS);
psMain->getStage(FFP_PS_COLOUR_END).assign(surfaceShininess, Out(out).w());
}

//-----------------------------------------------------------------------
void GBuffer::copyFrom(const SubRenderState& rhs)
{
const GBuffer& rhsTransform = static_cast<const GBuffer&>(rhs);
mOutBuffers = rhsTransform.mOutBuffers;
}

//-----------------------------------------------------------------------
const String& GBufferFactory::getType() const { return GBuffer::Type; }

static GBuffer::TargetLayout translate(const String& val)
{
if(val == "depth")
return GBuffer::TL_DEPTH;
if(val == "depth_normal")
return GBuffer::TL_DEPTH_NORMAL;
return GBuffer::TL_DIFFUSE_SPECULAR;
}

//-----------------------------------------------------------------------
SubRenderState* GBufferFactory::createInstance(ScriptCompiler* compiler, PropertyAbstractNode* prop, Pass* pass,
SGScriptTranslator* translator)
{
if (prop->name != "lighting_stage" || prop->values.size() < 2)
return NULL;

auto it = prop->values.begin();
String val;

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

if (val != "gbuffer")
return NULL;

GBuffer::TargetBuffers targets;

if(!SGScriptTranslator::getString(*it++, &val))
{
compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
return NULL;
}
targets.push_back(translate(val));

if(it != prop->values.end())
{
if(!SGScriptTranslator::getString(*it++, &val))
{
compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
return NULL;
}

targets.push_back(translate(val));
}

auto ret = static_cast<GBuffer*>(createOrRetrieveInstance(translator));
ret->setOutBuffers(targets);
return ret;
}

//-----------------------------------------------------------------------
void GBufferFactory::writeInstance(MaterialSerializer* ser, SubRenderState* subRenderState, Pass* srcPass,
Pass* dstPass)
{
ser->writeAttribute(4, "lighting_stage");
ser->writeValue("gbuffer");
ser->writeValue("depth");
}

//-----------------------------------------------------------------------
SubRenderState* GBufferFactory::createInstanceImpl() { return OGRE_NEW GBuffer; }

} // namespace RTShader
} // namespace Ogre

#endif
4 changes: 4 additions & 0 deletions Components/RTShaderSystem/src/OgreShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,10 @@ void ShaderGenerator::createBuiltinSRSFactories()
curFactory = OGRE_NEW TriplanarTexturingFactory;
addSubRenderStateFactory(curFactory);
mBuiltinSRSFactories.push_back(curFactory);

curFactory = OGRE_NEW GBufferFactory;
addSubRenderStateFactory(curFactory);
mBuiltinSRSFactories.push_back(curFactory);
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ THE SOFTWARE.
#include "OgreShaderExDualQuaternionSkinning.h"
#include "OgreShaderExTextureAtlasSampler.h"
#include "OgreShaderExTriplanarTexturing.h"
#include "OgreShaderExGBuffer.h"

#include "OgreShaderCGProgramProcessor.h"
#include "OgreShaderHLSLProgramProcessor.h"
Expand Down
8 changes: 6 additions & 2 deletions Docs/src/rtss.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,17 @@ Example: `transform_stage instanced 1`
Force a specific lighting model.

@par
Format1: `lighting_stage <ffp|per_pixel> [normalised]`
Format: `lighting_stage <ffp|per_pixel|normal_map|gbuffer> [normalised]`
@par
Format2: `lighting_stage normal_map <texturename> [tangent_space|object_space] [coordinateIndex] [samplerName]`
@par
Format3: `lighting_stage gbuffer <target_layout> [target_layout]`
@par
Example: `lighting_stage normal_map Panels_Normal_Tangent.png tangent_space 0 SamplerToUse`

@param normalised @copybrief Ogre::RTShader::FFPLighting::setNormaliseEnabled @copydetails Ogre::RTShader::FFPLighting::setNormaliseEnabled
@param normalised with @c ffp or @c per_pixel @copybrief Ogre::RTShader::FFPLighting::setNormaliseEnabled @copydetails Ogre::RTShader::FFPLighting::setNormaliseEnabled
@param texturename normal map to use with @c normal_map
@param target_layout with @c gbuffer, this specifies the data to be written into one ore two MRT targets. Possible values are @c depth, @c depth_normal and @c diffuse_specular

@see Ogre::RTShader::NormalMapLighting::NormalMapSpace
@see @ref Samplers
Expand Down
Loading

0 comments on commit d622b71

Please sign in to comment.