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->gameType = 0;
server->netType = 0;
server->punkbuster = 0;
server->g_humanplayers = 0;
server->g_needpass = 0;
}
#define MAX_SERVERSPERPACKET 256
@ -2937,13 +2940,13 @@ void CL_Frame ( int msec ) {
if ( CL_VideoRecording( ) && cl_aviFrameRate->integer && msec) {
// save the current screen
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( );
// fixed time for next frame'
msec = (int)ceil( (1000.0f / cl_aviFrameRate->value) * com_timescale->value );
if (msec == 0) {
msec = 1;
}
msec = (int)frameDuration;
clc.aviVideoFrameRemainder = frameDuration - msec;
}
}
@ -3836,21 +3839,8 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
// add this to the list
cls.numlocalservers = i+1;
cls.localServers[i].adr = 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;
CL_InitServerInfo( &cls.localServers[i], &from );
Q_strncpyz( info, MSG_ReadString( msg ), MAX_INFO_STRING );
if (strlen(info)) {
if (info[strlen(info)-1] != '\n') {

View file

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

View file

@ -271,6 +271,11 @@ static sfx_t *S_FindName( const char *name ) {
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);
sfx = sfxHash[hash];
@ -1237,7 +1242,13 @@ void S_GetSoundtime(void)
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;
}

View file

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

View file

@ -208,6 +208,11 @@ static sfxHandle_t S_AL_BufferFind(const char *filename)
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++)
{
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')
return;
// Player SFX
if(curSfx->filename[0] == '*')
return;
// Already done?
if((curSfx->inMemory) || (curSfx->isDefault) || (!cache && curSfx->isDefaultChecked))
return;

View file

@ -874,16 +874,6 @@ void GL_SetDefaultState( void )
qglEnable( GL_SCISSOR_TEST );
qglDisable( GL_CULL_FACE );
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 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 {
@ -266,7 +262,6 @@ typedef struct {
int videoMapHandle;
qboolean isLightmap;
qboolean vertexLightmap;
qboolean isVideoMap;
} textureBundle_t;
@ -370,27 +365,11 @@ typedef struct shader_s {
float clampTime; // time this shader is clamped to
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
int shaderStates[MAX_STATES_PER_SHADER]; // index to valid shader states
struct shader_s *next;
} 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,
// as well as the locally generated scene information
@ -610,6 +589,7 @@ typedef struct {
int num_frames;
int num_surfaces;
int num_joints;
int num_poses;
struct srfIQModel_s *surfaces;
float *positions;
@ -617,10 +597,18 @@ typedef struct {
float *normals;
float *tangents;
byte *blendIndexes;
byte *blendWeights;
union {
float *f;
byte *b;
} blendWeights;
byte *colors;
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;
float *jointMats;
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)
// 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,
int count,int 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;
srfIQModel_t *surface;
char meshName[MAX_QPATH];
byte blendIndexesType, blendWeightsType;
if( filesize < sizeof(iqmHeader_t) ) {
return qfalse;
@ -198,6 +206,8 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
return qfalse;
}
blendIndexesType = blendWeightsType = IQM_UBYTE;
// check and swap vertex arrays
if( IQM_CheckRange( header, header->ofs_vertexarrays,
header->num_vertexarrays,
@ -264,11 +274,20 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
}
break;
case IQM_BLENDINDEXES:
if( (vertexarray->format != IQM_INT &&
vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) {
return qfalse;
}
blendIndexesType = vertexarray->format;
break;
case IQM_BLENDWEIGHTS:
if( vertexarray->format != IQM_UBYTE ||
if( (vertexarray->format != IQM_FLOAT &&
vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) {
return qfalse;
}
blendWeightsType = vertexarray->format;
break;
case IQM_COLOR:
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;
}
@ -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->name ) + 1;
}
}
if ( header->num_poses )
{
// check and swap poses
if( IQM_CheckRange( header, header->ofs_poses,
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 += header->num_meshes * sizeof( srfIQModel_t );
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)
size += header->num_frames * 6 * sizeof(float); // model bounds
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 * 4 * sizeof(float); // tangents
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_joints * sizeof(int); // parents
size += header->num_triangles * 3 * sizeof(int); // triangles
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;
iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low );
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_surfaces = header->num_meshes;
iqmData->num_joints = header->num_joints;
iqmData->num_poses = header->num_poses;
iqmData->blendWeightsType = blendWeightsType;
iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints;
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;
}
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->normals = iqmData->texcoords + 2 * header->num_vertexes;
iqmData->tangents = iqmData->normals + 3 * 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->triangles = iqmData->jointParents + header->num_joints;
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
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
// 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) );
break;
case IQM_BLENDINDEXES:
Com_Memcpy( iqmData->blendIndexes,
(byte *)header + vertexarray->offset,
n * sizeof(byte) );
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,
(byte *)header + vertexarray->offset,
n * sizeof(byte) );
}
break;
case IQM_BLENDWEIGHTS:
Com_Memcpy( iqmData->blendWeights,
(byte *)header + vertexarray->offset,
n * sizeof(byte) );
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,
n * sizeof(byte) );
}
break;
case IQM_COLOR:
Com_Memcpy( iqmData->colors,
@ -892,9 +947,21 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
int *joint = data->jointParents;
int i;
if ( oldframe == frame ) {
mat1 = data->poseMats + 12 * data->num_joints * frame;
if ( data->num_poses == 0 ) {
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 ) {
Matrix34Multiply( mat + 12 * *joint,
mat1 + 12*i, mat + 12*i );
@ -903,10 +970,10 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
}
}
} else {
mat1 = data->poseMats + 12 * data->num_joints * frame;
mat2 = data->poseMats + 12 * data->num_joints * oldframe;
mat1 = data->poseMats + 12 * data->num_poses * frame;
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 ) {
float tmpMat[12];
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
@ -974,7 +1041,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
outColor = &tess.vertexColors[tess.numVertexes];
// compute interpolated joint matrices
if ( data->num_joints > 0 ) {
if ( data->num_poses > 0 ) {
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
}
@ -985,28 +1052,31 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
float vtxMat[12];
float nrmMat[9];
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++ ) {
if ( data->blendWeightsType == IQM_FLOAT )
blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights];
else
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.
for( j = 0; j < 3; j++ ) {
for( k = 0; k < 4; k++ )
vtxMat[4*j+k] = ( k == j ) ? 1 : 0;
}
Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) );
} else {
// compute the vertex matrix by blending the up to
// four blend weights
for( k = 0; k < 12; k++ )
vtxMat[k] = data->blendWeights[4*vtx]
* jointMats[12*data->blendIndexes[4*vtx] + k];
for( j = 1; j < 4; j++ ) {
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];
Com_Memset( vtxMat, 0, 12 * sizeof (float) );
for( j = 0; j < numWeights; j++ ) {
for( k = 0; k < 12; k++ ) {
vtxMat[k] += blendWeights[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

View file

@ -1145,12 +1145,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
//
// 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 );
@ -1160,7 +1155,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
R_DrawElements( input->numIndexes, input->indexes );
}
// 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;
}

View file

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

View file

@ -17,7 +17,7 @@ uniform vec4 u_DiffuseTexMatrix;
uniform vec4 u_DiffuseTexOffTurb;
#if defined(USE_TCGEN) || defined(USE_RGBAGEN)
uniform vec3 u_ViewOrigin;
uniform vec3 u_LocalViewOrigin;
#endif
#if defined(USE_TCGEN)
@ -48,7 +48,7 @@ uniform int u_ColorGen;
uniform int u_AlphaGen;
uniform vec3 u_AmbientLight;
uniform vec3 u_DirectedLight;
uniform vec4 u_LightOrigin;
uniform vec3 u_ModelLightDir;
uniform float u_PortalRange;
#endif
@ -93,7 +93,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
}
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)
{
@ -123,7 +123,7 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3
}
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;
}
else if (TCGen == TCGEN_VECTOR)
@ -158,30 +158,25 @@ vec4 CalcColor(vec3 position, vec3 normal)
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);
}
vec3 toView = u_ViewOrigin - position;
vec3 viewer = normalize(u_ViewOrigin - position);
vec3 viewer = u_LocalViewOrigin - position;
if (u_AlphaGen == AGEN_LIGHTING_SPECULAR)
{
vec3 lightDir = normalize(vec3(-960.0, -1980.0, 96.0) - position.xyz);
vec3 halfangle = normalize(lightDir + viewer);
vec3 lightDir = normalize(vec3(-960.0, 1980.0, 96.0) - position.xyz);
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)
{
float alpha = length(toView) / u_PortalRange;
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);
color.a = clamp(length(viewer) / u_PortalRange, 0.0, 1.0);
}
return color;
@ -194,14 +189,11 @@ float CalcFog(vec4 position)
float s = dot(position, u_FogDistance) * 8.0;
float t = dot(position, u_FogDepth);
if (t < 1.0)
{
t = step(step(0.0, -u_FogEyeT), t);
}
else
{
t /= t - min(u_FogEyeT, 0.0);
}
float eyeOutside = step(0.0, -u_FogEyeT);
float fogged = step(eyeOutside, t);
t = max(t, 1e-6);
t *= fogged / (t - u_FogEyeT * eyeOutside);
return s * t;
}

