Exemplo n.º 1
0
/**
 * @brief Developer tool for viewing BSP vertex normals. Only Phong interpolated
 * surfaces show their normals when r_shownormals > 1.
 */
void R_DrawBspNormals (int tile)
{
	int i, j, k;
	const mBspSurface_t* surf;
	const mBspModel_t* bsp;
	const vec4_t color = {1.0, 0.0, 0.0, 1.0};

	if (!r_shownormals->integer)
		return;

	R_EnableTexture(&texunit_diffuse, false);

	R_ResetArrayState();  /* default arrays */

	R_Color(color);

	k = 0;
	bsp = &r_mapTiles[tile]->bsp;
	surf = bsp->surfaces;
	for (i = 0; i < bsp->numsurfaces; i++, surf++) {
		if (surf->frame != r_locals.frame)
			continue; /* not visible */

		if (surf->texinfo->flags & SURF_WARP)
			continue;  /* don't care */

		if (r_shownormals->integer > 1 && !(surf->texinfo->flags & SURF_PHONG))
			continue;  /* don't care */

		/* avoid overflows, draw in batches */
		if (k > r_state.array_size - 512) {
			glDrawArrays(GL_LINES, 0, k / 3);
			k = 0;

			refdef.batchCount++;
		}

		for (j = 0; j < surf->numedges; j++) {
			vec3_t end;
			const GLfloat* vertex = &bsp->verts[(surf->index + j) * 3];
			const GLfloat* normal = &bsp->normals[(surf->index + j) * 3];

			VectorMA(vertex, 12.0, normal, end);

			memcpy(&r_state.vertex_array_3d[k], vertex, sizeof(vec3_t));
			memcpy(&r_state.vertex_array_3d[k + 3], end, sizeof(vec3_t));
			k += sizeof(vec3_t) / sizeof(vec_t) * 2;
			R_ReallocateStateArrays(k);
		}
	}

	glDrawArrays(GL_LINES, 0, k / 3);

	refdef.batchCount++;

	R_EnableTexture(&texunit_diffuse, true);

	R_Color(nullptr);
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
/**
 * @brief Restores renderer state for the given entity.
 */
static void R_ResetMeshShellState_default(const r_entity_t *e) {

	if (e->effects & EF_WEAPON) {
		R_DepthRange(0.0, 1.0);
	}

	R_RotateForEntity(NULL);

	R_ResetArrayState();

	R_UseInterpolation(0.0);
}
Exemplo n.º 4
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();
}
Exemplo n.º 5
0
/**
 * @param[in] drawFunc The function pointer to the surface draw function
 * @param[in] surfType The primary rendering type of the surface
 */
