예제 #1
0
/*
* R_ComputeShadowmapBounds
*/
static void R_ComputeShadowmapBounds( void )
{
	unsigned int i;
	vec3_t lightDir;
	vec4_t lightDiffuse;
	vec3_t mins, maxs;
	shadowGroup_t *group;

	for( i = 0; i < rsc.numShadowGroups; i++ ) {
		group = rsc.shadowGroups + i;

		// get projection dir from lightgrid
		R_LightForOrigin( group->origin, lightDir, group->lightAmbient, lightDiffuse, group->projDist * 0.5 );

		// prevent light dir from going upwards
		VectorSet( lightDir, -lightDir[0], -lightDir[1], -fabs( lightDir[2] ) );
		VectorNormalize2( lightDir, group->lightDir );

		VectorScale( group->lightDir, group->projDist, lightDir );
		VectorAdd( group->mins, lightDir, mins );
		VectorAdd( group->maxs, lightDir, maxs );

		AddPointToBounds( group->mins, group->visMins, group->visMaxs );
		AddPointToBounds( group->maxs, group->visMins, group->visMaxs );
		AddPointToBounds( mins, group->visMins, group->visMaxs );
		AddPointToBounds( maxs, group->visMins, group->visMaxs );
	}
}
예제 #2
0
/*
* R_RenderMeshGLSL_Material
*/
static void R_RenderMeshGLSL_Material( r_glslfeat_t programFeatures )
{
	int i;
	int tcgen, rgbgen;
	int state;
	int program, object;
	image_t *base, *normalmap, *glossmap, *decalmap, *entdecalmap;
	mat4x4_t unused;
	vec3_t lightDir = { 0.0f, 0.0f, 0.0f };
	vec4_t ambient = { 0.0f, 0.0f, 0.0f, 0.0f }, diffuse = { 0.0f, 0.0f, 0.0f, 0.0f };
	float offsetmappingScale, glossExponent;
	const superLightStyle_t *lightStyle = NULL;
	const mfog_t *fog = r_back.colorFog;
	shaderpass_t *pass = r_back.accumPasses[0];
	qboolean applyDecal;

	// handy pointers
	base = pass->anim_frames[0];
	normalmap = pass->anim_frames[1];
	glossmap = pass->anim_frames[2];
	decalmap = pass->anim_frames[3];
	entdecalmap = pass->anim_frames[4];

	tcgen = pass->tcgen;                // store the original tcgen
	rgbgen = pass->rgbgen.type;			// store the original rgbgen

	assert( normalmap );

	if( normalmap->samples == 4 )
		offsetmappingScale = r_offsetmapping_scale->value * r_back.currentShader->offsetmapping_scale;
	else	// no alpha in normalmap, don't bother with offset mapping
		offsetmappingScale = 0;

	if( r_back.currentShader->gloss_exponent )
		glossExponent = r_back.currentShader->gloss_exponent;
	else
		glossExponent = r_lighting_glossexponent->value;

	applyDecal = decalmap != NULL;

	if( ri.params & RP_CLIPPLANE )
		programFeatures |= GLSL_COMMON_APPLY_CLIPPING;
	if( pass->flags & SHADERPASS_GRAYSCALE )
		programFeatures |= GLSL_COMMON_APPLY_GRAYSCALE;

	if( fog )
	{
		programFeatures |= GLSL_COMMON_APPLY_FOG;
		if( fog != ri.fog_eye )
			programFeatures |= GLSL_COMMON_APPLY_FOG2;
		if( GL_IsAlphaBlending( pass->flags & GLSTATE_SRCBLEND_MASK, pass->flags & GLSTATE_DSTBLEND_MASK ) )
			programFeatures |= GLSL_COMMON_APPLY_COLOR_FOG_ALPHA;
	}

	if( r_back.currentMeshBuffer->infokey > 0 && ( rgbgen != RGB_GEN_LIGHTING_DIFFUSE ) )
	{
		if( !( r_offsetmapping->integer & 1 ) ) {
			offsetmappingScale = 0;
		}
		if( ri.params & RP_LIGHTMAP ) {
			programFeatures |= GLSL_MATERIAL_APPLY_BASETEX_ALPHA_ONLY;
		}
		if( ( ri.params & RP_DRAWFLAT ) && !( r_back.currentShader->flags & SHADER_NODRAWFLAT ) ) {
			programFeatures |= GLSL_COMMON_APPLY_DRAWFLAT|GLSL_MATERIAL_APPLY_BASETEX_ALPHA_ONLY;
		}
	}
	else if( ( r_back.currentMeshBuffer->sortkey & 3 ) == MB_POLY )
	{
		// polys
		if( !( r_offsetmapping->integer & 2 ) )
			offsetmappingScale = 0;

		R_BuildTangentVectors( r_backacc.numVerts, vertsArray, normalsArray, coordsArray, r_backacc.numElems/3, elemsArray, inSVectorsArray );
	}
	else
	{
		// models and world lightingDiffuse materials
		if( r_back.currentMeshBuffer->infokey > 0 )
		{
			if( !( r_offsetmapping->integer & 1 ) )
				offsetmappingScale = 0;
			pass->rgbgen.type = RGB_GEN_VERTEX;
		}
		else
		{
			// models
			if( !( r_offsetmapping->integer & 4 ) )
				offsetmappingScale = 0;
#ifdef CELLSHADEDMATERIAL
			programFeatures |= GLSL_MATERIAL_APPLY_CELLSHADING;
#endif
#ifdef HALFLAMBERTLIGHTING
			programFeatures |= GLSL_MATERIAL_APPLY_HALFLAMBERT;
#endif
		}
	}

	// add dynamic lights
	if( r_back.currentDlightBits ) {
		programFeatures |= R_DlightbitsToProgramFeatures();
	}

	pass->tcgen = TC_GEN_BASE;
	R_BindShaderpass( pass, base, 0, &programFeatures );

	// calculate vertex color
	R_ModifyColor( pass, applyDecal, r_back.currentMeshVBO != NULL );

	// since R_ModifyColor has forcefully generated RGBA for the first vertex,
	// set the proper number of color elements here, so GL_COLOR_ARRAY will be enabled
	// before the DrawElements call
	if( !(pass->flags & SHADERPASS_NOCOLORARRAY) )
		r_backacc.numColors = r_backacc.numVerts;

	// convert rgbgen and alphagen to GLSL feature defines
	programFeatures |= R_RGBAlphaGenToProgramFeatures( pass->rgbgen.type, pass->alphagen.type );

	GL_TexEnv( GL_MODULATE );

	// set shaderpass state (blending, depthwrite, etc)
	state = r_back.currentShaderState | ( pass->flags & r_back.currentShaderPassMask ) | GLSTATE_BLEND_MTEX;
	GL_SetState( state );

#if 1
	// don't waste time on processing GLSL programs with zero colormask
	if( ( ri.params & RP_SHADOWMAPVIEW ) & !(programFeatures & GLSL_COMMON_APPLY_BONETRANSFORMS) )
	{
		pass->tcgen = tcgen; // restore original tcgen
		R_FlushArrays();
		return;
	}
#endif

	// we only send S-vectors to GPU and recalc T-vectors as cross product
	// in vertex shader
	pass->tcgen = TC_GEN_SVECTORS;
	GL_Bind( 1, normalmap );         // normalmap
	GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY );
	R_VertexTCBase( pass, 1, unused, NULL );

	if( glossmap && r_lighting_glossintensity->value )
	{
		programFeatures |= GLSL_MATERIAL_APPLY_SPECULAR;
		GL_Bind( 2, glossmap ); // gloss
		GL_SetTexCoordArrayMode( 0 );
	}

	if( applyDecal )
	{
		programFeatures |= GLSL_MATERIAL_APPLY_DECAL;

		if( ri.params & RP_LIGHTMAP ) {
			decalmap = r_blacktexture;
			programFeatures |= GLSL_MATERIAL_APPLY_DECAL_ADD;
		}
		else {
			// if no alpha, use additive blending
			if( decalmap->samples == 3 )
				programFeatures |= GLSL_MATERIAL_APPLY_DECAL_ADD;
		}

		GL_Bind( 3, decalmap ); // decal
		GL_SetTexCoordArrayMode( 0 );
	}

	if( entdecalmap )
	{
		programFeatures |= GLSL_MATERIAL_APPLY_ENTITY_DECAL;

		// if no alpha, use additive blending
		if( entdecalmap->samples == 3 )
			programFeatures |= GLSL_MATERIAL_APPLY_ENTITY_DECAL_ADD;

		GL_Bind( 4, entdecalmap ); // decal
		GL_SetTexCoordArrayMode( 0 );
	}

	if( offsetmappingScale > 0 )
		programFeatures |= r_offsetmapping_reliefmapping->integer ? GLSL_MATERIAL_APPLY_RELIEFMAPPING : GLSL_MATERIAL_APPLY_OFFSETMAPPING;

	if( r_back.currentMeshBuffer->infokey > 0 && ( rgbgen != RGB_GEN_LIGHTING_DIFFUSE ) )
	{
		// world surface
		if( r_back.superLightStyle && r_back.superLightStyle->lightmapNum[0] >= 0 )
		{
			lightStyle = r_back.superLightStyle;

			// bind lightmap textures and set program's features for lightstyles
			pass->tcgen = TC_GEN_LIGHTMAP;

			for( i = 0; i < MAX_LIGHTMAPS && lightStyle->lightmapStyles[i] != 255; i++ )
			{
				r_back.lightmapStyleNum[i+4] = i;
				GL_Bind( i+4, r_worldbrushmodel->lightmapImages[lightStyle->lightmapNum[i]] ); // lightmap
				GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY );
				R_VertexTCBase( pass, i+4, unused, NULL );
			}

			programFeatures |= ( i * GLSL_MATERIAL_APPLY_LIGHTSTYLE0 );

			if( i == 1 && !mapConfig.lightingIntensity )
			{
				vec_t *rgb = r_lightStyles[lightStyle->lightmapStyles[0]].rgb;

				// GLSL_MATERIAL_APPLY_FB_LIGHTMAP indicates that there's no need to renormalize
				// the lighting vector for specular (saves 3 adds, 3 muls and 1 normalize per pixel)
				if( rgb[0] == 1 && rgb[1] == 1 && rgb[2] == 1 )
					programFeatures |= GLSL_MATERIAL_APPLY_FB_LIGHTMAP;
			}

			if( !VectorCompare( mapConfig.ambient, vec3_origin ) )
			{
				VectorCopy( mapConfig.ambient, ambient );
				programFeatures |= GLSL_MATERIAL_APPLY_AMBIENT_COMPENSATION;
			}
		}
	}
	else
	{
		vec3_t temp;

		programFeatures |= GLSL_MATERIAL_APPLY_DIRECTIONAL_LIGHT;

		if( ( r_back.currentMeshBuffer->sortkey & 3 ) == MB_POLY )
		{
			VectorCopy( r_polys[-r_back.currentMeshBuffer->infokey-1].normal, lightDir );
			Vector4Set( ambient, 0, 0, 0, 0 );
			Vector4Set( diffuse, 1, 1, 1, 1 );
		}
		else if( ri.currententity )
		{
			if( ri.currententity->flags & RF_FULLBRIGHT )
			{
				Vector4Set( ambient, 1, 1, 1, 1 );
				Vector4Set( diffuse, 1, 1, 1, 1 );
			}
			else
			{
				if( r_back.currentMeshBuffer->infokey > 0 )
				{
					programFeatures |= GLSL_MATERIAL_APPLY_DIRECTIONAL_LIGHT_MIX;
					if( r_back.overBrightBits )
						programFeatures |= GLSL_COMMON_APPLY_OVERBRIGHT_SCALING;
				}

				if( ri.currententity->model && ri.currententity != r_worldent )
				{
					// get weighted incoming direction of world and dynamic lights
					R_LightForOrigin( ri.currententity->lightingOrigin, temp, ambient, diffuse, 
						ri.currententity->model->radius * ri.currententity->scale);
				}
				else
				{
					VectorSet( temp, 0.1f, 0.2f, 0.7f );
				}

				if( ri.currententity->flags & RF_MINLIGHT )
				{
					if( ambient[0] <= 0.1f || ambient[1] <= 0.1f || ambient[2] <= 0.1f )
						VectorSet( ambient, 0.1f, 0.1f, 0.1f );
				}

				// rotate direction
				Matrix_TransformVector( ri.currententity->axis, temp, lightDir );
			}
		}
	}

	pass->tcgen = tcgen;    // restore original tcgen
	pass->rgbgen.type = rgbgen;		// restore original rgbgen

	program = R_RegisterGLSLProgram( pass->program_type, pass->program, NULL, 
		r_back.currentShader->name, r_back.currentShader->deforms, r_back.currentShader->numdeforms, programFeatures );
	object = R_GetProgramObject( program );
	if( object )
	{
		qglUseProgramObjectARB( object );

		// update uniforms
		R_UpdateProgramUniforms( program, ri.viewOrigin, vec3_origin, lightDir, ambient, diffuse, lightStyle,
			qtrue, 0, 0, 0, offsetmappingScale, glossExponent, 
			colorArrayCopy[0], r_back.overBrightBits, r_back.currentShaderTime, r_back.entityColor );

		if( programFeatures & GLSL_COMMON_APPLY_FOG )
		{
			cplane_t fogPlane, vpnPlane;

			R_TransformFogPlanes( fog, fogPlane.normal, &fogPlane.dist, vpnPlane.normal, &vpnPlane.dist );

			R_UpdateProgramFogParams( program, fog->shader->fog_color, fog->shader->fog_clearDist,
				fog->shader->fog_dist, &fogPlane, &vpnPlane, ri.fog_dist_to_eye[fog-r_worldbrushmodel->fogs] );
		}

		// submit animation data
		if( programFeatures & GLSL_COMMON_APPLY_BONETRANSFORMS ) {
			R_UpdateProgramBonesParams( program, r_back.currentAnimData->numBones, r_back.currentAnimData->dualQuats );
		}

		// dynamic lights
		if( r_back.currentDlightBits ) {
			R_UpdateProgramLightsParams( program, ri.currententity->origin, ri.currententity->axis, r_back.currentDlightBits );
			r_back.doDynamicLightsPass = qfalse;
		}

		// r_drawflat
		if( programFeatures & GLSL_COMMON_APPLY_DRAWFLAT ) {
			R_UpdateDrawFlatParams( program, r_front.wallColor, r_front.floorColor );
		}

		R_FlushArrays();

		qglUseProgramObjectARB( 0 );
	}
}
예제 #3
0
파일: r_frontend.c 프로젝트: DenMSC/qfusion
void RF_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t diffuse, float radius )
{
	R_LightForOrigin( origin, dir, ambient, diffuse, radius, false );
}