示例#1
0
static void R_UploadLightmapBlock (void)
{
#ifdef GL_VERSION_ES_CM_1_0
	const int texFormat = GL_RGB;
#else
	const int texFormat = r_config.gl_compressed_solid_format ? r_config.gl_compressed_solid_format : r_config.gl_solid_format;
#endif
	GLuint texid;
	if (r_lightmaps.lightmap_count >= MAX_GL_LIGHTMAPS) {
		Com_Printf("R_UploadLightmapBlock: MAX_GL_LIGHTMAPS reached.\n");
		return;
	}

	if (!r_lightmaps.incomplete_atlas) {
		glGenTextures(1, &texid);
		r_lightmaps.lightmap_texnums[r_lightmaps.lightmap_count++] = texid;
	} else {
		texid = r_lightmaps.lightmap_texnums[r_lightmaps.lightmap_count];
	}

	R_BindTexture(texid);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	glTexImage2D(GL_TEXTURE_2D, 0, texFormat, r_lightmaps.size, r_lightmaps.size,
		0, GL_RGB, GL_UNSIGNED_BYTE, r_lightmaps.sample_buffer);

	R_CheckError();

	if (r_lightmaps.deluxemap_count >= MAX_GL_DELUXEMAPS) {
		Com_Printf("R_UploadLightmapBlock: MAX_GL_DELUXEMAPS reached.\n");
		return;
	}

	if (!r_lightmaps.incomplete_atlas) {
		glGenTextures(1, &texid);
		r_lightmaps.deluxemap_texnums[r_lightmaps.deluxemap_count++] = texid;
	} else {
		texid = r_lightmaps.deluxemap_texnums[r_lightmaps.deluxemap_count];
	}

	R_BindTexture(texid);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	glTexImage2D(GL_TEXTURE_2D, 0, texFormat, r_lightmaps.size, r_lightmaps.size,
		0, GL_RGB, GL_UNSIGNED_BYTE, r_lightmaps.direction_buffer);

	/* clear the allocation block and buffers */
	memset(r_lightmaps.allocated, 0, r_lightmaps.size * sizeof(unsigned));
	memset(r_lightmaps.sample_buffer, 0, r_lightmaps.size * r_lightmaps.size * sizeof(unsigned));
	memset(r_lightmaps.direction_buffer, 0, r_lightmaps.size * r_lightmaps.size * sizeof(unsigned));

	r_lightmaps.incomplete_atlas = false;
}
示例#2
0
/**
 * @brief Bind and draw a texture
 * @param[in] texnum The texture id (already uploaded of course)
 * @param[in] x normalized x value on the screen
 * @param[in] y normalized y value on the screen
 * @param[in] w normalized width value
 * @param[in] h normalized height value
 */
void R_DrawTexture (int texnum, int x, int y, int w, int h)
{
	const vec2_t vertexes[] = {{x, y}, {x + w, y}, {x + w, y + h}, {x, y + h}};

	R_BindTexture(texnum);
	R_DrawImageArray(default_texcoords, vertexes, NULL);
}
示例#3
0
/**
 * @brief Set the surface state according to surface flags and bind the texture
 * @sa R_DrawSurfaces
 */
static void R_SetSurfaceState (const mBspSurface_t *surf)
{
	image_t *image;

	if (r_state.blend_enabled) {  /* alpha blend */
		vec4_t color = {1.0, 1.0, 1.0, 1.0};
		switch (surf->texinfo->flags & (SURF_BLEND33 | SURF_BLEND66)) {
		case SURF_BLEND33:
			color[3] = 0.33;
			break;
		case SURF_BLEND66:
			color[3] = 0.66;
			break;
		}

		R_Color(color);
	}

	image = surf->texinfo->image;
	R_BindTexture(image->texnum);  /* texture */

	if (texunit_lightmap.enabled) {  /* lightmap */
		if (surf->flags & MSURF_LIGHTMAP)
			R_BindLightmapTexture(surf->lightmap_texnum);
	}

	R_SetSurfaceBumpMappingParameters(surf, image->normalmap, image->specularmap);

	R_EnableGlowMap(image->glowmap);

	R_CheckError();
}
示例#4
0
文件: r_entity.c 项目: kevlund/ufoai
/**
 * @brief Draws a marker on the ground to indicate pathing CL_AddPathingBox
 * @sa CL_AddPathing
 * @sa RF_BOX
 */
static void R_DrawFloor (const entity_t * e)
{
	image_t *cellIndicator = R_FindImage("pics/sfx/cell", it_pic);
	const float dx = PLAYER_WIDTH * 2;
	const vec4_t color = {e->color[0], e->color[1], e->color[2], e->alpha};
	const float size = 4.0;
	/** @todo use default_texcoords */
	const vec2_t texcoords[] = { { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 0.0 } };
	const vec3_t points[] = { { e->origin[0] - size, e->origin[1] + dx + size, e->origin[2] }, { e->origin[0] + dx
			+ size, e->origin[1] + dx + size, e->origin[2] }, { e->origin[0] + dx + size, e->origin[1] - size,
			e->origin[2] }, { e->origin[0] - size, e->origin[1] - size, e->origin[2] } };

	glDisable(GL_DEPTH_TEST);

	R_Color(color);
	R_BindTexture(cellIndicator->texnum);

	/* circle points */
	R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords);
	R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points);
	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
	R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
	R_BindDefaultArray(GL_VERTEX_ARRAY);

	refdef.batchCount++;

	glEnable(GL_DEPTH_TEST);

	R_Color(NULL);
}
示例#5
0
/*
 * @brief Uploads the specified image to the OpenGL implementation. Images that
 * do not have a GL texture reserved (which is most diffuse textures) will have
 * one generated for them. This flexibility allows for explicitly managed
 * textures (such as lightmaps) to be here as well.
 */
