Exemplo n.º 1
0
/*
=================
R_BindAnimatedImage

=================
*/
static void R_BindAnimatedImage( textureBundle_t *bundle ) {
	int index;

	if ( bundle->isVideoMap ) {
		ri.CIN_RunCinematic( bundle->videoMapHandle );
		ri.CIN_UploadCinematic( bundle->videoMapHandle );
		return;
	}

	if ( bundle->numImageAnimations <= 1 ) {
		if ( bundle->isLightmap && ( backEnd.refdef.rdflags & RDF_SNOOPERVIEW ) ) {
			GL_Bind( tr.whiteImage );
		} else {
			GL_Bind( bundle->image[0] );
		}
		return;
	}

	// it is necessary to do this messy calc to make sure animations line up
	// exactly with waveforms of the same frequency
	index = myftol( tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE );
	index >>= FUNCTABLE_SIZE2;

	if ( index < 0 ) {
		index = 0;  // may happen with shader time offsets
	}
	index %= bundle->numImageAnimations;

	if ( bundle->isLightmap && ( backEnd.refdef.rdflags & RDF_SNOOPERVIEW ) ) {
		GL_Bind( tr.whiteImage );
	} else {
		GL_Bind( bundle->image[ index ] );
	}
}
Exemplo n.º 2
0
/*
=================
R_BindAnimatedImage

=================
*/
static void R_BindAnimatedImage( textureBundle_t *bundle ) {
    int		index;

    if ( bundle->isVideoMap ) {
        ri.CIN_RunCinematic(bundle->videoMapHandle);
        ri.CIN_UploadCinematic(bundle->videoMapHandle);
        return;
    }

    if ( bundle->isRenderTarget ) {
        qglBindTexture (GL_TEXTURE_2D, bundle->renderTarget);
        return;
    }

    if ( bundle->numImageAnimations <= 1 ) {
        GL_Bind( bundle->image[0] );
        return;
    }

    // it is necessary to do this messy calc to make sure animations line up
    // exactly with waveforms of the same frequency
    index = myftol( tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE );
    index >>= FUNCTABLE_SIZE2;

    if ( index < 0 ) {
        index = 0;	// may happen with shader time offsets
    }
    index %= bundle->numImageAnimations;

    GL_Bind( bundle->image[ index ] );
}
Exemplo n.º 3
0
static const d3dImage_t* GetAnimatedImage( textureBundle_t *bundle, float shaderTime ) {
	int		index;

	if ( bundle->isVideoMap ) {
		ri.CIN_RunCinematic(bundle->videoMapHandle);
		ri.CIN_UploadCinematic(bundle->videoMapHandle);
		return GetImageRenderInfo( tr.scratchImage[bundle->videoMapHandle] );
	}

	if ( bundle->numImageAnimations <= 1 ) {
		return GetImageRenderInfo( bundle->image[0] );
	}

	// it is necessary to do this messy calc to make sure animations line up
	// exactly with waveforms of the same frequency
	index = myftol( shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE );
	index >>= FUNCTABLE_SIZE2;

	if ( index < 0 ) {
		index = 0;	// may happen with shader time offsets
	}
	index %= bundle->numImageAnimations;

    return GetImageRenderInfo( bundle->image[index] );
}
Exemplo n.º 4
0
void foo(unsigned char *colors) {
	int v;
	float glow = g;

	v = myftol(255*glow);
	colors[0] = colors[1] = colors[2] = v;
}
Exemplo n.º 5
0
/*
=================
R_ComputeLOD

=================
*/
int R_ComputeLOD( trRefEntity_t *ent ) {
	float radius;
	float flod, lodscale;
	float projectedRadius;
	md3Frame_t *frame;
	int lod;

	if ( tr.currentModel->numLods < 2 )
	{
		// model has only 1 LOD level, skip computations and bias
		lod = 0;
	}
	else
	{
		// multiple LODs exist, so compute projected bounding sphere
		// and use that as a criteria for selecting LOD

		frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );

		frame += ent->e.frame;

		radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] );

		if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 )
		{
			lodscale = r_lodscale->value;
			if (lodscale > 20) lodscale = 20;
			flod = 1.0f - projectedRadius * lodscale;
		}
		else
		{
			// object intersects near view plane, e.g. view weapon
			flod = 0;
		}

		flod *= tr.currentModel->numLods;
		lod = myftol( flod );

		if ( lod < 0 )
		{
			lod = 0;
		}
		else if ( lod >= tr.currentModel->numLods )
		{
			lod = tr.currentModel->numLods - 1;
		}
	}

	lod += r_lodbias->integer;
	
	if ( lod >= tr.currentModel->numLods )
		lod = tr.currentModel->numLods - 1;
	if ( lod < 0 )
		lod = 0;

	return lod;
}
Exemplo n.º 6
0
float BG_GetGroundHeightAtPoint(vec3_t pos)
{
    int    i, j;
    vec2_t point;

    if (!tracemap.loaded)
    {
        return MIN_WORLD_HEIGHT;
    }

    BG_ClampPointToTracemapExtends(pos, point);

    i = myftol((point[0] - tracemap.world_mins[0]) * one_over_mapgrid_factor[0]);
    j = myftol((point[1] - tracemap.world_mins[1]) * one_over_mapgrid_factor[1]);

    // rain - re-clamp the points, because a rounding error can cause
    // them to go outside the array
    etpro_FinalizeTracemapClamp(&i, &j);

    return(tracemap.ground[j][i]);
}
Exemplo n.º 7
0
// Helper function
//-------------------------
void ClampVec( vec3_t dat, byte *res )
{
	int r;

	// clamp all vec values, then multiply the normalized values by 255 to maximize the result
	for ( int i = 0; i < 3; i++ )
	{
		r = myftol(dat[i] * 255.0f);

		if ( r < 0 )
		{
			r = 0;
		}
		else if ( r > 255 )
		{
			r = 255;
		}

		res[i] = (unsigned char)r;
	}	
}
Exemplo n.º 8
0
static void DynamicLightPass( void ) {
	int i, l, a, b, c, color, *intColors;
	vec3_t origin;
	byte        *colors;
	unsigned hitIndexes[ SHADER_MAX_INDEXES ];
	int numIndexes;
	float radius, radiusInverseCubed;
	float intensity, remainder, modulate;
	vec3_t floatColor, dir;
	dlight_t    *dl;


	// early out
	if ( backEnd.refdef.num_dlights == 0 ) {
		return;
	}

	// walk light list
	for ( l = 0; l < backEnd.refdef.num_dlights; l++ )
	{
		// early out
		if ( !( tess.dlightBits & ( 1 << l ) ) ) {
			continue;
		}

		// clear colors
		Com_Memset( tess.svars.colors, 0, sizeof( tess.svars.colors ) );

		// setup
		dl = &backEnd.refdef.dlights[ l ];
		VectorCopy( dl->transformed, origin );
		radius = dl->radius;
		radiusInverseCubed = dl->radiusInverseCubed;
		intensity = dl->intensity;
		floatColor[ 0 ] = dl->color[ 0 ] * 255.0f;
		floatColor[ 1 ] = dl->color[ 1 ] * 255.0f;
		floatColor[ 2 ] = dl->color[ 2 ] * 255.0f;

		// directional lights have max intensity and washout remainder intensity
		if ( dl->flags & REF_DIRECTED_DLIGHT ) {
			remainder = intensity * 0.125;
		} else {
			remainder = 0.0f;
		}

		// illuminate vertexes
		colors = tess.svars.colors[ 0 ];
		for ( i = 0; i < tess.numVertexes; i++, colors += 4 )
		{
			backEnd.pc.c_dlightVertexes++;

			// directional dlight, origin is a directional normal
			if ( dl->flags & REF_DIRECTED_DLIGHT ) {
				// twosided surfaces use absolute value of the calculated lighting
				modulate = intensity * DotProduct( dl->origin, tess.normal[ i ].v );
				if ( tess.shader->cullType == CT_TWO_SIDED ) {
					modulate = fabs( modulate );
				}
				modulate += remainder;
			}
			// ball dlight
			else
			{
				dir[ 0 ] = radius - fabs( origin[ 0 ] - tess.xyz[ i ].v[ 0 ] );
				if ( dir[ 0 ] <= 0.0f ) {
					continue;
				}
				dir[ 1 ] = radius - fabs( origin[ 1 ] - tess.xyz[ i ].v[ 1 ] );
				if ( dir[ 1 ] <= 0.0f ) {
					continue;
				}
				dir[ 2 ] = radius - fabs( origin[ 2 ] - tess.xyz[ i ].v[ 2 ] );
				if ( dir[ 2 ] <= 0.0f ) {
					continue;
				}

				modulate = intensity * dir[ 0 ] * dir[ 1 ] * dir[ 2 ] * radiusInverseCubed;
			}

			// optimizations
			if ( modulate < ( 1.0f / 128.0f ) ) {
				continue;
			} else if ( modulate > 1.0f ) {
				modulate = 1.0f;
			}

			// set color
			color = myftol( floatColor[ 0 ] * modulate );
			colors[ 0 ] = color > 255 ? 255 : color;
			color = myftol( floatColor[ 1 ] * modulate );
			colors[ 1 ] = color > 255 ? 255 : color;
			color = myftol( floatColor[ 2 ] * modulate );
			colors[ 2 ] = color > 255 ? 255 : color;
		}

		// build a list of triangles that need light
		intColors = (int*) tess.svars.colors;
		numIndexes = 0;
		for ( i = 0; i < tess.numIndexes; i += 3 )
		{
			a = tess.indexes[ i ];
			b = tess.indexes[ i + 1 ];
			c = tess.indexes[ i + 2 ];
			if ( !( intColors[ a ] | intColors[ b ] | intColors[ c ] ) ) {
				continue;
			}
			hitIndexes[ numIndexes++ ] = a;
			hitIndexes[ numIndexes++ ] = b;
			hitIndexes[ numIndexes++ ] = c;
		}

		if ( numIndexes == 0 ) {
			continue;
		}

		// debug code (fixme, there's a bug in this function!)
		//%	for( i = 0; i < numIndexes; i++ )
		//%		intColors[ hitIndexes[ i ] ] = 0x000000FF;

		qglEnableClientState( GL_COLOR_ARRAY );
		qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );

		R_FogOff();
		GL_Bind( tr.whiteImage );
		GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
		R_DrawElements( numIndexes, hitIndexes );
		backEnd.pc.c_totalIndexes += numIndexes;
		backEnd.pc.c_dlightIndexes += numIndexes;
		R_FogOn();
	}
}
Exemplo n.º 9
0
/*
=================
R_SetupEntityLighting

Calculates all the lighting values that will be used
by the Calc_* functions
=================
*/
void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
	int				i;
	dlight_t		*dl;
	float			power;
	vec3_t			dir;
	float			d;
	vec3_t			lightDir;
	vec3_t			lightOrigin;

	// lighting calculations 
	if ( ent->lightingCalculated ) {
		return;
	}
	ent->lightingCalculated = qtrue;

	//
	// trace a sample point down to find ambient light
	//
	if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
		// seperate lightOrigins are needed so an object that is
		// sinking into the ground can still be lit, and so
		// multi-part models can be lit identically
		VectorCopy( ent->e.lightingOrigin, lightOrigin );
	} else {
		VectorCopy( ent->e.origin, lightOrigin );
	}

	// if NOWORLDMODEL, only use dynamic lights (menu system, etc)
	if ( !(refdef->rdflags & RDF_NOWORLDMODEL ) 
		&& tr.world->lightGridData ) {
		R_SetupEntityLightingGrid( ent );
	} else {
		ent->ambientLight[0] = ent->ambientLight[1] = 
			ent->ambientLight[2] = tr.identityLight * 150;
		ent->directedLight[0] = ent->directedLight[1] = 
			ent->directedLight[2] = tr.identityLight * 150;
		VectorCopy( tr.sunDirection, ent->lightDir );
	}

	// bonus items and view weapons have a fixed minimum add
	if ( 1 /* ent->e.renderfx & RF_MINLIGHT */ ) {
		// give everything a minimum light add
		ent->ambientLight[0] += tr.identityLight * 32;
		ent->ambientLight[1] += tr.identityLight * 32;
		ent->ambientLight[2] += tr.identityLight * 32;
	}

	if (ent->e.renderfx & RF_MINLIGHT)
	{ //the minlight flag is now for items rotating on their holo thing
		if (ent->e.shaderRGBA[0] == 255 &&
			ent->e.shaderRGBA[1] == 255 &&
			ent->e.shaderRGBA[2] == 0)
		{
			ent->ambientLight[0] += tr.identityLight * 255;
			ent->ambientLight[1] += tr.identityLight * 255;
			ent->ambientLight[2] += tr.identityLight * 0;
		}
		else
		{
			ent->ambientLight[0] += tr.identityLight * 16;
			ent->ambientLight[1] += tr.identityLight * 96;
			ent->ambientLight[2] += tr.identityLight * 150;
		}
	}

	//
	// modify the light by dynamic lights
	//
	d = VectorLength( ent->directedLight );
	VectorScale( ent->lightDir, d, lightDir );

	for ( i = 0 ; i < refdef->num_dlights ; i++ ) {
		dl = &refdef->dlights[i];
		VectorSubtract( dl->origin, lightOrigin, dir );
		d = VectorNormalize( dir );

		power = DLIGHT_AT_RADIUS * ( dl->radius * dl->radius );
		if ( d < DLIGHT_MINIMUM_RADIUS ) {
			d = DLIGHT_MINIMUM_RADIUS;
		}
		d = power / ( d * d );

		VectorMA( ent->directedLight, d, dl->color, ent->directedLight );
		VectorMA( lightDir, d, dir, lightDir );
	}

	// clamp ambient
	for ( i = 0 ; i < 3 ; i++ ) {
		if ( ent->ambientLight[i] > tr.identityLightByte ) {
			ent->ambientLight[i] = tr.identityLightByte;
		}
	}

	if ( r_debugLight->integer ) {
		LogLight( ent );
	}

	// save out the byte packet version
	((byte *)&ent->ambientLightInt)[0] = myftol( ent->ambientLight[0] );
	((byte *)&ent->ambientLightInt)[1] = myftol( ent->ambientLight[1] );
	((byte *)&ent->ambientLightInt)[2] = myftol( ent->ambientLight[2] );
	((byte *)&ent->ambientLightInt)[3] = 0xff;
	
	// transform the direction to local space
	VectorNormalize( lightDir );
	ent->lightDir[0] = DotProduct( lightDir, ent->e.axis[0] );
	ent->lightDir[1] = DotProduct( lightDir, ent->e.axis[1] );
	ent->lightDir[2] = DotProduct( lightDir, ent->e.axis[2] );
}
Exemplo n.º 10
0
/*
=================
R_ComputeLOD

=================
*/
static int R_ComputeLOD( trRefEntity_t *ent ) {
	float radius;
	float flod, lodscale;
	float projectedRadius;
	md3Frame_t *frame;
	int lod;

	if ( tr.currentModel->numLods < 2 ) {
		// model has only 1 LOD level, skip computations and bias
		lod = 0;
	} else
	{
		// multiple LODs exist, so compute projected bounding sphere
		// and use that as a criteria for selecting LOD

		// RF, checked for a forced lowest LOD
		if ( ent->e.reFlags & REFLAG_FORCE_LOD ) {
			return ( tr.currentModel->numLods - 1 );
		}

		frame = ( md3Frame_t * )( ( ( unsigned char * ) tr.currentModel->mdc[0] ) + tr.currentModel->mdc[0]->ofsFrames );

		frame += ent->e.frame;

		radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] );

		//----(SA)	testing
		if ( ent->e.reFlags & REFLAG_ORIENT_LOD ) {
			// right now this is for trees, and pushes the lod distance way in.
			// this is not the intended purpose, but is helpful for the new
			// terrain level that has loads of trees
//			radius = radius/2.0f;
		}
		//----(SA)	end

		if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 ) {
			lodscale = r_lodscale->value;
			if ( lodscale > 20 ) {
				lodscale = 20;
			}
			flod = 1.0f - projectedRadius * lodscale;
		} else
		{
			// object intersects near view plane, e.g. view weapon
			flod = 0;
		}

		flod *= tr.currentModel->numLods;
		lod = myftol( flod );

		if ( lod < 0 ) {
			lod = 0;
		} else if ( lod >= tr.currentModel->numLods )   {
			lod = tr.currentModel->numLods - 1;
		}
	}

	lod += r_lodbias->integer;

	if ( lod >= tr.currentModel->numLods ) {
		lod = tr.currentModel->numLods - 1;
	}
	if ( lod < 0 ) {
		lod = 0;
	}

	return lod;
}
Exemplo n.º 11
0
static void ProjectDlightTexture_scalar( void ) {
	int		i, l;
	vec3_t	origin;
	float	*texCoords;
	byte	*colors;
	byte	clipBits[SHADER_MAX_VERTEXES];
	float	texCoordsArray[SHADER_MAX_VERTEXES][2];
	byte	colorArray[SHADER_MAX_VERTEXES][4];
	unsigned	hitIndexes[SHADER_MAX_INDEXES];
	int		numIndexes;
	float	scale;
	float	radius;
	vec3_t	floatColor;
	float	modulate = 0.0f;

	if ( !backEnd.refdef.num_dlights ) {
		return;
	}

	for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
		dlight_t	*dl;

		if ( !( tess.dlightBits & ( 1 << l ) ) ) {
			continue;	// this surface definately doesn't have any of this light
		}
		texCoords = texCoordsArray[0];
		colors = colorArray[0];

		dl = &backEnd.refdef.dlights[l];
		VectorCopy( dl->transformed, origin );
		radius = dl->radius;
		scale = 1.0f / radius;

		if(r_greyscale->integer)
		{
			float luminance;
			
			luminance = (dl->color[0] * 255.0f + dl->color[1] * 255.0f + dl->color[2] * 255.0f) / 3;
			floatColor[0] = floatColor[1] = floatColor[2] = luminance;
		}
		else
		{
			floatColor[0] = dl->color[0] * 255.0f;
			floatColor[1] = dl->color[1] * 255.0f;
			floatColor[2] = dl->color[2] * 255.0f;
		}

		for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) {
			int		clip = 0;
			vec3_t	dist;
			
			VectorSubtract( origin, tess.xyz[i], dist );

			backEnd.pc.c_dlightVertexes++;

			texCoords[0] = 0.5f + dist[0] * scale;
			texCoords[1] = 0.5f + dist[1] * scale;

			if( !r_dlightBacks->integer &&
					// dist . tess.normal[i]
					( dist[0] * tess.normal[i][0] +
					dist[1] * tess.normal[i][1] +
					dist[2] * tess.normal[i][2] ) < 0.0f ) {
				clip = 63;
			} else {
				if ( texCoords[0] < 0.0f ) {
					clip |= 1;
				} else if ( texCoords[0] > 1.0f ) {
					clip |= 2;
				}
				if ( texCoords[1] < 0.0f ) {
					clip |= 4;
				} else if ( texCoords[1] > 1.0f ) {
					clip |= 8;
				}
				texCoords[0] = texCoords[0];
				texCoords[1] = texCoords[1];

				// modulate the strength based on the height and color
				if ( dist[2] > radius ) {
					clip |= 16;
					modulate = 0.0f;
				} else if ( dist[2] < -radius ) {
					clip |= 32;
					modulate = 0.0f;
				} else {
					dist[2] = Q_fabs(dist[2]);
					if ( dist[2] < radius * 0.5f ) {
						modulate = 1.0f;
					} else {
						modulate = 2.0f * (radius - dist[2]) * scale;
					}
				}
			}
			clipBits[i] = clip;
			colors[0] = myftol(floatColor[0] * modulate);
			colors[1] = myftol(floatColor[1] * modulate);
			colors[2] = myftol(floatColor[2] * modulate);
			colors[3] = 255;
		}

		// build a list of triangles that need light
		numIndexes = 0;
		for ( i = 0 ; i < tess.numIndexes ; i += 3 ) {
			int		a, b, c;

			a = tess.indexes[i];
			b = tess.indexes[i+1];
			c = tess.indexes[i+2];
			if ( clipBits[a] & clipBits[b] & clipBits[c] ) {
				continue;	// not lighted
			}
			hitIndexes[numIndexes] = a;
			hitIndexes[numIndexes+1] = b;
			hitIndexes[numIndexes+2] = c;
			numIndexes += 3;
		}

		if ( !numIndexes ) {
			continue;
		}

		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
		qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );

		qglEnableClientState( GL_COLOR_ARRAY );
		qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );

		GL_Bind( tr.dlightImage );
		// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
		// where they aren't rendered
		if ( dl->additive ) {
			GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
		}
		else {
			GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
		}
		R_DrawElements( numIndexes, hitIndexes );
		backEnd.pc.c_totalIndexes += numIndexes;
		backEnd.pc.c_dlightIndexes += numIndexes;
	}
}
Exemplo n.º 12
0
/*
=================
R_ComputeLOD

=================
*/
int R_ComputeLOD( trRefEntity_t *ent ) {
	float radius;
	float flod, lodscale;
	float projectedRadius;
	md3Frame_t *frame;
#ifdef RAVENMD4
	mdrHeader_t *mdr;
	mdrFrame_t *mdrframe;
#endif
	int lod;

	if ( tr.currentModel->numLods < 2 )
	{
		// model has only 1 LOD level, skip computations and bias
		lod = 0;
	}
	else
	{
		// multiple LODs exist, so compute projected bounding sphere
		// and use that as a criteria for selecting LOD

#ifdef RAVENMD4
		if(tr.currentModel->type == MOD_MDR)
		{
			int frameSize;
			mdr = (mdrHeader_t *) tr.currentModel->modelData;
			frameSize = (size_t) (&((mdrFrame_t *)0)->bones[mdr->numBones]);
			
			mdrframe = (mdrFrame_t *) ((byte *) mdr + mdr->ofsFrames + frameSize * ent->e.frame);
			
			radius = RadiusFromBounds(mdrframe->bounds[0], mdrframe->bounds[1]);
		}
		else
#endif
		{
			frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );

			frame += ent->e.frame;

			radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] );
		}

		if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 )
		{
			lodscale = r_lodscale->value;
			if (lodscale > 20) lodscale = 20;
			flod = 1.0f - projectedRadius * lodscale;
		}
		else
		{
			// object intersects near view plane, e.g. view weapon
			flod = 0;
		}

		flod *= tr.currentModel->numLods;
		lod = myftol( flod );

		if ( lod < 0 )
		{
			lod = 0;
		}
		else if ( lod >= tr.currentModel->numLods )
		{
			lod = tr.currentModel->numLods - 1;
		}
	}

	lod += r_lodbias->integer;

	if ( lod >= tr.currentModel->numLods )
		lod = tr.currentModel->numLods - 1;
	if ( lod < 0 )
		lod = 0;

	return lod;
}
Exemplo n.º 13
0
/*
===================
ProjectDlightTexture

Perform dynamic lighting with another rendering pass
===================
*/
static void ProjectDlightTexture( void ) {
	int i, l;
	vec3_t origin;
	float   *texCoords;
	byte    *colors;
	byte clipBits[SHADER_MAX_VERTEXES];
	MAC_STATIC float texCoordsArray[SHADER_MAX_VERTEXES][2];
	byte colorArray[SHADER_MAX_VERTEXES][4];
	glIndex_t hitIndexes[SHADER_MAX_INDEXES];
	int numIndexes;
	float scale;
	float radius;
	vec3_t floatColor;

	if ( !backEnd.refdef.num_dlights ) {
		return;
	}


	if ( backEnd.refdef.rdflags & RDF_SNOOPERVIEW ) {  // no dlights for snooper
		return;
	}


	for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
		dlight_t    *dl;

		if ( !( tess.dlightBits & ( 1 << l ) ) ) {
			continue;   // this surface definately doesn't have any of this light
		}
		texCoords = texCoordsArray[0];
		colors = colorArray[0];

		dl = &backEnd.refdef.dlights[l];
		VectorCopy( dl->transformed, origin );
		radius = dl->radius;
		scale = 1.0f / radius;
		floatColor[0] = dl->color[0] * 255.0f;
		floatColor[1] = dl->color[1] * 255.0f;
		floatColor[2] = dl->color[2] * 255.0f;

		for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) {
			vec3_t dist;
			int clip;
			float modulate;

			if ( 0 ) {
				clipBits[i] = 255;  // definately not dlighted
				continue;
			}

			VectorSubtract( origin, tess.xyz[i], dist );

//			if(!r_dlightBacks->integer) {
//				vec3_t	dir;
//				VectorNormalize2(dist, dir);
//				if( DotProduct( tess.normal[i], dir) < 0) {
//					clipBits[i] = 255;	// not lighted (backface)
//					continue;
//				}
//			}

			backEnd.pc.c_dlightVertexes++;

			texCoords[0] = 0.5f + dist[0] * scale;
			texCoords[1] = 0.5f + dist[1] * scale;

			clip = 0;
			if ( texCoords[0] < 0.0f ) {
				clip |= 1;
			} else if ( texCoords[0] > 1.0f ) {
				clip |= 2;
			}
			if ( texCoords[1] < 0.0f ) {
				clip |= 4;
			} else if ( texCoords[1] > 1.0f ) {
				clip |= 8;
			}
			// modulate the strength based on the height and color
			if ( dist[2] > radius ) {
				clip |= 16;
				modulate = 0.0f;
			} else if ( dist[2] < -radius ) {
				clip |= 32;
				modulate = 0.0f;
			} else {
				modulate = dist[2] * scale;
				modulate = 1 - modulate * modulate;
			}
			clipBits[i] = clip;

			colors[0] = myftol( floatColor[0] * modulate );
			colors[1] = myftol( floatColor[1] * modulate );
			colors[2] = myftol( floatColor[2] * modulate );
			colors[3] = 255;
		}

		// build a list of triangles that need light
		numIndexes = 0;
		for ( i = 0 ; i < tess.numIndexes ; i += 3 ) {
			glIndex_t a, b, c;

			a = tess.indexes[i];
			b = tess.indexes[i + 1];
			c = tess.indexes[i + 2];
			if ( clipBits[a] & clipBits[b] & clipBits[c] ) {
				continue;   // not lighted
			}

//			if(!r_dlightBacks->integer) {
//				vec3_t	dir;
//				VectorSubtract( origin, tess.xyz[a], dir );
//				VectorNormalize(dir);
//				if( DotProduct( tess.normal[i], dir) < 0) {
//					continue;	// not lighted (backface)
//				}
//			}

			vec3_t  va,vb,vc,vx;
			VectorSubtract( origin, tess.xyz[a], va );
			VectorSubtract( tess.xyz[a], tess.xyz[b], vb );
			VectorSubtract( tess.xyz[a], tess.xyz[c], vc );
			CrossProduct(vb,vc,vx);
			if (DotProduct( vx, va ) > 0) continue;

			hitIndexes[numIndexes] = a;
			hitIndexes[numIndexes + 1] = b;
			hitIndexes[numIndexes + 2] = c;
			numIndexes += 3;
		}

		if ( !numIndexes ) {
			continue;
		}

		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
		qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );

		qglEnableClientState( GL_COLOR_ARRAY );
		qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );

		//----(SA) creating dlight shader to allow for special blends or alternate dlight texture
		{
			shader_t *dls = dl->dlshader;
			if ( dls ) {
//				if (!qglActiveTextureARB || dls->numUnfoggedPasses < 2) {
				for ( i = 0; i < dls->numUnfoggedPasses; i++ )
				{
					shaderStage_t *stage = dls->stages[i];
					R_BindAnimatedImage( &dls->stages[i]->bundle[0] );
					GL_State( stage->stateBits | GLS_DEPTHFUNC_EQUAL );
					R_DrawElements( numIndexes, hitIndexes );
					backEnd.pc.c_totalIndexes += numIndexes;
					backEnd.pc.c_dlightIndexes += numIndexes;
				}
/*
				} else {	// optimize for multitexture

					for(i=0;i<dls->numUnfoggedPasses;)
					{
						shaderStage_t *stage = dls->stages[i];

						GL_State(stage->stateBits | GLS_DEPTHFUNC_EQUAL);

						// setup each TMU
						for (tmu=0; tmu<glConfig.maxActiveTextures && i<dls->numUnfoggedPasses; tmu++, i++) {

							GL_SelectTexture( tmu );

							if (tmu) {
								qglEnable( GL_TEXTURE_2D );
							}

							R_BindAnimatedImage( &dls->stages[i]->bundle[0] );
						}

						// draw the elements
						R_DrawElements( numIndexes, hitIndexes );
						backEnd.pc.c_totalIndexes += numIndexes;
						backEnd.pc.c_dlightIndexes += numIndexes;
					}

					// turn off unused TMU's
					for (tmu=1; tmu<glConfig.maxActiveTextures; tmu++) {
						// set back to default state
						GL_SelectTexture( tmu );
						qglDisable( GL_TEXTURE_2D );
					}

					// return to TEXTURE0
					GL_SelectTexture( 0 );
				}
*/
			} else
			{
				R_FogOff();

//				if (!dl->overdraw || !qglActiveTextureARB) {
				GL_Bind( tr.dlightImage );
				// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
				// where they aren't rendered
				GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
				R_DrawElements( numIndexes, hitIndexes );
				backEnd.pc.c_totalIndexes += numIndexes;
				backEnd.pc.c_dlightIndexes += numIndexes;

				// Ridah, overdraw lights several times, rather than sending
				//	multiple lights through
				for ( i = 0; i < dl->overdraw; i++ ) {
					R_DrawElements( numIndexes, hitIndexes );
					backEnd.pc.c_totalIndexes += numIndexes;
					backEnd.pc.c_dlightIndexes += numIndexes;
				}
/*
				} else {	// optimize for multitexture

					GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );

					// setup each TMU (use all available TMU's)
					for (tmu=0; tmu<glConfig.maxActiveTextures && tmu<(dl->overdraw+1); tmu++) {
						GL_SelectTexture( tmu );
						if (tmu) {
							qglEnable( GL_TEXTURE_2D );
							GL_TexEnv( GL_ADD );
							GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
							qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
							qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );
							qglEnableClientState( GL_COLOR_ARRAY );
							qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );
						}
						GL_Bind( tr.dlightImage );
					}

					// draw each bundle
					for(i=0; i<(dl->overdraw+1); i+=glConfig.maxActiveTextures)
					{
						// make sure we dont draw with too many TMU's
						if (i+glConfig.maxActiveTextures>(dl->overdraw+1)) {
							for (tmu=0; tmu<glConfig.maxActiveTextures; tmu++) {
								if (tmu+i>=(dl->overdraw+1)) {
									GL_SelectTexture( tmu );
									qglDisable( GL_TEXTURE_2D );
								}
							}
						}
						// draw the elements
						R_DrawElements( numIndexes, hitIndexes );
						backEnd.pc.c_totalIndexes += numIndexes;
						backEnd.pc.c_dlightIndexes += numIndexes;
					}

					// turn off unused TMU's
					for (tmu=1; tmu<glConfig.maxActiveTextures; tmu++) {
						// set back to default state
						GL_SelectTexture( tmu );
						qglDisable( GL_TEXTURE_2D );
					}

					// return to TEXTURE0
					GL_SelectTexture( 0 );
				}
*/
				//R_FogOn();
			}
		}
	}
}
Exemplo n.º 14
0
/*
=================
R_SetupEntityLighting

Calculates all the lighting values that will be used
by the Calc_* functions
=================
*/
void R_SetupEntityLighting(const trRefdef_t *refdef, trRefEntity_t *ent)
{
	int i;
	dlight_t        *dl;
	float power;
	vec3_t dir;
	float d;
	vec3_t lightDir;
	vec3_t lightOrigin;
//	qboolean     highlighted = qfalse; // TTimo: unused

	// lighting calculations
	if(ent->lightingCalculated)
	{
		return;
	}

	ent->lightingCalculated = qtrue;

	//
	// trace a sample point down to find ambient light
	//
	if(ent->e.renderfx & RF_LIGHTING_ORIGIN)
	{
		// seperate lightOrigins are needed so an object that is
		// sinking into the ground can still be lit, and so
		// multi-part models can be lit identically
		VectorCopy(ent->e.lightingOrigin, lightOrigin);
	}
	else
	{
		VectorCopy(ent->e.origin, lightOrigin);
	}

	// if NOWORLDMODEL, only use dynamic lights (menu system, etc)
	if(!(refdef->rdflags & RDF_NOWORLDMODEL)
	        && tr.world->lightGridData)
	{
		R_SetupEntityLightingGrid(ent);
	}
	else
	{
		ent->ambientLight[0] = ent->ambientLight[1] =
		                           ent->ambientLight[2] = tr.identityLight * 150;
		ent->directedLight[0] = ent->directedLight[1] =
		                            ent->directedLight[2] = tr.identityLight * 150;
		VectorCopy(tr.sunDirection, ent->lightDir);
	}

	if(ent->e.hilightIntensity)
	{
		// level of intensity was set because the item was looked at
		ent->ambientLight[0] += tr.identityLight * 128 * ent->e.hilightIntensity;
		ent->ambientLight[1] += tr.identityLight * 128 * ent->e.hilightIntensity;
		ent->ambientLight[2] += tr.identityLight * 128 * ent->e.hilightIntensity;
	}
	else if(ent->e.renderfx & RF_MINLIGHT)
	{
		// give everything a minimum light add
		ent->ambientLight[0] += tr.identityLight * 32;
		ent->ambientLight[1] += tr.identityLight * 32;
		ent->ambientLight[2] += tr.identityLight * 32;
	}


	if(ent->e.entityNum < MAX_CLIENTS && (refdef->rdflags & RDF_SNOOPERVIEW))
	{
		VectorSet(ent->ambientLight, 245, 245, 245);      // allow a little room for flicker from directed light
	}


	//
	// modify the light by dynamic lights
	//
	d = VectorLength(ent->directedLight);
	VectorScale(ent->lightDir, d, lightDir);

	for(i = 0 ; i < refdef->num_dlights ; i++)
	{
		dl = &refdef->dlights[i];

		if(dl->dlshader)       //----(SA)   if the dlight has a diff shader specified, you don't know what it does, so don't let it affect entities lighting
		{
			continue;
		}

		VectorSubtract(dl->origin, lightOrigin, dir);
		d = VectorNormalize(dir);

		power = DLIGHT_AT_RADIUS * (dl->radius * dl->radius);

		if(d < DLIGHT_MINIMUM_RADIUS)
		{
			d = DLIGHT_MINIMUM_RADIUS;
		}

		d = power / (d * d);

		VectorMA(ent->directedLight, d, dl->color, ent->directedLight);
		VectorMA(lightDir, d, dir, lightDir);
	}

	// clamp ambient
	for(i = 0 ; i < 3 ; i++)
	{
		if(ent->ambientLight[i] > tr.identityLightByte)
		{
			ent->ambientLight[i] = tr.identityLightByte;
		}
	}

	if(r_debugLight->integer)
	{
		LogLight(ent);
	}

	// save out the byte packet version
	((byte *)&ent->ambientLightInt)[0] = myftol(ent->ambientLight[0]);
	((byte *)&ent->ambientLightInt)[1] = myftol(ent->ambientLight[1]);
	((byte *)&ent->ambientLightInt)[2] = myftol(ent->ambientLight[2]);
	((byte *)&ent->ambientLightInt)[3] = 0xff;

	// transform the direction to local space
	VectorNormalize(lightDir);
	ent->lightDir[0] = DotProduct(lightDir, ent->e.axis[0]);
	ent->lightDir[1] = DotProduct(lightDir, ent->e.axis[1]);
	ent->lightDir[2] = DotProduct(lightDir, ent->e.axis[2]);
}
Exemplo n.º 15
0
/*
===================
ProjectDlightTexture

Perform dynamic lighting with another rendering pass
===================
*/
static void ProjectDlightTexture( void ) {
    int		i, l;
#if idppc_altivec
    vec_t	origin0, origin1, origin2;
    float   texCoords0, texCoords1;
    vector float floatColorVec0, floatColorVec1;
    vector float modulateVec, colorVec, zero;
    vector short colorShort;
    vector signed int colorInt;
    vector unsigned char floatColorVecPerm, modulatePerm, colorChar;
    vector unsigned char vSel = (vector unsigned char)(0x00, 0x00, 0x00, 0xff,
                                0x00, 0x00, 0x00, 0xff,
                                0x00, 0x00, 0x00, 0xff,
                                0x00, 0x00, 0x00, 0xff);
#else
    vec3_t	origin;
#endif
    float	*texCoords;
    byte	*colors;
    byte	clipBits[SHADER_MAX_VERTEXES];
    MAC_STATIC float	texCoordsArray[SHADER_MAX_VERTEXES][2];
    byte	colorArray[SHADER_MAX_VERTEXES][4];
    unsigned	hitIndexes[SHADER_MAX_INDEXES];
    int		numIndexes;
    float	scale;
    float	radius;
    vec3_t	floatColor;
    float	modulate;

    if ( !backEnd.refdef.num_dlights ) {
        return;
    }

#if idppc_altivec
    // There has to be a better way to do this so that floatColor
    // and/or modulate are already 16-byte aligned.
    floatColorVecPerm = vec_lvsl(0,(float *)floatColor);
    modulatePerm = vec_lvsl(0,(float *)&modulate);
    modulatePerm = (vector unsigned char)vec_splat((vector unsigned int)modulatePerm,0);
    zero = (vector float)vec_splat_s8(0);
#endif

    for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
        dlight_t	*dl;

        if ( !( tess.dlightBits & ( 1 << l ) ) ) {
            continue;	// this surface definately doesn't have any of this light
        }
        texCoords = texCoordsArray[0];
        colors = colorArray[0];

        dl = &backEnd.refdef.dlights[l];
#if idppc_altivec
        origin0 = dl->transformed[0];
        origin1 = dl->transformed[1];
        origin2 = dl->transformed[2];
#else
        VectorCopy( dl->transformed, origin );
#endif
        radius = dl->radius;
        scale = 1.0f / radius;

        floatColor[0] = dl->color[0] * 255.0f;
        floatColor[1] = dl->color[1] * 255.0f;
        floatColor[2] = dl->color[2] * 255.0f;
#if idppc_altivec
        floatColorVec0 = vec_ld(0, floatColor);
        floatColorVec1 = vec_ld(11, floatColor);
        floatColorVec0 = vec_perm(floatColorVec0,floatColorVec0,floatColorVecPerm);
#endif
        for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) {
#if idppc_altivec
            vec_t dist0, dist1, dist2;
#else
            vec3_t	dist;
#endif
            int		clip;

            backEnd.pc.c_dlightVertexes++;

#if idppc_altivec
            //VectorSubtract( origin, tess.xyz[i], dist );
            dist0 = origin0 - tess.xyz[i][0];
            dist1 = origin1 - tess.xyz[i][1];
            dist2 = origin2 - tess.xyz[i][2];
            texCoords0 = 0.5f + dist0 * scale;
            texCoords1 = 0.5f + dist1 * scale;

            clip = 0;
            if ( texCoords0 < 0.0f ) {
                clip |= 1;
            } else if ( texCoords0 > 1.0f ) {
                clip |= 2;
            }
            if ( texCoords1 < 0.0f ) {
                clip |= 4;
            } else if ( texCoords1 > 1.0f ) {
                clip |= 8;
            }
            texCoords[0] = texCoords0;
            texCoords[1] = texCoords1;

            // modulate the strength based on the height and color
            if ( dist2 > radius ) {
                clip |= 16;
                modulate = 0.0f;
            } else if ( dist2 < -radius ) {
                clip |= 32;
                modulate = 0.0f;
            } else {
                dist2 = Q_fabs(dist2);
                if ( dist2 < radius * 0.5f ) {
                    modulate = 1.0f;
                } else {
                    modulate = 2.0f * (radius - dist2) * scale;
                }
            }
            clipBits[i] = clip;

            modulateVec = vec_ld(0,(float *)&modulate);
            modulateVec = vec_perm(modulateVec,modulateVec,modulatePerm);
            colorVec = vec_madd(floatColorVec0,modulateVec,zero);
            colorInt = vec_cts(colorVec,0);	// RGBx
            colorShort = vec_pack(colorInt,colorInt);		// RGBxRGBx
            colorChar = vec_packsu(colorShort,colorShort);	// RGBxRGBxRGBxRGBx
            colorChar = vec_sel(colorChar,vSel,vSel);		// RGBARGBARGBARGBA replace alpha with 255
            vec_ste((vector unsigned int)colorChar,0,(unsigned int *)colors);	// store color
#else
            VectorSubtract( origin, tess.xyz[i], dist );
            texCoords[0] = 0.5f + dist[0] * scale;
            texCoords[1] = 0.5f + dist[1] * scale;

            clip = 0;
            if ( texCoords[0] < 0.0f ) {
                clip |= 1;
            } else if ( texCoords[0] > 1.0f ) {
                clip |= 2;
            }
            if ( texCoords[1] < 0.0f ) {
                clip |= 4;
            } else if ( texCoords[1] > 1.0f ) {
                clip |= 8;
            }
            // modulate the strength based on the height and color
            if ( dist[2] > radius ) {
                clip |= 16;
                modulate = 0.0f;
            } else if ( dist[2] < -radius ) {
                clip |= 32;
                modulate = 0.0f;
            } else {
                dist[2] = Q_fabs(dist[2]);
                if ( dist[2] < radius * 0.5f ) {
                    modulate = 1.0f;
                } else {
                    modulate = 2.0f * (radius - dist[2]) * scale;
                }
            }
            clipBits[i] = clip;

            colors[0] = myftol(floatColor[0] * modulate);
            colors[1] = myftol(floatColor[1] * modulate);
            colors[2] = myftol(floatColor[2] * modulate);
            colors[3] = 255;
#endif
        }

        // build a list of triangles that need light
        numIndexes = 0;
        for ( i = 0 ; i < tess.numIndexes ; i += 3 ) {
            int		a, b, c;

            a = tess.indexes[i];
            b = tess.indexes[i+1];
            c = tess.indexes[i+2];
            if ( clipBits[a] & clipBits[b] & clipBits[c] ) {
                continue;	// not lighted
            }
            hitIndexes[numIndexes] = a;
            hitIndexes[numIndexes+1] = b;
            hitIndexes[numIndexes+2] = c;
            numIndexes += 3;
        }

        if ( !numIndexes ) {
            continue;
        }

        qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
        qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );

        qglEnableClientState( GL_COLOR_ARRAY );
        qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );

        GL_Bind( tr.dlightImage );
        // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
        // where they aren't rendered
        if ( dl->additive ) {
            GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
        }
        else {
            GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
        }
        R_DrawElements( numIndexes, hitIndexes );
        backEnd.pc.c_totalIndexes += numIndexes;
        backEnd.pc.c_dlightIndexes += numIndexes;
    }
}
Exemplo n.º 16
0
static void FillCloudBox( const shader_t *shader, int stage )
{
    int i;

    for ( i =0; i < 6; i++ )
    {
        int sky_mins_subd[2], sky_maxs_subd[2];
        int s, t;
        float MIN_T;

        if ( 1 ) // FIXME? shader->sky->fullClouds )
        {
            MIN_T = -HALF_SKY_SUBDIVISIONS;

            // still don't want to draw the bottom, even if fullClouds
            if ( i == 5 )
                continue;
        }
        else
        {
            switch( i )
            {
            case 0:
            case 1:
            case 2:
            case 3:
                MIN_T = -1;
                break;
            case 5:
                // don't draw clouds beneath you
                continue;
            case 4:		// top
            default:
                MIN_T = -HALF_SKY_SUBDIVISIONS;
                break;
            }
        }

        sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
        sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
        sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
        sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;

        if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
                ( sky_mins[1][i] >= sky_maxs[1][i] ) )
        {
            continue;
        }

        sky_mins_subd[0] = myftol( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS );
        sky_mins_subd[1] = myftol( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS );
        sky_maxs_subd[0] = myftol( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS );
        sky_maxs_subd[1] = myftol( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS );

        if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
            sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
        else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )
            sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
        if ( sky_mins_subd[1] < MIN_T )
            sky_mins_subd[1] = MIN_T;
        else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )
            sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;

        if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )
            sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
        else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )
            sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
        if ( sky_maxs_subd[1] < MIN_T )
            sky_maxs_subd[1] = MIN_T;
        else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )
            sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;

        //
        // iterate through the subdivisions
        //
        for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
        {
            for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
            {
                MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
                            ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
                            i,
                            NULL,
                            s_skyPoints[t][s] );

                s_skyTexCoords[t][s][0] = s_cloudTexCoords[i][t][s][0];
                s_skyTexCoords[t][s][1] = s_cloudTexCoords[i][t][s][1];
            }
        }

        // only add indexes for first stage
        FillCloudySkySide( sky_mins_subd, sky_maxs_subd, ( stage == 0 ) );
    }
}
Exemplo n.º 17
0
static void ProjectDecalOntoWinding(decalProjector_t * dp, int numPoints, vec3_t points[2][MAX_DECAL_VERTS], msurface_t * surf,
									bmodel_t * bmodel)
{
	int             i, pingPong, count, axis;
	float           pd, d, d2, alpha = 1.f;
	vec4_t          plane;
	vec3_t          absNormal;
	decal_t        *decal, *oldest;
	polyVert_t     *vert;


	/* make a plane from the winding */
	if(!PlaneFromPoints(plane, points[0][0], points[0][1], points[0][2]))
	{
		return;
	}

	/* omnidirectional projectors need plane type */
	if(dp->omnidirectional)
	{
		/* compiler warnings be gone */
		pd = 1.0f;

		/* fade by distance from plane */
		d = DotProduct(dp->center, plane) - plane[3];
		alpha = 1.0f - (fabs(d) / dp->radius);
		if(alpha < 0.0f)
		{
			return;
		}
		if(alpha > 1.0f)
		{
			alpha = 1.0f;
		}

		/* set projection axis */
		absNormal[0] = fabs(plane[0]);
		absNormal[1] = fabs(plane[1]);
		absNormal[2] = fabs(plane[2]);
		if(absNormal[2] >= absNormal[0] && absNormal[2] >= absNormal[1])
		{
			axis = 2;
		}
		else if(absNormal[0] >= absNormal[1] && absNormal[0] >= absNormal[2])
		{
			axis = 0;
		}
		else
		{
			axis = 1;
		}
	}
	else
	{
		/* backface check */
		pd = DotProduct(dp->planes[0], plane);
		if(pd < -0.0001f)
		{
			return;
		}

		/* directional decals use first texture matrix */
		axis = 0;
	}

	/* chop the winding by all the projector planes */
	pingPong = 0;
	for(i = 0; i < dp->numPlanes; i++)	//%    dp->numPlanes
	{
		ChopWindingBehindPlane(numPoints, points[pingPong], &numPoints, points[!pingPong], dp->planes[i], 0.0f);
		pingPong ^= 1;
		if(numPoints < 3)
		{
			return;
		}
		if(numPoints == MAX_DECAL_VERTS)
		{
			break;
		}
	}

	/* find first free decal (fixme: optimize this) */
	count = (bmodel == tr.world->bmodels ? MAX_WORLD_DECALS : MAX_ENTITY_DECALS);
	oldest = &bmodel->decals[0];
	decal = bmodel->decals;
	for(i = 0; i < count; i++, decal++)
	{
		/* try to find an empty decal slot */
		if(decal->shader == NULL)
		{
			break;
		}

		/* find oldest decal */
		if(decal->fadeEndTime < oldest->fadeEndTime)
		{
			oldest = decal;
		}
	}

	/* guess we have to use the oldest decal */
	if(i >= count)
	{
		decal = oldest;
	}

	/* r_speeds useful info */
	tr.pc.c_decalSurfacesCreated++;

	/* set it up (fixme: get the shader before this happens) */
	decal->parent = surf;
	decal->shader = dp->shader;
	decal->fadeStartTime = dp->fadeStartTime;
	decal->fadeEndTime = dp->fadeEndTime;
	decal->fogIndex = surf->fogIndex;

	/* add points */
	decal->numVerts = numPoints;
	vert = decal->verts;
	for(i = 0; i < numPoints; i++, vert++)
	{
		/* set xyz */
		VectorCopy(points[pingPong][i], vert->xyz);

		/* set st */
		vert->st[0] = DotProduct(vert->xyz, dp->texMat[axis][0]) + dp->texMat[axis][0][3];
		vert->st[1] = DotProduct(vert->xyz, dp->texMat[axis][1]) + dp->texMat[axis][1][3];

		/* unidirectional decals fade by half distance from front->back planes */
		if(!dp->omnidirectional)
		{
			/* set alpha */
			d = DotProduct(vert->xyz, dp->planes[0]) - dp->planes[0][3];
			d2 = DotProduct(vert->xyz, dp->planes[1]) - dp->planes[1][3];
			alpha = 2.0f * d2 / (d + d2);
			if(alpha > 1.0f)
			{
				alpha = 1.0f;
			}
			else if(alpha < 0.0f)
			{
				alpha = 0.0f;
			}
		}

		/* set color */
		vert->modulate[0] = myftol(pd * alpha * dp->color[0]);
		vert->modulate[1] = myftol(pd * alpha * dp->color[1]);
		vert->modulate[2] = myftol(pd * alpha * dp->color[2]);
		vert->modulate[3] = myftol(alpha * dp->color[3]);
	}
}