Merge branch 'master' into sdl2

This commit is contained in:
Tim Angus 2013-11-02 19:12:52 +00:00
commit 779ebfacfd
32 changed files with 996 additions and 1795 deletions

View file

@ -2429,6 +2429,9 @@ void CL_InitServerInfo( serverInfo_t *server, netadr_t *address ) {
server->game[0] = '\0'; server->game[0] = '\0';
server->gameType = 0; server->gameType = 0;
server->netType = 0; server->netType = 0;
server->punkbuster = 0;
server->g_humanplayers = 0;
server->g_needpass = 0;
} }
#define MAX_SERVERSPERPACKET 256 #define MAX_SERVERSPERPACKET 256
@ -2937,13 +2940,13 @@ void CL_Frame ( int msec ) {
if ( CL_VideoRecording( ) && cl_aviFrameRate->integer && msec) { if ( CL_VideoRecording( ) && cl_aviFrameRate->integer && msec) {
// save the current screen // save the current screen
if ( clc.state == CA_ACTIVE || cl_forceavidemo->integer) { if ( clc.state == CA_ACTIVE || cl_forceavidemo->integer) {
float fps = MIN(cl_aviFrameRate->value * com_timescale->value, 1000.0f);
float frameDuration = MAX(1000.0f / fps, 1.0f) + clc.aviVideoFrameRemainder;
CL_TakeVideoFrame( ); CL_TakeVideoFrame( );
// fixed time for next frame' msec = (int)frameDuration;
msec = (int)ceil( (1000.0f / cl_aviFrameRate->value) * com_timescale->value ); clc.aviVideoFrameRemainder = frameDuration - msec;
if (msec == 0) {
msec = 1;
}
} }
} }
@ -3836,20 +3839,7 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
// add this to the list // add this to the list
cls.numlocalservers = i+1; cls.numlocalservers = i+1;
cls.localServers[i].adr = from; CL_InitServerInfo( &cls.localServers[i], &from );
cls.localServers[i].clients = 0;
cls.localServers[i].hostName[0] = '\0';
cls.localServers[i].mapName[0] = '\0';
cls.localServers[i].maxClients = 0;
cls.localServers[i].maxPing = 0;
cls.localServers[i].minPing = 0;
cls.localServers[i].ping = -1;
cls.localServers[i].game[0] = '\0';
cls.localServers[i].gameType = 0;
cls.localServers[i].netType = from.type;
cls.localServers[i].punkbuster = 0;
cls.localServers[i].g_humanplayers = 0;
cls.localServers[i].g_needpass = 0;
Q_strncpyz( info, MSG_ReadString( msg ), MAX_INFO_STRING ); Q_strncpyz( info, MSG_ReadString( msg ), MAX_INFO_STRING );
if (strlen(info)) { if (strlen(info)) {

View file

@ -233,6 +233,9 @@ typedef struct {
int timeDemoMaxDuration; // maximum frame duration int timeDemoMaxDuration; // maximum frame duration
unsigned char timeDemoDurations[ MAX_TIMEDEMO_DURATIONS ]; // log of frame durations unsigned char timeDemoDurations[ MAX_TIMEDEMO_DURATIONS ]; // log of frame durations
float aviVideoFrameRemainder;
float aviSoundFrameRemainder;
#ifdef USE_VOIP #ifdef USE_VOIP
qboolean voipEnabled; qboolean voipEnabled;
qboolean speexInitialized; qboolean speexInitialized;

View file

@ -271,6 +271,11 @@ static sfx_t *S_FindName( const char *name ) {
return NULL; return NULL;
} }
if (name[0] == '*') {
Com_Printf( S_COLOR_YELLOW "WARNING: Tried to load player sound directly: %s\n", name );
return NULL;
}
hash = S_HashSFXName(name); hash = S_HashSFXName(name);
sfx = sfxHash[hash]; sfx = sfxHash[hash];
@ -1237,7 +1242,13 @@ void S_GetSoundtime(void)
if( CL_VideoRecording( ) ) if( CL_VideoRecording( ) )
{ {
s_soundtime += (int)ceil( dma.speed / cl_aviFrameRate->value ); float fps = MIN(cl_aviFrameRate->value, 1000.0f);
float frameDuration = MAX(dma.speed / fps, 1.0f) + clc.aviSoundFrameRemainder;
int msec = (int)frameDuration;
s_soundtime += msec;
clc.aviSoundFrameRemainder = frameDuration - msec;
return; return;
} }

View file

@ -208,11 +208,6 @@ qboolean S_LoadSound( sfx_t *sfx )
snd_info_t info; snd_info_t info;
// int size; // int size;
// player specific sounds are never directly loaded
if ( sfx->soundName[0] == '*') {
return qfalse;
}
// load it in // load it in
data = S_CodecLoad(sfx->soundName, &info); data = S_CodecLoad(sfx->soundName, &info);
if(!data) if(!data)

View file

@ -208,6 +208,11 @@ static sfxHandle_t S_AL_BufferFind(const char *filename)
return 0; return 0;
} }
if ( filename[0] == '*' ) {
Com_Printf( S_COLOR_YELLOW "WARNING: Tried to load player sound directly: %s\n", filename );
return 0;
}
for(i = 0; i < numSfx; i++) for(i = 0; i < numSfx; i++)
{ {
if(!Q_stricmp(knownSfx[i].filename, filename)) if(!Q_stricmp(knownSfx[i].filename, filename))
@ -325,10 +330,6 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
if(curSfx->filename[0] == '\0') if(curSfx->filename[0] == '\0')
return; return;
// Player SFX
if(curSfx->filename[0] == '*')
return;
// Already done? // Already done?
if((curSfx->inMemory) || (curSfx->isDefault) || (!cache && curSfx->isDefaultChecked)) if((curSfx->inMemory) || (curSfx->isDefault) || (!cache && curSfx->isDefaultChecked))
return; return;

View file

@ -874,16 +874,6 @@ void GL_SetDefaultState( void )
qglEnable( GL_SCISSOR_TEST ); qglEnable( GL_SCISSOR_TEST );
qglDisable( GL_CULL_FACE ); qglDisable( GL_CULL_FACE );
qglDisable( GL_BLEND ); qglDisable( GL_BLEND );
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
qglClearDepth( 1.0 );
qglDrawBuffer( GL_FRONT );
qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
qglDrawBuffer( GL_BACK );
qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
} }
/* /*

View file

@ -41,10 +41,6 @@ typedef unsigned int glIndex_t;
#define SHADERNUM_BITS 14 #define SHADERNUM_BITS 14
#define MAX_SHADERS (1<<SHADERNUM_BITS) #define MAX_SHADERS (1<<SHADERNUM_BITS)
//#define MAX_SHADER_STATES 2048
#define MAX_STATES_PER_SHADER 32
#define MAX_STATE_NAME 32
typedef struct dlight_s { typedef struct dlight_s {
@ -266,7 +262,6 @@ typedef struct {
int videoMapHandle; int videoMapHandle;
qboolean isLightmap; qboolean isLightmap;
qboolean vertexLightmap;
qboolean isVideoMap; qboolean isVideoMap;
} textureBundle_t; } textureBundle_t;
@ -370,27 +365,11 @@ typedef struct shader_s {
float clampTime; // time this shader is clamped to float clampTime; // time this shader is clamped to
float timeOffset; // current time offset for this shader float timeOffset; // current time offset for this shader
int numStates; // if non-zero this is a state shader
struct shader_s *currentShader; // current state if this is a state shader
struct shader_s *parentShader; // current state if this is a state shader
int currentState; // current state index for cycle purposes
long expireTime; // time in milliseconds this expires
struct shader_s *remappedShader; // current shader this one is remapped too struct shader_s *remappedShader; // current shader this one is remapped too
int shaderStates[MAX_STATES_PER_SHADER]; // index to valid shader states
struct shader_s *next; struct shader_s *next;
} shader_t; } shader_t;
typedef struct shaderState_s {
char shaderName[MAX_QPATH]; // name of shader this state belongs to
char name[MAX_STATE_NAME]; // name of this state
char stateShader[MAX_QPATH]; // shader this name invokes
int cycleTime; // time this cycle lasts, <= 0 is forever
shader_t *shader;
} shaderState_t;
// trRefdef_t holds everything that comes in refdef_t, // trRefdef_t holds everything that comes in refdef_t,
// as well as the locally generated scene information // as well as the locally generated scene information
@ -610,6 +589,7 @@ typedef struct {
int num_frames; int num_frames;
int num_surfaces; int num_surfaces;
int num_joints; int num_joints;
int num_poses;
struct srfIQModel_s *surfaces; struct srfIQModel_s *surfaces;
float *positions; float *positions;
@ -617,10 +597,18 @@ typedef struct {
float *normals; float *normals;
float *tangents; float *tangents;
byte *blendIndexes; byte *blendIndexes;
byte *blendWeights; union {
float *f;
byte *b;
} blendWeights;
byte *colors; byte *colors;
int *triangles; int *triangles;
// depending upon the exporter, blend indices and weights might be int/float
// as opposed to the recommended byte/byte, for example Noesis exports
// int/float whereas the official IQM tool exports byte/byte
byte blendWeightsType; // IQM_UBYTE or IQM_FLOAT
int *jointParents; int *jointParents;
float *jointMats; float *jointMats;
float *poseMats; float *poseMats;

View file

@ -25,6 +25,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define LL(x) x=LittleLong(x) #define LL(x) x=LittleLong(x)
// 3x4 identity matrix
static float identityMatrix[12] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0
};
static qboolean IQM_CheckRange( iqmHeader_t *header, int offset, static qboolean IQM_CheckRange( iqmHeader_t *header, int offset,
int count,int size ) { int count,int size ) {
// return true if the range specified by offset, count and size // return true if the range specified by offset, count and size
@ -143,6 +150,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
iqmData_t *iqmData; iqmData_t *iqmData;
srfIQModel_t *surface; srfIQModel_t *surface;
char meshName[MAX_QPATH]; char meshName[MAX_QPATH];
byte blendIndexesType, blendWeightsType;
if( filesize < sizeof(iqmHeader_t) ) { if( filesize < sizeof(iqmHeader_t) ) {
return qfalse; return qfalse;
@ -198,6 +206,8 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
return qfalse; return qfalse;
} }
blendIndexesType = blendWeightsType = IQM_UBYTE;
// check and swap vertex arrays // check and swap vertex arrays
if( IQM_CheckRange( header, header->ofs_vertexarrays, if( IQM_CheckRange( header, header->ofs_vertexarrays,
header->num_vertexarrays, header->num_vertexarrays,
@ -264,11 +274,20 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
} }
break; break;
case IQM_BLENDINDEXES: case IQM_BLENDINDEXES:
case IQM_BLENDWEIGHTS: if( (vertexarray->format != IQM_INT &&
if( vertexarray->format != IQM_UBYTE || vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) { vertexarray->size != 4 ) {
return qfalse; return qfalse;
} }
blendIndexesType = vertexarray->format;
break;
case IQM_BLENDWEIGHTS:
if( (vertexarray->format != IQM_FLOAT &&
vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) {
return qfalse;
}
blendWeightsType = vertexarray->format;
break; break;
case IQM_COLOR: case IQM_COLOR:
if( vertexarray->format != IQM_UBYTE || if( vertexarray->format != IQM_UBYTE ||
@ -343,7 +362,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
} }
} }
if( header->num_poses != header->num_joints ) { if( header->num_poses != header->num_joints && header->num_poses != 0 ) {
ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has %d poses and %d joints, must have the same number or 0 poses\n",
mod_name, header->num_poses, header->num_joints );
return qfalse; return qfalse;
} }
@ -379,7 +400,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
joint_names += strlen( (char *)header + header->ofs_text + joint_names += strlen( (char *)header + header->ofs_text +
joint->name ) + 1; joint->name ) + 1;
} }
}
if ( header->num_poses )
{
// check and swap poses // check and swap poses
if( IQM_CheckRange( header, header->ofs_poses, if( IQM_CheckRange( header, header->ofs_poses,
header->num_poses, sizeof(iqmPose_t) ) ) { header->num_poses, sizeof(iqmPose_t) ) ) {
@ -438,7 +462,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
size = sizeof(iqmData_t); size = sizeof(iqmData_t);
size += header->num_meshes * sizeof( srfIQModel_t ); size += header->num_meshes * sizeof( srfIQModel_t );
size += header->num_joints * 12 * sizeof( float ); // joint mats size += header->num_joints * 12 * sizeof( float ); // joint mats
size += header->num_joints * header->num_frames * 12 * sizeof( float ); // pose mats size += header->num_poses * header->num_frames * 12 * sizeof( float ); // pose mats
if(header->ofs_bounds) if(header->ofs_bounds)
size += header->num_frames * 6 * sizeof(float); // model bounds size += header->num_frames * 6 * sizeof(float); // model bounds
size += header->num_vertexes * 3 * sizeof(float); // positions size += header->num_vertexes * 3 * sizeof(float); // positions
@ -446,12 +470,18 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
size += header->num_vertexes * 3 * sizeof(float); // normals size += header->num_vertexes * 3 * sizeof(float); // normals
size += header->num_vertexes * 4 * sizeof(float); // tangents size += header->num_vertexes * 4 * sizeof(float); // tangents
size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes
size += header->num_vertexes * 4 * sizeof(byte); // blendWeights
size += header->num_vertexes * 4 * sizeof(byte); // colors size += header->num_vertexes * 4 * sizeof(byte); // colors
size += header->num_joints * sizeof(int); // parents size += header->num_joints * sizeof(int); // parents
size += header->num_triangles * 3 * sizeof(int); // triangles size += header->num_triangles * 3 * sizeof(int); // triangles
size += joint_names; // joint names size += joint_names; // joint names
// blendWeights
if (blendWeightsType == IQM_FLOAT) {
size += header->num_vertexes * 4 * sizeof(float);
} else {
size += header->num_vertexes * 4 * sizeof(byte);
}
mod->type = MOD_IQM; mod->type = MOD_IQM;
iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low ); iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low );
mod->modelData = iqmData; mod->modelData = iqmData;
@ -462,28 +492,40 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
iqmData->num_frames = header->num_frames; iqmData->num_frames = header->num_frames;
iqmData->num_surfaces = header->num_meshes; iqmData->num_surfaces = header->num_meshes;
iqmData->num_joints = header->num_joints; iqmData->num_joints = header->num_joints;
iqmData->num_poses = header->num_poses;
iqmData->blendWeightsType = blendWeightsType;
iqmData->surfaces = (srfIQModel_t *)(iqmData + 1); iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces); iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints; iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints;
if(header->ofs_bounds) if(header->ofs_bounds)
{ {
iqmData->bounds = iqmData->poseMats + 12 * header->num_joints * header->num_frames; iqmData->bounds = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
iqmData->positions = iqmData->bounds + 6 * header->num_frames; iqmData->positions = iqmData->bounds + 6 * header->num_frames;
} }
else else
iqmData->positions = iqmData->poseMats + 12 * header->num_joints * header->num_frames; iqmData->positions = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes; iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes;
iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes; iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes;
iqmData->tangents = iqmData->normals + 3 * header->num_vertexes; iqmData->tangents = iqmData->normals + 3 * header->num_vertexes;
iqmData->blendIndexes = (byte *)(iqmData->tangents + 4 * header->num_vertexes); iqmData->blendIndexes = (byte *)(iqmData->tangents + 4 * header->num_vertexes);
iqmData->blendWeights = iqmData->blendIndexes + 4 * header->num_vertexes;
iqmData->colors = iqmData->blendWeights + 4 * header->num_vertexes; if(blendWeightsType == IQM_FLOAT) {
iqmData->blendWeights.f = (float *)(iqmData->blendIndexes + 4 * header->num_vertexes);
iqmData->colors = (byte *)(iqmData->blendWeights.f + 4 * header->num_vertexes);
} else {
iqmData->blendWeights.b = iqmData->blendIndexes + 4 * header->num_vertexes;
iqmData->colors = iqmData->blendWeights.b + 4 * header->num_vertexes;
}
iqmData->jointParents = (int *)(iqmData->colors + 4 * header->num_vertexes); iqmData->jointParents = (int *)(iqmData->colors + 4 * header->num_vertexes);
iqmData->triangles = iqmData->jointParents + header->num_joints; iqmData->triangles = iqmData->jointParents + header->num_joints;
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles); iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
if ( header->num_joints == 0 ) if ( header->num_joints == 0 )
iqmData->jointMats = iqmData->poseMats = NULL; iqmData->jointMats = NULL;
if ( header->num_poses == 0 )
iqmData->poseMats = NULL;
// calculate joint matrices and their inverses // calculate joint matrices and their inverses
// joint inverses are needed only until the pose matrices are calculated // joint inverses are needed only until the pose matrices are calculated
@ -620,14 +662,27 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
n * sizeof(float) ); n * sizeof(float) );
break; break;
case IQM_BLENDINDEXES: case IQM_BLENDINDEXES:
if( blendIndexesType == IQM_INT ) {
int *data = (int*)((byte*)header + vertexarray->offset);
for ( j = 0; j < n; j++ ) {
iqmData->blendIndexes[j] = (byte)data[j];
}
} else {
Com_Memcpy( iqmData->blendIndexes, Com_Memcpy( iqmData->blendIndexes,
(byte *)header + vertexarray->offset, (byte *)header + vertexarray->offset,
n * sizeof(byte) ); n * sizeof(byte) );
}
break; break;
case IQM_BLENDWEIGHTS: case IQM_BLENDWEIGHTS:
Com_Memcpy( iqmData->blendWeights, if( blendWeightsType == IQM_FLOAT ) {
Com_Memcpy( iqmData->blendWeights.f,
(byte *)header + vertexarray->offset,
n * sizeof(float) );
} else {
Com_Memcpy( iqmData->blendWeights.b,
(byte *)header + vertexarray->offset, (byte *)header + vertexarray->offset,
n * sizeof(byte) ); n * sizeof(byte) );
}
break; break;
case IQM_COLOR: case IQM_COLOR:
Com_Memcpy( iqmData->colors, Com_Memcpy( iqmData->colors,
@ -892,9 +947,21 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
int *joint = data->jointParents; int *joint = data->jointParents;
int i; int i;
if ( oldframe == frame ) { if ( data->num_poses == 0 ) {
mat1 = data->poseMats + 12 * data->num_joints * frame;
for( i = 0; i < data->num_joints; i++, joint++ ) { for( i = 0; i < data->num_joints; i++, joint++ ) {
if( *joint >= 0 ) {
Matrix34Multiply( mat + 12 * *joint,
identityMatrix, mat + 12*i );
} else {
Com_Memcpy( mat + 12*i, identityMatrix, 12 * sizeof(float) );
}
}
return;
}
if ( oldframe == frame ) {
mat1 = data->poseMats + 12 * data->num_poses * frame;
for( i = 0; i < data->num_poses; i++, joint++ ) {
if( *joint >= 0 ) { if( *joint >= 0 ) {
Matrix34Multiply( mat + 12 * *joint, Matrix34Multiply( mat + 12 * *joint,
mat1 + 12*i, mat + 12*i ); mat1 + 12*i, mat + 12*i );
@ -903,10 +970,10 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
} }
} }
} else { } else {
mat1 = data->poseMats + 12 * data->num_joints * frame; mat1 = data->poseMats + 12 * data->num_poses * frame;
mat2 = data->poseMats + 12 * data->num_joints * oldframe; mat2 = data->poseMats + 12 * data->num_poses * oldframe;
for( i = 0; i < data->num_joints; i++, joint++ ) { for( i = 0; i < data->num_poses; i++, joint++ ) {
if( *joint >= 0 ) { if( *joint >= 0 ) {
float tmpMat[12]; float tmpMat[12];
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i, InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
@ -974,7 +1041,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
outColor = &tess.vertexColors[tess.numVertexes]; outColor = &tess.vertexColors[tess.numVertexes];
// compute interpolated joint matrices // compute interpolated joint matrices
if ( data->num_joints > 0 ) { if ( data->num_poses > 0 ) {
ComputePoseMats( data, frame, oldframe, backlerp, jointMats ); ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
} }
@ -985,28 +1052,31 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
float vtxMat[12]; float vtxMat[12];
float nrmMat[9]; float nrmMat[9];
int vtx = i + surf->first_vertex; int vtx = i + surf->first_vertex;
float blendWeights[4];
int numWeights;
if ( data->num_joints == 0 || data->blendWeights[4*vtx] <= 0 ) { for ( numWeights = 0; numWeights < 4; numWeights++ ) {
// no blend joint, use identity matrix. if ( data->blendWeightsType == IQM_FLOAT )
for( j = 0; j < 3; j++ ) { blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights];
for( k = 0; k < 4; k++ ) else
vtxMat[4*j+k] = ( k == j ) ? 1 : 0; blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f;
if ( blendWeights[numWeights] <= 0 )
break;
} }
if ( data->num_poses == 0 || numWeights == 0 ) {
// no blend joint, use identity matrix.
Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) );
} else { } else {
// compute the vertex matrix by blending the up to // compute the vertex matrix by blending the up to
// four blend weights // four blend weights
for( k = 0; k < 12; k++ ) Com_Memset( vtxMat, 0, 12 * sizeof (float) );
vtxMat[k] = data->blendWeights[4*vtx] for( j = 0; j < numWeights; j++ ) {
* jointMats[12*data->blendIndexes[4*vtx] + k]; for( k = 0; k < 12; k++ ) {
for( j = 1; j < 4; j++ ) { vtxMat[k] += blendWeights[j] * jointMats[12*data->blendIndexes[4*vtx + j] + k];
if( data->blendWeights[4*vtx + j] <= 0 ) }
break;
for( k = 0; k < 12; k++ )
vtxMat[k] += data->blendWeights[4*vtx + j]
* jointMats[12*data->blendIndexes[4*vtx + j] + k];
} }
for( k = 0; k < 12; k++ )
vtxMat[k] *= 1.0f / 255.0f;
} }
// compute the normal matrix as transpose of the adjoint // compute the normal matrix as transpose of the adjoint

View file

@ -1145,11 +1145,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
// //
// set state // set state
// //
if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer )
{
GL_Bind( tr.whiteImage );
}
else
R_BindAnimatedImage( &pStage->bundle[0] ); R_BindAnimatedImage( &pStage->bundle[0] );
GL_State( pStage->stateBits ); GL_State( pStage->stateBits );
@ -1160,7 +1155,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
R_DrawElements( input->numIndexes, input->indexes ); R_DrawElements( input->numIndexes, input->indexes );
} }
// allow skipping out to show just lightmaps during development // allow skipping out to show just lightmaps during development
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) ) if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) )
{ {
break; break;
} }

View file

@ -85,14 +85,11 @@ float CalcFog(vec4 position)
float s = dot(position, u_FogDistance) * 8.0; float s = dot(position, u_FogDistance) * 8.0;
float t = dot(position, u_FogDepth); float t = dot(position, u_FogDepth);
if (t < 1.0) float eyeOutside = step(0.0, -u_FogEyeT);
{ float fogged = step(eyeOutside, t);
t = step(step(0.0, -u_FogEyeT), t);
} t = max(t, 1e-6);
else t *= fogged / (t - u_FogEyeT * eyeOutside);
{
t /= t - min(u_FogEyeT, 0.0);
}
return s * t; return s * t;
} }

View file

@ -17,7 +17,7 @@ uniform vec4 u_DiffuseTexMatrix;
uniform vec4 u_DiffuseTexOffTurb; uniform vec4 u_DiffuseTexOffTurb;
#if defined(USE_TCGEN) || defined(USE_RGBAGEN) #if defined(USE_TCGEN) || defined(USE_RGBAGEN)
uniform vec3 u_ViewOrigin; uniform vec3 u_LocalViewOrigin;
#endif #endif
#if defined(USE_TCGEN) #if defined(USE_TCGEN)
@ -48,7 +48,7 @@ uniform int u_ColorGen;
uniform int u_AlphaGen; uniform int u_AlphaGen;
uniform vec3 u_AmbientLight; uniform vec3 u_AmbientLight;
uniform vec3 u_DirectedLight; uniform vec3 u_DirectedLight;
uniform vec4 u_LightOrigin; uniform vec3 u_ModelLightDir;
uniform float u_PortalRange; uniform float u_PortalRange;
#endif #endif
@ -93,7 +93,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
} }
else if (u_DeformGen == DGEN_WAVE_TRIANGLE) else if (u_DeformGen == DGEN_WAVE_TRIANGLE)
{ {
func = abs(fract(value + 0.75) - 0.5) * 4.0 - 1.0; func = 1.0 - abs(4.0 * fract(value + 0.25) - 2.0);
} }
else if (u_DeformGen == DGEN_WAVE_SAWTOOTH) else if (u_DeformGen == DGEN_WAVE_SAWTOOTH)
{ {
@ -123,7 +123,7 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3
} }
else if (TCGen == TCGEN_ENVIRONMENT_MAPPED) else if (TCGen == TCGEN_ENVIRONMENT_MAPPED)
{ {
vec3 viewer = normalize(u_ViewOrigin - position); vec3 viewer = normalize(u_LocalViewOrigin - position);
tex = -reflect(viewer, normal).yz * vec2(0.5, -0.5) + 0.5; tex = -reflect(viewer, normal).yz * vec2(0.5, -0.5) + 0.5;
} }
else if (TCGen == TCGEN_VECTOR) else if (TCGen == TCGEN_VECTOR)
@ -158,30 +158,25 @@ vec4 CalcColor(vec3 position, vec3 normal)
if (u_ColorGen == CGEN_LIGHTING_DIFFUSE) if (u_ColorGen == CGEN_LIGHTING_DIFFUSE)
{ {
float incoming = clamp(dot(normal, u_LightOrigin.xyz), 0.0, 1.0); float incoming = clamp(dot(normal, u_ModelLightDir), 0.0, 1.0);
color.rgb = clamp(u_DirectedLight * incoming + u_AmbientLight, 0.0, 1.0); color.rgb = clamp(u_DirectedLight * incoming + u_AmbientLight, 0.0, 1.0);
} }
vec3 toView = u_ViewOrigin - position; vec3 viewer = u_LocalViewOrigin - position;
vec3 viewer = normalize(u_ViewOrigin - position);
if (u_AlphaGen == AGEN_LIGHTING_SPECULAR) if (u_AlphaGen == AGEN_LIGHTING_SPECULAR)
{ {
vec3 lightDir = normalize(vec3(-960.0, -1980.0, 96.0) - position.xyz); vec3 lightDir = normalize(vec3(-960.0, 1980.0, 96.0) - position.xyz);
vec3 halfangle = normalize(lightDir + viewer); vec3 reflected = -reflect(lightDir, normal);
color.a = pow(max(dot(normal, halfangle), 0.0), 8.0); color.a = clamp(dot(reflected, normalize(viewer)), 0.0, 1.0);
color.a *= color.a;
color.a *= color.a;
} }
else if (u_AlphaGen == AGEN_PORTAL) else if (u_AlphaGen == AGEN_PORTAL)
{ {
float alpha = length(toView) / u_PortalRange; color.a = clamp(length(viewer) / u_PortalRange, 0.0, 1.0);
color.a = clamp(alpha, 0.0, 1.0);
}
else if (u_AlphaGen == AGEN_FRESNEL)
{
color.a = 0.10 + 0.90 * pow(1.0 - dot(normal, viewer), 5);
} }
return color; return color;
@ -194,14 +189,11 @@ float CalcFog(vec4 position)
float s = dot(position, u_FogDistance) * 8.0; float s = dot(position, u_FogDistance) * 8.0;
float t = dot(position, u_FogDepth); float t = dot(position, u_FogDepth);
if (t < 1.0) float eyeOutside = step(0.0, -u_FogEyeT);
{ float fogged = step(eyeOutside, t);
t = step(step(0.0, -u_FogEyeT), t);
} t = max(t, 1e-6);
else t *= fogged / (t - u_FogEyeT * eyeOutside);
{
t /= t - min(u_FogEyeT, 0.0);
}
return s * t; return s * t;
} }

View file

@ -24,45 +24,40 @@ uniform sampler2D u_ShadowMap;
uniform samplerCube u_CubeMap; uniform samplerCube u_CubeMap;
#endif #endif
#if defined(USE_LIGHT_VECTOR) #if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
uniform vec3 u_DirectedLight; uniform vec3 u_DirectedLight;
uniform vec3 u_AmbientLight; uniform vec3 u_AmbientLight;
uniform float u_LightRadius;
#endif #endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
uniform vec3 u_PrimaryLightColor; uniform vec3 u_PrimaryLightColor;
uniform vec3 u_PrimaryLightAmbient; uniform vec3 u_PrimaryLightAmbient;
uniform float u_PrimaryLightRadius;
#endif #endif
#if defined(USE_LIGHT) #if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
uniform vec2 u_MaterialInfo; uniform vec2 u_MaterialInfo;
#endif #endif
varying vec2 var_DiffuseTex; varying vec4 var_TexCoords;
#if defined(USE_LIGHTMAP)
varying vec2 var_LightTex;
#endif
varying vec4 var_Color; varying vec4 var_Color;
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
varying vec3 var_ViewDir; varying vec4 var_Normal;
varying vec3 var_Normal; varying vec4 var_Tangent;
varying vec3 var_Tangent; varying vec4 var_Bitangent;
varying vec3 var_Bitangent;
#endif #endif
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT) #if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
varying vec3 var_lightColor; varying vec3 var_LightColor;
#endif #endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) #if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
varying vec4 var_LightDir; varying vec4 var_LightDir;
#endif #endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
varying vec3 var_PrimaryLightDir; varying vec4 var_PrimaryLightDir;
#endif #endif
@ -181,17 +176,21 @@ float CalcBlinn(float NH, float shininess)
#endif #endif
} }
float CalcGGX(float NH, float shininess) float CalcGGX(float NH, float gloss)
{ {
// from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes.pdf // from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
float m_sq = 2.0 / shininess; float a_sq = exp2(gloss * -13.0 + 1.0);
float d = ((NH * NH) * (m_sq - 1.0) + 1.0); float d = ((NH * NH) * (a_sq - 1.0) + 1.0);
return m_sq / (d * d); return a_sq / (d * d);
} }
float CalcFresnel(float EH) float CalcFresnel(float EH)
{ {
#if 1 #if 1
// From http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
// not accurate, but fast
return exp2(-10.0 * EH);
#elif 0
// From http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/ // From http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/
return exp2((-5.55473 * EH - 6.98316) * EH); return exp2((-5.55473 * EH - 6.98316) * EH);
#elif 0 #elif 0
@ -201,42 +200,48 @@ float CalcFresnel(float EH)
return blend; return blend;
#else #else
return pow(1.0 - NH, 5.0); return pow(1.0 - EH, 5.0);
#endif #endif
} }
float CalcVisibility(float NH, float NL, float NE, float EH, float shininess) float CalcVisibility(float NH, float NL, float NE, float EH, float gloss)
{ {
#if 0 #if 1
float geo = 2.0 * NH * min(NE, NL); // From http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
geo /= max(EH, geo); float k = min(1.0, gloss + 0.545);
return 1.0 / (k * EH * EH + (1.0 - k));
#elif 0
float roughness = exp2(gloss * -6.5);
return geo;
#else
// Modified from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes.pdf
// NL, NE in numerator factored out from cook-torrance
#if defined(USE_GGX) #if defined(USE_GGX)
float roughness = sqrt(2.0 / (shininess + 2.0)); // From http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
float k = (roughness + 1.0); float k = roughness + 1.0;
k *= k * 0.125; k *= k * 0.125;
#else #else
float k = 2.0 / sqrt(3.1415926535 * (shininess + 2.0)); float k = roughness;
#endif #endif
// Modified from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
// NL, NE in numerator factored out from cook-torrance
float k2 = 1.0 - k; float k2 = 1.0 - k;
float invGeo1 = NL * k2 + k; float invGeo1 = NL * k2 + k;
float invGeo2 = NE * k2 + k; float invGeo2 = NE * k2 + k;
return 1.0 / (invGeo1 * invGeo2); return 1.0 / (invGeo1 * invGeo2);
#endif #else
float geo = 2.0 * NH * min(NE, NL);
geo /= max(EH, geo);
return geo;
#endif
} }
vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float shininess) vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float gloss, float shininess)
{ {
float blinn = CalcBlinn(NH, shininess); float blinn = CalcBlinn(NH, shininess);
vec3 fSpecular = mix(specular, vec3(1.0), CalcFresnel(EH)); vec3 fSpecular = mix(specular, vec3(1.0), CalcFresnel(EH));
float vis = CalcVisibility(NH, NL, NE, EH, shininess); float vis = CalcVisibility(NH, NL, NE, EH, gloss);
#if defined(USE_BLINN) #if defined(USE_BLINN)
// Normalized Blinn-Phong // Normalized Blinn-Phong
@ -261,17 +266,41 @@ vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float s
return vec3(0.0); return vec3(0.0);
} }
float CalcLightAttenuation(vec3 dir, float sqrRadius)
{
// point light at >0 radius, directional otherwise
float point = float(sqrRadius > 0.0);
// inverse square light
float attenuation = sqrRadius / dot(dir, dir);
// zero light at radius, approximating q3 style
// also don't attenuate directional light
attenuation = (0.5 * attenuation - 1.5) * point + 1.0;
// clamp attenuation
#if defined(NO_LIGHT_CLAMP)
attenuation = max(attenuation, 0.0);
#else
attenuation = clamp(attenuation, 0.0, 1.0);
#endif
return attenuation;
}
void main() void main()
{ {
vec3 L, N, E, H; vec3 L, N, E, H;
float NL, NH, NE, EH; float NL, NH, NE, EH;
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
mat3 tangentToWorld = mat3(var_Tangent, var_Bitangent, var_Normal); mat3 tangentToWorld = mat3(var_Tangent.xyz, var_Bitangent.xyz, var_Normal.xyz);
#endif #endif
#if defined(USE_DELUXEMAP) #if defined(USE_DELUXEMAP)
L = (2.0 * texture2D(u_DeluxeMap, var_LightTex).xyz - vec3(1.0)); L = (2.0 * texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(1.0));
#if defined(USE_TANGENT_SPACE_LIGHT) #if defined(USE_TANGENT_SPACE_LIGHT)
L = L * tangentToWorld; L = L * tangentToWorld;
#endif #endif
@ -280,41 +309,23 @@ void main()
#endif #endif
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
E = normalize(var_ViewDir); E = normalize(vec3(var_Normal.w, var_Tangent.w, var_Bitangent.w));
#endif #endif
#if defined(USE_LIGHTMAP) #if defined(USE_LIGHTMAP)
vec4 lightSample = texture2D(u_LightMap, var_LightTex).rgba; vec4 lightSample = texture2D(u_LightMap, var_TexCoords.zw).rgba;
#if defined(RGBM_LIGHTMAP) #if defined(RGBM_LIGHTMAP)
lightSample.rgb *= 32.0 * lightSample.a; lightSample.rgb *= 32.0 * lightSample.a;
#endif #endif
vec3 lightColor = lightSample.rgb; vec3 lightColor = lightSample.rgb;
#elif defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT) #elif defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
// inverse square light vec3 lightColor = u_DirectedLight * CalcLightAttenuation(L, var_LightDir.w);
float attenuation = u_LightRadius * u_LightRadius / dot(L, L);
// zero light at radius, approximating q3 style
attenuation = 0.5 * attenuation - 0.5;
//attenuation = 0.0697168 * attenuation;
//attenuation *= step(0.294117, attenuation);
// clamp attenuation
#if defined(NO_LIGHT_CLAMP)
attenuation *= step(0.0, attenuation);
#else
attenuation = clamp(attenuation, 0.0, 1.0);
#endif
// don't attenuate directional light
attenuation = (attenuation - 1.0) * var_LightDir.w + 1.0;
vec3 lightColor = u_DirectedLight * attenuation;
vec3 ambientColor = u_AmbientLight; vec3 ambientColor = u_AmbientLight;
#elif defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT) #elif defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
vec3 lightColor = var_lightColor; vec3 lightColor = var_LightColor;
#endif #endif
vec2 texCoords = var_DiffuseTex; vec2 texCoords = var_TexCoords.xy;
#if defined(USE_PARALLAXMAP) #if defined(USE_PARALLAXMAP)
#if defined(USE_TANGENT_SPACE_LIGHT) #if defined(USE_TANGENT_SPACE_LIGHT)
@ -329,13 +340,12 @@ void main()
#endif #endif
vec4 diffuse = texture2D(u_DiffuseMap, texCoords); vec4 diffuse = texture2D(u_DiffuseMap, texCoords);
#if defined(USE_GAMMA2_TEXTURES)
diffuse.rgb *= diffuse.rgb;
#endif
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) #if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
#if defined(USE_LINEAR_LIGHT)
diffuse.rgb *= diffuse.rgb;
#endif
#if defined(USE_NORMALMAP) #if defined(USE_NORMALMAP)
#if defined(SWIZZLE_NORMALMAP) #if defined(SWIZZLE_NORMALMAP)
N.xy = 2.0 * texture2D(u_NormalMap, texCoords).ag - vec2(1.0); N.xy = 2.0 * texture2D(u_NormalMap, texCoords).ag - vec2(1.0);
@ -349,7 +359,7 @@ void main()
#elif defined(USE_TANGENT_SPACE_LIGHT) #elif defined(USE_TANGENT_SPACE_LIGHT)
N = vec3(0.0, 0.0, 1.0); N = vec3(0.0, 0.0, 1.0);
#else #else
N = normalize(var_Normal); N = normalize(var_Normal.xyz);
#endif #endif
L = normalize(L); L = normalize(L);
@ -362,7 +372,7 @@ void main()
#if defined(USE_TANGENT_SPACE_LIGHT) #if defined(USE_TANGENT_SPACE_LIGHT)
shadowValue *= step(0.0, var_PrimaryLightDir.z); shadowValue *= step(0.0, var_PrimaryLightDir.z);
#else #else
shadowValue *= step(0.0, dot(var_Normal, var_PrimaryLightDir)); shadowValue *= step(0.0, dot(var_Normal.xyz, var_PrimaryLightDir.xyz));
#endif #endif
#if defined(SHADOWMAP_MODULATE) #if defined(SHADOWMAP_MODULATE)
@ -371,7 +381,7 @@ void main()
#if 0 #if 0
// Only shadow when the world light is parallel to the primary light // Only shadow when the world light is parallel to the primary light
shadowValue = 1.0 + (shadowValue - 1.0) * clamp(dot(L, var_PrimaryLightDir), 0.0, 1.0); shadowValue = 1.0 + (shadowValue - 1.0) * clamp(dot(L, var_PrimaryLightDir.xyz), 0.0, 1.0);
#endif #endif
lightColor = mix(shadowColor, lightColor, shadowValue); lightColor = mix(shadowColor, lightColor, shadowValue);
#endif #endif
@ -383,7 +393,7 @@ void main()
#if defined(USE_TANGENT_SPACE_LIGHT) #if defined(USE_TANGENT_SPACE_LIGHT)
float surfNL = L.z; float surfNL = L.z;
#else #else
float surfNL = clamp(dot(var_Normal, L), 0.0, 1.0); float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0);
#endif #endif
// Scale the incoming light to compensate for the baked-in light angle // Scale the incoming light to compensate for the baked-in light angle
@ -402,7 +412,7 @@ void main()
#if defined(USE_SPECULARMAP) #if defined(USE_SPECULARMAP)
vec4 specular = texture2D(u_SpecularMap, texCoords); vec4 specular = texture2D(u_SpecularMap, texCoords);
#if defined(USE_LINEAR_LIGHT) #if defined(USE_GAMMA2_TEXTURES)
specular.rgb *= specular.rgb; specular.rgb *= specular.rgb;
#endif #endif
#else #else
@ -413,7 +423,6 @@ void main()
float gloss = specular.a; float gloss = specular.a;
float shininess = exp2(gloss * 13.0); float shininess = exp2(gloss * 13.0);
float localOcclusion = clamp((diffuse.r + diffuse.g + diffuse.b) * 16.0f, 0.0, 1.0);
#if defined(SPECULAR_IS_METALLIC) #if defined(SPECULAR_IS_METALLIC)
// diffuse is actually base color, and red of specular is metallicness // diffuse is actually base color, and red of specular is metallicness
@ -430,10 +439,12 @@ void main()
reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess); reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess);
#if defined(r_deluxeSpecular) || defined(USE_LIGHT_VECTOR) #if defined(r_deluxeSpecular) || defined(USE_LIGHT_VECTOR)
float adjGloss = gloss;
float adjShininess = shininess; float adjShininess = shininess;
#if !defined(USE_LIGHT_VECTOR) #if !defined(USE_LIGHT_VECTOR)
adjShininess = exp2(gloss * r_deluxeSpecular * 13.0); adjGloss *= r_deluxeSpecular;
adjShininess = exp2(adjGloss * 13.0);
#endif #endif
H = normalize(L + E); H = normalize(L + E);
@ -442,9 +453,9 @@ void main()
NH = clamp(dot(N, H), 0.0, 1.0); NH = clamp(dot(N, H), 0.0, 1.0);
#if !defined(USE_LIGHT_VECTOR) #if !defined(USE_LIGHT_VECTOR)
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjShininess) * r_deluxeSpecular * localOcclusion; reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess) * r_deluxeSpecular;
#else #else
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjShininess) * localOcclusion; reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess);
#endif #endif
#endif #endif
@ -461,24 +472,20 @@ void main()
vec3 cubeLightColor = textureCubeLod(u_CubeMap, R, 7.0 - gloss * 7.0).rgb; vec3 cubeLightColor = textureCubeLod(u_CubeMap, R, 7.0 - gloss * 7.0).rgb;
#if defined(USE_LINEAR_LIGHT)
cubeLightColor *= cubeLightColor;
#endif
#if defined(USE_LIGHTMAP) #if defined(USE_LIGHTMAP)
cubeLightColor *= lightSample.rgb; cubeLightColor *= lightSample.rgb;
#elif defined (USE_LIGHT_VERTEX) #elif defined (USE_LIGHT_VERTEX)
cubeLightColor *= var_lightColor; cubeLightColor *= var_LightColor;
#else #else
cubeLightColor *= lightColor * NL + ambientColor; cubeLightColor *= lightColor * NL + ambientColor;
#endif #endif
//gl_FragColor.rgb += diffuse.rgb * textureCubeLod(u_CubeMap, N, 7.0).rgb; //gl_FragColor.rgb += diffuse.rgb * textureCubeLod(u_CubeMap, N, 7.0).rgb;
gl_FragColor.rgb += cubeLightColor * reflectance * localOcclusion; gl_FragColor.rgb += cubeLightColor * reflectance;
#endif #endif
#if defined(USE_PRIMARY_LIGHT) #if defined(USE_PRIMARY_LIGHT)
L = normalize(var_PrimaryLightDir); L = var_PrimaryLightDir.xyz; //normalize(var_PrimaryLightDir.xyz);
NL = clamp(dot(N, L), 0.0, 1.0); NL = clamp(dot(N, L), 0.0, 1.0);
H = normalize(L + E); H = normalize(L + E);
@ -486,17 +493,15 @@ void main()
NH = clamp(dot(N, H), 0.0, 1.0); NH = clamp(dot(N, H), 0.0, 1.0);
reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess); reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess);
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, shininess); reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, gloss, shininess);
lightColor = u_PrimaryLightColor; // * CalcLightAttenuation(L, u_PrimaryLightDir.w);
#if defined(USE_SHADOWMAP) #if defined(USE_SHADOWMAP)
reflectance *= shadowValue; lightColor *= shadowValue;
#endif #endif
gl_FragColor.rgb += u_PrimaryLightColor * reflectance * NL; gl_FragColor.rgb += lightColor * reflectance * NL;
#endif
#if defined(USE_LINEAR_LIGHT)
gl_FragColor.rgb = sqrt(gl_FragColor.rgb);
#endif #endif
gl_FragColor.a = diffuse.a; gl_FragColor.a = diffuse.a;

View file

@ -22,6 +22,7 @@ attribute vec3 attr_LightDirection;
#if defined(USE_TCGEN) || defined(USE_NORMALMAP) || defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) #if defined(USE_TCGEN) || defined(USE_NORMALMAP) || defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
uniform vec3 u_ViewOrigin; uniform vec3 u_ViewOrigin;
uniform vec3 u_LocalViewOrigin;
#endif #endif
#if defined(USE_TCGEN) #if defined(USE_TCGEN)
@ -49,37 +50,30 @@ uniform float u_VertexLerp;
#if defined(USE_LIGHT_VECTOR) #if defined(USE_LIGHT_VECTOR)
uniform vec4 u_LightOrigin; uniform vec4 u_LightOrigin;
#if defined(USE_FAST_LIGHT)
uniform vec3 u_DirectedLight;
uniform vec3 u_AmbientLight;
uniform float u_LightRadius; uniform float u_LightRadius;
uniform vec3 u_DirectedLight;
#if defined(USE_FAST_LIGHT)
uniform vec3 u_AmbientLight;
#endif #endif
#endif #endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
uniform vec4 u_PrimaryLightOrigin; uniform vec4 u_PrimaryLightOrigin;
uniform float u_PrimaryLightRadius;
#endif #endif
varying vec2 var_DiffuseTex; varying vec4 var_TexCoords;
#if defined(USE_LIGHTMAP)
varying vec2 var_LightTex;
#endif
#if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
varying vec3 var_ViewDir;
#endif
varying vec4 var_Color; varying vec4 var_Color;
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP) #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
varying vec3 var_Normal; varying vec4 var_Normal;
varying vec3 var_Tangent; varying vec4 var_Tangent;
varying vec3 var_Bitangent; varying vec4 var_Bitangent;
#endif #endif
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT) #if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
varying vec3 var_lightColor; varying vec3 var_LightColor;
#endif #endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT) #if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
@ -87,7 +81,7 @@ varying vec4 var_LightDir;
#endif #endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
varying vec3 var_PrimaryLightDir; varying vec4 var_PrimaryLightDir;
#endif #endif
#if defined(USE_TCGEN) #if defined(USE_TCGEN)
@ -101,7 +95,7 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3
} }
else if (TCGen == TCGEN_ENVIRONMENT_MAPPED) else if (TCGen == TCGEN_ENVIRONMENT_MAPPED)
{ {
vec3 viewer = normalize(u_ViewOrigin - position); vec3 viewer = normalize(u_LocalViewOrigin - position);
tex = -reflect(viewer, normal).yz * vec2(0.5, -0.5) + 0.5; tex = -reflect(viewer, normal).yz * vec2(0.5, -0.5) + 0.5;
} }
else if (TCGen == TCGEN_VECTOR) else if (TCGen == TCGEN_VECTOR)
@ -120,7 +114,7 @@ vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb)
float phase = offTurb.w; float phase = offTurb.w;
vec2 st2 = vec2(dot(st, texMatrix.xz), dot(st, texMatrix.yw)) + offTurb.xy; vec2 st2 = vec2(dot(st, texMatrix.xz), dot(st, texMatrix.yw)) + offTurb.xy;
vec3 offsetPos = position * 0.0009765625; vec3 offsetPos = position / 1024.0;
offsetPos.x += offsetPos.z; offsetPos.x += offsetPos.z;
vec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * M_PI); vec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * M_PI);
@ -130,6 +124,29 @@ vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb)
#endif #endif
float CalcLightAttenuation(vec3 dir, float sqrRadius)
{
// point light at >0 radius, directional otherwise
float point = float(sqrRadius > 0.0);
// inverse square light
float attenuation = sqrRadius / dot(dir, dir);
// zero light at radius, approximating q3 style
// also don't attenuate directional light
attenuation = (0.5 * attenuation - 1.5) * point + 1.0;
// clamp attenuation
#if defined(NO_LIGHT_CLAMP)
attenuation = max(attenuation, 0.0);
#else
attenuation = clamp(attenuation, 0.0, 1.0);
#endif
return attenuation;
}
void main() void main()
{ {
#if defined(USE_VERTEX_ANIMATION) #if defined(USE_VERTEX_ANIMATION)
@ -151,9 +168,9 @@ void main()
#endif #endif
#if defined(USE_TCMOD) #if defined(USE_TCMOD)
var_DiffuseTex = ModTexCoords(texCoords, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb); var_TexCoords.xy = ModTexCoords(texCoords, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb);
#else #else
var_DiffuseTex = texCoords; var_TexCoords.xy = texCoords;
#endif #endif
gl_Position = u_ModelViewProjectionMatrix * vec4(position, 1.0); gl_Position = u_ModelViewProjectionMatrix * vec4(position, 1.0);
@ -167,7 +184,7 @@ void main()
#if defined(USE_LIGHT_VECTOR) #if defined(USE_LIGHT_VECTOR)
vec3 L = u_LightOrigin.xyz - (position * u_LightOrigin.w); vec3 L = u_LightOrigin.xyz - (position * u_LightOrigin.w);
#elif defined(USE_LIGHT) && !defined(USE_LIGHT_VECTOR) #elif defined(USE_LIGHT) && !defined(USE_DELUXEMAP)
vec3 L = attr_LightDirection; vec3 L = attr_LightDirection;
#if defined(USE_MODELMATRIX) #if defined(USE_MODELMATRIX)
L = (u_ModelMatrix * vec4(L, 0.0)).xyz; L = (u_ModelMatrix * vec4(L, 0.0)).xyz;
@ -175,76 +192,59 @@ void main()
#endif #endif
#if defined(USE_LIGHTMAP) #if defined(USE_LIGHTMAP)
var_LightTex = attr_TexCoord1.st; var_TexCoords.zw = attr_TexCoord1.st;
#endif #endif
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
var_lightColor = u_VertColor.rgb * attr_Color.rgb;
var_Color.rgb = vec3(1.0);
var_Color.a = u_VertColor.a * attr_Color.a + u_BaseColor.a;
#else
var_Color = u_VertColor * attr_Color + u_BaseColor; var_Color = u_VertColor * attr_Color + u_BaseColor;
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
var_LightColor = var_Color.rgb;
var_Color.rgb = vec3(1.0);
#endif #endif
#if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT) #if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT)
// inverse square light float attenuation = CalcLightAttenuation(L, u_LightRadius * u_LightRadius);
float attenuation = u_LightRadius * u_LightRadius / dot(L, L);
// zero light at radius, approximating q3 style
attenuation = 0.5 * attenuation - 0.5;
//attenuation = 0.0697168 * attenuation;
//attenuation *= step(0.294117, attenuation);
// clamp attenuation
#if defined(NO_LIGHT_CLAMP)
attenuation *= step(0.0, attenuation);
#else
attenuation = clamp(attenuation, 0.0, 1.0);
#endif
// don't attenuate directional light
attenuation = (attenuation - 1.0) * u_LightOrigin.w + 1.0;
float NL = clamp(dot(normal, normalize(L)), 0.0, 1.0); float NL = clamp(dot(normal, normalize(L)), 0.0, 1.0);
var_Color.rgb *= u_DirectedLight * attenuation * NL + u_AmbientLight; var_Color.rgb *= u_DirectedLight * attenuation * NL + u_AmbientLight;
#endif #endif
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
var_Normal = normal;
var_Tangent = tangent;
var_Bitangent = bitangent;
#endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
var_PrimaryLightDir = (u_PrimaryLightOrigin.xyz - (position * u_PrimaryLightOrigin.w)); var_PrimaryLightDir.xyz = u_PrimaryLightOrigin.xyz - (position * u_PrimaryLightOrigin.w);
var_PrimaryLightDir.w = u_PrimaryLightRadius * u_PrimaryLightRadius;
#endif #endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT) #if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
#if defined(USE_LIGHT_VECTOR) #if defined(USE_LIGHT_VECTOR)
var_LightDir = vec4(L, u_LightOrigin.w); var_LightDir = vec4(L, u_LightRadius * u_LightRadius);
#else #else
var_LightDir = vec4(L, 0.0); var_LightDir = vec4(L, 0.0);
#endif #endif
#endif #endif
#if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
var_ViewDir = (u_ViewOrigin - position); vec3 viewDir = u_ViewOrigin - position;
#endif #endif
#if defined(USE_TANGENT_SPACE_LIGHT) #if defined(USE_TANGENT_SPACE_LIGHT)
mat3 tangentToWorld = mat3(tangent, bitangent, normal); mat3 tangentToWorld = mat3(tangent, bitangent, normal);
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
var_PrimaryLightDir = var_PrimaryLightDir * tangentToWorld; var_PrimaryLightDir.xyz = var_PrimaryLightDir.xyz * tangentToWorld;
#endif #endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT) #if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
var_LightDir.xyz = var_LightDir.xyz * tangentToWorld; var_LightDir.xyz = var_LightDir.xyz * tangentToWorld;
#endif #endif
#if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
var_ViewDir = var_ViewDir * tangentToWorld; viewDir = viewDir * tangentToWorld;
#endif #endif
#endif #endif
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
// store view direction in tangent space to save on varyings
var_Normal = vec4(normal, viewDir.x);
var_Tangent = vec4(tangent, viewDir.y);
var_Bitangent = vec4(bitangent, viewDir.z);
#endif
} }

View file

@ -271,7 +271,7 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) {
if (r_hdr->integer) if (r_hdr->integer)
{ {
if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel) if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer)
textureInternalFormat = GL_RGBA16F_ARB; textureInternalFormat = GL_RGBA16F_ARB;
else else
textureInternalFormat = GL_RGBA8; textureInternalFormat = GL_RGBA8;
@ -410,7 +410,7 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) {
VectorScale(color, lightScale, color); VectorScale(color, lightScale, color);
if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel) if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer)
ColorToRGBA16F(color, (unsigned short *)(&image[j*8])); ColorToRGBA16F(color, (unsigned short *)(&image[j*8]));
else else
ColorToRGBM(color, &image[j*4]); ColorToRGBM(color, &image[j*4]);
@ -652,7 +652,7 @@ ParseFace
*/ */
static void ParseFace( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf, int *indexes ) { static void ParseFace( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf, int *indexes ) {
int i, j; int i, j;
srfSurfaceFace_t *cv; srfBspSurface_t *cv;
srfTriangle_t *tri; srfTriangle_t *tri;
int numVerts, numTriangles, badTriangles; int numVerts, numTriangles, badTriangles;
int realLightmapNum; int realLightmapNum;
@ -767,12 +767,12 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors,
// take the plane information from the lightmap vector // take the plane information from the lightmap vector
for ( i = 0 ; i < 3 ; i++ ) { for ( i = 0 ; i < 3 ; i++ ) {
cv->plane.normal[i] = LittleFloat( ds->lightmapVecs[2][i] ); cv->cullPlane.normal[i] = LittleFloat( ds->lightmapVecs[2][i] );
} }
cv->plane.dist = DotProduct( cv->verts[0].xyz, cv->plane.normal ); cv->cullPlane.dist = DotProduct( cv->verts[0].xyz, cv->cullPlane.normal );
SetPlaneSignbits( &cv->plane ); SetPlaneSignbits( &cv->cullPlane );
cv->plane.type = PlaneTypeForNormal( cv->plane.normal ); cv->cullPlane.type = PlaneTypeForNormal( cv->cullPlane.normal );
surf->cullinfo.plane = cv->plane; surf->cullinfo.plane = cv->cullPlane;
surf->data = (surfaceType_t *)cv; surf->data = (surfaceType_t *)cv;
@ -800,7 +800,7 @@ ParseMesh
=============== ===============
*/ */
static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf ) { static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf ) {
srfGridMesh_t *grid; srfBspSurface_t *grid;
int i, j; int i, j;
int width, height, numPoints; int width, height, numPoints;
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE]; srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE];
@ -903,7 +903,7 @@ ParseTriSurf
=============== ===============
*/ */
static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf, int *indexes ) { static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf, int *indexes ) {
srfTriangles_t *cv; srfBspSurface_t *cv;
srfTriangle_t *tri; srfTriangle_t *tri;
int i, j; int i, j;
int numVerts, numTriangles, badTriangles; int numVerts, numTriangles, badTriangles;
@ -1065,7 +1065,7 @@ R_MergedWidthPoints
returns true if there are grid points merged on a width edge returns true if there are grid points merged on a width edge
================= =================
*/ */
int R_MergedWidthPoints(srfGridMesh_t *grid, int offset) { int R_MergedWidthPoints(srfBspSurface_t *grid, int offset) {
int i, j; int i, j;
for (i = 1; i < grid->width-1; i++) { for (i = 1; i < grid->width-1; i++) {
@ -1086,7 +1086,7 @@ R_MergedHeightPoints
returns true if there are grid points merged on a height edge returns true if there are grid points merged on a height edge
================= =================
*/ */
int R_MergedHeightPoints(srfGridMesh_t *grid, int offset) { int R_MergedHeightPoints(srfBspSurface_t *grid, int offset) {
int i, j; int i, j;
for (i = 1; i < grid->height-1; i++) { for (i = 1; i < grid->height-1; i++) {
@ -1109,13 +1109,13 @@ NOTE: never sync LoD through grid edges with merged points!
FIXME: write generalized version that also avoids cracks between a patch and one that meets half way? FIXME: write generalized version that also avoids cracks between a patch and one that meets half way?
================= =================
*/ */
void R_FixSharedVertexLodError_r( int start, srfGridMesh_t *grid1 ) { void R_FixSharedVertexLodError_r( int start, srfBspSurface_t *grid1 ) {
int j, k, l, m, n, offset1, offset2, touch; int j, k, l, m, n, offset1, offset2, touch;
srfGridMesh_t *grid2; srfBspSurface_t *grid2;
for ( j = start; j < s_worldData.numsurfaces; j++ ) { for ( j = start; j < s_worldData.numsurfaces; j++ ) {
// //
grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data; grid2 = (srfBspSurface_t *) s_worldData.surfaces[j].data;
// if this surface is not a grid // if this surface is not a grid
if ( grid2->surfaceType != SF_GRID ) continue; if ( grid2->surfaceType != SF_GRID ) continue;
// if the LOD errors are already fixed for this patch // if the LOD errors are already fixed for this patch
@ -1223,11 +1223,11 @@ If this is not the case this function will still do its job but won't fix the hi
*/ */
void R_FixSharedVertexLodError( void ) { void R_FixSharedVertexLodError( void ) {
int i; int i;
srfGridMesh_t *grid1; srfBspSurface_t *grid1;
for ( i = 0; i < s_worldData.numsurfaces; i++ ) { for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
// //
grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data; grid1 = (srfBspSurface_t *) s_worldData.surfaces[i].data;
// if this surface is not a grid // if this surface is not a grid
if ( grid1->surfaceType != SF_GRID ) if ( grid1->surfaceType != SF_GRID )
continue; continue;
@ -1249,11 +1249,11 @@ R_StitchPatches
*/ */
int R_StitchPatches( int grid1num, int grid2num ) { int R_StitchPatches( int grid1num, int grid2num ) {
float *v1, *v2; float *v1, *v2;
srfGridMesh_t *grid1, *grid2; srfBspSurface_t *grid1, *grid2;
int k, l, m, n, offset1, offset2, row, column; int k, l, m, n, offset1, offset2, row, column;
grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data; grid1 = (srfBspSurface_t *) s_worldData.surfaces[grid1num].data;
grid2 = (srfGridMesh_t *) s_worldData.surfaces[grid2num].data; grid2 = (srfBspSurface_t *) s_worldData.surfaces[grid2num].data;
for (n = 0; n < 2; n++) { for (n = 0; n < 2; n++) {
// //
if (n) offset1 = (grid1->height-1) * grid1->width; if (n) offset1 = (grid1->height-1) * grid1->width;
@ -1664,13 +1664,13 @@ might still appear at that side.
*/ */
int R_TryStitchingPatch( int grid1num ) { int R_TryStitchingPatch( int grid1num ) {
int j, numstitches; int j, numstitches;
srfGridMesh_t *grid1, *grid2; srfBspSurface_t *grid1, *grid2;
numstitches = 0; numstitches = 0;
grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data; grid1 = (srfBspSurface_t *) s_worldData.surfaces[grid1num].data;
for ( j = 0; j < s_worldData.numsurfaces; j++ ) { for ( j = 0; j < s_worldData.numsurfaces; j++ ) {
// //
grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data; grid2 = (srfBspSurface_t *) s_worldData.surfaces[j].data;
// if this surface is not a grid // if this surface is not a grid
if ( grid2->surfaceType != SF_GRID ) continue; if ( grid2->surfaceType != SF_GRID ) continue;
// grids in the same LOD group should have the exact same lod radius // grids in the same LOD group should have the exact same lod radius
@ -1695,7 +1695,7 @@ R_StitchAllPatches
*/ */
void R_StitchAllPatches( void ) { void R_StitchAllPatches( void ) {
int i, stitched, numstitches; int i, stitched, numstitches;
srfGridMesh_t *grid1; srfBspSurface_t *grid1;
numstitches = 0; numstitches = 0;
do do
@ -1703,7 +1703,7 @@ void R_StitchAllPatches( void ) {
stitched = qfalse; stitched = qfalse;
for ( i = 0; i < s_worldData.numsurfaces; i++ ) { for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
// //
grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data; grid1 = (srfBspSurface_t *) s_worldData.surfaces[i].data;
// if this surface is not a grid // if this surface is not a grid
if ( grid1->surfaceType != SF_GRID ) if ( grid1->surfaceType != SF_GRID )
continue; continue;
@ -1728,11 +1728,11 @@ R_MovePatchSurfacesToHunk
*/ */
void R_MovePatchSurfacesToHunk(void) { void R_MovePatchSurfacesToHunk(void) {
int i, size; int i, size;
srfGridMesh_t *grid, *hunkgrid; srfBspSurface_t *grid, *hunkgrid;
for ( i = 0; i < s_worldData.numsurfaces; i++ ) { for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
// //
grid = (srfGridMesh_t *) s_worldData.surfaces[i].data; grid = (srfBspSurface_t *) s_worldData.surfaces[i].data;
// if this surface is not a grid // if this surface is not a grid
if ( grid->surfaceType != SF_GRID ) if ( grid->surfaceType != SF_GRID )
continue; continue;
@ -1831,10 +1831,10 @@ static void CopyVert(const srfVert_t * in, srfVert_t * out)
/* /*
=============== ===============
R_CreateWorldVBO R_CreateWorldVBOs
=============== ===============
*/ */
static void R_CreateWorldVBO(void) static void R_CreateWorldVBOs(void)
{ {
int i, j, k; int i, j, k;
@ -1844,73 +1844,32 @@ static void R_CreateWorldVBO(void)
int numTriangles; int numTriangles;
srfTriangle_t *triangles; srfTriangle_t *triangles;
int numSurfaces; int numSortedSurfaces, numSurfaces;
msurface_t *surface; msurface_t *surface, **firstSurf, **lastSurf, **currSurf;
msurface_t **surfacesSorted; msurface_t **surfacesSorted;
VBO_t *vbo;
IBO_t *ibo;
int startTime, endTime; int startTime, endTime;
startTime = ri.Milliseconds(); startTime = ri.Milliseconds();
numVerts = 0; // count surfaces
numTriangles = 0; numSortedSurfaces = 0;
numSurfaces = 0; for(surface = &s_worldData.surfaces[0]; surface < &s_worldData.surfaces[s_worldData.numsurfaces]; surface++)
for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces /* s_worldData.numWorldSurfaces */; k++, surface++)
{ {
if(*surface->data == SF_FACE) if(*surface->data == SF_FACE || *surface->data == SF_GRID || *surface->data == SF_TRIANGLES)
{ {
srfSurfaceFace_t *face = (srfSurfaceFace_t *) surface->data; numSortedSurfaces++;
if(face->numVerts)
numVerts += face->numVerts;
if(face->numTriangles)
numTriangles += face->numTriangles;
numSurfaces++;
}
else if(*surface->data == SF_GRID)
{
srfGridMesh_t *grid = (srfGridMesh_t *) surface->data;
if(grid->numVerts)
numVerts += grid->numVerts;
if(grid->numTriangles)
numTriangles += grid->numTriangles;
numSurfaces++;
}
else if(*surface->data == SF_TRIANGLES)
{
srfTriangles_t *tri = (srfTriangles_t *) surface->data;
if(tri->numVerts)
numVerts += tri->numVerts;
if(tri->numTriangles)
numTriangles += tri->numTriangles;
numSurfaces++;
} }
} }
if(!numVerts || !numTriangles)
return;
ri.Printf(PRINT_ALL, "...calculating world VBO ( %i verts %i tris )\n", numVerts, numTriangles);
// create arrays
verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t));
// presort surfaces // presort surfaces
surfacesSorted = ri.Malloc(numSurfaces * sizeof(*surfacesSorted)); surfacesSorted = ri.Malloc(numSortedSurfaces * sizeof(*surfacesSorted));
j = 0; j = 0;
for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces; k++, surface++) for(surface = &s_worldData.surfaces[0]; surface < &s_worldData.surfaces[s_worldData.numsurfaces]; surface++)
{ {
if(*surface->data == SF_FACE || *surface->data == SF_GRID || *surface->data == SF_TRIANGLES) if(*surface->data == SF_FACE || *surface->data == SF_GRID || *surface->data == SF_TRIANGLES)
{ {
@ -1918,211 +1877,169 @@ static void R_CreateWorldVBO(void)
} }
} }
qsort(surfacesSorted, numSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare); qsort(surfacesSorted, numSortedSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare);
k = 0;
for(firstSurf = lastSurf = surfacesSorted; firstSurf < &surfacesSorted[numSortedSurfaces]; firstSurf = lastSurf)
{
while(lastSurf < &surfacesSorted[numSortedSurfaces] && (*lastSurf)->shader->sortedIndex == (*firstSurf)->shader->sortedIndex)
lastSurf++;
numVerts = 0;
numTriangles = 0;
numSurfaces = 0;
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{
srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data;
switch (bspSurf->surfaceType)
{
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
if(bspSurf->numVerts)
numVerts += bspSurf->numVerts;
if(bspSurf->numTriangles)
numTriangles += bspSurf->numTriangles;
numSurfaces++;
break;
default:
break;
}
}
if(!numVerts || !numTriangles)
continue;
ri.Printf(PRINT_ALL, "...calculating world VBO %d ( %i verts %i tris )\n", k, numVerts, numTriangles);
// create arrays
verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t));
// set up triangle indices // set up triangle indices
numVerts = 0; numVerts = 0;
numTriangles = 0; numTriangles = 0;
for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k]) for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{ {
if(*surface->data == SF_FACE) srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data;
switch (bspSurf->surfaceType)
{ {
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
bspSurf->firstIndex = numTriangles * 3;
srf->firstIndex = numTriangles * 3; if(bspSurf->numTriangles)
if(srf->numTriangles)
{ {
srfTriangle_t *tri; srfTriangle_t *tri;
srf->minIndex = numVerts + srf->triangles->indexes[0]; bspSurf->minIndex = numVerts + bspSurf->triangles->indexes[0];
srf->maxIndex = numVerts + srf->triangles->indexes[0]; bspSurf->maxIndex = numVerts + bspSurf->triangles->indexes[0];
for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) for(i = 0, tri = bspSurf->triangles; i < bspSurf->numTriangles; i++, tri++)
{ {
for(j = 0; j < 3; j++) for(j = 0; j < 3; j++)
{ {
triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]); bspSurf->minIndex = MIN(bspSurf->minIndex, numVerts + tri->indexes[j]);
srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]); bspSurf->maxIndex = MAX(bspSurf->maxIndex, numVerts + tri->indexes[j]);
} }
} }
numTriangles += srf->numTriangles; numTriangles += bspSurf->numTriangles;
} }
if(srf->numVerts) if(bspSurf->numVerts)
numVerts += srf->numVerts; numVerts += bspSurf->numVerts;
}
else if(*surface->data == SF_GRID)
{
srfGridMesh_t *srf = (srfGridMesh_t *) surface->data;
srf->firstIndex = numTriangles * 3; break;
if(srf->numTriangles) default:
{ break;
srfTriangle_t *tri;
srf->minIndex = numVerts + srf->triangles->indexes[0];
srf->maxIndex = numVerts + srf->triangles->indexes[0];
for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
{
for(j = 0; j < 3; j++)
{
triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]);
srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]);
}
}
numTriangles += srf->numTriangles;
}
if(srf->numVerts)
numVerts += srf->numVerts;
}
else if(*surface->data == SF_TRIANGLES)
{
srfTriangles_t *srf = (srfTriangles_t *) surface->data;
srf->firstIndex = numTriangles * 3;
if(srf->numTriangles)
{
srfTriangle_t *tri;
srf->minIndex = numVerts + srf->triangles->indexes[0];
srf->maxIndex = numVerts + srf->triangles->indexes[0];
for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
{
for(j = 0; j < 3; j++)
{
triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]);
srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]);
}
}
numTriangles += srf->numTriangles;
}
if(srf->numVerts)
numVerts += srf->numVerts;
} }
} }
// build vertices // build vertices
numVerts = 0; numVerts = 0;
for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k]) for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{ {
if(*surface->data == SF_FACE) srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data;
{
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
srf->firstVert = numVerts; switch (bspSurf->surfaceType)
{
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
bspSurf->firstVert = numVerts;
if(srf->numVerts) if(bspSurf->numVerts)
{ {
for(i = 0; i < srf->numVerts; i++) for(i = 0; i < bspSurf->numVerts; i++)
{ {
CopyVert(&srf->verts[i], &verts[numVerts + i]); CopyVert(&bspSurf->verts[i], &verts[numVerts + i]);
} }
numVerts += srf->numVerts; numVerts += bspSurf->numVerts;
}
}
else if(*surface->data == SF_GRID)
{
srfGridMesh_t *srf = (srfGridMesh_t *) surface->data;
srf->firstVert = numVerts;
if(srf->numVerts)
{
for(i = 0; i < srf->numVerts; i++)
{
CopyVert(&srf->verts[i], &verts[numVerts + i]);
} }
numVerts += srf->numVerts; break;
}
}
else if(*surface->data == SF_TRIANGLES)
{
srfTriangles_t *srf = (srfTriangles_t *) surface->data;
srf->firstVert = numVerts; default:
break;
if(srf->numVerts)
{
for(i = 0; i < srf->numVerts; i++)
{
CopyVert(&srf->verts[i], &verts[numVerts + i]);
}
numVerts += srf->numVerts;
}
} }
} }
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts, vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", k), numVerts, verts,
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT | ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT |
ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC); ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
#else #else
s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts, vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", k), numVerts, verts,
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD |
ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC); ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
#endif #endif
s_worldData.ibo = R_CreateIBO2(va("staticBspModel0_IBO %i", 0), numTriangles, triangles, VBO_USAGE_STATIC); ibo = R_CreateIBO2(va("staticBspModel0_IBO %i", k), numTriangles, triangles, VBO_USAGE_STATIC);
endTime = ri.Milliseconds(); // point triangle surfaces to VBO
ri.Printf(PRINT_ALL, "world VBO calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0); for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{
srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data;
// point triangle surfaces to world VBO switch (bspSurf->surfaceType)
for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k])
{ {
if(*surface->data == SF_FACE) case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
if( bspSurf->numVerts && bspSurf->numTriangles)
{ {
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; bspSurf->vbo = vbo;
bspSurf->ibo = ibo;
if( srf->numVerts && srf->numTriangles)
{
srf->vbo = s_worldData.vbo;
srf->ibo = s_worldData.ibo;
}
}
else if(*surface->data == SF_GRID)
{
srfGridMesh_t *srf = (srfGridMesh_t *) surface->data;
if( srf->numVerts && srf->numTriangles)
{
srf->vbo = s_worldData.vbo;
srf->ibo = s_worldData.ibo;
}
}
else if(*surface->data == SF_TRIANGLES)
{
srfTriangles_t *srf = (srfTriangles_t *) surface->data;
if( srf->numVerts && srf->numTriangles)
{
srf->vbo = s_worldData.vbo;
srf->ibo = s_worldData.ibo;
}
}
} }
break;
ri.Free(surfacesSorted); default:
break;
}
}
ri.Hunk_FreeTempMemory(triangles); ri.Hunk_FreeTempMemory(triangles);
ri.Hunk_FreeTempMemory(verts); ri.Hunk_FreeTempMemory(verts);
k++;
}
ri.Free(surfacesSorted);
endTime = ri.Milliseconds();
ri.Printf(PRINT_ALL, "world VBOs calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
} }
/* /*
@ -2196,10 +2113,10 @@ static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) {
// FIXME: do this // FIXME: do this
break; break;
case MST_TRIANGLE_SOUP: case MST_TRIANGLE_SOUP:
out->data = ri.Hunk_Alloc( sizeof(srfTriangles_t), h_low); out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t), h_low);
break; break;
case MST_PLANAR: case MST_PLANAR:
out->data = ri.Hunk_Alloc( sizeof(srfSurfaceFace_t), h_low); out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t), h_low);
break; break;
case MST_FLARE: case MST_FLARE:
out->data = ri.Hunk_Alloc( sizeof(srfFlare_t), h_low); out->data = ri.Hunk_Alloc( sizeof(srfFlare_t), h_low);
@ -2216,13 +2133,13 @@ static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) {
case MST_PATCH: case MST_PATCH:
ParseMesh ( in, dv, hdrVertColors, out ); ParseMesh ( in, dv, hdrVertColors, out );
{ {
srfGridMesh_t *surface = (srfGridMesh_t *)out->data; srfBspSurface_t *surface = (srfBspSurface_t *)out->data;
out->cullinfo.type = CULLINFO_BOX | CULLINFO_SPHERE; out->cullinfo.type = CULLINFO_BOX | CULLINFO_SPHERE;
VectorCopy(surface->meshBounds[0], out->cullinfo.bounds[0]); VectorCopy(surface->cullBounds[0], out->cullinfo.bounds[0]);
VectorCopy(surface->meshBounds[1], out->cullinfo.bounds[1]); VectorCopy(surface->cullBounds[1], out->cullinfo.bounds[1]);
VectorCopy(surface->localOrigin, out->cullinfo.localOrigin); VectorCopy(surface->cullOrigin, out->cullinfo.localOrigin);
out->cullinfo.radius = surface->meshRadius; out->cullinfo.radius = surface->cullRadius;
} }
numMeshes++; numMeshes++;
break; break;
@ -3006,6 +2923,7 @@ void R_MergeLeafSurfaces(void)
int mergedSurfIndex; int mergedSurfIndex;
int numMergedSurfaces; int numMergedSurfaces;
int numUnmergedSurfaces; int numUnmergedSurfaces;
VBO_t *vbo;
IBO_t *ibo; IBO_t *ibo;
msurface_t *mergedSurf; msurface_t *mergedSurf;
@ -3025,14 +2943,6 @@ void R_MergeLeafSurfaces(void)
s_worldData.surfacesViewCount[i] = -1; s_worldData.surfacesViewCount[i] = -1;
} }
// create ibo
ibo = tr.ibos[tr.numIBOs++] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
memset(ibo, 0, sizeof(*ibo));
Q_strncpyz(ibo->name, "staticWorldMesh_IBO_mergedSurfs", sizeof(ibo->name));
// allocate more than we need
iboIndexes = outIboIndexes = ri.Malloc(s_worldData.ibo->indexesSize);
// mark matching surfaces // mark matching surfaces
for (i = 0; i < s_worldData.numnodes - s_worldData.numDecisionNodes; i++) for (i = 0; i < s_worldData.numnodes - s_worldData.numDecisionNodes; i++)
{ {
@ -3166,6 +3076,9 @@ void R_MergeLeafSurfaces(void)
s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i]; s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i];
} }
// need to be synched here
R_IssuePendingRenderCommands();
// actually merge surfaces // actually merge surfaces
numIboIndexes = 0; numIboIndexes = 0;
mergedSurfIndex = 0; mergedSurfIndex = 0;
@ -3181,13 +3094,27 @@ void R_MergeLeafSurfaces(void)
int numVerts; int numVerts;
int firstIndex; int firstIndex;
srfVBOMesh_t *vboSurf; srfBspSurface_t *vboSurf;
if (s_worldData.surfacesViewCount[i] != i) if (s_worldData.surfacesViewCount[i] != i)
continue; continue;
surf1 = s_worldData.surfaces + i; surf1 = s_worldData.surfaces + i;
// retrieve vbo
switch(*surf1->data)
{
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
vbo = ((srfBspSurface_t *)(surf1->data))->vbo;
break;
default:
vbo = NULL;
break;
}
// count verts, indexes, and surfaces // count verts, indexes, and surfaces
numSurfsToMerge = 0; numSurfsToMerge = 0;
numTriangles = 0; numTriangles = 0;
@ -3195,42 +3122,21 @@ void R_MergeLeafSurfaces(void)
for (j = 0; j < numWorldSurfaces; j++) for (j = 0; j < numWorldSurfaces; j++)
{ {
msurface_t *surf2; msurface_t *surf2;
srfBspSurface_t *bspSurf;
if (s_worldData.surfacesViewCount[j] != i) if (s_worldData.surfacesViewCount[j] != i)
continue; continue;
surf2 = s_worldData.surfaces + j; surf2 = s_worldData.surfaces + j;
switch(*surf2->data) bspSurf = (srfBspSurface_t *) surf2->data;
switch(bspSurf->surfaceType)
{ {
case SF_FACE: case SF_FACE:
{
srfSurfaceFace_t *face;
face = (srfSurfaceFace_t *) surf2->data;
numTriangles += face->numTriangles;
numVerts += face->numVerts;
}
break;
case SF_GRID: case SF_GRID:
{
srfGridMesh_t *grid;
grid = (srfGridMesh_t *) surf2->data;
numTriangles += grid->numTriangles;
numVerts += grid->numVerts;
}
break;
case SF_TRIANGLES: case SF_TRIANGLES:
{ numTriangles += bspSurf->numTriangles;
srfTriangles_t *tris; numVerts += bspSurf->numVerts;
tris = (srfTriangles_t *) surf2->data;
numTriangles += tris->numTriangles;
numVerts += tris->numVerts;
}
break; break;
default: default:
@ -3245,12 +3151,22 @@ void R_MergeLeafSurfaces(void)
continue; continue;
} }
// create ibo
ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
memset(ibo, 0, sizeof(*ibo));
Q_strncpyz(ibo->name, va("staticWorldMesh_IBO_mergedSurfs%i", tr.numIBOs++), sizeof(ibo->name));
numIboIndexes = 0;
// allocate indexes
iboIndexes = outIboIndexes = ri.Malloc(numTriangles * 3 * sizeof(*outIboIndexes));
// Merge surfaces (indexes) and calculate bounds // Merge surfaces (indexes) and calculate bounds
ClearBounds(bounds[0], bounds[1]); ClearBounds(bounds[0], bounds[1]);
firstIndex = numIboIndexes; firstIndex = numIboIndexes;
for (j = 0; j < numWorldSurfaces; j++) for (j = 0; j < numWorldSurfaces; j++)
{ {
msurface_t *surf2; msurface_t *surf2;
srfBspSurface_t *bspSurf;
if (s_worldData.surfacesViewCount[j] != i) if (s_worldData.surfacesViewCount[j] != i)
continue; continue;
@ -3260,54 +3176,19 @@ void R_MergeLeafSurfaces(void)
AddPointToBounds(surf2->cullinfo.bounds[0], bounds[0], bounds[1]); AddPointToBounds(surf2->cullinfo.bounds[0], bounds[0], bounds[1]);
AddPointToBounds(surf2->cullinfo.bounds[1], bounds[0], bounds[1]); AddPointToBounds(surf2->cullinfo.bounds[1], bounds[0], bounds[1]);
switch(*surf2->data) bspSurf = (srfBspSurface_t *) surf2->data;
switch(bspSurf->surfaceType)
{ {
case SF_FACE: case SF_FACE:
{
srfSurfaceFace_t *face;
face = (srfSurfaceFace_t *) surf2->data;
for (k = 0; k < face->numTriangles; k++)
{
*outIboIndexes++ = face->triangles[k].indexes[0] + face->firstVert;
*outIboIndexes++ = face->triangles[k].indexes[1] + face->firstVert;
*outIboIndexes++ = face->triangles[k].indexes[2] + face->firstVert;
numIboIndexes += 3;
}
}
break;
case SF_GRID: case SF_GRID:
{
srfGridMesh_t *grid;
grid = (srfGridMesh_t *) surf2->data;
for (k = 0; k < grid->numTriangles; k++)
{
*outIboIndexes++ = grid->triangles[k].indexes[0] + grid->firstVert;
*outIboIndexes++ = grid->triangles[k].indexes[1] + grid->firstVert;
*outIboIndexes++ = grid->triangles[k].indexes[2] + grid->firstVert;
numIboIndexes += 3;
}
}
break;
case SF_TRIANGLES: case SF_TRIANGLES:
for (k = 0; k < bspSurf->numTriangles; k++)
{ {
srfTriangles_t *tris; *outIboIndexes++ = bspSurf->triangles[k].indexes[0] + bspSurf->firstVert;
*outIboIndexes++ = bspSurf->triangles[k].indexes[1] + bspSurf->firstVert;
tris = (srfTriangles_t *) surf2->data; *outIboIndexes++ = bspSurf->triangles[k].indexes[2] + bspSurf->firstVert;
for (k = 0; k < tris->numTriangles; k++)
{
*outIboIndexes++ = tris->triangles[k].indexes[0] + tris->firstVert;
*outIboIndexes++ = tris->triangles[k].indexes[1] + tris->firstVert;
*outIboIndexes++ = tris->triangles[k].indexes[2] + tris->firstVert;
numIboIndexes += 3; numIboIndexes += 3;
} }
}
break; break;
// never happens, but silences a compile warning // never happens, but silences a compile warning
@ -3320,10 +3201,10 @@ void R_MergeLeafSurfaces(void)
memset(vboSurf, 0, sizeof(*vboSurf)); memset(vboSurf, 0, sizeof(*vboSurf));
vboSurf->surfaceType = SF_VBO_MESH; vboSurf->surfaceType = SF_VBO_MESH;
vboSurf->vbo = s_worldData.vbo; vboSurf->vbo = vbo;
vboSurf->ibo = ibo; vboSurf->ibo = ibo;
vboSurf->numIndexes = numTriangles * 3; vboSurf->numTriangles = numTriangles;
vboSurf->numVerts = numVerts; vboSurf->numVerts = numVerts;
vboSurf->firstIndex = firstIndex; vboSurf->firstIndex = firstIndex;
@ -3336,12 +3217,8 @@ void R_MergeLeafSurfaces(void)
vboSurf->maxIndex = MAX(vboSurf->maxIndex, *(iboIndexes + firstIndex + j)); vboSurf->maxIndex = MAX(vboSurf->maxIndex, *(iboIndexes + firstIndex + j));
} }
vboSurf->shader = surf1->shader; VectorCopy(bounds[0], vboSurf->cullBounds[0]);
vboSurf->fogIndex = surf1->fogIndex; VectorCopy(bounds[1], vboSurf->cullBounds[1]);
vboSurf->cubemapIndex = surf1->cubemapIndex;
VectorCopy(bounds[0], vboSurf->bounds[0]);
VectorCopy(bounds[1], vboSurf->bounds[1]);
VectorCopy(bounds[0], mergedSurf->cullinfo.bounds[0]); VectorCopy(bounds[0], mergedSurf->cullinfo.bounds[0]);
VectorCopy(bounds[1], mergedSurf->cullinfo.bounds[1]); VectorCopy(bounds[1], mergedSurf->cullinfo.bounds[1]);
@ -3352,6 +3229,17 @@ void R_MergeLeafSurfaces(void)
mergedSurf->cubemapIndex = surf1->cubemapIndex; mergedSurf->cubemapIndex = surf1->cubemapIndex;
mergedSurf->shader = surf1->shader; mergedSurf->shader = surf1->shader;
// finish up the ibo
qglGenBuffersARB(1, &ibo->indexesVBO);
R_BindIBO(ibo);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numIboIndexes * sizeof(*iboIndexes), iboIndexes, GL_STATIC_DRAW_ARB);
R_BindNullIBO();
GL_CheckErrors();
ri.Free(iboIndexes);
// redirect view surfaces to this surf // redirect view surfaces to this surf
for (j = 0; j < numWorldSurfaces; j++) for (j = 0; j < numWorldSurfaces; j++)
{ {
@ -3372,21 +3260,6 @@ void R_MergeLeafSurfaces(void)
mergedSurf++; mergedSurf++;
} }
// finish up the ibo
R_IssuePendingRenderCommands();
qglGenBuffersARB(1, &ibo->indexesVBO);
R_BindIBO(ibo);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numIboIndexes * sizeof(*iboIndexes), iboIndexes, GL_STATIC_DRAW_ARB);
R_BindNullIBO();
GL_CheckErrors();
ri.Free(iboIndexes);
endTime = ri.Milliseconds(); endTime = ri.Milliseconds();
ri.Printf(PRINT_ALL, "Processed %d surfaces into %d merged, %d unmerged in %5.2f seconds\n", ri.Printf(PRINT_ALL, "Processed %d surfaces into %d merged, %d unmerged in %5.2f seconds\n",
@ -3407,41 +3280,20 @@ void R_CalcVertexLightDirs( void )
for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces /* s_worldData.numWorldSurfaces */; k++, surface++) for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces /* s_worldData.numWorldSurfaces */; k++, surface++)
{ {
if(*surface->data == SF_FACE) srfBspSurface_t *bspSurf = (srfBspSurface_t *) surface->data;
{
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
if(srf->numVerts) switch(bspSurf->surfaceType)
{ {
for(i = 0; i < srf->numVerts; i++) case SF_FACE:
{ case SF_GRID:
R_LightDirForPoint( srf->verts[i].xyz, srf->verts[i].lightdir, srf->verts[i].normal, &s_worldData ); case SF_TRIANGLES:
} for(i = 0; i < bspSurf->numVerts; i++)
} R_LightDirForPoint( bspSurf->verts[i].xyz, bspSurf->verts[i].lightdir, bspSurf->verts[i].normal, &s_worldData );
}
else if(*surface->data == SF_GRID)
{
srfGridMesh_t *srf = (srfGridMesh_t *) surface->data;
if(srf->numVerts) break;
{
for(i = 0; i < srf->numVerts; i++)
{
R_LightDirForPoint( srf->verts[i].xyz, srf->verts[i].lightdir, srf->verts[i].normal, &s_worldData );
}
}
}
else if(*surface->data == SF_TRIANGLES)
{
srfTriangles_t *srf = (srfTriangles_t *) surface->data;
if(srf->numVerts) default:
{ break;
for(i = 0; i < srf->numVerts; i++)
{
R_LightDirForPoint( srf->verts[i].xyz, srf->verts[i].lightdir, srf->verts[i].normal, &s_worldData );
}
}
} }
} }
} }
@ -3743,7 +3595,7 @@ void RE_LoadWorldMap( const char *name ) {
} }
// create static VBOS from the world // create static VBOS from the world
R_CreateWorldVBO(); R_CreateWorldVBOs();
if (r_mergeLeafSurfaces->integer) if (r_mergeLeafSurfaces->integer)
{ {
R_MergeLeafSurfaces(); R_MergeLeafSurfaces();

View file

@ -25,14 +25,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
/* /*
This file does all of the processing necessary to turn a raw grid of points This file does all of the processing necessary to turn a raw grid of points
read from the map file into a srfGridMesh_t ready for rendering. read from the map file into a srfBspSurface_t ready for rendering.
The level of detail solution is direction independent, based only on subdivided The level of detail solution is direction independent, based only on subdivided
distance from the true curve. distance from the true curve.
Only a single entry point: Only a single entry point:
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, srfBspSurface_t *R_SubdividePatchToGrid( int width, int height,
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) { srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
*/ */
@ -329,8 +329,6 @@ static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE
} }
} }
R_CalcSurfaceTriangleNeighbors(numTriangles, triangles);
// FIXME: use more elegant way // FIXME: use more elegant way
for(i = 0; i < width; i++) for(i = 0; i < width; i++)
{ {
@ -341,8 +339,6 @@ static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE
} }
} }
R_CalcSurfaceTrianglePlanes(numTriangles, triangles, ctrl2);
return numTriangles; return numTriangles;
} }
@ -420,13 +416,13 @@ static void PutPointsOnCurve( srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
R_CreateSurfaceGridMesh R_CreateSurfaceGridMesh
================= =================
*/ */
srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height, srfBspSurface_t *R_CreateSurfaceGridMesh(int width, int height,
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE], srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE],
int numTriangles, srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]) { int numTriangles, srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]) {
int i, j, size; int i, j, size;
srfVert_t *vert; srfVert_t *vert;
vec3_t tmpVec; vec3_t tmpVec;
srfGridMesh_t *grid; srfBspSurface_t *grid;
// copy the results out to a grid // copy the results out to a grid
size = (width * height - 1) * sizeof( srfVert_t ) + sizeof( *grid ); size = (width * height - 1) * sizeof( srfVert_t ) + sizeof( *grid );
@ -468,23 +464,23 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
grid->width = width; grid->width = width;
grid->height = height; grid->height = height;
grid->surfaceType = SF_GRID; grid->surfaceType = SF_GRID;
ClearBounds( grid->meshBounds[0], grid->meshBounds[1] ); ClearBounds( grid->cullBounds[0], grid->cullBounds[1] );
for ( i = 0 ; i < width ; i++ ) { for ( i = 0 ; i < width ; i++ ) {
for ( j = 0 ; j < height ; j++ ) { for ( j = 0 ; j < height ; j++ ) {
vert = &grid->verts[j*width+i]; vert = &grid->verts[j*width+i];
*vert = ctrl[j][i]; *vert = ctrl[j][i];
AddPointToBounds( vert->xyz, grid->meshBounds[0], grid->meshBounds[1] ); AddPointToBounds( vert->xyz, grid->cullBounds[0], grid->cullBounds[1] );
} }
} }
// compute local origin and bounds // compute local origin and bounds
VectorAdd( grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin ); VectorAdd( grid->cullBounds[0], grid->cullBounds[1], grid->cullOrigin );
VectorScale( grid->localOrigin, 0.5f, grid->localOrigin ); VectorScale( grid->cullOrigin, 0.5f, grid->cullOrigin );
VectorSubtract( grid->meshBounds[0], grid->localOrigin, tmpVec ); VectorSubtract( grid->cullBounds[0], grid->cullOrigin, tmpVec );
grid->meshRadius = VectorLength( tmpVec ); grid->cullRadius = VectorLength( tmpVec );
VectorCopy( grid->localOrigin, grid->lodOrigin ); VectorCopy( grid->cullOrigin, grid->lodOrigin );
grid->lodRadius = grid->meshRadius; grid->lodRadius = grid->cullRadius;
// //
return grid; return grid;
} }
@ -494,7 +490,7 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
R_FreeSurfaceGridMesh R_FreeSurfaceGridMesh
================= =================
*/ */
void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) { void R_FreeSurfaceGridMesh( srfBspSurface_t *grid ) {
ri.Free(grid->widthLodError); ri.Free(grid->widthLodError);
ri.Free(grid->heightLodError); ri.Free(grid->heightLodError);
ri.Free(grid->triangles); ri.Free(grid->triangles);
@ -507,7 +503,7 @@ void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) {
R_SubdividePatchToGrid R_SubdividePatchToGrid
================= =================
*/ */
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, srfBspSurface_t *R_SubdividePatchToGrid( int width, int height,
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) { srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
int i, j, k, l; int i, j, k, l;
srfVert_t_cleared( prev ); srfVert_t_cleared( prev );
@ -690,7 +686,7 @@ srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
R_GridInsertColumn R_GridInsertColumn
=============== ===============
*/ */
srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) { srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row, vec3_t point, float loderror ) {
int i, j; int i, j;
int width, height, oldwidth; int width, height, oldwidth;
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
@ -750,7 +746,7 @@ srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec
R_GridInsertRow R_GridInsertRow
=============== ===============
*/ */
srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) { srfBspSurface_t *R_GridInsertRow( srfBspSurface_t *grid, int row, int column, vec3_t point, float loderror ) {
int i, j; int i, j;
int width, height, oldheight; int width, height, oldheight;
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];

View file

@ -701,8 +701,10 @@ void GLimp_InitExtraExtensions()
glRefConfig.seamlessCubeMap = qfalse; glRefConfig.seamlessCubeMap = qfalse;
if( GLimp_HaveExtension( extension ) ) if( GLimp_HaveExtension( extension ) )
{ {
if (r_arb_seamless_cube_map->integer)
glRefConfig.seamlessCubeMap = qtrue; glRefConfig.seamlessCubeMap = qtrue;
ri.Printf(PRINT_ALL, result[1], extension);
ri.Printf(PRINT_ALL, result[glRefConfig.seamlessCubeMap], extension);
} }
else else
{ {

View file

@ -106,6 +106,7 @@ static uniformInfo_t uniformsInfo[] =
{ "u_LightUp", GLSL_VEC3 }, { "u_LightUp", GLSL_VEC3 },
{ "u_LightRight", GLSL_VEC3 }, { "u_LightRight", GLSL_VEC3 },
{ "u_LightOrigin", GLSL_VEC4 }, { "u_LightOrigin", GLSL_VEC4 },
{ "u_ModelLightDir", GLSL_VEC3 },
{ "u_LightRadius", GLSL_FLOAT }, { "u_LightRadius", GLSL_FLOAT },
{ "u_AmbientLight", GLSL_VEC3 }, { "u_AmbientLight", GLSL_VEC3 },
{ "u_DirectedLight", GLSL_VEC3 }, { "u_DirectedLight", GLSL_VEC3 },
@ -126,6 +127,7 @@ static uniformInfo_t uniformsInfo[] =
{ "u_ViewInfo", GLSL_VEC4 }, { "u_ViewInfo", GLSL_VEC4 },
{ "u_ViewOrigin", GLSL_VEC3 }, { "u_ViewOrigin", GLSL_VEC3 },
{ "u_LocalViewOrigin", GLSL_VEC3 },
{ "u_ViewForward", GLSL_VEC3 }, { "u_ViewForward", GLSL_VEC3 },
{ "u_ViewLeft", GLSL_VEC3 }, { "u_ViewLeft", GLSL_VEC3 },
{ "u_ViewUp", GLSL_VEC3 }, { "u_ViewUp", GLSL_VEC3 },
@ -294,11 +296,9 @@ static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, cha
"#define alphaGen_t\n" "#define alphaGen_t\n"
"#define AGEN_LIGHTING_SPECULAR %i\n" "#define AGEN_LIGHTING_SPECULAR %i\n"
"#define AGEN_PORTAL %i\n" "#define AGEN_PORTAL %i\n"
"#define AGEN_FRESNEL %i\n"
"#endif\n", "#endif\n",
AGEN_LIGHTING_SPECULAR, AGEN_LIGHTING_SPECULAR,
AGEN_PORTAL, AGEN_PORTAL));
AGEN_FRESNEL));
Q_strcat(dest, size, Q_strcat(dest, size,
va("#ifndef texenv_t\n" va("#ifndef texenv_t\n"
@ -907,7 +907,7 @@ void GLSL_InitGPUShaders(void)
if (i & GENERICDEF_USE_LIGHTMAP) if (i & GENERICDEF_USE_LIGHTMAP)
Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n"); Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n");
if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel)) if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer))
Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n"); Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n");
if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackShader_generic_vp, fallbackShader_generic_fp)) if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackShader_generic_vp, fallbackShader_generic_fp))
@ -1036,7 +1036,7 @@ void GLSL_InitGPUShaders(void)
Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n"); Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n");
} }
if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel)) if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer))
Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n"); Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n");
if (i & LIGHTDEF_LIGHTTYPE_MASK) if (i & LIGHTDEF_LIGHTTYPE_MASK)
@ -1696,7 +1696,7 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
// position/normal/tangent/bitangent are always set in case of animation // position/normal/tangent/bitangent are always set in case of animation
oldFrame = glState.vertexAttribsOldFrame; oldFrame = glState.vertexAttribsOldFrame;
newFrame = glState.vertexAttribsNewFrame; newFrame = glState.vertexAttribsNewFrame;
animated = (oldFrame != newFrame) && (glState.vertexAttribsInterpolation > 0.0f); animated = glState.vertexAnimation;
if((attribBits & ATTR_POSITION) && (!(glState.vertexAttribPointersSet & ATTR_POSITION) || animated)) if((attribBits & ATTR_POSITION) && (!(glState.vertexAttribPointersSet & ATTR_POSITION) || animated))
{ {
@ -1829,7 +1829,6 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage)
{ {
case AGEN_LIGHTING_SPECULAR: case AGEN_LIGHTING_SPECULAR:
case AGEN_PORTAL: case AGEN_PORTAL:
case AGEN_FRESNEL:
shaderAttribs |= GENERICDEF_USE_RGBAGEN; shaderAttribs |= GENERICDEF_USE_RGBAGEN;
break; break;
default: default:
@ -1846,7 +1845,7 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage)
shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES; shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES;
} }
if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) if (glState.vertexAnimation)
{ {
shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION; shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
} }

View file

@ -2303,6 +2303,9 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT
qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
if (image->flags & IMGFLAG_MIPMAP)
qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP);
image->uploadWidth = width; image->uploadWidth = width;
image->uploadHeight = height; image->uploadHeight = height;
} }

View file

@ -102,6 +102,7 @@ cvar_t *r_ext_framebuffer_object;
cvar_t *r_ext_texture_float; cvar_t *r_ext_texture_float;
cvar_t *r_arb_half_float_pixel; cvar_t *r_arb_half_float_pixel;
cvar_t *r_ext_framebuffer_multisample; cvar_t *r_ext_framebuffer_multisample;
cvar_t *r_arb_seamless_cube_map;
cvar_t *r_mergeMultidraws; cvar_t *r_mergeMultidraws;
cvar_t *r_mergeLeafSurfaces; cvar_t *r_mergeLeafSurfaces;
@ -111,6 +112,7 @@ cvar_t *r_cameraExposure;
cvar_t *r_softOverbright; cvar_t *r_softOverbright;
cvar_t *r_hdr; cvar_t *r_hdr;
cvar_t *r_floatLightmap;
cvar_t *r_postProcess; cvar_t *r_postProcess;
cvar_t *r_toneMap; cvar_t *r_toneMap;
@ -952,16 +954,6 @@ void GL_SetDefaultState( void )
qglDisable( GL_CULL_FACE ); qglDisable( GL_CULL_FACE );
qglDisable( GL_BLEND ); qglDisable( GL_BLEND );
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
qglClearDepth( 1.0 );
qglDrawBuffer( GL_FRONT );
qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
qglDrawBuffer( GL_BACK );
qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
if (glRefConfig.seamlessCubeMap) if (glRefConfig.seamlessCubeMap)
qglEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); qglEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
} }
@ -1135,6 +1127,7 @@ void R_Register( void )
r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_half_float_pixel = ri.Cvar_Get( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH); r_arb_half_float_pixel = ri.Cvar_Get( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH); r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic", r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
"0", CVAR_ARCHIVE | CVAR_LATCH ); "0", CVAR_ARCHIVE | CVAR_LATCH );
@ -1170,6 +1163,7 @@ void R_Register( void )
r_softOverbright = ri.Cvar_Get( "r_softOverbright", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_softOverbright = ri.Cvar_Get( "r_softOverbright", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_floatLightmap = ri.Cvar_Get( "r_floatLightmap", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE ); r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE );
r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH );

View file

@ -94,12 +94,17 @@ void R_DlightBmodel( bmodel_t *bmodel ) {
for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) { for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
surf = tr.world->surfaces + bmodel->firstSurface + i; surf = tr.world->surfaces + bmodel->firstSurface + i;
if ( *surf->data == SF_FACE ) { switch(*surf->data)
((srfSurfaceFace_t *)surf->data)->dlightBits = mask; {
} else if ( *surf->data == SF_GRID ) { case SF_FACE:
((srfGridMesh_t *)surf->data)->dlightBits = mask; case SF_GRID:
} else if ( *surf->data == SF_TRIANGLES ) { case SF_TRIANGLES:
((srfTriangles_t *)surf->data)->dlightBits = mask; case SF_VBO_MESH:
((srfBspSurface_t *)surf->data)->dlightBits = mask;
break;
default:
break;
} }
} }
} }
@ -403,8 +408,11 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
((byte *)&ent->ambientLightInt)[3] = 0xff; ((byte *)&ent->ambientLightInt)[3] = 0xff;
// transform the direction to local space // transform the direction to local space
// no need to do this if using lightentity glsl shader
VectorNormalize( lightDir ); VectorNormalize( lightDir );
ent->modelLightDir[0] = DotProduct( lightDir, ent->e.axis[0] );
ent->modelLightDir[1] = DotProduct( lightDir, ent->e.axis[1] );
ent->modelLightDir[2] = DotProduct( lightDir, ent->e.axis[2] );
VectorCopy(lightDir, ent->lightDir); VectorCopy(lightDir, ent->lightDir);
} }

