Esempio n. 1
0
/*
* R_BuildLightmap
*/
static void R_BuildLightmap( int w, int h, qboolean deluxe, const qbyte *data, qbyte *dest, int blockWidth )
{
	int x, y;
	qbyte *rgba;
	int bits = mapConfig.pow2MapOvrbr;

	if( !data || (r_fullbright->integer && !deluxe) )
	{
		int val = deluxe ? 127 : 255;
		for( y = 0; y < h; y++, dest )
			memset( dest + y * blockWidth, val, w * LIGHTMAP_BYTES * sizeof( *dest ) );
		return;
	}

	if( deluxe || ( !bits && !r_lighting_grayscale->integer ) )
	{
		int wB = w * LIGHTMAP_BYTES;
		for( y = 0, rgba = dest; y < h; y++, data += wB, rgba += blockWidth )
		{
			memcpy( rgba, data, wB );
		}
	}
	else
	{
		float scaled[3];
		float intensity = (1 << bits) / 255.0f;

		for( y = 0; y < h; y++ )
		{
			for( x = 0, rgba = dest + y * blockWidth; x < w; x++, data += LIGHTMAP_BYTES, rgba += LIGHTMAP_BYTES )
			{
				vec3_t normalized;

				scaled[0] = (float)( (int)data[0] ) * intensity;
				scaled[1] = (float)( (int)data[1] ) * intensity;
				scaled[2] = (float)( (int)data[2] ) * intensity;

				ColorNormalize( scaled, normalized );

				// monochrome lighting: convert to grayscale
				if( r_lighting_grayscale->integer ) {
					vec_t grey = ColorGrayscale( normalized );
					normalized[0] = normalized[1] = normalized[2] = bound( 0, grey, 1 );
				}

				rgba[0] = ( qbyte )( normalized[0] * 255 );
				rgba[1] = ( qbyte )( normalized[1] * 255 );
				rgba[2] = ( qbyte )( normalized[2] * 255 );
			}
		}
	}
}
Esempio n. 2
0
/** @note Defaults should match those of ufo2map, or lighting will be inconsistent between world and models */
static void SP_worldspawn (const localEntityParse_t* entData)
{
	/* maximum level */
	cl.mapMaxLevel = entData->maxLevel;

	if (GAME_IsMultiplayer()) {
		if (cl_teamnum->integer > entData->maxMultiplayerTeams || cl_teamnum->integer <= TEAM_CIVILIAN) {
			Com_Printf("The selected team is not usable. "
				"The map doesn't support %i teams but only %i teams\n",
				cl_teamnum->integer, entData->maxMultiplayerTeams);
			Cvar_SetValue("cl_teamnum", TEAM_DEFAULT);
			Com_Printf("Set teamnum to %i\n", cl_teamnum->integer);
		}
	}

	/** @todo - make sun position/color vary based on local time at location? */
	const int dayLightmap = CL_GetConfigStringInteger(CS_LIGHTMAP);

	/** @note Some vectors have exra elements to comply with mathlib and/or OpenGL conventions, but handled as shorter ones */
	vec3_t sunAngles;
	vec4_t sunColor;
	vec_t sunIntensity;
	if (dayLightmap) {
		/* set defaults for daylight */
		Vector4Set(refdef.ambientColor, 0.26, 0.26, 0.26, 1.0);
		sunIntensity = 280;
		VectorSet(sunAngles, -75, 100, 0);
		Vector4Set(sunColor, 0.90, 0.75, 0.65, 1.0);

		/* override defaults with data from worldspawn entity, if any */
		if (VectorNotEmpty(entData->ambientDayColor))
			VectorCopy(entData->ambientDayColor, refdef.ambientColor);

		if (entData->dayLight)
			sunIntensity = entData->dayLight;

		if (Vector2NotEmpty(entData->daySunAngles))
			Vector2Copy(entData->daySunAngles, sunAngles);

		if (VectorNotEmpty(entData->daySunColor))
			VectorCopy(entData->daySunColor, sunColor);

		Vector4Set(refdef.sunSpecularColor, 1.0, 1.0, 0.9, 1);
	} else {
		/* set defaults for night light */
		Vector4Set(refdef.ambientColor, 0.16, 0.16, 0.17, 1.0);
		sunIntensity = 15;
		VectorSet(sunAngles, -80, 220, 0);
		Vector4Set(sunColor, 0.25, 0.25, 0.35, 1.0);

		/* override defaults with data from worldspawn entity, if any */
		if (VectorNotEmpty(entData->ambientNightColor))
			VectorCopy(entData->ambientNightColor, refdef.ambientColor);

		if (entData->nightLight)
			sunIntensity = entData->nightLight;

		if (Vector2NotEmpty(entData->nightSunAngles))
			Vector2Copy(entData->nightSunAngles, sunAngles);

		if (VectorNotEmpty(entData->nightSunColor))
			VectorCopy(entData->nightSunColor, sunColor);

		Vector4Set(refdef.sunSpecularColor, 0.5, 0.5, 0.7, 1);
	}

	ColorNormalize(sunColor, sunColor);
	VectorScale(sunColor, sunIntensity/255.0, sunColor);
	Vector4Copy(sunColor, refdef.sunDiffuseColor);

	/* clamp ambient for models */
	Vector4Copy(refdef.ambientColor, refdef.modelAmbientColor);
	for (int i = 0; i < 3; i++)
		if (refdef.modelAmbientColor[i] < MIN_AMBIENT_COMPONENT)
			refdef.modelAmbientColor[i] = MIN_AMBIENT_COMPONENT;

	/* scale it into a reasonable range, the clamp above ensures this will work */
	while (VectorSum(refdef.modelAmbientColor) < MIN_AMBIENT_SUM)
		VectorScale(refdef.modelAmbientColor, 1.25, refdef.modelAmbientColor);

	AngleVectors(sunAngles, refdef.sunVector, nullptr, nullptr);
	refdef.sunVector[3] = 0.0; /* to use as directional light source in OpenGL */

	/** @todo Parse fog from worldspawn config */
	refdef.weather = WEATHER_NONE;
	refdef.fogColor[3] = 1.0;
	VectorSet(refdef.fogColor, 0.75, 0.75, 0.75);
}
Esempio n. 3
0
void MakePatchForFace( int fn, winding_t *w ){
	dface_t *f;
	float area;
	patch_t     *patch;
	dplane_t    *pl;
	int i;
	vec3_t color;
	dleaf_t     *leaf;

	f = &dfaces[fn];

	area = WindingArea( w );
	totalarea += area;

	patch = &patches[num_patches];
	if ( num_patches == MAX_PATCHES ) {
		Error( "num_patches == MAX_PATCHES" );
	}
	patch->next = face_patches[fn];
	face_patches[fn] = patch;

	patch->winding = w;

	if ( f->side ) {
		patch->plane = &backplanes[f->planenum];
	}
	else{
		patch->plane = &dplanes[f->planenum];
	}
	if ( face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] ) { // origin offset faces must create new planes
		if ( numplanes + fakeplanes >= MAX_MAP_PLANES ) {
			Error( "numplanes + fakeplanes >= MAX_MAP_PLANES" );
		}
		pl = &dplanes[numplanes + fakeplanes];
		fakeplanes++;

		*pl = *( patch->plane );
		pl->dist += DotProduct( face_offset[fn], pl->normal );
		patch->plane = pl;
	}

	WindingCenter( w, patch->origin );
	VectorAdd( patch->origin, patch->plane->normal, patch->origin );
	leaf = Rad_PointInLeaf( patch->origin );
	patch->cluster = leaf->cluster;
	if ( patch->cluster == -1 ) {
		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n" );
	}

	patch->area = area;
	if ( patch->area <= 1 ) {
		patch->area = 1;
	}
	patch->sky = IsSky( f );

	VectorCopy( texture_reflectivity[f->texinfo], patch->reflectivity );

	// non-bmodel patches can emit light
	if ( fn < dmodels[0].numfaces ) {
		BaseLightForFace( f, patch->baselight );

		ColorNormalize( patch->reflectivity, color );

		for ( i = 0 ; i < 3 ; i++ )
			patch->baselight[i] *= color[i];

		VectorCopy( patch->baselight, patch->totallight );
	}
	num_patches++;
}
Esempio n. 4
0
/*
   ======================
   CalcTextureReflectivity_Quake2
   ======================
 */
