在Havok Vision 中创建后期处理效果

如果有人参考了 官方手册的教程 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

让我们从头开始
postprocessing
打开 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 BaseTexture : register(t0);
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]

大功告成,运行看看吧

发表评论

电子邮件地址不会被公开。 必填项已用*标注