void CRenderTarget::phase_vol_accumulator() { if (!m_bHasActiveVolumetric) { m_bHasActiveVolumetric = true; if( !RImplementation.o.dx10_msaa ) u_setrt (rt_Generic_2, NULL,NULL,HW.pBaseZB); else u_setrt (rt_Generic_2, NULL,NULL,RImplementation.Target->rt_MSAADepth->pZRT); //u32 clr4clearVol = color_rgba(0,0,0,0); // 0x00 //CHK_DX (HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET, clr4clearVol, 1.0f, 0L)); FLOAT ColorRGBA[4] = {0.0f, 0.0f, 0.0f, 0.0f}; HW.pDevice->ClearRenderTargetView( rt_Generic_2->pRT, ColorRGBA); } else { if( !RImplementation.o.dx10_msaa ) u_setrt (rt_Generic_2, NULL,NULL,HW.pBaseZB); else u_setrt (rt_Generic_2, NULL,NULL,RImplementation.Target->rt_MSAADepth->pZRT); } RCache.set_Stencil (FALSE); RCache.set_CullMode (CULL_NONE); RCache.set_ColorWriteEnable (); }
// startup void CRenderTarget::phase_scene_prepare () { // Clear depth & stencil //u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB ); //CHK_DX ( HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x0, 1.0f, 0L) ); // Igor: soft particles CEnvDescriptor& E = *g_pGamePersistent->Environment().CurrentEnv; float fValue = E.m_fSunShaftsIntensity; // TODO: add multiplication by sun color here //if (fValue<0.0001) FlagSunShafts = 0; if ( RImplementation.o.advancedpp && ( ps_r2_ls_flags.test(R2FLAG_SOFT_PARTICLES|R2FLAG_DOF) || ( (ps_r_sun_shafts>0) && (fValue>=0.0001) ) || (ps_r_ssao>0) ) ) { u_setrt ( Device.dwWidth,Device.dwHeight,rt_Position->pRT,NULL,NULL,HW.pBaseZB ); CHK_DX ( HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x0, 1.0f, 0L) ); } else { u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB ); CHK_DX ( HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x0, 1.0f, 0L) ); } // Igor: for volumetric lights m_bHasActiveVolumetric = false; // Clear later if try to draw volumetric }
void CRenderTarget::phase_rain() { if( !RImplementation.o.dx10_msaa ) u_setrt (rt_Color,NULL,NULL,HW.pBaseZB); else u_setrt (rt_Color,NULL,NULL,rt_MSAADepth->pZRT); //u_setrt (rt_Normal,NULL,NULL,HW.pBaseZB); RImplementation.rmNormal(); }
void CRenderTarget::phase_occq () { if( !RImplementation.o.dx10_msaa ) u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB); else u_setrt ( Device.dwWidth,Device.dwHeight,NULL,NULL,NULL,rt_MSAADepth->pZRT); RCache.set_Shader ( s_occq ); RCache.set_CullMode ( CULL_CCW ); RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); RCache.set_ColorWriteEnable (FALSE ); }
void CRenderTarget::accum_direct_blend () { // blend-copy if (!RImplementation.o.fp16_blend) { u_setrt (rt_Accumulator,NULL,NULL,HW.pBaseZB); // Common calc for quad-rendering u32 Offset; u32 C = color_rgba (255,255,255,255); float _w = float (Device.dwWidth); float _h = float (Device.dwHeight); Fvector2 p0,p1; p0.set (.5f/_w, .5f/_h); p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); float d_Z = EPS_S, d_W = 1.f; // Fill vertex buffer FVF::TL2uv* pv = (FVF::TL2uv*) RCache.Vertex.Lock (4,g_combine_2UV->vb_stride,Offset); pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p1.y, p0.x, p1.y); pv++; pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p0.y, p0.x, p0.y); pv++; pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p1.y, p1.x, p1.y); pv++; pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p0.y, p1.x, p0.y); pv++; RCache.Vertex.Unlock (4,g_combine_2UV->vb_stride); RCache.set_Geometry (g_combine_2UV); RCache.set_Element (s_accum_mask->E[SE_MASK_ACCUM_2D] ); RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2 ); } dwLightMarkerID += 2; }
// begin void CRenderTarget::phase_scene_begin () { // Enable ANISO for (u32 i=0; i<HW.Caps.raster.dwStages; i++) CHK_DX(HW.pDevice->SetSamplerState( i, D3DSAMP_MAXANISOTROPY, ps_r__tf_Anisotropic )); // Targets, use accumulator for temporary storage if (RImplementation.o.albedo_wo) u_setrt (rt_Position, rt_Normal, rt_Accumulator, HW.pBaseZB); else u_setrt (rt_Position, rt_Normal, rt_Color, HW.pBaseZB); // Stencil - write 0x1 at pixel pos RCache.set_Stencil ( TRUE,D3DCMP_ALWAYS,0x01,0xff,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); // Misc - draw only front-faces CHK_DX(HW.pDevice->SetRenderState ( D3DRS_TWOSIDEDSTENCILMODE,FALSE )); RCache.set_CullMode ( CULL_CCW ); RCache.set_ColorWriteEnable ( ); }
void CRenderTarget::phase_smap_direct (light* L, u32 sub_phase) { // TODO: DX10: Check thst we will never need old SMap implementation // Targets if (RImplementation.o.HW_smap) u_setrt (rt_smap_surf, NULL, NULL, rt_smap_depth->pZRT); //else u_setrt (rt_smap_surf, NULL, NULL, rt_smap_ZB); else VERIFY(!"Use HW SMap only for DX10!"); // Don't have rect clear for DX10 // TODO: DX9: Full clear must be faster for the near phase for SLI // inobody clears this buffer _this_ frame. // Clear //if (SE_SUN_NEAR==sub_phase) { // optimized clear // D3DRECT R; // R.x1 = L->X.D.minX; // R.x2 = L->X.D.maxX; // R.y1 = L->X.D.minY; // R.y2 = L->X.D.maxY; // CHK_DX (HW.pDevice->Clear( 1L, &R, D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.0f, 0L)); //} else { // full-clear // CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.0f, 0L)); //} HW.pContext->ClearDepthStencilView(rt_smap_depth->pZRT, D3D_CLEAR_DEPTH, 1.0f, 0L); // Prepare viewport for shadow map rendering if (sub_phase!=SE_SUN_RAIN_SMAP ) RImplementation.rmNormal(); else { D3D_VIEWPORT VP = {(float)L->X.D.minX,(float)L->X.D.minY, (float)(L->X.D.maxX - L->X.D.minX) , (float)(L->X.D.maxY - L->X.D.minY) , 0,1 }; //CHK_DX (HW.pDevice->SetViewport(&VP)); HW.pContext->RSSetViewports(1, &VP); } // Stencil - disable RCache.set_Stencil ( FALSE ); // TODO: DX10: Implement culling reverse for DX10 // Misc - draw only front/back-faces /* if (SE_SUN_NEAR==sub_phase) RCache.set_CullMode ( CULL_CCW ); // near else { if (RImplementation.o.HW_smap) RCache.set_CullMode ( CULL_CW ); // far, reversed else RCache.set_CullMode ( CULL_CCW ); // far, front-faces } if (RImplementation.o.HW_smap) RCache.set_ColorWriteEnable ( FALSE ); else RCache.set_ColorWriteEnable ( ); */ }
void CRenderTarget::phase_pp () { // combination/postprocess u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB); // Element 0 for for normal post-process // Element 4 for color map post-process bool bCMap = u_need_CM(); //RCache.set_Element (s_postprocess->E[bCMap ? 4 : 0]); if( !RImplementation.o.dx10_msaa ) { // RCache.set_Shader (s_postprocess ); RCache.set_Element (s_postprocess->E[bCMap ? 4 : 0]); } else { // RCache.set_Shader( s_postprocess_msaa ); RCache.set_Element (s_postprocess_msaa->E[bCMap ? 4 : 0]); } int gblend = clampr (iFloor((1-param_gray)*255.f),0,255); int nblend = clampr (iFloor((1-param_noise)*255.f),0,255); u32 p_color = subst_alpha (param_color_base,nblend); u32 p_gray = subst_alpha (param_color_gray,gblend); Fvector p_brightness = param_color_add ; // Msg ("param_gray:%f(%d),param_noise:%f(%d)",param_gray,gblend,param_noise,nblend); // Msg ("base: %d,%d,%d", color_get_R(p_color), color_get_G(p_color), color_get_B(p_color)); // Msg ("gray: %d,%d,%d", color_get_R(p_gray), color_get_G(p_gray), color_get_B(p_gray)); // Msg ("add: %d,%d,%d", color_get_R(p_brightness), color_get_G(p_brightness), color_get_B(p_brightness)); // Draw full-screen quad textured with our scene image u32 Offset; float _w = float(Device.dwWidth); float _h = float(Device.dwHeight); Fvector2 n0,n1,r0,r1,l0,l1; u_calc_tc_duality_ss (r0,r1,l0,l1); u_calc_tc_noise (n0,n1); // Fill vertex buffer float du = ps_r1_pps_u, dv = ps_r1_pps_v; TL_2c3uv* pv = (TL_2c3uv*) RCache.Vertex.Lock (4,g_postprocess.stride(),Offset); pv->set(du+0, dv+float(_h), p_color, p_gray, r0.x, r1.y, l0.x, l1.y, n0.x, n1.y); pv++; pv->set(du+0, dv+0, p_color, p_gray, r0.x, r0.y, l0.x, l0.y, n0.x, n0.y); pv++; pv->set(du+float(_w), dv+float(_h), p_color, p_gray, r1.x, r1.y, l1.x, l1.y, n1.x, n1.y); pv++; pv->set(du+float(_w), dv+0, p_color, p_gray, r1.x, r0.y, l1.x, l0.y, n1.x, n0.y); pv++; RCache.Vertex.Unlock (4,g_postprocess.stride()); // Actual rendering static shared_str s_brightness = "c_brightness"; static shared_str s_colormap = "c_colormap"; RCache.set_c ( s_brightness, p_brightness.x, p_brightness.y, p_brightness.z, 0 ); RCache.set_c (s_colormap, param_color_map_influence,param_color_map_interpolate,0,0); RCache.set_Geometry (g_postprocess); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); }
void CRenderTarget::phase_wallmarks () { // Targets RCache.set_RT(NULL,2); RCache.set_RT(NULL,1); u_setrt (rt_Color,NULL,NULL,HW.pBaseZB); // Stencil - draw only where stencil >= 0x1 RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); RCache.set_CullMode (CULL_CCW); RCache.set_ColorWriteEnable (D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE); }
void CRenderTarget::phase_downsamp () { // DON'T DO THIS!!! //IDirect3DSurface9 *source, *dest; //rt_Position->pSurface->GetSurfaceLevel(0, &source); //rt_half_depth->pSurface->GetSurfaceLevel(0, &dest); //HW.pDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_POINT); //Fvector2 p0,p1; u32 Offset = 0; u_setrt( rt_half_depth,0,0,0/*HW.pBaseZB*/ ); FLOAT ColorRGBA[4] = {0.0f, 0.0f, 0.0f, 0.0f}; HW.pContext->ClearRenderTargetView(rt_half_depth->pRT, ColorRGBA); u32 w = Device.dwWidth; u32 h = Device.dwHeight; if (RImplementation.o.ssao_half_data) { set_viewport(HW.pDevice, Device.dwWidth/2, Device.dwHeight/2); w /= 2; h /= 2; } RCache.set_Stencil (FALSE); { Fmatrix m_v2w; m_v2w.invert (Device.mView ); // Fill VB float scale_X = float(w) / float(TEX_jitter); float scale_Y = float(h) / float(TEX_jitter); // Fill vertex buffer FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); pv->set ( -1, 1, 0, 1, 0, 0, scale_Y ); pv++; pv->set ( -1, -1, 0, 0, 0, 0, 0 ); pv++; pv->set ( 1, 1, 1, 1, 0, scale_X, scale_Y ); pv++; pv->set ( 1, -1, 1, 0, 0, scale_X, 0 ); pv++; RCache.Vertex.Unlock (4,g_combine->vb_stride); // Draw RCache.set_Element (s_ssao->E[1] ); RCache.set_Geometry (g_combine ); RCache.set_c ("m_v2w", m_v2w ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } if (RImplementation.o.ssao_half_data) set_viewport(HW.pDevice, Device.dwWidth, Device.dwHeight); }
void CRenderTarget::phase_accumulator() { // Targets if (dwAccumulatorClearMark==Device.dwFrame) { // normal operation - setup if( !RImplementation.o.dx10_msaa ) { if (RImplementation.o.fp16_blend) u_setrt (rt_Accumulator, NULL,NULL,HW.pBaseZB); else u_setrt (rt_Accumulator_temp, NULL,NULL,HW.pBaseZB); } else { if (RImplementation.o.fp16_blend) u_setrt (rt_Accumulator, NULL,NULL, rt_MSAADepth->pZRT); else u_setrt (rt_Accumulator_temp, NULL,NULL, rt_MSAADepth->pZRT); } } else { // initial setup dwAccumulatorClearMark = Device.dwFrame; // clear if( !RImplementation.o.dx10_msaa ) u_setrt (rt_Accumulator, NULL,NULL,HW.pBaseZB); else u_setrt (rt_Accumulator, NULL,NULL,rt_MSAADepth->pZRT); //dwLightMarkerID = 5; // start from 5, increment in 2 units reset_light_marker(); // Igor: AMD bug workaround. Should be fixed in 8.7 catalyst // Need for MSAA to work correctly. if( RImplementation.o.dx10_msaa ) { HW.pDevice->OMSetRenderTargets(1, &(rt_Accumulator->pRT), 0); } // u32 clr4clear = color_rgba(0,0,0,0); // 0x00 //CHK_DX (HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET, clr4clear, 1.0f, 0L)); FLOAT ColorRGBA[4] = {0.0f, 0.0f, 0.0f, 0.0f}; HW.pDevice->ClearRenderTargetView( rt_Accumulator->pRT, ColorRGBA); // render this after sun to avoid troubles with sun /* // Render emissive geometry, stencil - write 0x0 at pixel pos RCache.set_xform_project (Device.mProject); RCache.set_xform_view (Device.mView); // Stencil - write 0x1 at pixel pos - RCache.set_Stencil ( TRUE,D3DCMP_ALWAYS,0x01,0xff,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); //RCache.set_Stencil (TRUE,D3DCMP_ALWAYS,0x00,0xff,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); RCache.set_CullMode (CULL_CCW); RCache.set_ColorWriteEnable (); RImplementation.r_dsgraph_render_emissive (); */ // Stencil - draw only where stencil >= 0x1 RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); RCache.set_CullMode (CULL_NONE); RCache.set_ColorWriteEnable (); } // Restore viewport after shadow map rendering RImplementation.rmNormal(); }
void CRenderTarget::phase_smap_direct (light* L, u32 sub_phase) { // Targets if (RImplementation.o.HW_smap) u_setrt (rt_smap_surf, NULL, NULL, rt_smap_depth->pRT); else u_setrt (rt_smap_surf, NULL, NULL, rt_smap_ZB); // Clear if (SE_SUN_NEAR==sub_phase) { // optimized clear D3DRECT R; R.x1 = L->X.D.minX; R.x2 = L->X.D.maxX; R.y1 = L->X.D.minY; R.y2 = L->X.D.maxY; CHK_DX (HW.pDevice->Clear( 1L, &R, D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.0f, 0L)); } else { // full-clear CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.0f, 0L)); } // Stencil - disable RCache.set_Stencil ( FALSE ); // Misc - draw only front/back-faces /* if (SE_SUN_NEAR==sub_phase) RCache.set_CullMode ( CULL_CCW ); // near else { if (RImplementation.o.HW_smap) RCache.set_CullMode ( CULL_CW ); // far, reversed else RCache.set_CullMode ( CULL_CCW ); // far, front-faces } */ // Cull always CCW. If you want to revert to previouse solution, please, revert bias setup/ RCache.set_CullMode ( CULL_CCW ); // near if (RImplementation.o.HW_smap) RCache.set_ColorWriteEnable ( FALSE ); else RCache.set_ColorWriteEnable ( ); }
void CRenderTarget::phase_smap_spot (light* L) { // Targets + viewport // TODO: DX10: CHeck if we don't need old-style SMAP if (RImplementation.o.HW_smap) u_setrt (rt_smap_surf, NULL, NULL, rt_smap_depth->pZRT); //else u_setrt (rt_smap_surf, NULL, NULL, rt_smap_ZB); else VERIFY(!"Use HW SMap only for DX10!"); D3D_VIEWPORT VP = {(float)L->X.S.posX, (float)L->X.S.posY, (float)L->X.S.size, (float)L->X.S.size, 0, 1}; //CHK_DX (HW.pDevice->SetViewport(&VP)); HW.pContext->RSSetViewports(1, &VP); // Misc - draw only front-faces //back-faces RCache.set_CullMode ( CULL_CCW ); RCache.set_Stencil ( FALSE ); // no transparency #pragma todo("can optimize for multi-lights covering more than say 50%...") if (RImplementation.o.HW_smap) RCache.set_ColorWriteEnable (FALSE); //CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L)); // Do it once per smap generation pass in phase_smap_spot_clear //HW.pContext->ClearDepthStencilView( rt_smap_depth->pZRT, D3D_CLEAR_DEPTH, 1.0f, 0L); }
// end void CRenderTarget::phase_scene_end () { disable_aniso (); if (!RImplementation.o.albedo_wo) return; // transfer from "rt_Accumulator" into "rt_Color" u_setrt ( rt_Color, 0, 0, HW.pBaseZB ); RCache.set_CullMode ( CULL_NONE ); RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); // stencil should be >= 1 if (RImplementation.o.nvstencil) u_stencil_optimize (FALSE); RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); // stencil should be >= 1 RCache.set_ColorWriteEnable (); // common calc for quad-rendering u32 Offset; u32 C = color_rgba (255,255,255,255); float _w = float (Device.dwWidth); float _h = float (Device.dwHeight); Fvector2 p0,p1; p0.set (.5f/_w, .5f/_h); p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); float d_Z = EPS_S, d_W = 1.f; // Fill vertex buffer FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p1.y); pv++; pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p0.y); pv++; pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p1.y); pv++; pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p0.y); pv++; RCache.Vertex.Unlock (4,g_combine->vb_stride); // if (stencil>=1 && aref_pass) stencil = light_id RCache.set_Element (s_accum_mask->E[SE_MASK_ALBEDO]); // masker RCache.set_Geometry (g_combine); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); }
void CRenderTarget::mark_msaa_edges() { u32 Offset; float d_Z = EPS_S, d_W = 1.f; u32 C = color_rgba (255,255,255,255); // Fill vertex buffer FVF::TL2uv* pv = (FVF::TL2uv*) RCache.Vertex.Lock (4,g_combine_2UV->vb_stride,Offset); pv->set (-1, -1, 0, d_W, C, 0, 1, 0, 0); pv++; pv->set (-1, 1, d_Z, d_W, C, 0, 0, 0, 0); pv++; pv->set (1, -1, d_Z, d_W, C, 1, 1, 0, 0); pv++; pv->set (1, 1, d_Z, d_W, C, 1, 0, 0, 0); pv++; RCache.Vertex.Unlock (4,g_combine_2UV->vb_stride); u_setrt (NULL,NULL,NULL,rt_MSAADepth->pZRT); RCache.set_Element (s_mark_msaa_edges->E[0]); RCache.set_Geometry (g_combine_2UV); StateManager.SetStencil( TRUE, D3DCMP_ALWAYS, 0x80, 0xFF, 0x80, D3DSTENCILOP_KEEP, D3DSTENCILOP_REPLACE, D3DSTENCILOP_KEEP ); StateManager.SetColorWriteEnable( 0 ); StateManager.SetDepthFunc( D3DCMP_ALWAYS ); StateManager.SetDepthEnable( FALSE ); StateManager.SetCullMode( D3DCULL_NONE ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); StateManager.SetColorWriteEnable( D3D10_COLOR_WRITE_ENABLE_ALL ); }
CRenderTarget::CRenderTarget () { param_blur = 0.f; param_gray = 0.f; param_noise = 0.f; param_duality_h = 0.f; param_duality_v = 0.f; param_noise_fps = 25.f; param_noise_scale = 1.f; im_noise_time = 1/100; im_noise_shift_w = 0; im_noise_shift_h = 0; param_color_base = color_rgba(127,127,127, 0); param_color_gray = color_rgba(85,85,85, 0); param_color_add.set( 0.0f, 0.0f, 0.0f ); dwAccumulatorClearMark = 0; dxRenderDeviceRender::Instance().Resources->Evict (); // Blenders b_occq = new CBlender_light_occq(); b_accum_mask = new CBlender_accum_direct_mask(); b_accum_direct = new CBlender_accum_direct(); b_accum_point = new CBlender_accum_point(); b_accum_spot = new CBlender_accum_spot(); b_accum_reflected = new CBlender_accum_reflected(); b_bloom = new CBlender_bloom_build(); b_ssao = new CBlender_SSAO(); b_luminance = new CBlender_luminance(); b_combine = new CBlender_combine(); // NORMAL { u32 w=Device.dwWidth, h=Device.dwHeight; rt_Position.create (r2_RT_P, w,h,D3DFMT_A16B16G16R16F); rt_Normal.create (r2_RT_N, w,h,D3DFMT_A16B16G16R16F); // select albedo & accum if (RImplementation.o.mrtmixdepth) { // NV50 rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A8R8G8B8 ); rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F); } else { // can't - mix-depth if (RImplementation.o.fp16_blend) { // NV40 rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A16B16G16R16F); // expand to full rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F); } else { // R4xx, no-fp-blend,-> albedo_wo VERIFY (RImplementation.o.albedo_wo); rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A8R8G8B8 ); // normal rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F); rt_Accumulator_temp.create (r2_RT_accum_temp, w,h,D3DFMT_A16B16G16R16F); } } // generic(LDR) RTs rt_Generic_0.create (r2_RT_generic0,w,h,D3DFMT_A8R8G8B8 ); rt_Generic_1.create (r2_RT_generic1,w,h,D3DFMT_A8R8G8B8 ); // Igor: for volumetric lights //rt_Generic_2.create (r2_RT_generic2,w,h,D3DFMT_A8R8G8B8 ); // temp: for higher quality blends if (RImplementation.o.advancedpp) rt_Generic_2.create (r2_RT_generic2,w,h,D3DFMT_A16B16G16R16F); } // OCCLUSION s_occq.create (b_occq, "r2\\occq"); // DIRECT (spot) D3DFORMAT depth_format = (D3DFORMAT)RImplementation.o.HW_smap_FORMAT; if (RImplementation.o.HW_smap) { D3DFORMAT nullrt = D3DFMT_R5G6B5; if (RImplementation.o.nullrt) nullrt = (D3DFORMAT)MAKEFOURCC('N','U','L','L'); u32 size =RImplementation.o.smapsize ; rt_smap_depth.create (r2_RT_smap_depth, size,size,depth_format ); rt_smap_surf.create (r2_RT_smap_surf, size,size,nullrt ); rt_smap_ZB = NULL; s_accum_mask.create (b_accum_mask, "r2\\accum_mask"); s_accum_direct.create (b_accum_direct, "r2\\accum_direct"); if (RImplementation.o.advancedpp) s_accum_direct_volumetric.create("accum_volumetric_sun"); } else { u32 size =RImplementation.o.smapsize ; rt_smap_surf.create (r2_RT_smap_surf, size,size,D3DFMT_R32F); rt_smap_depth = NULL; R_CHK (HW.pDevice->CreateDepthStencilSurface (size,size,D3DFMT_D24X8,D3DMULTISAMPLE_NONE,0,TRUE,&rt_smap_ZB,NULL)); s_accum_mask.create (b_accum_mask, "r2\\accum_mask"); s_accum_direct.create (b_accum_direct, "r2\\accum_direct"); if (RImplementation.o.advancedpp) s_accum_direct_volumetric.create("accum_volumetric_sun"); } // POINT { s_accum_point.create (b_accum_point, "r2\\accum_point_s"); accum_point_geom_create (); g_accum_point.create (D3DFVF_XYZ, g_accum_point_vb, g_accum_point_ib); accum_omnip_geom_create (); g_accum_omnipart.create (D3DFVF_XYZ, g_accum_omnip_vb, g_accum_omnip_ib); } // SPOT { s_accum_spot.create (b_accum_spot, "r2\\accum_spot_s", "lights\\lights_spot01"); accum_spot_geom_create (); g_accum_spot.create (D3DFVF_XYZ, g_accum_spot_vb, g_accum_spot_ib); } { s_accum_volume.create("accum_volumetric", "lights\\lights_spot01"); accum_volumetric_geom_create(); g_accum_volumetric.create( D3DFVF_XYZ, g_accum_volumetric_vb, g_accum_volumetric_ib); } // REFLECTED { s_accum_reflected.create (b_accum_reflected, "r2\\accum_refl"); } // BLOOM { D3DFORMAT fmt = D3DFMT_A8R8G8B8; //; // D3DFMT_X8R8G8B8 u32 w=BLOOM_size_X, h=BLOOM_size_Y; u32 fvf_build = D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3); u32 fvf_filter = (u32)D3DFVF_XYZRHW|D3DFVF_TEX8|D3DFVF_TEXCOORDSIZE4(0)|D3DFVF_TEXCOORDSIZE4(1)|D3DFVF_TEXCOORDSIZE4(2)|D3DFVF_TEXCOORDSIZE4(3)|D3DFVF_TEXCOORDSIZE4(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6)|D3DFVF_TEXCOORDSIZE4(7); rt_Bloom_1.create (r2_RT_bloom1, w,h, fmt); rt_Bloom_2.create (r2_RT_bloom2, w,h, fmt); g_bloom_build.create (fvf_build, RCache.Vertex.Buffer(), RCache.QuadIB); g_bloom_filter.create (fvf_filter, RCache.Vertex.Buffer(), RCache.QuadIB); s_bloom_dbg_1.create ("effects\\screen_set", r2_RT_bloom1); s_bloom_dbg_2.create ("effects\\screen_set", r2_RT_bloom2); s_bloom.create (b_bloom, "r2\\bloom"); f_bloom_factor = 0.5f; } //HBAO if (RImplementation.o.ssao_opt_data) { u32 w = 0; u32 h = 0; if (RImplementation.o.ssao_half_data) { w = Device.dwWidth / 2; h = Device.dwHeight / 2; } else { w = Device.dwWidth; h = Device.dwHeight; } D3DFORMAT fmt = HW.Caps.id_vendor==0x10DE?D3DFMT_R32F:D3DFMT_R16F; rt_half_depth.create (r2_RT_half_depth, w, h, fmt); s_ssao.create (b_ssao, "r2\\ssao"); } //SSAO if (RImplementation.o.ssao_blur_on) { u32 w = Device.dwWidth, h = Device.dwHeight; rt_ssao_temp.create (r2_RT_ssao_temp, w, h, D3DFMT_G16R16F); s_ssao.create (b_ssao, "r2\\ssao"); } // TONEMAP { rt_LUM_64.create (r2_RT_luminance_t64, 64, 64, D3DFMT_A16B16G16R16F ); rt_LUM_8.create (r2_RT_luminance_t8, 8, 8, D3DFMT_A16B16G16R16F ); s_luminance.create (b_luminance, "r2\\luminance"); f_luminance_adapt = 0.5f; t_LUM_src.create (r2_RT_luminance_src); t_LUM_dest.create (r2_RT_luminance_cur); // create pool for (u32 it=0; it<HW.Caps.iGPUNum*2; it++) { string256 name; sprintf (name,"%s_%d", r2_RT_luminance_pool,it ); rt_LUM_pool[it].create (name, 1, 1, D3DFMT_R32F ); u_setrt (rt_LUM_pool[it], 0, 0, 0 ); CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x7f7f7f7f, 1.0f, 0L)); } u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB); } // COMBINE { static D3DVERTEXELEMENT9 dwDecl[] = { { 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, // pos+uv { 0, 16, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, { 0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() }; s_combine.create (b_combine, "r2\\combine"); s_combine_volumetric.create ("combine_volumetric"); s_combine_dbg_0.create ("effects\\screen_set", r2_RT_smap_surf ); s_combine_dbg_1.create ("effects\\screen_set", r2_RT_luminance_t8 ); s_combine_dbg_Accumulator.create ("effects\\screen_set", r2_RT_accum ); g_combine_VP.create (dwDecl, RCache.Vertex.Buffer(), RCache.QuadIB); g_combine.create (FVF::F_TL, RCache.Vertex.Buffer(), RCache.QuadIB); g_combine_2UV.create (FVF::F_TL2uv, RCache.Vertex.Buffer(), RCache.QuadIB); u32 fvf_aa_blur = D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3); g_aa_blur.create (fvf_aa_blur, RCache.Vertex.Buffer(), RCache.QuadIB); u32 fvf_aa_AA = D3DFVF_XYZRHW|D3DFVF_TEX7|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3)|D3DFVF_TEXCOORDSIZE2(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6); g_aa_AA.create (fvf_aa_AA, RCache.Vertex.Buffer(), RCache.QuadIB); t_envmap_0.create (r2_T_envs0); t_envmap_1.create (r2_T_envs1); } // Build textures { // Build material(s) { // Surface R_CHK (D3DXCreateVolumeTexture(HW.pDevice,TEX_material_LdotN,TEX_material_LdotH,4,1,0,D3DFMT_A8L8,D3DPOOL_MANAGED,&t_material_surf)); t_material = dxRenderDeviceRender::Instance().Resources->_CreateTexture(r2_material); t_material->surface_set (t_material_surf); // Fill it (addr: x=dot(L,N),y=dot(L,H)) D3DLOCKED_BOX R; R_CHK (t_material_surf->LockBox (0,&R,0,0)); for (u32 slice=0; slice<4; slice++) { for (u32 y=0; y<TEX_material_LdotH; y++) { for (u32 x=0; x<TEX_material_LdotN; x++) { u16* p = (u16*) (LPBYTE (R.pBits) + slice*R.SlicePitch + y*R.RowPitch + x*2); float ld = float(x) / float (TEX_material_LdotN-1); float ls = float(y) / float (TEX_material_LdotH-1) + EPS_S; ls *= powf(ld,1/32.f); float fd,fs; switch (slice) { case 0: { // looks like OrenNayar fd = powf(ld,0.75f); // 0.75 fs = powf(ls,16.f)*.5f; } break; case 1: {// looks like Blinn fd = powf(ld,0.90f); // 0.90 fs = powf(ls,24.f); } break; case 2: { // looks like Phong fd = ld; // 1.0 fs = powf(ls*1.01f,128.f ); } break; case 3: { // looks like Metal float s0 = _abs (1-_abs (0.05f*_sin(33.f*ld)+ld-ls)); float s1 = _abs (1-_abs (0.05f*_cos(33.f*ld*ls)+ld-ls)); float s2 = _abs (1-_abs (ld-ls)); fd = ld; // 1.0 fs = powf (_max(_max(s0,s1),s2), 24.f); fs *= powf (ld,1/7.f); } break; default: fd = fs = 0; } s32 _d = clampr (iFloor (fd*255.5f), 0,255); s32 _s = clampr (iFloor (fs*255.5f), 0,255); if ((y==(TEX_material_LdotH-1)) && (x==(TEX_material_LdotN-1))) { _d = 255; _s=255; } *p = u16 (_s*256 + _d); } } } R_CHK (t_material_surf->UnlockBox (0)); // #ifdef DEBUG // R_CHK (D3DXSaveTextureToFile ("x:\\r2_material.dds",D3DXIFF_DDS,t_material_surf,0)); // #endif } // Build noise table if (1) { // Surfaces D3DLOCKED_RECT R[TEX_jitter_count]; for (int it1=0; it1<TEX_jitter_count-1; it1++) { string_path name; sprintf (name,"%s%d",r2_jitter,it1); R_CHK (D3DXCreateTexture (HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_Q8W8V8U8,D3DPOOL_MANAGED,&t_noise_surf[it1])); t_noise[it1] = dxRenderDeviceRender::Instance().Resources->_CreateTexture (name); t_noise[it1]->surface_set (t_noise_surf[it1]); R_CHK (t_noise_surf[it1]->LockRect (0,&R[it1],0,0)); } // Fill it, for (u32 y=0; y<TEX_jitter; y++) { for (u32 x=0; x<TEX_jitter; x++) { DWORD data [TEX_jitter_count-1]; generate_jitter (data,TEX_jitter_count-1); for (u32 it2=0; it2<TEX_jitter_count-1; it2++) { u32* p = (u32*) (LPBYTE (R[it2].pBits) + y*R[it2].Pitch + x*4); *p = data [it2]; } } } for (int it3=0; it3<TEX_jitter_count-1; it3++) { R_CHK (t_noise_surf[it3]->UnlockRect(0)); } // generate HBAO jitter texture (last) int it = TEX_jitter_count - 1; string_path name; sprintf (name,"%s%d",r2_jitter,it); R_CHK (D3DXCreateTexture (HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_A32B32G32R32F,D3DPOOL_MANAGED,&t_noise_surf[it])); t_noise[it] = dxRenderDeviceRender::Instance().Resources->_CreateTexture (name); t_noise[it]->surface_set (t_noise_surf[it]); R_CHK (t_noise_surf[it]->LockRect (0,&R[it],0,0)); // Fill it, for (u32 y=0; y<TEX_jitter; y++) { for (u32 x=0; x<TEX_jitter; x++) { float numDir = 1.0f; switch (ps_r_ssao) { case 1: numDir = 4.0f; break; case 2: numDir = 6.0f; break; case 3: numDir = 8.0f; break; } float angle = 2 * PI * ::Random.randF(0.0f, 1.0f) / numDir; float dist = ::Random.randF(0.0f, 1.0f); //float dest[4]; float* p = (float*) (LPBYTE (R[it].pBits) + y*R[it].Pitch + x*4*sizeof(float)); *p = (float)(_cos(angle)); *(p+1) = (float)(_sin(angle)); *(p+2) = (float)(dist); *(p+3) = 0; //generate_hbao_jitter (data,TEX_jitter*TEX_jitter); } } R_CHK (t_noise_surf[it]->UnlockRect(0)); } } // PP s_postprocess.create ("postprocess"); g_postprocess.create (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX3,RCache.Vertex.Buffer(),RCache.QuadIB); // Menu s_menu.create ("distort"); g_menu.create (FVF::F_TL,RCache.Vertex.Buffer(),RCache.QuadIB); // Igor: TMP // Create an RT for online screenshot makining //u32 w = Device.dwWidth, h = Device.dwHeight; //HW.pDevice->CreateOffscreenPlainSurface(Device.dwWidth,Device.dwHeight,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&pFB,NULL); //HW.pDevice->CreateOffscreenPlainSurface(Device.dwWidth,Device.dwHeight,rt_Color->fmt,D3DPOOL_SYSTEMMEM,&pFB,NULL); D3DSURFACE_DESC desc; HW.pBaseRT->GetDesc(&desc); HW.pDevice->CreateOffscreenPlainSurface(Device.dwWidth,Device.dwHeight,desc.Format,D3DPOOL_SYSTEMMEM,&pFB,NULL); // dwWidth = Device.dwWidth; dwHeight = Device.dwHeight; }
void CRenderTarget::phase_bloom () { PIX_EVENT(phase_bloom); u32 Offset; // Targets u_setrt ( rt_Bloom_1,NULL,NULL,NULL ); // No need for ZBuffer at all //RImplementation.rmNormal(); // Clear - don't clear - it's stupid here :) // Stencil - disable // Misc - draw everything (no culling) //CHK_DX (HW.pDevice->SetRenderState ( D3DRS_ZENABLE, FALSE )); RCache.set_Z(FALSE); // Transfer into Bloom1 { float _w = float(Device.dwWidth); float _h = float(Device.dwHeight); float _2w = _w/2; float tw = BLOOM_size_X; float _2h = _h/2; float th = BLOOM_size_Y; float _aspect_w = _2w/tw; float _aspect_h = _2h/th; Fvector2 one = { 1.f/_w, 1.f/_h }; one.x*=_aspect_w; one.y*=_aspect_h; Fvector2 half = { .5f/_w, .5f/_h }; Fvector2 a_0 = { half.x + 0, half.y + 0 }; Fvector2 a_1 = { half.x + one.x, half.y + 0 }; Fvector2 a_2 = { half.x + 0, half.y + one.y }; Fvector2 a_3 = { half.x + one.x, half.y + one.y }; Fvector2 b_0 = { 1 + a_0.x, 1 + a_0.y }; Fvector2 b_1 = { 1 + a_1.x, 1 + a_1.y }; Fvector2 b_2 = { 1 + a_2.x, 1 + a_2.y }; Fvector2 b_3 = { 1 + a_3.x, 1 + a_3.y }; // Fill vertex buffer v_build* pv = (v_build*) RCache.Vertex.Lock (4,g_bloom_build->vb_stride,Offset); pv->p.set (EPS, float(th+EPS), EPS,1.f); pv->uv0.set (a_0.x,b_0.y); pv->uv1.set (a_1.x,b_1.y); pv->uv2.set (a_2.x,b_2.y); pv->uv3.set (a_3.x,b_3.y); pv++; pv->p.set (EPS, EPS, EPS,1.f); pv->uv0.set (a_0.x,a_0.y); pv->uv1.set (a_1.x,a_1.y); pv->uv2.set (a_2.x,a_2.y); pv->uv3.set (a_3.x,a_3.y); pv++; pv->p.set (float(tw+EPS),float(th+EPS), EPS,1.f); pv->uv0.set (b_0.x,b_0.y); pv->uv1.set (b_1.x,b_1.y); pv->uv2.set (b_2.x,b_2.y); pv->uv3.set (b_3.x,b_3.y); pv++; pv->p.set (float(tw+EPS),EPS, EPS,1.f); pv->uv0.set (b_0.x,a_0.y); pv->uv1.set (b_1.x,a_1.y); pv->uv2.set (b_2.x,a_2.y); pv->uv3.set (b_3.x,a_3.y); pv++; RCache.Vertex.Unlock (4,g_bloom_build->vb_stride); // Perform combine (all scalers must account for 4 samples + final diffuse multiply); float s = ps_r2_ls_bloom_threshold; // scale f_bloom_factor = .9f*f_bloom_factor + .1f*ps_r2_ls_bloom_speed*Device.fTimeDelta; // speed if( !RImplementation.o.dx10_msaa ) RCache.set_Element (s_bloom->E[0]); else RCache.set_Element (s_bloom_msaa->E[0]); RCache.set_c ("b_params", s,s,s, f_bloom_factor); RCache.set_Geometry (g_bloom_build ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } // Capture luminance values phase_luminance ( ); if (ps_r2_ls_flags.test(R2FLAG_FASTBLOOM)) { // FAST FILTER float _w = BLOOM_size_X; float _h = BLOOM_size_Y; float ddw = (1.f/_w)*ps_r2_ls_bloom_kernel_b; float ddh = (1.f/_h)*ps_r2_ls_bloom_kernel_b; Fvector2 p0; p0.set (.5f/_w, .5f/_h); Fvector2 p1; p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); v_build* pv = (v_build*) RCache.Vertex.Lock (4,g_bloom_build->vb_stride,Offset); pv->p.set(EPS, float(_h+EPS), EPS,1.f); pv->uv0.set(p0.x-ddw,p1.y-ddh);pv->uv1.set(p0.x+ddw,p1.y+ddh);pv->uv2.set(p0.x+ddw,p1.y-ddh);pv->uv3.set(p0.x-ddw,p1.y+ddh);pv++; pv->p.set(EPS, EPS, EPS,1.f); pv->uv0.set(p0.x-ddw,p0.y-ddh);pv->uv1.set(p0.x+ddw,p0.y+ddh);pv->uv2.set(p0.x+ddw,p0.y-ddh);pv->uv3.set(p0.x-ddw,p0.y+ddh);pv++; pv->p.set(float(_w+EPS),float(_h+EPS), EPS,1.f); pv->uv0.set(p1.x-ddw,p1.y-ddh);pv->uv1.set(p1.x+ddw,p1.y+ddh);pv->uv2.set(p1.x+ddw,p1.y-ddh);pv->uv3.set(p1.x-ddw,p1.y+ddh);pv++; pv->p.set(float(_w+EPS),EPS, EPS,1.f); pv->uv0.set(p1.x-ddw,p0.y-ddh);pv->uv1.set(p1.x+ddw,p0.y+ddh);pv->uv2.set(p1.x+ddw,p0.y-ddh);pv->uv3.set(p1.x-ddw,p0.y+ddh);pv++; RCache.Vertex.Unlock (4,g_bloom_build->vb_stride); RCache.set_Geometry (g_bloom_build); // P0 u_setrt (rt_Bloom_2,NULL,NULL,NULL); // No need for ZBuffer at all RCache.set_Element (s_bloom->E[3]); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); // P1 u_setrt (rt_Bloom_1,NULL,NULL,NULL); // No need for ZBuffer at all RCache.set_Element (s_bloom->E[4]); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } else { // SLOW FILTER // Transfer into Bloom2, horizontal filter { float _w = BLOOM_size_X; float _h = BLOOM_size_Y; Fvector2 two = { 2.f/_w, 2.f/_h }; Fvector2 one = { 1.f/_w, 1.f/_h }; Fvector2 half = { .5f/_w, .5f/_h }; Fvector4 a_0 = { half.x, half.y, half.y, half.x }; // center Fvector4 a_1 = { a_0.x - one.x - half.x, half.y, half.y, a_0.w + one.x + half.x }; // -1,+1i Fvector4 a_2 = { a_1.x - two.x, half.y, half.y, a_1.w + two.x }; // -2,+2i Fvector4 a_3 = { a_2.x - two.x, half.y, half.y, a_2.w + two.x }; // -3,+3i Fvector4 a_4 = { a_3.x - two.x, half.y, half.y, a_3.w + two.x }; // -4,+4i Fvector4 a_5 = { a_4.x - two.x, half.y, half.y, a_4.w + two.x }; // -5,+5i Fvector4 a_6 = { a_5.x - two.x, half.y, half.y, a_5.w + two.x }; // -6,+6i Fvector4 a_7 = { a_6.x - two.x, half.y, half.y, a_6.w + two.x }; // -7,+7i // Fill vertex buffer v_filter* pv = (v_filter*) RCache.Vertex.Lock (4,g_bloom_filter->vb_stride,Offset); // 0 - LB pv->p.set (EPS, float(_h+EPS), EPS,1.f); pv->uv0.set (a_0.x,1+a_0.y,0,0); pv->uv1.set (a_1.x,1+a_1.y,1+a_1.z,a_1.w); pv->uv2.set (a_2.x,1+a_2.y,1+a_2.z,a_2.w); pv->uv3.set (a_3.x,1+a_3.y,1+a_3.z,a_3.w); pv->uv4.set (a_4.x,1+a_4.y,1+a_4.z,a_4.w); pv->uv5.set (a_5.x,1+a_5.y,1+a_5.z,a_5.w); pv->uv6.set (a_6.x,1+a_6.y,1+a_6.z,a_6.w); pv->uv7.set (a_7.x,1+a_7.y,1+a_7.z,a_7.w); pv++; // 1 - LT pv->p.set (EPS, EPS, EPS,1.f); pv->uv0.set (a_0.x,a_0.y,0,0); pv->uv1.set (a_1.x,a_1.y,a_1.z,a_1.w); pv->uv2.set (a_2.x,a_2.y,a_2.z,a_2.w); pv->uv3.set (a_3.x,a_3.y,a_3.z,a_3.w); pv->uv4.set (a_4.x,a_4.y,a_4.z,a_4.w); pv->uv5.set (a_5.x,a_5.y,a_5.z,a_5.w); pv->uv6.set (a_6.x,a_6.y,a_6.z,a_6.w); pv->uv7.set (a_7.x,a_7.y,a_7.z,a_7.w); pv++; // 2 - RB pv->p.set (float(_w+EPS), float(_h+EPS), EPS,1.f); pv->uv0.set (1+a_0.x,1+a_0.y,0,0); pv->uv1.set (1+a_1.x,1+a_1.y,1+a_1.z,1+a_1.w); pv->uv2.set (1+a_2.x,1+a_2.y,1+a_2.z,1+a_2.w); pv->uv3.set (1+a_3.x,1+a_3.y,1+a_3.z,1+a_3.w); pv->uv4.set (1+a_4.x,1+a_4.y,1+a_4.z,1+a_4.w); pv->uv5.set (1+a_5.x,1+a_5.y,1+a_5.z,1+a_5.w); pv->uv6.set (1+a_6.x,1+a_6.y,1+a_6.z,1+a_6.w); pv->uv7.set (1+a_7.x,1+a_7.y,1+a_7.z,1+a_7.w); pv++; // 3 - RT pv->p.set (float(_w+EPS), EPS, EPS,1.f); pv->uv0.set (1+a_0.x,a_0.y,0,0); pv->uv1.set (1+a_1.x,a_1.y,a_1.z,1+a_1.w); pv->uv2.set (1+a_2.x,a_2.y,a_2.z,1+a_2.w); pv->uv3.set (1+a_3.x,a_3.y,a_3.z,1+a_3.w); pv->uv4.set (1+a_4.x,a_4.y,a_4.z,1+a_4.w); pv->uv5.set (1+a_5.x,a_5.y,a_5.z,1+a_5.w); pv->uv6.set (1+a_6.x,a_6.y,a_6.z,1+a_6.w); pv->uv7.set (1+a_7.x,a_7.y,a_7.z,1+a_7.w); pv++; RCache.Vertex.Unlock (4,g_bloom_filter->vb_stride); // Perform filtering Fvector4 w0,w1; float kernel = ps_r2_ls_bloom_kernel_g; CalcGauss_wave (w0,w1,kernel,kernel/3.f,ps_r2_ls_bloom_kernel_scale); u_setrt (rt_Bloom_2,NULL,NULL,NULL); // No need for ZBuffer at all RCache.set_Element (s_bloom->E[1]); RCache.set_ca ("weight", 0, w0); RCache.set_ca ("weight", 1, w1); RCache.set_Geometry (g_bloom_filter); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } // Transfer into Bloom1, vertical filter { float _w = BLOOM_size_X; float _h = BLOOM_size_Y; Fvector2 two = { 2.f/_w, 2.f/_h }; Fvector2 one = { 1.f/_w, 1.f/_h }; Fvector2 half = { .5f/_w, .5f/_h }; Fvector4 a_0 = { half.x, half.y, half.y, half.x }; // center Fvector4 a_1 = { half.x, a_0.y - one.y - half.y, half.y + one.y + a_0.z, half.x }; // -1,+1i Fvector4 a_2 = { half.x, a_1.y - two.y, two.y + a_1.z, half.x }; // -2,+2i Fvector4 a_3 = { half.x, a_2.y - two.y, two.y + a_2.z, half.x }; // -3,+3i Fvector4 a_4 = { half.x, a_3.y - two.y, two.y + a_3.z, half.x }; // -4,+4i Fvector4 a_5 = { half.x, a_4.y - two.y, two.y + a_4.z, half.x }; // -5,+5i Fvector4 a_6 = { half.x, a_5.y - two.y, two.y + a_5.z, half.x }; // -6,+6i Fvector4 a_7 = { half.x, a_6.y - two.y, two.y + a_6.z, half.x }; // -7,+7i // Fill vertex buffer v_filter* pv = (v_filter*) RCache.Vertex.Lock (4,g_bloom_filter->vb_stride,Offset); // 0 - LB pv->p.set (EPS, float(_h+EPS), EPS,1.f); pv->uv0.set (a_0.x,1+a_0.y,0,0); pv->uv1.set (a_1.x,1+a_1.y,1+a_1.z,a_1.w); pv->uv2.set (a_2.x,1+a_2.y,1+a_2.z,a_2.w); pv->uv3.set (a_3.x,1+a_3.y,1+a_3.z,a_3.w); pv->uv4.set (a_4.x,1+a_4.y,1+a_4.z,a_4.w); pv->uv5.set (a_5.x,1+a_5.y,1+a_5.z,a_5.w); pv->uv6.set (a_6.x,1+a_6.y,1+a_6.z,a_6.w); pv->uv7.set (a_7.x,1+a_7.y,1+a_7.z,a_7.w); pv++; // 1 - LT pv->p.set (EPS, EPS, EPS,1.f); pv->uv0.set (a_0.x,a_0.y,0,0); pv->uv1.set (a_1.x,a_1.y,a_1.z,a_1.w); pv->uv2.set (a_2.x,a_2.y,a_2.z,a_2.w); pv->uv3.set (a_3.x,a_3.y,a_3.z,a_3.w); pv->uv4.set (a_4.x,a_4.y,a_4.z,a_4.w); pv->uv5.set (a_5.x,a_5.y,a_5.z,a_5.w); pv->uv6.set (a_6.x,a_6.y,a_6.z,a_6.w); pv->uv7.set (a_7.x,a_7.y,a_7.z,a_7.w); pv++; // 2 - RB pv->p.set (float(_w+EPS), float(_h+EPS), EPS,1.f); pv->uv0.set (1+a_0.x,1+a_0.y,0,0); pv->uv1.set (1+a_1.x,1+a_1.y,1+a_1.z,1+a_1.w); pv->uv2.set (1+a_2.x,1+a_2.y,1+a_2.z,1+a_2.w); pv->uv3.set (1+a_3.x,1+a_3.y,1+a_3.z,1+a_3.w); pv->uv4.set (1+a_4.x,1+a_4.y,1+a_4.z,1+a_4.w); pv->uv5.set (1+a_5.x,1+a_5.y,1+a_5.z,1+a_5.w); pv->uv6.set (1+a_6.x,1+a_6.y,1+a_6.z,1+a_6.w); pv->uv7.set (1+a_7.x,1+a_7.y,1+a_7.z,1+a_7.w); pv++; // 3 - RT pv->p.set (float(_w+EPS), EPS, EPS,1.f); pv->uv0.set (1+a_0.x,a_0.y,0,0); pv->uv1.set (1+a_1.x,a_1.y,a_1.z,1+a_1.w); pv->uv2.set (1+a_2.x,a_2.y,a_2.z,1+a_2.w); pv->uv3.set (1+a_3.x,a_3.y,a_3.z,1+a_3.w); pv->uv4.set (1+a_4.x,a_4.y,a_4.z,1+a_4.w); pv->uv5.set (1+a_5.x,a_5.y,a_5.z,1+a_5.w); pv->uv6.set (1+a_6.x,a_6.y,a_6.z,1+a_6.w); pv->uv7.set (1+a_7.x,a_7.y,a_7.z,1+a_7.w); pv++; RCache.Vertex.Unlock (4,g_bloom_filter->vb_stride); // Perform filtering Fvector4 w0,w1; float kernel = ps_r2_ls_bloom_kernel_g * float(Device.dwHeight)/float(Device.dwWidth); CalcGauss_wave (w0,w1,kernel,kernel/3.f,ps_r2_ls_bloom_kernel_scale); u_setrt (rt_Bloom_1,NULL,NULL,NULL); // No need for ZBuffer at all RCache.set_Element (s_bloom->E[2]); RCache.set_ca ("weight", 0, w0); RCache.set_ca ("weight", 1, w1); RCache.set_Geometry (g_bloom_filter); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } } // we are left here with bloom-target setup as primary one // for FP16-BLEND capable HW we can blend flares into smaller target, because they are smooth //if (RImplementation.o.fp16_blend) g_pGamePersistent->Environment().RenderFlares (); // lens-flares bool _menu_pp = g_pGamePersistent?g_pGamePersistent->OnRenderPPUI_query():false; if (_menu_pp) { //CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0L)); FLOAT ColorRGBA[4] = {0.0f, 0.0f, 0.0f, 0.0f}; HW.pDevice->ClearRenderTargetView( RCache.get_RT(), ColorRGBA); }; // re-enable z-buffer //CHK_DX (HW.pDevice->SetRenderState ( D3DRS_ZENABLE, TRUE )); RCache.set_Z(TRUE); }
void CRenderTarget::phase_luminance() { u32 Offset = 0; float eps = EPS_S; // Targets RCache.set_Stencil (FALSE); RCache.set_CullMode (CULL_NONE); RCache.set_ColorWriteEnable (); CHK_DX (HW.pDevice->SetRenderState (D3DRS_ZENABLE,FALSE)); // 000: Perform LUM-SAT, pass 0, 256x256 => 64x64 u_setrt (rt_LUM_64,NULL,NULL,NULL); { float ts = 64; float _w = float(BLOOM_size_X); float _h = float(BLOOM_size_Y); Fvector2 one = { 2.f/_w, 2.f/_h }; // two, infact Fvector2 half = { 1.f/_w, 1.f/_h }; // one, infact Fvector2 a_0 = { half.x + 0, half.y + 0 }; Fvector2 a_1 = { half.x + one.x, half.y + 0 }; Fvector2 a_2 = { half.x + 0, half.y + one.y }; Fvector2 a_3 = { half.x + one.x, half.y + one.y }; Fvector2 b_0 = { 1 + a_0.x, 1 + a_0.y }; Fvector2 b_1 = { 1 + a_1.x, 1 + a_1.y }; Fvector2 b_2 = { 1 + a_2.x, 1 + a_2.y }; Fvector2 b_3 = { 1 + a_3.x, 1 + a_3.y }; // Fill vertex buffer v_build* pv = (v_build*) RCache.Vertex.Lock (4,g_bloom_build->vb_stride,Offset); pv->p.set (eps, float(ts+eps), eps,1.f); pv->uv0.set (a_0.x,b_0.y); pv->uv1.set (a_1.x,b_1.y); pv->uv2.set (a_2.x,b_2.y); pv->uv3.set (a_3.x,b_3.y); pv++; pv->p.set (eps, eps, eps,1.f); pv->uv0.set (a_0.x,a_0.y); pv->uv1.set (a_1.x,a_1.y); pv->uv2.set (a_2.x,a_2.y); pv->uv3.set (a_3.x,a_3.y); pv++; pv->p.set (float(ts+eps), float(ts+eps), eps,1.f); pv->uv0.set (b_0.x,b_0.y); pv->uv1.set (b_1.x,b_1.y); pv->uv2.set (b_2.x,b_2.y); pv->uv3.set (b_3.x,b_3.y); pv++; pv->p.set (float(ts+eps), eps, eps,1.f); pv->uv0.set (b_0.x,a_0.y); pv->uv1.set (b_1.x,a_1.y); pv->uv2.set (b_2.x,a_2.y); pv->uv3.set (b_3.x,a_3.y); pv++; RCache.Vertex.Unlock (4,g_bloom_build->vb_stride); RCache.set_Element (s_luminance->E[0]); RCache.set_Geometry (g_bloom_build ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } // 111: Perform LUM-SAT, pass 1, 64x64 => 8x8 u_setrt (rt_LUM_8,NULL,NULL,NULL); { // Build filter-kernel float _ts = 8; float _src = float(64); Fvector2 a[16],b[16]; for (int k=0; k<16; k++) { int _x = (k*2+1)%8; // 1,3,5,7 int _y = ((k/4)*2+1); // 1,1,1,1 ~ 3,3,3,3 ~...etc... a[k].set(_x,_y).div (_src); b[k].set(a[k]).add (1); } // Fill vertex buffer v_filter* pv = (v_filter*) RCache.Vertex.Lock (4,g_bloom_filter->vb_stride,Offset); pv->p.set (eps, float(_ts+eps), eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(a[t].x,b[t].y, b[t+8].y,a[t+8].x); // xy/yx - left+down pv++; pv->p.set (eps, eps, eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(a[t].x,a[t].y, a[t+8].y,a[t+8].x); // xy/yx - left+up pv++; pv->p.set (float(_ts+eps),float(_ts+eps), eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(b[t].x,b[t].y, b[t+8].y,b[t+8].x); // xy/yx - right+down pv++; pv->p.set (float(_ts+eps),eps, eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(b[t].x,a[t].y, a[t+8].y,b[t+8].x); // xy/yx - right+up pv++; RCache.Vertex.Unlock (4,g_bloom_filter->vb_stride); RCache.set_Element (s_luminance->E[1] ); RCache.set_Geometry (g_bloom_filter ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } // 222: Perform LUM-SAT, pass 2, 8x8 => 1x1 u32 gpu_id = Device.dwFrame%2; u_setrt (rt_LUM_pool[gpu_id*2+1],NULL,NULL,NULL); { // Build filter-kernel float _ts = 1; float _src = float(8); Fvector2 a[16],b[16]; for (int k=0; k<16; k++) { int _x = (k*2+1)%8; // 1,3,5,7 int _y = ((k/4)*2+1); // 1,1,1,1 ~ 3,3,3,3 ~...etc... a[k].set(_x,_y).div (_src); b[k].set(a[k]).add (1); } // Fill vertex buffer v_filter* pv = (v_filter*) RCache.Vertex.Lock (4,g_bloom_filter->vb_stride,Offset); pv->p.set (eps, float(_ts+eps), eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(a[t].x,b[t].y, b[t+8].y,a[t+8].x); // xy/yx - left+down pv++; pv->p.set (eps, eps, eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(a[t].x,a[t].y, a[t+8].y,a[t+8].x); // xy/yx - left+up pv++; pv->p.set (float(_ts+eps),float(_ts+eps), eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(b[t].x,b[t].y, b[t+8].y,b[t+8].x); // xy/yx - right+down pv++; pv->p.set (float(_ts+eps),eps, eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(b[t].x,a[t].y, a[t+8].y,b[t+8].x); // xy/yx - right+up pv++; RCache.Vertex.Unlock (4,g_bloom_filter->vb_stride); f_luminance_adapt = .9f*f_luminance_adapt + .1f*Device.fTimeDelta*ps_r2_tonemap_adaptation; float amount = ps_r2_ls_flags.test(R2FLAG_TONEMAP)?ps_r2_tonemap_amount:0; Fvector3 _none, _full, _result; _none.set (1, 0, 1 ); _full.set (ps_r2_tonemap_middlegray, 1.f, ps_r2_tonemap_low_lum ); _result.lerp (_none, _full, amount ); RCache.set_Element (s_luminance->E[2] ); RCache.set_Geometry (g_bloom_filter ); RCache.set_c("MiddleGray", _result.x,_result.y,_result.z,f_luminance_adapt ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } // Cleanup states CHK_DX (HW.pDevice->SetRenderState(D3DRS_ZENABLE,TRUE)); }
CRenderTarget::CRenderTarget () { u32 SampleCount = 1; if (ps_r_ssao_mode!=2/*hdao*/) ps_r_ssao = _min(ps_r_ssao, 3); if( RImplementation.o.dx10_msaa ) SampleCount = RImplementation.o.dx10_msaa_samples; #ifdef DEBUG Msg ("MSAA samples = %d", SampleCount ); if( RImplementation.o.dx10_msaa_opt ) Msg ("dx10_MSAA_opt = on" ); if( RImplementation.o.dx10_gbuffer_opt ) Msg ("dx10_gbuffer_opt = on" ); #endif // DEBUG param_blur = 0.f; param_gray = 0.f; param_noise = 0.f; param_duality_h = 0.f; param_duality_v = 0.f; param_noise_fps = 25.f; param_noise_scale = 1.f; im_noise_time = 1/100; im_noise_shift_w = 0; im_noise_shift_h = 0; param_color_base = color_rgba(127,127,127, 0); param_color_gray = color_rgba(85,85,85, 0); //param_color_add = color_rgba(0,0,0, 0); param_color_add.set( 0.0f, 0.0f, 0.0f ); dwAccumulatorClearMark = 0; dxRenderDeviceRender::Instance().Resources->Evict (); // Blenders b_occq = xr_new<CBlender_light_occq> (); b_accum_mask = xr_new<CBlender_accum_direct_mask> (); b_accum_direct = xr_new<CBlender_accum_direct> (); b_accum_point = xr_new<CBlender_accum_point> (); b_accum_spot = xr_new<CBlender_accum_spot> (); b_accum_reflected = xr_new<CBlender_accum_reflected> (); b_bloom = xr_new<CBlender_bloom_build> (); if( RImplementation.o.dx10_msaa ) { b_bloom_msaa = xr_new<CBlender_bloom_build_msaa> (); b_postprocess_msaa = xr_new<CBlender_postprocess_msaa> (); } b_luminance = xr_new<CBlender_luminance> (); b_combine = xr_new<CBlender_combine> (); b_ssao = xr_new<CBlender_SSAO_noMSAA> (); if( RImplementation.o.dx10_msaa ) { int bound = RImplementation.o.dx10_msaa_samples; if( RImplementation.o.dx10_msaa_opt ) bound = 1; for( int i = 0; i < bound; ++i ) { static LPCSTR SampleDefs[] = { "0","1","2","3","4","5","6","7" }; b_combine_msaa[i] = xr_new<CBlender_combine_msaa> (); b_accum_mask_msaa[i] = xr_new<CBlender_accum_direct_mask_msaa> (); b_accum_direct_msaa[i] = xr_new<CBlender_accum_direct_msaa> (); b_accum_direct_volumetric_msaa[i] = xr_new<CBlender_accum_direct_volumetric_msaa> (); //b_accum_direct_volumetric_sun_msaa[i] = xr_new<CBlender_accum_direct_volumetric_sun_msaa> (); b_accum_spot_msaa[i] = xr_new<CBlender_accum_spot_msaa> (); b_accum_volumetric_msaa[i] = xr_new<CBlender_accum_volumetric_msaa> (); b_accum_point_msaa[i] = xr_new<CBlender_accum_point_msaa> (); b_accum_reflected_msaa[i] = xr_new<CBlender_accum_reflected_msaa> (); b_ssao_msaa[i] = xr_new<CBlender_SSAO_MSAA> (); static_cast<CBlender_accum_direct_mask_msaa*>( b_accum_mask_msaa[i] )->SetDefine( "ISAMPLE", SampleDefs[i]); static_cast<CBlender_accum_direct_volumetric_msaa*>(b_accum_direct_volumetric_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]); //static_cast<CBlender_accum_direct_volumetric_sun_msaa*>(b_accum_direct_volumetric_sun_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]); static_cast<CBlender_accum_direct_msaa*>(b_accum_direct_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]); static_cast<CBlender_accum_volumetric_msaa*>(b_accum_volumetric_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]); static_cast<CBlender_accum_spot_msaa*>(b_accum_spot_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]); static_cast<CBlender_accum_point_msaa*>(b_accum_point_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]); static_cast<CBlender_accum_reflected_msaa*>(b_accum_reflected_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]); static_cast<CBlender_combine_msaa*>(b_combine_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]); static_cast<CBlender_SSAO_MSAA*>(b_ssao_msaa[i])->SetDefine("ISAMPLE", SampleDefs[i]); } } // NORMAL { u32 w=Device.dwWidth, h=Device.dwHeight; rt_Position.create (r2_RT_P, w,h,D3DFMT_A16B16G16R16F, SampleCount ); if( RImplementation.o.dx10_msaa ) rt_MSAADepth.create( r2_RT_MSAAdepth, w, h, D3DFMT_D24S8, SampleCount ); if( !RImplementation.o.dx10_gbuffer_opt ) rt_Normal.create (r2_RT_N, w,h,D3DFMT_A16B16G16R16F, SampleCount ); // select albedo & accum if (RImplementation.o.mrtmixdepth) { // NV50 rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A8R8G8B8 , SampleCount ); rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F, SampleCount ); } else { // can't - mix-depth if (RImplementation.o.fp16_blend) { // NV40 if( !RImplementation.o.dx10_gbuffer_opt ) { rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A16B16G16R16F, SampleCount ); // expand to full rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F, SampleCount ); } else { rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A8R8G8B8, SampleCount ); // expand to full rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F, SampleCount ); } } else { // R4xx, no-fp-blend,-> albedo_wo VERIFY (RImplementation.o.albedo_wo); rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A8R8G8B8 , SampleCount ); // normal rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F, SampleCount ); rt_Accumulator_temp.create (r2_RT_accum_temp, w,h,D3DFMT_A16B16G16R16F, SampleCount ); } } // generic(LDR) RTs rt_Generic_0.create (r2_RT_generic0,w,h,D3DFMT_A8R8G8B8, 1 ); rt_Generic_1.create (r2_RT_generic1,w,h,D3DFMT_A8R8G8B8, 1 ); if( RImplementation.o.dx10_msaa ) { rt_Generic_0_r.create(r2_RT_generic0_r,w,h,D3DFMT_A8R8G8B8, SampleCount ); rt_Generic_1_r.create(r2_RT_generic1_r,w,h,D3DFMT_A8R8G8B8, SampleCount ); rt_Generic.create (r2_RT_generic,w,h, D3DFMT_A8R8G8B8, 1 ); } // Igor: for volumetric lights //rt_Generic_2.create (r2_RT_generic2,w,h,D3DFMT_A8R8G8B8 ); // temp: for higher quality blends if (RImplementation.o.advancedpp) rt_Generic_2.create (r2_RT_generic2,w,h,D3DFMT_A16B16G16R16F, SampleCount ); } // OCCLUSION s_occq.create (b_occq, "r2\\occq"); // DIRECT (spot) D3DFORMAT depth_format = (D3DFORMAT)RImplementation.o.HW_smap_FORMAT; if (RImplementation.o.HW_smap) { D3DFORMAT nullrt = D3DFMT_R5G6B5; if (RImplementation.o.nullrt) nullrt = (D3DFORMAT)MAKEFOURCC('N','U','L','L'); u32 size =RImplementation.o.smapsize ; rt_smap_depth.create (r2_RT_smap_depth, size,size,depth_format ); if (RImplementation.o.dx10_minmax_sm) { rt_smap_depth_minmax.create( r2_RT_smap_depth_minmax, size/4,size/4, D3DFMT_R32F ); CBlender_createminmax TempBlender; s_create_minmax_sm.create( &TempBlender, "null" ); } //rt_smap_surf.create (r2_RT_smap_surf, size,size,nullrt ); //rt_smap_ZB = NULL; s_accum_mask.create (b_accum_mask, "r3\\accum_mask"); s_accum_direct.create (b_accum_direct, "r3\\accum_direct"); if( RImplementation.o.dx10_msaa ) { int bound = RImplementation.o.dx10_msaa_samples; if( RImplementation.o.dx10_msaa_opt ) bound = 1; for( int i = 0; i < bound; ++i ) { s_accum_direct_msaa[i].create (b_accum_direct_msaa[i], "r3\\accum_direct"); s_accum_mask_msaa[i].create (b_accum_mask_msaa[i], "r3\\accum_direct"); } } if (RImplementation.o.advancedpp) { s_accum_direct_volumetric.create("accum_volumetric_sun_nomsaa"); if (RImplementation.o.dx10_minmax_sm) s_accum_direct_volumetric_minmax.create("accum_volumetric_sun_nomsaa_minmax"); if( RImplementation.o.dx10_msaa ) { static LPCSTR snames[] = { "accum_volumetric_sun_msaa0", "accum_volumetric_sun_msaa1", "accum_volumetric_sun_msaa2", "accum_volumetric_sun_msaa3", "accum_volumetric_sun_msaa4", "accum_volumetric_sun_msaa5", "accum_volumetric_sun_msaa6", "accum_volumetric_sun_msaa7" }; int bound = RImplementation.o.dx10_msaa_samples; if( RImplementation.o.dx10_msaa_opt ) bound = 1; for( int i = 0; i < bound; ++i ) { //s_accum_direct_volumetric_msaa[i].create (b_accum_direct_volumetric_sun_msaa[i], "r3\\accum_direct"); s_accum_direct_volumetric_msaa[i].create (snames[i]); } } } } else { // TODO: DX10: Check if we need old-style SMap VERIFY(!"Use HW SMAPs only!"); //u32 size =RImplementation.o.smapsize ; //rt_smap_surf.create (r2_RT_smap_surf, size,size,D3DFMT_R32F); //rt_smap_depth = NULL; //R_CHK (HW.pDevice->CreateDepthStencilSurface (size,size,D3DFMT_D24X8,D3DMULTISAMPLE_NONE,0,TRUE,&rt_smap_ZB,NULL)); //s_accum_mask.create (b_accum_mask, "r2\\accum_mask"); //s_accum_direct.create (b_accum_direct, "r2\\accum_direct"); //if (RImplementation.o.advancedpp) // s_accum_direct_volumetric.create("accum_volumetric_sun"); } // RAIN // TODO: DX10: Create resources only when DX10 rain is enabled. // Or make DX10 rain switch dynamic? { CBlender_rain TempBlender; s_rain.create( &TempBlender, "null"); if( RImplementation.o.dx10_msaa ) { static LPCSTR SampleDefs[] = { "0","1","2","3","4","5","6","7" }; CBlender_rain_msaa TempBlender[8]; int bound = RImplementation.o.dx10_msaa_samples; if( RImplementation.o.dx10_msaa_opt ) bound = 1; for( int i = 0; i < bound; ++i ) { TempBlender[i].SetDefine( "ISAMPLE", SampleDefs[i] ); s_rain_msaa[i].create( &TempBlender[i], "null"); s_accum_spot_msaa[i].create (b_accum_spot_msaa[i], "r2\\accum_spot_s", "lights\\lights_spot01"); s_accum_point_msaa[i].create (b_accum_point_msaa[i], "r2\\accum_point_s"); //s_accum_volume_msaa[i].create(b_accum_direct_volumetric_msaa[i], "lights\\lights_spot01"); s_accum_volume_msaa[i].create(b_accum_volumetric_msaa[i], "lights\\lights_spot01"); s_combine_msaa[i].create (b_combine_msaa[i], "r2\\combine"); } } } if( RImplementation.o.dx10_msaa ) { CBlender_msaa TempBlender; s_mark_msaa_edges.create( &TempBlender, "null" ); } // POINT { s_accum_point.create (b_accum_point, "r2\\accum_point_s"); accum_point_geom_create (); g_accum_point.create (D3DFVF_XYZ, g_accum_point_vb, g_accum_point_ib); accum_omnip_geom_create (); g_accum_omnipart.create (D3DFVF_XYZ, g_accum_omnip_vb, g_accum_omnip_ib); } // SPOT { s_accum_spot.create (b_accum_spot, "r2\\accum_spot_s", "lights\\lights_spot01"); accum_spot_geom_create (); g_accum_spot.create (D3DFVF_XYZ, g_accum_spot_vb, g_accum_spot_ib); } { s_accum_volume.create("accum_volumetric", "lights\\lights_spot01"); accum_volumetric_geom_create(); g_accum_volumetric.create( D3DFVF_XYZ, g_accum_volumetric_vb, g_accum_volumetric_ib); } // REFLECTED { s_accum_reflected.create (b_accum_reflected, "r2\\accum_refl"); if( RImplementation.o.dx10_msaa ) { int bound = RImplementation.o.dx10_msaa_samples; if( RImplementation.o.dx10_msaa_opt ) bound = 1; for( int i = 0; i < bound; ++i ) { s_accum_reflected_msaa[i].create( b_accum_reflected_msaa[i], "null"); } } } // BLOOM { D3DFORMAT fmt = D3DFMT_A8R8G8B8; //; // D3DFMT_X8R8G8B8 u32 w=BLOOM_size_X, h=BLOOM_size_Y; u32 fvf_build = D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3); u32 fvf_filter = (u32)D3DFVF_XYZRHW|D3DFVF_TEX8|D3DFVF_TEXCOORDSIZE4(0)|D3DFVF_TEXCOORDSIZE4(1)|D3DFVF_TEXCOORDSIZE4(2)|D3DFVF_TEXCOORDSIZE4(3)|D3DFVF_TEXCOORDSIZE4(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6)|D3DFVF_TEXCOORDSIZE4(7); rt_Bloom_1.create (r2_RT_bloom1, w,h, fmt); rt_Bloom_2.create (r2_RT_bloom2, w,h, fmt); g_bloom_build.create (fvf_build, RCache.Vertex.Buffer(), RCache.QuadIB); g_bloom_filter.create (fvf_filter, RCache.Vertex.Buffer(), RCache.QuadIB); s_bloom_dbg_1.create ("effects\\screen_set", r2_RT_bloom1); s_bloom_dbg_2.create ("effects\\screen_set", r2_RT_bloom2); s_bloom.create (b_bloom, "r2\\bloom"); if( RImplementation.o.dx10_msaa ) { s_bloom_msaa.create (b_bloom_msaa, "r2\\bloom"); s_postprocess_msaa.create(b_postprocess_msaa, "r2\\post"); } f_bloom_factor = 0.5f; } // TONEMAP { rt_LUM_64.create (r2_RT_luminance_t64, 64, 64, D3DFMT_A16B16G16R16F ); rt_LUM_8.create (r2_RT_luminance_t8, 8, 8, D3DFMT_A16B16G16R16F ); s_luminance.create (b_luminance, "r2\\luminance"); f_luminance_adapt = 0.5f; t_LUM_src.create (r2_RT_luminance_src); t_LUM_dest.create (r2_RT_luminance_cur); // create pool for (u32 it=0; it<HW.Caps.iGPUNum*2; it++) { string256 name; xr_sprintf (name,"%s_%d", r2_RT_luminance_pool,it ); rt_LUM_pool[it].create (name, 1, 1, D3DFMT_R32F ); //u_setrt (rt_LUM_pool[it], 0, 0, 0 ); //CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x7f7f7f7f, 1.0f, 0L)); FLOAT ColorRGBA[4] = { 127.0f/255.0f, 127.0f/255.0f, 127.0f/255.0f, 127.0f/255.0f}; HW.pDevice->ClearRenderTargetView(rt_LUM_pool[it]->pRT, ColorRGBA); } u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB); } // HBAO if (RImplementation.o.ssao_opt_data) { u32 w = 0; u32 h = 0; if (RImplementation.o.ssao_half_data) { w = Device.dwWidth / 2; h = Device.dwHeight / 2; } else { w = Device.dwWidth; h = Device.dwHeight; } D3DFORMAT fmt = HW.Caps.id_vendor==0x10DE?D3DFMT_R32F:D3DFMT_R16F; rt_half_depth.create (r2_RT_half_depth, w, h, fmt); s_ssao.create (b_ssao, "r2\\ssao"); } if (RImplementation.o.ssao_blur_on) { u32 w = Device.dwWidth, h = Device.dwHeight; rt_ssao_temp.create (r2_RT_ssao_temp, w, h, D3DFMT_G16R16F, SampleCount); s_ssao.create (b_ssao, "r2\\ssao"); if( RImplementation.o.dx10_msaa ) { int bound = RImplementation.o.dx10_msaa_opt ? 1 : RImplementation.o.dx10_msaa_samples; for( int i = 0; i < bound; ++i ) { s_ssao_msaa[i].create( b_ssao_msaa[i], "null"); } } } // COMBINE { static D3DVERTEXELEMENT9 dwDecl[] = { { 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, // pos+uv D3DDECL_END() }; s_combine.create (b_combine, "r2\\combine"); s_combine_volumetric.create ("combine_volumetric"); s_combine_dbg_0.create ("effects\\screen_set", r2_RT_smap_surf ); s_combine_dbg_1.create ("effects\\screen_set", r2_RT_luminance_t8 ); s_combine_dbg_Accumulator.create ("effects\\screen_set", r2_RT_accum ); g_combine_VP.create (dwDecl, RCache.Vertex.Buffer(), RCache.QuadIB); g_combine.create (FVF::F_TL, RCache.Vertex.Buffer(), RCache.QuadIB); g_combine_2UV.create (FVF::F_TL2uv, RCache.Vertex.Buffer(), RCache.QuadIB); g_combine_cuboid.create (dwDecl, RCache.Vertex.Buffer(), RCache.Index.Buffer()); u32 fvf_aa_blur = D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3); g_aa_blur.create (fvf_aa_blur, RCache.Vertex.Buffer(), RCache.QuadIB); u32 fvf_aa_AA = D3DFVF_XYZRHW|D3DFVF_TEX7|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3)|D3DFVF_TEXCOORDSIZE2(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6); g_aa_AA.create (fvf_aa_AA, RCache.Vertex.Buffer(), RCache.QuadIB); t_envmap_0.create (r2_T_envs0); t_envmap_1.create (r2_T_envs1); } // Build textures { // Testure for async sreenshots { D3D10_TEXTURE2D_DESC desc; desc.Width = Device.dwWidth; desc.Height = Device.dwHeight; desc.MipLevels = 1; desc.ArraySize = 1; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Format = DXGI_FORMAT_R8G8B8A8_SNORM; desc.Usage = D3D10_USAGE_STAGING; desc.BindFlags = 0; desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; desc.MiscFlags = 0; R_CHK( HW.pDevice->CreateTexture2D(&desc, 0, &t_ss_async) ); } // Build material(s) { // Create immutable texture. // So we need to init data _before_ the creation. // Surface //R_CHK (D3DXCreateVolumeTexture(HW.pDevice,TEX_material_LdotN,TEX_material_LdotH,4,1,0,D3DFMT_A8L8,D3DPOOL_MANAGED,&t_material_surf)); //t_material = dxRenderDeviceRender::Instance().Resources->_CreateTexture(r2_material); //t_material->surface_set (t_material_surf); // Use DXGI_FORMAT_R8G8_UNORM u16 tempData[TEX_material_LdotN*TEX_material_LdotH*TEX_material_Count]; D3D10_TEXTURE3D_DESC desc; desc.Width = TEX_material_LdotN; desc.Height = TEX_material_LdotH; desc.Depth = TEX_material_Count; desc.MipLevels = 1; desc.Format = DXGI_FORMAT_R8G8_UNORM; desc.Usage = D3D10_USAGE_IMMUTABLE; desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; D3D10_SUBRESOURCE_DATA subData; subData.pSysMem = tempData; subData.SysMemPitch = desc.Width*2; subData.SysMemSlicePitch = desc.Height*subData.SysMemPitch; // Fill it (addr: x=dot(L,N),y=dot(L,H)) //D3DLOCKED_BOX R; //R_CHK (t_material_surf->LockBox (0,&R,0,0)); for (u32 slice=0; slice<TEX_material_Count; slice++) { for (u32 y=0; y<TEX_material_LdotH; y++) { for (u32 x=0; x<TEX_material_LdotN; x++) { u16* p = (u16*) (LPBYTE (subData.pSysMem) + slice*subData.SysMemSlicePitch + y*subData.SysMemPitch + x*2); float ld = float(x) / float (TEX_material_LdotN-1); float ls = float(y) / float (TEX_material_LdotH-1) + EPS_S; ls *= powf(ld,1/32.f); float fd,fs; switch (slice) { case 0: { // looks like OrenNayar fd = powf(ld,0.75f); // 0.75 fs = powf(ls,16.f)*.5f; } break; case 1: {// looks like Blinn fd = powf(ld,0.90f); // 0.90 fs = powf(ls,24.f); } break; case 2: { // looks like Phong fd = ld; // 1.0 fs = powf(ls*1.01f,128.f ); } break; case 3: { // looks like Metal float s0 = _abs (1-_abs (0.05f*_sin(33.f*ld)+ld-ls)); float s1 = _abs (1-_abs (0.05f*_cos(33.f*ld*ls)+ld-ls)); float s2 = _abs (1-_abs (ld-ls)); fd = ld; // 1.0 fs = powf (_max(_max(s0,s1),s2), 24.f); fs *= powf (ld,1/7.f); } break; default: fd = fs = 0; } s32 _d = clampr (iFloor (fd*255.5f), 0,255); s32 _s = clampr (iFloor (fs*255.5f), 0,255); if ((y==(TEX_material_LdotH-1)) && (x==(TEX_material_LdotN-1))) { _d = 255; _s=255; } *p = u16 (_s*256 + _d); } } } //R_CHK (t_material_surf->UnlockBox (0)); R_CHK(HW.pDevice->CreateTexture3D(&desc, &subData, &t_material_surf)); t_material = dxRenderDeviceRender::Instance().Resources->_CreateTexture(r2_material); t_material->surface_set (t_material_surf); //R_CHK (D3DXCreateVolumeTexture(HW.pDevice,TEX_material_LdotN,TEX_material_LdotH,4,1,0,D3DFMT_A8L8,D3DPOOL_MANAGED,&t_material_surf)); //t_material = dxRenderDeviceRender::Instance().Resources->_CreateTexture(r2_material); //t_material->surface_set (t_material_surf); // #ifdef DEBUG // R_CHK (D3DXSaveTextureToFile ("x:\\r2_material.dds",D3DXIFF_DDS,t_material_surf,0)); // #endif } // Build noise table if (1) { // Surfaces //D3DLOCKED_RECT R[TEX_jitter_count]; //for (int it=0; it<TEX_jitter_count; it++) //{ // string_path name; // xr_sprintf (name,"%s%d",r2_jitter,it); // R_CHK (D3DXCreateTexture (HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_Q8W8V8U8,D3DPOOL_MANAGED,&t_noise_surf[it])); // t_noise[it] = dxRenderDeviceRender::Instance().Resources->_CreateTexture (name); // t_noise[it]->surface_set (t_noise_surf[it]); // R_CHK (t_noise_surf[it]->LockRect (0,&R[it],0,0)); //} // Use DXGI_FORMAT_R8G8B8A8_SNORM static const int sampleSize = 4; u32 tempData[TEX_jitter_count][TEX_jitter*TEX_jitter]; D3D10_TEXTURE2D_DESC desc; desc.Width = TEX_jitter; desc.Height = TEX_jitter; desc.MipLevels = 1; desc.ArraySize = 1; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Format = DXGI_FORMAT_R8G8B8A8_SNORM; //desc.Usage = D3D10_USAGE_IMMUTABLE; desc.Usage = D3D10_USAGE_DEFAULT; desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; D3D10_SUBRESOURCE_DATA subData[TEX_jitter_count]; for (int it=0; it<TEX_jitter_count-1; it++) { subData[it].pSysMem = tempData[it]; subData[it].SysMemPitch = desc.Width*sampleSize; } // Fill it, for (u32 y=0; y<TEX_jitter; y++) { for (u32 x=0; x<TEX_jitter; x++) { DWORD data [TEX_jitter_count-1]; generate_jitter (data,TEX_jitter_count-1); for (u32 it=0; it<TEX_jitter_count-1; it++) { u32* p = (u32*) (LPBYTE (subData[it].pSysMem) + y*subData[it].SysMemPitch + x*4); *p = data [it]; } } } //for (int it=0; it<TEX_jitter_count; it++) { // R_CHK (t_noise_surf[it]->UnlockRect(0)); //} for (int it=0; it<TEX_jitter_count-1; it++) { string_path name; xr_sprintf (name,"%s%d",r2_jitter,it); //R_CHK (D3DXCreateTexture (HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_Q8W8V8U8,D3DPOOL_MANAGED,&t_noise_surf[it])); R_CHK( HW.pDevice->CreateTexture2D(&desc, &subData[it], &t_noise_surf[it]) ); t_noise[it] = dxRenderDeviceRender::Instance().Resources->_CreateTexture (name); t_noise[it]->surface_set (t_noise_surf[it]); //R_CHK (t_noise_surf[it]->LockRect (0,&R[it],0,0)); } float tempDataHBAO[TEX_jitter*TEX_jitter*4]; // generate HBAO jitter texture (last) D3D10_TEXTURE2D_DESC descHBAO; descHBAO.Width = TEX_jitter; descHBAO.Height = TEX_jitter; descHBAO.MipLevels = 1; descHBAO.ArraySize = 1; descHBAO.SampleDesc.Count = 1; descHBAO.SampleDesc.Quality = 0; descHBAO.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; //desc.Usage = D3D10_USAGE_IMMUTABLE; descHBAO.Usage = D3D10_USAGE_DEFAULT; descHBAO.BindFlags = D3D10_BIND_SHADER_RESOURCE; descHBAO.CPUAccessFlags = 0; descHBAO.MiscFlags = 0; it = TEX_jitter_count-1; subData[it].pSysMem = tempDataHBAO; subData[it].SysMemPitch = descHBAO.Width*sampleSize * sizeof(float); // Fill it, for (u32 y=0; y<TEX_jitter; y++) { for (u32 x=0; x<TEX_jitter; x++) { float numDir = 1.0f; switch (ps_r_ssao) { case 1: numDir = 4.0f; break; case 2: numDir = 6.0f; break; case 3: numDir = 8.0f; break; case 4: numDir = 8.0f; break; } float angle = 2 * PI * ::Random.randF(0.0f, 1.0f) / numDir; float dist = ::Random.randF(0.0f, 1.0f); float *p = (float*) (LPBYTE (subData[it].pSysMem) + y*subData[it].SysMemPitch + x*4*sizeof(float)); *p = (float)(_cos(angle)); *(p+1) = (float)(_sin(angle)); *(p+2) = (float)(dist); *(p+3) = 0; } } string_path name; xr_sprintf (name,"%s%d",r2_jitter,it); //R_CHK (D3DXCreateTexture (HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_Q8W8V8U8,D3DPOOL_MANAGED,&t_noise_surf[it])); R_CHK( HW.pDevice->CreateTexture2D(&descHBAO, &subData[it], &t_noise_surf[it]) ); t_noise[it] = dxRenderDeviceRender::Instance().Resources->_CreateTexture (name); t_noise[it]->surface_set (t_noise_surf[it]); // Create noise mipped { // Autogen mipmaps desc.MipLevels = 0; R_CHK( HW.pDevice->CreateTexture2D(&desc, 0, &t_noise_surf_mipped) ); t_noise_mipped = dxRenderDeviceRender::Instance().Resources->_CreateTexture(r2_jitter_mipped); t_noise_mipped->surface_set(t_noise_surf_mipped); // Update texture. Generate mips. HW.pDevice->CopySubresourceRegion( t_noise_surf_mipped, 0, 0, 0, 0, t_noise_surf[0], 0, 0 ); D3DX10FilterTexture(t_noise_surf_mipped, 0, D3DX10_FILTER_POINT); } } } // PP s_postprocess.create ("postprocess"); g_postprocess.create (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX3,RCache.Vertex.Buffer(),RCache.QuadIB); // Menu s_menu.create ("distort"); g_menu.create (FVF::F_TL,RCache.Vertex.Buffer(),RCache.QuadIB); // dwWidth = Device.dwWidth; dwHeight = Device.dwHeight; }
void CRenderTarget::phase_ssao () { u32 Offset = 0; FLOAT ColorRGBA[4] = {0.0f, 0.0f, 0.0f, 0.0f}; HW.pDevice->ClearRenderTargetView(rt_ssao_temp->pRT, ColorRGBA); // low/hi RTs if( !RImplementation.o.dx10_msaa ) { u_setrt ( rt_ssao_temp,0,0,0/*HW.pBaseZB*/ ); } else { u_setrt ( rt_ssao_temp, 0, 0, 0/*RImplementation.Target->rt_MSAADepth->pZRT*/ ); } RCache.set_Stencil (FALSE); /*RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); // stencil should be >= 1 if (RImplementation.o.nvstencil) { u_stencil_optimize (CRenderTarget::SO_Combine); RCache.set_ColorWriteEnable (); }*/ // Compute params Fmatrix m_v2w; m_v2w.invert (Device.mView ); float fSSAONoise = 2.0f; fSSAONoise *= tan(deg2rad(67.5f)); fSSAONoise /= tan(deg2rad(Device.fFOV)); float fSSAOKernelSize = 150.0f; fSSAOKernelSize *= tan(deg2rad(67.5f)); fSSAOKernelSize /= tan(deg2rad(Device.fFOV)); // Fill VB float scale_X = float(Device.dwWidth) * 0.5f / float(TEX_jitter); float scale_Y = float(Device.dwHeight) * 0.5f / float(TEX_jitter); u32 _w = Device.dwWidth/2; u32 _h = Device.dwHeight/2; set_viewport(HW.pDevice, _w, _h); // Fill vertex buffer FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); pv->set ( -1, 1, 0, 1, 0, 0, scale_Y ); pv++; pv->set ( -1, -1, 0, 0, 0, 0, 0 ); pv++; pv->set ( 1, 1, 1, 1, 0, scale_X, scale_Y ); pv++; pv->set ( 1, -1, 1, 0, 0, scale_X, 0 ); pv++; RCache.Vertex.Unlock (4,g_combine->vb_stride); // Draw RCache.set_Element (s_ssao->E[0] ); RCache.set_Geometry (g_combine ); RCache.set_c ("m_v2w", m_v2w ); RCache.set_c ("ssao_noise_tile_factor", fSSAONoise ); RCache.set_c ("ssao_kernel_size", fSSAOKernelSize ); RCache.set_c ("resolution", float(_w), float(_h), 1.0f / float(_w), 1.0f / float(_h) ); if( !RImplementation.o.dx10_msaa ) RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); else { RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); /*RCache.set_Stencil( TRUE, D3DCMP_EQUAL, 0x01, 0x81, 0 ); RCache.Render ( D3DPT_TRIANGLELIST,Offset,0,4,0,2); if( RImplementation.o.dx10_msaa_opt ) { RCache.set_Element( s_ssao_msaa[0]->E[0] ); RCache.set_Stencil( TRUE, D3DCMP_EQUAL, 0x81, 0x81, 0 ); RCache.Render ( D3DPT_TRIANGLELIST,Offset,0,4,0,2); } else { for( u32 i = 0; i < RImplementation.o.dx10_msaa_samples; ++i ) { RCache.set_Element ( s_ssao_msaa[i]->E[0] ); StateManager.SetSampleMask ( u32(1) << i ); RCache.set_Stencil ( TRUE, D3DCMP_EQUAL, 0x81, 0x81, 0 ); RCache.Render ( D3DPT_TRIANGLELIST,Offset,0,4,0,2); } StateManager.SetSampleMask( 0xffffffff ); }*/ //RCache.set_Stencil( FALSE, D3DCMP_EQUAL, 0x01, 0xff, 0 ); } set_viewport(HW.pDevice, Device.dwWidth, Device.dwHeight); RCache.set_Stencil (FALSE); }
void CRenderTarget::accum_direct_f (u32 sub_phase) { // Select target if (SE_SUN_LUMINANCE==sub_phase) { accum_direct_lum (); return ; } phase_accumulator (); u_setrt (rt_Generic_0,NULL,NULL,HW.pBaseZB); // *** assume accumulator setted up *** light* fuckingsun = (light*)RImplementation.Lights.sun_adapted._get() ; // Common calc for quad-rendering u32 Offset; u32 C = color_rgba (255,255,255,255); float _w = float (Device.dwWidth); float _h = float (Device.dwHeight); Fvector2 p0,p1; p0.set (.5f/_w, .5f/_h); p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); float d_Z = EPS_S, d_W = 1.f; // Common constants (light-related) Fvector L_dir,L_clr; float L_spec; L_clr.set (fuckingsun->color.r,fuckingsun->color.g,fuckingsun->color.b); L_spec = u_diffuse2s (L_clr); Device.mView.transform_dir (L_dir,fuckingsun->direction); L_dir.normalize (); // Perform masking (only once - on the first/near phase) RCache.set_CullMode (CULL_NONE ); if (SE_SUN_NEAR==sub_phase) //. { // For sun-filter - clear to zero CHK_DX (HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0L)); // Fill vertex buffer FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p1.y); pv++; pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p0.y); pv++; pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p1.y); pv++; pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p0.y); pv++; RCache.Vertex.Unlock (4,g_combine->vb_stride); RCache.set_Geometry (g_combine); // setup float intensity = 0.3f*fuckingsun->color.r + 0.48f*fuckingsun->color.g + 0.22f*fuckingsun->color.b; Fvector dir = L_dir; dir.normalize().mul (- _sqrt(intensity+EPS)); RCache.set_Element (s_accum_mask->E[SE_MASK_DIRECT]); // masker RCache.set_c ("Ldynamic_dir", dir.x,dir.y,dir.z,0 ); // if (stencil>=1 && aref_pass) stencil = light_id RCache.set_ColorWriteEnable (FALSE ); RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0x01,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } // recalculate d_Z, to perform depth-clipping Fvector center_pt; center_pt.mad (Device.vCameraPosition,Device.vCameraDirection,ps_r2_sun_near); Device.mFullTransform.transform(center_pt) ; d_Z = center_pt.z ; // nv-stencil recompression if (RImplementation.o.nvstencil && (SE_SUN_NEAR==sub_phase)) u_stencil_optimize(); //. driver bug? // Perform lighting { u_setrt (rt_Generic_0,NULL,NULL,HW.pBaseZB); // enshure RT setup RCache.set_CullMode (CULL_NONE ); RCache.set_ColorWriteEnable (); // texture adjustment matrix float fTexelOffs = (.5f / float(RImplementation.o.smapsize)); float fRange = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_scale:ps_r2_sun_depth_far_scale; float fBias = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_bias:ps_r2_sun_depth_far_bias; Fmatrix m_TexelAdjust = { 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, fRange, 0.0f, 0.5f + fTexelOffs, 0.5f + fTexelOffs, fBias, 1.0f }; // compute xforms Fmatrix m_shadow; { FPU::m64r (); Fmatrix xf_invview; xf_invview.invert (Device.mView) ; Fmatrix xf_project; xf_project.mul (m_TexelAdjust,fuckingsun->X.D.combine); m_shadow.mul (xf_project, xf_invview); // tsm-bias if (SE_SUN_FAR == sub_phase) { Fvector bias; bias.mul (L_dir,ps_r2_sun_tsm_bias); Fmatrix bias_t; bias_t.translate(bias); m_shadow.mulB_44 (bias_t); } FPU::m24r (); } // Make jitter texture Fvector2 j0,j1; float scale_X = float(Device.dwWidth) / float(TEX_jitter); //float scale_Y = float(Device.dwHeight)/ float(TEX_jitter); float offset = (.5f / float(TEX_jitter)); j0.set (offset,offset); j1.set (scale_X,scale_X).add(offset); // Fill vertex buffer FVF::TL2uv* pv = (FVF::TL2uv*) RCache.Vertex.Lock (4,g_combine_2UV->vb_stride,Offset); pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p1.y, j0.x, j1.y); pv++; pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p0.y, j0.x, j0.y); pv++; pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p1.y, j1.x, j1.y); pv++; pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p0.y, j1.x, j0.y); pv++; RCache.Vertex.Unlock (4,g_combine_2UV->vb_stride); RCache.set_Geometry (g_combine_2UV); // setup RCache.set_Element (s_accum_direct->E[sub_phase]); RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); RCache.set_c ("Ldynamic_color", L_clr.x,L_clr.y,L_clr.z,L_spec ); RCache.set_c ("m_shadow", m_shadow ); // setup stencil RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } }
// startup void CRenderTarget::phase_scene_prepare () { // Clear depth & stencil u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB ); CHK_DX ( HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x0, 1.0f, 0L) ); }
CRenderTarget::CRenderTarget () { param_blur = 0.f; param_gray = 0.f; param_noise = 0.f; param_duality_h = 0.f; param_duality_v = 0.f; param_noise_fps = 25.f; param_noise_scale = 1.f; im_noise_time = 1/100; im_noise_shift_w = 0; im_noise_shift_h = 0; param_color_base = color_rgba(127,127,127, 0); param_color_gray = color_rgba(85,85,85, 0); param_color_add = color_rgba(0,0,0, 0); dwAccumulatorClearMark = 0; Device.Resources->Evict (); // Blenders b_occq = xr_new<CBlender_light_occq> (); b_accum_mask = xr_new<CBlender_accum_direct_mask> (); b_accum_direct = xr_new<CBlender_accum_direct> (); b_accum_point = xr_new<CBlender_accum_point> (); b_accum_spot = xr_new<CBlender_accum_spot> (); b_accum_reflected = xr_new<CBlender_accum_reflected> (); b_bloom = xr_new<CBlender_bloom_build> (); b_luminance = xr_new<CBlender_luminance> (); b_combine = xr_new<CBlender_combine> (); // NORMAL { u32 w=Device.dwWidth, h=Device.dwHeight; rt_Position.create (r2_RT_P, w,h,D3DFMT_A16B16G16R16F); rt_Normal.create (r2_RT_N, w,h,D3DFMT_A16B16G16R16F); // select albedo & accum if (RImplementation.o.mrtmixdepth) { // NV50 rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A8R8G8B8 ); rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F); } else { // can't - mix-depth if (RImplementation.o.fp16_blend) { // NV40 rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A16B16G16R16F); // expand to full rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F); } else { // R4xx, no-fp-blend,-> albedo_wo VERIFY (RImplementation.o.albedo_wo); rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A8R8G8B8 ); // normal rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F); rt_Accumulator_temp.create (r2_RT_accum_temp, w,h,D3DFMT_A16B16G16R16F); } } // generic(LDR) RTs rt_Generic_0.create (r2_RT_generic0,w,h,D3DFMT_A8R8G8B8 ); rt_Generic_1.create (r2_RT_generic1,w,h,D3DFMT_A8R8G8B8 ); } // OCCLUSION s_occq.create (b_occq, "r2\\occq"); // DIRECT (spot) D3DFORMAT depth_format = (D3DFORMAT)RImplementation.o.HW_smap_FORMAT; if (RImplementation.o.HW_smap) { D3DFORMAT nullrt = D3DFMT_R5G6B5; if (RImplementation.o.nullrt) nullrt = (D3DFORMAT)MAKEFOURCC('N','U','L','L'); u32 size =RImplementation.o.smapsize ; rt_smap_depth.create (r2_RT_smap_depth, size,size,depth_format ); rt_smap_surf.create (r2_RT_smap_surf, size,size,nullrt ); rt_smap_ZB = NULL; s_accum_mask.create (b_accum_mask, "r2\\accum_mask"); s_accum_direct.create (b_accum_direct, "r2\\accum_direct"); } else { u32 size =RImplementation.o.smapsize ; rt_smap_surf.create (r2_RT_smap_surf, size,size,D3DFMT_R32F); rt_smap_depth = NULL; R_CHK (HW.pDevice->CreateDepthStencilSurface (size,size,D3DFMT_D24X8,D3DMULTISAMPLE_NONE,0,TRUE,&rt_smap_ZB,NULL)); s_accum_mask.create (b_accum_mask, "r2\\accum_mask"); s_accum_direct.create (b_accum_direct, "r2\\accum_direct"); } // POINT { s_accum_point.create (b_accum_point, "r2\\accum_point_s"); accum_point_geom_create (); g_accum_point.create (D3DFVF_XYZ, g_accum_point_vb, g_accum_point_ib); accum_omnip_geom_create (); g_accum_omnipart.create (D3DFVF_XYZ, g_accum_omnip_vb, g_accum_omnip_ib); } // SPOT { s_accum_spot.create (b_accum_spot, "r2\\accum_spot_s", "lights\\lights_spot01"); accum_spot_geom_create (); g_accum_spot.create (D3DFVF_XYZ, g_accum_spot_vb, g_accum_spot_ib); } // REFLECTED { s_accum_reflected.create (b_accum_reflected, "r2\\accum_refl"); } // BLOOM { D3DFORMAT fmt = D3DFMT_A8R8G8B8; //; // D3DFMT_X8R8G8B8 u32 w=BLOOM_size_X, h=BLOOM_size_Y; u32 fvf_build = D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3); u32 fvf_filter = (u32)D3DFVF_XYZRHW|D3DFVF_TEX8|D3DFVF_TEXCOORDSIZE4(0)|D3DFVF_TEXCOORDSIZE4(1)|D3DFVF_TEXCOORDSIZE4(2)|D3DFVF_TEXCOORDSIZE4(3)|D3DFVF_TEXCOORDSIZE4(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6)|D3DFVF_TEXCOORDSIZE4(7); rt_Bloom_1.create (r2_RT_bloom1, w,h, fmt); rt_Bloom_2.create (r2_RT_bloom2, w,h, fmt); g_bloom_build.create (fvf_build, RCache.Vertex.Buffer(), RCache.QuadIB); g_bloom_filter.create (fvf_filter, RCache.Vertex.Buffer(), RCache.QuadIB); s_bloom_dbg_1.create ("effects\\screen_set", r2_RT_bloom1); s_bloom_dbg_2.create ("effects\\screen_set", r2_RT_bloom2); s_bloom.create (b_bloom, "r2\\bloom"); f_bloom_factor = 0.5f; } // TONEMAP { rt_LUM_64.create (r2_RT_luminance_t64, 64, 64, D3DFMT_A16B16G16R16F ); rt_LUM_8.create (r2_RT_luminance_t8, 8, 8, D3DFMT_A16B16G16R16F ); s_luminance.create (b_luminance, "r2\\luminance"); f_luminance_adapt = 0.5f; t_LUM_src.create (r2_RT_luminance_src); t_LUM_dest.create (r2_RT_luminance_cur); // create pool for (u32 it=0; it<4; it++) { string256 name; sprintf (name,"%s_%d", r2_RT_luminance_pool,it ); rt_LUM_pool[it].create (name, 1, 1, D3DFMT_R32F ); u_setrt (rt_LUM_pool[it], 0, 0, 0 ); CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x7f7f7f7f, 1.0f, 0L)); } u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB); } // COMBINE { static D3DVERTEXELEMENT9 dwDecl[] = { { 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, // pos+uv D3DDECL_END() }; s_combine.create (b_combine, "r2\\combine"); s_combine_dbg_0.create ("effects\\screen_set", r2_RT_smap_surf ); s_combine_dbg_1.create ("effects\\screen_set", r2_RT_luminance_t8 ); s_combine_dbg_Accumulator.create ("effects\\screen_set", r2_RT_accum ); g_combine_VP.create (dwDecl, RCache.Vertex.Buffer(), RCache.QuadIB); g_combine.create (FVF::F_TL, RCache.Vertex.Buffer(), RCache.QuadIB); g_combine_2UV.create (FVF::F_TL2uv, RCache.Vertex.Buffer(), RCache.QuadIB); u32 fvf_aa_blur = D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3); g_aa_blur.create (fvf_aa_blur, RCache.Vertex.Buffer(), RCache.QuadIB); u32 fvf_aa_AA = D3DFVF_XYZRHW|D3DFVF_TEX7|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3)|D3DFVF_TEXCOORDSIZE2(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6); g_aa_AA.create (fvf_aa_AA, RCache.Vertex.Buffer(), RCache.QuadIB); t_envmap_0.create (r2_T_envs0); t_envmap_1.create (r2_T_envs1); } // Build textures { // Build material(s) { // Surface R_CHK (D3DXCreateVolumeTexture(HW.pDevice,TEX_material_LdotN,TEX_material_LdotH,4,1,0,D3DFMT_A8L8,D3DPOOL_MANAGED,&t_material_surf)); t_material = Device.Resources->_CreateTexture(r2_material); t_material->surface_set (t_material_surf); // Fill it (addr: x=dot(L,N),y=dot(L,H)) D3DLOCKED_BOX R; R_CHK (t_material_surf->LockBox (0,&R,0,0)); for (u32 slice=0; slice<4; slice++) { for (u32 y=0; y<TEX_material_LdotH; y++) { for (u32 x=0; x<TEX_material_LdotN; x++) { u16* p = (u16*) (LPBYTE (R.pBits) + slice*R.SlicePitch + y*R.RowPitch + x*2); float ld = float(x) / float (TEX_material_LdotN-1); float ls = float(y) / float (TEX_material_LdotH-1) + EPS_S; ls *= powf(ld,1/32.f); float fd,fs; switch (slice) { case 0: { // looks like OrenNayar fd = powf(ld,0.75f); // 0.75 fs = powf(ls,16.f)*.5f; } break; case 1: {// looks like Blinn fd = powf(ld,0.90f); // 0.90 fs = powf(ls,24.f); } break; case 2: { // looks like Phong fd = ld; // 1.0 fs = powf(ls*1.01f,128.f ); } break; case 3: { // looks like Metal float s0 = _abs (1-_abs (0.05f*_sin(33.f*ld)+ld-ls)); float s1 = _abs (1-_abs (0.05f*_cos(33.f*ld*ls)+ld-ls)); float s2 = _abs (1-_abs (ld-ls)); fd = ld; // 1.0 fs = powf (_max(_max(s0,s1),s2), 24.f); fs *= powf (ld,1/7.f); } break; default: fd = fs = 0; } s32 _d = clampr (iFloor (fd*255.5f), 0,255); s32 _s = clampr (iFloor (fs*255.5f), 0,255); if ((y==(TEX_material_LdotH-1)) && (x==(TEX_material_LdotN-1))) { _d = 255; _s=255; } *p = u16 (_s*256 + _d); } } } R_CHK (t_material_surf->UnlockBox (0)); // #ifdef DEBUG // R_CHK (D3DXSaveTextureToFile ("x:\\r2_material.dds",D3DXIFF_DDS,t_material_surf,0)); // #endif } // Build noise table if (1) { // Surfaces D3DLOCKED_RECT R[TEX_jitter_count]; for (int it=0; it<TEX_jitter_count; it++) { string_path name; sprintf (name,"%s%d",r2_jitter,it); R_CHK (D3DXCreateTexture (HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_Q8W8V8U8,D3DPOOL_MANAGED,&t_noise_surf[it])); t_noise[it] = Device.Resources->_CreateTexture (name); t_noise[it]->surface_set (t_noise_surf[it]); R_CHK (t_noise_surf[it]->LockRect (0,&R[it],0,0)); } // Fill it, for (u32 y=0; y<TEX_jitter; y++) { for (u32 x=0; x<TEX_jitter; x++) { DWORD data [TEX_jitter_count]; generate_jitter (data,TEX_jitter_count); for (u32 it=0; it<TEX_jitter_count; it++) { u32* p = (u32*) (LPBYTE (R[it].pBits) + y*R[it].Pitch + x*4); *p = data [it]; } } } for (int it=0; it<TEX_jitter_count; it++) { R_CHK (t_noise_surf[it]->UnlockRect(0)); } } } // PP s_postprocess.create ("postprocess"); g_postprocess.create (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX3,RCache.Vertex.Buffer(),RCache.QuadIB); // Menu s_menu.create ("distort"); g_menu.create (FVF::F_TL,RCache.Vertex.Buffer(),RCache.QuadIB); // dwWidth = Device.dwWidth; dwHeight = Device.dwHeight; }
void CRenderTarget::draw_rain( light &RainSetup ) { float fRainFactor = g_pGamePersistent->Environment().CurrentEnv->rain_density; // Common calc for quad-rendering u32 Offset; u32 C = color_rgba (255,255,255,255); float _w = float (Device.dwWidth); float _h = float (Device.dwHeight); Fvector2 p0,p1; p0.set (.5f/_w, .5f/_h); p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); float d_Z = EPS_S, d_W = 1.f; // Common constants (light-related) Fvector L_dir; Device.mView.transform_dir (L_dir,RainSetup.direction); L_dir.normalize (); Fvector W_dirX; Device.mView.transform_dir (W_dirX,Fvector().set(1.0f, 0.0f, 0.0f)); W_dirX.normalize (); Fvector W_dirZ; Device.mView.transform_dir (W_dirZ,Fvector().set(0.0f, 0.0f, 1.0f)); W_dirZ.normalize (); // Perform masking (only once - on the first/near phase) //RCache.set_CullMode (CULL_NONE ); //if (SE_SUN_NEAR==sub_phase) //. { // Fill vertex buffer FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p1.y); pv++; pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p0.y); pv++; pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p1.y); pv++; pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p0.y); pv++; RCache.Vertex.Unlock (4,g_combine->vb_stride); RCache.set_Geometry (g_combine); // setup // float intensity = 0.3f*fuckingsun->color.r + 0.48f*fuckingsun->color.g + 0.22f*fuckingsun->color.b; // Fvector dir = L_dir; // dir.normalize().mul (- _sqrt(intensity+EPS)); // RCache.set_Element (s_accum_mask->E[SE_MASK_DIRECT]); // masker // RCache.set_c ("Ldynamic_dir", dir.x,dir.y,dir.z,0 ); // if (stencil>=1 && aref_pass) stencil = light_id // Done in blender! //RCache.set_ColorWriteEnable (FALSE ); // RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0x01,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); // RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } // recalculate d_Z, to perform depth-clipping const float fRainFar = ps_r3_dyn_wet_surf_far; Fvector center_pt; center_pt.mad (Device.vCameraPosition,Device.vCameraDirection,fRainFar); Device.mFullTransform.transform(center_pt) ; d_Z = center_pt.z ; // nv-stencil recompression //if (RImplementation.o.nvstencil && (SE_SUN_NEAR==sub_phase)) u_stencil_optimize(); //. driver bug? // Perform lighting { // phase_accumulator () ; // RCache.set_CullMode (CULL_NONE); // RCache.set_ColorWriteEnable () ; // texture adjustment matrix //float fRange = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_scale:ps_r2_sun_depth_far_scale; float fRange = 1; //float fBias = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_bias:ps_r2_sun_depth_far_bias; //float fBias = 0.00001; float fBias = -0.0001; float smapsize = float(RImplementation.o.smapsize); float fTexelOffs = (.5f / smapsize); // float view_dimX = float(RainSetup.X.D.maxX-RainSetup.X.D.minX-2)/smapsize; // float view_dimY = float(RainSetup.X.D.maxX-RainSetup.X.D.minX-2)/smapsize; // float view_sx = float(RainSetup.X.D.minX+1)/smapsize; // float view_sy = float(RainSetup.X.D.minY+1)/smapsize; float view_dimX = float(RainSetup.X.D.maxX-RainSetup.X.D.minX)/smapsize; float view_dimY = float(RainSetup.X.D.maxX-RainSetup.X.D.minX)/smapsize; float view_sx = float(RainSetup.X.D.minX)/smapsize; float view_sy = float(RainSetup.X.D.minY)/smapsize; Fmatrix m_TexelAdjust = { view_dimX/2.f, 0.0f, 0.0f, 0.0f, 0.0f, -view_dimY/2.f, 0.0f, 0.0f, 0.0f, 0.0f, fRange, 0.0f, view_dimX/2.f + view_sx + fTexelOffs, view_dimY/2.f + view_sy + fTexelOffs, fBias, 1.0f }; // compute xforms FPU::m64r (); Fmatrix xf_invview; xf_invview.invert (Device.mView) ; // shadow xform Fmatrix m_shadow; { Fmatrix xf_project; xf_project.mul (m_TexelAdjust,RainSetup.X.D.combine); m_shadow.mul (xf_project, xf_invview); FPU::m24r (); } /* // texture adjustment matrix //float fRange = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_scale:ps_r2_sun_depth_far_scale; float fRange = 1; //float fBias = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_bias:ps_r2_sun_depth_far_bias; // TODO: DX10: Remove this when fix inverse culling for far region float fBias = 0; Fmatrix m_TexelAdjust = { 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, fRange, 0.0f, 0.5f, 0.5f, fBias, 1.0f }; // compute xforms FPU::m64r (); Fmatrix xf_invview; xf_invview.invert (Device.mView) ; // shadow xform Fmatrix m_shadow; { Fmatrix xf_project; xf_project.mul (m_TexelAdjust,RainSetup.X.D.combine); m_shadow.mul (xf_project, xf_invview); FPU::m24r (); } */ // clouds xform Fmatrix m_clouds_shadow; { static float w_shift = 0; Fmatrix m_xform; //Fvector direction = RainSetup.direction ; Fvector normal ; normal.setHP(1,0); //w_shift += 0.003f*Device.fTimeDelta; //Fvector position; position.set(0,0,0); //m_xform.build_camera_dir (position,direction,normal) ; m_xform.identity(); Fvector localnormal;m_xform.transform_dir(localnormal,normal); localnormal.normalize(); m_clouds_shadow.mul (m_xform,xf_invview) ; //m_xform.scale (0.002f,0.002f,1.f) ; m_xform.scale (1.f,1.f,1.f) ; m_clouds_shadow.mulA_44 (m_xform) ; m_xform.translate (localnormal.mul(w_shift)) ; m_clouds_shadow.mulA_44 (m_xform) ; } // Make jitter texture Fvector2 j0,j1; float scale_X = float(Device.dwWidth) / float(TEX_jitter); //float scale_Y = float(Device.dwHeight)/ float(TEX_jitter); float offset = (.5f / float(TEX_jitter)); j0.set (offset,offset); j1.set (scale_X,scale_X).add(offset); // Fill vertex buffer FVF::TL2uv* pv = (FVF::TL2uv*) RCache.Vertex.Lock (4,g_combine_2UV->vb_stride,Offset); pv->set (-1, -1, d_Z, d_W, C, 0, 1, 0, scale_X); pv++; pv->set (-1, 1, d_Z, d_W, C, 0, 0, 0, 0); pv++; pv->set (1, -1, d_Z, d_W, C, 1, 1, scale_X, scale_X); pv++; pv->set (1, 1, d_Z, d_W, C, 1, 0, scale_X, 0); pv++; RCache.Vertex.Unlock (4,g_combine_2UV->vb_stride); RCache.set_Geometry (g_combine_2UV); // setup //RCache.set_Element (s_accum_direct->E[sub_phase]); //u_setrt (rt_Normal,NULL,NULL,HW.pBaseZB); //RCache.set_Element (s_rain->E[0]); //RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); // RCache.set_c ("Ldynamic_color", L_clr.x,L_clr.y,L_clr.z,L_spec ); //RCache.set_c ("m_shadow", m_shadow ); //RCache.set_c ("m_sunmask", m_clouds_shadow ); /* // nv-DBT float zMin,zMax; if (SE_SUN_NEAR==sub_phase) { zMin = 0; zMax = ps_r2_sun_near; } else { extern float OLES_SUN_LIMIT_27_01_07; zMin = ps_r2_sun_near; zMax = OLES_SUN_LIMIT_27_01_07; } center_pt.mad(Device.vCameraPosition,Device.vCameraDirection,zMin); Device.mFullTransform.transform (center_pt); zMin = center_pt.z ; center_pt.mad(Device.vCameraPosition,Device.vCameraDirection,zMax); Device.mFullTransform.transform (center_pt); zMax = center_pt.z ; */ // TODO: DX10: Check if DX10 has analog for NV DBT // if (u_DBT_enable(zMin,zMax)) { // z-test always // HW.pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); // HW.pDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); // } // Fetch4 : enable // if (RImplementation.o.HW_smap_FETCH4) { //. we hacked the shader to force smap on S0 //# define FOURCC_GET4 MAKEFOURCC('G','E','T','4') // HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET4 ); // } // setup stencil // RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); // RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); // Fetch4 : disable // if (RImplementation.o.HW_smap_FETCH4) { //. we hacked the shader to force smap on S0 //# define FOURCC_GET1 MAKEFOURCC('G','E','T','1') // HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET1 ); // } // Use for intermediate results // Patch normal if( !RImplementation.o.dx10_msaa ) u_setrt (rt_Accumulator,NULL,NULL,HW.pBaseZB); else u_setrt (rt_Accumulator,NULL,NULL,rt_MSAADepth->pZRT); //u_setrt (rt_Normal,NULL,NULL,HW.pBaseZB); RCache.set_Element (s_rain->E[1]); RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); RCache.set_c ("WorldX", W_dirX.x,W_dirX.y,W_dirX.z,0 ); RCache.set_c ("WorldZ", W_dirZ.x,W_dirZ.y,W_dirZ.z,0 ); RCache.set_c ("m_shadow", m_shadow ); RCache.set_c ("m_sunmask", m_clouds_shadow ); RCache.set_c ("RainDensity", fRainFactor, 0, 0, 0 ); RCache.set_c ("RainFallof", ps_r3_dyn_wet_surf_near, ps_r3_dyn_wet_surf_far, 0, 0 ); if( !RImplementation.o.dx10_msaa ) { RCache.set_Stencil( TRUE, D3DCMP_EQUAL, 0x01, 0x01, 0 ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } else { // per pixel execution RCache.set_Stencil( TRUE, D3DCMP_EQUAL, 0x01, 0x81, 0 ); RCache.Render ( D3DPT_TRIANGLELIST,Offset,0,4,0,2); // per sample if( RImplementation.o.dx10_msaa_opt ) { RCache.set_Element( s_rain_msaa[0]->E[0]); RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); RCache.set_c ("WorldX", W_dirX.x,W_dirX.y,W_dirX.z,0 ); RCache.set_c ("WorldZ", W_dirZ.x,W_dirZ.y,W_dirZ.z,0 ); RCache.set_c ("m_shadow", m_shadow ); RCache.set_c ("m_sunmask", m_clouds_shadow ); RCache.set_c ("RainDensity", fRainFactor, 0, 0, 0 ); RCache.set_CullMode(CULL_NONE ); RCache.set_Stencil( TRUE, D3DCMP_EQUAL, 0x81, 0x81, 0 ); RCache.Render ( D3DPT_TRIANGLELIST,Offset,0,4,0,2); } else { for( u32 i = 0; i < RImplementation.o.dx10_msaa_samples; ++i ) { RCache.set_Element ( s_rain_msaa[i]->E[0]); RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); RCache.set_c ("WorldX", W_dirX.x,W_dirX.y,W_dirX.z,0 ); RCache.set_c ("WorldZ", W_dirZ.x,W_dirZ.y,W_dirZ.z,0 ); RCache.set_c ("m_shadow", m_shadow ); RCache.set_c ("m_sunmask", m_clouds_shadow ); RCache.set_c ("RainDensity", fRainFactor, 0, 0, 0 ); StateManager.SetSampleMask ( u32(1) << i ); RCache.set_CullMode(CULL_NONE ); RCache.set_Stencil ( TRUE, D3DCMP_EQUAL, 0x81, 0x81, 0 ); RCache.Render ( D3DPT_TRIANGLELIST,Offset,0,4,0,2); } StateManager.SetSampleMask( 0xffffffff ); } } // Apply normal RCache.set_Element (s_rain->E[2]); RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); RCache.set_c ("m_shadow", m_shadow ); RCache.set_c ("m_sunmask", m_clouds_shadow ); if( !RImplementation.o.dx10_gbuffer_opt ) { // Do this in blender! //StateManager.SetColorWriteEnable( D3Dxx_COLOR_WRITE_ENABLE_RED | D3Dxx_COLOR_WRITE_ENABLE_GREEN | D3Dxx_COLOR_WRITE_ENABLE_BLUE ); if( ! RImplementation.o.dx10_msaa ) u_setrt (rt_Normal,NULL,NULL,HW.pBaseZB); else u_setrt (rt_Normal,NULL,NULL,rt_MSAADepth->pZRT); } else { //StateManager.SetColorWriteEnable( D3Dxx_COLOR_WRITE_ENABLE_RED | D3Dxx_COLOR_WRITE_ENABLE_GREEN ); if( ! RImplementation.o.dx10_msaa ) u_setrt (rt_Position,NULL,NULL,HW.pBaseZB); else u_setrt (rt_Position,NULL,NULL,rt_MSAADepth->pZRT); } if( ! RImplementation.o.dx10_msaa ) { RCache.set_Stencil( TRUE, D3DCMP_EQUAL, 0x01, 0x01, 0 ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } else { // per pixel execution RCache.set_Stencil( TRUE, D3DCMP_EQUAL, 0x01, 0x81, 0 ); RCache.Render ( D3DPT_TRIANGLELIST,Offset,0,4,0,2); // per sample if( RImplementation.o.dx10_msaa_opt ) { RCache.set_Element ( s_rain_msaa[0]->E[1]); RCache.set_Stencil ( TRUE, D3DCMP_EQUAL, 0x81, 0x81, 0 ); RCache.set_CullMode(CULL_NONE ); RCache.Render ( D3DPT_TRIANGLELIST,Offset,0,4,0,2); } else { for( u32 i = 0; i < RImplementation.o.dx10_msaa_samples; ++ i ) { RCache.set_Element (s_rain_msaa[i]->E[1]); StateManager.SetSampleMask ( u32(1) << i ); RCache.set_Stencil ( TRUE, D3DCMP_EQUAL, 0x81, 0x81, 0 ); RCache.set_CullMode(CULL_NONE ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } StateManager.SetSampleMask( 0xffffffff ); } } // Apply gloss RCache.set_Element (s_rain->E[3]); RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); RCache.set_c ("m_shadow", m_shadow ); RCache.set_c ("m_sunmask", m_clouds_shadow ); // It is restored automatically by a set_Element call //StateManager.SetColorWriteEnable( D3Dxx_COLOR_WRITE_ENABLE_ALL ); if( ! RImplementation.o.dx10_msaa ) u_setrt (rt_Color,NULL,NULL,HW.pBaseZB); else u_setrt (rt_Color,NULL,NULL,rt_MSAADepth->pZRT); if( ! RImplementation.o.dx10_msaa ) { RCache.set_Stencil( TRUE, D3DCMP_EQUAL, 0x01, 0x01, 0 ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } else { // per pixel execution RCache.set_Stencil( TRUE, D3DCMP_EQUAL, 0x01, 0x81, 0 ); RCache.Render ( D3DPT_TRIANGLELIST,Offset,0,4,0,2); // per sample if( RImplementation.o.dx10_msaa_opt ) { RCache.set_Element(s_rain_msaa[0]->E[2]); RCache.set_Stencil( TRUE, D3DCMP_EQUAL, 0x81, 0x81, 0 ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } else { for( u32 i = 0; i < RImplementation.o.dx10_msaa_samples; ++i ) { RCache.set_Element (s_rain_msaa[i]->E[2]); RCache.set_Stencil ( TRUE, D3DCMP_EQUAL, 0x81, 0x81, 0 ); StateManager.SetSampleMask ( u32(1) << i ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } StateManager.SetSampleMask( 0xffffffff ); } } // TODO: DX10: Check if DX10 has analog for NV DBT // disable depth bounds // u_DBT_disable (); } }
void CRenderTarget::phase_combine () { bool _menu_pp = g_pGamePersistent?g_pGamePersistent->OnRenderPPUI_query():false; u32 Offset = 0; Fvector2 p0,p1; //*** exposure-pipeline u32 gpu_id = Device.dwFrame%2; { t_LUM_src->surface_set (rt_LUM_pool[gpu_id*2+0]->pSurface); t_LUM_dest->surface_set (rt_LUM_pool[gpu_id*2+1]->pSurface); } // low/hi RTs u_setrt ( rt_Generic_0,rt_Generic_1,0,HW.pBaseZB ); RCache.set_CullMode ( CULL_NONE ); RCache.set_Stencil ( FALSE ); BOOL split_the_scene_to_minimize_wait = FALSE; if (ps_r2_ls_flags.test(R2FLAG_EXP_SPLIT_SCENE)) split_the_scene_to_minimize_wait=TRUE; // draw skybox if (1) { RCache.set_ColorWriteEnable (); CHK_DX(HW.pDevice->SetRenderState ( D3DRS_ZENABLE, FALSE )); g_pGamePersistent->Environment().RenderSky (); CHK_DX(HW.pDevice->SetRenderState ( D3DRS_ZENABLE, TRUE )); } // //if (RImplementation.o.bug) { RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); // stencil should be >= 1 if (RImplementation.o.nvstencil) { u_stencil_optimize (FALSE); RCache.set_ColorWriteEnable (); } //} // calc m-blur matrices Fmatrix m_previous, m_current; Fvector2 m_blur_scale; { static Fmatrix m_saved_viewproj; // (new-camera) -> (world) -> (old_viewproj) Fmatrix m_invview; m_invview.invert (Device.mView); m_previous.mul (m_saved_viewproj,m_invview); m_current.set (Device.mProject) ; m_saved_viewproj.set(Device.mFullTransform) ; float scale = ps_r2_mblur/2.f; m_blur_scale.set (scale,-scale).div(12.f); } // Draw full-screen quad textured with our scene image if (!_menu_pp) { // Compute params Fmatrix m_v2w; m_v2w.invert (Device.mView ); CEnvDescriptorMixer& envdesc= g_pGamePersistent->Environment().CurrentEnv ; const float minamb = 0.001f; Fvector4 ambclr = { _max(envdesc.ambient.x*2,minamb), _max(envdesc.ambient.y*2,minamb), _max(envdesc.ambient.z*2,minamb), 0 }; ambclr.mul (ps_r2_sun_lumscale_amb); Fvector4 envclr = { envdesc.sky_color.x*2+EPS, envdesc.sky_color.y*2+EPS, envdesc.sky_color.z*2+EPS, envdesc.weight }; Fvector4 fogclr = { envdesc.fog_color.x, envdesc.fog_color.y, envdesc.fog_color.z, 0 }; envclr.x *= 2*ps_r2_sun_lumscale_hemi; envclr.y *= 2*ps_r2_sun_lumscale_hemi; envclr.z *= 2*ps_r2_sun_lumscale_hemi; Fvector4 sunclr,sundir; // sun-params { light* fuckingsun = (light*)RImplementation.Lights.sun_adapted._get() ; Fvector L_dir,L_clr; float L_spec; L_clr.set (fuckingsun->color.r,fuckingsun->color.g,fuckingsun->color.b); L_spec = u_diffuse2s (L_clr); Device.mView.transform_dir (L_dir,fuckingsun->direction); L_dir.normalize (); sunclr.set (L_clr.x,L_clr.y,L_clr.z,L_spec); sundir.set (L_dir.x,L_dir.y,L_dir.z,0); } // Fill VB float _w = float(Device.dwWidth); float _h = float(Device.dwHeight); p0.set (.5f/_w, .5f/_h); p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); // Fill vertex buffer Fvector4* pv = (Fvector4*) RCache.Vertex.Lock (4,g_combine_VP->vb_stride,Offset); pv->set (hclip(EPS, _w), hclip(_h+EPS, _h), p0.x, p1.y); pv++; pv->set (hclip(EPS, _w), hclip(EPS, _h), p0.x, p0.y); pv++; pv->set (hclip(_w+EPS, _w), hclip(_h+EPS, _h), p1.x, p1.y); pv++; pv->set (hclip(_w+EPS, _w), hclip(EPS, _h), p1.x, p0.y); pv++; RCache.Vertex.Unlock (4,g_combine_VP->vb_stride); // Setup textures IDirect3DBaseTexture9* e0 = _menu_pp?0:envdesc.sky_r_textures_env[0].second->surface_get(); IDirect3DBaseTexture9* e1 = _menu_pp?0:envdesc.sky_r_textures_env[1].second->surface_get(); t_envmap_0->surface_set (e0); _RELEASE(e0); t_envmap_1->surface_set (e1); _RELEASE(e1); // Draw RCache.set_Element (s_combine->E[0] ); RCache.set_Geometry (g_combine_VP ); RCache.set_c ("m_v2w", m_v2w ); RCache.set_c ("L_ambient", ambclr ); RCache.set_c ("Ldynamic_color", sunclr ); RCache.set_c ("Ldynamic_dir", sundir ); RCache.set_c ("env_color", envclr ); RCache.set_c ("fog_color", fogclr ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } // Forward rendering { u_setrt (rt_Generic_0,0,0,HW.pBaseZB); // LDR RT RCache.set_CullMode (CULL_CCW); RCache.set_Stencil (FALSE); RCache.set_ColorWriteEnable (); g_pGamePersistent->Environment().RenderClouds (); RImplementation.render_forward (); if (g_pGamePersistent) g_pGamePersistent->OnRenderPPUI_main() ; // PP-UI } // Perform blooming filter and distortion if needed RCache.set_Stencil (FALSE); phase_bloom ( ); // HDR RT invalidated here // Distortion filter BOOL bDistort = RImplementation.o.distortion_enabled; // This can be modified { if ((0==RImplementation.mapDistort.size()) && !_menu_pp) bDistort= FALSE; if (bDistort) { u_setrt (rt_Generic_1,0,0,HW.pBaseZB); // Now RT is a distortion mask RCache.set_CullMode (CULL_CCW); RCache.set_Stencil (FALSE); RCache.set_ColorWriteEnable (); CHK_DX(HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET, color_rgba(127,127,0,127), 1.0f, 0L)); RImplementation.r_dsgraph_render_distort (); if (g_pGamePersistent) g_pGamePersistent->OnRenderPPUI_PP() ; // PP-UI } } // PP enabled ? BOOL PP_Complex = u_need_PP (); if (_menu_pp) PP_Complex = FALSE; // Combine everything + perform AA if (PP_Complex) u_setrt ( rt_Color,0,0,HW.pBaseZB ); // LDR RT else u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB); //. u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB); RCache.set_CullMode ( CULL_NONE ) ; RCache.set_Stencil ( FALSE ) ; if (1) { // struct v_aa { Fvector4 p; Fvector2 uv0; Fvector2 uv1; Fvector2 uv2; Fvector2 uv3; Fvector2 uv4; Fvector4 uv5; Fvector4 uv6; }; float _w = float(Device.dwWidth); float _h = float(Device.dwHeight); float ddw = 1.f/_w; float ddh = 1.f/_h; p0.set (.5f/_w, .5f/_h); p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); // Fill vertex buffer v_aa* pv = (v_aa*) RCache.Vertex.Lock (4,g_aa_AA->vb_stride,Offset); pv->p.set(EPS, float(_h+EPS), EPS,1.f); pv->uv0.set(p0.x, p1.y);pv->uv1.set(p0.x-ddw,p1.y-ddh);pv->uv2.set(p0.x+ddw,p1.y+ddh);pv->uv3.set(p0.x+ddw,p1.y-ddh);pv->uv4.set(p0.x-ddw,p1.y+ddh);pv->uv5.set(p0.x-ddw,p1.y,p1.y,p0.x+ddw);pv->uv6.set(p0.x,p1.y-ddh,p1.y+ddh,p0.x);pv++; pv->p.set(EPS, EPS, EPS,1.f); pv->uv0.set(p0.x, p0.y);pv->uv1.set(p0.x-ddw,p0.y-ddh);pv->uv2.set(p0.x+ddw,p0.y+ddh);pv->uv3.set(p0.x+ddw,p0.y-ddh);pv->uv4.set(p0.x-ddw,p0.y+ddh);pv->uv5.set(p0.x-ddw,p0.y,p0.y,p0.x+ddw);pv->uv6.set(p0.x,p0.y-ddh,p0.y+ddh,p0.x);pv++; pv->p.set(float(_w+EPS),float(_h+EPS), EPS,1.f); pv->uv0.set(p1.x, p1.y);pv->uv1.set(p1.x-ddw,p1.y-ddh);pv->uv2.set(p1.x+ddw,p1.y+ddh);pv->uv3.set(p1.x+ddw,p1.y-ddh);pv->uv4.set(p1.x-ddw,p1.y+ddh);pv->uv5.set(p1.x-ddw,p1.y,p1.y,p1.x+ddw);pv->uv6.set(p1.x,p1.y-ddh,p1.y+ddh,p1.x);pv++; pv->p.set(float(_w+EPS),EPS, EPS,1.f); pv->uv0.set(p1.x, p0.y);pv->uv1.set(p1.x-ddw,p0.y-ddh);pv->uv2.set(p1.x+ddw,p0.y+ddh);pv->uv3.set(p1.x+ddw,p0.y-ddh);pv->uv4.set(p1.x-ddw,p0.y+ddh);pv->uv5.set(p1.x-ddw,p0.y,p0.y,p1.x+ddw);pv->uv6.set(p1.x,p0.y-ddh,p0.y+ddh,p1.x);pv++; RCache.Vertex.Unlock (4,g_aa_AA->vb_stride); // Draw COLOR if (ps_r2_ls_flags.test(R2FLAG_AA)) RCache.set_Element (s_combine->E[bDistort?3:1]); // look at blender_combine.cpp else RCache.set_Element (s_combine->E[bDistort?4:2]); // look at blender_combine.cpp RCache.set_c ("e_barrier", ps_r2_aa_barier.x, ps_r2_aa_barier.y, ps_r2_aa_barier.z, 0); RCache.set_c ("e_weights", ps_r2_aa_weight.x, ps_r2_aa_weight.y, ps_r2_aa_weight.z, 0); RCache.set_c ("e_kernel", ps_r2_aa_kernel, ps_r2_aa_kernel, ps_r2_aa_kernel, 0); RCache.set_c ("m_current", m_current); RCache.set_c ("m_previous", m_previous); RCache.set_c ("m_blur", m_blur_scale.x,m_blur_scale.y, 0,0); RCache.set_Geometry (g_aa_AA); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } RCache.set_Stencil (FALSE); // if FP16-BLEND !not! supported - draw flares here, overwise they are already in the bloom target /* if (!RImplementation.o.fp16_blend)*/ g_pGamePersistent->Environment().RenderFlares (); // lens-flares // PP-if required if (PP_Complex) { phase_pp (); } // Re-adapt luminance RCache.set_Stencil (FALSE); //*** exposure-pipeline-clear { std::swap (rt_LUM_pool[gpu_id*2+0],rt_LUM_pool[gpu_id*2+1]); t_LUM_src->surface_set (NULL); t_LUM_dest->surface_set (NULL); } #ifdef DEBUG RCache.set_CullMode ( CULL_CCW ); static xr_vector<Fplane> saved_dbg_planes; if (bDebug) saved_dbg_planes= dbg_planes; else dbg_planes = saved_dbg_planes; if (1) for (u32 it=0; it<dbg_planes.size(); it++) { Fplane& P = dbg_planes[it]; Fvector zero ; zero.mul (P.n,P.d); Fvector L_dir,L_up=P.n,L_right; L_dir.set (0,0,1); if (_abs(L_up.dotproduct(L_dir))>.99f) L_dir.set(1,0,0); L_right.crossproduct(L_up,L_dir); L_right.normalize (); L_dir.crossproduct (L_right,L_up); L_dir.normalize (); Fvector p0,p1,p2,p3; float sz = 100.f; p0.mad (zero,L_right,sz).mad (L_dir,sz); p1.mad (zero,L_right,sz).mad (L_dir,-sz); p2.mad (zero,L_right,-sz).mad (L_dir,-sz); p3.mad (zero,L_right,-sz).mad (L_dir,+sz); RCache.dbg_DrawTRI (Fidentity,p0,p1,p2,0xffffffff); RCache.dbg_DrawTRI (Fidentity,p2,p3,p0,0xffffffff); } static xr_vector<dbg_line_t> saved_dbg_lines; if (bDebug) saved_dbg_lines = dbg_lines; else dbg_lines = saved_dbg_lines; if (1) for (u32 it=0; it<dbg_lines.size(); it++) { RCache.dbg_DrawLINE (Fidentity,dbg_lines[it].P0,dbg_lines[it].P1,dbg_lines[it].color); } #endif // ********************* Debug /* if (0) { u32 C = color_rgba (255,255,255,255); float _w = float(Device.dwWidth)/3; float _h = float(Device.dwHeight)/3; // draw light-spheres #ifdef DEBUG if (0) for (u32 it=0; it<dbg_spheres.size(); it++) { Fsphere S = dbg_spheres[it].first; Fmatrix M; u32 ccc = dbg_spheres[it].second.get(); M.scale (S.R,S.R,S.R); M.translate_over (S.P); RCache.dbg_DrawEllipse (M,ccc); RCache.dbg_DrawAABB (S.P,.05f,.05f,.05f,ccc); } #endif // Draw quater-screen quad textured with our direct-shadow-map-image if (1) { u32 IX=0,IY=1; p0.set (.5f/_w, .5f/_h); p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); // Fill vertex buffer FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); pv->set ((IX+0)*_w+EPS, (IY+1)*_h+EPS, EPS, 1.f, C, p0.x, p1.y); pv++; pv->set ((IX+0)*_w+EPS, (IY+0)*_h+EPS, EPS, 1.f, C, p0.x, p0.y); pv++; pv->set ((IX+1)*_w+EPS, (IY+1)*_h+EPS, EPS, 1.f, C, p1.x, p1.y); pv++; pv->set ((IX+1)*_w+EPS, (IY+0)*_h+EPS, EPS, 1.f, C, p1.x, p0.y); pv++; RCache.Vertex.Unlock (4,g_combine->vb_stride); // Draw COLOR RCache.set_Shader (s_combine_dbg_0); RCache.set_Geometry (g_combine); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } // Draw quater-screen quad textured with our accumulator if (0) { u32 IX=1,IY=1; p0.set (.5f/_w, .5f/_h); p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); // Fill vertex buffer FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); pv->set ((IX+0)*_w+EPS, (IY+1)*_h+EPS, EPS, 1.f, C, p0.x, p1.y); pv++; pv->set ((IX+0)*_w+EPS, (IY+0)*_h+EPS, EPS, 1.f, C, p0.x, p0.y); pv++; pv->set ((IX+1)*_w+EPS, (IY+1)*_h+EPS, EPS, 1.f, C, p1.x, p1.y); pv++; pv->set ((IX+1)*_w+EPS, (IY+0)*_h+EPS, EPS, 1.f, C, p1.x, p0.y); pv++; RCache.Vertex.Unlock (4,g_combine->vb_stride); // Draw COLOR RCache.set_Shader (s_combine_dbg_1); RCache.set_Geometry (g_combine); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } } */ #ifdef DEBUG dbg_spheres.clear (); dbg_lines.clear (); dbg_planes.clear (); #endif }