View file

@ -47,10 +47,6 @@ typedef unsigned int glIndex_t;
#define SHADERNUM_BITS 14 #define SHADERNUM_BITS 14
#define MAX_SHADERS (1<<SHADERNUM_BITS) #define MAX_SHADERS (1<<SHADERNUM_BITS)
//#define MAX_SHADER_STATES 2048
#define MAX_STATES_PER_SHADER 32
#define MAX_STATE_NAME 32
#define MAX_FBOS 64 #define MAX_FBOS 64
#define MAX_VISCOUNTS 5 #define MAX_VISCOUNTS 5
#define MAX_VBOS 4096 #define MAX_VBOS 4096
@ -84,7 +80,8 @@ typedef struct {
qboolean needDlights; // true for bmodels that touch a dlight qboolean needDlights; // true for bmodels that touch a dlight
qboolean lightingCalculated; qboolean lightingCalculated;
qboolean mirrored; // mirrored matrix, needs reversed culling qboolean mirrored; // mirrored matrix, needs reversed culling
vec3_t lightDir; // normalized direction towards light vec3_t lightDir; // normalized direction towards light, in world space
vec3_t modelLightDir; // normalized direction towards light, in model space
vec3_t ambientLight; // color normalized to 0-255 vec3_t ambientLight; // color normalized to 0-255
int ambientLightInt; // 32 bit rgba packed int ambientLightInt; // 32 bit rgba packed
vec3_t directedLight; vec3_t directedLight;
@ -241,7 +238,6 @@ typedef enum {
AGEN_WAVEFORM, AGEN_WAVEFORM,
AGEN_PORTAL, AGEN_PORTAL,
AGEN_CONST, AGEN_CONST,
AGEN_FRESNEL
} alphaGen_t; } alphaGen_t;
typedef enum { typedef enum {
@ -354,7 +350,6 @@ typedef struct {
int videoMapHandle; int videoMapHandle;
qboolean isLightmap; qboolean isLightmap;
qboolean vertexLightmap;
qboolean isVideoMap; qboolean isVideoMap;
} textureBundle_t; } textureBundle_t;
@ -486,16 +481,8 @@ typedef struct shader_s {
float clampTime; // time this shader is clamped to float clampTime; // time this shader is clamped to
float timeOffset; // current time offset for this shader float timeOffset; // current time offset for this shader
int numStates; // if non-zero this is a state shader
struct shader_s *currentShader; // current state if this is a state shader
struct shader_s *parentShader; // current state if this is a state shader
int currentState; // current state index for cycle purposes
long expireTime; // time in milliseconds this expires
struct shader_s *remappedShader; // current shader this one is remapped too struct shader_s *remappedShader; // current shader this one is remapped too
int shaderStates[MAX_STATES_PER_SHADER]; // index to valid shader states
struct shader_s *next; struct shader_s *next;
} shader_t; } shader_t;
@ -522,14 +509,6 @@ static ID_INLINE qboolean ShaderRequiresCPUDeforms(const shader_t * shader)
return qfalse; return qfalse;
} }
typedef struct shaderState_s {
char shaderName[MAX_QPATH]; // name of shader this state belongs to
char name[MAX_STATE_NAME]; // name of this state
char stateShader[MAX_QPATH]; // shader this name invokes
int cycleTime; // time this cycle lasts, <= 0 is forever
shader_t *shader;
} shaderState_t;
enum enum
{ {
ATTR_INDEX_POSITION = 0, ATTR_INDEX_POSITION = 0,
@ -765,6 +744,7 @@ typedef enum
UNIFORM_LIGHTUP, UNIFORM_LIGHTUP,
UNIFORM_LIGHTRIGHT, UNIFORM_LIGHTRIGHT,
UNIFORM_LIGHTORIGIN, UNIFORM_LIGHTORIGIN,
UNIFORM_MODELLIGHTDIR,
UNIFORM_LIGHTRADIUS, UNIFORM_LIGHTRADIUS,
UNIFORM_AMBIENTLIGHT, UNIFORM_AMBIENTLIGHT,
UNIFORM_DIRECTEDLIGHT, UNIFORM_DIRECTEDLIGHT,
@ -785,6 +765,7 @@ typedef enum
UNIFORM_VIEWINFO, // znear, zfar, width/2, height/2 UNIFORM_VIEWINFO, // znear, zfar, width/2, height/2
UNIFORM_VIEWORIGIN, UNIFORM_VIEWORIGIN,
UNIFORM_LOCALVIEWORIGIN,
UNIFORM_VIEWFORWARD, UNIFORM_VIEWFORWARD,
UNIFORM_VIEWLEFT, UNIFORM_VIEWLEFT,
UNIFORM_VIEWUP, UNIFORM_VIEWUP,
@ -1026,13 +1007,10 @@ typedef struct
{ {
int indexes[3]; int indexes[3];
int neighbors[3]; int neighbors[3];
vec4_t plane;
qboolean facingLight;
qboolean degenerated;
} srfTriangle_t; } srfTriangle_t;
// srfBspSurface_t covers SF_GRID, SF_TRIANGLES, SF_POLY, and SF_VBO_MESH
typedef struct srfGridMesh_s typedef struct srfBspSurface_s
{ {
surfaceType_t surfaceType; surfaceType_t surfaceType;
@ -1041,9 +1019,30 @@ typedef struct srfGridMesh_s
int pshadowBits; int pshadowBits;
// culling information // culling information
vec3_t meshBounds[2]; vec3_t cullBounds[2];
vec3_t localOrigin; vec3_t cullOrigin;
float meshRadius; float cullRadius;
cplane_t cullPlane;
// triangle definitions
int numTriangles;
srfTriangle_t *triangles;
// vertexes
int numVerts;
srfVert_t *verts;
// BSP VBO offsets
int firstVert;
int firstIndex;
glIndex_t minIndex;
glIndex_t maxIndex;
// static render data
VBO_t *vbo;
IBO_t *ibo;
// SF_GRID specific variables after here
// lod information, which may be different // lod information, which may be different
// than the culling information to allow for // than the culling information to allow for
@ -1057,85 +1056,7 @@ typedef struct srfGridMesh_s
int width, height; int width, height;
float *widthLodError; float *widthLodError;
float *heightLodError; float *heightLodError;
} srfBspSurface_t;
int numTriangles;
srfTriangle_t *triangles;
int numVerts;
srfVert_t *verts;
// BSP VBO offsets
int firstVert;
int firstIndex;
glIndex_t minIndex;
glIndex_t maxIndex;
// static render data
VBO_t *vbo; // points to bsp model VBO
IBO_t *ibo;
} srfGridMesh_t;
typedef struct
{
surfaceType_t surfaceType;
// dynamic lighting information
int dlightBits;
int pshadowBits;
// culling information
cplane_t plane;
// vec3_t bounds[2];
// triangle definitions
int numTriangles;
srfTriangle_t *triangles;
int numVerts;
srfVert_t *verts;
// BSP VBO offsets
int firstVert;
int firstIndex;
glIndex_t minIndex;
glIndex_t maxIndex;
// static render data
VBO_t *vbo; // points to bsp model VBO
IBO_t *ibo;
} srfSurfaceFace_t;
// misc_models in maps are turned into direct geometry by xmap
typedef struct
{
surfaceType_t surfaceType;
// dynamic lighting information
int dlightBits;
int pshadowBits;
// culling information
// vec3_t bounds[2];
// triangle definitions
int numTriangles;
srfTriangle_t *triangles;
int numVerts;
srfVert_t *verts;
// BSP VBO offsets
int firstVert;
int firstIndex;
glIndex_t minIndex;
glIndex_t maxIndex;
// static render data
VBO_t *vbo; // points to bsp model VBO
IBO_t *ibo;
} srfTriangles_t;
// inter-quake-model // inter-quake-model
typedef struct { typedef struct {
@ -1144,6 +1065,7 @@ typedef struct {
int num_frames; int num_frames;
int num_surfaces; int num_surfaces;
int num_joints; int num_joints;
int num_poses;
struct srfIQModel_s *surfaces; struct srfIQModel_s *surfaces;
float *positions; float *positions;
@ -1151,10 +1073,18 @@ typedef struct {
float *normals; float *normals;
float *tangents; float *tangents;
byte *blendIndexes; byte *blendIndexes;
byte *blendWeights; union {
float *f;
byte *b;
} blendWeights;
byte *colors; byte *colors;
int *triangles; int *triangles;
// depending upon the exporter, blend indices and weights might be int/float
// as opposed to the recommended byte/byte, for example Noesis exports
// int/float whereas the official IQM tool exports byte/byte
byte blendWeightsType; // IQM_UBYTE or IQM_FLOAT
int *jointParents; int *jointParents;
float *jointMats; float *jointMats;
float *poseMats; float *poseMats;
@ -1172,33 +1102,6 @@ typedef struct srfIQModel_s {
int first_triangle, num_triangles; int first_triangle, num_triangles;
} srfIQModel_t; } srfIQModel_t;
typedef struct srfVBOMesh_s
{
surfaceType_t surfaceType;
struct shader_s *shader; // FIXME move this to somewhere else
int fogIndex;
int cubemapIndex;
// dynamic lighting information
int dlightBits;
int pshadowBits;
// culling information
vec3_t bounds[2];
// backEnd stats
int numIndexes;
int numVerts;
int firstIndex;
glIndex_t minIndex;
glIndex_t maxIndex;
// static render data
VBO_t *vbo;
IBO_t *ibo;
} srfVBOMesh_t;
typedef struct srfVBOMDVMesh_s typedef struct srfVBOMDVMesh_s
{ {
surfaceType_t surfaceType; surfaceType_t surfaceType;
@ -1332,9 +1235,6 @@ typedef struct {
int numDecisionNodes; int numDecisionNodes;
mnode_t *nodes; mnode_t *nodes;
VBO_t *vbo;
IBO_t *ibo;
int numWorldSurfaces; int numWorldSurfaces;
int numsurfaces; int numsurfaces;
@ -1564,6 +1464,7 @@ typedef struct {
uint32_t vertexAttribsNewFrame; uint32_t vertexAttribsNewFrame;
uint32_t vertexAttribsOldFrame; uint32_t vertexAttribsOldFrame;
float vertexAttribsInterpolation; float vertexAttribsInterpolation;
qboolean vertexAnimation;
shaderProgram_t *currentProgram; shaderProgram_t *currentProgram;
FBO_t *currentFBO; FBO_t *currentFBO;
VBO_t *currentVBO; VBO_t *currentVBO;
@ -1916,6 +1817,7 @@ extern cvar_t *r_ext_framebuffer_object;
extern cvar_t *r_ext_texture_float; extern cvar_t *r_ext_texture_float;
extern cvar_t *r_arb_half_float_pixel; extern cvar_t *r_arb_half_float_pixel;
extern cvar_t *r_ext_framebuffer_multisample; extern cvar_t *r_ext_framebuffer_multisample;
extern cvar_t *r_arb_seamless_cube_map;
extern cvar_t *r_nobind; // turns off binding to appropriate textures extern cvar_t *r_nobind; // turns off binding to appropriate textures
extern cvar_t *r_singleShader; // make most world faces use default shader extern cvar_t *r_singleShader; // make most world faces use default shader
@ -1959,6 +1861,7 @@ extern cvar_t *r_mergeLeafSurfaces;
extern cvar_t *r_softOverbright; extern cvar_t *r_softOverbright;
extern cvar_t *r_hdr; extern cvar_t *r_hdr;
extern cvar_t *r_floatLightmap;
extern cvar_t *r_postProcess; extern cvar_t *r_postProcess;
extern cvar_t *r_toneMap; extern cvar_t *r_toneMap;
@ -2053,8 +1956,6 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,
void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal, void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2); const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2);
qboolean R_CalcTangentVectors(srfVert_t * dv[3]); qboolean R_CalcTangentVectors(srfVert_t * dv[3]);
void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles);
void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts);
#define CULL_IN 0 // completely unclipped #define CULL_IN 0 // completely unclipped
#define CULL_CLIP 1 // clipped by one or more planes #define CULL_CLIP 1 // clipped by one or more planes
@ -2349,11 +2250,11 @@ CURVE TESSELATION
#define PATCH_STITCHING #define PATCH_STITCHING
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, srfBspSurface_t *R_SubdividePatchToGrid( int width, int height,
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ); srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] );
srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ); srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row, vec3_t point, float loderror );
srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ); srfBspSurface_t *R_GridInsertRow( srfBspSurface_t *grid, int row, int column, vec3_t point, float loderror );
void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ); void R_FreeSurfaceGridMesh( srfBspSurface_t *grid );
/* /*
============================================================ ============================================================
@ -2500,35 +2401,18 @@ void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t
void RB_DeformTessGeometry( void ); void RB_DeformTessGeometry( void );
void RB_CalcEnvironmentTexCoords( float *dstTexCoords );
void RB_CalcFogTexCoords( float *dstTexCoords ); void RB_CalcFogTexCoords( float *dstTexCoords );
void RB_CalcScrollTexCoords( const float scroll[2], float *dstTexCoords );
void RB_CalcRotateTexCoords( float rotSpeed, float *dstTexCoords );
void RB_CalcScaleTexCoords( const float scale[2], float *dstTexCoords );
void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *dstTexCoords );
void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *dstTexCoords );
void RB_CalcScaleTexMatrix( const float scale[2], float *matrix ); void RB_CalcScaleTexMatrix( const float scale[2], float *matrix );
void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix ); void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix );
void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix ); void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix );
void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix ); void RB_CalcTurbulentFactors( const waveForm_t *wf, float *amplitude, float *now );
void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix ); void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix );
void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix ); void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix );
void RB_CalcModulateColorsByFog( unsigned char *dstColors ); void RB_CalcModulateColorsByFog( unsigned char *dstColors );
void RB_CalcModulateAlphasByFog( unsigned char *dstColors );
void RB_CalcModulateRGBAsByFog( unsigned char *dstColors );
void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors );
float RB_CalcWaveAlphaSingle( const waveForm_t *wf ); float RB_CalcWaveAlphaSingle( const waveForm_t *wf );
void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors );
float RB_CalcWaveColorSingle( const waveForm_t *wf ); float RB_CalcWaveColorSingle( const waveForm_t *wf );
void RB_CalcAlphaFromEntity( unsigned char *dstColors );
void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors );
void RB_CalcStretchTexCoords( const waveForm_t *wf, float *texCoords );
void RB_CalcColorFromEntity( unsigned char *dstColors );
void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors );
void RB_CalcSpecularAlpha( unsigned char *alphas );
void RB_CalcDiffuseColor( unsigned char *colors );
/* /*
============================================================= =============================================================

View file

@ -492,99 +492,6 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
#endif #endif
/*
=================
R_FindSurfaceTriangleWithEdge
Recoded from Q2E
=================
*/
static int R_FindSurfaceTriangleWithEdge(int numTriangles, srfTriangle_t * triangles, int start, int end, int ignore)
{
srfTriangle_t *tri;
int count, match;
int i;
count = 0;
match = -1;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
if((tri->indexes[0] == start && tri->indexes[1] == end) ||
(tri->indexes[1] == start && tri->indexes[2] == end) || (tri->indexes[2] == start && tri->indexes[0] == end))
{
if(i != ignore)
{
match = i;
}
count++;
}
else if((tri->indexes[1] == start && tri->indexes[0] == end) ||
(tri->indexes[2] == start && tri->indexes[1] == end) || (tri->indexes[0] == start && tri->indexes[2] == end))
{
count++;
}
}
// detect edges shared by three triangles and make them seams
if(count > 2)
{
match = -1;
}
return match;
}
/*
=================
R_CalcSurfaceTriangleNeighbors
Recoded from Q2E
=================
*/
void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles)
{
int i;
srfTriangle_t *tri;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
tri->neighbors[0] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[1], tri->indexes[0], i);
tri->neighbors[1] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[2], tri->indexes[1], i);
tri->neighbors[2] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[0], tri->indexes[2], i);
}
}
/*
=================
R_CalcSurfaceTrianglePlanes
=================
*/
void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts)
{
int i;
srfTriangle_t *tri;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
float *v1, *v2, *v3;
vec3_t d1, d2;
v1 = verts[tri->indexes[0]].xyz;
v2 = verts[tri->indexes[1]].xyz;
v3 = verts[tri->indexes[2]].xyz;
VectorSubtract(v2, v1, d1);
VectorSubtract(v3, v1, d2);
CrossProduct(d2, d1, tri->plane);
tri->plane[3] = DotProduct(tri->plane, v1);
}
}
/* /*
================= =================
R_CullLocalBox R_CullLocalBox
@ -1365,7 +1272,7 @@ R_PlaneForSurface
============= =============
*/ */
void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) { void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) {
srfTriangles_t *tri; srfBspSurface_t *tri;
srfPoly_t *poly; srfPoly_t *poly;
srfVert_t *v1, *v2, *v3; srfVert_t *v1, *v2, *v3;
vec4_t plane4; vec4_t plane4;
@ -1377,10 +1284,10 @@ void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) {
} }
switch (*surfType) { switch (*surfType) {
case SF_FACE: case SF_FACE:
*plane = ((srfSurfaceFace_t *)surfType)->plane; *plane = ((srfBspSurface_t *)surfType)->cullPlane;
return; return;
case SF_TRIANGLES: case SF_TRIANGLES:
tri = (srfTriangles_t *)surfType; tri = (srfBspSurface_t *)surfType;
v1 = tri->verts + tri->triangles[0].indexes[0]; v1 = tri->verts + tri->triangles[0].indexes[0];
v2 = tri->verts + tri->triangles[0].indexes[1]; v2 = tri->verts + tri->triangles[0].indexes[1];
v3 = tri->verts + tri->triangles[0].indexes[2]; v3 = tri->verts + tri->triangles[0].indexes[2];

View file

@ -268,7 +268,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
vec3_t clipPoints[2][MAX_VERTS_ON_POLY]; vec3_t clipPoints[2][MAX_VERTS_ON_POLY];
int numClipPoints; int numClipPoints;
float *v; float *v;
srfGridMesh_t *cv; srfBspSurface_t *cv;
srfTriangle_t *tri; srfTriangle_t *tri;
srfVert_t *dv; srfVert_t *dv;
vec3_t normal; vec3_t normal;
@ -327,7 +327,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
if (*surfaces[i] == SF_GRID) { if (*surfaces[i] == SF_GRID) {
cv = (srfGridMesh_t *) surfaces[i]; cv = (srfBspSurface_t *) surfaces[i];
for ( m = 0 ; m < cv->height - 1 ; m++ ) { for ( m = 0 ; m < cv->height - 1 ; m++ ) {
for ( n = 0 ; n < cv->width - 1 ; n++ ) { for ( n = 0 ; n < cv->width - 1 ; n++ ) {
// We triangulate the grid and chop all triangles within // We triangulate the grid and chop all triangles within
@ -407,10 +407,10 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
} }
else if (*surfaces[i] == SF_FACE) { else if (*surfaces[i] == SF_FACE) {
srfSurfaceFace_t *surf = ( srfSurfaceFace_t * ) surfaces[i]; srfBspSurface_t *surf = ( srfBspSurface_t * ) surfaces[i];
// check the normal of this face // check the normal of this face
if (DotProduct(surf->plane.normal, projectionDir) > -0.5) { if (DotProduct(surf->cullPlane.normal, projectionDir) > -0.5) {
continue; continue;
} }
@ -419,7 +419,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
for(j = 0; j < 3; j++) for(j = 0; j < 3; j++)
{ {
v = surf->verts[tri->indexes[j]].xyz; v = surf->verts[tri->indexes[j]].xyz;
VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]); VectorMA(v, MARKER_OFFSET, surf->cullPlane.normal, clipPoints[0][j]);
} }
// add the fragments of this face // add the fragments of this face
@ -435,7 +435,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
} }
else if(*surfaces[i] == SF_TRIANGLES && r_marksOnTriangleMeshes->integer) { else if(*surfaces[i] == SF_TRIANGLES && r_marksOnTriangleMeshes->integer) {
srfTriangles_t *surf = (srfTriangles_t *) surfaces[i]; srfBspSurface_t *surf = (srfBspSurface_t *) surfaces[i];
for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++) for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++)
{ {

View file

@ -562,8 +562,6 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
tri->indexes[2] = LittleLong(md3Tri->indexes[2]); tri->indexes[2] = LittleLong(md3Tri->indexes[2]);
} }
R_CalcSurfaceTriangleNeighbors(surf->numTriangles, surf->triangles);
// swap all the XyzNormals // swap all the XyzNormals
surf->numVerts = md3Surf->numVerts; surf->numVerts = md3Surf->numVerts;
surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (md3Surf->numVerts * md3Surf->numFrames), h_low); surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (md3Surf->numVerts * md3Surf->numFrames), h_low);

View file

@ -25,6 +25,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define LL(x) x=LittleLong(x) #define LL(x) x=LittleLong(x)
// 3x4 identity matrix
static float identityMatrix[12] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0
};
static qboolean IQM_CheckRange( iqmHeader_t *header, int offset, static qboolean IQM_CheckRange( iqmHeader_t *header, int offset,
int count,int size ) { int count,int size ) {
// return true if the range specified by offset, count and size // return true if the range specified by offset, count and size
@ -143,6 +150,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
iqmData_t *iqmData; iqmData_t *iqmData;
srfIQModel_t *surface; srfIQModel_t *surface;
char meshName[MAX_QPATH]; char meshName[MAX_QPATH];
byte blendIndexesType, blendWeightsType;
if( filesize < sizeof(iqmHeader_t) ) { if( filesize < sizeof(iqmHeader_t) ) {
return qfalse; return qfalse;
@ -198,6 +206,8 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
return qfalse; return qfalse;
} }
blendIndexesType = blendWeightsType = IQM_UBYTE;
// check and swap vertex arrays // check and swap vertex arrays
if( IQM_CheckRange( header, header->ofs_vertexarrays, if( IQM_CheckRange( header, header->ofs_vertexarrays,
header->num_vertexarrays, header->num_vertexarrays,
@ -264,11 +274,20 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
} }
break; break;
case IQM_BLENDINDEXES: case IQM_BLENDINDEXES:
case IQM_BLENDWEIGHTS: if( (vertexarray->format != IQM_INT &&
if( vertexarray->format != IQM_UBYTE || vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) { vertexarray->size != 4 ) {
return qfalse; return qfalse;
} }
blendIndexesType = vertexarray->format;
break;
case IQM_BLENDWEIGHTS:
if( (vertexarray->format != IQM_FLOAT &&
vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) {
return qfalse;
}
blendWeightsType = vertexarray->format;
break; break;
case IQM_COLOR: case IQM_COLOR:
if( vertexarray->format != IQM_UBYTE || if( vertexarray->format != IQM_UBYTE ||
@ -343,7 +362,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
} }
} }
if( header->num_poses != header->num_joints ) { if( header->num_poses != header->num_joints && header->num_poses != 0 ) {
ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has %d poses and %d joints, must have the same number or 0 poses\n",
mod_name, header->num_poses, header->num_joints );
return qfalse; return qfalse;
} }
@ -379,7 +400,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
joint_names += strlen( (char *)header + header->ofs_text + joint_names += strlen( (char *)header + header->ofs_text +
joint->name ) + 1; joint->name ) + 1;
} }
}
if ( header->num_poses )
{
// check and swap poses // check and swap poses
if( IQM_CheckRange( header, header->ofs_poses, if( IQM_CheckRange( header, header->ofs_poses,
header->num_poses, sizeof(iqmPose_t) ) ) { header->num_poses, sizeof(iqmPose_t) ) ) {
@ -438,7 +462,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
size = sizeof(iqmData_t); size = sizeof(iqmData_t);
size += header->num_meshes * sizeof( srfIQModel_t ); size += header->num_meshes * sizeof( srfIQModel_t );
size += header->num_joints * 12 * sizeof( float ); // joint mats size += header->num_joints * 12 * sizeof( float ); // joint mats
size += header->num_joints * header->num_frames * 12 * sizeof( float ); // pose mats size += header->num_poses * header->num_frames * 12 * sizeof( float ); // pose mats
if(header->ofs_bounds) if(header->ofs_bounds)
size += header->num_frames * 6 * sizeof(float); // model bounds size += header->num_frames * 6 * sizeof(float); // model bounds
size += header->num_vertexes * 3 * sizeof(float); // positions size += header->num_vertexes * 3 * sizeof(float); // positions
@ -446,12 +470,18 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
size += header->num_vertexes * 3 * sizeof(float); // normals size += header->num_vertexes * 3 * sizeof(float); // normals
size += header->num_vertexes * 4 * sizeof(float); // tangents size += header->num_vertexes * 4 * sizeof(float); // tangents
size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes
size += header->num_vertexes * 4 * sizeof(byte); // blendWeights
size += header->num_vertexes * 4 * sizeof(byte); // colors size += header->num_vertexes * 4 * sizeof(byte); // colors
size += header->num_joints * sizeof(int); // parents size += header->num_joints * sizeof(int); // parents
size += header->num_triangles * 3 * sizeof(int); // triangles size += header->num_triangles * 3 * sizeof(int); // triangles
size += joint_names; // joint names size += joint_names; // joint names
// blendWeights
if (blendWeightsType == IQM_FLOAT) {
size += header->num_vertexes * 4 * sizeof(float);
} else {
size += header->num_vertexes * 4 * sizeof(byte);
}
mod->type = MOD_IQM; mod->type = MOD_IQM;
iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low ); iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low );
mod->modelData = iqmData; mod->modelData = iqmData;
@ -462,28 +492,40 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
iqmData->num_frames = header->num_frames; iqmData->num_frames = header->num_frames;
iqmData->num_surfaces = header->num_meshes; iqmData->num_surfaces = header->num_meshes;
iqmData->num_joints = header->num_joints; iqmData->num_joints = header->num_joints;
iqmData->num_poses = header->num_poses;
iqmData->blendWeightsType = blendWeightsType;
iqmData->surfaces = (srfIQModel_t *)(iqmData + 1); iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces); iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints; iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints;
if(header->ofs_bounds) if(header->ofs_bounds)
{ {
iqmData->bounds = iqmData->poseMats + 12 * header->num_joints * header->num_frames; iqmData->bounds = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
iqmData->positions = iqmData->bounds + 6 * header->num_frames; iqmData->positions = iqmData->bounds + 6 * header->num_frames;
} }
else else
iqmData->positions = iqmData->poseMats + 12 * header->num_joints * header->num_frames; iqmData->positions = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes; iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes;
iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes; iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes;
iqmData->tangents = iqmData->normals + 3 * header->num_vertexes; iqmData->tangents = iqmData->normals + 3 * header->num_vertexes;
iqmData->blendIndexes = (byte *)(iqmData->tangents + 4 * header->num_vertexes); iqmData->blendIndexes = (byte *)(iqmData->tangents + 4 * header->num_vertexes);
iqmData->blendWeights = iqmData->blendIndexes + 4 * header->num_vertexes;
iqmData->colors = iqmData->blendWeights + 4 * header->num_vertexes; if(blendWeightsType == IQM_FLOAT) {
iqmData->blendWeights.f = (float *)(iqmData->blendIndexes + 4 * header->num_vertexes);
iqmData->colors = (byte *)(iqmData->blendWeights.f + 4 * header->num_vertexes);
} else {
iqmData->blendWeights.b = iqmData->blendIndexes + 4 * header->num_vertexes;
iqmData->colors = iqmData->blendWeights.b + 4 * header->num_vertexes;
}
iqmData->jointParents = (int *)(iqmData->colors + 4 * header->num_vertexes); iqmData->jointParents = (int *)(iqmData->colors + 4 * header->num_vertexes);
iqmData->triangles = iqmData->jointParents + header->num_joints; iqmData->triangles = iqmData->jointParents + header->num_joints;
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles); iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
if ( header->num_joints == 0 ) if ( header->num_joints == 0 )
iqmData->jointMats = iqmData->poseMats = NULL; iqmData->jointMats = NULL;
if ( header->num_poses == 0 )
iqmData->poseMats = NULL;
// calculate joint matrices and their inverses // calculate joint matrices and their inverses
// joint inverses are needed only until the pose matrices are calculated // joint inverses are needed only until the pose matrices are calculated
@ -620,14 +662,27 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
n * sizeof(float) ); n * sizeof(float) );
break; break;
case IQM_BLENDINDEXES: case IQM_BLENDINDEXES:
if( blendIndexesType == IQM_INT ) {
int *data = (int*)((byte*)header + vertexarray->offset);
for ( j = 0; j < n; j++ ) {
iqmData->blendIndexes[j] = (byte)data[j];
}
} else {
Com_Memcpy( iqmData->blendIndexes, Com_Memcpy( iqmData->blendIndexes,
(byte *)header + vertexarray->offset, (byte *)header + vertexarray->offset,
n * sizeof(byte) ); n * sizeof(byte) );
}
break; break;
case IQM_BLENDWEIGHTS: case IQM_BLENDWEIGHTS:
Com_Memcpy( iqmData->blendWeights, if( blendWeightsType == IQM_FLOAT ) {
Com_Memcpy( iqmData->blendWeights.f,
(byte *)header + vertexarray->offset,
n * sizeof(float) );
} else {
Com_Memcpy( iqmData->blendWeights.b,
(byte *)header + vertexarray->offset, (byte *)header + vertexarray->offset,
n * sizeof(byte) ); n * sizeof(byte) );
}
break; break;
case IQM_COLOR: case IQM_COLOR:
Com_Memcpy( iqmData->colors, Com_Memcpy( iqmData->colors,
@ -895,9 +950,21 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
int *joint = data->jointParents; int *joint = data->jointParents;
int i; int i;
if ( oldframe == frame ) { if ( data->num_poses == 0 ) {
mat1 = data->poseMats + 12 * data->num_joints * frame;
for( i = 0; i < data->num_joints; i++, joint++ ) { for( i = 0; i < data->num_joints; i++, joint++ ) {
if( *joint >= 0 ) {
Matrix34Multiply( mat + 12 * *joint,
identityMatrix, mat + 12*i );
} else {
Com_Memcpy( mat + 12*i, identityMatrix, 12 * sizeof(float) );
}
}
return;
}
if ( oldframe == frame ) {
mat1 = data->poseMats + 12 * data->num_poses * frame;
for( i = 0; i < data->num_poses; i++, joint++ ) {
if( *joint >= 0 ) { if( *joint >= 0 ) {
Matrix34Multiply( mat + 12 * *joint, Matrix34Multiply( mat + 12 * *joint,
mat1 + 12*i, mat + 12*i ); mat1 + 12*i, mat + 12*i );
@ -906,10 +973,10 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
} }
} }
} else { } else {
mat1 = data->poseMats + 12 * data->num_joints * frame; mat1 = data->poseMats + 12 * data->num_poses * frame;
mat2 = data->poseMats + 12 * data->num_joints * oldframe; mat2 = data->poseMats + 12 * data->num_poses * oldframe;
for( i = 0; i < data->num_joints; i++, joint++ ) { for( i = 0; i < data->num_poses; i++, joint++ ) {
if( *joint >= 0 ) { if( *joint >= 0 ) {
float tmpMat[12]; float tmpMat[12];
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i, InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
@ -977,7 +1044,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
outColor = &tess.vertexColors[tess.numVertexes]; outColor = &tess.vertexColors[tess.numVertexes];
// compute interpolated joint matrices // compute interpolated joint matrices
if ( data->num_joints > 0 ) { if ( data->num_poses > 0 ) {
ComputePoseMats( data, frame, oldframe, backlerp, jointMats ); ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
} }
@ -988,28 +1055,31 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
float vtxMat[12]; float vtxMat[12];
float nrmMat[9]; float nrmMat[9];
int vtx = i + surf->first_vertex; int vtx = i + surf->first_vertex;
float blendWeights[4];
int numWeights;
if ( data->num_joints == 0 || data->blendWeights[4*vtx] <= 0 ) { for ( numWeights = 0; numWeights < 4; numWeights++ ) {
// no blend joint, use identity matrix. if ( data->blendWeightsType == IQM_FLOAT )
for( j = 0; j < 3; j++ ) { blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights];
for( k = 0; k < 4; k++ ) else
vtxMat[4*j+k] = ( k == j ) ? 1 : 0; blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f;
if ( blendWeights[numWeights] <= 0 )
break;
} }
if ( data->num_poses == 0 || numWeights == 0 ) {
// no blend joint, use identity matrix.
Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) );
} else { } else {
// compute the vertex matrix by blending the up to // compute the vertex matrix by blending the up to
// four blend weights // four blend weights
for( k = 0; k < 12; k++ ) Com_Memset( vtxMat, 0, 12 * sizeof (float) );
vtxMat[k] = data->blendWeights[4*vtx] for( j = 0; j < numWeights; j++ ) {
* jointMats[12*data->blendIndexes[4*vtx] + k]; for( k = 0; k < 12; k++ ) {
for( j = 1; j < 4; j++ ) { vtxMat[k] += blendWeights[j] * jointMats[12*data->blendIndexes[4*vtx + j] + k];
if( data->blendWeights[4*vtx + j] <= 0 ) }
break;
for( k = 0; k < 12; k++ )
vtxMat[k] += data->blendWeights[4*vtx + j]
* jointMats[12*data->blendIndexes[4*vtx + j] + k];
} }
for( k = 0; k < 12; k++ )
vtxMat[k] *= 1.0f / 255.0f;
} }
// compute the normal matrix as transpose of the adjoint // compute the normal matrix as transpose of the adjoint

View file

@ -221,14 +221,22 @@ extern float EvalWaveForm( const waveForm_t *wf );
extern float EvalWaveFormClamped( const waveForm_t *wf ); extern float EvalWaveFormClamped( const waveForm_t *wf );
static void ComputeTexMatrix( shaderStage_t *pStage, int bundleNum, float *outmatrix) static void ComputeTexMods( shaderStage_t *pStage, int bundleNum, float *outMatrix, float *outOffTurb)
{ {
int tm; int tm;
float matrix[16], currentmatrix[16]; float matrix[6], currentmatrix[6];
textureBundle_t *bundle = &pStage->bundle[bundleNum]; textureBundle_t *bundle = &pStage->bundle[bundleNum];
Matrix16Identity(outmatrix); matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = 0.0f;
Matrix16Identity(currentmatrix); matrix[1] = 0.0f; matrix[3] = 1.0f; matrix[5] = 0.0f;
currentmatrix[0] = 1.0f; currentmatrix[2] = 0.0f; currentmatrix[4] = 0.0f;
currentmatrix[1] = 0.0f; currentmatrix[3] = 1.0f; currentmatrix[5] = 0.0f;
outMatrix[0] = 1.0f; outMatrix[2] = 0.0f;
outMatrix[1] = 0.0f; outMatrix[3] = 1.0f;
outOffTurb[0] = 0.0f; outOffTurb[1] = 0.0f; outOffTurb[2] = 0.0f; outOffTurb[3] = 0.0f;
for ( tm = 0; tm < bundle->numTexMods ; tm++ ) { for ( tm = 0; tm < bundle->numTexMods ; tm++ ) {
switch ( bundle->texMods[tm].type ) switch ( bundle->texMods[tm].type )
@ -239,59 +247,73 @@ static void ComputeTexMatrix( shaderStage_t *pStage, int bundleNum, float *outma
break; break;
case TMOD_TURBULENT: case TMOD_TURBULENT:
RB_CalcTurbulentTexMatrix( &bundle->texMods[tm].wave, RB_CalcTurbulentFactors(&bundle->texMods[tm].wave, &outOffTurb[2], &outOffTurb[3]);
matrix );
outmatrix[12] = matrix[12];
outmatrix[13] = matrix[13];
Matrix16Copy(outmatrix, currentmatrix);
break; break;
case TMOD_ENTITY_TRANSLATE: case TMOD_ENTITY_TRANSLATE:
RB_CalcScrollTexMatrix( backEnd.currentEntity->e.shaderTexCoord, RB_CalcScrollTexMatrix( backEnd.currentEntity->e.shaderTexCoord, matrix );
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break; break;
case TMOD_SCROLL: case TMOD_SCROLL:
RB_CalcScrollTexMatrix( bundle->texMods[tm].scroll, RB_CalcScrollTexMatrix( bundle->texMods[tm].scroll,
matrix ); matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break; break;
case TMOD_SCALE: case TMOD_SCALE:
RB_CalcScaleTexMatrix( bundle->texMods[tm].scale, RB_CalcScaleTexMatrix( bundle->texMods[tm].scale,
matrix ); matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break; break;
case TMOD_STRETCH: case TMOD_STRETCH:
RB_CalcStretchTexMatrix( &bundle->texMods[tm].wave, RB_CalcStretchTexMatrix( &bundle->texMods[tm].wave,
matrix ); matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break; break;
case TMOD_TRANSFORM: case TMOD_TRANSFORM:
RB_CalcTransformTexMatrix( &bundle->texMods[tm], RB_CalcTransformTexMatrix( &bundle->texMods[tm],
matrix ); matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break; break;
case TMOD_ROTATE: case TMOD_ROTATE:
RB_CalcRotateTexMatrix( bundle->texMods[tm].rotateSpeed, RB_CalcRotateTexMatrix( bundle->texMods[tm].rotateSpeed,
matrix ); matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break; break;
default: default:
ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'", bundle->texMods[tm].type, tess.shader->name ); ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'", bundle->texMods[tm].type, tess.shader->name );
break; break;
} }
switch ( bundle->texMods[tm].type )
{
case TMOD_NONE:
case TMOD_TURBULENT:
default:
break;
case TMOD_ENTITY_TRANSLATE:
case TMOD_SCROLL:
case TMOD_SCALE:
case TMOD_STRETCH:
case TMOD_TRANSFORM:
case TMOD_ROTATE:
outMatrix[0] = matrix[0] * currentmatrix[0] + matrix[2] * currentmatrix[1];
outMatrix[1] = matrix[1] * currentmatrix[0] + matrix[3] * currentmatrix[1];
outMatrix[2] = matrix[0] * currentmatrix[2] + matrix[2] * currentmatrix[3];
outMatrix[3] = matrix[1] * currentmatrix[2] + matrix[3] * currentmatrix[3];
outOffTurb[0] = matrix[0] * currentmatrix[4] + matrix[2] * currentmatrix[5] + matrix[4];
outOffTurb[1] = matrix[1] * currentmatrix[4] + matrix[3] * currentmatrix[5] + matrix[5];
currentmatrix[0] = outMatrix[0];
currentmatrix[1] = outMatrix[1];
currentmatrix[2] = outMatrix[2];
currentmatrix[3] = outMatrix[3];
currentmatrix[4] = outOffTurb[0];
currentmatrix[5] = outOffTurb[1];
break;
}
} }
} }
@ -423,44 +445,27 @@ static void ProjectDlightTexture( void ) {
static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor ) static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor )
{ {
baseColor[0] =
baseColor[1] =
baseColor[2] =
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
// //
// rgbGen // rgbGen
// //
switch ( pStage->rgbGen ) switch ( pStage->rgbGen )
{ {
case CGEN_IDENTITY:
baseColor[0] =
baseColor[1] =
baseColor[2] =
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_IDENTITY_LIGHTING: case CGEN_IDENTITY_LIGHTING:
baseColor[0] = baseColor[0] =
baseColor[1] = baseColor[1] =
baseColor[2] = tr.identityLight; baseColor[2] = tr.identityLight;
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break; break;
case CGEN_EXACT_VERTEX: case CGEN_EXACT_VERTEX:
baseColor[0] =
baseColor[1] =
baseColor[2] =
baseColor[3] = 0.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 1.0f;
break;
case CGEN_EXACT_VERTEX_LIT: case CGEN_EXACT_VERTEX_LIT:
baseColor[0] = baseColor[0] =
baseColor[1] = baseColor[1] =
@ -477,11 +482,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[1] = pStage->constantColor[1] / 255.0f; baseColor[1] = pStage->constantColor[1] / 255.0f;
baseColor[2] = pStage->constantColor[2] / 255.0f; baseColor[2] = pStage->constantColor[2] / 255.0f;
baseColor[3] = pStage->constantColor[3] / 255.0f; baseColor[3] = pStage->constantColor[3] / 255.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break; break;
case CGEN_VERTEX: case CGEN_VERTEX:
baseColor[0] = baseColor[0] =
@ -509,12 +509,10 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[0] = baseColor[0] =
baseColor[1] = baseColor[1] =
baseColor[2] = tr.identityLight; baseColor[2] = tr.identityLight;
baseColor[3] = 1.0f;
vertColor[0] = vertColor[0] =
vertColor[1] = vertColor[1] =
vertColor[2] = -tr.identityLight; vertColor[2] = -tr.identityLight;
vertColor[3] = 0.0f;
break; break;
case CGEN_FOG: case CGEN_FOG:
{ {
@ -527,22 +525,11 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f; baseColor[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f;
baseColor[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f; baseColor[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f;
} }
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break; break;
case CGEN_WAVEFORM: case CGEN_WAVEFORM:
baseColor[0] = baseColor[0] =
baseColor[1] = baseColor[1] =
baseColor[2] = RB_CalcWaveColorSingle( &pStage->rgbWave ); baseColor[2] = RB_CalcWaveColorSingle( &pStage->rgbWave );
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break; break;
case CGEN_ENTITY: case CGEN_ENTITY:
if (backEnd.currentEntity) if (backEnd.currentEntity)
@ -552,11 +539,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[2] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f; baseColor[2] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f;
baseColor[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; baseColor[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
} }
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break; break;
case CGEN_ONE_MINUS_ENTITY: case CGEN_ONE_MINUS_ENTITY:
if (backEnd.currentEntity) if (backEnd.currentEntity)
@ -566,23 +548,10 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[2] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f; baseColor[2] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f;
baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
} }
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break; break;
case CGEN_IDENTITY:
case CGEN_LIGHTING_DIFFUSE: case CGEN_LIGHTING_DIFFUSE:
case CGEN_BAD: case CGEN_BAD:
baseColor[0] =
baseColor[1] =
baseColor[2] =
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break; break;
} }
@ -593,10 +562,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
{ {
case AGEN_SKIP: case AGEN_SKIP:
break; break;
case AGEN_IDENTITY:
baseColor[3] = 1.0f;
vertColor[3] = 0.0f;
break;
case AGEN_CONST: case AGEN_CONST:
baseColor[3] = pStage->constantColor[3] / 255.0f; baseColor[3] = pStage->constantColor[3] / 255.0f;
vertColor[3] = 0.0f; vertColor[3] = 0.0f;
@ -627,9 +592,9 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[3] = 1.0f; baseColor[3] = 1.0f;
vertColor[3] = -1.0f; vertColor[3] = -1.0f;
break; break;
case AGEN_IDENTITY:
case AGEN_LIGHTING_SPECULAR: case AGEN_LIGHTING_SPECULAR:
case AGEN_PORTAL: case AGEN_PORTAL:
case AGEN_FRESNEL:
// Done entirely in vertex program // Done entirely in vertex program
baseColor[3] = 1.0f; baseColor[3] = 1.0f;
vertColor[3] = 0.0f; vertColor[3] = 0.0f;
@ -749,7 +714,8 @@ static void ForwardDlight( void ) {
dlight_t *dl; dlight_t *dl;
shaderProgram_t *sp; shaderProgram_t *sp;
vec4_t vector; vec4_t vector;
matrix_t matrix; vec4_t texMatrix;
vec4_t texOffTurb;
if ( !( tess.dlightBits & ( 1 << l ) ) ) { if ( !( tess.dlightBits & ( 1 << l ) ) ) {
continue; // this surface definately doesn't have any of this light continue; // this surface definately doesn't have any of this light
@ -776,6 +742,7 @@ static void ForwardDlight( void ) {
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin);
GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
@ -851,13 +818,9 @@ static void ForwardDlight( void ) {
GL_SelectTexture(0); GL_SelectTexture(0);
} }
ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector);
VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector);
GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
@ -982,7 +945,7 @@ static void RB_FogPass( void ) {
if (deformGen != DGEN_NONE) if (deformGen != DGEN_NONE)
index |= FOGDEF_USE_DEFORM_VERTEXES; index |= FOGDEF_USE_DEFORM_VERTEXES;
if (glState.vertexAttribsInterpolation) if (glState.vertexAnimation)
index |= FOGDEF_USE_VERTEX_ANIMATION; index |= FOGDEF_USE_VERTEX_ANIMATION;
sp = &tr.fogShader[index]; sp = &tr.fogShader[index];
@ -1039,7 +1002,7 @@ static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input )
{ {
unsigned int vertexAttribs = input->shader->vertexAttribs; unsigned int vertexAttribs = input->shader->vertexAttribs;
if(glState.vertexAttribsInterpolation > 0.0f) if(glState.vertexAnimation)
{ {
vertexAttribs |= ATTR_POSITION2; vertexAttribs |= ATTR_POSITION2;
if (vertexAttribs & ATTR_NORMAL) if (vertexAttribs & ATTR_NORMAL)
@ -1058,7 +1021,6 @@ static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input )
static void RB_IterateStagesGeneric( shaderCommands_t *input ) static void RB_IterateStagesGeneric( shaderCommands_t *input )
{ {
int stage; int stage;
matrix_t matrix;
vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
float eyeT = 0; float eyeT = 0;
@ -1074,6 +1036,8 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
{ {
shaderStage_t *pStage = input->xstages[stage]; shaderStage_t *pStage = input->xstages[stage];
shaderProgram_t *sp; shaderProgram_t *sp;
vec4_t texMatrix;
vec4_t texOffTurb;
if ( !pStage ) if ( !pStage )
{ {
@ -1082,7 +1046,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
if (backEnd.depthFill) if (backEnd.depthFill)
{ {
if (pStage->glslShaderGroup) if (pStage->glslShaderGroup == tr.lightallShader)
{ {
int index = 0; int index = 0;
@ -1107,7 +1071,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES; shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES;
} }
if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) if (glState.vertexAnimation)
{ {
shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION; shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
} }
@ -1120,7 +1084,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
sp = &tr.genericShader[shaderAttribs]; sp = &tr.genericShader[shaderAttribs];
} }
} }
else if (pStage->glslShaderGroup) else if (pStage->glslShaderGroup == tr.lightallShader)
{ {
int index = pStage->glslShaderIndex; int index = pStage->glslShaderIndex;
@ -1146,11 +1110,8 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
sp = &pStage->glslShaderGroup[index]; sp = &pStage->glslShaderGroup[index];
if (pStage->glslShaderGroup == tr.lightallShader)
{
backEnd.pc.c_lightallDraws++; backEnd.pc.c_lightallDraws++;
} }
}
else else
{ {
sp = GLSL_GetGenericShaderProgram(stage); sp = GLSL_GetGenericShaderProgram(stage);
@ -1162,6 +1123,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin);
GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
@ -1210,8 +1172,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
VectorCopy(backEnd.currentEntity->lightDir, vec); VectorCopy(backEnd.currentEntity->lightDir, vec);
vec[3] = 0.0f; vec[3] = 0.0f;
GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vec); GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vec);
GLSL_SetUniformVec3(sp, UNIFORM_MODELLIGHTDIR, backEnd.currentEntity->modelLightDir);
GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, 999999.0f); GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, 0.0f);
} }
if (pStage->alphaGen == AGEN_PORTAL) if (pStage->alphaGen == AGEN_PORTAL)
@ -1231,16 +1194,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask); GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask);
} }
ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
{ GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb);
vec4_t vector;
VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector);
VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector);
}
GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
if (pStage->bundle[0].tcGen == TCGEN_VECTOR) if (pStage->bundle[0].tcGen == TCGEN_VECTOR)
@ -1269,7 +1225,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 ) else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 )
R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP ); R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP );
} }
else if ( pStage->glslShaderGroup ) else if ( pStage->glslShaderGroup == tr.lightallShader )
{ {
int i; int i;
@ -1285,13 +1241,27 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
{ {
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
{ {
if (i == TB_LIGHTMAP) if (pStage->bundle[i].image[0])
{ {
R_BindAnimatedImageToTMU( &pStage->bundle[i], i); switch(i)
}
else if (pStage->bundle[i].image[0])
{ {
case TB_LIGHTMAP:
R_BindAnimatedImageToTMU( &pStage->bundle[TB_LIGHTMAP], i);
break;
case TB_DIFFUSEMAP:
case TB_SPECULARMAP:
case TB_SHADOWMAP:
case TB_CUBEMAP:
default:
GL_BindToTMU( tr.whiteImage, i); GL_BindToTMU( tr.whiteImage, i);
break;
case TB_NORMALMAP:
case TB_DELUXEMAP:
GL_BindToTMU( tr.greyImage, i);
break;
}
} }
} }
} }
@ -1299,16 +1269,31 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
{ {
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
{ {
if (i == TB_LIGHTMAP) if (pStage->bundle[i].image[0])
{ {
switch(i)
{
case TB_LIGHTMAP:
R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i); R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i);
} break;
else if (pStage->bundle[i].image[0])
{ case TB_DIFFUSEMAP:
case TB_SPECULARMAP:
case TB_SHADOWMAP:
case TB_CUBEMAP:
default:
GL_BindToTMU( tr.whiteImage, i); GL_BindToTMU( tr.whiteImage, i);
break;
case TB_NORMALMAP:
case TB_DELUXEMAP:
GL_BindToTMU( tr.greyImage, i);
break;
} }
} }
} }
}
else else
{ {
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
@ -1340,11 +1325,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
// //
// set state // set state
// //
if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer )
{
GL_BindToTMU( tr.whiteImage, 0 );
}
else
R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 );
GLSL_SetUniformInt(sp, UNIFORM_TEXTURE1ENV, 0); GLSL_SetUniformInt(sp, UNIFORM_TEXTURE1ENV, 0);
@ -1369,7 +1349,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
} }
// allow skipping out to show just lightmaps during development // allow skipping out to show just lightmaps during development
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) ) if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) )
{ {
break; break;
} }

