Port r_studio_drawelements render

This commit is contained in:
mittorn 2019-02-07 02:36:34 +07:00
parent bccc0e63d5
commit d913ef0fc4
1 changed files with 304 additions and 21 deletions

View File

@ -102,13 +102,22 @@ typedef struct
vec4_t lightpos[MAXSTUDIOVERTS][MAX_LOCALLIGHTS];
vec3_t lightbonepos[MAXSTUDIOBONES][MAX_LOCALLIGHTS];
float locallightR2[MAX_LOCALLIGHTS];
// drawelements renderer
vec3_t arrayverts[MAXSTUDIOVERTS];
vec2_t arraycoord[MAXSTUDIOVERTS];
unsigned short arrayelems[MAXSTUDIOVERTS*6];
GLubyte arraycolor[MAXSTUDIOVERTS][4];
uint numverts;
uint numelems;
} studio_draw_state_t;
// studio-related cvars
convar_t *r_studio_sort_textures;
convar_t *r_drawviewmodel;
static convar_t *r_studio_sort_textures;
static convar_t *r_drawviewmodel;
convar_t *cl_righthand = NULL;
convar_t *cl_himodels;
static convar_t *cl_himodels;
static convar_t *r_studio_drawelements;
static r_studio_interface_t *pStudioDraw;
static studio_draw_state_t g_studio; // global studio state
@ -135,6 +144,7 @@ void R_StudioInit( void )
cl_himodels = Cvar_Get( "cl_himodels", "1", FCVAR_ARCHIVE, "draw high-resolution player models in multiplayer" );
r_studio_sort_textures = Cvar_Get( "r_studio_sort_textures", "0", FCVAR_ARCHIVE, "change draw order for additive meshes" );
r_drawviewmodel = Cvar_Get( "r_drawviewmodel", "1", 0, "draw firstperson weapon model" );
r_studio_drawelements = Cvar_Get( "r_studio_drawelements", "1", FCVAR_ARCHIVE, "use glDrawElements for studiomodels" );
Matrix3x4_LoadIdentity( g_studio.rotationmatrix );
Cvar_RegisterVariable( &r_glowshellfreq );
@ -1723,7 +1733,7 @@ R_LightLambert
====================
*/
void R_LightLambert( vec4_t light[MAX_LOCALLIGHTS], vec3_t normal, vec3_t color )
void R_LightLambert( vec4_t light[MAX_LOCALLIGHTS], vec3_t normal, vec3_t color, byte *out )
{
vec3_t finalLight;
vec3_t localLight;
@ -1761,7 +1771,53 @@ void R_LightLambert( vec4_t light[MAX_LOCALLIGHTS], vec3_t normal, vec3_t color
}
}
pglColor4f( finalLight[0], finalLight[1], finalLight[2], tr.blend );
out[0] = finalLight[0] * 255;
out[1] = finalLight[1] * 255;
out[2] = finalLight[2] * 255;
}
static void R_StudioSetColorBegin(short *ptricmds, vec3_t *pstudionorms )
{
float *lv = (float *)g_studio.lightvalues[ptricmds[1]];
rgba_t color;
if( g_studio.numlocallights )
{
color[3] = tr.blend * 255;
R_LightLambert( g_studio.lightpos[ptricmds[0]], pstudionorms[ptricmds[1]], lv, color );
pglColor4ubv( color );
}
else
{
if( RI.currententity->curstate.rendermode == kRenderTransColor )
{
color[3] = tr.blend * 255;
VectorCopy( (byte*)&RI.currententity->curstate.rendercolor, color );
pglColor4ubv( color );
}
else pglColor4f( lv[0], lv[1], lv[2], tr.blend );
}
}
static void R_StudioSetColorArray(short *ptricmds, vec3_t *pstudionorms, byte *color )
{
float *lv = (float *)g_studio.lightvalues[ptricmds[1]];
color[3] = tr.blend * 255;
if( g_studio.numlocallights )
R_LightLambert( g_studio.lightpos[ptricmds[0]], pstudionorms[ptricmds[1]], lv, color );
else
{
if( RI.currententity->curstate.rendermode == kRenderTransColor )
VectorCopy( (byte*)&RI.currententity->curstate.rendercolor, color );
else
{
color[0] = lv[0] * 255;
color[1] = lv[1] * 255;
color[2] = lv[2] * 255;
}
}
}
/*
@ -1934,11 +1990,8 @@ _inline void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, floa
for( ; i > 0; i--, ptricmds += 4 )
{
lv = (float *)g_studio.lightvalues[ptricmds[1]];
R_StudioSetColorBegin( ptricmds, pstudionorms );
if( g_studio.numlocallights )
R_LightLambert( g_studio.lightpos[ptricmds[0]], pstudionorms[ptricmds[1]], lv );
else pglColor4f( lv[0], lv[1], lv[2], tr.blend );
pglTexCoord2f( ptricmds[2] * s, ptricmds[3] * t );
pglVertex3fv( g_studio.verts[ptricmds[0]] );
}
@ -1970,10 +2023,7 @@ _inline void R_StudioDrawFloatMesh( short *ptricmds, vec3_t *pstudionorms )
for( ; i > 0; i--, ptricmds += 4 )
{
lv = (float *)g_studio.lightvalues[ptricmds[1]];
if( g_studio.numlocallights )
R_LightLambert( g_studio.lightpos[ptricmds[0]], pstudionorms[ptricmds[1]], lv );
else pglColor4f( lv[0], lv[1], lv[2], tr.blend );
R_StudioSetColorBegin( ptricmds, pstudionorms );
pglTexCoord2f( HalfToFloat( ptricmds[2] ), HalfToFloat( ptricmds[3] ));
pglVertex3fv( g_studio.verts[ptricmds[0]] );
}
@ -2009,10 +2059,13 @@ _inline void R_StudioDrawChromeMesh( short *ptricmds, vec3_t *pstudionorms, floa
{
if( glowShell )
{
color24 *clr = &RI.currententity->curstate.rendercolor;
idx = g_studio.normaltable[ptricmds[0]];
av = g_studio.verts[ptricmds[0]];
lv = g_studio.norms[ptricmds[0]];
VectorMA( av, scale, lv, vert );
pglColor4ub( clr->r, clr->g, clr->b, 255 );
pglTexCoord2f( g_studio.chrome[idx][0] * s, g_studio.chrome[idx][1] * t );
pglVertex3fv( vert );
}
@ -2020,9 +2073,7 @@ _inline void R_StudioDrawChromeMesh( short *ptricmds, vec3_t *pstudionorms, floa
{
idx = ptricmds[1];
lv = (float *)g_studio.lightvalues[ptricmds[1]];
if( g_studio.numlocallights )
R_LightLambert( g_studio.lightpos[ptricmds[0]], pstudionorms[ptricmds[1]], lv );
else pglColor4f( lv[0], lv[1], lv[2], tr.blend );
R_StudioSetColorBegin( ptricmds, pstudionorms );
pglTexCoord2f( g_studio.chrome[idx][0] * s, g_studio.chrome[idx][1] * t );
pglVertex3fv( g_studio.verts[ptricmds[0]] );
}
@ -2032,6 +2083,220 @@ _inline void R_StudioDrawChromeMesh( short *ptricmds, vec3_t *pstudionorms, floa
}
}
_inline int R_StudioBuildIndices( qboolean tri_strip, int vertexState )
{
// build in indices
if( vertexState++ < 3 )
{
g_studio.arrayelems[g_studio.numelems++] = g_studio.numverts;
}
else if( tri_strip )
{
// flip triangles between clockwise and counter clockwise
if( vertexState & 1 )
{
// draw triangle [n-2 n-1 n]
g_studio.arrayelems[g_studio.numelems++] = g_studio.numverts - 2;
g_studio.arrayelems[g_studio.numelems++] = g_studio.numverts - 1;
g_studio.arrayelems[g_studio.numelems++] = g_studio.numverts;
}
else
{
// draw triangle [n-1 n-2 n]
g_studio.arrayelems[g_studio.numelems++] = g_studio.numverts - 1;
g_studio.arrayelems[g_studio.numelems++] = g_studio.numverts - 2;
g_studio.arrayelems[g_studio.numelems++] = g_studio.numverts;
}
}
else
{
// draw triangle fan [0 n-1 n]
g_studio.arrayelems[g_studio.numelems++] = g_studio.numverts - ( vertexState - 1 );
g_studio.arrayelems[g_studio.numelems++] = g_studio.numverts - 1;
g_studio.arrayelems[g_studio.numelems++] = g_studio.numverts;
}
return vertexState;
}
/*
===============
R_StudioDrawNormalMesh
generic path
===============
*/
_inline void R_StudioBuildArrayNormalMesh( short *ptricmds, vec3_t *pstudionorms, float s, float t )
{
float *lv;
int i;
float alpha = tr.blend;
while( i = *( ptricmds++ ))
{
int vertexState = 0;
qboolean tri_strip = true;
if( i < 0 )
{
tri_strip = false;
i = -i;
}
for( ; i > 0; i--, ptricmds += 4 )
{
GLubyte *cl;
cl = g_studio.arraycolor[g_studio.numverts];
lv = (float *)g_studio.lightvalues[ptricmds[1]];
vertexState = R_StudioBuildIndices( tri_strip, vertexState );
R_StudioSetColorArray( ptricmds, pstudionorms, cl );
g_studio.arraycoord[g_studio.numverts][0] = ptricmds[2] * s;
g_studio.arraycoord[g_studio.numverts][1] = ptricmds[3] * t;
VectorCopy( g_studio.verts[ptricmds[0]], g_studio.arrayverts[g_studio.numverts] );
g_studio.numverts++;
}
}
}
/*
===============
R_StudioDrawNormalMesh
generic path
===============
*/
_inline void R_StudioBuildArrayFloatMesh( short *ptricmds, vec3_t *pstudionorms )
{
float *lv;
int i;
float alpha = tr.blend;
while( i = *( ptricmds++ ))
{
int vertexState = 0;
qboolean tri_strip = true;
if( i < 0 )
{
tri_strip = false;
i = -i;
}
for( ; i > 0; i--, ptricmds += 4 )
{
GLubyte *cl;
cl = g_studio.arraycolor[g_studio.numverts];
lv = (float *)g_studio.lightvalues[ptricmds[1]];
vertexState = R_StudioBuildIndices( tri_strip, vertexState );
R_StudioSetColorArray( ptricmds, pstudionorms, cl );
g_studio.arraycoord[g_studio.numverts][0] = HalfToFloat( ptricmds[2] );
g_studio.arraycoord[g_studio.numverts][1] = HalfToFloat( ptricmds[3] );
VectorCopy( g_studio.verts[ptricmds[0]], g_studio.arrayverts[g_studio.numverts] );
g_studio.numverts++;
}
}
}
/*
===============
R_StudioDrawNormalMesh
generic path
===============
*/
_inline void R_StudioBuildArrayChromeMesh( short *ptricmds, vec3_t *pstudionorms, float s, float t, float scale )
{
float *lv, *av;
int i, idx;
qboolean glowShell = (scale > 0.0f) ? true : false;
vec3_t vert;
float alpha = tr.blend;
while( i = *( ptricmds++ ))
{
int vertexState = 0;
qboolean tri_strip = true;
if( i < 0 )
{
tri_strip = false;
i = -i;
}
for( ; i > 0; i--, ptricmds += 4 )
{
GLubyte *cl;
cl = g_studio.arraycolor[g_studio.numverts];
lv = (float *)g_studio.lightvalues[ptricmds[1]];
vertexState = R_StudioBuildIndices( tri_strip, vertexState );
if( glowShell )
{
idx = g_studio.normaltable[ptricmds[0]];
av = g_studio.verts[ptricmds[0]];
lv = g_studio.norms[ptricmds[0]];
cl[0] = RI.currententity->curstate.rendercolor.r;
cl[1] = RI.currententity->curstate.rendercolor.g;
cl[2] = RI.currententity->curstate.rendercolor.b;
cl[3] = 255;
VectorMA( av, scale, lv, vert );
VectorCopy( vert, g_studio.arrayverts[g_studio.numverts] );
}
else
{
idx = ptricmds[1];
R_StudioSetColorArray( ptricmds, pstudionorms, cl );
VectorCopy( g_studio.verts[ptricmds[0]], g_studio.arrayverts[g_studio.numverts] );
}
g_studio.arraycoord[g_studio.numverts][0] = g_studio.chrome[idx][0] * s;
g_studio.arraycoord[g_studio.numverts][1] = g_studio.chrome[idx][1] * t;
g_studio.numverts++;
}
}
}
_inline void R_StudioDrawArrays( uint startverts, uint startelems )
{
pglEnableClientState( GL_VERTEX_ARRAY );
pglVertexPointer( 3, GL_FLOAT, 12, g_studio.arrayverts );
pglEnableClientState( GL_TEXTURE_COORD_ARRAY );
pglTexCoordPointer( 2, GL_FLOAT, 0, g_studio.arraycoord );
if( !( g_nForceFaceFlags & STUDIO_NF_CHROME ) )
{
pglEnableClientState( GL_COLOR_ARRAY );
pglColorPointer( 4, GL_UNSIGNED_BYTE, 0, g_studio.arraycolor );
}
#if !defined XASH_NANOGL || defined XASH_WES && defined __EMSCRIPTEN__ // WebGL need to know array sizes
if( pglDrawRangeElements )
pglDrawRangeElements( GL_TRIANGLES, startverts, g_studio.numverts,
g_studio.numelems - startelems, GL_UNSIGNED_SHORT, &g_studio.arrayelems[startelems] );
else
#endif
pglDrawElements( GL_TRIANGLES, g_studio.numelems - startelems, GL_UNSIGNED_SHORT, &g_studio.arrayelems[startelems] );
pglDisableClientState( GL_VERTEX_ARRAY );
pglDisableClientState( GL_TEXTURE_COORD_ARRAY );
if( !( g_nForceFaceFlags & STUDIO_NF_CHROME ) )
pglDisableClientState( GL_COLOR_ARRAY );
}
/*
===============
R_StudioDrawPoints
@ -2054,6 +2319,9 @@ static void R_StudioDrawPoints( void )
if( !m_pStudioHeader ) return;
g_studio.numverts = g_studio.numelems = 0;
// safety bounding the skinnum
m_skinnum = bound( 0, RI.currententity->curstate.skin, ( m_pStudioHeader->numskinfamilies - 1 ));
ptexture = (mstudiotexture_t *)((byte *)m_pStudioHeader + m_pStudioHeader->textureindex);
@ -2151,6 +2419,8 @@ static void R_StudioDrawPoints( void )
for( j = 0; j < m_pSubModel->nummesh; j++ )
{
float oldblend = tr.blend;
uint startArrayVerts = g_studio.numverts;
uint startArrayElems = g_studio.numelems;
short *ptricmds;
float s, t;
@ -2184,11 +2454,24 @@ static void R_StudioDrawPoints( void )
R_StudioSetupSkin( m_pStudioHeader, pskinref[pmesh->skinref] );
if( FBitSet( g_nFaceFlags, STUDIO_NF_CHROME ))
R_StudioDrawChromeMesh( ptricmds, pstudionorms, s, t, shellscale );
else if( FBitSet( g_nFaceFlags, STUDIO_NF_UV_COORDS ))
R_StudioDrawFloatMesh( ptricmds, pstudionorms );
else R_StudioDrawNormalMesh( ptricmds, pstudionorms, s, t );
if( CVAR_TO_BOOL(r_studio_drawelements) )
{
if( FBitSet( g_nFaceFlags, STUDIO_NF_CHROME ))
R_StudioBuildArrayChromeMesh( ptricmds, pstudionorms, s, t, shellscale );
else if( FBitSet( g_nFaceFlags, STUDIO_NF_UV_COORDS ))
R_StudioBuildArrayFloatMesh( ptricmds, pstudionorms );
else R_StudioBuildArrayNormalMesh( ptricmds, pstudionorms, s, t );
R_StudioDrawArrays( startArrayVerts, startArrayElems );
}
else
{
if( FBitSet( g_nFaceFlags, STUDIO_NF_CHROME ))
R_StudioDrawChromeMesh( ptricmds, pstudionorms, s, t, shellscale );
else if( FBitSet( g_nFaceFlags, STUDIO_NF_UV_COORDS ))
R_StudioDrawFloatMesh( ptricmds, pstudionorms );
else R_StudioDrawNormalMesh( ptricmds, pstudionorms, s, t );
}
if( FBitSet( g_nFaceFlags, STUDIO_NF_MASKED ))
{