void CalcTextureReflectivity_Quake2( void ){
	int i;
	int j, k, texels;
	int color[3];
	int texel;
	byte            *palette;
	char path[1024];
	float r, scale;
	miptex_t        *mt;

	sprintf( path, "%spics/colormap.pcx", gamedir );

	// get the game palette
	Load256Image( path, NULL, &palette, NULL, NULL );

	// allways set index 0 even if no textures
	texture_reflectivity[0][0] = 0.5;
	texture_reflectivity[0][1] = 0.5;
	texture_reflectivity[0][2] = 0.5;

	for ( i = 0 ; i < numtexinfo ; i++ )
	{
		// see if an earlier texinfo allready got the value
		for ( j = 0 ; j < i ; j++ )
		{
			if ( !strcmp( texinfo[i].texture, texinfo[j].texture ) ) {
				VectorCopy( texture_reflectivity[j], texture_reflectivity[i] );
				break;
			}
		}
		if ( j != i ) {
			continue;
		}

		// load the wal file
		sprintf( path, "%stextures/%s.wal", gamedir, texinfo[i].texture );
		if ( TryLoadFile( path, (void **)&mt ) == -1 ) {
			Sys_Printf( "Couldn't load %s\n", path );
			texture_reflectivity[i][0] = 0.5;
			texture_reflectivity[i][1] = 0.5;
			texture_reflectivity[i][2] = 0.5;
			continue;
		}
		texels = LittleLong( mt->width ) * LittleLong( mt->height );
		color[0] = color[1] = color[2] = 0;

		for ( j = 0 ; j < texels ; j++ )
		{
			texel = ( (byte *)mt )[LittleLong( mt->offsets[0] ) + j];
			for ( k = 0 ; k < 3 ; k++ )
				color[k] += palette[texel * 3 + k];
		}

		for ( j = 0 ; j < 3 ; j++ )
		{
			r = color[j] / texels / 255.0;
			texture_reflectivity[i][j] = r;
		}
		// scale the reflectivity up, because the textures are
		// so dim
		scale = ColorNormalize( texture_reflectivity[i],
								texture_reflectivity[i] );
		if ( scale < 0.5 ) {
			scale *= 2;
			VectorScale( texture_reflectivity[i], scale, texture_reflectivity[i] );
		}
#if 0
		texture_reflectivity[i][0] = 0.5;
		texture_reflectivity[i][1] = 0.5;
		texture_reflectivity[i][2] = 0.5;
#endif
	}
}
Esempio n. 5
0
/**
 * @brief Create lights out of patches and entity lights
 * @sa LightWorld
 * @sa BuildPatch
 */
