如果有人参考了 官方手册的教程 Tutorial: Creating Custom Post-Processing Effects
然后使用 PA 的 vGameSolutionCreator 默认设置创建项目,会发现运行报错
active renderer does not provide all buffers required by the post processor.Execute
经过debug,发现默认创建的render node 实际上是 VMobileForwardRenderingSystem
它只支持一个bufferflag 就是 VBUFFERFLAG_FINALCOLOR
让我们从头开始
打开 VForge 编写我们的后期处理特效,这次范例就用径向模糊(Dx9,Dx11)
打开Shader Code Editor
顶点Code
[cc language=”cpp”]
#include
#ifdef _VISION_DX11
cbuffer g_GlobalConstantBufferObject : register (b1)
{
float4x4 matMVP : packoffset(c4); // model view projection matrix
}
#else
float4x4 matMVP : register(c8);
#endif
struct Data_In
{
float4 VectPos : POSITION;
float4 UV : TEXCOORD0;
};
struct Data_Out
{
float4 ProjPos : SV_POSITION;
float4 UV : TEXCOORD0;
};
Data_Out vs_main( Data_In In )
{
Data_Out output;
output.ProjPos = mul(matMVP, In.VectPos);
output.UV = In.UV;
return output;
}
[/cc]
像素 Code
[cc language=”cpp”]
#include
#if defined(_VISION_DX11)
Texture2D
sampler BaseTextureSampler : register(s0);
cbuffer g_GlobalConstantBufferObject : register (b2)
{
float SampleDist : register(c0);
float SampleStrength : register(c1);
}
#else
sampler2D BaseTexture : register(s0);
float SampleDist;
float SampleStrength;
#endif
struct Data_In
{
float4 ProjPos : SV_POSITION;
float4 UV : TEXCOORD0;
};
float4 ps_main( Data_In In ) : SV_Target
{
float2 dir = 0.5 – In.UV;
float dist = length(dir);
dir /= dist;
float4 color = vTex2D(BaseTexture, BaseTextureSampler, In.UV);
float4 sum = color;
float startValue = -0.08;
for(int i = 0; i < 10; i++)
{
sum += vTex2D(BaseTexture,BaseTextureSampler,In.UV + dir * startValue * SampleDist);
startValue += 0.3;
}
sum /= 11.0;
float t = saturate(dist * SampleStrength);
float4 final = lerp(color, sum, t);
return final;
}
[/cc]
Shader Tech的名字为 RadialBlurShader 然后保存 ShaderLib
之后编写我们的 Vision Code
头文件
CustomPostProcessor.h
class CustomPostProcessor : public VPostProcessingBaseComponent { public: CustomPostProcessor(float fSampleDist = 0.5f, float fSampleStrength = 10.0f); virtual ~CustomPostProcessor(); virtual void Serialize( VArchive &ar ) HKV_OVERRIDE; virtual void OnHandleCallback(IVisCallbackDataObject_cl *pData); float m_fSampleDist; float m_fSampleStrength; private: V_DECLARE_SERIAL_DLLEXP(CustomPostProcessor,SAMPLEPLUGIN_IMPEXP); V_DECLARE_VARTABLE(CustomPostProcessor, SAMPLEPLUGIN_IMPEXP); virtual void Execute() HKV_OVERRIDE; void SetupContext(); void RemoveContext(); void CreateShaders(); void RemoveShaders(); //shader VCompiledTechniquePtr m_spCustomTechnique; };
cpp文件
[cc language=”cpp”]
V_IMPLEMENT_SERIAL( CustomPostProcessor, VPostProcessingBaseComponent, 0, &g_myComponentModule );
START_VAR_TABLE(CustomPostProcessor, VPostProcessingBaseComponent, “VCustomPostProcessor”, 0, “”)
DEFINE_VAR_FLOAT(CustomPostProcessor, m_fSampleDist, “m_fSampleDist”, “0.0”, 0, “Slider(0,100)”);
DEFINE_VAR_FLOAT(CustomPostProcessor, m_fSampleStrength, “m_fSampleStrength”, “0.0”, 0, “Slider(0,100)”);
END_VAR_TABLE
CustomPostProcessor::CustomPostProcessor( float fSampleDist /*= 0.5f*/, float fSampleStrength/* = 10.0f*/ )
:m_spCustomTechnique(NULL)
{
m_fSampleDist = fSampleDist;
m_fSampleStrength = fSampleStrength;
m_iRequiredBufferFlags = VBUFFERFLAG_FINALCOLOR;
m_fPriority = VIS_RENDERCONTEXTPRIORITY_POSTPROCESSOR_RESOLVED + 6000.0f;
// Our post-processor covers the entire render target
m_bufferUsageFlags = DRAWS_FULLSCREEN_QUAD;
Vision::Callbacks.OnUpdateSceneBegin += this;
}
CustomPostProcessor::~CustomPostProcessor()
{
Vision::Callbacks.OnUpdateSceneBegin -= this;
}
void CustomPostProcessor::Serialize( VArchive &ar )
{
char iLocalVersion = 0;
if(ar.IsLoading())
{
ar >> iLocalVersion;
ar >> m_bActive;
ar >> m_fSampleDist;
ar >> m_fSampleStrength;
}else{
ar << iLocalVersion;
ar << m_bActive;
ar << m_fSampleDist;
ar << m_fSampleStrength;
}
}
void CustomPostProcessor::InitializePostProcessor()
{
if(m_bIsInitialized)
{
return;
}
SetupContext();
CreateShaders();
m_bIsInitialized = true;
}
void CustomPostProcessor::DeInitializePostProcessor()
{
if(!m_bIsInitialized)
{
return;
}
RemoveShaders();
RemoveContext();
m_bIsInitialized = false;
}
void CustomPostProcessor::Execute()
{
VCompiledShaderPass * pPass = m_spCustomTechnique->GetShader(0);
IVRender2DInterface *pRender = Vision::RenderLoopHelper.BeginOverlayRendering();
Overlay2DVertex_t * pVertex = GetOwner()->GetRendererNodeHelper()->GetOverlayVertices();
pRender->Draw2DBufferWithShader(6, pVertex, m_spSourceTextures[0], *pPass);
Vision::RenderLoopHelper.EndOverlayRendering();
}
void CustomPostProcessor::SetupContext()
{
VisRenderContext_cl * pTargetContext = GetTargetContext();
pTargetContext->SetName(“VCustomPostProcessor – Target Context”);
//在渲染节点中注册上下文
GetOwner()->AddContext(pTargetContext);
//获取纹理引用
m_spSourceTextures[0] = GetOwner()->GetGBuffer(IVRendererNode::VGBT_Diffuse);
m_iNumSourceTextures = 1;
}
void CustomPostProcessor::RemoveContext()
{
m_spSourceTextures[0] = NULL;
GetOwner()->RemoveContext(GetTargetContext());
}
void CustomPostProcessor::CreateShaders()
{
if(Vision::Shaders.LoadShaderLibrary(“\shaders\EasyGameShader.ShaderLib”))
{
m_spCustomTechnique = Vision::Shaders.CreateTechnique(“RadialBlurShader”, NULL, NULL, EFFECTCREATEFLAG_FORCEUNIQUE);
if(m_spCustomTechnique){
//后期渲染不需要深度
m_spCustomTechnique->GetShader(0)->GetRenderState()->GetDepthStencilState().m_bDepthTestEnabled = false;
m_spCustomTechnique->GetShader(0)->GetRenderState()->GetDepthStencilState().ComputeHash();
}
}
}
void CustomPostProcessor::RemoveShaders()
{
m_spCustomTechnique = NULL;
}
void CustomPostProcessor::OnHandleCallback( IVisCallbackDataObject_cl *pData )
{
if(pData->m_pSender== &Vision::Callbacks.OnUpdateSceneBegin)
{
if(m_spCustomTechnique){
VCompiledShaderPass * pPass = m_spCustomTechnique->GetShader(0);
const float * fSampleDist = &m_fSampleDist;
const float * fSampeStrength = &m_fSampleStrength;
pPass->GetConstantBuffer(VSS_PixelShader)->SetSingleParameterF(“SampleDist”, fSampleDist);
pPass->GetConstantBuffer(VSS_PixelShader)->SetSingleParameterF(“SampleStrength”, fSampeStrength);
pPass->m_bModified = true;
}
}
}
[/cc]
最后加载这个后期处理特效
在 GameManager 的 OnAfterSceneLoaded callback 中
[cc language=”cpp”]
CustomPostProcessor * tmp = new CustomPostProcessor(0.5f,10.0f);
Vision::Renderer.GetRendererNode(0)->AddComponent(tmp);
tmp->SetActive(true);
[/cc]
大功告成,运行看看吧