Paranoia2/utils/p2rad/dirtmap.cpp

121 lines
3.2 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;
}