121 lines
3.3 KiB
C++
121 lines
3.3 KiB
C++
/***
|
|
*
|
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
|
*
|
|
* This product contains software technology licensed from Id
|
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
|
* All Rights Reserved.
|
|
*
|
|
****/
|
|
|
|
// dirtmap.c // quake3 dirt-mapping (fake Ambient Occlusion)
|
|
|
|
#include "qrad.h"
|
|
|
|
#define DIRT_CONE_ANGLE 115 // in degrees
|
|
#define DIRT_NUM_ELEVATION_STEPS 3
|
|
#define DIRT_NUM_ANGLE_STEPS 16
|
|
#define DIRT_NUM_VECTORS ( DIRT_NUM_ANGLE_STEPS * DIRT_NUM_ELEVATION_STEPS )
|
|
|
|
static vec3_t g_dirtvecs[DIRT_NUM_VECTORS];
|
|
static int g_num_dirtvecs = 0;
|
|
|
|
/*
|
|
============
|
|
SetupDirt
|
|
|
|
sets up dirtmap (ambient occlusion)
|
|
============
|
|
*/
|
|
void SetupDirt( void )
|
|
{
|
|
// check if needed
|
|
if( !g_dirtmapping )
|
|
return;
|
|
|
|
// calculate angular steps
|
|
vec_t angleStep = DEG2RAD( 360.0f / DIRT_NUM_ANGLE_STEPS );
|
|
vec_t elevationStep = DEG2RAD( DIRT_CONE_ANGLE / DIRT_NUM_ELEVATION_STEPS );
|
|
vec_t angle = 0.0f;
|
|
|
|
for( int i = 0; i < DIRT_NUM_ANGLE_STEPS; i++, angle += angleStep )
|
|
{
|
|
vec_t elevation = elevationStep * 0.5;
|
|
|
|
for( int j = 0; j < DIRT_NUM_ELEVATION_STEPS; j++, elevation += elevationStep )
|
|
{
|
|
g_dirtvecs[g_num_dirtvecs][0] = sin( elevation ) * cos( angle );
|
|
g_dirtvecs[g_num_dirtvecs][1] = sin( elevation ) * sin( angle );
|
|
g_dirtvecs[g_num_dirtvecs][2] = cos( elevation );
|
|
g_num_dirtvecs++;
|
|
}
|
|
}
|
|
|
|
MsgDev( D_REPORT, "%d dirtmap vectors\n", g_num_dirtvecs );
|
|
}
|
|
|
|
float GatherSampleDirt( int threadnum, int fn, const vec3_t pos, const vec3_t normal, entity_t *ignoreent )
|
|
{
|
|
vec3_t tangent, binormal, direction;
|
|
vec_t gatherDirt, outDirt;
|
|
vec_t dirtDepth = 128.0;
|
|
vec_t dirtScale = 2.0;
|
|
vec_t dirtGain = 2.0;
|
|
vec3_t vecSrc, vecEnd;
|
|
trace_t trace;
|
|
|
|
if( !g_dirtmapping ) return 1.0f; // early out
|
|
|
|
VectorCopy( pos, vecSrc );
|
|
gatherDirt = 0.0f;
|
|
|
|
if( fn >= 0 )
|
|
{
|
|
dface_t *f = &g_dfaces[fn];
|
|
dtexinfo_t *tx = &g_texinfo[f->texinfo];
|
|
float lmvecs[2][4];
|
|
|
|
if( FBitSet( tx->flags, TEX_NODIRT ))
|
|
return 1.0f; // disabled by user
|
|
|
|
LightMatrixFromTexMatrix( tx, lmvecs );
|
|
VectorCopy( lmvecs[1], binormal );
|
|
VectorCopy( lmvecs[0], tangent );
|
|
}
|
|
else
|
|
{
|
|
// compute tangent space from phong-shaded normal
|
|
VectorVectors( normal, tangent, binormal );
|
|
}
|
|
|
|
for( int i = 0; i < g_num_dirtvecs; i++ )
|
|
{
|
|
// transform vector into tangent space
|
|
direction[0] = tangent[0] * g_dirtvecs[i][0] + binormal[0] * g_dirtvecs[i][1] + normal[0] * g_dirtvecs[i][2];
|
|
direction[1] = tangent[1] * g_dirtvecs[i][0] + binormal[1] * g_dirtvecs[i][1] + normal[1] * g_dirtvecs[i][2];
|
|
direction[2] = tangent[2] * g_dirtvecs[i][0] + binormal[2] * g_dirtvecs[i][1] + normal[2] * g_dirtvecs[i][2];
|
|
|
|
VectorMA( pos, dirtDepth, direction, vecEnd );
|
|
TestLine( threadnum, vecSrc, vecEnd, &trace );
|
|
|
|
if( trace.contents == CONTENTS_SOLID )
|
|
gatherDirt += 1.0f - trace.fraction;
|
|
}
|
|
|
|
// direct ray
|
|
VectorMA( pos, dirtDepth, normal, vecEnd );
|
|
TestLine( threadnum, vecSrc, vecEnd, &trace );
|
|
|
|
if( trace.contents == CONTENTS_SOLID )
|
|
gatherDirt += 1.0f - trace.fraction;
|
|
|
|
// early out
|
|
if( gatherDirt <= 0.0f )
|
|
return 1.0f;
|
|
|
|
// apply gain (does this even do much? heh)
|
|
outDirt = pow( gatherDirt / ( g_num_dirtvecs + 1 ), dirtGain ) * dirtScale;
|
|
if( outDirt > 1.0f ) outDirt = 1.0f;
|
|
|
|
return 1.0f - outDirt;
|
|
} |