View file

@ -24,45 +24,40 @@ uniform sampler2D u_ShadowMap;
uniform samplerCube u_CubeMap;
#endif
#if defined(USE_LIGHT_VECTOR)
#if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
uniform vec3 u_DirectedLight;
uniform vec3 u_AmbientLight;
uniform float u_LightRadius;
#endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
uniform vec3 u_PrimaryLightColor;
uniform vec3 u_PrimaryLightAmbient;
uniform float u_PrimaryLightRadius;
#endif
#if defined(USE_LIGHT)
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
uniform vec2 u_MaterialInfo;
#endif
varying vec2 var_DiffuseTex;
#if defined(USE_LIGHTMAP)
varying vec2 var_LightTex;
#endif
varying vec4 var_TexCoords;
varying vec4 var_Color;
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
varying vec3 var_ViewDir;
varying vec3 var_Normal;
varying vec3 var_Tangent;
varying vec3 var_Bitangent;
varying vec4 var_Normal;
varying vec4 var_Tangent;
varying vec4 var_Bitangent;
#endif
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
varying vec3 var_lightColor;
varying vec3 var_LightColor;
#endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP)
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
varying vec4 var_LightDir;
#endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
varying vec3 var_PrimaryLightDir;
varying vec4 var_PrimaryLightDir;
#endif
@ -181,17 +176,21 @@ float CalcBlinn(float NH, float shininess)
#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
float m_sq = 2.0 / shininess;
float d = ((NH * NH) * (m_sq - 1.0) + 1.0);
return m_sq / (d * d);
// from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
float a_sq = exp2(gloss * -13.0 + 1.0);
float d = ((NH * NH) * (a_sq - 1.0) + 1.0);
return a_sq / (d * d);
}
float CalcFresnel(float EH)
{
#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/
return exp2((-5.55473 * EH - 6.98316) * EH);
#elif 0
@ -201,42 +200,48 @@ float CalcFresnel(float EH)
return blend;
#else
return pow(1.0 - NH, 5.0);
return pow(1.0 - EH, 5.0);
#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
float geo = 2.0 * NH * min(NE, NL);
geo /= max(EH, geo);
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 1
// From http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
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);
#if defined(USE_GGX)
float roughness = sqrt(2.0 / (shininess + 2.0));
float k = (roughness + 1.0);
// From http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
float k = roughness + 1.0;
k *= k * 0.125;
#else
float k = 2.0 / sqrt(3.1415926535 * (shininess + 2.0));
float k = roughness;
#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 invGeo1 = NL * k2 + k;
float invGeo2 = NE * k2 + k;
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);
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)
// Normalized Blinn-Phong
@ -261,60 +266,66 @@ vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float s
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()
{
vec3 L, N, E, H;
float NL, NH, NE, EH;
#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
#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)
L = L * tangentToWorld;
L = L * tangentToWorld;
#endif
#elif defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
L = var_LightDir.xyz;
#endif
#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
#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)
lightSample.rgb *= 32.0 * lightSample.a;
#endif
vec3 lightColor = lightSample.rgb;
#elif defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
// inverse square light
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 lightColor = u_DirectedLight * CalcLightAttenuation(L, var_LightDir.w);
vec3 ambientColor = u_AmbientLight;
#elif defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
vec3 lightColor = var_lightColor;
vec3 lightColor = var_LightColor;
#endif
vec2 texCoords = var_DiffuseTex;
vec2 texCoords = var_TexCoords.xy;
#if defined(USE_PARALLAXMAP)
#if defined(USE_TANGENT_SPACE_LIGHT)
@ -329,13 +340,12 @@ void main()
#endif
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_LINEAR_LIGHT)
diffuse.rgb *= diffuse.rgb;
#endif
#if defined(USE_NORMALMAP)
#if defined(SWIZZLE_NORMALMAP)
N.xy = 2.0 * texture2D(u_NormalMap, texCoords).ag - vec2(1.0);
@ -349,7 +359,7 @@ void main()
#elif defined(USE_TANGENT_SPACE_LIGHT)
N = vec3(0.0, 0.0, 1.0);
#else
N = normalize(var_Normal);
N = normalize(var_Normal.xyz);
#endif
L = normalize(L);
@ -362,7 +372,7 @@ void main()
#if defined(USE_TANGENT_SPACE_LIGHT)
shadowValue *= step(0.0, var_PrimaryLightDir.z);
#else
shadowValue *= step(0.0, dot(var_Normal, var_PrimaryLightDir));
shadowValue *= step(0.0, dot(var_Normal.xyz, var_PrimaryLightDir.xyz));
#endif
#if defined(SHADOWMAP_MODULATE)
@ -371,7 +381,7 @@ void main()
#if 0
// 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
lightColor = mix(shadowColor, lightColor, shadowValue);
#endif
@ -383,7 +393,7 @@ void main()
#if defined(USE_TANGENT_SPACE_LIGHT)
float surfNL = L.z;
#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
// Scale the incoming light to compensate for the baked-in light angle
@ -402,9 +412,9 @@ void main()
#if defined(USE_SPECULARMAP)
vec4 specular = texture2D(u_SpecularMap, texCoords);
#if defined(USE_LINEAR_LIGHT)
#if defined(USE_GAMMA2_TEXTURES)
specular.rgb *= specular.rgb;
#endif
#endif
#else
vec4 specular = vec4(1.0);
#endif
@ -413,7 +423,6 @@ void main()
float gloss = specular.a;
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)
// 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);
#if defined(r_deluxeSpecular) || defined(USE_LIGHT_VECTOR)
float adjGloss = gloss;
float adjShininess = shininess;
#if !defined(USE_LIGHT_VECTOR)
adjShininess = exp2(gloss * r_deluxeSpecular * 13.0);
adjGloss *= r_deluxeSpecular;
adjShininess = exp2(adjGloss * 13.0);
#endif
H = normalize(L + E);
@ -442,9 +453,9 @@ void main()
NH = clamp(dot(N, H), 0.0, 1.0);
#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
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjShininess) * localOcclusion;
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess);
#endif
#endif
@ -461,24 +472,20 @@ void main()
vec3 cubeLightColor = textureCubeLod(u_CubeMap, R, 7.0 - gloss * 7.0).rgb;
#if defined(USE_LINEAR_LIGHT)
cubeLightColor *= cubeLightColor;
#endif
#if defined(USE_LIGHTMAP)
cubeLightColor *= lightSample.rgb;
#elif defined (USE_LIGHT_VERTEX)
cubeLightColor *= var_lightColor;
cubeLightColor *= var_LightColor;
#else
cubeLightColor *= lightColor * NL + ambientColor;
#endif
//gl_FragColor.rgb += diffuse.rgb * textureCubeLod(u_CubeMap, N, 7.0).rgb;
gl_FragColor.rgb += cubeLightColor * reflectance * localOcclusion;
gl_FragColor.rgb += cubeLightColor * reflectance;
#endif
#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);
H = normalize(L + E);
@ -486,17 +493,15 @@ void main()
NH = clamp(dot(N, H), 0.0, 1.0);
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)
reflectance *= shadowValue;
lightColor *= shadowValue;
#endif
gl_FragColor.rgb += u_PrimaryLightColor * reflectance * NL;
#endif
#if defined(USE_LINEAR_LIGHT)
gl_FragColor.rgb = sqrt(gl_FragColor.rgb);
gl_FragColor.rgb += lightColor * reflectance * NL;
#endif
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)
uniform vec3 u_ViewOrigin;
uniform vec3 u_LocalViewOrigin;
#endif
#if defined(USE_TCGEN)
@ -49,37 +50,30 @@ uniform float u_VertexLerp;
#if defined(USE_LIGHT_VECTOR)
uniform vec4 u_LightOrigin;
#if defined(USE_FAST_LIGHT)
uniform vec3 u_DirectedLight;
uniform vec3 u_AmbientLight;
uniform float u_LightRadius;
uniform vec3 u_DirectedLight;
#if defined(USE_FAST_LIGHT)
uniform vec3 u_AmbientLight;
#endif
#endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
uniform vec4 u_PrimaryLightOrigin;
uniform float u_PrimaryLightRadius;
#endif
varying vec2 var_DiffuseTex;
#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_TexCoords;
varying vec4 var_Color;
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
varying vec3 var_Normal;
varying vec3 var_Tangent;
varying vec3 var_Bitangent;
varying vec4 var_Normal;
varying vec4 var_Tangent;
varying vec4 var_Bitangent;
#endif
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
varying vec3 var_lightColor;
varying vec3 var_LightColor;
#endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
@ -87,7 +81,7 @@ varying vec4 var_LightDir;
#endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
varying vec3 var_PrimaryLightDir;
varying vec4 var_PrimaryLightDir;
#endif
#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)
{
vec3 viewer = normalize(u_ViewOrigin - position);
vec3 viewer = normalize(u_LocalViewOrigin - position);
tex = -reflect(viewer, normal).yz * vec2(0.5, -0.5) + 0.5;
}
else if (TCGen == TCGEN_VECTOR)
@ -120,7 +114,7 @@ vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb)
float phase = offTurb.w;
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;
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
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()
{
#if defined(USE_VERTEX_ANIMATION)
@ -151,9 +168,9 @@ void main()
#endif
#if defined(USE_TCMOD)
var_DiffuseTex = ModTexCoords(texCoords, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb);
var_TexCoords.xy = ModTexCoords(texCoords, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb);
#else
var_DiffuseTex = texCoords;
var_TexCoords.xy = texCoords;
#endif
gl_Position = u_ModelViewProjectionMatrix * vec4(position, 1.0);
@ -167,84 +184,67 @@ void main()
#if defined(USE_LIGHT_VECTOR)
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;
#if defined(USE_MODELMATRIX)
L = (u_ModelMatrix * vec4(L, 0.0)).xyz;
L = (u_ModelMatrix * vec4(L, 0.0)).xyz;
#endif
#endif
#if defined(USE_LIGHTMAP)
var_LightTex = attr_TexCoord1.st;
var_TexCoords.zw = attr_TexCoord1.st;
#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;
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
var_LightColor = var_Color.rgb;
var_Color.rgb = vec3(1.0);
#endif
#if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT)
// inverse square light
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 attenuation = CalcLightAttenuation(L, u_LightRadius * u_LightRadius);
float NL = clamp(dot(normal, normalize(L)), 0.0, 1.0);
var_Color.rgb *= u_DirectedLight * attenuation * NL + u_AmbientLight;
#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)
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
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
#if defined(USE_LIGHT_VECTOR)
var_LightDir = vec4(L, u_LightOrigin.w);
var_LightDir = vec4(L, u_LightRadius * u_LightRadius);
#else
var_LightDir = vec4(L, 0.0);
#endif
#endif
#if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
var_ViewDir = (u_ViewOrigin - position);
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
vec3 viewDir = u_ViewOrigin - position;
#endif
#if defined(USE_TANGENT_SPACE_LIGHT)
mat3 tangentToWorld = mat3(tangent, bitangent, normal);
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
var_PrimaryLightDir = var_PrimaryLightDir * tangentToWorld;
var_PrimaryLightDir.xyz = var_PrimaryLightDir.xyz * tangentToWorld;
#endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
var_LightDir.xyz = var_LightDir.xyz * tangentToWorld;
#endif
#if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
var_ViewDir = var_ViewDir * tangentToWorld;
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
viewDir = viewDir * tangentToWorld;
#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 (glRefConfig.textureFloat && glRefConfig.halfFloatPixel)
if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer)
textureInternalFormat = GL_RGBA16F_ARB;
else
textureInternalFormat = GL_RGBA8;
@ -410,7 +410,7 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) {
VectorScale(color, lightScale, color);
if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel)
if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer)
ColorToRGBA16F(color, (unsigned short *)(&image[j*8]));
else
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 ) {
int i, j;
srfSurfaceFace_t *cv;
srfBspSurface_t *cv;
srfTriangle_t *tri;
int numVerts, numTriangles, badTriangles;
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
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 );
SetPlaneSignbits( &cv->plane );
cv->plane.type = PlaneTypeForNormal( cv->plane.normal );
surf->cullinfo.plane = cv->plane;
cv->cullPlane.dist = DotProduct( cv->verts[0].xyz, cv->cullPlane.normal );
SetPlaneSignbits( &cv->cullPlane );
cv->cullPlane.type = PlaneTypeForNormal( cv->cullPlane.normal );
surf->cullinfo.plane = cv->cullPlane;
surf->data = (surfaceType_t *)cv;
@ -800,7 +800,7 @@ ParseMesh
===============
*/
static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf ) {
srfGridMesh_t *grid;
srfBspSurface_t *grid;
int i, j;
int width, height, numPoints;
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 ) {
srfTriangles_t *cv;
srfBspSurface_t *cv;
srfTriangle_t *tri;
int i, j;
int numVerts, numTriangles, badTriangles;
@ -1065,7 +1065,7 @@ R_MergedWidthPoints
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;
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
=================
*/
int R_MergedHeightPoints(srfGridMesh_t *grid, int offset) {
int R_MergedHeightPoints(srfBspSurface_t *grid, int offset) {
int i, j;
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?
=================
*/
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;
srfGridMesh_t *grid2;
srfBspSurface_t *grid2;
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 ( grid2->surfaceType != SF_GRID ) continue;
// 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 ) {
int i;
srfGridMesh_t *grid1;
srfBspSurface_t *grid1;
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 ( grid1->surfaceType != SF_GRID )
continue;
@ -1249,11 +1249,11 @@ R_StitchPatches
*/
int R_StitchPatches( int grid1num, int grid2num ) {
float *v1, *v2;
srfGridMesh_t *grid1, *grid2;
srfBspSurface_t *grid1, *grid2;
int k, l, m, n, offset1, offset2, row, column;
grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data;
grid2 = (srfGridMesh_t *) s_worldData.surfaces[grid2num].data;
grid1 = (srfBspSurface_t *) s_worldData.surfaces[grid1num].data;
grid2 = (srfBspSurface_t *) s_worldData.surfaces[grid2num].data;
for (n = 0; n < 2; n++) {
//
if (n) offset1 = (grid1->height-1) * grid1->width;
@ -1664,13 +1664,13 @@ might still appear at that side.
*/
int R_TryStitchingPatch( int grid1num ) {
int j, numstitches;
srfGridMesh_t *grid1, *grid2;
srfBspSurface_t *grid1, *grid2;
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++ ) {
//
grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data;
grid2 = (srfBspSurface_t *) s_worldData.surfaces[j].data;
// if this surface is not a grid
if ( grid2->surfaceType != SF_GRID ) continue;
// grids in the same LOD group should have the exact same lod radius
@ -1695,7 +1695,7 @@ R_StitchAllPatches
*/
void R_StitchAllPatches( void ) {
int i, stitched, numstitches;
srfGridMesh_t *grid1;
srfBspSurface_t *grid1;
numstitches = 0;
do
@ -1703,7 +1703,7 @@ void R_StitchAllPatches( void ) {
stitched = qfalse;
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 ( grid1->surfaceType != SF_GRID )
continue;
@ -1728,11 +1728,11 @@ R_MovePatchSurfacesToHunk
*/
void R_MovePatchSurfacesToHunk(void) {
int i, size;
srfGridMesh_t *grid, *hunkgrid;
srfBspSurface_t *grid, *hunkgrid;
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 ( grid->surfaceType != SF_GRID )
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;
@ -1844,73 +1844,32 @@ static void R_CreateWorldVBO(void)
int numTriangles;
srfTriangle_t *triangles;
int numSurfaces;
msurface_t *surface;
int numSortedSurfaces, numSurfaces;
msurface_t *surface, **firstSurf, **lastSurf, **currSurf;
msurface_t **surfacesSorted;
VBO_t *vbo;
IBO_t *ibo;
int startTime, endTime;
startTime = ri.Milliseconds();
numVerts = 0;
numTriangles = 0;
numSurfaces = 0;
for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces /* s_worldData.numWorldSurfaces */; k++, surface++)
// count surfaces
numSortedSurfaces = 0;
for(surface = &s_worldData.surfaces[0]; surface < &s_worldData.surfaces[s_worldData.numsurfaces]; 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;
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++;
numSortedSurfaces++;
}
}
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
surfacesSorted = ri.Malloc(numSurfaces * sizeof(*surfacesSorted));
surfacesSorted = ri.Malloc(numSortedSurfaces * sizeof(*surfacesSorted));
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)
{
@ -1918,211 +1877,169 @@ static void R_CreateWorldVBO(void)
}
}
qsort(surfacesSorted, numSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare);
qsort(surfacesSorted, numSortedSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare);
// set up triangle indices
numVerts = 0;
numTriangles = 0;
for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k])
k = 0;
for(firstSurf = lastSurf = surfacesSorted; firstSurf < &surfacesSorted[numSortedSurfaces]; firstSurf = lastSurf)
{
if(*surface->data == SF_FACE)
while(lastSurf < &surfacesSorted[numSortedSurfaces] && (*lastSurf)->shader->sortedIndex == (*firstSurf)->shader->sortedIndex)
lastSurf++;
numVerts = 0;
numTriangles = 0;
numSurfaces = 0;
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data;
srf->firstIndex = numTriangles * 3;
if(srf->numTriangles)
switch (bspSurf->surfaceType)
{
srfTriangle_t *tri;
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
if(bspSurf->numVerts)
numVerts += bspSurf->numVerts;
srf->minIndex = numVerts + srf->triangles->indexes[0];
srf->maxIndex = numVerts + srf->triangles->indexes[0];
if(bspSurf->numTriangles)
numTriangles += bspSurf->numTriangles;
for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
{
for(j = 0; j < 3; j++)
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
numVerts = 0;
numTriangles = 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:
bspSurf->firstIndex = numTriangles * 3;
if(bspSurf->numTriangles)
{
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]);
srfTriangle_t *tri;
bspSurf->minIndex = numVerts + bspSurf->triangles->indexes[0];
bspSurf->maxIndex = numVerts + bspSurf->triangles->indexes[0];
for(i = 0, tri = bspSurf->triangles; i < bspSurf->numTriangles; i++, tri++)
{
for(j = 0; j < 3; j++)
{
triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
bspSurf->minIndex = MIN(bspSurf->minIndex, numVerts + tri->indexes[j]);
bspSurf->maxIndex = MAX(bspSurf->maxIndex, numVerts + tri->indexes[j]);
}
}
numTriangles += bspSurf->numTriangles;
}
}
numTriangles += srf->numTriangles;
if(bspSurf->numVerts)
numVerts += bspSurf->numVerts;
break;
default:
break;
}
if(srf->numVerts)
numVerts += srf->numVerts;
}
else if(*surface->data == SF_GRID)
// build vertices
numVerts = 0;
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{
srfGridMesh_t *srf = (srfGridMesh_t *) surface->data;
srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data;
srf->firstIndex = numTriangles * 3;
if(srf->numTriangles)
switch (bspSurf->surfaceType)
{
srfTriangle_t *tri;
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
bspSurf->firstVert = numVerts;
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++)
if(bspSurf->numVerts)
{
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]);
for(i = 0; i < bspSurf->numVerts; i++)
{
CopyVert(&bspSurf->verts[i], &verts[numVerts + i]);
}
numVerts += bspSurf->numVerts;
}
}
numTriangles += srf->numTriangles;
}
break;
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
numVerts = 0;
for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k])
{
if(*surface->data == SF_FACE)
{
srfSurfaceFace_t *srf = (srfSurfaceFace_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;
default:
break;
}
}
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;
}
}
else if(*surface->data == SF_TRIANGLES)
{
srfTriangles_t *srf = (srfTriangles_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;
}
}
}
#ifdef USE_VERT_TANGENT_SPACE
s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts,
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT |
ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", k), numVerts, verts,
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT |
ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
#else
s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts,
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD |
ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", k), numVerts, verts,
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD |
ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
#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();
ri.Printf(PRINT_ALL, "world VBO calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
// point triangle surfaces to world VBO
for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k])
{
if(*surface->data == SF_FACE)
// point triangle surfaces to VBO
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
{
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data;
if( srf->numVerts && srf->numTriangles)
switch (bspSurf->surfaceType)
{
srf->vbo = s_worldData.vbo;
srf->ibo = s_worldData.ibo;
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
if( bspSurf->numVerts && bspSurf->numTriangles)
{
bspSurf->vbo = vbo;
bspSurf->ibo = ibo;
}
break;
default:
break;
}
}
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;
ri.Hunk_FreeTempMemory(triangles);
ri.Hunk_FreeTempMemory(verts);
k++;
if( srf->numVerts && srf->numTriangles)
{
srf->vbo = s_worldData.vbo;
srf->ibo = s_worldData.ibo;
}
}
}
ri.Free(surfacesSorted);
ri.Hunk_FreeTempMemory(triangles);
ri.Hunk_FreeTempMemory(verts);
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
break;
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;
case MST_PLANAR:
out->data = ri.Hunk_Alloc( sizeof(srfSurfaceFace_t), h_low);
out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t), h_low);
break;
case MST_FLARE:
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:
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;
VectorCopy(surface->meshBounds[0], out->cullinfo.bounds[0]);
VectorCopy(surface->meshBounds[1], out->cullinfo.bounds[1]);
VectorCopy(surface->localOrigin, out->cullinfo.localOrigin);
out->cullinfo.radius = surface->meshRadius;
VectorCopy(surface->cullBounds[0], out->cullinfo.bounds[0]);
VectorCopy(surface->cullBounds[1], out->cullinfo.bounds[1]);
VectorCopy(surface->cullOrigin, out->cullinfo.localOrigin);
out->cullinfo.radius = surface->cullRadius;
}
numMeshes++;
break;
@ -3006,6 +2923,7 @@ void R_MergeLeafSurfaces(void)
int mergedSurfIndex;
int numMergedSurfaces;
int numUnmergedSurfaces;
VBO_t *vbo;
IBO_t *ibo;
msurface_t *mergedSurf;
@ -3025,14 +2943,6 @@ void R_MergeLeafSurfaces(void)
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
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];
}
// need to be synched here
R_IssuePendingRenderCommands();
// actually merge surfaces
numIboIndexes = 0;
mergedSurfIndex = 0;
@ -3181,13 +3094,27 @@ void R_MergeLeafSurfaces(void)
int numVerts;
int firstIndex;
srfVBOMesh_t *vboSurf;
srfBspSurface_t *vboSurf;
if (s_worldData.surfacesViewCount[i] != i)
continue;
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
numSurfsToMerge = 0;
numTriangles = 0;
@ -3195,42 +3122,21 @@ void R_MergeLeafSurfaces(void)
for (j = 0; j < numWorldSurfaces; j++)
{
msurface_t *surf2;
srfBspSurface_t *bspSurf;
if (s_worldData.surfacesViewCount[j] != i)
continue;
surf2 = s_worldData.surfaces + j;
switch(*surf2->data)
bspSurf = (srfBspSurface_t *) surf2->data;
switch(bspSurf->surfaceType)
{
case SF_FACE:
{
srfSurfaceFace_t *face;
face = (srfSurfaceFace_t *) surf2->data;
numTriangles += face->numTriangles;
numVerts += face->numVerts;
}
break;
case SF_GRID:
{
srfGridMesh_t *grid;
grid = (srfGridMesh_t *) surf2->data;
numTriangles += grid->numTriangles;
numVerts += grid->numVerts;
}
break;
case SF_TRIANGLES:
{
srfTriangles_t *tris;
tris = (srfTriangles_t *) surf2->data;
numTriangles += tris->numTriangles;
numVerts += tris->numVerts;
}
numTriangles += bspSurf->numTriangles;
numVerts += bspSurf->numVerts;
break;
default:
@ -3245,12 +3151,22 @@ void R_MergeLeafSurfaces(void)
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
ClearBounds(bounds[0], bounds[1]);
firstIndex = numIboIndexes;
for (j = 0; j < numWorldSurfaces; j++)
{
msurface_t *surf2;
srfBspSurface_t *bspSurf;
if (s_worldData.surfacesViewCount[j] != i)
continue;
@ -3260,53 +3176,18 @@ void R_MergeLeafSurfaces(void)
AddPointToBounds(surf2->cullinfo.bounds[0], 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:
{
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:
{
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:
for (k = 0; k < bspSurf->numTriangles; k++)
{
srfTriangles_t *tris;
tris = (srfTriangles_t *) surf2->data;
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;
}
*outIboIndexes++ = bspSurf->triangles[k].indexes[0] + bspSurf->firstVert;
*outIboIndexes++ = bspSurf->triangles[k].indexes[1] + bspSurf->firstVert;
*outIboIndexes++ = bspSurf->triangles[k].indexes[2] + bspSurf->firstVert;
numIboIndexes += 3;
}
break;
@ -3320,10 +3201,10 @@ void R_MergeLeafSurfaces(void)
memset(vboSurf, 0, sizeof(*vboSurf));
vboSurf->surfaceType = SF_VBO_MESH;
vboSurf->vbo = s_worldData.vbo;
vboSurf->vbo = vbo;
vboSurf->ibo = ibo;
vboSurf->numIndexes = numTriangles * 3;
vboSurf->numTriangles = numTriangles;
vboSurf->numVerts = numVerts;
vboSurf->firstIndex = firstIndex;
@ -3336,12 +3217,8 @@ void R_MergeLeafSurfaces(void)
vboSurf->maxIndex = MAX(vboSurf->maxIndex, *(iboIndexes + firstIndex + j));
}
vboSurf->shader = surf1->shader;
vboSurf->fogIndex = surf1->fogIndex;
vboSurf->cubemapIndex = surf1->cubemapIndex;
VectorCopy(bounds[0], vboSurf->bounds[0]);
VectorCopy(bounds[1], vboSurf->bounds[1]);
VectorCopy(bounds[0], vboSurf->cullBounds[0]);
VectorCopy(bounds[1], vboSurf->cullBounds[1]);
VectorCopy(bounds[0], mergedSurf->cullinfo.bounds[0]);
VectorCopy(bounds[1], mergedSurf->cullinfo.bounds[1]);
@ -3352,6 +3229,17 @@ void R_MergeLeafSurfaces(void)
mergedSurf->cubemapIndex = surf1->cubemapIndex;
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
for (j = 0; j < numWorldSurfaces; j++)
{
@ -3372,21 +3260,6 @@ void R_MergeLeafSurfaces(void)
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();
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++)
{
if(*surface->data == SF_FACE)
{
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
srfBspSurface_t *bspSurf = (srfBspSurface_t *) surface->data;
if(srf->numVerts)
{
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_GRID)
switch(bspSurf->surfaceType)
{
srfGridMesh_t *srf = (srfGridMesh_t *) surface->data;
case SF_FACE:
case SF_GRID:
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 );
if(srf->numVerts)
{
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;
break;
if(srf->numVerts)
{
for(i = 0; i < srf->numVerts; i++)
{
R_LightDirForPoint( srf->verts[i].xyz, srf->verts[i].lightdir, srf->verts[i].normal, &s_worldData );
}
}
default:
break;
}
}
}
@ -3743,7 +3595,7 @@ void RE_LoadWorldMap( const char *name ) {
}
// create static VBOS from the world
R_CreateWorldVBO();
R_CreateWorldVBOs();
if (r_mergeLeafSurfaces->integer)
{
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
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
distance from the true curve.
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] ) {
*/
@ -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
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;
}
@ -420,13 +416,13 @@ static void PutPointsOnCurve( srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
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],
int numTriangles, srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]) {
int i, j, size;
srfVert_t *vert;
vec3_t tmpVec;
srfGridMesh_t *grid;
srfBspSurface_t *grid;
// copy the results out to a 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->height = height;
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 ( j = 0 ; j < height ; j++ ) {
vert = &grid->verts[j*width+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
VectorAdd( grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin );
VectorScale( grid->localOrigin, 0.5f, grid->localOrigin );
VectorSubtract( grid->meshBounds[0], grid->localOrigin, tmpVec );
grid->meshRadius = VectorLength( tmpVec );
VectorAdd( grid->cullBounds[0], grid->cullBounds[1], grid->cullOrigin );
VectorScale( grid->cullOrigin, 0.5f, grid->cullOrigin );
VectorSubtract( grid->cullBounds[0], grid->cullOrigin, tmpVec );
grid->cullRadius = VectorLength( tmpVec );
VectorCopy( grid->localOrigin, grid->lodOrigin );
grid->lodRadius = grid->meshRadius;
VectorCopy( grid->cullOrigin, grid->lodOrigin );
grid->lodRadius = grid->cullRadius;
//
return grid;
}
@ -494,7 +490,7 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
R_FreeSurfaceGridMesh
=================
*/
void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) {
void R_FreeSurfaceGridMesh( srfBspSurface_t *grid ) {
ri.Free(grid->widthLodError);
ri.Free(grid->heightLodError);
ri.Free(grid->triangles);
@ -507,7 +503,7 @@ void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) {
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] ) {
int i, j, k, l;
srfVert_t_cleared( prev );
@ -690,7 +686,7 @@ srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
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 width, height, oldwidth;
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
===============
*/
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 width, height, oldheight;
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];

View file

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

View file

@ -106,6 +106,7 @@ static uniformInfo_t uniformsInfo[] =
{ "u_LightUp", GLSL_VEC3 },
{ "u_LightRight", GLSL_VEC3 },
{ "u_LightOrigin", GLSL_VEC4 },
{ "u_ModelLightDir", GLSL_VEC3 },
{ "u_LightRadius", GLSL_FLOAT },
{ "u_AmbientLight", GLSL_VEC3 },
{ "u_DirectedLight", GLSL_VEC3 },
@ -124,11 +125,12 @@ static uniformInfo_t uniformsInfo[] =
{ "u_VertexLerp" , GLSL_FLOAT },
{ "u_MaterialInfo", GLSL_VEC2 },
{ "u_ViewInfo", GLSL_VEC4 },
{ "u_ViewOrigin", GLSL_VEC3 },
{ "u_ViewForward", GLSL_VEC3 },
{ "u_ViewLeft", GLSL_VEC3 },
{ "u_ViewUp", GLSL_VEC3 },
{ "u_ViewInfo", GLSL_VEC4 },
{ "u_ViewOrigin", GLSL_VEC3 },
{ "u_LocalViewOrigin", GLSL_VEC3 },
{ "u_ViewForward", GLSL_VEC3 },
{ "u_ViewLeft", GLSL_VEC3 },
{ "u_ViewUp", GLSL_VEC3 },
{ "u_InvTexRes", GLSL_VEC2 },
{ "u_AutoExposureMinMax", GLSL_VEC2 },
@ -294,11 +296,9 @@ static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, cha
"#define alphaGen_t\n"
"#define AGEN_LIGHTING_SPECULAR %i\n"
"#define AGEN_PORTAL %i\n"
"#define AGEN_FRESNEL %i\n"
"#endif\n",
AGEN_LIGHTING_SPECULAR,
AGEN_PORTAL,
AGEN_FRESNEL));
AGEN_PORTAL));
Q_strcat(dest, size,
va("#ifndef texenv_t\n"
@ -907,7 +907,7 @@ void GLSL_InitGPUShaders(void)
if (i & GENERICDEF_USE_LIGHTMAP)
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");
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");
}
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");
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
oldFrame = glState.vertexAttribsOldFrame;
newFrame = glState.vertexAttribsNewFrame;
animated = (oldFrame != newFrame) && (glState.vertexAttribsInterpolation > 0.0f);
animated = glState.vertexAnimation;
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_PORTAL:
case AGEN_FRESNEL:
shaderAttribs |= GENERICDEF_USE_RGBAGEN;
break;
default:
@ -1846,7 +1845,7 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage)
shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES;
}
if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
if (glState.vertexAnimation)
{
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_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->uploadHeight = height;
}

