Ejemplo n.º 1
0
void R_DrawFills (void)
{
	if (!r_fill_arrays.vert_index)
		return;

	R_EnableTexture(&texunit_diffuse, false);

	R_EnableColorArray(true);

	/* alter the array pointers */
	R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, r_fill_arrays.colors);
	glVertexPointer(2, GL_SHORT, 0, r_fill_arrays.verts);

	glDrawArrays(GL_QUADS, 0, r_fill_arrays.vert_index / 2);

	refdef.batchCount++;

	/* and restore them */
	R_BindDefaultArray(GL_VERTEX_ARRAY);
	R_BindDefaultArray(GL_COLOR_ARRAY);

	R_EnableColorArray(false);

	R_EnableTexture(&texunit_diffuse, true);

	r_fill_arrays.vert_index = r_fill_arrays.color_index = 0;

	R_Color(NULL);
}
Ejemplo n.º 2
0
/*
 * @brief
 */
static void R_DrawChars(void) {
	uint16_t i;

	for (i = 0; i < r_draw.num_fonts; i++) {
		r_char_arrays_t *chars = &r_draw.char_arrays[i];

		if (!chars->vert_index)
			continue;

		R_BindTexture(r_draw.fonts[i].image->texnum);

		R_EnableColorArray(true);

		// alter the array pointers
		R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, chars->colors);
		R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, chars->texcoords);
		R_BindArray(GL_VERTEX_ARRAY, GL_SHORT, chars->verts);

		glDrawArrays(GL_QUADS, 0, chars->vert_index / 2);

		chars->color_index = 0;
		chars->texcoord_index = 0;
		chars->vert_index = 0;
	}

	// restore array pointers
	R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
	R_BindDefaultArray(GL_VERTEX_ARRAY);
	R_BindDefaultArray(GL_COLOR_ARRAY);

	R_EnableColorArray(false);

	// restore draw color
	R_Color(NULL);
}
Ejemplo n.º 3
0
void R_DrawChars (void)
{
	if (!r_char_arrays.vert_index)
		return;

	R_BindTexture(draw_chars->texnum);

	R_EnableColorArray(true);

	/* alter the array pointers */
	R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, r_char_arrays.colors);
	R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, r_char_arrays.texcoords);
	glVertexPointer(2, GL_SHORT, 0, r_char_arrays.verts);

	glDrawArrays(GL_QUADS, 0, r_char_arrays.vert_index / 2);

	refdef.batchCount++;

	r_char_arrays.color_index = 0;
	r_char_arrays.texcoord_index = 0;
	r_char_arrays.vert_index = 0;

	/* and restore them */
	R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
	R_BindDefaultArray(GL_VERTEX_ARRAY);
	R_BindDefaultArray(GL_COLOR_ARRAY);

	R_EnableColorArray(false);
}
Ejemplo n.º 4
0
/*
 * @brief
 */
static void R_DrawLines(void) {

	if (!r_draw.line_arrays.vert_index)
		return;

	R_EnableTexture(&texunit_diffuse, false);

	R_EnableColorArray(true);

	// alter the array pointers
	R_BindArray(GL_VERTEX_ARRAY, GL_SHORT, r_draw.line_arrays.verts);
	R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, r_draw.line_arrays.colors);

	glDrawArrays(GL_LINES, 0, r_draw.line_arrays.vert_index / 2);

	// and restore them
	R_BindDefaultArray(GL_VERTEX_ARRAY);
	R_BindDefaultArray(GL_COLOR_ARRAY);

	R_EnableColorArray(false);

	R_EnableTexture(&texunit_diffuse, true);

	r_draw.line_arrays.vert_index = r_draw.line_arrays.color_index = 0;
}
Ejemplo n.º 5
0
/*
 * R_DrawSurfacesLines_default
 */