void R_UploadImage(r_image_t *image, GLenum format, byte *data) {

	if (!image || !data) {
		Com_Error(ERR_DROP, "NULL image or data\n");
	}

	if (!image->texnum) {
		glGenTextures(1, &(image->texnum));
	}

	R_BindTexture(image->texnum);

	if (image->type & IT_MASK_MIPMAP) {
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_image_state.filter_min);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_image_state.filter_mag);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_image_state.anisotropy);
		glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
	} else {
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_image_state.filter_mag);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_image_state.filter_mag);
		glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
	}

	glTexImage2D(GL_TEXTURE_2D, 0, format, image->width, image->height, 0, format,
			GL_UNSIGNED_BYTE, data);

	R_RegisterMedia((r_media_t *) image);

	R_GetError(image->media.name);
}
示例#6
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);
}
示例#7
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);
}
示例#8
0
文件: r_state.c 项目: darkshade9/aq2w
/*
 * R_EnableWarp
 */
void R_EnableWarp(r_program_t *program, boolean_t enable) {

	if (!r_programs->value)
		return;

	if (enable && (!program || !program->id))
		return;

	if (!r_warp->value || r_state.warp_enabled == enable)
		return;

	r_state.warp_enabled = enable;

	R_SelectTexture(&texunit_lightmap);

	if (enable) {
		glEnable(GL_TEXTURE_2D);

		R_BindTexture(r_warp_image->texnum);

		R_UseProgram(program);
	} else {
		glDisable(GL_TEXTURE_2D);

		R_UseProgram(NULL);
	}

	R_SelectTexture(&texunit_diffuse);
}
示例#9
0
/**
 * @sa R_DrawParticles
 */
static void R_DrawSprite (const ptl_t * p)
{
	const ptl_t *q;
	vec3_t up, right;
	vec3_t nup, nright;
	vec3_t pos;
	float texcoords[8];

	/* load texture set up coordinates */
	assert(p->pic);
	R_BindTexture(p->pic->art.image->texnum);

	/* calculate main position and normalised up and right vectors */
	q = p->parent ? p->parent : p;
	R_GetSpriteVectors(q, right, up);

	/* Calculate normalised */
	VectorCopy(up, nup);
	VectorCopy(right, nright);
	VectorNormalizeFast(nup);
	VectorNormalizeFast(nright);

	/* offset */
	VectorCopy(q->s, pos);
	VectorMA(pos, q->offset[0], nup, pos);
	VectorMA(pos, q->offset[1], nright, pos);

	if (p->parent) {
		/* if this is a child then calculate our own up and right vectors and offsets */
		R_GetSpriteVectors(p, right, up);

		/* but offset by our parent's nup and nright */
		VectorMA(pos, p->offset[0], nup, pos);
		VectorMA(pos, p->offset[1], nright, pos);
	}

	/* center image */
	VectorMA(pos, -0.5, up, pos);
	VectorMA(pos, -0.5, right, pos);

	R_SpriteTexcoords(p, texcoords);

	R_Color(p->color);
	{
		/* draw it */
		const vec3_t points[] = { { pos[0], pos[1], pos[2] }, { pos[0] + up[0], pos[1] + up[1], pos[2] + up[2] }, { pos[0]
				+ up[0] + right[0], pos[1] + up[1] + right[1], pos[2] + up[2] + right[2] }, { pos[0] + right[0], pos[1]
				+ right[1], pos[2] + right[2] } };

		R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords);
		R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points);
		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
		R_BindDefaultArray(GL_VERTEX_ARRAY);
		R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);

		refdef.batchCount++;
	}
}
示例#10
0
/**
 * @brief Draws the field marker entity is specified in CL_AddTargeting
 * @sa CL_AddTargeting
 * @sa RF_BOX
 */
static void R_DrawBox (const entity_t* e)
{
	const vec4_t color = {e->color[0], e->color[1], e->color[2], e->alpha};

	if (e->texture) {
		R_Color(color);
		R_BindTexture(e->texture->texnum);
		if (VectorNotEmpty(e->eBox.mins) && VectorNotEmpty(e->eBox.maxs)) {
			R_DrawTexturedBox(e->eBox.mins, e->eBox.maxs);
		} else {
			R_DrawTexturedBox(e->oldorigin, e->origin);
		}
		R_Color(nullptr);
		return;
	}

	glDisable(GL_TEXTURE_2D);

	R_Color(color);

	if (VectorNotEmpty(e->eBox.mins) && VectorNotEmpty(e->eBox.maxs)) {
		R_DrawBoundingBox(e->eBox);
	} else {
		vec3_t points[] = { { e->oldorigin[0], e->oldorigin[1], e->oldorigin[2] }, { e->oldorigin[0], e->origin[1],
				e->oldorigin[2] }, { e->origin[0], e->origin[1], e->oldorigin[2] }, { e->origin[0], e->oldorigin[1],
				e->oldorigin[2] } };

		glLineWidth(2.0f);
		R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points);

		/** @todo fill one array */
		glDrawArrays(GL_LINE_LOOP, 0, 4);
		refdef.batchCount++;
		points[0][2] = e->origin[2];
		points[1][2] = e->origin[2];
		points[2][2] = e->origin[2];
		points[3][2] = e->origin[2];
		glDrawArrays(GL_LINE_LOOP, 0, 4);
		refdef.batchCount++;
		points[0][2] = e->oldorigin[2];
		points[1][1] = e->oldorigin[1];
		points[2][2] = e->oldorigin[2];
		points[3][1] = e->origin[1];
		glDrawArrays(GL_LINES, 0, 4);
		refdef.batchCount++;
		points[0][0] = e->origin[0];
		points[1][0] = e->origin[0];
		points[2][0] = e->oldorigin[0];
		points[3][0] = e->oldorigin[0];
		glDrawArrays(GL_LINES, 0, 4);
		refdef.batchCount++;
		R_BindDefaultArray(GL_VERTEX_ARRAY);
	}
	glEnable(GL_TEXTURE_2D);

	R_Color(nullptr);
}
示例#11
0
/**
 * @brief Uploads image data
 * @param[in] name The name of the texture to use for this data
 * @param[in] frame The frame data that is uploaded
 * @param[in] width The width of the texture
 * @param[in] height The height of the texture
 * @return the texture number of the uploaded images
 */
