diff --git a/client/client.plg b/client/client.plg
deleted file mode 100644
index 33666b63..00000000
--- a/client/client.plg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: client - Win32 Debug--------------------
-
-Command Lines
-
-
-
-Results
-client.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/engine/engine.plg b/engine/engine.plg
deleted file mode 100644
index 45d2c2f7..00000000
--- a/engine/engine.plg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: engine - Win32 Debug--------------------
-
-Command Lines
-
-
-
-Results
-engine.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/launch/launch.plg b/launch/launch.plg
deleted file mode 100644
index 67644887..00000000
--- a/launch/launch.plg
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: launch - Win32 Release--------------------
-
-Command Lines
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC7.tmp" with contents
-[
-/nologo /MD /W3 /GX /O2 /I "./" /I "imagelib" /I "../public" /I "../common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fo"..\temp\launch\!release/" /Fd"..\temp\launch\!release/" /FD /c
-"D:\Xash3D\src_main\launch\memlib.c"
-]
-Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC7.tmp"
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC8.tmp" with contents
-[
-zlib.lib png.lib user32.lib gdi32.lib advapi32.lib winmm.lib /nologo /dll /pdb:none /machine:I386 /nodefaultlib:"libc.lib" /out:"..\temp\launch\!release/launch.dll" /implib:"..\temp\launch\!release/launch.lib" /libpath:"./imagelib" /opt:nowin98
-"\Xash3D\src_main\temp\launch\!release\cmd.obj"
-"\Xash3D\src_main\temp\launch\!release\console.obj"
-"\Xash3D\src_main\temp\launch\!release\cpuinfo.obj"
-"\Xash3D\src_main\temp\launch\!release\crclib.obj"
-"\Xash3D\src_main\temp\launch\!release\cvar.obj"
-"\Xash3D\src_main\temp\launch\!release\export.obj"
-"\Xash3D\src_main\temp\launch\!release\filesystem.obj"
-"\Xash3D\src_main\temp\launch\!release\img_bmp.obj"
-"\Xash3D\src_main\temp\launch\!release\img_dds.obj"
-"\Xash3D\src_main\temp\launch\!release\img_jpg.obj"
-"\Xash3D\src_main\temp\launch\!release\img_main.obj"
-"\Xash3D\src_main\temp\launch\!release\img_pcx.obj"
-"\Xash3D\src_main\temp\launch\!release\img_png.obj"
-"\Xash3D\src_main\temp\launch\!release\img_tga.obj"
-"\Xash3D\src_main\temp\launch\!release\img_utils.obj"
-"\Xash3D\src_main\temp\launch\!release\img_vtf.obj"
-"\Xash3D\src_main\temp\launch\!release\img_wad.obj"
-"\Xash3D\src_main\temp\launch\!release\memlib.obj"
-"\Xash3D\src_main\temp\launch\!release\network.obj"
-"\Xash3D\src_main\temp\launch\!release\parselib.obj"
-"\Xash3D\src_main\temp\launch\!release\patch.obj"
-"\Xash3D\src_main\temp\launch\!release\stdlib.obj"
-"\Xash3D\src_main\temp\launch\!release\system.obj"
-"\Xash3D\src_main\temp\launch\!release\utils.obj"
-]
-Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC8.tmp"
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC9.bat" with contents
-[
-@echo off
-copy \Xash3D\src_main\temp\launch\!release\launch.dll "D:\Xash3D\bin\launch.dll"
-]
-Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC9.bat"
-Compiling...
-memlib.c
-Linking...
- Creating library ..\temp\launch\!release/launch.lib and object ..\temp\launch\!release/launch.exp
-Output Window
-Performing Custom Build Step on \Xash3D\src_main\temp\launch\!release\launch.dll
-Скопировано файлов: 1.
-
-
-
-Results
-launch.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/render/r_backend.c b/render/r_backend.c
index a1777124..c202a43d 100644
--- a/render/r_backend.c
+++ b/render/r_backend.c
@@ -33,6 +33,10 @@ static float r_triangletable[FTABLE_SIZE];
static float r_squaretable[FTABLE_SIZE];
static float r_sawtoothtable[FTABLE_SIZE];
static float r_inversesawtoothtable[FTABLE_SIZE];
+static float r_warpsintable[256] =
+{
+#include "warpsin.h"
+};
#define NOISE_SIZE 256
#define NOISE_VAL( a ) r_noiseperm[( a ) & ( NOISE_SIZE - 1 )]
@@ -59,10 +63,10 @@ vec2_t *coordsArray;
vec2_t *lightmapCoordsArray[LM_STYLES];
rgba_t colorArray[MAX_ARRAY_VERTS];
-ref_globals_t tr;
-ref_backacc_t r_backacc;
+ref_globals_t tr;
+ref_backacc_t r_backacc;
-bool r_triangleOutlines;
+bool r_triangleOutlines;
static vec4_t colorWhite = { 1.0f, 1.0f, 1.0f, 1.0f };
static vec4_t colorRed = { 1.0f, 0.0f, 0.0f, 1.0f };
@@ -109,25 +113,24 @@ R_BackendInit
*/
void R_BackendInit( void )
{
- int i;
- float t;
+ int i;
+ float t;
r_numAccumPasses = 0;
r_arraysLocked = false;
r_triangleOutlines = false;
+ tr.iRenderMode = kRenderNormal;
R_ClearArrays();
R_InitVertexBuffers();
-
R_BackendResetPassMask();
pglEnableClientState( GL_VERTEX_ARRAY );
if( !r_ignorehwgamma->integer )
- r_identityLighting = (int)( 255.0f / pow( 2, max( 0, floor( r_overbrightbits->value ) ) ) );
- else
- r_identityLighting = 255;
+ r_identityLighting = (int)( 255.0f / pow( 2, max( 0, floor( r_overbrightbits->value ))));
+ else r_identityLighting = 255;
// build lookup tables
for( i = 0; i < FTABLE_SIZE; i++ )
@@ -136,41 +139,34 @@ void R_BackendInit( void )
r_sintable[i] = sin( t * M_PI2 );
- if( t < 0.25 )
- r_triangletable[i] = t * 4.0;
- else if( t < 0.75 )
- r_triangletable[i] = 2 - 4.0 * t;
- else
- r_triangletable[i] = ( t - 0.75 ) * 4.0 - 1.0;
+ if( t < 0.25f ) r_triangletable[i] = t * 4.0f;
+ else if( t < 0.75f ) r_triangletable[i] = 2 - 4.0f * t;
+ else r_triangletable[i] = ( t - 0.75f ) * 4.0f - 1.0f;
- if( t < 0.5 )
- r_squaretable[i] = 1.0f;
- else
- r_squaretable[i] = -1.0f;
+ if( t < 0.5f ) r_squaretable[i] = 1.0f;
+ else r_squaretable[i] = -1.0f;
r_sawtoothtable[i] = t;
- r_inversesawtoothtable[i] = 1.0 - t;
+ r_inversesawtoothtable[i] = 1.0f - t;
}
for( i = 0; i < 256; i++ )
- r_sintableByte[i] = sin( (float)i / 255.0 * M_PI2 );
+ r_sintableByte[i] = sin((float)i / 255.0f * M_PI2 );
// init the noise table
- srand( 1001 );
-
for( i = 0; i < NOISE_SIZE; i++ )
{
- r_noisetable[i] = (float)( ( ( rand() / (float)RAND_MAX ) * 2.0 - 1.0 ) );
- r_noiseperm[i] = (unsigned char)( rand() / (float)RAND_MAX * 255 );
+ r_noisetable[i] = Com_RandomFloat( -1.0f, 1.0f );
+ r_noiseperm[i] = Com_RandomLong( 0, 255 );
}
// init dynamic lights pass
- memset( &r_dlightsPass, 0, sizeof( ref_stage_t ) );
+ Mem_Set( &r_dlightsPass, 0, sizeof( ref_stage_t ) );
r_dlightsPass.flags = SHADERSTAGE_DLIGHT;
r_dlightsPass.glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ONE;
// init fog pass
- memset( &r_fogPass, 0, sizeof( ref_stage_t ) );
+ Mem_Set( &r_fogPass, 0, sizeof( ref_stage_t ) );
r_fogPass.tcgen = TCGEN_FOG;
r_fogPass.rgbGen.type = RGBGEN_FOG;
r_fogPass.alphaGen.type = ALPHAGEN_IDENTITY;
@@ -192,7 +188,7 @@ void R_BackendInit( void )
}
// init optional GLSL program passes
- memset( r_GLSLpasses, 0, sizeof( r_GLSLpasses ) );
+ Mem_Set( r_GLSLpasses, 0, sizeof( r_GLSLpasses ) );
r_GLSLpasses[0].flags = SHADERSTAGE_DLIGHT|SHADERSTAGE_BLEND_ADD;
r_GLSLpasses[0].glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE;
@@ -248,11 +244,11 @@ R_LatLongToNorm
*/
void R_LatLongToNorm( const byte latlong[2], vec3_t out )
{
- float sin_a, sin_b, cos_a, cos_b;
+ float sin_a, sin_b, cos_a, cos_b;
- cos_a = r_sintableByte[( latlong[0] + 64 ) & 255];
+ cos_a = r_sintableByte[(latlong[0] + 64) & 255];
sin_a = r_sintableByte[latlong[0]];
- cos_b = r_sintableByte[( latlong[1] + 64 ) & 255];
+ cos_b = r_sintableByte[(latlong[1] + 64) & 255];
sin_b = r_sintableByte[latlong[1]];
VectorSet( out, cos_b * sin_a, sin_b * sin_a, cos_a );
@@ -263,7 +259,7 @@ void R_LatLongToNorm( const byte latlong[2], vec3_t out )
R_TableForFunc
==============
*/
-static float *R_TableForFunc( unsigned int func )
+static float *R_TableForFunc( uint func )
{
switch( func )
{
@@ -277,17 +273,26 @@ static float *R_TableForFunc( unsigned int func )
return r_sawtoothtable;
case WAVEFORM_INVERSESAWTOOTH:
return r_inversesawtoothtable;
-
case WAVEFORM_NOISE:
return r_sintable; // default to sintable
+ default:
+ return NULL;
}
-
- // assume error
- Host_Error( "R_TableForFunc: unknown function\n" );
-
- return NULL;
}
+static float R_TableEvaluate( waveFunc_t func, float index )
+{
+ float *table = R_TableForFunc( func.type );
+
+ if( table == NULL )
+ {
+ if( func.type == WAVEFORM_TABLE )
+ return R_LookupTable( func.tableIndex, index );
+ return 1.0f; // assume error
+ }
+ return FTABLE_EVALUATE( table, index );
+}
+
/*
==============
R_BackendGetNoiseValue
@@ -295,11 +300,11 @@ R_BackendGetNoiseValue
*/
float R_BackendGetNoiseValue( float x, float y, float z, float t )
{
- int i;
- int ix, iy, iz, it;
- float fx, fy, fz, ft;
- float front[4], back[4];
- float fvalue, bvalue, value[2], finalvalue;
+ int i;
+ int ix, iy, iz, it;
+ float fx, fy, fz, ft;
+ float front[4], back[4];
+ float fvalue, bvalue, value[2], finalvalue;
ix = ( int )floor( x );
fx = x - ix;
@@ -326,7 +331,6 @@ float R_BackendGetNoiseValue( float x, float y, float z, float t )
bvalue = NOISE_LERP( NOISE_LERP( back[0], back[1], fx ), NOISE_LERP( back[2], back[3], fx ), fy );
value[i] = NOISE_LERP( fvalue, bvalue, fz );
}
-
finalvalue = NOISE_LERP( value[0], value[1], ft );
return finalvalue;
@@ -339,7 +343,7 @@ R_BackendResetCounters
*/
void R_BackendResetCounters( void )
{
- memset( &r_backacc, 0, sizeof( r_backacc ) );
+ Mem_Set( &r_backacc, 0, sizeof( r_backacc ));
}
/*
@@ -546,7 +550,7 @@ R_CleanUpTextureUnits
*/
static void R_CleanUpTextureUnits( int last )
{
- int i;
+ int i;
for( i = glState.activeTMU; i > last - 1; i-- )
{
@@ -568,7 +572,6 @@ void R_DeformVertices( void )
uint i, j, k;
double args[4], temp;
float deflect, *quad[4];
- const float *table;
const deform_t *deformv;
vec3_t tv, rot_centre;
@@ -579,15 +582,12 @@ void R_DeformVertices( void )
{
case DEFORM_NONE:
break;
-
case DEFORM_WAVE:
- table = R_TableForFunc( deformv->func.type );
-
// Deflect vertex along its normal by wave amount
if( deformv->func.args[3] == 0 )
{
temp = deformv->func.args[2];
- deflect = FTABLE_EVALUATE( table, temp ) * deformv->func.args[1] + deformv->func.args[0];
+ deflect = R_TableEvaluate( deformv->func, temp ) * deformv->func.args[1] + deformv->func.args[0];
for( j = 0; j < r_backacc.numVerts; j++ )
VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
@@ -602,12 +602,11 @@ void R_DeformVertices( void )
for( j = 0; j < r_backacc.numVerts; j++ )
{
temp = args[2] + args[3] * ( inVertsArray[j][0] + inVertsArray[j][1] + inVertsArray[j][2] );
- deflect = FTABLE_EVALUATE( table, temp ) * args[1] + args[0];
+ deflect = R_TableEvaluate( deformv->func, temp ) * args[1] + args[0];
VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
}
}
break;
-
case DEFORM_NORMAL:
// without this * 0.1f deformation looks wrong, although q3a doesn't have it
args[0] = deformv->func.args[3] * r_currentShaderTime * 0.1f;
@@ -622,16 +621,13 @@ void R_DeformVertices( void )
VectorNormalizeFast( inNormalsArray[j] );
}
break;
-
case DEFORM_MOVE:
- table = R_TableForFunc( deformv->func.type );
temp = deformv->func.args[2] + r_currentShaderTime * deformv->func.args[3];
- deflect = FTABLE_EVALUATE( table, temp ) * deformv->func.args[1] + deformv->func.args[0];
+ deflect = R_TableEvaluate( deformv->func, temp ) * deformv->func.args[1] + deformv->func.args[0];
for( j = 0; j < r_backacc.numVerts; j++ )
VectorMA( inVertsArray[j], deflect, deformv->args, inVertsArray[j] );
break;
-
case DEFORM_BULGE:
args[0] = deformv->args[0];
args[1] = deformv->args[1];
@@ -644,7 +640,6 @@ void R_DeformVertices( void )
VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
}
break;
-
case DEFORM_AUTOSPRITE:
{
vec4_t *v;
@@ -709,7 +704,6 @@ void R_DeformVertices( void )
}
}
break;
-
case DEFORM_AUTOSPRITE2:
if( r_backacc.numElems % 6 )
break;
@@ -842,11 +836,9 @@ void R_DeformVertices( void )
}
}
break;
-
case DEFORM_PROJECTION_SHADOW:
R_DeformVPlanarShadow( r_backacc.numVerts, inVertsArray[0] );
break;
-
case DEFORM_AUTOPARTICLE:
{
float scale;
@@ -972,7 +964,6 @@ static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix )
pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer );
return true;
}
-
case TCGEN_VECTOR:
{
GLfloat genVector[2][4];
@@ -1032,7 +1023,6 @@ static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix )
pglTexGenfv( GL_Q, GL_OBJECT_PLANE, genVector[3] );
return false;
}
-
case TCGEN_REFLECTION_CELLSHADE:
if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) )
{
@@ -1056,7 +1046,6 @@ static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix )
GL_EnableTexGen( GL_R, GL_REFLECTION_MAP_ARB );
GL_EnableTexGen( GL_Q, 0 );
return true;
-
case TCGEN_FOG:
{
int fogPtype;
@@ -1135,7 +1124,6 @@ static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix )
pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer );
return false;
}
-
case TCGEN_SVECTORS:
GL_DisableAllTexGens();
R_UpdateVertexBuffer( tr.tcoordBuffer[unit], sVectorsArray, r_backacc.numVerts * sizeof( vec4_t ));
@@ -1159,10 +1147,10 @@ R_ApplyTCMods
static void R_ApplyTCMods( const ref_stage_t *pass, mat4x4_t result )
{
int i;
- const float *table;
double t1, t2, sint, cost;
mat4x4_t m1, m2;
const tcMod_t *tcmod;
+ waveFunc_t func;
for( i = 0, tcmod = pass->tcMods; i < pass->numtcMods; i++, tcmod++ )
{
@@ -1181,14 +1169,15 @@ static void R_ApplyTCMods( const ref_stage_t *pass, mat4x4_t result )
Matrix4_Scale2D( result, tcmod->args[0], tcmod->args[1] );
break;
case TCMOD_TURB:
- t1 = ( 1.0 / 4.0 );
+ t1 = ( 1.0f / 4.0f );
t2 = tcmod->args[2] + r_currentShaderTime * tcmod->args[3];
Matrix4_Scale2D( result, 1 + ( tcmod->args[1] * R_FastSin( t2 ) + tcmod->args[0] ) * t1, 1 + ( tcmod->args[1] * R_FastSin( t2 + 0.25 ) + tcmod->args[0] ) * t1 );
break;
case TCMOD_STRETCH:
- table = R_TableForFunc( tcmod->args[0] );
+ func.type = (uint)tcmod->args[0];
+ func.tableIndex = (uint)tcmod->args[5];
t2 = tcmod->args[3] + r_currentShaderTime * tcmod->args[4];
- t1 = FTABLE_EVALUATE( table, t2 ) * tcmod->args[2] + tcmod->args[1];
+ t1 = R_TableEvaluate( func, t2 ) * tcmod->args[2] + tcmod->args[1];
t1 = t1 ? 1.0f / t1 : 1.0f;
t2 = 0.5f - 0.5f * t1;
Matrix4_Stretch2D( result, t1, t2 );
@@ -1197,7 +1186,8 @@ static void R_ApplyTCMods( const ref_stage_t *pass, mat4x4_t result )
t1 = tcmod->args[0] * r_currentShaderTime;
t2 = tcmod->args[1] * r_currentShaderTime;
if( pass->program_type != PROGRAM_TYPE_DISTORTION )
- { // HACK HACK HACK
+ {
+ // HACKHACK
t1 = t1 - floor( t1 );
t2 = t2 - floor( t2 );
}
@@ -1231,6 +1221,196 @@ static _inline texture_t *R_ShaderpassTex( const ref_stage_t *pass, int unit )
return ( pass->textures[0] ? pass->textures[0] : tr.defaultTexture );
}
+/*
+=================
+RB_SetShaderRenderMode
+
+UNDONE: not all cases are filled
+=================
+*/
+static void R_ShaderpassRenderMode( ref_stage_t *pass )
+{
+ int mod_type = mod_bad; // mod_bad interpretate as orthogonal shader
+
+ if(!(pass->flags & SHADERSTAGE_RENDERMODE))
+ return;
+
+ if( RI.currentmodel && !glState.in2DMode )
+ mod_type = RI.currentmodel->type;
+
+ switch( tr.iRenderMode )
+ {
+ case kRenderNormal:
+ switch( mod_type )
+ {
+ case mod_bad:
+ pass->rgbGen.type = RGBGEN_IDENTITY;
+ pass->alphaGen.type = ALPHAGEN_IDENTITY;
+ break;
+ case mod_world:
+ case mod_brush:
+ // bsp surfaces uses lightmaps and ignore color values as well
+ pass->glState &= ~(GLSTATE_BLENDFUNC|GLSTATE_ALPHAFUNC);
+ pass->glState |= GLSTATE_DEPTHWRITE;
+ pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING;
+ pass->alphaGen.type = ALPHAGEN_IDENTITY;
+ break;
+ case mod_studio:
+ // UNDONE: wrote R_StudioLighting, change rgbGen to RGBGEN_VERTEX
+ // UNDONE: setup custom alpha channel for NF_ADDITIVE, change alphaGen to ALPHAGEN_VERTEX
+ pass->glState &= ~(GLSTATE_BLENDFUNC|GLSTATE_ALPHAFUNC);
+ pass->rgbGen.type = RGBGEN_LIGHTING_AMBIENT_ONLY;
+ pass->alphaGen.type = ALPHAGEN_IDENTITY;
+ break;
+ case mod_sprite:
+ pass->glState &= ~(GLSTATE_BLENDFUNC|GLSTATE_ALPHAFUNC);
+ pass->rgbGen.type = RGBGEN_LIGHTING_AMBIENT_ONLY;
+ pass->alphaGen.type = ALPHAGEN_IDENTITY;
+ break;
+ }
+ break;
+ case kRenderTransColor:
+ switch( mod_type )
+ {
+ case mod_bad:
+ pass->glState &= ~GLSTATE_ALPHAFUNC;
+ pass->glState |= (GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR);
+ pass->rgbGen.type = RGBGEN_VERTEX;
+ pass->alphaGen.type = ALPHAGEN_VERTEX;
+ break;
+ case mod_world:
+ pass->glState &= ~(GLSTATE_BLENDFUNC|GLSTATE_ALPHAFUNC);
+ pass->glState |= GLSTATE_DEPTHWRITE;
+ pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING;
+ pass->alphaGen.type = ALPHAGEN_IDENTITY;
+ break;
+ case mod_brush:
+ case mod_studio:
+ case mod_sprite:
+ break;
+ }
+ break;
+ case kRenderTransTexture:
+ switch( mod_type )
+ {
+ case mod_bad:
+ pass->glState &= ~GLSTATE_ALPHAFUNC;
+ pass->glState |= (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA);
+ pass->rgbGen.type = RGBGEN_VERTEX;
+ pass->alphaGen.type = ALPHAGEN_VERTEX;
+ break;
+ case mod_world:
+ pass->glState &= ~(GLSTATE_BLENDFUNC|GLSTATE_ALPHAFUNC);
+ pass->glState |= GLSTATE_DEPTHWRITE;
+ pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING;
+ pass->alphaGen.type = ALPHAGEN_IDENTITY;
+ break;
+ case mod_brush:
+ pass->glState &= ~(GLSTATE_DEPTHWRITE|GLSTATE_ALPHAFUNC);
+ pass->glState |= (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA);
+ pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING;
+ pass->alphaGen.type = ALPHAGEN_ENTITY;
+ break;
+ case mod_studio:
+ case mod_sprite:
+ break;
+ }
+ break;
+ case kRenderGlow:
+ switch( mod_type )
+ {
+ case mod_bad:
+ pass->glState &= ~GLSTATE_ALPHAFUNC;
+ pass->glState |= (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE);
+ pass->rgbGen.type = RGBGEN_VERTEX;
+ pass->alphaGen.type = ALPHAGEN_VERTEX;
+ break;
+ case mod_world:
+ case mod_brush:
+ // completely ignore glow mode for world surfaces
+ pass->glState &= ~(GLSTATE_BLENDFUNC|GLSTATE_ALPHAFUNC);
+ pass->glState |= GLSTATE_DEPTHWRITE;
+ pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING;
+ pass->alphaGen.type = ALPHAGEN_IDENTITY;
+ break;
+ case mod_studio:
+ case mod_sprite:
+ pass->glState &= ~(GLSTATE_ALPHAFUNC|GLSTATE_DEPTHWRITE|GLSTATE_DEPTHFUNC_EQ);
+ pass->glState |= (GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DSTBLEND_ONE);
+ pass->rgbGen.type = RGBGEN_IDENTITY; // hl1 glow sprites ignores color
+ pass->alphaGen.type = ALPHAGEN_ENTITY;
+ break;
+ }
+ break;
+ case kRenderTransAlpha:
+ switch( mod_type )
+ {
+ case mod_bad:
+ pass->glState &= ~GLSTATE_BLENDFUNC;
+ pass->glState |= GLSTATE_AFUNC_GE128;
+ pass->rgbGen.type = RGBGEN_VERTEX;
+ pass->alphaGen.type = ALPHAGEN_VERTEX;
+ break;
+ case mod_world:
+ // always ignore transparent surfaces for world
+ pass->glState &= ~(GLSTATE_BLENDFUNC|GLSTATE_ALPHAFUNC);
+ pass->glState |= GLSTATE_DEPTHWRITE;
+ pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING;
+ pass->alphaGen.type = ALPHAGEN_IDENTITY;
+ break;
+ case mod_brush:
+ pass->glState &= ~GLSTATE_BLENDFUNC;
+ pass->glState |= GLSTATE_AFUNC_GE128;
+ pass->rgbGen.type = RGBGEN_IDENTITY;
+ pass->alphaGen.type = ALPHAGEN_IDENTITY;
+ case mod_studio:
+ // UNDONE: wrote R_StudioLighting, change rgbGen to RGBGEN_VERTEX
+ // UNDONE: setup custom alpha channel for NF_ADDITIVE, change alphaGen to ALPHAGEN_VERTEX
+ pass->glState &= ~GLSTATE_BLENDFUNC;
+ pass->glState |= GLSTATE_AFUNC_GE128;
+ pass->rgbGen.type = RGBGEN_LIGHTING_AMBIENT_ONLY;
+ pass->alphaGen.type = ALPHAGEN_ENTITY;
+ case mod_sprite:
+ pass->glState &= ~GLSTATE_BLENDFUNC;
+ pass->glState |= GLSTATE_AFUNC_GE128;
+ pass->rgbGen.type = RGBGEN_LIGHTING_AMBIENT_ONLY;
+ pass->alphaGen.type = ALPHAGEN_ENTITY;
+ break;
+ }
+ break;
+ case kRenderTransAdd:
+ switch( mod_type )
+ {
+ case mod_bad:
+ pass->glState &= ~GLSTATE_ALPHAFUNC;
+ pass->glState |= (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE);
+ pass->rgbGen.type = RGBGEN_VERTEX;
+ pass->alphaGen.type = ALPHAGEN_VERTEX;
+ break;
+ case mod_world:
+ pass->glState &= ~(GLSTATE_BLENDFUNC|GLSTATE_ALPHAFUNC);
+ pass->glState |= GLSTATE_DEPTHWRITE;
+ pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING;
+ pass->alphaGen.type = ALPHAGEN_IDENTITY;
+ break;
+ case mod_brush:
+ pass->glState &= ~(GLSTATE_ALPHAFUNC|GLSTATE_DEPTHWRITE);
+ pass->glState |= (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE);
+ pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING;
+ pass->alphaGen.type = ALPHAGEN_ENTITY;
+ break;
+ case mod_studio:
+ case mod_sprite:
+ pass->glState &= ~(GLSTATE_ALPHAFUNC|GLSTATE_DEPTHWRITE);
+ pass->glState |= (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE);
+ pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING;
+ pass->alphaGen.type = ALPHAGEN_ENTITY;
+ break;
+ }
+ break;
+ }
+}
+
/*
================
R_BindShaderpass
@@ -1238,15 +1418,14 @@ R_BindShaderpass
*/
static void R_BindShaderpass( const ref_stage_t *pass, texture_t *tex, int unit )
{
- mat4x4_t m1, m2, result;
- bool identityMatrix;
+ mat4x4_t m1, m2, result;
+ bool identityMatrix;
- if( !tex )
- tex = R_ShaderpassTex( pass, unit );
+ if( !tex ) tex = R_ShaderpassTex( pass, unit );
GL_Bind( unit, tex );
if( unit && !pass->program ) pglEnable( GL_TEXTURE_2D );
- GL_SetTexCoordArrayMode( ( tex->flags & TF_CUBEMAP ? GL_TEXTURE_CUBE_MAP_ARB : GL_TEXTURE_COORD_ARRAY ));
+ GL_SetTexCoordArrayMode(( tex->flags & TF_CUBEMAP ? GL_TEXTURE_CUBE_MAP_ARB : GL_TEXTURE_COORD_ARRAY ));
identityMatrix = R_VertexTCBase( pass, unit, result );
@@ -1267,8 +1446,7 @@ static void R_BindShaderpass( const ref_stage_t *pass, texture_t *tex, int unit
if( identityMatrix )
GL_LoadIdentityTexMatrix();
- else
- GL_LoadTexMatrix( result );
+ else GL_LoadTexMatrix( result );
}
/*
@@ -1279,9 +1457,9 @@ R_ModifyColor
void R_ModifyColor( const ref_stage_t *pass )
{
uint i;
+ float a;
int c, bits;
double temp;
- float *table, a;
vec3_t t, v, style;
byte *bArray, *inArray, rgba[4] = { 255, 255, 255, 255 };
bool noArray, identityAlpha, entityAlpha;
@@ -1297,18 +1475,18 @@ void R_ModifyColor( const ref_stage_t *pass )
if( pass->rgbGen.type == RGBGEN_IDENTITY_LIGHTING )
{
entityAlpha = identityAlpha = false;
- memset( bArray, r_identityLighting, sizeof( rgba_t ) * r_backacc.numColors );
+ Mem_Set( bArray, r_identityLighting, sizeof( rgba_t ) * r_backacc.numColors );
}
else if( pass->rgbGen.type == RGBGEN_EXACT_VERTEX )
{
entityAlpha = identityAlpha = false;
- memcpy( bArray, inArray, sizeof( rgba_t ) * r_backacc.numColors );
+ Mem_Copy( bArray, inArray, sizeof( rgba_t ) * r_backacc.numColors );
}
else
{
entityAlpha = false;
identityAlpha = true;
- memset( bArray, 255, sizeof( rgba_t ) * r_backacc.numColors );
+ Mem_Set( bArray, 255, sizeof( rgba_t ) * r_backacc.numColors );
switch( pass->rgbGen.type )
{
@@ -1330,9 +1508,8 @@ void R_ModifyColor( const ref_stage_t *pass )
}
else
{
- table = R_TableForFunc( rgbgenfunc->type );
temp = r_currentShaderTime * rgbgenfunc->args[3] + rgbgenfunc->args[2];
- temp = FTABLE_EVALUATE( table, temp ) * rgbgenfunc->args[1] + rgbgenfunc->args[0];
+ temp = R_TableEvaluate( *rgbgenfunc, temp ) * rgbgenfunc->args[1] + rgbgenfunc->args[0];
}
temp = temp * rgbgenfunc->args[1] + rgbgenfunc->args[0];
@@ -1389,7 +1566,7 @@ void R_ModifyColor( const ref_stage_t *pass )
float *tc;
vec3_t temp[MAX_ARRAY_VERTS];
- memset( temp, 0, sizeof( vec3_t ) * r_backacc.numColors );
+ Mem_Set( temp, 0, sizeof( vec3_t ) * r_backacc.numColors );
for( j = 0; j < LM_STYLES && r_superLightStyle->vertexStyles[j] != 255; j++ )
{
@@ -1504,9 +1681,8 @@ void R_ModifyColor( const ref_stage_t *pass )
}
else
{
- table = R_TableForFunc( alphagenfunc->type );
a = alphagenfunc->args[2] + r_currentShaderTime * alphagenfunc->args[3];
- a = FTABLE_EVALUATE( table, a );
+ a = R_TableEvaluate( *alphagenfunc, a );
}
a = a * alphagenfunc->args[1] + alphagenfunc->args[0];
@@ -1734,6 +1910,7 @@ void R_RenderMeshGeneric( void )
{
const ref_stage_t *pass = r_accumPasses[0];
+ R_ShaderpassRenderMode( (ref_stage_t *)pass );
R_BindShaderpass( pass, NULL, 0 );
R_ModifyColor( pass );
diff --git a/render/r_backend.h b/render/r_backend.h
index ec5bc3ba..3431ddb7 100644
--- a/render/r_backend.h
+++ b/render/r_backend.h
@@ -80,6 +80,7 @@ typedef struct
{
// renderer global variables
int registration_sequence;
+ kRenderMode_t iRenderMode;
// vbo stuff
int numVertexBufferObjects;
diff --git a/render/r_backend.old b/render/r_backend.old
deleted file mode 100644
index 3814a09a..00000000
--- a/render/r_backend.old
+++ /dev/null
@@ -1,2845 +0,0 @@
-/*
-Copyright (C) 2002-2007 Victor Luchits
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "r_local.h"
-#include "mathlib.h"
-#include "quatlib.h"
-
-#define FTABLE_SIZE_POW 10
-#define FTABLE_SIZE ( 1<integer )
- r_identityLighting = (int)( 255.0f / pow( 2, max( 0, floor( r_overbrightbits->value ) ) ) );
- else
- r_identityLighting = 255;
-
- // build lookup tables
- for( i = 0; i < FTABLE_SIZE; i++ )
- {
- t = (float)i / (float)FTABLE_SIZE;
-
- r_sintable[i] = sin( t * M_PI2 );
-
- if( t < 0.25 )
- r_triangletable[i] = t * 4.0;
- else if( t < 0.75 )
- r_triangletable[i] = 2 - 4.0 * t;
- else
- r_triangletable[i] = ( t - 0.75 ) * 4.0 - 1.0;
-
- if( t < 0.5 )
- r_squaretable[i] = 1.0f;
- else
- r_squaretable[i] = -1.0f;
-
- r_sawtoothtable[i] = t;
- r_inversesawtoothtable[i] = 1.0 - t;
- }
-
- for( i = 0; i < 256; i++ )
- r_sintableByte[i] = sin( (float)i / 255.0 * M_PI2 );
-
- // init the noise table
- srand( 1001 );
-
- for( i = 0; i < NOISE_SIZE; i++ )
- {
- r_noisetable[i] = (float)( ( ( rand() / (float)RAND_MAX ) * 2.0 - 1.0 ) );
- r_noiseperm[i] = (unsigned char)( rand() / (float)RAND_MAX * 255 );
- }
-
- // init dynamic lights pass
- memset( &r_dlightsPass, 0, sizeof( ref_stage_t ) );
- r_dlightsPass.flags = SHADERSTAGE_DLIGHT;
- r_dlightsPass.glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ONE;
-
- // init fog pass
- memset( &r_fogPass, 0, sizeof( ref_stage_t ) );
- r_fogPass.tcgen = TCGEN_FOG;
- r_fogPass.rgbGen.type = RGBGEN_FOG;
- r_fogPass.alphaGen.type = ALPHAGEN_IDENTITY;
- r_fogPass.flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_DECAL;
- r_fogPass.glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA;
-
- // the very first lightmap pass is reserved for GL_REPLACE or GL_MODULATE
- Mem_Set( r_lightmapPasses, 0, sizeof( r_lightmapPasses ));
- r_lightmapPasses[0].rgbGen.args = r_lightmapPassesArgs[0];
-
- // the rest are GL_ADD
- for( i = 1; i < MAX_TEXTURE_UNITS+1; i++ )
- {
- r_lightmapPasses[i].flags = SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_ADD;
- r_lightmapPasses[i].glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE;
- r_lightmapPasses[i].tcgen = TCGEN_LIGHTMAP;
- r_lightmapPasses[i].alphaGen.type = ALPHAGEN_IDENTITY;
- r_lightmapPasses[i].rgbGen.args = r_lightmapPassesArgs[i];
- }
-
- // init optional GLSL program passes
- memset( r_GLSLpasses, 0, sizeof( r_GLSLpasses ) );
- r_GLSLpasses[0].flags = SHADERSTAGE_DLIGHT|SHADERSTAGE_BLEND_ADD;
- r_GLSLpasses[0].glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE;
-
- r_GLSLpasses[1].flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE;
- r_GLSLpasses[1].glState = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR;
- r_GLSLpasses[1].tcgen = TCGEN_BASE;
- r_GLSLpasses[1].rgbGen.type = RGBGEN_IDENTITY;
- r_GLSLpasses[1].alphaGen.type = ALPHAGEN_IDENTITY;
- Mem_Copy( &r_GLSLpasses[2], &r_GLSLpasses[1], sizeof( ref_stage_t ) );
-
- r_GLSLpasses[3].flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE;
- r_GLSLpasses[3].glState = GLSTATE_DEPTHFUNC_EQ /*|GLSTATE_OFFSET_FILL*/|GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR;
- r_GLSLpasses[3].tcgen = TCGEN_PROJECTION_SHADOW;
- r_GLSLpasses[3].rgbGen.type = RGBGEN_IDENTITY;
- r_GLSLpasses[3].alphaGen.type = ALPHAGEN_IDENTITY;
- r_GLSLpasses[3].program = DEFAULT_GLSL_SHADOWMAP_PROGRAM;
- r_GLSLpasses[3].program_type = PROGRAM_TYPE_SHADOWMAP;
-
- Mem_Set( &r_GLSLpassOutline, 0, sizeof( r_GLSLpassOutline ) );
- r_GLSLpassOutline.flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE;
- r_GLSLpassOutline.glState = GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ZERO|GLSTATE_DEPTHWRITE;
- r_GLSLpassOutline.rgbGen.type = RGBGEN_OUTLINE;
- r_GLSLpassOutline.alphaGen.type = ALPHAGEN_OUTLINE;
- r_GLSLpassOutline.tcgen = TCGEN_NONE;
- r_GLSLpassOutline.program = DEFAULT_GLSL_OUTLINE_PROGRAM;
- r_GLSLpassOutline.program_type = PROGRAM_TYPE_OUTLINE;
-}
-
-/*
-==============
-R_BackendShutdown
-==============
-*/
-void R_BackendShutdown( void )
-{
- R_ShutdownVertexBuffers ();
-}
-
-/*
-==============
-R_FastSin
-==============
-*/
-float R_FastSin( float t )
-{
- return FTABLE_EVALUATE( r_sintable, t );
-}
-
-/*
-=============
-R_LatLongToNorm
-=============
-*/
-void R_LatLongToNorm( const byte latlong[2], vec3_t out )
-{
- float sin_a, sin_b, cos_a, cos_b;
-
- cos_a = r_sintableByte[( latlong[0] + 64 ) & 255];
- sin_a = r_sintableByte[latlong[0]];
- cos_b = r_sintableByte[( latlong[1] + 64 ) & 255];
- sin_b = r_sintableByte[latlong[1]];
-
- VectorSet( out, cos_b * sin_a, sin_b * sin_a, cos_a );
-}
-
-/*
-==============
-R_TableForFunc
-==============
-*/
-static float *R_TableForFunc( unsigned int func )
-{
- switch( func )
- {
- case WAVEFORM_SIN:
- return r_sintable;
- case WAVEFORM_TRIANGLE:
- return r_triangletable;
- case WAVEFORM_SQUARE:
- return r_squaretable;
- case WAVEFORM_SAWTOOTH:
- return r_sawtoothtable;
- case WAVEFORM_INVERSESAWTOOTH:
- return r_inversesawtoothtable;
-
- case WAVEFORM_NOISE:
- return r_sintable; // default to sintable
- }
-
- // assume error
- Host_Error( "R_TableForFunc: unknown function\n" );
-
- return NULL;
-}
-
-/*
-==============
-R_BackendGetNoiseValue
-==============
-*/
-float R_BackendGetNoiseValue( float x, float y, float z, float t )
-{
- int i;
- int ix, iy, iz, it;
- float fx, fy, fz, ft;
- float front[4], back[4];
- float fvalue, bvalue, value[2], finalvalue;
-
- ix = ( int )floor( x );
- fx = x - ix;
- iy = ( int )floor( y );
- fy = y - iy;
- iz = ( int )floor( z );
- fz = z - iz;
- it = ( int )floor( t );
- ft = t - it;
-
- for( i = 0; i < 2; i++ )
- {
- front[0] = r_noisetable[NOISE_INDEX( ix, iy, iz, it + i )];
- front[1] = r_noisetable[NOISE_INDEX( ix+1, iy, iz, it + i )];
- front[2] = r_noisetable[NOISE_INDEX( ix, iy+1, iz, it + i )];
- front[3] = r_noisetable[NOISE_INDEX( ix+1, iy+1, iz, it + i )];
-
- back[0] = r_noisetable[NOISE_INDEX( ix, iy, iz + 1, it + i )];
- back[1] = r_noisetable[NOISE_INDEX( ix+1, iy, iz + 1, it + i )];
- back[2] = r_noisetable[NOISE_INDEX( ix, iy+1, iz + 1, it + i )];
- back[3] = r_noisetable[NOISE_INDEX( ix+1, iy+1, iz + 1, it + i )];
-
- fvalue = NOISE_LERP( NOISE_LERP( front[0], front[1], fx ), NOISE_LERP( front[2], front[3], fx ), fy );
- bvalue = NOISE_LERP( NOISE_LERP( back[0], back[1], fx ), NOISE_LERP( back[2], back[3], fx ), fy );
- value[i] = NOISE_LERP( fvalue, bvalue, fz );
- }
-
- finalvalue = NOISE_LERP( value[0], value[1], ft );
-
- return finalvalue;
-}
-
-/*
-==============
-R_BackendResetCounters
-==============
-*/
-void R_BackendResetCounters( void )
-{
- memset( &r_backacc, 0, sizeof( r_backacc ) );
-}
-
-/*
-==============
-R_BackendStartFrame
-==============
-*/
-void R_BackendStartFrame( void )
-{
- r_speeds_msg[0] = '\0';
- R_BackendResetCounters();
-}
-
-/*
-==============
-R_BackendEndFrame
-==============
-*/
-void R_BackendEndFrame( void )
-{
- // unlock arrays if any
- R_UnlockArrays();
-
- // clean up texture units
- R_CleanUpTextureUnits( 1 );
-
- if( r_speeds->integer && !( RI.refdef.rdflags & RDF_NOWORLDMODEL ) )
- {
- switch( r_speeds->integer )
- {
- case 1:
- default:
- com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ),
- "%4i wpoly %4i leafs %4i verts %4i tris %4i flushes %3i locks",
- c_brush_polys,
- c_world_leafs,
- r_backacc.c_totalVerts,
- r_backacc.c_totalTris,
- r_backacc.c_totalFlushes,
- r_backacc.c_totalKeptLocks
- );
- break;
- case 2:
- com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ),
- "lvs: %5i node: %5i farclip: %6.f",
- r_mark_leaves,
- r_world_node,
- RI.farClip
- );
- break;
- case 3:
- com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ),
- "polys\\ents: %5i\\%5i sort\\draw: %5i\\%i",
- r_add_polys, r_add_entities,
- r_sort_meshes, r_draw_meshes
- );
- break;
- case 4:
- if( r_debug_surface )
- {
- com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ),
- "%s", r_debug_surface->shader->name );
-
- if( r_debug_surface->fog && r_debug_surface->fog->shader
- && r_debug_surface->fog->shader != r_debug_surface->shader )
- {
- com.strncat( r_speeds_msg, "\n", sizeof( r_speeds_msg ) );
- com.strncat( r_speeds_msg, r_debug_surface->fog->shader->name, sizeof( r_speeds_msg ) );
- }
- }
- break;
- case 5:
- com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ),
- "%.1f %.1f %.1f (%.1f,%.1f,%.1f)",
- RI.refdef.vieworg[0], RI.refdef.vieworg[1], RI.refdef.vieworg[2],
- RI.refdef.viewangles[0], RI.refdef.viewangles[1], RI.refdef.viewangles[2]
- );
- break;
- }
- }
-}
-
-/*
-==============
-R_LockArrays
-==============
-*/
-void R_LockArrays( int numverts )
-{
- if( r_arraysLocked ) return;
-
- R_UpdateVertexBuffer( tr.vertexBuffer, vertsArray, numverts * sizeof( vec4_t ));
- pglVertexPointer( 3, GL_FLOAT, 16, tr.vertexBuffer->pointer );
-
- if( r_features & MF_ENABLENORMALS )
- {
- r_normalsEnabled = true;
- R_UpdateVertexBuffer( tr.normalBuffer, normalsArray, numverts * sizeof( vec4_t ));
- pglEnableClientState( GL_NORMAL_ARRAY );
- pglNormalPointer( GL_FLOAT, 16, tr.normalBuffer->pointer );
- }
-
- if( GL_Support( R_CUSTOM_VERTEX_ARRAY_EXT ))
- pglLockArraysEXT( 0, numverts );
-
- r_arraysLocked = true;
-}
-
-/*
-==============
-R_UnlockArrays
-==============
-*/
-void R_UnlockArrays( void )
-{
- if( !r_arraysLocked )
- return;
-
- if(GL_Support( R_CUSTOM_VERTEX_ARRAY_EXT ))
- pglUnlockArraysEXT();
-
- if( r_normalsEnabled )
- {
- r_normalsEnabled = false;
- pglDisableClientState( GL_NORMAL_ARRAY );
- }
- r_arraysLocked = false;
-}
-
-/*
-==============
-R_ClearArrays
-==============
-*/
-void R_ClearArrays( void )
-{
- int i;
-
- r_backacc.numVerts = 0;
- r_backacc.numElems = 0;
- r_backacc.numColors = 0;
-
- vertsArray = inVertsArray;
- elemsArray = inElemsArray;
- normalsArray = inNormalsArray;
- sVectorsArray = inSVectorsArray;
- coordsArray = inCoordsArray;
- for( i = 0; i < LM_STYLES; i++ )
- lightmapCoordsArray[i] = inLightmapCoordsArray[i];
-}
-
-/*
-==============
-R_FlushArrays
-==============
-*/
-void R_FlushArrays( void )
-{
- if( !r_backacc.numVerts || !r_backacc.numElems )
- return;
-
- if( r_backacc.numColors == 1 )
- {
- pglColor4ubv( colorArray[0] );
- }
- else if( r_backacc.numColors > 1 )
- {
- pglEnableClientState( GL_COLOR_ARRAY );
- R_UpdateVertexBuffer( tr.colorsBuffer, colorArray, r_backacc.numVerts * sizeof( rgba_t ));
- pglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tr.colorsBuffer->pointer );
- }
-
- if( r_drawelements->integer || glState.in2DMode || RI.refdef.rdflags & RDF_NOWORLDMODEL )
- {
- if( GL_Support( R_DRAW_RANGEELEMENTS_EXT ))
- pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
- else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
- }
-
- if( r_backacc.numColors > 1 )
- pglDisableClientState( GL_COLOR_ARRAY );
-
- r_backacc.c_totalTris += r_backacc.numElems / 3;
- r_backacc.c_totalFlushes++;
-}
-
-/*
-==============
-GL_DisableAllTexGens
-==============
-*/
-static _inline void GL_DisableAllTexGens( void )
-{
- GL_EnableTexGen( GL_S, 0 );
- GL_EnableTexGen( GL_T, 0 );
- GL_EnableTexGen( GL_R, 0 );
- GL_EnableTexGen( GL_Q, 0 );
-}
-
-/*
-==============
-R_CleanUpTextureUnits
-==============
-*/
-static void R_CleanUpTextureUnits( int last )
-{
- int i;
-
- for( i = glState.activeTMU; i > last - 1; i-- )
- {
- GL_DisableAllTexGens();
- GL_SetTexCoordArrayMode( 0 );
-
- pglDisable( GL_TEXTURE_2D );
- GL_SelectTexture( i - 1 );
- }
-}
-
-/*
-================
-R_DeformVertices
-================
-*/
-void R_DeformVertices( void )
-{
- uint i, j, k;
- double args[4], temp;
- float deflect, *quad[4];
- const float *table;
- const deform_t *deformv;
- vec3_t tv, rot_centre;
-
- deformv = &r_currentShader->deforms[0];
- for( i = 0; i < r_currentShader->numDeforms; i++, deformv++ )
- {
- switch( deformv->type )
- {
- case DEFORM_NONE:
- break;
-
- case DEFORM_WAVE:
- table = R_TableForFunc( deformv->func.type );
-
- // Deflect vertex along its normal by wave amount
- if( deformv->func.args[3] == 0 )
- {
- temp = deformv->func.args[2];
- deflect = FTABLE_EVALUATE( table, temp ) * deformv->func.args[1] + deformv->func.args[0];
-
- for( j = 0; j < r_backacc.numVerts; j++ )
- VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
- }
- else
- {
- args[0] = deformv->func.args[0];
- args[1] = deformv->func.args[1];
- args[2] = deformv->func.args[2] + deformv->func.args[3] * r_currentShaderTime;
- args[3] = deformv->args[0];
-
- for( j = 0; j < r_backacc.numVerts; j++ )
- {
- temp = args[2] + args[3] * ( inVertsArray[j][0] + inVertsArray[j][1] + inVertsArray[j][2] );
- deflect = FTABLE_EVALUATE( table, temp ) * args[1] + args[0];
- VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
- }
- }
- break;
-
- case DEFORM_NORMAL:
- // without this * 0.1f deformation looks wrong, although q3a doesn't have it
- args[0] = deformv->func.args[3] * r_currentShaderTime * 0.1f;
- args[1] = deformv->func.args[1];
-
- for( j = 0; j < r_backacc.numVerts; j++ )
- {
- VectorScale( inVertsArray[j], 0.98f, tv );
- inNormalsArray[j][0] += args[1] *R_BackendGetNoiseValue( tv[0], tv[1], tv[2], args[0] );
- inNormalsArray[j][1] += args[1] *R_BackendGetNoiseValue( tv[0] + 100, tv[1], tv[2], args[0] );
- inNormalsArray[j][2] += args[1] *R_BackendGetNoiseValue( tv[0] + 200, tv[1], tv[2], args[0] );
- VectorNormalizeFast( inNormalsArray[j] );
- }
- break;
-
- case DEFORM_MOVE:
- table = R_TableForFunc( deformv->func.type );
- temp = deformv->func.args[2] + r_currentShaderTime * deformv->func.args[3];
- deflect = FTABLE_EVALUATE( table, temp ) * deformv->func.args[1] + deformv->func.args[0];
-
- for( j = 0; j < r_backacc.numVerts; j++ )
- VectorMA( inVertsArray[j], deflect, deformv->args, inVertsArray[j] );
- break;
-
- case DEFORM_BULGE:
- args[0] = deformv->args[0];
- args[1] = deformv->args[1];
- args[2] = r_currentShaderTime * deformv->args[2];
-
- for( j = 0; j < r_backacc.numVerts; j++ )
- {
- temp = ( coordsArray[j][0] * args[0] + args[2] ) / M_PI2;
- deflect = R_FastSin( temp ) * args[1];
- VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
- }
- break;
-
- case DEFORM_AUTOSPRITE:
- {
- vec4_t *v;
- vec2_t *st;
- elem_t *elem;
- float radius;
- vec3_t point, v_centre, v_right, v_up;
-
- if( r_backacc.numVerts % 4 || r_backacc.numElems % 6 )
- break;
-
- if( RI.currententity && (RI.currentmodel != r_worldmodel) )
- {
- Matrix_TransformVector( RI.currententity->axis, RI.vright, v_right );
- Matrix_TransformVector( RI.currententity->axis, RI.vup, v_up );
- }
- else
- {
- VectorCopy( RI.vright, v_right );
- VectorCopy( RI.vup, v_up );
- }
-
- radius = RI.currententity->scale;
- if( radius && radius != 1.0f )
- {
- radius = 1.0f / radius;
- VectorScale( v_right, radius, v_right );
- VectorScale( v_up, radius, v_up );
- }
-
- for( k = 0, v = inVertsArray, st = coordsArray, elem = elemsArray; k < r_backacc.numVerts; k += 4, v += 4, st += 4, elem += 6 )
- {
- for( j = 0; j < 3; j++ )
- v_centre[j] = (v[0][j] + v[1][j] + v[2][j] + v[3][j]) * 0.25;
-
- VectorSubtract( v[0], v_centre, point );
- radius = VectorLength( point ) * 0.707106f; // 1.0f / sqrt(2)
-
- // very similar to R_PushSprite
- VectorMA( v_centre, -radius, v_up, point );
- VectorMA( point, -radius, v_right, v[0] );
- VectorMA( point, radius, v_right, v[3] );
-
- VectorMA( v_centre, radius, v_up, point );
- VectorMA( point, -radius, v_right, v[1] );
- VectorMA( point, radius, v_right, v[2] );
-
- // reset texcoords
- Vector2Set( st[0], 0, 1 );
- Vector2Set( st[1], 0, 0 );
- Vector2Set( st[2], 1, 0 );
- Vector2Set( st[3], 1, 1 );
-
- // trifan elems
- elem[0] = k;
- elem[1] = k + 2 - 1;
- elem[2] = k + 2;
-
- elem[3] = k;
- elem[4] = k + 3 - 1;
- elem[5] = k + 3;
- }
- }
- break;
-
- case DEFORM_AUTOSPRITE2:
- if( r_backacc.numElems % 6 )
- break;
-
- for( k = 0; k < r_backacc.numElems; k += 6 )
- {
- int long_axis = 0, short_axis = 0;
- vec3_t axis, tmp;
- float len[3];
- vec3_t m0[3], m1[3], m2[3], result[3];
-
- quad[0] = ( float * )( inVertsArray + elemsArray[k+0] );
- quad[1] = ( float * )( inVertsArray + elemsArray[k+1] );
- quad[2] = ( float * )( inVertsArray + elemsArray[k+2] );
-
- for( j = 2; j >= 0; j-- )
- {
- quad[3] = ( float * )( inVertsArray + elemsArray[k+3+j] );
-
- if( !VectorCompare( quad[3], quad[0] ) &&
- !VectorCompare( quad[3], quad[1] ) &&
- !VectorCompare( quad[3], quad[2] ) )
- {
- break;
- }
- }
-
- // build a matrix were the longest axis of the billboard is the Y-Axis
- VectorSubtract( quad[1], quad[0], m0[0] );
- VectorSubtract( quad[2], quad[0], m0[1] );
- VectorSubtract( quad[2], quad[1], m0[2] );
- len[0] = DotProduct( m0[0], m0[0] );
- len[1] = DotProduct( m0[1], m0[1] );
- len[2] = DotProduct( m0[2], m0[2] );
-
- if( ( len[2] > len[1] ) && ( len[2] > len[0] ) )
- {
- if( len[1] > len[0] )
- {
- long_axis = 1;
- short_axis = 0;
- }
- else
- {
- long_axis = 0;
- short_axis = 1;
- }
- }
- else if( ( len[1] > len[2] ) && ( len[1] > len[0] ) )
- {
- if( len[2] > len[0] )
- {
- long_axis = 2;
- short_axis = 0;
- }
- else
- {
- long_axis = 0;
- short_axis = 2;
- }
- }
- else if( ( len[0] > len[1] ) && ( len[0] > len[2] ) )
- {
- if( len[2] > len[1] )
- {
- long_axis = 2;
- short_axis = 1;
- }
- else
- {
- long_axis = 1;
- short_axis = 2;
- }
- }
-
- if( !len[long_axis] )
- break;
- len[long_axis] = Q_RSqrt( len[long_axis] );
- VectorScale( m0[long_axis], len[long_axis], axis );
-
- if( DotProduct( m0[long_axis], m0[short_axis] ) )
- {
- VectorCopy( axis, m0[1] );
- if( axis[0] || axis[1] )
- VectorVectors( m0[1], m0[0], m0[2] );
- else
- VectorVectors( m0[1], m0[2], m0[0] );
- }
- else
- {
- if( !len[short_axis] )
- break;
- len[short_axis] = Q_RSqrt( len[short_axis] );
- VectorScale( m0[short_axis], len[short_axis], m0[0] );
- VectorCopy( axis, m0[1] );
- CrossProduct( m0[0], m0[1], m0[2] );
- }
-
- for( j = 0; j < 3; j++ )
- rot_centre[j] = ( quad[0][j] + quad[1][j] + quad[2][j] + quad[3][j] ) * 0.25;
-
- if( RI.currententity && ( RI.currentmodel != r_worldmodel ) )
- {
- VectorAdd( RI.currententity->origin, rot_centre, tv );
- VectorSubtract( RI.viewOrigin, tv, tmp );
- Matrix_TransformVector( RI.currententity->axis, tmp, tv );
- }
- else
- {
- VectorCopy( rot_centre, tv );
- VectorSubtract( RI.viewOrigin, tv, tv );
- }
-
- // filter any longest-axis-parts off the camera-direction
- deflect = -DotProduct( tv, axis );
-
- VectorMA( tv, deflect, axis, m1[2] );
- VectorNormalizeFast( m1[2] );
- VectorCopy( axis, m1[1] );
- CrossProduct( m1[1], m1[2], m1[0] );
-
- Matrix_Transpose( m1, m2 );
- Matrix_Multiply( m2, m0, result );
-
- for( j = 0; j < 4; j++ )
- {
- VectorSubtract( quad[j], rot_centre, tv );
- Matrix_TransformVector( result, tv, quad[j] );
- VectorAdd( rot_centre, quad[j], quad[j] );
- }
- }
- break;
-
- case DEFORM_PROJECTION_SHADOW:
- R_DeformVPlanarShadow( r_backacc.numVerts, inVertsArray[0] );
- break;
-
- case DEFORM_AUTOPARTICLE:
- {
- float scale;
- vec3_t m0[3], m1[3], m2[3], result[3];
-
- if( r_backacc.numElems % 6 )
- break;
-
- if( RI.currententity && ( RI.currentmodel != r_worldmodel ) )
- Matrix4_Matrix( RI.modelviewMatrix, m1 );
- else
- Matrix4_Matrix( RI.worldviewMatrix, m1 );
-
- Matrix_Transpose( m1, m2 );
-
- for( k = 0; k < r_backacc.numElems; k += 6 )
- {
- quad[0] = ( float * )( inVertsArray + elemsArray[k+0] );
- quad[1] = ( float * )( inVertsArray + elemsArray[k+1] );
- quad[2] = ( float * )( inVertsArray + elemsArray[k+2] );
-
- for( j = 2; j >= 0; j-- )
- {
- quad[3] = ( float * )( inVertsArray + elemsArray[k+3+j] );
-
- if( !VectorCompare( quad[3], quad[0] ) &&
- !VectorCompare( quad[3], quad[1] ) &&
- !VectorCompare( quad[3], quad[2] ) )
- {
- break;
- }
- }
-
- Matrix_FromPoints( quad[0], quad[1], quad[2], m0 );
- Matrix_Multiply( m2, m0, result );
-
- // hack a scale up to keep particles from disappearing
- scale = ( quad[0][0] - RI.viewOrigin[0] ) * RI.vpn[0] + ( quad[0][1] - RI.viewOrigin[1] ) * RI.vpn[1] + ( quad[0][2] - RI.viewOrigin[2] ) * RI.vpn[2];
- if( scale < 20 )
- scale = 1.5;
- else
- scale = 1.5 + scale * 0.006f;
-
- for( j = 0; j < 3; j++ )
- rot_centre[j] = ( quad[0][j] + quad[1][j] + quad[2][j] + quad[3][j] ) * 0.25;
-
- for( j = 0; j < 4; j++ )
- {
- VectorSubtract( quad[j], rot_centre, tv );
- Matrix_TransformVector( result, tv, quad[j] );
- VectorMA( rot_centre, scale, quad[j], quad[j] );
- }
- }
- }
- break;
- case DEFORM_OUTLINE:
- // Deflect vertex along its normal by outline amount
- deflect = RI.currententity->outlineHeight * r_outlines_scale->value;
- for( j = 0; j < r_backacc.numVerts; j++ )
- VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
- break;
- default:
- break;
- }
- }
-}
-
-/*
-==============
-R_VertexTCBase
-==============
-*/
-static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix )
-{
- unsigned int i;
- float *outCoords;
- bool identityMatrix = false;
-
- Matrix4_Identity( matrix );
-
- switch( pass->tcgen )
- {
- case TCGEN_BASE:
- GL_DisableAllTexGens();
-
- R_UpdateVertexBuffer( tr.tcoordBuffer[unit], coordsArray, r_backacc.numVerts * sizeof( vec2_t ));
- pglTexCoordPointer( 2, GL_FLOAT, 0, coordsArray );
- return true;
- case TCGEN_LIGHTMAP:
- GL_DisableAllTexGens();
-
- R_UpdateVertexBuffer( tr.tcoordBuffer[unit], lightmapCoordsArray[r_lightmapStyleNum[unit]], r_backacc.numVerts * sizeof( vec2_t ));
- pglTexCoordPointer( 2, GL_FLOAT, 0, lightmapCoordsArray[r_lightmapStyleNum[unit]] );
- return true;
- case TCGEN_ENVIRONMENT:
- {
- float depth, *n;
- vec3_t projection, transform;
-
- if( glState.in2DMode )
- return true;
-
- if( !( RI.params & RP_SHADOWMAPVIEW ) )
- {
- VectorSubtract( RI.viewOrigin, RI.currententity->origin, projection );
- Matrix_TransformVector( RI.currententity->axis, projection, transform );
-
- outCoords = tUnitCoordsArray[unit][0];
- for( i = 0, n = normalsArray[0]; i < r_backacc.numVerts; i++, outCoords += 2, n += 4 )
- {
- VectorSubtract( transform, vertsArray[i], projection );
- VectorNormalizeFast( projection );
-
- depth = DotProduct( n, projection ); depth += depth;
- outCoords[0] = 0.5 + ( n[1] * depth - projection[1] ) * 0.5;
- outCoords[1] = 0.5 - ( n[2] * depth - projection[2] ) * 0.5;
- }
- }
-
- GL_DisableAllTexGens();
-
- R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray, r_backacc.numVerts * sizeof( vec2_t ));
- pglTexCoordPointer( 2, GL_FLOAT, 0, tUnitCoordsArray[unit] );
- return true;
- }
-
- case TCGEN_VECTOR:
- {
- GLfloat genVector[2][4];
-
- for( i = 0; i < 3; i++ )
- {
- genVector[0][i] = pass->tcgenVec[i];
- genVector[1][i] = pass->tcgenVec[i+4];
- }
- genVector[0][3] = genVector[1][3] = 0;
-
- matrix[12] = pass->tcgenVec[3];
- matrix[13] = pass->tcgenVec[7];
-
- GL_SetTexCoordArrayMode( 0 );
- GL_EnableTexGen( GL_S, GL_OBJECT_LINEAR );
- GL_EnableTexGen( GL_T, GL_OBJECT_LINEAR );
- GL_EnableTexGen( GL_R, 0 );
- GL_EnableTexGen( GL_Q, 0 );
- pglTexGenfv( GL_S, GL_OBJECT_PLANE, genVector[0] );
- pglTexGenfv( GL_T, GL_OBJECT_PLANE, genVector[1] );
- return false;
- }
- case TCGEN_PROJECTION:
- {
- mat4x4_t m1, m2;
- GLfloat genVector[4][4];
-
- GL_SetTexCoordArrayMode( 0 );
-
- Matrix4_Copy( RI.worldviewProjectionMatrix, matrix );
-
- Matrix4_Identity( m1 );
- Matrix4_Scale( m1, 0.5, 0.5, 0.5 );
- Matrix4_Multiply( m1, matrix, m2 );
-
- Matrix4_Identity( m1 );
- Matrix4_Translate( m1, 0.5, 0.5, 0.5 );
- Matrix4_Multiply( m1, m2, matrix );
-
- for( i = 0; i < 4; i++ )
- {
- genVector[0][i] = i == 0 ? 1 : 0;
- genVector[1][i] = i == 1 ? 1 : 0;
- genVector[2][i] = i == 2 ? 1 : 0;
- genVector[3][i] = i == 3 ? 1 : 0;
- }
-
- GL_EnableTexGen( GL_S, GL_OBJECT_LINEAR );
- GL_EnableTexGen( GL_T, GL_OBJECT_LINEAR );
- GL_EnableTexGen( GL_R, GL_OBJECT_LINEAR );
- GL_EnableTexGen( GL_Q, GL_OBJECT_LINEAR );
-
- pglTexGenfv( GL_S, GL_OBJECT_PLANE, genVector[0] );
- pglTexGenfv( GL_T, GL_OBJECT_PLANE, genVector[1] );
- pglTexGenfv( GL_R, GL_OBJECT_PLANE, genVector[2] );
- pglTexGenfv( GL_Q, GL_OBJECT_PLANE, genVector[3] );
- return false;
- }
-
- case TCGEN_REFLECTION_CELLSHADE:
- if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) )
- {
- vec3_t dir;
- mat4x4_t m;
-
- R_LightForOrigin( RI.currententity->lightingOrigin, dir, NULL, NULL, RI.currentmodel->radius * RI.currententity->scale );
-
- Matrix4_Identity( m );
-
- // rotate direction
- Matrix_TransformVector( RI.currententity->axis, dir, &m[0] );
- VectorNormalizeLength( &m[0] );
-
- VectorVectors( &m[0], &m[4], &m[8] );
- Matrix4_Transpose( m, matrix );
- }
- case TCGEN_REFLECTION:
- GL_EnableTexGen( GL_S, GL_REFLECTION_MAP_ARB );
- GL_EnableTexGen( GL_T, GL_REFLECTION_MAP_ARB );
- GL_EnableTexGen( GL_R, GL_REFLECTION_MAP_ARB );
- GL_EnableTexGen( GL_Q, 0 );
- return true;
-
- case TCGEN_FOG:
- {
- int fogPtype;
- cplane_t *fogPlane;
- ref_shader_t *fogShader;
- vec3_t viewtofog;
- float fogNormal[3], vpnNormal[3];
- float dist, vdist, fogDist, vpnDist;
-
- fogPlane = r_texFog->visibleplane;
- fogShader = r_texFog->shader;
-
- matrix[0] = matrix[5] = 1.0/(fogShader->fog_dist - fogShader->fog_clearDist);
- matrix[13] = 1.5f/(float)FOG_TEXTURE_HEIGHT;
-
- // distance to fog
- dist = RI.fog_dist_to_eye[r_texFog-r_worldbrushmodel->fogs];
-
- if( r_currentShader->flags & SHADER_SKYPARMS )
- {
- if( dist > 0 )
- VectorMA( RI.viewOrigin, -dist, fogPlane->normal, viewtofog );
- else
- VectorCopy( RI.viewOrigin, viewtofog );
- }
- else
- {
- VectorCopy( RI.currententity->origin, viewtofog );
- }
-
- // some math tricks to take entity's rotation matrix into account
- // for fog texture coordinates calculations:
- // M is rotation matrix, v is vertex, t is transform vector
- // n is plane's normal, d is plane's dist, r is view origin
- // (M*v + t)*n - d = (M*n)*v - ((d - t*n))
- // (M*v + t - r)*n = (M*n)*v - ((r - t)*n)
- fogNormal[0] = DotProduct( RI.currententity->axis[0], fogPlane->normal ) * RI.currententity->scale;
- fogNormal[1] = DotProduct( RI.currententity->axis[1], fogPlane->normal ) * RI.currententity->scale;
- fogNormal[2] = DotProduct( RI.currententity->axis[2], fogPlane->normal ) * RI.currententity->scale;
- fogPtype = ( fogNormal[0] == 1.0 ? PLANE_X : ( fogNormal[1] == 1.0 ? PLANE_Y : ( fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NONAXIAL ) ) );
- fogDist = ( fogPlane->dist - DotProduct( viewtofog, fogPlane->normal ) );
-
- vpnNormal[0] = DotProduct( RI.currententity->axis[0], RI.vpn ) * RI.currententity->scale;
- vpnNormal[1] = DotProduct( RI.currententity->axis[1], RI.vpn ) * RI.currententity->scale;
- vpnNormal[2] = DotProduct( RI.currententity->axis[2], RI.vpn ) * RI.currententity->scale;
- vpnDist = ( ( RI.viewOrigin[0] - viewtofog[0] ) * RI.vpn[0] + ( RI.viewOrigin[1] - viewtofog[1] ) * RI.vpn[1] + ( RI.viewOrigin[2] - viewtofog[2] ) * RI.vpn[2] ) + fogShader->fog_clearDist;
-
- outCoords = tUnitCoordsArray[unit][0];
- if( dist < 0 )
- { // camera is inside the fog brush
- for( i = 0; i < r_backacc.numVerts; i++, outCoords += 2 )
- {
- outCoords[0] = DotProduct( vertsArray[i], vpnNormal ) - vpnDist;
- if( fogPtype < 3 )
- outCoords[1] = -( vertsArray[i][fogPtype] - fogDist );
- else
- outCoords[1] = -( DotProduct( vertsArray[i], fogNormal ) - fogDist );
- }
- }
- else
- {
- for( i = 0; i < r_backacc.numVerts; i++, outCoords += 2 )
- {
- if( fogPtype < 3 )
- vdist = vertsArray[i][fogPtype] - fogDist;
- else
- vdist = DotProduct( vertsArray[i], fogNormal ) - fogDist;
- outCoords[0] = ( ( vdist < 0 ) ? ( DotProduct( vertsArray[i], vpnNormal ) - vpnDist ) * vdist / ( vdist - dist ) : 0.0f );
- outCoords[1] = -vdist;
- }
- }
-
- GL_DisableAllTexGens();
-
- R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray, r_backacc.numVerts * sizeof( vec2_t ));
- pglTexCoordPointer( 2, GL_FLOAT, 0, tUnitCoordsArray[unit] );
- return false;
- }
-
- case TCGEN_SVECTORS:
- GL_DisableAllTexGens();
- R_UpdateVertexBuffer( tr.tcoordBuffer[unit], sVectorsArray, r_backacc.numVerts * sizeof( vec4_t ));
- pglTexCoordPointer( 4, GL_FLOAT, 0, sVectorsArray );
- return true;
- case TCGEN_PROJECTION_SHADOW:
- GL_SetTexCoordArrayMode( 0 );
- GL_DisableAllTexGens();
- Matrix4_Multiply( r_currentCastGroup->worldviewProjectionMatrix, RI.objectMatrix, matrix );
- break;
- default: break;
- }
- return identityMatrix;
-}
-
-/*
-================
-R_ApplyTCMods
-================
-*/
-static void R_ApplyTCMods( const ref_stage_t *pass, mat4x4_t result )
-{
- int i;
- const float *table;
- double t1, t2, sint, cost;
- mat4x4_t m1, m2;
- const tcMod_t *tcmod;
-
- for( i = 0, tcmod = pass->tcMods; i < pass->numtcMods; i++, tcmod++ )
- {
- switch( tcmod->type )
- {
- case TCMOD_ROTATE:
- cost = tcmod->args[0] * r_currentShaderTime;
- sint = R_FastSin( cost );
- cost = R_FastSin( cost + 0.25 );
- m2[0] = cost, m2[1] = sint, m2[12] = 0.5f * ( sint - cost + 1 );
- m2[4] = -sint, m2[5] = cost, m2[13] = -0.5f * ( sint + cost - 1 );
- Matrix4_Copy2D( result, m1 );
- Matrix4_Multiply2D( m2, m1, result );
- break;
- case TCMOD_SCALE:
- Matrix4_Scale2D( result, tcmod->args[0], tcmod->args[1] );
- break;
- case TCMOD_TURB:
- t1 = ( 1.0 / 4.0 );
- t2 = tcmod->args[2] + r_currentShaderTime * tcmod->args[3];
- Matrix4_Scale2D( result, 1 + ( tcmod->args[1] * R_FastSin( t2 ) + tcmod->args[0] ) * t1, 1 + ( tcmod->args[1] * R_FastSin( t2 + 0.25 ) + tcmod->args[0] ) * t1 );
- break;
- case TCMOD_STRETCH:
- table = R_TableForFunc( tcmod->args[0] );
- t2 = tcmod->args[3] + r_currentShaderTime * tcmod->args[4];
- t1 = FTABLE_EVALUATE( table, t2 ) * tcmod->args[2] + tcmod->args[1];
- t1 = t1 ? 1.0f / t1 : 1.0f;
- t2 = 0.5f - 0.5f * t1;
- Matrix4_Stretch2D( result, t1, t2 );
- break;
- case TCMOD_SCROLL:
- t1 = tcmod->args[0] * r_currentShaderTime;
- t2 = tcmod->args[1] * r_currentShaderTime;
- if( pass->program_type != PROGRAM_TYPE_DISTORTION )
- { // HACK HACK HACK
- t1 = t1 - floor( t1 );
- t2 = t2 - floor( t2 );
- }
- Matrix4_Translate2D( result, t1, t2 );
- break;
- case TCMOD_TRANSFORM:
- m2[0] = tcmod->args[0], m2[1] = tcmod->args[2], m2[12] = tcmod->args[4],
- m2[5] = tcmod->args[1], m2[4] = tcmod->args[3], m2[13] = tcmod->args[5];
- Matrix4_Copy2D( result, m1 );
- Matrix4_Multiply2D( m2, m1, result );
- break;
- default:
- break;
- }
- }
-}
-
-/*
-==============
-R_ShaderpassTex
-==============
-*/
-static _inline texture_t *R_ShaderpassTex( const ref_stage_t *pass, int unit )
-{
- if( pass->flags & SHADERSTAGE_ANIMFREQUENCY && pass->animFrequency && pass->num_textures )
- return pass->textures[(int)( pass->animFrequency * r_currentShaderTime ) % pass->num_textures];
- if( pass->flags & SHADERSTAGE_LIGHTMAP )
- return tr.lightmapTextures[r_superLightStyle->lightmapNum[r_lightmapStyleNum[unit]]];
- if( pass->flags & SHADERSTAGE_PORTALMAP )
- return tr.portaltexture1;
- return ( pass->textures[0] ? pass->textures[0] : tr.defaultTexture );
-}
-
-/*
-================
-R_BindShaderpass
-================
-*/
-static void R_BindShaderpass( const ref_stage_t *pass, texture_t *tex, int unit )
-{
- mat4x4_t m1, m2, result;
- bool identityMatrix;
-
- if( !tex )
- tex = R_ShaderpassTex( pass, unit );
-
- GL_Bind( unit, tex );
- if( unit && !pass->program ) pglEnable( GL_TEXTURE_2D );
- GL_SetTexCoordArrayMode( ( tex->flags & TF_CUBEMAP ? GL_TEXTURE_CUBE_MAP_ARB : GL_TEXTURE_COORD_ARRAY ));
-
- identityMatrix = R_VertexTCBase( pass, unit, result );
-
- if( pass->numtcMods )
- {
- identityMatrix = false;
- R_ApplyTCMods( pass, result );
- }
-
- if( pass->tcgen == TCGEN_REFLECTION || pass->tcgen == TCGEN_REFLECTION_CELLSHADE )
- {
- Matrix4_Transpose( RI.modelviewMatrix, m1 );
- Matrix4_Copy( result, m2 );
- Matrix4_Multiply( m2, m1, result );
- GL_LoadTexMatrix( result );
- return;
- }
-
- if( identityMatrix )
- GL_LoadIdentityTexMatrix();
- else
- GL_LoadTexMatrix( result );
-}
-
-/*
-================
-R_ModifyColor
-================
-*/
-void R_ModifyColor( const ref_stage_t *pass )
-{
- uint i;
- int c, bits;
- double temp;
- float *table, a;
- vec3_t t, v, style;
- byte *bArray, *inArray, rgba[4] = { 255, 255, 255, 255 };
- bool noArray, identityAlpha, entityAlpha;
- const waveFunc_t *rgbgenfunc, *alphagenfunc;
-
- noArray = ( pass->flags & SHADERSTAGE_NOCOLORARRAY ) && !r_colorFog;
- r_backacc.numColors = noArray ? 1 : r_backacc.numVerts;
- bits = ( r_overbrightbits->integer > 0 ) && !( r_ignorehwgamma->integer ) ? r_overbrightbits->integer : 0;
-
- bArray = colorArray[0];
- inArray = inColorsArray[0][0];
-
- if( pass->rgbGen.type == RGBGEN_IDENTITY_LIGHTING )
- {
- entityAlpha = identityAlpha = false;
- memset( bArray, r_identityLighting, sizeof( rgba_t ) * r_backacc.numColors );
- }
- else if( pass->rgbGen.type == RGBGEN_EXACT_VERTEX )
- {
- entityAlpha = identityAlpha = false;
- memcpy( bArray, inArray, sizeof( rgba_t ) * r_backacc.numColors );
- }
- else
- {
- entityAlpha = false;
- identityAlpha = true;
- memset( bArray, 255, sizeof( rgba_t ) * r_backacc.numColors );
-
- switch( pass->rgbGen.type )
- {
- case RGBGEN_IDENTITY:
- break;
- case RGBGEN_CONST:
- rgba[0] = R_FloatToByte( pass->rgbGen.args[0] );
- rgba[1] = R_FloatToByte( pass->rgbGen.args[1] );
- rgba[2] = R_FloatToByte( pass->rgbGen.args[2] );
-
- for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 )
- *(int *)bArray = c;
- break;
- case RGBGEN_WAVE:
- rgbgenfunc = pass->rgbGen.func;
- if( rgbgenfunc->type == WAVEFORM_NOISE )
- {
- temp = R_BackendGetNoiseValue( 0, 0, 0, ( r_currentShaderTime + rgbgenfunc->args[2] ) * rgbgenfunc->args[3] );
- }
- else
- {
- table = R_TableForFunc( rgbgenfunc->type );
- temp = r_currentShaderTime * rgbgenfunc->args[3] + rgbgenfunc->args[2];
- temp = FTABLE_EVALUATE( table, temp ) * rgbgenfunc->args[1] + rgbgenfunc->args[0];
- }
-
- temp = temp * rgbgenfunc->args[1] + rgbgenfunc->args[0];
- a = pass->rgbGen.args[0] * temp; rgba[0] = a <= 0 ? 0 : R_FloatToByte( a );
- a = pass->rgbGen.args[1] * temp; rgba[1] = a <= 0 ? 0 : R_FloatToByte( a );
- a = pass->rgbGen.args[2] * temp; rgba[2] = a <= 0 ? 0 : R_FloatToByte( a );
-
- for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 )
- *(int *)bArray = c;
- break;
- case RGBGEN_ENTITY:
- entityAlpha = true;
- identityAlpha = ( RI.currententity->color[3] == 255 );
-
- for( i = 0, c = *(int *)RI.currententity->color; i < r_backacc.numColors; i++, bArray += 4 )
- *(int *)bArray = c;
- break;
- case RGBGEN_OUTLINE:
- identityAlpha = ( RI.currententity->outlineColor[3] == 255 );
-
- for( i = 0, c = *(int *)RI.currententity->outlineColor; i < r_backacc.numColors; i++, bArray += 4 )
- *(int *)bArray = c;
- break;
- case RGBGEN_ONE_MINUS_ENTITY:
- rgba[0] = 255 - RI.currententity->color[0];
- rgba[1] = 255 - RI.currententity->color[1];
- rgba[2] = 255 - RI.currententity->color[2];
-
- for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 )
- *(int *)bArray = c;
- break;
- case RGBGEN_VERTEX:
- VectorSet( style, -1, -1, -1 );
-
- if( !r_superLightStyle || r_superLightStyle->vertexStyles[1] == 255 )
- {
- VectorSet( style, 1, 1, 1 );
- if( r_superLightStyle && r_superLightStyle->vertexStyles[0] != 255 )
- VectorCopy( r_lightStyles[r_superLightStyle->vertexStyles[0]].rgb, style );
- }
-
- if( style[0] == style[1] && style[1] == style[2] && style[2] == 1 )
- {
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 )
- {
- bArray[0] = inArray[0] >> bits;
- bArray[1] = inArray[1] >> bits;
- bArray[2] = inArray[2] >> bits;
- }
- }
- else
- {
- int j;
- float *tc;
- vec3_t temp[MAX_ARRAY_VERTS];
-
- memset( temp, 0, sizeof( vec3_t ) * r_backacc.numColors );
-
- for( j = 0; j < LM_STYLES && r_superLightStyle->vertexStyles[j] != 255; j++ )
- {
- VectorCopy( r_lightStyles[r_superLightStyle->vertexStyles[j]].rgb, style );
- if( VectorCompare( style, vec3_origin ) )
- continue;
-
- inArray = inColorsArray[j][0];
- for( i = 0, tc = temp[0]; i < r_backacc.numColors; i++, tc += 3, inArray += 4 )
- {
- tc[0] += ( inArray[0] >> bits ) * style[0];
- tc[1] += ( inArray[1] >> bits ) * style[1];
- tc[2] += ( inArray[2] >> bits ) * style[2];
- }
- }
-
- for( i = 0, tc = temp[0]; i < r_backacc.numColors; i++, tc += 3, bArray += 4 )
- {
- bArray[0] = bound( 0, tc[0], 255 );
- bArray[1] = bound( 0, tc[1], 255 );
- bArray[2] = bound( 0, tc[2], 255 );
- }
- }
- break;
- case RGBGEN_ONE_MINUS_VERTEX:
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 )
- {
- bArray[0] = 255 - ( inArray[0] >> bits );
- bArray[1] = 255 - ( inArray[1] >> bits );
- bArray[2] = 255 - ( inArray[2] >> bits );
- }
- break;
- case RGBGEN_LIGHTING_DIFFUSE:
- if( RI.currententity )
- R_LightForEntity( RI.currententity, bArray );
- break;
- case RGBGEN_LIGHTING_DIFFUSE_ONLY:
- if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) )
- {
- vec4_t diffuse;
-
- if( RI.currententity->flags & RF_FULLBRIGHT )
- VectorSet( diffuse, 1, 1, 1 );
- else
- R_LightForOrigin( RI.currententity->lightingOrigin, t, NULL, diffuse, RI.currentmodel->radius * RI.currententity->scale );
-
- rgba[0] = R_FloatToByte( diffuse[0] );
- rgba[1] = R_FloatToByte( diffuse[1] );
- rgba[2] = R_FloatToByte( diffuse[2] );
-
- for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 )
- *(int *)bArray = c;
- }
- break;
- case RGBGEN_LIGHTING_AMBIENT_ONLY:
- if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) )
- {
- vec4_t ambient;
-
- if( RI.currententity->flags & RF_FULLBRIGHT )
- VectorSet( ambient, 1, 1, 1 );
- else
- R_LightForOrigin( RI.currententity->lightingOrigin, t, ambient, NULL, RI.currentmodel->radius * RI.currententity->scale );
-
- rgba[0] = R_FloatToByte( ambient[0] );
- rgba[1] = R_FloatToByte( ambient[1] );
- rgba[2] = R_FloatToByte( ambient[2] );
-
- for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 )
- *(int *)bArray = c;
- }
- break;
- case RGBGEN_FOG:
- for( i = 0, c = *(int *)r_texFog->shader->fog_color; i < r_backacc.numColors; i++, bArray += 4 )
- *(int *)bArray = c;
- break;
- case RGBGEN_CUSTOM:
- c = (int)pass->rgbGen.args[0];
- for( i = 0, c = R_GetCustomColor( c ); i < r_backacc.numColors; i++, bArray += 4 )
- *(int *)bArray = c;
- break;
- case RGBGEN_ENVIRONMENT:
- for( i = 0, c = *(int *)mapConfig.environmentColor; i < r_backacc.numColors; i++, bArray += 4 )
- *(int *)bArray = c;
- break;
- default:
- break;
- }
- }
-
- bArray = colorArray[0];
- inArray = inColorsArray[0][0];
-
- switch( pass->alphaGen.type )
- {
- case ALPHAGEN_IDENTITY:
- if( identityAlpha )
- break;
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- bArray[3] = 255;
- break;
- case ALPHAGEN_CONST:
- c = R_FloatToByte( pass->alphaGen.args[0] );
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- bArray[3] = c;
- break;
- case ALPHAGEN_WAVE:
- alphagenfunc = pass->alphaGen.func;
- if( alphagenfunc->type == WAVEFORM_NOISE )
- {
- a = R_BackendGetNoiseValue( 0, 0, 0, ( r_currentShaderTime + alphagenfunc->args[2] ) * alphagenfunc->args[3] );
- }
- else
- {
- table = R_TableForFunc( alphagenfunc->type );
- a = alphagenfunc->args[2] + r_currentShaderTime * alphagenfunc->args[3];
- a = FTABLE_EVALUATE( table, a );
- }
-
- a = a * alphagenfunc->args[1] + alphagenfunc->args[0];
- c = a <= 0 ? 0 : R_FloatToByte( a );
-
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- bArray[3] = c;
- break;
- case ALPHAGEN_PORTAL:
- VectorAdd( vertsArray[0], RI.currententity->origin, v );
- VectorSubtract( RI.viewOrigin, v, t );
- a = VectorLength( t ) * pass->alphaGen.args[0];
- a = bound( 0.0f, a, 1.0f );
- c = R_FloatToByte( a );
-
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- bArray[3] = c;
- break;
- case ALPHAGEN_VERTEX:
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 )
- bArray[3] = inArray[3];
- break;
- case ALPHAGEN_ONE_MINUS_VERTEX:
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 )
- bArray[3] = 255 - inArray[3];
- break;
- case ALPHAGEN_ENTITY:
- if( entityAlpha )
- break;
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- bArray[3] = RI.currententity->color[3];
- break;
- case ALPHAGEN_OUTLINE:
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- bArray[3] = RI.currententity->outlineColor[3];
- break;
- case ALPHAGEN_SPECULAR:
- VectorSubtract( RI.viewOrigin, RI.currententity->origin, t );
- if( !Matrix_Compare( RI.currententity->axis, axis_identity ) )
- Matrix_TransformVector( RI.currententity->axis, t, v );
- else
- VectorCopy( t, v );
-
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- {
- VectorSubtract( v, vertsArray[i], t );
- c = VectorLength( t );
- a = DotProduct( t, normalsArray[i] ) / max( 0.1, c );
- a = pow( a, pass->alphaGen.args[0] );
- bArray[3] = a <= 0 ? 0 : R_FloatToByte( a );
- }
- break;
- case ALPHAGEN_DOT:
- if( !Matrix_Compare( RI.currententity->axis, axis_identity ) )
- Matrix_TransformVector( RI.currententity->axis, RI.vpn, v );
- else
- VectorCopy( RI.vpn, v );
-
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- {
- a = DotProduct( v, inNormalsArray[i] ); if( a < 0 ) a = -a;
- bArray[3] = R_FloatToByte( bound( pass->alphaGen.args[0], a, pass->alphaGen.args[1] ) );
- }
- break;
- case ALPHAGEN_ONE_MINUS_DOT:
- if( !Matrix_Compare( RI.currententity->axis, axis_identity ) )
- Matrix_TransformVector( RI.currententity->axis, RI.vpn, v );
- else
- VectorCopy( RI.vpn, v );
-
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- {
- a = DotProduct( v, inNormalsArray[i] ); if( a < 0 ) a = -a;a = 1.0f - a;
- bArray[3] = R_FloatToByte( bound( pass->alphaGen.args[0], a, pass->alphaGen.args[1] ) );
- }
- default:
- break;
- }
-
- if( r_colorFog )
- {
- float dist, vdist;
- cplane_t *fogPlane;
- vec3_t viewtofog;
- float fogNormal[3], vpnNormal[3];
- float fogDist, vpnDist, fogShaderDistScale;
- int fogptype;
- bool alphaFog;
- int blendsrc, blenddst;
-
- blendsrc = pass->glState & GLSTATE_SRCBLEND_MASK;
- blenddst = pass->glState & GLSTATE_DSTBLEND_MASK;
- if(( blendsrc != GLSTATE_SRCBLEND_SRC_ALPHA && blenddst != GLSTATE_DSTBLEND_SRC_ALPHA ) && ( blendsrc != GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA && blenddst != GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA ))
- alphaFog = false;
- else alphaFog = true;
-
- fogPlane = r_colorFog->visibleplane;
- fogShaderDistScale = 1.0 / (r_colorFog->shader->fog_dist - r_colorFog->shader->fog_clearDist);
- dist = RI.fog_dist_to_eye[r_colorFog-r_worldbrushmodel->fogs];
-
- if( r_currentShader->flags & SHADER_SKYPARMS )
- {
- if( dist > 0 )
- VectorScale( fogPlane->normal, -dist, viewtofog );
- else
- VectorClear( viewtofog );
- }
- else
- {
- VectorCopy( RI.currententity->origin, viewtofog );
- }
-
- vpnNormal[0] = DotProduct( RI.currententity->axis[0], RI.vpn ) * fogShaderDistScale * RI.currententity->scale;
- vpnNormal[1] = DotProduct( RI.currententity->axis[1], RI.vpn ) * fogShaderDistScale * RI.currententity->scale;
- vpnNormal[2] = DotProduct( RI.currententity->axis[2], RI.vpn ) * fogShaderDistScale * RI.currententity->scale;
- vpnDist = (( ( RI.viewOrigin[0] - viewtofog[0] ) * RI.vpn[0] + ( RI.viewOrigin[1] - viewtofog[1] ) * RI.vpn[1] + ( RI.viewOrigin[2] - viewtofog[2] ) * RI.vpn[2] )
- + r_colorFog->shader->fog_clearDist) * fogShaderDistScale;
-
- bArray = colorArray[0];
- if( dist < 0 )
- { // camera is inside the fog
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- {
- temp = DotProduct( vertsArray[i], vpnNormal ) - vpnDist;
- c = ( 1.0f - bound( 0, temp, 1.0f ) ) * 0xFFFF;
-
- if( alphaFog )
- {
- bArray[3] = ( bArray[3] * c ) >> 16;
- }
- else
- {
- bArray[0] = ( bArray[0] * c ) >> 16;
- bArray[1] = ( bArray[1] * c ) >> 16;
- bArray[2] = ( bArray[2] * c ) >> 16;
- }
- }
- }
- else
- {
- fogNormal[0] = DotProduct( RI.currententity->axis[0], fogPlane->normal ) * RI.currententity->scale;
- fogNormal[1] = DotProduct( RI.currententity->axis[1], fogPlane->normal ) * RI.currententity->scale;
- fogNormal[2] = DotProduct( RI.currententity->axis[2], fogPlane->normal ) * RI.currententity->scale;
- fogptype = ( fogNormal[0] == 1.0 ? PLANE_X : ( fogNormal[1] == 1.0 ? PLANE_Y : ( fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NONAXIAL ) ) );
- fogDist = fogPlane->dist - DotProduct( viewtofog, fogPlane->normal );
-
- for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
- {
- if( fogptype < 3 )
- vdist = vertsArray[i][fogptype] - fogDist;
- else
- vdist = DotProduct( vertsArray[i], fogNormal ) - fogDist;
-
- if( vdist < 0 )
- {
- temp = ( DotProduct( vertsArray[i], vpnNormal ) - vpnDist ) * vdist / ( vdist - dist );
- c = ( 1.0f - bound( 0, temp, 1.0f ) ) * 0xFFFF;
-
- if( alphaFog )
- {
- bArray[3] = ( bArray[3] * c ) >> 16;
- }
- else
- {
- bArray[0] = ( bArray[0] * c ) >> 16;
- bArray[1] = ( bArray[1] * c ) >> 16;
- bArray[2] = ( bArray[2] * c ) >> 16;
- }
- }
- }
- }
- }
-}
-
-/*
-================
-R_ShaderpassBlendmode
-================
-*/
-static int R_ShaderpassBlendmode( int passFlags )
-{
- if( passFlags & SHADERSTAGE_BLEND_REPLACE )
- return GL_REPLACE;
- if( passFlags & SHADERSTAGE_BLEND_MODULATE )
- return GL_MODULATE;
- if( passFlags & SHADERSTAGE_BLEND_ADD )
- return GL_ADD;
- if( passFlags & SHADERSTAGE_BLEND_DECAL )
- return GL_DECAL;
- return 0;
-}
-
-/*
-================
-R_SetShaderState
-================
-*/
-static void R_SetShaderState( void )
-{
- int state;
-
- // Face culling
- if( !gl_cull->integer || ( r_features & MF_NOCULL ))
- GL_Cull( 0 );
- else if( r_currentShader->flags & SHADER_CULL_FRONT )
- GL_Cull( GL_FRONT );
- else if( r_currentShader->flags & SHADER_CULL_BACK )
- GL_Cull( GL_BACK );
- else GL_Cull( 0 );
-
- state = 0;
- if( r_currentShader->flags & SHADER_POLYGONOFFSET || RI.params & RP_SHADOWMAPVIEW )
- state |= GLSTATE_OFFSET_FILL;
- if( r_currentShader->type == SHADER_FLARE )
- state |= GLSTATE_NO_DEPTH_TEST;
- r_currentShaderState = state;
-}
-
-/*
-================
-R_RenderMeshGeneric
-================
-*/
-void R_RenderMeshGeneric( void )
-{
- const ref_stage_t *pass = r_accumPasses[0];
-
- R_BindShaderpass( pass, NULL, 0 );
- R_ModifyColor( pass );
-
- if( pass->flags & SHADERSTAGE_BLEND_REPLACE )
- GL_TexEnv( GL_REPLACE );
- else
- GL_TexEnv( GL_MODULATE );
- GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ));
-
- R_FlushArrays();
-}
-
-/*
-================
-R_RenderMeshMultitextured
-================
-*/
-void R_RenderMeshMultitextured( void )
-{
- int i;
- const ref_stage_t *pass = r_accumPasses[0];
-
- R_BindShaderpass( pass, NULL, 0 );
- R_ModifyColor( pass );
-
- GL_TexEnv( GL_MODULATE );
- GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX );
-
- for( i = 1; i < r_numAccumPasses; i++ )
- {
- pass = r_accumPasses[i];
- R_BindShaderpass( pass, NULL, i );
- GL_TexEnv( R_ShaderpassBlendmode( pass->flags ) );
- }
-
- R_FlushArrays();
-}
-
-/*
-================
-R_RenderMeshCombined
-================
-*/
-void R_RenderMeshCombined( void )
-{
- int i;
- const ref_stage_t *pass = r_accumPasses[0];
-
- R_BindShaderpass( pass, NULL, 0 );
- R_ModifyColor( pass );
-
- GL_TexEnv( GL_MODULATE );
- GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX );
-
- for( i = 1; i < r_numAccumPasses; i++ )
- {
- pass = r_accumPasses[i];
- R_BindShaderpass( pass, NULL, i );
-
- if( pass->flags & ( SHADERSTAGE_BLEND_REPLACE|SHADERSTAGE_BLEND_MODULATE ))
- {
- GL_TexEnv( GL_MODULATE );
- }
- else if( pass->flags & SHADERSTAGE_BLEND_ADD )
- {
- // these modes are best set with TexEnv, Combine4 would need much more setup
- GL_TexEnv( GL_ADD );
- }
- else if( pass->flags & SHADERSTAGE_BLEND_DECAL )
- {
- // mimics Alpha-Blending in upper texture stage, but instead of multiplying the alpha-channel, they're added
- // this way it can be possible to use GL_DECAL in both texture-units, while still looking good
- // normal mutlitexturing would multiply the alpha-channel which looks ugly
- GL_TexEnv( GL_COMBINE_ARB );
- pglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );
- pglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD );
-
- pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
- pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
- pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE );
- pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA );
-
- pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB );
- pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
- pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB );
- pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA );
-
- pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE );
- pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA );
- }
- else
- {
- Com_Assert( 1 );
- }
- }
-
- R_FlushArrays();
-}
-
-/*
-================
-R_RenderMeshGLSL_Material
-================
-*/
-static void R_RenderMeshGLSL_Material( void )
-{
- int i, tcgen;
- int state;
- bool breakIntoPasses = false;
- int program, object;
- int programFeatures = 0;
- texture_t *base, *normalmap, *glossmap, *decalmap;
- 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;
- superLightStyle_t *lightStyle;
- ref_stage_t *pass = r_accumPasses[0];
-
- // handy pointers
- base = pass->textures[0];
- normalmap = pass->textures[1];
- glossmap = pass->textures[2];
- decalmap = pass->textures[3];
-
- Com_Assert( normalmap == NULL );
-
- if( normalmap->samples == 4 )
- offsetmappingScale = r_offsetmapping_scale->value * r_currentShader->offsetmapping_scale;
- else // no alpha in normalmap, don't bother with offset mapping
- offsetmappingScale = 0;
-
- if( GL_Support( R_GLSL_BRANCHING ))
- programFeatures |= PROGRAM_APPLY_BRANCHING;
- if( GL_Support( R_GLSL_NO_HALF_TYPES ))
- programFeatures |= PROGRAM_APPLY_NO_HALF_TYPES;
- if( RI.params & RP_CLIPPLANE )
- programFeatures |= PROGRAM_APPLY_CLIPPING;
-
- if( r_currentMeshBuffer->infokey > 0 )
- {
- // world surface
- int srcAlpha = (pass->flags & SHADERSTAGE_BLEND_DECAL);
-
- // CHECKTHIS: this is right ?
- srcAlpha |= (pass->glState & (GLSTATE_ALPHAFUNC|GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DSTBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA));
-
- if( !( r_offsetmapping->integer & 1 ) )
- offsetmappingScale = 0;
-
- if( r_lightmap->integer || ( r_currentDlightBits && !pass->textures[5] ) )
- {
- if( !srcAlpha )
- base = tr.whiteTexture; // white
- else
- programFeatures |= PROGRAM_APPLY_BASETEX_ALPHA_ONLY;
- }
-
- // we use multipass for dynamic lights, so bind the white texture
- // instead of base in GLSL program and add another modulative pass (diffusemap)
- if( !r_lightmap->integer && ( r_currentDlightBits && !pass->textures[5] ) )
- {
- breakIntoPasses = true;
- r_GLSLpasses[1] = *pass;
- r_GLSLpasses[1].flags = ( pass->flags & SHADERSTAGE_NOCOLORARRAY )|SHADERSTAGE_BLEND_MODULATE;
- r_GLSLpasses[1].glState = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR|((pass->glState & GLSTATE_ALPHAFUNC) ? GLSTATE_DEPTHFUNC_EQ : 0);
-
- // decal
- if( decalmap )
- {
- r_GLSLpasses[1].rgbGen.type = RGBGEN_IDENTITY;
- r_GLSLpasses[1].alphaGen.type = ALPHAGEN_IDENTITY;
-
- r_GLSLpasses[2] = *pass;
- r_GLSLpasses[2].flags = ( pass->flags & SHADERSTAGE_NOCOLORARRAY )|SHADERSTAGE_BLEND_DECAL;
- r_GLSLpasses[2].glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA|((pass->glState & GLSTATE_ALPHAFUNC) ? GLSTATE_DEPTHFUNC_EQ : 0);
- r_GLSLpasses[2].textures[0] = decalmap;
- }
-
- if( offsetmappingScale <= 0 )
- {
- r_GLSLpasses[1].program = r_GLSLpasses[2].program = NULL;
- r_GLSLpasses[1].program_type = r_GLSLpasses[2].program_type = PROGRAM_TYPE_NONE;
- }
- else
- {
- r_GLSLpasses[1].textures[2] = r_GLSLpasses[2].textures[2] = NULL; // no specular
- r_GLSLpasses[1].textures[3] = r_GLSLpasses[2].textures[3] = NULL; // no decal
- r_GLSLpasses[1].textures[6] = r_GLSLpasses[6].textures[2] = ((texture_t *)1); // HACKHACK no ambient
- }
- }
- }
- else if( ( r_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
- if( !( r_offsetmapping->integer & 4 ) )
- offsetmappingScale = 0;
- }
-
- tcgen = pass->tcgen; // store the original tcgen
-
- pass->tcgen = TCGEN_BASE;
- R_BindShaderpass( pass, base, 0 );
- if( !breakIntoPasses )
- {
- // calculate the fragment color
- R_ModifyColor( pass );
- }
- else
- { // rgbgen identity (255,255,255,255)
- r_backacc.numColors = 1;
- colorArray[0][0] = colorArray[0][1] = colorArray[0][2] = colorArray[0][3] = 255;
- }
-
- // set shaderpass state (blending, depthwrite, etc)
- state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX;
- GL_SetState( state );
-
- // don't waste time on processing GLSL programs with zero colormask
- if( RI.params & RP_SHADOWMAPVIEW )
- {
- pass->tcgen = tcgen; // restore original tcgen
- R_FlushArrays();
- return;
- }
-
- // we only send S-vectors to GPU and recalc T-vectors as cross product
- // in vertex shader
- pass->tcgen = TCGEN_SVECTORS;
- GL_Bind( 1, normalmap ); // normalmap
- GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY );
- R_VertexTCBase( pass, 1, unused );
-
- if( glossmap && r_lighting_glossintensity->value )
- {
- programFeatures |= PROGRAM_APPLY_SPECULAR;
- GL_Bind( 2, glossmap ); // gloss
- GL_SetTexCoordArrayMode( 0 );
- }
-
- if( decalmap && !breakIntoPasses )
- {
- programFeatures |= PROGRAM_APPLY_DECAL;
- GL_Bind( 3, decalmap ); // decal
- GL_SetTexCoordArrayMode( 0 );
- }
-
- if( offsetmappingScale > 0 )
- programFeatures |= r_offsetmapping_reliefmapping->integer ? PROGRAM_APPLY_RELIEFMAPPING : PROGRAM_APPLY_OFFSETMAPPING;
-
- if( r_currentMeshBuffer->infokey > 0 )
- { // world surface
- lightStyle = r_superLightStyle;
-
- // bind lightmap textures and set program's features for lightstyles
- if( r_superLightStyle && r_superLightStyle->lightmapNum[0] >= 0 )
- {
- pass->tcgen = TCGEN_LIGHTMAP;
-
- for( i = 0; i < LM_STYLES && r_superLightStyle->lightmapStyles[i] != 255; i++ )
- {
- programFeatures |= ( PROGRAM_APPLY_LIGHTSTYLE0 << i );
-
- r_lightmapStyleNum[i+4] = i;
- GL_Bind( i+4, tr.lightmapTextures[r_superLightStyle->lightmapNum[i]] ); // lightmap
- GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY );
- R_VertexTCBase( pass, i+4, unused );
- }
-
- if( i == 1 )
- {
- vec_t *rgb = r_lightStyles[r_superLightStyle->lightmapStyles[0]].rgb;
-
- // PROGRAM_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 |= PROGRAM_APPLY_FB_LIGHTMAP;
- }
- }
-
- if( !pass->textures[6] && !VectorCompare( mapConfig.ambient, vec3_origin ) )
- {
- VectorCopy( mapConfig.ambient, ambient );
- programFeatures |= PROGRAM_APPLY_AMBIENT_COMPENSATION;
- }
- }
- else
- {
- vec3_t temp;
-
- lightStyle = NULL;
- programFeatures |= PROGRAM_APPLY_DIRECTIONAL_LIGHT;
-
- if( ( r_currentMeshBuffer->sortkey & 3 ) == MB_POLY )
- {
- VectorCopy( r_polys[-r_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
- {
- // get weighted incoming direction of world and dynamic lights
- R_LightForOrigin( RI.currententity->lightingOrigin, temp, ambient, diffuse,
- RI.currententity->model ? RI.currententity->model->radius * RI.currententity->scale : 0 );
-
- if( RI.currententity->flags & EF_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
-
- program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures );
- object = R_GetProgramObject( program );
- if( object )
- {
- pglUseProgramObjectARB( object );
-
- // update uniforms
- R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, lightDir, ambient, diffuse, lightStyle,
- true, 0, 0, 0, offsetmappingScale );
-
- R_FlushArrays();
-
- pglUseProgramObjectARB( 0 );
- }
-
- if( breakIntoPasses )
- {
- unsigned int oDB = r_currentDlightBits; // HACK HACK HACK
- superLightStyle_t *oSL = r_superLightStyle;
-
- R_AccumulatePass( &r_GLSLpasses[0] ); // dynamic lighting pass
-
- if( offsetmappingScale )
- {
- r_superLightStyle = NULL;
- r_currentDlightBits = 0;
- }
-
- R_AccumulatePass( &r_GLSLpasses[1] ); // modulate (diffusemap)
-
- if( decalmap )
- R_AccumulatePass( &r_GLSLpasses[2] ); // alpha-blended decal texture
-
- if( offsetmappingScale )
- {
- r_superLightStyle = oSL;
- r_currentDlightBits = oDB;
- }
- }
-}
-
-/*
-================
-R_RenderMeshGLSL_Distortion
-================
-*/
-static void R_RenderMeshGLSL_Distortion( void )
-{
- int state, tcgen;
- int program, object;
- int programFeatures = 0;
- mat4x4_t unused;
- ref_stage_t *pass = r_accumPasses[0];
- texture_t *portaltexture1, *portaltexture2;
- bool frontPlane;
-
- if( !( RI.params & ( RP_PORTALCAPTURED|RP_PORTALCAPTURED2 )))
- return;
-
- if( GL_Support( R_GLSL_BRANCHING ))
- programFeatures |= PROGRAM_APPLY_BRANCHING;
- if( GL_Support( R_GLSL_NO_HALF_TYPES ))
- programFeatures |= PROGRAM_APPLY_NO_HALF_TYPES;
- if( RI.params & RP_CLIPPLANE )
- programFeatures |= PROGRAM_APPLY_CLIPPING;
-
- portaltexture1 = ( RI.params & RP_PORTALCAPTURED ) ? tr.portaltexture1 : tr.blackTexture;
- portaltexture2 = ( RI.params & RP_PORTALCAPTURED2 ) ? tr.portaltexture2 : tr.blackTexture;
-
- frontPlane = (PlaneDiff( RI.viewOrigin, &RI.portalPlane ) > 0 ? true : false);
-
- tcgen = pass->tcgen; // store the original tcgen
-
- R_BindShaderpass( pass, pass->textures[0], 0 ); // dudvmap
-
- // calculate the fragment color
- R_ModifyColor( pass );
-
- if( frontPlane )
- {
- if( pass->alphaGen.type != ALPHAGEN_IDENTITY )
- programFeatures |= PROGRAM_APPLY_DISTORTION_ALPHA;
- }
-
- // set shaderpass state (blending, depthwrite, etc)
- state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX;
- GL_SetState( state );
-
- if( pass->textures[1] /* && ( RI.params & RP_PORTALCAPTURED )*/ )
- {
- // eyeDot
- programFeatures |= PROGRAM_APPLY_EYEDOT;
-
- pass->tcgen = TCGEN_SVECTORS;
- GL_Bind( 1, pass->textures[1] ); // normalmap
- GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY );
- R_VertexTCBase( pass, 1, unused );
- }
-
- GL_Bind( 2, portaltexture1 ); // reflection
- GL_Bind( 3, portaltexture2 ); // refraction
-
- pass->tcgen = tcgen; // restore original tcgen
-
- // update uniforms
- program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures );
- object = R_GetProgramObject( program );
- if( object )
- {
- pglUseProgramObjectARB( object );
-
- R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL,
- frontPlane, tr.portaltexture1->width, tr.portaltexture1->height, 0, 0 );
-
- R_FlushArrays();
-
- pglUseProgramObjectARB( 0 );
- }
-}
-
-/*
-================
-R_RenderMeshGLSL_Shadowmap
-================
-*/
-static void R_RenderMeshGLSL_Shadowmap( void )
-{
- int i;
- int state;
- int program, object;
- int programFeatures = GL_Support( R_GLSL_BRANCHING ) ? PROGRAM_APPLY_BRANCHING : 0;
- ref_stage_t *pass = r_accumPasses[0];
-
- if( r_shadows_pcf->integer == 2 )
- programFeatures |= PROGRAM_APPLY_PCF2x2;
- else if( r_shadows_pcf->integer == 3 )
- programFeatures |= PROGRAM_APPLY_PCF3x3;
-
- // update uniforms
- program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures );
- object = R_GetProgramObject( program );
- if( !object )
- return;
-
- for( i = 0, r_currentCastGroup = r_shadowGroups; i < r_numShadowGroups; i++, r_currentCastGroup++ )
- {
- if( !( r_currentShadowBits & r_currentCastGroup->bit ) )
- continue;
-
- R_BindShaderpass( pass, r_currentCastGroup->depthTexture, 0 );
-
- pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB );
- pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );
-
- // calculate the fragment color
- R_ModifyColor( pass );
-
- // set shaderpass state (blending, depthwrite, etc)
- state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX;
- GL_SetState( state );
-
- pglUseProgramObjectARB( object );
-
- R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL, true,
- r_currentCastGroup->depthTexture->width, r_currentCastGroup->depthTexture->height,
- r_currentCastGroup->projDist, 0 );
-
- R_FlushArrays();
-
- pglUseProgramObjectARB( 0 );
-
- pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
- }
-}
-
-/*
-================
-R_RenderMeshGLSL_Outline
-================
-*/
-static void R_RenderMeshGLSL_Outline( void )
-{
- int faceCull;
- int state;
- int program, object;
- int programFeatures = GL_Support( R_GLSL_BRANCHING ) ? PROGRAM_APPLY_BRANCHING : 0;
- ref_stage_t *pass = r_accumPasses[0];
-
- if( RI.params & RP_CLIPPLANE )
- programFeatures |= PROGRAM_APPLY_CLIPPING;
-
- // update uniforms
- program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures );
- object = R_GetProgramObject( program );
- if( !object )
- return;
-
- faceCull = glState.faceCull;
- GL_Cull( GL_BACK );
-
- GL_SelectTexture( 0 );
- GL_SetTexCoordArrayMode( 0 );
-
- // calculate the fragment color
- R_ModifyColor( pass );
-
- // set shaderpass state (blending, depthwrite, etc)
- state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX;
- GL_SetState( state );
-
- pglUseProgramObjectARB( object );
-
- R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL, true,
- 0, 0, RI.currententity->outlineHeight * r_outlines_scale->value, 0 );
-
- R_FlushArrays();
-
- pglUseProgramObjectARB( 0 );
-
- GL_Cull( faceCull );
-}
-
-/*
-================
-R_RenderMeshGLSLProgrammed
-================
-*/
-static void R_RenderMeshGLSLProgrammed( void )
-{
- const ref_stage_t *pass = ( ref_stage_t * )r_accumPasses[0];
-
- switch( pass->program_type )
- {
- case PROGRAM_TYPE_MATERIAL:
- R_RenderMeshGLSL_Material();
- break;
- case PROGRAM_TYPE_DISTORTION:
- R_RenderMeshGLSL_Distortion();
- break;
- case PROGRAM_TYPE_SHADOWMAP:
- R_RenderMeshGLSL_Shadowmap();
- break;
- case PROGRAM_TYPE_OUTLINE:
- R_RenderMeshGLSL_Outline ();
- break;
- default:
- MsgDev( D_WARN, "Unknown GLSL program type %i\n", pass->program_type );
- break;
- }
-}
-
-/*
-================
-R_RenderAccumulatedPasses
-================
-*/
-static void R_RenderAccumulatedPasses( void )
-{
- const ref_stage_t *pass = r_accumPasses[0];
-
- R_CleanUpTextureUnits( r_numAccumPasses );
-
- if( pass->program )
- {
- r_numAccumPasses = 0;
- R_RenderMeshGLSLProgrammed();
- return;
- }
- if( pass->flags & SHADERSTAGE_DLIGHT )
- {
- r_numAccumPasses = 0;
- R_AddDynamicLights( r_currentDlightBits, r_currentShaderState | ( pass->glState & r_currentShaderPassMask ));
- return;
- }
- if( pass->flags & SHADERSTAGE_STENCILSHADOW )
- {
- r_numAccumPasses = 0;
- R_PlanarShadowPass( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ));
- return;
- }
-
- if( r_numAccumPasses == 1 )
- R_RenderMeshGeneric();
- else if( GL_Support( R_COMBINE_EXT ))
- R_RenderMeshCombined();
- else
- R_RenderMeshMultitextured();
-
- r_numAccumPasses = 0;
-}
-
-/*
-================
-R_AccumulatePass
-================
-*/
-static void R_AccumulatePass( ref_stage_t *pass )
-{
- bool accumulate, renderNow;
- const ref_stage_t *prevPass;
-
- // for depth texture we render light's view to, ignore passes that do not write into depth buffer
- if( ( RI.params & RP_SHADOWMAPVIEW ) && !( pass->glState & GLSTATE_DEPTHWRITE ))
- return;
-
- // see if there are any free texture units
- renderNow = ( pass->flags & ( SHADERSTAGE_DLIGHT|SHADERSTAGE_STENCILSHADOW ) ) || pass->program;
- accumulate = ( r_numAccumPasses < glConfig.max_texture_units ) && !renderNow;
-
- if( accumulate )
- {
- if( !r_numAccumPasses )
- {
- r_accumPasses[r_numAccumPasses++] = pass;
- return;
- }
-
- // ok, we've got several passes, diff against the previous
- prevPass = r_accumPasses[r_numAccumPasses-1];
-
- // see if depthfuncs and colors are good
- if(
- (( prevPass->glState ^ pass->glState ) & GLSTATE_DEPTHFUNC_EQ ) ||
- ( pass->glState & GLSTATE_ALPHAFUNC ) ||
- ( pass->rgbGen.type != RGBGEN_IDENTITY ) ||
- ( pass->alphaGen.type != ALPHAGEN_IDENTITY ) ||
- ( ( prevPass->glState & GLSTATE_ALPHAFUNC ) && !( pass->glState & GLSTATE_DEPTHFUNC_EQ ))
- )
- accumulate = false;
-
- // see if blendmodes are good
- if( accumulate )
- {
- int mode, prevMode;
-
- mode = R_ShaderpassBlendmode( pass->flags );
- if( mode )
- {
- prevMode = R_ShaderpassBlendmode( prevPass->flags );
-
- if( GL_Support( R_COMBINE_EXT ))
- {
- if( prevMode == GL_REPLACE )
- accumulate = ( mode == GL_ADD ) ? GL_Support( R_TEXTURE_ENV_ADD_EXT ) : true;
- else if( prevMode == GL_ADD )
- accumulate = ( mode == GL_ADD ) && GL_Support( R_TEXTURE_ENV_ADD_EXT );
- else if( prevMode == GL_MODULATE )
- accumulate = ( mode == GL_MODULATE || mode == GL_REPLACE );
- else
- accumulate = false;
- }
- else /* if( GL_Support( R_ARB_MULTITEXTURE ))*/
- {
- if( prevMode == GL_REPLACE )
- accumulate = ( mode == GL_ADD ) ? GL_Support( R_TEXTURE_ENV_ADD_EXT ) : ( mode != GL_DECAL );
- else if( prevMode == GL_ADD )
- accumulate = ( mode == GL_ADD ) && GL_Support( R_TEXTURE_ENV_ADD_EXT );
- else if( prevMode == GL_MODULATE )
- accumulate = ( mode == GL_MODULATE || mode == GL_REPLACE );
- else
- accumulate = false;
- }
- }
- else
- {
- accumulate = false;
- }
- }
- }
-
- // no, failed to accumulate
- if( !accumulate )
- {
- if( r_numAccumPasses )
- R_RenderAccumulatedPasses();
- }
-
- r_accumPasses[r_numAccumPasses++] = pass;
- if( renderNow )
- R_RenderAccumulatedPasses();
-}
-
-/*
-================
-R_SetupLightmapMode
-================
-*/
-void R_SetupLightmapMode( void )
-{
- r_lightmapPasses[0].tcgen = TCGEN_LIGHTMAP;
- r_lightmapPasses[0].rgbGen.type = RGBGEN_IDENTITY;
- r_lightmapPasses[0].alphaGen.type = ALPHAGEN_IDENTITY;
- r_lightmapPasses[0].flags &= ~SHADERSTAGE_BLENDMODE;
- r_lightmapPasses[0].glState &= ~( GLSTATE_ALPHAFUNC|GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK|GLSTATE_DEPTHFUNC_EQ );
- r_lightmapPasses[0].flags |= SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE;
-// r_lightmapPasses[0].glState |= GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ZERO;
- if( r_lightmap->integer ) r_lightmapPasses[0].glState |= GLSTATE_DEPTHWRITE;
-}
-
-/*
-================
-R_RenderMeshBuffer
-================
-*/
-void R_RenderMeshBuffer( const meshbuffer_t *mb )
-{
- int i;
- msurface_t *surf;
- ref_stage_t *pass;
- mfog_t *fog;
-
- if( !r_backacc.numVerts || !r_backacc.numElems )
- {
- R_ClearArrays();
- return;
- }
-
- surf = mb->infokey > 0 ? &r_worldbrushmodel->surfaces[mb->infokey-1] : NULL;
- if( surf )
- r_superLightStyle = &r_superLightStyles[surf->superLightStyle];
- else
- r_superLightStyle = NULL;
- r_currentMeshBuffer = mb;
-
- MB_NUM2SHADER( mb->shaderkey, r_currentShader );
-
- if( glState.in2DMode )
- {
- r_currentShaderTime = Sys_DoubleTime();
- }
- else
- {
- r_currentShaderTime = (double)RI.refdef.time;
- if( RI.currententity )
- {
- r_currentShaderTime -= (double)RI.currententity->shaderTime;
- if( r_currentShaderTime < 0 ) r_currentShaderTime = 0;
- }
- }
-
- if( !r_triangleOutlines )
- R_SetShaderState();
-
- if( r_currentShader->numDeforms )
- R_DeformVertices();
-
- if( r_features & MF_KEEPLOCK )
- r_backacc.c_totalKeptLocks++;
- else
- R_UnlockArrays();
-
- if( r_triangleOutlines )
- {
- R_LockArrays( r_backacc.numVerts );
-
- if( RI.params & RP_TRISOUTLINES )
- R_DrawTriangles();
- if( RI.params & RP_SHOWNORMALS )
- R_DrawNormals();
-
- R_ClearArrays();
- return;
- }
-
- // extract the fog volume number from sortkey
- if( !r_worldmodel )
- fog = NULL;
- else
- MB_NUM2FOG( mb->sortkey, fog );
- if( fog && !fog->shader )
- fog = NULL;
-
- // can we fog the geometry with alpha texture?
- r_texFog = ( fog && ( ( r_currentShader->sort <= SORT_ALPHATEST &&
- ( r_currentShader->flags & (SHADER_DEPTHWRITE|SHADER_SKYPARMS))) || r_currentShader->fog_dist ) ) ? fog : NULL;
-
- // check if the fog volume is present but we can't use alpha texture
- r_colorFog = ( fog && !r_texFog ) ? fog : NULL;
-
- if( r_currentShader->type == SHADER_FLARE )
- r_currentDlightBits = 0;
- else
- r_currentDlightBits = surf ? mb->dlightbits : 0;
-
- r_currentShadowBits = mb->shadowbits & RI.shadowBits;
-
- R_LockArrays( r_backacc.numVerts );
-
- // accumulate passes for dynamic merging
- for( i = 0, pass = r_currentShader->stages; i < r_currentShader->num_stages; i++, pass++ )
- {
- if( !pass->program )
- {
- if( pass->flags & SHADERSTAGE_LIGHTMAP )
- {
- int j, k, l, u;
-
- // no valid lightmaps, goodbye
- if( !r_superLightStyle || r_superLightStyle->lightmapNum[0] < 0 || r_superLightStyle->lightmapStyles[0] == 255 )
- continue;
-
- // try to apply lightstyles
- if(( !( pass->glState & (GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK)) || ( pass->flags & SHADERSTAGE_BLEND_MODULATE )) && ( pass->rgbGen.type == RGBGEN_IDENTITY ) && ( pass->alphaGen.type == ALPHAGEN_IDENTITY ))
- {
- vec3_t colorSum, color;
-
- // the first pass is always GL_MODULATE or GL_REPLACE
- // other passes are GL_ADD
- r_lightmapPasses[0] = *pass;
-
- for( j = 0, l = 0, u = 0; j < LM_STYLES && r_superLightStyle->lightmapStyles[j] != 255; j++ )
- {
- VectorCopy( r_lightStyles[r_superLightStyle->lightmapStyles[j]].rgb, colorSum );
- VectorClear( color );
-
- for( ; ; l++ )
- {
- for( k = 0; k < 3; k++ )
- {
- colorSum[k] -= color[k];
- color[k] = bound( 0, colorSum[k], 1 );
- }
-
- if( l )
- {
- if( !color[0] && !color[1] && !color[2] )
- break;
- if( l == MAX_TEXTURE_UNITS+1 )
- r_lightmapPasses[0] = r_lightmapPasses[1];
- u = l % ( MAX_TEXTURE_UNITS+1 );
- }
-
- if( VectorCompare( color, colorWhite ) )
- {
- r_lightmapPasses[u].rgbGen.type = RGBGEN_IDENTITY;
- }
- else
- {
- if( !l )
- {
- r_lightmapPasses[0].flags &= ~SHADERSTAGE_BLENDMODE;
- r_lightmapPasses[0].flags |= SHADERSTAGE_BLEND_MODULATE;
- }
- r_lightmapPasses[u].rgbGen.type = RGBGEN_CONST;
- VectorCopy( color, r_lightmapPasses[u].rgbGen.args );
- }
-
- if( r_lightmap->integer && !l )
- R_SetupLightmapMode();
- R_AccumulatePass( &r_lightmapPasses[u] );
- r_lightmapStyleNum[r_numAccumPasses - 1] = j;
- }
- }
- }
- else
- {
- if( r_lightmap->integer )
- {
- R_SetupLightmapMode();
- pass = r_lightmapPasses;
- }
- R_AccumulatePass( pass );
- r_lightmapStyleNum[r_numAccumPasses - 1] = 0;
- }
- continue;
- }
- else if( r_lightmap->integer && ( r_currentShader->flags & SHADER_HASLIGHTMAP ))
- continue;
- if(( pass->flags & SHADERSTAGE_PORTALMAP ) && !( RI.params & RP_PORTALCAPTURED ))
- continue;
- if(( pass->flags & SHADERSTAGE_DETAIL ) && !r_detailtextures->integer )
- continue;
- if(( pass->flags & SHADERSTAGE_DLIGHT ) && !r_currentDlightBits )
- continue;
- }
-
- R_AccumulatePass( pass );
- }
-
- // accumulate dynamic lights pass and fog pass if any
- if( r_currentDlightBits && !( r_currentShader->flags & SHADER_NO_MODULATIVE_DLIGHTS ))
- {
- if( !r_lightmap->integer || !( r_currentShader->flags & SHADER_HASLIGHTMAP ))
- R_AccumulatePass( &r_dlightsPass );
- }
-
- if( r_currentShadowBits && ( r_currentShader->sort >= SORT_OPAQUE ) && ( r_currentShader->sort <= SORT_ALPHATEST ))
- R_AccumulatePass( &r_GLSLpasses[3] );
-
- if( GL_Support( R_SHADER_GLSL100_EXT ) && RI.currententity && RI.currententity->outlineHeight && r_outlines_scale->value > 0
- && ( r_currentShader->sort == SORT_OPAQUE ) && ( r_currentShader->flags & SHADER_CULL_FRONT ) )
- R_AccumulatePass( &r_GLSLpassOutline );
-
- if( r_texFog && r_texFog->shader )
- {
- r_fogPass.textures[0] = tr.fogTexture;
- if( !r_currentShader->num_stages || r_currentShader->fog_dist || ( r_currentShader->flags & SHADER_SKYPARMS ) )
- r_fogPass.glState &= ~GLSTATE_DEPTHFUNC_EQ;
- else r_fogPass.glState |= GLSTATE_DEPTHFUNC_EQ;
- R_AccumulatePass( &r_fogPass );
- }
-
- // flush any remaining passes
- if( r_numAccumPasses )
- R_RenderAccumulatedPasses();
-
- R_ClearArrays();
-
- pglMatrixMode( GL_MODELVIEW );
-}
-
-/*
-================
-R_BackendCleanUpTextureUnits
-================
-*/
-void R_BackendCleanUpTextureUnits( void )
-{
- R_CleanUpTextureUnits( 1 );
-
- GL_LoadIdentityTexMatrix();
- pglMatrixMode( GL_MODELVIEW );
-
- GL_DisableAllTexGens();
- GL_SetTexCoordArrayMode( 0 );
-}
-
-/*
-================
-R_BackendSetPassMask
-================
-*/
-void R_BackendSetPassMask( int mask )
-{
- r_currentShaderPassMask = mask;
-}
-
-/*
-================
-R_BackendResetPassMask
-================
-*/
-void R_BackendResetPassMask( void )
-{
- r_currentShaderPassMask = GLSTATE_MASK;
-}
-
-/*
-================
-R_BackendBeginTriangleOutlines
-================
-*/
-void R_BackendBeginTriangleOutlines( void )
-{
- r_triangleOutlines = true;
- pglColor4fv( colorWhite );
-
- GL_Cull( 0 );
- GL_SetState( GLSTATE_NO_DEPTH_TEST );
- pglDisable( GL_TEXTURE_2D );
- pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
-}
-
-/*
-================
-R_BackendEndTriangleOutlines
-================
-*/
-void R_BackendEndTriangleOutlines( void )
-{
- r_triangleOutlines = false;
- pglColor4fv( colorWhite );
- GL_SetState( 0 );
- pglEnable( GL_TEXTURE_2D );
- pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
-}
-
-/*
-================
-R_SetColorForOutlines
-================
-*/
-static _inline void R_SetColorForOutlines( void )
-{
- int type = r_currentMeshBuffer->sortkey & 3;
-
- switch( type )
- {
- case MB_MODEL:
- if( r_currentMeshBuffer->infokey < 0 )
- pglColor4fv( colorRed );
- else
- pglColor4fv( colorWhite );
- break;
- case MB_SPRITE:
- pglColor4fv( colorBlue );
- break;
- case MB_POLY:
- pglColor4fv( colorGreen );
- break;
- }
-}
-
-/*
-================
-R_DrawTriangles
-================
-*/
-static void R_DrawTriangles( void )
-{
- if( r_showtris->integer == 2 )
- R_SetColorForOutlines();
-
- if( GL_Support( R_DRAW_RANGEELEMENTS_EXT ))
- pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
- else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
-}
-
-/*
-================
-R_DrawNormals
-================
-*/
-static void R_DrawNormals( void )
-{
- unsigned int i;
-
- if( r_shownormals->integer == 2 )
- R_SetColorForOutlines();
-
- pglBegin( GL_LINES );
- for( i = 0; i < r_backacc.numVerts; i++ )
- {
- pglVertex3fv( vertsArray[i] );
- pglVertex3f( vertsArray[i][0] + normalsArray[i][0], vertsArray[i][1] + normalsArray[i][1], vertsArray[i][2] + normalsArray[i][2] );
- }
- pglEnd();
-}
-
-static void R_DrawLine( int color, int numpoints, const float *points, const int *elements )
-{
- int i = numpoints - 1;
- vec3_t p0, p1;
-
- VectorSet( p0, points[i*3+0], points[i*3+1], points[i*3+2] );
- if( r_physbdebug->integer == 1 ) ConvertPositionToGame( p0 );
-
- for( i = 0; i < numpoints; i++ )
- {
- VectorSet( p1, points[i*3+0], points[i*3+1], points[i*3+2] );
- if( r_physbdebug->integer == 1 ) ConvertPositionToGame( p1 );
-
- pglColor4fv( UnpackRGBA( color ));
- pglVertex3fv( p0 );
- pglVertex3fv( p1 );
-
- VectorCopy( p1, p0 );
- }
-}
-
-/*
-================
-R_DrawPhysDebug
-================
-*/
-void R_DrawPhysDebug( void )
-{
- if( r_physbdebug->integer )
- {
- // physic debug
- pglLoadMatrixf( RI.worldviewMatrix );
- pglBegin( GL_LINES );
- ri.ShowCollision( R_DrawLine );
- pglEnd();
- }
-}
\ No newline at end of file
diff --git a/render/r_draw.c b/render/r_draw.c
index c4570753..34f58c2c 100644
--- a/render/r_draw.c
+++ b/render/r_draw.c
@@ -56,6 +56,7 @@ void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, f
}
}
+ tr.iRenderMode = glState.draw_rendermode;
pic_mbuffer.infokey -= 4;
pic_mbuffer.shaderkey = shader->sortkey;
diff --git a/render/r_local.h b/render/r_local.h
index 8f3819ec..b5bb63cc 100644
--- a/render/r_local.h
+++ b/render/r_local.h
@@ -759,6 +759,7 @@ enum
// #define SHADERPASS_DSTBLEND_MASK (((GLSTATE_DSTBLEND_DST_ALPHA)<<1)-GLSTATE_DSTBLEND_ZERO)
#define GLSTATE_DSTBLEND_MASK 0xF0
+#define GLSTATE_BLENDFUNC ( GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK )
#define GLSTATE_ALPHAFUNC ( GLSTATE_AFUNC_GT0|GLSTATE_AFUNC_LT128|GLSTATE_AFUNC_GE128 )
typedef struct
diff --git a/render/r_shader.c b/render/r_shader.c
index d0d62bab..b887fb32 100644
--- a/render/r_shader.c
+++ b/render/r_shader.c
@@ -92,8 +92,8 @@ static void R_LoadTable( const char *name, tableFlags_t flags, size_t size, floa
Host_Error( "R_LoadTable: MAX_TABLES limit exceeds\n" );
// fill it in
- r_tables[r_numTables++] = table = Mem_Alloc( r_shaderpool, sizeof( table_t ));
- com.strncpy( table->name, name, sizeof( table->name ));
+ table = r_tables[r_numTables++] = Mem_Alloc( r_shaderpool, sizeof( table_t ));
+ table->name = Shader_CopyString( name );
table->index = r_numTables - 1;
table->flags = flags;
table->size = size;
@@ -274,7 +274,7 @@ static bool R_ParseTable( script_t *script, tableFlags_t flags )
R_LookupTable
=================
*/
-static float R_LookupTable( int tableIndex, float index )
+float R_LookupTable( int tableIndex, float index )
{
table_t *table;
float frac, value;
@@ -308,6 +308,27 @@ static float R_LookupTable( int tableIndex, float index )
return value;
}
+/*
+=================
+R_GetTableByHandle
+=================
+*/
+float *R_GetTableByHandle( int tableIndex )
+{
+ table_t *table;
+
+ if( tableIndex < 0 || tableIndex >= r_numTables )
+ {
+ MsgDev( D_ERROR, "R_GetTableByHandle: out of range\n" );
+ return NULL;
+ }
+ table = r_tables[tableIndex];
+
+ if( !table ) return NULL;
+ return table->values;
+}
+
+
/*
=======================================================================
@@ -637,10 +658,13 @@ static bool Shader_ParseSkySides( script_t *script, ref_shader_t *shader, ref_sh
static bool Shader_ParseFunc( script_t *script, waveFunc_t *func, ref_shader_t *shader )
{
token_t tok;
+ table_t *tb;
if( !Com_ReadToken( script, false, &tok ))
return false;
+ func->tableIndex = -1;
+
if( !com.stricmp( tok.string, "0" )) func->type = WAVEFORM_SIN;
else if( !com.stricmp( tok.string, "sin" )) func->type = WAVEFORM_SIN;
else if( !com.stricmp( tok.string, "triangle" )) func->type = WAVEFORM_TRIANGLE;
@@ -649,9 +673,18 @@ static bool Shader_ParseFunc( script_t *script, waveFunc_t *func, ref_shader_t *
else if( !com.stricmp( tok.string, "inverseSawtooth" )) func->type = WAVEFORM_INVERSESAWTOOTH;
else if( !com.stricmp( tok.string, "noise" )) func->type = WAVEFORM_NOISE;
else
- {
- MsgDev( D_WARN, "unknown waveform '%s' in shader '%s', defaulting to sin\n", tok.string, shader->name );
- func->type = WAVEFORM_SIN;
+ { // check for custom table
+ tb = R_FindTable( tok.string );
+ if( tb )
+ {
+ func->type = WAVEFORM_TABLE;
+ func->tableIndex = tb->index;
+ }
+ else
+ {
+ MsgDev( D_WARN, "unknown waveform '%s' in shader '%s', defaulting to sin\n", tok.string, shader->name );
+ func->type = WAVEFORM_SIN;
+ }
}
if( !Shader_ParseVector( script, func->args, 4 ))
@@ -2065,6 +2098,7 @@ static bool Shaderpass_TcMod( ref_shader_t *shader, ref_stage_t *pass, script_t
}
tcMod->args[0] = func.type;
+ tcMod->args[5] = func.tableIndex;
for( i = 1; i < 5; i++ )
tcMod->args[i] = func.args[i-1];
tcMod->type = TCMOD_STRETCH;
@@ -2352,7 +2386,10 @@ void R_ShaderList_f( void )
Msg( "?? %i", shader->type );
break;
}
- Msg( " %s\n", shader->name );
+ Msg( " %s", shader->name );
+ if( shader->flags & SHADER_DEFAULTED )
+ Msg( " DEFAULTED\n" );
+ else Msg( "\n" );
shaderCount++;
}
@@ -3504,6 +3541,7 @@ static ref_shader_t *Shader_CreateDefault( ref_shader_t *shader, int type, int a
// calculate sortkey
shader->sortkey = Shader_Sortkey( shader, shader->sort );
+ shader->flags |= SHADER_DEFAULTED;
// add to hash table
hashKey = Com_HashKey( shortname, SHADERS_HASH_SIZE );
diff --git a/render/r_shader.h b/render/r_shader.h
index 71ddad74..d9d71fad 100644
--- a/render/r_shader.h
+++ b/render/r_shader.h
@@ -70,6 +70,7 @@ typedef enum
SHADER_PORTAL_CAPTURE1 = BIT(15),
SHADER_PORTAL_CAPTURE2 = BIT(16),
SHADER_RENDERMODE = BIT(17),
+ SHADER_DEFAULTED = BIT(18),
SHADER_PORTAL_CAPTURE = (SHADER_PORTAL_CAPTURE1|SHADER_PORTAL_CAPTURE1),
SHADER_CULL = (SHADER_CULL_FRONT|SHADER_CULL_BACK)
} shaderFlags_t;
@@ -121,7 +122,8 @@ typedef enum
WAVEFORM_SAWTOOTH,
WAVEFORM_INVERSESAWTOOTH,
WAVEFORM_NOISE,
- WAVEFORM_CONSTANT
+ WAVEFORM_CONSTANT,
+ WAVEFORM_TABLE // custom table
} waveForm_t;
// RGB colors generation
@@ -237,6 +239,7 @@ typedef struct table_s
typedef struct
{
waveForm_t type; // SHADER_FUNC enum
+ uint tableIndex; // valid only for WAVEFORM_TABLE
float args[4]; // offset, amplitude, phase_offset, rate
} waveFunc_t;
@@ -333,6 +336,8 @@ ref_shader_t *R_LoadShader( const char *name, int type, bool forceDefault, int a
// misc utilities
void R_ShaderFreeUnused( void );
+float R_LookupTable( int tableIndex, float index );
+float *R_GetTableByHandle( int tableIndex );
void Shader_TouchImages( ref_shader_t *shader, bool free_unused );
void R_ShaderSetSpriteTexture( texture_t *mipTex );
void R_ShaderSetRenderMode( kRenderMode_t mode );
diff --git a/render/r_skm.c b/render/r_skm.c
deleted file mode 100644
index 0cb023a1..00000000
--- a/render/r_skm.c
+++ /dev/null
@@ -1,1430 +0,0 @@
-/*
-Copyright (C) 2002-2007 Victor Luchits
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-// r_skm.c: skeletal animation model format
-
-#include "r_local.h"
-#include "mathlib.h"
-#include "quatlib.h"
-#include "byteorder.h"
-
-static mesh_t skm_mesh;
-
-static vec3_t skm_mins;
-static vec3_t skm_maxs;
-static float skm_radius;
-char *COM_ParseExt( const char **data_p, bool nl );
-
-/*
-==============================================================================
-
-SKM MODELS
-
-==============================================================================
-*/
-
-/*
-=================
-Mod_LoadSkeletalPose
-=================
-*/
-void Mod_LoadSkeletalPose( char *name, ref_model_t *mod, void *buffer )
-{
- unsigned int i, j, k;
- mskmodel_t *poutmodel;
- dskpheader_t *pinmodel;
- dskpbone_t *pinbone;
- mskbone_t *poutbone;
- dskpframe_t *pinframe;
- mskframe_t *poutframe;
- dskpbonepose_t *pinbonepose;
- bonepose_t *poutbonepose;
- byte *membuffer;
- size_t memBufferSize;
-
- if( LittleLong(*(uint *)buffer) != SKMHEADER )
- Host_Error( "uknown fileid for %s\n", name );
-
- pinmodel = ( dskpheader_t * )buffer;
- poutmodel = ( mskmodel_t * )mod->extradata;
-
- if( LittleLong( pinmodel->type ) != SKM_MODELTYPE )
- Host_Error( "%s has wrong type number (%i should be %i)\n",
- name, LittleLong( pinmodel->type ), SKM_MODELTYPE );
- if( LittleLong( pinmodel->filesize ) > SKM_MAX_FILESIZE )
- Host_Error( "%s has has wrong filesize (%i should be less than %i)\n",
- name, LittleLong( pinmodel->filesize ), SKM_MAX_FILESIZE );
- if( LittleLong( pinmodel->num_bones ) != poutmodel->numbones )
- Host_Error( "%s has has wrong number of bones (%i should be less than %i)\n",
- name, LittleLong( pinmodel->num_bones ), poutmodel->numbones );
-
- poutmodel->numframes = LittleLong( pinmodel->num_frames );
- if( poutmodel->numframes <= 0 )
- Host_Error( "%s has no frames\n", name );
- else if( poutmodel->numframes > SKM_MAX_FRAMES )
- Host_Error( "%s has too many frames\n", name );
-
- memBufferSize = 0;
- memBufferSize += sizeof( mskbone_t ) * poutmodel->numbones;
- memBufferSize += sizeof( mskframe_t ) * poutmodel->numframes;
- memBufferSize += sizeof( bonepose_t ) * poutmodel->numbones * poutmodel->numframes;
- membuffer = Mod_Malloc( mod, memBufferSize );
-
- pinbone = ( dskpbone_t * )( ( byte * )pinmodel + LittleLong( pinmodel->ofs_bones ) );
- poutbone = poutmodel->bones = ( mskbone_t * )membuffer; membuffer += sizeof( mskbone_t ) * poutmodel->numbones;
-
- for( i = 0; i < poutmodel->numbones; i++, pinbone++, poutbone++ )
- {
- com.strncpy( poutbone->name, pinbone->name, SKM_MAX_NAME );
- poutbone->flags = LittleLong( pinbone->flags );
- poutbone->parent = LittleLong( pinbone->parent );
- }
-
- pinframe = ( dskpframe_t * )( ( byte * )pinmodel + LittleLong( pinmodel->ofs_frames ) );
- poutframe = poutmodel->frames = ( mskframe_t * )membuffer; membuffer += sizeof( mskframe_t ) * poutmodel->numframes;
-
- for( i = 0; i < poutmodel->numframes; i++, pinframe++, poutframe++ )
- {
- pinbonepose = ( dskpbonepose_t * )( ( byte * )pinmodel + LittleLong( pinframe->ofs_bonepositions ) );
- poutbonepose = poutframe->boneposes = ( bonepose_t * )membuffer; membuffer += sizeof( bonepose_t ) * poutmodel->numbones;
-
- ClearBounds( poutframe->mins, poutframe->maxs );
-
- for( j = 0; j < poutmodel->numbones; j++, pinbonepose++, poutbonepose++ )
- {
- for( k = 0; k < 4; k++ )
- poutbonepose->quat[k] = LittleFloat( pinbonepose->quat[k] );
- for( k = 0; k < 3; k++ )
- poutbonepose->origin[k] = LittleFloat( pinbonepose->origin[k] );
- }
- }
-}
-
-/*
-=================
-Mod_LoadSkeletalModel
-=================
-*/
-void Mod_LoadSkeletalModel( ref_model_t *mod, ref_model_t *parent, const void *buffer )
-{
- unsigned int i, j, k, l, m;
- vec_t *v, *n;
- dskmheader_t *pinmodel;
- mskmodel_t *poutmodel;
- dskmmesh_t *pinmesh;
- mskmesh_t *poutmesh;
- dskmvertex_t *pinskmvert;
- dskmbonevert_t *pinbonevert;
- dskmcoord_t *pinstcoord;
- vec2_t *poutstcoord;
- elem_t *pintris, *pouttris;
- unsigned int *pinreferences, *poutreferences;
- bonepose_t *bp, *basepose, *poutbonepose;
- mskframe_t *pframe;
- vec3_t ebbox = { 0, 0, 0 };
- size_t alignment = 16;
- byte *buf;
-
- pinmodel = ( dskmheader_t * )buffer;
-
- if( LittleLong( pinmodel->type ) != SKM_MODELTYPE )
- Host_Error( "%s has wrong type number (%i should be %i)\n",
- mod->name, LittleLong( pinmodel->type ), SKM_MODELTYPE );
- if( LittleLong( pinmodel->filesize ) > SKM_MAX_FILESIZE )
- Host_Error( "%s has has wrong filesize (%i should be less than %i)\n",
- mod->name, LittleLong( pinmodel->filesize ), SKM_MAX_FILESIZE );
-
- poutmodel = mod->extradata = Mod_Malloc( mod, sizeof( mskmodel_t ) );
- poutmodel->nummeshes = LittleLong( pinmodel->num_meshes );
- if( poutmodel->nummeshes <= 0 )
- Host_Error( "%s has no meshes\n", mod->name );
- else if( poutmodel->nummeshes > SKM_MAX_MESHES )
- Host_Error( "%s has too many meshes\n", mod->name );
-
- poutmodel->numbones = LittleLong( pinmodel->num_bones );
- if( poutmodel->numbones <= 0 )
- Host_Error( "%s has no bones\n", mod->name );
- else if( poutmodel->numbones > SKM_MAX_BONES )
- Host_Error( "%s has too many bones\n", mod->name );
-
- // if we have a parent model then we are a LOD file and should use parent model's pose data
- if( parent )
- {
- mskmodel_t *parentskm = ( mskmodel_t * )parent->extradata;
-
- if( !parentskm )
- Host_Error( "%s is not a LOD model for %s\n",
- mod->name, parent->name );
-
- if( poutmodel->numbones != parentskm->numbones )
- Host_Error( "%s has has wrong number of bones (%i should be less than %i)\n",
- mod->name, poutmodel->numbones, parentskm->numbones );
-
- poutmodel->bones = parentskm->bones;
- poutmodel->frames = parentskm->frames;
- poutmodel->numframes = parentskm->numframes;
- }
- else
- { // load a config file
- string temp;
- string poseName, configName;
-
- com.strcpy( temp, mod->name );
- FS_StripExtension( temp );
- com.snprintf( configName, sizeof( configName ), "%s.cfg", temp );
-
- memset( poseName, 0, sizeof( poseName ) );
-
- buf = FS_LoadFile( configName, NULL );
- if( !buf )
- {
- com.snprintf( poseName, sizeof( poseName ), "%s.skp", temp );
- }
- else
- {
- char *ptr, *token;
-
- ptr = ( char * )buf;
- while( ptr )
- {
- token = COM_ParseExt( &ptr, true );
- if( !token[0] )
- break;
-
- if( !com.stricmp( token, "import" ) )
- {
- token = COM_ParseExt( &ptr, false );
- com.strcpy( temp, token );
- FS_StripExtension( temp );
- com.snprintf( poseName, sizeof( poseName ), "%s.skp", temp );
- break;
- }
- }
-
- Mem_Free( buf );
- }
-
- buf = FS_LoadFile( poseName, NULL );
- if( !buf )
- Host_Error( "Could not find pose file for %s\n", mod->name );
-
- Mod_LoadSkeletalPose( poseName, mod, buf );
-
- Mem_Free( buf );
- }
-
- // clear model's bounding box
- mod->radius = 0;
- ClearBounds( mod->mins, mod->maxs );
-
- // reconstruct frame 0 bone poses and inverse bone poses
- basepose = Mod_Malloc( mod, sizeof( *basepose ) * poutmodel->numbones );
- poutmodel->invbaseposes = Mod_Malloc( mod, sizeof( *poutmodel->invbaseposes ) * poutmodel->numbones );
-
- for( i = 0, bp = basepose; i < poutmodel->numbones; i++, bp++ )
- {
- int parent = poutmodel->bones[i].parent;
- bonepose_t *obp = &poutmodel->frames[0].boneposes[i], *ibp = &poutmodel->invbaseposes[i];
-
- if( parent >= 0 )
- Quat_ConcatTransforms( basepose[parent].quat, basepose[parent].origin,
- obp->quat, obp->origin, bp->quat, bp->origin );
- else
- *bp = *obp;
-
- // reconstruct invserse bone pose
- Quat_Conjugate( bp->quat, ibp->quat );
- Quat_TransformVector( ibp->quat, bp->origin, ibp->origin );
- VectorNegate( ibp->origin, ibp->origin );
- }
-
- pinmesh = ( dskmmesh_t * )( ( byte * )pinmodel + LittleLong( pinmodel->ofs_meshes ) );
- poutmesh = poutmodel->meshes = Mod_Malloc( mod, sizeof( mskmesh_t ) * poutmodel->nummeshes );
-
- for( i = 0; i < poutmodel->nummeshes; i++, pinmesh++, poutmesh++ )
- {
- float *influences;
- unsigned int size, *bones;
-
- poutmesh->numverts = LittleLong( pinmesh->num_verts );
- if( poutmesh->numverts <= 0 )
- Host_Error("mesh %i in model %s has no vertexes\n", i, mod->name );
- else if( poutmesh->numverts > SKM_MAX_VERTS )
- Host_Error("mesh %i in model %s has too many vertexes", i, mod->name );
-
- poutmesh->numtris = LittleLong( pinmesh->num_tris );
- if( poutmesh->numtris <= 0 )
- Host_Error("mesh %i in model %s has no indices\n", i, mod->name );
- else if( poutmesh->numtris > SKM_MAX_TRIS )
- Host_Error("mesh %i in model %s has too many indices\n", i, mod->name );
-
- poutmesh->numreferences = LittleLong( pinmesh->num_references );
- if( poutmesh->numreferences <= 0 )
- Host_Error("mesh %i in model %s has no bone references\n", i, mod->name );
- else if( poutmesh->numreferences > SKM_MAX_BONES )
- Host_Error("mesh %i in model %s has too many bone references\n", i, mod->name );
-
- com.strncpy( poutmesh->name, pinmesh->meshname, sizeof( poutmesh->name ) );
- Mod_StripLODSuffix( poutmesh->name );
-
- FS_StripExtension( pinmesh->shadername );
- poutmesh->skin.shader = R_LoadShader( pinmesh->shadername, SHADER_ALIAS, false, 0, SHADER_INVALID );
- R_DeformvBBoxForShader( poutmesh->skin.shader, ebbox );
-
- pinreferences = ( elem_t *)( ( byte * )pinmodel + LittleLong( pinmesh->ofs_references ) );
- poutreferences = poutmesh->references = Mod_Malloc( mod, sizeof( unsigned int ) * poutmesh->numreferences );
- for( j = 0; j < poutmesh->numreferences; j++, pinreferences++, poutreferences++ )
- *poutreferences = LittleLong( *pinreferences );
-
- pinskmvert = ( dskmvertex_t * )( ( byte * )pinmodel + LittleLong( pinmesh->ofs_verts ) );
-
- poutmesh->influences = ( float * )Mod_Malloc( mod, ( sizeof( *poutmesh->influences ) + sizeof( *poutmesh->bones ) ) * SKM_MAX_WEIGHTS * poutmesh->numverts );
- poutmesh->bones = ( unsigned int * )( ( byte * )poutmesh->influences + sizeof( *poutmesh->influences ) * SKM_MAX_WEIGHTS * poutmesh->numverts );
-
- size = sizeof( vec4_t ) + sizeof( vec4_t ); // xyz and normals
- if( GL_Support( R_SHADER_GLSL100_EXT ))
- size += sizeof( vec4_t ); // s-vectors
-
- size *= ( poutmesh->numverts+1 ); // pad by one additional vertex for prefetching
-
- // align poutmesh->xyzArray on a 16-byte boundary (we leak 16 bytes at most though)
- buf = ( byte * )( Mod_Malloc( mod, size+alignment ) );
- poutmesh->xyzArray = ( vec4_t * )( buf+alignment-( (size_t)buf % alignment ) );
- poutmesh->normalsArray = ( vec4_t * )( ( byte * )poutmesh->xyzArray + sizeof( vec4_t ) * ( poutmesh->numverts+1 ) );
-
- v = ( vec_t * )poutmesh->xyzArray[0];
- n = ( vec_t * )poutmesh->normalsArray[0];
- influences = poutmesh->influences;
- bones = poutmesh->bones;
- pframe = &poutmodel->frames[0];
- for( j = 0; j < poutmesh->numverts; j++, v += 4, n += 4, influences += SKM_MAX_WEIGHTS, bones += SKM_MAX_WEIGHTS )
- {
- float sum, influence;
- unsigned int bonenum, numweights;
- vec3_t origin, normal, t, matrix[3];
-
- pinbonevert = ( dskmbonevert_t * )( ( byte * )pinskmvert + sizeof( pinskmvert->numweights ) );
- numweights = LittleLong( pinskmvert->numweights );
-
- for( l = 0; l < numweights; l++, pinbonevert++ )
- {
- bonenum = LittleLong( pinbonevert->bonenum );
- influence = LittleFloat( pinbonevert->influence );
- poutbonepose = basepose + bonenum;
- for( k = 0; k < 3; k++ )
- {
- origin[k] = LittleFloat( pinbonevert->origin[k] );
- normal[k] = LittleFloat( pinbonevert->normal[k] );
- }
-
- // rebuild the base pose
- Quat_Matrix( poutbonepose->quat, matrix );
-
- Matrix_TransformVector( matrix, origin, t );
- VectorAdd( v, t, v );
- VectorMA( v, influence, poutbonepose->origin, v );
- v[3] = 1;
-
- Matrix_TransformVector( matrix, normal, t );
- VectorAdd( n, t, n );
- n[3] = 0;
-
- if( !l )
- { // store the first influence
- bones[0] = bonenum;
- influences[0] = influence;
- }
- else
- { // store the new influence if needed
- for( k = 0; k < SKM_MAX_WEIGHTS; k++ )
- {
- if( influence > influences[k] )
- {
- // pop the most weak influences out of the array,
- // shifting the rest of them to the beginning
- for( m = SKM_MAX_WEIGHTS-1; m > k; m-- )
- {
- bones[m] = bones[m-1];
- influences[m] = influences[m-1];
- }
-
- // store the new influence
- bones[k] = bonenum;
- influences[k] = influence;
- break;
- }
- }
- }
- }
-
- // normalize influences if needed
- for( l = 0, sum = 0; l < SKM_MAX_WEIGHTS && influences[l]; l++ )
- sum += influences[l];
- if( sum > 1.0f - 1.0/256.0f )
- {
- for( l = 0, sum = 1.0f / sum; l < SKM_MAX_WEIGHTS && influences[l]; l++ )
- influences[l] *= sum;
- }
-
- for( l = 0; l < SKM_MAX_WEIGHTS; l++ )
- {
- if( influences[l] == 1.0f )
- {
- Com_Assert( l > SKM_MAX_WEIGHTS-1 );
- influences[l] = 1;
- influences[l+1] = 0;
- break;
- }
- }
-
- // test vertex against the bounding box
- AddPointToBounds( v, pframe->mins, pframe->maxs );
-
- pinskmvert = ( dskmvertex_t * )( ( byte * )pinbonevert );
- }
-
- pinstcoord = ( dskmcoord_t * )( ( byte * )pinmodel + LittleLong( pinmesh->ofs_texcoords ) );
- poutstcoord = poutmesh->stArray = Mod_Malloc( mod, poutmesh->numverts * sizeof( vec2_t ) );
- for( j = 0; j < poutmesh->numverts; j++, pinstcoord++ )
- {
- poutstcoord[j][0] = LittleFloat( pinstcoord->st[0] );
- poutstcoord[j][1] = LittleFloat( pinstcoord->st[1] );
- }
-
- pintris = ( elem_t * )( ( byte * )pinmodel + LittleLong( pinmesh->ofs_indices ) );
- pouttris = poutmesh->elems = Mod_Malloc( mod, sizeof( elem_t ) * poutmesh->numtris * 3 );
- for( j = 0; j < poutmesh->numtris; j++, pintris += 3, pouttris += 3 )
- {
- pouttris[0] = (elem_t)LittleLong( pintris[0] );
- pouttris[1] = (elem_t)LittleLong( pintris[1] );
- pouttris[2] = (elem_t)LittleLong( pintris[2] );
- }
-
- //
- // build S and T vectors
- //
- if( GL_Support( R_SHADER_GLSL100_EXT ))
- {
- poutmesh->sVectorsArray = ( vec4_t * )( ( byte * )poutmesh->normalsArray + sizeof( vec4_t ) * ( poutmesh->numverts+1 ) );
- R_BuildTangentVectors( poutmesh->numverts, poutmesh->xyzArray, poutmesh->normalsArray, poutmesh->stArray,
- poutmesh->numtris, poutmesh->elems, poutmesh->sVectorsArray );
- }
- }
-
-#if 0
- // enable this to speed up loading
- for( j = 0; j < 3; j++ )
- {
- mod->mins[j] -= 48;
- mod->maxs[j] += 48;
- }
-#else
- // so much work just to calc the model's bounds, doh
- for( j = 1; j < poutmodel->numframes; j++ )
- {
- pframe = &poutmodel->frames[j];
-
- for( i = 0, bp = basepose; i < poutmodel->numbones; i++, bp++ )
- {
- int parent = poutmodel->bones[i].parent;
- bonepose_t *obp = &pframe->boneposes[i];
-
- if( parent >= 0 )
- Quat_ConcatTransforms( basepose[parent].quat, basepose[parent].origin,
- obp->quat, obp->origin, bp->quat, bp->origin );
- else
- *bp = *obp;
- }
-
- pinmesh = ( dskmmesh_t * )( ( byte * )pinmodel + LittleLong( pinmodel->ofs_meshes ) );
- for( i = 0, poutmesh = poutmodel->meshes; i < poutmodel->nummeshes; i++, pinmesh++, poutmesh++ )
- {
- pinskmvert = ( dskmvertex_t * )( ( byte * )pinmodel + LittleLong( pinmesh->ofs_verts ) );
-
- for( k = 0; k < poutmesh->numverts; k++ )
- {
- float influence;
- unsigned int numweights, bonenum;
- vec3_t v;
-
- pinbonevert = ( dskmbonevert_t * )( ( byte * )pinskmvert + sizeof( pinskmvert->numweights ) );
- numweights = LittleLong( pinskmvert->numweights );
-
- VectorClear( v );
- for( l = 0; l < numweights; l++, pinbonevert++ )
- {
- vec3_t origin, t;
-
- bonenum = LittleLong( pinbonevert->bonenum );
- influence = LittleFloat( pinbonevert->influence );
- poutbonepose = basepose + bonenum;
- for( m = 0; m < 3; m++ )
- origin[m] = LittleFloat( pinbonevert->origin[m] );
-
- // transform vertex
- Quat_TransformVector( poutbonepose->quat, origin, t );
- VectorAdd( v, t, v );
- VectorMA( v, influence, poutbonepose->origin, v );
- }
-
- // test vertex against the bounding box
- AddPointToBounds( v, pframe->mins, pframe->maxs );
-
- pinskmvert = ( dskmvertex_t * )( ( byte * )pinbonevert );
- }
- }
-
- }
-#endif
-
- ClearBounds( mod->mins, mod->maxs );
- for( j = 0, pframe = poutmodel->frames; j < poutmodel->numframes; j++, pframe++ )
- {
- VectorSubtract( pframe->mins, ebbox, pframe->mins );
- VectorAdd( pframe->maxs, ebbox, pframe->maxs );
- pframe->radius = RadiusFromBounds( pframe->mins, pframe->maxs );
- AddPointToBounds( pframe->mins, mod->mins, mod->maxs );
- AddPointToBounds( pframe->maxs, mod->mins, mod->maxs );
- }
- mod->radius = RadiusFromBounds( mod->mins, mod->maxs );
-
- Mem_Free( basepose );
- mod->type = mod_studio;
- mod->touchFrame = tr.registration_sequence; // register model
-}
-
-/*
-================
-R_SkeletalGetNumBones
-================
-*/
-int R_SkeletalGetNumBones( const ref_model_t *mod, int *numFrames )
-{
- mskmodel_t *skmodel;
-
- if( !mod || mod->type != mod_studio )
- return 0;
-
- skmodel = ( mskmodel_t * )mod->extradata;
- if( numFrames )
- *numFrames = skmodel->numframes;
- return skmodel->numbones;
-}
-
-/*
-================
-R_SkeletalGetBoneInfo
-================
-*/
-int R_SkeletalGetBoneInfo( const ref_model_t *mod, int bonenum, char *name, size_t name_size, int *flags )
-{
- const mskbone_t *bone;
- const mskmodel_t *skmodel;
-
- if( !mod || mod->type != mod_studio )
- return 0;
-
- skmodel = ( mskmodel_t * )mod->extradata;
- if( (unsigned int)bonenum >= (int)skmodel->numbones )
- Host_Error("R_SkeletalGetBone: bad bone number" );
-
- bone = &skmodel->bones[bonenum];
- if( name && name_size )
- com.strncpy( name, bone->name, name_size );
- if( flags )
- *flags = bone->flags;
- return bone->parent;
-}
-
-/*
-================
-R_SkeletalGetBonePose
-================
-*/
-void R_SkeletalGetBonePose( const ref_model_t *mod, int bonenum, int frame, bonepose_t *bonepose )
-{
- const mskmodel_t *skmodel;
-
- if( !mod || mod->type != mod_studio )
- return;
-
- skmodel = ( mskmodel_t * )mod->extradata;
- if( bonenum < 0 || bonenum >= (int)skmodel->numbones )
- Host_Error("R_SkeletalGetBonePose: bad bone number\n" );
- if( frame < 0 || frame >= (int)skmodel->numframes )
- Host_Error("R_SkeletalGetBonePose: bad frame number\n" );
-
- if( bonepose )
- *bonepose = skmodel->frames[frame].boneposes[bonenum];
-}
-
-/*
-================
-R_SkeletalModelLOD
-================
-*/
-static ref_model_t *R_SkeletalModelLOD( ref_entity_t *e )
-{
- int lod;
- float dist;
-
- if( !e->model->numlods || ( e->flags & RF_FORCENOLOD ) )
- return e->model;
-
- dist = DistanceFast( e->origin, RI.viewOrigin );
- dist *= RI.lod_dist_scale_for_fov;
-
- lod = (int)( dist / e->model->radius );
- if( r_lodscale->integer )
- lod /= r_lodscale->integer;
- lod += r_lodbias->integer;
-
- if( lod < 1 )
- return e->model;
- return e->model->lods[min( lod, e->model->numlods )-1];
-}
-
-/*
-================
-R_SkeletalModelLerpBBox
-================
-*/
-static void R_SkeletalModelLerpBBox( ref_entity_t *e, ref_model_t *mod )
-{
- int i;
- mskframe_t *pframe, *poldframe;
- float *thismins, *oldmins, *thismaxs, *oldmaxs;
- mskmodel_t *skmodel = ( mskmodel_t * )mod->extradata;
-
- if( !skmodel->nummeshes )
- {
- skm_radius = 0;
- ClearBounds( skm_mins, skm_maxs );
- return;
- }
-
- if( ( e->frame >= (int)skmodel->numframes ) || ( e->frame < 0 ) )
- {
- MsgDev( D_ERROR, "R_SkeletalModelBBox %s: no such frame %d\n", mod->name, e->frame );
- e->frame = 0;
- }
- if( ( e->oldframe >= (int)skmodel->numframes ) || ( e->oldframe < 0 ) )
- {
- MsgDev( D_ERROR, "R_SkeletalModelBBox %s: no such oldframe %d\n", mod->name, e->oldframe );
- e->oldframe = 0;
- }
-
- pframe = skmodel->frames + e->frame;
- poldframe = skmodel->frames + e->oldframe;
-
- // compute axially aligned mins and maxs
- if( pframe == poldframe )
- {
- VectorCopy( pframe->mins, skm_mins );
- VectorCopy( pframe->maxs, skm_maxs );
- skm_radius = pframe->radius;
- }
- else
- {
- thismins = pframe->mins;
- thismaxs = pframe->maxs;
-
- oldmins = poldframe->mins;
- oldmaxs = poldframe->maxs;
-
- for( i = 0; i < 3; i++ )
- {
- skm_mins[i] = min( thismins[i], oldmins[i] );
- skm_maxs[i] = max( thismaxs[i], oldmaxs[i] );
- }
- skm_radius = RadiusFromBounds( thismins, thismaxs );
- }
-
- if( e->scale != 1.0f )
- {
- VectorScale( skm_mins, e->scale, skm_mins );
- VectorScale( skm_maxs, e->scale, skm_maxs );
- skm_radius *= e->scale;
- }
-}
-
-//=======================================================================
-
-/*
-================
-R_SkeletalTransformVerts
-================
-*/
-static void R_SkeletalTransformVerts( int numverts, const unsigned int *bones, const float *influences, mat4x4_t *relbonepose, const vec_t *v, vec_t *ov )
-{
- int j;
- float i;
- const float *pose;
-
- for( ; numverts; numverts--, v += 4, ov += 4, bones += SKM_MAX_WEIGHTS, influences += SKM_MAX_WEIGHTS )
- {
- i = *influences;
- pose = relbonepose[*bones];
-
- if( i == 1 )
- { // most common case
- ov[0] = v[0] * pose[0] + v[1] * pose[4] + v[2] * pose[8] + pose[12];
- ov[1] = v[0] * pose[1] + v[1] * pose[5] + v[2] * pose[9] + pose[13];
- ov[2] = v[0] * pose[2] + v[1] * pose[6] + v[2] * pose[10] + pose[14];
- }
- else
- {
- ov[0] = i * ( v[0] * pose[0] + v[1] * pose[4] + v[2] * pose[8] + pose[12] );
- ov[1] = i * ( v[0] * pose[1] + v[1] * pose[5] + v[2] * pose[9] + pose[13] );
- ov[2] = i * ( v[0] * pose[2] + v[1] * pose[6] + v[2] * pose[10] + pose[14] );
-
- for( j = 1; j < SKM_MAX_WEIGHTS && influences[j]; j++ )
- {
- i = influences[j];
- pose = relbonepose[bones[j]];
-
- ov[0] += i * ( v[0] * pose[0] + v[1] * pose[4] + v[2] * pose[8] + pose[12] );
- ov[1] += i * ( v[0] * pose[1] + v[1] * pose[5] + v[2] * pose[9] + pose[13] );
- ov[2] += i * ( v[0] * pose[2] + v[1] * pose[6] + v[2] * pose[10] + pose[14] );
- }
- }
- }
-}
-
-/*
-================
-R_SkeletalTransformNormals
-================
-*/
-static void R_SkeletalTransformNormals( int numverts, const unsigned int *bones, const float *influences, mat4x4_t *relbonepose, const vec_t *v, vec_t *ov )
-{
- int j;
- float i;
- const float *pose;
-
- for( ; numverts; numverts--, v += 4, ov += 4, bones += SKM_MAX_WEIGHTS, influences += SKM_MAX_WEIGHTS )
- {
- i = *influences;
- pose = relbonepose[*bones];
-
- if( i == 1 )
- { // most common case
- ov[0] = v[0] * pose[0] + v[1] * pose[4] + v[2] * pose[8];
- ov[1] = v[0] * pose[1] + v[1] * pose[5] + v[2] * pose[9];
- ov[2] = v[0] * pose[2] + v[1] * pose[6] + v[2] * pose[10];
- ov[3] = v[3];
- }
- else
- {
- ov[0] = i * ( v[0] * pose[0] + v[1] * pose[4] + v[2] * pose[8] );
- ov[1] = i * ( v[0] * pose[1] + v[1] * pose[5] + v[2] * pose[9] );
- ov[2] = i * ( v[0] * pose[2] + v[1] * pose[6] + v[2] * pose[10] );
- ov[3] = v[3];
-
- for( j = 1; j < SKM_MAX_WEIGHTS && influences[j]; j++ )
- {
- i = influences[j];
- pose = relbonepose[bones[j]];
-
- ov[0] += i * ( v[0] * pose[0] + v[1] * pose[4] + v[2] * pose[8] );
- ov[1] += i * ( v[0] * pose[1] + v[1] * pose[5] + v[2] * pose[9] );
- ov[2] += i * ( v[0] * pose[2] + v[1] * pose[6] + v[2] * pose[10] );
- }
- }
- }
-}
-
-#if defined ( id386 ) && !defined ( __MACOSX__ )
-
-#if defined ( __GNUC__ )
-
-#define R_SkeletalTransformVerts_SSE R_SkeletalTransformVerts
-#define R_SkeletalTransformNormals_SSE R_SkeletalTransformNormals
-
-#elif defined ( _WIN32 ) && ( _MSC_VER >= 1400 )
-#pragma optimize( "", off )
-
-/*
-================
-R_SkeletalTransformVerts_SSE
-================
-*/
-static void R_SkeletalTransformVerts_SSE( int numverts, const unsigned int *bones, const float *influences, mat4x4_t *relbonepose, const vec_t *v, vec_t *ov )
-{
- __asm {
- mov eax, numverts;
- test eax, eax;
- jz done;
-
- imul eax, 0x10;
- mov numverts, eax;
- xor eax, eax;
-
- mov ebx, v;
- mov edi, ov;
- mov ecx, relbonepose;
-
-sl1:
- movaps xmm0, ds : dword ptr[ebx+eax];
- movaps xmm1, ds : dword ptr[ebx+eax];
- movaps xmm2, ds : dword ptr[ebx+eax];
- // prefetchnta [ebx+eax+0x10];
-
- // loop init
- xor edx, edx;
-
- //i = influence[0];
- mov esi, influences;
- cmp ds : dword ptr[esi], 0x3F800000; // IEEE-format representation of 1.0f
-
- movss xmm7, ds : dword ptr[esi]; // xmm7 contains influence
- shufps xmm7, xmm7, 0x00;
-
- shufps xmm0, xmm0, 0x00;
- shufps xmm1, xmm1, 0x55;
- shufps xmm2, xmm2, 0xAA;
-
- mov esi, bones;
- mov esi, ds : dword ptr[esi];
- lea esi,[esi *8];
- lea esi,[esi *8+ecx];
-
- jne slowCase;
-
- // fastCase:
- // copying pose[0], pose[1], pose[2], pose[3] into xmm3
- movaps xmm3, ds : dword ptr[esi+0x00];
- // copying pose[4], pose[5], pose[6], pose[7] into xmm4
- movaps xmm4, ds : dword ptr[esi+0x10];
- // copying pose[8], pose[9], pose[10], pose[11] into xmm5
- movaps xmm5, ds : dword ptr[esi+0x20];
- // copying pose[12], pose[13], pose[14], pose[15] into xmm5
- movaps xmm6, ds : dword ptr[esi+0x30];
-
- mulps xmm3, xmm0; // xmm3 * v[0]
- mulps xmm4, xmm1; // xmm4 * v[1]
- mulps xmm5, xmm2; // xmm5 * v[2]
-
- // adding each column vector into xmm6
- addps xmm6, xmm3;
- addps xmm6, xmm4;
- addps xmm6, xmm5;
- jmp endOfLoop;
-
- // loop start
-slowCase:
- xorps xmm6, xmm6;
-
-continueSlowLoop:
- // copying pose[0], pose[1], pose[2], pose[3] into xmm4
- movaps xmm3, ds : dword ptr[esi+0x00];
- // copying pose[4], pose[5], pose[6], pose[7] into xmm5
- movaps xmm4, ds : dword ptr[esi+0x10];
- // copying pose[8], pose[9], pose[10], pose[11] into xmm4
- movaps xmm5, ds : dword ptr[esi+0x20];
-
- mulps xmm3, xmm0; // xmm3 * v[0]
- mulps xmm4, xmm1; // xmm4 * v[1]
- mulps xmm5, xmm2; // xmm5 * v[2]
-
- // adding each column vector into xmm5
- addps xmm5, ds : dword ptr[esi+0x30]; // adding pose[12], pose[13], pose[14], pose[15] into xmm5
-
- mulps xmm3, xmm7; // i * v[0] * pos
- mulps xmm4, xmm7; // i * v[1] * pos
- mulps xmm5, xmm7; // i * v[2] * pos
-
- addps xmm6, xmm3;
- addps xmm6, xmm4;
- addps xmm6, xmm5; // adding the result to ov vector
-
- inc edx;
- cmp edx, SKM_MAX_WEIGHTS;
-
- // loop condition
- je endOfLoop;
-
- mov esi, influences;
- cmp ds : dword ptr[esi+edx*0x04], 0;
- je endOfLoop;
-
- //i = influence[j];
- movss xmm7, ds : dword ptr[esi+edx*0x04]; // xmm6 contains i
- shufps xmm7, xmm7, 0x00;
-
- mov esi, bones;
- mov esi, ds : dword ptr[esi+edx*0x04];
- lea esi,[esi *8];
- lea esi,[esi *8+ecx];
-
- jmp continueSlowLoop;
-
-endOfLoop:
- movaps ds : dword ptr[edi+eax], xmm6;
-
- add bones, SKM_MAX_WEIGHTS *0x04;
- add influences, SKM_MAX_WEIGHTS *0x04;
-
- add eax, 0x10;
- cmp eax, numverts;
-
- jl sl1;
-done:
- ;
- }
-}
-
-/*
-================
-R_SkeletalTransformNormals_SSE
-================
-*/
-static void R_SkeletalTransformNormals_SSE( int numverts, const unsigned int *bones, const float *influences, mat4x4_t *relbonepose, const vec_t *v, vec_t *ov )
-{
- __asm {
- mov eax, numverts;
- test eax, eax;
- jz done;
-
- imul eax, 0x10;
- mov numverts, eax;
- xor eax, eax;
-
- mov ebx, v;
- mov edi, ov;
- mov ecx, relbonepose;
-
-sl1:
- movaps xmm0, ds : dword ptr[ebx+eax];
- movaps xmm1, ds : dword ptr[ebx+eax];
- movaps xmm2, ds : dword ptr[ebx+eax];
- // prefetchnta [ebx+eax+0x10];
-
- // loop init
- xor edx, edx;
-
- //i = influence[0];
- mov esi, influences;
- cmp ds : dword ptr[esi], 0x3F800000; // IEEE-format representation of 1.0f
-
- movss xmm7, ds : dword ptr[esi]; // xmm7 contains influence
- shufps xmm7, xmm7, 0x00;
-
- shufps xmm0, xmm0, 0x00;
- shufps xmm1, xmm1, 0x55;
- shufps xmm2, xmm2, 0xAA;
-
- mov esi, bones;
- mov esi, ds : dword ptr[esi];
- lea esi,[esi *8];
- lea esi,[esi *8+ecx];
-
- jne slowCase;
-
- // fastCase:
- xorps xmm6, xmm6;
-
- // copying pose[0], pose[1], pose[2], pose[3] into xmm3
- movaps xmm3, ds : dword ptr[esi+0x00];
- // copying pose[4], pose[5], pose[6], pose[7] into xmm4
- movaps xmm4, ds : dword ptr[esi+0x10];
- // copying pose[8], pose[9], pose[10], pose[11] into xmm5
- movaps xmm5, ds : dword ptr[esi+0x20];
-
- mulps xmm3, xmm0; // xmm3 * v[0]
- mulps xmm4, xmm1; // xmm4 * v[1]
- mulps xmm5, xmm2; // xmm5 * v[2]
-
- // adding each column vector into xmm6
- addps xmm6, xmm3;
- addps xmm6, xmm4;
- addps xmm6, xmm5;
- jmp endOfLoop;
-
- // loop start
-slowCase:
- xorps xmm6, xmm6;
-
-continueSlowLoop:
- // copying pose[0], pose[1], pose[2], pose[3] into xmm4
- movaps xmm3, ds : dword ptr[esi+0x00];
- // copying pose[4], pose[5], pose[6], pose[7] into xmm5
- movaps xmm4, ds : dword ptr[esi+0x10];
- // copying pose[8], pose[9], pose[10], pose[11] into xmm4
- movaps xmm5, ds : dword ptr[esi+0x20];
-
- mulps xmm3, xmm0; // xmm3 * v[0]
- mulps xmm4, xmm1; // xmm4 * v[1]
- mulps xmm5, xmm2; // xmm5 * v[2]
-
- mulps xmm3, xmm7; // i * v[0] * pos
- mulps xmm4, xmm7; // i * v[1] * pos
- mulps xmm5, xmm7; // i * v[2] * pos
-
- addps xmm6, xmm3;
- addps xmm6, xmm4;
- addps xmm6, xmm5; // adding the result to ov vector
-
- inc edx;
- cmp edx, SKM_MAX_WEIGHTS;
-
- // loop condition
- je endOfLoop;
-
- mov esi, influences;
- cmp ds : dword ptr[esi+edx*0x04], 0;
- je endOfLoop;
-
- //i = influence[j];
- movss xmm7, ds : dword ptr[esi+edx*0x04]; // xmm6 contains i
- shufps xmm7, xmm7, 0x00;
-
- mov esi, bones;
- mov esi, ds : dword ptr[esi+edx*0x04];
- lea esi,[esi *8];
- lea esi,[esi *8+ecx];
-
- jmp continueSlowLoop;
-
-endOfLoop:
- movaps ds : dword ptr[edi+eax], xmm6;
-
- add bones, SKM_MAX_WEIGHTS *0x04;
- add influences, SKM_MAX_WEIGHTS *0x04;
-
- add eax, 0x10;
- cmp eax, numverts;
-
- jl sl1;
-done:
- ;
- }
-}
-
-#pragma optimize( "", on )
-#else
-#define R_SkeletalTransformVerts_SSE R_SkeletalTransformVerts
-#define R_SkeletalTransformNormals_SSE R_SkeletalTransformNormals
-#endif
-#else
-#define R_SkeletalTransformVerts_SSE R_SkeletalTransformVerts
-#define R_SkeletalTransformNormals_SSE R_SkeletalTransformNormals
-#endif
-
-//=======================================================================
-
-static ALIGN( 16 ) mat4x4_t relbonepose[SKM_MAX_BONES];
-
-/*
-================
-R_DrawBonesFrameLerp
-================
-*/
-static void R_DrawBonesFrameLerp( const meshbuffer_t *mb, float backlerp )
-{
- unsigned int i, j, meshnum;
- int features;
- float frontlerp = 1.0 - backlerp, *pose;
- mskmesh_t *mesh;
- bonepose_t *bonepose, *oldbonepose, tempbonepose[SKM_MAX_BONES], *lerpedbonepose;
- bonepose_t *bp, *oldbp, *out, tp;
- ref_entity_t *e = RI.currententity;
- ref_model_t *mod = Mod_ForHandle( mb->LODModelHandle );
- mskmodel_t *skmodel = ( mskmodel_t * )mod->extradata;
- ref_shader_t *shader;
- mskbone_t *bone;
- vec4_t *xyzArray, *normalsArray, *sVectorsArray;
-
- meshnum = -( mb->infokey + 1 );
- if( meshnum >= skmodel->nummeshes )
- return;
- mesh = skmodel->meshes + meshnum;
-
- xyzArray = inVertsArray;
- normalsArray = inNormalsArray;
- sVectorsArray = inSVectorsArray;
-
- MB_NUM2SHADER( mb->shaderkey, shader );
-
- features = MF_NONBATCHED | shader->features;
- if( RI.params & RP_SHADOWMAPVIEW )
- {
- features &= ~( MF_COLORS|MF_SVECTORS|MF_ENABLENORMALS );
- if( !( shader->features & MF_DEFORMVS ) )
- features &= ~MF_NORMALS;
- }
- else
- {
- if( ( features & MF_SVECTORS ) || r_shownormals->integer )
- features |= MF_NORMALS;
- if( e->outlineHeight )
- features |= MF_NORMALS|(GL_Support( R_SHADER_GLSL100_EXT ) ? MF_ENABLENORMALS : 0);
- }
-
- // not sure if it's really needed
- if( e->boneposes == skmodel->frames[0].boneposes )
- {
- e->boneposes = NULL;
- e->frame = e->oldframe = 0;
- }
-
- // choose boneposes for lerping
- if( e->boneposes )
- {
- bp = e->boneposes;
- if( e->oldboneposes )
- oldbp = e->oldboneposes;
- else
- oldbp = bp;
- }
- else
- {
- if( ( e->frame >= (int)skmodel->numframes ) || ( e->frame < 0 ) )
- {
- MsgDev( D_ERROR, "R_DrawBonesFrameLerp %s: no such frame %d\n", mod->name, e->frame );
- e->frame = 0;
- }
- if( ( e->oldframe >= (int)skmodel->numframes ) || ( e->oldframe < 0 ) )
- {
- MsgDev( D_ERROR, "R_DrawBonesFrameLerp %s: no such oldframe %d\n", mod->name, e->oldframe );
- e->oldframe = 0;
- }
-
- bp = skmodel->frames[e->frame].boneposes;
- oldbp = skmodel->frames[e->oldframe].boneposes;
- }
-
- lerpedbonepose = tempbonepose;
- if( bp == oldbp || frontlerp == 1 )
- {
- if( e->boneposes )
- { // assume that parent transforms have already been applied
- lerpedbonepose = bp;
- }
- else
- { // transform
- if( !e->frame )
- { // fastpath: render frame 0 as is
- xyzArray = mesh->xyzArray;
- normalsArray = mesh->normalsArray;
- sVectorsArray = mesh->sVectorsArray;
-
- goto pushmesh;
- }
-
- for( i = 0; i < mesh->numreferences; i++ )
- {
- j = mesh->references[i];
- out = lerpedbonepose + j;
- bonepose = bp + j;
- bone = skmodel->bones + j;
-
- if( bone->parent >= 0 )
- {
- Quat_ConcatTransforms( lerpedbonepose[bone->parent].quat, lerpedbonepose[bone->parent].origin,
- bonepose->quat, bonepose->origin, out->quat, out->origin );
- }
- else
- {
- Quat_Copy( bonepose->quat, out->quat );
- VectorCopy( bonepose->origin, out->origin );
- }
- }
- }
- }
- else
- {
- if( e->boneposes )
- { // lerp, assume that parent transforms have already been applied
- for( i = 0, out = lerpedbonepose, bonepose = bp, oldbonepose = oldbp, bone = skmodel->bones; i < skmodel->numbones; i++, out++, bonepose++, oldbonepose++, bone++ )
- {
- Quat_Lerp( oldbonepose->quat, bonepose->quat, frontlerp, out->quat );
- out->origin[0] = oldbonepose->origin[0] + ( bonepose->origin[0] - oldbonepose->origin[0] ) * frontlerp;
- out->origin[1] = oldbonepose->origin[1] + ( bonepose->origin[1] - oldbonepose->origin[1] ) * frontlerp;
- out->origin[2] = oldbonepose->origin[2] + ( bonepose->origin[2] - oldbonepose->origin[2] ) * frontlerp;
- }
- }
- else
- { // lerp and transform
- for( i = 0; i < mesh->numreferences; i++ )
- {
- j = mesh->references[i];
- out = lerpedbonepose + j;
- bonepose = bp + j;
- oldbonepose = oldbp + j;
- bone = skmodel->bones + j;
-
- Quat_Lerp( oldbonepose->quat, bonepose->quat, frontlerp, tp.quat );
- tp.origin[0] = oldbonepose->origin[0] + ( bonepose->origin[0] - oldbonepose->origin[0] ) * frontlerp;
- tp.origin[1] = oldbonepose->origin[1] + ( bonepose->origin[1] - oldbonepose->origin[1] ) * frontlerp;
- tp.origin[2] = oldbonepose->origin[2] + ( bonepose->origin[2] - oldbonepose->origin[2] ) * frontlerp;
-
- if( bone->parent >= 0 )
- {
- Quat_ConcatTransforms( tempbonepose[bone->parent].quat, tempbonepose[bone->parent].origin,
- tp.quat, tp.origin, out->quat, out->origin );
- }
- else
- {
- Quat_Copy( tp.quat, out->quat );
- VectorCopy( tp.origin, out->origin );
- }
- }
- }
- }
-
- for( i = 0; i < mesh->numreferences; i++ )
- {
- j = mesh->references[i];
- pose = relbonepose[j];
-
- Quat_ConcatTransforms( lerpedbonepose[j].quat, lerpedbonepose[j].origin,
- skmodel->invbaseposes[j].quat, skmodel->invbaseposes[j].origin, tp.quat, &pose[12] );
- pose[15] = 1.0f;
-
- // make origin the forth column instead of row so that
- // things can be optimized more easily
- Matrix_FromQuaternion( tp.quat, pose );
- }
-
- if( 0 )
- {
- R_SkeletalTransformVerts_SSE( mesh->numverts, mesh->bones, mesh->influences, relbonepose,
- ( vec_t * )mesh->xyzArray[0], ( vec_t * )inVertsArray );
-
- if( features & MF_NORMALS )
- R_SkeletalTransformNormals_SSE( mesh->numverts, mesh->bones, mesh->influences, relbonepose,
- ( vec_t * )mesh->normalsArray[0], ( vec_t * )inNormalsArray );
-
- if( features & MF_SVECTORS )
- R_SkeletalTransformNormals_SSE( mesh->numverts, mesh->bones, mesh->influences, relbonepose,
- ( vec_t * )mesh->sVectorsArray[0], ( vec_t * )inSVectorsArray );
- }
- else
- {
- R_SkeletalTransformVerts( mesh->numverts, mesh->bones, mesh->influences, relbonepose,
- ( vec_t * )mesh->xyzArray[0], ( vec_t * )inVertsArray );
-
- if( features & MF_NORMALS )
- R_SkeletalTransformNormals( mesh->numverts, mesh->bones, mesh->influences, relbonepose,
- ( vec_t * )mesh->normalsArray[0], ( vec_t * )inNormalsArray );
-
- if( features & MF_SVECTORS )
- R_SkeletalTransformNormals( mesh->numverts, mesh->bones, mesh->influences, relbonepose,
- ( vec_t * )mesh->sVectorsArray[0], ( vec_t * )inSVectorsArray );
- }
-
-pushmesh:
- skm_mesh.elems = mesh->elems;
- skm_mesh.numElems = mesh->numtris * 3;
- skm_mesh.numVertexes = mesh->numverts;
- skm_mesh.xyzArray = xyzArray;
- skm_mesh.stArray = mesh->stArray;
- skm_mesh.normalsArray = normalsArray;
- skm_mesh.sVectorsArray = sVectorsArray;
-
- R_RotateForEntity( e );
-
- R_PushMesh( &skm_mesh, features );
- R_RenderMeshBuffer( mb );
-}
-
-/*
-=================
-R_DrawSkeletalModel
-=================
-*/
-void R_DrawSkeletalModel( const meshbuffer_t *mb )
-{
- ref_entity_t *e = RI.currententity;
-
- if( OCCLUSION_QUERIES_ENABLED( RI ) && OCCLUSION_TEST_ENTITY( e ) )
- {
- ref_shader_t *shader;
-
- MB_NUM2SHADER( mb->shaderkey, shader );
- if( !R_GetOcclusionQueryResultBool( shader->type == SHADER_PLANAR_SHADOW ? OQ_PLANARSHADOW : OQ_ENTITY,
- e - r_entities, true ) )
- return;
- }
-
- // hack the depth range to prevent view model from poking into walls
- if( e->flags & RF_WEAPONMODEL )
- pglDepthRange( gldepthmin, gldepthmin + 0.3 * ( gldepthmax - gldepthmin ) );
-
- // backface culling for left-handed weapons
- if( e->flags & RF_CULLHACK )
- GL_FrontFace( !glState.frontFace );
-
- if( !r_lerpmodels->integer )
- e->backlerp = 0;
-
- R_DrawBonesFrameLerp( mb, e->backlerp );
-
- if( e->flags & RF_WEAPONMODEL )
- pglDepthRange( gldepthmin, gldepthmax );
-
- if( e->flags & RF_CULLHACK )
- GL_FrontFace( !glState.frontFace );
-}
-
-/*
-=================
-R_SkeletalModelBBox
-=================
-*/
-float R_SkeletalModelBBox( ref_entity_t *e, vec3_t mins, vec3_t maxs )
-{
- ref_model_t *mod;
-
- mod = R_SkeletalModelLOD( e );
- if( !mod )
- return 0;
-
- R_SkeletalModelLerpBBox( e, mod );
-
- VectorCopy( skm_mins, mins );
- VectorCopy( skm_maxs, maxs );
- return skm_radius;
-}
-
-/*
-=================
-R_CullSkeletalModel
-=================
-*/
-bool R_CullSkeletalModel( ref_entity_t *e )
-{
- int i, clipped;
- bool frustum, query;
- unsigned int modhandle;
- ref_model_t *mod;
- ref_shader_t *shader;
- mskmesh_t *mesh;
- mskmodel_t *skmodel;
- meshbuffer_t *mb;
-
- mod = R_SkeletalModelLOD( e );
- if( !( skmodel = ( ( mskmodel_t * )mod->extradata ) ) || !skmodel->nummeshes )
- return true;
-
- R_SkeletalModelLerpBBox( e, mod );
- modhandle = Mod_Handle( mod );
-
- clipped = R_CullModel( e, skm_mins, skm_maxs, skm_radius );
- frustum = clipped & 1;
- if( clipped & 2 )
- return true;
-
- query = OCCLUSION_QUERIES_ENABLED( RI ) && OCCLUSION_TEST_ENTITY( e ) ? true : false;
- if( !frustum && query )
- {
- R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_ENTITY, e - r_entities ), e, skm_mins, skm_maxs );
- }
-
- if( RI.refdef.rdflags & RDF_NOWORLDMODEL
- || ( r_shadows->integer != SHADOW_PLANAR && !( r_shadows->integer == SHADOW_MAPPING && ( e->flags & RF_PLANARSHADOW ) ) )
- || R_CullPlanarShadow( e, skm_mins, skm_maxs, query ) )
- return frustum; // entity is not in PVS or shadow is culled away by frustum culling
-
- for( i = 0, mesh = skmodel->meshes; i < (int)skmodel->nummeshes; i++, mesh++ )
- {
- shader = NULL;
- if( e->customSkin )
- shader = R_FindShaderForSkinFile( e->customSkin, mesh->name );
- else if( e->customShader )
- shader = e->customShader;
- else if( mesh->skin.shader )
- shader = mesh->skin.shader;
-
- if( shader && ( shader->sort <= SORT_ALPHATEST ) )
- {
- mb = R_AddMeshToList( MB_MODEL, NULL, R_PlanarShadowShader(), -( i+1 ) );
- if( mb )
- mb->LODModelHandle = modhandle;
- }
- }
-
- return frustum;
-}
-
-/*
-=================
-R_AddSkeletalModelToList
-=================
-*/
-void R_AddSkeletalModelToList( ref_entity_t *e )
-{
- int i;
- unsigned int modhandle, entnum = e - r_entities;
- mfog_t *fog = NULL;
- ref_model_t *mod;
- ref_shader_t *shader;
- mskmesh_t *mesh;
- mskmodel_t *skmodel;
-
- mod = R_SkeletalModelLOD( e );
- skmodel = ( mskmodel_t * )mod->extradata;
- modhandle = Mod_Handle( mod );
-
- if( RI.params & RP_SHADOWMAPVIEW )
- {
- if( r_entShadowBits[entnum] & RI.shadowGroup->bit )
- {
- if( !r_shadows_self_shadow->integer )
- r_entShadowBits[entnum] &= ~RI.shadowGroup->bit;
- if( e->flags & RF_WEAPONMODEL )
- return;
- }
- else
- {
- R_SkeletalModelLerpBBox( e, mod );
- if( !R_CullModel( e, skm_mins, skm_maxs, skm_radius ) )
- r_entShadowBits[entnum] |= RI.shadowGroup->bit;
- return; // mark as shadowed, proceed with caster otherwise
- }
- }
- else
- {
- fog = R_FogForSphere( e->origin, skm_radius );
-#if 0
- if( !( e->flags & RF_WEAPONMODEL ) && fog )
- {
- R_SkeletalModelLerpBBox( e, mod );
- if( R_CompletelyFogged( fog, e->origin, skm_radius ) )
- return;
- }
-#endif
- }
-
- for( i = 0, mesh = skmodel->meshes; i < (int)skmodel->nummeshes; i++, mesh++ )
- {
- shader = NULL;
- if( e->customSkin )
- shader = R_FindShaderForSkinFile( e->customSkin, mesh->name );
- else if( e->customShader )
- shader = e->customShader;
- else
- shader = mesh->skin.shader;
-
- if( shader )
- R_AddModelMeshToList( modhandle, fog, shader, i );
- }
-}
diff --git a/render/render.plg b/render/render.plg
index 66e34829..ed77a3cd 100644
--- a/render/render.plg
+++ b/render/render.plg
@@ -6,13 +6,13 @@
--------------------Configuration: render - Win32 Debug--------------------
Command Lines
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD5.tmp" with contents
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP47C.tmp" with contents
[
/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../public" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\render\!debug/" /Fo"..\temp\render\!debug/" /Fd"..\temp\render\!debug/" /FD /c
-"D:\Xash3D\src_main\render\r_image.c"
+"D:\Xash3D\src_main\render\r_backend.c"
]
-Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD5.tmp"
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD6.tmp" with contents
+Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP47C.tmp"
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP47D.tmp" with contents
[
msvcrtd.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\render\!debug/render.pdb" /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"..\temp\render\!debug/render.dll" /implib:"..\temp\render\!debug/render.lib" /pdbtype:sept
"\Xash3D\src_main\temp\render\!debug\cin.obj"
@@ -38,16 +38,17 @@ msvcrtd.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:ye
"\Xash3D\src_main\temp\render\!debug\r_sky.obj"
"\Xash3D\src_main\temp\render\!debug\r_surf.obj"
]
-Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD6.tmp"
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD7.bat" with contents
+Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP47D.tmp"
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP47E.bat" with contents
[
@echo off
copy \Xash3D\src_main\temp\render\!debug\render.dll "D:\Xash3D\bin\render.dll"
]
-Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD7.bat"
+Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP47E.bat"
Compiling...
-r_image.c
+r_backend.c
Linking...
+ Creating library ..\temp\render\!debug/render.lib and object ..\temp\render\!debug/render.exp
Output Window
Performing Custom Build Step on \Xash3D\src_main\temp\render\!debug\render.dll
Скопировано файлов: 1.
diff --git a/render/warpsin.h b/render/warpsin.h
new file mode 100644
index 00000000..e140acf9
--- /dev/null
+++ b/render/warpsin.h
@@ -0,0 +1,53 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+
+0.000000, 0.098165, 0.196270, 0.294259, 0.392069, 0.489643, 0.586920, 0.683850,
+0.780360, 0.876405, 0.971920, 1.066850, 1.161140, 1.254725, 1.347560, 1.439580,
+1.530735, 1.620965, 1.710220, 1.798445, 1.885585, 1.971595, 2.056410, 2.139990,
+2.222280, 2.303235, 2.382795, 2.460925, 2.537575, 2.612690, 2.686235, 2.758160,
+2.828425, 2.896990, 2.963805, 3.028835, 3.092040, 3.153385, 3.212830, 3.270340,
+3.325880, 3.379415, 3.430915, 3.480350, 3.527685, 3.572895, 3.615955, 3.656840,
+3.695520, 3.731970, 3.766175, 3.798115, 3.827760, 3.855105, 3.880125, 3.902810,
+3.923140, 3.941110, 3.956705, 3.969920, 3.980740, 3.989160, 3.995180, 3.998795,
+4.000000, 3.998795, 3.995180, 3.989160, 3.980740, 3.969920, 3.956705, 3.941110,
+3.923140, 3.902810, 3.880125, 3.855105, 3.827760, 3.798115, 3.766175, 3.731970,
+3.695520, 3.656840, 3.615955, 3.572895, 3.527685, 3.480350, 3.430915, 3.379415,
+3.325880, 3.270340, 3.212830, 3.153385, 3.092040, 3.028835, 2.963805, 2.896990,
+2.828425, 2.758160, 2.686235, 2.612690, 2.537575, 2.460925, 2.382795, 2.303235,
+2.222280, 2.139990, 2.056410, 1.971595, 1.885585, 1.798445, 1.710220, 1.620965,
+1.530735, 1.439580, 1.347560, 1.254725, 1.161140, 1.066850, 0.971920, 0.876405,
+0.780360, 0.683850, 0.586920, 0.489643, 0.392069, 0.294259, 0.196270, 0.098165,
+0.000000, -0.098165, -0.196270, -0.294259, -0.392069, -0.489643, -0.586920, -0.683850,
+-0.780360, -0.876405, -0.971920, -1.066850, -1.161140, -1.254725, -1.347560, -1.439580,
+-1.530735, -1.620965, -1.710220, -1.798445, -1.885585, -1.971595, -2.056410, -2.139990,
+-2.222280, -2.303235, -2.382795, -2.460925, -2.537575, -2.612690, -2.686235, -2.758160,
+-2.828425, -2.896990, -2.963805, -3.028835, -3.092040, -3.153385, -3.212830, -3.270340,
+-3.325880, -3.379415, -3.430915, -3.480350, -3.527685, -3.572895, -3.615955, -3.656840,
+-3.695520, -3.731970, -3.766175, -3.798115, -3.827760, -3.855105, -3.880125, -3.902810,
+-3.923140, -3.941110, -3.956705, -3.969920, -3.980740, -3.989160, -3.995180, -3.998795,
+-4.000000, -3.998795, -3.995180, -3.989160, -3.980740, -3.969920, -3.956705, -3.941110,
+-3.923140, -3.902810, -3.880125, -3.855105, -3.827760, -3.798115, -3.766175, -3.731970,
+-3.695520, -3.656840, -3.615955, -3.572895, -3.527685, -3.480350, -3.430915, -3.379415,
+-3.325880, -3.270340, -3.212830, -3.153385, -3.092040, -3.028835, -2.963805, -2.896990,
+-2.828425, -2.758160, -2.686235, -2.612690, -2.537575, -2.460925, -2.382795, -2.303235,
+-2.222280, -2.139990, -2.056410, -1.971595, -1.885585, -1.798445, -1.710220, -1.620965,
+-1.530735, -1.439580, -1.347560, -1.254725, -1.161140, -1.066850, -0.971920, -0.876405,
+-0.780360, -0.683850, -0.586920, -0.489643, -0.392069, -0.294259, -0.196270, -0.098165,
diff --git a/server/server.plg b/server/server.plg
deleted file mode 100644
index 2aaf2920..00000000
--- a/server/server.plg
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-Build Log
-
---------------------Configuration: server - Win32 Debug--------------------
-
-Command Lines
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBB.tmp" with contents
-[
-/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "ents" /I "game" /I "global" /I "monsters" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\server\!debug/" /Fo"..\temp\server\!debug/" /Fd"..\temp\server\!debug/" /FD /c
-"D:\Xash3D\src_main\server\global\client.cpp"
-]
-Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBB.tmp"
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBC.tmp" with contents
-[
-msvcrtd.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\server\!debug/server.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /def:".\server.def" /out:"..\temp\server\!debug/server.dll" /implib:"..\temp\server\!debug/server.lib" /pdbtype:sept
-"\Xash3D\src_main\temp\server\!debug\ai_sound.obj"
-"\Xash3D\src_main\temp\server\!debug\animating.obj"
-"\Xash3D\src_main\temp\server\!debug\animation.obj"
-"\Xash3D\src_main\temp\server\!debug\apache.obj"
-"\Xash3D\src_main\temp\server\!debug\barnacle.obj"
-"\Xash3D\src_main\temp\server\!debug\barney.obj"
-"\Xash3D\src_main\temp\server\!debug\basebrush.obj"
-"\Xash3D\src_main\temp\server\!debug\baseentity.obj"
-"\Xash3D\src_main\temp\server\!debug\basefunc.obj"
-"\Xash3D\src_main\temp\server\!debug\basefx.obj"
-"\Xash3D\src_main\temp\server\!debug\baseinfo.obj"
-"\Xash3D\src_main\temp\server\!debug\baseitem.obj"
-"\Xash3D\src_main\temp\server\!debug\baselogic.obj"
-"\Xash3D\src_main\temp\server\!debug\basemonster.obj"
-"\Xash3D\src_main\temp\server\!debug\basemover.obj"
-"\Xash3D\src_main\temp\server\!debug\baseother.obj"
-"\Xash3D\src_main\temp\server\!debug\basepath.obj"
-"\Xash3D\src_main\temp\server\!debug\basephys.obj"
-"\Xash3D\src_main\temp\server\!debug\baserockets.obj"
-"\Xash3D\src_main\temp\server\!debug\basetank.obj"
-"\Xash3D\src_main\temp\server\!debug\basetrigger.obj"
-"\Xash3D\src_main\temp\server\!debug\baseutil.obj"
-"\Xash3D\src_main\temp\server\!debug\baseweapon.obj"
-"\Xash3D\src_main\temp\server\!debug\baseworld.obj"
-"\Xash3D\src_main\temp\server\!debug\client.obj"
-"\Xash3D\src_main\temp\server\!debug\combat.obj"
-"\Xash3D\src_main\temp\server\!debug\decals.obj"
-"\Xash3D\src_main\temp\server\!debug\defaultai.obj"
-"\Xash3D\src_main\temp\server\!debug\dll_int.obj"
-"\Xash3D\src_main\temp\server\!debug\flyingmonster.obj"
-"\Xash3D\src_main\temp\server\!debug\game.obj"
-"\Xash3D\src_main\temp\server\!debug\gamerules.obj"
-"\Xash3D\src_main\temp\server\!debug\generic.obj"
-"\Xash3D\src_main\temp\server\!debug\globals.obj"
-"\Xash3D\src_main\temp\server\!debug\gman.obj"
-"\Xash3D\src_main\temp\server\!debug\hassassin.obj"
-"\Xash3D\src_main\temp\server\!debug\headcrab.obj"
-"\Xash3D\src_main\temp\server\!debug\hgrunt.obj"
-"\Xash3D\src_main\temp\server\!debug\leech.obj"
-"\Xash3D\src_main\temp\server\!debug\legacy.obj"
-"\Xash3D\src_main\temp\server\!debug\lights.obj"
-"\Xash3D\src_main\temp\server\!debug\multiplay_gamerules.obj"
-"\Xash3D\src_main\temp\server\!debug\nodes.obj"
-"\Xash3D\src_main\temp\server\!debug\osprey.obj"
-"\Xash3D\src_main\temp\server\!debug\parent.obj"
-"\Xash3D\src_main\temp\server\!debug\player.obj"
-"\Xash3D\src_main\temp\server\!debug\rat.obj"
-"\Xash3D\src_main\temp\server\!debug\roach.obj"
-"\Xash3D\src_main\temp\server\!debug\saverestore.obj"
-"\Xash3D\src_main\temp\server\!debug\scientist.obj"
-"\Xash3D\src_main\temp\server\!debug\scripted.obj"
-"\Xash3D\src_main\temp\server\!debug\sfx.obj"
-"\Xash3D\src_main\temp\server\!debug\singleplay_gamerules.obj"
-"\Xash3D\src_main\temp\server\!debug\sound.obj"
-"\Xash3D\src_main\temp\server\!debug\squadmonster.obj"
-"\Xash3D\src_main\temp\server\!debug\talkmonster.obj"
-"\Xash3D\src_main\temp\server\!debug\teamplay_gamerules.obj"
-"\Xash3D\src_main\temp\server\!debug\turret.obj"
-"\Xash3D\src_main\temp\server\!debug\utils.obj"
-"\Xash3D\src_main\temp\server\!debug\weapon_generic.obj"
-"\Xash3D\src_main\temp\server\!debug\zombie.obj"
-]
-Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBC.tmp"
-Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBD.bat" with contents
-[
-@echo off
-copy \Xash3D\src_main\temp\server\!debug\server.dll "D:\Xash3D\bin\server.dll"
-]
-Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBD.bat"
-Compiling...
-client.cpp
-Linking...
-Output Window
-Performing Custom Build Step on \Xash3D\src_main\temp\server\!debug\server.dll
-Скопировано файлов: 1.
-
-
-
-Results
-server.dll - 0 error(s), 0 warning(s)
-
-
-
diff --git a/todo.log b/todo.log
index 0a122e8d..9529e899 100644
--- a/todo.log
+++ b/todo.log
@@ -111,9 +111,10 @@ Beta 13.12.08
80. implement $rgb, $alpha OK
89. get rid of R_Upload32 OK
90. get rid of Com_ParseExt OK
-91. Xash backend extensions
+91. implement rendermodes
92. implement VBO OK
93. implement sky rotate
94. make default sky shader, R_SetupSky
-95. support for custom tables (external)
-96. implement sprite format
+95. support for custom tables (external) OK
+96. implement sprite format
+97. fix fog color on q3tourney5