static void R_DrawSurfacesLines_default(const r_bsp_surfaces_t *surfs) {
	unsigned int i;

	R_EnableTexture(&texunit_diffuse, false);

	R_EnableColorArray(true);

	R_SetArrayState(r_world_model);

	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	for (i = 0; i < surfs->count; i++) {

		if (surfs->surfaces[i]->frame != r_locals.frame)
			continue;

		R_DrawSurface_default(surfs->surfaces[i]);
	}

	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	R_EnableColorArray(false);

	R_EnableTexture(&texunit_diffuse, true);
}
Ejemplo n.º 6
0
/*
 * @brief
 */
void R_DrawCoronas(void) {

	if (!r_coronas->value)
		return;

	if (!r_view.num_coronas)
		return;

	R_EnableTexture(&texunit_diffuse, false);

	R_EnableColorArray(true);

	R_ResetArrayState();

	R_BlendFunc(GL_SRC_ALPHA, GL_ONE);

	for (uint16_t i = 0; i < r_view.num_coronas; i++) {

		const r_corona_t *c = &r_view.coronas[i];
		const vec_t f = c->radius * c->flicker * sin(0.09 * r_view.time);

		// use at least 12 verts, more for larger coronas
		const uint16_t num_verts = Clamp(c->radius / 8.0, 12, 64);

		memcpy(&r_state.color_array[0], c->color, sizeof(vec3_t));
		r_state.color_array[3] = r_coronas->value; // set origin color

		// and the corner colors
		memset(&r_state.color_array[4], 0, num_verts * 2 * sizeof(vec4_t));

		memcpy(&r_state.vertex_array_3d[0], c->origin, sizeof(vec3_t));
		uint32_t vert_index = 3; // and the origin

		for (uint16_t j = 0; j <= num_verts; j++) { // now draw the corners
			const vec_t a = j / (vec_t) num_verts * M_PI * 2;

			vec3_t v;
			VectorCopy(c->origin, v);

			VectorMA(v, cos(a) * (c->radius + f), r_view.right, v);
			VectorMA(v, sin(a) * (c->radius + f), r_view.up, v);

			memcpy(&r_state.vertex_array_3d[vert_index], v, sizeof(vec3_t));
			vert_index += 3;
		}

		glDrawArrays(GL_TRIANGLE_FAN, 0, vert_index / 3);
	}

	R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	R_EnableColorArray(false);

	R_EnableTexture(&texunit_diffuse, true);

	R_Color(NULL);
}
Ejemplo n.º 7
0
/**
 * @brief Manages all state for the specified surface and stage.
 * @sa R_DrawMaterialSurfaces
 */
static void R_SetSurfaceStageState (const mBspSurface_t *surf, const materialStage_t *stage)
{
	/* bind the texture */
	R_BindTexture(stage->image->texnum);

	/* and optionally the lightmap */
	R_StageLighting(surf, stage);

	R_StageGlow(stage);

	/* load the texture matrix for rotations, stretches, etc.. */
	R_StageTextureMatrix(surf, stage);

	/* set the blend function, ensuring a good default */
	if (stage->flags & STAGE_BLEND)
		R_BlendFunc(stage->blend.src, stage->blend.dest);
	else
		R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	/* for terrain, enable the color array */
	if (stage->flags & (STAGE_TAPE | STAGE_TERRAIN | STAGE_DIRTMAP))
		R_EnableColorArray(true);
	else
		R_EnableColorArray(false);

	/* when not using the color array, resolve the shade color */
	if (!r_state.color_array_enabled) {
		vec4_t color;

		if (stage->flags & STAGE_COLOR)  /* explicit */
			VectorCopy(stage->color, color);

		else if (stage->flags & STAGE_ENVMAP)  /* implied */
			VectorCopy(surf->lightColor, color); /** @todo WTF? surely it was supposed to use the specular color */

		else  /* default */
			VectorSet(color, 1.0, 1.0, 1.0);

		/* modulate the alpha value for pulses */
		if (stage->flags & STAGE_PULSE) {
			/* disable fog, since it also sets alpha */
			R_EnableFog(false);
			color[3] = stage->pulse.dhz;
		} else {
			/* ensure fog is available */
			R_EnableFog(true);
			color[3] = 1.0;
		}

		R_Color(color);
	}
}
Ejemplo n.º 8
0
/*
 * R_SetDEfaultState
 *
 * Sets OpenGL state parameters to appropiate defaults.
 */