int R_UploadData (const char *name, byte *frame, int width, int height)
{
	image_t *img;
	unsigned *scaled;
	int scaledWidth, scaledHeight;
	int samples = r_config.gl_compressed_solid_format ? r_config.gl_compressed_solid_format : r_config.gl_solid_format;
	int i, c;
	byte *scan;

	R_GetScaledTextureSize(width, height, &scaledWidth, &scaledHeight);

	img = R_FindImage(name, it_pic);
	if (img == r_noTexture)
		Com_Error(ERR_FATAL, "Could not find the searched image: %s", name);

	/* scan the texture for any non-255 alpha */
	c = scaledWidth * scaledHeight;
	/* set scan to the first alpha byte */
	for (i = 0, scan = ((byte *) frame) + 3; i < c; i++, scan += 4) {
		if (*scan != 255) {
			samples = r_config.gl_compressed_alpha_format ? r_config.gl_compressed_alpha_format : r_config.gl_alpha_format;
			break;
		}
	}

	if (scaledWidth != width || scaledHeight != height) {  /* whereas others need to be scaled */
		scaled = (unsigned *)Mem_PoolAllocExt(scaledWidth * scaledHeight * sizeof(unsigned), qfalse, vid_imagePool, 0);
		R_ScaleTexture((unsigned *)frame, width, height, scaled, scaledWidth, scaledHeight);
	} else {
		scaled = (unsigned *)frame;
	}

	R_BindTexture(img->texnum);
	if (img->upload_width == scaledWidth && img->upload_height == scaledHeight) {
		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, scaledWidth, scaledHeight, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
	} else {
		/* Reallocate the texture */
		img->width = width;
		img->height = height;
		img->upload_width = scaledWidth;
		img->upload_height = scaledHeight;
#ifdef HAVE_GLES
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, scaledWidth, scaledHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
#else
		glTexImage2D(GL_TEXTURE_2D, 0, samples, scaledWidth, scaledHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
#endif
	}
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	R_CheckError();

	if (scaled != (unsigned *)frame)
		Mem_Free(scaled);

	return img->texnum;
}
示例#12
0
文件: r_state.c 项目: darkshade9/aq2w
/*
 * R_BindNormalmapTexture
 */
void R_BindNormalmapTexture(GLuint texnum) {

	if (texnum == texunit_normalmap.texnum)
		return; // small optimization to save state changes

	R_SelectTexture(&texunit_normalmap);

	R_BindTexture(texnum);

	R_SelectTexture(&texunit_diffuse);
}
示例#13
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);
	}
}
示例#14
0
/*
 * @brief
 */
void R_DrawSkyBox(void) {
	const int32_t sky_order[6] = { 0, 2, 1, 3, 4, 5 };
	r_bsp_surfaces_t *surfs;
	uint32_t i, j;

	surfs = &r_model_state.world->bsp->sorted_surfaces->sky;
	j = 0;

	// first add all visible sky surfaces to the sky bounds
	for (i = 0; i < surfs->count; i++) {
		if (surfs->surfaces[i]->frame == r_locals.frame) {
			R_AddSkySurface(surfs->surfaces[i]);
			j++;
		}
	}

	if (!j) // no visible sky surfaces
		return;

	R_ResetArrayState();

	glPushMatrix();
	glTranslatef(r_view.origin[0], r_view.origin[1], r_view.origin[2]);

	if (r_state.fog_enabled)
		glFogf(GL_FOG_END, FOG_END * 8);

	r_sky.texcoord_index = r_sky.vert_index = 0;

	for (i = 0; i < 6; i++) {

		if (r_sky.st_mins[0][i] >= r_sky.st_maxs[0][i] || r_sky.st_mins[1][i]
				>= r_sky.st_maxs[1][i])
			continue; // nothing on this plane

		R_BindTexture(r_sky.images[sky_order[i]]->texnum);

		R_MakeSkyVec(r_sky.st_mins[0][i], r_sky.st_mins[1][i], i);
		R_MakeSkyVec(r_sky.st_mins[0][i], r_sky.st_maxs[1][i], i);
		R_MakeSkyVec(r_sky.st_maxs[0][i], r_sky.st_maxs[1][i], i);
		R_MakeSkyVec(r_sky.st_maxs[0][i], r_sky.st_mins[1][i], i);

		glDrawArrays(GL_QUADS, 0, r_sky.vert_index / 3);
		r_sky.texcoord_index = r_sky.vert_index = 0;
	}

	if (r_state.fog_enabled)
		glFogf(GL_FOG_END, FOG_END);

	glPopMatrix();
}
示例#15
0
/*
 * R_SetSurfaceState_default
 */