static void R_RenderBspRRefs (drawSurfaceFunc drawFunc, surfaceArrayType_t surfType)
{
	glEnable(GL_CULL_FACE);
	glCullFace(GL_FRONT); /* our triangles are backwards to what OpenGL expects, so tell it to render only back faces */

	for (int i = 0; i < numBspRRefs; i++) {
		const bspRenderRef_t* const bspRR = &bspRRefs[i];
		const mBspModel_t* const bsp = bspRR->bsp;
		const mBspModel_t* const tile = &r_mapTiles[bsp->maptile]->bsp; /* This is required to find the tile (world) bsp model to which arrays belong (submodels do not own arrays, but use world model ones) */
		glElementIndex_t* indexPtr;

		if (!bsp->sorted_surfaces[surfType]->count)
			continue;

		R_SetArrayState(tile);

		/* Vertex buffers are nullptr-based, arrays are not */
		if (qglBindBuffer && r_vertexbuffers->integer)
			indexPtr = nullptr;
		else
			indexPtr = tile->indexes;

		glPushMatrix();

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

		drawFunc(bsp->sorted_surfaces[surfType], indexPtr);

		/** @todo make it work again; also reimplement r_showbox 2 */
#if 0
		/* show model bounding box */
		if (r_showbox->integer) {
			const model_t* model = bspRR->bsp;
			R_DrawBoundingBox(model->mins, model->maxs);
		}
#endif

		glPopMatrix();
	}

	/* and restore array pointers */
	R_ResetArrayState();

	glCullFace(GL_BACK);
	glDisable(GL_CULL_FACE);
}
Exemplo n.º 6
0
static mAliasMesh_t* R_DrawAliasModelBuffer (entity_t *e)
{
	mAliasModel_t *mod = &e->model->alias;
	mAliasMesh_t* lodMesh;

	R_ResetArrayState();

	/** @todo what about the origin of a tagged model here? */
	lodMesh = R_GetLevelOfDetailForModel(e->origin, mod);
	refdef.aliasCount += lodMesh->num_tris;
	if (mod->num_frames == 1)
		R_DrawAliasStatic(lodMesh, e->shell);
	else
		R_DrawAliasFrameLerp(mod, lodMesh, e->as.backlerp, e->as.frame, e->as.oldframe, e->shell);

	return lodMesh;
}
Exemplo n.º 7
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);
}
Exemplo n.º 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);
}
Exemplo n.º 9
0
/*
 * @brief Main entry point for drawing the scene (world and entities).
 */
void R_DrawView(void) {

	R_UpdateFrustum();

	R_UpdateVis();

	R_MarkBspSurfaces();

	R_EnableFog(true);

	R_DrawSkyBox();

	// wait for the client to populate our lights array
	Thread_Wait(&r_view.thread);

	// now dispatch another thread to cull entities while we draw the world
	r_view.thread = Thread_Create(R_CullEntities, NULL);

	R_MarkLights();

	const r_sorted_bsp_surfaces_t *surfs = r_model_state.world->bsp->sorted_surfaces;

	R_DrawOpaqueBspSurfaces(&surfs->opaque);

	R_DrawOpaqueWarpBspSurfaces(&surfs->opaque_warp);

	R_DrawAlphaTestBspSurfaces(&surfs->alpha_test);

	R_EnableBlend(true);

	R_DrawBackBspSurfaces(&surfs->back);

	R_DrawMaterialBspSurfaces(&surfs->material);

	R_DrawFlareBspSurfaces(&surfs->flare);

	R_EnableBlend(false);

	R_DrawBspNormals();

	// ensure the thread has finished culling entities
	Thread_Wait(&r_view.thread);

	// now dispatch another thread to update particles while we draw entities
	r_view.thread = Thread_Create(R_UpdateParticles, NULL);

	R_DrawEntities();

	R_EnableBlend(true);

	R_DrawBspLights();

	R_DrawBlendBspSurfaces(&surfs->blend);

	R_DrawBlendWarpBspSurfaces(&surfs->blend_warp);

	// ensure the thread has finished updating particles
	Thread_Wait(&r_view.thread);

	R_DrawParticles();

	R_EnableFog(false);

	R_DrawCoronas();

	R_DrawBspLeafs();

	R_EnableBlend(false);

	R_ResetArrayState();
}
Exemplo n.º 10
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);
}
Exemplo n.º 11
0
/*
 * @brief Main entry point for drawing the scene (world and entities).
 */
