mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 19:45:05 +08:00
496 lines
9.6 KiB
C
496 lines
9.6 KiB
C
/*
|
|
gu_triapi.c - TriAPI draw methods
|
|
Copyright (C) 2011 Uncle Mike
|
|
Copyright (C) 2019 a1batross
|
|
Copyright (C) 2021 Sergey Galushko
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
*/
|
|
|
|
#include "gu_local.h"
|
|
#include "const.h"
|
|
|
|
static struct
|
|
{
|
|
int renderMode; // override kRenderMode from TriAPI
|
|
vec4_t triRGBA;
|
|
} ds;
|
|
|
|
static struct
|
|
{
|
|
byte *start;
|
|
byte *end;
|
|
int count;
|
|
int prim;
|
|
uint flags;
|
|
float lastTexCord[2];
|
|
uint lastColor;
|
|
}triContext = { 0 };
|
|
|
|
/*
|
|
===============================================================
|
|
|
|
TRIAPI IMPLEMENTATION
|
|
|
|
===============================================================
|
|
*/
|
|
|
|
/*
|
|
=============
|
|
TriRenderMode
|
|
|
|
set rendermode
|
|
=============
|
|
*/
|
|
void TriRenderMode( int mode )
|
|
{
|
|
ds.renderMode = mode;
|
|
switch( mode )
|
|
{
|
|
case kRenderNormal:
|
|
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
|
sceGuDisable( GU_BLEND );
|
|
sceGuDepthMask( GU_FALSE );
|
|
break;
|
|
case kRenderTransAlpha:
|
|
sceGuEnable( GU_BLEND );
|
|
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
|
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
|
sceGuDepthMask( GU_TRUE );
|
|
break;
|
|
case kRenderTransColor:
|
|
case kRenderTransTexture:
|
|
sceGuEnable( GU_BLEND );
|
|
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
|
break;
|
|
case kRenderGlow:
|
|
case kRenderTransAdd:
|
|
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, GUBLEND1 );
|
|
sceGuEnable( GU_BLEND );
|
|
sceGuDepthMask( GU_TRUE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriBegin
|
|
|
|
begin triangle sequence
|
|
=============
|
|
*/
|
|
void TriBegin( int mode )
|
|
{
|
|
switch( mode )
|
|
{
|
|
case TRI_POINTS:
|
|
triContext.prim = GU_POINTS;
|
|
break;
|
|
case TRI_TRIANGLES:
|
|
triContext.prim = GU_TRIANGLES;
|
|
break;
|
|
case TRI_TRIANGLE_FAN:
|
|
triContext.prim = GU_TRIANGLE_FAN;
|
|
break;
|
|
case TRI_QUADS:
|
|
triContext.prim = GU_TRIANGLE_FAN;
|
|
break;
|
|
case TRI_LINES:
|
|
triContext.prim = GU_LINES;
|
|
break;
|
|
case TRI_TRIANGLE_STRIP:
|
|
triContext.prim = GU_TRIANGLE_STRIP;
|
|
break;
|
|
case TRI_QUAD_STRIP:
|
|
triContext.prim = GU_TRIANGLE_STRIP;
|
|
break;
|
|
case TRI_POLYGON:
|
|
default:
|
|
triContext.prim = GU_TRIANGLE_FAN;
|
|
break;
|
|
}
|
|
|
|
triContext.start = extGuBeginPacket( NULL );
|
|
triContext.end = triContext.start;
|
|
triContext.count = 0;
|
|
triContext.flags = 0;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriEnd
|
|
|
|
draw triangle sequence
|
|
=============
|
|
*/
|
|
void TriEnd( void )
|
|
{
|
|
if( !triContext.start || triContext.count == 0 )
|
|
return;
|
|
|
|
extGuEndPacket(( void* )triContext.end );
|
|
sceGuDrawArray( triContext.prim, triContext.flags, triContext.count, 0, triContext.start );
|
|
|
|
triContext.start = NULL;
|
|
triContext.end = NULL;
|
|
triContext.count = 0;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
_TriColor4f
|
|
|
|
=============
|
|
*/
|
|
void _TriColor4f( float r, float g, float b, float a )
|
|
{
|
|
if( triContext.start )
|
|
{
|
|
if( triContext.count > 0 && !( triContext.flags & GU_COLOR_8888 ))
|
|
return;
|
|
|
|
triContext.flags |= GU_COLOR_8888;
|
|
triContext.lastColor = GUCOLOR4F( r, g, b, a );
|
|
}
|
|
else sceGuColor( GUCOLOR4F( r, g, b, a ));
|
|
}
|
|
|
|
/*
|
|
=============
|
|
_TriColor4ub
|
|
|
|
=============
|
|
*/
|
|
void _TriColor4ub( byte r, byte g, byte b, byte a )
|
|
{
|
|
if( triContext.start )
|
|
{
|
|
if( triContext.count > 0 && !( triContext.flags & GU_COLOR_8888 ))
|
|
return;
|
|
|
|
triContext.flags |= GU_COLOR_8888;
|
|
triContext.lastColor = GUCOLOR4UB( r, g, b, a );
|
|
}
|
|
else sceGuColor( GUCOLOR4UB( r, g, b, a ));
|
|
}
|
|
|
|
|
|
/*
|
|
=============
|
|
TriColor4ub
|
|
|
|
=============
|
|
*/
|
|
void TriColor4ub( byte r, byte g, byte b, byte a )
|
|
{
|
|
ds.triRGBA[0] = r * (1.0f / 255.0f);
|
|
ds.triRGBA[1] = g * (1.0f / 255.0f);
|
|
ds.triRGBA[2] = b * (1.0f / 255.0f);
|
|
ds.triRGBA[3] = a * (1.0f / 255.0f);
|
|
|
|
_TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], 1.0f );
|
|
}
|
|
|
|
/*
|
|
=================
|
|
TriColor4f
|
|
=================
|
|
*/
|
|
void TriColor4f( float r, float g, float b, float a )
|
|
{
|
|
if( ds.renderMode == kRenderTransAlpha )
|
|
TriColor4ub( r * 255.0f, g * 255.0f, b * 255.0f, a * 255.0f );
|
|
else _TriColor4f( r * a, g * a, b * a, 1.0 );
|
|
|
|
ds.triRGBA[0] = r;
|
|
ds.triRGBA[1] = g;
|
|
ds.triRGBA[2] = b;
|
|
ds.triRGBA[3] = a;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriTexCoord2f
|
|
|
|
=============
|
|
*/
|
|
void TriTexCoord2f( float u, float v )
|
|
{
|
|
if( !triContext.start )
|
|
return;
|
|
|
|
if( triContext.count > 0 && !( triContext.flags & GU_TEXTURE_32BITF ))
|
|
return;
|
|
|
|
triContext.flags |= GU_TEXTURE_32BITF;
|
|
triContext.lastTexCord[0] = u;
|
|
triContext.lastTexCord[1] = v;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriVertex3fv
|
|
|
|
=============
|
|
*/
|
|
void TriVertex3fv( const float *v )
|
|
{
|
|
if( !triContext.start )
|
|
return;
|
|
|
|
if( triContext.flags & GU_TEXTURE_32BITF )
|
|
{
|
|
*( float* )triContext.end = triContext.lastTexCord[0];
|
|
triContext.end += sizeof( float );
|
|
*( float* )triContext.end = triContext.lastTexCord[1];
|
|
triContext.end += sizeof( float );
|
|
}
|
|
|
|
if( triContext.flags & GU_COLOR_8888 )
|
|
{
|
|
*( uint* )triContext.end = triContext.lastColor;
|
|
triContext.end += sizeof( uint );
|
|
}
|
|
|
|
triContext.flags |= GU_VERTEX_32BITF;
|
|
*( float* )triContext.end = v[0];
|
|
triContext.end += sizeof( float );
|
|
*( float* )triContext.end = v[1];
|
|
triContext.end += sizeof( float );
|
|
*( float* )triContext.end = v[2];
|
|
triContext.end += sizeof( float );
|
|
|
|
triContext.count++;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriVertex3f
|
|
|
|
=============
|
|
*/
|
|
void TriVertex3f( float x, float y, float z )
|
|
{
|
|
if( !triContext.start )
|
|
return;
|
|
|
|
if( triContext.flags & GU_TEXTURE_32BITF )
|
|
{
|
|
*( float* )triContext.end = triContext.lastTexCord[0];
|
|
triContext.end += sizeof( float );
|
|
*( float* )triContext.end = triContext.lastTexCord[1];
|
|
triContext.end += sizeof( float );
|
|
}
|
|
|
|
if( triContext.flags & GU_COLOR_8888 )
|
|
{
|
|
*( uint* )triContext.end = triContext.lastColor;
|
|
triContext.end += sizeof( uint );
|
|
}
|
|
|
|
triContext.flags |= GU_VERTEX_32BITF;
|
|
*( float* )triContext.end = x;
|
|
triContext.end += sizeof( float );
|
|
*( float* )triContext.end = y;
|
|
triContext.end += sizeof( float );
|
|
*( float* )triContext.end = z;
|
|
triContext.end += sizeof( float );
|
|
|
|
triContext.count++;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriWorldToScreen
|
|
|
|
convert world coordinates (x,y,z) into screen (x, y)
|
|
=============
|
|
*/
|
|
int TriWorldToScreen( const float *world, float *screen )
|
|
{
|
|
int retval;
|
|
|
|
retval = R_WorldToScreen( world, screen );
|
|
|
|
screen[0] = 0.5f * screen[0] * (float)RI.viewport[2];
|
|
screen[1] = -0.5f * screen[1] * (float)RI.viewport[3];
|
|
screen[0] += 0.5f * (float)RI.viewport[2];
|
|
screen[1] += 0.5f * (float)RI.viewport[3];
|
|
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriSpriteTexture
|
|
|
|
bind current texture
|
|
=============
|
|
*/
|
|
int TriSpriteTexture( model_t *pSpriteModel, int frame )
|
|
{
|
|
int gl_texturenum;
|
|
|
|
if(( gl_texturenum = R_GetSpriteTexture( pSpriteModel, frame )) == 0 )
|
|
return 0;
|
|
|
|
if( gl_texturenum <= 0 || gl_texturenum > MAX_TEXTURES )
|
|
gl_texturenum = tr.defaultTexture;
|
|
|
|
GL_Bind( XASH_TEXTURE0, gl_texturenum );
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriFog
|
|
|
|
enables global fog on the level
|
|
=============
|
|
*/
|
|
void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn )
|
|
{
|
|
// overrided by internal fog
|
|
if( RI.fogEnabled ) return;
|
|
RI.fogCustom = bOn;
|
|
|
|
// check for invalid parms
|
|
if( flEnd <= flStart )
|
|
{
|
|
glState.isFogEnabled = RI.fogCustom = false;
|
|
#if 1
|
|
sceGuDisable( GU_FOG );
|
|
#else
|
|
pglDisable( GL_FOG );
|
|
#endif
|
|
return;
|
|
}
|
|
#if 1
|
|
if( RI.fogCustom )
|
|
sceGuEnable( GU_FOG );
|
|
else sceGuDisable( GU_FOG );
|
|
#else
|
|
if( RI.fogCustom )
|
|
pglEnable( GL_FOG );
|
|
else pglDisable( GL_FOG );
|
|
#endif
|
|
// copy fog params
|
|
RI.fogColor[0] = flFogColor[0] / 255.0f;
|
|
RI.fogColor[1] = flFogColor[1] / 255.0f;
|
|
RI.fogColor[2] = flFogColor[2] / 255.0f;
|
|
RI.fogStart = flStart;
|
|
RI.fogColor[3] = 1.0f;
|
|
RI.fogDensity = 0.0f;
|
|
RI.fogSkybox = true;
|
|
RI.fogEnd = flEnd;
|
|
|
|
#if 1
|
|
printf("TRI FOG: s %f e %f c %f %f %f %f \n", RI.fogStart, RI.fogEnd,
|
|
RI.fogColor[0], RI.fogColor[1], RI.fogColor[2], RI.fogColor[3] );
|
|
|
|
//glState.fogDensity = RI.fogDensity
|
|
glState.fogColor = GUCOLOR4F( RI.fogColor[0], RI.fogColor[1], RI.fogColor[2], glState.fogDensity );
|
|
glState.fogStart = RI.fogStart;
|
|
glState.fogEnd = RI.fogEnd;
|
|
|
|
sceGuFog( glState.fogStart, glState.fogEnd, glState.fogColor );
|
|
#else
|
|
pglFogi( GL_FOG_MODE, GL_LINEAR );
|
|
pglFogfv( GL_FOG_COLOR, RI.fogColor );
|
|
pglFogf( GL_FOG_START, RI.fogStart );
|
|
pglFogf( GL_FOG_END, RI.fogEnd );
|
|
pglHint( GL_FOG_HINT, GL_NICEST );
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriGetMatrix
|
|
|
|
very strange export
|
|
=============
|
|
*/
|
|
void TriGetMatrix( const int pname, float *matrix )
|
|
{
|
|
#if 1
|
|
printf("%s:%i:%s - Not implemented\n", __FILE__, __LINE__, __FUNCTION__ );
|
|
#else
|
|
pglGetFloatv( pname, matrix );
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriForParams
|
|
|
|
=============
|
|
*/
|
|
void TriFogParams( float flDensity, int iFogSkybox )
|
|
{
|
|
RI.fogDensity = flDensity;
|
|
RI.fogSkybox = iFogSkybox;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriCullFace
|
|
|
|
=============
|
|
*/
|
|
void TriCullFace( TRICULLSTYLE mode )
|
|
{
|
|
int glMode;
|
|
|
|
switch( mode )
|
|
{
|
|
case TRI_FRONT:
|
|
glMode = GL_FRONT;
|
|
break;
|
|
default:
|
|
glMode = GL_NONE;
|
|
break;
|
|
}
|
|
|
|
GL_Cull( mode );
|
|
}
|
|
|
|
/*
|
|
=============
|
|
TriBrightness
|
|
=============
|
|
*/
|
|
void TriBrightness( float brightness )
|
|
{
|
|
float r, g, b;
|
|
|
|
r = ds.triRGBA[0] * ds.triRGBA[3] * brightness;
|
|
g = ds.triRGBA[1] * ds.triRGBA[3] * brightness;
|
|
b = ds.triRGBA[2] * ds.triRGBA[3] * brightness;
|
|
|
|
_TriColor4f( r, g, b, 1.0f );
|
|
}
|
|
|
|
unsigned int getTriBrightness( float brightness )
|
|
{
|
|
vec3_t color;
|
|
|
|
if(brightness < 0.0f) return 0;
|
|
|
|
color[0] = ds.triRGBA[0] * ds.triRGBA[3] * brightness;
|
|
color[1] = ds.triRGBA[1] * ds.triRGBA[3] * brightness;
|
|
color[2] = ds.triRGBA[2] * ds.triRGBA[3] * brightness;
|
|
|
|
VectorNormalizeFast( color );
|
|
|
|
return GUCOLOR3FV( color );
|
|
}
|