void R_SetDefaultState(void) {
	int i;
	r_texunit_t *tex;

	// setup vertex array pointers
	glEnableClientState(GL_VERTEX_ARRAY);
	R_BindDefaultArray(GL_VERTEX_ARRAY);

	R_EnableColorArray(true);
	R_BindDefaultArray(GL_COLOR_ARRAY);
	R_EnableColorArray(false);

	glEnableClientState(GL_NORMAL_ARRAY);
	R_BindDefaultArray(GL_NORMAL_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);

	// setup texture units
	for (i = 0; i < r_config.max_texunits && i < MAX_GL_TEXUNITS; i++) {

		tex = &r_state.texunits[i];
		tex->texture = GL_TEXTURE0_ARB + i;

		R_EnableTexture(tex, true);

		R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);

		if (i > 0) // turn them off for now
			R_EnableTexture(tex, false);
	}

	R_SelectTexture(&texunit_diffuse);

	// alpha test parameters
	glAlphaFunc(GL_GREATER, 0.25);

	// stencil test parameters
	glStencilFunc(GL_GEQUAL, 1, 0xff);
	glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);

	// fog parameters
	glFogi(GL_FOG_MODE, GL_LINEAR);
	glFogf(GL_FOG_DENSITY, 0.0);
	glFogf(GL_FOG_START, FOG_START);
	glFogf(GL_FOG_END, FOG_END);

	// alpha blend parameters
	R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
Ejemplo n.º 9
0
/*
 * @brief Draws all particles for the current frame.
 */
void R_DrawParticles(const r_element_t *e, const size_t count) {
	size_t i, j;

	R_EnableColorArray(true);

	R_ResetArrayState();

	// alter the array pointers
	R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, r_particle_state.verts);
	R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, r_particle_state.texcoords);
	R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, r_particle_state.colors);

	const GLuint base = (uintptr_t) e->data;

	for (i = j = 0; i < count; i++, e++) {
		const r_particle_t *p = (const r_particle_t *) e->element;

		// bind the particle's texture
		if (p->image->texnum != texunit_diffuse.texnum) {

			if (i > j) { // draw pending particles
				glDrawArrays(GL_QUADS, (base + j) * 4, (i - j) * 4);
				j = i;
			}

			R_BindTexture(p->image->texnum);
			R_BlendFunc(GL_SRC_ALPHA, p->blend);
		}
	}

	if (i > j) { // draw any remaining particles
		glDrawArrays(GL_QUADS, (base + j) * 4, (i - j) * 4);
	}

	// restore array pointers
	R_BindDefaultArray(GL_VERTEX_ARRAY);
	R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
	R_BindDefaultArray(GL_COLOR_ARRAY);

	R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	R_EnableColorArray(false);

	R_Color(NULL);
}
Ejemplo n.º 10
0
static void R_DrawAliasTags (const mAliasModel_t *mod)
{
	int i;
	const uint32_t color[] = {0xFF0000FF, 0xFF00FF00, 0xFFFF0000};
	glEnable(GL_LINE_SMOOTH);
	R_EnableTexture(&texunit_diffuse, false);
	R_EnableColorArray(true);

	for (i = 0; i < mod->num_tags; i++) {
		int j;
		const mAliasTag_t *tag = &mod->tags[i];
		for (j = 0; j < 3; j++) {
			vec3_t out;
			const mAliasTagOrientation_t *o = &tag->orient[mod->curFrame];
			VectorMA(o->origin, 5, o->axis[j], out);
			const vec3_t points[] = { { o->origin[0], o->origin[1], o->origin[2] }, { out[0], out[1], out[2] } };
			GLbyte colorArray[8];

			memcpy(&colorArray[0], &color[j], 4);
			memcpy(&colorArray[4], &color[j], 4);

			R_BindArray(GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, colorArray);
			R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points);
			glDrawArrays(GL_LINE_STRIP, 0, 2);

			refdef.batchCount++;
		}
	}

	/* restore default array bindings */
	R_BindDefaultArray(GL_COLOR_ARRAY);
	R_BindDefaultArray(GL_VERTEX_ARRAY);

	R_EnableColorArray(false);
	R_EnableTexture(&texunit_diffuse, true);
	glDisable(GL_LINE_SMOOTH);
}
Ejemplo n.º 11
0
/**
 * @brief Draws bounding boxes for all non-linked entities in `ents`.
 */
