void Renderer::RenderFrame(float time) { time_ = time; SetupFrame(); // draw scene Setup3DRendering(); glBindBuffer(GL_ARRAY_BUFFER, world.map_->vboId); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, world.map_->iboId); glEnableVertexAttribArray(2); for (unsigned int i = 0; i < renderables_.size(); ++i) { RenderFace(renderables_[i]); } RenderModel(); // draw gui and overlays // Setup2DRendering(); // font.PrintString("<Q3 BSP RENDERER>", glm::vec2(10.0f, 10.0f), // glm::vec4(1.0, 0.0, 0.0, 1.0)); // if (delta == 0) delta = 1; // // std::stringstream fps; // fps << "frametime in ms: " << delta << " fps: " << 1000 / delta; // font.PrintString(fps.str(), glm::vec2(10.0f, // (float)screen_height_-20.0f), glm::vec4(1.0, 1.0, 1.0, 1.0)); }
void Quake3BSP_GL::RenderLevel(unsigned int bufferID) { // Get the number of faces in our level int i = m_numOfLeafs; int leafIndex; if(!Camera::GetInstance().getVisibilityState()){ // Finding the leaf the camera is in m_cameraPos = Camera::GetInstance().GetCamEye(); leafIndex = FindLeaf(0,m_cameraPos); // Once the leaf is found, reset the bools for leaf searching m_foundLeaf=false; m_foundIndex=0; } else { // We are in a frozen state for visibility, so use the last stored camera position, // don't get the updated one. leafIndex = FindLeaf(0,m_cameraPos); // Once the leaf is found, reset the bools for leaf searching m_foundLeaf=false; m_foundIndex=0; } // Getting the cluster that leaf is assigned to int cluster = m_pLeafs[leafIndex].cluster; // Go through the BSP tree checking to draw only what is visible from our // current cluster and what is visible within the frustum while(i--) { // Getting the current leaf to check with our camera's leaf BSPLeaf *pLeaf = &(m_pLeafs[i]); // Cluster Visiblity check if(!IsClusterValid(cluster, pLeaf->cluster)) continue; // Frustum visibility check if(!ViewFrustum::GetInstance().RectangleIntersect((float)pLeaf->min.x, (float)pLeaf->min.y, (float)pLeaf->min.z, (float)pLeaf->max.x, (float)pLeaf->max.y, (float)pLeaf->max.z)){ continue; } // The leaf must be valid to draw, set the counter for his number // of faces, then call RenderFaces to draw them all. int faceTotal = pLeaf->numOfLeafFaces; // Loop through and render all of the faces in this leaf while(faceTotal--) { int faceIndex = m_pLeafFaces[pLeaf->leafface + faceTotal]; // Check if this is a valid face to draw if(m_pFaces[faceIndex].type != FACE_POLYGON) continue; RenderFace(bufferID, faceIndex); } } }
void CQuake3BSP::RenderLevel(const CVector3 &vPos) { // Reset our bitset so all the slots are zero. m_FacesDrawn.ClearAll(); // Grab the leaf index that our camera is in int leafIndex = FindLeaf(vPos); // Grab the cluster that is assigned to the leaf int cluster = m_pLeafs[leafIndex].cluster; // Initialize our counter variables (start at the last leaf and work down) int i = m_numOfLeafs; g_VisibleFaces = 0; // Go through all the leafs and check their visibility while(i--) { // Get the current leaf that is to be tested for visibility from our camera's leaf tBSPLeaf *pLeaf = &(m_pLeafs[i]); // If the current leaf can't be seen from our cluster, go to the next leaf if(!IsClusterVisible(cluster, pLeaf->cluster)) continue; // If the current leaf is not in the camera's frustum, go to the next leaf if(!g_Frustum.BoxInFrustum((float)pLeaf->min.x, (float)pLeaf->min.y, (float)pLeaf->min.z, (float)pLeaf->max.x, (float)pLeaf->max.y, (float)pLeaf->max.z)) continue; // If we get here, the leaf we are testing must be visible in our camera's view. // Get the number of faces that this leaf is in charge of. int faceCount = pLeaf->numOfLeafFaces; // Loop through and render all of the faces in this leaf while(faceCount--) { // Grab the current face index from our leaf faces array int faceIndex = m_pLeafFaces[pLeaf->leafface + faceCount]; // Before drawing this face, make sure it's a normal polygon if(m_pFaces[faceIndex].type != FACE_POLYGON) continue; // Since many faces are duplicated in other leafs, we need to // make sure this face already hasn't been drawn. if(!m_FacesDrawn.On(faceIndex)) { // Increase the rendered face count to display for fun g_VisibleFaces++; // Set this face as drawn and render it m_FacesDrawn.Set(faceIndex); RenderFace(faceIndex); } } } }
void RenderSide (CSegment *segP, short nSide) { CSide *sideP = segP->m_sides + nSide; tFaceProps props; #if LIGHTMAPS #define LMAP_SIZE (1.0 / 16.0) static tUVL uvl_lMaps [4] = { {F2X (LMAP_SIZE), F2X (LMAP_SIZE), 0}, {F2X (1.0 - LMAP_SIZE), F2X (LMAP_SIZE), 0}, {F2X (1.0 - LMAP_SIZE), F2X (1.0 - LMAP_SIZE), 0}, {F2X (LMAP_SIZE), F2X (1.0 - LMAP_SIZE), 0} }; #endif props.segNum = segP->Index (); props.sideNum = nSide; #if DBG if ((props.segNum == nDbgSeg) && ((nDbgSide < 0) || (props.sideNum == nDbgSide))) segP = segP; #endif props.widFlags = segP->IsDoorWay (props.sideNum, NULL); if (!(gameOpts->render.debug.bWalls || IsMultiGame) && IS_WALL (segP->WallNum (props.sideNum))) return; switch (gameStates.render.nType) { case -1: if (!(props.widFlags & WID_RENDER_FLAG) && (SEGMENTS [props.segNum].m_nType < SEGMENT_IS_WATER)) //if (WALL_IS_DOORWAY(segP, props.sideNum) == WID_NO_WALL) return; break; case 0: if (segP->m_children [props.sideNum] >= 0) //&& IS_WALL (WallNumP (segP, props.sideNum))) return; break; case 1: if (!IS_WALL (segP->WallNum (props.sideNum))) return; break; case 2: if ((SEGMENTS [props.segNum].m_nType < SEGMENT_IS_WATER) && (SEGMENTS [props.segNum].m_owner < 1)) return; break; case 3: if ((IsLight (sideP->m_nBaseTex) || (sideP->m_nOvlTex && IsLight (sideP->m_nOvlTex)))) RenderCorona (props.segNum, props.sideNum, 1, 20); return; } #if LIGHTMAPS if (gameStates.render.bDoLightmaps) { float Xs = 8; float h = 0.5f / (float) Xs; props.uvl_lMaps [0].u = props.uvl_lMaps [0].v = props.uvl_lMaps [1].v = props.uvl_lMaps [3].u = F2X (h); props.uvl_lMaps [1].u = props.uvl_lMaps [2].u = props.uvl_lMaps [2].v = props.uvl_lMaps [3].v = F2X (1-h); } #endif props.nBaseTex = sideP->m_nBaseTex; props.nOvlTex = sideP->m_nOvlTex; props.nOvlOrient = sideP->m_nOvlOrient; // ========== Mark: Here is the change...beginning here: ========== #if LIGHTMAPS if (gameStates.render.bDoLightmaps) { memcpy (props.uvl_lMaps, uvl_lMaps, sizeof (tUVL) * 4); #if LMAP_LIGHTADJUST props.uvls [0].l = props.uvls [1].l = props.uvls [2].l = props.uvls [3].l = I2X (1) / 2; # endif } #endif #if DBG //convenient place for a debug breakpoint if (props.segNum == nDbgSeg && props.sideNum == nDbgSide) props.segNum = props.segNum; if (props.nBaseTex == nDbgBaseTex) props.segNum = props.segNum; if (props.nOvlTex == nDbgOvlTex) props.segNum = props.segNum; # if 0 else return; # endif #endif if (!FaceIsVisible (props.segNum, props.sideNum)) return; if (sideP->m_nType == SIDE_IS_QUAD) { props.vNormal = sideP->m_normals [0]; props.nVertices = 4; memcpy (props.uvls, sideP->m_uvls, sizeof (tUVL) * 4); memcpy (props.vp, SEGMENTS [props.segNum].Corners (props.sideNum), 4 * sizeof (ushort)); RenderFace (&props); } else { // new code // non-planar faces are still passed as quads to the renderer as it will render triangles (GL_TRIANGLE_FAN) anyway // just need to make sure the vertices come in the proper order depending of the the orientation of the two non-planar triangles props.vNormal = sideP->m_normals [0] + sideP->m_normals [1]; props.vNormal *= (I2X (1) / 2); props.nVertices = 4; if (sideP->m_nType == SIDE_IS_TRI_02) { memcpy (props.uvls, sideP->m_uvls, sizeof (tUVL) * 4); memcpy (props.vp, SEGMENTS [props.segNum].Corners (props.sideNum), 4 * sizeof (ushort)); RenderFace (&props); } else if (sideP->m_nType == SIDE_IS_TRI_13) { //just rendering the fan with vertex 1 instead of 0 memcpy (props.uvls + 1, sideP->m_uvls, sizeof (tUVL) * 3); props.uvls [0] = sideP->m_uvls [3]; memcpy (props.vp + 1, SEGMENTS [props.segNum].Corners (props.sideNum), 4 * sizeof (ushort)); props.vp [0] = props.vp [4]; RenderFace (&props); } else { Error("Illegal CSide nType in RenderSide, nType = %i, CSegment # = %i, CSide # = %i\n", sideP->m_nType, segP->Index (), props.sideNum); return; } } }
void CQuake3BSP::RenderLevel(const CVector3 &vPos) { // Reset our bitset so all the slots are zero. m_FacesDrawn.ClearAll(); /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // In this new revision of RenderLevel(), we do things a bit differently. // Instead of looping through all the faces, we now want to loop through // all of the leafs. Each leaf stores a list of faces assign to it. // We call FindLeaf() to find the current leaf index that our camera is // in. This leaf will then give us the cluster that the camera is in. The // cluster is then used to test visibility between our current cluster // and other leaf clusters. If another leaf's cluster is visible from our // current cluster, the leaf's bounding box is checked against our frustum. // Assuming the bounding box is inside of our frustum, we draw all the faces // stored in that leaf. // Grab the leaf index that our camera is in int leafIndex = FindLeaf(vPos); // Grab the cluster that is assigned to the leaf int cluster = m_pLeafs[leafIndex].cluster; // Initialize our counter variables (start at the last leaf and work down) int i = m_numOfLeafs; g_VisibleFaces = 0; // Go through all the leafs and check their visibility while(i--) { // Get the current leaf that is to be tested for visibility from our camera's leaf tBSPLeaf *pLeaf = &(m_pLeafs[i]); // If the current leaf can't be seen from our cluster, go to the next leaf if(!IsClusterVisible(cluster, pLeaf->cluster)) continue; // If the current leaf is not in the camera's frustum, go to the next leaf if(!g_Frustum.BoxInFrustum((float)pLeaf->min.x, (float)pLeaf->min.y, (float)pLeaf->min.z, (float)pLeaf->max.x, (float)pLeaf->max.y, (float)pLeaf->max.z)) continue; // If we get here, the leaf we are testing must be visible in our camera's view. // Get the number of faces that this leaf is in charge of. int faceCount = pLeaf->numOfLeafFaces; // Loop through and render all of the faces in this leaf while(faceCount--) { // Grab the current face index from our leaf faces array int faceIndex = m_pLeafFaces[pLeaf->leafface + faceCount]; // Before drawing this face, make sure it's a normal polygon if(m_pFaces[faceIndex].type != FACE_POLYGON) continue; // Since many faces are duplicated in other leafs, we need to // make sure this face already hasn't been drawn. if(!m_FacesDrawn.On(faceIndex)) { // Increase the rendered face count to display for fun g_VisibleFaces++; // Set this face as drawn and render it m_FacesDrawn.Set(faceIndex); RenderFace(faceIndex); } } } /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * }