Beispiel #1
0
/*
 * R_EnableColorShell
 */
void R_EnableShell(boolean_t enable) {

	if (enable == r_state.shell_enabled)
		return;

	r_state.shell_enabled = enable;

	if (enable) {
		glEnable(GL_POLYGON_OFFSET_FILL);
		glPolygonOffset(-1.0, 0.0);

		R_EnableBlend(true);
		R_BlendFunc(GL_SRC_ALPHA, GL_ONE);

		if (r_state.lighting_enabled)
			R_ProgramParameter1f("OFFSET", r_view.time / 3.0);
	} else {
		R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		R_EnableBlend(false);

		glPolygonOffset(0.0, 0.0);
		glDisable(GL_POLYGON_OFFSET_FILL);

		if (r_state.lighting_enabled)
			R_ProgramParameter1f("OFFSET", 0.0);
	}
}
/**
 * @sa R_DrawParticles
 */
static void R_SetBlendMode (int mode)
{
	switch (mode) {
	case BLEND_REPLACE:
		R_TexEnv(GL_REPLACE);
		break;
	case BLEND_ONE:
		R_BlendFunc(GL_SRC_ALPHA, GL_ONE);
		break;
	case BLEND_BLEND:
		R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		break;
	case BLEND_ADD:
		R_BlendFunc(GL_ONE, GL_ONE);
		break;
	case BLEND_FILTER:
		R_BlendFunc(GL_ZERO, GL_SRC_COLOR);
		break;
	case BLEND_INVFILTER:
		R_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
		break;
	default:
		Com_Error(ERR_DROP, "unknown blend mode");
		break;
	}
}
Beispiel #3
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);
}
Beispiel #4
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);
	}
}
Beispiel #5
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);
}
Beispiel #6
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);
}
/**
 * @note No need to reset the blend mode - R_Setup2D will do this
 * @sa R_Setup2D
 */
void R_DrawParticles (void)
{
	ptl_t *p;
	int i;

	if (!r_particles->integer)
		return;

	for (i = 0, p = r_particleArray; i < r_numParticles; i++, p++)
		if (p->inuse && !p->invis) {
			/* test for visibility */
			if (p->levelFlags && !((1 << refdef.worldlevel) & p->levelFlags))
				continue;

			if (p->program != NULL)
				R_UseProgram(p->program);

			/* set blend mode and draw gfx */
			R_SetBlendMode(p->blend);
			switch (p->style) {
			case STYLE_LINE:
				R_DrawPtlLine(p);
				break;
			case STYLE_CIRCLE:
				R_DrawPtlCircle(p);
				break;
			default:
				break;
			}
			if (p->pic)
				R_DrawSprite(p);
			if (p->model)
				R_DrawParticleModel(p);
			R_TexEnv(GL_MODULATE);

			R_UseProgram(NULL);
		}

	R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	R_Color(NULL);
}
Beispiel #8
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);
}
Beispiel #9
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);
}
Beispiel #10
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);
}