static void R_DrawEntityBounds(const r_entities_t *ents, const vec4_t color) {

	if (!r_draw_entity_bounds->value) {
		return;
	}

	if (ents->count == 0) {
		return;
	}

	R_BindDiffuseTexture(r_image_state.null->texnum);

	R_EnableColorArray(true);

	R_BindAttributeInterleaveBuffer(&r_model_state.bound_vertice_buffer, R_ARRAY_MASK_ALL);
	R_BindAttributeBuffer(R_ARRAY_ELEMENTS, &r_model_state.bound_element_buffer);

	u8vec4_t bc;
	ColorDecompose(color, bc);

	for (int32_t i = 0; i < 8; ++i) {
		Vector4Set(r_model_state.bound_vertices[i].color, bc[0], bc[1], bc[2], bc[3]);
	}

	static matrix4x4_t mat, modelview;

	R_GetMatrix(R_MATRIX_MODELVIEW, &modelview);

	for (size_t i = 0; i < ents->count; i++) {
		const r_entity_t *e = ents->entities[i];

		if (e->parent || (e->effects & EF_WEAPON) || !IS_MESH_MODEL(e->model)) {
			continue;
		}

		VectorSet(r_model_state.bound_vertices[0].position, e->mins[0], e->mins[1], e->mins[2]);
		VectorSet(r_model_state.bound_vertices[1].position, e->maxs[0], e->mins[1], e->mins[2]);
		VectorSet(r_model_state.bound_vertices[2].position, e->maxs[0], e->maxs[1], e->mins[2]);
		VectorSet(r_model_state.bound_vertices[3].position, e->mins[0], e->maxs[1], e->mins[2]);

		VectorSet(r_model_state.bound_vertices[4].position, e->mins[0], e->mins[1], e->maxs[2]);
		VectorSet(r_model_state.bound_vertices[5].position, e->maxs[0], e->mins[1], e->maxs[2]);
		VectorSet(r_model_state.bound_vertices[6].position, e->maxs[0], e->maxs[1], e->maxs[2]);
		VectorSet(r_model_state.bound_vertices[7].position, e->mins[0], e->maxs[1], e->maxs[2]);

		R_UploadToBuffer(&r_model_state.bound_vertice_buffer, sizeof(r_bound_interleave_vertex_t) * 8,
		                 r_model_state.bound_vertices);

		// draw box
		const vec_t *origin;

		if (e->effects & EF_BOB) {
			origin = e->termination;
		} else {
			origin = e->origin;
		}

		Matrix4x4_CreateFromEntity(&mat, origin, vec3_origin, e->scale);

		Matrix4x4_Concat(&mat, &modelview, &mat);

		R_SetMatrix(R_MATRIX_MODELVIEW, &mat);

		R_DrawArrays(GL_LINES, 0, (GLint) r_model_state.bound_element_count - 6);

		// draw origin
		Matrix4x4_CreateFromEntity(&mat, origin, e->angles, e->scale);

		Matrix4x4_Concat(&mat, &modelview, &mat);

		R_SetMatrix(R_MATRIX_MODELVIEW, &mat);

		R_DrawArrays(GL_LINES, (GLint) r_model_state.bound_element_count - 6, 6);
	}

	R_SetMatrix(R_MATRIX_MODELVIEW, &modelview);

	R_UnbindAttributeBuffer(R_ARRAY_ELEMENTS);

	R_EnableColorArray(false);

	R_Color(NULL);
}
Ejemplo n.º 12
0
void R_DrawCoronas (void)
{
	int i, j, k;
	vec3_t v;

	if (!r_coronas->integer)
		return;

	if (!refdef.numCoronas)
		return;

	R_EnableTexture(&texunit_diffuse, false);

	R_EnableColorArray(true);

	R_ResetArrayState();

	R_BlendFunc(GL_ONE, GL_ONE);

	for (k = 0; k < refdef.numCoronas; k++) {
		const corona_t *c = &refdef.coronas[k];
		int verts, vertind;

		if (!c->radius)
			continue;

		/* use at least 12 verts, more for larger coronas */
		verts = 12 + c->radius / 8;

		memcpy(&r_state.color_array[0], c->color, sizeof(vec3_t));
		r_state.color_array[3] = 1.0f; /* set origin color */

		/* and the corner colors */
		memset(&r_state.color_array[4], 0, verts * 2 * sizeof(vec4_t));

		memcpy(&r_state.vertex_array_3d[0], c->org, sizeof(vec3_t));
		vertind = 3; /* and the origin */

		for (i = verts; i >= 0; i--) { /* now draw the corners */
			const float a = (M_PI * 2 / verts) * i;

			for (j = 0; j < 3; j++)
				v[j] = c->org[j] + r_locals.right[j] * (float) cos(a) * c->radius + r_locals.up[j] * (float) sin(a)
						* c->radius;

			memcpy(&r_state.vertex_array_3d[vertind], v, sizeof(vec3_t));
			vertind += 3;
		}

		glDrawArrays(GL_TRIANGLE_FAN, 0, vertind / 3);

		refdef.batchCount++;
	}

	R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	R_EnableColorArray(false);

	R_EnableTexture(&texunit_diffuse, true);

	R_Color(nullptr);
}
Ejemplo n.º 13
0
/**
 * @brief Iterates the specified surfaces list, updating materials as they are
 * encountered, and rendering all visible stages. State is lazily managed
 * throughout the iteration, so there is a concerted effort to restore the
 * state after all surface stages have been rendered.
 */
