void CDrawUtilities::DrawEntity(u32 clr, ref_shader s) { // fill VB _VertexStream* Stream = &RCache.Vertex; u32 vBase; FVF::L* pv = (FVF::L*)Stream->Lock(5,vs_L->vb_stride,vBase); pv->set (0.f,0.f,0.f,clr); pv++; pv->set (0.f,1.f,0.f,clr); pv++; pv->set (0.f,1.f,.5f,clr); pv++; pv->set (0.f,.5f,.5f,clr); pv++; pv->set (0.f,.5f,0.f,clr); pv++; Stream->Unlock (5,vs_L->vb_stride); // render flagshtok DU_DRAW_SH (dxRenderDeviceRender::Instance().m_WireShader); DU_DRAW_DP (D3DPT_LINESTRIP,vs_L,vBase,4); if (s) DU_DRAW_SH(s); { // fill VB FVF::LIT* pv = (FVF::LIT*)Stream->Lock(6,vs_LIT->vb_stride,vBase); pv->set (0.f,1.f,0.f,clr,0.f,0.f); pv++; pv->set (0.f,1.f,.5f,clr,1.f,0.f); pv++; pv->set (0.f,.5f,.5f,clr,1.f,1.f); pv++; pv->set (0.f,.5f,0.f,clr,0.f,1.f); pv++; pv->set (0.f,.5f,.5f,clr,1.f,1.f); pv++; pv->set (0.f,1.f,.5f,clr,1.f,0.f); pv++; Stream->Unlock (6,vs_LIT->vb_stride); // and Render it as line list DU_DRAW_DP (D3DPT_TRIANGLEFAN,vs_LIT,vBase,4); } }
void CDrawUtilities::DrawPrimitiveLIT(D3DPRIMITIVETYPE pt, u32 pc, FVF::LIT* vertices, int vc, BOOL bCull, BOOL bCycle) { // fill VB _VertexStream* Stream = &RCache.Vertex; u32 vBase, dwNeed=(bCycle)?vc+1:vc; FVF::LIT* pv = (FVF::LIT*)Stream->Lock(dwNeed,vs_LIT->vb_stride,vBase); for(int k=0; k<vc; k++,pv++) pv->set (vertices[k]); if (bCycle) pv->set(*(pv-vc)); Stream->Unlock(dwNeed,vs_LIT->vb_stride); if (!bCull) DU_DRAW_RS(D3DRS_CULLMODE,D3DCULL_NONE); DU_DRAW_DP (pt,vs_LIT,vBase,pc); if (!bCull) DU_DRAW_RS(D3DRS_CULLMODE,D3DCULL_CCW); }
void CActor::RenderIndicator (Fvector dpos, float r1, float r2, ref_shader IndShader) { if (!g_Alive()) return; u32 dwOffset = 0,dwCount = 0; FVF::LIT* pv_start = (FVF::LIT*)RCache.Vertex.Lock(4,hFriendlyIndicator->vb_stride,dwOffset); FVF::LIT* pv = pv_start; // base rect CBoneInstance& BI = smart_cast<CKinematics*>(Visual())->LL_GetBoneInstance(u16(m_head)); Fmatrix M; smart_cast<CKinematics*>(Visual())->CalculateBones (); M.mul (XFORM(),BI.mTransform); Fvector pos = M.c; pos.add(dpos); const Fvector& T = Device.vCameraTop; const Fvector& R = Device.vCameraRight; Fvector Vr, Vt; Vr.x = R.x*r1; Vr.y = R.y*r1; Vr.z = R.z*r1; Vt.x = T.x*r2; Vt.y = T.y*r2; Vt.z = T.z*r2; Fvector a,b,c,d; a.sub (Vt,Vr); b.add (Vt,Vr); c.invert (a); d.invert (b); pv->set (d.x+pos.x,d.y+pos.y,d.z+pos.z, 0xffffffff, 0.f,1.f); pv++; pv->set (a.x+pos.x,a.y+pos.y,a.z+pos.z, 0xffffffff, 0.f,0.f); pv++; pv->set (c.x+pos.x,c.y+pos.y,c.z+pos.z, 0xffffffff, 1.f,1.f); pv++; pv->set (b.x+pos.x,b.y+pos.y,b.z+pos.z, 0xffffffff, 1.f,0.f); pv++; // render dwCount = u32(pv-pv_start); RCache.Vertex.Unlock (dwCount,hFriendlyIndicator->vb_stride); RCache.set_xform_world (Fidentity); RCache.set_Shader (IndShader); RCache.set_Geometry (hFriendlyIndicator); RCache.Render (D3DPT_TRIANGLESTRIP,dwOffset,0, dwCount, 0, 2); };
void ESceneAIMapTool::OnRender(int priority, bool strictB2F) { if (m_Flags.is(flHideNodes) || !ai_map_shown) return; if (1==priority){ if (false==strictB2F){ RCache.set_xform_world(Fidentity); if (OBJCLASS_AIMAP==LTools->CurrentClassID()){ u32 clr = 0xffffc000; Device.SetShader (Device.m_WireShader); DU_impl.DrawSelectionBox (m_AIBBox,&clr); } if (Valid()){ // render nodes Device.SetShader (m_Shader); Device.SetRS (D3DRS_CULLMODE, D3DCULL_NONE); Irect rect; HashRect (Device.m_Camera.GetPosition(),m_VisRadius,rect); u32 vBase; _VertexStream* Stream= &RCache.Vertex; FVF::LIT* pv = (FVF::LIT*)Stream->Lock(block_size,m_RGeom->vb_stride,vBase); u32 cnt = 0; // Device.Statistic.TEST0.Begin(); // Device.Statistic.TEST2.Begin(); for (int x=rect.x1; x<=rect.x2; x++){ for (int z=rect.y1; z<=rect.y2; z++){ AINodeVec* nodes = HashMap(x,z); if (nodes){ const Fvector DUP={0,1,0}; const float st = (m_Params.fPatchSize*0.9f)*0.5f; for (AINodeIt it=nodes->begin(); it!=nodes->end(); it++){ SAINode& N = **it; Fvector v; v.set(N.Pos.x-st,N.Pos.y,N.Pos.z-st); float p_denom = N.Plane.n.dotproduct(DUP); float b = (_abs(p_denom)<EPS_S)?m_Params.fPatchSize:_abs(N.Plane.classify(v) / p_denom); if (Render->ViewBase.testSphere_dirty(N.Pos,_max(b,st))){ u32 clr; if (N.flags.is(SAINode::flSelected))clr = 0xffffffff; else clr = N.flags.is(SAINode::flHLSelected)?0xff909090:0xff606060; int k = 0; if (N.n1) k |= 1<<0; if (N.n2) k |= 1<<1; if (N.n3) k |= 1<<2; if (N.n4) k |= 1<<3; Fvector v; FVF::LIT v1,v2,v3,v4; float tt = 0.01f; v.set(N.Pos.x-st,N.Pos.y,N.Pos.z-st); N.Plane.intersectRayPoint(v,DUP,v1.p); v1.p.mad(v1.p,N.Plane.n,tt); v1.t.set(node_tc[k][0]); v1.color=clr; // minX,minZ v.set(N.Pos.x+st,N.Pos.y,N.Pos.z-st); N.Plane.intersectRayPoint(v,DUP,v2.p); v2.p.mad(v2.p,N.Plane.n,tt); v2.t.set(node_tc[k][1]); v2.color=clr; // maxX,minZ v.set(N.Pos.x+st,N.Pos.y,N.Pos.z+st); N.Plane.intersectRayPoint(v,DUP,v3.p); v3.p.mad(v3.p,N.Plane.n,tt); v3.t.set(node_tc[k][2]); v3.color=clr; // maxX,maxZ v.set(N.Pos.x-st,N.Pos.y,N.Pos.z+st); N.Plane.intersectRayPoint(v,DUP,v4.p); v4.p.mad(v4.p,N.Plane.n,tt); v4.t.set(node_tc[k][3]); v4.color=clr; // minX,maxZ pv->set(v3); pv++; pv->set(v2); pv++; pv->set(v1); pv++; pv->set(v1); pv++; pv->set(v4); pv++; pv->set(v3); pv++; cnt+=6; if (cnt>=block_size-6){ Stream->Unlock (cnt,m_RGeom->vb_stride); Device.DP (D3DPT_TRIANGLELIST,m_RGeom,vBase,cnt/3); pv = (FVF::LIT*)Stream->Lock(block_size,m_RGeom->vb_stride,vBase); cnt = 0; } } } } } } // Device.Statistic.TEST2.End(); // Device.Statistic.TEST0.End(); Stream->Unlock (cnt,m_RGeom->vb_stride); if (cnt) Device.DP (D3DPT_TRIANGLELIST,m_RGeom,vBase,cnt/3); Device.SetRS (D3DRS_CULLMODE, D3DCULL_CCW); } }else{ /* // render snap if (m_Flags.is(flDrawSnapObjects)) for(ObjectIt _F=m_SnapObjects.begin();_F!=m_SnapObjects.end();_F++) if((*_F)->Visible()) ((CSceneObject*)(*_F))->RenderSelection(0x4046B646); */ } } }
void dxThunderboltRender::Render(CEffect_Thunderbolt &owner) { VERIFY (owner.current); // lightning model float dv = owner.lightning_phase*0.5f; dv = (owner.lightning_phase>0.5f)?Random.randI(2)*0.5f:dv; RCache.set_CullMode (CULL_NONE); u32 v_offset,i_offset; dxThunderboltDescRender *pThRen = (dxThunderboltDescRender*)&*owner.current->m_pRender; u32 vCount_Lock = pThRen->l_model->number_vertices; u32 iCount_Lock = pThRen->l_model->number_indices; IRender_DetailModel::fvfVertexOut* v_ptr= (IRender_DetailModel::fvfVertexOut*) RCache.Vertex.Lock (vCount_Lock, hGeom_model->vb_stride, v_offset); u16* i_ptr = RCache.Index.Lock (iCount_Lock, i_offset); // XForm verts pThRen->l_model->transfer(owner.current_xform,v_ptr,0xffffffff,i_ptr,0,0.f,dv); // Flush if needed RCache.Vertex.Unlock(vCount_Lock,hGeom_model->vb_stride); RCache.Index.Unlock (iCount_Lock); RCache.set_xform_world(Fidentity); RCache.set_Shader (pThRen->l_model->shader); RCache.set_Geometry (hGeom_model); RCache.Render (D3DPT_TRIANGLELIST,v_offset,0,vCount_Lock,i_offset,iCount_Lock/3); RCache.set_CullMode (CULL_CCW); // gradient Fvector vecSx, vecSy; u32 VS_Offset; FVF::LIT *pv = (FVF::LIT*) RCache.Vertex.Lock(8,hGeom_gradient.stride(),VS_Offset); // top { u32 c_val = iFloor(owner.current->m_GradientTop->fOpacity*owner.lightning_phase*255.f); u32 c = color_rgba(c_val,c_val,c_val,c_val); vecSx.mul (Device.vCameraRight, owner.current->m_GradientTop->fRadius.x*owner.lightning_size); vecSy.mul (Device.vCameraTop, -owner.current->m_GradientTop->fRadius.y*owner.lightning_size); pv->set (owner.current_xform.c.x+vecSx.x-vecSy.x, owner.current_xform.c.y+vecSx.y-vecSy.y, owner.current_xform.c.z+vecSx.z-vecSy.z, c, 0, 0); pv++; pv->set (owner.current_xform.c.x+vecSx.x+vecSy.x, owner.current_xform.c.y+vecSx.y+vecSy.y, owner.current_xform.c.z+vecSx.z+vecSy.z, c, 0, 1); pv++; pv->set (owner.current_xform.c.x-vecSx.x-vecSy.x, owner.current_xform.c.y-vecSx.y-vecSy.y, owner.current_xform.c.z-vecSx.z-vecSy.z, c, 1, 0); pv++; pv->set (owner.current_xform.c.x-vecSx.x+vecSy.x, owner.current_xform.c.y-vecSx.y+vecSy.y, owner.current_xform.c.z-vecSx.z+vecSy.z, c, 1, 1); pv++; } // center { u32 c_val = iFloor(owner.current->m_GradientTop->fOpacity*owner.lightning_phase*255.f); u32 c = color_rgba(c_val,c_val,c_val,c_val); vecSx.mul (Device.vCameraRight, owner.current->m_GradientCenter->fRadius.x*owner.lightning_size); vecSy.mul (Device.vCameraTop, -owner.current->m_GradientCenter->fRadius.y*owner.lightning_size); pv->set (owner.lightning_center.x+vecSx.x-vecSy.x, owner.lightning_center.y+vecSx.y-vecSy.y, owner.lightning_center.z+vecSx.z-vecSy.z, c, 0, 0); pv++; pv->set (owner.lightning_center.x+vecSx.x+vecSy.x, owner.lightning_center.y+vecSx.y+vecSy.y, owner.lightning_center.z+vecSx.z+vecSy.z, c, 0, 1); pv++; pv->set (owner.lightning_center.x-vecSx.x-vecSy.x, owner.lightning_center.y-vecSx.y-vecSy.y, owner.lightning_center.z-vecSx.z-vecSy.z, c, 1, 0); pv++; pv->set (owner.lightning_center.x-vecSx.x+vecSy.x, owner.lightning_center.y-vecSx.y+vecSy.y, owner.lightning_center.z-vecSx.z+vecSy.z, c, 1, 1); pv++; } RCache.Vertex.Unlock (8,hGeom_gradient.stride()); RCache.set_xform_world (Fidentity); RCache.set_Geometry (hGeom_gradient); RCache.set_Shader (((dxFlareRender*)&*owner.current->m_GradientTop->m_pFlare)->hShader); #ifdef USE_DX10 // Hack. Since lightning gradient uses sun shader override z write settings manually RCache.set_Z(TRUE); RCache.set_ZFunc(D3DCMP_LESSEQUAL); #endif // USE_DX10 #ifdef USE_DX10 // Hack. Since lightning gradient uses sun shader override z write settings manually RCache.set_Z(TRUE); RCache.set_ZFunc(D3DCMP_LESSEQUAL); #endif // USE_DX10 RCache.Render (D3DPT_TRIANGLELIST,VS_Offset, 0,4,0,2); RCache.set_Shader (((dxFlareRender*)&*owner.current->m_GradientCenter->m_pFlare)->hShader); #ifdef USE_DX10 // Hack. Since lightning gradient uses sun shader override z write settings manually RCache.set_Z(TRUE); RCache.set_ZFunc(D3DCMP_LESSEQUAL); #endif // USE_DX10 #ifdef USE_DX10 // Hack. Since lightning gradient uses sun shader override z write settings manually RCache.set_Z(TRUE); RCache.set_ZFunc(D3DCMP_LESSEQUAL); #endif // USE_DX10 RCache.Render (D3DPT_TRIANGLELIST,VS_Offset+4, 0,4,0,2); }
void CLensFlare::Render(BOOL bSun, BOOL bFlares, BOOL bGradient) { if (!bRender) return; if(!m_Current) return; VERIFY (m_Current); Fcolor dwLight; Fcolor color; Fvector vec, vecSx, vecSy; Fvector vecDx, vecDy; dwLight.set ( LightColor ); svector<ref_shader,MAX_Flares> _2render; u32 VS_Offset; FVF::LIT *pv = (FVF::LIT*) RCache.Vertex.Lock(MAX_Flares*4,hGeom.stride(),VS_Offset); float fDistance = FAR_DIST*0.75f; if (bSun){ if (m_Current->m_Flags.is(CLensFlareDescriptor::flSource)){ vecSx.mul (vecX, m_Current->m_Source.fRadius*fDistance); vecSy.mul (vecY, m_Current->m_Source.fRadius*fDistance); if (m_Current->m_Source.ignore_color) color.set(1.f,1.f,1.f,1.f); else color.set(dwLight); color.a *= m_StateBlend; u32 c = color.get(); pv->set (vecLight.x+vecSx.x-vecSy.x, vecLight.y+vecSx.y-vecSy.y, vecLight.z+vecSx.z-vecSy.z, c, 0, 0); pv++; pv->set (vecLight.x+vecSx.x+vecSy.x, vecLight.y+vecSx.y+vecSy.y, vecLight.z+vecSx.z+vecSy.z, c, 0, 1); pv++; pv->set (vecLight.x-vecSx.x-vecSy.x, vecLight.y-vecSx.y-vecSy.y, vecLight.z-vecSx.z-vecSy.z, c, 1, 0); pv++; pv->set (vecLight.x-vecSx.x+vecSy.x, vecLight.y-vecSx.y+vecSy.y, vecLight.z-vecSx.z+vecSy.z, c, 1, 1); pv++; _2render.push_back (m_Current->m_Source.hShader); } } if (fBlend>=EPS_L) { if(bFlares){ vecDx.normalize (vecAxis); vecDy.crossproduct (vecDx, vecDir); if (m_Current->m_Flags.is(CLensFlareDescriptor::flFlare)){ for (CLensFlareDescriptor::FlareIt it=m_Current->m_Flares.begin(); it!=m_Current->m_Flares.end(); it++){ CLensFlareDescriptor::SFlare& F = *it; vec.mul (vecAxis, F.fPosition); vec.add (vecCenter); vecSx.mul (vecDx, F.fRadius*fDistance); vecSy.mul (vecDy, F.fRadius*fDistance); float cl = F.fOpacity * fBlend * m_StateBlend; color.set ( dwLight ); color.mul_rgba ( cl ); u32 c = color.get(); pv->set (vec.x+vecSx.x-vecSy.x, vec.y+vecSx.y-vecSy.y, vec.z+vecSx.z-vecSy.z, c, 0, 0); pv++; pv->set (vec.x+vecSx.x+vecSy.x, vec.y+vecSx.y+vecSy.y, vec.z+vecSx.z+vecSy.z, c, 0, 1); pv++; pv->set (vec.x-vecSx.x-vecSy.x, vec.y-vecSx.y-vecSy.y, vec.z-vecSx.z-vecSy.z, c, 1, 0); pv++; pv->set (vec.x-vecSx.x+vecSy.x, vec.y-vecSx.y+vecSy.y, vec.z-vecSx.z+vecSy.z, c, 1, 1); pv++; _2render.push_back (it->hShader); } } } // gradient if (bGradient&&(fGradientValue>=EPS_L)){ if (m_Current->m_Flags.is(CLensFlareDescriptor::flGradient)){ vecSx.mul (vecX, m_Current->m_Gradient.fRadius*fGradientValue*fDistance); vecSy.mul (vecY, m_Current->m_Gradient.fRadius*fGradientValue*fDistance); color.set ( dwLight ); color.mul_rgba ( fGradientValue*m_StateBlend ); u32 c = color.get (); pv->set (vecLight.x+vecSx.x-vecSy.x, vecLight.y+vecSx.y-vecSy.y, vecLight.z+vecSx.z-vecSy.z, c, 0, 0); pv++; pv->set (vecLight.x+vecSx.x+vecSy.x, vecLight.y+vecSx.y+vecSy.y, vecLight.z+vecSx.z+vecSy.z, c, 0, 1); pv++; pv->set (vecLight.x-vecSx.x-vecSy.x, vecLight.y-vecSx.y-vecSy.y, vecLight.z-vecSx.z-vecSy.z, c, 1, 0); pv++; pv->set (vecLight.x-vecSx.x+vecSy.x, vecLight.y-vecSx.y+vecSy.y, vecLight.z-vecSx.z+vecSy.z, c, 1, 1); pv++; _2render.push_back (m_Current->m_Gradient.hShader); } } } RCache.Vertex.Unlock (_2render.size()*4,hGeom.stride()); RCache.set_xform_world (Fidentity); RCache.set_Geometry (hGeom); for (u32 i=0; i<_2render.size(); i++) { if (_2render[i]) { u32 vBase = i*4+VS_Offset; RCache.set_Shader (_2render[i]); RCache.Render (D3DPT_TRIANGLELIST,vBase, 0,4,0,2); } } }
void CLightShadows::render () { // Gain access to collision-DB CDB::MODEL* DB = g_pGameLevel->ObjectSpace.GetStaticModel(); CDB::TRI* TRIS = DB->get_tris(); Fvector* VERTS = DB->get_verts(); int slot_line = S_rt_size/S_size; // Projection and xform float _43 = Device.mProject._43; Device.mProject._43 -= 0.002f; RCache.set_xform_world (Fidentity); RCache.set_xform_project (Device.mProject); Fvector View = Device.vCameraPosition; // Render shadows RCache.set_Shader (sh_World); RCache.set_Geometry (geom_World); int batch = 0; u32 Offset = 0; FVF::LIT* pv = (FVF::LIT*) RCache.Vertex.Lock (batch_size*3,geom_World->vb_stride,Offset); for (u32 s_it=0; s_it<shadows.size(); s_it++) { Device.Statistic->RenderDUMP_Srender.Begin (); shadow& S = shadows[s_it]; float Le = S.L->color.intensity()*S.E; int s_x = S.slot%slot_line; int s_y = S.slot/slot_line; Fvector2 t_scale, t_offset; t_scale.set (float(S_size)/float(S_rt_size),float(S_size)/float(S_rt_size)); t_scale.mul (.5f); t_offset.set(float(s_x)/float(slot_line),float(s_y)/float(slot_line)); t_offset.x += .5f/S_rt_size; t_offset.y += .5f/S_rt_size; // Search the cache cache_item* CI = 0; BOOL bValid = FALSE; cache_item CI_what; CI_what.O = S.O; CI_what.L = S.L; CI_what.tris=0; xr_vector<cache_item>::iterator CI_ptr = std::lower_bound(cache.begin(),cache.end(),CI_what,cache_search); if (CI_ptr==cache.end()) { // empty ? CI_ptr = cache.insert (CI_ptr,CI_what); CI = &*CI_ptr; bValid = FALSE; } else { if (CI_ptr->O != CI_what.O || CI_ptr->L != CI_what.L) { // we found something different CI_ptr = cache.insert (CI_ptr,CI_what); CI = &*CI_ptr; bValid = FALSE; } else { // Everything, OK. Check if info is still relevant... CI = &*CI_ptr; bValid = TRUE; if (!CI->Op.similar(CI->O->renderable.xform.c)) bValid = FALSE; else if (!CI->Lp.similar(CI->L->position)) bValid = FALSE; } } CI->time = Device.dwTimeGlobal; // acess time if (!bValid) { // Frustum CFrustum F; F.CreateFromMatrix (S.M,FRUSTUM_P_ALL); // Query xrc.frustum_options (0); xrc.frustum_query (DB,F); if (0==xrc.r_count()) continue; // Clip polys by frustum tess.clear (); for (CDB::RESULT* p = xrc.r_begin(); p!=xrc.r_end(); p++) { VERIFY((p->id>=0)&&(p->id<DB->get_tris_count())); // CDB::TRI& t = TRIS[p->id]; if (t.suppress_shadows) continue; sPoly A,B; A.push_back (VERTS[t.verts[0]]); A.push_back (VERTS[t.verts[1]]); A.push_back (VERTS[t.verts[2]]); // Calc plane, throw away degenerate tris and invisible to light polygons Fplane P; float mag = 0; Fvector t1,t2,n; t1.sub (A[0],A[1]); t2.sub (A[0],A[2]); n.crossproduct (t1,t2); mag = n.square_magnitude(); if (mag<EPS_S) continue; n.mul (1.f/_sqrt(mag)); P.build_unit_normal (A[0],n); float DOT_Fade = P.classify(S.L->position); if (DOT_Fade<0) continue; // Clip polygon sPoly* clip = F.ClipPoly (A,B); if (0==clip) continue; // Triangulate poly for (u32 v=2; v<clip->size(); v++) { tess.push_back (tess_tri()); tess_tri& T = tess.back(); T.v[0] = (*clip)[0]; T.v[1] = (*clip)[v-1]; T.v[2] = (*clip)[v]; T.N = P.n; } } // Remember params which builded cache item CI->O = S.O; CI->Op = CI->O->renderable.xform.c; CI->L = S.L; CI->Lp = CI->L->position; CI->tcnt = tess.size(); //Msg ("---free--- %x",u32(CI->tris)); xr_free (CI->tris); VERIFY(0==CI->tris); if (tess.size()) { CI->tris = xr_alloc<tess_tri>(CI->tcnt); //Msg ("---alloc--- %x",u32(CI->tris)); CopyMemory (CI->tris,&*tess.begin(),CI->tcnt * sizeof(tess_tri)); } } // Fill VB for (u32 tid=0; tid<CI->tcnt; tid++) { tess_tri& TT = CI->tris[tid]; Fvector* v = TT.v; Fvector T; Fplane ttp; ttp.build_unit_normal(v[0],TT.N); if (ttp.classify(View)<0) continue; int c0 = PLC_calc(v[0],TT.N,S.L,Le,S.C); int c1 = PLC_calc(v[1],TT.N,S.L,Le,S.C); int c2 = PLC_calc(v[2],TT.N,S.L,Le,S.C); if (c0>S_clip && c1>S_clip && c2>S_clip) continue; clamp (c0,S_ambient,255); clamp (c1,S_ambient,255); clamp (c2,S_ambient,255); S.M.transform(T,v[0]); pv->set(v[0],CLS(c0),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++; S.M.transform(T,v[1]); pv->set(v[1],CLS(c1),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++; S.M.transform(T,v[2]); pv->set(v[2],CLS(c2),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++; batch++; if (batch==batch_size) { // Flush RCache.Vertex.Unlock (batch*3,geom_World->vb_stride); RCache.Render (D3DPT_TRIANGLELIST,Offset,batch); pv = (FVF::LIT*) RCache.Vertex.Lock(batch_size*3,geom_World->vb_stride,Offset); batch = 0; } } Device.Statistic->RenderDUMP_Srender.End (); } // Flush if nessesary RCache.Vertex.Unlock (batch*3,geom_World->vb_stride); if (batch) { RCache.Render (D3DPT_TRIANGLELIST,Offset,batch); } // Clear all shadows and free old entries in the cache shadows.clear (); for (int cit=0; cit<int(cache.size()); cit++) { cache_item& ci = cache[cit]; u32 time = Device.dwTimeGlobal - ci.time; if (time > cache_old) { //Msg ("---free--- %x",u32(ci.tris)); xr_free (ci.tris); VERIFY(0==ci.tris); cache.erase (cache.begin()+cit); cit --; } } // Projection Device.mProject._43 = _43; RCache.set_xform_project (Device.mProject); }