void Vao_SetVertexPointers(vao_t *vao) { int attribIndex; // set vertex pointers for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++) { uint32_t attribBit = 1 << attribIndex; vaoAttrib_t *vAtb = &vao->attribs[attribIndex]; if (vAtb->enabled) { qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset)); if (glRefConfig.vertexArrayObject || !(glState.vertexAttribsEnabled & attribBit)) qglEnableVertexAttribArray(attribIndex); if (!glRefConfig.vertexArrayObject || vao == tess.vao) glState.vertexAttribsEnabled |= attribBit; } else { // don't disable vertex attribs when using vertex array objects // Vao_SetVertexPointers is only called during init when using VAOs, and vertex attribs start disabled anyway if (!glRefConfig.vertexArrayObject && (glState.vertexAttribsEnabled & attribBit)) qglDisableVertexAttribArray(attribIndex); if (!glRefConfig.vertexArrayObject || vao == tess.vao) glState.vertexAttribsEnabled &= ~attribBit; } } }
void R_EnableAttribute (const char* name) { r_progvar_t* v; if (!(v = R_ProgramVariable(GL_ATTRIBUTE, name))) return; qglEnableVertexAttribArray(v->location); }
/* * @brief */ void R_EnableAttribute(r_attribute_t *attribute) { if (!attribute || attribute->location == -1) { Com_Warn("NULL or invalid attribute\n"); return; } if (attribute->value.i != 1) { qglEnableVertexAttribArray(attribute->location); attribute->value.i = 1; } R_GetError(attribute->name); }
/* ============== 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); } }