static void R_SetSurfaceState_default(const r_bsp_surface_t *surf) {
	r_image_t *image;
	float a;

	if (r_state.blend_enabled) { // alpha blend
		switch (surf->texinfo->flags & (SURF_BLEND_33 | SURF_BLEND_66)) {
		case SURF_BLEND_33:
			a = 0.33;
			break;
		case SURF_BLEND_66:
			a = 0.66;
			break;
		default: // both flags mean use the texture's alpha channel
			a = 1.0;
			break;
		}

		glColor4f(1.0, 1.0, 1.0, a);
	}

	image = surf->texinfo->image;

	if (texunit_diffuse.enabled) // diffuse texture
		R_BindTexture(image->texnum);

	if (texunit_lightmap.enabled) // lightmap texture
		R_BindLightmapTexture(surf->lightmap_texnum);

	if (r_state.lighting_enabled) { // hardware lighting

		if (r_bumpmap->value) { // bump mapping

			if (image->normalmap) {
				R_BindDeluxemapTexture(surf->deluxemap_texnum);
				R_BindNormalmapTexture(image->normalmap->texnum);

				R_EnableBumpmap(&image->material, true);
			} else
				R_EnableBumpmap(NULL, false);
		}

		if (surf->light_frame == r_locals.light_frame) // dynamic light sources
			R_EnableLights(surf->lights);
		else
			R_EnableLights(0);
	}
}
示例#16
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);
}
示例#17
0
void R_DrawGrass ()
{
	if (clumpTriangleCount <= 0)
		return;

	R_BindTexture(R_FindImage("models/objects/vegi/plants2/plant_skin3", it_pic)->texnum);

	R_EnableAlphaTest(true);

	R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, gfv_texcoord);
	R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, gfv_pos);
	glDrawArrays(GL_TRIANGLES, 0, clumpTrianglesForLevel[refdef.worldlevel] * 3);
	R_BindDefaultArray(GL_VERTEX_ARRAY);
	R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);

	R_EnableAlphaTest(false);

	refdef.batchCount++;
}
示例#18
0
const image_t *R_DrawImageArray (const vec2_t texcoords[4], const vec2_t verts[4], const image_t *image)
{
	/* alter the array pointers */
	glVertexPointer(2, GL_FLOAT, 0, verts);
	R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords);

	if (image != NULL)
		R_BindTexture(image->texnum);

	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

	refdef.batchCount++;

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

	return image;
}
示例#19
0
/**
 * @brief Renders a particle model for the battlescape
 * @param[in,out] mi The model information that is used to render the particle model.
 * @sa R_DrawPtlModel
 */
void R_DrawModelParticle (modelInfo_t * mi)
{
	image_t *skin;
	mAliasMesh_t *mesh;

	/* check if the model exists */
	if (!mi->model)
		return;

	skin = R_AliasModelState(mi->model, &mi->mesh, &mi->frame, &mi->oldframe, &mi->skin);
	if (skin == NULL) {
		Com_Printf("Model '%s' is broken\n", mi->name);
		return;
	}

	R_Color(mi->color);

	glPushMatrix();

	glTranslatef(mi->origin[0], mi->origin[1], mi->origin[2]);
	glRotatef(mi->angles[YAW], 0, 0, 1);
	glRotatef(mi->angles[PITCH], 0, 1, 0);
	glRotatef(-mi->angles[ROLL], 1, 0, 0);

	/* draw it */
	R_BindTexture(skin->texnum);

	/* draw the model */
	mesh = &mi->model->alias.meshes[0];
	refdef.aliasCount += mesh->num_tris;
	if (mi->model->alias.num_frames == 1)
		R_DrawAliasStaticWithReset(mesh, vec4_origin);
	else
		R_DrawAliasFrameLerp(&mi->model->alias, mesh, mi->backlerp, mi->frame, mi->oldframe, vec4_origin);

	/* show model bounding box */
	if (r_showbox->integer)
		R_DrawBoundingBox(mi->model->alias.frames[mi->frame].mins, mi->model->alias.frames[mi->frame].maxs);

	glPopMatrix();

	R_Color(NULL);
}
示例#20
0
/*
 * @brief
 */
void R_DrawImage(r_pixel_t x, r_pixel_t y, vec_t scale, const r_image_t *image) {

	R_BindTexture(image->texnum);

	// our texcoords are already setup, just set verts and draw

	r_state.vertex_array_2d[0] = x;
	r_state.vertex_array_2d[1] = y;

	r_state.vertex_array_2d[2] = x + image->width * scale;
	r_state.vertex_array_2d[3] = y;

	r_state.vertex_array_2d[4] = x + image->width * scale;
	r_state.vertex_array_2d[5] = y + image->height * scale;

	r_state.vertex_array_2d[6] = x;
	r_state.vertex_array_2d[7] = y + image->height * scale;

	glDrawArrays(GL_QUADS, 0, 4);
}
示例#21
0
/**
 * @brief Draws an animated, colored shell for the specified entity. Rather than
 * re-lerping or re-scaling the entity, the currently bound vertex arrays
 * are simply re-drawn using a small depth offset and varying texcoord delta.
 */
static void R_DrawMeshModelShell (const mAliasMesh_t *mesh, const vec4_t color)
{
	/* check whether rgb is set */
	if (!VectorNotEmpty(color))
		return;

	R_Color(color);

	R_BindTexture(r_envmaptextures[1]->texnum);

	R_EnableShell(true);

	glDrawArrays(GL_TRIANGLES, 0, mesh->num_tris * 3);

	refdef.batchCount++;

	R_EnableShell(false);

	R_Color(NULL);
}
示例#22
0
/**
 * @brief Draws a marker on the ground to indicate pathing CL_AddPathingBox
 * @sa CL_AddPathing
 * @sa RF_BOX
 */
static void R_DrawFloor (const entity_t* e)
{
	GLint oldDepthFunc;
	glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);

	image_t* cellIndicator = R_FindImage("pics/sfx/cell", it_pic);
	const float dx = PLAYER_WIDTH * 2;
	const vec4_t color = {e->color[0], e->color[1], e->color[2], e->alpha};
	const float size = 4.0;
	/** @todo use default_texcoords */
	const vec2_t texcoords[] = { { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 0.0 } };
	const vec3_t points[] = { { e->origin[0] - size, e->origin[1] + dx + size, e->origin[2] }, { e->origin[0] + dx
			+ size, e->origin[1] + dx + size, e->origin[2] }, { e->origin[0] + dx + size, e->origin[1] - size,
			e->origin[2] }, { e->origin[0] - size, e->origin[1] - size, e->origin[2] } };

	/* Draw it twice, with and without depth check, so it will still be visible if obscured by a wall */
	R_Color(color);
	R_BindTexture(cellIndicator->texnum);

	/* circle points */
	R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords);
	R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points);
	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

	glDepthFunc(GL_GREATER);
	glColor4f(color[0], color[1], color[2], color[3] * 0.25f);

	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

	glDepthFunc(oldDepthFunc);

	R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
	R_BindDefaultArray(GL_VERTEX_ARRAY);

	refdef.batchCount += 2;

	R_Color(nullptr);
}
示例#23
0
/**
 * @brief Bind and draw starfield.
 * @param[in] texnum The texture id (already uploaded of course)
 * @note We draw a skybox: the camera is inside a cube rotating at earth rotation speed
 * (stars seems to rotate because we see earth as idle, but in reality stars are statics
 * and earth rotate around itself)
 * @sa R_Setup2D
 * @sa R_Draw3DGlobe
 */
static void R_DrawStarfield (int texnum, const vec3_t pos, const vec3_t rotate, float p)
{
	vec3_t angle;		/**< Angle of rotation of starfield */

	/* go to a new matrix */
	glPushMatrix();

	/* we must center the skybox on the camera border of view, and not on the earth, in order
	 * to see only the inside of the cube */
	glTranslatef(pos[0], pos[1], -SKYBOX_DEPTH);

	/* rotates starfield: only time and rotation of earth around itself causes starfield to rotate. */
	VectorSet(angle, rotate[0] - p * todeg, rotate[1], rotate[2]);
	glRotatef(angle[YAW], 1, 0, 0);
	glRotatef(angle[ROLL], 0, 1, 0);
	glRotatef(angle[PITCH], 0, 0, 1);

	R_BindTexture(texnum);

	/* alter the array pointers */
	glVertexPointer(3, GL_FLOAT, 0, starFieldVerts);
	glTexCoordPointer(2, GL_FLOAT, 0, starFieldTexCoords);

	/* draw the cube */
#ifdef GL_VERSION_ES_CM_1_0
	for( int ii = 0; ii < 6; ii++ )
		glDrawArrays(GL_TRIANGLE_FAN, ii * 4, 4);
#else
	glDrawArrays(GL_QUADS, 0, 24);
#endif

	refdef.batchCount++;

	/* restore previous matrix */
	glPopMatrix();
}
示例#24
0
文件: r_backend.c 项目: cfr/qfusion
/*
* RB_BindTexture
*/
void RB_BindTexture( int tmu, const image_t *tex )
{
	if( R_BindTexture( tmu, tex ) ) {
		rb.stats.c_totalBinds++;
	}
}
示例#25
0
/**
 * @brief Draws shadow and highlight effects for the entities (actors)
 * @note The origins are already transformed
 */