void BuildLights (void)
{
	int i;
	light_t* l;

	/* surfaces */
	for (i = 0; i < MAX_MAP_FACES; i++) {
		/* iterate subdivided patches */
		for(const patch_t* p = face_patches[i]; p; p = p->next) {
			if (VectorEmpty(p->light))
				continue;

			numlights[config.compile_for_day]++;
			l = Mem_AllocType(light_t);

			VectorCopy(p->origin, l->origin);

			l->next = lights[config.compile_for_day];
			lights[config.compile_for_day] = l;

			l->type = emit_surface;

			l->intensity = ColorNormalize(p->light, l->color);
			l->intensity *= p->area * config.surface_scale;
		}
	}

	/* entities (skip the world) */
	for (i = 1; i < num_entities; i++) {
		float intensity;
		const char* color;
		const char* target;
		const entity_t* e = &entities[i];
		const char* name = ValueForKey(e, "classname");
		if (!Q_strstart(name, "light"))
			continue;

		/* remove those lights that are only for the night version */
		if (config.compile_for_day) {
			const int spawnflags = atoi(ValueForKey(e, "spawnflags"));
			if (!(spawnflags & 1))	/* day */
				continue;
		}

		numlights[config.compile_for_day]++;
		l = Mem_AllocType(light_t);

		GetVectorForKey(e, "origin", l->origin);

		/* link in */
		l->next = lights[config.compile_for_day];
		lights[config.compile_for_day] = l;

		intensity = FloatForKey(e, "light");
		if (!intensity)
			intensity = 300.0;
		color = ValueForKey(e, "_color");
		if (color && color[0] != '\0'){
			if (sscanf(color, "%f %f %f", &l->color[0], &l->color[1], &l->color[2]) != 3)
				Sys_Error("Invalid _color entity property given: %s", color);
			ColorNormalize(l->color, l->color);
		} else
			VectorSet(l->color, 1.0, 1.0, 1.0);
		l->intensity = intensity * config.entity_scale;
		l->type = emit_point;

		target = ValueForKey(e, "target");
		if (target[0] != '\0' || Q_streq(name, "light_spot")) {
			l->type = emit_spotlight;
			l->stopdot = FloatForKey(e, "_cone");
			if (!l->stopdot)
				l->stopdot = 10;
			l->stopdot = cos(l->stopdot * torad);
			if (target[0] != '\0') {	/* point towards target */
				entity_t* e2 = FindTargetEntity(target);
				if (!e2)
					Com_Printf("WARNING: light at (%i %i %i) has missing target '%s' - e.g. create an info_null that has a 'targetname' set to '%s'\n",
						(int)l->origin[0], (int)l->origin[1], (int)l->origin[2], target, target);
				else {
					vec3_t dest;
					GetVectorForKey(e2, "origin", dest);
					VectorSubtract(dest, l->origin, l->normal);
					VectorNormalize(l->normal);
				}
			} else {	/* point down angle */
				const float angle = FloatForKey(e, "angle");
				if (angle == ANGLE_UP) {
					l->normal[0] = l->normal[1] = 0.0;
					l->normal[2] = 1.0;
				} else if (angle == ANGLE_DOWN) {
					l->normal[0] = l->normal[1] = 0.0;
					l->normal[2] = -1.0;
				} else {
					l->normal[2] = 0;
					l->normal[0] = cos(angle * torad);
					l->normal[1] = sin(angle * torad);
				}
			}
		}
	}

	/* handle worldspawn light settings */
	{
		const entity_t* e = &entities[0];
		const char* ambient, *light, *angles, *color;
		float f;
		int i;

		if (config.compile_for_day) {
			ambient = ValueForKey(e, "ambient_day");
			light = ValueForKey(e, "light_day");
			angles = ValueForKey(e, "angles_day");
			color = ValueForKey(e, "color_day");
		} else {
			ambient = ValueForKey(e, "ambient_night");
			light = ValueForKey(e, "light_night");
			angles = ValueForKey(e, "angles_night");
			color = ValueForKey(e, "color_night");
		}

		if (light[0] != '\0')
			sun_intensity = atoi(light);

		if (angles[0] != '\0') {
			VectorClear(sun_angles);
			if (sscanf(angles, "%f %f", &sun_angles[0], &sun_angles[1]) != 2)
				Sys_Error("wrong angles values given: '%s'", angles);
			AngleVectors(sun_angles, sun_normal, nullptr, nullptr);
		}

		if (color[0] != '\0') {
			GetVectorFromString(color, sun_color);
			ColorNormalize(sun_color, sun_color);
		}

		if (ambient[0] != '\0')
			GetVectorFromString(ambient, sun_ambient_color);

		/* optionally pull brightness from worldspawn */
		f = FloatForKey(e, "brightness");
		if (f > 0.0)
			config.brightness = f;

		/* saturation as well */
		f = FloatForKey(e, "saturation");
		if (f > 0.0)
			config.saturation = f;
		else
			Verb_Printf(VERB_EXTRA, "Invalid saturation setting (%f) in worldspawn found\n", f);

		f = FloatForKey(e, "contrast");
		if (f > 0.0)
			config.contrast = f;
		else
			Verb_Printf(VERB_EXTRA, "Invalid contrast setting (%f) in worldspawn found\n", f);

		/* lightmap resolution downscale (e.g. 4 = 1 << 4) */
		i = atoi(ValueForKey(e, "quant"));
		if (i >= 1 && i <= 6)
			config.lightquant = i;
		else
			Verb_Printf(VERB_EXTRA, "Invalid quant setting (%i) in worldspawn found\n", i);
	}

	Verb_Printf(VERB_EXTRA, "light settings:\n * intensity: %i\n * sun_angles: pitch %f yaw %f\n * sun_color: %f:%f:%f\n * sun_ambient_color: %f:%f:%f\n",
		sun_intensity, sun_angles[0], sun_angles[1], sun_color[0], sun_color[1], sun_color[2], sun_ambient_color[0], sun_ambient_color[1], sun_ambient_color[2]);
	Verb_Printf(VERB_NORMAL, "%i direct lights for %s lightmap\n", numlights[config.compile_for_day], (config.compile_for_day ? "day" : "night"));
}