📄 r_glide.c
字号:
{
FBITFIELD Xor;
if (!grPreviousContext) {
DBG_Printf ("HWRAPI SetBlend() : display not set\n");
return;
}
// Detect changes in the blending modes.
Xor = CurrentPolyFlags^PolyFlags;
if( !Xor )
return;
if( Xor&(PF_Blending) ) // if blending mode must be changed
{
switch(PolyFlags & PF_Blending) {
case PF_Translucent & PF_Blending:
grAlphaBlendFunction (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA,
GR_BLEND_ONE , GR_BLEND_ZERO );
break;
case PF_Masked & PF_Blending:
// no alpha blending
grAlphaBlendFunction(GR_BLEND_SRC_ALPHA, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
break;
case PF_Additive & PF_Blending:
// blend destination for transparency, but no source for additive
grAlphaBlendFunction(GR_BLEND_SRC_ALPHA, GR_BLEND_ONE, GR_BLEND_ONE, GR_BLEND_ZERO);
break;
case PF_Environment & PF_Blending:
grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ONE_MINUS_SRC_ALPHA,
GR_BLEND_ONE, GR_BLEND_ZERO );
break;
case PF_Substractive & PF_Blending:
// not realy but what else ?
grAlphaBlendFunction (GR_BLEND_ZERO, GR_BLEND_ONE_MINUS_SRC_COLOR,
GR_BLEND_ONE , GR_BLEND_ZERO );
break;
default :
grAlphaBlendFunction (GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ONE,GR_BLEND_ZERO );
break;
}
}
if( Xor & PF_NoAlphaTest)
{
if( PolyFlags & PF_NoAlphaTest)
// desable alpha testing
grAlphaTestFunction (GR_CMP_ALWAYS);
else
// discard 0 alpha pixels (holes in texture)
grAlphaTestFunction (GR_CMP_GREATER);
}
if( Xor & PF_Decal )
{
// work a little but not like opengl one :(
if( PolyFlags & PF_Decal )
grDepthBiasLevel( -1 );
else
grDepthBiasLevel( 0 );
}
if( Xor&(PF_Modulated | PF_NoTexture))
{
switch (PolyFlags & (PF_Modulated | PF_NoTexture)) {
case 0 :
// colour from texture is unchanged before blending
grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
GR_COMBINE_LOCAL_NONE,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE );
// use alpha texture only
grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
GR_COMBINE_LOCAL_NONE,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE );
break;
case PF_Modulated :
// mix texture colour with Surface->FlatColor (constant color)
grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, // factor * Color other
GR_COMBINE_FACTOR_LOCAL, // or local_alpha ???
GR_COMBINE_LOCAL_CONSTANT, // local is constant color
GR_COMBINE_OTHER_TEXTURE, // color from texture map
FXFALSE );
// use (alpha constant)*(alpha texture)
grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
GR_COMBINE_LOCAL_CONSTANT,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE );
break;
case PF_NoTexture :
// no texture, no modulate what color use ?
// in opengl fab use white texture
grConstantColorValue(0xffFFffFF);
// no need break
case PF_Modulated | PF_NoTexture :
grColorCombine( GR_COMBINE_FUNCTION_LOCAL, // factor * Color other
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_LOCAL_CONSTANT, // local is constant color
GR_COMBINE_OTHER_NONE, // color from texture map
FXFALSE);
// use (alpha constant)*(alpha texture)
grAlphaCombine( GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_LOCAL_CONSTANT,
GR_COMBINE_OTHER_NONE,
FXFALSE );
break;
}
}
if( Xor&PF_NoDepthTest )
{
if( PolyFlags & PF_NoDepthTest )
grDepthBufferFunction(GR_CMP_ALWAYS);
else
grDepthBufferFunction(GR_CMP_LEQUAL);
}
if( Xor & PF_Occlude )
{
// depth is tested but no writed
grDepthMask( (PolyFlags&PF_Occlude)!=0 );
}
if( Xor & PF_Invisible )
{
grColorMask( (PolyFlags&PF_Invisible)==0 , FXFALSE );
}
CurrentPolyFlags = PolyFlags;
}
// ==========================================================================
// Read a rectangle region of the truecolor framebuffer
// store pixels as 16bit 565 RGB
// ==========================================================================
EXPORT void HWRAPI( ReadRect ) (int x, int y, int width, int height,
int dst_stride, unsigned short * dst_data)
{
if (!grPreviousContext) {
DBG_Printf ("HWRAPI ReadRect() : display not set\n");
return;
}
grLfbReadRegion (GR_BUFFER_FRONTBUFFER,
x, y, width, height, dst_stride, dst_data);
}
// ==========================================================================
// Defines the 2D hardware clipping window
// ==========================================================================
EXPORT void HWRAPI( GClipRect ) (int minx, int miny, int maxx, int maxy, float nearclip)
{
if (!grPreviousContext) {
DBG_Printf ("HWRAPI GClipRect() : display not set\n");
return;
}
// BP: swap maxy and miny because wrong axe position
grClipWindow ( (FxU32)minx, (FxU32)miny, (FxU32)maxx, (FxU32)maxy);
}
// -----------------+
// HWRAPI ClearBuffer
// : Clear the color/alpha/depth buffer(s)
// -----------------+
EXPORT void HWRAPI( ClearBuffer ) ( FBOOLEAN ColorMask,
FBOOLEAN DepthMask,
FRGBAFloat * ClearColor )
{
FBITFIELD polyflags;
if (!grPreviousContext) {
DBG_Printf ("HWRAPI ClearBuffer() : display not set\n");
return;
}
grColorMask (ColorMask, FXFALSE);
polyflags = CurrentPolyFlags;
// enable or desable z-buffer
if( DepthMask )
polyflags |= PF_Occlude;
else
polyflags &= ~PF_Occlude;
// enable disable colorbuffer
if( ColorMask )
polyflags &= ~PF_Invisible;
else
polyflags |= PF_Invisible;
SetBlend( polyflags );
if( ClearColor )
grBufferClear ((int)(ClearColor->alpha*255)<<24|
(int)(ClearColor->red*255)<<16 |
(int)(ClearColor->green*255)<<8 |
(int)(ClearColor->blue)*255,
0, gr_wrange[1]);
else
grBufferClear (0,0,gr_wrange[1]);
}
// -----------------+
// HWRAPI Draw2DLine: Render a 2D line
// -----------------+
EXPORT void HWRAPI( Draw2DLine ) ( F2DCoord * v1,
F2DCoord * v2,
RGBA_t Color )
{
FOutVector a,b;
if (!grPreviousContext) {
DBG_Printf ("HWRAPI DrawLine() : display not set\n");
return;
}
a.x = v1->x;
a.y = v1->y;
a.oow = 1.0f;
b.x = v2->x;
b.y = v2->y;
b.oow = 1.0f;
SetBlend( PF_Modulated|PF_NoTexture );
grConstantColorValue(Color.rgba);
// damed, 3dfx have a bug in grDrawLine !
//v1->y = -v1->y;
//v2->y = -v2->y;
grDrawLine (&a, &b);
}
// convert 4exp mantice 12 (w-buffer) to ieee float
#define W16_TO_FLOAT(w) ((( ( ((int)w) & 0xF000) <<11) + 0x3F800000) | ((( ((int)w) & 0xFFF)<<11) + (1<<10)) )
// convert ieee float to 4exp mantice 12 (w-buffer)
#define FLOAT_TO_W16(f) ( ( ( ( (*(int*)&(f)) & 0x7F800000) - 0x3F800000)>>11 ) | ( ( *(int*)&(f) & 0x7FFFFF)>>11) )
#define BYTEPERPIXEL 2
// test if center of corona is visible with the zbuffer (need raw acces to zbuffer)
static boolean ComputeCoronaAlpha( float *retscalef, FOutVector *projVerts )
{
#define NUMPIXELS 8
unsigned short buf[NUMPIXELS][NUMPIXELS];
float cx, cy, cz;
float scalef = 0;
int x,y;
int i,j;
unsigned short z;
// negative z, so not drawed !
if( projVerts[0].oow < 0)
return false;
cx = (projVerts[0].x + projVerts[2].x) / 2.0f; // we should change the coronas' ...
cy = (projVerts[0].y + projVerts[2].y) / 2.0f; // ... code so its only done once.
cz = projVerts[0].oow;
//DBG_Printf("z : %f\n",cz);
// project (note y is -y in glide)
x = (int)(currentmode_width * (1 + cx / cz) /2);
if(x>=currentmode_width || x<0) return false;
y = (int)(currentmode_height * (1 - cy / cz) /2);
if(y>=currentmode_height || y<0) return false;
// get z buffer
grLfbReadRegion( GR_BUFFER_AUXBUFFER,
x-NUMPIXELS/2,y-NUMPIXELS/2,NUMPIXELS,NUMPIXELS,
BYTEPERPIXEL*NUMPIXELS,buf);
// comparaison in float are the same as in int so use int compare
// anyway 1 comparaison is better than 64 !
z = FLOAT_TO_W16(cz);
//DBG_Printf("z (w16) : %x\n",z);
for (i=0; i<NUMPIXELS; i++)
if(i+x>=0 && i+x<currentmode_width)
for (j=0; j<NUMPIXELS; j++)
{
// BP: it seam like not perfect :( not find why ...
#if 1
if(z < buf[i][j] && j+y>=0 && j+y<currentmode_height)
scalef += 1;
//DBG_Printf("buf[%d][%d]=%x (w16) : %x scale %f\n",i,j,buf[i][j],z,scalef);
#else
float f;
*(int *)&f = W16_TO_FLOAT(buf[i][j]);
if(cz < f && j+y>=0 && j+y<currentmode_height)
scalef += 1;
//DBG_Printf("buf[%d][%d] : %f scale %f\n",i,j,f,scalef);
#endif
}
scalef /= NUMPIXELS*NUMPIXELS;
#if 0 // see what pixel we are testing !
// write white rectangle
for(i=0;i<NUMPIXELS;i++)
for(j=0;j<NUMPIXELS;j++)
buf[i][j] = 0xffff;
grLfbWriteRegion( GR_BUFFER_BACKBUFFER,
x-NUMPIXELS/2,y-NUMPIXELS/2,GR_LFB_SRC_FMT_565,
NUMPIXELS,NUMPIXELS,FXTRUE,
BYTEPERPIXEL*NUMPIXELS,buf);
// can't be overwrited, z=0
for(i=0;i<8;i++)
for(j=0;j<8;j++)
buf[i][j] = 0x0000;
grLfbWriteRegion( GR_BUFFER_AUXBUFFER,
x-NUMPIXELS/2,y-NUMPIXELS/2,GR_LFB_SRC_FMT_ZA16,
NUMPIXELS,NUMPIXELS,FXTRUE,
BYTEPERPIXEL*NUMPIXELS,buf);
#endif
if (scalef < 0.05) // alpha too spmall so don't draw
return false;
*retscalef = scalef;
return true;
}
// ==========================================================================
// Draw a triangulated polygon
// ==========================================================================
EXPORT void HWRAPI( DrawPolygon ) ( FSurfaceInfo *pSurf,
FOutVector *projVerts,
FUINT nClipVerts,
FBITFIELD PolyFlags )
{
int i;
if (!grPreviousContext) {
DBG_Printf ("HWRAPI DrawPolygon() : display not set\n");
return;
}
if (nClipVerts < 3)
return;
SetBlend( PolyFlags );
// this test is added for new coronas' code (without depth buffer)
// I think I should do a separate function for drawing coronas, so it will be a little faster
if (PolyFlags & PF_Corona) // check to see if we need to draw the corona
{
RGBA_t c;
float scalef;
if( !ComputeCoronaAlpha(&scalef, projVerts) )
return;
c.rgba = pSurf->FlatColor.rgba;
c.s.alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona)
grConstantColorValue(c.rgba);
}
else
if( (CurrentPolyFlags & PF_Modulated) && pSurf )
grConstantColorValue(pSurf->FlatColor.rgba);
// cut polygone to the screen
if( CurrentPolyFlags & PF_Clip )
{
if( CurrentPolyFlags & PF_NoZClip )
{
nClipVerts = ClipToFrustum (projVerts, tmp2Verts, nClipVerts );
if (nClipVerts<3)
return;
}
else
{
// clip to near z plane
nClipVerts = ClipZ (projVerts, tmpVerts, nClipVerts );
// -!!!- EXIT HERE if not enough points
if (nClipVerts<3)
return;
nClipVerts = ClipToFrustum (tmpVerts, tmp2Verts, nClipVerts );
if (nClipVerts<3)
return;
}
projVerts=tmp2Verts;
}
for(i=0; (FUINT)i < nClipVerts; i++)
projVerts[i].y = -projVerts[i].y;
grDrawVertexArrayContiguous(GR_POLYGON, nClipVerts, projVerts, sizeof(FOutVector));
}
// ==========================================================================
// Fog stuff
// ==========================================================================
static GrFog_t *fogtable =NULL;
static float fogdensity=500.0f/(6000.0f);
static int nFog=0;
static void ComputeFogTable(void)
{
int i,j;
// happen because cvar execution of config.cfg
if(!fogtable)
{
DBG_Printf ("Fog table size: nFog %d\n", nFog);
return;
}
// the table is an exponential fog table. It computes q from i using guFogTableIndexToW()
// and then computes the fog table entries as fog[i]=(1杄 -kw )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -