Esempio n. 1
0
/*
** 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
}
Esempio n. 2
0
File: tr_vbo.c Progetto: UniQP/ioq3
/*
============
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);
		}
	}
}
Esempio n. 3
0
/*
 * 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);
}
Esempio n. 4
0
File: tr_vbo.c Progetto: UniQP/ioq3
/*
============
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();
}
Esempio n. 5
0
/*
 * 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);
}
Esempio n. 6
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);
}
Esempio n. 7
0
/*
 ==================
 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);
}
Esempio n. 8
0
/*
 * @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);
}
Esempio n. 9
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);
	}
}
Esempio n. 10
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");
}
Esempio n. 11
0
File: tr_vbo.c Progetto: UniQP/ioq3
/*
============
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;
}
Esempio n. 12
0
File: tr_vbo.c Progetto: UniQP/ioq3
/*
============
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;
}
Esempio n. 13
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 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);
	}
}
Esempio n. 14
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);
}
Esempio n. 15
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;
}