/* * @brief Allocates and populates static VBO's for the specified r_model_t. */ static void R_LoadVertexBuffers(r_model_t *mod) { if (!qglGenBuffers) return; if (IS_MESH_MODEL(mod) && mod->mesh->num_frames > 1) // animated models don't use VBO return; const GLsizei v = mod->num_verts * 3 * sizeof(GLfloat); const GLsizei st = mod->num_verts * 2 * sizeof(GLfloat); const GLsizei t = mod->num_verts * 4 * sizeof(GLfloat); // load the vertex buffer objects qglGenBuffers(1, &mod->vertex_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->vertex_buffer); qglBufferData(GL_ARRAY_BUFFER, v, mod->verts, GL_STATIC_DRAW); qglGenBuffers(1, &mod->texcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->texcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, st, mod->texcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->normal_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->normal_buffer); qglBufferData(GL_ARRAY_BUFFER, v, mod->normals, GL_STATIC_DRAW); qglGenBuffers(1, &mod->tangent_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->tangent_buffer); qglBufferData(GL_ARRAY_BUFFER, t, mod->tangents, GL_STATIC_DRAW); if (mod->lightmap_texcoords) { qglGenBuffers(1, &mod->lightmap_texcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->lightmap_texcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, st, mod->lightmap_texcoords, GL_STATIC_DRAW); } qglBindBuffer(GL_ARRAY_BUFFER, 0); R_GetError(mod->media.name); }
/* * R_LoadVertexBuffers */ static void R_LoadVertexBuffers(r_model_t *mod) { int v, st, t, c; if (!qglGenBuffers) return; if (mod->num_frames > 1) // animated models don't use VBO return; v = mod->num_verts * 3 * sizeof(GLfloat); st = mod->num_verts * 2 * sizeof(GLfloat); t = mod->num_verts * 4 * sizeof(GLfloat); c = mod->num_verts * 4 * sizeof(GLfloat); // load the vertex buffer objects qglGenBuffers(1, &mod->vertex_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->vertex_buffer); qglBufferData(GL_ARRAY_BUFFER, v, mod->verts, GL_STATIC_DRAW); qglGenBuffers(1, &mod->texcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->texcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, st, mod->texcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->normal_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->normal_buffer); qglBufferData(GL_ARRAY_BUFFER, v, mod->normals, GL_STATIC_DRAW); qglBindBuffer(GL_ARRAY_BUFFER, 0); if (mod->type != mod_bsp) return; // including lightmap coords, tangents, and colors for bsp qglGenBuffers(1, &mod->lmtexcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->lmtexcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, st, mod->lmtexcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->tangent_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->tangent_buffer); qglBufferData(GL_ARRAY_BUFFER, t, mod->tangents, GL_STATIC_DRAW); qglGenBuffers(1, &mod->color_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->color_buffer); qglBufferData(GL_ARRAY_BUFFER, c, mod->colors, GL_STATIC_DRAW); qglBindBuffer(GL_ARRAY_BUFFER, 0); }
/** * @brief Puts the map data into buffers * @sa R_ModAddMapTile * @note Shift the verts after the texcoords for diffuse and lightmap are loaded * @sa R_ModShiftTile * @todo Don't use the buffers from r_state here - they might overflow * @todo Decrease MAX_GL_ARRAY_LENGTH to 32768 again when this is fixed */ static void R_LoadBspVertexArrays (model_t *mod) { int i, j; int vertind, coordind, tangind; float *vecShifted; float soff, toff, s, t; float *point, *sdir, *tdir; vec4_t tangent; vec3_t binormal; mBspSurface_t *surf; mBspVertex_t *vert; int vertexcount; vertind = coordind = tangind = vertexcount = 0; for (i = 0, surf = mod->bsp.surfaces; i < mod->bsp.numsurfaces; i++, surf++) for (j = 0; j < surf->numedges; j++) vertexcount++; surf = mod->bsp.surfaces; /* allocate the vertex arrays */ mod->bsp.texcoords = (GLfloat *)Mem_PoolAlloc(vertexcount * 2 * sizeof(GLfloat), vid_modelPool, 0); mod->bsp.lmtexcoords = (GLfloat *)Mem_PoolAlloc(vertexcount * 2 * sizeof(GLfloat), vid_modelPool, 0); mod->bsp.verts = (GLfloat *)Mem_PoolAlloc(vertexcount * 3 * sizeof(GLfloat), vid_modelPool, 0); mod->bsp.normals = (GLfloat *)Mem_PoolAlloc(vertexcount * 3 * sizeof(GLfloat), vid_modelPool, 0); mod->bsp.tangents = (GLfloat *)Mem_PoolAlloc(vertexcount * 4 * sizeof(GLfloat), vid_modelPool, 0); for (i = 0; i < mod->bsp.numsurfaces; i++, surf++) { surf->index = vertind / 3; for (j = 0; j < surf->numedges; j++) { const float *normal; const int index = mod->bsp.surfedges[surf->firstedge + j]; if (vertind >= MAX_GL_ARRAY_LENGTH * 3) Com_Error(ERR_DROP, "R_LoadBspVertexArrays: Exceeded MAX_GL_ARRAY_LENGTH %i", vertind); /* vertex */ if (index > 0) { /* negative indices to differentiate which end of the edge */ const mBspEdge_t *edge = &mod->bsp.edges[index]; vert = &mod->bsp.vertexes[edge->v[0]]; } else { const mBspEdge_t *edge = &mod->bsp.edges[-index]; vert = &mod->bsp.vertexes[edge->v[1]]; } point = vert->position; /* shift it for assembled maps */ vecShifted = &mod->bsp.verts[vertind]; /* origin (func_door, func_rotating) bmodels must not have shifted vertices, * they are translated by their entity origin value */ if (surf->isOriginBrushModel) VectorCopy(point, vecShifted); else VectorAdd(point, shift, vecShifted); /* texture directional vectors and offsets */ sdir = surf->texinfo->uv; soff = surf->texinfo->u_offset; tdir = surf->texinfo->vv; toff = surf->texinfo->v_offset; /* texture coordinates */ s = DotProduct(point, sdir) + soff; s /= surf->texinfo->image->width; t = DotProduct(point, tdir) + toff; t /= surf->texinfo->image->height; mod->bsp.texcoords[coordind + 0] = s; mod->bsp.texcoords[coordind + 1] = t; if (surf->flags & MSURF_LIGHTMAP) { /* lightmap coordinates */ s = DotProduct(point, sdir) + soff; s -= surf->stmins[0]; s += surf->light_s * surf->lightmap_scale; s += surf->lightmap_scale / 2.0; s /= r_lightmaps.size * surf->lightmap_scale; t = DotProduct(point, tdir) + toff; t -= surf->stmins[1]; t += surf->light_t * surf->lightmap_scale; t += surf->lightmap_scale / 2.0; t /= r_lightmaps.size * surf->lightmap_scale; } mod->bsp.lmtexcoords[coordind + 0] = s; mod->bsp.lmtexcoords[coordind + 1] = t; /* normal vectors */ if (surf->texinfo->flags & SURF_PHONG && VectorNotEmpty(vert->normal)) normal = vert->normal; /* phong shaded */ else normal = surf->normal; /* per plane */ memcpy(&mod->bsp.normals[vertind], normal, sizeof(vec3_t)); /* tangent vector */ TangentVectors(normal, sdir, tdir, tangent, binormal); memcpy(&mod->bsp.tangents[tangind], tangent, sizeof(vec4_t)); vertind += 3; coordind += 2; tangind += 4; } } if (qglBindBuffer) { /* and also the vertex buffer objects */ qglGenBuffers(1, &mod->bsp.vertex_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer); qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.texcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.normal_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer); qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.tangent_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer); qglBufferData(GL_ARRAY_BUFFER, tangind * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW); qglBindBuffer(GL_ARRAY_BUFFER, 0); } }
/* ============== RB_UpdateTessVao Adapted from Tess_UpdateVBOs from xreal Update the default VAO to replace the client side vertex arrays ============== */ void RB_UpdateTessVao(unsigned int attribBits) { GLimp_LogComment("--- RB_UpdateTessVao ---\n"); backEnd.pc.c_dynamicVaoDraws++; // update the default VAO if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES && tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES) { int attribIndex; int attribUpload; R_BindVao(tess.vao); // orphan old vertex buffer so we don't stall on it qglBufferData(GL_ARRAY_BUFFER, tess.vao->vertexesSize, NULL, GL_DYNAMIC_DRAW); // if nothing to set, set everything if(!(attribBits & ATTR_BITS)) attribBits = ATTR_BITS; attribUpload = attribBits; if((attribUpload & ATTR_TEXCOORD) || (attribUpload & ATTR_LIGHTCOORD)) { // these are interleaved, so we update both if either need it // this translates to updating ATTR_TEXCOORD twice as large as it needs attribUpload &= ~ATTR_LIGHTCOORD; attribUpload |= ATTR_TEXCOORD; } for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++) { uint32_t attribBit = 1 << attribIndex; vaoAttrib_t *vAtb = &tess.vao->attribs[attribIndex]; if (attribUpload & attribBit) { // note: tess has a VBO where stride == size qglBufferSubData(GL_ARRAY_BUFFER, vAtb->offset, tess.numVertexes * vAtb->stride, tess.attribPointers[attribIndex]); } if (attribBits & attribBit) { if (!glRefConfig.vertexArrayObject) qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset)); if (!(glState.vertexAttribsEnabled & attribBit)) { qglEnableVertexAttribArray(attribIndex); glState.vertexAttribsEnabled |= attribBit; } } else { if ((glState.vertexAttribsEnabled & attribBit)) { qglDisableVertexAttribArray(attribIndex); glState.vertexAttribsEnabled &= ~attribBit; } } } // orphan old index buffer so we don't stall on it qglBufferData(GL_ELEMENT_ARRAY_BUFFER, tess.vao->indexesSize, NULL, GL_DYNAMIC_DRAW); qglBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes); } }
/* ============ R_CreateVao2 ============ */ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int numIndexes, glIndex_t *indexes) { vao_t *vao; int i; byte *data; int dataSize; int dataOfs; int glUsage = GL_STATIC_DRAW; if(!numVertexes || !numIndexes) return NULL; if(strlen(name) >= MAX_QPATH) { ri.Error(ERR_DROP, "R_CreateVao2: \"%s\" is too long", name); } if ( tr.numVaos == MAX_VAOS ) { ri.Error( ERR_DROP, "R_CreateVao2: MAX_VAOS hit"); } R_IssuePendingRenderCommands(); vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low); tr.numVaos++; memset(vao, 0, sizeof(*vao)); Q_strncpyz(vao->name, name, sizeof(vao->name)); // since these vertex attributes are never altered, interleave them vao->attribs[ATTR_INDEX_POSITION ].enabled = 1; vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1; #ifdef USE_VERT_TANGENT_SPACE vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1; #endif vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1; vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1; vao->attribs[ATTR_INDEX_COLOR ].enabled = 1; vao->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1; vao->attribs[ATTR_INDEX_POSITION ].count = 3; vao->attribs[ATTR_INDEX_NORMAL ].count = 4; vao->attribs[ATTR_INDEX_TANGENT ].count = 4; vao->attribs[ATTR_INDEX_TEXCOORD ].count = 2; vao->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2; vao->attribs[ATTR_INDEX_COLOR ].count = 4; vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4; vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT; vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType; vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType; vao->attribs[ATTR_INDEX_TEXCOORD ].type = glRefConfig.packedTexcoordDataType; vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = glRefConfig.packedTexcoordDataType; vao->attribs[ATTR_INDEX_COLOR ].type = glRefConfig.packedColorDataType; vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType; vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE; vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE; vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE; vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE; vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE; vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE; vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE; vao->attribs[ATTR_INDEX_POSITION ].offset = 0; dataSize = sizeof(verts[0].xyz); vao->attribs[ATTR_INDEX_NORMAL ].offset = dataSize; dataSize += sizeof(uint32_t); #ifdef USE_VERT_TANGENT_SPACE vao->attribs[ATTR_INDEX_TANGENT ].offset = dataSize; dataSize += sizeof(uint32_t); #endif vao->attribs[ATTR_INDEX_TEXCOORD ].offset = dataSize; dataSize += glRefConfig.packedTexcoordDataSize; vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = dataSize; dataSize += glRefConfig.packedTexcoordDataSize; vao->attribs[ATTR_INDEX_COLOR ].offset = dataSize; dataSize += glRefConfig.packedColorDataSize; vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(uint32_t); vao->attribs[ATTR_INDEX_POSITION ].stride = dataSize; vao->attribs[ATTR_INDEX_NORMAL ].stride = dataSize; vao->attribs[ATTR_INDEX_TANGENT ].stride = dataSize; vao->attribs[ATTR_INDEX_TEXCOORD ].stride = dataSize; vao->attribs[ATTR_INDEX_LIGHTCOORD ].stride = dataSize; vao->attribs[ATTR_INDEX_COLOR ].stride = dataSize; vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = dataSize; if (glRefConfig.vertexArrayObject) { qglGenVertexArrays(1, &vao->vao); qglBindVertexArray(vao->vao); } // create VBO dataSize *= numVertexes; data = ri.Hunk_AllocateTempMemory(dataSize); dataOfs = 0; for (i = 0; i < numVertexes; i++) { // xyz memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz)); dataOfs += sizeof(verts[i].xyz); // normal dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].normal); #ifdef USE_VERT_TANGENT_SPACE // tangent dataOfs += R_VaoPackTangent(data + dataOfs, verts[i].tangent); #endif // texcoords dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].st); // lightmap texcoords dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].lightmap); // colors dataOfs += R_VaoPackColors(data + dataOfs, verts[i].vertexColors); // light directions dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].lightdir); } vao->vertexesSize = dataSize; qglGenBuffers(1, &vao->vertexesVBO); qglBindBuffer(GL_ARRAY_BUFFER, vao->vertexesVBO); qglBufferData(GL_ARRAY_BUFFER, vao->vertexesSize, data, glUsage); // create IBO vao->indexesSize = numIndexes * sizeof(glIndex_t); qglGenBuffers(1, &vao->indexesIBO); qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO); qglBufferData(GL_ELEMENT_ARRAY_BUFFER, vao->indexesSize, indexes, glUsage); Vao_SetVertexPointers(vao); glState.currentVao = vao; GL_CheckErrors(); ri.Hunk_FreeTempMemory(data); return vao; }
/* ============ R_CreateVao ============ */ vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *indexes, int indexesSize, vaoUsage_t usage) { vao_t *vao; int glUsage; switch (usage) { case VAO_USAGE_STATIC: glUsage = GL_STATIC_DRAW; break; case VAO_USAGE_DYNAMIC: glUsage = GL_DYNAMIC_DRAW; break; default: Com_Error(ERR_FATAL, "bad vaoUsage_t given: %i", usage); return NULL; } if(strlen(name) >= MAX_QPATH) { ri.Error(ERR_DROP, "R_CreateVao: \"%s\" is too long", name); } if ( tr.numVaos == MAX_VAOS ) { ri.Error( ERR_DROP, "R_CreateVao: MAX_VAOS hit"); } R_IssuePendingRenderCommands(); vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low); tr.numVaos++; memset(vao, 0, sizeof(*vao)); Q_strncpyz(vao->name, name, sizeof(vao->name)); if (glRefConfig.vertexArrayObject) { qglGenVertexArrays(1, &vao->vao); qglBindVertexArray(vao->vao); } vao->vertexesSize = vertexesSize; qglGenBuffers(1, &vao->vertexesVBO); qglBindBuffer(GL_ARRAY_BUFFER, vao->vertexesVBO); qglBufferData(GL_ARRAY_BUFFER, vertexesSize, vertexes, glUsage); vao->indexesSize = indexesSize; qglGenBuffers(1, &vao->indexesIBO); qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO); qglBufferData(GL_ELEMENT_ARRAY_BUFFER, indexesSize, indexes, glUsage); glState.currentVao = vao; GL_CheckErrors(); return vao; }
/** * @brief Puts the map data into buffers * @sa R_ModAddMapTile * @note Shift the verts after the texcoords for diffuse and lightmap are loaded * @sa R_ModShiftTile * @todo Don't use the buffers from r_state here - they might overflow * @todo Decrease MAX_GL_ARRAY_LENGTH to 32768 again when this is fixed */ static void R_LoadBspVertexArrays (model_t *mod) { int i, j; int vertOfs, texCoordOfs, tangOfs; float *vecShifted; float soff, toff, s, t; float *point, *sdir, *tdir; vec4_t tangent; vec3_t binormal; mBspSurface_t *surf; mBspVertex_t *vert; int vertexCount, indexCount; vertOfs = texCoordOfs = tangOfs = 0; vertexCount = indexCount = 0; for (i = 0, surf = mod->bsp.surfaces; i < mod->bsp.numsurfaces; i++, surf++) { const int numedges = surf->numedges; vertexCount += numedges; if (numedges > 2) /* no triangles for degenerate polys */ indexCount += (numedges - 2) * 3; } surf = mod->bsp.surfaces; /* allocate the vertex arrays */ mod->bsp.texcoords = Mem_PoolAllocTypeN(GLfloat, vertexCount * 2, vid_modelPool); mod->bsp.lmtexcoords = Mem_PoolAllocTypeN(GLfloat, vertexCount * 2, vid_modelPool); mod->bsp.verts = Mem_PoolAllocTypeN(GLfloat, vertexCount * 3, vid_modelPool); mod->bsp.normals = Mem_PoolAllocTypeN(GLfloat, vertexCount * 3, vid_modelPool); mod->bsp.tangents = Mem_PoolAllocTypeN(GLfloat, vertexCount * 4, vid_modelPool); mod->bsp.indexes = Mem_PoolAllocTypeN(GLint, indexCount, vid_modelPool); /* Will be filled at the end of map loading, after building surface lists */ for (i = 0; i < mod->bsp.numsurfaces; i++, surf++) { surf->index = vertOfs / 3; surf->firstTriangle = -1; /* Mark as "no triangles generated yet" */ for (j = 0; j < surf->numedges; j++) { const float *normal; const int index = mod->bsp.surfedges[surf->firstedge + j]; /* vertex */ if (index > 0) { /* negative indices to differentiate which end of the edge */ const mBspEdge_t *edge = &mod->bsp.edges[index]; vert = &mod->bsp.vertexes[edge->v[0]]; } else { const mBspEdge_t *edge = &mod->bsp.edges[-index]; vert = &mod->bsp.vertexes[edge->v[1]]; } point = vert->position; /* shift it for assembled maps */ vecShifted = &mod->bsp.verts[vertOfs]; /* origin (func_door, func_rotating) bmodels must not have shifted vertices, * they are translated by their entity origin value */ if (surf->isOriginBrushModel) VectorCopy(point, vecShifted); else VectorAdd(point, shift, vecShifted); /* texture directional vectors and offsets */ sdir = surf->texinfo->uv; soff = surf->texinfo->u_offset; tdir = surf->texinfo->vv; toff = surf->texinfo->v_offset; /* texture coordinates */ s = DotProduct(point, sdir) + soff; s /= surf->texinfo->image->width; t = DotProduct(point, tdir) + toff; t /= surf->texinfo->image->height; mod->bsp.texcoords[texCoordOfs + 0] = s; mod->bsp.texcoords[texCoordOfs + 1] = t; if (surf->flags & MSURF_LIGHTMAP) { /* lightmap coordinates */ s = DotProduct(point, sdir) + soff; s -= surf->stmins[0]; s += surf->light_s * surf->lightmap_scale; s += surf->lightmap_scale / 2.0; s /= r_lightmaps.size * surf->lightmap_scale; t = DotProduct(point, tdir) + toff; t -= surf->stmins[1]; t += surf->light_t * surf->lightmap_scale; t += surf->lightmap_scale / 2.0; t /= r_lightmaps.size * surf->lightmap_scale; } mod->bsp.lmtexcoords[texCoordOfs + 0] = s; mod->bsp.lmtexcoords[texCoordOfs + 1] = t; /* normal vectors */ if ((surf->texinfo->flags & SURF_PHONG) && VectorNotEmpty(vert->normal)) normal = vert->normal; /* phong shaded */ else normal = surf->normal; /* per plane */ memcpy(&mod->bsp.normals[vertOfs], normal, sizeof(vec3_t)); /* tangent vector */ TangentVectors(normal, sdir, tdir, tangent, binormal); memcpy(&mod->bsp.tangents[tangOfs], tangent, sizeof(vec4_t)); vertOfs += 3; texCoordOfs += 2; tangOfs += 4; } } R_ReallocateStateArrays(vertOfs / 3); if (qglBindBuffer) { /* and also the vertex buffer objects */ qglGenBuffers(1, &mod->bsp.vertex_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer); qglBufferData(GL_ARRAY_BUFFER, vertOfs * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.texcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, texCoordOfs * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, texCoordOfs * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.normal_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer); qglBufferData(GL_ARRAY_BUFFER, vertOfs * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.tangent_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer); qglBufferData(GL_ARRAY_BUFFER, tangOfs * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW); qglBindBuffer(GL_ARRAY_BUFFER, 0); } }
/** * @brief Re-initializes OpenGL state machine, all textures and renderer variables, this needed when application is put to background on Android. */ void R_ReinitOpenglContext (void) { /* De-allocate old GL state, these functinos will call glDeleteTexture(), so they should go before everything else */ R_FontCleanCache(); R_ShutdownFBObjects(); R_ShutdownPrograms(); R_BeginBuildingLightmaps(); /* This function will also call glDeleteTexture() */ /* Re-initialize GL state */ R_SetDefaultState(); R_InitPrograms(); /* Re-upload all textures */ R_InitMiscTexture(); R_ReloadImages(); /* Re-upload other GL stuff */ R_InitFBObjects(); R_UpdateDefaultMaterial("", "", "", NULL); /* Re-upload the battlescape terrain geometry */ if (!qglBindBuffer) return; for (int tile = 0; tile < r_numMapTiles; tile++) { model_t *mod = r_mapTiles[tile]; int vertind = 0, coordind = 0, tangind = 0; mBspSurface_t *surf = mod->bsp.surfaces; for (int i = 0; i < mod->bsp.numsurfaces; i++, surf++) { vertind += 3 * surf->numedges; coordind += 2 * surf->numedges; tangind += 4 * surf->numedges; } qglGenBuffers(1, &mod->bsp.vertex_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer); qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.texcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.normal_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer); qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.tangent_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer); qglBufferData(GL_ARRAY_BUFFER, tangind * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.index_buffer); qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mod->bsp.index_buffer); qglBufferData(GL_ELEMENT_ARRAY_BUFFER, mod->bsp.numIndexes * sizeof(GLushort), mod->bsp.indexes, GL_STATIC_DRAW); qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); for (int i = 0; i < mod->bsp.numsurfaces; i++) R_CreateSurfaceLightmap(&mod->bsp.surfaces[i]); } R_EndBuildingLightmaps(); qglBindBuffer(GL_ARRAY_BUFFER, 0); }