void RB_CheckVao(vao_t *vao) { if (vao != glState.currentVao) { RB_EndSurface(); RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex); R_BindVao(vao); } if (vao != tess.vao) tess.useInternalVao = qfalse; }
void RB_CheckVao(vao_t *vao) { if (vao != glState.currentVao || tess.multiDrawPrimitives >= MAX_MULTIDRAW_PRIMITIVES) { RB_EndSurface(); RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex); R_BindVao(vao); } if (vao != tess.vao) tess.useInternalVao = qfalse; }
/* ============== 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); } }
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; }