void R_DrawView(void) {

	R_UpdateFrustum();

	R_UpdateVis();

	R_MarkBspSurfaces();

	R_EnableFog(true);

	R_DrawSkyBox();

	// wait for the client to fully populate the scene
	Thread_Wait(r_view.thread);

	// dispatch threads to cull entities and sort elements while we draw the world
	thread_t *cull_entities = Thread_Create(R_CullEntities, NULL);
	thread_t *sort_elements = Thread_Create(R_SortElements, NULL);

	R_MarkLights();

	const r_sorted_bsp_surfaces_t *surfs = r_model_state.world->bsp->sorted_surfaces;

	R_DrawOpaqueBspSurfaces(&surfs->opaque);

	R_DrawOpaqueWarpBspSurfaces(&surfs->opaque_warp);

	R_DrawAlphaTestBspSurfaces(&surfs->alpha_test);

	R_EnableBlend(true);

	R_DrawBackBspSurfaces(&surfs->back);

	R_DrawMaterialBspSurfaces(&surfs->material);

	R_DrawFlareBspSurfaces(&surfs->flare);

	R_EnableBlend(false);

	// wait for entity culling to complete
	Thread_Wait(cull_entities);

	R_DrawEntities();

	R_EnableBlend(true);

	// wait for element sorting to complete
	Thread_Wait(sort_elements);

	R_DrawElements();

	R_EnableFog(false);

	R_DrawDeveloperTools();

	R_DrawCoronas();

	R_EnableBlend(false);

	R_ResetArrayState();

#if 0
	vec3_t tmp;
	VectorMA(r_view.origin, MAX_WORLD_DIST, r_view.forward, tmp);

	cm_trace_t tr = Cl_Trace(r_view.origin, tmp, NULL, NULL, cl.client_num + 1, MASK_SOLID);
	if (tr.fraction > 0.0 && tr.fraction < 1.0) {
		Com_Print("%s: %d: %s\n", tr.surface->name, tr.plane.num, vtos(tr.plane.normal));
	}

#endif
}
Exemplo n.º 12
0
/**
 * @sa R_BeginFrame
 * @sa R_EndFrame
 */
void R_RenderFrame (void)
{
	R_Setup3D();

	/* activate wire mode */
	if (r_wire->integer)
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	if (!(refdef.rendererFlags & RDF_NOWORLDMODEL)) {
		int tile;
		if (r_threads->integer) {
			while (r_threadstate.state != THREAD_RENDERER)
				Sys_Sleep(0);

			r_threadstate.state = THREAD_CLIENT;
		} else {
			R_SetupFrustum();

			/* draw brushes on current worldlevel */
			R_GetLevelSurfaceLists();
		}

		R_UpdateSustainedLights();

		R_CheckError();

		for (tile = 0; tile < r_numMapTiles; tile++) {
			const model_t *mapTile = r_mapTiles[tile];
			const mBspModel_t *bsp = &mapTile->bsp;

			R_AddBspRRef(bsp, vec3_origin, vec3_origin, false);
		}

		R_GetEntityLists();

		R_EnableFog(true);

		R_RenderOpaqueBspRRefs();
		R_RenderOpaqueWarpBspRRefs();
		R_DrawOpaqueMeshEntities(r_opaque_mesh_entities);

		R_RenderAlphaTestBspRRefs();

		R_EnableBlend(true);
		R_RenderMaterialBspRRefs();

		R_EnableFog(false);

		R_RenderBlendBspRRefs();
		R_RenderBlendWarpBspRRefs();
		R_DrawBlendMeshEntities(r_blend_mesh_entities);

		R_EnableFog(true);
		R_RenderFlareBspRRefs();
		R_EnableFog(false);

		if (r_debug_lights->integer) {
			int i;

			for (i = 0; i < refdef.numStaticLights; i++) {
				const light_t *l = &refdef.staticLights[i];
				R_AddCorona(l->origin, l->radius, l->color);
			}
			for (i = 0; i < refdef.numDynamicLights; i++) {
				const light_t *l = &refdef.dynamicLights[i];
				R_AddCorona(l->origin, l->radius, l->color);
			}
		}

		R_DrawCoronas();
		R_EnableBlend(false);

		for (tile = 0; tile < r_numMapTiles; tile++) {
			R_DrawBspNormals(tile);
		}

		R_Color(NULL);
		R_DrawSpecialEntities(r_special_entities);
		R_DrawNullEntities(r_null_entities);
		R_DrawEntityEffects();
	} else {
		glClear(GL_DEPTH_BUFFER_BIT);

		R_GetEntityLists();

		R_RenderOpaqueBspRRefs();
		R_RenderOpaqueWarpBspRRefs();
		R_DrawOpaqueMeshEntities(r_opaque_mesh_entities);
		R_RenderAlphaTestBspRRefs();

		R_EnableBlend(true);

		R_RenderMaterialBspRRefs();

		R_RenderBlendBspRRefs();
		R_RenderBlendWarpBspRRefs();
		R_DrawBlendMeshEntities(r_blend_mesh_entities);

		R_RenderFlareBspRRefs();

		R_EnableBlend(false);

		R_Color(NULL);
		R_DrawSpecialEntities(r_special_entities);
		R_DrawNullEntities(r_null_entities);
		R_DrawEntityEffects();
	}

	R_EnableBlend(true);

	R_DrawParticles();

	R_EnableBlend(false);

	/* leave wire mode again */
	if (r_wire->integer)
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	R_DrawBloom();

	R_DrawBoundingBoxes();

	R_ResetArrayState();

	/* go back into 2D mode for hud and the like */
	R_Setup2D();

	R_CheckError();
}
Exemplo n.º 13
0
/**
 * @brief Re-initializes OpenGL state machine, all textures and renderer variables, this needed when application is put to background on Android.
 */
