void CRender::Calculate () { #ifdef _GPA_ENABLED TAL_SCOPED_TASK_NAMED( "CRender::Calculate()" ); #endif // _GPA_ENABLED Device.Statistic->RenderCALC.Begin(); // Transfer to global space to avoid deep pointer access IRender_Target* T = getTarget (); float fov_factor = _sqr (90.f / Device.fFOV); g_fSCREEN = float(T->get_width()*T->get_height())*fov_factor*(EPS_S+ps_r__LOD); r_ssaDISCARD = _sqr(ps_r__ssaDISCARD) /g_fSCREEN; r_ssaDONTSORT = _sqr(ps_r__ssaDONTSORT/3) /g_fSCREEN; r_ssaLOD_A = _sqr(ps_r1_ssaLOD_A/3) /g_fSCREEN; r_ssaLOD_B = _sqr(ps_r1_ssaLOD_B/3) /g_fSCREEN; r_ssaGLOD_start = _sqr(ps_r__GLOD_ssa_start/3)/g_fSCREEN; r_ssaGLOD_end = _sqr(ps_r__GLOD_ssa_end/3) /g_fSCREEN; r_ssaHZBvsTEX = _sqr(ps_r__ssaHZBvsTEX/3) /g_fSCREEN; // Frustum & HOM rendering ViewBase.CreateFromMatrix (Device.mFullTransform,FRUSTUM_P_LRTB|FRUSTUM_P_FAR); View = 0; HOM.Enable (); HOM.Render (ViewBase); gm_SetNearer (FALSE); phase = PHASE_NORMAL; // Detect camera-sector if (!vLastCameraPos.similar(Device.vCameraPosition,EPS_S)) { CSector* pSector = (CSector*)detectSector(Device.vCameraPosition); if (pSector && (pSector!=pLastSector)) g_pGamePersistent->OnSectorChanged( translateSector(pSector) ); if (0==pSector) pSector = pLastSector; pLastSector = pSector; vLastCameraPos.set(Device.vCameraPosition); } // Check if camera is too near to some portal - if so force DualRender if (rmPortals) { Fvector box_radius; box_radius.set(EPS_L*2,EPS_L*2,EPS_L*2); Sectors_xrc.box_options (CDB::OPT_FULL_TEST); Sectors_xrc.box_query (rmPortals,Device.vCameraPosition,box_radius); for (int K=0; K<Sectors_xrc.r_count(); K++) { CPortal* pPortal = (CPortal*) Portals[rmPortals->get_tris()[Sectors_xrc.r_begin()[K].id].dummy]; pPortal->bDualRender = TRUE; } } // if (L_DB) L_DB->Update(); // Main process marker ++; if (pLastSector) { // Traverse sector/portal structure PortalTraverser.traverse ( pLastSector, ViewBase, Device.vCameraPosition, Device.mFullTransform, CPortalTraverser::VQ_HOM + CPortalTraverser::VQ_SSA + CPortalTraverser::VQ_FADE ); // Determine visibility for static geometry hierrarhy if (psDeviceFlags.test(rsDrawStatic)) { for (u32 s_it=0; s_it<PortalTraverser.r_sectors.size(); s_it++) { CSector* sector = (CSector*)PortalTraverser.r_sectors[s_it]; dxRender_Visual* root = sector->root(); for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); add_Geometry (root); } } } // Traverse object database if (psDeviceFlags.test(rsDrawDynamic)) { g_SpatialSpace->q_frustum ( lstRenderables, ISpatial_DB::O_ORDERED, STYPE_RENDERABLE + STYPE_LIGHTSOURCE, ViewBase ); // Exact sorting order (front-to-back) std::sort (lstRenderables.begin(),lstRenderables.end(),pred_sp_sort); // Determine visibility for dynamic part of scene set_Object (0); g_hud->Render_First ( ); // R1 shadows g_hud->Render_Last ( ); u32 uID_LTRACK = 0xffffffff; if (phase==PHASE_NORMAL) { uLastLTRACK ++; if (lstRenderables.size()) uID_LTRACK = uLastLTRACK%lstRenderables.size(); // update light-vis for current entity / actor CObject* O = g_pGameLevel->CurrentViewEntity(); if (O) { CROS_impl* R = (CROS_impl*) O->ROS(); if (R) R->update (O); } } for (u32 o_it=0; o_it<lstRenderables.size(); o_it++) { ISpatial* spatial = lstRenderables[o_it]; spatial->spatial_updatesector (); CSector* sector = (CSector*)spatial->spatial.sector ; if (0==sector) continue; // disassociated from S/P structure // Filter only not light spatial if (PortalTraverser.i_marker != sector->r_marker && (spatial->spatial.type & STYPE_RENDERABLE) ) continue; // inactive (untouched) sector if (spatial->spatial.type & STYPE_RENDERABLE) { for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); if (!View->testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R) /*&& (spatial->spatial.type & STYPE_RENDERABLE)*/) continue; // renderable IRenderable* renderable = spatial->dcast_Renderable (); if (0==renderable) { // It may be an glow CGlow* glow = dynamic_cast<CGlow*>(spatial); VERIFY (glow); L_Glows->add (glow); } else { // Occlusiond vis_data& v_orig = renderable->renderable.visual->getVisData(); vis_data v_copy = v_orig; v_copy.box.xform (renderable->renderable.xform); BOOL bVisible = HOM.visible(v_copy); v_orig.accept_frame = v_copy.accept_frame; v_orig.marker = v_copy.marker; v_orig.hom_frame = v_copy.hom_frame; v_orig.hom_tested = v_copy.hom_tested; if (!bVisible) break; // exit loop on frustums // rendering if (o_it==uID_LTRACK && renderable->renderable_ROS()) { // track lighting environment CROS_impl* T = (CROS_impl*)renderable->renderable_ROS(); T->update (renderable); } set_Object (renderable); renderable->renderable_Render (); set_Object (0); //? is it needed at all } break; // exit loop on frustums } } else { if ( ViewBase.testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R) ) { VERIFY (spatial->spatial.type & STYPE_LIGHTSOURCE); // lightsource light* L = (light*) spatial->dcast_Light (); VERIFY (L); if (L->spatial.sector) { vis_data& vis = L->get_homdata ( ); if (HOM.visible(vis)) L_DB->add_light (L); } } } } } // Calculate miscelaneous stuff L_Shadows->calculate (); L_Projector->calculate (); } else { set_Object (0); /* g_pGameLevel->pHUD->Render_First (); g_pGameLevel->pHUD->Render_Last (); // Calculate miscelaneous stuff L_Shadows->calculate (); L_Projector->calculate (); */ } // End calc Device.Statistic->RenderCALC.End (); }
void CROS_impl::update (IRenderable* O) { // clip & verify if (dwFrame==Device.dwFrame) return; dwFrame = Device.dwFrame; if (0==O) return; if (0==O->renderable.visual) return; VERIFY (dynamic_cast<CROS_impl*> (O->renderable_ROS())); float dt = Device.fTimeDelta; CObject* _object = dynamic_cast<CObject*> (O); // select sample, randomize position inside object Fvector position; O->renderable.xform.transform_tiny (position,O->renderable.visual->vis.sphere.P); float radius; radius = O->renderable.visual->vis.sphere.R; position.y += .3f * radius; Fvector direction; direction.random_dir(); //. position.mad(direction,0.25f*radius); //. position.mad(direction,0.025f*radius); // sun-tracing #if RENDER==R_R1 light* sun = (light*)RImplementation.L_DB->sun_adapted._get() ; #else light* sun = (light*)RImplementation.Lights.sun_adapted._get() ; #endif if (MODE & IRender_ObjectSpecific::TRACE_SUN) { if (--result_sun < 0) { result_sun += ::Random.randI(lt_hemisamples/4,lt_hemisamples/2) ; Fvector direction; direction.set (sun->direction).invert().normalize (); sun_value = !(g_pGameLevel->ObjectSpace.RayTest(position,direction,500.f,collide::rqtBoth,&cache_sun,_object))?1.f:0.f; } } // hemi-tracing bool bFirstTime = (0==result_count); if (MODE & IRender_ObjectSpecific::TRACE_HEMI) { for (u32 it=0; it<(u32)ps_r2_dhemi_count; it++) { // five samples per one frame u32 sample = 0 ; if (result_count<lt_hemisamples) { sample=result_count; result_count++; } else { sample=(result_iterator%lt_hemisamples); result_iterator++; } // take sample Fvector direction; direction.set (hdir[sample][0],hdir[sample][1],hdir[sample][2]).normalize (); //. result[sample] = !g_pGameLevel->ObjectSpace.RayTest(position,direction,50.f,collide::rqtBoth,&cache[sample],_object); result[sample] = !g_pGameLevel->ObjectSpace.RayTest(position,direction,50.f,collide::rqtStatic,&cache[sample],_object); // Msg ("%d:-- %s",sample,result[sample]?"true":"false"); } } // hemi & sun: update and smooth // float l_f = dt*lt_smooth; // float l_i = 1.f-l_f; int _pass = 0; for (int it=0; it<result_count; it++) if (result[it]) _pass ++; hemi_value = float (_pass)/float(result_count?result_count:1); hemi_value *= ps_r2_dhemi_scale; if (bFirstTime) hemi_smooth = hemi_value; update_smooth () ; // light-tracing BOOL bTraceLights = MODE & IRender_ObjectSpecific::TRACE_LIGHTS; if ((!O->renderable_ShadowGenerate()) && (!O->renderable_ShadowReceive())) bTraceLights = FALSE; if (bTraceLights) { // Select nearest lights Fvector bb_size = {radius,radius,radius}; g_SpatialSpace->q_box (RImplementation.lstSpatial,0,STYPE_LIGHTSOURCE,position,bb_size); for (u32 o_it=0; o_it<RImplementation.lstSpatial.size(); o_it++) { ISpatial* spatial = RImplementation.lstSpatial[o_it]; light* source = (light*) (spatial->dcast_Light()); VERIFY (source); // sanity check float R = radius+source->range; if (position.distance_to(source->position) < R) add (source); } // Trace visibility lights.clear (); float traceR = radius*.5f; for (s32 id=0; id<s32(track.size()); id++) { // remove untouched lights xr_vector<CROS_impl::Item>::iterator I = track.begin()+id; if (I->frame_touched!=Device.dwFrame) { track.erase(I) ; id-- ; continue ; } // Trace visibility Fvector P,D; float amount = 0; light* xrL = I->source; Fvector& LP = xrL->position; P.mad (position,P.random_dir(),traceR); // Random point inside range // point/spot float f = D.sub(P,LP).magnitude(); if (g_pGameLevel->ObjectSpace.RayTest(LP,D.div(f),f,collide::rqtStatic,&I->cache,_object)) amount -= lt_dec; else amount += lt_inc; I->test += amount * dt; clamp (I->test,-.5f,1.f); I->energy = .9f*I->energy + .1f*I->test; // float E = I->energy * xrL->color.intensity (); if (E > EPS) { // Select light lights.push_back (CROS_impl::Light()) ; CROS_impl::Light& L = lights.back() ; L.source = xrL ; L.color.mul_rgb (xrL->color,I->energy/2) ; L.energy = I->energy/2 ; if (!xrL->flags.bStatic) { L.color.mul_rgb(.5f); L.energy *= .5f; } } } // Sun float E = sun_smooth * sun->color.intensity (); if (E > EPS) { // Select light lights.push_back (CROS_impl::Light()) ; CROS_impl::Light& L = lights.back() ; L.source = sun ; L.color.mul_rgb (sun->color,sun_smooth/2) ; L.energy = sun_smooth ; } // Sort lights by importance - important for R1-shadows std::sort (lights.begin(),lights.end(), pred_energy); } // Process ambient lighting and approximate average lighting // Process our lights to find average luminiscense CEnvDescriptor& desc = g_pGamePersistent->Environment().CurrentEnv; Fvector accum = { desc.ambient.x, desc.ambient.y, desc.ambient.z }; Fvector hemi = { desc.hemi_color.x, desc.hemi_color.y, desc.hemi_color.z }; Fvector sun_ = { desc.sun_color.x, desc.sun_color.y, desc.sun_color.z }; if (MODE & IRender_ObjectSpecific::TRACE_HEMI ) hemi.mul(hemi_smooth); else hemi.mul(.2f); accum.add ( hemi ); if (MODE & IRender_ObjectSpecific::TRACE_SUN ) sun_.mul(sun_smooth); else sun_.mul(.2f); accum.add ( sun_ ); if (MODE & IRender_ObjectSpecific::TRACE_LIGHTS ) { Fvector lacc = { 0,0,0 }; for (u32 lit=0; lit<lights.size(); lit++) { float d = lights[lit].source->position.distance_to(position); float r = lights[lit].source->range; float a = clampr(1.f - d/(r+EPS),0.f,1.f)*(lights[lit].source->flags.bStatic?1.f:2.f); lacc.x += lights[lit].color.r*a; lacc.y += lights[lit].color.g*a; lacc.z += lights[lit].color.b*a; } // lacc.x *= desc.lmap_color.x; // lacc.y *= desc.lmap_color.y; // lacc.z *= desc.lmap_color.z; // Msg ("- rgb[%f,%f,%f]",lacc.x,lacc.y,lacc.z); accum.add (lacc); } else accum.set ( .1f, .1f, .1f ); approximate = accum; }
void dx103DFluidRenderer::CalculateLighting(const dx103DFluidData &FluidData, FogLighting &LightData) { m_lstRenderables.clear_not_free(); LightData.Reset(); const dx103DFluidData::Settings &VolumeSettings = FluidData.GetSettings(); Fvector4 hemi_color = g_pGamePersistent->Environment().CurrentEnv->hemi_color; //hemi_color.mul(0.2f); hemi_color.mul(VolumeSettings.m_fHemi); LightData.m_vLightIntencity.set(hemi_color.x, hemi_color.y, hemi_color.z); LightData.m_vLightIntencity.add(g_pGamePersistent->Environment().CurrentEnv->ambient); const Fmatrix &Transform = FluidData.GetTransform(); Fbox box; box.min = Fvector3().set(-0.5f, -0.5f, -0.5f); box.max = Fvector3().set( 0.5f, 0.5f, 0.5f); box.xform(Transform); Fvector3 center; Fvector3 size; box.getcenter(center); box.getradius(size); // Traverse object database g_SpatialSpace->q_box ( m_lstRenderables, 0, //ISpatial_DB::O_ORDERED, STYPE_LIGHTSOURCE, center, size ); u32 iNumRenderables = m_lstRenderables.size(); // Determine visibility for dynamic part of scene for (u32 i=0; i<iNumRenderables; ++i) { ISpatial* spatial = m_lstRenderables[i]; // Light light* pLight = (light*) spatial->dcast_Light(); VERIFY(pLight); if (pLight->flags.bStatic) continue; float d = pLight->position.distance_to(Transform.c); float R = pLight->range + _max( size.x, _max( size.y, size.z ) ); if ( d >= R ) continue; Fvector3 LightIntencity; LightIntencity.set(pLight->color.r, pLight->color.g, pLight->color.b); //LightIntencity.mul(0.5f); //if (!pLight->flags.bStatic) // LightIntencity.mul(0.5f); float r = pLight->range; float a = clampr(1.f - d/(r+EPS),0.f,1.f)*(pLight->flags.bStatic?1.f:2.f); LightIntencity.mul(a); LightData.m_vLightIntencity.add(LightIntencity); } //LightData.m_vLightIntencity.set( 1.0f, 0.5f, 0.0f); //LightData.m_vLightIntencity.set( 1.0f, 1.0f, 1.0f); }
void CRender::render_main (Fmatrix& m_ViewProjection, bool _fportals) { // Msg ("---begin"); marker ++; // Calculate sector(s) and their objects if (pLastSector) { //!!! //!!! BECAUSE OF PARALLEL HOM RENDERING TRY TO DELAY ACCESS TO HOM AS MUCH AS POSSIBLE //!!! { // Traverse object database g_SpatialSpace->q_frustum ( lstRenderables, ISpatial_DB::O_ORDERED, STYPE_RENDERABLE + STYPE_LIGHTSOURCE, ViewBase ); // (almost) Exact sorting order (front-to-back) std::sort (lstRenderables.begin(),lstRenderables.end(),pred_sp_sort); // Determine visibility for dynamic part of scene set_Object (0); u32 uID_LTRACK = 0xffffffff; if (phase==PHASE_NORMAL) { uLastLTRACK ++; if (lstRenderables.size()) uID_LTRACK = uLastLTRACK%lstRenderables.size(); // update light-vis for current entity / actor CObject* O = g_pGameLevel->CurrentViewEntity(); if (O) { CROS_impl* R = (CROS_impl*) O->ROS(); if (R) R->update (O); } // update light-vis for selected entity // track lighting environment if (lstRenderables.size()) { IRenderable* renderable = lstRenderables[uID_LTRACK]->dcast_Renderable (); if (renderable) { CROS_impl* T = (CROS_impl*)renderable->renderable_ROS (); if (T) T->update (renderable); } } } } // Traverse sector/portal structure PortalTraverser.traverse ( pLastSector, ViewBase, Device.vCameraPosition, m_ViewProjection, CPortalTraverser::VQ_HOM + CPortalTraverser::VQ_SSA + CPortalTraverser::VQ_FADE //. disabled scissoring (HW.Caps.bScissor?CPortalTraverser::VQ_SCISSOR:0) // generate scissoring info ); // Determine visibility for static geometry hierrarhy for (u32 s_it=0; s_it<PortalTraverser.r_sectors.size(); s_it++) { CSector* sector = (CSector*)PortalTraverser.r_sectors[s_it]; IRender_Visual* root = sector->root(); for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); add_Geometry (root); } } // Traverse frustums for (u32 o_it=0; o_it<lstRenderables.size(); o_it++) { ISpatial* spatial = lstRenderables[o_it]; spatial->spatial_updatesector (); CSector* sector = (CSector*)spatial->spatial.sector; if (0==sector) continue; // disassociated from S/P structure if (spatial->spatial.type & STYPE_LIGHTSOURCE) { // lightsource light* L = (light*) (spatial->dcast_Light()); VERIFY (L); float lod = L->get_LOD (); if (lod>EPS_L) { vis_data& vis = L->get_homdata ( ); if (HOM.visible(vis)) Lights.add_light (L); } continue ; } if (PortalTraverser.i_marker != sector->r_marker) continue; // inactive (untouched) sector for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { CFrustum& view = sector->r_frustums[v_it]; if (!view.testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R)) continue; if (spatial->spatial.type & STYPE_RENDERABLE) { // renderable IRenderable* renderable = spatial->dcast_Renderable (); VERIFY (renderable); // Occlusion vis_data& v_orig = renderable->renderable.visual->vis; vis_data v_copy = v_orig; v_copy.box.xform (renderable->renderable.xform); BOOL bVisible = HOM.visible(v_copy); v_orig.marker = v_copy.marker; v_orig.accept_frame = v_copy.accept_frame; v_orig.hom_frame = v_copy.hom_frame; v_orig.hom_tested = v_copy.hom_tested; if (!bVisible) break; // exit loop on frustums // Rendering set_Object (renderable); renderable->renderable_Render (); set_Object (0); } break; // exit loop on frustums } } if (g_pGameLevel && (phase==PHASE_NORMAL)) g_pGameLevel->pHUD->Render_Last(); // HUD } else { set_Object (0); if (g_pGameLevel && (phase==PHASE_NORMAL)) g_pGameLevel->pHUD->Render_Last(); // HUD } }