View file

@ -84,42 +84,16 @@ static float EvalWaveFormClamped( const waveForm_t *wf )
} }
/* /*
** RB_CalcStretchTexCoords ** RB_CalcStretchTexMatrix
*/ */
void RB_CalcStretchTexCoords( const waveForm_t *wf, float *st )
{
float p;
texModInfo_t tmi;
p = 1.0f / EvalWaveForm( wf );
tmi.matrix[0][0] = p;
tmi.matrix[1][0] = 0;
tmi.translate[0] = 0.5f - 0.5f * p;
tmi.matrix[0][1] = 0;
tmi.matrix[1][1] = p;
tmi.translate[1] = 0.5f - 0.5f * p;
RB_CalcTransformTexCoords( &tmi, st );
}
void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix ) void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix )
{ {
float p; float p;
texModInfo_t tmi;
p = 1.0f / EvalWaveForm( wf ); p = 1.0f / EvalWaveForm( wf );
tmi.matrix[0][0] = p; matrix[0] = p; matrix[2] = 0; matrix[4] = 0.5f - 0.5f * p;
tmi.matrix[1][0] = 0; matrix[1] = 0; matrix[3] = p; matrix[5] = 0.5f - 0.5f * p;
tmi.translate[0] = 0.5f - 0.5f * p;
tmi.matrix[0][1] = 0;
tmi.matrix[1][1] = p;
tmi.translate[1] = 0.5f - 0.5f * p;
RB_CalcTransformTexMatrix( &tmi, matrix );
} }
/* /*
@ -618,88 +592,6 @@ COLORS
*/ */
/*
** RB_CalcColorFromEntity
*/
void RB_CalcColorFromEntity( unsigned char *dstColors )
{
int i;
int *pColors = ( int * ) dstColors;
int c;
if ( !backEnd.currentEntity )
return;
c = * ( int * ) backEnd.currentEntity->e.shaderRGBA;
for ( i = 0; i < tess.numVertexes; i++, pColors++ )
{
*pColors = c;
}
}
/*
** RB_CalcColorFromOneMinusEntity
*/
void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors )
{
int i;
int *pColors = ( int * ) dstColors;
unsigned char invModulate[4];
int c;
if ( !backEnd.currentEntity )
return;
invModulate[0] = 255 - backEnd.currentEntity->e.shaderRGBA[0];
invModulate[1] = 255 - backEnd.currentEntity->e.shaderRGBA[1];
invModulate[2] = 255 - backEnd.currentEntity->e.shaderRGBA[2];
invModulate[3] = 255 - backEnd.currentEntity->e.shaderRGBA[3]; // this trashes alpha, but the AGEN block fixes it
c = * ( int * ) invModulate;
for ( i = 0; i < tess.numVertexes; i++, pColors++ )
{
*pColors = c;
}
}
/*
** RB_CalcAlphaFromEntity
*/
void RB_CalcAlphaFromEntity( unsigned char *dstColors )
{
int i;
if ( !backEnd.currentEntity )
return;
dstColors += 3;
for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
{
*dstColors = backEnd.currentEntity->e.shaderRGBA[3];
}
}
/*
** RB_CalcAlphaFromOneMinusEntity
*/
void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors )
{
int i;
if ( !backEnd.currentEntity )
return;
dstColors += 3;
for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
{
*dstColors = 0xff - backEnd.currentEntity->e.shaderRGBA[3];
}
}
/* /*
** RB_CalcWaveColorSingle ** RB_CalcWaveColorSingle
*/ */
@ -723,29 +615,6 @@ float RB_CalcWaveColorSingle( const waveForm_t *wf )
return glow; return glow;
} }
/*
** RB_CalcWaveColor
*/
void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors )
{
int i;
int v;
float glow;
int *colors = ( int * ) dstColors;
byte color[4];
glow = RB_CalcWaveColorSingle( wf );
v = ri.ftol(255 * glow);
color[0] = color[1] = color[2] = v;
color[3] = 255;
v = *(int *)color;
for ( i = 0; i < tess.numVertexes; i++, colors++ ) {
*colors = v;
}
}
/* /*
** RB_CalcWaveAlphaSingle ** RB_CalcWaveAlphaSingle
*/ */
@ -754,25 +623,6 @@ float RB_CalcWaveAlphaSingle( const waveForm_t *wf )
return EvalWaveFormClamped( wf ); return EvalWaveFormClamped( wf );
} }
/*
** RB_CalcWaveAlpha
*/
void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors )
{
int i;
int v;
float glow;
glow = EvalWaveFormClamped( wf );
v = 255 * glow;
for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
{
dstColors[3] = v;
}
}
/* /*
** RB_CalcModulateColorsByFog ** RB_CalcModulateColorsByFog
*/ */
@ -793,45 +643,6 @@ void RB_CalcModulateColorsByFog( unsigned char *colors ) {
} }
} }
/*
** RB_CalcModulateAlphasByFog
*/
void RB_CalcModulateAlphasByFog( unsigned char *colors ) {
int i;
float texCoords[SHADER_MAX_VERTEXES][2];
// calculate texcoords so we can derive density
// this is not wasted, because it would only have
// been previously called if the surface was opaque
RB_CalcFogTexCoords( texCoords[0] );
for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
colors[3] *= f;
}
}
/*
** RB_CalcModulateRGBAsByFog
*/
void RB_CalcModulateRGBAsByFog( unsigned char *colors ) {
int i;
float texCoords[SHADER_MAX_VERTEXES][2];
// calculate texcoords so we can derive density
// this is not wasted, because it would only have
// been previously called if the surface was opaque
RB_CalcFogTexCoords( texCoords[0] );
for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
colors[0] *= f;
colors[1] *= f;
colors[2] *= f;
colors[3] *= f;
}
}
/* /*
==================================================================== ====================================================================
@ -928,118 +739,27 @@ void RB_CalcFogTexCoords( float *st ) {
} }
} }
/* /*
** RB_CalcEnvironmentTexCoords ** RB_CalcTurbulentFactors
*/ */
void RB_CalcEnvironmentTexCoords( float *st ) void RB_CalcTurbulentFactors( const waveForm_t *wf, float *amplitude, float *now )
{ {
int i; *now = wf->phase + tess.shaderTime * wf->frequency;
float *v, *normal; *amplitude = wf->amplitude;
vec3_t viewer, reflected;
float d;
v = tess.xyz[0];
normal = tess.normal[0];
for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 )
{
VectorSubtract (backEnd.or.viewOrigin, v, viewer);
VectorNormalizeFast (viewer);
d = DotProduct (normal, viewer);
reflected[0] = normal[0]*2*d - viewer[0];
reflected[1] = normal[1]*2*d - viewer[1];
reflected[2] = normal[2]*2*d - viewer[2];
st[0] = 0.5 + reflected[1] * 0.5;
st[1] = 0.5 - reflected[2] * 0.5;
}
} }
/* /*
** RB_CalcTurbulentTexCoords ** RB_CalcScaleTexMatrix
*/ */
void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st )
{
int i;
float now;
now = ( wf->phase + tess.shaderTime * wf->frequency );
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
float s = st[0];
float t = st[1];
st[0] = s + tr.sinTable[ ( ( int ) ( ( ( tess.xyz[i][0] + tess.xyz[i][2] )* 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
st[1] = t + tr.sinTable[ ( ( int ) ( ( tess.xyz[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
}
}
void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix )
{
float now;
now = ( wf->phase + tess.shaderTime * wf->frequency );
// bit of a hack here, hide amplitude and now in the matrix
// the vertex program will extract them and perform a turbulent pass last if it's nonzero
matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = wf->amplitude;
matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = 0.0f; matrix[13] = now;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
}
/*
** RB_CalcScaleTexCoords
*/
void RB_CalcScaleTexCoords( const float scale[2], float *st )
{
int i;
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
st[0] *= scale[0];
st[1] *= scale[1];
}
}
void RB_CalcScaleTexMatrix( const float scale[2], float *matrix ) void RB_CalcScaleTexMatrix( const float scale[2], float *matrix )
{ {
matrix[ 0] = scale[0]; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = 0.0f; matrix[0] = scale[0]; matrix[2] = 0.0f; matrix[4] = 0.0f;
matrix[ 1] = 0.0f; matrix[ 5] = scale[1]; matrix[ 9] = 0.0f; matrix[13] = 0.0f; matrix[1] = 0.0f; matrix[3] = scale[1]; matrix[5] = 0.0f;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
} }
/* /*
** RB_CalcScrollTexCoords ** RB_CalcScrollTexMatrix
*/ */
void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st )
{
int i;
float timeScale = tess.shaderTime;
float adjustedScrollS, adjustedScrollT;
adjustedScrollS = scrollSpeed[0] * timeScale;
adjustedScrollT = scrollSpeed[1] * timeScale;
// clamp so coordinates don't continuously get larger, causing problems
// with hardware limits
adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
st[0] += adjustedScrollS;
st[1] += adjustedScrollT;
}
}
void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix ) void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix )
{ {
float timeScale = tess.shaderTime; float timeScale = tess.shaderTime;
@ -1053,73 +773,28 @@ void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix )
adjustedScrollS = adjustedScrollS - floor( adjustedScrollS ); adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
adjustedScrollT = adjustedScrollT - floor( adjustedScrollT ); adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = adjustedScrollS;
matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = adjustedScrollS; matrix[12] = 0.0f; matrix[1] = 0.0f; matrix[3] = 1.0f; matrix[5] = adjustedScrollT;
matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = adjustedScrollT; matrix[13] = 0.0f;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
} }
/* /*
** RB_CalcTransformTexCoords ** RB_CalcTransformTexMatrix
*/ */
void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st )
{
int i;
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
float s = st[0];
float t = st[1];
st[0] = s * tmi->matrix[0][0] + t * tmi->matrix[1][0] + tmi->translate[0];
st[1] = s * tmi->matrix[0][1] + t * tmi->matrix[1][1] + tmi->translate[1];
}
}
void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix ) void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix )
{ {
matrix[ 0] = tmi->matrix[0][0]; matrix[ 4] = tmi->matrix[1][0]; matrix[ 8] = tmi->translate[0]; matrix[12] = 0.0f; matrix[0] = tmi->matrix[0][0]; matrix[2] = tmi->matrix[1][0]; matrix[4] = tmi->translate[0];
matrix[ 1] = tmi->matrix[0][1]; matrix[ 5] = tmi->matrix[1][1]; matrix[ 9] = tmi->translate[1]; matrix[13] = 0.0f; matrix[1] = tmi->matrix[0][1]; matrix[3] = tmi->matrix[1][1]; matrix[5] = tmi->translate[1];
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
} }
/* /*
** RB_CalcRotateTexCoords ** RB_CalcRotateTexMatrix
*/ */
void RB_CalcRotateTexCoords( float degsPerSecond, float *st )
{
float timeScale = tess.shaderTime;
float degs;
int index;
float sinValue, cosValue;
texModInfo_t tmi;
degs = -degsPerSecond * timeScale;
index = degs * ( FUNCTABLE_SIZE / 360.0f );
sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
tmi.matrix[0][0] = cosValue;
tmi.matrix[1][0] = -sinValue;
tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
tmi.matrix[0][1] = sinValue;
tmi.matrix[1][1] = cosValue;
tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
RB_CalcTransformTexCoords( &tmi, st );
}
void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix ) void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
{ {
float timeScale = tess.shaderTime; float timeScale = tess.shaderTime;
float degs; float degs;
int index; int index;
float sinValue, cosValue; float sinValue, cosValue;
texModInfo_t tmi;
degs = -degsPerSecond * timeScale; degs = -degsPerSecond * timeScale;
index = degs * ( FUNCTABLE_SIZE / 360.0f ); index = degs * ( FUNCTABLE_SIZE / 360.0f );
@ -1127,213 +802,6 @@ void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
sinValue = tr.sinTable[ index & FUNCTABLE_MASK ]; sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ]; cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
tmi.matrix[0][0] = cosValue; matrix[0] = cosValue; matrix[2] = -sinValue; matrix[4] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
tmi.matrix[1][0] = -sinValue; matrix[1] = sinValue; matrix[3] = cosValue; matrix[5] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
tmi.matrix[0][1] = sinValue;
tmi.matrix[1][1] = cosValue;
tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
RB_CalcTransformTexMatrix( &tmi, matrix );
} }
/*
** RB_CalcSpecularAlpha
**
** Calculates specular coefficient and places it in the alpha channel
*/
vec3_t lightOrigin = { -960, 1980, 96 }; // FIXME: track dynamically
void RB_CalcSpecularAlpha( unsigned char *alphas ) {
int i;
float *v, *normal;
vec3_t viewer, reflected;
float l, d;
int b;
vec3_t lightDir;
int numVertexes;
v = tess.xyz[0];
normal = tess.normal[0];
alphas += 3;
numVertexes = tess.numVertexes;
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) {
float ilength;
VectorSubtract( lightOrigin, v, lightDir );
// ilength = Q_rsqrt( DotProduct( lightDir, lightDir ) );
VectorNormalizeFast( lightDir );
// calculate the specular color
d = DotProduct (normal, lightDir);
// d *= ilength;
// we don't optimize for the d < 0 case since this tends to
// cause visual artifacts such as faceted "snapping"
reflected[0] = normal[0]*2*d - lightDir[0];
reflected[1] = normal[1]*2*d - lightDir[1];
reflected[2] = normal[2]*2*d - lightDir[2];
VectorSubtract (backEnd.or.viewOrigin, v, viewer);
ilength = Q_rsqrt( DotProduct( viewer, viewer ) );
l = DotProduct (reflected, viewer);
l *= ilength;
if (l < 0) {
b = 0;
} else {
l = l*l;
l = l*l;
b = l * 255;
if (b > 255) {
b = 255;
}
}
*alphas = b;
}
}
/*
** RB_CalcDiffuseColor
**
** The basic vertex lighting calc
*/
#if idppc_altivec
static void RB_CalcDiffuseColor_altivec( unsigned char *colors )
{
int i;
float *v, *normal;
trRefEntity_t *ent;
int ambientLightInt;
vec3_t lightDir;
int numVertexes;
vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff);
vector float ambientLightVec;
vector float directedLightVec;
vector float lightDirVec;
vector float normalVec0, normalVec1;
vector float incomingVec0, incomingVec1, incomingVec2;
vector float zero, jVec;
vector signed int jVecInt;
vector signed short jVecShort;
vector unsigned char jVecChar, normalPerm;
ent = backEnd.currentEntity;
ambientLightInt = ent->ambientLightInt;
// A lot of this could be simplified if we made sure
// entities light info was 16-byte aligned.
jVecChar = vec_lvsl(0, ent->ambientLight);
ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight);
jVec = vec_ld(11, (vector float *)ent->ambientLight);
ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar);
jVecChar = vec_lvsl(0, ent->directedLight);
directedLightVec = vec_ld(0,(vector float *)ent->directedLight);
jVec = vec_ld(11,(vector float *)ent->directedLight);
directedLightVec = vec_perm(directedLightVec,jVec,jVecChar);
jVecChar = vec_lvsl(0, ent->lightDir);
lightDirVec = vec_ld(0,(vector float *)ent->lightDir);
jVec = vec_ld(11,(vector float *)ent->lightDir);
lightDirVec = vec_perm(lightDirVec,jVec,jVecChar);
zero = (vector float)vec_splat_s8(0);
VectorCopy( ent->lightDir, lightDir );
v = tess.xyz[0];
normal = tess.normal[0];
normalPerm = vec_lvsl(0,normal);
numVertexes = tess.numVertexes;
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
normalVec0 = vec_ld(0,(vector float *)normal);
normalVec1 = vec_ld(11,(vector float *)normal);
normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm);
incomingVec0 = vec_madd(normalVec0, lightDirVec, zero);
incomingVec1 = vec_sld(incomingVec0,incomingVec0,4);
incomingVec2 = vec_add(incomingVec0,incomingVec1);
incomingVec1 = vec_sld(incomingVec1,incomingVec1,4);
incomingVec2 = vec_add(incomingVec2,incomingVec1);
incomingVec0 = vec_splat(incomingVec2,0);
incomingVec0 = vec_max(incomingVec0,zero);
normalPerm = vec_lvsl(12,normal);
jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec);
jVecInt = vec_cts(jVec,0); // RGBx
jVecShort = vec_pack(jVecInt,jVecInt); // RGBxRGBx
jVecChar = vec_packsu(jVecShort,jVecShort); // RGBxRGBxRGBxRGBx
jVecChar = vec_sel(jVecChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255
vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]); // store color
}
}
#endif
static void RB_CalcDiffuseColor_scalar( unsigned char *colors )
{
int i, j;
float *v, *normal;
float incoming;
trRefEntity_t *ent;
int ambientLightInt;
vec3_t ambientLight;
vec3_t lightDir;
vec3_t directedLight;
int numVertexes;
ent = backEnd.currentEntity;
ambientLightInt = ent->ambientLightInt;
VectorCopy( ent->ambientLight, ambientLight );
VectorCopy( ent->directedLight, directedLight );
VectorCopy( ent->lightDir, lightDir );
v = tess.xyz[0];
normal = tess.normal[0];
numVertexes = tess.numVertexes;
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
incoming = DotProduct (normal, lightDir);
if ( incoming <= 0 ) {
*(int *)&colors[i*4] = ambientLightInt;
continue;
}
j = ri.ftol(ambientLight[0] + incoming * directedLight[0]);
if ( j > 255 ) {
j = 255;
}
colors[i*4+0] = j;
j = ri.ftol(ambientLight[1] + incoming * directedLight[1]);
if ( j > 255 ) {
j = 255;
}
colors[i*4+1] = j;
j = ri.ftol(ambientLight[2] + incoming * directedLight[2]);
if ( j > 255 ) {
j = 255;
}
colors[i*4+2] = j;
colors[i*4+3] = 255;
}
}
void RB_CalcDiffuseColor( unsigned char *colors )
{
#if idppc_altivec
if (com_altivec->integer) {
// must be in a seperate function or G3 systems will crash.
RB_CalcDiffuseColor_altivec( colors );
return;
}
#endif
RB_CalcDiffuseColor_scalar( colors );
}