void R_ReinitOpenglContext (void)
{
	/* De-allocate old GL state, these functinos will call glDeleteTexture(), so they should go before everything else */
	R_FontCleanCache();
	R_ShutdownFBObjects();
	R_ShutdownPrograms();
	R_BeginBuildingLightmaps(); /* This function will also call glDeleteTexture() */
	/* Re-initialize GL state */
	R_SetDefaultState();
	R_InitPrograms();
	R_ResetArrayState();
	/* Re-upload all textures */
	R_InitMiscTexture();
	R_ReloadImages();
	/* Re-upload other GL stuff */
	R_InitFBObjects();
	R_UpdateDefaultMaterial("", "", "", NULL);

	/* Re-upload the battlescape terrain geometry */
	if (!qglBindBuffer)
		return;

	for (int tile = 0; tile < r_numMapTiles; tile++) {
		model_t *mod = r_mapTiles[tile];

		int vertind = 0, coordind = 0, tangind = 0;
		mBspSurface_t *surf = mod->bsp.surfaces;

		for (int i = 0; i < mod->bsp.numsurfaces; i++, surf++) {
			vertind += 3 * surf->numedges;
			coordind += 2 * surf->numedges;
			tangind += 4 * surf->numedges;
		}

		qglGenBuffers(1, &mod->bsp.vertex_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer);
		qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.texcoord_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer);
		qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer);
		qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.normal_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer);
		qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.tangent_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer);
		qglBufferData(GL_ARRAY_BUFFER, tangind * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.index_buffer);
		qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mod->bsp.index_buffer);
		qglBufferData(GL_ELEMENT_ARRAY_BUFFER, mod->bsp.numIndexes * sizeof(GLushort), mod->bsp.indexes, GL_STATIC_DRAW);
		qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

		for (int i = 0; i < mod->bsp.numsurfaces; i++)
			R_CreateSurfaceLightmap(&mod->bsp.surfaces[i]);
	}

	R_EndBuildingLightmaps();
	qglBindBuffer(GL_ARRAY_BUFFER, 0);
}
Exemplo 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);
}
Exemplo n.º 15
0
/**
 * @brief Draws weather effects
 */
