/* * RB_LoadCameraMatrix */ void RB_LoadCameraMatrix( const mat4_t m ) { Matrix4_Copy( m, rb.cameraMatrix ); }
/* * RB_FlushDynamicMeshes */ void RB_FlushDynamicMeshes( void ) { int i, numDraws = rb.numDynamicDraws; rbDynamicStream_t *stream; rbDynamicDraw_t *draw; int sx, sy, sw, sh; float offsetx = 0.0f, offsety = 0.0f, transx, transy; mat4_t m; if( !numDraws ) { return; } for( i = 0; i < RB_VBO_NUM_STREAMS; i++ ) { stream = &rb.dynamicStreams[i]; // R_UploadVBO* are going to rebind buffer arrays for upload // so update our local VBO state cache by calling RB_BindVBO RB_BindVBO( -i - 1, GL_TRIANGLES ); // dummy value for primitive here // because of firstVert, upload elems first if( stream->drawElements.numElems ) { mesh_t elemMesh; memset( &elemMesh, 0, sizeof( elemMesh ) ); elemMesh.elems = dynamicStreamElems[i] + stream->drawElements.firstElem; elemMesh.numElems = stream->drawElements.numElems; R_UploadVBOElemData( stream->vbo, 0, stream->drawElements.firstElem, &elemMesh ); stream->drawElements.firstElem += stream->drawElements.numElems; stream->drawElements.numElems = 0; } if( stream->drawElements.numVerts ) { R_UploadVBOVertexRawData( stream->vbo, stream->drawElements.firstVert, stream->drawElements.numVerts, stream->vertexData + stream->drawElements.firstVert * stream->vbo->vertexSize ); stream->drawElements.firstVert += stream->drawElements.numVerts; stream->drawElements.numVerts = 0; } } RB_GetScissor( &sx, &sy, &sw, &sh ); Matrix4_Copy( rb.objectMatrix, m ); transx = m[12]; transy = m[13]; for( i = 0, draw = rb.dynamicDraws; i < numDraws; i++, draw++ ) { RB_BindShader( draw->entity, draw->shader, draw->fog ); RB_BindVBO( draw->streamId, draw->primitive ); RB_SetPortalSurface( draw->portalSurface ); RB_SetShadowBits( draw->shadowBits ); RB_Scissor( draw->scissor[0], draw->scissor[1], draw->scissor[2], draw->scissor[3] ); // translate the mesh in 2D if( ( offsetx != draw->offset[0] ) || ( offsety != draw->offset[1] ) ) { offsetx = draw->offset[0]; offsety = draw->offset[1]; m[12] = transx + offsetx; m[13] = transy + offsety; RB_LoadObjectMatrix( m ); } RB_DrawElements( draw->drawElements.firstVert, draw->drawElements.numVerts, draw->drawElements.firstElem, draw->drawElements.numElems, draw->drawElements.firstVert, draw->drawElements.numVerts, draw->drawElements.firstElem, draw->drawElements.numElems ); } rb.numDynamicDraws = 0; RB_Scissor( sx, sy, sw, sh ); // restore the original translation in the object matrix if it has been changed if( offsetx || offsety ) { m[12] = transx; m[13] = transy; RB_LoadObjectMatrix( m ); } }
/* * RB_LoadProjectionMatrix */ void RB_LoadProjectionMatrix( const mat4_t m ) { Matrix4_Copy( m, rb.projectionMatrix ); Matrix4_Multiply( m, rb.modelviewMatrix, rb.modelviewProjectionMatrix ); }
/* * RB_LoadObjectMatrix */ void RB_LoadObjectMatrix( const mat4_t m ) { Matrix4_Copy( m, rb.objectMatrix ); Matrix4_MultiplyFast( rb.cameraMatrix, m, rb.modelviewMatrix ); Matrix4_Multiply( rb.projectionMatrix, rb.modelviewMatrix, rb.modelviewProjectionMatrix ); }
/* * RB_LoadObjectMatrix */ void RB_LoadObjectMatrix( const mat4_t m ) { Matrix4_Copy( m, rb.objectMatrix ); }
/* * R_DrawShadowmaps */ void R_DrawShadowmaps( void ) { unsigned int i; image_t *shadowmap; int textureWidth, textureHeight; float lodScale; vec3_t lodOrigin; vec3_t viewerOrigin; shadowGroup_t *group; int shadowBits = rn.shadowBits; refdef_t refdef; int lod; float farClip; float dist; if( !rsc.numShadowGroups ) { return; } if( rn.renderFlags & RF_SHADOWMAPVIEW ) { return; } if( rn.refdef.rdflags & RDF_NOWORLDMODEL ) { return; } if( !shadowBits ) { return; } if( !R_PushRefInst() ) { return; } lodScale = rn.lod_dist_scale_for_fov; VectorCopy( rn.lodOrigin, lodOrigin ); VectorCopy( rn.viewOrigin, viewerOrigin ); refdef = rn.refdef; // find lighting group containing entities with same lightingOrigin as ours for( i = 0; i < rsc.numShadowGroups; i++ ) { if( !shadowBits ) { break; } group = rsc.shadowGroups + i; if( !( shadowBits & group->bit ) ) { continue; } shadowBits &= ~group->bit; // make sure we don't render the same shadowmap twice in the same scene frame if( rsc.renderedShadowBits & group->bit ) { continue; } // calculate LOD for shadowmap dist = DistanceFast( group->origin, lodOrigin ); lod = (int)( dist * lodScale ) / group->projDist - SHADOWMAP_LODBIAS; if( lod < 0 ) { lod = 0; } // allocate/resize the texture if needed shadowmap = R_GetShadowmapTexture( i, rsc.refdef.width, rsc.refdef.height, 0 ); assert( shadowmap && shadowmap->upload_width && shadowmap->upload_height ); group->shadowmap = shadowmap; textureWidth = shadowmap->upload_width; textureHeight = shadowmap->upload_height; if( !shadowmap->fbo ) { continue; } farClip = R_SetupShadowmapView( group, &refdef, lod ); if( farClip <= 0.0f ) { continue; } // ignore shadowmaps of very low detail level if( refdef.width < SHADOWMAP_MIN_VIEWPORT_SIZE || refdef.height < SHADOWMAP_MIN_VIEWPORT_SIZE ) { continue; } rn.renderTarget = shadowmap->fbo; rn.farClip = farClip; rn.renderFlags = RF_SHADOWMAPVIEW | RF_FLIPFRONTFACE; if( !( shadowmap->flags & IT_DEPTH ) ) { rn.renderFlags |= RF_SHADOWMAPVIEW_RGB; } rn.clipFlags |= 16; // clip by far plane too rn.meshlist = &r_shadowlist; rn.portalmasklist = NULL; rn.shadowGroup = group; rn.lod_dist_scale_for_fov = lodScale; VectorCopy( viewerOrigin, rn.pvsOrigin ); VectorCopy( lodOrigin, rn.lodOrigin ); // 3 pixels border on each side to prevent nasty stretching/bleeding of shadows, // also accounting for smoothing done in the fragment shader Vector4Set( rn.viewport, refdef.x + 3,refdef.y + textureHeight - refdef.height + 3, refdef.width - 6, refdef.height - 6 ); Vector4Set( rn.scissor, refdef.x, refdef.y, textureWidth, textureHeight ); R_RenderView( &refdef ); Matrix4_Copy( rn.cameraProjectionMatrix, group->cameraProjectionMatrix ); rsc.renderedShadowBits |= group->bit; } R_PopRefInst(); }