Esempio n. 1
0
void Gui_FillCrosshairBuffer()
{
    GLfloat x = (GLfloat)screen_info.w / 2.0f;
    GLfloat y = (GLfloat)screen_info.h / 2.0f;
    GLfloat *v, crosshairArray[32];
    const GLfloat size = 8.0f;
    const GLfloat color[4] = {1.0f, 0.0f, 0.0f, 1.0f};

    v = crosshairArray;
   *v++ = x; *v++ = y - size;
    vec4_copy(v, color);
    v += 4;
   *v++ = 0.0; *v++ = 0.0;

   *v++ = x; *v++ = y + size;
    vec4_copy(v, color);
    v += 4;
   *v++ = 0.0; *v++ = 0.0;

   *v++ = x - size; *v++ = y;
    vec4_copy(v, color);
    v += 4;
   *v++ = 0.0; *v++ = 0.0;

   *v++ = x + size; *v++ = y;
    vec4_copy(v, color);
    v += 4;
   *v++ = 0.0; *v++ = 0.0;

    // copy vertices into GL buffer
    qglBindBufferARB(GL_ARRAY_BUFFER, crosshairBuffer);
    qglBufferDataARB(GL_ARRAY_BUFFER, sizeof(GLfloat[32]), crosshairArray, GL_STATIC_DRAW);
}
Esempio n. 2
0
/*
========================
idJointBuffer::AllocBufferObject
========================
*/
bool idJointBuffer::AllocBufferObject( const float * joints, int numAllocJoints ) {
	assert( apiObject == NULL );
	assert_16_byte_aligned( joints );

	if ( numAllocJoints <= 0 ) {
		idLib::Error( "idJointBuffer::AllocBufferObject: joints = %i", numAllocJoints );
	}

	numJoints = numAllocJoints;

	bool allocationFailed = false;

	const int numBytes = GetAllocedSize();

	GLuint buffer = 0;
	qglGenBuffersARB( 1, &buffer );
	qglBindBufferARB( GL_UNIFORM_BUFFER, buffer );
	qglBufferDataARB( GL_UNIFORM_BUFFER, numBytes, NULL, GL_STREAM_DRAW_ARB );
	qglBindBufferARB( GL_UNIFORM_BUFFER, 0);
	apiObject = reinterpret_cast< void * >( buffer );

	if ( r_showBuffers.GetBool() ) {
		idLib::Printf( "joint buffer alloc %p, api %p (%i joints)\n", this, GetAPIObject(), GetNumJoints() );
	}

	// copy the data
	if ( joints != NULL ) {
		Update( joints, numAllocJoints );
	}

	return !allocationFailed;
}
Esempio n. 3
0
void Gui_FillBackgroundBuffer()
{
    GLfloat x0 = 0.0f;
    GLfloat y0 = 0.0f;
    GLfloat x1 = screen_info.w;
    GLfloat y1 = screen_info.h;
    GLfloat *v, backgroundArray[32];
    GLfloat color[4] = {0.0f, 0.0f, 0.0f, 0.5f};

    v = backgroundArray;
   *v++ = x0; *v++ = y0;
    vec4_copy(v, color);
    v += 4;
   *v++ = 0.0f; *v++ = 0.0f;

   *v++ = x1; *v++ = y0;
    vec4_copy(v, color);
    v += 4;
   *v++ = 1.0f; *v++ = 0.0f;

   *v++ = x1; *v++ = y1;
    vec4_copy(v, color);
    v += 4;
   *v++ = 1.0f; *v++ = 1.0f;

   *v++ = x0; *v++ = y1;
    vec4_copy(v, color);
    v += 4;
   *v++ = 0.0f; *v++ = 1.0f;

    qglBindBufferARB(GL_ARRAY_BUFFER, backgroundBuffer);
    qglBufferDataARB(GL_ARRAY_BUFFER, sizeof(GLfloat[32]), backgroundArray, GL_STATIC_DRAW);
}
Esempio n. 4
0
/*
* R_DiscardVBOElemData
*/
void R_DiscardVBOElemData( mesh_vbo_t *vbo )
{
	GLenum elem_usage = VBO_ELEM_USAGE_FOR_TAG(vbo->tag);

	if( vbo->elemId ) {
		RB_BindElementArrayBuffer( vbo->elemId );
		qglBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, vbo->elemBufferSize, NULL, elem_usage );
	}
}
Esempio n. 5
0
/*
* R_DiscardVBOVertexData
*/
void R_DiscardVBOVertexData( mesh_vbo_t *vbo )
{
	GLenum array_usage = VBO_ARRAY_USAGE_FOR_TAG(vbo->tag);

	if( vbo->vertexId ) {
		RB_BindArrayBuffer( vbo->vertexId );
		qglBufferDataARB( GL_ARRAY_BUFFER_ARB, vbo->arrayBufferSize, NULL, array_usage );
	}

}
Esempio n. 6
0
/*
============
R_CreateVBO
============
*/
VBO_t          *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage)
{
	VBO_t          *vbo;
	int				glUsage;

	switch (usage)
	{
		case VBO_USAGE_STATIC:
			glUsage = GL_STATIC_DRAW_ARB;
			break;

		case VBO_USAGE_DYNAMIC:
			glUsage = GL_DYNAMIC_DRAW_ARB;
			break;

		default:
			Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
			return NULL;
	}

	if(strlen(name) >= MAX_QPATH)
	{
		ri.Error(ERR_DROP, "R_CreateVBO: \"%s\" is too long\n", name);
	}

	if ( tr.numVBOs == MAX_VBOS ) {
		ri.Error( ERR_DROP, "R_CreateVBO: MAX_VBOS hit\n");
	}

	// make sure the render thread is stopped
	R_SyncRenderThread();

	vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low);
	tr.numVBOs++;

	memset(vbo, 0, sizeof(*vbo));

	Q_strncpyz(vbo->name, name, sizeof(vbo->name));

	vbo->vertexesSize = vertexesSize;

	qglGenBuffersARB(1, &vbo->vertexesVBO);

	qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
	qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexesSize, vertexes, glUsage);

	qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

	glState.currentVBO = NULL;

	GL_CheckErrors();

	return vbo;
}
Esempio n. 7
0
/*
============
R_CreateIBO
============
*/
IBO_t          *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage)
{
	IBO_t          *ibo;
	int				glUsage;

	switch (usage)
	{
		case VBO_USAGE_STATIC:
			glUsage = GL_STATIC_DRAW_ARB;
			break;

		case VBO_USAGE_DYNAMIC:
			glUsage = GL_DYNAMIC_DRAW_ARB;
			break;

		default:
			Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
			return NULL;
	}

	if(strlen(name) >= MAX_QPATH)
	{
		ri.Error(ERR_DROP, "R_CreateIBO: \"%s\" is too long", name);
	}

	if ( tr.numIBOs == MAX_IBOS ) {
		ri.Error( ERR_DROP, "R_CreateIBO: MAX_IBOS hit");
	}

	R_IssuePendingRenderCommands();

	ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
	tr.numIBOs++;

	Q_strncpyz(ibo->name, name, sizeof(ibo->name));

	ibo->indexesSize = indexesSize;

	qglGenBuffersARB(1, &ibo->indexesVBO);

	qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO);
	qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage);

	qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);

	glState.currentIBO = NULL;

	GL_CheckErrors();

	return ibo;
}
/*
==============
idVertexCache::ActuallyFree
==============
*/
void idVertexCache::ActuallyFree(vertCache_t *block)
{
	if (!block) {
		common->Error("idVertexCache Free: NULL pointer");
	}

	if (block->user) {
		// let the owner know we have purged it
		*block->user = NULL;
		block->user = NULL;
	}

	// temp blocks are in a shared space that won't be freed
	if (block->tag != TAG_TEMP) {
		staticAllocTotal -= block->size;
		staticCountTotal--;

		if (block->vbo) {
#if 0		// this isn't really necessary, it will be reused soon enough
			// filling with zero length data is the equivalent of freeing
			qglBindBufferARB(GL_ARRAY_BUFFER_ARB, block->vbo);
			qglBufferDataARB(GL_ARRAY_BUFFER_ARB, 0, 0, GL_DYNAMIC_DRAW_ARB);
#endif
		} else if (block->virtMem) {
			Mem_Free(block->virtMem);
			block->virtMem = NULL;
		}
	}

	block->tag = TAG_FREE;		// mark as free

	// unlink stick it back on the free list
	block->next->prev = block->prev;
	block->prev->next = block->next;

#if 1
	// stick it on the front of the free list so it will be reused immediately
	block->next = freeStaticHeaders.next;
	block->prev = &freeStaticHeaders;
#else
	// stick it on the back of the free list so it won't be reused soon (just for debugging)
	block->next = &freeStaticHeaders;
	block->prev = freeStaticHeaders.prev;
#endif

	block->next->prev = block;
	block->prev->next = block;
}
Esempio n. 9
0
/*
========================
idIndexBuffer::AllocBufferObject
========================
*/
bool idIndexBuffer::AllocBufferObject( const void * data, int allocSize ) {
	assert( apiObject == NULL );
	assert_16_byte_aligned( data );

	if ( allocSize <= 0 ) {
		idLib::Error( "idIndexBuffer::AllocBufferObject: allocSize = %i", allocSize );
	}

	size = allocSize;

	bool allocationFailed = false;

	int numBytes = GetAllocedSize();


	// clear out any previous error
	qglGetError();

	GLuint bufferObject = 0xFFFF;
	qglGenBuffersARB( 1, & bufferObject );
	if ( bufferObject == 0xFFFF ) {
		GLenum error = qglGetError();
		idLib::FatalError( "idIndexBuffer::AllocBufferObject: failed - GL_Error %d", error );
	}
	qglBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, bufferObject );

	// these are rewritten every frame
	qglBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, numBytes, NULL, bufferUsage );
	apiObject = reinterpret_cast< void * >( bufferObject );

	GLenum err = qglGetError();
	if ( err == GL_OUT_OF_MEMORY ) {
		idLib::Warning( "idIndexBuffer:AllocBufferObject: allocation failed" );
		allocationFailed = true;
	}


	if ( r_showBuffers.GetBool() ) {
		idLib::Printf( "index buffer alloc %p, api %p (%i bytes)\n", this, GetAPIObject(), GetSize() );
	}

	// copy the data
	if ( data != NULL ) {
		Update( data, allocSize );
	}

	return !allocationFailed;
}
Esempio n. 10
0
/*
============
R_CreateVBO2
============
*/
VBO_t          *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * verts, unsigned int stateBits, vboUsage_t usage)
{
	VBO_t          *vbo;
	int             i;

	byte           *data;
	int             dataSize;
	int             dataOfs;

	int				glUsage;

	switch (usage)
	{
		case VBO_USAGE_STATIC:
			glUsage = GL_STATIC_DRAW_ARB;
			break;

		case VBO_USAGE_DYNAMIC:
			glUsage = GL_DYNAMIC_DRAW_ARB;
			break;

		default:
			Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
			return NULL;
	}

	if(!numVertexes)
		return NULL;

	if(strlen(name) >= MAX_QPATH)
	{
		ri.Error(ERR_DROP, "R_CreateVBO2: \"%s\" is too long", name);
	}

	if ( tr.numVBOs == MAX_VBOS ) {
		ri.Error( ERR_DROP, "R_CreateVBO2: MAX_VBOS hit");
	}

	R_IssuePendingRenderCommands();

	vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low);
	tr.numVBOs++;

	memset(vbo, 0, sizeof(*vbo));

	Q_strncpyz(vbo->name, name, sizeof(vbo->name));

	if (usage == VBO_USAGE_STATIC)
	{
		// since these vertex attributes are never altered, interleave them
		vbo->ofs_xyz = 0;
		dataSize = sizeof(verts[0].xyz);

		if(stateBits & ATTR_NORMAL)
		{
			vbo->ofs_normal = dataSize;
			dataSize += sizeof(uint8_t) * 4;
		}

#ifdef USE_VERT_TANGENT_SPACE
		if(stateBits & ATTR_TANGENT)
		{
			vbo->ofs_tangent = dataSize;
			dataSize += sizeof(uint8_t) * 4;
		}
#endif

		if(stateBits & ATTR_TEXCOORD)
		{
			vbo->ofs_st = dataSize;
			dataSize += sizeof(verts[0].st);
		}

		if(stateBits & ATTR_LIGHTCOORD)
		{
			vbo->ofs_lightmap = dataSize;
			dataSize += sizeof(verts[0].lightmap);
		}

		if(stateBits & ATTR_COLOR)
		{
			vbo->ofs_vertexcolor = dataSize;
			dataSize += sizeof(verts[0].vertexColors);
		}

		if(stateBits & ATTR_LIGHTDIRECTION)
		{
			vbo->ofs_lightdir = dataSize;
			dataSize += sizeof(verts[0].lightdir);
		}

		vbo->stride_xyz         = dataSize;
		vbo->stride_normal      = dataSize;
#ifdef USE_VERT_TANGENT_SPACE
		vbo->stride_tangent     = dataSize;
#endif
		vbo->stride_st          = dataSize;
		vbo->stride_lightmap    = dataSize;
		vbo->stride_vertexcolor = dataSize;
		vbo->stride_lightdir    = dataSize;

		// create VBO
		dataSize *= numVertexes;
		data = ri.Hunk_AllocateTempMemory(dataSize);
		dataOfs = 0;

		//ri.Printf(PRINT_ALL, "CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor,
			//vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor);

		for (i = 0; i < numVertexes; i++)
		{
			// xyz
			memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz));
			dataOfs += sizeof(verts[i].xyz);

			// normal
			if(stateBits & ATTR_NORMAL)
			{
				uint8_t *p = data + dataOfs;

				p[0] = (uint8_t)(verts[i].normal[0] * 127.5f + 128.0f);
				p[1] = (uint8_t)(verts[i].normal[1] * 127.5f + 128.0f);
				p[2] = (uint8_t)(verts[i].normal[2] * 127.5f + 128.0f);
				p[3] = 0;

				dataOfs += sizeof(uint8_t) * 4;
			}

