/* ** GL_SetDefaultState */ void GL_SetDefaultState( void ) { qglClearDepth( 1.0f ); qglCullFace(GL_FRONT); qglColor4f (1,1,1,1); GL_BindNullTextures(); if (glRefConfig.framebufferObject) GL_BindNullFramebuffers(); qglEnable(GL_TEXTURE_2D); GL_TextureMode( r_textureMode->string ); //qglShadeModel( GL_SMOOTH ); qglDepthFunc( GL_LEQUAL ); // // make sure our GL state vector is set correctly // glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE; glState.storedGlState = 0; glState.faceCulling = CT_TWO_SIDED; glState.faceCullFront = qtrue; GL_BindNullProgram(); if (glRefConfig.vertexArrayObject) qglBindVertexArray(0); qglBindBuffer(GL_ARRAY_BUFFER, 0); qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glState.currentVao = NULL; glState.vertexAttribsEnabled = 0; qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); qglDepthMask( GL_TRUE ); qglDisable( GL_DEPTH_TEST ); qglEnable( GL_SCISSOR_TEST ); qglDisable( GL_CULL_FACE ); qglDisable( GL_BLEND ); if (glRefConfig.seamlessCubeMap) qglEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // GL_POLYGON_OFFSET_FILL will be glEnable()d when this is used qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky }
/* ============ R_BindVao ============ */ void R_BindVao(vao_t * vao) { if(!vao) { //R_BindNullVao(); ri.Error(ERR_DROP, "R_BindVao: NULL vao"); return; } if(r_logFile->integer) { // don't just call LogComment, or we will get a call to va() every frame! GLimp_LogComment(va("--- R_BindVao( %s ) ---\n", vao->name)); } if(glState.currentVao != vao) { glState.currentVao = vao; glState.vertexAttribsInterpolation = 0; glState.vertexAnimation = qfalse; backEnd.pc.c_vaoBinds++; if (glRefConfig.vertexArrayObject) { qglBindVertexArray(vao->vao); // why you no save GL_ELEMENT_ARRAY_BUFFER binding, Intel? if (1) qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO); // tess VAO always has buffers bound if (vao == tess.vao) qglBindBuffer(GL_ARRAY_BUFFER, vao->vertexesVBO); } else { qglBindBuffer(GL_ARRAY_BUFFER, vao->vertexesVBO); qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO); // tess VAO doesn't have vertex pointers set until data is uploaded if (vao != tess.vao) Vao_SetVertexPointers(vao); } } }
/* * R_BindBuffer */ void R_BindBuffer(GLenum target, GLenum type, GLuint id) { if (!qglBindBuffer) return; if (!r_vertex_buffers->value) return; qglBindBuffer(GL_ARRAY_BUFFER, id); if (type && id) // assign the array pointer as well R_BindArray(target, type, NULL); }
/* ============ R_BindNullVao ============ */ void R_BindNullVao(void) { GLimp_LogComment("--- R_BindNullVao ---\n"); if(glState.currentVao) { if (glRefConfig.vertexArrayObject) { qglBindVertexArray(0); // why you no save GL_ELEMENT_ARRAY_BUFFER binding, Intel? if (1) qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } else { qglBindBuffer(GL_ARRAY_BUFFER, 0); qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } glState.currentVao = NULL; } GL_CheckErrors(); }
/* * 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); }
/* ================== GL_BindVertexBuffer ================== */ void GL_BindVertexBuffer (arrayBuffer_t *vertexBuffer){ if (!vertexBuffer){ if (!glState.vertexBuffer) return; glState.vertexBuffer = NULL; qglBindBuffer(GL_ARRAY_BUFFER, 0); return; } if (vertexBuffer->frameUsed != rg.frameCount){ vertexBuffer->frameUsed = rg.frameCount; rg.pc.vertexBuffers[vertexBuffer->dynamic]++; rg.pc.vertexBufferBytes[vertexBuffer->dynamic] += vertexBuffer->size; } if (glState.vertexBuffer == vertexBuffer) return; glState.vertexBuffer = vertexBuffer; qglBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->bufferId); }
/* ================== GL_BindIndexBuffer ================== */ void GL_BindIndexBuffer (arrayBuffer_t *indexBuffer){ if (!indexBuffer){ if (!glState.indexBuffer) return; glState.indexBuffer = NULL; qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); return; } if (indexBuffer->frameUsed != rg.frameCount){ indexBuffer->frameUsed = rg.frameCount; rg.pc.indexBuffers[indexBuffer->dynamic]++; rg.pc.indexBufferBytes[indexBuffer->dynamic] += indexBuffer->size; } if (glState.indexBuffer == indexBuffer) return; glState.indexBuffer = indexBuffer; qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer->bufferId); }
/* * @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); }
/** * @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); } }
/* ================== GL_SetDefaultState ================== */ void GL_SetDefaultState (){ int i; QGL_LogPrintf("---------- GL_SetDefaultState ----------\n"); // Reset the state manager glState.projectionMatrixIdentity = true; glState.modelviewMatrixIdentity = true; for (i = 0; i < MAX_TEXTURE_UNITS; i++) glState.textureMatrixIdentity[i] = true; for (i = 0; i < MAX_TEXTURE_UNITS; i++) glState.texture[i] = NULL; glState.program = NULL; glState.indexBuffer = NULL; glState.vertexBuffer = NULL; glState.viewportX = 0; glState.viewportY = 0; glState.viewportWidth = glConfig.videoWidth; glState.viewportHeight = glConfig.videoHeight; glState.scissorX = 0; glState.scissorY = 0; glState.scissorWidth = glConfig.videoWidth; glState.scissorHeight = glConfig.videoHeight; glState.depthBoundsMin = 0.0f; glState.depthBoundsMax = 1.0f; glState.texUnit = 0; for (i = 0; i < MAX_TEXTURE_UNITS; i++){ glState.texTarget[i] = 0; glState.texEnv[i] = GL_MODULATE; glState.texGen[i][0] = GL_OBJECT_LINEAR; glState.texGen[i][1] = GL_OBJECT_LINEAR; glState.texGen[i][2] = GL_OBJECT_LINEAR; glState.texGen[i][3] = GL_OBJECT_LINEAR; } glState.cullFace = false; glState.polygonOffsetFill = false; glState.polygonOffsetLine = false; glState.blend = false; glState.alphaTest = false; glState.depthTest = false; glState.stencilTest = false; for (i = 0; i < MAX_TEXTURE_UNITS; i++){ glState.textureGen[i][0] = false; glState.textureGen[i][1] = false; glState.textureGen[i][2] = false; glState.textureGen[i][3] = false; } glState.cullMode = GL_FRONT; glState.polygonMode = GL_FILL; glState.polygonOffsetFactor = 0.0f; glState.polygonOffsetUnits = 0.0f; glState.blendSrc = GL_ONE; glState.blendDst = GL_ZERO; glState.blendMode = GL_FUNC_ADD; glState.alphaFunc = GL_GREATER; glState.alphaFuncRef = 0.0f; glState.depthFunc = GL_LEQUAL; glState.stencilFunc[0] = GL_ALWAYS; glState.stencilFunc[1] = GL_ALWAYS; glState.stencilFuncRef[0] = 0; glState.stencilFuncRef[1] = 0; glState.stencilFuncMask[0] = 255; glState.stencilFuncMask[1] = 255; glState.stencilOpFail[0] = GL_KEEP; glState.stencilOpFail[1] = GL_KEEP; glState.stencilOpZFail[0] = GL_KEEP; glState.stencilOpZFail[1] = GL_KEEP; glState.stencilOpZPass[0] = GL_KEEP; glState.stencilOpZPass[1] = GL_KEEP; glState.depthMin = 0.0f; glState.depthMax = 1.0f; glState.colorMask[0] = GL_TRUE; glState.colorMask[1] = GL_TRUE; glState.colorMask[2] = GL_TRUE; glState.colorMask[3] = GL_TRUE; glState.depthMask = GL_TRUE; glState.stencilMask[0] = 255; glState.stencilMask[1] = 255; // Set default state qglMatrixMode(GL_PROJECTION); qglLoadIdentity(); qglMatrixMode(GL_MODELVIEW); qglLoadIdentity(); for (i = MAX_TEXTURE_UNITS - 1; i >= 0; i--){ if (i >= glConfig.maxTextureImageUnits) continue; if (i >= glConfig.maxTextureUnits){ qglActiveTexture(GL_TEXTURE0 + i); qglBindTexture(GL_TEXTURE_2D, 0); qglBindTexture(GL_TEXTURE_3D, 0); qglBindTexture(GL_TEXTURE_CUBE_MAP, 0); qglBindTexture(GL_TEXTURE_2D_ARRAY, 0); continue; } qglActiveTexture(GL_TEXTURE0 + i); qglMatrixMode(GL_TEXTURE); qglLoadIdentity(); qglDisable(GL_TEXTURE_2D); qglDisable(GL_TEXTURE_3D); qglDisable(GL_TEXTURE_CUBE_MAP); qglDisable(GL_TEXTURE_2D_ARRAY); qglBindTexture(GL_TEXTURE_2D, 0); qglBindTexture(GL_TEXTURE_3D, 0); qglBindTexture(GL_TEXTURE_CUBE_MAP, 0); qglBindTexture(GL_TEXTURE_2D_ARRAY, 0); qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); qglDisable(GL_TEXTURE_GEN_S); qglDisable(GL_TEXTURE_GEN_T); qglDisable(GL_TEXTURE_GEN_R); qglDisable(GL_TEXTURE_GEN_Q); qglTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); qglTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); qglTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); qglTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); } qglDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); qglUseProgram(0); qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); qglBindBuffer(GL_ARRAY_BUFFER, 0); qglViewport(0, 0, glConfig.videoWidth, glConfig.videoHeight); qglEnable(GL_SCISSOR_TEST); qglScissor(0, 0, glConfig.videoWidth, glConfig.videoHeight); qglEnable(GL_DEPTH_BOUNDS_TEST_EXT); qglDepthBoundsEXT(0.0f, 1.0f); qglFrontFace(GL_CCW); qglShadeModel(GL_SMOOTH); qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); qglDisable(GL_CULL_FACE); qglCullFace(GL_FRONT); qglDisable(GL_POLYGON_OFFSET_FILL); qglDisable(GL_POLYGON_OFFSET_LINE); qglPolygonOffset(0.0f, 0.0f); qglDisable(GL_BLEND); qglBlendFunc(GL_ONE, GL_ZERO); qglBlendEquation(GL_FUNC_ADD); qglDisable(GL_ALPHA_TEST); qglAlphaFunc(GL_GREATER, 0.0f); qglDisable(GL_DEPTH_TEST); qglDepthFunc(GL_LEQUAL); qglDisable(GL_STENCIL_TEST); qglStencilFunc(GL_ALWAYS, 128, 255); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglDepthRange(0.0f, 1.0f); qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); qglDepthMask(GL_TRUE); qglStencilMask(255); qglDisable(GL_DEPTH_CLAMP); qglDisable(GL_CLIP_PLANE0); if (glConfig.multiSamples > 1){ qglDisable(GL_MULTISAMPLE); qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); } qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); qglClearDepth(1.0f); qglClearStencil(128); qglEnableClientState(GL_VERTEX_ARRAY); qglDisableVertexAttribArray(GL_ATTRIB_NORMAL); qglDisableVertexAttribArray(GL_ATTRIB_TANGENT1); qglDisableVertexAttribArray(GL_ATTRIB_TANGENT2); qglDisableVertexAttribArray(GL_ATTRIB_TEXCOORD); qglDisableVertexAttribArray(GL_ATTRIB_COLOR); QGL_LogPrintf("--------------------\n"); }
/* ============ 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); }
void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface) { //mdvModel_t *mdvModel; //mdvSurface_t *mdvSurface; refEntity_t *refEnt; GLimp_LogComment("--- RB_SurfaceVaoMdvMesh ---\n"); if (ShaderRequiresCPUDeforms(tess.shader)) { RB_SurfaceMesh(surface->mdvSurface); return; } if(!surface->vao) return; //RB_CheckVao(surface->vao); RB_EndSurface(); RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex); R_BindVao(surface->vao); tess.useInternalVao = qfalse; tess.numIndexes = surface->numIndexes; tess.numVertexes = surface->numVerts; //mdvModel = surface->mdvModel; //mdvSurface = surface->mdvSurface; refEnt = &backEnd.currentEntity->e; glState.vertexAttribsInterpolation = (refEnt->oldframe == refEnt->frame) ? 0.0f : refEnt->backlerp; if (surface->mdvModel->numFrames > 1) { int frameOffset, attribIndex; vaoAttrib_t *vAtb; glState.vertexAnimation = qtrue; if (glRefConfig.vertexArrayObject) { qglBindBuffer(GL_ARRAY_BUFFER, surface->vao->vertexesVBO); } frameOffset = refEnt->frame * surface->vao->frameSize; attribIndex = ATTR_INDEX_POSITION; vAtb = &surface->vao->attribs[attribIndex]; qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); attribIndex = ATTR_INDEX_NORMAL; vAtb = &surface->vao->attribs[attribIndex]; qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); attribIndex = ATTR_INDEX_TANGENT; vAtb = &surface->vao->attribs[attribIndex]; qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); frameOffset = refEnt->oldframe * surface->vao->frameSize; attribIndex = ATTR_INDEX_POSITION2; vAtb = &surface->vao->attribs[attribIndex]; qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); attribIndex = ATTR_INDEX_NORMAL2; vAtb = &surface->vao->attribs[attribIndex]; qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); attribIndex = ATTR_INDEX_TANGENT2; vAtb = &surface->vao->attribs[attribIndex]; qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); if (!glRefConfig.vertexArrayObject) { attribIndex = ATTR_INDEX_TEXCOORD; vAtb = &surface->vao->attribs[attribIndex]; qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset)); } } RB_EndSurface(); // So we don't lerp surfaces that shouldn't be lerped glState.vertexAnimation = qfalse; }