2018-04-13 18:23:45 +02:00
|
|
|
/*
|
|
|
|
gl_draw.c - orthogonal drawing stuff
|
|
|
|
Copyright (C) 2010 Uncle Mike
|
|
|
|
|
|
|
|
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 "gl_local.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_GetImageParms
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void R_GetTextureParms( int *w, int *h, int texnum )
|
|
|
|
{
|
2018-10-04 08:08:48 +02:00
|
|
|
gl_texture_t *glt;
|
2018-04-13 18:23:45 +02:00
|
|
|
|
|
|
|
glt = R_GetTexture( texnum );
|
|
|
|
if( w ) *w = glt->srcWidth;
|
|
|
|
if( h ) *h = glt->srcHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_GetSpriteParms
|
|
|
|
|
|
|
|
same as GetImageParms but used
|
|
|
|
for sprite models
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite )
|
|
|
|
{
|
|
|
|
mspriteframe_t *pFrame;
|
|
|
|
|
|
|
|
if( !pSprite || pSprite->type != mod_sprite ) return; // bad model ?
|
|
|
|
pFrame = R_GetSpriteFrame( pSprite, currentFrame, 0.0f );
|
|
|
|
|
|
|
|
if( frameWidth ) *frameWidth = pFrame->width;
|
|
|
|
if( frameHeight ) *frameHeight = pFrame->height;
|
|
|
|
if( numFrames ) *numFrames = pSprite->numframes;
|
|
|
|
}
|
|
|
|
|
|
|
|
int R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame )
|
|
|
|
{
|
|
|
|
if( !m_pSpriteModel || m_pSpriteModel->type != mod_sprite || !m_pSpriteModel->cache.data )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return R_GetSpriteFrame( m_pSpriteModel, frame, 0.0f )->gl_texturenum;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_DrawStretchPic
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum )
|
|
|
|
{
|
2018-04-17 02:55:36 +02:00
|
|
|
GL_Bind( XASH_TEXTURE0, texnum );
|
2018-04-13 18:23:45 +02:00
|
|
|
|
|
|
|
pglBegin( GL_QUADS );
|
|
|
|
pglTexCoord2f( s1, t1 );
|
|
|
|
pglVertex2f( x, y );
|
|
|
|
|
|
|
|
pglTexCoord2f( s2, t1 );
|
|
|
|
pglVertex2f( x + w, y );
|
|
|
|
|
|
|
|
pglTexCoord2f( s2, t2 );
|
|
|
|
pglVertex2f( x + w, y + h );
|
|
|
|
|
|
|
|
pglTexCoord2f( s1, t2 );
|
|
|
|
pglVertex2f( x, y + h );
|
|
|
|
pglEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_TileClear
|
|
|
|
|
|
|
|
This repeats a 64*64 tile graphic to fill the screen around a sized down
|
|
|
|
refresh window.
|
|
|
|
=============
|
|
|
|
*/
|
2019-02-24 16:45:27 +01:00
|
|
|
void R_DrawTileClear( int texnum, int x, int y, int w, int h )
|
2018-04-13 18:23:45 +02:00
|
|
|
{
|
|
|
|
float tw, th;
|
2018-10-04 08:08:48 +02:00
|
|
|
gl_texture_t *glt;
|
2018-04-13 18:23:45 +02:00
|
|
|
|
|
|
|
GL_SetRenderMode( kRenderNormal );
|
|
|
|
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
2019-02-24 16:45:27 +01:00
|
|
|
GL_Bind( XASH_TEXTURE0, texnum );
|
2018-04-13 18:23:45 +02:00
|
|
|
|
2019-02-24 16:45:27 +01:00
|
|
|
glt = R_GetTexture( texnum );
|
2018-04-13 18:23:45 +02:00
|
|
|
tw = glt->srcWidth;
|
|
|
|
th = glt->srcHeight;
|
|
|
|
|
|
|
|
pglBegin( GL_QUADS );
|
|
|
|
pglTexCoord2f( x / tw, y / th );
|
|
|
|
pglVertex2f( x, y );
|
|
|
|
pglTexCoord2f((x + w) / tw, y / th );
|
|
|
|
pglVertex2f( x + w, y );
|
|
|
|
pglTexCoord2f((x + w) / tw, (y + h) / th );
|
|
|
|
pglVertex2f( x + w, y + h );
|
|
|
|
pglTexCoord2f( x / tw, (y + h) / th );
|
|
|
|
pglVertex2f( x, y + h );
|
|
|
|
pglEnd ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_DrawStretchRaw
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty )
|
|
|
|
{
|
|
|
|
byte *raw = NULL;
|
2018-10-04 08:08:48 +02:00
|
|
|
gl_texture_t *tex;
|
2018-04-13 18:23:45 +02:00
|
|
|
|
|
|
|
if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT ))
|
|
|
|
{
|
|
|
|
int width = 1, height = 1;
|
2021-01-03 02:28:45 +01:00
|
|
|
|
2018-04-13 18:23:45 +02:00
|
|
|
// check the dimensions
|
|
|
|
width = NearestPOW( cols, true );
|
|
|
|
height = NearestPOW( rows, false );
|
|
|
|
|
|
|
|
if( cols != width || rows != height )
|
|
|
|
{
|
|
|
|
raw = GL_ResampleTexture( data, cols, rows, width, height, false );
|
|
|
|
cols = width;
|
|
|
|
rows = height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
raw = (byte *)data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( cols > glConfig.max_2d_texture_size )
|
2019-03-06 14:23:33 +01:00
|
|
|
gEngfuncs.Host_Error( "R_DrawStretchRaw: size %i exceeds hardware limits\n", cols );
|
2018-04-13 18:23:45 +02:00
|
|
|
if( rows > glConfig.max_2d_texture_size )
|
2019-03-06 14:23:33 +01:00
|
|
|
gEngfuncs.Host_Error( "R_DrawStretchRaw: size %i exceeds hardware limits\n", rows );
|
2018-04-13 18:23:45 +02:00
|
|
|
|
|
|
|
pglDisable( GL_BLEND );
|
|
|
|
pglDisable( GL_ALPHA_TEST );
|
|
|
|
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
|
|
|
|
|
|
|
tex = R_GetTexture( tr.cinTexture );
|
2018-04-17 02:55:36 +02:00
|
|
|
GL_Bind( XASH_TEXTURE0, tr.cinTexture );
|
2018-04-13 18:23:45 +02:00
|
|
|
|
|
|
|
if( cols == tex->width && rows == tex->height )
|
|
|
|
{
|
|
|
|
if( dirty )
|
|
|
|
{
|
|
|
|
pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_BGRA, GL_UNSIGNED_BYTE, raw );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-04-19 22:11:24 +02:00
|
|
|
tex->size = cols * rows * 4;
|
2018-04-13 18:23:45 +02:00
|
|
|
tex->width = cols;
|
|
|
|
tex->height = rows;
|
|
|
|
if( dirty )
|
|
|
|
{
|
|
|
|
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, raw );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pglBegin( GL_QUADS );
|
|
|
|
pglTexCoord2f( 0, 0 );
|
|
|
|
pglVertex2f( x, y );
|
|
|
|
pglTexCoord2f( 1, 0 );
|
|
|
|
pglVertex2f( x + w, y );
|
|
|
|
pglTexCoord2f( 1, 1 );
|
|
|
|
pglVertex2f( x + w, y + h );
|
|
|
|
pglTexCoord2f( 0, 1 );
|
|
|
|
pglVertex2f( x, y + h );
|
|
|
|
pglEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_UploadStretchRaw
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data )
|
|
|
|
{
|
|
|
|
byte *raw = NULL;
|
2018-10-04 08:08:48 +02:00
|
|
|
gl_texture_t *tex;
|
2018-04-13 18:23:45 +02:00
|
|
|
|
|
|
|
if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT ))
|
|
|
|
{
|
|
|
|
// check the dimensions
|
|
|
|
width = NearestPOW( width, true );
|
|
|
|
height = NearestPOW( height, false );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
width = bound( 128, width, glConfig.max_2d_texture_size );
|
|
|
|
height = bound( 128, height, glConfig.max_2d_texture_size );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( cols != width || rows != height )
|
|
|
|
{
|
|
|
|
raw = GL_ResampleTexture( data, cols, rows, width, height, false );
|
|
|
|
cols = width;
|
|
|
|
rows = height;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
raw = (byte *)data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( cols > glConfig.max_2d_texture_size )
|
2019-03-06 14:23:33 +01:00
|
|
|
gEngfuncs.Host_Error( "R_UploadStretchRaw: size %i exceeds hardware limits\n", cols );
|
2018-04-13 18:23:45 +02:00
|
|
|
if( rows > glConfig.max_2d_texture_size )
|
2019-03-06 14:23:33 +01:00
|
|
|
gEngfuncs.Host_Error( "R_UploadStretchRaw: size %i exceeds hardware limits\n", rows );
|
2018-04-13 18:23:45 +02:00
|
|
|
|
|
|
|
tex = R_GetTexture( texture );
|
|
|
|
GL_Bind( GL_KEEP_UNIT, texture );
|
|
|
|
tex->width = cols;
|
|
|
|
tex->height = rows;
|
|
|
|
|
|
|
|
pglTexImage2D( GL_TEXTURE_2D, 0, tex->format, cols, rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, raw );
|
|
|
|
GL_ApplyTextureParams( tex );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_Set2DMode
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void R_Set2DMode( qboolean enable )
|
|
|
|
{
|
|
|
|
if( enable )
|
|
|
|
{
|
|
|
|
if( glState.in2DMode )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// set 2D virtual screen size
|
2019-02-27 00:23:03 +01:00
|
|
|
pglViewport( 0, 0, gpGlobals->width, gpGlobals->height );
|
2018-04-13 18:23:45 +02:00
|
|
|
pglMatrixMode( GL_PROJECTION );
|
|
|
|
pglLoadIdentity();
|
2019-02-27 00:23:03 +01:00
|
|
|
pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 );
|
2018-04-13 18:23:45 +02:00
|
|
|
pglMatrixMode( GL_MODELVIEW );
|
|
|
|
pglLoadIdentity();
|
|
|
|
|
|
|
|
GL_Cull( GL_NONE );
|
|
|
|
|
|
|
|
pglDepthMask( GL_FALSE );
|
|
|
|
pglDisable( GL_DEPTH_TEST );
|
|
|
|
pglEnable( GL_ALPHA_TEST );
|
|
|
|
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
|
|
|
|
|
|
|
glState.in2DMode = true;
|
|
|
|
RI.currententity = NULL;
|
|
|
|
RI.currentmodel = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pglDepthMask( GL_TRUE );
|
|
|
|
pglEnable( GL_DEPTH_TEST );
|
|
|
|
glState.in2DMode = false;
|
|
|
|
|
|
|
|
pglMatrixMode( GL_PROJECTION );
|
|
|
|
GL_LoadMatrix( RI.projectionMatrix );
|
|
|
|
|
|
|
|
pglMatrixMode( GL_MODELVIEW );
|
|
|
|
GL_LoadMatrix( RI.worldviewMatrix );
|
|
|
|
|
|
|
|
GL_Cull( GL_FRONT );
|
|
|
|
}
|
2019-02-23 19:49:46 +01:00
|
|
|
}
|