#ifdef USE_VERT_TANGENT_SPACE
			// tangent
			if(stateBits & ATTR_TANGENT)
			{
				vec3_t nxt;
				uint8_t *p = data + dataOfs;

				CrossProduct(verts[i].normal, verts[i].tangent, nxt);

				p[0] = (uint8_t)(verts[i].tangent[0] * 127.5f + 128.0f);
				p[1] = (uint8_t)(verts[i].tangent[1] * 127.5f + 128.0f);
				p[2] = (uint8_t)(verts[i].tangent[2] * 127.5f + 128.0f);				
				p[3] = (uint8_t)(verts[i].tangent[3] * 127.5f + 128.0f);

				dataOfs += sizeof(uint8_t) * 4;
			}
#endif

			// vertex texcoords
			if(stateBits & ATTR_TEXCOORD)
			{
				memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st));
				dataOfs += sizeof(verts[i].st);
			}

			// feed vertex lightmap texcoords
			if(stateBits & ATTR_LIGHTCOORD)
			{
				memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap));
				dataOfs += sizeof(verts[i].lightmap);
			}

			// feed vertex colors
			if(stateBits & ATTR_COLOR)
			{
				memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors));
				dataOfs += sizeof(verts[i].vertexColors);
			}

			// feed vertex light directions
			if(stateBits & ATTR_LIGHTDIRECTION)
			{
				memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir));
				dataOfs += sizeof(verts[i].lightdir);
			}
		}
	}
	else
	{
		// since these vertex attributes may be changed, put them in flat arrays
		dataSize = sizeof(verts[0].xyz);

		if(stateBits & ATTR_NORMAL)
		{
			dataSize += sizeof(uint8_t) * 4;
		}

#ifdef USE_VERT_TANGENT_SPACE
		if(stateBits & ATTR_TANGENT)
		{
			dataSize += sizeof(uint8_t) * 4;
		}
#endif

		if(stateBits & ATTR_TEXCOORD)
		{
			dataSize += sizeof(verts[0].st);
		}

		if(stateBits & ATTR_LIGHTCOORD)
		{
			dataSize += sizeof(verts[0].lightmap);
		}

		if(stateBits & ATTR_COLOR)
		{
			dataSize += sizeof(verts[0].vertexColors);
		}

		if(stateBits & ATTR_LIGHTDIRECTION)
		{
			dataSize += sizeof(verts[0].lightdir);
		}

		// create VBO
		dataSize *= numVertexes;
		data = ri.Hunk_AllocateTempMemory(dataSize);
		dataOfs = 0;

		vbo->ofs_xyz            = 0;
		vbo->ofs_normal         = 0;
#ifdef USE_VERT_TANGENT_SPACE
		vbo->ofs_tangent        = 0;
#endif
		vbo->ofs_st             = 0;
		vbo->ofs_lightmap       = 0;
		vbo->ofs_vertexcolor    = 0;
		vbo->ofs_lightdir       = 0;

		vbo->stride_xyz         = sizeof(verts[0].xyz);
		vbo->stride_normal      = sizeof(uint8_t) * 4;
#ifdef USE_VERT_TANGENT_SPACE
		vbo->stride_tangent     = sizeof(uint8_t) * 4;
#endif
		vbo->stride_vertexcolor = sizeof(verts[0].vertexColors);
		vbo->stride_st          = sizeof(verts[0].st);
		vbo->stride_lightmap    = sizeof(verts[0].lightmap);
		vbo->stride_lightdir    = sizeof(verts[0].lightdir);

		//ri.Printf(PRINT_ALL, "2CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor,
			//vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor);

		// xyz
		for (i = 0; i < numVertexes; i++)
		{
			memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz));
			dataOfs += sizeof(verts[i].xyz);
		}

		// normal
		if(stateBits & ATTR_NORMAL)
		{
			vbo->ofs_normal = dataOfs;
			for (i = 0; i < numVertexes; i++)
			{
				uint8_t *p = data + dataOfs;

				p[0] = (uint8_t)(verts[i].normal[0] * 127.5f + 128.0f);
				p[1] = (uint8_t)(verts[i].normal[1] * 127.5f + 128.0f);
				p[2] = (uint8_t)(verts[i].normal[2] * 127.5f + 128.0f);
				p[3] = 0;

				dataOfs += sizeof(uint8_t) * 4;
			}
		}