void R_DrawMaterialSurfaces (const mBspSurfaces_t *surfs, GLushort *indexPtr)
{
	int i;

	if (!r_materials->integer || r_wire->integer)
		return;

	if (!surfs->count)
		return;

	assert(r_state.blend_enabled);

	/** @todo - integrate BSP lighting with model lighting */
	R_EnableModelLights(nullptr, 0, false, false);

	R_EnableColorArray(true);

	R_ResetArrayState();

	R_EnableColorArray(false);

	R_EnableLighting(nullptr, false);

	R_EnableTexture(&texunit_lightmap, false);

#ifndef GL_VERSION_ES_CM_1_0
	glEnable(GL_POLYGON_OFFSET_FILL);
#endif
	glPolygonOffset(-1.f, -1.f);

	glMatrixMode(GL_TEXTURE);  /* some stages will manipulate texcoords */

	for (i = 0; i < surfs->count; i++) {
		materialStage_t *s;
		mBspSurface_t *surf = surfs->surfaces[i];
		material_t *m = &surf->texinfo->image->material;
		int j = -1;

		if (surf->frame != r_locals.frame)
			continue;

		R_UpdateMaterial(m);

		for (s = m->stages; s; s = s->next, j--) {
			if (!(s->flags & STAGE_RENDER))
				continue;

			R_SetSurfaceStageState(surf, s);

			R_DrawSurfaceStage(surf, s);
		}
	}

	R_Color(nullptr);

	/* polygon offset parameters */
	glPolygonOffset(0.0, 0.0);
#ifndef GL_VERSION_ES_CM_1_0
	glDisable(GL_POLYGON_OFFSET_FILL);
#endif

	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);

	R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	R_EnableFog(true);

	R_EnableColorArray(false);

	R_EnableTexture(&texunit_lightmap, false);

	R_EnableBumpmap(nullptr);

	R_EnableLighting(nullptr, false);

	R_EnableGlowMap(nullptr);

	R_Color(nullptr);
}
Ejemplo n.º 14
0
/**
 * @brief Flares are batched by their texture.  Usually, this means one draw operation
 * for all flares in view.  Flare visibility is calculated every few millis, and
 * flare alpha is ramped up or down depending on the results of the visibility
 * trace.  Flares are also faded according to the angle of their surface to the
 * view origin.
 */
