예제 #1
0
파일: TEST30.C 프로젝트: grakidov/Render3D
void
main( int argc, char **argv ) {
  float
    minColor = 55.f,
    maxColor = 200.f;

  GrVertex
    localVerts[3],
    texVerts[4];

  float
    alpha = 192.0f,
    y_angle = 0.0f;

  int
    n,
    nTris = 0;

  FxBool
    depthBias = FXTRUE,
    blend = FXFALSE,
    texturing = FXFALSE,
    antialias = FXTRUE,
    bilinear = FXTRUE,
    render = FXTRUE,
    backbuffer = FXTRUE,
    background = FXTRUE;

  GrState
    nonBlendState, blendState;

  float
    wWidth, wHeight;

  GrScreenResolution_t
    screenRes;

  GrMipMapId_t
    triDecal,
    bgDecal;

  Gu3dfInfo
    bgInfo, triInfo;

  FxU16
    *scrnImage;

  GrColorCombineFnc_t
    ccFnc = GR_COLORCOMBINE_ITRGB;

  int
    numFrames = -1,
    frameCount = 0;

  char
    *bgFileName = NULL,
    *triFileName = NULL;
  wWidth = 640.0f;
  wHeight = 480.0f;

  screenRes = GR_RESOLUTION_640x480;

  --argc; ++argv;

  while (argc) {
    if (strstr(*argv, "320x200")) {
      wWidth = 320.0f; wHeight = 200.0f;
      screenRes = GR_RESOLUTION_320x200;
      --argc; ++argv;
    } else if (strstr(*argv, "320x240")) {
      wWidth = 320.0f; wHeight = 240.0f;
      screenRes = GR_RESOLUTION_320x240;
      --argc; ++argv;
    } else if (strstr(*argv, "400x256")) {
      wWidth = 400.0f; wHeight = 256.0f;
      screenRes = GR_RESOLUTION_400x256;
      --argc; ++argv;
    } else if (strstr(*argv, "512x384")) {
      wWidth = 512.0f; wHeight = 384.0f;
      screenRes = GR_RESOLUTION_512x384;
      --argc; ++argv;
    } else if (strstr(*argv, "640x480")) {
      wWidth = 640.0f; wHeight = 480.0f;
      screenRes = GR_RESOLUTION_640x480;
      --argc; ++argv;
    } else if (strstr(*argv, "800x600")) {
      wWidth = 800.0f; wHeight = 600.0f;
      screenRes = GR_RESOLUTION_800x600;
      --argc; ++argv;
    } else if (strstr(*argv, "856x480")) {
      wWidth = 856.0f; wHeight = 480.0f;
      screenRes = GR_RESOLUTION_856x480;
      --argc; ++argv;
    } else if (strstr(*argv, "960x720")) {
      wWidth = 960.0f; wHeight = 720.0f;
      screenRes = GR_RESOLUTION_960x720;
      --argc; ++argv;
    } else if (strstr(*argv, "640x200")) {
      wWidth = 640.f; wHeight = 200.f;
      screenRes = GR_RESOLUTION_640x200;
      --argc; ++argv;
    } else if (strstr(*argv, "640x350")) {
      wWidth = 640.f; wHeight = 350.f;
      screenRes = GR_RESOLUTION_640x350;
      --argc; ++argv;
    } else if (strstr(*argv, "640x400")) {
      wWidth = 640.f; wHeight = 400.f;
      screenRes = GR_RESOLUTION_640x400;
      --argc; ++argv;
    } else if (strstr(*argv, "bgFile")) {
      bgFileName = argv[1];
      argc-= 2; argv += 2;
    } else if (strstr(*argv, "triFile")) {
      triFileName = argv[1];
      argc-= 2; argv += 2;
    } else if (strstr(*argv, "alpha")) {
      alpha = (float)atof(argv[1]);
      argc -= 2; argv += 2;                    
    } else if (strstr(*argv, "-n")) {
      numFrames = atoi(argv[1]);
      argc -= 2; argv += 2;
    } else {
      fprintf(
              stderr,
              "Useage:  test24 [-bgFile bgfile.3ds] [-triFile triFile.3ds] [ScreenRes (i.e. 640x480 .. 960x720] [-alpha alphavalue] [-n numFrames]\n");
      exit(-1);
    }
  }

  scrnImage = malloc((int)wWidth * (int)wHeight * sizeof(FxU16));

  puts( "\ntest30:" );
  puts( "Depth Bias Level Test\n" );
  puts("press H for help\n");
  if(numFrames == -1)
  {
    puts("Press a key to continue");
    getch();
  }

  grGlideInit();

  if ( !grSstQueryHardware( &hwconfig ) )
  {
    fprintf( stderr, "main: grSstQueryHardware failed!\n" );
    grGlideShutdown();
    exit( -1 );
  }

  /* Select SST 0 */
  grSstSelect( 0 );

  /* Open up the hardware */
  if ( !grSstOpen( screenRes,
                   GR_REFRESH_60Hz,
                   GR_COLORFORMAT_ABGR,
                   GR_ORIGIN_LOWER_LEFT,
                   GR_SMOOTHING_ENABLE,
                   2 ) )
  {
    fprintf( stderr, "main: grSstOpen failed!\n" );
    grGlideShutdown();
    exit( -1 );
  }

  localVerts[0].x = 0.f;
  localVerts[0].y = 0.75f;
  localVerts[0].z = 0.0f;
  localVerts[0].tmuvtx[0].sow = 255.f;
  localVerts[0].tmuvtx[0].tow = 255.f;
  localVerts[0].oow = 1.f;  
  localVerts[0].r = maxColor;
  localVerts[0].g = minColor;
  localVerts[0].b = minColor;
  localVerts[0].a = 255.f;

  localVerts[1].x = -0.75f;
  localVerts[1].y = -0.75f;
  localVerts[1].z = 0.0f;
  localVerts[1].tmuvtx[0].sow = 0.f;
  localVerts[1].tmuvtx[0].tow = 255.f;
  localVerts[1].oow = 1.f;  
  localVerts[1].r = minColor;
  localVerts[1].g = maxColor;
  localVerts[1].b = minColor;
  localVerts[1].a = 255.f;

  localVerts[2].x = 0.75f;
  localVerts[2].y = -0.75f;
  localVerts[2].z = 0.0f;
  localVerts[2].tmuvtx[0].sow = 255.f;
  localVerts[2].tmuvtx[0].tow = 0.f;
  localVerts[2].oow = 1.f;  
  localVerts[2].r = minColor;
  localVerts[2].g = minColor;
  localVerts[2].b = maxColor;
  localVerts[2].a = 255.f;

  texVerts[0].x = 0.f;
  texVerts[0].y = 0.f;
  texVerts[0].a = 255.f;
  texVerts[0].oow = 1.f;
  texVerts[0].tmuvtx[0].sow = 0.f * texVerts[0].oow;
  texVerts[0].tmuvtx[0].tow = 255.f * texVerts[0].oow;

  texVerts[1].x = wWidth;
  texVerts[1].y = 0.f;
  texVerts[1].a = 255.f;
  texVerts[1].oow = 1.f;
  texVerts[1].tmuvtx[0].sow = 255.f * texVerts[1].oow;
  texVerts[1].tmuvtx[0].tow = 255.f * texVerts[1].oow;

  texVerts[2].x = wWidth;
  texVerts[2].y = wHeight;
  texVerts[2].a = 255.f;
  texVerts[2].oow = 1.f;
  texVerts[2].tmuvtx[0].sow = 255.f * texVerts[2].oow;
  texVerts[2].tmuvtx[0].tow = 0.f * texVerts[2].oow;
  
  texVerts[3].x = 0.f;
  texVerts[3].y = wHeight;
  texVerts[3].a = 255.f;
  texVerts[3].oow = 1.f;
  texVerts[3].tmuvtx[0].sow = 0.f * texVerts[3].oow;
  texVerts[3].tmuvtx[0].tow = 0.f * texVerts[3].oow;
  
  if (bgFileName == NULL)
    bgFileName = "miro.3df";
  if (triFileName == NULL)
    triFileName = "matt1.3df";

  if ( gu3dfGetInfo( bgFileName, &bgInfo ) )  {
     bgInfo.data = malloc( bgInfo.mem_required );

     if ( bgInfo.data == 0 ) {
       fprintf( stderr, "out of memory for texture file %s\n", bgFileName );
       grGlideShutdown();
       exit( -1 );
     }

     if ( !gu3dfLoad( bgFileName, &bgInfo ) ) {
       fprintf( stderr, "could not load texture file %s\n", bgFileName );
       grGlideShutdown();
       exit( -1 );
     }

     bgDecal = guTexAllocateMemory( 0, GR_MIPMAPLEVELMASK_BOTH,
                                  bgInfo.header.width, bgInfo.header.height,
                                  bgInfo.header.format,
                                  GR_MIPMAP_NEAREST,
                                  bgInfo.header.small_lod, bgInfo.header.large_lod,
                                  bgInfo.header.aspect_ratio,
                                  GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
                                  GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR,
                                  0.0F,
                                  FXFALSE );
     if ( bgDecal == GR_NULL_MIPMAP_HANDLE ) {
       fprintf( stderr, "could not allocate memory for texture file %s\n", bgFileName );
       grGlideShutdown();
       exit( -1 );
     }
     guTexDownloadMipMap( bgDecal, bgInfo.data, &bgInfo.table.nccTable );
     free( bgInfo.data );
  } else {
    fprintf( stderr, "could not get info on %s\n", bgFileName );
    grGlideShutdown();
    exit( -1 );
  }
  
  if ( gu3dfGetInfo( triFileName, &triInfo ) )  {
    triInfo.data = malloc( triInfo.mem_required );
    
    if ( triInfo.data == 0 ) {
      fprintf( stderr, "out of memory for texture file  %s\n", triFileName );
      grGlideShutdown();
      exit( -1 );
    }
    
    if ( !gu3dfLoad( triFileName, &triInfo ) ) {
      fprintf( stderr, "could not load texture file %s\n", triFileName );
      grGlideShutdown();
      exit( -1 );
    }

    triDecal = guTexAllocateMemory( 0, GR_MIPMAPLEVELMASK_BOTH,
                                    triInfo.header.width,  
                                    triInfo.header.height, 
                                    triInfo.header.format,
                                    GR_MIPMAP_NEAREST,
                                    triInfo.header.small_lod,
                                    triInfo.header.large_lod, 
                                    triInfo.header.aspect_ratio,
                                    GR_TEXTURECLAMP_WRAP,
                                    GR_TEXTURECLAMP_WRAP, 
                                    GR_TEXTUREFILTER_BILINEAR,
                                    GR_TEXTUREFILTER_BILINEAR, 
                                    0.0F,
                                    FXFALSE );
    if ( triDecal == GR_NULL_MIPMAP_HANDLE ) {
       fprintf( stderr, "could not allocate memory for %s\n", triFileName );
       grGlideShutdown();
       exit( -1 );
     }
     guTexDownloadMipMap( triDecal, triInfo.data, &triInfo.table.nccTable );
     free( triInfo.data );
  } else {
    fprintf( stderr, "could not get info on %s\n", triFileName );
    grGlideShutdown();
    exit( -1 );
  }

  grTexCombineFunction(GR_TMU0, GR_TEXTURECOMBINE_DECAL);
  grRenderBuffer(backbuffer == FXTRUE ? GR_BUFFER_BACKBUFFER : GR_BUFFER_FRONTBUFFER);

  /* Set up alpha blend state for compositing and antialiasing */
  guAlphaSource( GR_ALPHASOURCE_ITERATED_ALPHA );
  grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,
                        GR_BLEND_ONE_MINUS_SRC_ALPHA, GR_BLEND_ONE,
                        GR_BLEND_ZERO ); 
  grAlphaTestFunction( GR_CMP_ALWAYS );
  
  while ( 1 ) {
    Matrix rotm;
    GrVertex xformedVerts[4];
    int i;

    grSstIdle();

    
    ++nTris;
    MatMakeYRot( rotm, DEG2RAD( y_angle ) );
    
    for( i = 0; i < 4; i++ ) {
      PointMatMult( &xformedVerts[i], &localVerts[i], rotm );
      xformedVerts[i].x = xformedVerts[i].x / ( xformedVerts[i].z + 2.0f );
      xformedVerts[i].y = xformedVerts[i].y / ( xformedVerts[i].z + 2.0f );
      xformedVerts[i].x *= wHeight / 2.0f;
      xformedVerts[i].y *= wHeight / 2.0f;
      xformedVerts[i].x += wHeight / 2.0f;
      xformedVerts[i].y += wHeight / 2.0f;
      xformedVerts[i].oow = 1.f / ((xformedVerts[i].z + 2) * wHeight);
      xformedVerts[i].tmuvtx[0].sow *= xformedVerts[i].oow;
      xformedVerts[i].tmuvtx[0].tow *= xformedVerts[i].oow;
      SNAP_COORD( xformedVerts[i].x );
      SNAP_COORD( xformedVerts[i].y );
    }
    

    if (render == FXTRUE) {
      grBufferClear( 0xffffffff, 0, GR_WDEPTHVALUE_FARTHEST );
    
      if (background == FXTRUE) {
        GrState
          oldState;

        grGlideGetState(&oldState);

        grAlphaBlendFunction(
                             GR_BLEND_ONE, GR_BLEND_ZERO,
                             GR_BLEND_ONE, GR_BLEND_ZERO);

        grColorCombine(
                       GR_COMBINE_FUNCTION_SCALE_OTHER,
                       GR_COMBINE_FACTOR_ONE,
                       GR_COMBINE_LOCAL_NONE,
                       GR_COMBINE_OTHER_TEXTURE, FXFALSE
                       );

        guTexSource(bgDecal);
        
        for (i = 0; i < NTRIS; i++) {
          grDrawTriangle(&texVerts[0], &texVerts[1], &texVerts[2]);
          grDrawTriangle(&texVerts[2], &texVerts[3], &texVerts[0]);
        }
        grGlideSetState(&oldState);

      }

      guTexSource(triDecal);

      if (antialias == FXTRUE) {
        if (depthBias) 
            grDepthBiasLevel((short)0x8000);
        guColorCombineFunction(GR_COLORCOMBINE_DECAL_TEXTURE);
        grAADrawTriangle(
                         &xformedVerts[0],  &xformedVerts[1],
                         &xformedVerts[2], FXTRUE, FXTRUE, FXTRUE
                         );
#define SHIFT 20.f;
        for (n = 0; n < 3; n++) {
          xformedVerts[n].x += SHIFT;
          xformedVerts[n].y -= SHIFT;
        }
        if (depthBias)
          grDepthBiasLevel(0x7fff);
        guColorCombineFunction(GR_COLORCOMBINE_ITRGB);
        grAADrawTriangle(
                         &xformedVerts[0],  &xformedVerts[1],
                         &xformedVerts[2], FXTRUE, FXTRUE, FXTRUE
                         );
        
      } else {
        if (depthBias)
            grDepthBiasLevel((short)0x8000);
        guColorCombineFunction(GR_COLORCOMBINE_DECAL_TEXTURE);
        grDrawTriangle(
                       &xformedVerts[0], &xformedVerts[1],
                       &xformedVerts[2]
                       );
        for (n = 0; n < 3; n++) {
          xformedVerts[n].x += SHIFT;
          xformedVerts[n].y -= SHIFT;
        }
        if (depthBias)
          grDepthBiasLevel(0x7fff);
        guColorCombineFunction(GR_COLORCOMBINE_ITRGB);
        grDrawTriangle(
                       &xformedVerts[0], &xformedVerts[1],
                       &xformedVerts[2]
                       );
      }
      if (backbuffer) {
        grBufferSwap( 1 );
      }
    }
    
    if (kbhit()) {
      char c = getch();
      
      switch (c) {
      case 'a':
      case 'A':
        if (antialias == FXFALSE) {
          printf("Turning ON Antialiasing\n");
          antialias = FXTRUE;
        } else {
          printf("Turning OFF Antialiasing\n");
          antialias = FXFALSE;
        }
        break;
      case 'B':
      case 'b':
        if (bilinear == FXFALSE) {
          bilinear = FXTRUE;
          printf("Turning ON BiLinear blending\n");
          guTexChangeAttributes(
                                triDecal, bgInfo.header.width,
                                bgInfo.header.height, 
                                bgInfo.header.format, GR_MIPMAP_NEAREST,
                                bgInfo.header.small_lod,
                                bgInfo.header.large_lod, 
                                bgInfo.header.aspect_ratio,
                                GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
                                GR_TEXTUREFILTER_BILINEAR,
                                GR_TEXTUREFILTER_BILINEAR);
        } else {
          bilinear = FXFALSE;
          printf("Turning OFF BiLinear blending\n");
          guTexChangeAttributes(
                                triDecal, bgInfo.header.width,
                                bgInfo.header.height, 
                                bgInfo.header.format, GR_MIPMAP_NEAREST,
                                bgInfo.header.small_lod,
                                bgInfo.header.large_lod,
                                bgInfo.header.aspect_ratio, 
                                GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
                                GR_TEXTUREFILTER_POINT_SAMPLED,
                                GR_TEXTUREFILTER_POINT_SAMPLED);
        }
        break;

      case 'c':
      case 'C':
        if (blend == FXTRUE) {
          blend = FXFALSE;
          localVerts[0].a = 255.0f;
          localVerts[1].a = 255.0f;
          localVerts[2].a = 255.0f;
          localVerts[3].a = 255.0f;

        } else {
          blend = FXTRUE;
          localVerts[0].a = alpha;
          localVerts[1].a = alpha;
          localVerts[2].a = alpha;
        }
        break;

      case 'd':
      case 'D':
        if (depthBias == FXTRUE)  {
          printf("Turning OFF depth bias level\n");
          depthBias = FXFALSE;
          grDepthBiasLevel(0);
        } else {
          printf("Turning ON depth bias level\n");        
          depthBias = FXTRUE;
        }
        break;

      case 'f':
      case 'F':
        if (backbuffer == FXTRUE) {
          backbuffer = FXFALSE;
          grRenderBuffer(GR_BUFFER_FRONTBUFFER);
        } else {
          backbuffer = FXTRUE;
          grRenderBuffer(GR_BUFFER_BACKBUFFER);
        }
        break;

      case 'g':
      case 'G':
        grLfbBegin();

        grLfbWriteMode(GR_LFBWRITEMODE_565);
        grLfbOrigin(GR_ORIGIN_UPPER_LEFT);
        grLfbGetReadPtr(GR_BUFFER_FRONTBUFFER);
        printf("Press a key to get front buffer\n");
        while (!kbhit());
        c = getch();
        guFbReadRegion(0,0,(int)wWidth,(int)wHeight,scrnImage,(int)wWidth * sizeof(FxU16));
        printf("Press a key to put image in back buffer and swap\n");
        while (!kbhit());
        getch();

        grLfbGetWritePtr(GR_BUFFER_BACKBUFFER);
        guFbWriteRegion(0,0,(int)wWidth,(int)wHeight,scrnImage,(int)wWidth * sizeof(FxU16));
        grBufferSwap(1);

        printf("Press a key to continue...\n");
        while (!kbhit());
        getch();

        grLfbEnd();

        break;

      case 'h':
      case 'H':
      case '?':
        grSstPassthruMode(GR_PASSTHRU_SHOW_VGA);
        printf("Keymap:\n");
        printf("        A or a:         toggle Antialiasing\n");
        printf("        B or b:         toggle Bilinear\n");
        printf("        D or d:         toggle Depth bias level\n");
        printf("        F or f:         toggle Front buffer \n");
        printf("        H, h, or ?:     Help\n");
        printf("        I or i:         toggle background Image\n");
        printf("        P or p:         Pause rendering\n");
        printf("        Q or q:         Quit\n");
        printf("Press a key to continue...\n");
        getch();
        grSstPassthruMode(GR_PASSTHRU_SHOW_SST1);
        break;

      case 'i':
      case 'I':
        if (background == FXTRUE) {
          background = FXFALSE;
          printf("Turning off background\n");
        } else {
          printf("Turning on background\n");
          background = FXTRUE;
        }
        break;

      case 'p':
      case 'P':
        if (render == FXTRUE)
          render = FXFALSE;
        else
          render = FXTRUE;
        break;
        
      case 'q':
      case 'Q':
        grGlideShutdown();
        exit(0);
        break;

      case 'T':
      case 't':
        if (texturing == FXFALSE) {
          printf("Turning ON texturing\n");
          ccFnc = GR_COLORCOMBINE_DECAL_TEXTURE;
          texturing = FXTRUE;
        } else {
          printf("Turning OFF texturing\n");
          ccFnc = GR_COLORCOMBINE_ITRGB;
          texturing = FXFALSE;
        }
        break;
        
      }
    }
    
    if (render) {
      y_angle += 2.f;
      if( y_angle > 360.0f )
        y_angle -= 360.0f;
    }

    frameCount++;
    if(frameCount < 0)
      frameCount = 0;
    if(numFrames == frameCount)
      break;
  }
  grGlideShutdown();
}
예제 #2
0
void main( int argc, char **argv) {
    char match;
    char **remArgs;
    int  rv;

    GrScreenResolution_t resolution = GR_RESOLUTION_640x480;
    float                scrWidth   = 640.0f;
    float                scrHeight  = 480.0f;
    int frames                      = -1;

    TlTexture  baseTexture;
    unsigned long baseTextureAddr;
    TlTexture  lightTexture;
    unsigned long lightTextureAddr;

    GrFog_t  fogtable[GR_FOG_TABLE_SIZE];

    TlVertex3D srcVerts[4];
    float      distance, dDelta;

    /* Process Command Line Arguments */
    while( rv = tlGetOpt( argc, argv, "nr", &match, &remArgs ) ) {
        if ( rv == -1 ) {
            printf( "Unrecognized command line argument\n" );
            printf( "%s %s\n", name, usage );
            printf( "Available resolutions:\n%s\n",
                    tlGetResolutionList() );
            return;
        }
        switch( match ) {
        case 'n':
            frames = atoi( remArgs[0] );
            break;
        case 'r':
            resolution = tlGetResolutionConstant( remArgs[0],
                                                  &scrWidth,
                                                  &scrHeight );
            break;
        }
    }

    tlSetScreen( scrWidth, scrHeight );

    grGlideGetVersion( version );

    printf( "%s:\n%s\n", name, purpose );
    printf( "%s\n", version );
    printf( "Resolution: %s\n", tlGetResolutionString( resolution ) );
    if ( frames == -1 ) {
        printf( "Press A Key To Begin Test.\n" );
        tlGetCH();
    }

    /* Initialize Glide */
    grGlideInit();
    assert( grSstQueryHardware( &hwconfig ) );
    grSstSelect( 0 );
    assert( grSstWinOpen( 0,
                          resolution,
                          GR_REFRESH_60Hz,
                          GR_COLORFORMAT_ABGR,
                          GR_ORIGIN_LOWER_LEFT,
                          2, 1 ) );

    tlConSet( 0.0f, 0.0f, 1.0f, 0.5f,
              60, 15, 0xffffff );

    /* Set up Render State - decal - bilinear - nearest mipmapping - fogging */
    grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
                    GR_COMBINE_FACTOR_ONE,
                    GR_COMBINE_LOCAL_NONE,
                    GR_COMBINE_OTHER_TEXTURE,
                    FXFALSE );
    grTexMipMapMode( GR_TMU0,
                     GR_MIPMAP_NEAREST,
                     FXFALSE );
    grTexFilterMode( GR_TMU0,
                     GR_TEXTUREFILTER_BILINEAR,
                     GR_TEXTUREFILTER_BILINEAR );
    grFogColorValue( 0x404040 );
    guFogGenerateExp( fogtable, .2f );
    grFogTable( fogtable );

    /* Load texture data into system ram */
    assert( tlLoadTexture( "decal1.3df",
                           &baseTexture.info,
                           &baseTexture.tableType,
                           &baseTexture.tableData ) );
    assert( tlLoadTexture( "light.3df",
                           &lightTexture.info,
                           &lightTexture.tableType,
                           &lightTexture.tableData ) );

    /* Download texture data to TMU */
    baseTextureAddr = grTexMinAddress( GR_TMU0 );
    grTexDownloadMipMap( GR_TMU0,
                         baseTextureAddr,
                         GR_MIPMAPLEVELMASK_BOTH,
                         &baseTexture.info );
    if ( baseTexture.tableType != NO_TABLE ) {
        grTexDownloadTable( GR_TMU0,
                            baseTexture.tableType,
                            &baseTexture.tableData );
    }

    lightTextureAddr =
        baseTextureAddr +
        grTexTextureMemRequired( GR_MIPMAPLEVELMASK_BOTH,
                                 &baseTexture.info );
    grTexDownloadMipMap( GR_TMU0,
                         lightTextureAddr,
                         GR_MIPMAPLEVELMASK_BOTH,
                         &lightTexture.info );
    if ( lightTexture.tableType != NO_TABLE ) {
        grTexDownloadTable( GR_TMU0,
                            lightTexture.tableType,
                            &lightTexture.tableData );
    }

    /* Initialize Source 3D data - Rectangle on X/Z Plane
       Centered about Y Axis

       0--1  Z+
       |  |  |
       2--3   - X+

     */
    srcVerts[0].x = -0.5f, srcVerts[0].y = 0.0f, srcVerts[0].z =  0.5f, srcVerts[0].w = 1.0f;
    srcVerts[1].x =  0.5f, srcVerts[1].y = 0.0f, srcVerts[1].z =  0.5f, srcVerts[1].w = 1.0f;
    srcVerts[2].x = -0.5f, srcVerts[2].y = 0.0f, srcVerts[2].z = -0.5f, srcVerts[2].w = 1.0f;
    srcVerts[3].x =  0.5f, srcVerts[3].y = 0.0f, srcVerts[3].z = -0.5f, srcVerts[3].w = 1.0f;

    srcVerts[0].s = 0.0f, srcVerts[0].t = 0.0f;
    srcVerts[1].s = 1.0f, srcVerts[1].t = 0.0f;
    srcVerts[2].s = 0.0f, srcVerts[2].t = 1.0f;
    srcVerts[3].s = 1.0f, srcVerts[3].t = 1.0f;