#ifdef USE_VERT_TANGENT_SPACE
		// tangent
		if(stateBits & ATTR_TANGENT)
		{
			vbo->ofs_tangent = dataOfs;
			for (i = 0; i < numVertexes; i++)
			{
				vec3_t nxt;
				uint8_t *p = data + dataOfs;

				CrossProduct(verts[i].normal, verts[i].tangent, nxt);

				p[0] = (uint8_t)(verts[i].tangent[0] * 127.5f + 128.0f);
				p[1] = (uint8_t)(verts[i].tangent[1] * 127.5f + 128.0f);
				p[2] = (uint8_t)(verts[i].tangent[2] * 127.5f + 128.0f);
				p[3] = (uint8_t)(verts[i].tangent[3] * 127.5f + 128.0f);

				dataOfs += sizeof(uint8_t) * 4;
			}
		}
#endif

		// vertex texcoords
		if(stateBits & ATTR_TEXCOORD)
		{
			vbo->ofs_st = dataOfs;
			for (i = 0; i < numVertexes; i++)
			{
				memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st));
				dataOfs += sizeof(verts[i].st);
			}
		}

		// feed vertex lightmap texcoords
		if(stateBits & ATTR_LIGHTCOORD)
		{
			vbo->ofs_lightmap = dataOfs;
			for (i = 0; i < numVertexes; i++)
			{
				memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap));
				dataOfs += sizeof(verts[i].lightmap);
			}
		}

		// feed vertex colors
		if(stateBits & ATTR_COLOR)
		{
			vbo->ofs_vertexcolor = dataOfs;
			for (i = 0; i < numVertexes; i++)
			{
				memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors));
				dataOfs += sizeof(verts[i].vertexColors);
			}
		}

		// feed vertex lightdirs
		if(stateBits & ATTR_LIGHTDIRECTION)
		{
			vbo->ofs_lightdir = dataOfs;
			for (i = 0; i < numVertexes; i++)
			{
				memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir));
				dataOfs += sizeof(verts[i].lightdir);
			}
		}
	}


	vbo->vertexesSize = dataSize;

	qglGenBuffersARB(1, &vbo->vertexesVBO);

	qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
	qglBufferDataARB(GL_ARRAY_BUFFER_ARB, dataSize, data, glUsage);

	qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

	glState.currentVBO = NULL;

	GL_CheckErrors();

	ri.Hunk_FreeTempMemory(data);

	return vbo;
}
Esempio n. 11
0
/*
==============
RB_UpdateVBOs

Adapted from Tess_UpdateVBOs from xreal

Update the default VBO to replace the client side vertex arrays
==============
*/
void RB_UpdateVBOs(unsigned int attribBits)
{
	GLimp_LogComment("--- RB_UpdateVBOs ---\n");

	backEnd.pc.c_dynamicVboDraws++;

	// update the default VBO
	if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES)
	{
		R_BindVBO(tess.vbo);

		// orphan old buffer so we don't stall on it
		qglBufferDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->vertexesSize, NULL, GL_DYNAMIC_DRAW_ARB);

		if(attribBits & ATTR_BITS)
		{
			if(attribBits & ATTR_POSITION)
			{
				//ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]));
				qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz,         tess.numVertexes * sizeof(tess.xyz[0]),              tess.xyz);
			}

			if(attribBits & ATTR_TEXCOORD || attribBits & ATTR_LIGHTCOORD)
			{
				// these are interleaved, so we update both if either need it
				//ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2);
				qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st,          tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords);
			}

			if(attribBits & ATTR_NORMAL)
			{
				//ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]));
				qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal,      tess.numVertexes * sizeof(tess.normal[0]),           tess.normal);
			}