void R_DrawEntityEffects (void)
{
	const int mask = r_stencilshadows->integer ? RF_BLOOD : (RF_SHADOW | RF_BLOOD);
	GLint oldDepthFunc;
	glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);

	R_EnableBlend(true);

	if (actorIndicator == nullptr) {
		selectedActorIndicator = R_FindImage("pics/sfx/actor_selected", it_effect);
		actorIndicator = R_FindImage("pics/sfx/actor", it_effect);
	}

	for (int i = 0; i < refdef.numEntities; i++) {
		const entity_t* e = &r_entities[i];

		if (e->flags <= RF_BOX)
			continue;

		glPushMatrix();
		glMultMatrixf(e->transform.matrix);

		if (e->flags & mask) {
			const vec3_t points[] = { { -18.0, 14.0, -28.5 }, { 10.0, 14.0, -28.5 }, { 10.0, -14.0, -28.5 }, { -18.0,
					-14.0, -28.5 } };
			/** @todo use default_texcoords */
			const vec2_t texcoords[] = { { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 0.0 } };

			if (e->flags & RF_SHADOW) {
				R_BindTexture(shadow->texnum);
			} else {
				assert(e->texture);
				R_BindTexture(e->texture->texnum);
			}

			R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords);
			R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points);
			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
			R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
			R_BindDefaultArray(GL_VERTEX_ARRAY);

			refdef.batchCount++;
		}

		if (e->flags & RF_ACTOR) {
			const float size = 15.0;
			int texnum;
			/* draw the circles for team-members and allied troops */
			vec4_t color = {1, 1, 1, 1};
			const vec3_t points[] = { { -size, size, -SELECTION_DELTA }, { size, size, -SELECTION_DELTA }, { size, -size,
					-SELECTION_DELTA }, { -size, -size, -SELECTION_DELTA } };
			/** @todo use default_texcoords */
			const vec2_t texcoords[] = { { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 0.0 } };

			if (e->flags & RF_SELECTED)
				Vector4Set(color, 0, 1, 0, 0.5);
			else if (e->flags & RF_MEMBER)
				Vector4Set(color, 0, 0.8, 0, 0.5);
			else if (e->flags & RF_ALLIED)
				Vector4Set(color, 0, 1, 0.5, 0.5);
			else if (e->flags & RF_NEUTRAL)
				Vector4Set(color, 1, 1, 0, 0.5);
			else if (e->flags & RF_OPPONENT)
				Vector4Set(color, 1, 0, 0, 0.5);
			else
				Vector4Set(color, 0.3, 0.3, 0.3, 0.5);

			if (e->flags & RF_SELECTED)
				texnum = selectedActorIndicator->texnum;
			else
				texnum = actorIndicator->texnum;

			R_BindTexture(texnum);
			R_Color(color);
			R_EnableDrawAsGlow(true);

			/* circle points */
			R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords);
			R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points);

			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

			refdef.batchCount++;

			/* add transparency when something is in front of the circle */
			color[3] *= 0.25;
			R_Color(color);
			glDepthFunc(GL_GREATER);
			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
			glDepthFunc(oldDepthFunc);

			refdef.batchCount++;

			R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
			R_BindDefaultArray(GL_VERTEX_ARRAY);

			R_Color(nullptr);
			R_EnableDrawAsGlow(false);
		}
		glPopMatrix();
	}
}
示例#26
0
/**
 * @brief handle post-processing bloom
 */
void R_DrawBloom (void)
{
	int i;
	bool renderBufferState;

	if (!r_config.frameBufferObject || !r_postprocess->integer || !r_programs->integer)
		return;

	/* save state, then set up for blit-style rendering to quads */
	renderBufferState = R_RenderbufferEnabled();
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_TEXTURE);
	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
#ifndef GL_VERSION_ES_CM_1_0
	glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT);
#endif
	glOrtho(0, viddef.context.width, viddef.context.height, 0, 9999.0f, SKYBOX_DEPTH);

	glDisable(GL_LIGHTING);
	glDisable(GL_DEPTH_TEST);

	/* downsample into image pyramid */
	R_ResolveMSAA(fbo_render);
	R_BindTexture(fbo_render->textures[1]);
	qglGenerateMipmapEXT(GL_TEXTURE_2D);

	R_Blur(fbo_render, fbo_bloom0, 1, 0);
	R_Blur(fbo_bloom0, fbo_bloom1, 0, 1);

	R_UseFramebuffer(r_state.buffers0[0]);
	R_BindTexture(fbo_bloom1->textures[0]);
	qglGenerateMipmapEXT(GL_TEXTURE_2D);
	R_UseViewport(r_state.buffers0[0]);
	R_DrawQuad();

	for (i = 1; i < DOWNSAMPLE_PASSES; i++) {
		R_Blur(r_state.buffers0[i - 1], r_state.buffers1[i - 1], 0, 0);
		R_Blur(r_state.buffers1[i - 1], r_state.buffers2[i - 1], 0, 1);
		R_UseFramebuffer(r_state.buffers0[i]);
		R_BindTexture(r_state.buffers2[i - 1]->textures[0]);
		R_UseViewport(r_state.buffers0[i]);
		R_DrawQuad();
	}

	/* blur and combine downsampled images */
	R_BlurStack(DOWNSAMPLE_PASSES, r_state.buffers0, r_state.buffers1);

	/* re-combine the blurred version with the original "glow" image */
	R_UseProgram(r_state.combine2_program);
	R_UseFramebuffer(fbo_bloom0);
	R_BindTextureForTexUnit(fbo_render->textures[1], &texunit_0);
	R_BindTextureForTexUnit(r_state.buffers1[0]->textures[0], &texunit_1);

	R_UseViewport(fbo_screen);
	R_DrawQuad();

	/* draw final result to the screenbuffer */
	R_UseFramebuffer(fbo_screen);
	R_UseProgram(r_state.combine2_program);
	R_BindTextureForTexUnit(fbo_render->textures[0], &texunit_0);
	R_BindTextureForTexUnit(fbo_bloom0->textures[0], &texunit_1);

	R_DrawQuad();

	/* cleanup before returning */
	R_UseProgram(default_program);

	R_CheckError();

#ifndef GL_VERSION_ES_CM_1_0
	glPopAttrib();
#endif
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_TEXTURE);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
	R_CheckError();

	/* reset renderbuffer state to what it was before */
	R_EnableRenderbuffer(renderBufferState);
}
示例#27
0
/**
 * @brief Draw the day and night images of a flat geoscape
 * multitexture feature is used to blend the images
 * @sa R_Draw3DGlobe
 * @param[in] p The horizontal shift of the night map
 * @param[in] cx The x texture coordinate
 * @param[in] cy The y texture coordinate
 * @param[in] iz The zoomlevel of the geoscape - see ccs.zoom
 * @param[in] map The geoscape map to draw (can be changed in the campaign definition)
 * @param[in] overlayNation,overlayXVI,overlayRadar Whether these overlays should be drawn or not
 */
