⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 r_glide.c

📁 The source code of Doom legacy for windows
💻 C
📖 第 1 页 / 共 3 页
字号:
{
    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 + -