#ifdef USE_VERT_TANGENT_SPACE
			if(attribBits & ATTR_TANGENT)
			{
				//ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]));
				qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent,     tess.numVertexes * sizeof(tess.tangent[0]),          tess.tangent);
			}
#endif

			if(attribBits & ATTR_COLOR)
			{
				//ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]));
				qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]),     tess.vertexColors);
			}

			if(attribBits & ATTR_LIGHTDIRECTION)
			{
				//ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]));
				qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir,    tess.numVertexes * sizeof(tess.lightdir[0]),         tess.lightdir);
			}
		}
		else
		{
			qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz,         tess.numVertexes * sizeof(tess.xyz[0]),              tess.xyz);
			qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st,          tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords);
			qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal,      tess.numVertexes * sizeof(tess.normal[0]),           tess.normal);
#ifdef USE_VERT_TANGENT_SPACE
			qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent,     tess.numVertexes * sizeof(tess.tangent[0]),          tess.tangent);
#endif
			qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]),     tess.vertexColors);
			qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir,    tess.numVertexes * sizeof(tess.lightdir[0]),         tess.lightdir);
		}

	}

	// update the default IBO
	if(tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES)
	{
		R_BindIBO(tess.ibo);

		// orphan old buffer so we don't stall on it
		qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.ibo->indexesSize, NULL, GL_DYNAMIC_DRAW_ARB);

		qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes);
	}
}
Esempio n. 12
0
/*
* R_CreateMeshVBO
*
* Create two static buffer objects: vertex buffer and elements buffer, the real
* data is uploaded by calling R_UploadVBOVertexData and R_UploadVBOElemData.
*
* Tag allows vertex buffer objects to be grouped and released simultaneously.
*/
mesh_vbo_t *R_CreateMeshVBO( void *owner, int numVerts, int numElems, int numInstances,
	vattribmask_t vattribs, vbo_tag_t tag, vattribmask_t halfFloatVattribs )
{
	int i;
	size_t size;
	GLuint vbo_id;
	vbohandle_t *vboh = NULL;
	mesh_vbo_t *vbo = NULL;
	GLenum array_usage = VBO_ARRAY_USAGE_FOR_TAG(tag);
	GLenum elem_usage = VBO_ELEM_USAGE_FOR_TAG(tag);
	size_t vertexSize;
	vattribbit_t lmattrbit;

	if( !glConfig.ext.vertex_buffer_object )
		return NULL;

	if( !r_free_vbohandles )
		return NULL;

	if( !glConfig.ext.half_float_vertex ) {
		halfFloatVattribs = 0;
	}
	else {
		if( !(halfFloatVattribs & VATTRIB_POSITION_BIT) ) {
			halfFloatVattribs &= ~(VATTRIB_AUTOSPRITE_BIT);
		}

		halfFloatVattribs &= ~VATTRIB_COLORS_BITS;
		halfFloatVattribs &= ~VATTRIB_BONES_BITS;

		// TODO: convert quaternion component of instance_t to half-float
		// when uploading instances data
		halfFloatVattribs &= ~VATTRIB_INSTANCES_BITS;
	}

	vboh = r_free_vbohandles;
	vbo = &r_mesh_vbo[vboh->index];
	memset( vbo, 0, sizeof( *vbo ) );

	// vertex data
	vertexSize = 0;

	vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_POSITION_BIT, halfFloatVattribs) * 4;

	// normals data
	if( vattribs & VATTRIB_NORMAL_BIT )
	{
		assert( !(vertexSize & 3) );
		vbo->normalsOffset = vertexSize;
		vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_NORMAL_BIT, halfFloatVattribs) * 4;
	}

	// s-vectors (tangent vectors)
	if( vattribs & VATTRIB_SVECTOR_BIT )
	{
		assert( !(vertexSize & 3) );
		vbo->sVectorsOffset = vertexSize;
		vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_SVECTOR_BIT, halfFloatVattribs) * 4;
	}

	// texture coordinates
	if( vattribs & VATTRIB_TEXCOORDS_BIT )
	{
		assert( !(vertexSize & 3) );
		vbo->stOffset = vertexSize;
		vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_TEXCOORDS_BIT, halfFloatVattribs) * 2;
	}

	// lightmap texture coordinates
	lmattrbit = VATTRIB_LMCOORDS0_BIT;
	for( i = 0; i < MAX_LIGHTMAPS/2; i++ ) {
		if( !(vattribs & lmattrbit) ) {
			break;
		}
		assert( !(vertexSize & 3) );
		vbo->lmstOffset[i] = vertexSize;
		vbo->lmstSize[i] = vattribs & VATTRIB_LMCOORDS0_BIT<<1 ? 4 : 2;
		vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_LMCOORDS0_BIT, halfFloatVattribs) * vbo->lmstSize[i];
		lmattrbit = ( vattribbit_t )( ( vattribmask_t )lmattrbit << 2 );
	}

	// vertex colors
	if( vattribs & VATTRIB_COLOR0_BIT )
	{
		assert( !(vertexSize & 3) );
		vbo->colorsOffset[0] = vertexSize;
		vertexSize += sizeof( int );
	}

	// bones data for skeletal animation
	if( (vattribs & VATTRIB_BONES_BITS) == VATTRIB_BONES_BITS ) {
		assert( SKM_MAX_WEIGHTS == 4 );

		assert( !(vertexSize & 3) );
		vbo->bonesIndicesOffset = vertexSize;
		vertexSize += sizeof( int );

		assert( !(vertexSize & 3) );
		vbo->bonesWeightsOffset = vertexSize;
		vertexSize += sizeof( int );
	}

	// autosprites
	// FIXME: autosprite2 requires waaaay too much data for such a trivial
	// transformation..
	if( (vattribs & VATTRIB_AUTOSPRITE_BIT) == VATTRIB_AUTOSPRITE_BIT ) {
		assert( !(vertexSize & 3) );
		vbo->spritePointsOffset = vertexSize;
		vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_AUTOSPRITE_BIT, halfFloatVattribs) * 4;
	}

	size = vertexSize * numVerts;


	// instances data
	if( ( (vattribs & VATTRIB_INSTANCES_BITS) == VATTRIB_INSTANCES_BITS ) && 
		numInstances && glConfig.ext.instanced_arrays ) {
		assert( !(vertexSize & 3) );
		vbo->instancesOffset = size;
		size += numInstances * sizeof( GLfloat ) * 8;
	}

	// pre-allocate vertex buffer
	vbo_id = 0;
	qglGenBuffersARB( 1, &vbo_id );
	if( !vbo_id )
		goto error;
	vbo->vertexId = vbo_id;

	RB_BindArrayBuffer( vbo->vertexId );
	qglBufferDataARB( GL_ARRAY_BUFFER_ARB, size, NULL, array_usage );
	if( qglGetError () == GL_OUT_OF_MEMORY )
		goto error;

	vbo->arrayBufferSize = size;

	// pre-allocate elements buffer
	vbo_id = 0;
	qglGenBuffersARB( 1, &vbo_id );
	if( !vbo_id )
		goto error;
	vbo->elemId = vbo_id;

	size = numElems * sizeof( elem_t );
	RB_BindElementArrayBuffer( vbo->elemId );
	qglBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, size, NULL, elem_usage );
	if( qglGetError () == GL_OUT_OF_MEMORY )
		goto error;

	vbo->elemBufferSize = size;

	r_free_vbohandles = vboh->next;

	// link to the list of active vbo handles
	vboh->prev = &r_vbohandles_headnode;
	vboh->next = r_vbohandles_headnode.next;
	vboh->next->prev = vboh;
	vboh->prev->next = vboh;

	r_num_active_vbos++;

	vbo->registrationSequence = rsh.registrationSequence;
	vbo->vertexSize = vertexSize;
	vbo->numVerts = numVerts;
	vbo->numElems = numElems;
	vbo->owner = owner;
	vbo->index = vboh->index + 1;
	vbo->tag = tag;
	vbo->halfFloatAttribs = halfFloatVattribs;

	return vbo;