void R_DrawFlatGeoscape (const vec2_t nodePos, const vec2_t nodeSize, float p, float cx, float cy, float iz, const char *map, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t *r_dayandnightTexture, image_t *r_xviTexture, image_t *r_radarTexture)
{
	image_t *gl;
	float geoscape_texcoords[4 * 2];
	short geoscape_verts[4 * 2];

	/* normalize */
	const float nx = nodePos[0] * viddef.rx;
	const float ny = nodePos[1] * viddef.ry;
	const float nw = nodeSize[0] * viddef.rx;
	const float nh = nodeSize[1] * viddef.ry;

	/* load day image */
	gl = R_FindImage(va("pics/geoscape/%s_day", map), it_wrappic);
	if (gl == r_noTexture)
		Com_Error(ERR_FATAL, "Could not load geoscape day image");

	/* alter the array pointers */
	glVertexPointer(2, GL_SHORT, 0, geoscape_verts);
	R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords);

	geoscape_texcoords[0] = cx - iz;
	geoscape_texcoords[1] = cy - iz;
	geoscape_texcoords[2] = cx + iz;
	geoscape_texcoords[3] = cy - iz;
	geoscape_texcoords[4] = cx + iz;
	geoscape_texcoords[5] = cy + iz;
	geoscape_texcoords[6] = cx - iz;
	geoscape_texcoords[7] = cy + iz;

	geoscape_verts[0] = nx;
	geoscape_verts[1] = ny;
	geoscape_verts[2] = nx + nw;
	geoscape_verts[3] = ny;
	geoscape_verts[4] = nx + nw;
	geoscape_verts[5] = ny + nh;
	geoscape_verts[6] = nx;
	geoscape_verts[7] = ny + nh;

	/* draw day image */
	R_BindTexture(gl->texnum);
	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

	refdef.batchCount++;

	/* draw night map */
	gl = R_FindImage(va("pics/geoscape/%s_night", map), it_wrappic);
	/* maybe the campaign map doesn't have a night image */
	if (gl != r_noTexture) {
		float geoscape_nighttexcoords[4 * 2];

		R_BindTexture(gl->texnum);
		R_EnableTexture(&texunit_lightmap, true);
		R_SelectTexture(&texunit_lightmap);

		geoscape_nighttexcoords[0] = geoscape_texcoords[0] + p;
		geoscape_nighttexcoords[1] = geoscape_texcoords[1];
		geoscape_nighttexcoords[2] = geoscape_texcoords[2] + p;
		geoscape_nighttexcoords[3] = geoscape_texcoords[3];
		geoscape_nighttexcoords[4] = geoscape_texcoords[4] + p;
		geoscape_nighttexcoords[5] = geoscape_texcoords[5];
		geoscape_nighttexcoords[6] = geoscape_texcoords[6] + p;
		geoscape_nighttexcoords[7] = geoscape_texcoords[7];

		R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_nighttexcoords);

		R_BindTexture(r_dayandnightTexture->texnum);

		R_SelectTexture(&texunit_diffuse);
		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

		refdef.batchCount++;

		R_SelectTexture(&texunit_lightmap);
		R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords);

		R_EnableTexture(&texunit_lightmap, false);
	}

	/* draw nation overlay */
	if (overlayNation) {
		gl = R_FindImage(va("pics/geoscape/%s_nations_overlay", map), it_wrappic);
		if (gl == r_noTexture)
			Com_Error(ERR_FATAL, "Could not load geoscape nation overlay image");

		/* draw day image */
		R_BindTexture(gl->texnum);
		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

		refdef.batchCount++;
	}

	/* draw XVI image */
	if (overlayXVI) {
		gl = R_FindImage(va("pics/geoscape/%s_xvi_overlay", map), it_wrappic);
		if (gl == r_noTexture)
			Com_Error(ERR_FATAL, "Could not load xvi overlay image");

		R_BindTexture(gl->texnum);

		R_EnableTexture(&texunit_lightmap, true);
		R_BindLightmapTexture(r_xviTexture->texnum);

		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

		refdef.batchCount++;

		R_EnableTexture(&texunit_lightmap, false);
	}

	/* draw radar image */
	if (overlayRadar) {
		R_BindTexture(r_radarTexture->texnum);
		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

		refdef.batchCount++;
	}

	/* and restore them */
	R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
	R_BindDefaultArray(GL_VERTEX_ARRAY);
}
示例#28
0
/**
 * @brief Draws a model in 2d mode (for rendering model data from the ui)
 * @param[in,out] mi All the needed model information to render the model
 * @param[in,out] pmi The model information of the parent model. This is used
 * in those cases, where the model that should get rendered here is placed relativly
 * to an already existing model in the world.
 * @param[in] tagname If a parent model is given, a @c tagname is given in most cases, too. It's used
 * to transform the model location relative to the parent model location again. E.g. a
 * @c tagname of tag_rweapon will transform the location to the right hand of an actor.
 * @sa R_DrawAliasModel
 */
