Added full sprite support

This commit is contained in:
OM 2023-05-29 14:27:36 +02:00
parent d5c2c22dbb
commit 3acda727d2
6 changed files with 456 additions and 29 deletions

View file

@ -916,6 +916,74 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
#endif
}
/*
==================
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 = 0;
backEnd.pc.c_surfaces += numDrawSurfs;
backEnd.ori = 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 || (oldShader->flags & RF_THIRD_PERSON) != 0) && !shader->entityMergable)
{
if (oldShader) {
RB_EndSurface();
}
RB_BeginSurface(shader);
oldShader = shader;
}
qglLoadMatrixf(backEnd.ori.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
qglLoadMatrixf(backEnd.viewParms.world.modelMatrix);
// go back to the previous depth range
if (depthRange) {
qglDepthRange(0.0, 1.0);
}
}
/*
============================================================================
@ -1153,6 +1221,31 @@ const void *RB_DrawSurfs( const void *data ) {
}
/*
=============
RB_DrawSurfs
=============
*/
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_RenderSpriteSurfList(cmd->drawSurfs, cmd->numDrawSurfs);
return (const void*)(cmd + 1);
}
/*
=============
RB_DrawBuffer
@ -1319,6 +1412,9 @@ void RB_ExecuteRenderCommands( const void *data ) {
case RC_DRAW_SURFS:
data = RB_DrawSurfs( data );
break;
case RC_SPRITE_SURFS:
data = RB_SpriteSurfs( data );
break;
case RC_DRAW_BUFFER:
data = RB_DrawBuffer( data );
break;

View file

@ -254,6 +254,29 @@ void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ) {
}
/*
=============
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;
}
/*
=============
RE_SetColor

View file

@ -2526,6 +2526,8 @@ image_t* R_FindImageFile(const char* name, qboolean mipmap, qboolean allowPicmip
//
// load the pic from disk
//
numMipmaps = mipmap;
iMipmapsAvailable = 0;
R_LoadImage(name, &pic, &width, &height, &hasAlpha, &glCompressMode, &numMipmaps, &iMipmapsAvailable);
if (pic == NULL) {
return NULL;

View file

@ -293,6 +293,29 @@ void myGlMultMatrix( const float *a, const float *b, float *out ) {
}
}
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_RotateForEntity
@ -1318,6 +1341,25 @@ void R_AddDrawSurf(surfaceType_t* surface, shader_t* shader, int dlightMap) {
tr.refdef.numDrawSurfs++;
}
/*
=================
R_AddSpriteSurf
=================
*/
void R_AddSpriteSurf(surfaceType_t* surface, shader_t* shader, float zDistance)
{
int index;
if (zDistance > MAX_SPRITE_DIST_SQUARED) {
zDistance = MAX_SPRITE_DIST_SQUARED;
}
index = tr.refdef.numSpriteSurfs % MAX_SPRITES;
tr.refdef.spriteSurfs[index].sort = (int)(MAX_SPRITE_DIST_SQUARED - zDistance) | (shader->sortedIndex << QSORT_SHADERNUM_SHIFT);
tr.refdef.spriteSurfs[index].surface = surface;
tr.refdef.numSpriteSurfs++;
}
/*
=================
R_DecomposeSort
@ -1335,7 +1377,7 @@ void R_DecomposeSort(unsigned int sort, int* entityNum, shader_t** shader, int*
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 entityNum;
int dlighted;
@ -1351,39 +1393,49 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
// if we overflowed MAX_DRAWSURFS, the drawsurfs
// wrapped around in the buffer and we will be missing
// the first surfaces, not the last ones
if ( numDrawSurfs > MAX_DRAWSURFS ) {
numDrawSurfs = MAX_DRAWSURFS;
}
// the first surfaces, not the last ones
if (numDrawSurfs > MAX_DRAWSURFS) {
numDrawSurfs = MAX_DRAWSURFS;
}
if (numSpriteSurfs > MAX_SPRITESURFS) {
numSpriteSurfs = MAX_SPRITESURFS;
}
// sort the drawsurfs by sort type, then orientation, then shader
qsortFast (drawSurfs, numDrawSurfs, sizeof(drawSurf_t) );
qsortFast (spriteSurfs, numSpriteSurfs, sizeof(drawSurf_t) );
// check for any pass through drawing, which
// may cause another view to be rendered first
for (i = 0; i < numDrawSurfs; i++) {
R_DecomposeSort((drawSurfs + i)->sort, &entityNum, &shader, &dlighted, &bStaticModel);
R_Sky_Render();
if ( shader->sort > SS_PORTAL ) {
break;
}
if (!tr.viewParms.isPortal)
{
// check for any pass through drawing, which
// may cause another view to be rendered first
for (i = 0; i < numDrawSurfs; i++) {
R_DecomposeSort((drawSurfs + i)->sort, &entityNum, &shader, &dlighted, &bStaticModel);
// no shader should ever have this sort type
if ( shader->sort == SS_BAD ) {
ri.Error (ERR_DROP, "Shader '%s'with sort == SS_BAD", shader->name );
}
// if the mirror was completely clipped away, we may need to check another surface
if ( R_MirrorViewBySurface( (drawSurfs+i), entityNum) ) {
// this is a debug option to see exactly what is being mirrored
if ( r_portalOnly->integer ) {
return;
if (shader->sort > SS_PORTAL) {
break;
}
// no shader should ever have this sort type
if (shader->sort == SS_BAD) {
ri.Error(ERR_DROP, "Shader '%s'with sort == SS_BAD", shader->name);
}
// if the mirror was completely clipped away, we may need to check another surface
if (R_MirrorViewBySurface((drawSurfs + i), entityNum)) {
// this is a debug option to see exactly what is being mirrored
if (r_portalOnly->integer) {
return;
}
break; // only one mirror view at a time
}
break; // only one mirror view at a time
}
}
R_AddDrawSurfCmd( drawSurfs, numDrawSurfs );
R_AddDrawSurfCmd(drawSurfs, numDrawSurfs);
R_AddSpriteSurfCmd(spriteSurfs, numSpriteSurfs);
}
/*
@ -1470,6 +1522,55 @@ void R_AddEntitySurfaces (void) {
}
void R_AddSpriteSurfaces()
{
refSprite_t* sprite;
vec3_t delta;
if (!r_drawsprites->integer) {
return;
}
for (tr.currentSpriteNum = 0; tr.currentSpriteNum < tr.refdef.num_sprites; ++tr.currentSpriteNum)
{
sprite = &tr.refdef.sprites[tr.currentSpriteNum];
if (tr.portalsky.inUse)
{
if ((sprite->renderfx & RF_SKYENTITY) == 0) {
continue;
}
}
else if ((sprite->renderfx & RF_SKYENTITY) != 0)
{
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_ENTITYNUM_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.ori );
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));
}
}
/*
====================
@ -1478,17 +1579,24 @@ R_GenerateDrawSurfs
*/
void R_GenerateDrawSurfs( void ) {
R_AddWorldSurfaces ();
if (!(tr.refdef.rdflags & RDF_NOWORLDMODEL)) {
R_AddSwipeSurfaces();
}
R_AddPolygonSurfaces();
R_AddTerrainMarkSurfaces();
R_AddEntitySurfaces();
R_AddSpriteSurfaces();
// set the projection matrix with the minimum zfar
// now that we have the world bounded
// this needs to be done before entities are
// added, because they use the projection
// matrix for lod calculation
R_SetupProjection ();
R_AddEntitySurfaces ();
}
/*
@ -1641,6 +1749,15 @@ void R_DrawDebugLines(void) {
// FIXME: stub
}
/*
================
R_DrawDebugLines
================
*/
void R_DrawDebugStrings(void) {
// FIXME: stub
}
/*
================
R_RenderView
@ -1651,6 +1768,7 @@ or a mirror / remote location
*/
void R_RenderView (viewParms_t *parms) {
int firstDrawSurf;
int firstSpriteSurf;
if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) {
return;
@ -1663,6 +1781,7 @@ void R_RenderView (viewParms_t *parms) {
tr.viewParms.frameCount = tr.frameCount;
firstDrawSurf = tr.refdef.numDrawSurfs;
firstSpriteSurf = tr.refdef.numSpriteSurfs;
tr.viewCount++;
@ -1673,9 +1792,16 @@ void R_RenderView (viewParms_t *parms) {
R_Sky_Reset();
R_DrawDebugStrings();
R_GenerateDrawSurfs();
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
);
R_DrawDebugLines();
// draw main system development information (surface outlines, etc)
R_DebugGraphics();

View file

@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tiki.h"
int r_firstSceneDrawSurf;
int r_firstSceneSpriteSurf;
int r_numdlights;
int r_firstSceneDlight;
@ -62,6 +63,7 @@ void R_ToggleSmpFrame( void ) {
backEndData[tr.smpFrame]->commands.used = 0;
r_firstSceneDrawSurf = 0;
r_firstSceneSpriteSurf = 0;
r_numdlights = 0;
r_firstSceneDlight = 0;
@ -245,7 +247,31 @@ void RE_AddRefEntityToScene( const refEntity_t *ent, int parentEntityNumber) {
}
void RE_AddRefSpriteToScene(const refEntity_t* ent) {
// FIXME: unimplemented
refSprite_t* spr;
int i;
if (!tr.registered) {
return;
}
if (r_numsprites >= MAX_SPRITES) {
return;
}
spr = &backEndData[tr.smpFrame]->sprites[r_numsprites];
VectorCopy(ent->origin, spr->origin);
spr->surftype = SF_SPRITE;
spr->hModel = ent->hModel;
spr->scale = ent->scale;
spr->renderfx = ent->renderfx;
spr->shaderTime = ent->shaderTime;
AxisCopy(ent->axis, spr->axis);
for (i = 0; i < 4; ++i) {
spr->shaderRGBA[i] = ent->shaderRGBA[i];
}
++r_numsprites;
}
/*
@ -388,6 +414,9 @@ void RE_RenderScene( const refdef_t *fd ) {
tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
tr.refdef.drawSurfs = backEndData[tr.smpFrame]->drawSurfs;
tr.refdef.numSpriteSurfs = r_firstSceneSpriteSurf;
tr.refdef.spriteSurfs = backEndData[tr.smpFrame]->spriteSurfs;
tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
tr.refdef.entities = &backEndData[tr.smpFrame]->entities[r_firstSceneEntity];
@ -456,6 +485,7 @@ void RE_RenderScene( const refdef_t *fd ) {
// the next scene rendered in this frame will tack on after this one
r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
r_firstSceneSpriteSurf = tr.refdef.numSpriteSurfs;
r_firstSceneEntity = r_numentities;
r_firstSceneSprite = r_numsprites;
r_firstSceneDlight = r_numdlights;

View file

@ -56,11 +56,161 @@ sprite_t *SPR_RegisterSprite(const char *name)
return 0;
}
static int CullSprite(const vec3_t* points) {
int i, j;
for (i = 0; i < backEnd.viewParms.fog.extrafrustums + 4; i++) {
for (j = 0; j < 4; j++) {
if (DotProduct(points[j], backEnd.viewParms.frustum[i].normal) - backEnd.viewParms.frustum[i].dist > 0.0f) {
break;
}
}
if (j == 4) {
return CULL_CLIP;
}
}
return CULL_IN;
}
/*
=====================
RB_DrawSprite
=====================
*/
void RB_DrawSprite( const refSprite_t *spr ) {
// FIXME: stub
model_t* model;
vec3_t norm;
vec3_t up, right;
vec3_t points[4];
float org_x, org_y;
float scale;
if (!spr->hModel)
{
ri.Printf(PRINT_WARNING, "No model found for Sprite\n");
return;
}
model = tr.models;
if (spr->hModel > 0 && spr->hModel < tr.numModels) {
model = &tr.models[spr->hModel];
}
scale = spr->scale * model->d.sprite->scale;
switch (model->d.sprite->shader->sprite.type)
{
case SPRITE_PARALLEL_ORIENTED:
{
float invmag;
float cr, sr;
int i;
invmag = 1.0 / sqrt(spr->axis[1][2] * spr->axis[1][2] + spr->axis[1][1] * spr->axis[1][1]);
cr = invmag * spr->axis[1][1];
sr = invmag * spr->axis[1][2];
for (i = 0; i < 3; i++)
{
up[i] = backEnd.viewParms.ori.axis[2][i] * cr - backEnd.viewParms.ori.axis[1][i] * sr;
right[i] = backEnd.viewParms.ori.axis[1][i] * cr + backEnd.viewParms.ori.axis[2][i] * sr;
}
}
break;
case SPRITE_PARALLEL:
VectorCopy(backEnd.viewParms.ori.axis[2], up);
if (!backEnd.viewParms.isMirror) {
VectorNegate(backEnd.viewParms.ori.axis[1], right);
} else {
VectorCopy(backEnd.viewParms.ori.axis[1], right);
}
break;
case SPRITE_ORIENTED:
VectorCopy(spr->axis[1], right);
VectorCopy(spr->axis[2], up);
break;
case SPRITE_PARALLEL_UPRIGHT:
VectorCopy(backEnd.viewParms.ori.axis[0], norm);
VectorCopy(backEnd.viewParms.ori.axis[1], right);
VectorCopy(backEnd.viewParms.ori.axis[2], up);
if (backEnd.viewParms.ori.axis[0][2] > 0.999) {
return;
} else if (backEnd.viewParms.ori.axis[0][2] < -0.999) {
return;
}
VectorSet(up, 0.0f, 0.0f, 1.0f);
VectorSet(right, backEnd.viewParms.ori.axis[0][1], -backEnd.viewParms.ori.axis[0][0], 0.0f);
VectorNormalize(right);
VectorSet(norm, -right[1], right[0], 0.0f);
break;
}
org_x = model->d.sprite->origin_x * scale;
org_y = model->d.sprite->origin_y * scale;
VectorScale(up, org_y, up);
VectorScale(right, org_x, right);
points[0][0] = spr->origin[0] + up[0] - right[0];
points[1][0] = spr->origin[0] + up[0] + right[0];
points[2][0] = spr->origin[0] - up[0] - right[0];
points[3][0] = spr->origin[0] - up[0] + right[0];
points[0][1] = spr->origin[1] + up[1] - right[1];
points[1][1] = spr->origin[1] + up[1] + right[1];
points[2][1] = spr->origin[1] - up[1] - right[1];
points[3][1] = spr->origin[1] - up[1] + right[1];
points[0][2] = spr->origin[2] + up[2] - right[2];
points[1][2] = spr->origin[2] + up[2] + right[2];
points[2][2] = spr->origin[2] - up[2] - right[2];
points[3][2] = spr->origin[2] - up[2] + right[2];
if (CullSprite(points) == CULL_OUT) {
return;
}
RB_CHECKOVERFLOW(4, 6);
memcpy(tess.vertexColors[tess.numVertexes], spr->shaderRGBA, sizeof(byte) * 4);
memcpy(tess.vertexColors[tess.numVertexes + 1], spr->shaderRGBA, sizeof(byte) * 4);
memcpy(tess.vertexColors[tess.numVertexes + 2], spr->shaderRGBA, sizeof(byte) * 4);
memcpy(tess.vertexColors[tess.numVertexes + 3], spr->shaderRGBA, sizeof(byte) * 4);
tess.vertexColorValid = qtrue;
tess.texCoords[tess.numVertexes][0][0] = 0.0f;
tess.texCoords[tess.numVertexes][0][1] = 0.0f;
tess.texCoords[tess.numVertexes + 1][0][0] = 1.0f;
tess.texCoords[tess.numVertexes + 1][0][1] = 0.0f;
tess.texCoords[tess.numVertexes + 2][0][0] = 0.0f;
tess.texCoords[tess.numVertexes + 2][0][1] = 1.0f;
tess.texCoords[tess.numVertexes + 3][0][0] = 1.0f;
tess.texCoords[tess.numVertexes + 3][0][1] = 1.0f;
tess.xyz[tess.numVertexes][0] = points[0][0];
tess.xyz[tess.numVertexes][1] = points[0][1];
tess.xyz[tess.numVertexes][2] = points[0][2];
tess.xyz[tess.numVertexes + 1][0] = points[1][0];
tess.xyz[tess.numVertexes + 1][1] = points[1][1];
tess.xyz[tess.numVertexes + 1][2] = points[1][2];
tess.xyz[tess.numVertexes + 2][0] = points[2][0];
tess.xyz[tess.numVertexes + 2][1] = points[2][1];
tess.xyz[tess.numVertexes + 2][2] = points[2][2];
tess.xyz[tess.numVertexes + 3][0] = points[3][0];
tess.xyz[tess.numVertexes + 3][1] = points[3][1];
tess.xyz[tess.numVertexes + 3][2] = points[3][2];
tess.indexes[tess.numIndexes] = tess.numVertexes + 2;
tess.indexes[tess.numIndexes + 1] = tess.numVertexes + 1;
tess.indexes[tess.numIndexes + 2] = tess.numVertexes;
tess.indexes[tess.numIndexes + 3] = tess.numVertexes + 2;
tess.indexes[tess.numIndexes + 4] = tess.numVertexes + 3;
tess.indexes[tess.numIndexes + 5] = tess.numVertexes + 1;
tess.numVertexes += 4;
tess.numIndexes += 6;
}