void R_DrawFlareSurfaces (const mBspSurfaces_t* surfs, glElementIndex_t* indexPtr)
{
	const image_t* image;
	int i, j, k, l, m;
	vec3_t view, verts[4];
	vec3_t right, up, upright, downright;
	float dot, dist, scale, alpha;
	bool visible;
	bool oldblend;

	if (!r_flares->integer)
		return;

	if (!surfs->count)
		return;

	oldblend = r_state.blend_enabled;

	R_EnableColorArray(true);

	R_ResetArrayState();

	/** @todo better GL state handling */
	glDisable(GL_DEPTH_TEST);
	R_EnableBlend(true);
	R_BlendFunc(GL_SRC_ALPHA, GL_ONE);

	image = r_flaretextures[0];
	R_BindTexture(image->texnum);

	j = k = l = 0;
	for (i = 0; i < surfs->count; i++) {
		mBspSurface_t* surf = surfs->surfaces[i];
		mBspFlare_t* f;

		if (surf->frame != r_locals.frame)
			continue;

		f = surf->flare;

		/* bind the flare's texture */
		if (f->image != image) {
			R_DrawArrays(0, l / 3);
			j = k = l = 0;

			refdef.batchCount++;

			image = f->image;
			R_BindTexture(image->texnum);
		}

		/* periodically test visibility to ramp alpha */
		if (refdef.time - f->time > 0.02) {
			if (refdef.time - f->time > 0.5) /* reset old flares */
				f->alpha = 0;

			R_Trace(refdef.viewOrigin, f->origin, 0, MASK_SOLID);
			visible = refdef.trace.fraction == 1.0;

			f->alpha += (visible ? 0.03 : -0.15); /* ramp */

			if (f->alpha > 0.75) /* clamp */
				f->alpha = 0.75;
			else if (f->alpha < 0)
				f->alpha = 0.0;

			f->time = refdef.time;
		}

		VectorSubtract(f->origin, refdef.viewOrigin, view);
		dist = VectorNormalize(view);

		/* fade according to angle */
		dot = DotProduct(surf->normal, view);
		if (dot > 0)
			continue;

		alpha = 0.1 + -dot * r_flares->value;

		if (alpha > 1.0)
			alpha = 1.0;

		alpha = f->alpha * alpha;

		/* scale according to distance */
		scale = f->radius + (f->radius * dist * .0005);

		VectorScale(r_locals.right, scale, right);
		VectorScale(r_locals.up, scale, up);

		VectorAdd(up, right, upright);
		VectorSubtract(right, up, downright);

		VectorSubtract(f->origin, downright, verts[0]);
		VectorAdd(f->origin, upright, verts[1]);
		VectorAdd(f->origin, downright, verts[2]);
		VectorSubtract(f->origin, upright, verts[3]);

		for (m = 0; m < 4; m++) { /* duplicate color data to all 4 verts */
			memcpy(&r_state.color_array[j], f->color, sizeof(vec3_t));
			r_state.color_array[j + 3] = alpha;
			j += 4;
		}

		/* copy texcoord info */
		memcpy(&texunit_diffuse.texcoord_array[k], default_texcoords, sizeof(vec2_t) * 4);
		k += sizeof(vec2_t) / sizeof(vec_t) * 4;

		/* and lastly copy the 4 verts */
		memcpy(&r_state.vertex_array_3d[l], verts, sizeof(vec3_t) * 4);
		l += sizeof(vec3_t) / sizeof(vec_t) * 4;
	}

	R_DrawArrays(0, l / 3);

	refdef.batchCount++;

	R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	R_EnableBlend(oldblend);
	glEnable(GL_DEPTH_TEST);

	R_EnableColorArray(false);

	R_Color(nullptr);
}