View file

@ -1109,10 +1109,6 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
shader.portalRange = atof( token ); shader.portalRange = atof( token );
} }
} }
else if ( !Q_stricmp( token, "fresnel" ) )
{
stage->alphaGen = AGEN_FRESNEL;
}
else else
{ {
ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name ); ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name );
@ -2011,7 +2007,6 @@ static void ComputeVertexAttribs(void)
switch(pStage->alphaGen) switch(pStage->alphaGen)
{ {
case AGEN_LIGHTING_SPECULAR: case AGEN_LIGHTING_SPECULAR:
case AGEN_FRESNEL:
shader.vertexAttribs |= ATTR_NORMAL; shader.vertexAttribs |= ATTR_NORMAL;
break; break;
@ -2247,15 +2242,6 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
defs |= LIGHTDEF_USE_PARALLAXMAP; defs |= LIGHTDEF_USE_PARALLAXMAP;
} }
} }
if (!diffuse->bundle[TB_NORMALMAP].image[0])
{
// use 0x80 image, shader will interpret as (0,0,1)
diffuse->bundle[TB_NORMALMAP] = diffuse->bundle[0];
diffuse->bundle[TB_NORMALMAP].numImageAnimations = 0;
diffuse->bundle[TB_NORMALMAP].image[0] = tr.greyImage;
//ri.Printf(PRINT_ALL, ", normalmap %s", diffuse->bundle[TB_NORMALMAP].image[0]->imgName);
}
} }
if (r_specularMapping->integer) if (r_specularMapping->integer)
@ -2267,18 +2253,6 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
diffuse->materialInfo[0] = specular->materialInfo[0]; diffuse->materialInfo[0] = specular->materialInfo[0];
diffuse->materialInfo[1] = specular->materialInfo[1]; diffuse->materialInfo[1] = specular->materialInfo[1];
} }
else if (lightmap || useLightVector || useLightVertex)
{
// use a white image, materialinfo will do the rest
diffuse->bundle[TB_SPECULARMAP] = diffuse->bundle[0];
diffuse->bundle[TB_SPECULARMAP].numImageAnimations = 0;
diffuse->bundle[TB_SPECULARMAP].image[0] = tr.whiteImage;
if (!diffuse->materialInfo[0])
diffuse->materialInfo[0] = r_baseSpecular->value;
if (!diffuse->materialInfo[1])
diffuse->materialInfo[1] = r_baseGloss->value;
//ri.Printf(PRINT_ALL, ", specularmap %s", diffuse->bundle[TB_SPECULARMAP].image[0]->imgName);
}
} }
if (tcgen || diffuse->bundle[0].numTexMods) if (tcgen || diffuse->bundle[0].numTexMods)
@ -2308,7 +2282,7 @@ static qboolean CollapseStagesToGLSL(void)
{ {
// if 2+ stages and first stage is lightmap, switch them // if 2+ stages and first stage is lightmap, switch them
// this makes it easier for the later bits to process // this makes it easier for the later bits to process
if (stages[0].active && stages[0].bundle[0].isLightmap && stages[1].active) if (stages[0].active && stages[0].bundle[0].tcGen == TCGEN_LIGHTMAP && stages[1].active)
{ {
int blendBits = stages[1].stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); int blendBits = stages[1].stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
@ -2345,7 +2319,7 @@ static qboolean CollapseStagesToGLSL(void)
break; break;
} }
if (pStage->bundle[0].isLightmap) if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
{ {
int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
@ -2362,6 +2336,7 @@ static qboolean CollapseStagesToGLSL(void)
case TCGEN_TEXTURE: case TCGEN_TEXTURE:
case TCGEN_LIGHTMAP: case TCGEN_LIGHTMAP:
case TCGEN_ENVIRONMENT_MAPPED: case TCGEN_ENVIRONMENT_MAPPED:
case TCGEN_VECTOR:
break; break;
default: default:
skip = qtrue; skip = qtrue;
@ -2372,7 +2347,6 @@ static qboolean CollapseStagesToGLSL(void)
{ {
case AGEN_LIGHTING_SPECULAR: case AGEN_LIGHTING_SPECULAR:
case AGEN_PORTAL: case AGEN_PORTAL:
case AGEN_FRESNEL:
skip = qtrue; skip = qtrue;
break; break;
default: default:
@ -2397,7 +2371,7 @@ static qboolean CollapseStagesToGLSL(void)
continue; continue;
// skip lightmaps // skip lightmaps
if (pStage->bundle[0].isLightmap) if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
continue; continue;
diffuse = pStage; diffuse = pStage;
@ -2439,7 +2413,7 @@ static qboolean CollapseStagesToGLSL(void)
break; break;
case ST_COLORMAP: case ST_COLORMAP:
if (pStage2->bundle[0].isLightmap) if (pStage2->bundle[0].tcGen == TCGEN_LIGHTMAP)
{ {
lightmap = pStage2; lightmap = pStage2;
} }
@ -2481,7 +2455,7 @@ static qboolean CollapseStagesToGLSL(void)
if (!pStage->active) if (!pStage->active)
continue; continue;
if (pStage->bundle[0].isLightmap) if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
{ {
pStage->active = qfalse; pStage->active = qfalse;
} }
@ -2547,7 +2521,7 @@ static qboolean CollapseStagesToGLSL(void)
if (pStage->adjustColorsForFog) if (pStage->adjustColorsForFog)
continue; continue;
if (pStage->bundle[TB_DIFFUSEMAP].isLightmap) if (pStage->bundle[TB_DIFFUSEMAP].tcGen == TCGEN_LIGHTMAP)
{ {
pStage->glslShaderGroup = tr.lightallShader; pStage->glslShaderGroup = tr.lightallShader;
pStage->glslShaderIndex = LIGHTDEF_USE_LIGHTMAP; pStage->glslShaderIndex = LIGHTDEF_USE_LIGHTMAP;
@ -2556,6 +2530,7 @@ static qboolean CollapseStagesToGLSL(void)
pStage->bundle[TB_LIGHTMAP] = pStage->bundle[TB_DIFFUSEMAP]; pStage->bundle[TB_LIGHTMAP] = pStage->bundle[TB_DIFFUSEMAP];
pStage->bundle[TB_DIFFUSEMAP].image[0] = tr.whiteImage; pStage->bundle[TB_DIFFUSEMAP].image[0] = tr.whiteImage;
pStage->bundle[TB_DIFFUSEMAP].isLightmap = qfalse; pStage->bundle[TB_DIFFUSEMAP].isLightmap = qfalse;
pStage->bundle[TB_DIFFUSEMAP].tcGen = TCGEN_TEXTURE;
} }
} }
} }
@ -2577,11 +2552,14 @@ static qboolean CollapseStagesToGLSL(void)
{ {
pStage->glslShaderGroup = tr.lightallShader; pStage->glslShaderGroup = tr.lightallShader;
pStage->glslShaderIndex = LIGHTDEF_USE_LIGHT_VECTOR; pStage->glslShaderIndex = LIGHTDEF_USE_LIGHT_VECTOR;
if (pStage->bundle[0].tcGen != TCGEN_TEXTURE || pStage->bundle[0].numTexMods != 0)
pStage->glslShaderIndex |= LIGHTDEF_USE_TCGEN_AND_TCMOD;
} }
} }
} }
// convert any remaining lightingdiffuse stages to a lighting pass // insert default normal and specular textures if necessary
for (i = 0; i < MAX_SHADER_STAGES; i++) for (i = 0; i < MAX_SHADER_STAGES; i++)
{ {
shaderStage_t *pStage = &stages[i]; shaderStage_t *pStage = &stages[i];
@ -2589,13 +2567,26 @@ static qboolean CollapseStagesToGLSL(void)
if (!pStage->active) if (!pStage->active)
continue; continue;
if (pStage->rgbGen == CGEN_LIGHTING_DIFFUSE) if (pStage->glslShaderGroup != tr.lightallShader)
continue;
if ((pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) == 0)
continue;
if (!pStage->bundle[TB_NORMALMAP].image[0] && r_normalMapping->integer)
{ {
pStage->glslShaderGroup = tr.lightallShader; pStage->bundle[TB_NORMALMAP].image[0] = tr.greyImage;
pStage->glslShaderIndex = LIGHTDEF_USE_LIGHT_VECTOR;
}
} }
if (!pStage->bundle[TB_SPECULARMAP].image[0] && r_specularMapping->integer)
{
pStage->bundle[TB_SPECULARMAP].image[0] = tr.whiteImage;
if (!pStage->materialInfo[0])
pStage->materialInfo[0] = r_baseSpecular->value;
if (!pStage->materialInfo[1])
pStage->materialInfo[1] = r_baseGloss->value;
}
}
return numStages; return numStages;
} }

