From e04cbd57ea5ce6b154a0f578855f45fbb3e83434 Mon Sep 17 00:00:00 2001 From: smallmodel <15067410+smallmodel@users.noreply.github.com> Date: Sat, 21 Dec 2024 21:43:42 +0100 Subject: [PATCH] Fix most shader errors, light rendering --- code/renderergl2/tr_backend.c | 113 ++++++++ code/renderergl2/tr_bsp.c | 9 +- code/renderergl2/tr_cmds.c | 26 ++ code/renderergl2/tr_init.c | 28 +- code/renderergl2/tr_light.c | 373 ++++++++++++++++++++++++++- code/renderergl2/tr_local.h | 81 +++++- code/renderergl2/tr_main.c | 129 ++++++++- code/renderergl2/tr_shade_calc.c | 52 +++- code/renderergl2/tr_shader.c | 285 +++++++++++++++++--- code/renderergl2/tr_sphere_shade.cpp | 39 ++- code/renderergl2/tr_sprite.c | 2 +- code/renderergl2/tr_world.c | 46 ++++ 12 files changed, 1105 insertions(+), 78 deletions(-) diff --git a/code/renderergl2/tr_backend.c b/code/renderergl2/tr_backend.c index b9c09637..cc3bc1c8 100644 --- a/code/renderergl2/tr_backend.c +++ b/code/renderergl2/tr_backend.c @@ -36,6 +36,13 @@ static float s_flipMatrix[16] = { 0, 0, 0, 1 }; +// +// OPENMOHAA-specific stuff +//========================= + +const void* RB_SpriteSurfs(const void* data); + +//========================= /* ** GL_BindToTMU @@ -1839,6 +1846,13 @@ void RB_ExecuteRenderCommands( const void *data ) { case RC_EXPORT_CUBEMAPS: data = RB_ExportCubemaps(data); break; + // + // OPENMOHAA-specific stuff + //========================= + case RC_SPRITE_SURFS: + data = RB_SpriteSurfs( data ); + break; + //========================= case RC_END_OF_LIST: default: // finish any 2D drawing if needed @@ -1853,3 +1867,102 @@ void RB_ExecuteRenderCommands( const void *data ) { } } + +// +// OPENMOHAA-specific stuff +// + + + +/* +================== +RB_RenderSpriteSurfList +================== +*/ +void RB_RenderSpriteSurfList(drawSurf_t* drawSurfs, int numDrawSurfs) { + shader_t *shader; + shader_t *oldShader; + qboolean depthRange; + qboolean oldDepthRange; + int i; + drawSurf_t *drawSurf; + + backEnd.currentEntity = &tr.worldEntity; + backEnd.currentStaticModel = NULL; + + backEnd.pc.c_surfaces += numDrawSurfs; + backEnd.or = backEnd.viewParms.world; + + oldShader = NULL; + depthRange = qfalse; + oldDepthRange = qfalse; + + for (i = 0, drawSurf = drawSurfs; i < numDrawSurfs; i++, drawSurf++) { + shader = tr.sortedShaders[((refSprite_t*)drawSurf->surface)->shaderNum]; + depthRange = (((refSprite_t*)drawSurf->surface)->renderfx & RF_DEPTHHACK) != 0; + + if (shader != oldShader) + { + if (oldShader) { + RB_EndSurface(); + } + + RB_BeginSurface(shader, 0, 0); + oldShader = shader; + } + + GL_SetModelviewMatrix( backEnd.or.modelMatrix ); + + if (oldDepthRange != depthRange) + { + if (depthRange) { + qglDepthRange(0.0, 0.3); + } else { + qglDepthRange(0.0, 1.0); + } + + oldDepthRange = depthRange; + } + + backEnd.shaderStartTime = ((refSprite_t*)drawSurf->surface)->shaderTime; + + // add the triangles for this surface + rb_surfaceTable[*drawSurf->surface](drawSurf->surface); + } + + if (oldShader) { + RB_EndSurface(); + } + + // go back to the world modelview matrix + GL_SetModelviewMatrix( backEnd.viewParms.world.modelMatrix ); + // go back to the previous depth range + if (depthRange) { + qglDepthRange(0.0, 1.0); + } +} + +/* +============= +RB_SpriteSurfs + +============= +*/ +const void* RB_SpriteSurfs(const void* data) { + const drawSurfsCommand_t* cmd; + + // finish any 2D drawing if needed + if (tess.numIndexes) { + RB_EndSurface(); + } + + cmd = (const drawSurfsCommand_t*)data; + + backEnd.refdef = cmd->refdef; + backEnd.viewParms = cmd->viewParms; + + //RB_SetupFog(); + RB_RenderSpriteSurfList(cmd->drawSurfs, cmd->numDrawSurfs); + + return (const void*)(cmd + 1); +} diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c index 78fb6881..5f30f7ab 100644 --- a/code/renderergl2/tr_bsp.c +++ b/code/renderergl2/tr_bsp.c @@ -3163,8 +3163,8 @@ void R_LoadLightGrid2(lump_t* plPal, lump_t* plOffsets, lump_t* plData) { } Com_Memcpy(w->lightGridPalette, fileBase + plPal->fileofs, sizeof(s_worldData.lightGridPalette)); - //w->lightGridData = ri.Hunk_Alloc(plData->filelen, h_dontcare); - //Com_Memcpy(w->lightGridData, fileBase + plData->fileofs, plData->filelen); + w->lightGridData = ri.Hunk_Alloc(plData->filelen, h_dontcare); + Com_Memcpy(w->lightGridData, fileBase + plData->fileofs, plData->filelen); } /* @@ -3480,6 +3480,9 @@ void RE_LoadWorldMap( const char *name ) { g_nStaticModels = 0; g_nStaticModelIndices = 0; } + + ri.UI_LoadResource("*111"); + R_Sphere_InitLights(); //========================= // determine vertex light directions @@ -3715,8 +3718,6 @@ void RE_LoadWorldMap( const char *name ) { // // OPENMOHAA-specific stuff //========================= - ri.UI_LoadResource("*111"); - R_Sphere_InitLights(); ri.UI_LoadResource("*112"); R_InitTerrain(); ri.UI_LoadResource("*113"); diff --git a/code/renderergl2/tr_cmds.c b/code/renderergl2/tr_cmds.c index 2d4279e8..d1b5fc58 100644 --- a/code/renderergl2/tr_cmds.c +++ b/code/renderergl2/tr_cmds.c @@ -624,3 +624,29 @@ void RE_TakeVideoFrame( int width, int height, cmd->encodeBuffer = encodeBuffer; cmd->motionJpeg = motionJpeg; } + +// +// OPENMOHAA-specific stuff +// + +/* +============= +R_AddSpriteSurfCmd + +============= +*/ +void R_AddSpriteSurfCmd(drawSurf_t* drawSurfs, int numDrawSurfs) { + drawSurfsCommand_t* cmd; + + cmd = R_GetCommandBuffer(sizeof(*cmd)); + if (!cmd) { + return; + } + cmd->commandId = RC_SPRITE_SURFS; + + cmd->drawSurfs = drawSurfs; + cmd->numDrawSurfs = numDrawSurfs; + + cmd->refdef = tr.refdef; + cmd->viewParms = tr.viewParms; +} diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c index db1133e2..1e6bc1c4 100644 --- a/code/renderergl2/tr_init.c +++ b/code/renderergl2/tr_init.c @@ -272,7 +272,20 @@ cvar_t* r_farplane_nocull; cvar_t* r_farplane_nofog; cvar_t* r_skybox_farplane; cvar_t* r_farclip; + +// Lighting + cvar_t* r_lightcoronasize; +cvar_t *r_entlight_scale; +cvar_t *r_entlight_errbound; +cvar_t *r_entlight_cubelevel; +cvar_t *r_entlight_cubefraction; +cvar_t *r_entlight_maxcalc; +cvar_t *r_light_lines; +cvar_t *r_light_sun_line; +cvar_t *r_light_int_scale; +cvar_t *r_light_nolight; +cvar_t *r_light_showgrid; // LOD @@ -1560,7 +1573,7 @@ void R_Register( void ) r_numdebuglines = ri.Cvar_Get("g_numdebuglines", "4096", CVAR_LATCH); r_maxtermarks = ri.Cvar_Get("r_maxtermarks", va("%d", MAX_TERMARKS), 0); - + r_skyportal = ri.Cvar_Get("r_skyportal", "0", 0); r_skyportal_origin = ri.Cvar_Get("r_skyportal_origin", "0 0 0", 0); r_farplane = ri.Cvar_Get("r_farplane", "0", CVAR_CHEAT); @@ -1570,7 +1583,20 @@ void R_Register( void ) r_farplane_nofog = ri.Cvar_Get("r_farplane_nofog", "0", CVAR_CHEAT); r_skybox_farplane = ri.Cvar_Get("r_skybox_farplane", "0", CVAR_CHEAT); r_farclip = ri.Cvar_Get("r_farclip", "0", CVAR_CHEAT); + + // Lighting + r_lightcoronasize = ri.Cvar_Get("r_lightcoronasize", ".1", CVAR_ARCHIVE); + r_light_lines = ri.Cvar_Get("r_light_lines", "0", CVAR_CHEAT); + r_light_sun_line = ri.Cvar_Get("r_light_sun_line", "0", CVAR_CHEAT); + r_light_int_scale = ri.Cvar_Get("r_light_int_scale", "0.05", CVAR_ARCHIVE); + r_light_nolight = ri.Cvar_Get("r_light_nolight", "0", CVAR_CHEAT | CVAR_ARCHIVE); + r_light_showgrid = ri.Cvar_Get("r_light_showgrid", "0", CVAR_CHEAT); + r_entlight_scale = ri.Cvar_Get("r_entlight_scale", "1.3", CVAR_CHEAT); + r_entlight_errbound = ri.Cvar_Get("r_entlight_errbound", "6", CVAR_ARCHIVE); + r_entlight_cubelevel = ri.Cvar_Get("r_entlight_cubelevel", "0", CVAR_ARCHIVE); + r_entlight_cubefraction = ri.Cvar_Get("r_entlight_cubefraction", "0.5", CVAR_ARCHIVE); + r_entlight_maxcalc = ri.Cvar_Get("r_entlight_maxcalc", "2", CVAR_ARCHIVE); // LOD diff --git a/code/renderergl2/tr_light.c b/code/renderergl2/tr_light.c index 1c46024a..183f7280 100644 --- a/code/renderergl2/tr_light.c +++ b/code/renderergl2/tr_light.c @@ -127,6 +127,7 @@ R_SetupEntityLightingGrid ================= */ +#if 0 static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) { vec3_t lightOrigin; int pos[3]; @@ -277,6 +278,9 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) { VectorNormalize2( direction, ent->lightDir ); } +#endif + +static void R_SetupEntityLightingGrid(trRefEntity_t* ent, world_t* world); /* @@ -461,7 +465,7 @@ int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, ve return qtrue; } - +#if 0 int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *world ) { trRefEntity_t ent; @@ -480,7 +484,7 @@ int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *w return qtrue; } - +#endif int R_CubemapForPoint( vec3_t point ) { @@ -514,6 +518,246 @@ int R_CubemapForPoint( vec3_t point ) // OPENMOHAA-specific stuff // +/* +=============== +RB_SetupEntityGridLighting +=============== +*/ +void RB_SetupEntityGridLighting() +{ + // FIXME: unimplemented +} + +/* +=============== +RB_SetupStaticModelGridLighting +=============== +*/ +void RB_SetupStaticModelGridLighting(trRefdef_t *refdef, cStaticModelUnpacked_t *ent, const vec3_t lightOrigin) +{ + // FIXME: unimplemented +} + +/* +=============== +R_PointInLeaf +=============== +*/ +mnode_t *R_FindPoint( world_t *world, const vec3_t p ) { + mnode_t *node; + float d; + cplane_t *plane; + + node = world->nodes; + while( 1 ) { + if (node->contents != -1) { + break; + } + plane = node->plane; + d = DotProduct (p,plane->normal) - plane->dist; + if (d > 0) { + node = node->children[0]; + } else { + node = node->children[1]; + } + } + + return node; +} + +/* +=============== +R_GetLightGridPalettedColor +=============== +*/ +static byte *R_GetLightGridPalettedColor(world_t *world, int iColor) +{ + return &world->lightGridPalette[iColor * 3]; +} + +/* +=============== +R_GetLightingGridValue +=============== +*/ +void R_GetLightingGridValue(world_t *world, const vec3_t vPos, vec3_t vAmbientLight, vec3_t vDirectedLight) +{ + byte *pColor; + int iBaseOffset; + int i; + int iOffset; + int iRowPos; + int iData; + int iLen; + int iGridPos[3]; + int iArrayXStep; + float fV; + float fFrac[3]; + float fOMFrac[3]; + float fWeight, fWeight2; + float fTotalFactor; + int iCurData; + vec3_t vLightOrigin; + byte *pCurData; + + if (!world || !world->lightGridData || !world->lightGridOffsets) { + vDirectedLight[0] = vDirectedLight[1] = vDirectedLight[2] = tr.identityLightByte; + vAmbientLight[0] = vAmbientLight[1] = vAmbientLight[2] = tr.identityLightByte; + return; + } + + VectorSubtract(vPos, world->lightGridOrigin, vLightOrigin); + + for (i = 0; i < 3; i++) { + fV = vLightOrigin[i] * world->lightGridInverseSize[i]; + iGridPos[i] = floor(fV); + fFrac[i] = fV - iGridPos[i]; + fOMFrac[i] = 1.0 - fFrac[i]; + + if (iGridPos[i] < 0) { + iGridPos[i] = 0; + } else if (iGridPos[i] > world->lightGridBounds[i] - 2) { + iGridPos[i] = world->lightGridBounds[i] - 2; + } + } + + fTotalFactor = 0; + iArrayXStep = world->lightGridBounds[1]; + iBaseOffset = world->lightGridBounds[0] + iGridPos[1] + iArrayXStep * iGridPos[0]; + VectorClear(vDirectedLight); + VectorClear(vAmbientLight); + + for (i = 0; i < 4; i++) { + qboolean bContinue = qfalse; + + switch (i) { + case 0: + fWeight = fOMFrac[0] * fOMFrac[1] * fOMFrac[2]; + fWeight2 = fOMFrac[0] * fOMFrac[1] * fFrac[2]; + iOffset = world->lightGridOffsets[iBaseOffset] + (world->lightGridOffsets[iGridPos[0]] << 8); + break; + case 1: + fWeight = fOMFrac[0] * fFrac[1] * fOMFrac[2]; + fWeight2 = fOMFrac[0] * fFrac[1] * fFrac[2]; + iOffset = world->lightGridOffsets[iBaseOffset + 1] + (world->lightGridOffsets[iGridPos[0]] << 8); + break; + case 2: + fWeight = fFrac[0] * fOMFrac[1] * fOMFrac[2]; + fWeight2 = fFrac[0] * fOMFrac[1] * fFrac[2]; + iOffset = world->lightGridOffsets[iBaseOffset + iArrayXStep] + + (world->lightGridOffsets[iGridPos[0] + 1] << 8); + break; + case 3: + fWeight = fFrac[0] * fFrac[1] * fOMFrac[2]; + fWeight2 = fFrac[0] * fFrac[1] * fFrac[2]; + iOffset = world->lightGridOffsets[iBaseOffset + iArrayXStep + 1] + + (world->lightGridOffsets[iGridPos[0] + 1] << 8); + break; + } + + iRowPos = iGridPos[2]; + pCurData = &world->lightGridData[iOffset]; + iData = 0; + + while (1) { + while (1) { + iCurData = (char)pCurData[iData]; + iData++; + if (iCurData >= 0) { + break; + } + + iLen = -iCurData; + if (iLen > iRowPos) { + iData += iRowPos; + + if (pCurData[iData]) { + pColor = R_GetLightGridPalettedColor(world, pCurData[iData]); + VectorMA(vAmbientLight, fWeight, pColor, vAmbientLight); + fTotalFactor += fWeight; + } + + iData++; + if (iLen - 1 == iRowPos) { + iData++; + } + + if (pCurData[iData]) { + pColor = R_GetLightGridPalettedColor(world, pCurData[iData]); + VectorMA(vDirectedLight, fWeight2, pColor, vDirectedLight); + fTotalFactor += fWeight2; + } + + bContinue = qtrue; + break; + } + + iRowPos -= iLen; + iData += iLen; + } + + if (bContinue) { + break; + } + + iLen = iCurData + 2; + if (iLen - 1 >= iRowPos) { + break; + } + + iRowPos -= iLen; + iData++; + } + + if (bContinue) { + continue; + } + + if (iLen - 1 > iRowPos) { + if (!pCurData[iData]) { + continue; + } + + pColor = R_GetLightGridPalettedColor(world, pCurData[iData]); + VectorMA(vAmbientLight, fWeight + fWeight2, pColor, vAmbientLight); + VectorMA(vDirectedLight, fWeight + fWeight2, pColor, vDirectedLight); + fTotalFactor += fWeight + fWeight2; + } else { + if (pCurData[iData]) { + pColor = R_GetLightGridPalettedColor(world, pCurData[iData]); + VectorMA(vAmbientLight, fWeight, pColor, vAmbientLight); + fTotalFactor += fWeight; + } + + iData += 2; + if (pCurData[iData]) { + pColor = R_GetLightGridPalettedColor(world, pCurData[iData]); + VectorMA(vDirectedLight, fWeight2, pColor, vDirectedLight); + fTotalFactor += fWeight2; + } + } + } + + if (fTotalFactor > 0.0 && fTotalFactor < 0.99) { + VectorScale(vAmbientLight, 1.0 / fTotalFactor, vAmbientLight); + VectorScale(vDirectedLight, 1.0 / fTotalFactor, vDirectedLight); + } + + if (fTotalFactor) { + /* + if (vLight[0] > 255.0 || vLight[1] > 255.0 || vLight[2] > 255.0) { + float t; + // normalize color values + t = 255.0 / Q_max(vLight[0], Q_max(vLight[1], vLight[2])); + VectorScale(vLight, t, vLight); + } + */ + } else { + vDirectedLight[0] = vDirectedLight[1] = vDirectedLight[2] = tr.identityLightByte; + vAmbientLight[0] = vAmbientLight[1] = vAmbientLight[2] = tr.identityLightByte; + } +} + /* =============== R_GetLightingForDecal @@ -533,3 +777,128 @@ void R_GetLightingForSmoke(vec3_t vLight, const vec3_t vOrigin) { // FIXME: unimplemented (GL2) } + +qboolean R_FindGridPointForSphere(world_t *world, const vec3_t sphereOrigin, const vec3_t point, vec3_t out) { + int i, j, k; + int gridStep[3][3]; + trace_t trace; + + for (i = 0; i < 3; i++) { + gridStep[i][0] = 0; + gridStep[i][1] = -world->lightGridSize[i]; + gridStep[i][2] = world->lightGridSize[i]; + } + + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + for (k = 0; k < 3; k++) { + vec3_t vOffset; + + vOffset[0] = point[0] + gridStep[0][i]; + vOffset[1] = point[1] + gridStep[1][j]; + vOffset[2] = point[2] + gridStep[2][k]; + + ri.CM_BoxTrace(&trace, point, sphereOrigin, vec3_origin, vec3_origin, 0, CONTENTS_SOLID, 0); + + if (trace.fraction == 1 || trace.surfaceFlags & SURF_SKY) { + return qtrue; + } + } + } + } + + return qfalse; +} + +int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *world ) +{ + vec3_t vLight; + vec3_t vEnd; + mnode_t* leaf; + trace_t trace; + vec3_t summedDir; + float addSize; + int iNumLights; + int i; + int j, k, l; + int gridStep[3][3]; + + if ( world->lightGridData == NULL ) + return qfalse; + + VectorClear(summedDir); + leaf = NULL; + iNumLights = 0; + + if (world->vis) { + leaf = R_FindPoint(world, point); + if (leaf->area == -1 || !leaf->numlights) { + leaf = NULL; + } + } + + if (leaf && leaf->numlights) { + spherel_t* sphere; + + for (i = (leaf->lights[0] == &tr.sSunLight ? 1 : 0); i < leaf->numlights; i++) { + sphere = leaf->lights[i]; + if (sphere->leaf != (mnode_t*)-1) { + byte mask = backEnd.refdef.areamask[sphere->leaf->area >> 3]; + + if (!(mask & (1 << (sphere->leaf->area & 7)))) { + + ri.CM_BoxTrace(&trace, point, sphere->origin, vec3_origin, vec3_origin, 0, CONTENTS_SOLID, 0); + + if (trace.fraction == 1) { + vec3_t dir; + + VectorSubtract(sphere->origin, point, dir); + + addSize = VectorLength(sphere->color); + VectorMA(summedDir, addSize, dir, summedDir); + + iNumLights++; + } + } + } + } + } + + if (s_sun.exists) { + if (leaf && leaf->lights[0] == &tr.sSunLight) { + vec3_t newPoint; + + VectorMA(point, 16384.0, s_sun.direction, vEnd); + + + ri.CM_BoxTrace(&trace, point, vEnd, vec3_origin, vec3_origin, 0, CONTENTS_SOLID, 0); + + if (trace.surfaceFlags & SURF_SKY) { + addSize = VectorLength(s_sun.color); + + VectorMA(summedDir, addSize, s_sun.direction, summedDir); + + iNumLights++; + } + } + } + + VectorNormalize(summedDir); + + if (DotProduct(summedDir, normal) > 0.2f) + VectorCopy(summedDir, lightDir); + else + VectorCopy(normal, lightDir); + + return qtrue; +} + +static void R_SetupEntityLightingGrid(trRefEntity_t* ent, world_t* world) +{ + vec3_t normal; + + R_GetLightingGridValue(world, ent->e.origin, ent->ambientLight, ent->directedLight); + + VectorSet(normal, 1, 0, 0); + R_LightDirForPoint(ent->e.origin, ent->lightDir, normal, world); +} diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 911565a6..8dd394bd 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -88,6 +88,13 @@ typedef unsigned int vaoCacheGlIndex_t; #define MAX_SPRITE_DIST 16384.0f #define MAX_SPRITE_DIST_SQUARED (MAX_SPRITE_DIST * MAX_SPRITE_DIST) +typedef enum { + USE_S_COORDS, + USE_T_COORDS +} texDirection_t; + +#define BUNDLE_ANIMATE_ONCE 1 + //========================= typedef struct cubemap_s { @@ -133,6 +140,7 @@ typedef struct { // OPENMOHAA-specific stuff // + int iGridLighting; float lodpercentage[2]; } trRefEntity_t; @@ -243,7 +251,14 @@ typedef enum { DEFORM_TEXT4, DEFORM_TEXT5, DEFORM_TEXT6, - DEFORM_TEXT7 + DEFORM_TEXT7, + // + // OPENMOHAA-specific stuff + //========================= + DEFORM_LIGHTGLOW, + DEFORM_FLAP_S, + DEFORM_FLAP_T, + //========================= } deform_t; // deformVertexes types that can be handled by the GPU @@ -409,7 +424,12 @@ typedef struct { } texModInfo_t; -#define MAX_IMAGE_ANIMATIONS 8 +//#define MAX_IMAGE_ANIMATIONS 8 +// +// OPENMOHAA-specific stuff +//========================= +#define MAX_IMAGE_ANIMATIONS 64 +//========================= typedef struct { image_t *image[MAX_IMAGE_ANIMATIONS]; @@ -425,6 +445,13 @@ typedef struct { int videoMapHandle; qboolean isLightmap; qboolean isVideoMap; + + // + // OPENMOHAA-specific stuff + //========================= + float imageAnimationPhase; + int flags; + //========================= } textureBundle_t; enum @@ -2156,6 +2183,7 @@ typedef struct { // OPENMOHAA-specific stuff // + int currentSpriteNum; int shiftedIsStatic; int overbrightShift; @@ -2381,7 +2409,20 @@ extern cvar_t* r_farplane_nocull; extern cvar_t* r_farplane_nofog; extern cvar_t* r_skybox_farplane; extern cvar_t* r_farclip; + +// Lighting + extern cvar_t* r_lightcoronasize; +extern cvar_t *r_entlight_scale; +extern cvar_t *r_entlight_errbound; +extern cvar_t *r_entlight_cubelevel; +extern cvar_t *r_entlight_cubefraction; +extern cvar_t *r_entlight_maxcalc; +extern cvar_t *r_light_lines; +extern cvar_t *r_light_sun_line; +extern cvar_t *r_light_int_scale; +extern cvar_t *r_light_nolight; +extern cvar_t *r_light_showgrid; // LOD @@ -2641,6 +2682,7 @@ void R_SavePerformanceCounters(void); // tr_main.c // +void R_AddSpriteSurfaces(); qboolean SurfIsOffscreen2(const srfBspSurface_t* surface, shader_t* shader, int entityNum); // @@ -2784,8 +2826,6 @@ int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, ve int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *world ); int R_CubemapForPoint( vec3_t point ); -void R_Sphere_InitLights(); - /* ============================================================ @@ -3022,6 +3062,17 @@ LIGHTS void R_GetLightingForDecal(vec3_t vLight, const vec3_t vFacing, const vec3_t vOrigin); void R_GetLightingForSmoke(vec3_t vLight, const vec3_t vOrigin); +void R_GetLightingGridValue(world_t* world, const vec3_t vPos, vec3_t vAmbientLight, vec3_t vDirectedLight); +void RB_SetupEntityGridLighting(); +void RB_SetupStaticModelGridLighting(trRefdef_t* refdef, cStaticModelUnpacked_t* ent, const vec3_t lightOrigin); + +void RB_Light_Real(unsigned char* colors); +void RB_Sphere_BuildDLights(); +void RB_Sphere_SetupEntity(); +void RB_Grid_SetupEntity(); +void RB_Grid_SetupStaticModel(); +void RB_Light_Fullbright(unsigned char* colors); +void R_Sphere_InitLights(); int R_GatherLightSources(const vec3_t vPos, vec3_t* pvLightPos, vec3_t* pvLightIntensity, int iMaxLights); extern suninfo_t s_sun; @@ -3052,6 +3103,17 @@ void RE_AddTerrainMarkToScene(int iTerrainIndex, qhandle_t hShader, int numVerts refEntity_t* RE_GetRenderEntity(int entityNumber); qboolean RE_AddPolyToScene2(qhandle_t hShader, int numVerts, const polyVert_t* verts, int renderfx); + +/* +============================================================ + +SHADE CALC + +============================================================ +*/ + +void RB_CalcLightGridColor(unsigned char* colors); + /* ============================================================= @@ -3202,9 +3264,12 @@ WORLD MAP ============================================================ */ void R_GetInlineModelBounds(int iIndex, vec3_t vMins, vec3_t vMaxs); +int R_SphereInLeafs(const vec3_t p, float r, mnode_t** nodes, int nMaxNodes); mnode_t* R_PointInLeaf(const vec3_t p); int R_CheckDlightTerrain(cTerraPatchUnpacked_t* surf, int dlightBits); +void R_AddSpriteSurfCmd(drawSurf_t* drawSurfs, int numDrawSurfs); + //========================= /* @@ -3359,7 +3424,13 @@ typedef enum { RC_CLEARDEPTH, RC_CAPSHADOWMAP, RC_POSTPROCESS, - RC_EXPORT_CUBEMAPS + RC_EXPORT_CUBEMAPS, + + // + // OPENMOHAA-specific stuff + // + + RC_SPRITE_SURFS, } renderCommand_t; diff --git a/code/renderergl2/tr_main.c b/code/renderergl2/tr_main.c index 249f4516..2eef5387 100644 --- a/code/renderergl2/tr_main.c +++ b/code/renderergl2/tr_main.c @@ -1586,7 +1586,9 @@ void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader, R_SortDrawSurfs ================= */ -void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) { +void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs, + drawSurf_t *spriteSurfs, int numSpriteSurfs +) { shader_t *shader; int fogNum; int entityNum; @@ -1601,11 +1603,13 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) { if ( numDrawSurfs < 1 ) { // we still need to add it for hyperspace cases R_AddDrawSurfCmd( drawSurfs, numDrawSurfs ); + R_AddSpriteSurfCmd( spriteSurfs, numSpriteSurfs ); return; } // sort the drawsurfs by sort type, then orientation, then shader R_RadixSort( drawSurfs, numDrawSurfs ); + R_RadixSort( spriteSurfs, numSpriteSurfs ); // skip pass through drawing if rendering a shadow map if (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW)) @@ -1639,6 +1643,7 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) { } R_AddDrawSurfCmd( drawSurfs, numDrawSurfs ); + R_AddSpriteSurfCmd( spriteSurfs, numSpriteSurfs ); } static void R_AddEntitySurface (int entityNum) @@ -1780,6 +1785,12 @@ void R_GenerateDrawSurfs( void ) { R_SetupProjectionZ (&tr.viewParms); R_AddEntitySurfaces (); + + // + // OPENMOHAA-specific stuff + //========================= + R_AddSpriteSurfaces(); + //========================= } /* @@ -2066,7 +2077,8 @@ or a mirror / remote location */ void R_RenderView (viewParms_t *parms) { int firstDrawSurf; - int numDrawSurfs; + int numDrawSurfs; + int firstSpriteSurf; if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) { return; @@ -2078,7 +2090,8 @@ void R_RenderView (viewParms_t *parms) { tr.viewParms.frameSceneNum = tr.frameSceneNum; tr.viewParms.frameCount = tr.frameCount; - firstDrawSurf = tr.refdef.numDrawSurfs; + firstDrawSurf = tr.refdef.numDrawSurfs; + firstSpriteSurf = tr.refdef.numSpriteSurfs; tr.viewCount++; @@ -2097,7 +2110,9 @@ void R_RenderView (viewParms_t *parms) { numDrawSurfs = MAX_DRAWSURFS; } - R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, numDrawSurfs - firstDrawSurf ); + R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, numDrawSurfs - firstDrawSurf, + tr.refdef.spriteSurfs + firstSpriteSurf, tr.refdef.numSpriteSurfs - firstSpriteSurf + ); // draw main system development information (surface outlines, etc) R_DebugGraphics(); @@ -2248,6 +2263,24 @@ void R_RenderPshadowMaps(const refdef_t *fd) radius = 0.5f * VectorLength( diag ); } break; + // OPENMOHAA-specific stuff + //========================= + case MOD_TIKI: + radius = ri.TIKI_GlobalRadius(model->d.tiki); + break; + case MOD_SPRITE: + { + float w; + + radius = model->d.sprite->width * model->d.sprite->scale * 0.5; + w = model->d.sprite->height * model->d.sprite->scale * 0.5; + + if (radius <= w) { + radius = w; + } + } + break; + //========================= default: break; @@ -2401,6 +2434,7 @@ void R_RenderPshadowMaps(const refdef_t *fd) for ( i = 0; i < tr.refdef.num_pshadows; i++) { int firstDrawSurf; + int firstSpriteSurf; pshadow_t *shadow = &tr.refdef.pshadows[i]; int j; @@ -2443,7 +2477,8 @@ void R_RenderPshadowMaps(const refdef_t *fd) tr.viewParms.frameSceneNum = tr.frameSceneNum; tr.viewParms.frameCount = tr.frameCount; - firstDrawSurf = tr.refdef.numDrawSurfs; + firstDrawSurf = tr.refdef.numDrawSurfs; + firstSpriteSurf = tr.refdef.numSpriteSurfs; tr.viewCount++; @@ -2514,7 +2549,9 @@ void R_RenderPshadowMaps(const refdef_t *fd) R_AddEntitySurface(shadow->entityNums[j]); } - R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf ); + R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf, + tr.refdef.spriteSurfs + firstSpriteSurf, tr.refdef.numSpriteSurfs - firstSpriteSurf + ); if (!glRefConfig.framebufferObject) R_AddCapShadowmapCmd( i, -1 ); @@ -2810,6 +2847,7 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level) { int firstDrawSurf; + int firstSpriteSurf; Com_Memset( &shadowParms, 0, sizeof( shadowParms ) ); @@ -2853,6 +2891,7 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level) tr.viewParms.frameCount = tr.frameCount; firstDrawSurf = tr.refdef.numDrawSurfs; + firstSpriteSurf = tr.refdef.numSpriteSurfs; tr.viewCount++; @@ -2867,7 +2906,8 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level) R_AddEntitySurfaces (); - R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf ); + R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf, + tr.refdef.spriteSurfs + firstSpriteSurf, tr.refdef.numSpriteSurfs - firstSpriteSurf ); } Mat4Multiply(tr.viewParms.projectionMatrix, tr.viewParms.world.modelMatrix, tr.refdef.sunShadowMvp[level]); @@ -3003,6 +3043,29 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene ) // OPENMOHAA-specific stuff // +void R_AdjustVisBoundsForSprite(refSprite_t* ent, viewParms_t* viewParms, orientationr_t* or ) +{ + if (tr.viewParms.visBounds[0][0] > ent->origin[0] - ent->scale) { + tr.viewParms.visBounds[0][0] = ent->origin[0] - ent->scale; + } + if (tr.viewParms.visBounds[0][1] > ent->origin[1] - ent->scale) { + tr.viewParms.visBounds[0][1] = ent->origin[1] - ent->scale; + } + if (tr.viewParms.visBounds[0][2] > ent->origin[2] - ent->scale) { + tr.viewParms.visBounds[0][2] = ent->origin[2] - ent->scale; + } + + if (tr.viewParms.visBounds[1][0] < ent->origin[0] + ent->scale) { + tr.viewParms.visBounds[1][0] = ent->origin[0] + ent->scale; + } + if (tr.viewParms.visBounds[1][1] < ent->origin[1] + ent->scale) { + tr.viewParms.visBounds[1][1] = ent->origin[1] + ent->scale; + } + if (tr.viewParms.visBounds[1][2] < ent->origin[2] + ent->scale) { + tr.viewParms.visBounds[1][2] = ent->origin[2] + ent->scale; + } +} + /* ================= R_AddSpriteSurf @@ -3022,6 +3085,58 @@ void R_AddSpriteSurf(surfaceType_t* surface, shader_t* shader, float zDistance) tr.refdef.numSpriteSurfs++; } +void R_AddSpriteSurfaces() +{ + refSprite_t* sprite; + vec3_t delta; + + if (!r_drawsprites->integer) { + return; + } + + // FIXME: fix buggy sprites causing annoying crashes + return; + + for (tr.currentSpriteNum = 0; tr.currentSpriteNum < tr.refdef.num_sprites; ++tr.currentSpriteNum) + { + sprite = &tr.refdef.sprites[tr.currentSpriteNum]; + + if (tr.viewParms.isPortalSky) { + if (!(sprite->renderfx & RF_SKYENTITY)) { + continue; + } + } else { + if (sprite->renderfx & RF_SKYENTITY) { + continue; + } + } + + if (tr.viewParms.isPortal) { + if (!(sprite->renderfx & (RF_SHADOW_PLANE | RF_WRAP_FRAMES))) { + continue; + } + } else { + if (sprite->renderfx & RF_SHADOW_PLANE) { + continue; + } + } + + tr.currentEntityNum = ENTITYNUM_WORLD; + tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT; + if (sprite->hModel && sprite->hModel < tr.numModels) { + tr.currentModel = tr.models[sprite->hModel]; + } else { + tr.currentModel = tr.models[0]; + } + + R_AdjustVisBoundsForSprite(&tr.refdef.sprites[tr.currentSpriteNum], &tr.viewParms, &tr.or ); + sprite->shaderNum = tr.currentModel->d.sprite->shader->sortedIndex; + + VectorSubtract(sprite->origin, tr.refdef.vieworg, delta); + R_AddSpriteSurf(&sprite->surftype, tr.currentModel->d.sprite->shader, VectorLengthSquared(delta)); + } +} + /* ================= R_RotateForStaticModel diff --git a/code/renderergl2/tr_shade_calc.c b/code/renderergl2/tr_shade_calc.c index 15cfb9c6..3f5c28d9 100644 --- a/code/renderergl2/tr_shade_calc.c +++ b/code/renderergl2/tr_shade_calc.c @@ -400,9 +400,19 @@ static void AutospriteDeform( void ) { } // compensate for scale in the axes if necessary - if ( backEnd.currentEntity->e.nonNormalizedAxes ) { + if ( backEnd.currentStaticModel || backEnd.currentEntity->e.nonNormalizedAxes ) { float axisLength; - axisLength = VectorLength( backEnd.currentEntity->e.axis[0] ); + + // OPENMOHAA-specific stuff + //========================= + if (backEnd.currentStaticModel) { + axisLength = VectorLength(backEnd.currentStaticModel->axis[0]); + } + else + //========================= + { + axisLength = VectorLength(backEnd.currentEntity->e.axis[0]); + } if ( !axisLength ) { axisLength = 0; } else { @@ -816,3 +826,41 @@ void RB_CalcRotateTexMatrix( float degsPerSecond, float *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; } + +// +// OPENMOHAA-specific stuff +// + +void RB_CalcLightGridColor(unsigned char* colors) +{ + int i; + + if (!backEnd.currentEntity) { + for (i = 0; i < tess.numVertexes; i++) { + colors[i * 4] = ((byte*)&backEnd.currentStaticModel->iGridLighting)[0]; + colors[i * 4 + 1] = ((byte*)&backEnd.currentStaticModel->iGridLighting)[1]; + colors[i * 4 + 2] = ((byte*)&backEnd.currentStaticModel->iGridLighting)[2]; + colors[i * 4 + 3] = ((byte*)&backEnd.currentStaticModel->iGridLighting)[3]; + } + } + else if (backEnd.currentEntity != &tr.worldEntity) { + for (i = 0; i < tess.numVertexes; i++) { + colors[i * 4] = ((byte*)&backEnd.currentEntity->iGridLighting)[0]; + colors[i * 4 + 1] = ((byte*)&backEnd.currentEntity->iGridLighting)[1]; + colors[i * 4 + 2] = ((byte*)&backEnd.currentEntity->iGridLighting)[2]; + colors[i * 4 + 3] = ((byte*)&backEnd.currentEntity->iGridLighting)[3]; + } + } + else { + ri.Printf(PRINT_ALL, + "##### shader '%s' incorrectly uses rgbGen lightingGrid or lightingSpherical; was rgbGen vertex intended?\n", + tess.shader->name); + + for (i = 0; i < tess.numVertexes; i++) { + colors[i * 4] = 0xFF; + colors[i * 4 + 1] = 0xFF; + colors[i * 4 + 2] = 0xFF; + colors[i * 4 + 3] = 0xFF; + } + } +} \ No newline at end of file diff --git a/code/renderergl2/tr_shader.c b/code/renderergl2/tr_shader.c index ac140cd0..4ee311ed 100644 --- a/code/renderergl2/tr_shader.c +++ b/code/renderergl2/tr_shader.c @@ -38,6 +38,12 @@ static shader_t* hashTable[FILE_HASH_SIZE]; #define MAX_SHADERTEXT_HASH 2048 static char **shaderTextHashTable[MAX_SHADERTEXT_HASH]; +// +// OPENMOHAA-specific stuff +//========================= +static void CreateMultistageFromBundle(); +//========================= + /* ================ return a hash value for the filename @@ -663,16 +669,16 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) if ( !Q_stricmp( token, "$whiteimage" ) ) { - stage->bundle[0].image[0] = tr.whiteImage; + stage->bundle[cntBundle].image[0] = tr.whiteImage; continue; } else if ( !Q_stricmp( token, "$lightmap" ) ) { - stage->bundle[0].isLightmap = qtrue; + stage->bundle[cntBundle].isLightmap = qtrue; if ( shader.lightmapIndex < 0 || !tr.lightmaps ) { - stage->bundle[0].image[0] = tr.whiteImage; + stage->bundle[cntBundle].image[0] = tr.whiteImage; } else { - stage->bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex]; + stage->bundle[cntBundle].image[0] = tr.lightmaps[shader.lightmapIndex]; } continue; } @@ -684,11 +690,11 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) return qfalse; } - stage->bundle[0].isLightmap = qtrue; + stage->bundle[cntBundle].isLightmap = qtrue; if ( shader.lightmapIndex < 0 ) { - stage->bundle[0].image[0] = tr.whiteImage; + stage->bundle[cntBundle].image[0] = tr.whiteImage; } else { - stage->bundle[0].image[0] = tr.deluxemaps[shader.lightmapIndex]; + stage->bundle[cntBundle].image[0] = tr.deluxemaps[shader.lightmapIndex]; } continue; } @@ -717,9 +723,9 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) flags |= IMGFLAG_GENNORMALMAP; } - stage->bundle[0].image[0] = R_FindImageFile( token, type, flags ); + stage->bundle[cntBundle].image[0] = R_FindImageFile( token, type, flags ); - if ( !stage->bundle[0].image[0] ) + if ( !stage->bundle[cntBundle].image[0] ) { ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); return qfalse; @@ -762,8 +768,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) } - stage->bundle[0].image[0] = R_FindImageFile( token, type, flags ); - if ( !stage->bundle[0].image[0] ) + stage->bundle[cntBundle].image[0] = R_FindImageFile( token, type, flags ); + if ( !stage->bundle[cntBundle].image[0] ) { ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); return qfalse; @@ -782,7 +788,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMap' keyword in shader '%s'\n", shader.name ); return qfalse; } - stage->bundle[0].imageAnimationSpeed = atof( token ); + stage->bundle[cntBundle].imageAnimationSpeed = atof( token ); // parse up to MAX_IMAGE_ANIMATIONS animations while ( 1 ) { @@ -792,7 +798,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) if ( !token[0] ) { break; } - num = stage->bundle[0].numImageAnimations; + num = stage->bundle[cntBundle].numImageAnimations; if ( num < MAX_IMAGE_ANIMATIONS ) { imgFlags_t flags = IMGFLAG_NONE; @@ -802,13 +808,13 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) if (!shader.noPicMip) flags |= IMGFLAG_PICMIP; - stage->bundle[0].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags ); - if ( !stage->bundle[0].image[num] ) + stage->bundle[cntBundle].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags ); + if ( !stage->bundle[cntBundle].image[num] ) { ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); return qfalse; } - stage->bundle[0].numImageAnimations++; + stage->bundle[cntBundle].numImageAnimations++; } totalImages++; } @@ -826,10 +832,10 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMap' keyword in shader '%s'\n", shader.name ); return qfalse; } - stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader)); - if (stage->bundle[0].videoMapHandle != -1) { - stage->bundle[0].isVideoMap = qtrue; - stage->bundle[0].image[0] = tr.scratchImage[stage->bundle[0].videoMapHandle]; + stage->bundle[cntBundle].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader)); + if (stage->bundle[cntBundle].videoMapHandle != -1) { + stage->bundle[cntBundle].isVideoMap = qtrue; + stage->bundle[cntBundle].image[0] = tr.scratchImage[stage->bundle[cntBundle].videoMapHandle]; } else { ri.Printf( PRINT_WARNING, "WARNING: could not load '%s' for 'videoMap' keyword in shader '%s'\n", token, shader.name ); } @@ -1677,22 +1683,22 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) if ( !Q_stricmp( token, "environment" ) ) { - stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED; + stage->bundle[cntBundle].tcGen = TCGEN_ENVIRONMENT_MAPPED; } else if ( !Q_stricmp( token, "lightmap" ) ) { - stage->bundle[0].tcGen = TCGEN_LIGHTMAP; + stage->bundle[cntBundle].tcGen = TCGEN_LIGHTMAP; } else if ( !Q_stricmp( token, "texture" ) || !Q_stricmp( token, "base" ) ) { - stage->bundle[0].tcGen = TCGEN_TEXTURE; + stage->bundle[cntBundle].tcGen = TCGEN_TEXTURE; } else if ( !Q_stricmp( token, "vector" ) ) { - ParseVector( text, 3, stage->bundle[0].tcGenVectors[0] ); - ParseVector( text, 3, stage->bundle[0].tcGenVectors[1] ); + ParseVector( text, 3, stage->bundle[cntBundle].tcGenVectors[0] ); + ParseVector( text, 3, stage->bundle[cntBundle].tcGenVectors[1] ); - stage->bundle[0].tcGen = TCGEN_VECTOR; + stage->bundle[cntBundle].tcGen = TCGEN_VECTOR; } else { @@ -1731,7 +1737,70 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) } // // OPENMOHAA-specific stuff - // + //========================= + else if ( !Q_stricmp(token, "animMapOnce") || !Q_stricmp(token, "animMapPhase")) + { + qboolean phased; + + if (!Q_stricmp(token, "animMapOnce")) { + stage->bundle[cntBundle].flags |= BUNDLE_ANIMATE_ONCE; + } + + phased = !Q_stricmp(token, "animMapPhase"); + + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) + { + ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMmap' keyword in shader '%s'\n", shader.name ); + return qfalse; + } + stage->bundle[cntBundle].imageAnimationSpeed = atof( token ); + stage->bundle[cntBundle].imageAnimationPhase = 0; + + if (phased) + { + token = COM_ParseExt(text, qfalse); + if (!token[0]) + { + ri.Printf(PRINT_WARNING, "WARNING: missing phase for 'animMapPhase' keyword in shader '%s'\n", shader.name); + return qfalse; + } + + stage->bundle[cntBundle].imageAnimationPhase = atof(token); + } + // parse up to MAX_IMAGE_ANIMATIONS animations + while ( 1 ) { + int num; + + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + break; + } + num = stage->bundle[cntBundle].numImageAnimations; + if ( num < MAX_IMAGE_ANIMATIONS ) { + imgFlags_t flags = IMGFLAG_NONE; + + if (!shader.noMipMaps) + flags |= IMGFLAG_MIPMAP; + + if (!shader.noPicMip) + flags |= IMGFLAG_PICMIP; + + stage->bundle[cntBundle].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags ); + if ( !stage->bundle[cntBundle].image[num] ) + { + ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); + return qfalse; + } + stage->bundle[cntBundle].numImageAnimations++; + } + } + } + else if (!Q_stricmp(token, "nofog")) + { + // FIXME: unimplemented + continue; + } else if (!Q_stricmp(token, "depthmask")) { depthMaskBits = GLS_DEPTHMASK_TRUE; @@ -1759,10 +1828,10 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) } else if (!Q_stricmp(token, "nextBundle")) { - if (!qglActiveTextureARB) { - ri.Printf(PRINT_ALL, "WARNING: " PRODUCT_NAME " requires a video card with multitexturing capability\n"); - return qfalse; - } + //if (!qglActiveTextureARB) { + // ri.Printf(PRINT_ALL, "WARNING: " PRODUCT_NAME " requires a video card with multitexturing capability\n"); + // return qfalse; + //} token = COM_ParseExt(text, qfalse); if (token[0] && !Q_stricmp(token, "add")) { @@ -1814,7 +1883,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) } shouldProcess &= evaluatedValue ^ isNot; - } + } + //========================= else { ri.Printf( PRINT_WARNING, "WARNING: unknown parameter '%s' in shader '%s'\n", token, shader.name ); @@ -2016,6 +2086,72 @@ static void ParseDeform( char **text ) { return; } + // + // OPENMOHAA-specific stuff + //========================= + if (!Q_stricmp(token, "lightglow")) { + ds->deformation = DEFORM_LIGHTGLOW; + return; + } + + if (!Q_stricmp(token, "flap")) { + texDirection_t coordDirection; + + token = COM_ParseExt(text, qfalse); + if (token[0] == 's') { + coordDirection = USE_S_COORDS; + } + else if (token[0] == 't') { + coordDirection = USE_T_COORDS; + } + else { + ri.Printf(PRINT_WARNING, "WARNING: deformVertexes flap requires 's' or 't' in shader '%s'\n", shader.name); + return; + } + + token = COM_ParseExt(text, qfalse); + if (token[0] == 0) { + ri.Printf(PRINT_WARNING, "WARNING: missing deformVertexes flap parm in shader '%s'\n", shader.name); + return; + } + + if (!atof(token)) { + ds->deformationSpread = 100.0; + ri.Printf(PRINT_WARNING, "WARNING: illegal div value of 0 in deformVertexes command for shader '%s'\n", shader.name); + } + else { + ds->deformationSpread = 1.0 / atof(token); + } + + ParseWaveForm(text, &ds->deformationWave); + + if (coordDirection == USE_T_COORDS) { + ds->deformation = DEFORM_FLAP_T; + } + else { + ds->deformation = DEFORM_FLAP_S; + } + + token = COM_ParseExt(text, qfalse); + if (token[0] == 0) + { + ds->bulgeWidth = 0.0; + ds->bulgeHeight = 1.0; + return; + } + ds->bulgeWidth = atof(token); + + token = COM_ParseExt(text, qfalse); + if (token[0] == 0) + { + ri.Printf(PRINT_WARNING, "WARNING: missing deformVertexes parm 'max' in shader '%s'\n\n", shader.name); + return; + } + ds->bulgeHeight = atof(token); + return; + } + //========================= + ri.Printf( PRINT_WARNING, "WARNING: unknown deformVertexes subtype '%s' found in shader '%s'\n", token, shader.name ); } @@ -2473,7 +2609,44 @@ static qboolean ParseShader( char **text ) } // // OPENMOHAA-specific stuff - //========================= + //========================= + else if (!Q_stricmp(token, "noMerge")) + { + // FIXME: unimplemented + continue; + } + else if (!Q_stricmp(token, "spritegen")) + { + token = COM_ParseExt(text, qfalse); + if (token[0] == 0) { + ri.Printf(PRINT_WARNING, "WARNING: missing spritegen parm in shader '%s'\n", shader.name); + continue; + } + + if (!Q_stricmp(token, "parallel")) { + shader.sprite.type = SPRITE_PARALLEL; + } else if (!Q_stricmp(token, "parallel_oriented")) { + shader.sprite.type = SPRITE_PARALLEL_ORIENTED; + } else if (!Q_stricmp(token, "parallel_upright")) { + shader.sprite.type = SPRITE_PARALLEL_UPRIGHT; + } else if (!Q_stricmp(token, "oriented")) { + shader.sprite.type = SPRITE_ORIENTED; + } + + shader.sprite.scale = 1.0; + continue; + } + else if (!Q_stricmp(token, "spritescale")) + { + token = COM_ParseExt(text, qfalse); + if (token[0] == 0) { + ri.Printf(PRINT_WARNING, "WARNING: missing spritescale parm in shader '%s'\n", shader.name); + continue; + } + + shader.sprite.scale = atof(token); + continue; + } // force 32 bit images if (!Q_stricmp(token, "force32bit")) { @@ -3535,6 +3708,12 @@ static shader_t *FinishShader( void ) { hasLightmapStage = qfalse; vertexLightmap = qfalse; + // + // OPENMOHAA-specific stuff + //========================= + CreateMultistageFromBundle(); + //========================= + // // set sky stuff appropriate // @@ -4500,6 +4679,46 @@ void R_InitShaders( void ) { CreateExternalShaders(); } +// +// OPENMOHAA-specific stuff +//========================= + +static void CreateMultistageFromBundle() { + int stage, bundle; + int i; + + for (stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { + shaderStage_t* pStage = &stages[stage]; + + if (!pStage->active) { + break; + } + + if (pStage->bundle[TB_LIGHTMAP].isLightmap) { + shaderStage_t* newStage = NULL; + + for (i = stage; i < MAX_SHADER_STAGES; i++) { + if (!stages[i].active) { + newStage = &stages[i]; + break; + } + } + + if (newStage) { + *newStage = *pStage; + newStage->stateBits = GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHFUNC_EQUAL; + + newStage->bundle[TB_COLORMAP] = pStage->bundle[TB_LIGHTMAP]; + memset(&newStage->bundle[TB_LIGHTMAP], 0, sizeof(textureBundle_t)); + memset(&pStage->bundle[TB_LIGHTMAP], 0, sizeof(textureBundle_t)); + stage = i; + } + } + } +} + +//========================= + qhandle_t RE_RefreshShaderNoMip(const char* name) { shader_t* sh; char strippedName[64]; diff --git a/code/renderergl2/tr_sphere_shade.cpp b/code/renderergl2/tr_sphere_shade.cpp index cf4d1951..3611d913 100644 --- a/code/renderergl2/tr_sphere_shade.cpp +++ b/code/renderergl2/tr_sphere_shade.cpp @@ -72,8 +72,6 @@ static vec3_t offsets[26] = { {-one_third_root, -one_third_root, -one_third_root} }; -#if 0 - int compare_light_intensities(const void *p1, const void *p2) { return *(int *)&((const reallightinfo_t *)p2)->fIntensity - *(int *)&((const reallightinfo_t *)p1)->fIntensity; @@ -624,9 +622,11 @@ static void RB_Sphere_Light_Sun() GL_State(GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE); + // FIXME: unimplemented +#if 0 qglPushMatrix(); - qglLoadMatrixf(backEnd.ori.modelMatrix); + qglLoadMatrixf(backEnd.or.modelMatrix); // Clear the depth range qglDepthRange(0.0, 0.0); @@ -645,6 +645,7 @@ static void RB_Sphere_Light_Sun() qglDepthRange(0.0, 1.0); qglPopMatrix(); +#endif } return; @@ -666,9 +667,11 @@ static void RB_Sphere_Light_Sun() GL_State(GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE); + // FIXME: unimplemented +#if 0 qglPushMatrix(); - qglLoadMatrixf(backEnd.ori.modelMatrix); + qglLoadMatrixf(backEnd.or.modelMatrix); // Clear the depth range qglDepthRange(0.0, 0.0); @@ -693,6 +696,7 @@ static void RB_Sphere_Light_Sun() qglDepthRange(0.0, 1.0); qglPopMatrix(); +#endif } if (hitSun) { @@ -771,7 +775,7 @@ static bool RB_Sphere_SetupGlobals() } else if (!RB_Sphere_CalculateSphereOrigin()) { backEnd.currentSphere->TessFunction = &RB_CalcLightGridColor; - if (!backEnd.currentEntity->bLightGridCalculated) { + if (!backEnd.currentEntity->lightingCalculated) { RB_SetupEntityGridLighting(); } @@ -793,9 +797,9 @@ static bool RB_Sphere_SetupGlobals() static bool RB_Sphere_ResetPointColors() { - vec3_t light_offset, amb; + vec3_t light_offset, amb_light_offset, amb; - R_GetLightingGridValue(backEnd.currentSphere->worldOrigin, light_offset); + R_GetLightingGridValue(tr.world, backEnd.currentSphere->worldOrigin, light_offset, amb_light_offset); light_offset[0] = ambientlight[0] + light_offset[0] * 0.18; light_offset[1] = ambientlight[1] + light_offset[1] * 0.18; light_offset[2] = ambientlight[2] + light_offset[2] * 0.18; @@ -809,7 +813,7 @@ static bool RB_Sphere_ResetPointColors() } } - VectorScale(light_offset, tr.overbrightMult * r_entlight_scale->value, amb); + VectorScale(amb_light_offset, tr.overbrightMult * r_entlight_scale->value, amb); backEnd.currentSphere->ambient.level[0] = Q_min(amb[0], 0xff); backEnd.currentSphere->ambient.level[1] = Q_min(amb[1], 0xff); backEnd.currentSphere->ambient.level[2] = Q_min(amb[2], 0xff); @@ -828,9 +832,11 @@ static void RB_Sphere_DrawDebugLine(const spherel_t *thislight, float falloff, c return; } + // FIXME: unimplemented +#if 0 qglPushMatrix(); - qglLoadMatrixf(backEnd.ori.modelMatrix); + qglLoadMatrixf(backEnd.or.modelMatrix); // Clear the depth range qglDepthRange(0.0, 0.0); @@ -883,6 +889,7 @@ static void RB_Sphere_DrawDebugLine(const spherel_t *thislight, float falloff, c // Restore depth qglDepthRange(0.0, 1.0); qglPopMatrix(); +#endif } static void RB_Sphere_AddSpotLight(const spherel_t *thislight) @@ -1344,23 +1351,10 @@ static void R_InsertLightIntoList(spherel_t *pLight, float fIntensity, gatheredL pCurrLight->pLight = pLight; } -#else - -void R_Sphere_InitLights() -{ - // UNIMPLEMENTED -} - -#endif - #define MAX_GATHERED_LIGHTS 8 int R_GatherLightSources(const vec3_t vPos, vec3_t *pvLightPos, vec3_t *pvLightIntensity, int iMaxLights) { - // FIXME: unimplemented (GL2) - return 0; - -#if 0 int i, j; int iLightCount; vec3_t vEnd; @@ -1468,5 +1462,4 @@ int R_GatherLightSources(const vec3_t vPos, vec3_t *pvLightPos, vec3_t *pvLightI } return iLightCount; -#endif } diff --git a/code/renderergl2/tr_sprite.c b/code/renderergl2/tr_sprite.c index 1739c63d..3604fa8c 100644 --- a/code/renderergl2/tr_sprite.c +++ b/code/renderergl2/tr_sprite.c @@ -96,7 +96,7 @@ void RB_DrawSprite( const refSprite_t *spr ) { model = tr.models; if (spr->hModel > 0 && spr->hModel < tr.numModels) { - model = &tr.models[spr->hModel]; + model = tr.models[spr->hModel]; } scale = spr->scale * model->d.sprite->scale; diff --git a/code/renderergl2/tr_world.c b/code/renderergl2/tr_world.c index 850996d0..4f3931b8 100644 --- a/code/renderergl2/tr_world.c +++ b/code/renderergl2/tr_world.c @@ -869,6 +869,52 @@ void R_AddWorldSurfaces (void) { // OPENMOHAA-specific stuff // +int R_SphereInLeafs(const vec3_t p, float r, mnode_t** nodes, int nMaxNodes) { + mnode_t* nodestack[1024]; + int iNodeStackPos; + mnode_t* pCurNode; + int nFoundNodes; + + iNodeStackPos = 0; + pCurNode = tr.world->nodes; + nFoundNodes = 0; + + while (1) + { + cplane_t* plane; + float d; + + while (pCurNode->contents == -1) + { + plane = pCurNode->plane; + if (plane->type >= PLANE_NON_AXIAL) { + d = DotProduct(p, plane->normal) - plane->dist; + } else { + d = p[plane->type] - plane->dist; + } + + if (d < r) { + if (d > -r) { + nodestack[iNodeStackPos++] = pCurNode->children[0]; + } + pCurNode = pCurNode->children[1]; + } else { + pCurNode = pCurNode->children[0]; + } + } + + nodes[nFoundNodes++] = pCurNode; + if (!iNodeStackPos || nFoundNodes == nMaxNodes) { + break; + } + + iNodeStackPos--; + pCurNode = nodestack[iNodeStackPos]; + } + + return nFoundNodes; +} + void R_GetInlineModelBounds(int iIndex, vec3_t vMins, vec3_t vMaxs) { bmodel_t* bmodel;