#define RED  0x000000ff
#define BLUE 0x00ff0000

#define MAX_DIST 10.0f
#define MIN_DIST 1.0f

    distance = 1.0f;
    dDelta   = 0.05f;

    tlConOutput( "Press any key to quit\n\n" );
    while( frames-- && tlOkToRender()) {
        GrVertex vtxA, vtxB, vtxC, vtxD;
        TlVertex3D xfVerts[4];
        TlVertex3D prjVerts[4];

        if (hwconfig.SSTs[0].type == GR_SSTTYPE_SST96) {
            tlGetDimsByConst(resolution,
                             &scrWidth,
                             &scrHeight );

            grClipWindow(0, 0, (FxU32) scrWidth, (FxU32) scrHeight);
        }

        grBufferClear( 0x00404040, 0, GR_ZDEPTHVALUE_FARTHEST );


        /* 3D Transformations */
        /*----
          A-B
          |\|
          C-D
          -----*/
        vtxA.oow = 1.0f;
        vtxB = vtxC = vtxD = vtxA;

        distance += dDelta;
        if ( distance > MAX_DIST ||
                distance < MIN_DIST ) {
            dDelta *= -1.0f;
            distance += dDelta;
        }

        tlSetMatrix( tlIdentity() );
        tlMultMatrix( tlXRotation( -90.0f ) );
        tlMultMatrix( tlTranslation( 0.0f, 0.0f, distance ) );

        tlTransformVertices( xfVerts, srcVerts, 4 );
        tlProjectVertices( prjVerts, xfVerts, 4 );

        vtxA.x = tlScaleX( prjVerts[0].x );
        vtxA.y = tlScaleY( prjVerts[0].y );
        vtxA.oow = 1.0f / prjVerts[0].w;

        vtxB.x = tlScaleX( prjVerts[1].x );
        vtxB.y = tlScaleY( prjVerts[1].y );
        vtxB.oow = 1.0f / prjVerts[1].w;

        vtxC.x = tlScaleX( prjVerts[2].x );
        vtxC.y = tlScaleY( prjVerts[2].y );
        vtxC.oow = 1.0f / prjVerts[2].w;

        vtxD.x = tlScaleX( prjVerts[3].x );
        vtxD.y = tlScaleY( prjVerts[3].y );
        vtxD.oow = 1.0f / prjVerts[3].w;

        vtxA.tmuvtx[0].sow = prjVerts[0].s * 255.0f * vtxA.oow;
        vtxA.tmuvtx[0].tow = prjVerts[0].t * 255.0f * vtxA.oow;

        vtxB.tmuvtx[0].sow = prjVerts[1].s * 255.0f * vtxB.oow;
        vtxB.tmuvtx[0].tow = prjVerts[1].t * 255.0f * vtxB.oow;

        vtxC.tmuvtx[0].sow = prjVerts[2].s * 255.0f * vtxC.oow;
        vtxC.tmuvtx[0].tow = prjVerts[2].t * 255.0f * vtxC.oow;

        vtxD.tmuvtx[0].sow = prjVerts[3].s * 255.0f * vtxD.oow;
        vtxD.tmuvtx[0].tow = prjVerts[3].t * 255.0f * vtxD.oow;

        /* Render First Pass */
        grTexCombine( GR_TMU0,
                      GR_COMBINE_FUNCTION_LOCAL,
                      GR_COMBINE_FACTOR_NONE,
                      GR_COMBINE_FUNCTION_LOCAL,
                      GR_COMBINE_FACTOR_NONE,
                      FXFALSE,
                      FXFALSE );
        grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ZERO,
                              GR_BLEND_ONE, GR_BLEND_ZERO );
        grTexSource( GR_TMU0,
                     baseTextureAddr,
                     GR_MIPMAPLEVELMASK_BOTH,
                     &baseTexture.info );

        grFogMode( GR_FOG_ADD2 | GR_FOG_WITH_TABLE );

        grDrawTriangle( &vtxA, &vtxB, &vtxD );
        grDrawTriangle( &vtxA, &vtxD, &vtxC );

        /* Render Second Pass */
        grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_PREFOG_COLOR,
                              GR_BLEND_ZERO, GR_BLEND_ZERO );
        grTexSource( GR_TMU0,
                     lightTextureAddr,
                     GR_MIPMAPLEVELMASK_BOTH,
                     &lightTexture.info );

        grFogMode( GR_FOG_MULT2 | GR_FOG_WITH_TABLE );

        grDrawTriangle( &vtxA, &vtxB, &vtxD );
        grDrawTriangle( &vtxA, &vtxD, &vtxC );

        tlConRender();
        grBufferSwap( 1 );
        grSstIdle();

        while( tlKbHit() ) {
            switch( tlGetCH() ) {
            default:
                frames = 0;
                break;
            }
        }
    }

    grGlideShutdown();
    return;
}