void R_DrawModelDirect (modelInfo_t * mi, modelInfo_t * pmi, const char *tagname)
{
	image_t *skin;
	mAliasMesh_t *mesh;

	if (Q_strnull(mi->name))
		return;

	/* register the model */
	mi->model = R_FindModel(mi->name);

	/* check if the model exists */
	if (!mi->model) {
		Com_Printf("No model found for '%s'\n", mi->name);
		return;
	}

	skin = R_AliasModelState(mi->model, &mi->mesh, &mi->frame, &mi->oldframe, &mi->skin);
	if (skin == NULL) {
		Com_Printf("Model '%s' is broken\n", mi->name);
		return;
	}

	glPushMatrix();
	glScalef(viddef.rx, viddef.ry, (viddef.rx + viddef.ry) / 2);

	R_Color(mi->color);

	if (pmi) {
		/* register the parent model */
		pmi->model = R_FindModel(pmi->name);

		/* transform - the next transform for the child model will be relative from the
		 * parent model location now */
		R_TransformModelDirect(pmi);

		/* tag transformation */
		if (tagname) {
			const mAliasTagOrientation_t *current = NULL;
			const mAliasTagOrientation_t *old = NULL;
			R_GetTags(pmi->model, tagname, pmi->frame, pmi->oldframe, &current, &old);
			if (current != NULL && old != NULL) {
				float interpolated[16];

				/* do interpolation */
				R_InterpolateTransform(pmi->backlerp, pmi->model->alias.num_frames, current, old, interpolated);

				/* transform */
				glMultMatrixf(interpolated);
				R_CheckError();
			}
		}
	}

	/* transform */
	R_TransformModelDirect(mi);

	/* we have to reenable this here - we are in 2d mode here already */
	glEnable(GL_DEPTH_TEST);

	/* draw it */
	R_BindTexture(skin->texnum);

	/* draw the model */
	mesh = &mi->model->alias.meshes[0];
	refdef.aliasCount += mesh->num_tris;
	if (mi->model->alias.num_frames == 1)
		R_DrawAliasStaticWithReset(mesh, vec4_origin);
	else
		R_DrawAliasFrameLerp(&mi->model->alias, mesh, mi->backlerp, mi->frame, mi->oldframe, vec4_origin);

	/* show model bounding box */
	if (r_showbox->integer)
		R_DrawBoundingBox(mi->model->alias.frames[mi->frame].mins, mi->model->alias.frames[mi->frame].maxs);

	glDisable(GL_DEPTH_TEST);

	glPopMatrix();

	R_Color(NULL);
}
示例#29
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);
}
示例#30
0
/**
 * @brief Draw a model from the battlescape entity list
 * @sa R_GetEntityLists
 */
void R_DrawAliasModel (entity_t *e)
{
	mAliasModel_t *mod = &e->model->alias;
	/* the values are sane here already - see R_GetEntityLists */
	const image_t *skin = mod->meshes[e->as.mesh].skins[e->skinnum].skin;
	int i;
	float g;
	vec4_t color = {0.8, 0.8, 0.8, 1.0};
	mAliasMesh_t *mesh;

	/* IR goggles override color for entities that are affected */
	if ((refdef.rendererFlags & RDF_IRGOGGLES) && (e->flags & RF_IRGOGGLES))
		Vector4Set(e->shell, 1.0, 0.3, 0.3, 1.0);

	if (e->flags & RF_PULSE) {  /* and then adding in a pulse */
		const float f = 1.0 + sin((refdef.time + (e->model->alias.meshes[0].num_tris)) * 6.0) * 0.33;
		VectorScale(color, 1.0 + f, color);
	}

	g = 0.0;
	/* find brightest component */
	for (i = 0; i < 3; i++) {
		if (color[i] > g)  /* keep it */
			g = color[i];
	}

	/* scale it back to 1.0 */
	if (g > 1.0)
		VectorScale(color, 1.0 / g, color);

	R_Color(color);

	assert(skin->texnum > 0);
	R_BindTexture(skin->texnum);

	R_EnableGlowMap(skin->glowmap);

	R_UpdateLightList(e);
	R_EnableModelLights(e->lights, e->numLights, e->inShadow, true);

	/** @todo this breaks the encapsulation - don't call CL_* functions from within the renderer code */
	if (r_debug_lights->integer) {
		for (i = 0; i < e->numLights && i < r_dynamic_lights->integer; i++)
			CL_ParticleSpawn("lightTracerDebug", 0, e->transform.matrix + 12, e->lights[i]->origin);
	}

	if (skin->normalmap)
		R_EnableBumpmap(skin->normalmap);

	if (skin->specularmap)
		R_EnableSpecularMap(skin->specularmap, true);

	if (skin->roughnessmap)
		R_EnableRoughnessMap(skin->roughnessmap, true);

	glPushMatrix();
	glMultMatrixf(e->transform.matrix);

	if (VectorNotEmpty(e->scale))
		glScalef(e->scale[0], e->scale[1], e->scale[2]);

	mesh = R_DrawAliasModelBuffer(e);

	if (r_state.specularmap_enabled)
		R_EnableSpecularMap(NULL, false);

	if (r_state.roughnessmap_enabled)
		R_EnableRoughnessMap(NULL, false);

	R_EnableModelLights(NULL, 0, false, false);

	R_EnableGlowMap(NULL);

	if (r_state.active_normalmap)
		R_EnableBumpmap(NULL);

	R_DrawMeshShadow(e, mesh);

	if (mod->num_frames == 1)
		R_ResetArraysAfterStaticMeshRender();

	glPopMatrix();

	/* show model bounding box */
	if (r_showbox->integer)
		R_DrawBoundingBox(mod->frames[e->as.frame].mins, mod->frames[e->as.frame].maxs);

	R_Color(NULL);
}