void Weather::render (void)
{
	/* Don't play the weather particles if the user doesn't want them */
	if (!Cvar_GetInteger("cl_particleweather")) {
		return;
	}

	GLfloat prtPos[3 * 4 * Weather::MAX_PARTICLES];
	GLfloat prtTexcoord[2 * 4 * Weather::MAX_PARTICLES];
	GLushort prtIndex[3 * 2 * Weather::MAX_PARTICLES];
	size_t prtCount = 0;
	//const float splashTimeScale = 0.001f / splashTime; /* from msec to 1/sec units, so division is done only once per frame */
	/** @todo shadowcasting at least for the sunlight */
#if 0 // disabled because of bizarre colors
	vec4_t prtColor = {color[0] * (refdef.ambientColor[0] + refdef.sunDiffuseColor[0]),
		color[1] * (refdef.ambientColor[1] + refdef.sunDiffuseColor[1]),
		color[2] * (refdef.ambientColor[2] + refdef.sunDiffuseColor[2]),
		color[3]};
#else
	vec_t prtBrightness = VectorLength(refdef.ambientColor) + VectorLength(refdef.sunDiffuseColor); /** @todo proper color to brightness mapping */
	vec4_t prtColor = {color[0] * prtBrightness, color[1] * prtBrightness, color[2] * prtBrightness, color[3]}; /* alpha is not to be scaled */
#endif

	for (size_t i = 0; i < Weather::MAX_PARTICLES; i++) {
		Weather::particle &prt = particles[i];

		if (prt.ttl < 0)
			continue;

		/* if particle is alive, construct a camera-facing quad */
		GLfloat x, y, z;
		GLfloat dx, dy, dz;
		GLfloat thisParticleSize = particleSize;
		if (prt.vz == 0 && splashTime > 0) {
			/* splash particle, do zoom and other things */
			/** @todo alpha decay */
			const float splashFactor = prt.ttl / 500.0f;//1.0f - prt.ttl * splashTimeScale;
			thisParticleSize *= (splashSize - 1.0f) * splashFactor  + 1.0f;
			dx = dy = thisParticleSize;
		} else {
			dx = i & 1 ? thisParticleSize* 2 : thisParticleSize; dy = i & 1 ? thisParticleSize : thisParticleSize * 2 ; /** @todo make a proper projection instead of this hack */
		}

		x = prt.x; y = prt.y; z = prt.z;
		dz = smearLength * prt.vz * 0.5; /** @todo should use proper velocity vector ... or maybe not */
		/* construct a particle geometry; */
		GLfloat *pos = &prtPos[3 * 4 * prtCount];
		GLfloat *texcoord = &prtTexcoord[2 * 4 * prtCount];
		GLushort *idx = &prtIndex[3 * 2 * prtCount];

		/** @todo actually rotate billboard in the correct position */
		pos[0] = x - dx; pos[1] = y - dy; pos[2] = z + dz * 2;
		pos[3] = x + dx; pos[4] = y - dy; pos[5] = z + dz *2;
		pos[6] = x + dx; pos[7] = y + dy; pos[8] = z;
		pos[9] = x - dx; pos[10] = y + dy; pos[11] = z;

		texcoord[0] = 0; texcoord[1] = 0; /* upper left vertex */
		texcoord[2] = 1.0f; texcoord[3] = 0; /* upper right vertex */
		texcoord[4] = 1.0f; texcoord[5] = 1.0f; /* bottom right vertex */
		texcoord[6] = 0; texcoord[7] = 1.0f; /* bottom left vertex */

		idx[0] = 4 * prtCount; idx[1] = 4 * prtCount + 1; idx[2] = 4 * prtCount + 2;
		idx[3] = 4 * prtCount + 2; idx[4] = 4 * prtCount + 3; idx[5] = 4 * prtCount;

		prtCount++;
	}

	if (prtCount < 1)
		return;

	/* draw the generated array */
	R_Color(prtColor);
	glBindTexture(GL_TEXTURE_2D, wpTexture());
	R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, prtPos);
	R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, prtTexcoord);
	R_EnableBlend(true);
	glDrawElements(GL_TRIANGLES, prtCount * 3 * 2, GL_UNSIGNED_SHORT, prtIndex);
	R_EnableBlend(false);
	R_ResetArrayState();
	R_Color(nullptr);

	refdef.batchCount++;
}