View file

@ -102,6 +102,7 @@ cvar_t *r_ext_framebuffer_object;
cvar_t *r_ext_texture_float;
cvar_t *r_arb_half_float_pixel;
cvar_t *r_ext_framebuffer_multisample;
cvar_t *r_arb_seamless_cube_map;
cvar_t *r_mergeMultidraws;
cvar_t *r_mergeLeafSurfaces;
@ -111,6 +112,7 @@ cvar_t *r_cameraExposure;
cvar_t *r_softOverbright;
cvar_t *r_hdr;
cvar_t *r_floatLightmap;
cvar_t *r_postProcess;
cvar_t *r_toneMap;
@ -952,16 +954,6 @@ void GL_SetDefaultState( void )
qglDisable( GL_CULL_FACE );
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)
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_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_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",
"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_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_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++ ) {
surf = tr.world->surfaces + bmodel->firstSurface + i;
if ( *surf->data == SF_FACE ) {
((srfSurfaceFace_t *)surf->data)->dlightBits = mask;
} else if ( *surf->data == SF_GRID ) {
((srfGridMesh_t *)surf->data)->dlightBits = mask;
} else if ( *surf->data == SF_TRIANGLES ) {
((srfTriangles_t *)surf->data)->dlightBits = mask;
switch(*surf->data)
{
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
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;
// transform the direction to local space
// no need to do this if using lightentity glsl shader
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);
}