View file

@ -522,7 +522,7 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex
RB_SurfaceTriangles RB_SurfaceTriangles
============= =============
*/ */
static void RB_SurfaceTriangles( srfTriangles_t *srf ) { static void RB_SurfaceTriangles( srfBspSurface_t *srf ) {
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3,
srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) ) srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
{ {
@ -1247,7 +1247,7 @@ static void RB_SurfaceMesh(mdvSurface_t *surface) {
RB_SurfaceFace RB_SurfaceFace
============== ==============
*/ */
static void RB_SurfaceFace( srfSurfaceFace_t *srf ) { static void RB_SurfaceFace( srfBspSurface_t *srf ) {
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3,
srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) ) srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
{ {
@ -1296,7 +1296,7 @@ RB_SurfaceGrid
Just copy the grid of points and triangulate Just copy the grid of points and triangulate
============= =============
*/ */
static void RB_SurfaceGrid( srfGridMesh_t *srf ) { static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
int i, j; int i, j;
float *xyz; float *xyz;
float *texCoords, *lightCoords; float *texCoords, *lightCoords;
@ -1574,9 +1574,9 @@ static void RB_SurfaceFlare(srfFlare_t *surf)
RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal); RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal);
} }
static void RB_SurfaceVBOMesh(srfVBOMesh_t * srf) static void RB_SurfaceVBOMesh(srfBspSurface_t * srf)
{ {
RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, srf->firstIndex, RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex,
srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qfalse ); srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qfalse );
} }
@ -1621,11 +1621,12 @@ void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface)
glState.vertexAttribsOldFrame = refEnt->oldframe; glState.vertexAttribsOldFrame = refEnt->oldframe;
glState.vertexAttribsNewFrame = refEnt->frame; glState.vertexAttribsNewFrame = refEnt->frame;
glState.vertexAnimation = qtrue;
RB_EndSurface(); RB_EndSurface();
// So we don't lerp surfaces that shouldn't be lerped // So we don't lerp surfaces that shouldn't be lerped
glState.vertexAttribsInterpolation = 0; glState.vertexAnimation = qfalse;
} }
static void RB_SurfaceDisplayList( srfDisplayList_t *surf ) { static void RB_SurfaceDisplayList( srfDisplayList_t *surf ) {

View file

@ -608,6 +608,7 @@ void R_BindVBO(VBO_t * vbo)
glState.vertexAttribsInterpolation = 0; glState.vertexAttribsInterpolation = 0;
glState.vertexAttribsOldFrame = 0; glState.vertexAttribsOldFrame = 0;
glState.vertexAttribsNewFrame = 0; glState.vertexAttribsNewFrame = 0;
glState.vertexAnimation = qfalse;
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
@ -856,6 +857,9 @@ void RB_UpdateVBOs(unsigned int attribBits)
{ {
R_BindVBO(tess.vbo); R_BindVBO(tess.vbo);
// orphan old buffer so we don't stall on it
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->vertexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
if(attribBits & ATTR_BITS) if(attribBits & ATTR_BITS)
{ {
if(attribBits & ATTR_POSITION) if(attribBits & ATTR_POSITION)
@ -923,6 +927,9 @@ void RB_UpdateVBOs(unsigned int attribBits)
{ {
R_BindIBO(tess.ibo); R_BindIBO(tess.ibo);
// orphan old buffer so we don't stall on it
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.ibo->indexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes); qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes);
} }
} }

View file

@ -208,16 +208,18 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
} }
} }
if ( *surf->data == SF_FACE ) { switch(*surf->data)
((srfSurfaceFace_t *)surf->data)->dlightBits = dlightBits; {
} else if ( *surf->data == SF_GRID ) { case SF_FACE:
((srfGridMesh_t *)surf->data)->dlightBits = dlightBits; case SF_GRID:
} else if ( *surf->data == SF_TRIANGLES ) { case SF_TRIANGLES:
((srfTriangles_t *)surf->data)->dlightBits = dlightBits; case SF_VBO_MESH:
} else if ( *surf->data == SF_VBO_MESH ) { ((srfBspSurface_t *)surf->data)->dlightBits = dlightBits;
((srfVBOMesh_t *)surf->data)->dlightBits = dlightBits; break;
} else {
default:
dlightBits = 0; dlightBits = 0;
break;
} }
if ( dlightBits ) { if ( dlightBits ) {
@ -292,16 +294,18 @@ static int R_PshadowSurface( msurface_t *surf, int pshadowBits ) {
} }
} }
if ( *surf->data == SF_FACE ) { switch(*surf->data)
((srfSurfaceFace_t *)surf->data)->pshadowBits = pshadowBits; {
} else if ( *surf->data == SF_GRID ) { case SF_FACE:
((srfGridMesh_t *)surf->data)->pshadowBits = pshadowBits; case SF_GRID:
} else if ( *surf->data == SF_TRIANGLES ) { case SF_TRIANGLES:
((srfTriangles_t *)surf->data)->pshadowBits = pshadowBits; case SF_VBO_MESH:
} else if ( *surf->data == SF_VBO_MESH ) { ((srfBspSurface_t *)surf->data)->pshadowBits = pshadowBits;
((srfVBOMesh_t *)surf->data)->pshadowBits = pshadowBits; break;
} else {
default:
pshadowBits = 0; pshadowBits = 0;
break;
} }
if ( pshadowBits ) { if ( pshadowBits ) {

View file

@ -849,7 +849,7 @@ void UI_ParseMenu(const char *menuFile) {
int handle; int handle;
pc_token_t token; pc_token_t token;
Com_Printf("Parsing menu file:%s\n", menuFile); Com_Printf("Parsing menu file: %s\n", menuFile);
handle = trap_PC_LoadSource(menuFile); handle = trap_PC_LoadSource(menuFile);
if (!handle) { if (!handle) {