//----------------------------------------------------------------------------- // Debugging aid to display a texture //----------------------------------------------------------------------------- static void OverlayShowTexture( const char* textureName, float scale ) { bool foundVar; IMaterial *pMaterial; IMaterialVar *BaseTextureVar; ITexture *pTex; float x, y, w, h; // ___error is created in code in CMaterialSystem::CreateDebugMaterials() pMaterial = materials->FindMaterial( "___error", TEXTURE_GROUP_OTHER, true ); BaseTextureVar = pMaterial->FindVar( "$basetexture", &foundVar, false ); if (!foundVar) return; CMatRenderContextPtr pRenderContext( materials ); if ( textureName && textureName[0] ) { pTex = materials->FindTexture( textureName, TEXTURE_GROUP_OTHER, false ); BaseTextureVar->SetTextureValue( pTex ); w = pTex->GetActualWidth() * scale; h = pTex->GetActualHeight() * scale; } else { w = h = 64.0f * scale; } // Center relative to current viewport int nViewportX, nViewportY, nViewportWidth, nViewportHeight; pRenderContext->GetViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight ); x = ( nViewportWidth - w ) * 0.5f; y = ( nViewportHeight - h ) * 0.5f; pRenderContext->Bind( pMaterial ); IMesh* pMesh = pRenderContext->GetDynamicMesh( true ); CMeshBuilder meshBuilder; meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 ); meshBuilder.Position3f( x, y, 0.0f ); meshBuilder.TexCoord2f( 0, 0.0f, 0.0f ); meshBuilder.AdvanceVertex(); meshBuilder.Position3f( x+w, y, 0.0f ); meshBuilder.TexCoord2f( 0, 1.0f, 0.0f ); meshBuilder.AdvanceVertex(); meshBuilder.Position3f( x+w, y+h, 0.0f ); meshBuilder.TexCoord2f( 0, 1.0f, 1.0f ); meshBuilder.AdvanceVertex(); meshBuilder.Position3f( x, y+h, 0.0f ); meshBuilder.TexCoord2f( 0, 0.0f, 1.0f ); meshBuilder.AdvanceVertex(); meshBuilder.End(); pMesh->Draw(); }
//----------------------------------------------------------------------------- // Debugging aid to display a texture //----------------------------------------------------------------------------- static void OverlayShowTexture( const char* textureName, float scale ) { bool foundVar; IMaterial *pMaterial; IMaterialVar *BaseTextureVar; ITexture *pTex; float x, y, w, h; // screen safe x = 32; y = 32; pMaterial = materials->FindMaterial( "___debug", TEXTURE_GROUP_OTHER, true ); BaseTextureVar = pMaterial->FindVar( "$basetexture", &foundVar, false ); if (!foundVar) return; CMatRenderContextPtr pRenderContext( materials ); if ( textureName && textureName[0] ) { pTex = materials->FindTexture( textureName, TEXTURE_GROUP_OTHER, false ); BaseTextureVar->SetTextureValue( pTex ); w = pTex->GetActualWidth() * scale; h = pTex->GetActualHeight() * scale; } else { w = h = 64.0f * scale; } pRenderContext->Bind( pMaterial ); IMesh* pMesh = pRenderContext->GetDynamicMesh( true ); CMeshBuilder meshBuilder; meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 ); meshBuilder.Position3f( x, y, 0.0f ); meshBuilder.TexCoord2f( 0, 0.0f, 0.0f ); meshBuilder.AdvanceVertex(); meshBuilder.Position3f( x+w, y, 0.0f ); meshBuilder.TexCoord2f( 0, 1.0f, 0.0f ); meshBuilder.AdvanceVertex(); meshBuilder.Position3f( x+w, y+h, 0.0f ); meshBuilder.TexCoord2f( 0, 1.0f, 1.0f ); meshBuilder.AdvanceVertex(); meshBuilder.Position3f( x, y+h, 0.0f ); meshBuilder.TexCoord2f( 0, 0.0f, 1.0f ); meshBuilder.AdvanceVertex(); meshBuilder.End(); pMesh->Draw(); }
//------------------------------------------------------------------------------ // CExampleEffect render //------------------------------------------------------------------------------ void CExampleEffect::Render( int x, int y, int w, int h ) { if ( !IsEnabled() ) return; // Render Effect Rect_t actualRect; UpdateScreenEffectTexture( 0, x, y, w, h, false, &actualRect ); ITexture *pTexture = GetFullFrameFrameBufferTexture( 0 ); CMatRenderContextPtr pRenderContext( materials ); pRenderContext->DrawScreenSpaceRectangle( m_Material, x, y, w, h, actualRect.x, actualRect.y, actualRect.x+actualRect.width-1, actualRect.y+actualRect.height-1, pTexture->GetActualWidth(), pTexture->GetActualHeight() ); }
void draw_pp_shader( const CViewSetup &view, IMaterial *pMaterial) { int x = view.x; int y = view.y; int w = view.width; int h = view.height; Rect_t actualRect; UpdateScreenEffectTexture( 0, x, y, w, h, false, &actualRect); int u1 = actualRect.x; int v1 = actualRect.y; int u2 = actualRect.x+actualRect.width-1; int v2 = actualRect.y+actualRect.height-1; ITexture *pTexture = GetFullFrameFrameBufferTexture( 0 ); int aw = pTexture->GetActualWidth(); int ah = pTexture->GetActualHeight(); CMatRenderContextPtr pRenderContext( materials ); pRenderContext->DrawScreenSpaceRectangle( pMaterial, x, y, w, h, u1, v1, u2, v2, aw, ah ); pRenderContext.SafeRelease(); }
void CGlowObjectManager::ApplyEntityGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, float flBloomScale, int x, int y, int w, int h ) { static bool s_bFirstPass = true; //=======================================================// // Render objects into stencil buffer // //=======================================================// // Set override shader to the same simple shader we use to render the glow models IMaterial *pMatGlowColor = materials->FindMaterial( "dev/glow_color", TEXTURE_GROUP_OTHER, true ); g_pStudioRender->ForcedMaterialOverride( pMatGlowColor ); ShaderStencilState_t stencilStateDisable; stencilStateDisable.m_bEnable = false; float flSavedBlend = render->GetBlend(); // Set alpha to 0 so we don't touch any color pixels render->SetBlend( 0.0f ); pRenderContext->OverrideDepthEnable( true, false ); RenderableInstance_t instance; instance.m_nAlpha = 255; int iNumGlowObjects = 0; for ( int i = 0; i < m_GlowObjectDefinitions.Count(); ++ i ) { if ( m_GlowObjectDefinitions[i].IsUnused() || !m_GlowObjectDefinitions[i].ShouldDraw( nSplitScreenSlot ) ) continue; // Full bloom rendered objects should not be stenciled out here if ( m_GlowObjectDefinitions[i].m_bFullBloomRender ) { ++ iNumGlowObjects; continue; } if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded || m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded ) { if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded && m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded ) { ShaderStencilState_t stencilState; stencilState.m_bEnable = true; stencilState.m_nReferenceValue = 1; stencilState.m_CompareFunc = SHADER_STENCILFUNC_ALWAYS; stencilState.m_PassOp = SHADER_STENCILOP_SET_TO_REFERENCE; stencilState.m_FailOp = SHADER_STENCILOP_KEEP; stencilState.m_ZFailOp = SHADER_STENCILOP_SET_TO_REFERENCE; pRenderContext->SetStencilState( stencilState ); m_GlowObjectDefinitions[i].DrawModel(); } else if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded ) { ShaderStencilState_t stencilState; stencilState.m_bEnable = true; stencilState.m_nReferenceValue = 1; stencilState.m_CompareFunc = SHADER_STENCILFUNC_ALWAYS; stencilState.m_PassOp = SHADER_STENCILOP_KEEP; stencilState.m_FailOp = SHADER_STENCILOP_KEEP; stencilState.m_ZFailOp = SHADER_STENCILOP_SET_TO_REFERENCE; pRenderContext->SetStencilState( stencilState ); m_GlowObjectDefinitions[i].DrawModel(); } else if ( m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded ) { ShaderStencilState_t stencilState; stencilState.m_bEnable = true; stencilState.m_nReferenceValue = 2; stencilState.m_nTestMask = 0x1; stencilState.m_nWriteMask = 0x3; stencilState.m_CompareFunc = SHADER_STENCILFUNC_EQUAL; stencilState.m_PassOp = SHADER_STENCILOP_INCREMENT_CLAMP; stencilState.m_FailOp = SHADER_STENCILOP_KEEP; stencilState.m_ZFailOp = SHADER_STENCILOP_SET_TO_REFERENCE; pRenderContext->SetStencilState( stencilState ); m_GlowObjectDefinitions[i].DrawModel(); } } iNumGlowObjects++; } // Need to do a 2nd pass to warm stencil for objects which are rendered only when occluded for ( int i = 0; i < m_GlowObjectDefinitions.Count(); ++ i ) { if ( m_GlowObjectDefinitions[i].IsUnused() || !m_GlowObjectDefinitions[i].ShouldDraw( nSplitScreenSlot ) ) continue; // Full bloom rendered objects should not be stenciled out here if ( m_GlowObjectDefinitions[i].m_bFullBloomRender ) continue; if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded && !m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded ) { ShaderStencilState_t stencilState; stencilState.m_bEnable = true; stencilState.m_nReferenceValue = 2; stencilState.m_CompareFunc = SHADER_STENCILFUNC_ALWAYS; stencilState.m_PassOp = SHADER_STENCILOP_SET_TO_REFERENCE; stencilState.m_FailOp = SHADER_STENCILOP_KEEP; stencilState.m_ZFailOp = SHADER_STENCILOP_KEEP; pRenderContext->SetStencilState( stencilState ); m_GlowObjectDefinitions[i].DrawModel(); } } pRenderContext->OverrideDepthEnable( false, false ); render->SetBlend( flSavedBlend ); pRenderContext->SetStencilState( stencilStateDisable ); g_pStudioRender->ForcedMaterialOverride( NULL ); // If there aren't any objects to glow, don't do all this other stuff // this fixes a bug where if there are glow objects in the list, but none of them are glowing, // the whole screen blooms. if ( iNumGlowObjects <= 0 ) return; //============================================= // Render the glow colors to _rt_FullFrameFB //============================================= { PIXEvent pixEvent( pRenderContext, "RenderGlowModels" ); RenderGlowModels( pSetup, nSplitScreenSlot, pRenderContext ); } //=================================== // Setup state for downsample/bloom //=================================== pRenderContext->PushRenderTargetAndViewport(); // Get viewport int nSrcWidth = pSetup->width; int nSrcHeight = pSetup->height; int nViewportX, nViewportY, nViewportWidth, nViewportHeight; pRenderContext->GetViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight ); // Get material and texture pointers IMaterial *pMatDownsample = materials->FindMaterial( "dev/glow_downsample", TEXTURE_GROUP_OTHER, true); IMaterial *pMatBlurX = materials->FindMaterial( "dev/glow_blur_x", TEXTURE_GROUP_OTHER, true ); IMaterial *pMatBlurY = materials->FindMaterial( "dev/glow_blur_y", TEXTURE_GROUP_OTHER, true ); ITexture *pRtFullFrame = materials->FindTexture( FULL_FRAME_TEXTURE, TEXTURE_GROUP_RENDER_TARGET ); ITexture *pRtQuarterSize0 = materials->FindTexture( "_rt_SmallFB0", TEXTURE_GROUP_RENDER_TARGET ); ITexture *pRtQuarterSize1 = materials->FindTexture( "_rt_SmallFB1", TEXTURE_GROUP_RENDER_TARGET ); //============================================ // Downsample _rt_FullFrameFB to _rt_SmallFB0 //============================================ // First clear the full target to black if we're not going to touch every pixel if ( ( pRtQuarterSize0->GetActualWidth() != ( pSetup->width / 4 ) ) || ( pRtQuarterSize0->GetActualHeight() != ( pSetup->height / 4 ) ) ) { SetRenderTargetAndViewPort( pRtQuarterSize0, pRtQuarterSize0->GetActualWidth(), pRtQuarterSize0->GetActualHeight() ); pRenderContext->ClearColor3ub( 0, 0, 0 ); pRenderContext->ClearBuffers( true, false, false ); } // Set the viewport SetRenderTargetAndViewPort( pRtQuarterSize0, pSetup->width / 4, pSetup->height / 4 ); IMaterialVar *pbloomexpvar = pMatDownsample->FindVar( "$bloomexp", null ); if ( pbloomexpvar != NULL ) { pbloomexpvar->SetFloatValue( 2.5f ); } IMaterialVar *pbloomsaturationvar = pMatDownsample->FindVar( "$bloomsaturation", null ); if ( pbloomsaturationvar != NULL ) { pbloomsaturationvar->SetFloatValue( 1.0f ); } // note the -2's below. Thats because we are downsampling on each axis and the shader // accesses pixels on both sides of the source coord int nFullFbWidth = nSrcWidth; int nFullFbHeight = nSrcHeight; pRenderContext->DrawScreenSpaceRectangle( pMatDownsample, 0, 0, nSrcWidth/4, nSrcHeight/4, 0, 0, nFullFbWidth - 4, nFullFbHeight - 4, pRtFullFrame->GetActualWidth(), pRtFullFrame->GetActualHeight() ); //============================// // Guassian blur x rt0 to rt1 // //============================// // First clear the full target to black if we're not going to touch every pixel if ( s_bFirstPass || ( pRtQuarterSize1->GetActualWidth() != ( pSetup->width / 4 ) ) || ( pRtQuarterSize1->GetActualHeight() != ( pSetup->height / 4 ) ) ) { // On the first render, this viewport may require clearing s_bFirstPass = false; SetRenderTargetAndViewPort( pRtQuarterSize1, pRtQuarterSize1->GetActualWidth(), pRtQuarterSize1->GetActualHeight() ); pRenderContext->ClearColor3ub( 0, 0, 0 ); pRenderContext->ClearBuffers( true, false, false ); } // Set the viewport SetRenderTargetAndViewPort( pRtQuarterSize1, pSetup->width / 4, pSetup->height / 4 ); pRenderContext->DrawScreenSpaceRectangle( pMatBlurX, 0, 0, nSrcWidth/4, nSrcHeight/4, 0, 0, nSrcWidth/4-1, nSrcHeight/4-1, pRtQuarterSize0->GetActualWidth(), pRtQuarterSize0->GetActualHeight() ); //============================// // Gaussian blur y rt1 to rt0 // //============================// SetRenderTargetAndViewPort( pRtQuarterSize0, pSetup->width / 4, pSetup->height / 4 ); IMaterialVar *pBloomAmountVar = pMatBlurY->FindVar( "$bloomamount", NULL ); pBloomAmountVar->SetFloatValue( flBloomScale ); pRenderContext->DrawScreenSpaceRectangle( pMatBlurY, 0, 0, nSrcWidth / 4, nSrcHeight / 4, 0, 0, nSrcWidth / 4 - 1, nSrcHeight / 4 - 1, pRtQuarterSize1->GetActualWidth(), pRtQuarterSize1->GetActualHeight() ); // Pop RT pRenderContext->PopRenderTargetAndViewport(); { //=======================================================================================================// // At this point, pRtQuarterSize0 is filled with the fully colored glow around everything as solid glowy // // blobs. Now we need to stencil out the original objects by only writing pixels that have no // // stencil bits set in the range we care about. // //=======================================================================================================// IMaterial *pMatHaloAddToScreen = materials->FindMaterial( "dev/halo_add_to_screen", TEXTURE_GROUP_OTHER, true ); // Do not fade the glows out at all (weight = 1.0) IMaterialVar *pDimVar = pMatHaloAddToScreen->FindVar( "$C0_X", NULL ); pDimVar->SetFloatValue( 1.0f ); ShaderStencilState_t stencilState; stencilState.m_bEnable = true; stencilState.m_nWriteMask = 0x0; // We're not changing stencil stencilState.m_nTestMask = 0x3; stencilState.m_nReferenceValue = 0x0; stencilState.m_CompareFunc = SHADER_STENCILFUNC_EQUAL; stencilState.m_PassOp = SHADER_STENCILOP_KEEP; stencilState.m_FailOp = SHADER_STENCILOP_KEEP; stencilState.m_ZFailOp = SHADER_STENCILOP_KEEP; pRenderContext->SetStencilState( stencilState ); // Draw quad pRenderContext->DrawScreenSpaceRectangle( pMatHaloAddToScreen, 0, 0, nViewportWidth, nViewportHeight, 0.0f, -0.5f, nSrcWidth / 4 - 1, nSrcHeight / 4 - 1, pRtQuarterSize1->GetActualWidth(), pRtQuarterSize1->GetActualHeight() ); // Disable stencil pRenderContext->SetStencilState( stencilStateDisable ); } }
void CGodRaysEffect::Render( int x, int y, int w, int h ) { CMatRenderContextPtr pRenderContext( materials ); // Save off the current render target and put the occlusion // mask on the top of the rt stack. pRenderContext->PushRenderTargetAndViewport( m_OcclusionMask ); // Create the god rays rendering view. CViewRender* pViewRender = CViewRender::GetMainView(); CRefPtr<CGodRaysView> pGodRaysView = new CGodRaysView( pViewRender ); // Set the sun instance. pGodRaysView->m_pSun = m_pSun; // Draw the occlusion mask. pViewRender->AddViewToScene( pGodRaysView ); // Restore original render targets. pRenderContext->PopRenderTargetAndViewport(); // Now, downsample the occlusion mask. Start by setting the quarter // sized render target as the texture to render to. pRenderContext->PushRenderTargetAndViewport( m_SmallRT0 ); // Get the dimensions of the god rays texture. ITexture* pMaskTexture = m_OcclusionMask; const int nSrcWidth = pMaskTexture->GetActualWidth(); const int nSrcHeight = pMaskTexture->GetActualHeight(); const int nQtrWidth = nSrcWidth / 4; const int nQtrHeight = nSrcHeight / 4; // Blit the data from the occlusion mask texture to the quarter sized one // and use the downsample shader to do it with. pRenderContext->DrawScreenSpaceRectangle( m_DownsampleMaterial, 0, 0, nQtrWidth, nQtrHeight, 0, 0, nSrcWidth - 2, nSrcHeight - 2, nSrcWidth, nSrcHeight ); // Restore the original render target. pRenderContext->PopRenderTargetAndViewport(); Vector vLightPos; GetLightPosition( vLightPos ); if( SetMaterialParms( vLightPos ) ) { // Apply godrays on _rt_SmallFB0 -> _rt_SmallFB1. pRenderContext->PushRenderTargetAndViewport( m_SmallRT1 ); pRenderContext->DrawScreenSpaceRectangle( m_GodRaysMaterial, 0, 0, nQtrWidth, nQtrHeight, 0, 0, nQtrWidth - 2, nQtrHeight - 2, nQtrWidth, nQtrHeight ); pRenderContext->PopRenderTargetAndViewport(); // Now blur _rt_SmallFB1 -> _rt_SmallFB0. pRenderContext->PushRenderTargetAndViewport( m_SmallRT0 ); pRenderContext->DrawScreenSpaceRectangle( m_BlurYMaterial, 0, 0, nQtrWidth, nQtrHeight, 0, 0, nQtrWidth - 2, nQtrHeight - 2, nQtrWidth, nQtrHeight ); pRenderContext->PopRenderTargetAndViewport(); // Now blur _rt_SmallFB0 -> _rt_SmallFB1. pRenderContext->PushRenderTargetAndViewport( m_SmallRT1 ); pRenderContext->DrawScreenSpaceRectangle( m_BlurXMaterial, 0, 0, nQtrWidth, nQtrHeight, 0, 0, nQtrWidth - 2, nQtrHeight - 2, nQtrWidth, nQtrHeight ); // Restore old render target and viewport. pRenderContext->PopRenderTargetAndViewport(); // This forces the framebuffer to update with the latest scene. UpdateScreenEffectTexture( 0, x, y, w, h, true ); // Now combine the godrays results with the main frame buffer. pRenderContext->DrawScreenSpaceQuad( m_GodRaysCombineMaterial ); } // Release the render context. pRenderContext->Release(); }