/*
 ==================
 R_AllocDecal
 ==================
*/
static decal_t *R_AllocDecal (){

	decal_t	*decal;

	// Allocate a slot, freeing the oldest if necessary
	if (!r_freeDecals)
		R_FreeDecal(r_activeDecals.prev);

	decal = r_freeDecals;

	// Link
	r_freeDecals = r_freeDecals->next;

	Mem_Fill(decal, 0, sizeof(decal_t));

	decal->next = r_activeDecals.next;
	decal->prev = &r_activeDecals;

	r_activeDecals.next->prev = decal;
	r_activeDecals.next = decal;

	return decal;
}
Exemple #2
0
/*
=================
R_DrawDecals

Draws all decals on the decal list
=================
*/
void R_DrawDecals (void)
{
	cdecal_t    *dl, *next, *active;
	float		mindist, time;
	int			r_numdecals = 0;
	vec3_t		v;
	vec4_t		color;

	if (!gl_decals->value)
		return;

	if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
		return;

	active = &active_decals;

	mindist = DotProduct(r_origin, vpn) + 4.0;

	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonOffset(-2, -2);

	GL_Enable(BLEND_BIT | DEPTHTEST_BIT);

	GL_UseProgram(gl_decalprog);

	glProgramUniformMatrix4fv (gl_decalprog, gl_decalmvpMatrix, 1, GL_FALSE, r_mvpmatrix.m[0]);

	for (dl = active->next; dl != active; dl = next)
	{
		next = dl->next;

		if (dl->node == NULL || dl->node->visframe != r_visframecount)
			continue;

		// check type
		if (dl->type < 0 || dl->type > MAX_DECAL_TEX)
		{
			R_FreeDecal (dl);
			continue;
		}

		// have we faded out yet?
		if (dl->time + gl_decalsTime->value <= r_newrefdef.time)
		{
			R_FreeDecal (dl);
			continue;
		}

		// do not render if the decal is behind the view
		if (DotProduct(dl->org, vpn) < mindist)
			continue;

		// do not render if the view origin is behind the decal
		VectorSubtract(dl->org, r_origin, v);
		if (DotProduct(dl->direction, v) < 0)
			continue;

		Vector4Copy(dl->color, color);

		time = dl->time + gl_decalsTime->value - r_newrefdef.time;
		if (time < 1.5)
			color[3] *= time / 1.5;

		// bind texture
		GL_BindTexture(GL_TEXTURE0, GL_TEXTURE_2D, r_drawnearestclampsampler, r_decalImages[dl->type]);

		// bind data into vbo
		glBindBuffer(GL_ARRAY_BUFFER, gl_decalvbo);
		glBufferData(GL_ARRAY_BUFFER, sizeof(dl->verts) + sizeof(dl->stcoords) + sizeof(color), NULL, GL_DYNAMIC_DRAW);
		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(dl->verts), dl->verts);
		glBufferSubData(GL_ARRAY_BUFFER, sizeof(dl->verts), sizeof(dl->stcoords), dl->stcoords);
		glBufferSubData(GL_ARRAY_BUFFER, sizeof(dl->verts) + sizeof(dl->stcoords), sizeof(color), color);

		// bind vao
		GL_BindVertexArray(gl_decalvao);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void *)sizeof(dl->verts));
		glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (void *)(sizeof(dl->verts) + sizeof(dl->stcoords)));

		// draw
		glDrawArrays(GL_TRIANGLE_FAN, 0, dl->numverts);

		r_numdecals++;
		if (r_numdecals >= MAX_DECALS)
			break;
	}

	glDisable(GL_POLYGON_OFFSET_FILL);
}