error:
	if( vbo )
		R_ReleaseMeshVBO( vbo );

	RB_BindArrayBuffer( 0 );
	RB_BindElementArrayBuffer( 0 );

	return NULL;
}
Esempio n. 13
0
/**
 * Draws simple colored rectangle with given parameters.
 */
void Gui_DrawRect(const GLfloat &x, const GLfloat &y,
                  const GLfloat &width, const GLfloat &height,
                  const float colorUpperLeft[], const float colorUpperRight[],
                  const float colorLowerLeft[], const float colorLowerRight[],
                  const int &blendMode,
                  const GLuint texture)
{
    switch(blendMode)
    {
        case BM_HIDE:
            return;
        case BM_MULTIPLY:
            qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
            break;
        case BM_SIMPLE_SHADE:
            qglBlendFunc(GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
            break;
        case BM_SCREEN:
            qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            break;
        default:
        case BM_OPAQUE:
            qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            break;
    };

    GLfloat x0 = x;
    GLfloat y0 = y + height;
    GLfloat x1 = x + width;
    GLfloat y1 = y;
    GLfloat *v, rectArray[32];

    v = rectArray;
   *v++ = x0; *v++ = y0;
   *v++ = 0.0f; *v++ = 0.0f;
    vec4_copy(v, colorUpperLeft);
    v += 4;

   *v++ = x1; *v++ = y0;
   *v++ = 1.0f; *v++ = 0.0f;
    vec4_copy(v, colorUpperRight);
    v += 4;

   *v++ = x1; *v++ = y1;
   *v++ = 1.0f; *v++ = 1.0f;
    vec4_copy(v, colorLowerRight);
    v += 4;

   *v++ = x0; *v++ = y1;
   *v++ = 0.0f; *v++ = 1.0f;
    vec4_copy(v, colorLowerLeft);

    if(qglIsTexture(texture))
    {
        qglBindTexture(GL_TEXTURE_2D, texture);
    }
    else
    {
        BindWhiteTexture();
    }
    qglBindBufferARB(GL_ARRAY_BUFFER, rectBuffer);
    qglBufferDataARB(GL_ARRAY_BUFFER, sizeof(GLfloat[32]), rectArray, GL_DYNAMIC_DRAW);
    qglVertexPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), (void *)0);
    qglTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), (void *)sizeof(GLfloat[2]));
    qglColorPointer(4, GL_FLOAT, 8 * sizeof(GLfloat), (void *)sizeof(GLfloat[4]));
    qglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
