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 }
void CRenderTarget::accum_direct (u32 sub_phase) { // Choose normal code-path or filtered phase_accumulator (); if (RImplementation.o.sunfilter) { accum_direct_f (sub_phase); return ; } // *** 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) //. { // 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 { phase_accumulator () ; 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 FPU::m64r (); Fmatrix xf_invview; xf_invview.invert (Device.mView) ; // shadow xform Fmatrix m_shadow; { 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) && (RImplementation.o.HW_smap) ) { 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 (); } // clouds xform Fmatrix m_clouds_shadow; { static float w_shift = 0; Fmatrix m_xform; Fvector direction = fuckingsun->direction ; float w_dir = g_pGamePersistent->Environment().CurrentEnv.wind_direction ; //float w_speed = g_pGamePersistent->Environment().CurrentEnv.wind_velocity ; Fvector normal ; normal.setHP(w_dir,0); w_shift += 0.003f*Device.fTimeDelta; Fvector position; position.set(0,0,0); m_xform.build_camera_dir (position,direction,normal) ; 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_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 (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 ); RCache.set_c ("m_sunmask", m_clouds_shadow ); // nv-DBT if (RImplementation.o.nvdbt && ps_r2_ls_flags.test(R2FLAG_USE_NVDBT)) { 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 ; // enable cheat HW.pDevice->SetRenderState(D3DRS_ADAPTIVETESS_X,MAKEFOURCC('N','V','D','B')); HW.pDevice->SetRenderState(D3DRS_ADAPTIVETESS_Z,*(DWORD*)&zMin); HW.pDevice->SetRenderState(D3DRS_ADAPTIVETESS_W,*(DWORD*)&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 ); } // disable depth bounds if (RImplementation.o.nvdbt && ps_r2_ls_flags.test(R2FLAG_USE_NVDBT)) HW.pDevice->SetRenderState(D3DRS_ADAPTIVETESS_X,0); } }
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); } }
void CRenderTarget::accum_direct_lum () { // Select target phase_accumulator (); // *** 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 (); // 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 RCache.set_CullMode (CULL_NONE ); RCache.set_ColorWriteEnable (); // 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); struct v_aa { Fvector4 p; Fvector2 uv0; Fvector2 uvJ; Fvector2 uv1; Fvector2 uv2; Fvector2 uv3; Fvector4 uv4; Fvector4 uv5; }; float smooth = 0.6f; float ddw = smooth/_w; float ddh = smooth/_h; // Fill vertex buffer VERIFY (sizeof(v_aa)==g_aa_AA->vb_stride); 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->uvJ.set(j0.x, j1.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,0,0);pv->uv5.set(0,0,0,0);pv++; pv->p.set(EPS, EPS, EPS,1.f); pv->uv0.set(p0.x, p0.y);pv->uvJ.set(j0.x, j0.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,0,0);pv->uv5.set(0,0,0,0);pv++; pv->p.set(float(_w+EPS),float(_h+EPS), EPS,1.f); pv->uv0.set(p1.x, p1.y);pv->uvJ.set(j1.x, j1.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,0,0);pv->uv5.set(0,0,0,0);pv++; pv->p.set(float(_w+EPS),EPS, EPS,1.f); pv->uv0.set(p1.x, p0.y);pv->uvJ.set(j1.x, j0.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,0,0);pv->uv5.set(0,0,0,0);pv++; RCache.Vertex.Unlock (4,g_aa_AA->vb_stride); RCache.set_Geometry (g_aa_AA); // setup RCache.set_Element (s_accum_direct->E[SE_SUN_LUMINANCE]); 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 ); // setup stencil RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); }
void CRender::Render () { g_r = 1; VERIFY (0==mapDistort.size()); bool _menu_pp = g_pGamePersistent?g_pGamePersistent->OnRenderPPUI_query():false; if (_menu_pp) { render_menu () ; return ; }; if( !(g_pGameLevel && g_pGameLevel->pHUD) ) return; //. VERIFY (g_pGameLevel && g_pGameLevel->pHUD); // Configure RImplementation.o.distortion = FALSE; // disable distorion Fcolor sun_color = ((light*)Lights.sun_adapted._get())->color; BOOL bSUN = ps_r2_ls_flags.test(R2FLAG_SUN) && (u_diffuse2s(sun_color.r,sun_color.g,sun_color.b)>EPS); if (o.sunstatic) bSUN = FALSE; // Msg ("sstatic: %s, sun: %s",o.sunstatic?"true":"false", bSUN?"true":"false"); // HOM ViewBase.CreateFromMatrix (Device.mFullTransform, FRUSTUM_P_LRTB + FRUSTUM_P_FAR); View = 0; if (!ps_r2_ls_flags.test(R2FLAG_EXP_MT_CALC)) { HOM.Enable (); HOM.Render (ViewBase); } //******* Z-prefill calc - DEFERRER RENDERER if (ps_r2_ls_flags.test(R2FLAG_ZFILL)) { Device.Statistic->RenderCALC.Begin (); float z_distance = ps_r2_zfill ; Fmatrix m_zfill, m_project ; m_project.build_projection ( deg2rad(Device.fFOV/* *Device.fASPECT*/), Device.fASPECT, VIEWPORT_NEAR, z_distance * g_pGamePersistent->Environment().CurrentEnv.far_plane); m_zfill.mul (m_project,Device.mView); r_pmask (true,false); // enable priority "0" set_Recorder (NULL) ; phase = PHASE_SMAP; render_main (m_zfill,false) ; r_pmask (true,false); // disable priority "1" Device.Statistic->RenderCALC.End ( ) ; // flush Target->phase_scene_prepare (); RCache.set_ColorWriteEnable (FALSE); r_dsgraph_render_graph (0); RCache.set_ColorWriteEnable ( ); } else { Target->phase_scene_prepare (); } //******* // Sync point Device.Statistic->RenderDUMP_Wait_S.Begin (); if (1) { CTimer T; T.Start (); BOOL result = FALSE; HRESULT hr = S_FALSE; while ((hr=q_sync_point[q_sync_count]->GetData (&result,sizeof(result),D3DGETDATA_FLUSH))==S_FALSE) { if (!SwitchToThread()) Sleep(ps_r2_wait_sleep); if (T.GetElapsed_ms() > 500) { result = FALSE; break; } } } Device.Statistic->RenderDUMP_Wait_S.End (); q_sync_count = (q_sync_count+1)%2; CHK_DX (q_sync_point[q_sync_count]->Issue(D3DISSUE_END)); //******* Main calc - DEFERRER RENDERER // Main calc Device.Statistic->RenderCALC.Begin (); r_pmask (true,false,true); // enable priority "0",+ capture wmarks if (bSUN) set_Recorder (&main_coarse_structure); else set_Recorder (NULL); phase = PHASE_NORMAL; render_main (Device.mFullTransform,true); set_Recorder (NULL); r_pmask (true,false); // disable priority "1" Device.Statistic->RenderCALC.End (); 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; //******* Main render :: PART-0 -- first if (!split_the_scene_to_minimize_wait) { // level, DO NOT SPLIT Target->phase_scene_begin (); r_dsgraph_render_hud (); r_dsgraph_render_graph (0); r_dsgraph_render_lods (true,true); if(Details) Details->Render (); Target->phase_scene_end (); } else { // level, SPLIT Target->phase_scene_begin (); r_dsgraph_render_graph (0); Target->disable_aniso (); } //******* Occlusion testing of volume-limited light-sources Target->phase_occq (); LP_normal.clear (); LP_pending.clear (); { // perform tests u32 count = 0; light_Package& LP = Lights.package; // stats stats.l_shadowed = LP.v_shadowed.size(); stats.l_unshadowed = LP.v_point.size() + LP.v_spot.size(); stats.l_total = stats.l_shadowed + stats.l_unshadowed; // perform tests count = _max (count,LP.v_point.size()); count = _max (count,LP.v_spot.size()); count = _max (count,LP.v_shadowed.size()); for (u32 it=0; it<count; it++) { if (it<LP.v_point.size()) { light* L = LP.v_point [it]; L->vis_prepare (); if (L->vis.pending) LP_pending.v_point.push_back (L); else LP_normal.v_point.push_back (L); } if (it<LP.v_spot.size()) { light* L = LP.v_spot [it]; L->vis_prepare (); if (L->vis.pending) LP_pending.v_spot.push_back (L); else LP_normal.v_spot.push_back (L); } if (it<LP.v_shadowed.size()) { light* L = LP.v_shadowed [it]; L->vis_prepare (); if (L->vis.pending) LP_pending.v_shadowed.push_back (L); else LP_normal.v_shadowed.push_back (L); } } } LP_normal.sort (); LP_pending.sort (); //******* Main render :: PART-1 (second) if (split_the_scene_to_minimize_wait) { // skybox can be drawn here if (0) { Target->u_setrt ( Target->rt_Generic_0, Target->rt_Generic_1,0,HW.pBaseZB ); RCache.set_CullMode ( CULL_NONE ); RCache.set_Stencil ( FALSE ); // draw skybox RCache.set_ColorWriteEnable (); CHK_DX(HW.pDevice->SetRenderState ( D3DRS_ZENABLE, FALSE )); g_pGamePersistent->Environment().RenderSky (); CHK_DX(HW.pDevice->SetRenderState ( D3DRS_ZENABLE, TRUE )); } // level Target->phase_scene_begin (); r_dsgraph_render_hud (); r_dsgraph_render_lods (true,true); if(Details) Details->Render (); Target->phase_scene_end (); } // Wall marks if(Wallmarks) { Target->phase_wallmarks (); if (!ps_common_flags.test(RFLAG_BLOODMARKS)) g_r = 0; Wallmarks->Render (); // wallmarks has priority as normal geometry } // Update incremental shadowmap-visibility solver { u32 it=0; for (it=0; it<Lights_LastFrame.size(); it++) { if (0==Lights_LastFrame[it]) continue ; try { Lights_LastFrame[it]->svis.flushoccq() ; } catch (...) { Msg ("! Failed to flush-OCCq on light [%d] %X",it,*(u32*)(&Lights_LastFrame[it])); } } Lights_LastFrame.clear (); } // Directional light - f*****g sun if (bSUN) { RImplementation.stats.l_visible ++; render_sun_near (); render_sun (); render_sun_filtered (); Target->accum_direct_blend (); } // Lighting, non dependant on OCCQ Target->phase_accumulator (); HOM.Disable (); render_lights (LP_normal); // Lighting, dependant on OCCQ render_lights (LP_pending); // Postprocess Target->phase_combine (); VERIFY (0==mapDistort.size()); }