如果有人参考了 官方手册的教程 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <Shaders/VisionCommon.inc> #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; } |
像素 Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include <Shaders/VisionCommon.inc> #if defined(_VISION_DX11) Texture2D <float4> 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; } |
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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | 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; } } } |
最后加载这个后期处理特效
在 GameManager 的 OnAfterSceneLoaded callback 中
1 2 3 | CustomPostProcessor * tmp = new CustomPostProcessor(0.5f,10.0f); Vision::Renderer.GetRendererNode(0)->AddComponent(tmp); tmp->SetActive(true); |
大功告成,运行看看吧