Esempio n. 14
0
/*
===========
idVertexCache::Alloc
===========
*/
void idVertexCache::Alloc(void *data, int size, vertCache_t **buffer, bool indexBuffer)
{
	vertCache_t	*block;

	if (size <= 0) {
		common->Error("idVertexCache::Alloc: size = %i\n", size);
	}

	// if we can't find anything, it will be NULL
	*buffer = NULL;

	// if we don't have any remaining unused headers, allocate some more
	if (freeStaticHeaders.next == &freeStaticHeaders) {

		for (int i = 0; i < EXPAND_HEADERS; i++) {
			block = headerAllocator.Alloc();
			block->next = freeStaticHeaders.next;
			block->prev = &freeStaticHeaders;
			block->next->prev = block;
			block->prev->next = block;

			if (!virtualMemory) {
				qglGenBuffersARB(1, & block->vbo);
			}
		}
	}

	// move it from the freeStaticHeaders list to the staticHeaders list
	block = freeStaticHeaders.next;
	block->next->prev = block->prev;
	block->prev->next = block->next;
	block->next = staticHeaders.next;
	block->prev = &staticHeaders;
	block->next->prev = block;
	block->prev->next = block;

	block->size = size;
	block->offset = 0;
	block->tag = TAG_USED;

	// save data for debugging
	staticAllocThisFrame += block->size;
	staticCountThisFrame++;
	staticCountTotal++;
	staticAllocTotal += block->size;

	// this will be set to zero when it is purged
	block->user = buffer;
	*buffer = block;

	// allocation doesn't imply used-for-drawing, because at level
	// load time lots of things may be created, but they aren't
	// referenced by the GPU yet, and can be purged if needed.
	block->frameUsed = currentFrame - NUM_VERTEX_FRAMES;

	block->indexBuffer = indexBuffer;

	// copy the data
	if (block->vbo) {
		if (indexBuffer) {
			qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, block->vbo);
			qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, (GLsizeiptrARB)size, data, GL_STATIC_DRAW_ARB);
		} else {
			qglBindBufferARB(GL_ARRAY_BUFFER_ARB, block->vbo);

			if (allocatingTempBuffer) {
				qglBufferDataARB(GL_ARRAY_BUFFER_ARB, (GLsizeiptrARB)size, data, GL_STREAM_DRAW_ARB);
			} else {
				qglBufferDataARB(GL_ARRAY_BUFFER_ARB, (GLsizeiptrARB)size, data, GL_STATIC_DRAW_ARB);
			}
		}
	} else {
		block->virtMem = Mem_Alloc(size);
		SIMDProcessor->Memcpy(block->virtMem, data, size);
	}
}
Esempio n. 15
0
/*
============
R_CreateIBO2
============
*/
IBO_t          *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t * triangles, vboUsage_t usage)
{
	IBO_t          *ibo;
	int             i, j;

	byte           *indexes;
	int             indexesSize;
	int             indexesOfs;

	srfTriangle_t  *tri;
	glIndex_t       index;
	int				glUsage;

	switch (usage)
	{
		case VBO_USAGE_STATIC:
			glUsage = GL_STATIC_DRAW_ARB;
			break;

		case VBO_USAGE_DYNAMIC:
			glUsage = GL_DYNAMIC_DRAW_ARB;
			break;

		default:
			Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
			return NULL;
	}

	if(!numTriangles)
		return NULL;

	if(strlen(name) >= MAX_QPATH)
	{
		ri.Error(ERR_DROP, "R_CreateIBO2: \"%s\" is too long\n", name);
	}

	if ( tr.numIBOs == MAX_IBOS ) {
		ri.Error( ERR_DROP, "R_CreateIBO2: MAX_IBOS hit\n");
	}

	// make sure the render thread is stopped
	R_SyncRenderThread();

	ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
	tr.numIBOs++;

	Q_strncpyz(ibo->name, name, sizeof(ibo->name));

	indexesSize = numTriangles * 3 * sizeof(int);
	indexes = ri.Hunk_AllocateTempMemory(indexesSize);
	indexesOfs = 0;

	for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
	{
		for(j = 0; j < 3; j++)
		{
			index = tri->indexes[j];
			memcpy(indexes + indexesOfs, &index, sizeof(glIndex_t));
			indexesOfs += sizeof(glIndex_t);
		}
	}

	ibo->indexesSize = indexesSize;

	qglGenBuffersARB(1, &ibo->indexesVBO);

	qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO);
	qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage);

	qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);

	glState.currentIBO = NULL;

	GL_CheckErrors();

	ri.Hunk_FreeTempMemory(indexes);

	return ibo;
}