View file

@ -47,10 +47,6 @@ typedef unsigned int glIndex_t;
#define SHADERNUM_BITS 14
#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_VISCOUNTS 5
#define MAX_VBOS 4096
@ -84,7 +80,8 @@ typedef struct {
qboolean needDlights; // true for bmodels that touch a dlight
qboolean lightingCalculated;
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
int ambientLightInt; // 32 bit rgba packed
vec3_t directedLight;
@ -241,7 +238,6 @@ typedef enum {
AGEN_WAVEFORM,
AGEN_PORTAL,
AGEN_CONST,
AGEN_FRESNEL
} alphaGen_t;
typedef enum {
@ -354,7 +350,6 @@ typedef struct {
int videoMapHandle;
qboolean isLightmap;
qboolean vertexLightmap;
qboolean isVideoMap;
} textureBundle_t;
@ -486,16 +481,8 @@ typedef struct shader_s {
float clampTime; // time this shader is clamped to
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
int shaderStates[MAX_STATES_PER_SHADER]; // index to valid shader states
struct shader_s *next;
} shader_t;
@ -522,14 +509,6 @@ static ID_INLINE qboolean ShaderRequiresCPUDeforms(const shader_t * shader)
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
{
ATTR_INDEX_POSITION = 0,
@ -765,6 +744,7 @@ typedef enum
UNIFORM_LIGHTUP,
UNIFORM_LIGHTRIGHT,
UNIFORM_LIGHTORIGIN,
UNIFORM_MODELLIGHTDIR,
UNIFORM_LIGHTRADIUS,
UNIFORM_AMBIENTLIGHT,
UNIFORM_DIRECTEDLIGHT,
@ -785,6 +765,7 @@ typedef enum
UNIFORM_VIEWINFO, // znear, zfar, width/2, height/2
UNIFORM_VIEWORIGIN,
UNIFORM_LOCALVIEWORIGIN,
UNIFORM_VIEWFORWARD,
UNIFORM_VIEWLEFT,
UNIFORM_VIEWUP,
@ -1026,13 +1007,10 @@ typedef struct
{
int indexes[3];
int neighbors[3];
vec4_t plane;
qboolean facingLight;
qboolean degenerated;
} srfTriangle_t;
typedef struct srfGridMesh_s
// srfBspSurface_t covers SF_GRID, SF_TRIANGLES, SF_POLY, and SF_VBO_MESH
typedef struct srfBspSurface_s
{
surfaceType_t surfaceType;
@ -1041,9 +1019,30 @@ typedef struct srfGridMesh_s
int pshadowBits;
// culling information
vec3_t meshBounds[2];
vec3_t localOrigin;
float meshRadius;
vec3_t cullBounds[2];
vec3_t cullOrigin;
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
// than the culling information to allow for
@ -1057,85 +1056,7 @@ typedef struct srfGridMesh_s
int width, height;
float *widthLodError;
float *heightLodError;
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;
} srfBspSurface_t;
// inter-quake-model
typedef struct {
@ -1144,6 +1065,7 @@ typedef struct {
int num_frames;
int num_surfaces;
int num_joints;
int num_poses;
struct srfIQModel_s *surfaces;
float *positions;
@ -1151,10 +1073,18 @@ typedef struct {
float *normals;
float *tangents;
byte *blendIndexes;
byte *blendWeights;
union {
float *f;
byte *b;
} blendWeights;
byte *colors;
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;
float *jointMats;
float *poseMats;
@ -1172,33 +1102,6 @@ typedef struct srfIQModel_s {
int first_triangle, num_triangles;
} 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
{
surfaceType_t surfaceType;
@ -1332,9 +1235,6 @@ typedef struct {
int numDecisionNodes;
mnode_t *nodes;
VBO_t *vbo;
IBO_t *ibo;
int numWorldSurfaces;
int numsurfaces;
@ -1564,6 +1464,7 @@ typedef struct {
uint32_t vertexAttribsNewFrame;
uint32_t vertexAttribsOldFrame;
float vertexAttribsInterpolation;
qboolean vertexAnimation;
shaderProgram_t *currentProgram;
FBO_t *currentFBO;
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_arb_half_float_pixel;
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_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_hdr;
extern cvar_t *r_floatLightmap;
extern cvar_t *r_postProcess;
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,
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]);
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_CLIP 1 // clipped by one or more planes
@ -2349,11 +2250,11 @@ CURVE TESSELATION
#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] );
srfGridMesh_t *R_GridInsertColumn( srfGridMesh_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 );
void R_FreeSurfaceGridMesh( srfGridMesh_t *grid );
srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row, vec3_t point, float loderror );
srfBspSurface_t *R_GridInsertRow( srfBspSurface_t *grid, int row, int column, vec3_t point, float loderror );
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_CalcEnvironmentTexCoords( 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_CalcScrollTexMatrix( const float scrollSpeed[2], 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_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix );
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 );
void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors );
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
/*
=================
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
@ -1365,7 +1272,7 @@ R_PlaneForSurface
=============
*/
void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) {
srfTriangles_t *tri;
srfBspSurface_t *tri;
srfPoly_t *poly;
srfVert_t *v1, *v2, *v3;
vec4_t plane4;
@ -1377,10 +1284,10 @@ void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) {
}
switch (*surfType) {
case SF_FACE:
*plane = ((srfSurfaceFace_t *)surfType)->plane;
*plane = ((srfBspSurface_t *)surfType)->cullPlane;
return;
case SF_TRIANGLES:
tri = (srfTriangles_t *)surfType;
tri = (srfBspSurface_t *)surfType;
v1 = tri->verts + tri->triangles[0].indexes[0];
v2 = tri->verts + tri->triangles[0].indexes[1];
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];
int numClipPoints;
float *v;
srfGridMesh_t *cv;
srfBspSurface_t *cv;
srfTriangle_t *tri;
srfVert_t *dv;
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) {
cv = (srfGridMesh_t *) surfaces[i];
cv = (srfBspSurface_t *) surfaces[i];
for ( m = 0 ; m < cv->height - 1 ; m++ ) {
for ( n = 0 ; n < cv->width - 1 ; n++ ) {
// 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) {
srfSurfaceFace_t *surf = ( srfSurfaceFace_t * ) surfaces[i];
srfBspSurface_t *surf = ( srfBspSurface_t * ) surfaces[i];
// check the normal of this face
if (DotProduct(surf->plane.normal, projectionDir) > -0.5) {
if (DotProduct(surf->cullPlane.normal, projectionDir) > -0.5) {
continue;
}
@ -419,7 +419,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
for(j = 0; j < 3; j++)
{
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
@ -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) {
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++)
{

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]);
}
R_CalcSurfaceTriangleNeighbors(surf->numTriangles, surf->triangles);
// swap all the XyzNormals
surf->numVerts = md3Surf->numVerts;
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)
// 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,
int count,int 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;
srfIQModel_t *surface;
char meshName[MAX_QPATH];
byte blendIndexesType, blendWeightsType;
if( filesize < sizeof(iqmHeader_t) ) {
return qfalse;
@ -198,6 +206,8 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
return qfalse;
}
blendIndexesType = blendWeightsType = IQM_UBYTE;
// check and swap vertex arrays
if( IQM_CheckRange( header, header->ofs_vertexarrays,
header->num_vertexarrays,
@ -264,11 +274,20 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
}
break;
case IQM_BLENDINDEXES:
if( (vertexarray->format != IQM_INT &&
vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) {
return qfalse;
}
blendIndexesType = vertexarray->format;
break;
case IQM_BLENDWEIGHTS:
if( vertexarray->format != IQM_UBYTE ||
if( (vertexarray->format != IQM_FLOAT &&
vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) {
return qfalse;
}
blendWeightsType = vertexarray->format;
break;
case IQM_COLOR:
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;
}
@ -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->name ) + 1;
}
}
if ( header->num_poses )
{
// check and swap poses
if( IQM_CheckRange( header, header->ofs_poses,
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 += header->num_meshes * sizeof( srfIQModel_t );
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)
size += header->num_frames * 6 * sizeof(float); // model bounds
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 * 4 * sizeof(float); // tangents
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_joints * sizeof(int); // parents
size += header->num_triangles * 3 * sizeof(int); // triangles
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;
iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low );
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_surfaces = header->num_meshes;
iqmData->num_joints = header->num_joints;
iqmData->num_poses = header->num_poses;
iqmData->blendWeightsType = blendWeightsType;
iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints;
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;
}
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->normals = iqmData->texcoords + 2 * header->num_vertexes;
iqmData->tangents = iqmData->normals + 3 * 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->triangles = iqmData->jointParents + header->num_joints;
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
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
// 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) );
break;
case IQM_BLENDINDEXES:
Com_Memcpy( iqmData->blendIndexes,
(byte *)header + vertexarray->offset,
n * sizeof(byte) );
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,
(byte *)header + vertexarray->offset,
n * sizeof(byte) );
}
break;
case IQM_BLENDWEIGHTS:
Com_Memcpy( iqmData->blendWeights,
(byte *)header + vertexarray->offset,
n * sizeof(byte) );
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,
n * sizeof(byte) );
}
break;
case IQM_COLOR:
Com_Memcpy( iqmData->colors,
@ -895,9 +950,21 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
int *joint = data->jointParents;
int i;
if ( oldframe == frame ) {
mat1 = data->poseMats + 12 * data->num_joints * frame;
if ( data->num_poses == 0 ) {
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 ) {
Matrix34Multiply( mat + 12 * *joint,
mat1 + 12*i, mat + 12*i );
@ -906,10 +973,10 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
}
}
} else {
mat1 = data->poseMats + 12 * data->num_joints * frame;
mat2 = data->poseMats + 12 * data->num_joints * oldframe;
mat1 = data->poseMats + 12 * data->num_poses * frame;
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 ) {
float tmpMat[12];
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
@ -977,7 +1044,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
outColor = &tess.vertexColors[tess.numVertexes];
// compute interpolated joint matrices
if ( data->num_joints > 0 ) {
if ( data->num_poses > 0 ) {
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
}
@ -988,28 +1055,31 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
float vtxMat[12];
float nrmMat[9];
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++ ) {
if ( data->blendWeightsType == IQM_FLOAT )
blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights];
else
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.
for( j = 0; j < 3; j++ ) {
for( k = 0; k < 4; k++ )
vtxMat[4*j+k] = ( k == j ) ? 1 : 0;
}
Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) );
} else {
// compute the vertex matrix by blending the up to
// four blend weights
for( k = 0; k < 12; k++ )
vtxMat[k] = data->blendWeights[4*vtx]
* jointMats[12*data->blendIndexes[4*vtx] + k];
for( j = 1; j < 4; j++ ) {
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];
Com_Memset( vtxMat, 0, 12 * sizeof (float) );
for( j = 0; j < numWeights; j++ ) {
for( k = 0; k < 12; k++ ) {
vtxMat[k] += blendWeights[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

View file

@ -221,14 +221,22 @@ extern float EvalWaveForm( 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;
float matrix[16], currentmatrix[16];
float matrix[6], currentmatrix[6];
textureBundle_t *bundle = &pStage->bundle[bundleNum];
Matrix16Identity(outmatrix);
Matrix16Identity(currentmatrix);
matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = 0.0f;
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++ ) {
switch ( bundle->texMods[tm].type )
@ -239,59 +247,73 @@ static void ComputeTexMatrix( shaderStage_t *pStage, int bundleNum, float *outma
break;
case TMOD_TURBULENT:
RB_CalcTurbulentTexMatrix( &bundle->texMods[tm].wave,
matrix );
outmatrix[12] = matrix[12];
outmatrix[13] = matrix[13];
Matrix16Copy(outmatrix, currentmatrix);
RB_CalcTurbulentFactors(&bundle->texMods[tm].wave, &outOffTurb[2], &outOffTurb[3]);
break;
case TMOD_ENTITY_TRANSLATE:
RB_CalcScrollTexMatrix( backEnd.currentEntity->e.shaderTexCoord,
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
RB_CalcScrollTexMatrix( backEnd.currentEntity->e.shaderTexCoord, matrix );
break;
case TMOD_SCROLL:
RB_CalcScrollTexMatrix( bundle->texMods[tm].scroll,
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break;
case TMOD_SCALE:
RB_CalcScaleTexMatrix( bundle->texMods[tm].scale,
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break;
case TMOD_STRETCH:
RB_CalcStretchTexMatrix( &bundle->texMods[tm].wave,
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break;
case TMOD_TRANSFORM:
RB_CalcTransformTexMatrix( &bundle->texMods[tm],
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break;
case TMOD_ROTATE:
RB_CalcRotateTexMatrix( bundle->texMods[tm].rotateSpeed,
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break;
default:
ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'", bundle->texMods[tm].type, tess.shader->name );
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 )
{
baseColor[0] =
baseColor[1] =
baseColor[2] =
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
//
// 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:
baseColor[0] =
baseColor[1] =
baseColor[2] = tr.identityLight;
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
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:
baseColor[0] =
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[2] = pStage->constantColor[2] / 255.0f;
baseColor[3] = pStage->constantColor[3] / 255.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_VERTEX:
baseColor[0] =
@ -509,12 +509,10 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[0] =
baseColor[1] =
baseColor[2] = tr.identityLight;
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] = -tr.identityLight;
vertColor[3] = 0.0f;
break;
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[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f;
}
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_WAVEFORM:
baseColor[0] =
baseColor[1] =
baseColor[2] = RB_CalcWaveColorSingle( &pStage->rgbWave );
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_ENTITY:
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[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
}
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_ONE_MINUS_ENTITY:
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[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
}
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_IDENTITY:
case CGEN_LIGHTING_DIFFUSE:
case CGEN_BAD:
baseColor[0] =
baseColor[1] =
baseColor[2] =
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
}
@ -593,10 +562,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
{
case AGEN_SKIP:
break;
case AGEN_IDENTITY:
baseColor[3] = 1.0f;
vertColor[3] = 0.0f;
break;
case AGEN_CONST:
baseColor[3] = pStage->constantColor[3] / 255.0f;
vertColor[3] = 0.0f;
@ -627,9 +592,9 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[3] = 1.0f;
vertColor[3] = -1.0f;
break;
case AGEN_IDENTITY:
case AGEN_LIGHTING_SPECULAR:
case AGEN_PORTAL:
case AGEN_FRESNEL:
// Done entirely in vertex program
baseColor[3] = 1.0f;
vertColor[3] = 0.0f;
@ -749,7 +714,8 @@ static void ForwardDlight( void ) {
dlight_t *dl;
shaderProgram_t *sp;
vec4_t vector;
matrix_t matrix;
vec4_t texMatrix;
vec4_t texOffTurb;
if ( !( tess.dlightBits & ( 1 << l ) ) ) {
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_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin);
GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
@ -851,13 +818,9 @@ static void ForwardDlight( void ) {
GL_SelectTexture(0);
}
ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix );
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);
ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb);
GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
@ -982,7 +945,7 @@ static void RB_FogPass( void ) {
if (deformGen != DGEN_NONE)
index |= FOGDEF_USE_DEFORM_VERTEXES;
if (glState.vertexAttribsInterpolation)
if (glState.vertexAnimation)
index |= FOGDEF_USE_VERTEX_ANIMATION;
sp = &tr.fogShader[index];
@ -1039,7 +1002,7 @@ static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input )
{
unsigned int vertexAttribs = input->shader->vertexAttribs;
if(glState.vertexAttribsInterpolation > 0.0f)
if(glState.vertexAnimation)
{
vertexAttribs |= ATTR_POSITION2;
if (vertexAttribs & ATTR_NORMAL)
@ -1058,7 +1021,6 @@ static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input )
static void RB_IterateStagesGeneric( shaderCommands_t *input )
{
int stage;
matrix_t matrix;
vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
float eyeT = 0;
@ -1074,6 +1036,8 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
{
shaderStage_t *pStage = input->xstages[stage];
shaderProgram_t *sp;
vec4_t texMatrix;
vec4_t texOffTurb;
if ( !pStage )
{
@ -1082,7 +1046,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
if (backEnd.depthFill)
{
if (pStage->glslShaderGroup)
if (pStage->glslShaderGroup == tr.lightallShader)
{
int index = 0;
@ -1107,7 +1071,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES;
}
if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
if (glState.vertexAnimation)
{
shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
}
@ -1120,7 +1084,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
sp = &tr.genericShader[shaderAttribs];
}
}
else if (pStage->glslShaderGroup)
else if (pStage->glslShaderGroup == tr.lightallShader)
{
int index = pStage->glslShaderIndex;
@ -1146,10 +1110,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
sp = &pStage->glslShaderGroup[index];
if (pStage->glslShaderGroup == tr.lightallShader)
{
backEnd.pc.c_lightallDraws++;
}
backEnd.pc.c_lightallDraws++;
}
else
{
@ -1162,6 +1123,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin);
GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
@ -1210,8 +1172,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
VectorCopy(backEnd.currentEntity->lightDir, vec);
vec[3] = 0.0f;
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)
@ -1231,16 +1194,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask);
}
ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix );
{
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);
}
ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb);
GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
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 )
R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP );
}
else if ( pStage->glslShaderGroup )
else if ( pStage->glslShaderGroup == tr.lightallShader )
{
int i;
@ -1285,13 +1241,27 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
{
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
{
if (i == TB_LIGHTMAP)
if (pStage->bundle[i].image[0])
{
R_BindAnimatedImageToTMU( &pStage->bundle[i], i);
}
else if (pStage->bundle[i].image[0])
{
GL_BindToTMU( tr.whiteImage, i);
switch(i)
{
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);
break;
case TB_NORMALMAP:
case TB_DELUXEMAP:
GL_BindToTMU( tr.greyImage, i);
break;
}
}
}
}
@ -1299,15 +1269,30 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
{
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
{
if (i == TB_LIGHTMAP)
if (pStage->bundle[i].image[0])
{
R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i);
}
else if (pStage->bundle[i].image[0])
{
GL_BindToTMU( tr.whiteImage, i);
switch(i)
{
case TB_LIGHTMAP:
R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i);
break;
case TB_DIFFUSEMAP:
case TB_SPECULARMAP:
case TB_SHADOWMAP:
case TB_CUBEMAP:
default:
GL_BindToTMU( tr.whiteImage, i);
break;
case TB_NORMALMAP:
case TB_DELUXEMAP:
GL_BindToTMU( tr.greyImage, i);
break;
}
}
}
}
else
{
@ -1340,12 +1325,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
//
// 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);
}
@ -1369,7 +1349,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
}
// 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;
}

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 )
{
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_CalcTransformTexMatrix( &tmi, matrix );
matrix[0] = p; matrix[2] = 0; matrix[4] = 0.5f - 0.5f * p;
matrix[1] = 0; matrix[3] = p; matrix[5] = 0.5f - 0.5f * p;
}
/*
@ -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
*/
@ -723,29 +615,6 @@ float RB_CalcWaveColorSingle( const waveForm_t *wf )
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
*/
@ -754,25 +623,6 @@ float RB_CalcWaveAlphaSingle( const waveForm_t *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
*/
@ -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;
float *v, *normal;
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;
}
*now = wf->phase + tess.shaderTime * wf->frequency;
*amplitude = wf->amplitude;
}
/*
** 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 )
{
matrix[ 0] = scale[0]; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = 0.0f;
matrix[ 1] = 0.0f; matrix[ 5] = scale[1]; matrix[ 9] = 0.0f; 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;
matrix[0] = scale[0]; matrix[2] = 0.0f; matrix[4] = 0.0f;
matrix[1] = 0.0f; matrix[3] = scale[1]; matrix[5] = 0.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 )
{
float timeScale = tess.shaderTime;
@ -1053,73 +773,28 @@ void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix )
adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = adjustedScrollS; matrix[12] = 0.0f;
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;
matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = adjustedScrollS;
matrix[1] = 0.0f; matrix[3] = 1.0f; matrix[5] = adjustedScrollT;
}
/*
** 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 )
{
matrix[ 0] = tmi->matrix[0][0]; matrix[ 4] = tmi->matrix[1][0]; matrix[ 8] = tmi->translate[0]; matrix[12] = 0.0f;
matrix[ 1] = tmi->matrix[0][1]; matrix[ 5] = tmi->matrix[1][1]; matrix[ 9] = tmi->translate[1]; 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;
matrix[0] = tmi->matrix[0][0]; matrix[2] = tmi->matrix[1][0]; matrix[4] = tmi->translate[0];
matrix[1] = tmi->matrix[0][1]; matrix[3] = tmi->matrix[1][1]; matrix[5] = tmi->translate[1];
}
/*
** 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 )
{
float timeScale = tess.shaderTime;
float degs;
int index;
float sinValue, cosValue;
texModInfo_t tmi;
degs = -degsPerSecond * timeScale;
index = degs * ( FUNCTABLE_SIZE / 360.0f );
@ -1127,213 +802,6 @@ void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
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_CalcTransformTexMatrix( &tmi, matrix );
matrix[0] = cosValue; matrix[2] = -sinValue; matrix[4] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
matrix[1] = sinValue; matrix[3] = cosValue; matrix[5] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
}
/*
** 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 );
}
}
else if ( !Q_stricmp( token, "fresnel" ) )
{
stage->alphaGen = AGEN_FRESNEL;
}
else
{
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)
{
case AGEN_LIGHTING_SPECULAR:
case AGEN_FRESNEL:
shader.vertexAttribs |= ATTR_NORMAL;
break;
@ -2247,15 +2242,6 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
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)
@ -2267,18 +2253,6 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
diffuse->materialInfo[0] = specular->materialInfo[0];
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)
@ -2308,7 +2282,7 @@ static qboolean CollapseStagesToGLSL(void)
{
// if 2+ stages and first stage is lightmap, switch them
// 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 );
@ -2345,7 +2319,7 @@ static qboolean CollapseStagesToGLSL(void)
break;
}
if (pStage->bundle[0].isLightmap)
if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
{
int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
@ -2362,6 +2336,7 @@ static qboolean CollapseStagesToGLSL(void)
case TCGEN_TEXTURE:
case TCGEN_LIGHTMAP:
case TCGEN_ENVIRONMENT_MAPPED:
case TCGEN_VECTOR:
break;
default:
skip = qtrue;
@ -2372,7 +2347,6 @@ static qboolean CollapseStagesToGLSL(void)
{
case AGEN_LIGHTING_SPECULAR:
case AGEN_PORTAL:
case AGEN_FRESNEL:
skip = qtrue;
break;
default:
@ -2397,7 +2371,7 @@ static qboolean CollapseStagesToGLSL(void)
continue;
// skip lightmaps
if (pStage->bundle[0].isLightmap)
if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
continue;
diffuse = pStage;
@ -2439,7 +2413,7 @@ static qboolean CollapseStagesToGLSL(void)
break;
case ST_COLORMAP:
if (pStage2->bundle[0].isLightmap)
if (pStage2->bundle[0].tcGen == TCGEN_LIGHTMAP)
{
lightmap = pStage2;
}
@ -2481,7 +2455,7 @@ static qboolean CollapseStagesToGLSL(void)
if (!pStage->active)
continue;
if (pStage->bundle[0].isLightmap)
if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
{
pStage->active = qfalse;
}
@ -2547,7 +2521,7 @@ static qboolean CollapseStagesToGLSL(void)
if (pStage->adjustColorsForFog)
continue;
if (pStage->bundle[TB_DIFFUSEMAP].isLightmap)
if (pStage->bundle[TB_DIFFUSEMAP].tcGen == TCGEN_LIGHTMAP)
{
pStage->glslShaderGroup = tr.lightallShader;
pStage->glslShaderIndex = LIGHTDEF_USE_LIGHTMAP;
@ -2556,6 +2530,7 @@ static qboolean CollapseStagesToGLSL(void)
pStage->bundle[TB_LIGHTMAP] = pStage->bundle[TB_DIFFUSEMAP];
pStage->bundle[TB_DIFFUSEMAP].image[0] = tr.whiteImage;
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->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++)
{
shaderStage_t *pStage = &stages[i];
@ -2589,14 +2567,27 @@ static qboolean CollapseStagesToGLSL(void)
if (!pStage->active)
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->glslShaderIndex = LIGHTDEF_USE_LIGHT_VECTOR;
pStage->bundle[TB_NORMALMAP].image[0] = tr.greyImage;
}
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;
}

View file

@ -522,7 +522,7 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex
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,
srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
{
@ -1247,7 +1247,7 @@ static void RB_SurfaceMesh(mdvSurface_t *surface) {
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,
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
=============
*/
static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
int i, j;
float *xyz;
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);
}
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 );
}
@ -1621,11 +1621,12 @@ void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface)
glState.vertexAttribsOldFrame = refEnt->oldframe;
glState.vertexAttribsNewFrame = refEnt->frame;
glState.vertexAnimation = qtrue;
RB_EndSurface();
// So we don't lerp surfaces that shouldn't be lerped
glState.vertexAttribsInterpolation = 0;
glState.vertexAnimation = qfalse;
}
static void RB_SurfaceDisplayList( srfDisplayList_t *surf ) {

View file

@ -608,6 +608,7 @@ void R_BindVBO(VBO_t * vbo)
glState.vertexAttribsInterpolation = 0;
glState.vertexAttribsOldFrame = 0;
glState.vertexAttribsNewFrame = 0;
glState.vertexAnimation = qfalse;
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
@ -856,6 +857,9 @@ void RB_UpdateVBOs(unsigned int attribBits)
{
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_POSITION)
@ -923,6 +927,9 @@ void RB_UpdateVBOs(unsigned int attribBits)
{
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);
}
}

View file

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

View file

@ -849,7 +849,7 @@ void UI_ParseMenu(const char *menuFile) {
int handle;
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);
if (!handle) {