Files
FC1/BinkSDK/glrad3d.c
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

1379 lines
36 KiB
C

//############################################################################
//## ##
//## GLRAD3D.C ##
//## ##
//## API to use GL for video textures ##
//## ##
//## Author: Jeff Roberts ##
//## ##
//############################################################################
//## ##
//## Copyright (C) RAD Game Tools, Inc. ##
//## ##
//## For technical support, contact RAD Game Tools at 425 - 893 - 4300. ##
//## ##
//############################################################################
#include <windows.h>
#include <gl/gl.h>
#include "rad3d.h"
//############################################################################
//## ##
//## Get the desktop color depth in bits. ##
//## ##
//############################################################################
static S32 Get_desktop_color_depth( void )
{
HDC screen_dc;
S32 desktop_color_bits;
//
// Calculate the desktop color depth
//
screen_dc = GetDC( 0 );
desktop_color_bits = ( GetDeviceCaps( screen_dc, BITSPIXEL ) *
GetDeviceCaps( screen_dc, PLANES ) );
ReleaseDC( 0, screen_dc );
return( desktop_color_bits );
}
//############################################################################
//## ##
//## Find a pixel format to use with GL (at least 16-bit). ##
//## ##
//############################################################################
static S32 Find_good_pixel_format( HDC window_dc,
PIXELFORMATDESCRIPTOR* out_pixel_format )
{
S32 closest_format_index;
S32 desktop_color_bits;
PIXELFORMATDESCRIPTOR desired_format;
//
// Setup the description of the pixel format we want.
// (at least 16-bit color, 16-bit Z-buffer).
//
memset( &desired_format, 0, sizeof( PIXELFORMATDESCRIPTOR ) );
desired_format.nSize = sizeof( PIXELFORMATDESCRIPTOR );
desired_format.nVersion = 1;
desired_format.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER;
desired_format.iPixelType = PFD_TYPE_RGBA;
desired_format.cColorBits = 16;
desired_format.cDepthBits = 16;
//
// Check to see if the desktop is already running in higher than
// 16-bit color, and if so, use the desktop's color depth.
//
desktop_color_bits = Get_desktop_color_depth( );
if ( desired_format.cColorBits < desktop_color_bits )
{
desired_format.cColorBits = ( unsigned char ) desktop_color_bits;
}
//
// Find a suitable pixel format match.
//
closest_format_index = ChoosePixelFormat( window_dc, &desired_format );
if ( closest_format_index )
{
//
// Get a description of the matched format and return.
//
if ( DescribePixelFormat( window_dc, closest_format_index,
sizeof( PIXELFORMATDESCRIPTOR ),
out_pixel_format ) )
{
return( closest_format_index );
}
}
//
// Return nothing.
//
return( 0 );
}
//############################################################################
//## ##
//## Configure the DC to use a OpenGL pixel format. ##
//## ##
//############################################################################
static S32 Configure_dc_to_pixel_format( HDC rendering_dc,
S32 format_index,
PIXELFORMATDESCRIPTOR const* pixel_format )
{
//
// Ensure that we're running on a non-palettized display.
//
if ( ( GetDeviceCaps( rendering_dc, RASTERCAPS ) & RC_PALETTE ) != RC_PALETTE )
{
//
// Set the pixel format.
//
if ( SetPixelFormat( rendering_dc,
format_index,
pixel_format ) )
{
//
// Return success.
//
return( 1 );
}
}
//
// Return failure.
//
return( 0 );
}
//############################################################################
//## ##
//## Create an OpenGL context for rendering. ##
//## ##
//############################################################################
static HGLRC Create_gl_context( HDC rendering_dc )
{
HGLRC context;
//
// Create a context
//
context = wglCreateContext( rendering_dc );
//
// If we got a context, make it current.
//
if ( context )
{
wglMakeCurrent( rendering_dc, context );
}
return( context );
}
//
// Open GL RAD3D structure.
//
typedef struct RAD3D
{
HWND window;
HGLRC context;
HDC rendering_dc;
} RAD3D;
//############################################################################
//## ##
//## Call this function to actually open GL. ##
//## ##
//############################################################################
RADCFUNC HRAD3D Open_RAD_3D( HWND window )
{
HRAD3D rad_3d;
PIXELFORMATDESCRIPTOR pixel_format;
S32 format_index;
//
// try to create a RAD3D structure
//
rad_3d = ( HRAD3D ) malloc( sizeof( RAD3D ) );
if ( rad_3d == 0 )
{
return( 0 );
}
//
// Get a DC to use.
//
rad_3d->rendering_dc = GetDC( window );
//
// Try to find a pixel format to use.
//
format_index = Find_good_pixel_format( rad_3d->rendering_dc, &pixel_format );
if ( format_index )
{
//
// Try to set the pixel format of the DC to match.
//
if ( Configure_dc_to_pixel_format( rad_3d->rendering_dc,
format_index,
&pixel_format ) )
{
//
// Now try to create an OpenGL context.
//
rad_3d->context = Create_gl_context( rad_3d->rendering_dc );
if ( rad_3d->context )
{
RECT c;
//
// Get the client size of the window.
//
GetClientRect( window, &c );
//
// Set GL to use our width and height.
//
glViewport( c.left, c.top, c.right - c.left, c.bottom - c.top );
//
// Set GL to use simple orthographic mode.
//
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
glOrtho( 0, c.right - c.left, c.bottom - c.top, 0, -1.0F, 1.0F );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
//
// Set some of the initial simple GL state.
//
glDisable( GL_CULL_FACE );
glDisable( GL_DEPTH_TEST );
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
glEnable( GL_TEXTURE_2D );
//
// Set the background color.
//
glClearColor( 0, 0, 0, 0 );
//
// Return the new DC to use.
//
rad_3d->window = window;
return( rad_3d );
}
}
}
//
// Open failed, release the DC, cleanup, and return.
//
ReleaseDC( window, rad_3d->rendering_dc );
free( rad_3d );
return(0);
}
//############################################################################
//## ##
//## Call this function to close GL. ##
//## ##
//############################################################################
RADCFUNC void Close_RAD_3D( HRAD3D rad_3d )
{
//
// Clean up after ourselves.
//
if ( rad_3d )
{
wglMakeCurrent( 0, 0 );
wglDeleteContext( rad_3d->context );
ReleaseDC( rad_3d->window, rad_3d->rendering_dc );
free( rad_3d );
}
}
//############################################################################
//## ##
//## Return a string describing this 3D provider. ##
//## ##
//############################################################################
RADCFUNC char* Describe_RAD_3D( void )
{
return( "OpenGL" );
}
//############################################################################
//## ##
//## Begin a GL frame. ##
//## ##
//############################################################################
RADCFUNC void Start_RAD_3D_frame( HRAD3D rad_3d )
{
if ( rad_3d )
{
//
// Clear the screen.
//
glClear( GL_COLOR_BUFFER_BIT );
}
}
//############################################################################
//## ##
//## End a GL frame. ##
//## ##
//############################################################################
RADCFUNC void End_RAD_3D_frame( HRAD3D rad_3d )
{
if ( rad_3d )
{
//
// Swap the buffers and render.
//
SwapBuffers( rad_3d->rendering_dc );
}
}
//############################################################################
//## ##
//## Resize the GL viewport. ##
//## ##
//############################################################################
RADCFUNC void Resize_RAD_3D( HRAD3D rad_3d,
U32 width,
U32 height )
{
glViewport( 0, 0, width, height );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
}
//############################################################################
//## ##
//## Simple function to round up to the next power of 2. ##
//## ##
//############################################################################
static U32 Round_up_to_next_2_power( U32 value )
{
if ( value > 16 )
if ( value > 64 )
if ( value > 128 )
if ( value > 256 )
if ( value > 512 )
return( 1024 );
else
return( 512 );
else
return( 256 );
else
return( 128 );
else
if ( value > 32 )
return( 64 );
else
return( 32 );
else
if ( value > 4 )
if ( value > 8 )
return( 16 );
else
return( 8 );
else
if ( value > 2 )
return( 4 );
return( value );
}
//############################################################################
//## ##
//## Setup the specified GL texture. ##
//## ##
//############################################################################
static void Setup_gl_texture( U32 texture,
U32 pitch,
U32 pixel_size,
U32 texture_width,
U32 texture_height,
U32 gl_surface_type,
void* buffer )
{
//
// Make the texture current.
//
glBindTexture( GL_TEXTURE_2D, texture );
//
// Set the texture wrap and filtering options.
//
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
//
// Set the pixel format options.
//
glPixelStorei( GL_UNPACK_ROW_LENGTH, pitch / pixel_size );
glPixelStorei( GL_UNPACK_ALIGNMENT, ( pitch % pixel_size ) + 1 );
//
// Upload data into the texture.
//
glTexImage2D ( GL_TEXTURE_2D,
0,
gl_surface_type,
texture_width,
texture_height,
0,
gl_surface_type,
GL_UNSIGNED_BYTE,
buffer );
}
//############################################################################
//## ##
//## Structure to contain a RAD 3D image. ##
//## ##
//############################################################################
typedef struct RAD3DIMAGE
{
U32 total_textures;
U32 pitch;
U32 width;
U32 height;
S32 alpha_pixels;
U32 pixel_size;
U32 textures_across;
U32 textures_down;
U32 remnant_width;
U32 remnant_height;
U32 remnant_input_width;
U32 remnant_input_height;
U32 maximum_texture_size;
U32 rad_surface_type;
U32 gl_surface_type;
U32* gl_textures;
U8* pixels;
S32 download_textures;
U32 row_length;
U32 texture_count;
} RAD3DIMAGE;
//############################################################################
//## ##
//## Open a RAD 3D image (a data structure to blit an image through GL). ##
//## ##
//############################################################################
RADCFUNC HRAD3DIMAGE Open_RAD_3D_image( HRAD3D rad_3d,
U32 width,
U32 height,
S32 alpha_pixels,
U32 maximum_texture_size )
{
HRAD3DIMAGE rad_image;
U32 remnant_width, remnant_height;
U32 buffer_pitch, buffer_height;
U32 pitch, pixel_size;
U32 total_textures;
U32* textures;
U32 x, y;
//
// Calculate the pixel size and the pitch
//
pixel_size = ( alpha_pixels ) ? 4 : 3;
pitch=( ( width * pixel_size ) + 15 ) & ~15;
//
// Calculate the remnant size (for the width and the height)
//
remnant_width = Round_up_to_next_2_power( width % maximum_texture_size );
remnant_height = Round_up_to_next_2_power( height % maximum_texture_size );
//
// The buffer_pitch is the greater of the remnant size and the input pitch.
//
buffer_pitch = remnant_width * pixel_size;
if ( buffer_pitch < pitch )
{
buffer_pitch = pitch;
}
//
// The buffer_height is the greater of the remnant size and the input height.
//
buffer_height = ( height > remnant_height) ? height : remnant_height;
//
// Calculate the total number of textures we'll need.
//
total_textures = ( ( width + ( maximum_texture_size - 1 ) ) / maximum_texture_size ) *
( ( height + ( maximum_texture_size - 1 ) ) / maximum_texture_size );
//
// Allocate enough memory for a RAD image, a list of textures and a buffer.
//
rad_image = ( HRAD3DIMAGE ) malloc( sizeof( RAD3DIMAGE ) +
( total_textures * 4 ) +
31 + ( buffer_pitch * buffer_height) );
if ( rad_image == 0 )
{
return( 0 );
}
//
// The textures come after the structure.
//
rad_image->gl_textures = ( U32 * ) ( rad_image + 1 );
//
// And the buffer comes after the textures (aligned to a 32-byte address).
//
rad_image->pixels = ( U8 * ) ( ( ( ( U32 ) ( rad_image->gl_textures +
total_textures ) ) + 8 ) & ~7 );
//
// Set all the variables in our new structure.
//
rad_image->total_textures = total_textures;
rad_image->pitch = pitch;
rad_image->width = width;
rad_image->height = height;
rad_image->alpha_pixels = alpha_pixels;
rad_image->pixel_size = pixel_size;
rad_image->textures_across = width / maximum_texture_size;
rad_image->textures_down = height / maximum_texture_size;
rad_image->remnant_width = remnant_width;
rad_image->remnant_height = remnant_height;
rad_image->remnant_input_width = width % maximum_texture_size;
rad_image->remnant_input_height = height % maximum_texture_size;
rad_image->maximum_texture_size = maximum_texture_size;
rad_image->rad_surface_type = ( alpha_pixels ) ? RAD3DSURFACE32RA : RAD3DSURFACE24R;
rad_image->gl_surface_type = ( alpha_pixels ) ? GL_RGBA : GL_RGB;
rad_image->download_textures = 0;
rad_image->row_length = pitch / pixel_size;
rad_image->texture_count = 0;
//
// Clear the buffer.
//
memset( rad_image->pixels,
0,
buffer_pitch * buffer_height );
//
// Call GL to create a bunch of textures (clear the last one as a flag to
// see if all of the textures were created).
//
rad_image->gl_textures[ rad_image->total_textures - 1 ] = 0;
glGenTextures( rad_image->total_textures, rad_image->gl_textures );
if ( rad_image->gl_textures[ rad_image->total_textures - 1 ] == 0 )
{
//
// GL didn't allocate enough textures for us, so just fail.
//
free( rad_image );
return(0);
}
//
// Loop through and init each texture (setting each of their sizes).
//
textures = rad_image->gl_textures;
for (y = 0; y < rad_image->textures_down ; y++ )
{
for ( x = 0 ; x < rad_image->textures_across ; x++ )
{
//
// Setup the texture.
//
Setup_gl_texture( *textures++,
rad_image->pitch,
rad_image->pixel_size,
rad_image->maximum_texture_size,
rad_image->maximum_texture_size,
rad_image->gl_surface_type,
rad_image->pixels );
}
//
// Do the rememnant texture at the end of the scanline.
//
if ( rad_image->remnant_width )
{
//
// Setup the texture.
//
Setup_gl_texture( *textures++,
rad_image->pitch,
rad_image->pixel_size,
rad_image->remnant_width,
rad_image->maximum_texture_size,
rad_image->gl_surface_type,
rad_image->pixels );
}
}
//
// Do the remnants along the bottom edge (if any).
//
if ( rad_image->remnant_height )
{
for ( x = 0 ; x < rad_image->textures_across ; x++ )
{
//
// Setup the texture.
//
Setup_gl_texture( *textures++,
rad_image->pitch,
rad_image->pixel_size,
rad_image->maximum_texture_size,
rad_image->remnant_height,
rad_image->gl_surface_type,
rad_image->pixels );
}
if ( rad_image->remnant_width )
{
//
// Setup the texture.
//
Setup_gl_texture( *textures++,
rad_image->pitch,
rad_image->pixel_size,
rad_image->remnant_width,
rad_image->remnant_height,
rad_image->gl_surface_type,
rad_image->pixels );
}
}
return( rad_image );
}
//############################################################################
//## ##
//## Closes a RAD 3D image (frees textures and memory). ##
//## ##
//############################################################################
RADCFUNC void Close_RAD_3D_image( HRAD3DIMAGE rad_image )
{
if ( rad_image )
{
if ( rad_image->gl_textures )
{
//
// Ask GL to delete the textures.
//
glDeleteTextures( rad_image->total_textures, rad_image->gl_textures );
rad_image->gl_textures = 0;
//
// Free our memory.
//
free( rad_image );
}
}
}
//############################################################################
//## ##
//## Lock a RAD 3D image and return the buffer address and pitch. ##
//## ##
//############################################################################
RADCFUNC S32 Lock_RAD_3D_image( HRAD3DIMAGE rad_image,
void* out_pixel_buffer,
U32* out_buffer_pitch,
U32* out_surface_type,
U32* src_x,
U32* src_y,
U32* src_w,
U32* src_h )
{
if ( rad_image == 0 )
{
return( 0 );
}
//
// Fill the variables that were requested.
//
if ( rad_image->texture_count < 1 )
{
if ( out_pixel_buffer )
{
*( void** )out_pixel_buffer = rad_image->pixels;
}
if ( out_buffer_pitch )
{
*out_buffer_pitch = rad_image->pitch;
}
if ( out_surface_type )
{
*out_surface_type = rad_image->rad_surface_type;
}
if ( src_x )
{
*src_x = 0;
}
if ( src_y )
{
*src_y = 0;
}
if ( src_w )
{
*src_w = rad_image->width;
}
if ( src_h )
{
*src_h = rad_image->height;
}
rad_image->texture_count = 1;
return( 1 );
}
else
{
rad_image->texture_count = 0;
return( 0 );
}
}
//############################################################################
//## ##
//## Unlock a RAD 3D image (mark it for redownloading next frame). ##
//## ##
//############################################################################
RADCFUNC void Unlock_RAD_3D_image( HRAD3DIMAGE rad_image )
{
if ( rad_image == 0)
{
return;
}
//
// Set the flag to redownload the texture for the next frame.
//
rad_image->download_textures = 1;
}
//############################################################################
//## ##
//## Submit a new texture. ##
//## ##
//############################################################################
static void Submit_texture( void* pixels,
U32 row_length,
U32 width,
U32 height,
U32 surface_type )
{
//
// Set the pixel format options.
//
glPixelStorei( GL_UNPACK_ROW_LENGTH, row_length );
glPixelStorei( GL_UNPACK_ALIGNMENT, 8);
//
// Use TexSubImage because it is faster on some hardware.
//
glTexSubImage2D ( GL_TEXTURE_2D,
0, 0, 0,
width,
height,
surface_type,
GL_UNSIGNED_BYTE,
pixels );
}
//############################################################################
//## ##
//## Submit the vertices for one texture. ##
//## ##
//############################################################################
static void Submit_vertices( F32 dest_x,
F32 dest_y,
F32 scale_x,
F32 scale_y,
U32 width,
U32 height,
F32 alpha_level )
{
F32 right, bottom;
//
// Start a quad.
//
glBegin( GL_QUADS );
//
// Set the colors for these vertices.
//
glColor4f( 1.0F, 1.0F, 1.0F, alpha_level );
//
// Draw around a rectangle.
//
right = dest_x + ( scale_x * ( F32 ) width );
bottom = dest_y + ( scale_y * ( F32 ) height );
glTexCoord2f( 0, 0 );
glVertex3f( dest_x, dest_y, 0.0F );
glTexCoord2f( 1.0f, 0 );
glVertex3f( right, dest_y, 0.0F );
glTexCoord2f( 1.0f, 1.0f );
glVertex3f( right, bottom, 0.0F );
glTexCoord2f( 0, 1.0f );
glVertex3f( dest_x, bottom, 0.0F );
//
// Done with the vertices.
//
glEnd( );
}
//############################################################################
//## ##
//## Submit the lines to outline a texture. ##
//## ##
//############################################################################
static void Submit_lines( F32 dest_x,
F32 dest_y,
F32 scale_x,
F32 scale_y,
U32 width,
U32 height )
{
F32 right, bottom;
//
// Start a quad.
//
glBegin( GL_LINES );
glColor4f( 1.0F, 1.0F, 1.0F, 1.0F );
//
// Draw around a rectangle.
//
right = dest_x + ( scale_x * ( F32 ) width );
bottom = dest_y + ( scale_y * ( F32 ) height );
glVertex3f( dest_x, dest_y, 0.0F );
glVertex3f( right, dest_y, 0.0F );
glVertex3f( right, dest_y, 0.0F );
glVertex3f( right, bottom, 0.0F );
glVertex3f( right, bottom, 0.0F );
glVertex3f( dest_x, bottom, 0.0F );
glVertex3f( dest_x, bottom, 0.0F );
glVertex3f( dest_x, dest_y, 0.0F );
glColor4f( 1.0F, 0.0F, 0.0F, 1.0F );
glVertex3f( dest_x, dest_y, 0.0F );
glVertex3f( right, bottom, 0.0F );
glVertex3f( right, dest_y, 0.0F );
glVertex3f( dest_x, bottom, 0.0F );
//
// Done with the lines.
//
glEnd( );
}
//############################################################################
//## ##
//## Blit a 3D image onto the render target. ##
//## ##
//############################################################################
RADCFUNC void Blit_RAD_3D_image( HRAD3DIMAGE rad_image,
F32 x_offset,
F32 y_offset,
F32 x_scale,
F32 y_scale,
F32 alpha_level )
{
U32* textures;
U8* pixels;
U32 x, y;
F32 dest_x, dest_y;
F32 adjust_x, adjust_y;
U32 x_skip, y_skip;
if ( rad_image == 0 )
{
return;
}
//
// If alpha is disabled and there is no texture alpha, turn alpha off.
//
if ( ( alpha_level >= (1.0F-0.0001) ) && ( ! rad_image->alpha_pixels ) )
{
glDisable( GL_BLEND );
}
else
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}
//
// Now loop through all of our textures, submitting them.
//
pixels = rad_image->pixels;
textures = rad_image->gl_textures;
//
// Calculate how many bytes to move to the next texture block in X.
//
x_skip = ( rad_image->maximum_texture_size * rad_image->pixel_size );
//
// Calculate how many bytes to move to the next texture block in Y.
//
y_skip = ( rad_image->pitch *
rad_image->maximum_texture_size ) -
( rad_image->textures_across *
rad_image->maximum_texture_size *
rad_image->pixel_size );
adjust_x = ( x_scale * ( F32 ) rad_image->maximum_texture_size );
adjust_y = ( y_scale * ( F32 ) rad_image->maximum_texture_size );
dest_y = y_offset;
for ( y = 0 ; y < rad_image->textures_down ; y++ )
{
dest_x = x_offset;
for ( x = 0 ; x < rad_image->textures_across ; x++ )
{
//
// Select the proper texture.
//
glBindTexture( GL_TEXTURE_2D, *textures++ );
//
// If we got new pixels, download them.
//
if ( rad_image->download_textures )
{
Submit_texture( pixels,
rad_image->row_length,
rad_image->maximum_texture_size,
rad_image->maximum_texture_size,
rad_image->gl_surface_type );
}
//
// Submit the vertices.
//
Submit_vertices( dest_x,
dest_y,
x_scale,
y_scale,
rad_image->maximum_texture_size,
rad_image->maximum_texture_size,
alpha_level );
dest_x += adjust_x;
pixels += x_skip;
}
//
// Handle the right side remnant (if any).
//
if ( rad_image->remnant_width )
{
//
// Select the proper texture.
//
glBindTexture( GL_TEXTURE_2D, *textures++ );
//
// If we got new pixels, download them.
//
if ( rad_image->download_textures )
{
Submit_texture( pixels,
rad_image->row_length,
rad_image->remnant_input_width,
rad_image->maximum_texture_size,
rad_image->gl_surface_type );
}
//
// Submit the vertices.
//
Submit_vertices( dest_x,
dest_y,
x_scale,
y_scale,
rad_image->remnant_width,
rad_image->maximum_texture_size,
alpha_level );
}
dest_y += adjust_y;
pixels += y_skip;
}
//
// Handle the bottom row remnants (if any).
//
if ( rad_image->remnant_height )
{
dest_x = x_offset;
for ( x = 0 ; x < rad_image->textures_across ; x++ )
{
//
// Select the proper texture.
//
glBindTexture( GL_TEXTURE_2D, *textures++ );
//
// If we got new pixels, download them.
//
if ( rad_image->download_textures )
{
Submit_texture( pixels,
rad_image->row_length,
rad_image->maximum_texture_size,
rad_image->remnant_input_height,
rad_image->gl_surface_type );
}
//
// Submit the vertices.
//
Submit_vertices( dest_x,
dest_y,
x_scale,
y_scale,
rad_image->maximum_texture_size,
rad_image->remnant_height,
alpha_level );
dest_x += adjust_x;
pixels += x_skip;
}
if ( rad_image->remnant_width )
{
//
// Select the proper texture.
//
glBindTexture( GL_TEXTURE_2D, *textures++ );
//
// If we got new pixels, download them.
//
if ( rad_image->download_textures )
{
Submit_texture( pixels,
rad_image->row_length,
rad_image->remnant_input_width,
rad_image->remnant_input_height,
rad_image->gl_surface_type );
}
//
// Submit the vertices.
//
Submit_vertices( dest_x,
dest_y,
x_scale,
y_scale,
rad_image->remnant_width,
rad_image->remnant_height,
alpha_level );
}
}
//
// Clear the download texture flag after a blit.
//
rad_image->download_textures = 0;
}
//############################################################################
//## ##
//## Draw the edges of each texture for debugging purposes. ##
//## ##
//############################################################################
RADCFUNC void Draw_lines_RAD_3D_image( HRAD3DIMAGE rad_image,
F32 x_offset,
F32 y_offset,
F32 x_scale,
F32 y_scale )
{
U32 x, y;
F32 dest_x, dest_y;
F32 adjust_x, adjust_y;
if ( rad_image == 0 )
{
return;
}
//
// Disable texturing when drawing lines.
//
glDisable(GL_TEXTURE_2D);
adjust_x = ( x_scale * ( F32 ) rad_image->maximum_texture_size );
adjust_y = ( y_scale * ( F32 ) rad_image->maximum_texture_size );
dest_y = y_offset;
for ( y = 0 ; y < rad_image->textures_down ; y++ )
{
dest_x = x_offset;
for ( x = 0 ; x < rad_image->textures_across ; x++ )
{
//
// Submit the lines.
//
Submit_lines( dest_x,
dest_y,
x_scale,
y_scale,
rad_image->maximum_texture_size,
rad_image->maximum_texture_size );
dest_x += adjust_x;
}
//
// Handle the right side remnant (if any).
//
if ( rad_image->remnant_width )
{
//
// Submit the lines.
//
Submit_lines( dest_x,
dest_y,
x_scale,
y_scale,
rad_image->remnant_width,
rad_image->maximum_texture_size );
}
dest_y += adjust_y;
}
//
// Handle the bottom row remnants (if any).
//
if ( rad_image->remnant_height )
{
dest_x = x_offset;
for ( x = 0 ; x < rad_image->textures_across ; x++ )
{
//
// Submit the lines.
//
Submit_lines( dest_x,
dest_y,
x_scale,
y_scale,
rad_image->maximum_texture_size,
rad_image->remnant_height );
dest_x += adjust_x;
}
if ( rad_image->remnant_width )
{
//
// Submit the lines.
//
Submit_lines( dest_x,
dest_y,
x_scale,
y_scale,
rad_image->remnant_width,
rad_image->remnant_height );
}
}
//
// Re-enable texturing.
//
glEnable(GL_TEXTURE_2D);
}
// @cdep pre $requiresbinary(opengl32.lib)