mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 13:47:58 +03:00
Readded ioq3 renderer
This commit is contained in:
parent
410fa7ac15
commit
e2910930da
90 changed files with 29872 additions and 12427 deletions
|
@ -335,10 +335,4 @@ extern int qglesMajorVersion, qglesMinorVersion;
|
||||||
#define QGL_VERSION_ATLEAST( major, minor ) ( qglMajorVersion > major || ( qglMajorVersion == major && qglMinorVersion >= minor ) )
|
#define QGL_VERSION_ATLEAST( major, minor ) ( qglMajorVersion > major || ( qglMajorVersion == major && qglMinorVersion >= minor ) )
|
||||||
#define QGLES_VERSION_ATLEAST( major, minor ) ( qglesMajorVersion > major || ( qglesMajorVersion == major && qglesMinorVersion >= minor ) )
|
#define QGLES_VERSION_ATLEAST( major, minor ) ( qglesMajorVersion > major || ( qglesMajorVersion == major && qglesMinorVersion >= minor ) )
|
||||||
|
|
||||||
#define qglCopyTexImage2D glCopyTexImage2D
|
|
||||||
#define qglColor4fv glColor4fv
|
|
||||||
#define qglLineStipple glLineStipple
|
|
||||||
#define qglVertex2i glVertex2i
|
|
||||||
#define qglReadBuffer glReadBuffer
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,14 +23,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#define TR_COMMON_H
|
#define TR_COMMON_H
|
||||||
|
|
||||||
#include "../qcommon/q_shared.h"
|
#include "../qcommon/q_shared.h"
|
||||||
#include "../qcommon/qcommon.h"
|
|
||||||
#include "../renderercommon/tr_public.h"
|
#include "../renderercommon/tr_public.h"
|
||||||
#include "qgl.h"
|
#include "qgl.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
IMGTYPE_COLORALPHA, // for color, lightmap, diffuse, and specular
|
IMGTYPE_COLORALPHA, // for color, lightmap, diffuse, and specular
|
||||||
|
@ -48,8 +43,7 @@ typedef enum
|
||||||
IMGFLAG_NO_COMPRESSION = 0x0010,
|
IMGFLAG_NO_COMPRESSION = 0x0010,
|
||||||
IMGFLAG_NOLIGHTSCALE = 0x0020,
|
IMGFLAG_NOLIGHTSCALE = 0x0020,
|
||||||
IMGFLAG_CLAMPTOEDGE = 0x0040,
|
IMGFLAG_CLAMPTOEDGE = 0x0040,
|
||||||
IMGFLAG_SRGB = 0x0080,
|
IMGFLAG_GENNORMALMAP = 0x0080,
|
||||||
IMGFLAG_GENNORMALMAP = 0x0100,
|
|
||||||
} imgFlags_t;
|
} imgFlags_t;
|
||||||
|
|
||||||
typedef struct image_s {
|
typedef struct image_s {
|
||||||
|
@ -123,12 +117,11 @@ extern cvar_t *r_saveFontData;
|
||||||
|
|
||||||
qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode );
|
qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode );
|
||||||
|
|
||||||
float R_NoiseGet4f( float x, float y, float z, float t );
|
float R_NoiseGet4f( float x, float y, float z, double t );
|
||||||
void R_NoiseInit( void );
|
void R_NoiseInit( void );
|
||||||
|
|
||||||
image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags );
|
image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags );
|
||||||
image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat );
|
image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat );
|
||||||
qboolean R_ImageExists( const char *name );
|
|
||||||
|
|
||||||
void R_IssuePendingRenderCommands( void );
|
void R_IssuePendingRenderCommands( void );
|
||||||
qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex );
|
qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex );
|
||||||
|
@ -140,16 +133,6 @@ qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_
|
||||||
void R_InitFreeType( void );
|
void R_InitFreeType( void );
|
||||||
void R_DoneFreeType( void );
|
void R_DoneFreeType( void );
|
||||||
void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font);
|
void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font);
|
||||||
fontheader_t *R_LoadFont( const char *name );
|
|
||||||
void R_LoadFontShader( fontheader_t *font );
|
|
||||||
void R_DrawString( fontheader_t *font, const char *text, float x, float y, int maxlen, qboolean bVirtualScreen );
|
|
||||||
void R_DrawFloatingString( fontheader_t *font, const char *text, const vec3_t org, float *color, float scale, int maxlen );
|
|
||||||
float R_GetFontHeight( fontheader_t *font );
|
|
||||||
float R_GetFontStringWidth( fontheader_t *font, const char *s );
|
|
||||||
int RE_Text_Width( fontInfo_t *font, const char *text, int limit, qboolean useColourCodes );
|
|
||||||
int RE_Text_Height( fontInfo_t *font, const char *text, int limit, qboolean useColourCodes );
|
|
||||||
void RE_Text_PaintChar( fontInfo_t *font, float x, float y, float scale, int c, qboolean is640 );
|
|
||||||
void RE_Text_Paint( fontInfo_t *font, float x, float y, float scale, float alpha, const char *text, float adjust, int limit, qboolean useColourCodes, qboolean is640 );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============================================================
|
=============================================================
|
||||||
|
@ -173,19 +156,16 @@ IMPLEMENTATION SPECIFIC FUNCTIONS
|
||||||
====================================================================
|
====================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void GLimp_Init( void );
|
void GLimp_Init( qboolean fixedFunction );
|
||||||
void GLimp_Shutdown( void );
|
void GLimp_Shutdown( void );
|
||||||
void GLimp_EndFrame( void );
|
void GLimp_EndFrame( void );
|
||||||
|
|
||||||
void GLimp_LogComment( const char *comment );
|
void GLimp_LogComment( char *comment );
|
||||||
void GLimp_Minimize(void);
|
void GLimp_Minimize(void);
|
||||||
|
|
||||||
void GLimp_SetGamma( unsigned char red[256],
|
void GLimp_SetGamma( unsigned char red[256],
|
||||||
unsigned char green[256],
|
unsigned char green[256],
|
||||||
unsigned char blue[256] );
|
unsigned char blue[256] );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -70,7 +70,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "tr_common.h"
|
#include "tr_common.h"
|
||||||
#include "../qcommon/qcommon.h"
|
#include "../qcommon/qcommon.h"
|
||||||
#include "../renderergl2/tr_local.h"
|
|
||||||
|
|
||||||
#ifdef BUILD_FREETYPE
|
#ifdef BUILD_FREETYPE
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
|
@ -87,12 +86,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
FT_Library ftLibrary = NULL;
|
FT_Library ftLibrary = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX_FONTS 255
|
#define MAX_FONTS 6
|
||||||
static int registeredFontCount = 0;
|
static int registeredFontCount = 0;
|
||||||
static fontInfo_t registeredFont[MAX_FONTS];
|
static fontInfo_t registeredFont[MAX_FONTS];
|
||||||
|
|
||||||
static fontheader_t s_loadedFonts[MAX_FONTS];
|
|
||||||
|
|
||||||
#ifdef BUILD_FREETYPE
|
#ifdef BUILD_FREETYPE
|
||||||
void R_GetGlyphInfo(FT_GlyphSlot glyph, int *left, int *right, int *width, int *top, int *bottom, int *height, int *pitch) {
|
void R_GetGlyphInfo(FT_GlyphSlot glyph, int *left, int *right, int *width, int *top, int *bottom, int *height, int *pitch) {
|
||||||
*left = _FLOOR( glyph->metrics.horiBearingX );
|
*left = _FLOOR( glyph->metrics.horiBearingX );
|
||||||
|
@ -306,7 +303,7 @@ static int fdOffset;
|
||||||
static byte *fdFile;
|
static byte *fdFile;
|
||||||
|
|
||||||
int readInt( void ) {
|
int readInt( void ) {
|
||||||
int i = fdFile[fdOffset]+(fdFile[fdOffset+1]<<8)+(fdFile[fdOffset+2]<<16)+(fdFile[fdOffset+3]<<24);
|
int i = ((unsigned int)fdFile[fdOffset] | ((unsigned int)fdFile[fdOffset+1]<<8) | ((unsigned int)fdFile[fdOffset+2]<<16) | ((unsigned int)fdFile[fdOffset+3]<<24));
|
||||||
fdOffset += 4;
|
fdOffset += 4;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -366,109 +363,6 @@ void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IneQuation: try a RitualFont first
|
|
||||||
Com_sprintf( name, sizeof( name ), "fonts/%s.RitualFont", fontName );
|
|
||||||
for( i = 0; i < registeredFontCount; i++ ) {
|
|
||||||
if( !Q_stricmp( name, registeredFont[ i ].name ) ) {
|
|
||||||
Com_Memcpy( font, ®isteredFont[ i ], sizeof( fontInfo_t ) );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len = ri.FS_ReadFile( name, &faceData );
|
|
||||||
if( len > 0 ) {
|
|
||||||
char *p = ( char * )faceData;
|
|
||||||
const char *token;
|
|
||||||
|
|
||||||
Q_strncpyz( font->name, name, sizeof( font->name ) );
|
|
||||||
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
if( !strcmp( token, "RitFont" ) ) {
|
|
||||||
int j;
|
|
||||||
float height, aspect; // aspect is the aspect ratio of the tga file
|
|
||||||
char indirections[ 256 ];
|
|
||||||
shader_t *fontShader;
|
|
||||||
vec4_t locations;
|
|
||||||
|
|
||||||
Com_sprintf( name, sizeof( name ), "gfx/fonts/%s", fontName );
|
|
||||||
fontShader = R_FindShader( name, LIGHTMAP_2D, qfalse );
|
|
||||||
Com_Memset( font->glyphs, 0, sizeof( font->glyphs ) );
|
|
||||||
font->glyphScale = 1.f;
|
|
||||||
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
while( token && token[ 0 ] ) {
|
|
||||||
if( !Q_stricmp( token, "height" ) ) {
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
height = atof( token );
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "aspect" ) ) {
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
aspect = atof( token );
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "indirections" ) ) {
|
|
||||||
// skip the opening brace
|
|
||||||
COM_Parse( &p );
|
|
||||||
for( i = 0; i < 256; i++ ) {
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
indirections[ i ] = atoi( token );
|
|
||||||
}
|
|
||||||
// skip the trailing brace
|
|
||||||
COM_Parse( &p );
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "locations" ) ) {
|
|
||||||
// skip the opening brace
|
|
||||||
COM_Parse( &p );
|
|
||||||
for( i = 0; i < 256; i++ ) {
|
|
||||||
for( j = 0; j < 256; j++ ) {
|
|
||||||
if( indirections[ j ] == i )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// we'll need the value of j in a while, and parsing all the locations is required anyway in order to exit cleanly
|
|
||||||
// skip the opening brace
|
|
||||||
COM_Parse( &p );
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
locations[ 0 ] = atoi( token );
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
locations[ 1 ] = atoi( token );
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
locations[ 2 ] = atoi( token );
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
locations[ 3 ] = atoi( token );
|
|
||||||
// skip the trailing brace
|
|
||||||
COM_Parse( &p );
|
|
||||||
if( j == 256 )
|
|
||||||
continue; // character not supported by font, skip it
|
|
||||||
//font->glyphs[i].top = locations[1];
|
|
||||||
//font->glyphs[i].bottom = font->glyphs[i].top + locations[3];
|
|
||||||
font->glyphs[ j ].s = ( float )locations[ 0 ] / fontShader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->width;
|
|
||||||
font->glyphs[ j ].t = ( float )locations[ 1 ] / fontShader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->height;
|
|
||||||
font->glyphs[ j ].s2 = ( float )( locations[ 0 ] + locations[ 2 ] ) / fontShader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->width;
|
|
||||||
font->glyphs[ j ].t2 = ( float )( locations[ 1 ] + locations[ 3 ] ) / fontShader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->height;
|
|
||||||
font->glyphs[ j ].imageWidth = font->glyphs[ j ].xSkip = font->glyphs[ j ].pitch = locations[ 2 ];
|
|
||||||
font->glyphs[ j ].imageHeight = font->glyphs[ j ].height = locations[ 3 ];
|
|
||||||
font->glyphs[ j ].glyph = fontShader->index;
|
|
||||||
Q_strncpyz( font->glyphs[ j ].shaderName, name, sizeof( font->glyphs[ 0 ].shaderName ) );
|
|
||||||
}
|
|
||||||
// skip the trailing brace
|
|
||||||
COM_Parse( &p );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ri.Printf( PRINT_WARNING, "RE_RegisterFont: unknown token %s.\n", token );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
}
|
|
||||||
if( registeredFontCount < MAX_FONTS - 1 )
|
|
||||||
Com_Memcpy( ®isteredFont[ registeredFontCount++ ], font, sizeof( fontInfo_t ) );
|
|
||||||
else
|
|
||||||
ri.Printf( PRINT_WARNING, "RE_RegisterFont: MAX_FONTS (%d) exceeded.\n", MAX_FONTS );
|
|
||||||
return; // successfully loaded a RitualFont
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ri.Printf( PRINT_WARNING, "RE_RegisterFont: %s is not a valid RitualFont (invalid ident %s).\n", name, token );
|
|
||||||
}
|
|
||||||
// if this fails, try loading the FreeType-rendered fonts
|
|
||||||
|
|
||||||
Com_sprintf(name, sizeof(name), "fonts/fontImage_%i.dat",pointSize);
|
Com_sprintf(name, sizeof(name), "fonts/fontImage_%i.dat",pointSize);
|
||||||
for (i = 0; i < registeredFontCount; i++) {
|
for (i = 0; i < registeredFontCount; i++) {
|
||||||
if (Q_stricmp(name, registeredFont[i].name) == 0) {
|
if (Q_stricmp(name, registeredFont[i].name) == 0) {
|
||||||
|
@ -665,688 +559,3 @@ void R_DoneFreeType(void) {
|
||||||
registeredFontCount = 0;
|
registeredFontCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s_numLoadedFonts = 0;
|
|
||||||
static float s_fontHeightScale = 1.0;
|
|
||||||
static float s_fontGeneralScale = 1.0;
|
|
||||||
static float s_fontZ = 0.0;
|
|
||||||
|
|
||||||
void R_SetFontHeightScale( float scale ) {
|
|
||||||
s_fontHeightScale = scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_SetFontScale( float scale ) {
|
|
||||||
s_fontGeneralScale = scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_SetFontZ( float zed ) {
|
|
||||||
s_fontZ = zed;
|
|
||||||
}
|
|
||||||
|
|
||||||
fontheader_t *R_LoadFont( const char *name ) {
|
|
||||||
int i;
|
|
||||||
const char *theFile;
|
|
||||||
fontheader_t *header;
|
|
||||||
char *ref;
|
|
||||||
const char *token;
|
|
||||||
qboolean error = qfalse;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
for( i = 0; i < s_numLoadedFonts; i++ )
|
|
||||||
{
|
|
||||||
if( !Q_stricmp( name, s_loadedFonts[ i ].name ) ) {
|
|
||||||
return &s_loadedFonts[ i ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( s_numLoadedFonts >= MAX_FONTS ) {
|
|
||||||
ri.Printf( PRINT_WARNING, "LoadFont: Too many fonts loaded! Couldn't load %s\n", name );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
theFile = va( "fonts/%s.RitualFont", name );
|
|
||||||
|
|
||||||
if( ri.FS_ReadFile( theFile, ( void ** )&ref ) == -1 )
|
|
||||||
{
|
|
||||||
ri.Printf( PRINT_WARNING, "LoadFont: Couldn't load font %s\n", name );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
header = &s_loadedFonts[ s_numLoadedFonts ];
|
|
||||||
header->height = 0.0;
|
|
||||||
header->aspectRatio = 0.0;
|
|
||||||
strcpy( header->name, name );
|
|
||||||
|
|
||||||
p = ref;
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
if( !strcmp( token, "RitFont" ) ) {
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
while( token && token[ 0 ] ) {
|
|
||||||
if( !Q_stricmp( token, "height" ) ) {
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
header->height = atof( token );
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "aspect" ) ) {
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
header->aspectRatio = atof( token );
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "indirections" ) ) {
|
|
||||||
// check the opening brace
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
if( Q_stricmp( token, "{" ) )
|
|
||||||
{
|
|
||||||
error = qtrue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for( i = 0; i < 256; i++ ) {
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
if( !*token ) {
|
|
||||||
error = qtrue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
header->indirection[ i ] = atoi( token );
|
|
||||||
}
|
|
||||||
if( error ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// check the trailing brace
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
if( Q_stricmp( token, "}" ) )
|
|
||||||
{
|
|
||||||
error = qtrue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "locations" ) ) {
|
|
||||||
// check the opening brace
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
if( Q_stricmp( token, "{" ) )
|
|
||||||
{
|
|
||||||
error = qtrue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for( i = 0; i < 256; i++ ) {
|
|
||||||
/*for( j = 0; j < 256; j++ ) {
|
|
||||||
if( indirections[ j ] == i )
|
|
||||||
break;
|
|
||||||
}*/
|
|
||||||
// we'll need the value of j in a while, and parsing all the locations is required anyway in order to exit cleanly
|
|
||||||
// check the opening brace
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
if( Q_stricmp( token, "{" ) )
|
|
||||||
{
|
|
||||||
error = qtrue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
header->locations[ i ].pos[ 0 ] = ( float )atoi( token ) * 0.00390625;
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
header->locations[ i ].pos[ 1 ] = ( float )atoi( token ) * header->aspectRatio * 0.00390625;
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
header->locations[ i ].pos[ 2 ] = ( float )atoi( token ) * 0.00390625;
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
header->locations[ i ].pos[ 3 ] = ( float )atoi( token ) * header->aspectRatio * 0.00390625;
|
|
||||||
|
|
||||||
// check the trailing brace
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
if( Q_stricmp( token, "}" ) )
|
|
||||||
{
|
|
||||||
error = qtrue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( error ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// check the trailing brace
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
if( Q_stricmp( token, "}" ) )
|
|
||||||
{
|
|
||||||
error = qtrue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: Unknown token '%s' parsing font '%s'.\n", token, name );
|
|
||||||
error = qtrue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
token = COM_Parse( &p );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: %s is not a valid RitualFont (invalid ident '%s').\n", name, token );
|
|
||||||
}
|
|
||||||
|
|
||||||
R_LoadFontShader( header );
|
|
||||||
|
|
||||||
if( header->height == 0.0 || header->aspectRatio == 0.0 ) {
|
|
||||||
error = qtrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ri.FS_FreeFile( ref );
|
|
||||||
|
|
||||||
if( error )
|
|
||||||
{
|
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: Error parsing font %s.\n", name );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_numLoadedFonts++;
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_LoadFontShader( fontheader_t *font ) {
|
|
||||||
int i;
|
|
||||||
int save;
|
|
||||||
shader_t *fontshader;
|
|
||||||
char filename[ 64 ];
|
|
||||||
|
|
||||||
save = r_sequencenumber;
|
|
||||||
r_sequencenumber = -1;
|
|
||||||
|
|
||||||
Com_sprintf( filename, sizeof( filename ), "gfx/fonts/%s", font->name );
|
|
||||||
fontshader = R_FindShader( filename, -1, qfalse );
|
|
||||||
font->shader = fontshader;
|
|
||||||
|
|
||||||
r_sequencenumber = save;
|
|
||||||
|
|
||||||
if( !fontshader ) {
|
|
||||||
ri.Error( ERR_DROP, "Could not load font shader for %s\n", filename );
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the font to use the global color/alpha
|
|
||||||
for( i = 0; i < fontshader->numUnfoggedPasses; i++ )
|
|
||||||
{
|
|
||||||
if( fontshader->stages[ i ] && fontshader->stages[ i ]->active )
|
|
||||||
{
|
|
||||||
fontshader->stages[ i ]->rgbGen = CGEN_GLOBAL_COLOR;
|
|
||||||
fontshader->stages[ i ]->alphaGen = AGEN_GLOBAL_ALPHA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
font->trhandle = r_sequencenumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_DrawString( fontheader_t *font, const char *text, float x, float y, int maxlen, qboolean bVirtualScreen ) {
|
|
||||||
shader_t *fontshader;
|
|
||||||
float charHeight;
|
|
||||||
float startx, starty;
|
|
||||||
int i;
|
|
||||||
float fWidthScale, fHeightScale;
|
|
||||||
|
|
||||||
if( !font ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
startx = x;
|
|
||||||
starty = y;
|
|
||||||
fWidthScale = glConfig.vidWidth / 640.0;
|
|
||||||
fHeightScale = glConfig.vidHeight / 480.0;
|
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
if( font->trhandle != r_sequencenumber ) {
|
|
||||||
font->shader = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fontshader = font->shader;
|
|
||||||
if( !fontshader ) {
|
|
||||||
R_LoadFontShader( font );
|
|
||||||
}
|
|
||||||
|
|
||||||
charHeight = s_fontGeneralScale * s_fontHeightScale * font->height;
|
|
||||||
|
|
||||||
RB_Prepare2D();
|
|
||||||
|
|
||||||
RB_BeginSurface( fontshader, 0, 0 );
|
|
||||||
|
|
||||||
for( i = 0; text[ i ] && ( maxlen == -1 || i < maxlen ); i++ )
|
|
||||||
{
|
|
||||||
unsigned char c = text[ i ];
|
|
||||||
int indirected;
|
|
||||||
letterloc_t *loc;
|
|
||||||
|
|
||||||
if( c == '\n' )
|
|
||||||
{
|
|
||||||
starty += charHeight;
|
|
||||||
}
|
|
||||||
else if( c == '\r' )
|
|
||||||
{
|
|
||||||
x = startx;
|
|
||||||
}
|
|
||||||
else if( c == '\t' )
|
|
||||||
{
|
|
||||||
indirected = font->indirection[ ' ' ];
|
|
||||||
if( indirected == -1 )
|
|
||||||
{
|
|
||||||
Com_DPrintf( "R_DrawString: no space-character in font!\n" );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
x += font->locations[ indirected ].size[ 0 ] * 256.0 * s_fontGeneralScale * 3.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
indirected = font->indirection[ c ];
|
|
||||||
|
|
||||||
if( indirected == -1 )
|
|
||||||
{
|
|
||||||
Com_DPrintf( "R_DrawString: no 0x%02x-character in font!\n", c );
|
|
||||||
indirected = font->indirection[ '?' ];
|
|
||||||
if( indirected == -1 )
|
|
||||||
{
|
|
||||||
Com_DPrintf( "R_DrawString: no '?' character in font!\n" );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
font->indirection[ c ] = indirected;
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw the character
|
|
||||||
if( tess.numVertexes + 4 >= 1000 || tess.numIndexes + 6 >= 6000 ) {
|
|
||||||
RB_CheckOverflow( 4, 6 );
|
|
||||||
}
|
|
||||||
|
|
||||||
loc = &font->locations[ indirected ];
|
|
||||||
|
|
||||||
tess.texCoords[ tess.numVertexes + 0 ][ 0 ][ 0 ] = loc->pos[ 0 ];
|
|
||||||
tess.texCoords[ tess.numVertexes + 0 ][ 0 ][ 1 ] = loc->pos[ 1 ];
|
|
||||||
tess.texCoords[ tess.numVertexes + 1 ][ 0 ][ 0 ] = loc->pos[ 0 ] + loc->size[ 0 ];
|
|
||||||
tess.texCoords[ tess.numVertexes + 1 ][ 0 ][ 1 ] = loc->pos[ 1 ];
|
|
||||||
tess.texCoords[ tess.numVertexes + 2 ][ 0 ][ 0 ] = loc->pos[ 0 ];
|
|
||||||
tess.texCoords[ tess.numVertexes + 2 ][ 0 ][ 1 ] = loc->pos[ 1 ] + loc->size[ 1 ];
|
|
||||||
tess.texCoords[ tess.numVertexes + 3 ][ 0 ][ 0 ] = loc->pos[ 0 ] + loc->size[ 0 ];
|
|
||||||
tess.texCoords[ tess.numVertexes + 3 ][ 0 ][ 1 ] = loc->pos[ 1 ] + loc->size[ 1 ];
|
|
||||||
|
|
||||||
tess.xyz[ tess.numVertexes + 0 ][ 0 ] = x;
|
|
||||||
tess.xyz[ tess.numVertexes + 0 ][ 1 ] = y;
|
|
||||||
tess.xyz[ tess.numVertexes + 0 ][ 2 ] = s_fontZ;
|
|
||||||
tess.xyz[ tess.numVertexes + 1 ][ 0 ] = x + loc->size[ 0 ] * 256.0 * s_fontGeneralScale;
|
|
||||||
tess.xyz[ tess.numVertexes + 1 ][ 1 ] = y;
|
|
||||||
tess.xyz[ tess.numVertexes + 1 ][ 2 ] = s_fontZ;
|
|
||||||
tess.xyz[ tess.numVertexes + 2 ][ 0 ] = x;
|
|
||||||
tess.xyz[ tess.numVertexes + 2 ][ 1 ] = y + charHeight;
|
|
||||||
tess.xyz[ tess.numVertexes + 2 ][ 2 ] = s_fontZ;
|
|
||||||
tess.xyz[ tess.numVertexes + 3 ][ 0 ] = x + loc->size[ 0 ] * 256.0 * s_fontGeneralScale;
|
|
||||||
tess.xyz[ tess.numVertexes + 3 ][ 1 ] = y + charHeight;
|
|
||||||
tess.xyz[ tess.numVertexes + 3 ][ 2 ] = s_fontZ;
|
|
||||||
|
|
||||||
tess.indexes[ tess.numIndexes + 0 ] = tess.numVertexes + 0;
|
|
||||||
tess.indexes[ tess.numIndexes + 1 ] = tess.numVertexes + 1;
|
|
||||||
tess.indexes[ tess.numIndexes + 2 ] = tess.numVertexes + 2;
|
|
||||||
tess.indexes[ tess.numIndexes + 3 ] = tess.numVertexes + 1;
|
|
||||||
tess.indexes[ tess.numIndexes + 4 ] = tess.numVertexes + 3;
|
|
||||||
tess.indexes[ tess.numIndexes + 5 ] = tess.numVertexes + 2;
|
|
||||||
|
|
||||||
if( bVirtualScreen )
|
|
||||||
{
|
|
||||||
tess.xyz[ tess.numVertexes + 0 ][ 0 ] *= fWidthScale;
|
|
||||||
tess.xyz[ tess.numVertexes + 0 ][ 1 ] *= fHeightScale;
|
|
||||||
tess.xyz[ tess.numVertexes + 1 ][ 0 ] *= fWidthScale;
|
|
||||||
tess.xyz[ tess.numVertexes + 1 ][ 1 ] *= fHeightScale;
|
|
||||||
tess.xyz[ tess.numVertexes + 2 ][ 0 ] *= fWidthScale;
|
|
||||||
tess.xyz[ tess.numVertexes + 2 ][ 1 ] *= fHeightScale;
|
|
||||||
tess.xyz[ tess.numVertexes + 3 ][ 0 ] *= fWidthScale;
|
|
||||||
tess.xyz[ tess.numVertexes + 3 ][ 1 ] *= fHeightScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
tess.numVertexes += 4;
|
|
||||||
tess.numIndexes += 6;
|
|
||||||
|
|
||||||
x += loc->size[ 0 ] * 256.0 * s_fontGeneralScale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RB_EndSurface();
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_DrawFloatingString( fontheader_t *font, const char *text, const vec3_t org, float *color, float scale, int maxlen ) {
|
|
||||||
shader_t *fontshader;
|
|
||||||
qhandle_t fsh;
|
|
||||||
float charWidth;
|
|
||||||
float charHeight;
|
|
||||||
int i;
|
|
||||||
vec3_t pos;
|
|
||||||
polyVert_t verts[ 4 ];
|
|
||||||
|
|
||||||
if( !font ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
if( font->trhandle != r_sequencenumber ) {
|
|
||||||
font->shader = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !font->shader ) {
|
|
||||||
R_LoadFontShader( font );
|
|
||||||
}
|
|
||||||
fontshader = font->shader;
|
|
||||||
|
|
||||||
fsh = 0;
|
|
||||||
for( i = 0; i < tr.numShaders; i++ )
|
|
||||||
{
|
|
||||||
if( fontshader == tr.shaders[ i ] ) {
|
|
||||||
fsh = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
charHeight = font->height * s_fontHeightScale * s_fontGeneralScale * scale;
|
|
||||||
VectorCopy( org, pos );
|
|
||||||
|
|
||||||
for( i = 0; text[ i ] && ( maxlen == -1 || i < maxlen ); i++ )
|
|
||||||
{
|
|
||||||
unsigned char c = text[ i ];
|
|
||||||
int indirected;
|
|
||||||
letterloc_t *loc;
|
|
||||||
|
|
||||||
indirected = font->indirection[ c ];
|
|
||||||
if( indirected == -1 )
|
|
||||||
{
|
|
||||||
Com_Printf( "R_DrawFloatingString: no 0x%02x-character in font!\n", c );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
loc = &font->locations[ indirected ];
|
|
||||||
charWidth = loc->size[ 0 ] * 256.0 * s_fontGeneralScale * scale;
|
|
||||||
|
|
||||||
verts[ 0 ].modulate[ 0 ] = color[ 0 ] * 255.0;
|
|
||||||
verts[ 0 ].modulate[ 1 ] = color[ 1 ] * 255.0;
|
|
||||||
verts[ 0 ].modulate[ 2 ] = color[ 2 ] * 255.0;
|
|
||||||
verts[ 1 ].modulate[ 0 ] = verts[ 0 ].modulate[ 0 ];
|
|
||||||
verts[ 1 ].modulate[ 1 ] = verts[ 0 ].modulate[ 1 ];
|
|
||||||
verts[ 1 ].modulate[ 2 ] = verts[ 0 ].modulate[ 2 ];
|
|
||||||
verts[ 2 ].modulate[ 0 ] = verts[ 0 ].modulate[ 0 ];
|
|
||||||
verts[ 2 ].modulate[ 1 ] = verts[ 0 ].modulate[ 1 ];
|
|
||||||
verts[ 2 ].modulate[ 2 ] = verts[ 0 ].modulate[ 2 ];
|
|
||||||
verts[ 3 ].modulate[ 0 ] = verts[ 0 ].modulate[ 0 ];
|
|
||||||
verts[ 3 ].modulate[ 1 ] = verts[ 0 ].modulate[ 1 ];
|
|
||||||
verts[ 3 ].modulate[ 2 ] = verts[ 0 ].modulate[ 2 ];
|
|
||||||
|
|
||||||
verts[ 0 ].st[ 0 ] = loc->pos[ 0 ];
|
|
||||||
verts[ 0 ].st[ 1 ] = loc->pos[ 1 ];
|
|
||||||
verts[ 1 ].st[ 0 ] = loc->pos[ 0 ] + loc->size[ 0 ];
|
|
||||||
verts[ 1 ].st[ 1 ] = loc->pos[ 1 ];
|
|
||||||
verts[ 2 ].st[ 0 ] = loc->pos[ 0 ] + loc->size[ 0 ];
|
|
||||||
verts[ 2 ].st[ 1 ] = loc->pos[ 1 ] + loc->size[ 1 ];
|
|
||||||
verts[ 3 ].st[ 0 ] = loc->pos[ 0 ];
|
|
||||||
verts[ 3 ].st[ 1 ] = loc->pos[ 1 ] + loc->size[ 1 ];
|
|
||||||
|
|
||||||
verts[ 0 ].xyz[ 0 ] = pos[ 0 ] + tr.refdef.viewaxis[ 1 ][ 0 ] * -charWidth + tr.refdef.viewaxis[ 1 ][ 0 ] * charWidth + tr.refdef.viewaxis[ 2 ][ 0 ] * charHeight;
|
|
||||||
verts[ 0 ].xyz[ 1 ] = pos[ 1 ] + tr.refdef.viewaxis[ 1 ][ 1 ] * -charWidth + tr.refdef.viewaxis[ 1 ][ 1 ] * charWidth + tr.refdef.viewaxis[ 2 ][ 1 ] * charHeight;
|
|
||||||
verts[ 0 ].xyz[ 2 ] = pos[ 2 ] + tr.refdef.viewaxis[ 1 ][ 2 ] * -charWidth + tr.refdef.viewaxis[ 1 ][ 2 ] * charWidth + tr.refdef.viewaxis[ 2 ][ 2 ] * charHeight;
|
|
||||||
verts[ 1 ].xyz[ 0 ] = pos[ 0 ] + tr.refdef.viewaxis[ 1 ][ 0 ] * -charWidth + tr.refdef.viewaxis[ 2 ][ 0 ] * charHeight;
|
|
||||||
verts[ 1 ].xyz[ 1 ] = pos[ 1 ] + tr.refdef.viewaxis[ 1 ][ 1 ] * -charWidth + tr.refdef.viewaxis[ 2 ][ 1 ] * charHeight;
|
|
||||||
verts[ 1 ].xyz[ 2 ] = pos[ 2 ] + tr.refdef.viewaxis[ 1 ][ 2 ] * -charWidth + tr.refdef.viewaxis[ 2 ][ 2 ] * charHeight;
|
|
||||||
verts[ 2 ].xyz[ 0 ] = pos[ 0 ] + tr.refdef.viewaxis[ 1 ][ 0 ] * -charWidth;
|
|
||||||
verts[ 2 ].xyz[ 1 ] = pos[ 1 ] + tr.refdef.viewaxis[ 1 ][ 1 ] * -charWidth;
|
|
||||||
verts[ 2 ].xyz[ 2 ] = pos[ 2 ] + tr.refdef.viewaxis[ 1 ][ 2 ] * -charWidth;
|
|
||||||
verts[ 3 ].xyz[ 0 ] = pos[ 0 ];
|
|
||||||
verts[ 3 ].xyz[ 1 ] = pos[ 1 ];
|
|
||||||
verts[ 3 ].xyz[ 2 ] = pos[ 2 ];
|
|
||||||
|
|
||||||
if( RE_AddPolyToScene( fsh, 4, verts, 0 ) ) {
|
|
||||||
tr.refdef.numPolys++;
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorCopy( verts[ 2 ].xyz, pos );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float R_GetFontHeight( fontheader_t *font ) {
|
|
||||||
if( font ) {
|
|
||||||
return s_fontGeneralScale * s_fontHeightScale * font->height;
|
|
||||||
} else {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float R_GetFontStringWidth( fontheader_t *font, const char *s ) {
|
|
||||||
float widths = 0.0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if( !font ) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( i = 0; s[ i ]; i++ )
|
|
||||||
{
|
|
||||||
unsigned char c = s[ i ];
|
|
||||||
int indirected;
|
|
||||||
|
|
||||||
if( c == '\t' )
|
|
||||||
{
|
|
||||||
indirected = font->indirection[ ' ' ];
|
|
||||||
|
|
||||||
if( indirected == -1 ) {
|
|
||||||
Com_Printf( "R_GetFontStringWidth: no space-character in font!\n" );
|
|
||||||
} else {
|
|
||||||
widths += font->locations[ indirected ].size[ 0 ] * 3.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
indirected = font->indirection[ c ];
|
|
||||||
|
|
||||||
if( indirected == -1 ) {
|
|
||||||
Com_Printf( "R_GetFontStringWidth: no 0x%02x-character in font!\n", c );
|
|
||||||
} else {
|
|
||||||
widths += font->locations[ indirected ].size[ 0 ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
widths *= s_fontGeneralScale * 256.0;
|
|
||||||
return widths;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IneQuation: exports to deal with universal text drawing; adapted from cgame
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
RE_Text_Width
|
|
||||||
===================
|
|
||||||
Returns text width in pixels.
|
|
||||||
*/
|
|
||||||
int RE_Text_Width( fontInfo_t *font, const char *text, int limit, qboolean useColourCodes ) {
|
|
||||||
int count, len;
|
|
||||||
float out;
|
|
||||||
glyphInfo_t *glyph;
|
|
||||||
// FIXME: see ui_main.c, same problem
|
|
||||||
// const unsigned char *s = text;
|
|
||||||
const char *s = text;
|
|
||||||
|
|
||||||
if( !font ) {
|
|
||||||
font = ®isteredFont[ 0 ];
|
|
||||||
if( !font ) {
|
|
||||||
ri.Printf( PRINT_WARNING, "RE_Text_Width: no fonts registered!\n" );
|
|
||||||
return strlen( text ) * 16; // return something
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out = 0;
|
|
||||||
if( text ) {
|
|
||||||
len = strlen( text );
|
|
||||||
if( limit > 0 && len > limit )
|
|
||||||
len = limit;
|
|
||||||
count = 0;
|
|
||||||
while( s && *s && count < len ) {
|
|
||||||
if( useColourCodes && Q_IsColorString( s ) ) {
|
|
||||||
s += 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
glyph = &font->glyphs[ ( int )*s ];
|
|
||||||
out += glyph->xSkip;
|
|
||||||
s++;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out * font->glyphScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
RE_Text_Height
|
|
||||||
===================
|
|
||||||
Returns text height in pixels.
|
|
||||||
*/
|
|
||||||
int RE_Text_Height( fontInfo_t *font, const char *text, int limit, qboolean useColourCodes ) {
|
|
||||||
int len, count;
|
|
||||||
float max;
|
|
||||||
glyphInfo_t *glyph;
|
|
||||||
// TTimo: FIXME
|
|
||||||
// const unsigned char *s = text;
|
|
||||||
const char *s = text;
|
|
||||||
|
|
||||||
if( !font ) {
|
|
||||||
font = ®isteredFont[ 0 ];
|
|
||||||
if( !font ) {
|
|
||||||
ri.Printf( PRINT_WARNING, "RE_Text_Height: no fonts registered!\n" );
|
|
||||||
return 16; // return something
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
max = 0;
|
|
||||||
if( text ) {
|
|
||||||
len = strlen( text );
|
|
||||||
if( limit > 0 && len > limit )
|
|
||||||
len = limit;
|
|
||||||
count = 0;
|
|
||||||
while( s && *s && count < len ) {
|
|
||||||
if( useColourCodes && Q_IsColorString( s ) ) {
|
|
||||||
s += 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
glyph = &font->glyphs[ ( int )*s ]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build
|
|
||||||
if( max < glyph->height )
|
|
||||||
max = glyph->height;
|
|
||||||
s++;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return max * font->glyphScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
RE_Text_PaintChar
|
|
||||||
===================
|
|
||||||
Paints a single character.
|
|
||||||
*/
|
|
||||||
void RE_Text_PaintChar( fontInfo_t *font, float x, float y, float scale, int c, qboolean is640 ) {
|
|
||||||
glyphInfo_t *glyph;
|
|
||||||
float xscale;
|
|
||||||
float yscale;
|
|
||||||
|
|
||||||
if( is640 ) {
|
|
||||||
xscale = glConfig.vidWidth / 640.0f;
|
|
||||||
yscale = glConfig.vidHeight / 480.0f;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
xscale = 1.0f;
|
|
||||||
yscale = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
glyph = &font->glyphs[ c ];
|
|
||||||
if( c != '\n' && glyph->imageWidth == 0 && glyph->imageHeight == 0 ) {
|
|
||||||
glyph = &font->glyphs[ '?' ];
|
|
||||||
// this is so annoying..
|
|
||||||
//ri.Printf(PRINT_WARNING, "RE_Text_PaintChar: no #%d character in font %s!\n", (int)c, font->name);
|
|
||||||
}
|
|
||||||
RE_StretchPic( x * xscale, y*yscale - font->glyphScale * glyph->top,
|
|
||||||
glyph->imageWidth * font->glyphScale * scale * xscale,
|
|
||||||
glyph->imageHeight * font->glyphScale * scale * yscale,
|
|
||||||
glyph->s,
|
|
||||||
glyph->t,
|
|
||||||
glyph->s2,
|
|
||||||
glyph->t2,
|
|
||||||
glyph->glyph );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
RE_Text_Paint
|
|
||||||
===================
|
|
||||||
Paints a string. The alpha value will be ignored unless useColourCodes is qtrue.
|
|
||||||
*/
|
|
||||||
void RE_Text_Paint( fontInfo_t *font, float x, float y, float scale, float alpha, const char *text, float adjust, int limit, qboolean useColourCodes, qboolean is640 ) {
|
|
||||||
int len, count;
|
|
||||||
vec4_t newColor;
|
|
||||||
glyphInfo_t *glyph;
|
|
||||||
float xscale;
|
|
||||||
float yscale;
|
|
||||||
|
|
||||||
if( !font ) {
|
|
||||||
if( !registeredFontCount )
|
|
||||||
return;
|
|
||||||
font = ®isteredFont[ 0 ];
|
|
||||||
}
|
|
||||||
if( is640 ) {
|
|
||||||
xscale = glConfig.vidWidth / 640.0f;
|
|
||||||
yscale = glConfig.vidHeight / 480.0f;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
xscale = 1.0f;
|
|
||||||
yscale = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( text ) {
|
|
||||||
// TTimo: FIXME
|
|
||||||
// const unsigned char *s = text;
|
|
||||||
const char *s = text;
|
|
||||||
len = strlen( text );
|
|
||||||
if( limit > 0 && len > limit )
|
|
||||||
len = limit;
|
|
||||||
count = 0;
|
|
||||||
while( s && *s && count < len ) {
|
|
||||||
glyph = &font->glyphs[ ( int )*s ]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build
|
|
||||||
if( *s != '\n' && glyph->imageWidth == 0 && glyph->imageHeight == 0 ) {
|
|
||||||
glyph = &font->glyphs[ '?' ];
|
|
||||||
//ri.Printf(PRINT_WARNING, "RE_Text_Paint: no #%d character in font %s!\n", (int)*s, font->name);
|
|
||||||
}
|
|
||||||
if( useColourCodes && Q_IsColorString( s ) ) {
|
|
||||||
memcpy( newColor, g_color_table[ ColorIndex( *( s + 1 ) ) ], sizeof( newColor ) );
|
|
||||||
newColor[ 3 ] = alpha;
|
|
||||||
RE_SetColor( newColor );
|
|
||||||
s += 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
float yadj = font->glyphScale * scale * glyph->top;
|
|
||||||
/*if (style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE) {
|
|
||||||
int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
|
|
||||||
colorBlack[3] = newColor[3];
|
|
||||||
RE_SetColor(colorBlack);
|
|
||||||
RE_StretchPic(x + ofs, y - yadj + ofs,
|
|
||||||
glyph->imageWidth * font->glyphScale,
|
|
||||||
glyph->imageHeight * font->glyphScale,
|
|
||||||
glyph->s,
|
|
||||||
glyph->t,
|
|
||||||
glyph->s2,
|
|
||||||
glyph->t2,
|
|
||||||
glyph->glyph);
|
|
||||||
colorBlack[3] = 1.0;
|
|
||||||
RE_SetColor( newColor );
|
|
||||||
}*/
|
|
||||||
RE_StretchPic( x*xscale, ( y - yadj )*yscale,
|
|
||||||
glyph->imageWidth * font->glyphScale * scale*xscale,
|
|
||||||
glyph->imageHeight * font->glyphScale * scale*yscale,
|
|
||||||
glyph->s,
|
|
||||||
glyph->t,
|
|
||||||
glyph->s2,
|
|
||||||
glyph->t2,
|
|
||||||
glyph->glyph );
|
|
||||||
x += ( glyph->xSkip * font->glyphScale * scale ) + adjust;
|
|
||||||
s++;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( useColourCodes ) {
|
|
||||||
RE_SetColor( NULL );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,38 +20,51 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
===========================================================================
|
===========================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
#include <setjmp.h>
|
||||||
* Include file for users of JPEG library.
|
|
||||||
* You will need to have included system headers that define at least
|
|
||||||
* the typedefs FILE and size_t before you can include jpeglib.h.
|
|
||||||
* (stdio.h is sufficient on ANSI-conforming systems.)
|
|
||||||
* You may also wish to include "jerror.h".
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#define JPEG_INTERNALS
|
|
||||||
|
|
||||||
#include "../jpeg-8c/jinclude.h"
|
|
||||||
#include "../jpeg-8c/jpeglib.h"
|
|
||||||
|
|
||||||
#include "tr_common.h"
|
#include "tr_common.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include file for users of JPEG library.
|
||||||
|
* You will need to have included system headers that define at least
|
||||||
|
* the typedefs FILE and size_t before you can include jpeglib.h.
|
||||||
|
* (stdio.h is sufficient on ANSI-conforming systems.)
|
||||||
|
* You may also wish to include "jerror.h".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_INTERNAL_JPEG
|
||||||
|
# define JPEG_INTERNALS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <jpeglib.h>
|
||||||
|
|
||||||
#ifndef USE_INTERNAL_JPEG
|
#ifndef USE_INTERNAL_JPEG
|
||||||
# if JPEG_LIB_VERSION < 80 && !defined(MEM_SRCDST_SUPPORTED)
|
# if JPEG_LIB_VERSION < 80 && !defined(MEM_SRCDST_SUPPORTED)
|
||||||
# error Need system libjpeg >= 80 or jpeg_mem_ support
|
# error Need system libjpeg >= 80 or jpeg_mem_ support
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void __attribute__((__noreturn__)) R_JPGErrorExit(j_common_ptr cinfo)
|
/* Catching errors, as done in libjpeg's example.c */
|
||||||
|
typedef struct q_jpeg_error_mgr_s
|
||||||
|
{
|
||||||
|
struct jpeg_error_mgr pub; /* "public" fields */
|
||||||
|
|
||||||
|
jmp_buf setjmp_buffer; /* for return to caller */
|
||||||
|
} q_jpeg_error_mgr_t;
|
||||||
|
|
||||||
|
static void R_JPGErrorExit(j_common_ptr cinfo)
|
||||||
{
|
{
|
||||||
char buffer[JMSG_LENGTH_MAX];
|
char buffer[JMSG_LENGTH_MAX];
|
||||||
|
|
||||||
|
/* cinfo->err really points to a q_jpeg_error_mgr_s struct, so coerce pointer */
|
||||||
|
q_jpeg_error_mgr_t *jerr = (q_jpeg_error_mgr_t *)cinfo->err;
|
||||||
|
|
||||||
(*cinfo->err->format_message) (cinfo, buffer);
|
(*cinfo->err->format_message) (cinfo, buffer);
|
||||||
|
|
||||||
/* Let the memory manager delete any temp files before we die */
|
ri.Printf(PRINT_ALL, "Error: %s", buffer);
|
||||||
jpeg_destroy(cinfo);
|
|
||||||
|
/* Return control to the setjmp point */
|
||||||
ri.Error(ERR_FATAL, "%s", buffer);
|
longjmp(jerr->setjmp_buffer, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void R_JPGOutputMessage(j_common_ptr cinfo)
|
static void R_JPGOutputMessage(j_common_ptr cinfo)
|
||||||
|
@ -83,7 +96,7 @@ void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *heigh
|
||||||
* Note that this struct must live as long as the main JPEG parameter
|
* Note that this struct must live as long as the main JPEG parameter
|
||||||
* struct, to avoid dangling-pointer problems.
|
* struct, to avoid dangling-pointer problems.
|
||||||
*/
|
*/
|
||||||
struct jpeg_error_mgr jerr;
|
q_jpeg_error_mgr_t jerr;
|
||||||
/* More stuff */
|
/* More stuff */
|
||||||
JSAMPARRAY buffer; /* Output row buffer */
|
JSAMPARRAY buffer; /* Output row buffer */
|
||||||
unsigned int row_stride; /* physical row width in output buffer */
|
unsigned int row_stride; /* physical row width in output buffer */
|
||||||
|
@ -115,10 +128,24 @@ void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *heigh
|
||||||
* This routine fills in the contents of struct jerr, and returns jerr's
|
* This routine fills in the contents of struct jerr, and returns jerr's
|
||||||
* address which we place into the link field in cinfo.
|
* address which we place into the link field in cinfo.
|
||||||
*/
|
*/
|
||||||
cinfo.err = jpeg_std_error(&jerr);
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||||
cinfo.err->error_exit = R_JPGErrorExit;
|
cinfo.err->error_exit = R_JPGErrorExit;
|
||||||
cinfo.err->output_message = R_JPGOutputMessage;
|
cinfo.err->output_message = R_JPGOutputMessage;
|
||||||
|
|
||||||
|
/* Establish the setjmp return context for R_JPGErrorExit to use. */
|
||||||
|
if (setjmp(jerr.setjmp_buffer))
|
||||||
|
{
|
||||||
|
/* If we get here, the JPEG code has signaled an error.
|
||||||
|
* We need to clean up the JPEG object, close the input file, and return.
|
||||||
|
*/
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
ri.FS_FreeFile(fbuffer.v);
|
||||||
|
|
||||||
|
/* Append the filename to the error for easier debugging */
|
||||||
|
ri.Printf(PRINT_ALL, ", loading file %s\n", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we can initialize the JPEG decompression object. */
|
/* Now we can initialize the JPEG decompression object. */
|
||||||
jpeg_create_decompress(&cinfo);
|
jpeg_create_decompress(&cinfo);
|
||||||
|
|
||||||
|
@ -361,17 +388,29 @@ size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality,
|
||||||
int image_width, int image_height, byte *image_buffer, int padding)
|
int image_width, int image_height, byte *image_buffer, int padding)
|
||||||
{
|
{
|
||||||
struct jpeg_compress_struct cinfo;
|
struct jpeg_compress_struct cinfo;
|
||||||
struct jpeg_error_mgr jerr;
|
q_jpeg_error_mgr_t jerr;
|
||||||
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
||||||
my_dest_ptr dest;
|
my_dest_ptr dest;
|
||||||
int row_stride; /* physical row width in image buffer */
|
int row_stride; /* physical row width in image buffer */
|
||||||
size_t outcount;
|
size_t outcount;
|
||||||
|
|
||||||
/* Step 1: allocate and initialize JPEG compression object */
|
/* Step 1: allocate and initialize JPEG compression object */
|
||||||
cinfo.err = jpeg_std_error(&jerr);
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||||
cinfo.err->error_exit = R_JPGErrorExit;
|
cinfo.err->error_exit = R_JPGErrorExit;
|
||||||
cinfo.err->output_message = R_JPGOutputMessage;
|
cinfo.err->output_message = R_JPGOutputMessage;
|
||||||
|
|
||||||
|
/* Establish the setjmp return context for R_JPGErrorExit to use. */
|
||||||
|
if (setjmp(jerr.setjmp_buffer))
|
||||||
|
{
|
||||||
|
/* If we get here, the JPEG code has signaled an error.
|
||||||
|
* We need to clean up the JPEG object and return.
|
||||||
|
*/
|
||||||
|
jpeg_destroy_compress(&cinfo);
|
||||||
|
|
||||||
|
ri.Printf(PRINT_ALL, "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we can initialize the JPEG compression object. */
|
/* Now we can initialize the JPEG compression object. */
|
||||||
jpeg_create_compress(&cinfo);
|
jpeg_create_compress(&cinfo);
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,31 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "tr_common.h"
|
#include "tr_common.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================================================================
|
||||||
|
|
||||||
|
PCX files are used for 8 bit images
|
||||||
|
|
||||||
|
========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char manufacturer;
|
||||||
|
char version;
|
||||||
|
char encoding;
|
||||||
|
char bits_per_pixel;
|
||||||
|
unsigned short xmin,ymin,xmax,ymax;
|
||||||
|
unsigned short hres,vres;
|
||||||
|
unsigned char palette[48];
|
||||||
|
char reserved;
|
||||||
|
char color_planes;
|
||||||
|
unsigned short bytes_per_line;
|
||||||
|
unsigned short palette_type;
|
||||||
|
unsigned short hscreensize, vscreensize;
|
||||||
|
char filler[54];
|
||||||
|
unsigned char data[];
|
||||||
|
} pcx_t;
|
||||||
|
|
||||||
void R_LoadPCX ( const char *filename, byte **pic, int *width, int *height)
|
void R_LoadPCX ( const char *filename, byte **pic, int *width, int *height)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
|
|
|
@ -571,7 +571,7 @@ static uint32_t DecompressIDATs(struct BufferedFile *BF, uint8_t **Buffer)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Rewind to the start of this adventure
|
* Rewind to the start of this adventure
|
||||||
* and return unsuccessfull
|
* and return unsuccessful
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BufferedFileRewind(BF, BytesToRewind);
|
BufferedFileRewind(BF, BytesToRewind);
|
||||||
|
@ -754,7 +754,7 @@ static uint32_t DecompressIDATs(struct BufferedFile *BF, uint8_t **Buffer)
|
||||||
ri.Free(CompressedData);
|
ri.Free(CompressedData);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the last puff() was successfull.
|
* Check if the last puff() was successful.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(!((puffResult == 0) && (puffDestLen > 0)))
|
if(!((puffResult == 0) && (puffDestLen > 0)))
|
||||||
|
|
|
@ -30,6 +30,14 @@ TGA files are used for 24/32 bit images
|
||||||
========================================================================
|
========================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef struct _TargaHeader {
|
||||||
|
unsigned char id_length, colormap_type, image_type;
|
||||||
|
unsigned short colormap_index, colormap_length;
|
||||||
|
unsigned char colormap_size;
|
||||||
|
unsigned short x_origin, y_origin, width, height;
|
||||||
|
unsigned char pixel_size, attributes;
|
||||||
|
} TargaHeader;
|
||||||
|
|
||||||
void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
|
void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
|
||||||
{
|
{
|
||||||
unsigned columns, rows, numPixels;
|
unsigned columns, rows, numPixels;
|
||||||
|
|
|
@ -49,7 +49,7 @@ void R_NoiseInit( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float R_NoiseGet4f( float x, float y, float z, float t )
|
float R_NoiseGet4f( float x, float y, float z, double t )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int ix, iy, iz, it;
|
int ix, iy, iz, it;
|
||||||
|
|
|
@ -22,15 +22,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#ifndef __TR_PUBLIC_H
|
#ifndef __TR_PUBLIC_H
|
||||||
#define __TR_PUBLIC_H
|
#define __TR_PUBLIC_H
|
||||||
|
|
||||||
#include "../cgame/tr_types.h"
|
#include "tr_types.h"
|
||||||
#include "q_shared.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define REF_API_VERSION 14
|
|
||||||
|
|
||||||
|
#define REF_API_VERSION 8
|
||||||
|
|
||||||
typedef struct dtiki_s dtiki_t;
|
typedef struct dtiki_s dtiki_t;
|
||||||
typedef struct skelAnimFrame_s skelAnimFrame_t;
|
typedef struct skelAnimFrame_s skelAnimFrame_t;
|
||||||
|
@ -39,255 +33,205 @@ typedef struct skelAnimFrame_s skelAnimFrame_t;
|
||||||
// these are the functions exported by the refresh module
|
// these are the functions exported by the refresh module
|
||||||
//
|
//
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// called before the library is unloaded
|
// called before the library is unloaded
|
||||||
// if the system is just reconfiguring, pass destroyWindow = qfalse,
|
// if the system is just reconfiguring, pass destroyWindow = qfalse,
|
||||||
// which will keep the screen from flashing to the desktop.
|
// which will keep the screen from flashing to the desktop.
|
||||||
void (*Shutdown)( qboolean destroyWindow );
|
void (*Shutdown)(qboolean destroyWindow);
|
||||||
|
|
||||||
// All data that will be used in a level should be
|
// All data that will be used in a level should be
|
||||||
// registered before rendering any frames to prevent disk hits,
|
// registered before rendering any frames to prevent disk hits,
|
||||||
// but they can still be registered at a later time
|
// but they can still be registered at a later time
|
||||||
// if necessary.
|
// if necessary.
|
||||||
//
|
//
|
||||||
// BeginRegistration makes any existing media pointers invalid
|
// BeginRegistration makes any existing media pointers invalid
|
||||||
// and returns the current gl configuration, including screen width
|
// and returns the current gl configuration, including screen width
|
||||||
// and height, which can be used by the client to intelligently
|
// and height, which can be used by the client to intelligently
|
||||||
// size display elements
|
// size display elements
|
||||||
void ( *BeginRegistration )( glconfig_t *glConfigOut );
|
void (*BeginRegistration)(glconfig_t* glConfigOut);
|
||||||
qhandle_t ( *RegisterModel )( const char *name );
|
qhandle_t(*RegisterModel)(const char* name);
|
||||||
qhandle_t ( *SpawnEffectModel )( const char *name, vec3_t pos, vec3_t axis[3] );
|
qhandle_t(*SpawnEffectModel)(const char* name, vec3_t pos, vec3_t axis[3]);
|
||||||
qhandle_t ( *RegisterServerModel )( const char *name );
|
qhandle_t(*RegisterServerModel)(const char* name);
|
||||||
void ( *UnregisterServerModel )( qhandle_t model );
|
void (*UnregisterServerModel)(qhandle_t model);
|
||||||
qhandle_t ( *RegisterShader )( const char *name );
|
qhandle_t(*RegisterShader)(const char* name);
|
||||||
qhandle_t ( *RegisterShaderNoMip )( const char *name );
|
qhandle_t(*RegisterShaderNoMip)(const char* name);
|
||||||
qhandle_t ( *RefreshShaderNoMip )( const char *name );
|
qhandle_t(*RefreshShaderNoMip)(const char* name);
|
||||||
|
|
||||||
// EndRegistration will draw a tiny polygon with each texture, forcing
|
// EndRegistration will draw a tiny polygon with each texture, forcing
|
||||||
// them to be loaded into card memory
|
// them to be loaded into card memory
|
||||||
void ( *EndRegistration )( void );
|
void (*EndRegistration)();
|
||||||
void ( *FreeModels )( void );
|
void (*FreeModels)();
|
||||||
|
|
||||||
// the vis data is a large enough block of data that we go to the trouble
|
// the vis data is a large enough block of data that we go to the trouble
|
||||||
// of sharing it with the clipmodel subsystem
|
// of sharing it with the clipmodel subsystem
|
||||||
void ( *SetWorldVisData )( const byte *vis );
|
void (*SetWorldVisData)(const byte* vis);
|
||||||
|
|
||||||
void ( *LoadWorld )( const char *name );
|
void (*LoadWorld)(const char* name);
|
||||||
void ( *PrintBSPFileSizes )( void );
|
void (*PrintBSPFileSizes)();
|
||||||
int ( *MapVersion )( void );
|
int (*MapVersion)();
|
||||||
|
|
||||||
// a scene is built up by calls to R_ClearScene and the various R_Add functions.
|
// a scene is built up by calls to R_ClearScene and the various R_Add functions.
|
||||||
// Nothing is drawn until R_RenderScene is called.
|
// Nothing is drawn until R_RenderScene is called.
|
||||||
void (*ClearScene)( void );
|
void (*ClearScene)(void);
|
||||||
void (*AddRefEntityToScene)( const refEntity_t *re, int parentEntityNumber );
|
void (*AddRefEntityToScene)(const refEntity_t* re, int parentEntityNumber);
|
||||||
void (*AddRefSpriteToScene )( const refEntity_t *ent );
|
void (*AddRefSpriteToScene)(const refEntity_t* ent);
|
||||||
qboolean (*AddPolyToScene)( qhandle_t hShader , int numVerts, const polyVert_t *verts, int renderFx );
|
qboolean(*AddPolyToScene)(qhandle_t hShader, int numVerts, const polyVert_t* verts, int renderfx);
|
||||||
void (*AddTerrainMarkToScene)( int terrainIndex, qhandle_t hShader, int numVerts, polyVert_t *verts, int renderfx );
|
void (*AddTerrainMarkToScene)(int terrainIndex, qhandle_t hShader, int numVerts, const polyVert_t* verts, int renderfx);
|
||||||
void (*AddLightToScene)( const vec3_t org, float intensity, float r, float g, float b, int type );
|
void (*AddLightToScene)(const vec3_t org, float intensity, float r, float g, float b, int type);
|
||||||
void (*AddAdditiveLightToScene)( const vec3_t org, float intensity, float r, float g, float b );
|
void (*RenderScene)(const refdef_t* fd);
|
||||||
void (*RenderScene)( const refdef_t *fd );
|
|
||||||
|
|
||||||
refEntity_t *(*GetRenderEntity )( int entityNumber );
|
refEntity_t* (*GetRenderEntity)(int entityNumber);
|
||||||
void (*SavePerformanceCounters)( void );
|
void (*SavePerformanceCounters)();
|
||||||
|
void (*SetColor)(const float* rgba); // NULL = 1,1,1,1
|
||||||
|
void (*Set2DWindow)(int x, int y, int w, int h, float left, float right, float bottom, float top, float n, float f);
|
||||||
|
void (*DrawStretchPic) (float x, float y, float w, float h,
|
||||||
|
float s1, float t1, float s2, float t2, qhandle_t hShader); // 0 = white
|
||||||
|
|
||||||
void (*SetColor)( const vec4_t rgba ); // NULL = 1,1,1,1
|
void (*DrawTilePic)(float x, float y, float w, float h, qhandle_t hShader);
|
||||||
void (*Set2DWindow)( int x, int y, int w, int h, float left, float right, float bottom, float top, float n, float f );
|
void (*DrawTilePicOffset)(float x, float y, float w, float h, qhandle_t hShader, int offsetX, int offsetY);
|
||||||
void (*DrawStretchPic) ( float x, float y, float w, float h,
|
void (*DrawTrianglePic)(vec2_t* points, vec2_t* texCoords, qhandle_t hShader);
|
||||||
float s1, float t1, float s2, float t2, qhandle_t hShader ); // 0 = white
|
void (*DrawBackground)(int cols, int rows, int bgr, uint8_t* data);
|
||||||
|
|
||||||
void (*DrawTilePic)( float x, float y, float w, float h, qhandle_t hShader );
|
// Draw images for cinematic rendering, pass as 32 bit rgba
|
||||||
void (*DrawTilePicOffset)( float x, float y, float w, float h, qhandle_t hShader, int offsetX, int offsetY );
|
void (*DrawStretchRaw) (int x, int y, int w, int h, int cols, int rows, int components, const byte* data);
|
||||||
void (*DrawTrianglePic)( vec2_t *points, vec2_t *texCoords, qhandle_t hShader );
|
void (*DebugLine)(const vec3_t start, const vec3_t end, float r, float g, float b, float alpha);
|
||||||
void (*DrawBackground)( int cols, int rows, int bgr, unsigned char *data );
|
void (*DrawBox)(float x, float y, float w, float h);
|
||||||
|
void (*AddBox)(float x, float y, float w, float h);
|
||||||
|
|
||||||
// Draw images for cinematic rendering, pass as 32 bit rgba
|
void (*BeginFrame)(stereoFrame_t stereoFrame);
|
||||||
void (*DrawStretchRaw) (int x, int y, int w, int h, int cols, int rows, int components, const byte *data);
|
void (*Scissor)(int x, int y, int width, int height);
|
||||||
|
void (*DrawLineLoop)(const vec2_t* points, int count, int stippleFactor, int stippleMask);
|
||||||
|
|
||||||
void (*DebugLine)( vec3_t start, vec3_t end, float r, float g, float b, float alpha );
|
// if the pointers are not NULL, timing info will be returned
|
||||||
void (*DrawBox)( float x, float y, float w, float h );
|
void (*EndFrame)(int* frontEndMsec, int* backEndMsec);
|
||||||
void (*AddBox)( float x, float y, float w, float h );
|
|
||||||
|
|
||||||
void (*BeginFrame)( stereoFrame_t stereoFrame );
|
|
||||||
|
|
||||||
void (*Scissor)( int x, int y, int width, int height );
|
|
||||||
void (*DrawLineLoop)( vec2_t *points, int count, int stippleFactor, int stippleMask );
|
|
||||||
|
|
||||||
// if the pointers are not NULL, timing info will be returned
|
|
||||||
void (*EndFrame)( int *frontEndMsec, int *backEndMsec );
|
|
||||||
|
|
||||||
|
|
||||||
int (*MarkFragments)( int numPoints, const vec3_t *points, const vec3_t projection,
|
int (*MarkFragments)(int numPoints, const vec3_t* points, const vec3_t projection,
|
||||||
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer, float fRadiusSquared );
|
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t* fragmentBuffer, float fRadiusSquared);
|
||||||
|
int (*MarkFragmentsForInlineModel)(clipHandle_t bmodel, const vec3_t angles, const vec3_t origin, int numPoints,
|
||||||
|
const vec3_t* points, const vec3_t projection, int maxPoints, vec3_t pointBuffer,
|
||||||
|
int maxFragments, markFragment_t* fragmentBuffer, float radiusSquared);
|
||||||
|
|
||||||
int (*MarkFragmentsForInlineModel)( clipHandle_t bmodel, vec3_t vAngles, vec3_t vOrigin,
|
void (*GetInlineModelBounds)(int index, vec3_t mins, vec3_t maxs);
|
||||||
int numPoints, const vec3_t *points, const vec3_t projection,
|
void (*GetLightingForDecal)(vec3_t light, vec3_t facing, vec3_t origin);
|
||||||
int maxPoints, vec3_t pointBuffer,
|
void (*GetLightingForSmoke)(vec3_t light, vec3_t origin);
|
||||||
int maxFragments, markFragment_t *fragmentBuffer, float fRadiusSquared );
|
int (*R_GatherLightSources)(const vec3_t pos, vec3_t* lightPos, vec3_t* lightIntensity, int maxLights);
|
||||||
|
|
||||||
void ( *GetInlineModelBounds )( int index, vec3_t mins, vec3_t maxs );
|
void (*ModelBounds)(qhandle_t model, vec3_t mins, vec3_t maxs);
|
||||||
void ( *GetLightingForDecal )( vec3_t light, vec3_t facing, vec3_t origin );
|
float (*ModelRadius)(qhandle_t handle);
|
||||||
void ( *GetLightingForSmoke )( vec3_t light, vec3_t origin );
|
|
||||||
int ( *R_GatherLightSources )( vec3_t pos, vec3_t *lightPos, vec3_t *lightIntensity, int maxLights );
|
|
||||||
void ( *ModelBounds )( qhandle_t handle, vec3_t mins, vec3_t maxs );
|
|
||||||
float ( *ModelRadius )( qhandle_t handle );
|
|
||||||
dtiki_t *( *R_Model_GetHandle )( qhandle_t handle );
|
|
||||||
void ( *DrawString )( fontheader_t *font, const char *text, float x, float y, int maxLen, qboolean virtualScreen );
|
|
||||||
float ( *GetFontHeight )( fontheader_t *font );
|
|
||||||
float ( *GetFontStringWidth )( fontheader_t *font, const char *string );
|
|
||||||
|
|
||||||
fontheader_t *(*LoadFont)( const char *name );
|
dtiki_t* (*R_Model_GetHandle)(qhandle_t handle);
|
||||||
|
void (*DrawString)(const fontheader_t* font, const char* text, float x, float y, int maxLen, qboolean virtualScreen);
|
||||||
void (*SwipeBegin)( float thisTime, float life, qhandle_t hShader );
|
float (*GetFontHeight)(const fontheader_t* font);
|
||||||
void (*SwipePoint)( vec3_t point1, vec3_t point2, float time );
|
float (*GetFontStringWidth)(const fontheader_t* font, char* string);
|
||||||
void (*SwipeEnd)( );
|
fontheader_t* (*LoadFont)(const char* name);
|
||||||
void (*SetRenderTime)( int t );
|
void (*SwipeBegin)(float thisTime, float life, qhandle_t hShader);
|
||||||
float (*Noise)( float x, float y, float z, float t );
|
void (*SwipePoint)(vec3_t point1, vec3_t point2, float time);
|
||||||
qboolean (*SetMode)( int mode, glconfig_t *glConfig );
|
void (*SwipeEnd)();
|
||||||
void (*SetFullscreen)( qboolean fullscreen, glconfig_t *config );
|
void (*SetRenderTime)(int t);
|
||||||
|
float (*Noise)(float x, float y, float z, float t);
|
||||||
#ifdef __USEA3D
|
qboolean(*SetMode)(int mode, const glconfig_t* glConfig);
|
||||||
void (*A3D_RenderGeometry) (void *pVoidA3D, void *pVoidGeom, void *pVoidMat, void *pVoidGeomStatus);
|
void (*SetFullscreen)(qboolean fullScreen);
|
||||||
#endif
|
int (*GetShaderWidth)(qhandle_t hShader);
|
||||||
|
int (*GetShaderHeight)(qhandle_t hShader);
|
||||||
// IneQuation
|
char* (*GetGraphicsInfo)();
|
||||||
int (*Text_Width)(fontInfo_t *font, const char *text, int limit, qboolean useColourCodes);
|
void (*ForceUpdatePose)(refEntity_t* model);
|
||||||
int (*Text_Height)(fontInfo_t *font, const char *text, int limit, qboolean useColourCodes);
|
orientation_t(*TIKI_Orientation)(refEntity_t* model, int tagNum);
|
||||||
// Paints a string. The alpha value will be ignored unless useColourCodes is qtrue.
|
qboolean(*TIKI_IsOnGround)(refEntity_t* model, int tagNum, float threshold);
|
||||||
void (*Text_Paint)(fontInfo_t *font, float x, float y, float scale, float alpha, const char *text, float adjust, int limit, qboolean useColourCodes, qboolean is640);
|
void (*SetFrameNumber)(int frameNumber);
|
||||||
void (*Text_PaintChar)(fontInfo_t *font, float x, float y, float scale, int c, qboolean is640);
|
|
||||||
// su44
|
|
||||||
int (*GetShaderWidth)(qhandle_t shader);
|
|
||||||
int (*GetShaderHeight)(qhandle_t shader);
|
|
||||||
|
|
||||||
const char *(*GetGraphicsInfo)( );
|
|
||||||
void (*ForceUpdatePose)( refEntity_t *model );
|
|
||||||
orientation_t (*TIKI_Orientation)( refEntity_t *model, int tagNum );
|
|
||||||
qboolean (*TIKI_IsOnGround)( refEntity_t *model, int tagNum, float threshold );
|
|
||||||
void (*SetFrameNumber)( int frameNumber );
|
|
||||||
|
|
||||||
// obsolete functions
|
|
||||||
//void (*TakeVideoFrame)( int h, int w, byte* captureBuffer, byte *encodeBuffer, qboolean motionJpeg );
|
|
||||||
const char *(*GetShaderName)(qhandle_t shader);
|
|
||||||
void (*RegisterFont)(const char *fontName, int pointSize, fontInfo_t *font);
|
|
||||||
qboolean (*inPVS)( const vec3_t p1, const vec3_t p2 );
|
|
||||||
void (*UploadCinematic) (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty);
|
|
||||||
} refexport_t;
|
} refexport_t;
|
||||||
|
|
||||||
//
|
//
|
||||||
// these are the functions imported by the refresh module
|
// these are the functions imported by the refresh module
|
||||||
//
|
//
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// print message on the local console
|
// print message on the local console
|
||||||
void (QDECL *Printf)( int printLevel, const char *fmt, ...);
|
void (QDECL* Printf)(int printLevel, const char* fmt, ...);
|
||||||
|
|
||||||
// abort the game
|
// abort the game
|
||||||
void (QDECL *Error)( int errorLevel, const char *fmt, ...);
|
void (QDECL* Error)(int errorLevel, const char* fmt, ...);
|
||||||
|
|
||||||
// milliseconds should only be used for profiling, never
|
// milliseconds should only be used for profiling, never
|
||||||
// for anything game related. Get time from the refdef
|
// for anything game related. Get time from the refdef
|
||||||
int (*Milliseconds)( void );
|
int (*Milliseconds)(void);
|
||||||
|
|
||||||
// transform the text into its localized version
|
char* (*LV_ConvertString)(char* string);
|
||||||
const char *(*LV_ConvertString)( const char *text );
|
void (*Hunk_Clear)();
|
||||||
|
|
||||||
// stack based memory allocation for per-level things that
|
// stack based memory allocation for per-level things that
|
||||||
// won't be freed
|
// won't be freed
|
||||||
void (*Hunk_Clear )( void );
|
#ifdef HUNK_DEBUG
|
||||||
void *(*Hunk_Alloc)(size_t size );
|
void* (*Hunk_AllocDebug)(size_t size, const char* label, const char* file, int line);
|
||||||
void *(*Hunk_AllocateTempMemory)(size_t size );
|
#else
|
||||||
void (*Hunk_FreeTempMemory)( void *block );
|
void* (*Hunk_Alloc)(size_t size);
|
||||||
|
#endif
|
||||||
|
void* (*Hunk_AllocateTempMemory)(size_t size);
|
||||||
|
void (*Hunk_FreeTempMemory)(void* block);
|
||||||
|
|
||||||
// dynamic memory allocator for things that need to be freed
|
// dynamic memory allocator for things that need to be freed
|
||||||
void *(*Malloc)(size_t bytes );
|
void* (*Malloc)(size_t bytes);
|
||||||
void (*Free)( void *buf );
|
void (*Free)(void* buf);
|
||||||
void (*Clear)( void );
|
void (*Clear)();
|
||||||
|
|
||||||
cvar_t *(*Cvar_Get)( const char *name, const char *value, int flags );
|
cvar_t* (*Cvar_Get)(const char* name, const char* value, int flags);
|
||||||
void (*Cvar_Set)( const char *name, const char *value );
|
void (*Cvar_Set)(const char* name, const char* value);
|
||||||
void (*Cvar_SetDefault)( cvar_t *var, const char *value );
|
void (*Cvar_SetDefault)(cvar_t* var, const char* varValue);
|
||||||
|
|
||||||
void (*Cmd_AddCommand)( const char *name, void(*cmd)(void) );
|
void (*Cmd_AddCommand)(const char* name, void (*command) (void));
|
||||||
void (*Cmd_RemoveCommand)( const char *name );
|
void (*Cmd_RemoveCommand)(const char* name);
|
||||||
|
|
||||||
int (*Cmd_Argc) (void);
|
int (*Cmd_Argc) (void);
|
||||||
char *(*Cmd_Argv) (int i);
|
char* (*Cmd_Argv) (int i);
|
||||||
|
|
||||||
void (*Cmd_ExecuteText) (cbufExec_t exec_when, const char *text);
|
void (*Cmd_ExecuteText) (cbufExec_t exec_when, const char* text);
|
||||||
|
|
||||||
// visualization for debugging collision detection
|
// visualization for debugging collision detection
|
||||||
void (*CM_DrawDebugSurface)( void (*drawPoly)(int color, int numPoints, float *points) );
|
void (*CM_DrawDebugSurface)(void (*drawPoly)(int color, int numPoints, float* points));
|
||||||
|
|
||||||
// a -1 return means the file does not exist
|
// a -1 return means the file does not exist
|
||||||
// NULL can be passed for buf to just determine existance
|
// NULL can be passed for buf to just determine existance
|
||||||
int (*FS_FOpenFile)( const char *filename, fileHandle_t *file, qboolean uniqueFILE, qboolean quiet );
|
int (*FS_OpenFile)(const char* qpath, fileHandle_t* file, qboolean uniqueFILE, qboolean quiet);
|
||||||
size_t (*FS_Read)( void *buffer, size_t len, fileHandle_t f );
|
size_t(*FS_Read)(void* buffer, size_t len, fileHandle_t fileHandle);
|
||||||
void (*FS_CloseFile)( fileHandle_t f );
|
void (*FS_CloseFile)(fileHandle_t fileHandle);
|
||||||
int (*FS_Seek)( fileHandle_t f, long offset, fsOrigin_t origin );
|
int (*FS_Seek)(fileHandle_t fileHandle, long offset, fsOrigin_t origin);
|
||||||
int (*FS_FileIsInPAK)( const char *filename, int *pChecksum );
|
int (*FS_FileIsInPAK)(const char* name, int* pCheckSum);
|
||||||
int (*FS_ReadFile)( const char *name, void **buf );
|
int (*FS_ReadFile)(const char* name, void** buf);
|
||||||
int (*FS_ReadFileEx)( const char *name, void **buf, qboolean quiet );
|
int (*FS_ReadFileEx)(const char* qpath, void** buffer, qboolean quiet);
|
||||||
void (*FS_FreeFile)( void *buf );
|
void (*FS_FreeFile)(void* buf);
|
||||||
char ** (*FS_ListFiles)( const char *name, const char *extension, qboolean wantStubs, int *numfilesfound );
|
char** (*FS_ListFiles)(const char* name, const char* extension, qboolean wantSubs, int* numFiles);
|
||||||
void (*FS_FreeFileList)( char **filelist );
|
void (*FS_FreeFileList)(char** filelist);
|
||||||
int (*FS_WriteFile)( const char *qpath, const void *buffer, int size );
|
int (*FS_WriteFile)(const char* qpath, const void* buffer, int size);
|
||||||
qboolean (*FS_FileExists)( const char *file );
|
qboolean(*FS_FileExists)(const char* file);
|
||||||
|
|
||||||
// cm stuff
|
void (*CM_BoxTrace)(trace_t* results, const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, int model, int brushMask, int cylinder);
|
||||||
void (*CM_BoxTrace)( trace_t *results, const vec3_t start, const vec3_t end,
|
int (*CM_TerrainSquareType)(int terrainPatch, int i, int j);
|
||||||
const vec3_t mins, const vec3_t maxs,
|
char* (*CM_EntityString)();
|
||||||
clipHandle_t model, int brushmask, int cylinder );
|
const char* (*CM_MapTime)();
|
||||||
int (*CM_TerrainSquareType)( int iTerrainPatch, int i, int j );
|
int (*CG_PermanentMark)(const vec3_t origin, const vec3_t dir, float orientation, float sScale, float tScale, float red, float green, float blue, float alpha, qboolean doLighting, float sCenter, float tCenter, markFragment_t* markFragments, void* polyVerts);
|
||||||
char *(*CM_EntityString)( void );
|
int (*CG_PermanentTreadMarkDecal)(treadMark_t* treadMark, qboolean startSegment, qboolean doLighting, markFragment_t* markFragments, void* polyVerts);
|
||||||
const char *(*CM_MapTime)( void );
|
int (*CG_PermanentUpdateTreadMark)(treadMark_t* treadMark, float alpha, float minSegment, float maxSegment, float maxOffset, float texScale);
|
||||||
|
void (*CG_ProcessInitCommands)(dtiki_t* tiki, refEntity_t* ent);
|
||||||
|
void (*CG_EndTiki)(dtiki_t* tiki);
|
||||||
|
void (*SetPerformanceCounters)(int totalTris, int totalVerts, int totalTexels, int worldTris, int worldVerts, int characterLights);
|
||||||
|
|
||||||
// client game stuff
|
debugline_t** DebugLines;
|
||||||
int (*CG_PermanentMark)( vec3_t origin, vec3_t dir, float orientation,
|
int* numDebugLines;
|
||||||
float fSScale, float fTScale, float red, float green, float blue, float alpha,
|
debugstring_t** DebugStrings;
|
||||||
qboolean dolighting, float fSCenter, float fTCenter,
|
int* numDebugStrings;
|
||||||
markFragment_t *pMarkFragments, void *pPolyVerts );
|
|
||||||
int (*CG_PermanentTreadMarkDecal)( treadMark_t *pTread, qboolean bStartSegment, qboolean dolighting,
|
|
||||||
markFragment_t *pMarkFragments, void *pVoidPolyVerts );
|
|
||||||
int (*CG_PermanentUpdateTreadMark)( treadMark_t *pTread, float fAlpha, float fMinSegment, float fMaxSegment, float fMaxOffset, float fTexScale );
|
|
||||||
void (*CG_ProcessInitCommands)( dtiki_t *tiki, refEntity_t *ent );
|
|
||||||
void (*CG_EndTiki)( dtiki_t *tiki );
|
|
||||||
|
|
||||||
|
orientation_t(*TIKI_OrientationInternal)(dtiki_t* tiki, int entNum, int tagNum, float scale);
|
||||||
void (*SetPerformanceCounters)( int total_tris, int total_verts, int total_texels, int world_tris, int world_verts, int character_lights );
|
qboolean(*TIKI_IsOnGroundInternal)(dtiki_t* tiki, int entNum, int tagNum, float thresHold);
|
||||||
|
void (*TIKI_SetPoseInternal)(void* skeletor, const frameInfo_t* frameInfo, const int* boneTag, const vec4_t* boneQuat, float actionWeight);
|
||||||
// debugging stuff
|
void* (*TIKI_Alloc)(size_t size);
|
||||||
debugline_t **DebugLines;
|
float (*GetRadiusInternal)(dtiki_t* tiki, int entNum, float scale);
|
||||||
int *numDebugLines;
|
float (*GetCentroidRadiusInternal)(dtiki_t* tiki, int entNum, float scale, vec3_t centroid);
|
||||||
debugstring_t **DebugStrings;
|
void (*GetFrameInternal)(dtiki_t* tiki, int entNum, skelAnimFrame_t* newFrame);
|
||||||
int *numDebugStrings;
|
|
||||||
|
|
||||||
// TIKI stuff
|
|
||||||
orientation_t (*TIKI_OrientationInternal)( dtiki_t *tiki, int entnum, int tagnum, float scale );
|
|
||||||
qboolean (*TIKI_IsOnGroundInternal) (dtiki_t *tiki, int entnum, int tagnum, float threshold );
|
|
||||||
void (*TIKI_SetPoseInternal)( void *skeletor, const frameInfo_t *frameInfo, int *bone_tag, vec4_t *bone_quat, float actionWeight );
|
|
||||||
void *(*TIKI_Alloc)(size_t size );
|
|
||||||
float (*GetRadiusInternal)( dtiki_t *tiki, int entnum, float scale );
|
|
||||||
float (*GetCentroidRadiusInternal)( dtiki_t *tiki, int entnum, float scale, float *centroid );
|
|
||||||
void (*GetFrameInternal)( dtiki_t *tiki, int entnum, skelAnimFrame_t *newFrame );
|
|
||||||
|
|
||||||
// cinematic stuff
|
|
||||||
void (*CIN_UploadCinematic)(int handle);
|
|
||||||
int (*CIN_PlayCinematic)( const char *arg0, int xpos, int ypos, int width, int height, int bits);
|
|
||||||
e_status (*CIN_RunCinematic) (int handle);
|
|
||||||
|
|
||||||
void (*CL_WriteAVIVideoFrame)( const byte *buffer, int size );
|
|
||||||
|
|
||||||
// su44 - plugable renderer architecture
|
|
||||||
byte *(*CM_ClusterPVS)(int cluster);
|
|
||||||
|
|
||||||
// input event handling
|
|
||||||
void (*IN_Init)(void *windowData);
|
|
||||||
void (*IN_Shutdown)(void);
|
|
||||||
void (*IN_Restart)(void);
|
|
||||||
|
|
||||||
// system stuff
|
// system stuff
|
||||||
void (*Sys_SetEnv)(const char* name, const char* value);
|
void (*Sys_SetEnv)(const char* name, const char* value);
|
||||||
void (*Sys_GLimpSafeInit)(void);
|
void (*Sys_GLimpSafeInit)(void);
|
||||||
void (*Sys_GLimpInit)(void);
|
void (*Sys_GLimpInit)(void);
|
||||||
qboolean(*Sys_LowPhysicalMemory)(void);
|
qboolean(*Sys_LowPhysicalMemory)(void);
|
||||||
|
|
||||||
} refimport_t;
|
} refimport_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -300,8 +244,4 @@ typedef refexport_t* (QDECL *GetRefAPI_t) (int apiVersion, refimport_t * rimp);
|
||||||
refexport_t*GetRefAPI( int apiVersion, refimport_t *rimp );
|
refexport_t*GetRefAPI( int apiVersion, refimport_t *rimp );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __TR_PUBLIC_H
|
#endif // __TR_PUBLIC_H
|
||||||
|
|
|
@ -20,19 +20,16 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
===========================================================================
|
===========================================================================
|
||||||
*/
|
*/
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../cgame/tr_types.h"
|
||||||
|
|
||||||
|
|
||||||
#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces
|
#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces
|
||||||
|
|
||||||
#define REFENTITYNUM_BITS 10 // can't be increased without changing drawsurf bit packing
|
#define REFENTITYNUM_BITS 10 // can't be increased without changing drawsurf bit packing
|
||||||
#define REFSPRITE_BITS 10 // can't be increased without changing drawsurf bit packing
|
|
||||||
#define REFENTITYNUM_MASK ((1<<REFENTITYNUM_BITS) - 1)
|
#define REFENTITYNUM_MASK ((1<<REFENTITYNUM_BITS) - 1)
|
||||||
// the last N-bit number (2^REFENTITYNUM_BITS - 1) is reserved for the special world refentity,
|
// the last N-bit number (2^REFENTITYNUM_BITS - 1) is reserved for the special world refentity,
|
||||||
// and this is reflected by the value of MAX_REFENTITIES (which therefore is not a power-of-2)
|
// and this is reflected by the value of MAX_REFENTITIES (which therefore is not a power-of-2)
|
||||||
#define MAX_REFENTITIES ((1<<REFENTITYNUM_BITS) - 1)
|
#define MAX_REFENTITIES ((1<<REFENTITYNUM_BITS) - 1)
|
||||||
#define MAX_REFSPRITES ((1<<REFSPRITE_BITS) - 1)
|
|
||||||
#define REFENTITYNUM_WORLD ((1<<REFENTITYNUM_BITS) - 1)
|
#define REFENTITYNUM_WORLD ((1<<REFENTITYNUM_BITS) - 1)
|
||||||
|
|
||||||
#define MAX_RENDER_STRINGS 8
|
|
||||||
#define MAX_RENDER_STRING_LENGTH 32
|
|
||||||
|
|
414
code/renderergl1/tr_altivec.c
Normal file
414
code/renderergl1/tr_altivec.c
Normal file
|
@ -0,0 +1,414 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file is only compiled for PowerPC builds with Altivec support.
|
||||||
|
Altivec intrinsics need to be in a separate file, so GCC's -maltivec
|
||||||
|
command line can enable them, but give us the option to _not_ use that
|
||||||
|
on other files, where the compiler might then generate Altivec
|
||||||
|
instructions for normal floating point, crashing on G3 (etc) processors. */
|
||||||
|
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
#if idppc_altivec
|
||||||
|
|
||||||
|
#if !defined(__APPLE__)
|
||||||
|
#include <altivec.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ProjectDlightTexture_altivec( void ) {
|
||||||
|
int i, l;
|
||||||
|
vec_t origin0, origin1, origin2;
|
||||||
|
float texCoords0, texCoords1;
|
||||||
|
vector float floatColorVec0, floatColorVec1;
|
||||||
|
vector float modulateVec, colorVec, zero;
|
||||||
|
vector short colorShort;
|
||||||
|
vector signed int colorInt;
|
||||||
|
vector unsigned char floatColorVecPerm, modulatePerm, colorChar;
|
||||||
|
vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0xff);
|
||||||
|
float *texCoords;
|
||||||
|
byte *colors;
|
||||||
|
byte clipBits[SHADER_MAX_VERTEXES];
|
||||||
|
float texCoordsArray[SHADER_MAX_VERTEXES][2];
|
||||||
|
byte colorArray[SHADER_MAX_VERTEXES][4];
|
||||||
|
glIndex_t hitIndexes[SHADER_MAX_INDEXES];
|
||||||
|
int numIndexes;
|
||||||
|
float scale;
|
||||||
|
float radius;
|
||||||
|
vec3_t floatColor;
|
||||||
|
float modulate = 0.0f;
|
||||||
|
|
||||||
|
if ( !backEnd.refdef.num_dlights ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There has to be a better way to do this so that floatColor
|
||||||
|
// and/or modulate are already 16-byte aligned.
|
||||||
|
floatColorVecPerm = vec_lvsl(0,(float *)floatColor);
|
||||||
|
modulatePerm = vec_lvsl(0,(float *)&modulate);
|
||||||
|
modulatePerm = (vector unsigned char)vec_splat((vector unsigned int)modulatePerm,0);
|
||||||
|
zero = (vector float)vec_splat_s8(0);
|
||||||
|
|
||||||
|
for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
|
||||||
|
dlight_t *dl;
|
||||||
|
|
||||||
|
if ( !( tess.dlightBits & ( 1 << l ) ) ) {
|
||||||
|
continue; // this surface definitely doesn't have any of this light
|
||||||
|
}
|
||||||
|
texCoords = texCoordsArray[0];
|
||||||
|
colors = colorArray[0];
|
||||||
|
|
||||||
|
dl = &backEnd.refdef.dlights[l];
|
||||||
|
origin0 = dl->transformed[0];
|
||||||
|
origin1 = dl->transformed[1];
|
||||||
|
origin2 = dl->transformed[2];
|
||||||
|
radius = dl->radius;
|
||||||
|
scale = 1.0f / radius;
|
||||||
|
|
||||||
|
if(r_greyscale->integer)
|
||||||
|
{
|
||||||
|
float luminance;
|
||||||
|
|
||||||
|
luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f;
|
||||||
|
floatColor[0] = floatColor[1] = floatColor[2] = luminance;
|
||||||
|
}
|
||||||
|
else if(r_greyscale->value)
|
||||||
|
{
|
||||||
|
float luminance;
|
||||||
|
|
||||||
|
luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f;
|
||||||
|
floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value);
|
||||||
|
floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value);
|
||||||
|
floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
floatColor[0] = dl->color[0] * 255.0f;
|
||||||
|
floatColor[1] = dl->color[1] * 255.0f;
|
||||||
|
floatColor[2] = dl->color[2] * 255.0f;
|
||||||
|
}
|
||||||
|
floatColorVec0 = vec_ld(0, floatColor);
|
||||||
|
floatColorVec1 = vec_ld(11, floatColor);
|
||||||
|
floatColorVec0 = vec_perm(floatColorVec0,floatColorVec0,floatColorVecPerm);
|
||||||
|
for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) {
|
||||||
|
int clip = 0;
|
||||||
|
vec_t dist0, dist1, dist2;
|
||||||
|
|
||||||
|
dist0 = origin0 - tess.xyz[i][0];
|
||||||
|
dist1 = origin1 - tess.xyz[i][1];
|
||||||
|
dist2 = origin2 - tess.xyz[i][2];
|
||||||
|
|
||||||
|
backEnd.pc.c_dlightVertexes++;
|
||||||
|
|
||||||
|
texCoords0 = 0.5f + dist0 * scale;
|
||||||
|
texCoords1 = 0.5f + dist1 * scale;
|
||||||
|
|
||||||
|
if( !r_dlightBacks->integer &&
|
||||||
|
// dist . tess.normal[i]
|
||||||
|
( dist0 * tess.normal[i][0] +
|
||||||
|
dist1 * tess.normal[i][1] +
|
||||||
|
dist2 * tess.normal[i][2] ) < 0.0f ) {
|
||||||
|
clip = 63;
|
||||||
|
} else {
|
||||||
|
if ( texCoords0 < 0.0f ) {
|
||||||
|
clip |= 1;
|
||||||
|
} else if ( texCoords0 > 1.0f ) {
|
||||||
|
clip |= 2;
|
||||||
|
}
|
||||||
|
if ( texCoords1 < 0.0f ) {
|
||||||
|
clip |= 4;
|
||||||
|
} else if ( texCoords1 > 1.0f ) {
|
||||||
|
clip |= 8;
|
||||||
|
}
|
||||||
|
texCoords[0] = texCoords0;
|
||||||
|
texCoords[1] = texCoords1;
|
||||||
|
|
||||||
|
// modulate the strength based on the height and color
|
||||||
|
if ( dist2 > radius ) {
|
||||||
|
clip |= 16;
|
||||||
|
modulate = 0.0f;
|
||||||
|
} else if ( dist2 < -radius ) {
|
||||||
|
clip |= 32;
|
||||||
|
modulate = 0.0f;
|
||||||
|
} else {
|
||||||
|
dist2 = Q_fabs(dist2);
|
||||||
|
if ( dist2 < radius * 0.5f ) {
|
||||||
|
modulate = 1.0f;
|
||||||
|
} else {
|
||||||
|
modulate = 2.0f * (radius - dist2) * scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clipBits[i] = clip;
|
||||||
|
|
||||||
|
modulateVec = vec_ld(0,(float *)&modulate);
|
||||||
|
modulateVec = vec_perm(modulateVec,modulateVec,modulatePerm);
|
||||||
|
colorVec = vec_madd(floatColorVec0,modulateVec,zero);
|
||||||
|
colorInt = vec_cts(colorVec,0); // RGBx
|
||||||
|
colorShort = vec_pack(colorInt,colorInt); // RGBxRGBx
|
||||||
|
colorChar = vec_packsu(colorShort,colorShort); // RGBxRGBxRGBxRGBx
|
||||||
|
colorChar = vec_sel(colorChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255
|
||||||
|
vec_ste((vector unsigned int)colorChar,0,(unsigned int *)colors); // store color
|
||||||
|
}
|
||||||
|
|
||||||
|
// build a list of triangles that need light
|
||||||
|
numIndexes = 0;
|
||||||
|
for ( i = 0 ; i < tess.numIndexes ; i += 3 ) {
|
||||||
|
int a, b, c;
|
||||||
|
|
||||||
|
a = tess.indexes[i];
|
||||||
|
b = tess.indexes[i+1];
|
||||||
|
c = tess.indexes[i+2];
|
||||||
|
if ( clipBits[a] & clipBits[b] & clipBits[c] ) {
|
||||||
|
continue; // not lighted
|
||||||
|
}
|
||||||
|
hitIndexes[numIndexes] = a;
|
||||||
|
hitIndexes[numIndexes+1] = b;
|
||||||
|
hitIndexes[numIndexes+2] = c;
|
||||||
|
numIndexes += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !numIndexes ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||||
|
qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );
|
||||||
|
|
||||||
|
qglEnableClientState( GL_COLOR_ARRAY );
|
||||||
|
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );
|
||||||
|
|
||||||
|
GL_Bind( tr.dlightImage );
|
||||||
|
// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
|
||||||
|
// where they aren't rendered
|
||||||
|
if ( dl->additive ) {
|
||||||
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
|
||||||
|
}
|
||||||
|
R_DrawElements( numIndexes, hitIndexes );
|
||||||
|
backEnd.pc.c_totalIndexes += numIndexes;
|
||||||
|
backEnd.pc.c_dlightIndexes += numIndexes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RB_CalcDiffuseColor_altivec( unsigned char *colors )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float *v, *normal;
|
||||||
|
trRefEntity_t *ent;
|
||||||
|
int ambientLightInt;
|
||||||
|
vec3_t lightDir;
|
||||||
|
int numVertexes;
|
||||||
|
vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0xff);
|
||||||
|
vector float ambientLightVec;
|
||||||
|
vector float directedLightVec;
|
||||||
|
vector float lightDirVec;
|
||||||
|
vector float normalVec0, normalVec1;
|
||||||
|
vector float incomingVec0, incomingVec1, incomingVec2;
|
||||||
|
vector float zero, jVec;
|
||||||
|
vector signed int jVecInt;
|
||||||
|
vector signed short jVecShort;
|
||||||
|
vector unsigned char jVecChar, normalPerm;
|
||||||
|
ent = backEnd.currentEntity;
|
||||||
|
ambientLightInt = ent->ambientLightInt;
|
||||||
|
// A lot of this could be simplified if we made sure
|
||||||
|
// entities light info was 16-byte aligned.
|
||||||
|
jVecChar = vec_lvsl(0, ent->ambientLight);
|
||||||
|
ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight);
|
||||||
|
jVec = vec_ld(11, (vector float *)ent->ambientLight);
|
||||||
|
ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar);
|
||||||
|
|
||||||
|
jVecChar = vec_lvsl(0, ent->directedLight);
|
||||||
|
directedLightVec = vec_ld(0,(vector float *)ent->directedLight);
|
||||||
|
jVec = vec_ld(11,(vector float *)ent->directedLight);
|
||||||
|
directedLightVec = vec_perm(directedLightVec,jVec,jVecChar);
|
||||||
|
|
||||||
|
jVecChar = vec_lvsl(0, ent->lightDir);
|
||||||
|
lightDirVec = vec_ld(0,(vector float *)ent->lightDir);
|
||||||
|
jVec = vec_ld(11,(vector float *)ent->lightDir);
|
||||||
|
lightDirVec = vec_perm(lightDirVec,jVec,jVecChar);
|
||||||
|
|
||||||
|
zero = (vector float)vec_splat_s8(0);
|
||||||
|
VectorCopy( ent->lightDir, lightDir );
|
||||||
|
|
||||||
|
v = tess.xyz[0];
|
||||||
|
normal = tess.normal[0];
|
||||||
|
|
||||||
|
normalPerm = vec_lvsl(0,normal);
|
||||||
|
numVertexes = tess.numVertexes;
|
||||||
|
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
|
||||||
|
normalVec0 = vec_ld(0,(vector float *)normal);
|
||||||
|
normalVec1 = vec_ld(11,(vector float *)normal);
|
||||||
|
normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm);
|
||||||
|
incomingVec0 = vec_madd(normalVec0, lightDirVec, zero);
|
||||||
|
incomingVec1 = vec_sld(incomingVec0,incomingVec0,4);
|
||||||
|
incomingVec2 = vec_add(incomingVec0,incomingVec1);
|
||||||
|
incomingVec1 = vec_sld(incomingVec1,incomingVec1,4);
|
||||||
|
incomingVec2 = vec_add(incomingVec2,incomingVec1);
|
||||||
|
incomingVec0 = vec_splat(incomingVec2,0);
|
||||||
|
incomingVec0 = vec_max(incomingVec0,zero);
|
||||||
|
normalPerm = vec_lvsl(12,normal);
|
||||||
|
jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec);
|
||||||
|
jVecInt = vec_cts(jVec,0); // RGBx
|
||||||
|
jVecShort = vec_pack(jVecInt,jVecInt); // RGBxRGBx
|
||||||
|
jVecChar = vec_packsu(jVecShort,jVecShort); // RGBxRGBxRGBxRGBx
|
||||||
|
jVecChar = vec_sel(jVecChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255
|
||||||
|
vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]); // store color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp)
|
||||||
|
{
|
||||||
|
short *oldXyz, *newXyz, *oldNormals, *newNormals;
|
||||||
|
float *outXyz, *outNormal;
|
||||||
|
float oldXyzScale QALIGN(16);
|
||||||
|
float newXyzScale QALIGN(16);
|
||||||
|
float oldNormalScale QALIGN(16);
|
||||||
|
float newNormalScale QALIGN(16);
|
||||||
|
int vertNum;
|
||||||
|
unsigned lat, lng;
|
||||||
|
int numVerts;
|
||||||
|
|
||||||
|
outXyz = tess.xyz[tess.numVertexes];
|
||||||
|
outNormal = tess.normal[tess.numVertexes];
|
||||||
|
|
||||||
|
newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
|
||||||
|
+ (backEnd.currentEntity->e.frame * surf->numVerts * 4);
|
||||||
|
newNormals = newXyz + 3;
|
||||||
|
|
||||||
|
newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
|
||||||
|
newNormalScale = 1.0 - backlerp;
|
||||||
|
|
||||||
|
numVerts = surf->numVerts;
|
||||||
|
|
||||||
|
if ( backlerp == 0 ) {
|
||||||
|
vector signed short newNormalsVec0;
|
||||||
|
vector signed short newNormalsVec1;
|
||||||
|
vector signed int newNormalsIntVec;
|
||||||
|
vector float newNormalsFloatVec;
|
||||||
|
vector float newXyzScaleVec;
|
||||||
|
vector unsigned char newNormalsLoadPermute;
|
||||||
|
vector unsigned char newNormalsStorePermute;
|
||||||
|
vector float zero;
|
||||||
|
|
||||||
|
newNormalsStorePermute = vec_lvsl(0,(float *)&newXyzScaleVec);
|
||||||
|
newXyzScaleVec = *(vector float *)&newXyzScale;
|
||||||
|
newXyzScaleVec = vec_perm(newXyzScaleVec,newXyzScaleVec,newNormalsStorePermute);
|
||||||
|
newXyzScaleVec = vec_splat(newXyzScaleVec,0);
|
||||||
|
newNormalsLoadPermute = vec_lvsl(0,newXyz);
|
||||||
|
newNormalsStorePermute = vec_lvsr(0,outXyz);
|
||||||
|
zero = (vector float)vec_splat_s8(0);
|
||||||
|
//
|
||||||
|
// just copy the vertexes
|
||||||
|
//
|
||||||
|
for (vertNum=0 ; vertNum < numVerts ; vertNum++,
|
||||||
|
newXyz += 4, newNormals += 4,
|
||||||
|
outXyz += 4, outNormal += 4)
|
||||||
|
{
|
||||||
|
newNormalsLoadPermute = vec_lvsl(0,newXyz);
|
||||||
|
newNormalsStorePermute = vec_lvsr(0,outXyz);
|
||||||
|
newNormalsVec0 = vec_ld(0,newXyz);
|
||||||
|
newNormalsVec1 = vec_ld(16,newXyz);
|
||||||
|
newNormalsVec0 = vec_perm(newNormalsVec0,newNormalsVec1,newNormalsLoadPermute);
|
||||||
|
newNormalsIntVec = vec_unpackh(newNormalsVec0);
|
||||||
|
newNormalsFloatVec = vec_ctf(newNormalsIntVec,0);
|
||||||
|
newNormalsFloatVec = vec_madd(newNormalsFloatVec,newXyzScaleVec,zero);
|
||||||
|
newNormalsFloatVec = vec_perm(newNormalsFloatVec,newNormalsFloatVec,newNormalsStorePermute);
|
||||||
|
//outXyz[0] = newXyz[0] * newXyzScale;
|
||||||
|
//outXyz[1] = newXyz[1] * newXyzScale;
|
||||||
|
//outXyz[2] = newXyz[2] * newXyzScale;
|
||||||
|
|
||||||
|
lat = ( newNormals[0] >> 8 ) & 0xff;
|
||||||
|
lng = ( newNormals[0] & 0xff );
|
||||||
|
lat *= (FUNCTABLE_SIZE/256);
|
||||||
|
lng *= (FUNCTABLE_SIZE/256);
|
||||||
|
|
||||||
|
// decode X as cos( lat ) * sin( long )
|
||||||
|
// decode Y as sin( lat ) * sin( long )
|
||||||
|
// decode Z as cos( long )
|
||||||
|
|
||||||
|
outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
|
||||||
|
outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
|
||||||
|
outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
|
||||||
|
|
||||||
|
vec_ste(newNormalsFloatVec,0,outXyz);
|
||||||
|
vec_ste(newNormalsFloatVec,4,outXyz);
|
||||||
|
vec_ste(newNormalsFloatVec,8,outXyz);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// interpolate and copy the vertex and normal
|
||||||
|
//
|
||||||
|
oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
|
||||||
|
+ (backEnd.currentEntity->e.oldframe * surf->numVerts * 4);
|
||||||
|
oldNormals = oldXyz + 3;
|
||||||
|
|
||||||
|
oldXyzScale = MD3_XYZ_SCALE * backlerp;
|
||||||
|
oldNormalScale = backlerp;
|
||||||
|
|
||||||
|
for (vertNum=0 ; vertNum < numVerts ; vertNum++,
|
||||||
|
oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
|
||||||
|
outXyz += 4, outNormal += 4)
|
||||||
|
{
|
||||||
|
vec3_t uncompressedOldNormal, uncompressedNewNormal;
|
||||||
|
|
||||||
|
// interpolate the xyz
|
||||||
|
outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
|
||||||
|
outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
|
||||||
|
outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
|
||||||
|
|
||||||
|
// FIXME: interpolate lat/long instead?
|
||||||
|
lat = ( newNormals[0] >> 8 ) & 0xff;
|
||||||
|
lng = ( newNormals[0] & 0xff );
|
||||||
|
lat *= 4;
|
||||||
|
lng *= 4;
|
||||||
|
uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
|
||||||
|
uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
|
||||||
|
uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
|
||||||
|
|
||||||
|
lat = ( oldNormals[0] >> 8 ) & 0xff;
|
||||||
|
lng = ( oldNormals[0] & 0xff );
|
||||||
|
lat *= 4;
|
||||||
|
lng *= 4;
|
||||||
|
|
||||||
|
uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
|
||||||
|
uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
|
||||||
|
uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
|
||||||
|
|
||||||
|
outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
|
||||||
|
outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
|
||||||
|
outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
|
||||||
|
|
||||||
|
// VectorNormalize (outNormal);
|
||||||
|
}
|
||||||
|
VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -35,7 +35,6 @@ frame.
|
||||||
|
|
||||||
|
|
||||||
// copied and adapted from tr_mesh.c
|
// copied and adapted from tr_mesh.c
|
||||||
#if 0
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
|
@ -189,13 +188,11 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
|
||||||
int lodnum = 0;
|
int lodnum = 0;
|
||||||
int fogNum = 0;
|
int fogNum = 0;
|
||||||
int cull;
|
int cull;
|
||||||
int cubemapIndex;
|
|
||||||
qboolean personalModel;
|
qboolean personalModel;
|
||||||
|
|
||||||
header = (mdrHeader_t *) tr.currentModel->modelData;
|
header = (mdrHeader_t *) tr.currentModel->modelData;
|
||||||
|
|
||||||
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal
|
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
|
||||||
|| (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW)));
|
|
||||||
|
|
||||||
if ( ent->e.renderfx & RF_WRAP_FRAMES )
|
if ( ent->e.renderfx & RF_WRAP_FRAMES )
|
||||||
{
|
{
|
||||||
|
@ -252,8 +249,6 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
|
||||||
// fogNum?
|
// fogNum?
|
||||||
fogNum = R_MDRComputeFogNum( header, ent );
|
fogNum = R_MDRComputeFogNum( header, ent );
|
||||||
|
|
||||||
cubemapIndex = R_CubemapForPoint(ent->e.origin);
|
|
||||||
|
|
||||||
surface = (mdrSurface_t *)( (byte *)lod + lod->ofsSurfaces );
|
surface = (mdrSurface_t *)( (byte *)lod + lod->ofsSurfaces );
|
||||||
|
|
||||||
for ( i = 0 ; i < lod->numSurfaces ; i++ )
|
for ( i = 0 ; i < lod->numSurfaces ; i++ )
|
||||||
|
@ -268,9 +263,9 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
|
||||||
|
|
||||||
for(j = 0; j < skin->numSurfaces; j++)
|
for(j = 0; j < skin->numSurfaces; j++)
|
||||||
{
|
{
|
||||||
if (!strcmp(skin->surfaces[j]->name, surface->name))
|
if (!strcmp(skin->surfaces[j].name, surface->name))
|
||||||
{
|
{
|
||||||
shader = skin->surfaces[j]->shader;
|
shader = skin->surfaces[j].shader;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,7 +284,7 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
|
||||||
&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
|
&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
|
||||||
&& shader->sort == SS_OPAQUE )
|
&& shader->sort == SS_OPAQUE )
|
||||||
{
|
{
|
||||||
R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse, qfalse, 0 );
|
R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse );
|
||||||
}
|
}
|
||||||
|
|
||||||
// projection shadows work fine with personal models
|
// projection shadows work fine with personal models
|
||||||
|
@ -298,11 +293,11 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
|
||||||
&& (ent->e.renderfx & RF_SHADOW_PLANE )
|
&& (ent->e.renderfx & RF_SHADOW_PLANE )
|
||||||
&& shader->sort == SS_OPAQUE )
|
&& shader->sort == SS_OPAQUE )
|
||||||
{
|
{
|
||||||
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse, 0 );
|
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!personalModel)
|
if (!personalModel)
|
||||||
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse, qfalse, cubemapIndex );
|
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse );
|
||||||
|
|
||||||
surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd );
|
surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd );
|
||||||
}
|
}
|
||||||
|
@ -413,7 +408,9 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface )
|
||||||
tess.xyz[baseVertex + j][1] = tempVert[1];
|
tess.xyz[baseVertex + j][1] = tempVert[1];
|
||||||
tess.xyz[baseVertex + j][2] = tempVert[2];
|
tess.xyz[baseVertex + j][2] = tempVert[2];
|
||||||
|
|
||||||
R_VaoPackNormal((byte *)&tess.normal[baseVertex + j], tempNormal);
|
tess.normal[baseVertex + j][0] = tempNormal[0];
|
||||||
|
tess.normal[baseVertex + j][1] = tempNormal[1];
|
||||||
|
tess.normal[baseVertex + j][2] = tempNormal[2];
|
||||||
|
|
||||||
tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
|
tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
|
||||||
tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
|
tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
|
||||||
|
@ -522,5 +519,3 @@ void MC_UnCompress(float mat[3][4],const unsigned char * comp)
|
||||||
val-=1<<(MC_BITS_VECT-1);
|
val-=1<<(MC_BITS_VECT-1);
|
||||||
mat[2][2]=((float)(val))*MC_SCALE_VECT;
|
mat[2][2]=((float)(val))*MC_SCALE_VECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
1151
code/renderergl1/tr_backend.c
Normal file
1151
code/renderergl1/tr_backend.c
Normal file
File diff suppressed because it is too large
Load diff
1870
code/renderergl1/tr_bsp.c
Normal file
1870
code/renderergl1/tr_bsp.c
Normal file
File diff suppressed because it is too large
Load diff
514
code/renderergl1/tr_cmds.c
Normal file
514
code/renderergl1/tr_cmds.c
Normal file
|
@ -0,0 +1,514 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
R_PerformanceCounters
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void R_PerformanceCounters( void ) {
|
||||||
|
if ( !r_speeds->integer ) {
|
||||||
|
// clear the counters even if we aren't printing
|
||||||
|
Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
|
||||||
|
Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_speeds->integer == 1) {
|
||||||
|
ri.Printf (PRINT_ALL, "%i/%i shaders/surfs %i leafs %i verts %i/%i tris %.2f mtex %.2f dc\n",
|
||||||
|
backEnd.pc.c_shaders, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes,
|
||||||
|
backEnd.pc.c_indexes/3, backEnd.pc.c_totalIndexes/3,
|
||||||
|
R_SumOfUsedImages()/(1000000.0f), backEnd.pc.c_overDraw / (float)(glConfig.vidWidth * glConfig.vidHeight) );
|
||||||
|
} else if (r_speeds->integer == 2) {
|
||||||
|
ri.Printf (PRINT_ALL, "(patch) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
|
||||||
|
tr.pc.c_sphere_cull_patch_in, tr.pc.c_sphere_cull_patch_clip, tr.pc.c_sphere_cull_patch_out,
|
||||||
|
tr.pc.c_box_cull_patch_in, tr.pc.c_box_cull_patch_clip, tr.pc.c_box_cull_patch_out );
|
||||||
|
ri.Printf (PRINT_ALL, "(md3) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
|
||||||
|
tr.pc.c_sphere_cull_md3_in, tr.pc.c_sphere_cull_md3_clip, tr.pc.c_sphere_cull_md3_out,
|
||||||
|
tr.pc.c_box_cull_md3_in, tr.pc.c_box_cull_md3_clip, tr.pc.c_box_cull_md3_out );
|
||||||
|
} else if (r_speeds->integer == 3) {
|
||||||
|
ri.Printf (PRINT_ALL, "viewcluster: %i\n", tr.viewCluster );
|
||||||
|
} else if (r_speeds->integer == 4) {
|
||||||
|
if ( backEnd.pc.c_dlightVertexes ) {
|
||||||
|
ri.Printf (PRINT_ALL, "dlight srf:%i culled:%i verts:%i tris:%i\n",
|
||||||
|
tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled,
|
||||||
|
backEnd.pc.c_dlightVertexes, backEnd.pc.c_dlightIndexes / 3 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (r_speeds->integer == 5 )
|
||||||
|
{
|
||||||
|
ri.Printf( PRINT_ALL, "zFar: %.0f\n", tr.viewParms.zFar );
|
||||||
|
}
|
||||||
|
else if (r_speeds->integer == 6 )
|
||||||
|
{
|
||||||
|
ri.Printf( PRINT_ALL, "flare adds:%i tests:%i renders:%i\n",
|
||||||
|
backEnd.pc.c_flareAdds, backEnd.pc.c_flareTests, backEnd.pc.c_flareRenders );
|
||||||
|
}
|
||||||
|
|
||||||
|
Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
|
||||||
|
Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
R_IssueRenderCommands
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
void R_IssueRenderCommands( qboolean runPerformanceCounters ) {
|
||||||
|
renderCommandList_t *cmdList;
|
||||||
|
|
||||||
|
cmdList = &backEndData->commands;
|
||||||
|
assert(cmdList);
|
||||||
|
// add an end-of-list command
|
||||||
|
*(int *)(cmdList->cmds + cmdList->used) = RC_END_OF_LIST;
|
||||||
|
|
||||||
|
// clear it out, in case this is a sync and not a buffer flip
|
||||||
|
cmdList->used = 0;
|
||||||
|
|
||||||
|
if ( runPerformanceCounters ) {
|
||||||
|
R_PerformanceCounters();
|
||||||
|
}
|
||||||
|
|
||||||
|
// actually start the commands going
|
||||||
|
if ( !r_skipBackEnd->integer ) {
|
||||||
|
// let it start on the new batch
|
||||||
|
RB_ExecuteRenderCommands( cmdList->cmds );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
R_IssuePendingRenderCommands
|
||||||
|
|
||||||
|
Issue any pending commands and wait for them to complete.
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
void R_IssuePendingRenderCommands( void ) {
|
||||||
|
if ( !tr.registered ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
R_IssueRenderCommands( qfalse );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
============
|
||||||
|
R_GetCommandBufferReserved
|
||||||
|
|
||||||
|
make sure there is enough command space
|
||||||
|
============
|
||||||
|
*/
|
||||||
|
void *R_GetCommandBufferReserved( int bytes, int reservedBytes ) {
|
||||||
|
renderCommandList_t *cmdList;
|
||||||
|
|
||||||
|
cmdList = &backEndData->commands;
|
||||||
|
bytes = PAD(bytes, sizeof(void *));
|
||||||
|
|
||||||
|
// always leave room for the end of list command
|
||||||
|
if ( cmdList->used + bytes + sizeof( int ) + reservedBytes > MAX_RENDER_COMMANDS ) {
|
||||||
|
if ( bytes > MAX_RENDER_COMMANDS - sizeof( int ) ) {
|
||||||
|
ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes );
|
||||||
|
}
|
||||||
|
// if we run out of room, just start dropping commands
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdList->used += bytes;
|
||||||
|
|
||||||
|
return cmdList->cmds + cmdList->used - bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_GetCommandBuffer
|
||||||
|
|
||||||
|
returns NULL if there is not enough space for important commands
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void *R_GetCommandBuffer( int bytes ) {
|
||||||
|
return R_GetCommandBufferReserved( bytes, PAD( sizeof( swapBuffersCommand_t ), sizeof(void *) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_AddDrawSurfCmd
|
||||||
|
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||||
|
drawSurfsCommand_t *cmd;
|
||||||
|
|
||||||
|
cmd = R_GetCommandBuffer( sizeof( *cmd ) );
|
||||||
|
if ( !cmd ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmd->commandId = RC_DRAW_SURFS;
|
||||||
|
|
||||||
|
cmd->drawSurfs = drawSurfs;
|
||||||
|
cmd->numDrawSurfs = numDrawSurfs;
|
||||||
|
|
||||||
|
cmd->refdef = tr.refdef;
|
||||||
|
cmd->viewParms = tr.viewParms;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
RE_SetColor
|
||||||
|
|
||||||
|
Passing NULL will set the color to white
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void RE_SetColor( const float *rgba ) {
|
||||||
|
setColorCommand_t *cmd;
|
||||||
|
|
||||||
|
if ( !tr.registered ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmd = R_GetCommandBuffer( sizeof( *cmd ) );
|
||||||
|
if ( !cmd ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmd->commandId = RC_SET_COLOR;
|
||||||
|
if ( !rgba ) {
|
||||||
|
static float colorWhite[4] = { 1, 1, 1, 1 };
|
||||||
|
|
||||||
|
rgba = colorWhite;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->color[0] = rgba[0];
|
||||||
|
cmd->color[1] = rgba[1];
|
||||||
|
cmd->color[2] = rgba[2];
|
||||||
|
cmd->color[3] = rgba[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
RE_StretchPic
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void RE_StretchPic ( float x, float y, float w, float h,
|
||||||
|
float s1, float t1, float s2, float t2, qhandle_t hShader ) {
|
||||||
|
stretchPicCommand_t *cmd;
|
||||||
|
|
||||||
|
if (!tr.registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmd = R_GetCommandBuffer( sizeof( *cmd ) );
|
||||||
|
if ( !cmd ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmd->commandId = RC_STRETCH_PIC;
|
||||||
|
cmd->shader = R_GetShaderByHandle( hShader );
|
||||||
|
cmd->x = x;
|
||||||
|
cmd->y = y;
|
||||||
|
cmd->w = w;
|
||||||
|
cmd->h = h;
|
||||||
|
cmd->s1 = s1;
|
||||||
|
cmd->t1 = t1;
|
||||||
|
cmd->s2 = s2;
|
||||||
|
cmd->t2 = t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MODE_RED_CYAN 1
|
||||||
|
#define MODE_RED_BLUE 2
|
||||||
|
#define MODE_RED_GREEN 3
|
||||||
|
#define MODE_GREEN_MAGENTA 4
|
||||||
|
#define MODE_MAX MODE_GREEN_MAGENTA
|
||||||
|
|
||||||
|
void R_SetColorMode(GLboolean *rgba, stereoFrame_t stereoFrame, int colormode)
|
||||||
|
{
|
||||||
|
rgba[0] = rgba[1] = rgba[2] = rgba[3] = GL_TRUE;
|
||||||
|
|
||||||
|
if(colormode > MODE_MAX)
|
||||||
|
{
|
||||||
|
if(stereoFrame == STEREO_LEFT)
|
||||||
|
stereoFrame = STEREO_RIGHT;
|
||||||
|
else if(stereoFrame == STEREO_RIGHT)
|
||||||
|
stereoFrame = STEREO_LEFT;
|
||||||
|
|
||||||
|
colormode -= MODE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(colormode == MODE_GREEN_MAGENTA)
|
||||||
|
{
|
||||||
|
if(stereoFrame == STEREO_LEFT)
|
||||||
|
rgba[0] = rgba[2] = GL_FALSE;
|
||||||
|
else if(stereoFrame == STEREO_RIGHT)
|
||||||
|
rgba[1] = GL_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(stereoFrame == STEREO_LEFT)
|
||||||
|
rgba[1] = rgba[2] = GL_FALSE;
|
||||||
|
else if(stereoFrame == STEREO_RIGHT)
|
||||||
|
{
|
||||||
|
rgba[0] = GL_FALSE;
|
||||||
|
|
||||||
|
if(colormode == MODE_RED_BLUE)
|
||||||
|
rgba[1] = GL_FALSE;
|
||||||
|
else if(colormode == MODE_RED_GREEN)
|
||||||
|
rgba[2] = GL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
RE_BeginFrame
|
||||||
|
|
||||||
|
If running in stereo, RE_BeginFrame will be called twice
|
||||||
|
for each RE_EndFrame
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
void RE_BeginFrame( stereoFrame_t stereoFrame ) {
|
||||||
|
drawBufferCommand_t *cmd = NULL;
|
||||||
|
colorMaskCommand_t *colcmd = NULL;
|
||||||
|
|
||||||
|
if ( !tr.registered ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glState.finishCalled = qfalse;
|
||||||
|
|
||||||
|
tr.frameCount++;
|
||||||
|
tr.frameSceneNum = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// do overdraw measurement
|
||||||
|
//
|
||||||
|
if ( r_measureOverdraw->integer )
|
||||||
|
{
|
||||||
|
if ( glConfig.stencilBits < 4 )
|
||||||
|
{
|
||||||
|
ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits );
|
||||||
|
ri.Cvar_Set( "r_measureOverdraw", "0" );
|
||||||
|
r_measureOverdraw->modified = qfalse;
|
||||||
|
}
|
||||||
|
else if ( r_shadows->integer == 2 )
|
||||||
|
{
|
||||||
|
ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" );
|
||||||
|
ri.Cvar_Set( "r_measureOverdraw", "0" );
|
||||||
|
r_measureOverdraw->modified = qfalse;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
R_IssuePendingRenderCommands();
|
||||||
|
qglEnable( GL_STENCIL_TEST );
|
||||||
|
qglStencilMask( ~0U );
|
||||||
|
qglClearStencil( 0U );
|
||||||
|
qglStencilFunc( GL_ALWAYS, 0U, ~0U );
|
||||||
|
qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
|
||||||
|
}
|
||||||
|
r_measureOverdraw->modified = qfalse;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// this is only reached if it was on and is now off
|
||||||
|
if ( r_measureOverdraw->modified ) {
|
||||||
|
R_IssuePendingRenderCommands();
|
||||||
|
qglDisable( GL_STENCIL_TEST );
|
||||||
|
}
|
||||||
|
r_measureOverdraw->modified = qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// texturemode stuff
|
||||||
|
//
|
||||||
|
if ( r_textureMode->modified ) {
|
||||||
|
R_IssuePendingRenderCommands();
|
||||||
|
GL_TextureMode( r_textureMode->string );
|
||||||
|
r_textureMode->modified = qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// gamma stuff
|
||||||
|
//
|
||||||
|
if ( r_gamma->modified ) {
|
||||||
|
r_gamma->modified = qfalse;
|
||||||
|
|
||||||
|
R_IssuePendingRenderCommands();
|
||||||
|
R_SetColorMappings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for errors
|
||||||
|
if ( !r_ignoreGLErrors->integer )
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
R_IssuePendingRenderCommands();
|
||||||
|
if ((err = qglGetError()) != GL_NO_ERROR)
|
||||||
|
ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glConfig.stereoEnabled) {
|
||||||
|
if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
cmd->commandId = RC_DRAW_BUFFER;
|
||||||
|
|
||||||
|
if ( stereoFrame == STEREO_LEFT ) {
|
||||||
|
cmd->buffer = (int)GL_BACK_LEFT;
|
||||||
|
} else if ( stereoFrame == STEREO_RIGHT ) {
|
||||||
|
cmd->buffer = (int)GL_BACK_RIGHT;
|
||||||
|
} else {
|
||||||
|
ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(r_anaglyphMode->integer)
|
||||||
|
{
|
||||||
|
if(r_anaglyphMode->modified)
|
||||||
|
{
|
||||||
|
// clear both, front and backbuffer.
|
||||||
|
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
qglClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
qglDrawBuffer(GL_FRONT);
|
||||||
|
qglClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
qglDrawBuffer(GL_BACK);
|
||||||
|
qglClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
r_anaglyphMode->modified = qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stereoFrame == STEREO_LEFT)
|
||||||
|
{
|
||||||
|
if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(stereoFrame == STEREO_RIGHT)
|
||||||
|
{
|
||||||
|
clearDepthCommand_t *cldcmd;
|
||||||
|
|
||||||
|
if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
cldcmd->commandId = RC_CLEARDEPTH;
|
||||||
|
|
||||||
|
if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
|
||||||
|
|
||||||
|
R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer);
|
||||||
|
colcmd->commandId = RC_COLORMASK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(stereoFrame != STEREO_CENTER)
|
||||||
|
ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame );
|
||||||
|
|
||||||
|
if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cmd)
|
||||||
|
{
|
||||||
|
cmd->commandId = RC_DRAW_BUFFER;
|
||||||
|
|
||||||
|
if(r_anaglyphMode->modified)
|
||||||
|
{
|
||||||
|
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
r_anaglyphMode->modified = qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT"))
|
||||||
|
cmd->buffer = (int)GL_FRONT;
|
||||||
|
else
|
||||||
|
cmd->buffer = (int)GL_BACK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.refdef.stereoFrame = stereoFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
RE_EndFrame
|
||||||
|
|
||||||
|
Returns the number of msec spent in the back end
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
|
||||||
|
swapBuffersCommand_t *cmd;
|
||||||
|
|
||||||
|
if ( !tr.registered ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmd = R_GetCommandBufferReserved( sizeof( *cmd ), 0 );
|
||||||
|
if ( !cmd ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmd->commandId = RC_SWAP_BUFFERS;
|
||||||
|
|
||||||
|
R_IssueRenderCommands( qtrue );
|
||||||
|
|
||||||
|
R_InitNextFrame();
|
||||||
|
|
||||||
|
if ( frontEndMsec ) {
|
||||||
|
*frontEndMsec = tr.frontEndMsec;
|
||||||
|
}
|
||||||
|
tr.frontEndMsec = 0;
|
||||||
|
if ( backEndMsec ) {
|
||||||
|
*backEndMsec = backEnd.pc.msec;
|
||||||
|
}
|
||||||
|
backEnd.pc.msec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
RE_TakeVideoFrame
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void RE_TakeVideoFrame( int width, int height,
|
||||||
|
byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg )
|
||||||
|
{
|
||||||
|
videoFrameCommand_t *cmd;
|
||||||
|
|
||||||
|
if( !tr.registered ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = R_GetCommandBuffer( sizeof( *cmd ) );
|
||||||
|
if( !cmd ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->commandId = RC_VIDEOFRAME;
|
||||||
|
|
||||||
|
cmd->width = width;
|
||||||
|
cmd->height = height;
|
||||||
|
cmd->captureBuffer = captureBuffer;
|
||||||
|
cmd->encodeBuffer = encodeBuffer;
|
||||||
|
cmd->motionJpeg = motionJpeg;
|
||||||
|
}
|
625
code/renderergl1/tr_curve.c
Normal file
625
code/renderergl1/tr_curve.c
Normal file
|
@ -0,0 +1,625 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file does all of the processing necessary to turn a raw grid of points
|
||||||
|
read from the map file into a srfGridMesh_t ready for rendering.
|
||||||
|
|
||||||
|
The level of detail solution is direction independent, based only on subdivided
|
||||||
|
distance from the true curve.
|
||||||
|
|
||||||
|
Only a single entry point:
|
||||||
|
|
||||||
|
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
|
||||||
|
drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
============
|
||||||
|
LerpDrawVert
|
||||||
|
============
|
||||||
|
*/
|
||||||
|
static void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) {
|
||||||
|
out->xyz[0] = 0.5f * (a->xyz[0] + b->xyz[0]);
|
||||||
|
out->xyz[1] = 0.5f * (a->xyz[1] + b->xyz[1]);
|
||||||
|
out->xyz[2] = 0.5f * (a->xyz[2] + b->xyz[2]);
|
||||||
|
|
||||||
|
out->st[0] = 0.5f * (a->st[0] + b->st[0]);
|
||||||
|
out->st[1] = 0.5f * (a->st[1] + b->st[1]);
|
||||||
|
|
||||||
|
out->lightmap[0] = 0.5f * (a->lightmap[0] + b->lightmap[0]);
|
||||||
|
out->lightmap[1] = 0.5f * (a->lightmap[1] + b->lightmap[1]);
|
||||||
|
|
||||||
|
out->color[0] = (a->color[0] + b->color[0]) >> 1;
|
||||||
|
out->color[1] = (a->color[1] + b->color[1]) >> 1;
|
||||||
|
out->color[2] = (a->color[2] + b->color[2]) >> 1;
|
||||||
|
out->color[3] = (a->color[3] + b->color[3]) >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
============
|
||||||
|
Transpose
|
||||||
|
============
|
||||||
|
*/
|
||||||
|
static void Transpose( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
|
||||||
|
int i, j;
|
||||||
|
drawVert_t temp;
|
||||||
|
|
||||||
|
if ( width > height ) {
|
||||||
|
for ( i = 0 ; i < height ; i++ ) {
|
||||||
|
for ( j = i + 1 ; j < width ; j++ ) {
|
||||||
|
if ( j < height ) {
|
||||||
|
// swap the value
|
||||||
|
temp = ctrl[j][i];
|
||||||
|
ctrl[j][i] = ctrl[i][j];
|
||||||
|
ctrl[i][j] = temp;
|
||||||
|
} else {
|
||||||
|
// just copy
|
||||||
|
ctrl[j][i] = ctrl[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for ( i = 0 ; i < width ; i++ ) {
|
||||||
|
for ( j = i + 1 ; j < height ; j++ ) {
|
||||||
|
if ( j < width ) {
|
||||||
|
// swap the value
|
||||||
|
temp = ctrl[i][j];
|
||||||
|
ctrl[i][j] = ctrl[j][i];
|
||||||
|
ctrl[j][i] = temp;
|
||||||
|
} else {
|
||||||
|
// just copy
|
||||||
|
ctrl[i][j] = ctrl[j][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
MakeMeshNormals
|
||||||
|
|
||||||
|
Handles all the complicated wrapping and degenerate cases
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
|
||||||
|
int i, j, k, dist;
|
||||||
|
vec3_t normal;
|
||||||
|
vec3_t sum;
|
||||||
|
int count = 0;
|
||||||
|
vec3_t base;
|
||||||
|
vec3_t delta;
|
||||||
|
int x, y;
|
||||||
|
drawVert_t *dv;
|
||||||
|
vec3_t around[8], temp;
|
||||||
|
qboolean good[8];
|
||||||
|
qboolean wrapWidth, wrapHeight;
|
||||||
|
float len;
|
||||||
|
static int neighbors[8][2] = {
|
||||||
|
{0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
|
||||||
|
};
|
||||||
|
|
||||||
|
wrapWidth = qfalse;
|
||||||
|
for ( i = 0 ; i < height ; i++ ) {
|
||||||
|
VectorSubtract( ctrl[i][0].xyz, ctrl[i][width-1].xyz, delta );
|
||||||
|
len = VectorLengthSquared( delta );
|
||||||
|
if ( len > 1.0 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( i == height ) {
|
||||||
|
wrapWidth = qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapHeight = qfalse;
|
||||||
|
for ( i = 0 ; i < width ; i++ ) {
|
||||||
|
VectorSubtract( ctrl[0][i].xyz, ctrl[height-1][i].xyz, delta );
|
||||||
|
len = VectorLengthSquared( delta );
|
||||||
|
if ( len > 1.0 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( i == width) {
|
||||||
|
wrapHeight = qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for ( i = 0 ; i < width ; i++ ) {
|
||||||
|
for ( j = 0 ; j < height ; j++ ) {
|
||||||
|
count = 0;
|
||||||
|
dv = &ctrl[j][i];
|
||||||
|
VectorCopy( dv->xyz, base );
|
||||||
|
for ( k = 0 ; k < 8 ; k++ ) {
|
||||||
|
VectorClear( around[k] );
|
||||||
|
good[k] = qfalse;
|
||||||
|
|
||||||
|
for ( dist = 1 ; dist <= 3 ; dist++ ) {
|
||||||
|
x = i + neighbors[k][0] * dist;
|
||||||
|
y = j + neighbors[k][1] * dist;
|
||||||
|
if ( wrapWidth ) {
|
||||||
|
if ( x < 0 ) {
|
||||||
|
x = width - 1 + x;
|
||||||
|
} else if ( x >= width ) {
|
||||||
|
x = 1 + x - width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( wrapHeight ) {
|
||||||
|
if ( y < 0 ) {
|
||||||
|
y = height - 1 + y;
|
||||||
|
} else if ( y >= height ) {
|
||||||
|
y = 1 + y - height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( x < 0 || x >= width || y < 0 || y >= height ) {
|
||||||
|
break; // edge of patch
|
||||||
|
}
|
||||||
|
VectorSubtract( ctrl[y][x].xyz, base, temp );
|
||||||
|
if ( VectorNormalize( temp ) < 0.001f ) {
|
||||||
|
continue; // degenerate edge, get more dist
|
||||||
|
} else {
|
||||||
|
good[k] = qtrue;
|
||||||
|
VectorCopy( temp, around[k] );
|
||||||
|
break; // good edge
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorClear( sum );
|
||||||
|
for ( k = 0 ; k < 8 ; k++ ) {
|
||||||
|
if ( !good[k] || !good[(k+1)&7] ) {
|
||||||
|
continue; // didn't get two points
|
||||||
|
}
|
||||||
|
CrossProduct( around[(k+1)&7], around[k], normal );
|
||||||
|
if ( VectorNormalize( normal ) < 0.001f ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
VectorAdd( normal, sum, sum );
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
//if ( count == 0 ) {
|
||||||
|
// printf("bad normal\n");
|
||||||
|
//}
|
||||||
|
VectorNormalize2( sum, dv->normal );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
============
|
||||||
|
InvertCtrl
|
||||||
|
============
|
||||||
|
*/
|
||||||
|
static void InvertCtrl( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
|
||||||
|
int i, j;
|
||||||
|
drawVert_t temp;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < height ; i++ ) {
|
||||||
|
for ( j = 0 ; j < width/2 ; j++ ) {
|
||||||
|
temp = ctrl[i][j];
|
||||||
|
ctrl[i][j] = ctrl[i][width-1-j];
|
||||||
|
ctrl[i][width-1-j] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
InvertErrorTable
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void InvertErrorTable( float errorTable[2][MAX_GRID_SIZE], int width, int height ) {
|
||||||
|
int i;
|
||||||
|
float copy[2][MAX_GRID_SIZE];
|
||||||
|
|
||||||
|
Com_Memcpy( copy, errorTable, sizeof( copy ) );
|
||||||
|
|
||||||
|
for ( i = 0 ; i < width ; i++ ) {
|
||||||
|
errorTable[1][i] = copy[0][i]; //[width-1-i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0 ; i < height ; i++ ) {
|
||||||
|
errorTable[0][i] = copy[1][height-1-i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
PutPointsOnCurve
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static void PutPointsOnCurve( drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
|
||||||
|
int width, int height ) {
|
||||||
|
int i, j;
|
||||||
|
drawVert_t prev, next;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < width ; i++ ) {
|
||||||
|
for ( j = 1 ; j < height ; j += 2 ) {
|
||||||
|
LerpDrawVert( &ctrl[j][i], &ctrl[j+1][i], &prev );
|
||||||
|
LerpDrawVert( &ctrl[j][i], &ctrl[j-1][i], &next );
|
||||||
|
LerpDrawVert( &prev, &next, &ctrl[j][i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for ( j = 0 ; j < height ; j++ ) {
|
||||||
|
for ( i = 1 ; i < width ; i += 2 ) {
|
||||||
|
LerpDrawVert( &ctrl[j][i], &ctrl[j][i+1], &prev );
|
||||||
|
LerpDrawVert( &ctrl[j][i], &ctrl[j][i-1], &next );
|
||||||
|
LerpDrawVert( &prev, &next, &ctrl[j][i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_CreateSurfaceGridMesh
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
|
||||||
|
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE] ) {
|
||||||
|
int i, j, size;
|
||||||
|
drawVert_t *vert;
|
||||||
|
vec3_t tmpVec;
|
||||||
|
srfGridMesh_t *grid;
|
||||||
|
|
||||||
|
// copy the results out to a grid
|
||||||
|
size = (width * height - 1) * sizeof( drawVert_t ) + sizeof( *grid );
|
||||||
|
|
||||||
|
#ifdef PATCH_STITCHING
|
||||||
|
grid = /*ri.Hunk_Alloc*/ ri.Malloc( size );
|
||||||
|
Com_Memset(grid, 0, size);
|
||||||
|
|
||||||
|
grid->widthLodError = /*ri.Hunk_Alloc*/ ri.Malloc( width * 4 );
|
||||||
|
Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
|
||||||
|
|
||||||
|
grid->heightLodError = /*ri.Hunk_Alloc*/ ri.Malloc( height * 4 );
|
||||||
|
Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
|
||||||
|
#else
|
||||||
|
grid = ri.Hunk_Alloc( size );
|
||||||
|
Com_Memset(grid, 0, size);
|
||||||
|
|
||||||
|
grid->widthLodError = ri.Hunk_Alloc( width * 4 );
|
||||||
|
Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
|
||||||
|
|
||||||
|
grid->heightLodError = ri.Hunk_Alloc( height * 4 );
|
||||||
|
Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
grid->width = width;
|
||||||
|
grid->height = height;
|
||||||
|
grid->surfaceType = SF_GRID;
|
||||||
|
ClearBounds( grid->meshBounds[0], grid->meshBounds[1] );
|
||||||
|
for ( i = 0 ; i < width ; i++ ) {
|
||||||
|
for ( j = 0 ; j < height ; j++ ) {
|
||||||
|
vert = &grid->verts[j*width+i];
|
||||||
|
*vert = ctrl[j][i];
|
||||||
|
AddPointToBounds( vert->xyz, grid->meshBounds[0], grid->meshBounds[1] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute local origin and bounds
|
||||||
|
VectorAdd( grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin );
|
||||||
|
VectorScale( grid->localOrigin, 0.5f, grid->localOrigin );
|
||||||
|
VectorSubtract( grid->meshBounds[0], grid->localOrigin, tmpVec );
|
||||||
|
grid->meshRadius = VectorLength( tmpVec );
|
||||||
|
|
||||||
|
VectorCopy( grid->localOrigin, grid->lodOrigin );
|
||||||
|
grid->lodRadius = grid->meshRadius;
|
||||||
|
//
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_FreeSurfaceGridMesh
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) {
|
||||||
|
ri.Free(grid->widthLodError);
|
||||||
|
ri.Free(grid->heightLodError);
|
||||||
|
ri.Free(grid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_SubdividePatchToGrid
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
|
||||||
|
drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
|
||||||
|
int i, j, k, l;
|
||||||
|
drawVert_t_cleared( prev );
|
||||||
|
drawVert_t_cleared( next );
|
||||||
|
drawVert_t_cleared( mid );
|
||||||
|
float len, maxLen;
|
||||||
|
int dir;
|
||||||
|
int t;
|
||||||
|
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
|
||||||
|
float errorTable[2][MAX_GRID_SIZE];
|
||||||
|
|
||||||
|
for ( i = 0 ; i < width ; i++ ) {
|
||||||
|
for ( j = 0 ; j < height ; j++ ) {
|
||||||
|
ctrl[j][i] = points[j*width+i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( dir = 0 ; dir < 2 ; dir++ ) {
|
||||||
|
|
||||||
|
for ( j = 0 ; j < MAX_GRID_SIZE ; j++ ) {
|
||||||
|
errorTable[dir][j] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// horizontal subdivisions
|
||||||
|
for ( j = 0 ; j + 2 < width ; j += 2 ) {
|
||||||
|
// check subdivided midpoints against control points
|
||||||
|
|
||||||
|
// FIXME: also check midpoints of adjacent patches against the control points
|
||||||
|
// this would basically stitch all patches in the same LOD group together.
|
||||||
|
|
||||||
|
maxLen = 0;
|
||||||
|
for ( i = 0 ; i < height ; i++ ) {
|
||||||
|
vec3_t midxyz;
|
||||||
|
vec3_t midxyz2;
|
||||||
|
vec3_t dir;
|
||||||
|
vec3_t projected;
|
||||||
|
float d;
|
||||||
|
|
||||||
|
// calculate the point on the curve
|
||||||
|
for ( l = 0 ; l < 3 ; l++ ) {
|
||||||
|
midxyz[l] = (ctrl[i][j].xyz[l] + ctrl[i][j+1].xyz[l] * 2
|
||||||
|
+ ctrl[i][j+2].xyz[l] ) * 0.25f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see how far off the line it is
|
||||||
|
// using dist-from-line will not account for internal
|
||||||
|
// texture warping, but it gives a lot less polygons than
|
||||||
|
// dist-from-midpoint
|
||||||
|
VectorSubtract( midxyz, ctrl[i][j].xyz, midxyz );
|
||||||
|
VectorSubtract( ctrl[i][j+2].xyz, ctrl[i][j].xyz, dir );
|
||||||
|
VectorNormalize( dir );
|
||||||
|
|
||||||
|
d = DotProduct( midxyz, dir );
|
||||||
|
VectorScale( dir, d, projected );
|
||||||
|
VectorSubtract( midxyz, projected, midxyz2);
|
||||||
|
len = VectorLengthSquared( midxyz2 ); // we will do the sqrt later
|
||||||
|
if ( len > maxLen ) {
|
||||||
|
maxLen = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maxLen = sqrt(maxLen);
|
||||||
|
|
||||||
|
// if all the points are on the lines, remove the entire columns
|
||||||
|
if ( maxLen < 0.1f ) {
|
||||||
|
errorTable[dir][j+1] = 999;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if we want to insert subdivided columns
|
||||||
|
if ( width + 2 > MAX_GRID_SIZE ) {
|
||||||
|
errorTable[dir][j+1] = 1.0f/maxLen;
|
||||||
|
continue; // can't subdivide any more
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( maxLen <= r_subdivisions->value ) {
|
||||||
|
errorTable[dir][j+1] = 1.0f/maxLen;
|
||||||
|
continue; // didn't need subdivision
|
||||||
|
}
|
||||||
|
|
||||||
|
errorTable[dir][j+2] = 1.0f/maxLen;
|
||||||
|
|
||||||
|
// insert two columns and replace the peak
|
||||||
|
width += 2;
|
||||||
|
for ( i = 0 ; i < height ; i++ ) {
|
||||||
|
LerpDrawVert( &ctrl[i][j], &ctrl[i][j+1], &prev );
|
||||||
|
LerpDrawVert( &ctrl[i][j+1], &ctrl[i][j+2], &next );
|
||||||
|
LerpDrawVert( &prev, &next, &mid );
|
||||||
|
|
||||||
|
for ( k = width - 1 ; k > j + 3 ; k-- ) {
|
||||||
|
ctrl[i][k] = ctrl[i][k-2];
|
||||||
|
}
|
||||||
|
ctrl[i][j + 1] = prev;
|
||||||
|
ctrl[i][j + 2] = mid;
|
||||||
|
ctrl[i][j + 3] = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// back up and recheck this set again, it may need more subdivision
|
||||||
|
j -= 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Transpose( width, height, ctrl );
|
||||||
|
t = width;
|
||||||
|
width = height;
|
||||||
|
height = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// put all the aproximating points on the curve
|
||||||
|
PutPointsOnCurve( ctrl, width, height );
|
||||||
|
|
||||||
|
// cull out any rows or columns that are colinear
|
||||||
|
for ( i = 1 ; i < width-1 ; i++ ) {
|
||||||
|
if ( errorTable[0][i] != 999 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for ( j = i+1 ; j < width ; j++ ) {
|
||||||
|
for ( k = 0 ; k < height ; k++ ) {
|
||||||
|
ctrl[k][j-1] = ctrl[k][j];
|
||||||
|
}
|
||||||
|
errorTable[0][j-1] = errorTable[0][j];
|
||||||
|
}
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 1 ; i < height-1 ; i++ ) {
|
||||||
|
if ( errorTable[1][i] != 999 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for ( j = i+1 ; j < height ; j++ ) {
|
||||||
|
for ( k = 0 ; k < width ; k++ ) {
|
||||||
|
ctrl[j-1][k] = ctrl[j][k];
|
||||||
|
}
|
||||||
|
errorTable[1][j-1] = errorTable[1][j];
|
||||||
|
}
|
||||||
|
height--;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// flip for longest tristrips as an optimization
|
||||||
|
// the results should be visually identical with or
|
||||||
|
// without this step
|
||||||
|
if ( height > width ) {
|
||||||
|
Transpose( width, height, ctrl );
|
||||||
|
InvertErrorTable( errorTable, width, height );
|
||||||
|
t = width;
|
||||||
|
width = height;
|
||||||
|
height = t;
|
||||||
|
InvertCtrl( width, height, ctrl );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// calculate normals
|
||||||
|
MakeMeshNormals( width, height, ctrl );
|
||||||
|
|
||||||
|
return R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_GridInsertColumn
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) {
|
||||||
|
int i, j;
|
||||||
|
int width, height, oldwidth;
|
||||||
|
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
|
||||||
|
float errorTable[2][MAX_GRID_SIZE];
|
||||||
|
float lodRadius;
|
||||||
|
vec3_t lodOrigin;
|
||||||
|
|
||||||
|
oldwidth = 0;
|
||||||
|
width = grid->width + 1;
|
||||||
|
if (width > MAX_GRID_SIZE)
|
||||||
|
return NULL;
|
||||||
|
height = grid->height;
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
if (i == column) {
|
||||||
|
//insert new column
|
||||||
|
for (j = 0; j < grid->height; j++) {
|
||||||
|
LerpDrawVert( &grid->verts[j * grid->width + i-1], &grid->verts[j * grid->width + i], &ctrl[j][i] );
|
||||||
|
if (j == row)
|
||||||
|
VectorCopy(point, ctrl[j][i].xyz);
|
||||||
|
}
|
||||||
|
errorTable[0][i] = loderror;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
errorTable[0][i] = grid->widthLodError[oldwidth];
|
||||||
|
for (j = 0; j < grid->height; j++) {
|
||||||
|
ctrl[j][i] = grid->verts[j * grid->width + oldwidth];
|
||||||
|
}
|
||||||
|
oldwidth++;
|
||||||
|
}
|
||||||
|
for (j = 0; j < grid->height; j++) {
|
||||||
|
errorTable[1][j] = grid->heightLodError[j];
|
||||||
|
}
|
||||||
|
// put all the aproximating points on the curve
|
||||||
|
//PutPointsOnCurve( ctrl, width, height );
|
||||||
|
// calculate normals
|
||||||
|
MakeMeshNormals( width, height, ctrl );
|
||||||
|
|
||||||
|
VectorCopy(grid->lodOrigin, lodOrigin);
|
||||||
|
lodRadius = grid->lodRadius;
|
||||||
|
// free the old grid
|
||||||
|
R_FreeSurfaceGridMesh(grid);
|
||||||
|
// create a new grid
|
||||||
|
grid = R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
|
||||||
|
grid->lodRadius = lodRadius;
|
||||||
|
VectorCopy(lodOrigin, grid->lodOrigin);
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_GridInsertRow
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) {
|
||||||
|
int i, j;
|
||||||
|
int width, height, oldheight;
|
||||||
|
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
|
||||||
|
float errorTable[2][MAX_GRID_SIZE];
|
||||||
|
float lodRadius;
|
||||||
|
vec3_t lodOrigin;
|
||||||
|
|
||||||
|
oldheight = 0;
|
||||||
|
width = grid->width;
|
||||||
|
height = grid->height + 1;
|
||||||
|
if (height > MAX_GRID_SIZE)
|
||||||
|
return NULL;
|
||||||
|
for (i = 0; i < height; i++) {
|
||||||
|
if (i == row) {
|
||||||
|
//insert new row
|
||||||
|
for (j = 0; j < grid->width; j++) {
|
||||||
|
LerpDrawVert( &grid->verts[(i-1) * grid->width + j], &grid->verts[i * grid->width + j], &ctrl[i][j] );
|
||||||
|
if (j == column)
|
||||||
|
VectorCopy(point, ctrl[i][j].xyz);
|
||||||
|
}
|
||||||
|
errorTable[1][i] = loderror;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
errorTable[1][i] = grid->heightLodError[oldheight];
|
||||||
|
for (j = 0; j < grid->width; j++) {
|
||||||
|
ctrl[i][j] = grid->verts[oldheight * grid->width + j];
|
||||||
|
}
|
||||||
|
oldheight++;
|
||||||
|
}
|
||||||
|
for (j = 0; j < grid->width; j++) {
|
||||||
|
errorTable[0][j] = grid->widthLodError[j];
|
||||||
|
}
|
||||||
|
// put all the aproximating points on the curve
|
||||||
|
//PutPointsOnCurve( ctrl, width, height );
|
||||||
|
// calculate normals
|
||||||
|
MakeMeshNormals( width, height, ctrl );
|
||||||
|
|
||||||
|
VectorCopy(grid->lodOrigin, lodOrigin);
|
||||||
|
lodRadius = grid->lodRadius;
|
||||||
|
// free the old grid
|
||||||
|
R_FreeSurfaceGridMesh(grid);
|
||||||
|
// create a new grid
|
||||||
|
grid = R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
|
||||||
|
grid->lodRadius = lodRadius;
|
||||||
|
VectorCopy(lodOrigin, grid->lodOrigin);
|
||||||
|
return grid;
|
||||||
|
}
|
539
code/renderergl1/tr_flares.c
Normal file
539
code/renderergl1/tr_flares.c
Normal file
|
@ -0,0 +1,539 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// tr_flares.c
|
||||||
|
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============================================================================
|
||||||
|
|
||||||
|
LIGHT FLARES
|
||||||
|
|
||||||
|
A light flare is an effect that takes place inside the eye when bright light
|
||||||
|
sources are visible. The size of the flare relative to the screen is nearly
|
||||||
|
constant, irrespective of distance, but the intensity should be proportional to the
|
||||||
|
projected area of the light source.
|
||||||
|
|
||||||
|
A surface that has been flagged as having a light flare will calculate the depth
|
||||||
|
buffer value that its midpoint should have when the surface is added.
|
||||||
|
|
||||||
|
After all opaque surfaces have been rendered, the depth buffer is read back for
|
||||||
|
each flare in view. If the point has not been obscured by a closer surface, the
|
||||||
|
flare should be drawn.
|
||||||
|
|
||||||
|
Surfaces that have a repeated texture should never be flagged as flaring, because
|
||||||
|
there will only be a single flare added at the midpoint of the polygon.
|
||||||
|
|
||||||
|
To prevent abrupt popping, the intensity of the flare is interpolated up and
|
||||||
|
down as it changes visibility. This involves scene to scene state, unlike almost
|
||||||
|
all other aspects of the renderer, and is complicated by the fact that a single
|
||||||
|
frame may have multiple scenes.
|
||||||
|
|
||||||
|
RB_RenderFlares() will be called once per view (twice in a mirrored scene, potentially
|
||||||
|
up to five or more times in a frame with 3D status bar icons).
|
||||||
|
|
||||||
|
=============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// flare states maintain visibility over multiple frames for fading
|
||||||
|
// layers: view, mirror, menu
|
||||||
|
typedef struct flare_s {
|
||||||
|
struct flare_s *next; // for active chain
|
||||||
|
|
||||||
|
int addedFrame;
|
||||||
|
|
||||||
|
qboolean inPortal; // true if in a portal view of the scene
|
||||||
|
int frameSceneNum;
|
||||||
|
void *surface;
|
||||||
|
int fogNum;
|
||||||
|
|
||||||
|
int fadeTime;
|
||||||
|
|
||||||
|
qboolean visible; // state of last test
|
||||||
|
float drawIntensity; // may be non 0 even if !visible due to fading
|
||||||
|
|
||||||
|
int windowX, windowY;
|
||||||
|
float eyeZ;
|
||||||
|
|
||||||
|
vec3_t origin;
|
||||||
|
vec3_t color;
|
||||||
|
} flare_t;
|
||||||
|
|
||||||
|
#define MAX_FLARES 256
|
||||||
|
|
||||||
|
flare_t r_flareStructs[MAX_FLARES];
|
||||||
|
flare_t *r_activeFlares, *r_inactiveFlares;
|
||||||
|
|
||||||
|
int flareCoeff;
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
R_SetFlareCoeff
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static void R_SetFlareCoeff( void ) {
|
||||||
|
|
||||||
|
if(r_flareCoeff->value == 0.0f)
|
||||||
|
flareCoeff = atof(FLARE_STDCOEFF);
|
||||||
|
else
|
||||||
|
flareCoeff = r_flareCoeff->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
R_ClearFlares
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void R_ClearFlares( void ) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Com_Memset( r_flareStructs, 0, sizeof( r_flareStructs ) );
|
||||||
|
r_activeFlares = NULL;
|
||||||
|
r_inactiveFlares = NULL;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < MAX_FLARES ; i++ ) {
|
||||||
|
r_flareStructs[i].next = r_inactiveFlares;
|
||||||
|
r_inactiveFlares = &r_flareStructs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SetFlareCoeff();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
RB_AddFlare
|
||||||
|
|
||||||
|
This is called at surface tesselation time
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal ) {
|
||||||
|
int i;
|
||||||
|
flare_t *f;
|
||||||
|
vec3_t local;
|
||||||
|
float d = 1;
|
||||||
|
vec4_t eye, clip, normalized, window;
|
||||||
|
|
||||||
|
backEnd.pc.c_flareAdds++;
|
||||||
|
|
||||||
|
if(normal && (normal[0] || normal[1] || normal[2]))
|
||||||
|
{
|
||||||
|
VectorSubtract( backEnd.viewParms.or.origin, point, local );
|
||||||
|
VectorNormalizeFast(local);
|
||||||
|
d = DotProduct(local, normal);
|
||||||
|
|
||||||
|
// If the viewer is behind the flare don't add it.
|
||||||
|
if(d < 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the point is off the screen, don't bother adding it
|
||||||
|
// calculate screen coordinates and depth
|
||||||
|
R_TransformModelToClip( point, backEnd.or.modelMatrix,
|
||||||
|
backEnd.viewParms.projectionMatrix, eye, clip );
|
||||||
|
|
||||||
|
// check to see if the point is completely off screen
|
||||||
|
for ( i = 0 ; i < 3 ; i++ ) {
|
||||||
|
if ( clip[i] >= clip[3] || clip[i] <= -clip[3] ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R_TransformClipToWindow( clip, &backEnd.viewParms, normalized, window );
|
||||||
|
|
||||||
|
if ( window[0] < 0 || window[0] >= backEnd.viewParms.viewportWidth
|
||||||
|
|| window[1] < 0 || window[1] >= backEnd.viewParms.viewportHeight ) {
|
||||||
|
return; // shouldn't happen, since we check the clip[] above, except for FP rounding
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if a flare with a matching surface, scene, and view exists
|
||||||
|
for ( f = r_activeFlares ; f ; f = f->next ) {
|
||||||
|
if ( f->surface == surface && f->frameSceneNum == backEnd.viewParms.frameSceneNum
|
||||||
|
&& f->inPortal == backEnd.viewParms.isPortal ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate a new one
|
||||||
|
if (!f ) {
|
||||||
|
if ( !r_inactiveFlares ) {
|
||||||
|
// the list is completely full
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
f = r_inactiveFlares;
|
||||||
|
r_inactiveFlares = r_inactiveFlares->next;
|
||||||
|
f->next = r_activeFlares;
|
||||||
|
r_activeFlares = f;
|
||||||
|
|
||||||
|
f->surface = surface;
|
||||||
|
f->frameSceneNum = backEnd.viewParms.frameSceneNum;
|
||||||
|
f->inPortal = backEnd.viewParms.isPortal;
|
||||||
|
f->addedFrame = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( f->addedFrame != backEnd.viewParms.frameCount - 1 ) {
|
||||||
|
f->visible = qfalse;
|
||||||
|
f->fadeTime = backEnd.refdef.time - 2000;
|
||||||
|
}
|
||||||
|
|
||||||
|
f->addedFrame = backEnd.viewParms.frameCount;
|
||||||
|
f->fogNum = fogNum;
|
||||||
|
|
||||||
|
VectorCopy(point, f->origin);
|
||||||
|
VectorCopy( color, f->color );
|
||||||
|
|
||||||
|
// fade the intensity of the flare down as the
|
||||||
|
// light surface turns away from the viewer
|
||||||
|
VectorScale( f->color, d, f->color );
|
||||||
|
|
||||||
|
// save info needed to test
|
||||||
|
f->windowX = backEnd.viewParms.viewportX + window[0];
|
||||||
|
f->windowY = backEnd.viewParms.viewportY + window[1];
|
||||||
|
|
||||||
|
f->eyeZ = eye[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
RB_AddDlightFlares
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void RB_AddDlightFlares( void ) {
|
||||||
|
dlight_t *l;
|
||||||
|
int i, j, k;
|
||||||
|
fog_t *fog = NULL;
|
||||||
|
|
||||||
|
if ( !r_flares->integer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = backEnd.refdef.dlights;
|
||||||
|
|
||||||
|
if(tr.world)
|
||||||
|
fog = tr.world->fogs;
|
||||||
|
|
||||||
|
for (i=0 ; i<backEnd.refdef.num_dlights ; i++, l++) {
|
||||||
|
|
||||||
|
if(fog)
|
||||||
|
{
|
||||||
|
// find which fog volume the light is in
|
||||||
|
for ( j = 1 ; j < tr.world->numfogs ; j++ ) {
|
||||||
|
fog = &tr.world->fogs[j];
|
||||||
|
for ( k = 0 ; k < 3 ; k++ ) {
|
||||||
|
if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( k == 3 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( j == tr.world->numfogs ) {
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
j = 0;
|
||||||
|
|
||||||
|
RB_AddFlare( (void *)l, j, l->origin, l->color, NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============================================================================
|
||||||
|
|
||||||
|
FLARE BACK END
|
||||||
|
|
||||||
|
===============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
RB_TestFlare
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void RB_TestFlare( flare_t *f ) {
|
||||||
|
float depth;
|
||||||
|
qboolean visible;
|
||||||
|
float fade;
|
||||||
|
float screenZ;
|
||||||
|
|
||||||
|
backEnd.pc.c_flareTests++;
|
||||||
|
|
||||||
|
// doing a readpixels is as good as doing a glFinish(), so
|
||||||
|
// don't bother with another sync
|
||||||
|
glState.finishCalled = qfalse;
|
||||||
|
|
||||||
|
// read back the z buffer contents
|
||||||
|
qglReadPixels( f->windowX, f->windowY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth );
|
||||||
|
|
||||||
|
screenZ = backEnd.viewParms.projectionMatrix[14] /
|
||||||
|
( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] );
|
||||||
|
|
||||||
|
visible = ( -f->eyeZ - -screenZ ) < 24;
|
||||||
|
|
||||||
|
if ( visible ) {
|
||||||
|
if ( !f->visible ) {
|
||||||
|
f->visible = qtrue;
|
||||||
|
f->fadeTime = backEnd.refdef.time - 1;
|
||||||
|
}
|
||||||
|
fade = ( ( backEnd.refdef.time - f->fadeTime ) /1000.0f ) * r_flareFade->value;
|
||||||
|
} else {
|
||||||
|
if ( f->visible ) {
|
||||||
|
f->visible = qfalse;
|
||||||
|
f->fadeTime = backEnd.refdef.time - 1;
|
||||||
|
}
|
||||||
|
fade = 1.0f - ( ( backEnd.refdef.time - f->fadeTime ) / 1000.0f ) * r_flareFade->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fade < 0 ) {
|
||||||
|
fade = 0;
|
||||||
|
}
|
||||||
|
if ( fade > 1 ) {
|
||||||
|
fade = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
f->drawIntensity = fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
RB_RenderFlare
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void RB_RenderFlare( flare_t *f ) {
|
||||||
|
float size;
|
||||||
|
vec3_t color;
|
||||||
|
int iColor[3];
|
||||||
|
float distance, intensity, factor;
|
||||||
|
byte fogFactors[3] = {255, 255, 255};
|
||||||
|
|
||||||
|
backEnd.pc.c_flareRenders++;
|
||||||
|
|
||||||
|
// We don't want too big values anyways when dividing by distance.
|
||||||
|
if(f->eyeZ > -1.0f)
|
||||||
|
distance = 1.0f;
|
||||||
|
else
|
||||||
|
distance = -f->eyeZ;
|
||||||
|
|
||||||
|
// calculate the flare size..
|
||||||
|
size = backEnd.viewParms.viewportWidth * ( r_flareSize->value/640.0f + 8 / distance );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an alternative to intensity scaling. It changes the size of the flare on screen instead
|
||||||
|
* with growing distance. See in the description at the top why this is not the way to go.
|
||||||
|
// size will change ~ 1/r.
|
||||||
|
size = backEnd.viewParms.viewportWidth * (r_flareSize->value / (distance * -2.0f));
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As flare sizes stay nearly constant with increasing distance we must decrease the intensity
|
||||||
|
* to achieve a reasonable visual result. The intensity is ~ (size^2 / distance^2) which can be
|
||||||
|
* got by considering the ratio of
|
||||||
|
* (flaresurface on screen) : (Surface of sphere defined by flare origin and distance from flare)
|
||||||
|
* An important requirement is:
|
||||||
|
* intensity <= 1 for all distances.
|
||||||
|
*
|
||||||
|
* The formula used here to compute the intensity is as follows:
|
||||||
|
* intensity = flareCoeff * size^2 / (distance + size*sqrt(flareCoeff))^2
|
||||||
|
* As you can see, the intensity will have a max. of 1 when the distance is 0.
|
||||||
|
* The coefficient flareCoeff will determine the falloff speed with increasing distance.
|
||||||
|
*/
|
||||||
|
|
||||||
|
factor = distance + size * sqrt(flareCoeff);
|
||||||
|
|
||||||
|
intensity = flareCoeff * size * size / (factor * factor);
|
||||||
|
|
||||||
|
VectorScale(f->color, f->drawIntensity * intensity, color);
|
||||||
|
|
||||||
|
// Calculations for fogging
|
||||||
|
if(tr.world && f->fogNum > 0 && f->fogNum < tr.world->numfogs)
|
||||||
|
{
|
||||||
|
tess.numVertexes = 1;
|
||||||
|
VectorCopy(f->origin, tess.xyz[0]);
|
||||||
|
tess.fogNum = f->fogNum;
|
||||||
|
|
||||||
|
RB_CalcModulateColorsByFog(fogFactors);
|
||||||
|
|
||||||
|
// We don't need to render the flare if colors are 0 anyways.
|
||||||
|
if(!(fogFactors[0] || fogFactors[1] || fogFactors[2]))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iColor[0] = color[0] * fogFactors[0];
|
||||||
|
iColor[1] = color[1] * fogFactors[1];
|
||||||
|
iColor[2] = color[2] * fogFactors[2];
|
||||||
|
|
||||||
|
RB_BeginSurface( tr.flareShader, f->fogNum );
|
||||||
|
|
||||||
|
// FIXME: use quadstamp?
|
||||||
|
tess.xyz[tess.numVertexes][0] = f->windowX - size;
|
||||||
|
tess.xyz[tess.numVertexes][1] = f->windowY - size;
|
||||||
|
tess.texCoords[tess.numVertexes][0][0] = 0;
|
||||||
|
tess.texCoords[tess.numVertexes][0][1] = 0;
|
||||||
|
tess.vertexColors[tess.numVertexes][0] = iColor[0];
|
||||||
|
tess.vertexColors[tess.numVertexes][1] = iColor[1];
|
||||||
|
tess.vertexColors[tess.numVertexes][2] = iColor[2];
|
||||||
|
tess.vertexColors[tess.numVertexes][3] = 255;
|
||||||
|
tess.numVertexes++;
|
||||||
|
|
||||||
|
tess.xyz[tess.numVertexes][0] = f->windowX - size;
|
||||||
|
tess.xyz[tess.numVertexes][1] = f->windowY + size;
|
||||||
|
tess.texCoords[tess.numVertexes][0][0] = 0;
|
||||||
|
tess.texCoords[tess.numVertexes][0][1] = 1;
|
||||||
|
tess.vertexColors[tess.numVertexes][0] = iColor[0];
|
||||||
|
tess.vertexColors[tess.numVertexes][1] = iColor[1];
|
||||||
|
tess.vertexColors[tess.numVertexes][2] = iColor[2];
|
||||||
|
tess.vertexColors[tess.numVertexes][3] = 255;
|
||||||
|
tess.numVertexes++;
|
||||||
|
|
||||||
|
tess.xyz[tess.numVertexes][0] = f->windowX + size;
|
||||||
|
tess.xyz[tess.numVertexes][1] = f->windowY + size;
|
||||||
|
tess.texCoords[tess.numVertexes][0][0] = 1;
|
||||||
|
tess.texCoords[tess.numVertexes][0][1] = 1;
|
||||||
|
tess.vertexColors[tess.numVertexes][0] = iColor[0];
|
||||||
|
tess.vertexColors[tess.numVertexes][1] = iColor[1];
|
||||||
|
tess.vertexColors[tess.numVertexes][2] = iColor[2];
|
||||||
|
tess.vertexColors[tess.numVertexes][3] = 255;
|
||||||
|
tess.numVertexes++;
|
||||||
|
|
||||||
|
tess.xyz[tess.numVertexes][0] = f->windowX + size;
|
||||||
|
tess.xyz[tess.numVertexes][1] = f->windowY - size;
|
||||||
|
tess.texCoords[tess.numVertexes][0][0] = 1;
|
||||||
|
tess.texCoords[tess.numVertexes][0][1] = 0;
|
||||||
|
tess.vertexColors[tess.numVertexes][0] = iColor[0];
|
||||||
|
tess.vertexColors[tess.numVertexes][1] = iColor[1];
|
||||||
|
tess.vertexColors[tess.numVertexes][2] = iColor[2];
|
||||||
|
tess.vertexColors[tess.numVertexes][3] = 255;
|
||||||
|
tess.numVertexes++;
|
||||||
|
|
||||||
|
tess.indexes[tess.numIndexes++] = 0;
|
||||||
|
tess.indexes[tess.numIndexes++] = 1;
|
||||||
|
tess.indexes[tess.numIndexes++] = 2;
|
||||||
|
tess.indexes[tess.numIndexes++] = 0;
|
||||||
|
tess.indexes[tess.numIndexes++] = 2;
|
||||||
|
tess.indexes[tess.numIndexes++] = 3;
|
||||||
|
|
||||||
|
RB_EndSurface();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
RB_RenderFlares
|
||||||
|
|
||||||
|
Because flares are simulating an occular effect, they should be drawn after
|
||||||
|
everything (all views) in the entire frame has been drawn.
|
||||||
|
|
||||||
|
Because of the way portals use the depth buffer to mark off areas, the
|
||||||
|
needed information would be lost after each view, so we are forced to draw
|
||||||
|
flares after each view.
|
||||||
|
|
||||||
|
The resulting artifact is that flares in mirrors or portals don't dim properly
|
||||||
|
when occluded by something in the main view, and portal flares that should
|
||||||
|
extend past the portal edge will be overwritten.
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void RB_RenderFlares (void) {
|
||||||
|
flare_t *f;
|
||||||
|
flare_t **prev;
|
||||||
|
qboolean draw;
|
||||||
|
|
||||||
|
if ( !r_flares->integer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(r_flareCoeff->modified)
|
||||||
|
{
|
||||||
|
R_SetFlareCoeff();
|
||||||
|
r_flareCoeff->modified = qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset currentEntity to world so that any previously referenced entities
|
||||||
|
// don't have influence on the rendering of these flares (i.e. RF_ renderer flags).
|
||||||
|
backEnd.currentEntity = &tr.worldEntity;
|
||||||
|
backEnd.or = backEnd.viewParms.world;
|
||||||
|
|
||||||
|
// RB_AddDlightFlares();
|
||||||
|
|
||||||
|
// perform z buffer readback on each flare in this view
|
||||||
|
draw = qfalse;
|
||||||
|
prev = &r_activeFlares;
|
||||||
|
while ( ( f = *prev ) != NULL ) {
|
||||||
|
// throw out any flares that weren't added last frame
|
||||||
|
if ( f->addedFrame < backEnd.viewParms.frameCount - 1 ) {
|
||||||
|
*prev = f->next;
|
||||||
|
f->next = r_inactiveFlares;
|
||||||
|
r_inactiveFlares = f;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't draw any here that aren't from this scene / portal
|
||||||
|
f->drawIntensity = 0;
|
||||||
|
if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum
|
||||||
|
&& f->inPortal == backEnd.viewParms.isPortal ) {
|
||||||
|
RB_TestFlare( f );
|
||||||
|
if ( f->drawIntensity ) {
|
||||||
|
draw = qtrue;
|
||||||
|
} else {
|
||||||
|
// this flare has completely faded out, so remove it from the chain
|
||||||
|
*prev = f->next;
|
||||||
|
f->next = r_inactiveFlares;
|
||||||
|
r_inactiveFlares = f;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = &f->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !draw ) {
|
||||||
|
return; // none visible
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( backEnd.viewParms.isPortal ) {
|
||||||
|
qglDisable (GL_CLIP_PLANE0);
|
||||||
|
}
|
||||||
|
|
||||||
|
qglPushMatrix();
|
||||||
|
qglLoadIdentity();
|
||||||
|
qglMatrixMode( GL_PROJECTION );
|
||||||
|
qglPushMatrix();
|
||||||
|
qglLoadIdentity();
|
||||||
|
qglOrtho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
|
||||||
|
backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
|
||||||
|
-99999, 99999 );
|
||||||
|
|
||||||
|
for ( f = r_activeFlares ; f ; f = f->next ) {
|
||||||
|
if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum
|
||||||
|
&& f->inPortal == backEnd.viewParms.isPortal
|
||||||
|
&& f->drawIntensity ) {
|
||||||
|
RB_RenderFlare( f );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qglPopMatrix();
|
||||||
|
qglMatrixMode( GL_MODELVIEW );
|
||||||
|
qglPopMatrix();
|
||||||
|
}
|
||||||
|
|
1673
code/renderergl1/tr_image.c
Normal file
1673
code/renderergl1/tr_image.c
Normal file
File diff suppressed because it is too large
Load diff
1388
code/renderergl1/tr_init.c
Normal file
1388
code/renderergl1/tr_init.c
Normal file
File diff suppressed because it is too large
Load diff
400
code/renderergl1/tr_light.c
Normal file
400
code/renderergl1/tr_light.c
Normal file
|
@ -0,0 +1,400 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// tr_light.c
|
||||||
|
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
#define DLIGHT_AT_RADIUS 16
|
||||||
|
// at the edge of a dlight's influence, this amount of light will be added
|
||||||
|
|
||||||
|
#define DLIGHT_MINIMUM_RADIUS 16
|
||||||
|
// never calculate a range less than this to prevent huge light numbers
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_TransformDlights
|
||||||
|
|
||||||
|
Transforms the origins of an array of dlights.
|
||||||
|
Used by both the front end (for DlightBmodel) and
|
||||||
|
the back end (before doing the lighting calculation)
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void R_TransformDlights( int count, dlight_t *dl, orientationr_t *or) {
|
||||||
|
int i;
|
||||||
|
vec3_t temp;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < count ; i++, dl++ ) {
|
||||||
|
VectorSubtract( dl->origin, or->origin, temp );
|
||||||
|
dl->transformed[0] = DotProduct( temp, or->axis[0] );
|
||||||
|
dl->transformed[1] = DotProduct( temp, or->axis[1] );
|
||||||
|
dl->transformed[2] = DotProduct( temp, or->axis[2] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_DlightBmodel
|
||||||
|
|
||||||
|
Determine which dynamic lights may effect this bmodel
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_DlightBmodel( bmodel_t *bmodel ) {
|
||||||
|
int i, j;
|
||||||
|
dlight_t *dl;
|
||||||
|
int mask;
|
||||||
|
msurface_t *surf;
|
||||||
|
|
||||||
|
// transform all the lights
|
||||||
|
R_TransformDlights( tr.refdef.num_dlights, tr.refdef.dlights, &tr.or );
|
||||||
|
|
||||||
|
mask = 0;
|
||||||
|
for ( i=0 ; i<tr.refdef.num_dlights ; i++ ) {
|
||||||
|
dl = &tr.refdef.dlights[i];
|
||||||
|
|
||||||
|
// see if the point is close enough to the bounds to matter
|
||||||
|
for ( j = 0 ; j < 3 ; j++ ) {
|
||||||
|
if ( dl->transformed[j] - bmodel->bounds[1][j] > dl->radius ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( bmodel->bounds[0][j] - dl->transformed[j] > dl->radius ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( j < 3 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to check this light
|
||||||
|
mask |= 1 << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.currentEntity->needDlights = (mask != 0);
|
||||||
|
|
||||||
|
// set the dlight bits in all the surfaces
|
||||||
|
for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
|
||||||
|
surf = bmodel->firstSurface + i;
|
||||||
|
|
||||||
|
if ( *surf->data == SF_FACE ) {
|
||||||
|
((srfSurfaceFace_t *)surf->data)->dlightBits = mask;
|
||||||
|
} else if ( *surf->data == SF_GRID ) {
|
||||||
|
((srfGridMesh_t *)surf->data)->dlightBits = mask;
|
||||||
|
} else if ( *surf->data == SF_TRIANGLES ) {
|
||||||
|
((srfTriangles_t *)surf->data)->dlightBits = mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============================================================================
|
||||||
|
|
||||||
|
LIGHT SAMPLING
|
||||||
|
|
||||||
|
=============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern cvar_t *r_ambientScale;
|
||||||
|
extern cvar_t *r_directedScale;
|
||||||
|
extern cvar_t *r_debugLight;
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_SetupEntityLightingGrid
|
||||||
|
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
|
||||||
|
vec3_t lightOrigin;
|
||||||
|
int pos[3];
|
||||||
|
int i, j;
|
||||||
|
byte *gridData;
|
||||||
|
float frac[3];
|
||||||
|
int gridStep[3];
|
||||||
|
vec3_t direction;
|
||||||
|
float totalFactor;
|
||||||
|
|
||||||
|
if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
|
||||||
|
// separate lightOrigins are needed so an object that is
|
||||||
|
// sinking into the ground can still be lit, and so
|
||||||
|
// multi-part models can be lit identically
|
||||||
|
VectorCopy( ent->e.lightingOrigin, lightOrigin );
|
||||||
|
} else {
|
||||||
|
VectorCopy( ent->e.origin, lightOrigin );
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorSubtract( lightOrigin, tr.world->lightGridOrigin, lightOrigin );
|
||||||
|
for ( i = 0 ; i < 3 ; i++ ) {
|
||||||
|
float v;
|
||||||
|
|
||||||
|
v = lightOrigin[i]*tr.world->lightGridInverseSize[i];
|
||||||
|
pos[i] = floor( v );
|
||||||
|
frac[i] = v - pos[i];
|
||||||
|
if ( pos[i] < 0 ) {
|
||||||
|
pos[i] = 0;
|
||||||
|
} else if ( pos[i] > tr.world->lightGridBounds[i] - 1 ) {
|
||||||
|
pos[i] = tr.world->lightGridBounds[i] - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorClear( ent->ambientLight );
|
||||||
|
VectorClear( ent->directedLight );
|
||||||
|
VectorClear( direction );
|
||||||
|
|
||||||
|
assert( tr.world->lightGridData ); // NULL with -nolight maps
|
||||||
|
|
||||||
|
// trilerp the light value
|
||||||
|
gridStep[0] = 8;
|
||||||
|
gridStep[1] = 8 * tr.world->lightGridBounds[0];
|
||||||
|
gridStep[2] = 8 * tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1];
|
||||||
|
gridData = tr.world->lightGridData + pos[0] * gridStep[0]
|
||||||
|
+ pos[1] * gridStep[1] + pos[2] * gridStep[2];
|
||||||
|
|
||||||
|
totalFactor = 0;
|
||||||
|
for ( i = 0 ; i < 8 ; i++ ) {
|
||||||
|
float factor;
|
||||||
|
byte *data;
|
||||||
|
int lat, lng;
|
||||||
|
vec3_t normal;
|
||||||
|
#if idppc
|
||||||
|
float d0, d1, d2, d3, d4, d5;
|
||||||
|
#endif
|
||||||
|
factor = 1.0;
|
||||||
|
data = gridData;
|
||||||
|
for ( j = 0 ; j < 3 ; j++ ) {
|
||||||
|
if ( i & (1<<j) ) {
|
||||||
|
if ( pos[j] + 1 > tr.world->lightGridBounds[j] - 1 ) {
|
||||||
|
break; // ignore values outside lightgrid
|
||||||
|
}
|
||||||
|
factor *= frac[j];
|
||||||
|
data += gridStep[j];
|
||||||
|
} else {
|
||||||
|
factor *= (1.0f - frac[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( j != 3 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( !(data[0]+data[1]+data[2]) ) {
|
||||||
|
continue; // ignore samples in walls
|
||||||
|
}
|
||||||
|
totalFactor += factor;
|
||||||
|
#if idppc
|
||||||
|
d0 = data[0]; d1 = data[1]; d2 = data[2];
|
||||||
|
d3 = data[3]; d4 = data[4]; d5 = data[5];
|
||||||
|
|
||||||
|
ent->ambientLight[0] += factor * d0;
|
||||||
|
ent->ambientLight[1] += factor * d1;
|
||||||
|
ent->ambientLight[2] += factor * d2;
|
||||||
|
|
||||||
|
ent->directedLight[0] += factor * d3;
|
||||||
|
ent->directedLight[1] += factor * d4;
|
||||||
|
ent->directedLight[2] += factor * d5;
|
||||||
|
#else
|
||||||
|
ent->ambientLight[0] += factor * data[0];
|
||||||
|
ent->ambientLight[1] += factor * data[1];
|
||||||
|
ent->ambientLight[2] += factor * data[2];
|
||||||
|
|
||||||
|
ent->directedLight[0] += factor * data[3];
|
||||||
|
ent->directedLight[1] += factor * data[4];
|
||||||
|
ent->directedLight[2] += factor * data[5];
|
||||||
|
#endif
|
||||||
|
lat = data[7];
|
||||||
|
lng = data[6];
|
||||||
|
lat *= (FUNCTABLE_SIZE/256);
|
||||||
|
lng *= (FUNCTABLE_SIZE/256);
|
||||||
|
|
||||||
|
// decode X as cos( lat ) * sin( long )
|
||||||
|
// decode Y as sin( lat ) * sin( long )
|
||||||
|
// decode Z as cos( long )
|
||||||
|
|
||||||
|
normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
|
||||||
|
normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
|
||||||
|
normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
|
||||||
|
|
||||||
|
VectorMA( direction, factor, normal, direction );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( totalFactor > 0 && totalFactor < 0.99 ) {
|
||||||
|
totalFactor = 1.0f / totalFactor;
|
||||||
|
VectorScale( ent->ambientLight, totalFactor, ent->ambientLight );
|
||||||
|
VectorScale( ent->directedLight, totalFactor, ent->directedLight );
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorScale( ent->ambientLight, r_ambientScale->value, ent->ambientLight );
|
||||||
|
VectorScale( ent->directedLight, r_directedScale->value, ent->directedLight );
|
||||||
|
|
||||||
|
VectorNormalize2( direction, ent->lightDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
LogLight
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void LogLight( trRefEntity_t *ent ) {
|
||||||
|
int max1, max2;
|
||||||
|
|
||||||
|
if ( !(ent->e.renderfx & RF_FIRST_PERSON ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
max1 = ent->ambientLight[0];
|
||||||
|
if ( ent->ambientLight[1] > max1 ) {
|
||||||
|
max1 = ent->ambientLight[1];
|
||||||
|
} else if ( ent->ambientLight[2] > max1 ) {
|
||||||
|
max1 = ent->ambientLight[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
max2 = ent->directedLight[0];
|
||||||
|
if ( ent->directedLight[1] > max2 ) {
|
||||||
|
max2 = ent->directedLight[1];
|
||||||
|
} else if ( ent->directedLight[2] > max2 ) {
|
||||||
|
max2 = ent->directedLight[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
ri.Printf( PRINT_ALL, "amb:%i dir:%i\n", max1, max2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_SetupEntityLighting
|
||||||
|
|
||||||
|
Calculates all the lighting values that will be used
|
||||||
|
by the Calc_* functions
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
|
||||||
|
int i;
|
||||||
|
dlight_t *dl;
|
||||||
|
float power;
|
||||||
|
vec3_t dir;
|
||||||
|
float d;
|
||||||
|
vec3_t lightDir;
|
||||||
|
vec3_t lightOrigin;
|
||||||
|
|
||||||
|
// lighting calculations
|
||||||
|
if ( ent->lightingCalculated ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ent->lightingCalculated = qtrue;
|
||||||
|
|
||||||
|
//
|
||||||
|
// trace a sample point down to find ambient light
|
||||||
|
//
|
||||||
|
if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
|
||||||
|
// separate lightOrigins are needed so an object that is
|
||||||
|
// sinking into the ground can still be lit, and so
|
||||||
|
// multi-part models can be lit identically
|
||||||
|
VectorCopy( ent->e.lightingOrigin, lightOrigin );
|
||||||
|
} else {
|
||||||
|
VectorCopy( ent->e.origin, lightOrigin );
|
||||||
|
}
|
||||||
|
|
||||||
|
// if NOWORLDMODEL, only use dynamic lights (menu system, etc)
|
||||||
|
if ( !(refdef->rdflags & RDF_NOWORLDMODEL )
|
||||||
|
&& tr.world->lightGridData ) {
|
||||||
|
R_SetupEntityLightingGrid( ent );
|
||||||
|
} else {
|
||||||
|
ent->ambientLight[0] = ent->ambientLight[1] =
|
||||||
|
ent->ambientLight[2] = tr.identityLight * 150;
|
||||||
|
ent->directedLight[0] = ent->directedLight[1] =
|
||||||
|
ent->directedLight[2] = tr.identityLight * 150;
|
||||||
|
VectorCopy( tr.sunDirection, ent->lightDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
// bonus items and view weapons have a fixed minimum add
|
||||||
|
if ( 1 /* ent->e.renderfx & RF_MINLIGHT */ ) {
|
||||||
|
// give everything a minimum light add
|
||||||
|
ent->ambientLight[0] += tr.identityLight * 32;
|
||||||
|
ent->ambientLight[1] += tr.identityLight * 32;
|
||||||
|
ent->ambientLight[2] += tr.identityLight * 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// modify the light by dynamic lights
|
||||||
|
//
|
||||||
|
d = VectorLength( ent->directedLight );
|
||||||
|
VectorScale( ent->lightDir, d, lightDir );
|
||||||
|
|
||||||
|
for ( i = 0 ; i < refdef->num_dlights ; i++ ) {
|
||||||
|
dl = &refdef->dlights[i];
|
||||||
|
VectorSubtract( dl->origin, lightOrigin, dir );
|
||||||
|
d = VectorNormalize( dir );
|
||||||
|
|
||||||
|
power = DLIGHT_AT_RADIUS * ( dl->radius * dl->radius );
|
||||||
|
if ( d < DLIGHT_MINIMUM_RADIUS ) {
|
||||||
|
d = DLIGHT_MINIMUM_RADIUS;
|
||||||
|
}
|
||||||
|
d = power / ( d * d );
|
||||||
|
|
||||||
|
VectorMA( ent->directedLight, d, dl->color, ent->directedLight );
|
||||||
|
VectorMA( lightDir, d, dir, lightDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
// clamp ambient
|
||||||
|
for ( i = 0 ; i < 3 ; i++ ) {
|
||||||
|
if ( ent->ambientLight[i] > tr.identityLightByte ) {
|
||||||
|
ent->ambientLight[i] = tr.identityLightByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( r_debugLight->integer ) {
|
||||||
|
LogLight( ent );
|
||||||
|
}
|
||||||
|
|
||||||
|
// save out the byte packet version
|
||||||
|
((byte *)&ent->ambientLightInt)[0] = ri.ftol(ent->ambientLight[0]);
|
||||||
|
((byte *)&ent->ambientLightInt)[1] = ri.ftol(ent->ambientLight[1]);
|
||||||
|
((byte *)&ent->ambientLightInt)[2] = ri.ftol(ent->ambientLight[2]);
|
||||||
|
((byte *)&ent->ambientLightInt)[3] = 0xff;
|
||||||
|
|
||||||
|
// transform the direction to local space
|
||||||
|
VectorNormalize( lightDir );
|
||||||
|
ent->lightDir[0] = DotProduct( lightDir, ent->e.axis[0] );
|
||||||
|
ent->lightDir[1] = DotProduct( lightDir, ent->e.axis[1] );
|
||||||
|
ent->lightDir[2] = DotProduct( lightDir, ent->e.axis[2] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_LightForPoint
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir )
|
||||||
|
{
|
||||||
|
trRefEntity_t ent;
|
||||||
|
|
||||||
|
if ( tr.world->lightGridData == NULL )
|
||||||
|
return qfalse;
|
||||||
|
|
||||||
|
Com_Memset(&ent, 0, sizeof(ent));
|
||||||
|
VectorCopy( point, ent.e.origin );
|
||||||
|
R_SetupEntityLightingGrid( &ent );
|
||||||
|
VectorCopy(ent.ambientLight, ambientLight);
|
||||||
|
VectorCopy(ent.directedLight, directedLight);
|
||||||
|
VectorCopy(ent.lightDir, lightDir);
|
||||||
|
|
||||||
|
return qtrue;
|
||||||
|
}
|
1616
code/renderergl1/tr_local.h
Normal file
1616
code/renderergl1/tr_local.h
Normal file
File diff suppressed because it is too large
Load diff
1398
code/renderergl1/tr_main.c
Normal file
1398
code/renderergl1/tr_main.c
Normal file
File diff suppressed because it is too large
Load diff
458
code/renderergl1/tr_marks.c
Normal file
458
code/renderergl1/tr_marks.c
Normal file
|
@ -0,0 +1,458 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// tr_marks.c -- polygon projection on the world polygons
|
||||||
|
|
||||||
|
#include "tr_local.h"
|
||||||
|
//#include "assert.h"
|
||||||
|
|
||||||
|
#define MAX_VERTS_ON_POLY 64
|
||||||
|
|
||||||
|
#define MARKER_OFFSET 0 // 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_ChopPolyBehindPlane
|
||||||
|
|
||||||
|
Out must have space for two more vertexes than in
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
#define SIDE_FRONT 0
|
||||||
|
#define SIDE_BACK 1
|
||||||
|
#define SIDE_ON 2
|
||||||
|
static void R_ChopPolyBehindPlane( int numInPoints, vec3_t inPoints[MAX_VERTS_ON_POLY],
|
||||||
|
int *numOutPoints, vec3_t outPoints[MAX_VERTS_ON_POLY],
|
||||||
|
vec3_t normal, vec_t dist, vec_t epsilon) {
|
||||||
|
float dists[MAX_VERTS_ON_POLY+4] = { 0 };
|
||||||
|
int sides[MAX_VERTS_ON_POLY+4] = { 0 };
|
||||||
|
int counts[3];
|
||||||
|
float dot;
|
||||||
|
int i, j;
|
||||||
|
float *p1, *p2, *clip;
|
||||||
|
float d;
|
||||||
|
|
||||||
|
// don't clip if it might overflow
|
||||||
|
if ( numInPoints >= MAX_VERTS_ON_POLY - 2 ) {
|
||||||
|
*numOutPoints = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
counts[0] = counts[1] = counts[2] = 0;
|
||||||
|
|
||||||
|
// determine sides for each point
|
||||||
|
for ( i = 0 ; i < numInPoints ; i++ ) {
|
||||||
|
dot = DotProduct( inPoints[i], normal );
|
||||||
|
dot -= dist;
|
||||||
|
dists[i] = dot;
|
||||||
|
if ( dot > epsilon ) {
|
||||||
|
sides[i] = SIDE_FRONT;
|
||||||
|
} else if ( dot < -epsilon ) {
|
||||||
|
sides[i] = SIDE_BACK;
|
||||||
|
} else {
|
||||||
|
sides[i] = SIDE_ON;
|
||||||
|
}
|
||||||
|
counts[sides[i]]++;
|
||||||
|
}
|
||||||
|
sides[i] = sides[0];
|
||||||
|
dists[i] = dists[0];
|
||||||
|
|
||||||
|
*numOutPoints = 0;
|
||||||
|
|
||||||
|
if ( !counts[0] ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( !counts[1] ) {
|
||||||
|
*numOutPoints = numInPoints;
|
||||||
|
Com_Memcpy( outPoints, inPoints, numInPoints * sizeof(vec3_t) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0 ; i < numInPoints ; i++ ) {
|
||||||
|
p1 = inPoints[i];
|
||||||
|
clip = outPoints[ *numOutPoints ];
|
||||||
|
|
||||||
|
if ( sides[i] == SIDE_ON ) {
|
||||||
|
VectorCopy( p1, clip );
|
||||||
|
(*numOutPoints)++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( sides[i] == SIDE_FRONT ) {
|
||||||
|
VectorCopy( p1, clip );
|
||||||
|
(*numOutPoints)++;
|
||||||
|
clip = outPoints[ *numOutPoints ];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( sides[i+1] == SIDE_ON || sides[i+1] == sides[i] ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate a split point
|
||||||
|
p2 = inPoints[ (i+1) % numInPoints ];
|
||||||
|
|
||||||
|
d = dists[i] - dists[i+1];
|
||||||
|
if ( d == 0 ) {
|
||||||
|
dot = 0;
|
||||||
|
} else {
|
||||||
|
dot = dists[i] / d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clip xyz
|
||||||
|
|
||||||
|
for (j=0 ; j<3 ; j++) {
|
||||||
|
clip[j] = p1[j] + dot * ( p2[j] - p1[j] );
|
||||||
|
}
|
||||||
|
|
||||||
|
(*numOutPoints)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_BoxSurfaces_r
|
||||||
|
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir) {
|
||||||
|
|
||||||
|
int s, c;
|
||||||
|
msurface_t *surf, **mark;
|
||||||
|
|
||||||
|
// do the tail recursion in a loop
|
||||||
|
while ( node->contents == -1 ) {
|
||||||
|
s = BoxOnPlaneSide( mins, maxs, node->plane );
|
||||||
|
if (s == 1) {
|
||||||
|
node = node->children[0];
|
||||||
|
} else if (s == 2) {
|
||||||
|
node = node->children[1];
|
||||||
|
} else {
|
||||||
|
R_BoxSurfaces_r(node->children[0], mins, maxs, list, listsize, listlength, dir);
|
||||||
|
node = node->children[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the individual surfaces
|
||||||
|
mark = node->firstmarksurface;
|
||||||
|
c = node->nummarksurfaces;
|
||||||
|
while (c--) {
|
||||||
|
//
|
||||||
|
if (*listlength >= listsize) break;
|
||||||
|
//
|
||||||
|
surf = *mark;
|
||||||
|
// check if the surface has NOIMPACT or NOMARKS set
|
||||||
|
if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) )
|
||||||
|
|| ( surf->shader->contentFlags & CONTENTS_FOG ) ) {
|
||||||
|
surf->viewCount = tr.viewCount;
|
||||||
|
}
|
||||||
|
// extra check for surfaces to avoid list overflows
|
||||||
|
else if (*(surf->data) == SF_FACE) {
|
||||||
|
// the face plane should go through the box
|
||||||
|
s = BoxOnPlaneSide( mins, maxs, &(( srfSurfaceFace_t * ) surf->data)->plane );
|
||||||
|
if (s == 1 || s == 2) {
|
||||||
|
surf->viewCount = tr.viewCount;
|
||||||
|
} else if (DotProduct((( srfSurfaceFace_t * ) surf->data)->plane.normal, dir) > -0.5) {
|
||||||
|
// don't add faces that make sharp angles with the projection direction
|
||||||
|
surf->viewCount = tr.viewCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*(surfaceType_t *) (surf->data) != SF_GRID &&
|
||||||
|
*(surfaceType_t *) (surf->data) != SF_TRIANGLES)
|
||||||
|
surf->viewCount = tr.viewCount;
|
||||||
|
// check the viewCount because the surface may have
|
||||||
|
// already been added if it spans multiple leafs
|
||||||
|
if (surf->viewCount != tr.viewCount) {
|
||||||
|
surf->viewCount = tr.viewCount;
|
||||||
|
list[*listlength] = (surfaceType_t *) surf->data;
|
||||||
|
(*listlength)++;
|
||||||
|
}
|
||||||
|
mark++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_AddMarkFragments
|
||||||
|
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void R_AddMarkFragments(int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_POLY],
|
||||||
|
int numPlanes, vec3_t *normals, float *dists,
|
||||||
|
int maxPoints, vec3_t pointBuffer,
|
||||||
|
int maxFragments, markFragment_t *fragmentBuffer,
|
||||||
|
int *returnedPoints, int *returnedFragments,
|
||||||
|
vec3_t mins, vec3_t maxs) {
|
||||||
|
int pingPong, i;
|
||||||
|
markFragment_t *mf;
|
||||||
|
|
||||||
|
// chop the surface by all the bounding planes of the to be projected polygon
|
||||||
|
pingPong = 0;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < numPlanes ; i++ ) {
|
||||||
|
|
||||||
|
R_ChopPolyBehindPlane( numClipPoints, clipPoints[pingPong],
|
||||||
|
&numClipPoints, clipPoints[!pingPong],
|
||||||
|
normals[i], dists[i], 0.5 );
|
||||||
|
pingPong ^= 1;
|
||||||
|
if ( numClipPoints == 0 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// completely clipped away?
|
||||||
|
if ( numClipPoints == 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add this fragment to the returned list
|
||||||
|
if ( numClipPoints + (*returnedPoints) > maxPoints ) {
|
||||||
|
return; // not enough space for this polygon
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// all the clip points should be within the bounding box
|
||||||
|
for ( i = 0 ; i < numClipPoints ; i++ ) {
|
||||||
|
int j;
|
||||||
|
for ( j = 0 ; j < 3 ; j++ ) {
|
||||||
|
if (clipPoints[pingPong][i][j] < mins[j] - 0.5) break;
|
||||||
|
if (clipPoints[pingPong][i][j] > maxs[j] + 0.5) break;
|
||||||
|
}
|
||||||
|
if (j < 3) break;
|
||||||
|
}
|
||||||
|
if (i < numClipPoints) return;
|
||||||
|
*/
|
||||||
|
|
||||||
|
mf = fragmentBuffer + (*returnedFragments);
|
||||||
|
mf->firstPoint = (*returnedPoints);
|
||||||
|
mf->numPoints = numClipPoints;
|
||||||
|
Com_Memcpy( pointBuffer + (*returnedPoints) * 3, clipPoints[pingPong], numClipPoints * sizeof(vec3_t) );
|
||||||
|
|
||||||
|
(*returnedPoints) += numClipPoints;
|
||||||
|
(*returnedFragments)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_MarkFragments
|
||||||
|
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
|
||||||
|
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) {
|
||||||
|
int numsurfaces, numPlanes;
|
||||||
|
int i, j, k, m, n;
|
||||||
|
surfaceType_t *surfaces[64];
|
||||||
|
vec3_t mins, maxs;
|
||||||
|
int returnedFragments;
|
||||||
|
int returnedPoints;
|
||||||
|
vec3_t normals[MAX_VERTS_ON_POLY+2];
|
||||||
|
float dists[MAX_VERTS_ON_POLY+2];
|
||||||
|
vec3_t clipPoints[2][MAX_VERTS_ON_POLY];
|
||||||
|
int numClipPoints;
|
||||||
|
float *v;
|
||||||
|
srfGridMesh_t *cv;
|
||||||
|
drawVert_t *dv;
|
||||||
|
vec3_t normal;
|
||||||
|
vec3_t projectionDir;
|
||||||
|
vec3_t v1, v2;
|
||||||
|
int *indexes;
|
||||||
|
|
||||||
|
if (numPoints <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//increment view count for double check prevention
|
||||||
|
tr.viewCount++;
|
||||||
|
|
||||||
|
//
|
||||||
|
VectorNormalize2( projection, projectionDir );
|
||||||
|
// find all the brushes that are to be considered
|
||||||
|
ClearBounds( mins, maxs );
|
||||||
|
for ( i = 0 ; i < numPoints ; i++ ) {
|
||||||
|
vec3_t temp;
|
||||||
|
|
||||||
|
AddPointToBounds( points[i], mins, maxs );
|
||||||
|
VectorAdd( points[i], projection, temp );
|
||||||
|
AddPointToBounds( temp, mins, maxs );
|
||||||
|
// make sure we get all the leafs (also the one(s) in front of the hit surface)
|
||||||
|
VectorMA( points[i], -20, projectionDir, temp );
|
||||||
|
AddPointToBounds( temp, mins, maxs );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numPoints > MAX_VERTS_ON_POLY) numPoints = MAX_VERTS_ON_POLY;
|
||||||
|
// create the bounding planes for the to be projected polygon
|
||||||
|
for ( i = 0 ; i < numPoints ; i++ ) {
|
||||||
|
VectorSubtract(points[(i+1)%numPoints], points[i], v1);
|
||||||
|
VectorAdd(points[i], projection, v2);
|
||||||
|
VectorSubtract(points[i], v2, v2);
|
||||||
|
CrossProduct(v1, v2, normals[i]);
|
||||||
|
VectorNormalizeFast(normals[i]);
|
||||||
|
dists[i] = DotProduct(normals[i], points[i]);
|
||||||
|
}
|
||||||
|
// add near and far clipping planes for projection
|
||||||
|
VectorCopy(projectionDir, normals[numPoints]);
|
||||||
|
dists[numPoints] = DotProduct(normals[numPoints], points[0]) - 32;
|
||||||
|
VectorCopy(projectionDir, normals[numPoints+1]);
|
||||||
|
VectorInverse(normals[numPoints+1]);
|
||||||
|
dists[numPoints+1] = DotProduct(normals[numPoints+1], points[0]) - 20;
|
||||||
|
numPlanes = numPoints + 2;
|
||||||
|
|
||||||
|
numsurfaces = 0;
|
||||||
|
R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, 64, &numsurfaces, projectionDir);
|
||||||
|
//assert(numsurfaces <= 64);
|
||||||
|
//assert(numsurfaces != 64);
|
||||||
|
|
||||||
|
returnedPoints = 0;
|
||||||
|
returnedFragments = 0;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < numsurfaces ; i++ ) {
|
||||||
|
|
||||||
|
if (*surfaces[i] == SF_GRID) {
|
||||||
|
|
||||||
|
cv = (srfGridMesh_t *) surfaces[i];
|
||||||
|
for ( m = 0 ; m < cv->height - 1 ; m++ ) {
|
||||||
|
for ( n = 0 ; n < cv->width - 1 ; n++ ) {
|
||||||
|
// We triangulate the grid and chop all triangles within
|
||||||
|
// the bounding planes of the to be projected polygon.
|
||||||
|
// LOD is not taken into account, not such a big deal though.
|
||||||
|
//
|
||||||
|
// It's probably much nicer to chop the grid itself and deal
|
||||||
|
// with this grid as a normal SF_GRID surface so LOD will
|
||||||
|
// be applied. However the LOD of that chopped grid must
|
||||||
|
// be synced with the LOD of the original curve.
|
||||||
|
// One way to do this; the chopped grid shares vertices with
|
||||||
|
// the original curve. When LOD is applied to the original
|
||||||
|
// curve the unused vertices are flagged. Now the chopped curve
|
||||||
|
// should skip the flagged vertices. This still leaves the
|
||||||
|
// problems with the vertices at the chopped grid edges.
|
||||||
|
//
|
||||||
|
// To avoid issues when LOD applied to "hollow curves" (like
|
||||||
|
// the ones around many jump pads) we now just add a 2 unit
|
||||||
|
// offset to the triangle vertices.
|
||||||
|
// The offset is added in the vertex normal vector direction
|
||||||
|
// so all triangles will still fit together.
|
||||||
|
// The 2 unit offset should avoid pretty much all LOD problems.
|
||||||
|
|
||||||
|
numClipPoints = 3;
|
||||||
|
|
||||||
|
dv = cv->verts + m * cv->width + n;
|
||||||
|
|
||||||
|
VectorCopy(dv[0].xyz, clipPoints[0][0]);
|
||||||
|
VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
|
||||||
|
VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
|
||||||
|
VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
|
||||||
|
VectorCopy(dv[1].xyz, clipPoints[0][2]);
|
||||||
|
VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
|
||||||
|
// check the normal of this triangle
|
||||||
|
VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
|
||||||
|
VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
|
||||||
|
CrossProduct(v1, v2, normal);
|
||||||
|
VectorNormalizeFast(normal);
|
||||||
|
if (DotProduct(normal, projectionDir) < -0.1) {
|
||||||
|
// add the fragments of this triangle
|
||||||
|
R_AddMarkFragments(numClipPoints, clipPoints,
|
||||||
|
numPlanes, normals, dists,
|
||||||
|
maxPoints, pointBuffer,
|
||||||
|
maxFragments, fragmentBuffer,
|
||||||
|
&returnedPoints, &returnedFragments, mins, maxs);
|
||||||
|
|
||||||
|
if ( returnedFragments == maxFragments ) {
|
||||||
|
return returnedFragments; // not enough space for more fragments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorCopy(dv[1].xyz, clipPoints[0][0]);
|
||||||
|
VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
|
||||||
|
VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
|
||||||
|
VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
|
||||||
|
VectorCopy(dv[cv->width+1].xyz, clipPoints[0][2]);
|
||||||
|
VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width+1].normal, clipPoints[0][2]);
|
||||||
|
// check the normal of this triangle
|
||||||
|
VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
|
||||||
|
VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
|
||||||
|
CrossProduct(v1, v2, normal);
|
||||||
|
VectorNormalizeFast(normal);
|
||||||
|
if (DotProduct(normal, projectionDir) < -0.05) {
|
||||||
|
// add the fragments of this triangle
|
||||||
|
R_AddMarkFragments(numClipPoints, clipPoints,
|
||||||
|
numPlanes, normals, dists,
|
||||||
|
maxPoints, pointBuffer,
|
||||||
|
maxFragments, fragmentBuffer,
|
||||||
|
&returnedPoints, &returnedFragments, mins, maxs);
|
||||||
|
|
||||||
|
if ( returnedFragments == maxFragments ) {
|
||||||
|
return returnedFragments; // not enough space for more fragments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*surfaces[i] == SF_FACE) {
|
||||||
|
|
||||||
|
srfSurfaceFace_t *surf = ( srfSurfaceFace_t * ) surfaces[i];
|
||||||
|
|
||||||
|
// check the normal of this face
|
||||||
|
if (DotProduct(surf->plane.normal, projectionDir) > -0.5) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
indexes = (int *)( (byte *)surf + surf->ofsIndices );
|
||||||
|
for ( k = 0 ; k < surf->numIndices ; k += 3 ) {
|
||||||
|
for ( j = 0 ; j < 3 ; j++ ) {
|
||||||
|
v = &surf->points[0][0] + VERTEXSIZE * indexes[k+j];
|
||||||
|
VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the fragments of this face
|
||||||
|
R_AddMarkFragments( 3 , clipPoints,
|
||||||
|
numPlanes, normals, dists,
|
||||||
|
maxPoints, pointBuffer,
|
||||||
|
maxFragments, fragmentBuffer,
|
||||||
|
&returnedPoints, &returnedFragments, mins, maxs);
|
||||||
|
if ( returnedFragments == maxFragments ) {
|
||||||
|
return returnedFragments; // not enough space for more fragments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(*surfaces[i] == SF_TRIANGLES && r_marksOnTriangleMeshes->integer) {
|
||||||
|
|
||||||
|
srfTriangles_t *surf = (srfTriangles_t *) surfaces[i];
|
||||||
|
|
||||||
|
for (k = 0; k < surf->numIndexes; k += 3)
|
||||||
|
{
|
||||||
|
for(j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
v = surf->verts[surf->indexes[k + j]].xyz;
|
||||||
|
VectorMA(v, MARKER_OFFSET, surf->verts[surf->indexes[k + j]].normal, clipPoints[0][j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the fragments of this face
|
||||||
|
R_AddMarkFragments(3, clipPoints,
|
||||||
|
numPlanes, normals, dists,
|
||||||
|
maxPoints, pointBuffer,
|
||||||
|
maxFragments, fragmentBuffer, &returnedPoints, &returnedFragments, mins, maxs);
|
||||||
|
if(returnedFragments == maxFragments)
|
||||||
|
{
|
||||||
|
return returnedFragments; // not enough space for more fragments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnedFragments;
|
||||||
|
}
|
||||||
|
|
|
@ -23,21 +23,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
int TIKI_Skel_Bones_Index;
|
|
||||||
int skeletorMorphCacheIndex;
|
|
||||||
skelBoneCache_t TIKI_Skel_Bones[ MAX_SKELBONES ];
|
|
||||||
int skeletorMorphCache[ MAX_SKELMORPH ];
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
TIKI_Reset_Caches
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void TIKI_Reset_Caches( void ) {
|
|
||||||
TIKI_Skel_Bones_Index = 0;
|
|
||||||
skeletorMorphCacheIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float ProjectRadius( float r, vec3_t location )
|
static float ProjectRadius( float r, vec3_t location )
|
||||||
{
|
{
|
||||||
float pr;
|
float pr;
|
||||||
|
@ -85,20 +70,19 @@ static float ProjectRadius( float r, vec3_t location )
|
||||||
return pr;
|
return pr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
R_CullModel
|
R_CullModel
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) {
|
static int R_CullModel( md3Header_t *header, trRefEntity_t *ent ) {
|
||||||
vec3_t bounds[2];
|
vec3_t bounds[2];
|
||||||
mdvFrame_t *oldFrame, *newFrame;
|
md3Frame_t *oldFrame, *newFrame;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// compute frame pointers
|
// compute frame pointers
|
||||||
newFrame = model->frames + ent->e.frame;
|
newFrame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame;
|
||||||
oldFrame = model->frames + ent->e.oldframe;
|
oldFrame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.oldframe;
|
||||||
|
|
||||||
// cull bounding sphere ONLY if this is not an upscaled entity
|
// cull bounding sphere ONLY if this is not an upscaled entity
|
||||||
if ( !ent->e.nonNormalizedAxes )
|
if ( !ent->e.nonNormalizedAxes )
|
||||||
|
@ -172,6 +156,7 @@ static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
R_ComputeLOD
|
R_ComputeLOD
|
||||||
|
@ -182,7 +167,7 @@ int R_ComputeLOD( trRefEntity_t *ent ) {
|
||||||
float radius;
|
float radius;
|
||||||
float flod, lodscale;
|
float flod, lodscale;
|
||||||
float projectedRadius;
|
float projectedRadius;
|
||||||
mdvFrame_t *frame;
|
md3Frame_t *frame;
|
||||||
mdrHeader_t *mdr;
|
mdrHeader_t *mdr;
|
||||||
mdrFrame_t *mdrframe;
|
mdrFrame_t *mdrframe;
|
||||||
int lod;
|
int lod;
|
||||||
|
@ -209,8 +194,7 @@ int R_ComputeLOD( trRefEntity_t *ent ) {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
|
frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
|
||||||
frame = tr.currentModel->mdv[0]->frames;
|
|
||||||
|
|
||||||
frame += ent->e.frame;
|
frame += ent->e.frame;
|
||||||
|
|
||||||
|
@ -230,7 +214,7 @@ int R_ComputeLOD( trRefEntity_t *ent ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
flod *= tr.currentModel->numLods;
|
flod *= tr.currentModel->numLods;
|
||||||
lod = ftol(flod);
|
lod = ri.ftol(flod);
|
||||||
|
|
||||||
if ( lod < 0 )
|
if ( lod < 0 )
|
||||||
{
|
{
|
||||||
|
@ -251,19 +235,17 @@ int R_ComputeLOD( trRefEntity_t *ent ) {
|
||||||
|
|
||||||
return lod;
|
return lod;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
R_ComputeFogNum
|
R_ComputeFogNum
|
||||||
|
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) {
|
int R_ComputeFogNum( md3Header_t *header, trRefEntity_t *ent ) {
|
||||||
int i, j;
|
int i, j;
|
||||||
fog_t *fog;
|
fog_t *fog;
|
||||||
mdvFrame_t *mdvFrame;
|
md3Frame_t *md3Frame;
|
||||||
vec3_t localOrigin;
|
vec3_t localOrigin;
|
||||||
|
|
||||||
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
|
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
|
||||||
|
@ -271,15 +253,15 @@ int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: non-normalized axis issues
|
// FIXME: non-normalized axis issues
|
||||||
mdvFrame = model->frames + ent->e.frame;
|
md3Frame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame;
|
||||||
VectorAdd( ent->e.origin, mdvFrame->localOrigin, localOrigin );
|
VectorAdd( ent->e.origin, md3Frame->localOrigin, localOrigin );
|
||||||
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
|
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
|
||||||
fog = &tr.world->fogs[i];
|
fog = &tr.world->fogs[i];
|
||||||
for ( j = 0 ; j < 3 ; j++ ) {
|
for ( j = 0 ; j < 3 ; j++ ) {
|
||||||
if ( localOrigin[j] - mdvFrame->radius >= fog->bounds[1][j] ) {
|
if ( localOrigin[j] - md3Frame->radius >= fog->bounds[1][j] ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( localOrigin[j] + mdvFrame->radius <= fog->bounds[0][j] ) {
|
if ( localOrigin[j] + md3Frame->radius <= fog->bounds[0][j] ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,10 +269,10 @@ int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
R_AddMD3Surfaces
|
R_AddMD3Surfaces
|
||||||
|
@ -299,22 +281,21 @@ R_AddMD3Surfaces
|
||||||
*/
|
*/
|
||||||
void R_AddMD3Surfaces( trRefEntity_t *ent ) {
|
void R_AddMD3Surfaces( trRefEntity_t *ent ) {
|
||||||
int i;
|
int i;
|
||||||
mdvModel_t *model = NULL;
|
md3Header_t *header = NULL;
|
||||||
mdvSurface_t *surface = NULL;
|
md3Surface_t *surface = NULL;
|
||||||
|
md3Shader_t *md3Shader = NULL;
|
||||||
shader_t *shader = NULL;
|
shader_t *shader = NULL;
|
||||||
int cull;
|
int cull;
|
||||||
int lod;
|
int lod;
|
||||||
int fogNum;
|
int fogNum;
|
||||||
int cubemapIndex;
|
|
||||||
qboolean personalModel;
|
qboolean personalModel;
|
||||||
|
|
||||||
// don't add third_person objects if not in a portal
|
// don't add third_person objects if not in a portal
|
||||||
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal
|
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
|
||||||
|| (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW)));
|
|
||||||
|
|
||||||
if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
|
if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
|
||||||
ent->e.frame %= tr.currentModel->mdv[0]->numFrames;
|
ent->e.frame %= tr.currentModel->md3[0]->numFrames;
|
||||||
ent->e.oldframe %= tr.currentModel->mdv[0]->numFrames;
|
ent->e.oldframe %= tr.currentModel->md3[0]->numFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -323,9 +304,9 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
|
||||||
// when the surfaces are rendered, they don't need to be
|
// when the surfaces are rendered, they don't need to be
|
||||||
// range checked again.
|
// range checked again.
|
||||||
//
|
//
|
||||||
if ( (ent->e.frame >= tr.currentModel->mdv[0]->numFrames)
|
if ( (ent->e.frame >= tr.currentModel->md3[0]->numFrames)
|
||||||
|| (ent->e.frame < 0)
|
|| (ent->e.frame < 0)
|
||||||
|| (ent->e.oldframe >= tr.currentModel->mdv[0]->numFrames)
|
|| (ent->e.oldframe >= tr.currentModel->md3[0]->numFrames)
|
||||||
|| (ent->e.oldframe < 0) ) {
|
|| (ent->e.oldframe < 0) ) {
|
||||||
ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n",
|
ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n",
|
||||||
ent->e.oldframe, ent->e.frame,
|
ent->e.oldframe, ent->e.frame,
|
||||||
|
@ -339,13 +320,13 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
|
||||||
//
|
//
|
||||||
lod = R_ComputeLOD( ent );
|
lod = R_ComputeLOD( ent );
|
||||||
|
|
||||||
model = tr.currentModel->mdv[lod];
|
header = tr.currentModel->md3[lod];
|
||||||
|
|
||||||
//
|
//
|
||||||
// cull the entire model if merged bounding box of both frames
|
// cull the entire model if merged bounding box of both frames
|
||||||
// is outside the view frustum.
|
// is outside the view frustum.
|
||||||
//
|
//
|
||||||
cull = R_CullModel ( model, ent );
|
cull = R_CullModel ( header, ent );
|
||||||
if ( cull == CULL_OUT ) {
|
if ( cull == CULL_OUT ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -360,15 +341,13 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
|
||||||
//
|
//
|
||||||
// see if we are in a fog volume
|
// see if we are in a fog volume
|
||||||
//
|
//
|
||||||
fogNum = R_ComputeFogNum( model, ent );
|
fogNum = R_ComputeFogNum( header, ent );
|
||||||
|
|
||||||
cubemapIndex = R_CubemapForPoint(ent->e.origin);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// draw all surfaces
|
// draw all surfaces
|
||||||
//
|
//
|
||||||
surface = model->surfaces;
|
surface = (md3Surface_t *)( (byte *)header + header->ofsSurfaces );
|
||||||
for ( i = 0 ; i < model->numSurfaces ; i++ ) {
|
for ( i = 0 ; i < header->numSurfaces ; i++ ) {
|
||||||
|
|
||||||
if ( ent->e.customShader ) {
|
if ( ent->e.customShader ) {
|
||||||
shader = R_GetShaderByHandle( ent->e.customShader );
|
shader = R_GetShaderByHandle( ent->e.customShader );
|
||||||
|
@ -382,8 +361,8 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
|
||||||
shader = tr.defaultShader;
|
shader = tr.defaultShader;
|
||||||
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
|
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
|
||||||
// the names have both been lowercased
|
// the names have both been lowercased
|
||||||
if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
|
if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
|
||||||
shader = skin->surfaces[j]->shader;
|
shader = skin->surfaces[j].shader;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,29 +372,41 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
|
||||||
else if (shader->defaultShader) {
|
else if (shader->defaultShader) {
|
||||||
ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
|
ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
|
||||||
}
|
}
|
||||||
//} else if ( surface->numShaders <= 0 ) {
|
} else if ( surface->numShaders <= 0 ) {
|
||||||
//shader = tr.defaultShader;
|
shader = tr.defaultShader;
|
||||||
} else {
|
} else {
|
||||||
//md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders );
|
md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders );
|
||||||
//md3Shader += ent->e.skinNum % surface->numShaders;
|
md3Shader += ent->e.skinNum % surface->numShaders;
|
||||||
//shader = tr.shaders[ md3Shader->shaderIndex ];
|
shader = tr.shaders[ md3Shader->shaderIndex ];
|
||||||
shader = tr.shaders[ surface->shaderIndexes[ ent->e.skinNum % surface->numShaderIndexes ] ];
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// we will add shadows even if the main object isn't visible in the view
|
||||||
|
|
||||||
|
// stencil shadows can't do personal models unless I polyhedron clip
|
||||||
|
if ( !personalModel
|
||||||
|
&& r_shadows->integer == 2
|
||||||
|
&& fogNum == 0
|
||||||
|
&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
|
||||||
|
&& shader->sort == SS_OPAQUE ) {
|
||||||
|
R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse );
|
||||||
|
}
|
||||||
|
|
||||||
|
// projection shadows work fine with personal models
|
||||||
|
if ( r_shadows->integer == 3
|
||||||
|
&& fogNum == 0
|
||||||
|
&& (ent->e.renderfx & RF_SHADOW_PLANE )
|
||||||
|
&& shader->sort == SS_OPAQUE ) {
|
||||||
|
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't add third_person objects if not viewing through a portal
|
// don't add third_person objects if not viewing through a portal
|
||||||
if(!personalModel)
|
if ( !personalModel ) {
|
||||||
{
|
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse );
|
||||||
srfVaoMdvMesh_t *vaoSurface = &model->vaoSurfaces[i];
|
|
||||||
|
|
||||||
R_AddDrawSurf((void *)vaoSurface, shader, fogNum, qfalse, qfalse, cubemapIndex );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
surface++;
|
surface = (md3Surface_t *)( (byte *)surface + surface->ofsEnd );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1120
code/renderergl1/tr_model.c
Normal file
1120
code/renderergl1/tr_model.c
Normal file
File diff suppressed because it is too large
Load diff
1495
code/renderergl1/tr_model_iqm.c
Normal file
1495
code/renderergl1/tr_model_iqm.c
Normal file
File diff suppressed because it is too large
Load diff
411
code/renderergl1/tr_scene.c
Normal file
411
code/renderergl1/tr_scene.c
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
int r_firstSceneDrawSurf;
|
||||||
|
|
||||||
|
int r_numdlights;
|
||||||
|
int r_firstSceneDlight;
|
||||||
|
|
||||||
|
int r_numentities;
|
||||||
|
int r_firstSceneEntity;
|
||||||
|
|
||||||
|
int r_numpolys;
|
||||||
|
int r_firstScenePoly;
|
||||||
|
|
||||||
|
int r_numpolyverts;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
R_InitNextFrame
|
||||||
|
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
void R_InitNextFrame( void ) {
|
||||||
|
backEndData->commands.used = 0;
|
||||||
|
|
||||||
|
r_firstSceneDrawSurf = 0;
|
||||||
|
|
||||||
|
r_numdlights = 0;
|
||||||
|
r_firstSceneDlight = 0;
|
||||||
|
|
||||||
|
r_numentities = 0;
|
||||||
|
r_firstSceneEntity = 0;
|
||||||
|
|
||||||
|
r_numpolys = 0;
|
||||||
|
r_firstScenePoly = 0;
|
||||||
|
|
||||||
|
r_numpolyverts = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
RE_ClearScene
|
||||||
|
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
void RE_ClearScene( void ) {
|
||||||
|
r_firstSceneDlight = r_numdlights;
|
||||||
|
r_firstSceneEntity = r_numentities;
|
||||||
|
r_firstScenePoly = r_numpolys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
DISCRETE POLYS
|
||||||
|
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
R_AddPolygonSurfaces
|
||||||
|
|
||||||
|
Adds all the scene's polys into this view's drawsurf list
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void R_AddPolygonSurfaces( void ) {
|
||||||
|
int i;
|
||||||
|
shader_t *sh;
|
||||||
|
srfPoly_t *poly;
|
||||||
|
|
||||||
|
tr.currentEntityNum = REFENTITYNUM_WORLD;
|
||||||
|
tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
|
||||||
|
|
||||||
|
for ( i = 0, poly = tr.refdef.polys; i < tr.refdef.numPolys ; i++, poly++ ) {
|
||||||
|
sh = R_GetShaderByHandle( poly->hShader );
|
||||||
|
R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex, qfalse );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
RE_AddPolyToScene
|
||||||
|
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) {
|
||||||
|
srfPoly_t *poly;
|
||||||
|
int i, j;
|
||||||
|
int fogIndex;
|
||||||
|
fog_t *fog;
|
||||||
|
vec3_t bounds[2];
|
||||||
|
|
||||||
|
if ( !tr.registered ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !hShader ) {
|
||||||
|
ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( j = 0; j < numPolys; j++ ) {
|
||||||
|
if ( r_numpolyverts + numVerts > max_polyverts || r_numpolys >= max_polys ) {
|
||||||
|
/*
|
||||||
|
NOTE TTimo this was initially a PRINT_WARNING
|
||||||
|
but it happens a lot with high fighting scenes and particles
|
||||||
|
since we don't plan on changing the const and making for room for those effects
|
||||||
|
simply cut this message to developer only
|
||||||
|
*/
|
||||||
|
ri.Printf( PRINT_DEVELOPER, "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
poly = &backEndData->polys[r_numpolys];
|
||||||
|
poly->surfaceType = SF_POLY;
|
||||||
|
poly->hShader = hShader;
|
||||||
|
poly->numVerts = numVerts;
|
||||||
|
poly->verts = &backEndData->polyVerts[r_numpolyverts];
|
||||||
|
|
||||||
|
Com_Memcpy( poly->verts, &verts[numVerts*j], numVerts * sizeof( *verts ) );
|
||||||
|
|
||||||
|
if ( glConfig.hardwareType == GLHW_RAGEPRO ) {
|
||||||
|
poly->verts->modulate[0] = 255;
|
||||||
|
poly->verts->modulate[1] = 255;
|
||||||
|
poly->verts->modulate[2] = 255;
|
||||||
|
poly->verts->modulate[3] = 255;
|
||||||
|
}
|
||||||
|
// done.
|
||||||
|
r_numpolys++;
|
||||||
|
r_numpolyverts += numVerts;
|
||||||
|
|
||||||
|
// if no world is loaded
|
||||||
|
if ( tr.world == NULL ) {
|
||||||
|
fogIndex = 0;
|
||||||
|
}
|
||||||
|
// see if it is in a fog volume
|
||||||
|
else if ( tr.world->numfogs == 1 ) {
|
||||||
|
fogIndex = 0;
|
||||||
|
} else {
|
||||||
|
// find which fog volume the poly is in
|
||||||
|
VectorCopy( poly->verts[0].xyz, bounds[0] );
|
||||||
|
VectorCopy( poly->verts[0].xyz, bounds[1] );
|
||||||
|
for ( i = 1 ; i < poly->numVerts ; i++ ) {
|
||||||
|
AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
|
||||||
|
}
|
||||||
|
for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
|
||||||
|
fog = &tr.world->fogs[fogIndex];
|
||||||
|
if ( bounds[1][0] >= fog->bounds[0][0]
|
||||||
|
&& bounds[1][1] >= fog->bounds[0][1]
|
||||||
|
&& bounds[1][2] >= fog->bounds[0][2]
|
||||||
|
&& bounds[0][0] <= fog->bounds[1][0]
|
||||||
|
&& bounds[0][1] <= fog->bounds[1][1]
|
||||||
|
&& bounds[0][2] <= fog->bounds[1][2] ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( fogIndex == tr.world->numfogs ) {
|
||||||
|
fogIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
poly->fogIndex = fogIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
RE_AddRefEntityToScene
|
||||||
|
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void RE_AddRefEntityToScene( const refEntity_t *ent ) {
|
||||||
|
if ( !tr.registered ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( r_numentities >= MAX_REFENTITIES ) {
|
||||||
|
ri.Printf(PRINT_DEVELOPER, "RE_AddRefEntityToScene: Dropping refEntity, reached MAX_REFENTITIES\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( Q_isnan(ent->origin[0]) || Q_isnan(ent->origin[1]) || Q_isnan(ent->origin[2]) ) {
|
||||||
|
static qboolean firstTime = qtrue;
|
||||||
|
if (firstTime) {
|
||||||
|
firstTime = qfalse;
|
||||||
|
ri.Printf( PRINT_WARNING, "RE_AddRefEntityToScene passed a refEntity which has an origin with a NaN component\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( (int)ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) {
|
||||||
|
ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
|
||||||
|
}
|
||||||
|
|
||||||
|
backEndData->entities[r_numentities].e = *ent;
|
||||||
|
backEndData->entities[r_numentities].lightingCalculated = qfalse;
|
||||||
|
|
||||||
|
r_numentities++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
RE_AddDynamicLightToScene
|
||||||
|
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void RE_AddDynamicLightToScene( const vec3_t org, float intensity, float r, float g, float b, int additive ) {
|
||||||
|
dlight_t *dl;
|
||||||
|
|
||||||
|
if ( !tr.registered ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( r_numdlights >= MAX_DLIGHTS ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( intensity <= 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// these cards don't have the correct blend mode
|
||||||
|
if ( glConfig.hardwareType == GLHW_RIVA128 || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dl = &backEndData->dlights[r_numdlights++];
|
||||||
|
VectorCopy (org, dl->origin);
|
||||||
|
dl->radius = intensity;
|
||||||
|
dl->color[0] = r;
|
||||||
|
dl->color[1] = g;
|
||||||
|
dl->color[2] = b;
|
||||||
|
dl->additive = additive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
RE_AddLightToScene
|
||||||
|
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
|
||||||
|
RE_AddDynamicLightToScene( org, intensity, r, g, b, qfalse );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
RE_AddAdditiveLightToScene
|
||||||
|
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
|
||||||
|
RE_AddDynamicLightToScene( org, intensity, r, g, b, qtrue );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@@@@@@@@@@@@@@@@@@@@
|
||||||
|
RE_RenderScene
|
||||||
|
|
||||||
|
Draw a 3D view into a part of the window, then return
|
||||||
|
to 2D drawing.
|
||||||
|
|
||||||
|
Rendering a scene may require multiple views to be rendered
|
||||||
|
to handle mirrors,
|
||||||
|
@@@@@@@@@@@@@@@@@@@@@
|
||||||
|
*/
|
||||||
|
void RE_RenderScene( const refdef_t *fd ) {
|
||||||
|
viewParms_t parms;
|
||||||
|
int startTime;
|
||||||
|
|
||||||
|
if ( !tr.registered ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GLimp_LogComment( "====== RE_RenderScene =====\n" );
|
||||||
|
|
||||||
|
if ( r_norefresh->integer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
startTime = ri.Milliseconds();
|
||||||
|
|
||||||
|
if (!tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) {
|
||||||
|
ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
|
||||||
|
}
|
||||||
|
|
||||||
|
Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
|
||||||
|
|
||||||
|
tr.refdef.x = fd->x;
|
||||||
|
tr.refdef.y = fd->y;
|
||||||
|
tr.refdef.width = fd->width;
|
||||||
|
tr.refdef.height = fd->height;
|
||||||
|
tr.refdef.fov_x = fd->fov_x;
|
||||||
|
tr.refdef.fov_y = fd->fov_y;
|
||||||
|
|
||||||
|
VectorCopy( fd->vieworg, tr.refdef.vieworg );
|
||||||
|
VectorCopy( fd->viewaxis[0], tr.refdef.viewaxis[0] );
|
||||||
|
VectorCopy( fd->viewaxis[1], tr.refdef.viewaxis[1] );
|
||||||
|
VectorCopy( fd->viewaxis[2], tr.refdef.viewaxis[2] );
|
||||||
|
|
||||||
|
tr.refdef.time = fd->time;
|
||||||
|
tr.refdef.rdflags = fd->rdflags;
|
||||||
|
|
||||||
|
// copy the areamask data over and note if it has changed, which
|
||||||
|
// will force a reset of the visible leafs even if the view hasn't moved
|
||||||
|
tr.refdef.areamaskModified = qfalse;
|
||||||
|
if ( ! (tr.refdef.rdflags & RDF_NOWORLDMODEL) ) {
|
||||||
|
int areaDiff;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// compare the area bits
|
||||||
|
areaDiff = 0;
|
||||||
|
for (i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++) {
|
||||||
|
areaDiff |= ((int *)tr.refdef.areamask)[i] ^ ((int *)fd->areamask)[i];
|
||||||
|
((int *)tr.refdef.areamask)[i] = ((int *)fd->areamask)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( areaDiff ) {
|
||||||
|
// a door just opened or something
|
||||||
|
tr.refdef.areamaskModified = qtrue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// derived info
|
||||||
|
|
||||||
|
tr.refdef.floatTime = tr.refdef.time * 0.001;
|
||||||
|
|
||||||
|
tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
|
||||||
|
tr.refdef.drawSurfs = backEndData->drawSurfs;
|
||||||
|
|
||||||
|
tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
|
||||||
|
tr.refdef.entities = &backEndData->entities[r_firstSceneEntity];
|
||||||
|
|
||||||
|
tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
|
||||||
|
tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight];
|
||||||
|
|
||||||
|
tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
|
||||||
|
tr.refdef.polys = &backEndData->polys[r_firstScenePoly];
|
||||||
|
|
||||||
|
// turn off dynamic lighting globally by clearing all the
|
||||||
|
// dlights if it needs to be disabled or if vertex lighting is enabled
|
||||||
|
if ( r_dynamiclight->integer == 0 ||
|
||||||
|
r_vertexLight->integer == 1 ||
|
||||||
|
glConfig.hardwareType == GLHW_PERMEDIA2 ) {
|
||||||
|
tr.refdef.num_dlights = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// a single frame may have multiple scenes draw inside it --
|
||||||
|
// a 3D game view, 3D status bar renderings, 3D menus, etc.
|
||||||
|
// They need to be distinguished by the light flare code, because
|
||||||
|
// the visibility state for a given surface may be different in
|
||||||
|
// each scene / view.
|
||||||
|
tr.frameSceneNum++;
|
||||||
|
tr.sceneCount++;
|
||||||
|
|
||||||
|
// setup view parms for the initial view
|
||||||
|
//
|
||||||
|
// set up viewport
|
||||||
|
// The refdef takes 0-at-the-top y coordinates, so
|
||||||
|
// convert to GL's 0-at-the-bottom space
|
||||||
|
//
|
||||||
|
Com_Memset( &parms, 0, sizeof( parms ) );
|
||||||
|
parms.viewportX = tr.refdef.x;
|
||||||
|
parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height );
|
||||||
|
parms.viewportWidth = tr.refdef.width;
|
||||||
|
parms.viewportHeight = tr.refdef.height;
|
||||||
|
parms.isPortal = qfalse;
|
||||||
|
|
||||||
|
parms.fovX = tr.refdef.fov_x;
|
||||||
|
parms.fovY = tr.refdef.fov_y;
|
||||||
|
|
||||||
|
parms.stereoFrame = tr.refdef.stereoFrame;
|
||||||
|
|
||||||
|
VectorCopy( fd->vieworg, parms.or.origin );
|
||||||
|
VectorCopy( fd->viewaxis[0], parms.or.axis[0] );
|
||||||
|
VectorCopy( fd->viewaxis[1], parms.or.axis[1] );
|
||||||
|
VectorCopy( fd->viewaxis[2], parms.or.axis[2] );
|
||||||
|
|
||||||
|
VectorCopy( fd->vieworg, parms.pvsOrigin );
|
||||||
|
|
||||||
|
R_RenderView( &parms );
|
||||||
|
|
||||||
|
// the next scene rendered in this frame will tack on after this one
|
||||||
|
r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
|
||||||
|
r_firstSceneEntity = r_numentities;
|
||||||
|
r_firstSceneDlight = r_numdlights;
|
||||||
|
r_firstScenePoly = r_numpolys;
|
||||||
|
|
||||||
|
tr.frontEndMsec += ri.Milliseconds() - startTime;
|
||||||
|
}
|
1341
code/renderergl1/tr_shade.c
Normal file
1341
code/renderergl1/tr_shade.c
Normal file
File diff suppressed because it is too large
Load diff
1142
code/renderergl1/tr_shade_calc.c
Normal file
1142
code/renderergl1/tr_shade_calc.c
Normal file
File diff suppressed because it is too large
Load diff
3155
code/renderergl1/tr_shader.c
Normal file
3155
code/renderergl1/tr_shader.c
Normal file
File diff suppressed because it is too large
Load diff
325
code/renderergl1/tr_shadows.c
Normal file
325
code/renderergl1/tr_shadows.c
Normal file
|
@ -0,0 +1,325 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
for a projection shadow:
|
||||||
|
|
||||||
|
point[x] += light vector * ( z - shadow plane )
|
||||||
|
point[y] +=
|
||||||
|
point[z] = shadow plane
|
||||||
|
|
||||||
|
1 0 light[x] / light[z]
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int i2;
|
||||||
|
int facing;
|
||||||
|
} edgeDef_t;
|
||||||
|
|
||||||
|
#define MAX_EDGE_DEFS 32
|
||||||
|
|
||||||
|
static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
|
||||||
|
static int numEdgeDefs[SHADER_MAX_VERTEXES];
|
||||||
|
static int facing[SHADER_MAX_INDEXES/3];
|
||||||
|
static vec3_t shadowXyz[SHADER_MAX_VERTEXES];
|
||||||
|
|
||||||
|
void R_AddEdgeDef( int i1, int i2, int facing ) {
|
||||||
|
int c;
|
||||||
|
|
||||||
|
c = numEdgeDefs[ i1 ];
|
||||||
|
if ( c == MAX_EDGE_DEFS ) {
|
||||||
|
return; // overflow
|
||||||
|
}
|
||||||
|
edgeDefs[ i1 ][ c ].i2 = i2;
|
||||||
|
edgeDefs[ i1 ][ c ].facing = facing;
|
||||||
|
|
||||||
|
numEdgeDefs[ i1 ]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_RenderShadowEdges( void ) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int numTris;
|
||||||
|
|
||||||
|
// dumb way -- render every triangle's edges
|
||||||
|
numTris = tess.numIndexes / 3;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < numTris ; i++ ) {
|
||||||
|
int i1, i2, i3;
|
||||||
|
|
||||||
|
if ( !facing[i] ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1 = tess.indexes[ i*3 + 0 ];
|
||||||
|
i2 = tess.indexes[ i*3 + 1 ];
|
||||||
|
i3 = tess.indexes[ i*3 + 2 ];
|
||||||
|
|
||||||
|
qglBegin( GL_TRIANGLE_STRIP );
|
||||||
|
qglVertex3fv( tess.xyz[ i1 ] );
|
||||||
|
qglVertex3fv( shadowXyz[ i1 ] );
|
||||||
|
qglVertex3fv( tess.xyz[ i2 ] );
|
||||||
|
qglVertex3fv( shadowXyz[ i2 ] );
|
||||||
|
qglVertex3fv( tess.xyz[ i3 ] );
|
||||||
|
qglVertex3fv( shadowXyz[ i3 ] );
|
||||||
|
qglVertex3fv( tess.xyz[ i1 ] );
|
||||||
|
qglVertex3fv( shadowXyz[ i1 ] );
|
||||||
|
qglEnd();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int c, c2;
|
||||||
|
int j, k;
|
||||||
|
int i2;
|
||||||
|
int c_edges, c_rejected;
|
||||||
|
int hit[2];
|
||||||
|
|
||||||
|
// an edge is NOT a silhouette edge if its face doesn't face the light,
|
||||||
|
// or if it has a reverse paired edge that also faces the light.
|
||||||
|
// A well behaved polyhedron would have exactly two faces for each edge,
|
||||||
|
// but lots of models have dangling edges or overfanned edges
|
||||||
|
c_edges = 0;
|
||||||
|
c_rejected = 0;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < tess.numVertexes ; i++ ) {
|
||||||
|
c = numEdgeDefs[ i ];
|
||||||
|
for ( j = 0 ; j < c ; j++ ) {
|
||||||
|
if ( !edgeDefs[ i ][ j ].facing ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hit[0] = 0;
|
||||||
|
hit[1] = 0;
|
||||||
|
|
||||||
|
i2 = edgeDefs[ i ][ j ].i2;
|
||||||
|
c2 = numEdgeDefs[ i2 ];
|
||||||
|
for ( k = 0 ; k < c2 ; k++ ) {
|
||||||
|
if ( edgeDefs[ i2 ][ k ].i2 == i ) {
|
||||||
|
hit[ edgeDefs[ i2 ][ k ].facing ]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it doesn't share the edge with another front facing
|
||||||
|
// triangle, it is a sil edge
|
||||||
|
if ( hit[ 1 ] == 0 ) {
|
||||||
|
qglBegin( GL_TRIANGLE_STRIP );
|
||||||
|
qglVertex3fv( tess.xyz[ i ] );
|
||||||
|
qglVertex3fv( shadowXyz[ i ] );
|
||||||
|
qglVertex3fv( tess.xyz[ i2 ] );
|
||||||
|
qglVertex3fv( shadowXyz[ i2 ] );
|
||||||
|
qglEnd();
|
||||||
|
c_edges++;
|
||||||
|
} else {
|
||||||
|
c_rejected++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
RB_ShadowTessEnd
|
||||||
|
|
||||||
|
triangleFromEdge[ v1 ][ v2 ]
|
||||||
|
|
||||||
|
|
||||||
|
set triangle from edge( v1, v2, tri )
|
||||||
|
if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) {
|
||||||
|
}
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void RB_ShadowTessEnd( void ) {
|
||||||
|
int i;
|
||||||
|
int numTris;
|
||||||
|
vec3_t lightDir;
|
||||||
|
GLboolean rgba[4];
|
||||||
|
|
||||||
|
if ( glConfig.stencilBits < 4 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorCopy( backEnd.currentEntity->lightDir, lightDir );
|
||||||
|
|
||||||
|
// project vertexes away from light direction
|
||||||
|
for ( i = 0 ; i < tess.numVertexes ; i++ ) {
|
||||||
|
VectorMA( tess.xyz[i], -512, lightDir, shadowXyz[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// decide which triangles face the light
|
||||||
|
Com_Memset( numEdgeDefs, 0, 4 * tess.numVertexes );
|
||||||
|
|
||||||
|
numTris = tess.numIndexes / 3;
|
||||||
|
for ( i = 0 ; i < numTris ; i++ ) {
|
||||||
|
int i1, i2, i3;
|
||||||
|
vec3_t d1, d2, normal;
|
||||||
|
float *v1, *v2, *v3;
|
||||||
|
float d;
|
||||||
|
|
||||||
|
i1 = tess.indexes[ i*3 + 0 ];
|
||||||
|
i2 = tess.indexes[ i*3 + 1 ];
|
||||||
|
i3 = tess.indexes[ i*3 + 2 ];
|
||||||
|
|
||||||
|
v1 = tess.xyz[ i1 ];
|
||||||
|
v2 = tess.xyz[ i2 ];
|
||||||
|
v3 = tess.xyz[ i3 ];
|
||||||
|
|
||||||
|
VectorSubtract( v2, v1, d1 );
|
||||||
|
VectorSubtract( v3, v1, d2 );
|
||||||
|
CrossProduct( d1, d2, normal );
|
||||||
|
|
||||||
|
d = DotProduct( normal, lightDir );
|
||||||
|
if ( d > 0 ) {
|
||||||
|
facing[ i ] = 1;
|
||||||
|
} else {
|
||||||
|
facing[ i ] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the edges
|
||||||
|
R_AddEdgeDef( i1, i2, facing[ i ] );
|
||||||
|
R_AddEdgeDef( i2, i3, facing[ i ] );
|
||||||
|
R_AddEdgeDef( i3, i1, facing[ i ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the silhouette edges
|
||||||
|
|
||||||
|
GL_Bind( tr.whiteImage );
|
||||||
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
||||||
|
qglColor3f( 0.2f, 0.2f, 0.2f );
|
||||||
|
|
||||||
|
// don't write to the color buffer
|
||||||
|
qglGetBooleanv(GL_COLOR_WRITEMASK, rgba);
|
||||||
|
qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
|
||||||
|
|
||||||
|
qglEnable( GL_STENCIL_TEST );
|
||||||
|
qglStencilFunc( GL_ALWAYS, 1, 255 );
|
||||||
|
|
||||||
|
GL_Cull( CT_BACK_SIDED );
|
||||||
|
qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
|
||||||
|
|
||||||
|
R_RenderShadowEdges();
|
||||||
|
|
||||||
|
GL_Cull( CT_FRONT_SIDED );
|
||||||
|
qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
|
||||||
|
|
||||||
|
R_RenderShadowEdges();
|
||||||
|
|
||||||
|
|
||||||
|
// reenable writing to the color buffer
|
||||||
|
qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
RB_ShadowFinish
|
||||||
|
|
||||||
|
Darken everything that is is a shadow volume.
|
||||||
|
We have to delay this until everything has been shadowed,
|
||||||
|
because otherwise shadows from different body parts would
|
||||||
|
overlap and double darken.
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void RB_ShadowFinish( void ) {
|
||||||
|
if ( r_shadows->integer != 2 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( glConfig.stencilBits < 4 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qglEnable( GL_STENCIL_TEST );
|
||||||
|
qglStencilFunc( GL_NOTEQUAL, 0, 255 );
|
||||||
|
|
||||||
|
qglDisable (GL_CLIP_PLANE0);
|
||||||
|
GL_Cull( CT_TWO_SIDED );
|
||||||
|
|
||||||
|
GL_Bind( tr.whiteImage );
|
||||||
|
|
||||||
|
qglLoadIdentity ();
|
||||||
|
|
||||||
|
qglColor3f( 0.6f, 0.6f, 0.6f );
|
||||||
|
GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );
|
||||||
|
|
||||||
|
// qglColor3f( 1, 0, 0 );
|
||||||
|
// GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
||||||
|
|
||||||
|
qglBegin( GL_QUADS );
|
||||||
|
qglVertex3f( -100, 100, -10 );
|
||||||
|
qglVertex3f( 100, 100, -10 );
|
||||||
|
qglVertex3f( 100, -100, -10 );
|
||||||
|
qglVertex3f( -100, -100, -10 );
|
||||||
|
qglEnd ();
|
||||||
|
|
||||||
|
qglColor4f(1,1,1,1);
|
||||||
|
qglDisable( GL_STENCIL_TEST );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
RB_ProjectionShadowDeform
|
||||||
|
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void RB_ProjectionShadowDeform( void ) {
|
||||||
|
float *xyz;
|
||||||
|
int i;
|
||||||
|
float h;
|
||||||
|
vec3_t ground;
|
||||||
|
vec3_t light;
|
||||||
|
float groundDist;
|
||||||
|
float d;
|
||||||
|
vec3_t lightDir;
|
||||||
|
|
||||||
|
xyz = ( float * ) tess.xyz;
|
||||||
|
|
||||||
|
ground[0] = backEnd.or.axis[0][2];
|
||||||
|
ground[1] = backEnd.or.axis[1][2];
|
||||||
|
ground[2] = backEnd.or.axis[2][2];
|
||||||
|
|
||||||
|
groundDist = backEnd.or.origin[2] - backEnd.currentEntity->e.shadowPlane;
|
||||||
|
|
||||||
|
VectorCopy( backEnd.currentEntity->lightDir, lightDir );
|
||||||
|
d = DotProduct( lightDir, ground );
|
||||||
|
// don't let the shadows get too long or go negative
|
||||||
|
if ( d < 0.5 ) {
|
||||||
|
VectorMA( lightDir, (0.5 - d), ground, lightDir );
|
||||||
|
d = DotProduct( lightDir, ground );
|
||||||
|
}
|
||||||
|
d = 1.0 / d;
|
||||||
|
|
||||||
|
light[0] = lightDir[0] * d;
|
||||||
|
light[1] = lightDir[1] * d;
|
||||||
|
light[2] = lightDir[2] * d;
|
||||||
|
|
||||||
|
for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
|
||||||
|
h = DotProduct( xyz, ground ) + groundDist;
|
||||||
|
|
||||||
|
xyz[0] -= light[0] * h;
|
||||||
|
xyz[1] -= light[1] * h;
|
||||||
|
xyz[2] -= light[2] * h;
|
||||||
|
}
|
||||||
|
}
|
795
code/renderergl1/tr_sky.c
Normal file
795
code/renderergl1/tr_sky.c
Normal file
|
@ -0,0 +1,795 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// tr_sky.c
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
#define SKY_SUBDIVISIONS 8
|
||||||
|
#define HALF_SKY_SUBDIVISIONS (SKY_SUBDIVISIONS/2)
|
||||||
|
|
||||||
|
static float s_cloudTexCoords[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
|
||||||
|
static float s_cloudTexP[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1];
|
||||||
|
|
||||||
|
/*
|
||||||
|
===================================================================================
|
||||||
|
|
||||||
|
POLYGON TO BOX SIDE PROJECTION
|
||||||
|
|
||||||
|
===================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
static vec3_t sky_clip[6] =
|
||||||
|
{
|
||||||
|
{1,1,0},
|
||||||
|
{1,-1,0},
|
||||||
|
{0,-1,1},
|
||||||
|
{0,1,1},
|
||||||
|
{1,0,1},
|
||||||
|
{-1,0,1}
|
||||||
|
};
|
||||||
|
|
||||||
|
static float sky_mins[2][6], sky_maxs[2][6];
|
||||||
|
static float sky_min, sky_max;
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
AddSkyPolygon
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static void AddSkyPolygon (int nump, vec3_t vecs)
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
vec3_t v, av;
|
||||||
|
float s, t, dv;
|
||||||
|
int axis;
|
||||||
|
float *vp;
|
||||||
|
// s = [0]/[2], t = [1]/[2]
|
||||||
|
static int vec_to_st[6][3] =
|
||||||
|
{
|
||||||
|
{-2,3,1},
|
||||||
|
{2,3,-1},
|
||||||
|
|
||||||
|
{1,3,2},
|
||||||
|
{-1,3,-2},
|
||||||
|
|
||||||
|
{-2,-1,3},
|
||||||
|
{-2,1,-3}
|
||||||
|
|
||||||
|
// {-1,2,3},
|
||||||
|
// {1,2,-3}
|
||||||
|
};
|
||||||
|
|
||||||
|
// decide which face it maps to
|
||||||
|
VectorCopy (vec3_origin, v);
|
||||||
|
for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
|
||||||
|
{
|
||||||
|
VectorAdd (vp, v, v);
|
||||||
|
}
|
||||||
|
av[0] = fabs(v[0]);
|
||||||
|
av[1] = fabs(v[1]);
|
||||||
|
av[2] = fabs(v[2]);
|
||||||
|
if (av[0] > av[1] && av[0] > av[2])
|
||||||
|
{
|
||||||
|
if (v[0] < 0)
|
||||||
|
axis = 1;
|
||||||
|
else
|
||||||
|
axis = 0;
|
||||||
|
}
|
||||||
|
else if (av[1] > av[2] && av[1] > av[0])
|
||||||
|
{
|
||||||
|
if (v[1] < 0)
|
||||||
|
axis = 3;
|
||||||
|
else
|
||||||
|
axis = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (v[2] < 0)
|
||||||
|
axis = 5;
|
||||||
|
else
|
||||||
|
axis = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// project new texture coords
|
||||||
|
for (i=0 ; i<nump ; i++, vecs+=3)
|
||||||
|
{
|
||||||
|
j = vec_to_st[axis][2];
|
||||||
|
if (j > 0)
|
||||||
|
dv = vecs[j - 1];
|
||||||
|
else
|
||||||
|
dv = -vecs[-j - 1];
|
||||||
|
if (dv < 0.001)
|
||||||
|
continue; // don't divide by zero
|
||||||
|
j = vec_to_st[axis][0];
|
||||||
|
if (j < 0)
|
||||||
|
s = -vecs[-j -1] / dv;
|
||||||
|
else
|
||||||
|
s = vecs[j-1] / dv;
|
||||||
|
j = vec_to_st[axis][1];
|
||||||
|
if (j < 0)
|
||||||
|
t = -vecs[-j -1] / dv;
|
||||||
|
else
|
||||||
|
t = vecs[j-1] / dv;
|
||||||
|
|
||||||
|
if (s < sky_mins[0][axis])
|
||||||
|
sky_mins[0][axis] = s;
|
||||||
|
if (t < sky_mins[1][axis])
|
||||||
|
sky_mins[1][axis] = t;
|
||||||
|
if (s > sky_maxs[0][axis])
|
||||||
|
sky_maxs[0][axis] = s;
|
||||||
|
if (t > sky_maxs[1][axis])
|
||||||
|
sky_maxs[1][axis] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ON_EPSILON 0.1f // point on plane side epsilon
|
||||||
|
#define MAX_CLIP_VERTS 64
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
ClipSkyPolygon
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
|
||||||
|
{
|
||||||
|
float *norm;
|
||||||
|
float *v;
|
||||||
|
qboolean front, back;
|
||||||
|
float d, e;
|
||||||
|
float dists[MAX_CLIP_VERTS];
|
||||||
|
int sides[MAX_CLIP_VERTS];
|
||||||
|
vec3_t newv[2][MAX_CLIP_VERTS];
|
||||||
|
int newc[2];
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (nump > MAX_CLIP_VERTS-2)
|
||||||
|
ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS");
|
||||||
|
if (stage == 6)
|
||||||
|
{ // fully clipped, so draw it
|
||||||
|
AddSkyPolygon (nump, vecs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
front = back = qfalse;
|
||||||
|
norm = sky_clip[stage];
|
||||||
|
for (i=0, v = vecs ; i<nump ; i++, v+=3)
|
||||||
|
{
|
||||||
|
d = DotProduct (v, norm);
|
||||||
|
if (d > ON_EPSILON)
|
||||||
|
{
|
||||||
|
front = qtrue;
|
||||||
|
sides[i] = SIDE_FRONT;
|
||||||
|
}
|
||||||
|
else if (d < -ON_EPSILON)
|
||||||
|
{
|
||||||
|
back = qtrue;
|
||||||
|
sides[i] = SIDE_BACK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sides[i] = SIDE_ON;
|
||||||
|
dists[i] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!front || !back)
|
||||||
|
{ // not clipped
|
||||||
|
ClipSkyPolygon (nump, vecs, stage+1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clip it
|
||||||
|
sides[i] = sides[0];
|
||||||
|
dists[i] = dists[0];
|
||||||
|
VectorCopy (vecs, (vecs+(i*3)) );
|
||||||
|
newc[0] = newc[1] = 0;
|
||||||
|
|
||||||
|
for (i=0, v = vecs ; i<nump ; i++, v+=3)
|
||||||
|
{
|
||||||
|
switch (sides[i])
|
||||||
|
{
|
||||||
|
case SIDE_FRONT:
|
||||||
|
VectorCopy (v, newv[0][newc[0]]);
|
||||||
|
newc[0]++;
|
||||||
|
break;
|
||||||
|
case SIDE_BACK:
|
||||||
|
VectorCopy (v, newv[1][newc[1]]);
|
||||||
|
newc[1]++;
|
||||||
|
break;
|
||||||
|
case SIDE_ON:
|
||||||
|
VectorCopy (v, newv[0][newc[0]]);
|
||||||
|
newc[0]++;
|
||||||
|
VectorCopy (v, newv[1][newc[1]]);
|
||||||
|
newc[1]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
d = dists[i] / (dists[i] - dists[i+1]);
|
||||||
|
for (j=0 ; j<3 ; j++)
|
||||||
|
{
|
||||||
|
e = v[j] + d*(v[j+3] - v[j]);
|
||||||
|
newv[0][newc[0]][j] = e;
|
||||||
|
newv[1][newc[1]][j] = e;
|
||||||
|
}
|
||||||
|
newc[0]++;
|
||||||
|
newc[1]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// continue
|
||||||
|
ClipSkyPolygon (newc[0], newv[0][0], stage+1);
|
||||||
|
ClipSkyPolygon (newc[1], newv[1][0], stage+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
ClearSkyBox
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
static void ClearSkyBox (void) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0 ; i<6 ; i++) {
|
||||||
|
sky_mins[0][i] = sky_mins[1][i] = 9999;
|
||||||
|
sky_maxs[0][i] = sky_maxs[1][i] = -9999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
RB_ClipSkyPolygons
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void RB_ClipSkyPolygons( shaderCommands_t *input )
|
||||||
|
{
|
||||||
|
vec3_t p[5]; // need one extra point for clipping
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
ClearSkyBox();
|
||||||
|
|
||||||
|
for ( i = 0; i < input->numIndexes; i += 3 )
|
||||||
|
{
|
||||||
|
for (j = 0 ; j < 3 ; j++)
|
||||||
|
{
|
||||||
|
VectorSubtract( input->xyz[input->indexes[i+j]],
|
||||||
|
backEnd.viewParms.or.origin,
|
||||||
|
p[j] );
|
||||||
|
}
|
||||||
|
ClipSkyPolygon( 3, p[0], 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===================================================================================
|
||||||
|
|
||||||
|
CLOUD VERTEX GENERATION
|
||||||
|
|
||||||
|
===================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** MakeSkyVec
|
||||||
|
**
|
||||||
|
** Parms: s, t range from -1 to 1
|
||||||
|
*/
|
||||||
|
static void MakeSkyVec( float s, float t, int axis, float outSt[2], vec3_t outXYZ )
|
||||||
|
{
|
||||||
|
// 1 = s, 2 = t, 3 = 2048
|
||||||
|
static int st_to_vec[6][3] =
|
||||||
|
{
|
||||||
|
{3,-1,2},
|
||||||
|
{-3,1,2},
|
||||||
|
|
||||||
|
{1,3,2},
|
||||||
|
{-1,-3,2},
|
||||||
|
|
||||||
|
{-2,-1,3}, // 0 degrees yaw, look straight up
|
||||||
|
{2,-1,-3} // look straight down
|
||||||
|
};
|
||||||
|
|
||||||
|
vec3_t b;
|
||||||
|
int j, k;
|
||||||
|
float boxSize;
|
||||||
|
|
||||||
|
boxSize = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
|
||||||
|
b[0] = s*boxSize;
|
||||||
|
b[1] = t*boxSize;
|
||||||
|
b[2] = boxSize;
|
||||||
|
|
||||||
|
for (j=0 ; j<3 ; j++)
|
||||||
|
{
|
||||||
|
k = st_to_vec[axis][j];
|
||||||
|
if (k < 0)
|
||||||
|
{
|
||||||
|
outXYZ[j] = -b[-k - 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outXYZ[j] = b[k - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// avoid bilerp seam
|
||||||
|
s = (s+1)*0.5;
|
||||||
|
t = (t+1)*0.5;
|
||||||
|
if (s < sky_min)
|
||||||
|
{
|
||||||
|
s = sky_min;
|
||||||
|
}
|
||||||
|
else if (s > sky_max)
|
||||||
|
{
|
||||||
|
s = sky_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t < sky_min)
|
||||||
|
{
|
||||||
|
t = sky_min;
|
||||||
|
}
|
||||||
|
else if (t > sky_max)
|
||||||
|
{
|
||||||
|
t = sky_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
t = 1.0 - t;
|
||||||
|
|
||||||
|
|
||||||
|
if ( outSt )
|
||||||
|
{
|
||||||
|
outSt[0] = s;
|
||||||
|
outSt[1] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sky_texorder[6] = {0,2,1,3,4,5};
|
||||||
|
static vec3_t s_skyPoints[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1];
|
||||||
|
static float s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
|
||||||
|
|
||||||
|
static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] )
|
||||||
|
{
|
||||||
|
int s, t;
|
||||||
|
|
||||||
|
GL_Bind( image );
|
||||||
|
|
||||||
|
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
|
||||||
|
{
|
||||||
|
qglBegin( GL_TRIANGLE_STRIP );
|
||||||
|
|
||||||
|
for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
|
||||||
|
{
|
||||||
|
qglTexCoord2fv( s_skyTexCoords[t][s] );
|
||||||
|
qglVertex3fv( s_skyPoints[t][s] );
|
||||||
|
|
||||||
|
qglTexCoord2fv( s_skyTexCoords[t+1][s] );
|
||||||
|
qglVertex3fv( s_skyPoints[t+1][s] );
|
||||||
|
}
|
||||||
|
|
||||||
|
qglEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawSkyBox( shader_t *shader )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sky_min = 0;
|
||||||
|
sky_max = 1;
|
||||||
|
|
||||||
|
Com_Memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) );
|
||||||
|
|
||||||
|
for (i=0 ; i<6 ; i++)
|
||||||
|
{
|
||||||
|
int sky_mins_subd[2], sky_maxs_subd[2];
|
||||||
|
int s, t;
|
||||||
|
|
||||||
|
sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
|
||||||
|
sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
|
||||||
|
sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
|
||||||
|
sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
|
||||||
|
|
||||||
|
if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
|
||||||
|
( sky_mins[1][i] >= sky_maxs[1][i] ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sky_mins_subd[0] = sky_mins[0][i] * HALF_SKY_SUBDIVISIONS;
|
||||||
|
sky_mins_subd[1] = sky_mins[1][i] * HALF_SKY_SUBDIVISIONS;
|
||||||
|
sky_maxs_subd[0] = sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS;
|
||||||
|
sky_maxs_subd[1] = sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS;
|
||||||
|
|
||||||
|
if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
|
||||||
|
else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
|
||||||
|
if ( sky_mins_subd[1] < -HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_mins_subd[1] = -HALF_SKY_SUBDIVISIONS;
|
||||||
|
else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;
|
||||||
|
|
||||||
|
if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
|
||||||
|
else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
|
||||||
|
if ( sky_maxs_subd[1] < -HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_maxs_subd[1] = -HALF_SKY_SUBDIVISIONS;
|
||||||
|
else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;
|
||||||
|
|
||||||
|
//
|
||||||
|
// iterate through the subdivisions
|
||||||
|
//
|
||||||
|
for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
|
||||||
|
{
|
||||||
|
for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
|
||||||
|
{
|
||||||
|
MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
|
||||||
|
( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
|
||||||
|
i,
|
||||||
|
s_skyTexCoords[t][s],
|
||||||
|
s_skyPoints[t][s] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawSkySide( shader->sky.outerbox[sky_texorder[i]],
|
||||||
|
sky_mins_subd,
|
||||||
|
sky_maxs_subd );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean addIndexes )
|
||||||
|
{
|
||||||
|
int s, t;
|
||||||
|
int vertexStart = tess.numVertexes;
|
||||||
|
int tHeight, sWidth;
|
||||||
|
|
||||||
|
tHeight = maxs[1] - mins[1] + 1;
|
||||||
|
sWidth = maxs[0] - mins[0] + 1;
|
||||||
|
|
||||||
|
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
|
||||||
|
{
|
||||||
|
for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
|
||||||
|
{
|
||||||
|
VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] );
|
||||||
|
tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0];
|
||||||
|
tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1];
|
||||||
|
|
||||||
|
tess.numVertexes++;
|
||||||
|
|
||||||
|
if ( tess.numVertexes >= SHADER_MAX_VERTEXES )
|
||||||
|
{
|
||||||
|
ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only add indexes for one pass, otherwise it would draw multiple times for each pass
|
||||||
|
if ( addIndexes ) {
|
||||||
|
for ( t = 0; t < tHeight-1; t++ )
|
||||||
|
{
|
||||||
|
for ( s = 0; s < sWidth-1; s++ )
|
||||||
|
{
|
||||||
|
tess.indexes[tess.numIndexes] = vertexStart + s + t * ( sWidth );
|
||||||
|
tess.numIndexes++;
|
||||||
|
tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth );
|
||||||
|
tess.numIndexes++;
|
||||||
|
tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth );
|
||||||
|
tess.numIndexes++;
|
||||||
|
|
||||||
|
tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth );
|
||||||
|
tess.numIndexes++;
|
||||||
|
tess.indexes[tess.numIndexes] = vertexStart + s + 1 + ( t + 1 ) * ( sWidth );
|
||||||
|
tess.numIndexes++;
|
||||||
|
tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth );
|
||||||
|
tess.numIndexes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillCloudBox( const shader_t *shader, int stage )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i =0; i < 6; i++ )
|
||||||
|
{
|
||||||
|
int sky_mins_subd[2], sky_maxs_subd[2];
|
||||||
|
int s, t;
|
||||||
|
float MIN_T;
|
||||||
|
|
||||||
|
if ( 1 ) // FIXME? shader->sky.fullClouds )
|
||||||
|
{
|
||||||
|
MIN_T = -HALF_SKY_SUBDIVISIONS;
|
||||||
|
|
||||||
|
// still don't want to draw the bottom, even if fullClouds
|
||||||
|
if ( i == 5 )
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch( i )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
MIN_T = -1;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
// don't draw clouds beneath you
|
||||||
|
continue;
|
||||||
|
case 4: // top
|
||||||
|
default:
|
||||||
|
MIN_T = -HALF_SKY_SUBDIVISIONS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
|
||||||
|
sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
|
||||||
|
sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
|
||||||
|
sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
|
||||||
|
|
||||||
|
if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
|
||||||
|
( sky_mins[1][i] >= sky_maxs[1][i] ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sky_mins_subd[0] = ri.ftol(sky_mins[0][i] * HALF_SKY_SUBDIVISIONS);
|
||||||
|
sky_mins_subd[1] = ri.ftol(sky_mins[1][i] * HALF_SKY_SUBDIVISIONS);
|
||||||
|
sky_maxs_subd[0] = ri.ftol(sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS);
|
||||||
|
sky_maxs_subd[1] = ri.ftol(sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS);
|
||||||
|
|
||||||
|
if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
|
||||||
|
else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
|
||||||
|
if ( sky_mins_subd[1] < MIN_T )
|
||||||
|
sky_mins_subd[1] = MIN_T;
|
||||||
|
else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;
|
||||||
|
|
||||||
|
if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
|
||||||
|
else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
|
||||||
|
if ( sky_maxs_subd[1] < MIN_T )
|
||||||
|
sky_maxs_subd[1] = MIN_T;
|
||||||
|
else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )
|
||||||
|
sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;
|
||||||
|
|
||||||
|
//
|
||||||
|
// iterate through the subdivisions
|
||||||
|
//
|
||||||
|
for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
|
||||||
|
{
|
||||||
|
for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
|
||||||
|
{
|
||||||
|
MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
|
||||||
|
( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
|
||||||
|
i,
|
||||||
|
NULL,
|
||||||
|
s_skyPoints[t][s] );
|
||||||
|
|
||||||
|
s_skyTexCoords[t][s][0] = s_cloudTexCoords[i][t][s][0];
|
||||||
|
s_skyTexCoords[t][s][1] = s_cloudTexCoords[i][t][s][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only add indexes for first stage
|
||||||
|
FillCloudySkySide( sky_mins_subd, sky_maxs_subd, ( stage == 0 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** R_BuildCloudData
|
||||||
|
*/
|
||||||
|
void R_BuildCloudData( shaderCommands_t *input )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
shader_t *shader;
|
||||||
|
|
||||||
|
shader = input->shader;
|
||||||
|
|
||||||
|
assert( shader->isSky );
|
||||||
|
|
||||||
|
sky_min = 1.0 / 256.0f; // FIXME: not correct?
|
||||||
|
sky_max = 255.0 / 256.0f;
|
||||||
|
|
||||||
|
// set up for drawing
|
||||||
|
tess.numIndexes = 0;
|
||||||
|
tess.numVertexes = 0;
|
||||||
|
|
||||||
|
if ( shader->sky.cloudHeight )
|
||||||
|
{
|
||||||
|
for ( i = 0; i < MAX_SHADER_STAGES; i++ )
|
||||||
|
{
|
||||||
|
if ( !tess.xstages[i] ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FillCloudBox( shader, i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** R_InitSkyTexCoords
|
||||||
|
** Called when a sky shader is parsed
|
||||||
|
*/
|
||||||
|
#define SQR( a ) ((a)*(a))
|
||||||
|
void R_InitSkyTexCoords( float heightCloud )
|
||||||
|
{
|
||||||
|
int i, s, t;
|
||||||
|
float radiusWorld = 4096;
|
||||||
|
float p;
|
||||||
|
float sRad, tRad;
|
||||||
|
vec3_t skyVec;
|
||||||
|
vec3_t v;
|
||||||
|
|
||||||
|
// init zfar so MakeSkyVec works even though
|
||||||
|
// a world hasn't been bounded
|
||||||
|
backEnd.viewParms.zFar = 1024;
|
||||||
|
|
||||||
|
for ( i = 0; i < 6; i++ )
|
||||||
|
{
|
||||||
|
for ( t = 0; t <= SKY_SUBDIVISIONS; t++ )
|
||||||
|
{
|
||||||
|
for ( s = 0; s <= SKY_SUBDIVISIONS; s++ )
|
||||||
|
{
|
||||||
|
// compute vector from view origin to sky side integral point
|
||||||
|
MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
|
||||||
|
( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
|
||||||
|
i,
|
||||||
|
NULL,
|
||||||
|
skyVec );
|
||||||
|
|
||||||
|
// compute parametric value 'p' that intersects with cloud layer
|
||||||
|
p = ( 1.0f / ( 2 * DotProduct( skyVec, skyVec ) ) ) *
|
||||||
|
( -2 * skyVec[2] * radiusWorld +
|
||||||
|
2 * sqrt( SQR( skyVec[2] ) * SQR( radiusWorld ) +
|
||||||
|
2 * SQR( skyVec[0] ) * radiusWorld * heightCloud +
|
||||||
|
SQR( skyVec[0] ) * SQR( heightCloud ) +
|
||||||
|
2 * SQR( skyVec[1] ) * radiusWorld * heightCloud +
|
||||||
|
SQR( skyVec[1] ) * SQR( heightCloud ) +
|
||||||
|
2 * SQR( skyVec[2] ) * radiusWorld * heightCloud +
|
||||||
|
SQR( skyVec[2] ) * SQR( heightCloud ) ) );
|
||||||
|
|
||||||
|
s_cloudTexP[i][t][s] = p;
|
||||||
|
|
||||||
|
// compute intersection point based on p
|
||||||
|
VectorScale( skyVec, p, v );
|
||||||
|
v[2] += radiusWorld;
|
||||||
|
|
||||||
|
// compute vector from world origin to intersection point 'v'
|
||||||
|
VectorNormalize( v );
|
||||||
|
|
||||||
|
sRad = Q_acos( v[0] );
|
||||||
|
tRad = Q_acos( v[1] );
|
||||||
|
|
||||||
|
s_cloudTexCoords[i][t][s][0] = sRad;
|
||||||
|
s_cloudTexCoords[i][t][s][1] = tRad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
** RB_DrawSun
|
||||||
|
*/
|
||||||
|
void RB_DrawSun( float scale, shader_t *shader ) {
|
||||||
|
float size;
|
||||||
|
float dist;
|
||||||
|
vec3_t origin, vec1, vec2;
|
||||||
|
byte sunColor[4] = { 255, 255, 255, 255 };
|
||||||
|
|
||||||
|
if ( !backEnd.skyRenderedThisView ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
|
||||||
|
qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
|
||||||
|
|
||||||
|
dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
|
||||||
|
size = dist * scale;
|
||||||
|
|
||||||
|
VectorScale( tr.sunDirection, dist, origin );
|
||||||
|
PerpendicularVector( vec1, tr.sunDirection );
|
||||||
|
CrossProduct( tr.sunDirection, vec1, vec2 );
|
||||||
|
|
||||||
|
VectorScale( vec1, size, vec1 );
|
||||||
|
VectorScale( vec2, size, vec2 );
|
||||||
|
|
||||||
|
// farthest depth range
|
||||||
|
qglDepthRange( 1.0, 1.0 );
|
||||||
|
|
||||||
|
RB_BeginSurface( shader, 0 );
|
||||||
|
|
||||||
|
RB_AddQuadStamp(origin, vec1, vec2, sunColor);
|
||||||
|
|
||||||
|
RB_EndSurface();
|
||||||
|
|
||||||
|
// back to normal depth range
|
||||||
|
qglDepthRange( 0.0, 1.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
RB_StageIteratorSky
|
||||||
|
|
||||||
|
All of the visible sky triangles are in tess
|
||||||
|
|
||||||
|
Other things could be stuck in here, like birds in the sky, etc
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void RB_StageIteratorSky( void ) {
|
||||||
|
if ( r_fastsky->integer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// go through all the polygons and project them onto
|
||||||
|
// the sky box to see which blocks on each side need
|
||||||
|
// to be drawn
|
||||||
|
RB_ClipSkyPolygons( &tess );
|
||||||
|
|
||||||
|
// r_showsky will let all the sky blocks be drawn in
|
||||||
|
// front of everything to allow developers to see how
|
||||||
|
// much sky is getting sucked in
|
||||||
|
if ( r_showsky->integer ) {
|
||||||
|
qglDepthRange( 0.0, 0.0 );
|
||||||
|
} else {
|
||||||
|
qglDepthRange( 1.0, 1.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the outer skybox
|
||||||
|
if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) {
|
||||||
|
qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
|
||||||
|
|
||||||
|
qglPushMatrix ();
|
||||||
|
GL_State( 0 );
|
||||||
|
GL_Cull( CT_FRONT_SIDED );
|
||||||
|
qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
|
||||||
|
|
||||||
|
DrawSkyBox( tess.shader );
|
||||||
|
|
||||||
|
qglPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the vertexes for all the clouds, which will be drawn
|
||||||
|
// by the generic shader routine
|
||||||
|
R_BuildCloudData( &tess );
|
||||||
|
|
||||||
|
RB_StageIteratorGeneric();
|
||||||
|
|
||||||
|
// draw the inner skybox
|
||||||
|
|
||||||
|
|
||||||
|
// back to normal depth range
|
||||||
|
qglDepthRange( 0.0, 1.0 );
|
||||||
|
|
||||||
|
// note that sky was drawn so we will draw a sun later
|
||||||
|
backEnd.skyRenderedThisView = qtrue;
|
||||||
|
}
|
||||||
|
|
48
code/renderergl1/tr_subs.c
Normal file
48
code/renderergl1/tr_subs.c
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2010 James Canete (use.less01@gmail.com)
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// tr_subs.c - common function replacements for modular renderer
|
||||||
|
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
void QDECL Com_Printf( const char *msg, ... )
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
char text[1024];
|
||||||
|
|
||||||
|
va_start(argptr, msg);
|
||||||
|
Q_vsnprintf(text, sizeof(text), msg, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
ri.Printf(PRINT_ALL, "%s", text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QDECL Com_Error( int level, const char *error, ... )
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
char text[1024];
|
||||||
|
|
||||||
|
va_start(argptr, error);
|
||||||
|
Q_vsnprintf(text, sizeof(text), error, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
ri.Error(level, "%s", text);
|
||||||
|
}
|
1104
code/renderergl1/tr_surface.c
Normal file
1104
code/renderergl1/tr_surface.c
Normal file
File diff suppressed because it is too large
Load diff
668
code/renderergl1/tr_world.c
Normal file
668
code/renderergl1/tr_world.c
Normal file
|
@ -0,0 +1,668 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_CullTriSurf
|
||||||
|
|
||||||
|
Returns true if the grid is completely culled away.
|
||||||
|
Also sets the clipped hint bit in tess
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static qboolean R_CullTriSurf( srfTriangles_t *cv ) {
|
||||||
|
int boxCull;
|
||||||
|
|
||||||
|
boxCull = R_CullLocalBox( cv->bounds );
|
||||||
|
|
||||||
|
if ( boxCull == CULL_OUT ) {
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_CullGrid
|
||||||
|
|
||||||
|
Returns true if the grid is completely culled away.
|
||||||
|
Also sets the clipped hint bit in tess
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static qboolean R_CullGrid( srfGridMesh_t *cv ) {
|
||||||
|
int boxCull;
|
||||||
|
int sphereCull;
|
||||||
|
|
||||||
|
if ( r_nocurves->integer ) {
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( tr.currentEntityNum != REFENTITYNUM_WORLD ) {
|
||||||
|
sphereCull = R_CullLocalPointAndRadius( cv->localOrigin, cv->meshRadius );
|
||||||
|
} else {
|
||||||
|
sphereCull = R_CullPointAndRadius( cv->localOrigin, cv->meshRadius );
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for trivial reject
|
||||||
|
if ( sphereCull == CULL_OUT )
|
||||||
|
{
|
||||||
|
tr.pc.c_sphere_cull_patch_out++;
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
// check bounding box if necessary
|
||||||
|
else if ( sphereCull == CULL_CLIP )
|
||||||
|
{
|
||||||
|
tr.pc.c_sphere_cull_patch_clip++;
|
||||||
|
|
||||||
|
boxCull = R_CullLocalBox( cv->meshBounds );
|
||||||
|
|
||||||
|
if ( boxCull == CULL_OUT )
|
||||||
|
{
|
||||||
|
tr.pc.c_box_cull_patch_out++;
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
else if ( boxCull == CULL_IN )
|
||||||
|
{
|
||||||
|
tr.pc.c_box_cull_patch_in++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tr.pc.c_box_cull_patch_clip++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tr.pc.c_sphere_cull_patch_in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
R_CullSurface
|
||||||
|
|
||||||
|
Tries to back face cull surfaces before they are lighted or
|
||||||
|
added to the sorting list.
|
||||||
|
|
||||||
|
This will also allow mirrors on both sides of a model without recursion.
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static qboolean R_CullSurface( surfaceType_t *surface, shader_t *shader ) {
|
||||||
|
srfSurfaceFace_t *sface;
|
||||||
|
float d;
|
||||||
|
|
||||||
|
if ( r_nocull->integer ) {
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( *surface == SF_GRID ) {
|
||||||
|
return R_CullGrid( (srfGridMesh_t *)surface );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( *surface == SF_TRIANGLES ) {
|
||||||
|
return R_CullTriSurf( (srfTriangles_t *)surface );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( *surface != SF_FACE ) {
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( shader->cullType == CT_TWO_SIDED ) {
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// face culling
|
||||||
|
if ( !r_facePlaneCull->integer ) {
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
sface = ( srfSurfaceFace_t * ) surface;
|
||||||
|
d = DotProduct (tr.or.viewOrigin, sface->plane.normal);
|
||||||
|
|
||||||
|
// don't cull exactly on the plane, because there are levels of rounding
|
||||||
|
// through the BSP, ICD, and hardware that may cause pixel gaps if an
|
||||||
|
// epsilon isn't allowed here
|
||||||
|
if ( shader->cullType == CT_FRONT_SIDED ) {
|
||||||
|
if ( d < sface->plane.dist - 8 ) {
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( d > sface->plane.dist + 8 ) {
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int R_DlightFace( srfSurfaceFace_t *face, int dlightBits ) {
|
||||||
|
float d;
|
||||||
|
int i;
|
||||||
|
dlight_t *dl;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
|
||||||
|
if ( ! ( dlightBits & ( 1 << i ) ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dl = &tr.refdef.dlights[i];
|
||||||
|
d = DotProduct( dl->origin, face->plane.normal ) - face->plane.dist;
|
||||||
|
if ( d < -dl->radius || d > dl->radius ) {
|
||||||
|
// dlight doesn't reach the plane
|
||||||
|
dlightBits &= ~( 1 << i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !dlightBits ) {
|
||||||
|
tr.pc.c_dlightSurfacesCulled++;
|
||||||
|
}
|
||||||
|
|
||||||
|
face->dlightBits = dlightBits;
|
||||||
|
return dlightBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int R_DlightGrid( srfGridMesh_t *grid, int dlightBits ) {
|
||||||
|
int i;
|
||||||
|
dlight_t *dl;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
|
||||||
|
if ( ! ( dlightBits & ( 1 << i ) ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dl = &tr.refdef.dlights[i];
|
||||||
|
if ( dl->origin[0] - dl->radius > grid->meshBounds[1][0]
|
||||||
|
|| dl->origin[0] + dl->radius < grid->meshBounds[0][0]
|
||||||
|
|| dl->origin[1] - dl->radius > grid->meshBounds[1][1]
|
||||||
|
|| dl->origin[1] + dl->radius < grid->meshBounds[0][1]
|
||||||
|
|| dl->origin[2] - dl->radius > grid->meshBounds[1][2]
|
||||||
|
|| dl->origin[2] + dl->radius < grid->meshBounds[0][2] ) {
|
||||||
|
// dlight doesn't reach the bounds
|
||||||
|
dlightBits &= ~( 1 << i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !dlightBits ) {
|
||||||
|
tr.pc.c_dlightSurfacesCulled++;
|
||||||
|
}
|
||||||
|
|
||||||
|
grid->dlightBits = dlightBits;
|
||||||
|
return dlightBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int R_DlightTrisurf( srfTriangles_t *surf, int dlightBits ) {
|
||||||
|
// FIXME: more dlight culling to trisurfs...
|
||||||
|
surf->dlightBits = dlightBits;
|
||||||
|
return dlightBits;
|
||||||
|
#if 0
|
||||||
|
int i;
|
||||||
|
dlight_t *dl;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
|
||||||
|
if ( ! ( dlightBits & ( 1 << i ) ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dl = &tr.refdef.dlights[i];
|
||||||
|
if ( dl->origin[0] - dl->radius > grid->meshBounds[1][0]
|
||||||
|
|| dl->origin[0] + dl->radius < grid->meshBounds[0][0]
|
||||||
|
|| dl->origin[1] - dl->radius > grid->meshBounds[1][1]
|
||||||
|
|| dl->origin[1] + dl->radius < grid->meshBounds[0][1]
|
||||||
|
|| dl->origin[2] - dl->radius > grid->meshBounds[1][2]
|
||||||
|
|| dl->origin[2] + dl->radius < grid->meshBounds[0][2] ) {
|
||||||
|
// dlight doesn't reach the bounds
|
||||||
|
dlightBits &= ~( 1 << i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !dlightBits ) {
|
||||||
|
tr.pc.c_dlightSurfacesCulled++;
|
||||||
|
}
|
||||||
|
|
||||||
|
grid->dlightBits = dlightBits;
|
||||||
|
return dlightBits;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
R_DlightSurface
|
||||||
|
|
||||||
|
The given surface is going to be drawn, and it touches a leaf
|
||||||
|
that is touched by one or more dlights, so try to throw out
|
||||||
|
more dlights if possible.
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
|
||||||
|
if ( *surf->data == SF_FACE ) {
|
||||||
|
dlightBits = R_DlightFace( (srfSurfaceFace_t *)surf->data, dlightBits );
|
||||||
|
} else if ( *surf->data == SF_GRID ) {
|
||||||
|
dlightBits = R_DlightGrid( (srfGridMesh_t *)surf->data, dlightBits );
|
||||||
|
} else if ( *surf->data == SF_TRIANGLES ) {
|
||||||
|
dlightBits = R_DlightTrisurf( (srfTriangles_t *)surf->data, dlightBits );
|
||||||
|
} else {
|
||||||
|
dlightBits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dlightBits ) {
|
||||||
|
tr.pc.c_dlightSurfaces++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dlightBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
======================
|
||||||
|
R_AddWorldSurface
|
||||||
|
======================
|
||||||
|
*/
|
||||||
|
static void R_AddWorldSurface( msurface_t *surf, int dlightBits ) {
|
||||||
|
if ( surf->viewCount == tr.viewCount ) {
|
||||||
|
return; // already in this view
|
||||||
|
}
|
||||||
|
|
||||||
|
surf->viewCount = tr.viewCount;
|
||||||
|
// FIXME: bmodel fog?
|
||||||
|
|
||||||
|
// try to cull before dlighting or adding
|
||||||
|
if ( R_CullSurface( surf->data, surf->shader ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for dlighting
|
||||||
|
if ( dlightBits ) {
|
||||||
|
dlightBits = R_DlightSurface( surf, dlightBits );
|
||||||
|
dlightBits = ( dlightBits != 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
R_AddDrawSurf( surf->data, surf->shader, surf->fogIndex, dlightBits );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============================================================
|
||||||
|
|
||||||
|
BRUSH MODELS
|
||||||
|
|
||||||
|
=============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_AddBrushModelSurfaces
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) {
|
||||||
|
bmodel_t *bmodel;
|
||||||
|
int clip;
|
||||||
|
model_t *pModel;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pModel = R_GetModelByHandle( ent->e.hModel );
|
||||||
|
|
||||||
|
bmodel = pModel->bmodel;
|
||||||
|
|
||||||
|
clip = R_CullLocalBox( bmodel->bounds );
|
||||||
|
if ( clip == CULL_OUT ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SetupEntityLighting( &tr.refdef, ent );
|
||||||
|
R_DlightBmodel( bmodel );
|
||||||
|
|
||||||
|
for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
|
||||||
|
R_AddWorldSurface( bmodel->firstSurface + i, tr.currentEntity->needDlights );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============================================================
|
||||||
|
|
||||||
|
WORLD MODEL
|
||||||
|
|
||||||
|
=============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
R_RecursiveWorldNode
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static void R_RecursiveWorldNode( mnode_t *node, unsigned int planeBits, unsigned int dlightBits ) {
|
||||||
|
|
||||||
|
do {
|
||||||
|
unsigned int newDlights[2];
|
||||||
|
|
||||||
|
// if the node wasn't marked as potentially visible, exit
|
||||||
|
if (node->visframe != tr.visCount) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the bounding volume is outside the frustum, nothing
|
||||||
|
// inside can be visible OPTIMIZE: don't do this all the way to leafs?
|
||||||
|
|
||||||
|
if ( !r_nocull->integer ) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ( planeBits & 1 ) {
|
||||||
|
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[0]);
|
||||||
|
if (r == 2) {
|
||||||
|
return; // culled
|
||||||
|
}
|
||||||
|
if ( r == 1 ) {
|
||||||
|
planeBits &= ~1; // all descendants will also be in front
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( planeBits & 2 ) {
|
||||||
|
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[1]);
|
||||||
|
if (r == 2) {
|
||||||
|
return; // culled
|
||||||
|
}
|
||||||
|
if ( r == 1 ) {
|
||||||
|
planeBits &= ~2; // all descendants will also be in front
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( planeBits & 4 ) {
|
||||||
|
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[2]);
|
||||||
|
if (r == 2) {
|
||||||
|
return; // culled
|
||||||
|
}
|
||||||
|
if ( r == 1 ) {
|
||||||
|
planeBits &= ~4; // all descendants will also be in front
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( planeBits & 8 ) {
|
||||||
|
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[3]);
|
||||||
|
if (r == 2) {
|
||||||
|
return; // culled
|
||||||
|
}
|
||||||
|
if ( r == 1 ) {
|
||||||
|
planeBits &= ~8; // all descendants will also be in front
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( node->contents != -1 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// node is just a decision point, so go down both sides
|
||||||
|
// since we don't care about sort orders, just go positive to negative
|
||||||
|
|
||||||
|
// determine which dlights are needed
|
||||||
|
newDlights[0] = 0;
|
||||||
|
newDlights[1] = 0;
|
||||||
|
if ( dlightBits ) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
|
||||||
|
dlight_t *dl;
|
||||||
|
float dist;
|
||||||
|
|
||||||
|
if ( dlightBits & ( 1 << i ) ) {
|
||||||
|
dl = &tr.refdef.dlights[i];
|
||||||
|
dist = DotProduct( dl->origin, node->plane->normal ) - node->plane->dist;
|
||||||
|
|
||||||
|
if ( dist > -dl->radius ) {
|
||||||
|
newDlights[0] |= ( 1 << i );
|
||||||
|
}
|
||||||
|
if ( dist < dl->radius ) {
|
||||||
|
newDlights[1] |= ( 1 << i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// recurse down the children, front side first
|
||||||
|
R_RecursiveWorldNode (node->children[0], planeBits, newDlights[0] );
|
||||||
|
|
||||||
|
// tail recurse
|
||||||
|
node = node->children[1];
|
||||||
|
dlightBits = newDlights[1];
|
||||||
|
} while ( 1 );
|
||||||
|
|
||||||
|
{
|
||||||
|
// leaf node, so add mark surfaces
|
||||||
|
int c;
|
||||||
|
msurface_t *surf, **mark;
|
||||||
|
|
||||||
|
tr.pc.c_leafs++;
|
||||||
|
|
||||||
|
// add to z buffer bounds
|
||||||
|
if ( node->mins[0] < tr.viewParms.visBounds[0][0] ) {
|
||||||
|
tr.viewParms.visBounds[0][0] = node->mins[0];
|
||||||
|
}
|
||||||
|
if ( node->mins[1] < tr.viewParms.visBounds[0][1] ) {
|
||||||
|
tr.viewParms.visBounds[0][1] = node->mins[1];
|
||||||
|
}
|
||||||
|
if ( node->mins[2] < tr.viewParms.visBounds[0][2] ) {
|
||||||
|
tr.viewParms.visBounds[0][2] = node->mins[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( node->maxs[0] > tr.viewParms.visBounds[1][0] ) {
|
||||||
|
tr.viewParms.visBounds[1][0] = node->maxs[0];
|
||||||
|
}
|
||||||
|
if ( node->maxs[1] > tr.viewParms.visBounds[1][1] ) {
|
||||||
|
tr.viewParms.visBounds[1][1] = node->maxs[1];
|
||||||
|
}
|
||||||
|
if ( node->maxs[2] > tr.viewParms.visBounds[1][2] ) {
|
||||||
|
tr.viewParms.visBounds[1][2] = node->maxs[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the individual surfaces
|
||||||
|
mark = node->firstmarksurface;
|
||||||
|
c = node->nummarksurfaces;
|
||||||
|
while (c--) {
|
||||||
|
// the surface may have already been added if it
|
||||||
|
// spans multiple leafs
|
||||||
|
surf = *mark;
|
||||||
|
R_AddWorldSurface( surf, dlightBits );
|
||||||
|
mark++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_PointInLeaf
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static mnode_t *R_PointInLeaf( const vec3_t p ) {
|
||||||
|
mnode_t *node;
|
||||||
|
float d;
|
||||||
|
cplane_t *plane;
|
||||||
|
|
||||||
|
if ( !tr.world ) {
|
||||||
|
ri.Error (ERR_DROP, "R_PointInLeaf: bad model");
|
||||||
|
}
|
||||||
|
|
||||||
|
node = tr.world->nodes;
|
||||||
|
while( 1 ) {
|
||||||
|
if (node->contents != -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
plane = node->plane;
|
||||||
|
d = DotProduct (p,plane->normal) - plane->dist;
|
||||||
|
if (d > 0) {
|
||||||
|
node = node->children[0];
|
||||||
|
} else {
|
||||||
|
node = node->children[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
R_ClusterPVS
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
static const byte *R_ClusterPVS (int cluster) {
|
||||||
|
if (!tr.world->vis || cluster < 0 || cluster >= tr.world->numClusters ) {
|
||||||
|
return tr.world->novis;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tr.world->vis + cluster * tr.world->clusterBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_inPVS
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
qboolean R_inPVS( const vec3_t p1, const vec3_t p2 ) {
|
||||||
|
mnode_t *leaf;
|
||||||
|
byte *vis;
|
||||||
|
|
||||||
|
leaf = R_PointInLeaf( p1 );
|
||||||
|
vis = ri.CM_ClusterPVS( leaf->cluster ); // why not R_ClusterPVS ??
|
||||||
|
leaf = R_PointInLeaf( p2 );
|
||||||
|
|
||||||
|
if ( !(vis[leaf->cluster>>3] & (1<<(leaf->cluster&7))) ) {
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_MarkLeaves
|
||||||
|
|
||||||
|
Mark the leaves and nodes that are in the PVS for the current
|
||||||
|
cluster
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void R_MarkLeaves (void) {
|
||||||
|
const byte *vis;
|
||||||
|
mnode_t *leaf, *parent;
|
||||||
|
int i;
|
||||||
|
int cluster;
|
||||||
|
|
||||||
|
// lockpvs lets designers walk around to determine the
|
||||||
|
// extent of the current pvs
|
||||||
|
if ( r_lockpvs->integer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// current viewcluster
|
||||||
|
leaf = R_PointInLeaf( tr.viewParms.pvsOrigin );
|
||||||
|
cluster = leaf->cluster;
|
||||||
|
|
||||||
|
// if the cluster is the same and the area visibility matrix
|
||||||
|
// hasn't changed, we don't need to mark everything again
|
||||||
|
|
||||||
|
// if r_showcluster was just turned on, remark everything
|
||||||
|
if ( tr.viewCluster == cluster && !tr.refdef.areamaskModified
|
||||||
|
&& !r_showcluster->modified ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( r_showcluster->modified || r_showcluster->integer ) {
|
||||||
|
r_showcluster->modified = qfalse;
|
||||||
|
if ( r_showcluster->integer ) {
|
||||||
|
ri.Printf( PRINT_ALL, "cluster:%i area:%i\n", cluster, leaf->area );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.visCount++;
|
||||||
|
tr.viewCluster = cluster;
|
||||||
|
|
||||||
|
if ( r_novis->integer || tr.viewCluster == -1 ) {
|
||||||
|
for (i=0 ; i<tr.world->numnodes ; i++) {
|
||||||
|
if (tr.world->nodes[i].contents != CONTENTS_SOLID) {
|
||||||
|
tr.world->nodes[i].visframe = tr.visCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vis = R_ClusterPVS (tr.viewCluster);
|
||||||
|
|
||||||
|
for (i=0,leaf=tr.world->nodes ; i<tr.world->numnodes ; i++, leaf++) {
|
||||||
|
cluster = leaf->cluster;
|
||||||
|
if ( cluster < 0 || cluster >= tr.world->numClusters ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check general pvs
|
||||||
|
if ( !(vis[cluster>>3] & (1<<(cluster&7))) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for door connection
|
||||||
|
if ( (tr.refdef.areamask[leaf->area>>3] & (1<<(leaf->area&7)) ) ) {
|
||||||
|
continue; // not visible
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = leaf;
|
||||||
|
do {
|
||||||
|
if (parent->visframe == tr.visCount)
|
||||||
|
break;
|
||||||
|
parent->visframe = tr.visCount;
|
||||||
|
parent = parent->parent;
|
||||||
|
} while (parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_AddWorldSurfaces
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_AddWorldSurfaces (void) {
|
||||||
|
if ( !r_drawworld->integer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.currentEntityNum = REFENTITYNUM_WORLD;
|
||||||
|
tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
|
||||||
|
|
||||||
|
// determine which leaves are in the PVS / areamask
|
||||||
|
R_MarkLeaves ();
|
||||||
|
|
||||||
|
// clear out the visible min/max
|
||||||
|
ClearBounds( tr.viewParms.visBounds[0], tr.viewParms.visBounds[1] );
|
||||||
|
|
||||||
|
// perform frustum culling and add all the potentially visible surfaces
|
||||||
|
if ( tr.refdef.num_dlights > MAX_DLIGHTS ) {
|
||||||
|
tr.refdef.num_dlights = MAX_DLIGHTS ;
|
||||||
|
}
|
||||||
|
R_RecursiveWorldNode( tr.world->nodes, 15, ( 1ULL << tr.refdef.num_dlights ) - 1 );
|
||||||
|
}
|
|
@ -11,7 +11,15 @@ void main()
|
||||||
vec2 tc;
|
vec2 tc;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
float c[7] = float[7](1.0, 0.9659258263, 0.8660254038, 0.7071067812, 0.5, 0.2588190451, 0.0);
|
float c[7];
|
||||||
|
|
||||||
|
c[0] = 1.0;
|
||||||
|
c[1] = 0.9659258263;
|
||||||
|
c[2] = 0.8660254038;
|
||||||
|
c[3] = 0.7071067812;
|
||||||
|
c[4] = 0.5;
|
||||||
|
c[5] = 0.2588190451;
|
||||||
|
c[6] = 0.0;
|
||||||
|
|
||||||
tc = var_TexCoords + u_InvTexRes * vec2( c[0], c[6]); color = texture2D(u_TextureMap, tc);
|
tc = var_TexCoords + u_InvTexRes * vec2( c[0], c[6]); color = texture2D(u_TextureMap, tc);
|
||||||
tc = var_TexCoords + u_InvTexRes * vec2( c[1], c[5]); color += texture2D(u_TextureMap, tc);
|
tc = var_TexCoords + u_InvTexRes * vec2( c[1], c[5]); color += texture2D(u_TextureMap, tc);
|
||||||
|
@ -44,7 +52,13 @@ void main()
|
||||||
gl_FragColor = color * 0.04166667 * u_Color;
|
gl_FragColor = color * 0.04166667 * u_Color;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float c[5] = float[5](1.0, 0.9238795325, 0.7071067812, 0.3826834324, 0.0);
|
float c[5];
|
||||||
|
|
||||||
|
c[0] = 1.0;
|
||||||
|
c[1] = 0.9238795325;
|
||||||
|
c[2] = 0.7071067812;
|
||||||
|
c[3] = 0.3826834324;
|
||||||
|
c[4] = 0.0;
|
||||||
|
|
||||||
tc = var_TexCoords + u_InvTexRes * vec2( c[0], c[4]); color = texture2D(u_TextureMap, tc);
|
tc = var_TexCoords + u_InvTexRes * vec2( c[0], c[4]); color = texture2D(u_TextureMap, tc);
|
||||||
tc = var_TexCoords + u_InvTexRes * vec2( c[1], c[3]); color += texture2D(u_TextureMap, tc);
|
tc = var_TexCoords + u_InvTexRes * vec2( c[1], c[3]); color += texture2D(u_TextureMap, tc);
|
||||||
|
|
|
@ -14,8 +14,8 @@ vec3 GetValues(vec2 offset, vec3 current)
|
||||||
|
|
||||||
#ifdef FIRST_PASS
|
#ifdef FIRST_PASS
|
||||||
|
|
||||||
#if defined(r_framebufferGamma)
|
#if defined(USE_PBR)
|
||||||
minAvgMax = pow(minAvgMax, vec3(r_framebufferGamma));
|
minAvgMax *= minAvgMax;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float lumi = max(dot(LUMINANCE_VECTOR, minAvgMax), 0.000001);
|
float lumi = max(dot(LUMINANCE_VECTOR, minAvgMax), 0.000001);
|
||||||
|
@ -56,5 +56,5 @@ void main()
|
||||||
current.y *= 0.0625;
|
current.y *= 0.0625;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gl_FragColor = vec4(current, 1.0f);
|
gl_FragColor = vec4(current, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,58 +1,88 @@
|
||||||
uniform sampler2D u_ScreenImageMap;
|
uniform sampler2D u_ScreenImageMap;
|
||||||
uniform sampler2D u_ScreenDepthMap;
|
uniform sampler2D u_ScreenDepthMap;
|
||||||
|
|
||||||
uniform vec4 u_ViewInfo; // zfar / znear, zfar
|
uniform vec4 u_ViewInfo; // zfar / znear, zfar, 1/width, 1/height
|
||||||
varying vec2 var_ScreenTex;
|
varying vec2 var_ScreenTex;
|
||||||
|
|
||||||
|
//float gauss[8] = float[8](0.17, 0.17, 0.16, 0.14, 0.12, 0.1, 0.08, 0.06);
|
||||||
//float gauss[5] = float[5](0.30, 0.23, 0.097, 0.024, 0.0033);
|
//float gauss[5] = float[5](0.30, 0.23, 0.097, 0.024, 0.0033);
|
||||||
float gauss[4] = float[4](0.40, 0.24, 0.054, 0.0044);
|
//float gauss[4] = float[4](0.40, 0.24, 0.054, 0.0044);
|
||||||
//float gauss[3] = float[3](0.60, 0.19, 0.0066);
|
//float gauss[3] = float[3](0.60, 0.19, 0.0066);
|
||||||
#define GAUSS_SIZE 4
|
#define BLUR_SIZE 4
|
||||||
|
|
||||||
|
#if !defined(USE_DEPTH)
|
||||||
|
//#define USE_GAUSS
|
||||||
|
#endif
|
||||||
|
|
||||||
float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear)
|
float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear)
|
||||||
{
|
{
|
||||||
float sampleZDivW = texture2D(depthMap, tex).r;
|
float sampleZDivW = texture2D(depthMap, tex).r;
|
||||||
return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
|
return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFarDivZNear, float zFar)
|
vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFarDivZNear, float zFar, vec2 scale)
|
||||||
{
|
{
|
||||||
float scale = 1.0 / 256.0;
|
float gauss[4];
|
||||||
|
|
||||||
|
gauss[0] = 0.40;
|
||||||
|
gauss[1] = 0.24;
|
||||||
|
gauss[2] = 0.054;
|
||||||
|
gauss[3] = 0.0044;
|
||||||
|
|
||||||
|
#if defined(USE_DEPTH)
|
||||||
|
float depthCenter = getLinearDepth(depthMap, tex, zFarDivZNear);
|
||||||
|
vec2 slope = vec2(dFdx(depthCenter), dFdy(depthCenter)) / vec2(dFdx(tex.x), dFdy(tex.y));
|
||||||
|
scale /= clamp(zFarDivZNear * depthCenter / 32.0, 1.0, 2.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(USE_HORIZONTAL_BLUR)
|
#if defined(USE_HORIZONTAL_BLUR)
|
||||||
vec2 direction = vec2(1.0, 0.0) * scale;
|
vec2 direction = vec2(scale.x * 2.0, 0.0);
|
||||||
|
vec2 nudge = vec2(0.0, scale.y * 0.5);
|
||||||
#else // if defined(USE_VERTICAL_BLUR)
|
#else // if defined(USE_VERTICAL_BLUR)
|
||||||
vec2 direction = vec2(0.0, 1.0) * scale;
|
vec2 direction = vec2(0.0, scale.y * 2.0);
|
||||||
|
vec2 nudge = vec2(-scale.x * 0.5, 0.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float depthCenter = zFar * getLinearDepth(depthMap, tex, zFarDivZNear);
|
#if defined(USE_GAUSS)
|
||||||
vec2 centerSlope = vec2(dFdx(depthCenter), dFdy(depthCenter)) / vec2(dFdx(tex.x), dFdy(tex.y));
|
|
||||||
|
|
||||||
vec4 result = texture2D(imageMap, tex) * gauss[0];
|
vec4 result = texture2D(imageMap, tex) * gauss[0];
|
||||||
float total = gauss[0];
|
float total = gauss[0];
|
||||||
|
#else
|
||||||
|
vec4 result = texture2D(imageMap, tex);
|
||||||
|
float total = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float zLimit = 5.0 / zFar;
|
||||||
int i, j;
|
int i, j;
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
for (j = 1; j < GAUSS_SIZE; j++)
|
for (j = 1; j < BLUR_SIZE; j++)
|
||||||
{
|
{
|
||||||
vec2 offset = direction * j;
|
vec2 offset = direction * (float(j) - 0.25) + nudge;
|
||||||
float depthSample = zFar * getLinearDepth(depthMap, tex + offset, zFarDivZNear);
|
#if defined(USE_DEPTH)
|
||||||
float depthExpected = depthCenter + dot(centerSlope, offset);
|
float depthSample = getLinearDepth(depthMap, tex + offset, zFarDivZNear);
|
||||||
if(abs(depthSample - depthExpected) < 5.0)
|
float depthExpected = depthCenter + dot(slope, offset);
|
||||||
{
|
float useSample = float(abs(depthSample - depthExpected) < zLimit);
|
||||||
result += texture2D(imageMap, tex + offset) * gauss[j];
|
#else
|
||||||
total += gauss[j];
|
float useSample = 1.0;
|
||||||
}
|
#endif
|
||||||
|
#if defined(USE_GAUSS)
|
||||||
|
result += texture2D(imageMap, tex + offset) * (gauss[j] * useSample);
|
||||||
|
total += gauss[j] * useSample;
|
||||||
|
#else
|
||||||
|
result += texture2D(imageMap, tex + offset) * useSample;
|
||||||
|
total += useSample;
|
||||||
|
#endif
|
||||||
|
nudge = -nudge;
|
||||||
}
|
}
|
||||||
|
|
||||||
direction = -direction;
|
direction = -direction;
|
||||||
}
|
nudge = -nudge;
|
||||||
|
}
|
||||||
|
|
||||||
return result / total;
|
return result / total;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_FragColor = depthGaussian1D(u_ScreenImageMap, u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y);
|
gl_FragColor = depthGaussian1D(u_ScreenImageMap, u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y, u_ViewInfo.zw);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
attribute vec4 attr_Position;
|
attribute vec4 attr_Position;
|
||||||
attribute vec4 attr_TexCoord0;
|
attribute vec4 attr_TexCoord0;
|
||||||
|
|
||||||
|
uniform vec4 u_ViewInfo; // zfar / znear, zfar, 1/width, 1/height
|
||||||
|
|
||||||
varying vec2 var_ScreenTex;
|
varying vec2 var_ScreenTex;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = attr_Position;
|
gl_Position = attr_Position;
|
||||||
var_ScreenTex = attr_TexCoord0.xy;
|
vec2 wh = vec2(1.0) / u_ViewInfo.zw - vec2(1.0);
|
||||||
|
var_ScreenTex = (floor(attr_TexCoord0.xy * wh) + vec2(0.5)) * u_ViewInfo.zw;
|
||||||
|
|
||||||
//vec2 screenCoords = gl_Position.xy / gl_Position.w;
|
//vec2 screenCoords = gl_Position.xy / gl_Position.w;
|
||||||
//var_ScreenTex = screenCoords * 0.5 + 0.5;
|
//var_ScreenTex = screenCoords * 0.5 + 0.5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
uniform sampler2D u_DiffuseMap;
|
uniform sampler2D u_DiffuseMap;
|
||||||
|
|
||||||
|
uniform int u_AlphaTest;
|
||||||
|
|
||||||
varying vec2 var_Tex1;
|
varying vec2 var_Tex1;
|
||||||
varying vec4 var_Color;
|
varying vec4 var_Color;
|
||||||
|
|
||||||
|
@ -8,5 +10,23 @@ void main()
|
||||||
{
|
{
|
||||||
vec4 color = texture2D(u_DiffuseMap, var_Tex1);
|
vec4 color = texture2D(u_DiffuseMap, var_Tex1);
|
||||||
|
|
||||||
gl_FragColor = color * var_Color;
|
float alpha = color.a * var_Color.a;
|
||||||
|
if (u_AlphaTest == 1)
|
||||||
|
{
|
||||||
|
if (alpha == 0.0)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
else if (u_AlphaTest == 2)
|
||||||
|
{
|
||||||
|
if (alpha >= 0.5)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
else if (u_AlphaTest == 3)
|
||||||
|
{
|
||||||
|
if (alpha < 0.5)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragColor.rgb = color.rgb * var_Color.rgb;
|
||||||
|
gl_FragColor.a = alpha;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ attribute vec4 attr_TexCoord0;
|
||||||
#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
attribute vec3 attr_Position2;
|
attribute vec3 attr_Position2;
|
||||||
attribute vec3 attr_Normal2;
|
attribute vec3 attr_Normal2;
|
||||||
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
attribute vec4 attr_BoneIndexes;
|
||||||
|
attribute vec4 attr_BoneWeights;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uniform vec4 u_FogDistance;
|
uniform vec4 u_FogDistance;
|
||||||
|
@ -22,6 +25,8 @@ uniform mat4 u_ModelViewProjectionMatrix;
|
||||||
|
|
||||||
#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
uniform float u_VertexLerp;
|
uniform float u_VertexLerp;
|
||||||
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
uniform mat4 u_BoneMatrix[MAX_GLSL_BONES];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uniform vec4 u_Color;
|
uniform vec4 u_Color;
|
||||||
|
@ -102,6 +107,15 @@ void main()
|
||||||
#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
|
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
|
||||||
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
|
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
|
||||||
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
mat4 vtxMat = u_BoneMatrix[int(attr_BoneIndexes.x)] * attr_BoneWeights.x;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.y)] * attr_BoneWeights.y;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.z)] * attr_BoneWeights.z;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.w)] * attr_BoneWeights.w;
|
||||||
|
mat3 nrmMat = mat3(cross(vtxMat[1].xyz, vtxMat[2].xyz), cross(vtxMat[2].xyz, vtxMat[0].xyz), cross(vtxMat[0].xyz, vtxMat[1].xyz));
|
||||||
|
|
||||||
|
vec3 position = vec3(vtxMat * vec4(attr_Position, 1.0));
|
||||||
|
vec3 normal = normalize(nrmMat * attr_Normal);
|
||||||
#else
|
#else
|
||||||
vec3 position = attr_Position;
|
vec3 position = attr_Position;
|
||||||
vec3 normal = attr_Normal;
|
vec3 normal = attr_Normal;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
uniform sampler2D u_DiffuseMap;
|
uniform sampler2D u_DiffuseMap;
|
||||||
|
|
||||||
|
uniform int u_AlphaTest;
|
||||||
|
|
||||||
varying vec2 var_DiffuseTex;
|
varying vec2 var_DiffuseTex;
|
||||||
|
|
||||||
varying vec4 var_Color;
|
varying vec4 var_Color;
|
||||||
|
@ -8,5 +10,24 @@ varying vec4 var_Color;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 color = texture2D(u_DiffuseMap, var_DiffuseTex);
|
vec4 color = texture2D(u_DiffuseMap, var_DiffuseTex);
|
||||||
gl_FragColor = color * var_Color;
|
|
||||||
|
float alpha = color.a * var_Color.a;
|
||||||
|
if (u_AlphaTest == 1)
|
||||||
|
{
|
||||||
|
if (alpha == 0.0)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
else if (u_AlphaTest == 2)
|
||||||
|
{
|
||||||
|
if (alpha >= 0.5)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
else if (u_AlphaTest == 3)
|
||||||
|
{
|
||||||
|
if (alpha < 0.5)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragColor.rgb = color.rgb * var_Color.rgb;
|
||||||
|
gl_FragColor.a = alpha;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@ attribute vec3 attr_Normal;
|
||||||
#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
attribute vec3 attr_Position2;
|
attribute vec3 attr_Position2;
|
||||||
attribute vec3 attr_Normal2;
|
attribute vec3 attr_Normal2;
|
||||||
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
attribute vec4 attr_BoneIndexes;
|
||||||
|
attribute vec4 attr_BoneWeights;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
attribute vec4 attr_Color;
|
attribute vec4 attr_Color;
|
||||||
|
@ -54,6 +57,8 @@ uniform float u_PortalRange;
|
||||||
|
|
||||||
#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
uniform float u_VertexLerp;
|
uniform float u_VertexLerp;
|
||||||
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
uniform mat4 u_BoneMatrix[MAX_GLSL_BONES];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
varying vec2 var_DiffuseTex;
|
varying vec2 var_DiffuseTex;
|
||||||
|
@ -204,6 +209,15 @@ void main()
|
||||||
#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
|
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
|
||||||
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
|
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
|
||||||
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
mat4 vtxMat = u_BoneMatrix[int(attr_BoneIndexes.x)] * attr_BoneWeights.x;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.y)] * attr_BoneWeights.y;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.z)] * attr_BoneWeights.z;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.w)] * attr_BoneWeights.w;
|
||||||
|
mat3 nrmMat = mat3(cross(vtxMat[1].xyz, vtxMat[2].xyz), cross(vtxMat[2].xyz, vtxMat[0].xyz), cross(vtxMat[0].xyz, vtxMat[1].xyz));
|
||||||
|
|
||||||
|
vec3 position = vec3(vtxMat * vec4(attr_Position, 1.0));
|
||||||
|
vec3 normal = normalize(nrmMat * attr_Normal);
|
||||||
#else
|
#else
|
||||||
vec3 position = attr_Position;
|
vec3 position = attr_Position;
|
||||||
vec3 normal = attr_Normal;
|
vec3 normal = attr_Normal;
|
||||||
|
|
|
@ -29,11 +29,6 @@ uniform samplerCube u_CubeMap;
|
||||||
uniform vec4 u_EnableTextures;
|
uniform vec4 u_EnableTextures;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
|
|
||||||
uniform vec3 u_DirectedLight;
|
|
||||||
uniform vec3 u_AmbientLight;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
||||||
uniform vec3 u_PrimaryLightColor;
|
uniform vec3 u_PrimaryLightColor;
|
||||||
uniform vec3 u_PrimaryLightAmbient;
|
uniform vec3 u_PrimaryLightAmbient;
|
||||||
|
@ -50,19 +45,19 @@ uniform vec4 u_CubeMapInfo;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uniform int u_AlphaTest;
|
||||||
|
|
||||||
varying vec4 var_TexCoords;
|
varying vec4 var_TexCoords;
|
||||||
|
|
||||||
varying vec4 var_Color;
|
varying vec4 var_Color;
|
||||||
|
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
|
||||||
|
varying vec4 var_ColorAmbient;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
|
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
|
||||||
#if defined(USE_VERT_TANGENT_SPACE)
|
|
||||||
varying vec4 var_Normal;
|
varying vec4 var_Normal;
|
||||||
varying vec4 var_Tangent;
|
varying vec4 var_Tangent;
|
||||||
varying vec4 var_Bitangent;
|
varying vec4 var_Bitangent;
|
||||||
#else
|
|
||||||
varying vec3 var_Normal;
|
|
||||||
varying vec3 var_ViewDir;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
|
@ -94,6 +89,9 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap)
|
||||||
// current size of search window
|
// current size of search window
|
||||||
float size = 1.0 / float(linearSearchSteps);
|
float size = 1.0 / float(linearSearchSteps);
|
||||||
|
|
||||||
|
// adjust position if offset above surface
|
||||||
|
dp -= ds * r_parallaxMapOffset;
|
||||||
|
|
||||||
// current depth position
|
// current depth position
|
||||||
float depth = 0.0;
|
float depth = 0.0;
|
||||||
|
|
||||||
|
@ -146,160 +144,68 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return bestDepth;
|
return bestDepth - r_parallaxMapOffset;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
vec3 CalcDiffuse(vec3 diffuseAlbedo, vec3 N, vec3 L, vec3 E, float NE, float NL, float shininess)
|
float LightRay(vec2 dp, vec2 ds, sampler2D normalMap)
|
||||||
{
|
{
|
||||||
#if defined(USE_OREN_NAYAR) || defined(USE_TRIACE_OREN_NAYAR)
|
const int linearSearchSteps = 16;
|
||||||
float gamma = dot(E, L) - NE * NL;
|
|
||||||
float B = 2.22222 + 0.1 * shininess;
|
|
||||||
|
|
||||||
#if defined(USE_OREN_NAYAR)
|
|
||||||
float A = 1.0 - 1.0 / (2.0 + 0.33 * shininess);
|
|
||||||
gamma = clamp(gamma, 0.0, 1.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_TRIACE_OREN_NAYAR)
|
|
||||||
float A = 1.0 - 1.0 / (2.0 + 0.65 * shininess);
|
|
||||||
|
|
||||||
if (gamma >= 0.0)
|
// current size of search window
|
||||||
#endif
|
float size = 1.0 / float(linearSearchSteps);
|
||||||
|
|
||||||
|
// current height from initial texel depth
|
||||||
|
float height = 0.0;
|
||||||
|
|
||||||
|
float startDepth = SampleDepth(normalMap, dp);
|
||||||
|
|
||||||
|
// find a collision or escape
|
||||||
|
for(int i = 0; i < linearSearchSteps - 1; ++i)
|
||||||
{
|
{
|
||||||
B = max(B * max(NL, NE), EPSILON);
|
height += size;
|
||||||
|
|
||||||
|
if (startDepth < height)
|
||||||
|
return 1.0;
|
||||||
|
|
||||||
|
float t = SampleDepth(normalMap, dp + ds * height);
|
||||||
|
|
||||||
|
if (startDepth > t + height)
|
||||||
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return diffuseAlbedo * (A + gamma / B);
|
|
||||||
#else
|
|
||||||
return diffuseAlbedo;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 EnvironmentBRDF(float gloss, float NE, vec3 specular)
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
// from http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
|
|
||||||
vec4 t = vec4( 1.0/0.96, 0.475, (0.0275 - 0.25 * 0.04)/0.96,0.25 ) * gloss;
|
|
||||||
t += vec4( 0.0, 0.0, (0.015 - 0.75 * 0.04)/0.96,0.75 );
|
|
||||||
float a0 = t.x * min( t.y, exp2( -9.28 * NE ) ) + t.z;
|
|
||||||
float a1 = t.w;
|
|
||||||
return clamp( a0 + specular * ( a1 - a0 ), 0.0, 1.0 );
|
|
||||||
#elif 0
|
|
||||||
// from http://seblagarde.wordpress.com/2011/08/17/hello-world/
|
|
||||||
return specular + CalcFresnel(NE) * clamp(vec3(gloss) - specular, 0.0, 1.0);
|
|
||||||
#else
|
|
||||||
// from http://advances.realtimerendering.com/s2011/Lazarov-Physically-Based-Lighting-in-Black-Ops%20%28Siggraph%202011%20Advances%20in%20Real-Time%20Rendering%20Course%29.pptx
|
|
||||||
return mix(specular.rgb, vec3(1.0), CalcFresnel(NE) / (4.0 - 3.0 * gloss));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
float CalcBlinn(float NH, float shininess)
|
|
||||||
{
|
|
||||||
#if defined(USE_BLINN) || defined(USE_BLINN_FRESNEL)
|
|
||||||
// Normalized Blinn-Phong
|
|
||||||
float norm = shininess * 0.125 + 1.0;
|
|
||||||
#elif defined(USE_MCAULEY)
|
|
||||||
// Cook-Torrance as done by Stephen McAuley
|
|
||||||
// http://blog.selfshadow.com/publications/s2012-shading-course/mcauley/s2012_pbs_farcry3_notes_v2.pdf
|
|
||||||
float norm = shininess * 0.25 + 0.125;
|
|
||||||
#elif defined(USE_GOTANDA)
|
|
||||||
// Neumann-Neumann as done by Yoshiharu Gotanda
|
|
||||||
// http://research.tri-ace.com/Data/s2012_beyond_CourseNotes.pdf
|
|
||||||
float norm = shininess * 0.124858 + 0.269182;
|
|
||||||
#elif defined(USE_LAZAROV)
|
|
||||||
// Cook-Torrance as done by Dimitar Lazarov
|
|
||||||
// http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
|
|
||||||
float norm = shininess * 0.125 + 0.25;
|
|
||||||
#else
|
|
||||||
float norm = 1.0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// from http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/
|
|
||||||
float a = shininess + 0.775;
|
|
||||||
return norm * exp(a * NH - a);
|
|
||||||
#else
|
|
||||||
return norm * pow(NH, shininess);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
float CalcGGX(float NH, float gloss)
|
|
||||||
{
|
|
||||||
// from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
|
|
||||||
float a_sq = exp2(gloss * -13.0 + 1.0);
|
|
||||||
float d = ((NH * NH) * (a_sq - 1.0) + 1.0);
|
|
||||||
return a_sq / (d * d);
|
|
||||||
}
|
|
||||||
|
|
||||||
float CalcFresnel(float EH)
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
// From http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
|
|
||||||
// not accurate, but fast
|
|
||||||
return exp2(-10.0 * EH);
|
|
||||||
#elif 0
|
|
||||||
// From http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/
|
|
||||||
return exp2((-5.55473 * EH - 6.98316) * EH);
|
|
||||||
#elif 0
|
|
||||||
float blend = 1.0 - EH;
|
|
||||||
float blend2 = blend * blend;
|
|
||||||
blend *= blend2 * blend2;
|
|
||||||
|
|
||||||
return blend;
|
|
||||||
#else
|
|
||||||
return pow(1.0 - EH, 5.0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
float CalcVisibility(float NH, float NL, float NE, float EH, float gloss)
|
|
||||||
{
|
|
||||||
#if defined(USE_GOTANDA)
|
|
||||||
// Neumann-Neumann as done by Yoshiharu Gotanda
|
|
||||||
// http://research.tri-ace.com/Data/s2012_beyond_CourseNotes.pdf
|
|
||||||
return 1.0 / max(max(NL, NE), EPSILON);
|
|
||||||
#elif defined(USE_LAZAROV)
|
|
||||||
// Cook-Torrance as done by Dimitar Lazarov
|
|
||||||
// http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
|
|
||||||
float k = min(1.0, gloss + 0.545);
|
|
||||||
return 1.0 / (k * (EH * EH - 1.0) + 1.0);
|
|
||||||
#elif defined(USE_GGX)
|
|
||||||
float roughness = exp2(gloss * -6.5);
|
|
||||||
|
|
||||||
// Modified from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
|
|
||||||
// NL, NE in numerator factored out from cook-torrance
|
|
||||||
float k = roughness + 1.0;
|
|
||||||
k *= k * 0.125;
|
|
||||||
|
|
||||||
float k2 = 1.0 - k;
|
|
||||||
|
|
||||||
float invGeo1 = NL * k2 + k;
|
|
||||||
float invGeo2 = NE * k2 + k;
|
|
||||||
|
|
||||||
return 1.0 / (invGeo1 * invGeo2);
|
|
||||||
#else
|
|
||||||
return 1.0;
|
return 1.0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec3 CalcDiffuse(vec3 diffuseAlbedo, float NH, float EH, float roughness)
|
||||||
|
{
|
||||||
|
#if defined(USE_BURLEY)
|
||||||
|
// modified from https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf
|
||||||
|
float fd90 = -0.5 + EH * EH * roughness;
|
||||||
|
float burley = 1.0 + fd90 * 0.04 / NH;
|
||||||
|
burley *= burley;
|
||||||
|
return diffuseAlbedo * burley;
|
||||||
|
#else
|
||||||
|
return diffuseAlbedo;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec3 EnvironmentBRDF(float roughness, float NE, vec3 specular)
|
||||||
vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float gloss, float shininess)
|
|
||||||
{
|
{
|
||||||
#if defined(USE_GGX)
|
// from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf
|
||||||
float distrib = CalcGGX(NH, gloss);
|
float v = 1.0 - max(roughness, NE);
|
||||||
#else
|
v *= v * v;
|
||||||
float distrib = CalcBlinn(NH, shininess);
|
return vec3(v) + specular;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
#if defined(USE_BLINN)
|
vec3 CalcSpecular(vec3 specular, float NH, float EH, float roughness)
|
||||||
vec3 fSpecular = specular;
|
{
|
||||||
#else
|
// from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf
|
||||||
vec3 fSpecular = mix(specular, vec3(1.0), CalcFresnel(EH));
|
float rr = roughness*roughness;
|
||||||
#endif
|
float rrrr = rr*rr;
|
||||||
|
float d = (NH * NH) * (rrrr - 1.0) + 1.0;
|
||||||
float vis = CalcVisibility(NH, NL, NE, EH, gloss);
|
float v = (EH * EH) * (roughness + 0.5) + EPSILON;
|
||||||
|
return specular * (rrrr / (4.0 * d * d * v));
|
||||||
return fSpecular * (distrib * vis);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -319,61 +225,68 @@ float CalcLightAttenuation(float point, float normDist)
|
||||||
return attenuation;
|
return attenuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from http://www.thetenthplanet.de/archives/1180
|
#if defined(USE_BOX_CUBEMAP_PARALLAX)
|
||||||
mat3 cotangent_frame( vec3 N, vec3 p, vec2 uv )
|
vec4 hitCube(vec3 ray, vec3 pos, vec3 invSize, float lod, samplerCube tex)
|
||||||
{
|
{
|
||||||
// get edge vectors of the pixel triangle
|
// find any hits on cubemap faces facing the camera
|
||||||
vec3 dp1 = dFdx( p );
|
vec3 scale = (sign(ray) - pos) / ray;
|
||||||
vec3 dp2 = dFdy( p );
|
|
||||||
vec2 duv1 = dFdx( uv );
|
|
||||||
vec2 duv2 = dFdy( uv );
|
|
||||||
|
|
||||||
// solve the linear system
|
// find the nearest hit
|
||||||
vec3 dp2perp = cross( dp2, N );
|
float minScale = min(min(scale.x, scale.y), scale.z);
|
||||||
vec3 dp1perp = cross( N, dp1 );
|
|
||||||
vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
|
|
||||||
vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
|
|
||||||
|
|
||||||
// construct a scale-invariant frame
|
// if the nearest hit is behind the camera, ignore
|
||||||
float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
|
// should not be necessary as long as pos is inside the cube
|
||||||
return mat3( T * invmax, B * invmax, N );
|
//if (minScale < 0.0)
|
||||||
|
//return vec4(0.0);
|
||||||
|
|
||||||
|
// calculate the hit position, that's our texture coordinates
|
||||||
|
vec3 tc = pos + ray * minScale;
|
||||||
|
|
||||||
|
// if the texture coordinates are outside the cube, ignore
|
||||||
|
// necessary since we're not fading out outside the cube
|
||||||
|
if (any(greaterThan(abs(tc), vec3(1.00001))))
|
||||||
|
return vec4(0.0);
|
||||||
|
|
||||||
|
// fade out when approaching the cubemap edges
|
||||||
|
//vec3 fade3 = abs(pos);
|
||||||
|
//float fade = max(max(fade3.x, fade3.y), fade3.z);
|
||||||
|
//fade = clamp(1.0 - fade, 0.0, 1.0);
|
||||||
|
|
||||||
|
//return vec4(textureCubeLod(tex, tc, lod).rgb * fade, fade);
|
||||||
|
return vec4(textureCubeLod(tex, tc, lod).rgb, 1.0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 viewDir, lightColor, ambientColor;
|
vec3 viewDir, lightColor, ambientColor, reflectance;
|
||||||
vec3 L, N, E, H;
|
vec3 L, N, E, H;
|
||||||
float NL, NH, NE, EH, attenuation;
|
float NL, NH, NE, EH, attenuation;
|
||||||
|
|
||||||
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
#if defined(USE_VERT_TANGENT_SPACE)
|
vec3 surfNormal = (!gl_FrontFacing ? var_Normal : -var_Normal).xyz;
|
||||||
mat3 tangentToWorld = mat3(var_Tangent.xyz, var_Bitangent.xyz, var_Normal.xyz);
|
mat3 tangentToWorld = mat3(var_Tangent.xyz, var_Bitangent.xyz, surfNormal);
|
||||||
viewDir = vec3(var_Normal.w, var_Tangent.w, var_Bitangent.w);
|
viewDir = vec3(var_Normal.w, var_Tangent.w, var_Bitangent.w);
|
||||||
#else
|
|
||||||
mat3 tangentToWorld = cotangent_frame(var_Normal, -var_ViewDir, var_TexCoords.xy);
|
|
||||||
viewDir = var_ViewDir;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
E = normalize(viewDir);
|
E = normalize(viewDir);
|
||||||
|
|
||||||
L = var_LightDir.xyz;
|
|
||||||
#if defined(USE_DELUXEMAP)
|
|
||||||
L += (texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(0.5)) * u_EnableTextures.y;
|
|
||||||
#endif
|
|
||||||
float sqrLightDist = dot(L, L);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
lightColor = var_Color.rgb;
|
||||||
|
|
||||||
#if defined(USE_LIGHTMAP)
|
#if defined(USE_LIGHTMAP)
|
||||||
vec4 lightmapColor = texture2D(u_LightMap, var_TexCoords.zw);
|
vec4 lightmapColor = texture2D(u_LightMap, var_TexCoords.zw);
|
||||||
#if defined(RGBM_LIGHTMAP)
|
#if defined(RGBM_LIGHTMAP)
|
||||||
lightmapColor.rgb *= lightmapColor.a;
|
lightmapColor.rgb *= lightmapColor.a;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(USE_PBR) && !defined(USE_FAST_LIGHT)
|
||||||
|
lightmapColor.rgb *= lightmapColor.rgb;
|
||||||
|
#endif
|
||||||
|
lightColor *= lightmapColor.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec2 texCoords = var_TexCoords.xy;
|
vec2 texCoords = var_TexCoords.xy;
|
||||||
|
|
||||||
#if defined(USE_PARALLAXMAP)
|
#if defined(USE_PARALLAXMAP)
|
||||||
vec3 offsetDir = viewDir * tangentToWorld;
|
vec3 offsetDir = E * tangentToWorld;
|
||||||
|
|
||||||
offsetDir.xy *= -u_NormalScale.a / offsetDir.z;
|
offsetDir.xy *= -u_NormalScale.a / offsetDir.z;
|
||||||
|
|
||||||
|
@ -381,19 +294,35 @@ void main()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec4 diffuse = texture2D(u_DiffuseMap, texCoords);
|
vec4 diffuse = texture2D(u_DiffuseMap, texCoords);
|
||||||
|
|
||||||
|
float alpha = diffuse.a * var_Color.a;
|
||||||
|
if (u_AlphaTest == 1)
|
||||||
|
{
|
||||||
|
if (alpha == 0.0)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
else if (u_AlphaTest == 2)
|
||||||
|
{
|
||||||
|
if (alpha >= 0.5)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
else if (u_AlphaTest == 3)
|
||||||
|
{
|
||||||
|
if (alpha < 0.5)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
#if defined(USE_LIGHTMAP)
|
L = var_LightDir.xyz;
|
||||||
lightColor = lightmapColor.rgb * var_Color.rgb;
|
#if defined(USE_DELUXEMAP)
|
||||||
ambientColor = vec3(0.0);
|
L += (texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(0.5)) * u_EnableTextures.y;
|
||||||
attenuation = 1.0;
|
#endif
|
||||||
#elif defined(USE_LIGHT_VECTOR)
|
float sqrLightDist = dot(L, L);
|
||||||
lightColor = u_DirectedLight * var_Color.rgb;
|
L /= sqrt(sqrLightDist);
|
||||||
ambientColor = u_AmbientLight * var_Color.rgb;
|
|
||||||
|
#if defined(USE_LIGHT_VECTOR)
|
||||||
attenuation = CalcLightAttenuation(float(var_LightDir.w > 0.0), var_LightDir.w / sqrLightDist);
|
attenuation = CalcLightAttenuation(float(var_LightDir.w > 0.0), var_LightDir.w / sqrLightDist);
|
||||||
#elif defined(USE_LIGHT_VERTEX)
|
#else
|
||||||
lightColor = var_Color.rgb;
|
|
||||||
ambientColor = vec3(0.0);
|
|
||||||
attenuation = 1.0;
|
attenuation = 1.0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -407,39 +336,36 @@ void main()
|
||||||
N.z = sqrt(clamp((0.25 - N.x * N.x) - N.y * N.y, 0.0, 1.0));
|
N.z = sqrt(clamp((0.25 - N.x * N.x) - N.y * N.y, 0.0, 1.0));
|
||||||
N = tangentToWorld * N;
|
N = tangentToWorld * N;
|
||||||
#else
|
#else
|
||||||
N = var_Normal.xyz;
|
N = surfNormal;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
N = normalize(N);
|
N = normalize(N);
|
||||||
L /= sqrt(sqrLightDist);
|
|
||||||
|
|
||||||
#if defined(USE_SHADOWMAP)
|
#if defined(USE_SHADOWMAP)
|
||||||
vec2 shadowTex = gl_FragCoord.xy * r_FBufScale;
|
vec2 shadowTex = gl_FragCoord.xy * r_FBufScale;
|
||||||
float shadowValue = texture2D(u_ShadowMap, shadowTex).r;
|
float shadowValue = texture2D(u_ShadowMap, shadowTex).r;
|
||||||
|
|
||||||
// surfaces not facing the light are always shadowed
|
// surfaces not facing the light are always shadowed
|
||||||
shadowValue *= float(dot(var_Normal.xyz, var_PrimaryLightDir.xyz) > 0.0);
|
shadowValue *= clamp(dot(N, var_PrimaryLightDir.xyz), 0.0, 1.0);
|
||||||
|
|
||||||
#if defined(SHADOWMAP_MODULATE)
|
#if defined(SHADOWMAP_MODULATE)
|
||||||
//vec3 shadowColor = min(u_PrimaryLightAmbient, lightColor);
|
lightColor *= shadowValue * (1.0 - u_PrimaryLightAmbient.r) + u_PrimaryLightAmbient.r;
|
||||||
vec3 shadowColor = u_PrimaryLightAmbient * lightColor;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Only shadow when the world light is parallel to the primary light
|
|
||||||
shadowValue = 1.0 + (shadowValue - 1.0) * clamp(dot(L, var_PrimaryLightDir.xyz), 0.0, 1.0);
|
|
||||||
#endif
|
|
||||||
lightColor = mix(shadowColor, lightColor, shadowValue);
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(r_lightGamma)
|
#if defined(USE_PARALLAXMAP) && defined(USE_PARALLAXMAP_SHADOWS)
|
||||||
lightColor = pow(lightColor, vec3(r_lightGamma));
|
offsetDir = L * tangentToWorld;
|
||||||
ambientColor = pow(ambientColor, vec3(r_lightGamma));
|
offsetDir.xy *= u_NormalScale.a / offsetDir.z;
|
||||||
|
lightColor *= LightRay(texCoords, offsetDir.xy, u_NormalMap);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX)
|
|
||||||
|
#if !defined(USE_LIGHT_VECTOR)
|
||||||
ambientColor = lightColor;
|
ambientColor = lightColor;
|
||||||
float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0);
|
float surfNL = clamp(dot(surfNormal, L), 0.0, 1.0);
|
||||||
|
|
||||||
|
// reserve 25% ambient to avoid black areas on normalmaps
|
||||||
|
lightColor *= 0.75;
|
||||||
|
|
||||||
// Scale the incoming light to compensate for the baked-in light angle
|
// Scale the incoming light to compensate for the baked-in light angle
|
||||||
// attenuation.
|
// attenuation.
|
||||||
|
@ -447,83 +373,71 @@ void main()
|
||||||
|
|
||||||
// Recover any unused light as ambient, in case attenuation is over 4x or
|
// Recover any unused light as ambient, in case attenuation is over 4x or
|
||||||
// light is below the surface
|
// light is below the surface
|
||||||
ambientColor = clamp(ambientColor - lightColor * surfNL, 0.0, 1.0);
|
ambientColor = max(ambientColor - lightColor * surfNL, vec3(0.0));
|
||||||
|
#else
|
||||||
|
ambientColor = var_ColorAmbient.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec3 reflectance;
|
|
||||||
|
|
||||||
NL = clamp(dot(N, L), 0.0, 1.0);
|
NL = clamp(dot(N, L), 0.0, 1.0);
|
||||||
NE = clamp(dot(N, E), 0.0, 1.0);
|
NE = clamp(dot(N, E), 0.0, 1.0);
|
||||||
|
H = normalize(L + E);
|
||||||
|
EH = clamp(dot(E, H), 0.0, 1.0);
|
||||||
|
NH = clamp(dot(N, H), 0.0, 1.0);
|
||||||
|
|
||||||
#if defined(USE_SPECULARMAP)
|
#if defined(USE_SPECULARMAP)
|
||||||
vec4 specular = texture2D(u_SpecularMap, texCoords);
|
vec4 specular = texture2D(u_SpecularMap, texCoords);
|
||||||
#else
|
#else
|
||||||
vec4 specular = vec4(1.0);
|
vec4 specular = vec4(1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
specular *= u_SpecularScale;
|
specular *= u_SpecularScale;
|
||||||
|
|
||||||
#if defined(r_materialGamma)
|
#if defined(USE_PBR)
|
||||||
diffuse.rgb = pow(diffuse.rgb, vec3(r_materialGamma));
|
diffuse.rgb *= diffuse.rgb;
|
||||||
specular.rgb = pow(specular.rgb, vec3(r_materialGamma));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float gloss = specular.a;
|
#if defined(USE_PBR)
|
||||||
float shininess = exp2(gloss * 13.0);
|
// diffuse rgb is base color
|
||||||
|
// specular red is gloss
|
||||||
#if defined(SPECULAR_IS_METALLIC)
|
// specular green is metallicness
|
||||||
// diffuse is actually base color, and red of specular is metallicness
|
float gloss = specular.r;
|
||||||
float metallic = specular.r;
|
float metal = specular.g;
|
||||||
|
specular.rgb = metal * diffuse.rgb + vec3(0.04 - 0.04 * metal);
|
||||||
specular.rgb = (0.96 * metallic) * diffuse.rgb + vec3(0.04);
|
diffuse.rgb *= 1.0 - metal;
|
||||||
diffuse.rgb *= 1.0 - metallic;
|
|
||||||
#else
|
#else
|
||||||
|
// diffuse rgb is diffuse
|
||||||
|
// specular rgb is specular reflectance at normal incidence
|
||||||
|
// specular alpha is gloss
|
||||||
|
float gloss = specular.a;
|
||||||
|
|
||||||
// adjust diffuse by specular reflectance, to maintain energy conservation
|
// adjust diffuse by specular reflectance, to maintain energy conservation
|
||||||
diffuse.rgb *= vec3(1.0) - specular.rgb;
|
diffuse.rgb *= vec3(1.0) - specular.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess);
|
#if defined(GLOSS_IS_GLOSS)
|
||||||
|
float roughness = exp2(-3.0 * gloss);
|
||||||
|
#elif defined(GLOSS_IS_SMOOTHNESS)
|
||||||
|
float roughness = 1.0 - gloss;
|
||||||
|
#elif defined(GLOSS_IS_ROUGHNESS)
|
||||||
|
float roughness = gloss;
|
||||||
|
#elif defined(GLOSS_IS_SHININESS)
|
||||||
|
float roughness = pow(2.0 / (8190.0 * gloss + 2.0), 0.25);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(r_deluxeSpecular) || defined(USE_LIGHT_VECTOR)
|
reflectance = CalcDiffuse(diffuse.rgb, NH, EH, roughness);
|
||||||
float adjGloss = gloss;
|
|
||||||
float adjShininess = shininess;
|
|
||||||
|
|
||||||
#if !defined(USE_LIGHT_VECTOR)
|
#if defined(r_deluxeSpecular)
|
||||||
adjGloss *= r_deluxeSpecular;
|
#if defined(USE_LIGHT_VECTOR)
|
||||||
adjShininess = exp2(adjGloss * 13.0);
|
reflectance += CalcSpecular(specular.rgb, NH, EH, roughness) * r_deluxeSpecular;
|
||||||
#endif
|
|
||||||
|
|
||||||
H = normalize(L + E);
|
|
||||||
|
|
||||||
EH = clamp(dot(E, H), 0.0, 1.0);
|
|
||||||
NH = clamp(dot(N, H), 0.0, 1.0);
|
|
||||||
|
|
||||||
#if !defined(USE_LIGHT_VECTOR)
|
|
||||||
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess) * r_deluxeSpecular;
|
|
||||||
#else
|
#else
|
||||||
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess);
|
reflectance += CalcSpecular(specular.rgb, NH, EH, pow(roughness, r_deluxeSpecular));
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL);
|
gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL);
|
||||||
|
gl_FragColor.rgb += ambientColor * diffuse.rgb;
|
||||||
#if 0
|
|
||||||
vec3 aSpecular = EnvironmentBRDF(gloss, NE, specular.rgb);
|
|
||||||
|
|
||||||
// do ambient as two hemisphere lights, one straight up one straight down
|
|
||||||
float hemiDiffuseUp = N.z * 0.5 + 0.5;
|
|
||||||
float hemiDiffuseDown = 1.0 - hemiDiffuseUp;
|
|
||||||
float hemiSpecularUp = mix(hemiDiffuseUp, float(N.z >= 0.0), gloss);
|
|
||||||
float hemiSpecularDown = 1.0 - hemiSpecularUp;
|
|
||||||
|
|
||||||
gl_FragColor.rgb += ambientColor * 0.75 * (diffuse.rgb * hemiDiffuseUp + aSpecular * hemiSpecularUp);
|
|
||||||
gl_FragColor.rgb += ambientColor * 0.25 * (diffuse.rgb * hemiDiffuseDown + aSpecular * hemiSpecularDown);
|
|
||||||
#else
|
|
||||||
gl_FragColor.rgb += ambientColor * (diffuse.rgb + specular.rgb);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_CUBEMAP)
|
#if defined(USE_CUBEMAP)
|
||||||
reflectance = EnvironmentBRDF(gloss, NE, specular.rgb);
|
reflectance = EnvironmentBRDF(roughness, NE, specular.rgb);
|
||||||
|
|
||||||
vec3 R = reflect(E, N);
|
vec3 R = reflect(E, N);
|
||||||
|
|
||||||
|
@ -531,15 +445,19 @@ void main()
|
||||||
// from http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
// from http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
||||||
vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir;
|
vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir;
|
||||||
|
|
||||||
vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 - gloss * 7.0).rgb * u_EnableTextures.w;
|
#if defined(USE_BOX_CUBEMAP_PARALLAX)
|
||||||
|
vec3 cubeLightColor = hitCube(R * u_CubeMapInfo.w, parallax, u_CubeMapInfo.www, ROUGHNESS_MIPS * roughness, u_CubeMap).rgb * u_EnableTextures.w;
|
||||||
|
#else
|
||||||
|
vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, ROUGHNESS_MIPS * roughness).rgb * u_EnableTextures.w;
|
||||||
|
#endif
|
||||||
|
|
||||||
// normalize cubemap based on lowest mip (~diffuse)
|
// normalize cubemap based on last roughness mip (~diffuse)
|
||||||
// multiplying cubemap values by lighting below depends on either this or the cubemap being normalized at generation
|
// multiplying cubemap values by lighting below depends on either this or the cubemap being normalized at generation
|
||||||
//vec3 cubeLightDiffuse = max(textureCubeLod(u_CubeMap, N, 6.0).rgb, 0.5 / 255.0);
|
//vec3 cubeLightDiffuse = max(textureCubeLod(u_CubeMap, N, ROUGHNESS_MIPS).rgb, 0.5 / 255.0);
|
||||||
//cubeLightColor /= dot(cubeLightDiffuse, vec3(0.2125, 0.7154, 0.0721));
|
//cubeLightColor /= dot(cubeLightDiffuse, vec3(0.2125, 0.7154, 0.0721));
|
||||||
|
|
||||||
#if defined(r_framebufferGamma)
|
#if defined(USE_PBR)
|
||||||
cubeLightColor = pow(cubeLightColor, vec3(r_framebufferGamma));
|
cubeLightColor *= cubeLightColor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// multiply cubemap values by lighting
|
// multiply cubemap values by lighting
|
||||||
|
@ -549,7 +467,7 @@ void main()
|
||||||
gl_FragColor.rgb += cubeLightColor * reflectance;
|
gl_FragColor.rgb += cubeLightColor * reflectance;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_PRIMARY_LIGHT)
|
#if defined(USE_PRIMARY_LIGHT) || defined(SHADOWMAP_MODULATE)
|
||||||
vec3 L2, H2;
|
vec3 L2, H2;
|
||||||
float NL2, EH2, NH2;
|
float NL2, EH2, NH2;
|
||||||
|
|
||||||
|
@ -560,20 +478,19 @@ void main()
|
||||||
//L2 /= sqrt(sqrLightDist);
|
//L2 /= sqrt(sqrLightDist);
|
||||||
|
|
||||||
NL2 = clamp(dot(N, L2), 0.0, 1.0);
|
NL2 = clamp(dot(N, L2), 0.0, 1.0);
|
||||||
|
|
||||||
H2 = normalize(L2 + E);
|
H2 = normalize(L2 + E);
|
||||||
EH2 = clamp(dot(E, H2), 0.0, 1.0);
|
EH2 = clamp(dot(E, H2), 0.0, 1.0);
|
||||||
NH2 = clamp(dot(N, H2), 0.0, 1.0);
|
NH2 = clamp(dot(N, H2), 0.0, 1.0);
|
||||||
|
|
||||||
reflectance = CalcDiffuse(diffuse.rgb, N, L2, E, NE, NL2, shininess);
|
reflectance = CalcSpecular(specular.rgb, NH2, EH2, roughness);
|
||||||
reflectance += CalcSpecular(specular.rgb, NH2, NL2, NE, EH2, gloss, shininess);
|
|
||||||
|
|
||||||
lightColor = u_PrimaryLightColor * var_Color.rgb;
|
// bit of a hack, with modulated shadowmaps, ignore diffuse
|
||||||
|
#if !defined(SHADOWMAP_MODULATE)
|
||||||
#if defined(r_lightGamma)
|
reflectance += CalcDiffuse(diffuse.rgb, NH2, EH2, roughness);
|
||||||
lightColor = pow(lightColor, vec3(r_lightGamma));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
lightColor = u_PrimaryLightColor;
|
||||||
|
|
||||||
#if defined(USE_SHADOWMAP)
|
#if defined(USE_SHADOWMAP)
|
||||||
lightColor *= shadowValue;
|
lightColor *= shadowValue;
|
||||||
#endif
|
#endif
|
||||||
|
@ -581,30 +498,24 @@ void main()
|
||||||
// enable when point lights are supported as primary lights
|
// enable when point lights are supported as primary lights
|
||||||
//lightColor *= CalcLightAttenuation(float(u_PrimaryLightDir.w > 0.0), u_PrimaryLightDir.w / sqrLightDist);
|
//lightColor *= CalcLightAttenuation(float(u_PrimaryLightDir.w > 0.0), u_PrimaryLightDir.w / sqrLightDist);
|
||||||
|
|
||||||
|
#if defined(USE_PARALLAXMAP) && defined(USE_PARALLAXMAP_SHADOWS)
|
||||||
|
offsetDir = L2 * tangentToWorld;
|
||||||
|
offsetDir.xy *= u_NormalScale.a / offsetDir.z;
|
||||||
|
lightColor *= LightRay(texCoords, offsetDir.xy, u_NormalMap);
|
||||||
|
#endif
|
||||||
|
|
||||||
gl_FragColor.rgb += lightColor * reflectance * NL2;
|
gl_FragColor.rgb += lightColor * reflectance * NL2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_PBR)
|
||||||
|
gl_FragColor.rgb = sqrt(gl_FragColor.rgb);
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
lightColor = var_Color.rgb;
|
|
||||||
|
|
||||||
#if defined(USE_LIGHTMAP)
|
|
||||||
lightColor *= lightmapColor.rgb;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(r_lightGamma)
|
|
||||||
lightColor = pow(lightColor, vec3(r_lightGamma));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(r_materialGamma)
|
|
||||||
diffuse.rgb = pow(diffuse.rgb, vec3(r_materialGamma));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gl_FragColor.rgb = diffuse.rgb * lightColor;
|
gl_FragColor.rgb = diffuse.rgb * lightColor;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(r_framebufferGamma)
|
gl_FragColor.a = alpha;
|
||||||
gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / r_framebufferGamma));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gl_FragColor.a = diffuse.a * var_Color.a;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,15 @@ attribute vec4 attr_Color;
|
||||||
|
|
||||||
attribute vec3 attr_Position;
|
attribute vec3 attr_Position;
|
||||||
attribute vec3 attr_Normal;
|
attribute vec3 attr_Normal;
|
||||||
#if defined(USE_VERT_TANGENT_SPACE)
|
|
||||||
attribute vec4 attr_Tangent;
|
attribute vec4 attr_Tangent;
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
attribute vec3 attr_Position2;
|
attribute vec3 attr_Position2;
|
||||||
attribute vec3 attr_Normal2;
|
attribute vec3 attr_Normal2;
|
||||||
#if defined(USE_VERT_TANGENT_SPACE)
|
|
||||||
attribute vec4 attr_Tangent2;
|
attribute vec4 attr_Tangent2;
|
||||||
#endif
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
attribute vec4 attr_BoneIndexes;
|
||||||
|
attribute vec4 attr_BoneWeights;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_LIGHT) && !defined(USE_LIGHT_VECTOR)
|
#if defined(USE_LIGHT) && !defined(USE_LIGHT_VECTOR)
|
||||||
|
@ -52,15 +51,15 @@ uniform mat4 u_ModelMatrix;
|
||||||
|
|
||||||
#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
uniform float u_VertexLerp;
|
uniform float u_VertexLerp;
|
||||||
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
uniform mat4 u_BoneMatrix[MAX_GLSL_BONES];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_LIGHT_VECTOR)
|
#if defined(USE_LIGHT_VECTOR)
|
||||||
uniform vec4 u_LightOrigin;
|
uniform vec4 u_LightOrigin;
|
||||||
uniform float u_LightRadius;
|
uniform float u_LightRadius;
|
||||||
#if defined(USE_FAST_LIGHT)
|
|
||||||
uniform vec3 u_DirectedLight;
|
uniform vec3 u_DirectedLight;
|
||||||
uniform vec3 u_AmbientLight;
|
uniform vec3 u_AmbientLight;
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
||||||
|
@ -71,16 +70,14 @@ uniform float u_PrimaryLightRadius;
|
||||||
varying vec4 var_TexCoords;
|
varying vec4 var_TexCoords;
|
||||||
|
|
||||||
varying vec4 var_Color;
|
varying vec4 var_Color;
|
||||||
|
#if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
|
||||||
|
varying vec4 var_ColorAmbient;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
#if defined(USE_VERT_TANGENT_SPACE)
|
|
||||||
varying vec4 var_Normal;
|
varying vec4 var_Normal;
|
||||||
varying vec4 var_Tangent;
|
varying vec4 var_Tangent;
|
||||||
varying vec4 var_Bitangent;
|
varying vec4 var_Bitangent;
|
||||||
#else
|
|
||||||
varying vec3 var_Normal;
|
|
||||||
varying vec3 var_ViewDir;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
|
@ -156,13 +153,25 @@ void main()
|
||||||
#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
|
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
|
||||||
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
|
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
|
||||||
#if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
vec3 tangent = mix(attr_Tangent.xyz, attr_Tangent2.xyz, u_VertexLerp);
|
vec3 tangent = mix(attr_Tangent.xyz, attr_Tangent2.xyz, u_VertexLerp);
|
||||||
#endif
|
#endif
|
||||||
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
mat4 vtxMat = u_BoneMatrix[int(attr_BoneIndexes.x)] * attr_BoneWeights.x;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.y)] * attr_BoneWeights.y;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.z)] * attr_BoneWeights.z;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.w)] * attr_BoneWeights.w;
|
||||||
|
mat3 nrmMat = mat3(cross(vtxMat[1].xyz, vtxMat[2].xyz), cross(vtxMat[2].xyz, vtxMat[0].xyz), cross(vtxMat[0].xyz, vtxMat[1].xyz));
|
||||||
|
|
||||||
|
vec3 position = vec3(vtxMat * vec4(attr_Position, 1.0));
|
||||||
|
vec3 normal = normalize(nrmMat * attr_Normal);
|
||||||
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
|
vec3 tangent = normalize(nrmMat * attr_Tangent.xyz);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
vec3 position = attr_Position;
|
vec3 position = attr_Position;
|
||||||
vec3 normal = attr_Normal;
|
vec3 normal = attr_Normal;
|
||||||
#if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
vec3 tangent = attr_Tangent.xyz;
|
vec3 tangent = attr_Tangent.xyz;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -184,12 +193,12 @@ void main()
|
||||||
#if defined(USE_MODELMATRIX)
|
#if defined(USE_MODELMATRIX)
|
||||||
position = (u_ModelMatrix * vec4(position, 1.0)).xyz;
|
position = (u_ModelMatrix * vec4(position, 1.0)).xyz;
|
||||||
normal = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
|
normal = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
|
||||||
#if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
tangent = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;
|
tangent = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
vec3 bitangent = cross(normal, tangent) * attr_Tangent.w;
|
vec3 bitangent = cross(normal, tangent) * attr_Tangent.w;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -208,12 +217,24 @@ void main()
|
||||||
|
|
||||||
var_Color = u_VertColor * attr_Color + u_BaseColor;
|
var_Color = u_VertColor * attr_Color + u_BaseColor;
|
||||||
|
|
||||||
#if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT_VECTOR)
|
||||||
|
#if defined(USE_FAST_LIGHT)
|
||||||
float sqrLightDist = dot(L, L);
|
float sqrLightDist = dot(L, L);
|
||||||
float attenuation = CalcLightAttenuation(u_LightOrigin.w, u_LightRadius * u_LightRadius / sqrLightDist);
|
|
||||||
float NL = clamp(dot(normalize(normal), L) / sqrt(sqrLightDist), 0.0, 1.0);
|
float NL = clamp(dot(normalize(normal), L) / sqrt(sqrLightDist), 0.0, 1.0);
|
||||||
|
float attenuation = CalcLightAttenuation(u_LightOrigin.w, u_LightRadius * u_LightRadius / sqrLightDist);
|
||||||
|
|
||||||
var_Color.rgb *= u_DirectedLight * (attenuation * NL) + u_AmbientLight;
|
var_Color.rgb *= u_DirectedLight * (attenuation * NL) + u_AmbientLight;
|
||||||
|
#else
|
||||||
|
var_ColorAmbient.rgb = u_AmbientLight * var_Color.rgb;
|
||||||
|
var_Color.rgb *= u_DirectedLight;
|
||||||
|
#if defined(USE_PBR)
|
||||||
|
var_ColorAmbient.rgb *= var_ColorAmbient.rgb;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) && defined(USE_PBR)
|
||||||
|
var_Color.rgb *= var_Color.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
||||||
|
@ -234,14 +255,9 @@ void main()
|
||||||
|
|
||||||
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
vec3 viewDir = u_ViewOrigin - position;
|
vec3 viewDir = u_ViewOrigin - position;
|
||||||
#if defined(USE_VERT_TANGENT_SPACE)
|
|
||||||
// store view direction in tangent space to save on varyings
|
// store view direction in tangent space to save on varyings
|
||||||
var_Normal = vec4(normal, viewDir.x);
|
var_Normal = vec4(normal, viewDir.x);
|
||||||
var_Tangent = vec4(tangent, viewDir.y);
|
var_Tangent = vec4(tangent, viewDir.y);
|
||||||
var_Bitangent = vec4(bitangent, viewDir.z);
|
var_Bitangent = vec4(bitangent, viewDir.z);
|
||||||
#else
|
|
||||||
var_Normal = normal;
|
|
||||||
var_ViewDir = viewDir;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,6 @@ uniform float u_LightRadius;
|
||||||
varying vec3 var_Position;
|
varying vec3 var_Position;
|
||||||
varying vec3 var_Normal;
|
varying vec3 var_Normal;
|
||||||
|
|
||||||
float sampleDistMap(sampler2D texMap, vec2 uv, float scale)
|
|
||||||
{
|
|
||||||
vec3 distv = texture2D(texMap, uv).xyz;
|
|
||||||
return dot(distv, vec3(1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0)) * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 lightToPos = var_Position - u_LightOrigin.xyz;
|
vec3 lightToPos = var_Position - u_LightOrigin.xyz;
|
||||||
|
@ -57,42 +51,28 @@ void main()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
intensity *= fade;
|
intensity *= fade;
|
||||||
#if defined(USE_PCF)
|
|
||||||
float part;
|
float part;
|
||||||
|
#if defined(USE_PCF)
|
||||||
dist = sampleDistMap(u_ShadowMap, st + vec2(-1.0/512.0, -1.0/512.0), u_LightRadius);
|
part = float(texture2D(u_ShadowMap, st + vec2(-1.0/512.0, -1.0/512.0)).r != 1.0);
|
||||||
part = max(sign(lightDist - dist), 0.0);
|
part += float(texture2D(u_ShadowMap, st + vec2( 1.0/512.0, -1.0/512.0)).r != 1.0);
|
||||||
|
part += float(texture2D(u_ShadowMap, st + vec2(-1.0/512.0, 1.0/512.0)).r != 1.0);
|
||||||
|
part += float(texture2D(u_ShadowMap, st + vec2( 1.0/512.0, 1.0/512.0)).r != 1.0);
|
||||||
|
#else
|
||||||
|
part = float(texture2D(u_ShadowMap, st).r != 1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
dist = sampleDistMap(u_ShadowMap, st + vec2( 1.0/512.0, -1.0/512.0), u_LightRadius);
|
|
||||||
part += max(sign(lightDist - dist), 0.0);
|
|
||||||
|
|
||||||
dist = sampleDistMap(u_ShadowMap, st + vec2(-1.0/512.0, 1.0/512.0), u_LightRadius);
|
|
||||||
part += max(sign(lightDist - dist), 0.0);
|
|
||||||
|
|
||||||
dist = sampleDistMap(u_ShadowMap, st + vec2( 1.0/512.0, 1.0/512.0), u_LightRadius);
|
|
||||||
part += max(sign(lightDist - dist), 0.0);
|
|
||||||
|
|
||||||
#if defined(USE_DISCARD)
|
|
||||||
if (part <= 0.0)
|
if (part <= 0.0)
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#if defined(USE_PCF)
|
||||||
intensity *= part * 0.25;
|
intensity *= part * 0.25;
|
||||||
#else
|
#else
|
||||||
dist = sampleDistMap(u_ShadowMap, st, u_LightRadius);
|
intensity *= part;
|
||||||
|
|
||||||
#if defined(USE_DISCARD)
|
|
||||||
if (lightDist - dist <= 0.0)
|
|
||||||
{
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
intensity *= max(sign(lightDist - dist), 0.0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gl_FragColor.rgb = vec3(0);
|
gl_FragColor.rgb = vec3(0);
|
||||||
gl_FragColor.a = clamp(intensity, 0.0, 0.75);
|
gl_FragColor.a = clamp(intensity, 0.0, 0.75);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,13 @@ attribute vec3 attr_Position;
|
||||||
attribute vec3 attr_Normal;
|
attribute vec3 attr_Normal;
|
||||||
attribute vec4 attr_TexCoord0;
|
attribute vec4 attr_TexCoord0;
|
||||||
|
|
||||||
//#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
attribute vec3 attr_Position2;
|
attribute vec3 attr_Position2;
|
||||||
attribute vec3 attr_Normal2;
|
attribute vec3 attr_Normal2;
|
||||||
//#endif
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
attribute vec4 attr_BoneIndexes;
|
||||||
|
attribute vec4 attr_BoneWeights;
|
||||||
|
#endif
|
||||||
|
|
||||||
//#if defined(USE_DEFORM_VERTEXES)
|
//#if defined(USE_DEFORM_VERTEXES)
|
||||||
uniform int u_DeformGen;
|
uniform int u_DeformGen;
|
||||||
|
@ -17,9 +20,11 @@ uniform mat4 u_ModelViewProjectionMatrix;
|
||||||
|
|
||||||
uniform mat4 u_ModelMatrix;
|
uniform mat4 u_ModelMatrix;
|
||||||
|
|
||||||
//#if defined(USE_VERTEX_ANIMATION)
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
uniform float u_VertexLerp;
|
uniform float u_VertexLerp;
|
||||||
//#endif
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
uniform mat4 u_BoneMatrix[MAX_GLSL_BONES];
|
||||||
|
#endif
|
||||||
|
|
||||||
varying vec3 var_Position;
|
varying vec3 var_Position;
|
||||||
|
|
||||||
|
@ -78,8 +83,22 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
#if defined(USE_VERTEX_ANIMATION)
|
||||||
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
|
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
|
||||||
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
|
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
|
||||||
|
#elif defined(USE_BONE_ANIMATION)
|
||||||
|
mat4 vtxMat = u_BoneMatrix[int(attr_BoneIndexes.x)] * attr_BoneWeights.x;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.y)] * attr_BoneWeights.y;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.z)] * attr_BoneWeights.z;
|
||||||
|
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.w)] * attr_BoneWeights.w;
|
||||||
|
mat3 nrmMat = mat3(cross(vtxMat[1].xyz, vtxMat[2].xyz), cross(vtxMat[2].xyz, vtxMat[0].xyz), cross(vtxMat[0].xyz, vtxMat[1].xyz));
|
||||||
|
|
||||||
|
vec3 position = vec3(vtxMat * vec4(attr_Position, 1.0));
|
||||||
|
vec3 normal = normalize(nrmMat * attr_Normal);
|
||||||
|
#else
|
||||||
|
vec3 position = attr_Position;
|
||||||
|
vec3 normal = attr_Normal;
|
||||||
|
#endif
|
||||||
|
|
||||||
position = DeformPosition(position, normal, attr_TexCoord0.st);
|
position = DeformPosition(position, normal, attr_TexCoord0.st);
|
||||||
|
|
||||||
|
|
|
@ -52,10 +52,10 @@ float PCF(const sampler2DShadow shadowmap, const vec2 st, const float dist)
|
||||||
offset.y += offset.x;
|
offset.y += offset.x;
|
||||||
if (offset.y > 1.1) offset.y = 0.0;
|
if (offset.y > 1.1) offset.y = 0.0;
|
||||||
|
|
||||||
mult = shadow2D(shadowmap, vec3(st + (offset + vec2(-1.5, 0.5)) * scale, dist)).r
|
mult = shadow2D(shadowmap, vec3(st + (offset + vec2(-1.5, 0.5)) * scale, dist))
|
||||||
+ shadow2D(shadowmap, vec3(st + (offset + vec2( 0.5, 0.5)) * scale, dist)).r
|
+ shadow2D(shadowmap, vec3(st + (offset + vec2( 0.5, 0.5)) * scale, dist))
|
||||||
+ shadow2D(shadowmap, vec3(st + (offset + vec2(-1.5, -1.5)) * scale, dist)).r
|
+ shadow2D(shadowmap, vec3(st + (offset + vec2(-1.5, -1.5)) * scale, dist))
|
||||||
+ shadow2D(shadowmap, vec3(st + (offset + vec2( 0.5, -1.5)) * scale, dist)).r;
|
+ shadow2D(shadowmap, vec3(st + (offset + vec2( 0.5, -1.5)) * scale, dist));
|
||||||
|
|
||||||
mult *= 0.25;
|
mult *= 0.25;
|
||||||
#endif
|
#endif
|
||||||
|
@ -66,23 +66,23 @@ float PCF(const sampler2DShadow shadowmap, const vec2 st, const float dist)
|
||||||
float cosr = cos(r) * scale;
|
float cosr = cos(r) * scale;
|
||||||
mat2 rmat = mat2(cosr, sinr, -sinr, cosr);
|
mat2 rmat = mat2(cosr, sinr, -sinr, cosr);
|
||||||
|
|
||||||
mult = shadow2D(shadowmap, vec3(st + rmat * vec2(-0.7055767, 0.196515), dist)).r;
|
mult = shadow2D(shadowmap, vec3(st + rmat * vec2(-0.7055767, 0.196515), dist));
|
||||||
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.3524343, -0.7791386), dist)).r;
|
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.3524343, -0.7791386), dist));
|
||||||
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.2391056, 0.9189604), dist)).r;
|
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.2391056, 0.9189604), dist));
|
||||||
#if defined(USE_SHADOW_FILTER2)
|
#if defined(USE_SHADOW_FILTER2)
|
||||||
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.07580382, -0.09224417), dist)).r;
|
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.07580382, -0.09224417), dist));
|
||||||
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.5784913, -0.002528916), dist)).r;
|
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.5784913, -0.002528916), dist));
|
||||||
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.192888, 0.4064181), dist)).r;
|
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.192888, 0.4064181), dist));
|
||||||
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.6335801, -0.5247476), dist)).r;
|
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.6335801, -0.5247476), dist));
|
||||||
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.5579782, 0.7491854), dist)).r;
|
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.5579782, 0.7491854), dist));
|
||||||
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.7320465, 0.6317794), dist)).r;
|
mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.7320465, 0.6317794), dist));
|
||||||
|
|
||||||
mult *= 0.11111;
|
mult *= 0.11111;
|
||||||
#else
|
#else
|
||||||
mult *= 0.33333;
|
mult *= 0.33333;
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
mult = shadow2D(shadowmap, vec3(st, dist)).r;
|
mult = shadow2D(shadowmap, vec3(st, dist));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return mult;
|
return mult;
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
uniform sampler2D u_ScreenDepthMap;
|
uniform sampler2D u_ScreenDepthMap;
|
||||||
|
|
||||||
uniform vec4 u_ViewInfo; // zfar / znear, zfar
|
uniform vec4 u_ViewInfo; // zfar / znear, zfar, 1/width, 1/height
|
||||||
|
|
||||||
varying vec2 var_ScreenTex;
|
varying vec2 var_ScreenTex;
|
||||||
|
|
||||||
|
#if 0
|
||||||
vec2 poissonDisc[9] = vec2[9](
|
vec2 poissonDisc[9] = vec2[9](
|
||||||
vec2(-0.7055767, 0.196515), vec2(0.3524343, -0.7791386),
|
vec2(-0.7055767, 0.196515), vec2(0.3524343, -0.7791386),
|
||||||
vec2(0.2391056, 0.9189604), vec2(-0.07580382, -0.09224417),
|
vec2(0.2391056, 0.9189604), vec2(-0.07580382, -0.09224417),
|
||||||
|
@ -11,6 +12,9 @@ vec2(0.5784913, -0.002528916), vec2(0.192888, 0.4064181),
|
||||||
vec2(-0.6335801, -0.5247476), vec2(-0.5579782, 0.7491854),
|
vec2(-0.6335801, -0.5247476), vec2(-0.5579782, 0.7491854),
|
||||||
vec2(0.7320465, 0.6317794)
|
vec2(0.7320465, 0.6317794)
|
||||||
);
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NUM_SAMPLES 3
|
||||||
|
|
||||||
// Input: It uses texture coords as the random number seed.
|
// Input: It uses texture coords as the random number seed.
|
||||||
// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive.
|
// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive.
|
||||||
|
@ -39,48 +43,59 @@ mat2 randomRotation( const vec2 p )
|
||||||
|
|
||||||
float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear)
|
float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear)
|
||||||
{
|
{
|
||||||
float sampleZDivW = texture2D(depthMap, tex).r;
|
float sampleZDivW = texture2D(depthMap, tex).r;
|
||||||
return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
|
return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
|
||||||
}
|
}
|
||||||
|
|
||||||
float ambientOcclusion(sampler2D depthMap, const vec2 tex, const float zFarDivZNear, const float zFar)
|
float ambientOcclusion(sampler2D depthMap, const vec2 tex, const float zFarDivZNear, const float zFar, const vec2 scale)
|
||||||
{
|
{
|
||||||
float result = 0;
|
vec2 poissonDisc[9];
|
||||||
|
|
||||||
float sampleZ = zFar * getLinearDepth(depthMap, tex, zFarDivZNear);
|
poissonDisc[0] = vec2(-0.7055767, 0.196515);
|
||||||
|
poissonDisc[1] = vec2(0.3524343, -0.7791386);
|
||||||
|
poissonDisc[2] = vec2(0.2391056, 0.9189604);
|
||||||
|
poissonDisc[3] = vec2(-0.07580382, -0.09224417);
|
||||||
|
poissonDisc[4] = vec2(0.5784913, -0.002528916);
|
||||||
|
poissonDisc[5] = vec2(0.192888, 0.4064181);
|
||||||
|
poissonDisc[6] = vec2(-0.6335801, -0.5247476);
|
||||||
|
poissonDisc[7] = vec2(-0.5579782, 0.7491854);
|
||||||
|
poissonDisc[8] = vec2(0.7320465, 0.6317794);
|
||||||
|
|
||||||
vec2 expectedSlope = vec2(dFdx(sampleZ), dFdy(sampleZ)) / vec2(dFdx(tex.x), dFdy(tex.y));
|
float result = 0.0;
|
||||||
|
|
||||||
if (length(expectedSlope) > 5000.0)
|
float sampleZ = getLinearDepth(depthMap, tex, zFarDivZNear);
|
||||||
|
float scaleZ = zFarDivZNear * sampleZ;
|
||||||
|
|
||||||
|
vec2 slope = vec2(dFdx(sampleZ), dFdy(sampleZ)) / vec2(dFdx(tex.x), dFdy(tex.y));
|
||||||
|
|
||||||
|
if (length(slope) * zFar > 5000.0)
|
||||||
return 1.0;
|
return 1.0;
|
||||||
|
|
||||||
vec2 offsetScale = vec2(3.0 / sampleZ);
|
vec2 offsetScale = vec2(scale * 1024.0 / scaleZ);
|
||||||
|
|
||||||
mat2 rmat = randomRotation(tex);
|
mat2 rmat = randomRotation(tex);
|
||||||
|
|
||||||
|
float invZFar = 1.0 / zFar;
|
||||||
|
float zLimit = 20.0 * invZFar;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < NUM_SAMPLES; i++)
|
||||||
{
|
{
|
||||||
vec2 offset = rmat * poissonDisc[i] * offsetScale;
|
vec2 offset = rmat * poissonDisc[i] * offsetScale;
|
||||||
float sampleZ2 = zFar * getLinearDepth(depthMap, tex + offset, zFarDivZNear);
|
float sampleDiff = getLinearDepth(depthMap, tex + offset, zFarDivZNear) - sampleZ;
|
||||||
|
|
||||||
if (abs(sampleZ - sampleZ2) > 20.0)
|
bool s1 = abs(sampleDiff) > zLimit;
|
||||||
result += 1.0;
|
bool s2 = sampleDiff + invZFar > dot(slope, offset);
|
||||||
else
|
result += float(s1 || s2);
|
||||||
{
|
|
||||||
float expectedZ = sampleZ + dot(expectedSlope, offset);
|
|
||||||
result += step(expectedZ - 1.0, sampleZ2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result *= 0.33333;
|
result *= 1.0 / float(NUM_SAMPLES);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
float result = ambientOcclusion(u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y);
|
float result = ambientOcclusion(u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y, u_ViewInfo.wz);
|
||||||
|
|
||||||
gl_FragColor = vec4(vec3(result), 1.0);
|
gl_FragColor = vec4(vec3(result), 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,8 @@ void main()
|
||||||
{
|
{
|
||||||
vec4 color = texture2D(u_TextureMap, var_TexCoords) * u_Color;
|
vec4 color = texture2D(u_TextureMap, var_TexCoords) * u_Color;
|
||||||
|
|
||||||
#if defined(r_framebufferGamma)
|
#if defined(USE_PBR)
|
||||||
color.rgb = pow(color.rgb, vec3(r_framebufferGamma));
|
color.rgb *= color.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec3 minAvgMax = texture2D(u_LevelsMap, var_TexCoords).rgb;
|
vec3 minAvgMax = texture2D(u_LevelsMap, var_TexCoords).rgb;
|
||||||
|
@ -46,9 +46,12 @@ void main()
|
||||||
|
|
||||||
color.rgb = clamp(color.rgb * var_InvWhite, 0.0, 1.0);
|
color.rgb = clamp(color.rgb * var_InvWhite, 0.0, 1.0);
|
||||||
|
|
||||||
#if defined(r_tonemapGamma)
|
#if defined(USE_PBR)
|
||||||
color.rgb = pow(color.rgb, vec3(1.0 / r_tonemapGamma));
|
color.rgb = sqrt(color.rgb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// add a bit of dither to reduce banding
|
||||||
|
color.rgb += vec3(1.0/510.0 * mod(gl_FragCoord.x + gl_FragCoord.y, 2.0) - 1.0/1020.0);
|
||||||
|
|
||||||
gl_FragColor = color;
|
gl_FragColor = color;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -21,17 +21,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
static backEndCounters_t pc_save;
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
R_PerformanceCounters
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void R_SavePerformanceCounters( void ) {
|
|
||||||
memcpy( &pc_save, &backEnd.pc, sizeof( pc_save ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=====================
|
=====================
|
||||||
R_PerformanceCounters
|
R_PerformanceCounters
|
||||||
|
@ -77,8 +66,8 @@ void R_PerformanceCounters( void ) {
|
||||||
}
|
}
|
||||||
else if (r_speeds->integer == 7 )
|
else if (r_speeds->integer == 7 )
|
||||||
{
|
{
|
||||||
ri.Printf( PRINT_ALL, "VAO draws: static %i dynamic %i\nMultidraws: %i merged %i\n",
|
ri.Printf( PRINT_ALL, "VAO draws: static %i dynamic %i\n",
|
||||||
backEnd.pc.c_staticVaoDraws, backEnd.pc.c_dynamicVaoDraws, backEnd.pc.c_multidraws, backEnd.pc.c_multidrawsMerged );
|
backEnd.pc.c_staticVaoDraws, backEnd.pc.c_dynamicVaoDraws);
|
||||||
ri.Printf( PRINT_ALL, "GLSL binds: %i draws: gen %i light %i fog %i dlight %i\n",
|
ri.Printf( PRINT_ALL, "GLSL binds: %i draws: gen %i light %i fog %i dlight %i\n",
|
||||||
backEnd.pc.c_glslShaderBinds, backEnd.pc.c_genericDraws, backEnd.pc.c_lightallDraws, backEnd.pc.c_fogDraws, backEnd.pc.c_dlightDraws);
|
backEnd.pc.c_glslShaderBinds, backEnd.pc.c_genericDraws, backEnd.pc.c_lightallDraws, backEnd.pc.c_fogDraws, backEnd.pc.c_dlightDraws);
|
||||||
}
|
}
|
||||||
|
@ -214,11 +203,11 @@ void R_AddCapShadowmapCmd( int map, int cubeSide ) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
R_PostProcessingCmd
|
R_AddPostProcessCmd
|
||||||
|
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
void R_AddPostProcessCmd( ) {
|
void R_AddPostProcessCmd( void ) {
|
||||||
postProcessCommand_t *cmd;
|
postProcessCommand_t *cmd;
|
||||||
|
|
||||||
cmd = R_GetCommandBuffer( sizeof( *cmd ) );
|
cmd = R_GetCommandBuffer( sizeof( *cmd ) );
|
||||||
|
@ -353,7 +342,6 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
|
||||||
|
|
||||||
tr.frameCount++;
|
tr.frameCount++;
|
||||||
tr.frameSceneNum = 0;
|
tr.frameSceneNum = 0;
|
||||||
g_nStaticSurfaces = 0;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// do overdraw measurement
|
// do overdraw measurement
|
||||||
|
|
|
@ -54,10 +54,10 @@ static void LerpDrawVert( srfVert_t *a, srfVert_t *b, srfVert_t *out ) {
|
||||||
out->lightmap[0] = 0.5f * (a->lightmap[0] + b->lightmap[0]);
|
out->lightmap[0] = 0.5f * (a->lightmap[0] + b->lightmap[0]);
|
||||||
out->lightmap[1] = 0.5f * (a->lightmap[1] + b->lightmap[1]);
|
out->lightmap[1] = 0.5f * (a->lightmap[1] + b->lightmap[1]);
|
||||||
|
|
||||||
out->vertexColors[0] = 0.5f * (a->vertexColors[0] + b->vertexColors[0]);
|
out->color[0] = ((int)a->color[0] + (int)b->color[0]) >> 1;
|
||||||
out->vertexColors[1] = 0.5f * (a->vertexColors[1] + b->vertexColors[1]);
|
out->color[1] = ((int)a->color[1] + (int)b->color[1]) >> 1;
|
||||||
out->vertexColors[2] = 0.5f * (a->vertexColors[2] + b->vertexColors[2]);
|
out->color[2] = ((int)a->color[2] + (int)b->color[2]) >> 1;
|
||||||
out->vertexColors[3] = 0.5f * (a->vertexColors[3] + b->vertexColors[3]);
|
out->color[3] = ((int)a->color[3] + (int)b->color[3]) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -182,7 +182,7 @@ static int neighbors[8][2] = {
|
||||||
break; // edge of patch
|
break; // edge of patch
|
||||||
}
|
}
|
||||||
VectorSubtract( ctrl[y][x].xyz, base, temp );
|
VectorSubtract( ctrl[y][x].xyz, base, temp );
|
||||||
if ( VectorNormalize2( temp, temp ) == 0 ) {
|
if ( VectorNormalize( temp ) < 0.001f ) {
|
||||||
continue; // degenerate edge, get more dist
|
continue; // degenerate edge, get more dist
|
||||||
} else {
|
} else {
|
||||||
good[k] = qtrue;
|
good[k] = qtrue;
|
||||||
|
@ -198,7 +198,7 @@ static int neighbors[8][2] = {
|
||||||
continue; // didn't get two points
|
continue; // didn't get two points
|
||||||
}
|
}
|
||||||
CrossProduct( around[(k+1)&7], around[k], normal );
|
CrossProduct( around[(k+1)&7], around[k], normal );
|
||||||
if ( VectorNormalize2( normal, normal ) == 0 ) {
|
if ( VectorNormalize( normal ) < 0.001f ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
VectorAdd( normal, sum, sum );
|
VectorAdd( normal, sum, sum );
|
||||||
|
@ -207,12 +207,15 @@ static int neighbors[8][2] = {
|
||||||
//if ( count == 0 ) {
|
//if ( count == 0 ) {
|
||||||
// printf("bad normal\n");
|
// printf("bad normal\n");
|
||||||
//}
|
//}
|
||||||
VectorNormalize2( sum, dv->normal );
|
{
|
||||||
|
vec3_t fNormal;
|
||||||
|
VectorNormalize2(sum, fNormal);
|
||||||
|
R_VaoPackNormal(dv->normal, fNormal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int numIndexes,
|
static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int numIndexes,
|
||||||
glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3])
|
glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3])
|
||||||
{
|
{
|
||||||
|
@ -251,17 +254,13 @@ static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static int MakeMeshIndexes(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
|
static int MakeMeshIndexes(int width, int height, glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3])
|
||||||
glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3])
|
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
int numIndexes;
|
int numIndexes;
|
||||||
int w, h;
|
int w, h;
|
||||||
srfVert_t *dv;
|
|
||||||
static srfVert_t ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
|
|
||||||
|
|
||||||
h = height - 1;
|
h = height - 1;
|
||||||
w = width - 1;
|
w = width - 1;
|
||||||
|
@ -288,16 +287,6 @@ static int MakeMeshIndexes(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: use more elegant way
|
|
||||||
for(i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for(j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
dv = &ctrl2[j * width + i];
|
|
||||||
*dv = ctrl[j][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return numIndexes;
|
return numIndexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,21 +364,17 @@ static void PutPointsOnCurve( srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
|
||||||
R_CreateSurfaceGridMesh
|
R_CreateSurfaceGridMesh
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
srfBspSurface_t *R_CreateSurfaceGridMesh(int width, int height,
|
void R_CreateSurfaceGridMesh(srfBspSurface_t *grid, int width, int height,
|
||||||
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE],
|
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE],
|
||||||
int numIndexes, glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3]) {
|
int numIndexes, glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3]) {
|
||||||
int i, j, size;
|
int i, j;
|
||||||
srfVert_t *vert;
|
srfVert_t *vert;
|
||||||
vec3_t tmpVec;
|
vec3_t tmpVec;
|
||||||
srfBspSurface_t *grid;
|
|
||||||
|
|
||||||
// copy the results out to a grid
|
// copy the results out to a grid
|
||||||
size = (width * height - 1) * sizeof( srfVert_t ) + sizeof( *grid );
|
Com_Memset(grid, 0, sizeof(*grid));
|
||||||
|
|
||||||
#ifdef PATCH_STITCHING
|
#ifdef PATCH_STITCHING
|
||||||
grid = /*ri.Hunk_Alloc*/ ri.Malloc( size );
|
|
||||||
Com_Memset(grid, 0, size);
|
|
||||||
|
|
||||||
grid->widthLodError = /*ri.Hunk_Alloc*/ ri.Malloc( width * 4 );
|
grid->widthLodError = /*ri.Hunk_Alloc*/ ri.Malloc( width * 4 );
|
||||||
Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
|
Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
|
||||||
|
|
||||||
|
@ -403,9 +388,6 @@ srfBspSurface_t *R_CreateSurfaceGridMesh(int width, int height,
|
||||||
grid->numVerts = (width * height);
|
grid->numVerts = (width * height);
|
||||||
grid->verts = ri.Malloc(grid->numVerts * sizeof(srfVert_t));
|
grid->verts = ri.Malloc(grid->numVerts * sizeof(srfVert_t));
|
||||||
#else
|
#else
|
||||||
grid = ri.Hunk_Alloc( size );
|
|
||||||
Com_Memset(grid, 0, size);
|
|
||||||
|
|
||||||
grid->widthLodError = ri.Hunk_Alloc( width * 4 );
|
grid->widthLodError = ri.Hunk_Alloc( width * 4 );
|
||||||
Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
|
Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
|
||||||
|
|
||||||
|
@ -441,7 +423,6 @@ srfBspSurface_t *R_CreateSurfaceGridMesh(int width, int height,
|
||||||
VectorCopy( grid->cullOrigin, grid->lodOrigin );
|
VectorCopy( grid->cullOrigin, grid->lodOrigin );
|
||||||
grid->lodRadius = grid->cullRadius;
|
grid->lodRadius = grid->cullRadius;
|
||||||
//
|
//
|
||||||
return grid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -449,12 +430,11 @@ srfBspSurface_t *R_CreateSurfaceGridMesh(int width, int height,
|
||||||
R_FreeSurfaceGridMesh
|
R_FreeSurfaceGridMesh
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void R_FreeSurfaceGridMesh( srfBspSurface_t *grid ) {
|
static void R_FreeSurfaceGridMeshData( srfBspSurface_t *grid ) {
|
||||||
ri.Free(grid->widthLodError);
|
ri.Free(grid->widthLodError);
|
||||||
ri.Free(grid->heightLodError);
|
ri.Free(grid->heightLodError);
|
||||||
ri.Free(grid->indexes);
|
ri.Free(grid->indexes);
|
||||||
ri.Free(grid->verts);
|
ri.Free(grid->verts);
|
||||||
ri.Free(grid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -462,7 +442,7 @@ void R_FreeSurfaceGridMesh( srfBspSurface_t *grid ) {
|
||||||
R_SubdividePatchToGrid
|
R_SubdividePatchToGrid
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
srfBspSurface_t *R_SubdividePatchToGrid( int width, int height,
|
void R_SubdividePatchToGrid( srfBspSurface_t *grid, int width, int height,
|
||||||
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
|
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
|
||||||
int i, j, k, l;
|
int i, j, k, l;
|
||||||
srfVert_t_cleared( prev );
|
srfVert_t_cleared( prev );
|
||||||
|
@ -629,15 +609,13 @@ srfBspSurface_t *R_SubdividePatchToGrid( int width, int height,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// calculate indexes
|
// calculate indexes
|
||||||
numIndexes = MakeMeshIndexes(width, height, ctrl, indexes);
|
numIndexes = MakeMeshIndexes(width, height, indexes);
|
||||||
|
|
||||||
// calculate normals
|
// calculate normals
|
||||||
MakeMeshNormals( width, height, ctrl );
|
MakeMeshNormals( width, height, ctrl );
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
MakeMeshTangentVectors(width, height, ctrl, numIndexes, indexes);
|
MakeMeshTangentVectors(width, height, ctrl, numIndexes, indexes);
|
||||||
#endif
|
|
||||||
|
|
||||||
return R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numIndexes, indexes);
|
R_CreateSurfaceGridMesh(grid, width, height, ctrl, errorTable, numIndexes, indexes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -645,7 +623,7 @@ srfBspSurface_t *R_SubdividePatchToGrid( int width, int height,
|
||||||
R_GridInsertColumn
|
R_GridInsertColumn
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row, vec3_t point, float loderror ) {
|
void R_GridInsertColumn( srfBspSurface_t *grid, int column, int row, vec3_t point, float loderror ) {
|
||||||
int i, j;
|
int i, j;
|
||||||
int width, height, oldwidth;
|
int width, height, oldwidth;
|
||||||
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
|
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
|
||||||
|
@ -658,7 +636,7 @@ srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row,
|
||||||
oldwidth = 0;
|
oldwidth = 0;
|
||||||
width = grid->width + 1;
|
width = grid->width + 1;
|
||||||
if (width > MAX_GRID_SIZE)
|
if (width > MAX_GRID_SIZE)
|
||||||
return NULL;
|
return;
|
||||||
height = grid->height;
|
height = grid->height;
|
||||||
for (i = 0; i < width; i++) {
|
for (i = 0; i < width; i++) {
|
||||||
if (i == column) {
|
if (i == column) {
|
||||||
|
@ -684,20 +662,20 @@ srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row,
|
||||||
//PutPointsOnCurve( ctrl, width, height );
|
//PutPointsOnCurve( ctrl, width, height );
|
||||||
|
|
||||||
// calculate indexes
|
// calculate indexes
|
||||||
numIndexes = MakeMeshIndexes(width, height, ctrl, indexes);
|
numIndexes = MakeMeshIndexes(width, height, indexes);
|
||||||
|
|
||||||
// calculate normals
|
// calculate normals
|
||||||
MakeMeshNormals( width, height, ctrl );
|
MakeMeshNormals( width, height, ctrl );
|
||||||
|
MakeMeshTangentVectors(width, height, ctrl, numIndexes, indexes);
|
||||||
|
|
||||||
VectorCopy(grid->lodOrigin, lodOrigin);
|
VectorCopy(grid->lodOrigin, lodOrigin);
|
||||||
lodRadius = grid->lodRadius;
|
lodRadius = grid->lodRadius;
|
||||||
// free the old grid
|
// free the old grid
|
||||||
R_FreeSurfaceGridMesh(grid);
|
R_FreeSurfaceGridMeshData(grid);
|
||||||
// create a new grid
|
// create a new grid
|
||||||
grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numIndexes, indexes);
|
R_CreateSurfaceGridMesh(grid, width, height, ctrl, errorTable, numIndexes, indexes);
|
||||||
grid->lodRadius = lodRadius;
|
grid->lodRadius = lodRadius;
|
||||||
VectorCopy(lodOrigin, grid->lodOrigin);
|
VectorCopy(lodOrigin, grid->lodOrigin);
|
||||||
return grid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -705,7 +683,7 @@ srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row,
|
||||||
R_GridInsertRow
|
R_GridInsertRow
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
srfBspSurface_t *R_GridInsertRow( srfBspSurface_t *grid, int row, int column, vec3_t point, float loderror ) {
|
void R_GridInsertRow( srfBspSurface_t *grid, int row, int column, vec3_t point, float loderror ) {
|
||||||
int i, j;
|
int i, j;
|
||||||
int width, height, oldheight;
|
int width, height, oldheight;
|
||||||
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
|
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
|
||||||
|
@ -719,7 +697,7 @@ srfBspSurface_t *R_GridInsertRow( srfBspSurface_t *grid, int row, int column, ve
|
||||||
width = grid->width;
|
width = grid->width;
|
||||||
height = grid->height + 1;
|
height = grid->height + 1;
|
||||||
if (height > MAX_GRID_SIZE)
|
if (height > MAX_GRID_SIZE)
|
||||||
return NULL;
|
return;
|
||||||
for (i = 0; i < height; i++) {
|
for (i = 0; i < height; i++) {
|
||||||
if (i == row) {
|
if (i == row) {
|
||||||
//insert new row
|
//insert new row
|
||||||
|
@ -744,18 +722,18 @@ srfBspSurface_t *R_GridInsertRow( srfBspSurface_t *grid, int row, int column, ve
|
||||||
//PutPointsOnCurve( ctrl, width, height );
|
//PutPointsOnCurve( ctrl, width, height );
|
||||||
|
|
||||||
// calculate indexes
|
// calculate indexes
|
||||||
numIndexes = MakeMeshIndexes(width, height, ctrl, indexes);
|
numIndexes = MakeMeshIndexes(width, height, indexes);
|
||||||
|
|
||||||
// calculate normals
|
// calculate normals
|
||||||
MakeMeshNormals( width, height, ctrl );
|
MakeMeshNormals( width, height, ctrl );
|
||||||
|
MakeMeshTangentVectors(width, height, ctrl, numIndexes, indexes);
|
||||||
|
|
||||||
VectorCopy(grid->lodOrigin, lodOrigin);
|
VectorCopy(grid->lodOrigin, lodOrigin);
|
||||||
lodRadius = grid->lodRadius;
|
lodRadius = grid->lodRadius;
|
||||||
// free the old grid
|
// free the old grid
|
||||||
R_FreeSurfaceGridMesh(grid);
|
R_FreeSurfaceGridMeshData(grid);
|
||||||
// create a new grid
|
// create a new grid
|
||||||
grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numIndexes, indexes);
|
R_CreateSurfaceGridMesh(grid, width, height, ctrl, errorTable, numIndexes, indexes);
|
||||||
grid->lodRadius = lodRadius;
|
grid->lodRadius = lodRadius;
|
||||||
VectorCopy(lodOrigin, grid->lodOrigin);
|
VectorCopy(lodOrigin, grid->lodOrigin);
|
||||||
return grid;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,505 +0,0 @@
|
||||||
/*
|
|
||||||
===========================================================================
|
|
||||||
Copyright (C) 1999-2005 Id Software, Inc.
|
|
||||||
|
|
||||||
This file is part of Quake III Arena source code.
|
|
||||||
|
|
||||||
Quake III Arena source code 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 2 of the License,
|
|
||||||
or (at your option) any later version.
|
|
||||||
|
|
||||||
Quake III Arena source code 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.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Quake III Arena source code; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
===========================================================================
|
|
||||||
*/
|
|
||||||
// tr_draw.c -- drawing
|
|
||||||
|
|
||||||
#include "tr_local.h"
|
|
||||||
|
|
||||||
vec4_t r_colorWhite = { 1.0, 1.0, 1.0, 1.0 };
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
Draw_SetColor
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void Draw_SetColor( const vec4_t rgba ) {
|
|
||||||
#if 1
|
|
||||||
if( !rgba ) {
|
|
||||||
rgba = r_colorWhite;
|
|
||||||
}
|
|
||||||
|
|
||||||
backEnd.color2D[ 0 ] = rgba[ 0 ] * tr.identityLight;
|
|
||||||
backEnd.color2D[ 1 ] = rgba[ 1 ] * tr.identityLight;
|
|
||||||
backEnd.color2D[ 2 ] = rgba[ 2 ] * tr.identityLight;
|
|
||||||
backEnd.color2D[ 3 ] = rgba[ 3 ];
|
|
||||||
qglColor4fv( backEnd.color2D );
|
|
||||||
#else
|
|
||||||
RE_SetColor( rgba );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
Draw_StretchPic
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void Draw_StretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader ) {
|
|
||||||
#if 1
|
|
||||||
shader_t *shader;
|
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
if( hShader ) {
|
|
||||||
shader = R_GetShaderByHandle( hShader );
|
|
||||||
} else {
|
|
||||||
shader = tr.defaultShader;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( w <= 0 ) {
|
|
||||||
w = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->width;
|
|
||||||
h = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
RB_Prepare2D();
|
|
||||||
|
|
||||||
// draw the pic
|
|
||||||
RB_Color4f( backEnd.color2D[ 0 ], backEnd.color2D[ 1 ], backEnd.color2D[ 2 ], backEnd.color2D[ 3 ] );
|
|
||||||
RB_BeginSurface( shader, 0, 0 );
|
|
||||||
|
|
||||||
RB_Texcoord2f( s1, t1 );
|
|
||||||
RB_Vertex2f( x, y );
|
|
||||||
|
|
||||||
RB_Texcoord2f( s2, t1 );
|
|
||||||
RB_Vertex2f( x + w, y );
|
|
||||||
|
|
||||||
RB_Texcoord2f( s1, t2 );
|
|
||||||
RB_Vertex2f( x, y + h );
|
|
||||||
|
|
||||||
RB_Texcoord2f( s2, t2 );
|
|
||||||
RB_Vertex2f( x + w, y + h );
|
|
||||||
|
|
||||||
RB_StreamEnd();
|
|
||||||
#else
|
|
||||||
RE_StretchPic( x, y, w, h, s1, t1, s2, t2, hShader );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
Draw_TilePic
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void Draw_TilePic( float x, float y, float w, float h , qhandle_t hShader ) {
|
|
||||||
shader_t *shader;
|
|
||||||
float picw, pich;
|
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
if( hShader ) {
|
|
||||||
shader = R_GetShaderByHandle( hShader );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
shader = tr.defaultShader;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( w <= 0 ) {
|
|
||||||
w = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->width;
|
|
||||||
h = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
picw = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadWidth;
|
|
||||||
pich = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadHeight;
|
|
||||||
|
|
||||||
RB_Prepare2D();
|
|
||||||
|
|
||||||
// draw the pic
|
|
||||||
RB_Color4f( backEnd.color2D[ 0 ], backEnd.color2D[ 1 ], backEnd.color2D[ 2 ], backEnd.color2D[ 3 ] );
|
|
||||||
|
|
||||||
RB_StreamBegin( shader );
|
|
||||||
|
|
||||||
RB_Texcoord2f( x / picw, y / pich );
|
|
||||||
RB_Vertex2f( x, y );
|
|
||||||
|
|
||||||
RB_Texcoord2f( ( x + w ) / picw, y / pich );
|
|
||||||
RB_Vertex2f( x + w, y );
|
|
||||||
|
|
||||||
RB_Texcoord2f( x / picw, ( y + h ) / pich );
|
|
||||||
RB_Vertex2f( x, y + h );
|
|
||||||
|
|
||||||
RB_Texcoord2f( ( x + w ) / picw, ( y + h ) / pich );
|
|
||||||
RB_Vertex2f( x + w, y + h );
|
|
||||||
|
|
||||||
RB_StreamEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
Draw_TilePicOffset
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void Draw_TilePicOffset( float x, float y, float w, float h, qhandle_t hShader, int offsetX, int offsetY ) {
|
|
||||||
shader_t *shader;
|
|
||||||
float picw, pich;
|
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
if( hShader ) {
|
|
||||||
shader = R_GetShaderByHandle( hShader );
|
|
||||||
} else {
|
|
||||||
shader = tr.defaultShader;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( w <= 0 ) {
|
|
||||||
w = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->width;
|
|
||||||
h = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
picw = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadWidth;
|
|
||||||
pich = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadHeight;
|
|
||||||
|
|
||||||
RB_Prepare2D();
|
|
||||||
|
|
||||||
// draw the pic
|
|
||||||
RB_Color4f( backEnd.color2D[ 0 ], backEnd.color2D[ 1 ], backEnd.color2D[ 2 ], backEnd.color2D[ 3 ] );
|
|
||||||
|
|
||||||
RB_StreamBegin( shader );
|
|
||||||
|
|
||||||
RB_Texcoord2f( x / picw, y / pich );
|
|
||||||
RB_Vertex2f( x + offsetX, y + offsetY );
|
|
||||||
|
|
||||||
RB_Texcoord2f( ( x + w ) / picw, y / pich );
|
|
||||||
RB_Vertex2f( x + offsetX + w, y + offsetY );
|
|
||||||
|
|
||||||
RB_Texcoord2f( x / picw, ( y + h ) / pich );
|
|
||||||
RB_Vertex2f( x + offsetX, y + offsetY + h );
|
|
||||||
|
|
||||||
RB_Texcoord2f( ( x + w ) / picw, ( y + h ) / pich );
|
|
||||||
RB_Vertex2f( x + offsetX + w, y + offsetY + h );
|
|
||||||
|
|
||||||
RB_StreamEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
Draw_TrianglePic
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void Draw_TrianglePic( const vec2_t vPoints[ 3 ], const vec2_t vTexCoords[ 3 ], qhandle_t hShader ) {
|
|
||||||
int i;
|
|
||||||
shader_t *shader;
|
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
if( hShader ) {
|
|
||||||
shader = R_GetShaderByHandle( hShader );
|
|
||||||
} else {
|
|
||||||
shader = tr.defaultShader;
|
|
||||||
}
|
|
||||||
|
|
||||||
RB_Prepare2D();
|
|
||||||
|
|
||||||
// draw the pic
|
|
||||||
RB_Color4f( backEnd.color2D[ 0 ], backEnd.color2D[ 1 ], backEnd.color2D[ 2 ], backEnd.color2D[ 3 ] );
|
|
||||||
|
|
||||||
RB_BeginSurface( shader, 0, 0 );
|
|
||||||
|
|
||||||
for( i = 0; i < 3; i++ ) {
|
|
||||||
RB_Texcoord2f( vTexCoords[ i ][ 0 ], vTexCoords[ i ][ 1 ] );
|
|
||||||
RB_Vertex2f( vPoints[ i ][ 0 ], vPoints[ i ][ 1 ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
RB_StreamEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
RE_DrawBackground_TexSubImage
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void RE_DrawBackground_TexSubImage( int cols, int rows, int bgr, byte *data ) {
|
|
||||||
GLenum format;
|
|
||||||
int w, h;
|
|
||||||
|
|
||||||
w = glConfig.vidWidth;
|
|
||||||
h = glConfig.vidHeight;
|
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
qglFinish();
|
|
||||||
|
|
||||||
if( bgr ) {
|
|
||||||
format = GL_BGR_EXT;
|
|
||||||
} else {
|
|
||||||
format = GL_RGB;
|
|
||||||
}
|
|
||||||
|
|
||||||
GL_Bind( tr.scratchImage[ 0 ] );
|
|
||||||
|
|
||||||
if( cols == tr.scratchImage[ 0 ]->width && rows == tr.scratchImage[ 0 ]->height && format == tr.scratchImage[ 0 ]->internalFormat )
|
|
||||||
{
|
|
||||||
qglTexSubImage2D( 3553, 0, 0, 0, cols, rows, format, 5121, data );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tr.scratchImage[ 0 ]->uploadWidth = cols;
|
|
||||||
tr.scratchImage[ 0 ]->uploadHeight = rows;
|
|
||||||
tr.scratchImage[ 0 ]->internalFormat = format;
|
|
||||||
qglTexImage2D( GL_TEXTURE_2D, 0, 3, cols, rows, 0, format, 5121, data );
|
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9729.0 );
|
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9729.0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
qglDisable( GL_CULL_FACE );
|
|
||||||
qglDisable( GL_DEPTH_TEST );
|
|
||||||
qglEnable( GL_TEXTURE_2D );
|
|
||||||
|
|
||||||
qglBegin( GL_QUADS );
|
|
||||||
|
|
||||||
qglTexCoord2f( 0.5 / ( GLfloat )cols, ( ( GLfloat )rows - 0.5 ) / rows );
|
|
||||||
qglVertex2f( 0, 0 );
|
|
||||||
|
|
||||||
qglTexCoord2f( ( ( GLfloat )cols - 0.5 ) / cols, ( ( GLfloat )rows - 0.5 ) / rows );
|
|
||||||
qglVertex2f( w, 0 );
|
|
||||||
|
|
||||||
qglTexCoord2f( ( ( GLfloat )cols - 0.5 ) / cols, 0.5 / ( GLfloat )rows );
|
|
||||||
qglVertex2f( w, h );
|
|
||||||
|
|
||||||
qglTexCoord2f( 0.5 / ( GLfloat )rows, 0.5 / ( GLfloat )rows );
|
|
||||||
qglVertex2f( 0, h );
|
|
||||||
|
|
||||||
qglEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
RE_DrawBackground_DrawPixels
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void RE_DrawBackground_DrawPixels( int cols, int rows, int bgr, byte *data ) {
|
|
||||||
// FIXME: stub
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
RE_StretchRaw
|
|
||||||
|
|
||||||
Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
|
|
||||||
Used for cinematics.
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void RE_StretchRaw( int x, int y, int w, int h, int cols, int rows, int components, const byte *data ) {
|
|
||||||
int i, j;
|
|
||||||
int start, end;
|
|
||||||
vec4_t quadVerts[4];
|
|
||||||
vec2_t texCoords[4];
|
|
||||||
|
|
||||||
if ( !tr.registered ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
if ( tess.numIndexes ) {
|
|
||||||
RB_EndSurface();
|
|
||||||
}
|
|
||||||
|
|
||||||
// we definately want to sync every frame for the cinematics
|
|
||||||
qglFinish();
|
|
||||||
|
|
||||||
start = 0;
|
|
||||||
if ( r_speeds->integer ) {
|
|
||||||
start = ri.Milliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure rows and cols are powers of 2
|
|
||||||
for ( i = 0 ; ( 1 << i ) < cols ; i++ ) {
|
|
||||||
}
|
|
||||||
for ( j = 0 ; ( 1 << j ) < rows ; j++ ) {
|
|
||||||
}
|
|
||||||
if ( ( 1 << i ) != cols || ( 1 << j ) != rows) {
|
|
||||||
ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
RE_UploadCinematic (w, h, cols, rows, data, 0, qtrue);
|
|
||||||
|
|
||||||
if ( r_speeds->integer ) {
|
|
||||||
end = ri.Milliseconds();
|
|
||||||
ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );
|
|
||||||
}
|
|
||||||
|
|
||||||
RB_Prepare2D();
|
|
||||||
|
|
||||||
RB_SetGL2D();
|
|
||||||
|
|
||||||
VectorSet4(quadVerts[0], x, y, 0.0f, 1.0f);
|
|
||||||
VectorSet4(quadVerts[1], x + w, y, 0.0f, 1.0f);
|
|
||||||
VectorSet4(quadVerts[2], x + w, y + h, 0.0f, 1.0f);
|
|
||||||
VectorSet4(quadVerts[3], x, y + h, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
VectorSet2(texCoords[0], 0.5f / cols, 0.5f / rows);
|
|
||||||
VectorSet2(texCoords[1], (cols - 0.5f) / cols, 0.5f / rows);
|
|
||||||
VectorSet2(texCoords[2], (cols - 0.5f) / cols, (rows - 0.5f) / rows);
|
|
||||||
VectorSet2(texCoords[3], 0.5f / cols, (rows - 0.5f) / rows);
|
|
||||||
|
|
||||||
GLSL_BindProgram(&tr.textureColorShader);
|
|
||||||
|
|
||||||
GLSL_SetUniformMat4(&tr.textureColorShader, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
|
|
||||||
GLSL_SetUniformVec4(&tr.textureColorShader, UNIFORM_COLOR, colorWhite);
|
|
||||||
|
|
||||||
RB_InstantQuad2(quadVerts, texCoords);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
AddBox
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void AddBox( float x, float y, float w, float h ) {
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
qglColor4fv( backEnd.color2D );
|
|
||||||
qglDisable( GL_TEXTURE_2D );
|
|
||||||
GL_State( 0x422 );
|
|
||||||
|
|
||||||
qglBegin( GL_QUADS );
|
|
||||||
|
|
||||||
qglVertex2f( x, y );
|
|
||||||
qglVertex2f( x + w, y );
|
|
||||||
qglVertex2f( x + w, y + h );
|
|
||||||
qglVertex2f( x, y + h );
|
|
||||||
|
|
||||||
qglEnd();
|
|
||||||
|
|
||||||
qglEnable( GL_TEXTURE_2D );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
DrawBox
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void DrawBox( float x, float y, float w, float h ) {
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
qglColor4fv( backEnd.color2D );
|
|
||||||
qglDisable( GL_TEXTURE_2D );
|
|
||||||
GL_State( 0x465 );
|
|
||||||
|
|
||||||
qglBegin( GL_QUADS );
|
|
||||||
|
|
||||||
qglVertex2f( x, y );
|
|
||||||
qglVertex2f( x + w, y );
|
|
||||||
qglVertex2f( x + w, y + h );
|
|
||||||
qglVertex2f( x, y + h );
|
|
||||||
|
|
||||||
qglEnd();
|
|
||||||
|
|
||||||
qglEnable( GL_TEXTURE_2D );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
DrawLineLoop
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void DrawLineLoop( const vec2_t *points, int count, int stipple_factor, int stipple_mask ) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
qglDisable( GL_TEXTURE_2D );
|
|
||||||
|
|
||||||
if( stipple_factor ) {
|
|
||||||
qglEnable( GL_LINE_STIPPLE );
|
|
||||||
qglLineStipple( stipple_factor, stipple_mask );
|
|
||||||
}
|
|
||||||
|
|
||||||
qglBegin( GL_LINE_LOOP );
|
|
||||||
|
|
||||||
for( i = 0; i < count; i++ ) {
|
|
||||||
qglVertex2i( points[ i ][ 0 ], points[ i ][ 1 ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
qglEnd();
|
|
||||||
|
|
||||||
qglEnable( GL_TEXTURE_2D );
|
|
||||||
|
|
||||||
if( stipple_factor ) {
|
|
||||||
qglDisable( GL_LINE_STIPPLE );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
Set2DWindow
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void Set2DWindow( int x, int y, int w, int h, float left, float right, float bottom, float top, float n, float f ) {
|
|
||||||
matrix_t matrix;
|
|
||||||
|
|
||||||
backEnd.projection2D = qtrue;
|
|
||||||
backEnd.last2DFBO = glState.currentFBO;
|
|
||||||
|
|
||||||
// set 2D virtual screen size
|
|
||||||
qglViewport( 0, 0, w, h );
|
|
||||||
qglScissor( 0, 0, w, h );
|
|
||||||
|
|
||||||
Mat4Ortho( 0, w, h, 0, 0, 1, matrix );
|
|
||||||
GL_SetProjectionMatrix( matrix );
|
|
||||||
Mat4Identity( matrix );
|
|
||||||
GL_SetModelviewMatrix( matrix );
|
|
||||||
|
|
||||||
GL_State( GLS_DEPTHTEST_DISABLE |
|
|
||||||
GLS_SRCBLEND_SRC_ALPHA |
|
|
||||||
GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
|
|
||||||
|
|
||||||
GL_Cull( CT_TWO_SIDED );
|
|
||||||
qglDisable( GL_CLIP_PLANE0 );
|
|
||||||
|
|
||||||
// set time for 2D shaders
|
|
||||||
backEnd.refdef.time = ri.Milliseconds();
|
|
||||||
backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;
|
|
||||||
|
|
||||||
// reset color scaling
|
|
||||||
backEnd.refdef.colorScale = 1.0f;
|
|
||||||
|
|
||||||
/*qglViewport( x, y, w, h );
|
|
||||||
qglScissor( x, y, w, h );
|
|
||||||
|
|
||||||
qglMatrixMode( GL_MODELVIEW0_ARB + 1 );
|
|
||||||
qglLoadIdentity();
|
|
||||||
qglOrtho( left, right, bottom, top, n, f );
|
|
||||||
|
|
||||||
qglMatrixMode( GL_MODELVIEW0_ARB );
|
|
||||||
qglLoadIdentity();
|
|
||||||
GL_State( 0x465 );
|
|
||||||
|
|
||||||
qglEnable( GL_BLEND );
|
|
||||||
qglDisable( GL_CULL_FACE );
|
|
||||||
qglDisable( GL_CLIP_PLANE0 );
|
|
||||||
|
|
||||||
//if( r_reset_tc_array->integer )
|
|
||||||
// qglDisableClientState( 32888 );
|
|
||||||
if( !backEnd.projection2D )
|
|
||||||
{
|
|
||||||
backEnd.refdef.time = ri.Milliseconds();
|
|
||||||
backEnd.projection2D = qtrue;
|
|
||||||
backEnd.refdef.floatTime = ( float )backEnd.refdef.time * 0.001;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
RE_Scissor
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void RE_Scissor( int x, int y, int width, int height ) {
|
|
||||||
qglEnable( GL_SCISSOR_TEST );
|
|
||||||
qglScissor( x, y, width, height );
|
|
||||||
}
|
|
287
code/renderergl2/tr_dsa.c
Normal file
287
code/renderergl2/tr_dsa.c
Normal file
|
@ -0,0 +1,287 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2016 James Canete
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
#include "tr_dsa.h"
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
GLuint textures[NUM_TEXTURE_BUNDLES];
|
||||||
|
GLenum texunit;
|
||||||
|
|
||||||
|
GLuint program;
|
||||||
|
|
||||||
|
GLuint drawFramebuffer;
|
||||||
|
GLuint readFramebuffer;
|
||||||
|
GLuint renderbuffer;
|
||||||
|
}
|
||||||
|
glDsaState;
|
||||||
|
|
||||||
|
void GL_BindNullTextures(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (glRefConfig.directStateAccess)
|
||||||
|
{
|
||||||
|
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
|
||||||
|
{
|
||||||
|
qglBindMultiTextureEXT(GL_TEXTURE0 + i, GL_TEXTURE_2D, 0);
|
||||||
|
glDsaState.textures[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
|
||||||
|
{
|
||||||
|
qglActiveTexture(GL_TEXTURE0 + i);
|
||||||
|
qglBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glDsaState.textures[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qglActiveTexture(GL_TEXTURE0);
|
||||||
|
glDsaState.texunit = GL_TEXTURE0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture)
|
||||||
|
{
|
||||||
|
GLuint tmu = texunit - GL_TEXTURE0;
|
||||||
|
|
||||||
|
if (glDsaState.textures[tmu] == texture)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
|
||||||
|
target = GL_TEXTURE_CUBE_MAP;
|
||||||
|
|
||||||
|
qglBindMultiTextureEXT(texunit, target, texture);
|
||||||
|
glDsaState.textures[tmu] = texture;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_BindMultiTextureEXT(GLenum texunit, GLenum target, GLuint texture)
|
||||||
|
{
|
||||||
|
if (glDsaState.texunit != texunit)
|
||||||
|
{
|
||||||
|
qglActiveTexture(texunit);
|
||||||
|
glDsaState.texunit = texunit;
|
||||||
|
}
|
||||||
|
|
||||||
|
qglBindTexture(target, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_TextureParameterfEXT(GLuint texture, GLenum target, GLenum pname, GLfloat param)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglTexParameterf(target, pname, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_TextureParameteriEXT(GLuint texture, GLenum target, GLenum pname, GLint param)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglTexParameteri(target, pname, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_TextureImage2DEXT(GLuint texture, GLenum target, GLint level, GLint internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_TextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
|
GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_CopyTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
|
GLint x, GLint y, GLsizei width, GLsizei height)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_CompressedTextureImage2DEXT(GLuint texture, GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_CompressedTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level,
|
||||||
|
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
|
||||||
|
GLsizei imageSize, const GLvoid *data)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_GenerateTextureMipmapEXT(GLuint texture, GLenum target)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglGenerateMipmap(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_BindNullProgram(void)
|
||||||
|
{
|
||||||
|
qglUseProgram(0);
|
||||||
|
glDsaState.program = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GL_UseProgram(GLuint program)
|
||||||
|
{
|
||||||
|
if (glDsaState.program == program)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
qglUseProgram(program);
|
||||||
|
glDsaState.program = program;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1iEXT(GLuint program, GLint location, GLint v0)
|
||||||
|
{
|
||||||
|
GL_UseProgram(program);
|
||||||
|
qglUniform1i(location, v0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1fEXT(GLuint program, GLint location, GLfloat v0)
|
||||||
|
{
|
||||||
|
GL_UseProgram(program);
|
||||||
|
qglUniform1f(location, v0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform2fEXT(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1)
|
||||||
|
{
|
||||||
|
GL_UseProgram(program);
|
||||||
|
qglUniform2f(location, v0, v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform3fEXT(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2)
|
||||||
|
{
|
||||||
|
GL_UseProgram(program);
|
||||||
|
qglUniform3f(location, v0, v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform4fEXT(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
|
||||||
|
{
|
||||||
|
GL_UseProgram(program);
|
||||||
|
qglUniform4f(location, v0, v1, v2, v3);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1fvEXT(GLuint program, GLint location,
|
||||||
|
GLsizei count, const GLfloat *value)
|
||||||
|
{
|
||||||
|
GL_UseProgram(program);
|
||||||
|
qglUniform1fv(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fvEXT(GLuint program, GLint location,
|
||||||
|
GLsizei count, GLboolean transpose,
|
||||||
|
const GLfloat *value)
|
||||||
|
{
|
||||||
|
GL_UseProgram(program);
|
||||||
|
qglUniformMatrix4fv(location, count, transpose, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_BindNullFramebuffers(void)
|
||||||
|
{
|
||||||
|
qglBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
glDsaState.drawFramebuffer = glDsaState.readFramebuffer = 0;
|
||||||
|
qglBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
|
glDsaState.renderbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_BindFramebuffer(GLenum target, GLuint framebuffer)
|
||||||
|
{
|
||||||
|
switch (target)
|
||||||
|
{
|
||||||
|
case GL_FRAMEBUFFER:
|
||||||
|
if (framebuffer != glDsaState.drawFramebuffer || framebuffer != glDsaState.readFramebuffer)
|
||||||
|
{
|
||||||
|
qglBindFramebuffer(target, framebuffer);
|
||||||
|
glDsaState.drawFramebuffer = glDsaState.readFramebuffer = framebuffer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_DRAW_FRAMEBUFFER:
|
||||||
|
if (framebuffer != glDsaState.drawFramebuffer)
|
||||||
|
{
|
||||||
|
qglBindFramebuffer(target, framebuffer);
|
||||||
|
glDsaState.drawFramebuffer = framebuffer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_READ_FRAMEBUFFER:
|
||||||
|
if (framebuffer != glDsaState.readFramebuffer)
|
||||||
|
{
|
||||||
|
qglBindFramebuffer(target, framebuffer);
|
||||||
|
glDsaState.readFramebuffer = framebuffer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_BindRenderbuffer(GLuint renderbuffer)
|
||||||
|
{
|
||||||
|
if (renderbuffer != glDsaState.renderbuffer)
|
||||||
|
{
|
||||||
|
qglBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
|
||||||
|
glDsaState.renderbuffer = renderbuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedRenderbufferStorageEXT(GLuint renderbuffer,
|
||||||
|
GLenum internalformat, GLsizei width, GLsizei height)
|
||||||
|
{
|
||||||
|
GL_BindRenderbuffer(renderbuffer);
|
||||||
|
qglRenderbufferStorage(GL_RENDERBUFFER, internalformat, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedRenderbufferStorageMultisampleEXT(GLuint renderbuffer,
|
||||||
|
GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
|
||||||
|
{
|
||||||
|
GL_BindRenderbuffer(renderbuffer);
|
||||||
|
qglRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum APIENTRY GLDSA_CheckNamedFramebufferStatusEXT(GLuint framebuffer, GLenum target)
|
||||||
|
{
|
||||||
|
GL_BindFramebuffer(target, framebuffer);
|
||||||
|
return qglCheckFramebufferStatus(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedFramebufferTexture2DEXT(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum textarget, GLuint texture, GLint level)
|
||||||
|
{
|
||||||
|
GL_BindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||||
|
qglFramebufferTexture2D(GL_FRAMEBUFFER, attachment, textarget, texture, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedFramebufferRenderbufferEXT(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
|
||||||
|
{
|
||||||
|
GL_BindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||||
|
qglFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, renderbuffertarget, renderbuffer);
|
||||||
|
}
|
80
code/renderergl2/tr_dsa.h
Normal file
80
code/renderergl2/tr_dsa.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2016 James Canete
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TR_DSA_H__
|
||||||
|
#define __TR_DSA_H__
|
||||||
|
|
||||||
|
#include "../renderercommon/qgl.h"
|
||||||
|
|
||||||
|
void GL_BindNullTextures(void);
|
||||||
|
int GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture);
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_BindMultiTextureEXT(GLenum texunit, GLenum target, GLuint texture);
|
||||||
|
GLvoid APIENTRY GLDSA_TextureParameterfEXT(GLuint texture, GLenum target, GLenum pname, GLfloat param);
|
||||||
|
GLvoid APIENTRY GLDSA_TextureParameteriEXT(GLuint texture, GLenum target, GLenum pname, GLint param);
|
||||||
|
GLvoid APIENTRY GLDSA_TextureImage2DEXT(GLuint texture, GLenum target, GLint level, GLint internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||||
|
GLvoid APIENTRY GLDSA_TextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
|
GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
|
||||||
|
GLvoid APIENTRY GLDSA_CopyTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
|
GLint x, GLint y, GLsizei width, GLsizei height);
|
||||||
|
GLvoid APIENTRY GLDSA_CompressedTextureImage2DEXT(GLuint texture, GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
|
||||||
|
GLvoid APIENTRY GLDSA_CompressedTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level,
|
||||||
|
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
|
||||||
|
GLsizei imageSize, const GLvoid *data);
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_GenerateTextureMipmapEXT(GLuint texture, GLenum target);
|
||||||
|
|
||||||
|
void GL_BindNullProgram(void);
|
||||||
|
int GL_UseProgram(GLuint program);
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1iEXT(GLuint program, GLint location, GLint v0);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1fEXT(GLuint program, GLint location, GLfloat v0);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform2fEXT(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform3fEXT(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform4fEXT(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1fvEXT(GLuint program, GLint location,
|
||||||
|
GLsizei count, const GLfloat *value);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fvEXT(GLuint program, GLint location,
|
||||||
|
GLsizei count, GLboolean transpose,
|
||||||
|
const GLfloat *value);
|
||||||
|
|
||||||
|
void GL_BindNullFramebuffers(void);
|
||||||
|
void GL_BindFramebuffer(GLenum target, GLuint framebuffer);
|
||||||
|
void GL_BindRenderbuffer(GLuint renderbuffer);
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedRenderbufferStorageEXT(GLuint renderbuffer,
|
||||||
|
GLenum internalformat, GLsizei width, GLsizei height);
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedRenderbufferStorageMultisampleEXT(GLuint renderbuffer,
|
||||||
|
GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
|
||||||
|
|
||||||
|
GLenum APIENTRY GLDSA_CheckNamedFramebufferStatusEXT(GLuint framebuffer, GLenum target);
|
||||||
|
GLvoid APIENTRY GLDSA_NamedFramebufferTexture2DEXT(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||||
|
GLvoid APIENTRY GLDSA_NamedFramebufferRenderbufferEXT(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -28,507 +28,50 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
#include "tr_dsa.h"
|
||||||
|
|
||||||
// GL_EXT_draw_range_elements
|
void GLimp_InitExtraExtensions(void)
|
||||||
void (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
|
|
||||||
|
|
||||||
// GL_EXT_multi_draw_arrays
|
|
||||||
void (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
|
|
||||||
void (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
|
|
||||||
|
|
||||||
// GL_ARB_vertex_shader
|
|
||||||
void (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name);
|
|
||||||
void (APIENTRY * qglGetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length,
|
|
||||||
GLint * size, GLenum * type, GLcharARB * name);
|
|
||||||
GLint(APIENTRY * qglGetAttribLocationARB) (GLhandleARB programObj, const GLcharARB * name);
|
|
||||||
|
|
||||||
// GL_ARB_vertex_program
|
|
||||||
void (APIENTRY * qglVertexAttrib4fARB) (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
|
|
||||||
void (APIENTRY * qglVertexAttrib4fvARB) (GLuint, const GLfloat *);
|
|
||||||
void (APIENTRY * qglVertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized,
|
|
||||||
GLsizei stride, const GLvoid * pointer);
|
|
||||||
void (APIENTRY * qglEnableVertexAttribArrayARB) (GLuint index);
|
|
||||||
void (APIENTRY * qglDisableVertexAttribArrayARB) (GLuint index);
|
|
||||||
|
|
||||||
// GL_ARB_vertex_buffer_object
|
|
||||||
void (APIENTRY * qglBindBufferARB) (GLenum target, GLuint buffer);
|
|
||||||
void (APIENTRY * qglDeleteBuffersARB) (GLsizei n, const GLuint * buffers);
|
|
||||||
void (APIENTRY * qglGenBuffersARB) (GLsizei n, GLuint * buffers);
|
|
||||||
|
|
||||||
GLboolean(APIENTRY * qglIsBufferARB) (GLuint buffer);
|
|
||||||
void (APIENTRY * qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage);
|
|
||||||
void (APIENTRY * qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data);
|
|
||||||
void (APIENTRY * qglGetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data);
|
|
||||||
|
|
||||||
void (APIENTRY * qglGetBufferParameterivARB) (GLenum target, GLenum pname, GLint * params);
|
|
||||||
void (APIENTRY * qglGetBufferPointervARB) (GLenum target, GLenum pname, GLvoid * *params);
|
|
||||||
|
|
||||||
// GL_ARB_shader_objects
|
|
||||||
void (APIENTRY * qglDeleteObjectARB) (GLhandleARB obj);
|
|
||||||
|
|
||||||
GLhandleARB(APIENTRY * qglGetHandleARB) (GLenum pname);
|
|
||||||
void (APIENTRY * qglDetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj);
|
|
||||||
|
|
||||||
GLhandleARB(APIENTRY * qglCreateShaderObjectARB) (GLenum shaderType);
|
|
||||||
void (APIENTRY * qglShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB * *string,
|
|
||||||
const GLint * length);
|
|
||||||
void (APIENTRY * qglCompileShaderARB) (GLhandleARB shaderObj);
|
|
||||||
|
|
||||||
GLhandleARB(APIENTRY * qglCreateProgramObjectARB) (void);
|
|
||||||
void (APIENTRY * qglAttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj);
|
|
||||||
void (APIENTRY * qglLinkProgramARB) (GLhandleARB programObj);
|
|
||||||
void (APIENTRY * qglUseProgramObjectARB) (GLhandleARB programObj);
|
|
||||||
void (APIENTRY * qglValidateProgramARB) (GLhandleARB programObj);
|
|
||||||
void (APIENTRY * qglUniform1fARB) (GLint location, GLfloat v0);
|
|
||||||
void (APIENTRY * qglUniform2fARB) (GLint location, GLfloat v0, GLfloat v1);
|
|
||||||
void (APIENTRY * qglUniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
|
|
||||||
void (APIENTRY * qglUniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
|
||||||
void (APIENTRY * qglUniform1iARB) (GLint location, GLint v0);
|
|
||||||
void (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1);
|
|
||||||
void (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2);
|
|
||||||
void (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
|
|
||||||
void (APIENTRY * qglUniform1fvARB) (GLint location, GLsizei count, const GLfloat * value);
|
|
||||||
void (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value);
|
|
||||||
void (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value);
|
|
||||||
void (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value);
|
|
||||||
void (APIENTRY * qglUniform2ivARB) (GLint location, GLsizei count, const GLint * value);
|
|
||||||
void (APIENTRY * qglUniform3ivARB) (GLint location, GLsizei count, const GLint * value);
|
|
||||||
void (APIENTRY * qglUniform4ivARB) (GLint location, GLsizei count, const GLint * value);
|
|
||||||
void (APIENTRY * qglUniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
|
|
||||||
void (APIENTRY * qglUniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
|
|
||||||
void (APIENTRY * qglUniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
|
|
||||||
void (APIENTRY * qglGetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat * params);
|
|
||||||
void (APIENTRY * qglGetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint * params);
|
|
||||||
void (APIENTRY * qglGetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog);
|
|
||||||
void (APIENTRY * qglGetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei * count,
|
|
||||||
GLhandleARB * obj);
|
|
||||||
GLint(APIENTRY * qglGetUniformLocationARB) (GLhandleARB programObj, const GLcharARB * name);
|
|
||||||
void (APIENTRY * qglGetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxIndex, GLsizei * length,
|
|
||||||
GLint * size, GLenum * type, GLcharARB * name);
|
|
||||||
void (APIENTRY * qglGetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat * params);
|
|
||||||
void (APIENTRY * qglGetUniformivARB) (GLhandleARB programObj, GLint location, GLint * params);
|
|
||||||
void (APIENTRY * qglGetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source);
|
|
||||||
|
|
||||||
// GL_ARB_texture_compression
|
|
||||||
void (APIENTRY * qglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
|
|
||||||
GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
|
|
||||||
void (APIENTRY * qglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
|
|
||||||
GLint border, GLsizei imageSize, const GLvoid *data);
|
|
||||||
void (APIENTRY * qglCompressedTexImage1DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border,
|
|
||||||
GLsizei imageSize, const GLvoid *data);
|
|
||||||
void (APIENTRY * qglCompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
|
||||||
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
|
|
||||||
void (APIENTRY * qglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
|
|
||||||
GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
|
|
||||||
void (APIENTRY * qglCompressedTexSubImage1DARB)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format,
|
|
||||||
GLsizei imageSize, const GLvoid *data);
|
|
||||||
void (APIENTRY * qglGetCompressedTexImageARB)(GLenum target, GLint lod,
|
|
||||||
GLvoid *img);
|
|
||||||
|
|
||||||
// GL_EXT_framebuffer_object
|
|
||||||
GLboolean (APIENTRY * qglIsRenderbufferEXT)(GLuint renderbuffer);
|
|
||||||
void (APIENTRY * qglBindRenderbufferEXT)(GLenum target, GLuint renderbuffer);
|
|
||||||
void (APIENTRY * qglDeleteRenderbuffersEXT)(GLsizei n, const GLuint *renderbuffers);
|
|
||||||
void (APIENTRY * qglGenRenderbuffersEXT)(GLsizei n, GLuint *renderbuffers);
|
|
||||||
|
|
||||||
void (APIENTRY * qglRenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
|
|
||||||
|
|
||||||
void (APIENTRY * qglGetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint *params);
|
|
||||||
|
|
||||||
GLboolean (APIENTRY * qglIsFramebufferEXT)(GLuint framebuffer);
|
|
||||||
void (APIENTRY * qglBindFramebufferEXT)(GLenum target, GLuint framebuffer);
|
|
||||||
void (APIENTRY * qglDeleteFramebuffersEXT)(GLsizei n, const GLuint *framebuffers);
|
|
||||||
void (APIENTRY * qglGenFramebuffersEXT)(GLsizei n, GLuint *framebuffers);
|
|
||||||
|
|
||||||
GLenum (APIENTRY * qglCheckFramebufferStatusEXT)(GLenum target);
|
|
||||||
|
|
||||||
void (APIENTRY * qglFramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
|
|
||||||
GLint level);
|
|
||||||
void (APIENTRY * qglFramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
|
|
||||||
GLint level);
|
|
||||||
void (APIENTRY * qglFramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
|
|
||||||
GLint level, GLint zoffset);
|
|
||||||
|
|
||||||
void (APIENTRY * qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget,
|
|
||||||
GLuint renderbuffer);
|
|
||||||
|
|
||||||
void (APIENTRY * qglGetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
|
|
||||||
|
|
||||||
void (APIENTRY * qglGenerateMipmapEXT)(GLenum target);
|
|
||||||
|
|
||||||
// GL_ARB_occlusion_query
|
|
||||||
void (APIENTRY * qglGenQueriesARB)(GLsizei n, GLuint *ids);
|
|
||||||
void (APIENTRY * qglDeleteQueriesARB)(GLsizei n, const GLuint *ids);
|
|
||||||
GLboolean (APIENTRY * qglIsQueryARB)(GLuint id);
|
|
||||||
void (APIENTRY * qglBeginQueryARB)(GLenum target, GLuint id);
|
|
||||||
void (APIENTRY * qglEndQueryARB)(GLenum target);
|
|
||||||
void (APIENTRY * qglGetQueryivARB)(GLenum target, GLenum pname, GLint *params);
|
|
||||||
void (APIENTRY * qglGetQueryObjectivARB)(GLuint id, GLenum pname, GLint *params);
|
|
||||||
void (APIENTRY * qglGetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint *params);
|
|
||||||
|
|
||||||
// GL_EXT_framebuffer_blit
|
|
||||||
void (APIENTRY * qglBlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
|
||||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
|
||||||
GLbitfield mask, GLenum filter);
|
|
||||||
|
|
||||||
// GL_EXT_framebuffer_multisample
|
|
||||||
void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples,
|
|
||||||
GLenum internalformat, GLsizei width, GLsizei height);
|
|
||||||
|
|
||||||
// GL_ARB_draw_buffers
|
|
||||||
void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs);
|
|
||||||
|
|
||||||
// GL_ARB_vertex_array_object
|
|
||||||
void (APIENTRY * qglBindVertexArrayARB)(GLuint array);
|
|
||||||
void (APIENTRY * qglDeleteVertexArraysARB)(GLsizei n, const GLuint *arrays);
|
|
||||||
void (APIENTRY * qglGenVertexArraysARB)(GLsizei n, GLuint *arrays);
|
|
||||||
GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array);
|
|
||||||
|
|
||||||
static qboolean GLimp_HaveExtension(const char *ext)
|
|
||||||
{
|
|
||||||
const char *ptr = Q_stristr( glConfig.extensions_string, ext );
|
|
||||||
if (ptr == NULL)
|
|
||||||
return qfalse;
|
|
||||||
ptr += strlen(ext);
|
|
||||||
return ((*ptr == ' ') || (*ptr == '\0')); // verify it's complete string.
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLimp_InitExtraExtensions()
|
|
||||||
{
|
{
|
||||||
char *extension;
|
char *extension;
|
||||||
const char* result[3] = { "...ignoring %s\n", "...using %s\n", "...%s not found\n" };
|
const char* result[3] = { "...ignoring %s\n", "...using %s\n", "...%s not found\n" };
|
||||||
|
qboolean q_gl_version_at_least_3_0;
|
||||||
|
qboolean q_gl_version_at_least_3_2;
|
||||||
|
|
||||||
// GL_EXT_draw_range_elements
|
q_gl_version_at_least_3_0 = QGL_VERSION_ATLEAST( 3, 0 );
|
||||||
extension = "GL_EXT_draw_range_elements";
|
q_gl_version_at_least_3_2 = QGL_VERSION_ATLEAST( 3, 2 );
|
||||||
glRefConfig.drawRangeElements = qfalse;
|
|
||||||
qglMultiDrawArraysEXT = NULL;
|
|
||||||
qglMultiDrawElementsEXT = NULL;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
qglDrawRangeElementsEXT = (void *) SDL_GL_GetProcAddress("glDrawRangeElementsEXT");
|
|
||||||
|
|
||||||
if ( r_ext_draw_range_elements->integer)
|
// Check if we need Intel graphics specific fixes.
|
||||||
glRefConfig.drawRangeElements = qtrue;
|
glRefConfig.intelGraphics = qfalse;
|
||||||
|
if (strstr((char *)qglGetString(GL_RENDERER), "Intel"))
|
||||||
|
glRefConfig.intelGraphics = qtrue;
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.drawRangeElements], extension);
|
// set DSA fallbacks
|
||||||
}
|
#define GLE(ret, name, ...) qgl##name = GLDSA_##name;
|
||||||
else
|
QGL_EXT_direct_state_access_PROCS;
|
||||||
{
|
#undef GLE
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_EXT_multi_draw_arrays
|
// GL function loader, based on https://gist.github.com/rygorous/16796a0c876cf8a5f542caddb55bce8a
|
||||||
extension = "GL_EXT_multi_draw_arrays";
|
#define GLE(ret, name, ...) qgl##name = (name##proc *) SDL_GL_GetProcAddress("gl" #name);
|
||||||
glRefConfig.multiDrawArrays = qfalse;
|
|
||||||
qglMultiDrawArraysEXT = NULL;
|
|
||||||
qglMultiDrawElementsEXT = NULL;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
qglMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC) SDL_GL_GetProcAddress("glMultiDrawArraysEXT");
|
|
||||||
qglMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC) SDL_GL_GetProcAddress("glMultiDrawElementsEXT");
|
|
||||||
|
|
||||||
if ( r_ext_multi_draw_arrays->integer )
|
// OpenGL 1.5 - GL_ARB_occlusion_query
|
||||||
glRefConfig.multiDrawArrays = qtrue;
|
glRefConfig.occlusionQuery = qtrue;
|
||||||
|
QGL_ARB_occlusion_query_PROCS;
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.multiDrawArrays], extension);
|
// OpenGL 3.0 - GL_ARB_framebuffer_object
|
||||||
}
|
extension = "GL_ARB_framebuffer_object";
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_vertex_program
|
|
||||||
//glRefConfig.vertexProgram = qfalse;
|
|
||||||
extension = "GL_ARB_vertex_program";
|
|
||||||
qglVertexAttrib4fARB = NULL;
|
|
||||||
qglVertexAttrib4fvARB = NULL;
|
|
||||||
qglVertexAttribPointerARB = NULL;
|
|
||||||
qglEnableVertexAttribArrayARB = NULL;
|
|
||||||
qglDisableVertexAttribArrayARB = NULL;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
qglVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) SDL_GL_GetProcAddress("glVertexAttrib4fARB");
|
|
||||||
qglVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) SDL_GL_GetProcAddress("glVertexAttrib4fvARB");
|
|
||||||
qglVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) SDL_GL_GetProcAddress("glVertexAttribPointerARB");
|
|
||||||
qglEnableVertexAttribArrayARB =
|
|
||||||
(PFNGLENABLEVERTEXATTRIBARRAYARBPROC) SDL_GL_GetProcAddress("glEnableVertexAttribArrayARB");
|
|
||||||
qglDisableVertexAttribArrayARB =
|
|
||||||
(PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) SDL_GL_GetProcAddress("glDisableVertexAttribArrayARB");
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[1], extension);
|
|
||||||
//glRefConfig.vertexProgram = qtrue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Error(ERR_FATAL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_vertex_buffer_object
|
|
||||||
//glRefConfig.vertexBufferObject = qfalse;
|
|
||||||
extension = "GL_ARB_vertex_buffer_object";
|
|
||||||
qglBindBufferARB = NULL;
|
|
||||||
qglDeleteBuffersARB = NULL;
|
|
||||||
qglGenBuffersARB = NULL;
|
|
||||||
qglIsBufferARB = NULL;
|
|
||||||
qglBufferDataARB = NULL;
|
|
||||||
qglBufferSubDataARB = NULL;
|
|
||||||
qglGetBufferSubDataARB = NULL;
|
|
||||||
qglGetBufferParameterivARB = NULL;
|
|
||||||
qglGetBufferPointervARB = NULL;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
qglBindBufferARB = (PFNGLBINDBUFFERARBPROC) SDL_GL_GetProcAddress("glBindBufferARB");
|
|
||||||
qglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB");
|
|
||||||
qglGenBuffersARB = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB");
|
|
||||||
qglIsBufferARB = (PFNGLISBUFFERARBPROC) SDL_GL_GetProcAddress("glIsBufferARB");
|
|
||||||
qglBufferDataARB = (PFNGLBUFFERDATAARBPROC) SDL_GL_GetProcAddress("glBufferDataARB");
|
|
||||||
qglBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glBufferSubDataARB");
|
|
||||||
qglGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glGetBufferSubDataARB");
|
|
||||||
qglGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetBufferParameterivARB");
|
|
||||||
qglGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC) SDL_GL_GetProcAddress("glGetBufferPointervARB");
|
|
||||||
ri.Printf(PRINT_ALL, result[1], extension);
|
|
||||||
//glRefConfig.vertexBufferObject = qtrue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Error(ERR_FATAL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_shader_objects
|
|
||||||
extension = "GL_ARB_shader_objects";
|
|
||||||
//glRefConfig.shaderObjects = qfalse;
|
|
||||||
qglDeleteObjectARB = NULL;
|
|
||||||
qglGetHandleARB = NULL;
|
|
||||||
qglDetachObjectARB = NULL;
|
|
||||||
qglCreateShaderObjectARB = NULL;
|
|
||||||
qglShaderSourceARB = NULL;
|
|
||||||
qglCompileShaderARB = NULL;
|
|
||||||
qglCreateProgramObjectARB = NULL;
|
|
||||||
qglAttachObjectARB = NULL;
|
|
||||||
qglLinkProgramARB = NULL;
|
|
||||||
qglUseProgramObjectARB = NULL;
|
|
||||||
qglValidateProgramARB = NULL;
|
|
||||||
qglUniform1fARB = NULL;
|
|
||||||
qglUniform2fARB = NULL;
|
|
||||||
qglUniform3fARB = NULL;
|
|
||||||
qglUniform4fARB = NULL;
|
|
||||||
qglUniform1iARB = NULL;
|
|
||||||
qglUniform2iARB = NULL;
|
|
||||||
qglUniform3iARB = NULL;
|
|
||||||
qglUniform4iARB = NULL;
|
|
||||||
qglUniform1fvARB = NULL;
|
|
||||||
qglUniform2fvARB = NULL;
|
|
||||||
qglUniform3fvARB = NULL;
|
|
||||||
qglUniform4fvARB = NULL;
|
|
||||||
qglUniform2ivARB = NULL;
|
|
||||||
qglUniform3ivARB = NULL;
|
|
||||||
qglUniform4ivARB = NULL;
|
|
||||||
qglUniformMatrix2fvARB = NULL;
|
|
||||||
qglUniformMatrix3fvARB = NULL;
|
|
||||||
qglUniformMatrix4fvARB = NULL;
|
|
||||||
qglGetObjectParameterfvARB = NULL;
|
|
||||||
qglGetObjectParameterivARB = NULL;
|
|
||||||
qglGetInfoLogARB = NULL;
|
|
||||||
qglGetAttachedObjectsARB = NULL;
|
|
||||||
qglGetUniformLocationARB = NULL;
|
|
||||||
qglGetActiveUniformARB = NULL;
|
|
||||||
qglGetUniformfvARB = NULL;
|
|
||||||
qglGetUniformivARB = NULL;
|
|
||||||
qglGetShaderSourceARB = NULL;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
qglDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB");
|
|
||||||
qglGetHandleARB = (PFNGLGETHANDLEARBPROC) SDL_GL_GetProcAddress("glGetHandleARB");
|
|
||||||
qglDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) SDL_GL_GetProcAddress("glDetachObjectARB");
|
|
||||||
qglCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB");
|
|
||||||
qglShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB");
|
|
||||||
qglCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB");
|
|
||||||
qglCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB");
|
|
||||||
qglAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB");
|
|
||||||
qglLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB");
|
|
||||||
qglUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB");
|
|
||||||
qglValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) SDL_GL_GetProcAddress("glValidateProgramARB");
|
|
||||||
qglUniform1fARB = (PFNGLUNIFORM1FARBPROC) SDL_GL_GetProcAddress("glUniform1fARB");
|
|
||||||
qglUniform2fARB = (PFNGLUNIFORM2FARBPROC) SDL_GL_GetProcAddress("glUniform2fARB");
|
|
||||||
qglUniform3fARB = (PFNGLUNIFORM3FARBPROC) SDL_GL_GetProcAddress("glUniform3fARB");
|
|
||||||
qglUniform4fARB = (PFNGLUNIFORM4FARBPROC) SDL_GL_GetProcAddress("glUniform4fARB");
|
|
||||||
qglUniform1iARB = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB");
|
|
||||||
qglUniform2iARB = (PFNGLUNIFORM2IARBPROC) SDL_GL_GetProcAddress("glUniform2iARB");
|
|
||||||
qglUniform3iARB = (PFNGLUNIFORM3IARBPROC) SDL_GL_GetProcAddress("glUniform3iARB");
|
|
||||||
qglUniform4iARB = (PFNGLUNIFORM4IARBPROC) SDL_GL_GetProcAddress("glUniform4iARB");
|
|
||||||
qglUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) SDL_GL_GetProcAddress("glUniform1fvARB");
|
|
||||||
qglUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) SDL_GL_GetProcAddress("glUniform2fvARB");
|
|
||||||
qglUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) SDL_GL_GetProcAddress("glUniform3fvARB");
|
|
||||||
qglUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) SDL_GL_GetProcAddress("glUniform4fvARB");
|
|
||||||
qglUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) SDL_GL_GetProcAddress("glUniform2ivARB");
|
|
||||||
qglUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) SDL_GL_GetProcAddress("glUniform3ivARB");
|
|
||||||
qglUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) SDL_GL_GetProcAddress("glUniform4ivARB");
|
|
||||||
qglUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix2fvARB");
|
|
||||||
qglUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix3fvARB");
|
|
||||||
qglUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix4fvARB");
|
|
||||||
qglGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterfvARB");
|
|
||||||
qglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB");
|
|
||||||
qglGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB");
|
|
||||||
qglGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) SDL_GL_GetProcAddress("glGetAttachedObjectsARB");
|
|
||||||
qglGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB");
|
|
||||||
qglGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) SDL_GL_GetProcAddress("glGetActiveUniformARB");
|
|
||||||
qglGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) SDL_GL_GetProcAddress("glGetUniformfvARB");
|
|
||||||
qglGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) SDL_GL_GetProcAddress("glGetUniformivARB");
|
|
||||||
qglGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glGetShaderSourceARB");
|
|
||||||
ri.Printf(PRINT_ALL, result[1], extension);
|
|
||||||
//glRefConfig.shaderObjects = qtrue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Error(ERR_FATAL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_vertex_shader
|
|
||||||
//glRefConfig.vertexShader = qfalse;
|
|
||||||
extension = "GL_ARB_vertex_shader";
|
|
||||||
qglBindAttribLocationARB = NULL;
|
|
||||||
qglGetActiveAttribARB = NULL;
|
|
||||||
qglGetAttribLocationARB = NULL;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
//int reservedComponents;
|
|
||||||
|
|
||||||
//qglGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &glConfig.maxVertexUniforms);
|
|
||||||
//qglGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &glConfig.maxVaryingFloats);
|
|
||||||
//qglGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &glConfig.maxVertexAttribs);
|
|
||||||
|
|
||||||
//reservedComponents = 16 * 10; // approximation how many uniforms we have besides the bone matrices
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if(glConfig.driverType == GLDRV_MESA)
|
|
||||||
{
|
|
||||||
// HACK
|
|
||||||
// restrict to number of vertex uniforms to 512 because of:
|
|
||||||
// xreal.x86_64: nv50_program.c:4181: nv50_program_validate_data: Assertion `p->param_nr <= 512' failed
|
|
||||||
|
|
||||||
glConfig.maxVertexUniforms = Q_bound(0, glConfig.maxVertexUniforms, 512);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//glConfig.maxVertexSkinningBones = (int) Q_bound(0.0, (Q_max(glConfig.maxVertexUniforms - reservedComponents, 0) / 16), MAX_BONES);
|
|
||||||
//glConfig.vboVertexSkinningAvailable = r_vboVertexSkinning->integer && ((glConfig.maxVertexSkinningBones >= 12) ? qtrue : qfalse);
|
|
||||||
|
|
||||||
qglBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glBindAttribLocationARB");
|
|
||||||
qglGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) SDL_GL_GetProcAddress("glGetActiveAttribARB");
|
|
||||||
qglGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetAttribLocationARB");
|
|
||||||
ri.Printf(PRINT_ALL, result[1], extension);
|
|
||||||
//glRefConfig.vertexShader = qtrue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Error(ERR_FATAL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_shading_language_100
|
|
||||||
extension = "GL_ARB_shading_language_100";
|
|
||||||
glRefConfig.textureFloat = qfalse;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
char version[256];
|
|
||||||
|
|
||||||
Q_strncpyz( version, (char *) qglGetString (GL_SHADING_LANGUAGE_VERSION_ARB), sizeof( version ) );
|
|
||||||
|
|
||||||
sscanf(version, "%d.%d", &glRefConfig.glslMajorVersion, &glRefConfig.glslMinorVersion);
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, "...using GLSL version %s\n", version);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Error(ERR_FATAL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
glRefConfig.memInfo = MI_NONE;
|
|
||||||
|
|
||||||
if( GLimp_HaveExtension( "GL_NVX_gpu_memory_info" ) )
|
|
||||||
{
|
|
||||||
glRefConfig.memInfo = MI_NVX;
|
|
||||||
}
|
|
||||||
else if( GLimp_HaveExtension( "GL_ATI_meminfo" ) )
|
|
||||||
{
|
|
||||||
glRefConfig.memInfo = MI_ATI;
|
|
||||||
}
|
|
||||||
|
|
||||||
extension = "GL_ARB_texture_non_power_of_two";
|
|
||||||
glRefConfig.textureNonPowerOfTwo = qfalse;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
if(1) //(r_ext_texture_non_power_of_two->integer)
|
|
||||||
{
|
|
||||||
glRefConfig.textureNonPowerOfTwo = qtrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.textureNonPowerOfTwo], extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_texture_float
|
|
||||||
extension = "GL_ARB_texture_float";
|
|
||||||
glRefConfig.textureFloat = qfalse;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
if( r_ext_texture_float->integer )
|
|
||||||
{
|
|
||||||
glRefConfig.textureFloat = qtrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.textureFloat], extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_half_float_pixel
|
|
||||||
extension = "GL_ARB_half_float_pixel";
|
|
||||||
glRefConfig.halfFloatPixel = qfalse;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
if( r_arb_half_float_pixel->integer )
|
|
||||||
glRefConfig.halfFloatPixel = qtrue;
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.halfFloatPixel], extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_EXT_framebuffer_object
|
|
||||||
extension = "GL_EXT_framebuffer_object";
|
|
||||||
glRefConfig.framebufferObject = qfalse;
|
glRefConfig.framebufferObject = qfalse;
|
||||||
if( GLimp_HaveExtension( extension ) )
|
glRefConfig.framebufferBlit = qfalse;
|
||||||
|
glRefConfig.framebufferMultisample = qfalse;
|
||||||
|
if (q_gl_version_at_least_3_0 || SDL_GL_ExtensionSupported(extension))
|
||||||
{
|
{
|
||||||
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &glRefConfig.maxRenderbufferSize);
|
glRefConfig.framebufferObject = !!r_ext_framebuffer_object->integer;
|
||||||
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &glRefConfig.maxColorAttachments);
|
glRefConfig.framebufferBlit = qtrue;
|
||||||
|
glRefConfig.framebufferMultisample = qtrue;
|
||||||
|
|
||||||
qglIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glIsRenderbufferEXT");
|
qglGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glRefConfig.maxRenderbufferSize);
|
||||||
qglBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glBindRenderbufferEXT");
|
qglGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &glRefConfig.maxColorAttachments);
|
||||||
qglDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) SDL_GL_GetProcAddress("glDeleteRenderbuffersEXT");
|
|
||||||
qglGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) SDL_GL_GetProcAddress("glGenRenderbuffersEXT");
|
|
||||||
qglRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) SDL_GL_GetProcAddress("glRenderbufferStorageEXT");
|
|
||||||
qglGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) SDL_GL_GetProcAddress("glGetRenderbufferParameterivEXT");
|
|
||||||
qglIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) SDL_GL_GetProcAddress("glIsFramebufferEXT");
|
|
||||||
qglBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) SDL_GL_GetProcAddress("glBindFramebufferEXT");
|
|
||||||
qglDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
|
|
||||||
qglGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) SDL_GL_GetProcAddress("glGenFramebuffersEXT");
|
|
||||||
qglCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
|
|
||||||
qglFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture1DEXT");
|
|
||||||
qglFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
|
|
||||||
qglFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture3DEXT");
|
|
||||||
qglFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glFramebufferRenderbufferEXT");
|
|
||||||
qglGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) SDL_GL_GetProcAddress("glGetFramebufferAttachmentParameterivEXT");
|
|
||||||
qglGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) SDL_GL_GetProcAddress("glGenerateMipmapEXT");
|
|
||||||
|
|
||||||
if(r_ext_framebuffer_object->value)
|
QGL_ARB_framebuffer_object_PROCS;
|
||||||
glRefConfig.framebufferObject = qtrue;
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.framebufferObject], extension);
|
ri.Printf(PRINT_ALL, result[glRefConfig.framebufferObject], extension);
|
||||||
}
|
}
|
||||||
|
@ -537,132 +80,64 @@ void GLimp_InitExtraExtensions()
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GL_EXT_packed_depth_stencil
|
// OpenGL 3.0 - GL_ARB_vertex_array_object
|
||||||
extension = "GL_EXT_packed_depth_stencil";
|
extension = "GL_ARB_vertex_array_object";
|
||||||
glRefConfig.packedDepthStencil = qfalse;
|
glRefConfig.vertexArrayObject = qfalse;
|
||||||
if( GLimp_HaveExtension(extension))
|
if (q_gl_version_at_least_3_0 || SDL_GL_ExtensionSupported(extension))
|
||||||
{
|
{
|
||||||
glRefConfig.packedDepthStencil = qtrue;
|
if (q_gl_version_at_least_3_0)
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.packedDepthStencil], extension);
|
{
|
||||||
|
// force VAO, core context requires it
|
||||||
|
glRefConfig.vertexArrayObject = qtrue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glRefConfig.vertexArrayObject = !!r_arb_vertex_array_object->integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGL_ARB_vertex_array_object_PROCS;
|
||||||
|
|
||||||
|
ri.Printf(PRINT_ALL, result[glRefConfig.vertexArrayObject], extension);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GL_ARB_occlusion_query
|
// OpenGL 3.0 - GL_ARB_texture_float
|
||||||
extension = "GL_ARB_occlusion_query";
|
extension = "GL_ARB_texture_float";
|
||||||
glRefConfig.occlusionQuery = qfalse;
|
glRefConfig.textureFloat = qfalse;
|
||||||
if (GLimp_HaveExtension(extension))
|
if (q_gl_version_at_least_3_0 || SDL_GL_ExtensionSupported(extension))
|
||||||
{
|
{
|
||||||
qglGenQueriesARB = (PFNGLGENQUERIESARBPROC) SDL_GL_GetProcAddress("glGenQueriesARB");
|
glRefConfig.textureFloat = !!r_ext_texture_float->integer;
|
||||||
qglDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC) SDL_GL_GetProcAddress("glDeleteQueriesARB");
|
|
||||||
qglIsQueryARB = (PFNGLISQUERYARBPROC) SDL_GL_GetProcAddress("glIsQueryARB");
|
ri.Printf(PRINT_ALL, result[glRefConfig.textureFloat], extension);
|
||||||
qglBeginQueryARB = (PFNGLBEGINQUERYARBPROC) SDL_GL_GetProcAddress("glBeginQueryARB");
|
|
||||||
qglEndQueryARB = (PFNGLENDQUERYARBPROC) SDL_GL_GetProcAddress("glEndQueryARB");
|
|
||||||
qglGetQueryivARB = (PFNGLGETQUERYIVARBPROC) SDL_GL_GetProcAddress("glGetQueryivARB");
|
|
||||||
qglGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC) SDL_GL_GetProcAddress("glGetQueryObjectivARB");
|
|
||||||
qglGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC) SDL_GL_GetProcAddress("glGetQueryObjectuivARB");
|
|
||||||
glRefConfig.occlusionQuery = qtrue;
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.occlusionQuery], extension);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GL_EXT_framebuffer_blit
|
// OpenGL 3.2 - GL_ARB_depth_clamp
|
||||||
extension = "GL_EXT_framebuffer_blit";
|
|
||||||
glRefConfig.framebufferBlit = qfalse;
|
|
||||||
if (GLimp_HaveExtension(extension))
|
|
||||||
{
|
|
||||||
qglBlitFramebufferEXT = (void *)SDL_GL_GetProcAddress("glBlitFramebufferEXT");
|
|
||||||
glRefConfig.framebufferBlit = qtrue;
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.framebufferBlit], extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_EXT_framebuffer_multisample
|
|
||||||
extension = "GL_EXT_framebuffer_multisample";
|
|
||||||
glRefConfig.framebufferMultisample = qfalse;
|
|
||||||
if (GLimp_HaveExtension(extension))
|
|
||||||
{
|
|
||||||
qglRenderbufferStorageMultisampleEXT = (void *)SDL_GL_GetProcAddress("glRenderbufferStorageMultisampleEXT");
|
|
||||||
glRefConfig.framebufferMultisample = qtrue;
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.framebufferMultisample], extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
glRefConfig.textureCompression = TCR_NONE;
|
|
||||||
|
|
||||||
// GL_EXT_texture_compression_latc
|
|
||||||
extension = "GL_EXT_texture_compression_latc";
|
|
||||||
if (GLimp_HaveExtension(extension))
|
|
||||||
{
|
|
||||||
if (r_ext_compressed_textures->integer)
|
|
||||||
glRefConfig.textureCompression |= TCR_LATC;
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[r_ext_compressed_textures->integer ? 1 : 0], extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_texture_compression_bptc
|
|
||||||
extension = "GL_ARB_texture_compression_bptc";
|
|
||||||
if (GLimp_HaveExtension(extension))
|
|
||||||
{
|
|
||||||
if (r_ext_compressed_textures->integer >= 2)
|
|
||||||
glRefConfig.textureCompression |= TCR_BPTC;
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[(r_ext_compressed_textures->integer >= 2) ? 1 : 0], extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_draw_buffers
|
|
||||||
extension = "GL_ARB_draw_buffers";
|
|
||||||
qglDrawBuffersARB = NULL;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
qglDrawBuffersARB = (void *) SDL_GL_GetProcAddress("glDrawBuffersARB");
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[1], extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_depth_clamp
|
|
||||||
extension = "GL_ARB_depth_clamp";
|
extension = "GL_ARB_depth_clamp";
|
||||||
glRefConfig.depthClamp = qfalse;
|
glRefConfig.depthClamp = qfalse;
|
||||||
if( GLimp_HaveExtension( extension ) )
|
if (q_gl_version_at_least_3_2 || SDL_GL_ExtensionSupported(extension))
|
||||||
{
|
{
|
||||||
glRefConfig.depthClamp = qtrue;
|
glRefConfig.depthClamp = qtrue;
|
||||||
ri.Printf(PRINT_ALL, result[1], extension);
|
|
||||||
|
ri.Printf(PRINT_ALL, result[glRefConfig.depthClamp], extension);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GL_ARB_seamless_cube_map
|
// OpenGL 3.2 - GL_ARB_seamless_cube_map
|
||||||
extension = "GL_ARB_seamless_cube_map";
|
extension = "GL_ARB_seamless_cube_map";
|
||||||
glRefConfig.seamlessCubeMap = qfalse;
|
glRefConfig.seamlessCubeMap = qfalse;
|
||||||
if( GLimp_HaveExtension( extension ) )
|
if (q_gl_version_at_least_3_2 || SDL_GL_ExtensionSupported(extension))
|
||||||
{
|
{
|
||||||
if (r_arb_seamless_cube_map->integer)
|
glRefConfig.seamlessCubeMap = !!r_arb_seamless_cube_map->integer;
|
||||||
glRefConfig.seamlessCubeMap = qtrue;
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.seamlessCubeMap], extension);
|
ri.Printf(PRINT_ALL, result[glRefConfig.seamlessCubeMap], extension);
|
||||||
}
|
}
|
||||||
|
@ -671,65 +146,108 @@ void GLimp_InitExtraExtensions()
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GL_ARB_vertex_type_2_10_10_10_rev
|
// Determine GLSL version
|
||||||
extension = "GL_ARB_vertex_type_2_10_10_10_rev";
|
if (1)
|
||||||
glRefConfig.packedNormalDataType = GL_BYTE;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
{
|
||||||
if (r_arb_vertex_type_2_10_10_10_rev->integer)
|
char version[256];
|
||||||
glRefConfig.packedNormalDataType = GL_INT_2_10_10_10_REV;
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[r_arb_vertex_type_2_10_10_10_rev->integer ? 1 : 0], extension);
|
Q_strncpyz(version, (char *)qglGetString(GL_SHADING_LANGUAGE_VERSION), sizeof(version));
|
||||||
|
|
||||||
|
sscanf(version, "%d.%d", &glRefConfig.glslMajorVersion, &glRefConfig.glslMinorVersion);
|
||||||
|
|
||||||
|
ri.Printf(PRINT_ALL, "...using GLSL version %s\n", version);
|
||||||
|
}
|
||||||
|
|
||||||
|
glRefConfig.memInfo = MI_NONE;
|
||||||
|
|
||||||
|
// GL_NVX_gpu_memory_info
|
||||||
|
extension = "GL_NVX_gpu_memory_info";
|
||||||
|
if( SDL_GL_ExtensionSupported( extension ) )
|
||||||
|
{
|
||||||
|
glRefConfig.memInfo = MI_NVX;
|
||||||
|
|
||||||
|
ri.Printf(PRINT_ALL, result[1], extension);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
// use float lightmaps?
|
// GL_ATI_meminfo
|
||||||
glRefConfig.floatLightmap = (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer && r_hdr->integer);
|
extension = "GL_ATI_meminfo";
|
||||||
|
if( SDL_GL_ExtensionSupported( extension ) )
|
||||||
// GL_ARB_vertex_array_object
|
|
||||||
extension = "GL_ARB_vertex_array_object";
|
|
||||||
glRefConfig.vertexArrayObject = qfalse;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
{
|
||||||
qglBindVertexArrayARB = (void *) SDL_GL_GetProcAddress("glBindVertexArray");
|
if (glRefConfig.memInfo == MI_NONE)
|
||||||
qglDeleteVertexArraysARB = (void *) SDL_GL_GetProcAddress("glDeleteVertexArrays");
|
|
||||||
qglGenVertexArraysARB = (void *) SDL_GL_GetProcAddress("glGenVertexArrays");
|
|
||||||
qglIsVertexArrayARB = (void *) SDL_GL_GetProcAddress("glIsVertexArray");
|
|
||||||
|
|
||||||
if (r_arb_vertex_array_object->integer)
|
|
||||||
glRefConfig.vertexArrayObject = qtrue;
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[glRefConfig.vertexArrayObject ? 1 : 0], extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GL_ARB_half_float_vertex
|
|
||||||
extension = "GL_ARB_half_float_vertex";
|
|
||||||
glRefConfig.packedTexcoordDataType = GL_FLOAT;
|
|
||||||
glRefConfig.packedTexcoordDataSize = sizeof(float) * 2;
|
|
||||||
glRefConfig.packedColorDataType = GL_FLOAT;
|
|
||||||
glRefConfig.packedColorDataSize = sizeof(float) * 4;
|
|
||||||
if( GLimp_HaveExtension( extension ) )
|
|
||||||
{
|
|
||||||
if (r_arb_half_float_vertex->integer)
|
|
||||||
{
|
{
|
||||||
glRefConfig.packedTexcoordDataType = GL_HALF_FLOAT;
|
glRefConfig.memInfo = MI_ATI;
|
||||||
glRefConfig.packedTexcoordDataSize = sizeof(uint16_t) * 2;
|
|
||||||
glRefConfig.packedColorDataType = GL_HALF_FLOAT;
|
ri.Printf(PRINT_ALL, result[1], extension);
|
||||||
glRefConfig.packedColorDataSize = sizeof(uint16_t) * 4;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, result[0], extension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
glRefConfig.textureCompression = TCR_NONE;
|
||||||
|
|
||||||
|
// GL_ARB_texture_compression_rgtc
|
||||||
|
extension = "GL_ARB_texture_compression_rgtc";
|
||||||
|
if (SDL_GL_ExtensionSupported(extension))
|
||||||
|
{
|
||||||
|
qboolean useRgtc = r_ext_compressed_textures->integer >= 1;
|
||||||
|
|
||||||
|
if (useRgtc)
|
||||||
|
glRefConfig.textureCompression |= TCR_RGTC;
|
||||||
|
|
||||||
|
ri.Printf(PRINT_ALL, result[useRgtc], extension);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
glRefConfig.swizzleNormalmap = r_ext_compressed_textures->integer && !(glRefConfig.textureCompression & TCR_RGTC);
|
||||||
|
|
||||||
|
// GL_ARB_texture_compression_bptc
|
||||||
|
extension = "GL_ARB_texture_compression_bptc";
|
||||||
|
if (SDL_GL_ExtensionSupported(extension))
|
||||||
|
{
|
||||||
|
qboolean useBptc = r_ext_compressed_textures->integer >= 2;
|
||||||
|
|
||||||
|
if (useBptc)
|
||||||
|
glRefConfig.textureCompression |= TCR_BPTC;
|
||||||
|
|
||||||
|
ri.Printf(PRINT_ALL, result[useBptc], extension);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GL_EXT_direct_state_access
|
||||||
|
extension = "GL_EXT_direct_state_access";
|
||||||
|
glRefConfig.directStateAccess = qfalse;
|
||||||
|
if (SDL_GL_ExtensionSupported(extension))
|
||||||
|
{
|
||||||
|
glRefConfig.directStateAccess = !!r_ext_direct_state_access->integer;
|
||||||
|
|
||||||
|
// QGL_*_PROCS becomes several functions, do not remove {}
|
||||||
|
if (glRefConfig.directStateAccess)
|
||||||
|
{
|
||||||
|
QGL_EXT_direct_state_access_PROCS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[r_arb_half_float_vertex->integer ? 1 : 0], extension);
|
ri.Printf(PRINT_ALL, result[glRefConfig.directStateAccess], extension);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef GLE
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ int NextPowerOfTwo(int in)
|
||||||
|
|
||||||
union f32_u {
|
union f32_u {
|
||||||
float f;
|
float f;
|
||||||
uint32_t i;
|
uint32_t ui;
|
||||||
struct {
|
struct {
|
||||||
unsigned int fraction:23;
|
unsigned int fraction:23;
|
||||||
unsigned int exponent:8;
|
unsigned int exponent:8;
|
||||||
|
@ -203,7 +203,7 @@ union f32_u {
|
||||||
};
|
};
|
||||||
|
|
||||||
union f16_u {
|
union f16_u {
|
||||||
uint16_t i;
|
uint16_t ui;
|
||||||
struct {
|
struct {
|
||||||
unsigned int fraction:10;
|
unsigned int fraction:10;
|
||||||
unsigned int exponent:5;
|
unsigned int exponent:5;
|
||||||
|
@ -222,5 +222,19 @@ uint16_t FloatToHalf(float in)
|
||||||
f16.pack.fraction = f32.pack.fraction >> 13;
|
f16.pack.fraction = f32.pack.fraction >> 13;
|
||||||
f16.pack.sign = f32.pack.sign;
|
f16.pack.sign = f32.pack.sign;
|
||||||
|
|
||||||
return f16.i;
|
return f16.ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
float HalfToFloat(uint16_t in)
|
||||||
|
{
|
||||||
|
union f32_u f32;
|
||||||
|
union f16_u f16;
|
||||||
|
|
||||||
|
f16.ui = in;
|
||||||
|
|
||||||
|
f32.pack.exponent = (int)(f16.pack.exponent) + 112;
|
||||||
|
f32.pack.fraction = f16.pack.fraction << 13;
|
||||||
|
f32.pack.sign = f16.pack.sign;
|
||||||
|
|
||||||
|
return f32.f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,13 +44,17 @@ void Mat4SimpleInverse( const mat4_t in, mat4_t out);
|
||||||
#define VectorCopy2(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1])
|
#define VectorCopy2(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1])
|
||||||
#define VectorSet2(v,x,y) ((v)[0]=(x),(v)[1]=(y));
|
#define VectorSet2(v,x,y) ((v)[0]=(x),(v)[1]=(y));
|
||||||
|
|
||||||
|
#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
|
||||||
|
#define VectorSet4(v,x,y,z,w) ((v)[0]=(x),(v)[1]=(y),(v)[2]=(z),(v)[3]=(w))
|
||||||
|
#define VectorScale4(a,b,c) ((c)[0]=(a)[0]*(b),(c)[1]=(a)[1]*(b),(c)[2]=(a)[2]*(b),(c)[3]=(a)[3]*(b))
|
||||||
|
|
||||||
|
#define VectorCopy5(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3],(b)[4]=(a)[4])
|
||||||
|
|
||||||
#define OffsetByteToFloat(a) ((float)(a) * 1.0f/127.5f - 1.0f)
|
#define OffsetByteToFloat(a) ((float)(a) * 1.0f/127.5f - 1.0f)
|
||||||
#define FloatToOffsetByte(a) (byte)((a) * 127.5f + 128.0f)
|
#define FloatToOffsetByte(a) (byte)((a) * 127.5f + 128.0f)
|
||||||
#define ByteToFloat(a) ((float)(a) * 1.0f/255.0f)
|
#define ByteToFloat(a) ((float)(a) * 1.0f/255.0f)
|
||||||
#define FloatToByte(a) (byte)((a) * 255.0f)
|
#define FloatToByte(a) (byte)((a) * 255.0f)
|
||||||
|
|
||||||
void VectorLerp( const vec3_t a, const vec3_t b, float lerp, vec3_t c);
|
|
||||||
|
|
||||||
|
|
||||||
qboolean SpheresIntersect(vec3_t origin1, float radius1, vec3_t origin2, float radius2);
|
qboolean SpheresIntersect(vec3_t origin1, float radius1, vec3_t origin2, float radius2);
|
||||||
void BoundingSphereOfSpheres(vec3_t origin1, float radius1, vec3_t origin2, float radius2, vec3_t origin3, float *radius3);
|
void BoundingSphereOfSpheres(vec3_t origin1, float radius1, vec3_t origin2, float radius2, vec3_t origin3, float *radius3);
|
||||||
|
@ -73,5 +77,6 @@ void BoundingSphereOfSpheres(vec3_t origin1, float radius1, vec3_t origin2, floa
|
||||||
|
|
||||||
int NextPowerOfTwo(int in);
|
int NextPowerOfTwo(int in);
|
||||||
unsigned short FloatToHalf(float in);
|
unsigned short FloatToHalf(float in);
|
||||||
|
float HalfToFloat(unsigned short in);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
// tr_fbo.c
|
// tr_fbo.c
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
#include "tr_dsa.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
R_CheckFBO
|
R_CheckFBO
|
||||||
|
@ -30,66 +32,43 @@ R_CheckFBO
|
||||||
*/
|
*/
|
||||||
qboolean R_CheckFBO(const FBO_t * fbo)
|
qboolean R_CheckFBO(const FBO_t * fbo)
|
||||||
{
|
{
|
||||||
int code;
|
GLenum code = qglCheckNamedFramebufferStatusEXT(fbo->frameBuffer, GL_FRAMEBUFFER);
|
||||||
int id;
|
|
||||||
|
|
||||||
qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &id);
|
if(code == GL_FRAMEBUFFER_COMPLETE)
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer);
|
|
||||||
|
|
||||||
code = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
|
||||||
|
|
||||||
if(code == GL_FRAMEBUFFER_COMPLETE_EXT)
|
|
||||||
{
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
|
|
||||||
return qtrue;
|
return qtrue;
|
||||||
}
|
|
||||||
|
|
||||||
// an error occured
|
// an error occurred
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
case GL_FRAMEBUFFER_UNSUPPORTED:
|
||||||
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Unsupported framebuffer format\n", fbo->name);
|
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Unsupported framebuffer format\n", fbo->name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
||||||
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete attachment\n", fbo->name);
|
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete attachment\n", fbo->name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
||||||
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing attachment\n", fbo->name);
|
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing attachment\n", fbo->name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
|
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
|
||||||
// ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, duplicate attachment\n", fbo->name);
|
|
||||||
// break;
|
|
||||||
|
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
|
||||||
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, attached images must have same dimensions\n",
|
|
||||||
fbo->name);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
|
||||||
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, attached images must have same format\n",
|
|
||||||
fbo->name);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
|
||||||
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing draw buffer\n", fbo->name);
|
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing draw buffer\n", fbo->name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
|
||||||
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing read buffer\n", fbo->name);
|
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing read buffer\n", fbo->name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
|
||||||
|
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete multisample\n", fbo->name);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) unknown error 0x%X\n", fbo->name, code);
|
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) unknown error 0x%X\n", fbo->name, code);
|
||||||
//ri.Error(ERR_FATAL, "R_CheckFBO: (%s) unknown error 0x%X", fbo->name, code);
|
|
||||||
//assert(0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
|
|
||||||
|
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,11 +107,16 @@ FBO_t *FBO_Create(const char *name, int width, int height)
|
||||||
fbo->width = width;
|
fbo->width = width;
|
||||||
fbo->height = height;
|
fbo->height = height;
|
||||||
|
|
||||||
qglGenFramebuffersEXT(1, &fbo->frameBuffer);
|
qglGenFramebuffers(1, &fbo->frameBuffer);
|
||||||
|
|
||||||
return fbo;
|
return fbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
FBO_CreateBuffer
|
||||||
|
=================
|
||||||
|
*/
|
||||||
void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
|
void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
|
||||||
{
|
{
|
||||||
uint32_t *pRenderBuffer;
|
uint32_t *pRenderBuffer;
|
||||||
|
@ -151,7 +135,7 @@ void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
|
||||||
case GL_RGBA32F_ARB:
|
case GL_RGBA32F_ARB:
|
||||||
fbo->colorFormat = format;
|
fbo->colorFormat = format;
|
||||||
pRenderBuffer = &fbo->colorBuffers[index];
|
pRenderBuffer = &fbo->colorBuffers[index];
|
||||||
attachment = GL_COLOR_ATTACHMENT0_EXT + index;
|
attachment = GL_COLOR_ATTACHMENT0 + index;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_DEPTH_COMPONENT:
|
case GL_DEPTH_COMPONENT:
|
||||||
|
@ -160,21 +144,21 @@ void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
|
||||||
case GL_DEPTH_COMPONENT32_ARB:
|
case GL_DEPTH_COMPONENT32_ARB:
|
||||||
fbo->depthFormat = format;
|
fbo->depthFormat = format;
|
||||||
pRenderBuffer = &fbo->depthBuffer;
|
pRenderBuffer = &fbo->depthBuffer;
|
||||||
attachment = GL_DEPTH_ATTACHMENT_EXT;
|
attachment = GL_DEPTH_ATTACHMENT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_STENCIL_INDEX:
|
case GL_STENCIL_INDEX:
|
||||||
case GL_STENCIL_INDEX1_EXT:
|
case GL_STENCIL_INDEX1:
|
||||||
case GL_STENCIL_INDEX4_EXT:
|
case GL_STENCIL_INDEX4:
|
||||||
case GL_STENCIL_INDEX8_EXT:
|
case GL_STENCIL_INDEX8:
|
||||||
case GL_STENCIL_INDEX16_EXT:
|
case GL_STENCIL_INDEX16:
|
||||||
fbo->stencilFormat = format;
|
fbo->stencilFormat = format;
|
||||||
pRenderBuffer = &fbo->stencilBuffer;
|
pRenderBuffer = &fbo->stencilBuffer;
|
||||||
attachment = GL_STENCIL_ATTACHMENT_EXT;
|
attachment = GL_STENCIL_ATTACHMENT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_DEPTH_STENCIL_EXT:
|
case GL_DEPTH_STENCIL:
|
||||||
case GL_DEPTH24_STENCIL8_EXT:
|
case GL_DEPTH24_STENCIL8:
|
||||||
fbo->packedDepthStencilFormat = format;
|
fbo->packedDepthStencilFormat = format;
|
||||||
pRenderBuffer = &fbo->packedDepthStencilBuffer;
|
pRenderBuffer = &fbo->packedDepthStencilBuffer;
|
||||||
attachment = 0; // special for stencil and depth
|
attachment = 0; // special for stencil and depth
|
||||||
|
@ -187,117 +171,47 @@ void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
|
||||||
|
|
||||||
absent = *pRenderBuffer == 0;
|
absent = *pRenderBuffer == 0;
|
||||||
if (absent)
|
if (absent)
|
||||||
qglGenRenderbuffersEXT(1, pRenderBuffer);
|
qglGenRenderbuffers(1, pRenderBuffer);
|
||||||
|
|
||||||
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
|
||||||
if (multisample && glRefConfig.framebufferMultisample)
|
if (multisample && glRefConfig.framebufferMultisample)
|
||||||
{
|
qglNamedRenderbufferStorageMultisampleEXT(*pRenderBuffer, multisample, format, fbo->width, fbo->height);
|
||||||
qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multisample, format, fbo->width, fbo->height);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
qglNamedRenderbufferStorageEXT(*pRenderBuffer, format, fbo->width, fbo->height);
|
||||||
qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, fbo->width, fbo->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(absent)
|
if(absent)
|
||||||
{
|
{
|
||||||
if (attachment == 0)
|
if (attachment == 0)
|
||||||
{
|
{
|
||||||
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
qglNamedFramebufferRenderbufferEXT(fbo->frameBuffer, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *pRenderBuffer);
|
||||||
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
qglNamedFramebufferRenderbufferEXT(fbo->frameBuffer, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *pRenderBuffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
{
|
||||||
|
qglNamedFramebufferRenderbufferEXT(fbo->frameBuffer, attachment, GL_RENDERBUFFER, *pRenderBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
R_AttachFBOTexture1D
|
FBO_AttachImage
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void R_AttachFBOTexture1D(int texId, int index)
|
void FBO_AttachImage(FBO_t *fbo, image_t *image, GLenum attachment, GLuint cubemapside)
|
||||||
{
|
{
|
||||||
if(index < 0 || index >= glRefConfig.maxColorAttachments)
|
GLenum target = GL_TEXTURE_2D;
|
||||||
{
|
int index;
|
||||||
ri.Printf(PRINT_WARNING, "R_AttachFBOTexture1D: invalid attachment index %i\n", index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qglFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_1D, texId, 0);
|
if (image->flags & IMGFLAG_CUBEMAP)
|
||||||
|
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + cubemapside;
|
||||||
|
|
||||||
|
qglNamedFramebufferTexture2DEXT(fbo->frameBuffer, attachment, target, image->texnum, 0);
|
||||||
|
index = attachment - GL_COLOR_ATTACHMENT0;
|
||||||
|
if (index >= 0 && index <= 15)
|
||||||
|
fbo->colorImage[index] = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_AttachFBOTexture2D
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_AttachFBOTexture2D(int target, int texId, int index)
|
|
||||||
{
|
|
||||||
if(target != GL_TEXTURE_2D && (target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB))
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid target %i\n", target);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(index < 0 || index >= glRefConfig.maxColorAttachments)
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid attachment index %i\n", index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, target, texId, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_AttachFBOTexture3D
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_AttachFBOTexture3D(int texId, int index, int zOffset)
|
|
||||||
{
|
|
||||||
if(index < 0 || index >= glRefConfig.maxColorAttachments)
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_WARNING, "R_AttachFBOTexture3D: invalid attachment index %i\n", index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qglFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_3D_EXT, texId, 0, zOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_AttachFBOTextureDepth
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_AttachFBOTextureDepth(int texId)
|
|
||||||
{
|
|
||||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_AttachFBOTexturePackedDepthStencil
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_AttachFBOTexturePackedDepthStencil(int texId)
|
|
||||||
{
|
|
||||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
|
|
||||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FBO_AttachTextureImage(image_t *img, int index)
|
|
||||||
{
|
|
||||||
if (!glState.currentFBO)
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_WARNING, "FBO: attempted to attach a texture image with no FBO bound!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
R_AttachFBOTexture2D(GL_TEXTURE_2D, img->texnum, index);
|
|
||||||
glState.currentFBO->colorImage[index] = img;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
============
|
============
|
||||||
|
@ -306,44 +220,22 @@ FBO_Bind
|
||||||
*/
|
*/
|
||||||
void FBO_Bind(FBO_t * fbo)
|
void FBO_Bind(FBO_t * fbo)
|
||||||
{
|
{
|
||||||
|
if (!glRefConfig.framebufferObject)
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_WARNING, "FBO_Bind() called without framebuffers enabled!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (glState.currentFBO == fbo)
|
if (glState.currentFBO == fbo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (r_logFile->integer)
|
if (r_logFile->integer)
|
||||||
{
|
{
|
||||||
// don't just call LogComment, or we will get a call to va() every frame!
|
// don't just call LogComment, or we will get a call to va() every frame!
|
||||||
if (fbo)
|
GLimp_LogComment(va("--- FBO_Bind( %s ) ---\n", fbo ? fbo->name : "NULL"));
|
||||||
GLimp_LogComment(va("--- FBO_Bind( %s ) ---\n", fbo->name));
|
|
||||||
else
|
|
||||||
GLimp_LogComment("--- FBO_Bind ( NULL ) ---\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fbo)
|
GL_BindFramebuffer(GL_FRAMEBUFFER, fbo ? fbo->frameBuffer : 0);
|
||||||
{
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
||||||
//qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
|
||||||
glState.currentFBO = NULL;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(fbo->colorBuffers[0])
|
|
||||||
{
|
|
||||||
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->colorBuffers[0]);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(fbo->depthBuffer)
|
|
||||||
{
|
|
||||||
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->depthBuffer);
|
|
||||||
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthBuffer);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
glState.currentFBO = fbo;
|
glState.currentFBO = fbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,8 +247,7 @@ FBO_Init
|
||||||
void FBO_Init(void)
|
void FBO_Init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
// int width, height, hdrFormat, multisample;
|
int hdrFormat, multisample = 0;
|
||||||
int hdrFormat, multisample;
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, "------- FBO_Init -------\n");
|
ri.Printf(PRINT_ALL, "------- FBO_Init -------\n");
|
||||||
|
|
||||||
|
@ -369,36 +260,22 @@ void FBO_Init(void)
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
R_IssuePendingRenderCommands();
|
||||||
|
|
||||||
/* if(glRefConfig.textureNonPowerOfTwo)
|
|
||||||
{
|
|
||||||
width = glConfig.vidWidth;
|
|
||||||
height = glConfig.vidHeight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
width = NextPowerOfTwo(glConfig.vidWidth);
|
|
||||||
height = NextPowerOfTwo(glConfig.vidHeight);
|
|
||||||
} */
|
|
||||||
|
|
||||||
hdrFormat = GL_RGBA8;
|
hdrFormat = GL_RGBA8;
|
||||||
if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat)
|
if (r_hdr->integer && glRefConfig.textureFloat)
|
||||||
{
|
|
||||||
hdrFormat = GL_RGBA16F_ARB;
|
hdrFormat = GL_RGBA16F_ARB;
|
||||||
}
|
|
||||||
|
|
||||||
qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample);
|
if (glRefConfig.framebufferMultisample)
|
||||||
|
qglGetIntegerv(GL_MAX_SAMPLES, &multisample);
|
||||||
|
|
||||||
if (r_ext_framebuffer_multisample->integer < multisample)
|
if (r_ext_framebuffer_multisample->integer < multisample)
|
||||||
{
|
|
||||||
multisample = r_ext_framebuffer_multisample->integer;
|
multisample = r_ext_framebuffer_multisample->integer;
|
||||||
}
|
|
||||||
|
|
||||||
if (multisample < 2 || !glRefConfig.framebufferBlit)
|
if (multisample < 2 || !glRefConfig.framebufferBlit)
|
||||||
multisample = 0;
|
multisample = 0;
|
||||||
|
|
||||||
if (multisample != r_ext_framebuffer_multisample->integer)
|
if (multisample != r_ext_framebuffer_multisample->integer) {
|
||||||
{
|
char buf[10];
|
||||||
ri.Cvar_Set( "r_ext_framebuffer_multisample", va( "%f", ( float )multisample ) );
|
ri.Cvar_Set("r_ext_framebuffer_multisample", itoa(multisample, buf, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
// only create a render FBO if we need to resolve MSAA or do HDR
|
// only create a render FBO if we need to resolve MSAA or do HDR
|
||||||
|
@ -406,36 +283,20 @@ void FBO_Init(void)
|
||||||
if (multisample && glRefConfig.framebufferMultisample)
|
if (multisample && glRefConfig.framebufferMultisample)
|
||||||
{
|
{
|
||||||
tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
||||||
FBO_Bind(tr.renderFbo);
|
|
||||||
|
|
||||||
FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, multisample);
|
FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, multisample);
|
||||||
FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, multisample);
|
FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24, 0, multisample);
|
||||||
|
|
||||||
R_CheckFBO(tr.renderFbo);
|
R_CheckFBO(tr.renderFbo);
|
||||||
|
|
||||||
|
|
||||||
tr.msaaResolveFbo = FBO_Create("_msaaResolve", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
tr.msaaResolveFbo = FBO_Create("_msaaResolve", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
||||||
FBO_Bind(tr.msaaResolveFbo);
|
FBO_AttachImage(tr.msaaResolveFbo, tr.renderImage, GL_COLOR_ATTACHMENT0, 0);
|
||||||
|
FBO_AttachImage(tr.msaaResolveFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT, 0);
|
||||||
//FBO_CreateBuffer(tr.msaaResolveFbo, hdrFormat, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.renderImage, 0);
|
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.msaaResolveFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
|
||||||
R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.msaaResolveFbo);
|
R_CheckFBO(tr.msaaResolveFbo);
|
||||||
}
|
}
|
||||||
else if (r_hdr->integer)
|
else if (r_hdr->integer)
|
||||||
{
|
{
|
||||||
tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
||||||
FBO_Bind(tr.renderFbo);
|
FBO_AttachImage(tr.renderFbo, tr.renderImage, GL_COLOR_ATTACHMENT0, 0);
|
||||||
|
FBO_AttachImage(tr.renderFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT, 0);
|
||||||
//FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.renderImage, 0);
|
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
|
||||||
R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.renderFbo);
|
R_CheckFBO(tr.renderFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,144 +304,118 @@ void FBO_Init(void)
|
||||||
// this fixes the corrupt screen bug with r_hdr 1 on older hardware
|
// this fixes the corrupt screen bug with r_hdr 1 on older hardware
|
||||||
if (tr.renderFbo)
|
if (tr.renderFbo)
|
||||||
{
|
{
|
||||||
FBO_Bind(tr.renderFbo);
|
GL_BindFramebuffer(GL_FRAMEBUFFER, tr.renderFbo->frameBuffer);
|
||||||
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
FBO_Bind(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_drawSunRays->integer)
|
if (tr.screenScratchImage)
|
||||||
|
{
|
||||||
|
tr.screenScratchFbo = FBO_Create("screenScratch", tr.screenScratchImage->width, tr.screenScratchImage->height);
|
||||||
|
FBO_AttachImage(tr.screenScratchFbo, tr.screenScratchImage, GL_COLOR_ATTACHMENT0, 0);
|
||||||
|
FBO_AttachImage(tr.screenScratchFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT, 0);
|
||||||
|
R_CheckFBO(tr.screenScratchFbo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tr.sunRaysImage)
|
||||||
{
|
{
|
||||||
tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
||||||
FBO_Bind(tr.sunRaysFbo);
|
FBO_AttachImage(tr.sunRaysFbo, tr.sunRaysImage, GL_COLOR_ATTACHMENT0, 0);
|
||||||
|
FBO_AttachImage(tr.sunRaysFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT, 0);
|
||||||
FBO_AttachTextureImage(tr.sunRaysImage, 0);
|
|
||||||
|
|
||||||
R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.sunRaysFbo);
|
R_CheckFBO(tr.sunRaysFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Don't use separate color/depth buffers for a shadow buffer
|
|
||||||
if (MAX_DRAWN_PSHADOWS && tr.pshadowMaps[0])
|
if (MAX_DRAWN_PSHADOWS && tr.pshadowMaps[0])
|
||||||
{
|
{
|
||||||
for( i = 0; i < MAX_DRAWN_PSHADOWS; i++)
|
for( i = 0; i < MAX_DRAWN_PSHADOWS; i++)
|
||||||
{
|
{
|
||||||
tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height);
|
tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height);
|
||||||
FBO_Bind(tr.pshadowFbos[i]);
|
// FIXME: this next line wastes 16mb with 16x512x512 sun shadow maps, skip if OpenGL 4.3+ or ARB_framebuffer_no_attachments
|
||||||
|
FBO_CreateBuffer(tr.pshadowFbos[i], GL_RGBA8, 0, 0);
|
||||||
//FBO_CreateBuffer(tr.pshadowFbos[i], GL_RGBA8, 0, 0);
|
FBO_AttachImage(tr.pshadowFbos[i], tr.pshadowMaps[i], GL_DEPTH_ATTACHMENT, 0);
|
||||||
FBO_AttachTextureImage(tr.pshadowMaps[i], 0);
|
|
||||||
|
|
||||||
FBO_CreateBuffer(tr.pshadowFbos[i], GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
|
||||||
//R_AttachFBOTextureDepth(tr.textureDepthImage->texnum);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.pshadowFbos[i]);
|
R_CheckFBO(tr.pshadowFbos[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tr.sunShadowDepthImage[0])
|
if (tr.sunShadowDepthImage[0])
|
||||||
{
|
{
|
||||||
for ( i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
|
tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
|
||||||
FBO_Bind(tr.sunShadowFbo[i]);
|
// FIXME: this next line wastes 16mb with 4x1024x1024 sun shadow maps, skip if OpenGL 4.3+ or ARB_framebuffer_no_attachments
|
||||||
|
// This at least gets sun shadows working on older GPUs (Intel)
|
||||||
//FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0);
|
FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0);
|
||||||
//FBO_AttachTextureImage(tr.sunShadowImage, 0);
|
FBO_AttachImage(tr.sunShadowFbo[i], tr.sunShadowDepthImage[i], GL_DEPTH_ATTACHMENT, 0);
|
||||||
qglDrawBuffer(GL_NONE);
|
|
||||||
qglReadBuffer(GL_NONE);
|
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.sunShadowFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
|
||||||
R_AttachFBOTextureDepth(tr.sunShadowDepthImage[i]->texnum);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.sunShadowFbo[i]);
|
R_CheckFBO(tr.sunShadowFbo[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tr.screenShadowImage)
|
||||||
|
{
|
||||||
tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height);
|
tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height);
|
||||||
FBO_Bind(tr.screenShadowFbo);
|
FBO_AttachImage(tr.screenShadowFbo, tr.screenShadowImage, GL_COLOR_ATTACHMENT0, 0);
|
||||||
|
|
||||||
FBO_AttachTextureImage(tr.screenShadowImage, 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.screenShadowFbo);
|
R_CheckFBO(tr.screenShadowFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
if (tr.textureScratchImage[0])
|
||||||
{
|
{
|
||||||
tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height);
|
for (i = 0; i < 2; i++)
|
||||||
FBO_Bind(tr.textureScratchFbo[i]);
|
{
|
||||||
|
tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height);
|
||||||
//FBO_CreateBuffer(tr.textureScratchFbo[i], GL_RGBA8, 0, 0);
|
FBO_AttachImage(tr.textureScratchFbo[i], tr.textureScratchImage[i], GL_COLOR_ATTACHMENT0, 0);
|
||||||
FBO_AttachTextureImage(tr.textureScratchImage[i], 0);
|
R_CheckFBO(tr.textureScratchFbo[i]);
|
||||||
|
}
|
||||||
R_CheckFBO(tr.textureScratchFbo[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tr.calcLevelsImage)
|
||||||
{
|
{
|
||||||
tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height);
|
tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height);
|
||||||
FBO_Bind(tr.calcLevelsFbo);
|
FBO_AttachImage(tr.calcLevelsFbo, tr.calcLevelsImage, GL_COLOR_ATTACHMENT0, 0);
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.calcLevelsFbo, hdrFormat, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.calcLevelsImage, 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.calcLevelsFbo);
|
R_CheckFBO(tr.calcLevelsFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tr.targetLevelsImage)
|
||||||
{
|
{
|
||||||
tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height);
|
tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height);
|
||||||
FBO_Bind(tr.targetLevelsFbo);
|
FBO_AttachImage(tr.targetLevelsFbo, tr.targetLevelsImage, GL_COLOR_ATTACHMENT0, 0);
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.targetLevelsFbo, hdrFormat, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.targetLevelsImage, 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.targetLevelsFbo);
|
R_CheckFBO(tr.targetLevelsFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
if (tr.quarterImage[0])
|
||||||
{
|
{
|
||||||
tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height);
|
for (i = 0; i < 2; i++)
|
||||||
FBO_Bind(tr.quarterFbo[i]);
|
{
|
||||||
|
tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height);
|
||||||
//FBO_CreateBuffer(tr.quarterFbo[i], hdrFormat, 0, 0);
|
FBO_AttachImage(tr.quarterFbo[i], tr.quarterImage[i], GL_COLOR_ATTACHMENT0, 0);
|
||||||
FBO_AttachTextureImage(tr.quarterImage[i], 0);
|
R_CheckFBO(tr.quarterFbo[i]);
|
||||||
|
}
|
||||||
R_CheckFBO(tr.quarterFbo[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_ssao->integer)
|
if (tr.hdrDepthImage)
|
||||||
{
|
{
|
||||||
tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height);
|
tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height);
|
||||||
FBO_Bind(tr.hdrDepthFbo);
|
FBO_AttachImage(tr.hdrDepthFbo, tr.hdrDepthImage, GL_COLOR_ATTACHMENT0, 0);
|
||||||
|
|
||||||
FBO_AttachTextureImage(tr.hdrDepthImage, 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.hdrDepthFbo);
|
R_CheckFBO(tr.hdrDepthFbo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tr.screenSsaoImage)
|
||||||
|
{
|
||||||
tr.screenSsaoFbo = FBO_Create("_screenssao", tr.screenSsaoImage->width, tr.screenSsaoImage->height);
|
tr.screenSsaoFbo = FBO_Create("_screenssao", tr.screenSsaoImage->width, tr.screenSsaoImage->height);
|
||||||
FBO_Bind(tr.screenSsaoFbo);
|
FBO_AttachImage(tr.screenSsaoFbo, tr.screenSsaoImage, GL_COLOR_ATTACHMENT0, 0);
|
||||||
|
|
||||||
FBO_AttachTextureImage(tr.screenSsaoImage, 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.screenSsaoFbo);
|
R_CheckFBO(tr.screenSsaoFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tr.renderCubeImage)
|
if (tr.renderCubeImage)
|
||||||
{
|
{
|
||||||
tr.renderCubeFbo = FBO_Create("_renderCubeFbo", tr.renderCubeImage->width, tr.renderCubeImage->height);
|
tr.renderCubeFbo = FBO_Create("_renderCubeFbo", tr.renderCubeImage->width, tr.renderCubeImage->height);
|
||||||
FBO_Bind(tr.renderCubeFbo);
|
FBO_AttachImage(tr.renderCubeFbo, tr.renderCubeImage, GL_COLOR_ATTACHMENT0, 0);
|
||||||
|
|
||||||
//FBO_AttachTextureImage(tr.renderCubeImage, 0);
|
|
||||||
R_AttachFBOTexture2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, tr.renderCubeImage->texnum, 0);
|
|
||||||
glState.currentFBO->colorImage[0] = tr.renderCubeImage;
|
|
||||||
|
|
||||||
FBO_CreateBuffer(tr.renderCubeFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
FBO_CreateBuffer(tr.renderCubeFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
||||||
|
|
||||||
R_CheckFBO(tr.renderCubeFbo);
|
R_CheckFBO(tr.renderCubeFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_CheckErrors();
|
GL_CheckErrors();
|
||||||
|
|
||||||
FBO_Bind(NULL);
|
GL_BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
glState.currentFBO = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -607,17 +442,17 @@ void FBO_Shutdown(void)
|
||||||
for(j = 0; j < glRefConfig.maxColorAttachments; j++)
|
for(j = 0; j < glRefConfig.maxColorAttachments; j++)
|
||||||
{
|
{
|
||||||
if(fbo->colorBuffers[j])
|
if(fbo->colorBuffers[j])
|
||||||
qglDeleteRenderbuffersEXT(1, &fbo->colorBuffers[j]);
|
qglDeleteRenderbuffers(1, &fbo->colorBuffers[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fbo->depthBuffer)
|
if(fbo->depthBuffer)
|
||||||
qglDeleteRenderbuffersEXT(1, &fbo->depthBuffer);
|
qglDeleteRenderbuffers(1, &fbo->depthBuffer);
|
||||||
|
|
||||||
if(fbo->stencilBuffer)
|
if(fbo->stencilBuffer)
|
||||||
qglDeleteRenderbuffersEXT(1, &fbo->stencilBuffer);
|
qglDeleteRenderbuffers(1, &fbo->stencilBuffer);
|
||||||
|
|
||||||
if(fbo->frameBuffer)
|
if(fbo->frameBuffer)
|
||||||
qglDeleteFramebuffersEXT(1, &fbo->frameBuffer);
|
qglDeleteFramebuffers(1, &fbo->frameBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,10 +485,9 @@ void R_FBOList_f(void)
|
||||||
ri.Printf(PRINT_ALL, " %i FBOs\n", tr.numFBOs);
|
ri.Printf(PRINT_ALL, " %i FBOs\n", tr.numFBOs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend)
|
void FBO_BlitFromTexture(struct image_s *src, vec4_t inSrcTexCorners, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend)
|
||||||
{
|
{
|
||||||
ivec4_t dstBox, srcBox;
|
ivec4_t dstBox;
|
||||||
vec2_t srcTexScale;
|
|
||||||
vec4_t color;
|
vec4_t color;
|
||||||
vec4_t quadVerts[4];
|
vec4_t quadVerts[4];
|
||||||
vec2_t texCoords[4];
|
vec2_t texCoords[4];
|
||||||
|
@ -663,51 +497,49 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
if (!src)
|
if (!src)
|
||||||
return;
|
|
||||||
|
|
||||||
if (inSrcBox)
|
|
||||||
{
|
{
|
||||||
VectorSet4(srcBox, inSrcBox[0], inSrcBox[1], inSrcBox[0] + inSrcBox[2], inSrcBox[1] + inSrcBox[3]);
|
ri.Printf(PRINT_WARNING, "Tried to blit from a NULL texture!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
width = dst ? dst->width : glConfig.vidWidth;
|
||||||
|
height = dst ? dst->height : glConfig.vidHeight;
|
||||||
|
|
||||||
|
if (inSrcTexCorners)
|
||||||
|
{
|
||||||
|
VectorSet2(texCoords[0], inSrcTexCorners[0], inSrcTexCorners[1]);
|
||||||
|
VectorSet2(texCoords[1], inSrcTexCorners[2], inSrcTexCorners[1]);
|
||||||
|
VectorSet2(texCoords[2], inSrcTexCorners[2], inSrcTexCorners[3]);
|
||||||
|
VectorSet2(texCoords[3], inSrcTexCorners[0], inSrcTexCorners[3]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VectorSet4(srcBox, 0, 0, src->width, src->height);
|
VectorSet2(texCoords[0], 0.0f, 1.0f);
|
||||||
|
VectorSet2(texCoords[1], 1.0f, 1.0f);
|
||||||
|
VectorSet2(texCoords[2], 1.0f, 0.0f);
|
||||||
|
VectorSet2(texCoords[3], 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// framebuffers are 0 bottom, Y up.
|
// framebuffers are 0 bottom, Y up.
|
||||||
if (inDstBox)
|
if (inDstBox)
|
||||||
{
|
{
|
||||||
if (dst)
|
dstBox[0] = inDstBox[0];
|
||||||
{
|
dstBox[1] = height - inDstBox[1] - inDstBox[3];
|
||||||
dstBox[0] = inDstBox[0];
|
dstBox[2] = inDstBox[0] + inDstBox[2];
|
||||||
dstBox[1] = dst->height - inDstBox[1] - inDstBox[3];
|
dstBox[3] = height - inDstBox[1];
|
||||||
dstBox[2] = inDstBox[0] + inDstBox[2];
|
|
||||||
dstBox[3] = dst->height - inDstBox[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dstBox[0] = inDstBox[0];
|
|
||||||
dstBox[1] = glConfig.vidHeight - inDstBox[1] - inDstBox[3];
|
|
||||||
dstBox[2] = inDstBox[0] + inDstBox[2];
|
|
||||||
dstBox[3] = glConfig.vidHeight - inDstBox[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (dst)
|
|
||||||
{
|
|
||||||
VectorSet4(dstBox, 0, dst->height, dst->width, 0);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VectorSet4(dstBox, 0, glConfig.vidHeight, glConfig.vidWidth, 0);
|
VectorSet4(dstBox, 0, height, width, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inSrcTexScale)
|
if (inSrcTexScale)
|
||||||
{
|
{
|
||||||
VectorCopy2(inSrcTexScale, srcTexScale);
|
VectorCopy2(inSrcTexScale, invTexRes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
srcTexScale[0] = srcTexScale[1] = 1.0f;
|
VectorSet2(invTexRes, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inColor)
|
if (inColor)
|
||||||
|
@ -726,17 +558,6 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS
|
||||||
|
|
||||||
FBO_Bind(dst);
|
FBO_Bind(dst);
|
||||||
|
|
||||||
if (glState.currentFBO)
|
|
||||||
{
|
|
||||||
width = glState.currentFBO->width;
|
|
||||||
height = glState.currentFBO->height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
width = glConfig.vidWidth;
|
|
||||||
height = glConfig.vidHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
qglViewport( 0, 0, width, height );
|
qglViewport( 0, 0, width, height );
|
||||||
qglScissor( 0, 0, width, height );
|
qglScissor( 0, 0, width, height );
|
||||||
|
|
||||||
|
@ -746,18 +567,13 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS
|
||||||
|
|
||||||
GL_BindToTMU(src, TB_COLORMAP);
|
GL_BindToTMU(src, TB_COLORMAP);
|
||||||
|
|
||||||
VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0, 1);
|
VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0.0f, 1.0f);
|
||||||
VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0, 1);
|
VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0.0f, 1.0f);
|
||||||
VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0, 1);
|
VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0.0f, 1.0f);
|
||||||
VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0, 1);
|
VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0.0f, 1.0f);
|
||||||
|
|
||||||
texCoords[0][0] = srcBox[0] / (float)src->width; texCoords[0][1] = 1.0f - srcBox[1] / (float)src->height;
|
invTexRes[0] /= src->width;
|
||||||
texCoords[1][0] = srcBox[2] / (float)src->width; texCoords[1][1] = 1.0f - srcBox[1] / (float)src->height;
|
invTexRes[1] /= src->height;
|
||||||
texCoords[2][0] = srcBox[2] / (float)src->width; texCoords[2][1] = 1.0f - srcBox[3] / (float)src->height;
|
|
||||||
texCoords[3][0] = srcBox[0] / (float)src->width; texCoords[3][1] = 1.0f - srcBox[3] / (float)src->height;
|
|
||||||
|
|
||||||
invTexRes[0] = 1.0f / src->width * srcTexScale[0];
|
|
||||||
invTexRes[1] = 1.0f / src->height * srcTexScale[1];
|
|
||||||
|
|
||||||
GL_State( blend );
|
GL_State( blend );
|
||||||
|
|
||||||
|
@ -769,14 +585,14 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS
|
||||||
GLSL_SetUniformVec2(shaderProgram, UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax);
|
GLSL_SetUniformVec2(shaderProgram, UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax);
|
||||||
GLSL_SetUniformVec3(shaderProgram, UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear);
|
GLSL_SetUniformVec3(shaderProgram, UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear);
|
||||||
|
|
||||||
RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes);
|
RB_InstantQuad2(quadVerts, texCoords);
|
||||||
|
|
||||||
FBO_Bind(oldFbo);
|
FBO_Bind(oldFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBO_Blit(FBO_t *src, ivec4_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
|
void FBO_Blit(FBO_t *src, ivec4_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
|
||||||
{
|
{
|
||||||
ivec4_t srcBox;
|
vec4_t srcTexCorners;
|
||||||
|
|
||||||
if (!src)
|
if (!src)
|
||||||
{
|
{
|
||||||
|
@ -784,20 +600,19 @@ void FBO_Blit(FBO_t *src, ivec4_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, ivec
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// framebuffers are 0 bottom, Y up.
|
|
||||||
if (inSrcBox)
|
if (inSrcBox)
|
||||||
{
|
{
|
||||||
srcBox[0] = inSrcBox[0];
|
srcTexCorners[0] = inSrcBox[0] / (float)src->width;
|
||||||
srcBox[1] = src->height - inSrcBox[1] - inSrcBox[3];
|
srcTexCorners[1] = (inSrcBox[1] + inSrcBox[3]) / (float)src->height;
|
||||||
srcBox[2] = inSrcBox[2];
|
srcTexCorners[2] = (inSrcBox[0] + inSrcBox[2]) / (float)src->width;
|
||||||
srcBox[3] = inSrcBox[3];
|
srcTexCorners[3] = inSrcBox[1] / (float)src->height;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VectorSet4(srcBox, 0, src->height, src->width, -src->height);
|
VectorSet4(srcTexCorners, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
FBO_BlitFromTexture(src->colorImage[0], srcBox, srcTexScale, dst, dstBox, shaderProgram, color, blend | GLS_DEPTHTEST_DISABLE);
|
FBO_BlitFromTexture(src->colorImage[0], srcTexCorners, srcTexScale, dst, dstBox, shaderProgram, color, blend | GLS_DEPTHTEST_DISABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter)
|
void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter)
|
||||||
|
@ -811,22 +626,15 @@ void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int bu
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get to a neutral state first
|
|
||||||
//FBO_Bind(NULL);
|
|
||||||
|
|
||||||
srcFb = src ? src->frameBuffer : 0;
|
srcFb = src ? src->frameBuffer : 0;
|
||||||
dstFb = dst ? dst->frameBuffer : 0;
|
dstFb = dst ? dst->frameBuffer : 0;
|
||||||
|
|
||||||
if (!srcBox)
|
if (!srcBox)
|
||||||
{
|
{
|
||||||
if (src)
|
int width = src ? src->width : glConfig.vidWidth;
|
||||||
{
|
int height = src ? src->height : glConfig.vidHeight;
|
||||||
VectorSet4(srcBoxFinal, 0, 0, src->width, src->height);
|
|
||||||
}
|
VectorSet4(srcBoxFinal, 0, 0, width, height);
|
||||||
else
|
|
||||||
{
|
|
||||||
VectorSet4(srcBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -835,26 +643,22 @@ void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int bu
|
||||||
|
|
||||||
if (!dstBox)
|
if (!dstBox)
|
||||||
{
|
{
|
||||||
if (dst)
|
int width = dst ? dst->width : glConfig.vidWidth;
|
||||||
{
|
int height = dst ? dst->height : glConfig.vidHeight;
|
||||||
VectorSet4(dstBoxFinal, 0, 0, dst->width, dst->height);
|
|
||||||
}
|
VectorSet4(dstBoxFinal, 0, 0, width, height);
|
||||||
else
|
|
||||||
{
|
|
||||||
VectorSet4(dstBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[0] + dstBox[2], dstBox[1] + dstBox[3]);
|
VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[0] + dstBox[2], dstBox[1] + dstBox[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, srcFb);
|
GL_BindFramebuffer(GL_READ_FRAMEBUFFER, srcFb);
|
||||||
qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dstFb);
|
GL_BindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFb);
|
||||||
qglBlitFramebufferEXT(srcBoxFinal[0], srcBoxFinal[1], srcBoxFinal[2], srcBoxFinal[3],
|
qglBlitFramebuffer(srcBoxFinal[0], srcBoxFinal[1], srcBoxFinal[2], srcBoxFinal[3],
|
||||||
dstBoxFinal[0], dstBoxFinal[1], dstBoxFinal[2], dstBoxFinal[3],
|
dstBoxFinal[0], dstBoxFinal[1], dstBoxFinal[2], dstBoxFinal[3],
|
||||||
buffers, filter);
|
buffers, filter);
|
||||||
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
GL_BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
glState.currentFBO = NULL;
|
glState.currentFBO = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#ifndef __TR_FBO_H__
|
#ifndef __TR_FBO_H__
|
||||||
#define __TR_FBO_H__
|
#define __TR_FBO_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct image_s;
|
struct image_s;
|
||||||
struct shaderProgram_s;
|
struct shaderProgram_s;
|
||||||
|
|
||||||
|
@ -56,16 +52,14 @@ typedef struct FBO_s
|
||||||
int height;
|
int height;
|
||||||
} FBO_t;
|
} FBO_t;
|
||||||
|
|
||||||
|
void FBO_AttachImage(FBO_t *fbo, image_t *image, GLenum attachment, GLuint cubemapside);
|
||||||
void FBO_Bind(FBO_t *fbo);
|
void FBO_Bind(FBO_t *fbo);
|
||||||
void FBO_Init(void);
|
void FBO_Init(void);
|
||||||
void FBO_Shutdown(void);
|
void FBO_Shutdown(void);
|
||||||
|
|
||||||
void FBO_BlitFromTexture(struct image_s *src, ivec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
|
void FBO_BlitFromTexture(struct image_s *src, vec4_t inSrcTexCorners, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend);
|
||||||
void FBO_Blit(FBO_t *src, ivec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
|
void FBO_Blit(FBO_t *src, ivec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
|
||||||
void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter);
|
void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -395,51 +395,51 @@ void RB_RenderFlare( flare_t *f ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
iColor[0] = color[0] * fogFactors[0];
|
iColor[0] = color[0] * fogFactors[0] * 257;
|
||||||
iColor[1] = color[1] * fogFactors[1];
|
iColor[1] = color[1] * fogFactors[1] * 257;
|
||||||
iColor[2] = color[2] * fogFactors[2];
|
iColor[2] = color[2] * fogFactors[2] * 257;
|
||||||
|
|
||||||
RB_BeginSurface( tr.flareShader, f->fogNum, 0 );
|
RB_BeginSurface( tr.flareShader, f->fogNum, 0 );
|
||||||
|
|
||||||
// FIXME: use quadstamp?
|
// FIXME: use quadstamp?
|
||||||
tess.xyz[tess.numVertexes][0] = f->windowX - size;
|
tess.xyz[tess.numVertexes][0] = f->windowX - size;
|
||||||
tess.xyz[tess.numVertexes][1] = f->windowY - size;
|
tess.xyz[tess.numVertexes][1] = f->windowY - size;
|
||||||
tess.texCoords[tess.numVertexes][0][0] = 0;
|
tess.texCoords[tess.numVertexes][0] = 0;
|
||||||
tess.texCoords[tess.numVertexes][0][1] = 0;
|
tess.texCoords[tess.numVertexes][1] = 0;
|
||||||
tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f;
|
tess.color[tess.numVertexes][0] = iColor[0];
|
||||||
tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f;
|
tess.color[tess.numVertexes][1] = iColor[1];
|
||||||
tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f;
|
tess.color[tess.numVertexes][2] = iColor[2];
|
||||||
tess.vertexColors[tess.numVertexes][3] = 1.0f;
|
tess.color[tess.numVertexes][3] = 65535;
|
||||||
tess.numVertexes++;
|
tess.numVertexes++;
|
||||||
|
|
||||||
tess.xyz[tess.numVertexes][0] = f->windowX - size;
|
tess.xyz[tess.numVertexes][0] = f->windowX - size;
|
||||||
tess.xyz[tess.numVertexes][1] = f->windowY + size;
|
tess.xyz[tess.numVertexes][1] = f->windowY + size;
|
||||||
tess.texCoords[tess.numVertexes][0][0] = 0;
|
tess.texCoords[tess.numVertexes][0] = 0;
|
||||||
tess.texCoords[tess.numVertexes][0][1] = 1;
|
tess.texCoords[tess.numVertexes][1] = 1;
|
||||||
tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f;
|
tess.color[tess.numVertexes][0] = iColor[0];
|
||||||
tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f;
|
tess.color[tess.numVertexes][1] = iColor[1];
|
||||||
tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f;
|
tess.color[tess.numVertexes][2] = iColor[2];
|
||||||
tess.vertexColors[tess.numVertexes][3] = 1.0f;
|
tess.color[tess.numVertexes][3] = 65535;
|
||||||
tess.numVertexes++;
|
tess.numVertexes++;
|
||||||
|
|
||||||
tess.xyz[tess.numVertexes][0] = f->windowX + size;
|
tess.xyz[tess.numVertexes][0] = f->windowX + size;
|
||||||
tess.xyz[tess.numVertexes][1] = f->windowY + size;
|
tess.xyz[tess.numVertexes][1] = f->windowY + size;
|
||||||
tess.texCoords[tess.numVertexes][0][0] = 1;
|
tess.texCoords[tess.numVertexes][0] = 1;
|
||||||
tess.texCoords[tess.numVertexes][0][1] = 1;
|
tess.texCoords[tess.numVertexes][1] = 1;
|
||||||
tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f;
|
tess.color[tess.numVertexes][0] = iColor[0];
|
||||||
tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f;
|
tess.color[tess.numVertexes][1] = iColor[1];
|
||||||
tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f;
|
tess.color[tess.numVertexes][2] = iColor[2];
|
||||||
tess.vertexColors[tess.numVertexes][3] = 1.0f;
|
tess.color[tess.numVertexes][3] = 65535;
|
||||||
tess.numVertexes++;
|
tess.numVertexes++;
|
||||||
|
|
||||||
tess.xyz[tess.numVertexes][0] = f->windowX + size;
|
tess.xyz[tess.numVertexes][0] = f->windowX + size;
|
||||||
tess.xyz[tess.numVertexes][1] = f->windowY - size;
|
tess.xyz[tess.numVertexes][1] = f->windowY - size;
|
||||||
tess.texCoords[tess.numVertexes][0][0] = 1;
|
tess.texCoords[tess.numVertexes][0] = 1;
|
||||||
tess.texCoords[tess.numVertexes][0][1] = 0;
|
tess.texCoords[tess.numVertexes][1] = 0;
|
||||||
tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f;
|
tess.color[tess.numVertexes][0] = iColor[0];
|
||||||
tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f;
|
tess.color[tess.numVertexes][1] = iColor[1];
|
||||||
tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f;
|
tess.color[tess.numVertexes][2] = iColor[2];
|
||||||
tess.vertexColors[tess.numVertexes][3] = 1.0f;
|
tess.color[tess.numVertexes][3] = 65535;
|
||||||
tess.numVertexes++;
|
tess.numVertexes++;
|
||||||
|
|
||||||
tess.indexes[tess.numIndexes++] = 0;
|
tess.indexes[tess.numIndexes++] = 0;
|
||||||
|
@ -526,10 +526,6 @@ void RB_RenderFlares (void) {
|
||||||
return; // none visible
|
return; // none visible
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( backEnd.viewParms.isPortal ) {
|
|
||||||
qglDisable (GL_CLIP_PLANE0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4Copy(glState.projection, oldprojection);
|
Mat4Copy(glState.projection, oldprojection);
|
||||||
Mat4Copy(glState.modelview, oldmodelview);
|
Mat4Copy(glState.modelview, oldmodelview);
|
||||||
Mat4Identity(matrix);
|
Mat4Identity(matrix);
|
||||||
|
|
66
code/renderergl2/tr_font.cpp
Normal file
66
code/renderergl2/tr_font.cpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// tr_font.c -- font rendering
|
||||||
|
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
static int s_numLoadedFonts;
|
||||||
|
static float s_fontHeightScale;
|
||||||
|
static float s_fontGeneralScale;
|
||||||
|
static float s_fontZ;
|
||||||
|
|
||||||
|
void R_SetFontHeightScale(float scale)
|
||||||
|
{
|
||||||
|
// FIXME: unimplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_SetFontScale(float scale)
|
||||||
|
{
|
||||||
|
// FIXME: unimplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_SetFontZ(float zed)
|
||||||
|
{
|
||||||
|
// FIXME: unimplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
fontheader_t* R_LoadFont(const char* name)
|
||||||
|
{
|
||||||
|
// FIXME: unimplemented
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_DrawString(const fontheader_t* font, const char* text, float x, float y, int maxlen, qboolean bVirtualScreen) {
|
||||||
|
// FIXME: unimplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
float R_GetFontHeight(const fontheader_t* font)
|
||||||
|
{
|
||||||
|
// FIXME: unimplemented
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float R_GetFontStringWidth(const fontheader_t* font, const char* s)
|
||||||
|
{
|
||||||
|
// FIXME: unimplemented
|
||||||
|
return 0;
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
498
code/renderergl2/tr_image_dds.c
Normal file
498
code/renderergl2/tr_image_dds.c
Normal file
|
@ -0,0 +1,498 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
2015 James Canete
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../renderercommon/tr_common.h"
|
||||||
|
|
||||||
|
typedef unsigned int ui32_t;
|
||||||
|
|
||||||
|
typedef struct ddsHeader_s
|
||||||
|
{
|
||||||
|
ui32_t headerSize;
|
||||||
|
ui32_t flags;
|
||||||
|
ui32_t height;
|
||||||
|
ui32_t width;
|
||||||
|
ui32_t pitchOrFirstMipSize;
|
||||||
|
ui32_t volumeDepth;
|
||||||
|
ui32_t numMips;
|
||||||
|
ui32_t reserved1[11];
|
||||||
|
ui32_t always_0x00000020;
|
||||||
|
ui32_t pixelFormatFlags;
|
||||||
|
ui32_t fourCC;
|
||||||
|
ui32_t rgbBitCount;
|
||||||
|
ui32_t rBitMask;
|
||||||
|
ui32_t gBitMask;
|
||||||
|
ui32_t bBitMask;
|
||||||
|
ui32_t aBitMask;
|
||||||
|
ui32_t caps;
|
||||||
|
ui32_t caps2;
|
||||||
|
ui32_t caps3;
|
||||||
|
ui32_t caps4;
|
||||||
|
ui32_t reserved2;
|
||||||
|
}
|
||||||
|
ddsHeader_t;
|
||||||
|
|
||||||
|
// flags:
|
||||||
|
#define _DDSFLAGS_REQUIRED 0x001007
|
||||||
|
#define _DDSFLAGS_PITCH 0x8
|
||||||
|
#define _DDSFLAGS_MIPMAPCOUNT 0x20000
|
||||||
|
#define _DDSFLAGS_FIRSTMIPSIZE 0x80000
|
||||||
|
#define _DDSFLAGS_VOLUMEDEPTH 0x800000
|
||||||
|
|
||||||
|
// pixelFormatFlags:
|
||||||
|
#define DDSPF_ALPHAPIXELS 0x1
|
||||||
|
#define DDSPF_ALPHA 0x2
|
||||||
|
#define DDSPF_FOURCC 0x4
|
||||||
|
#define DDSPF_RGB 0x40
|
||||||
|
#define DDSPF_YUV 0x200
|
||||||
|
#define DDSPF_LUMINANCE 0x20000
|
||||||
|
|
||||||
|
// caps:
|
||||||
|
#define DDSCAPS_COMPLEX 0x8
|
||||||
|
#define DDSCAPS_MIPMAP 0x400000
|
||||||
|
#define DDSCAPS_REQUIRED 0x1000
|
||||||
|
|
||||||
|
// caps2:
|
||||||
|
#define DDSCAPS2_CUBEMAP 0xFE00
|
||||||
|
#define DDSCAPS2_VOLUME 0x200000
|
||||||
|
|
||||||
|
typedef struct ddsHeaderDxt10_s
|
||||||
|
{
|
||||||
|
ui32_t dxgiFormat;
|
||||||
|
ui32_t dimensions;
|
||||||
|
ui32_t miscFlags;
|
||||||
|
ui32_t arraySize;
|
||||||
|
ui32_t miscFlags2;
|
||||||
|
}
|
||||||
|
ddsHeaderDxt10_t;
|
||||||
|
|
||||||
|
// dxgiFormat
|
||||||
|
// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb173059%28v=vs.85%29.aspx
|
||||||
|
typedef enum DXGI_FORMAT {
|
||||||
|
DXGI_FORMAT_UNKNOWN = 0,
|
||||||
|
DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
|
||||||
|
DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
|
||||||
|
DXGI_FORMAT_R32G32B32A32_UINT = 3,
|
||||||
|
DXGI_FORMAT_R32G32B32A32_SINT = 4,
|
||||||
|
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
|
||||||
|
DXGI_FORMAT_R32G32B32_FLOAT = 6,
|
||||||
|
DXGI_FORMAT_R32G32B32_UINT = 7,
|
||||||
|
DXGI_FORMAT_R32G32B32_SINT = 8,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_UNORM = 11,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_UINT = 12,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_SNORM = 13,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_SINT = 14,
|
||||||
|
DXGI_FORMAT_R32G32_TYPELESS = 15,
|
||||||
|
DXGI_FORMAT_R32G32_FLOAT = 16,
|
||||||
|
DXGI_FORMAT_R32G32_UINT = 17,
|
||||||
|
DXGI_FORMAT_R32G32_SINT = 18,
|
||||||
|
DXGI_FORMAT_R32G8X24_TYPELESS = 19,
|
||||||
|
DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
|
||||||
|
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
|
||||||
|
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
|
||||||
|
DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
|
||||||
|
DXGI_FORMAT_R10G10B10A2_UNORM = 24,
|
||||||
|
DXGI_FORMAT_R10G10B10A2_UINT = 25,
|
||||||
|
DXGI_FORMAT_R11G11B10_FLOAT = 26,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM = 28,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UINT = 30,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_SNORM = 31,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_SINT = 32,
|
||||||
|
DXGI_FORMAT_R16G16_TYPELESS = 33,
|
||||||
|
DXGI_FORMAT_R16G16_FLOAT = 34,
|
||||||
|
DXGI_FORMAT_R16G16_UNORM = 35,
|
||||||
|
DXGI_FORMAT_R16G16_UINT = 36,
|
||||||
|
DXGI_FORMAT_R16G16_SNORM = 37,
|
||||||
|
DXGI_FORMAT_R16G16_SINT = 38,
|
||||||
|
DXGI_FORMAT_R32_TYPELESS = 39,
|
||||||
|
DXGI_FORMAT_D32_FLOAT = 40,
|
||||||
|
DXGI_FORMAT_R32_FLOAT = 41,
|
||||||
|
DXGI_FORMAT_R32_UINT = 42,
|
||||||
|
DXGI_FORMAT_R32_SINT = 43,
|
||||||
|
DXGI_FORMAT_R24G8_TYPELESS = 44,
|
||||||
|
DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
|
||||||
|
DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
|
||||||
|
DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
|
||||||
|
DXGI_FORMAT_R8G8_TYPELESS = 48,
|
||||||
|
DXGI_FORMAT_R8G8_UNORM = 49,
|
||||||
|
DXGI_FORMAT_R8G8_UINT = 50,
|
||||||
|
DXGI_FORMAT_R8G8_SNORM = 51,
|
||||||
|
DXGI_FORMAT_R8G8_SINT = 52,
|
||||||
|
DXGI_FORMAT_R16_TYPELESS = 53,
|
||||||
|
DXGI_FORMAT_R16_FLOAT = 54,
|
||||||
|
DXGI_FORMAT_D16_UNORM = 55,
|
||||||
|
DXGI_FORMAT_R16_UNORM = 56,
|
||||||
|
DXGI_FORMAT_R16_UINT = 57,
|
||||||
|
DXGI_FORMAT_R16_SNORM = 58,
|
||||||
|
DXGI_FORMAT_R16_SINT = 59,
|
||||||
|
DXGI_FORMAT_R8_TYPELESS = 60,
|
||||||
|
DXGI_FORMAT_R8_UNORM = 61,
|
||||||
|
DXGI_FORMAT_R8_UINT = 62,
|
||||||
|
DXGI_FORMAT_R8_SNORM = 63,
|
||||||
|
DXGI_FORMAT_R8_SINT = 64,
|
||||||
|
DXGI_FORMAT_A8_UNORM = 65,
|
||||||
|
DXGI_FORMAT_R1_UNORM = 66,
|
||||||
|
DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
|
||||||
|
DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
|
||||||
|
DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
|
||||||
|
DXGI_FORMAT_BC1_TYPELESS = 70,
|
||||||
|
DXGI_FORMAT_BC1_UNORM = 71,
|
||||||
|
DXGI_FORMAT_BC1_UNORM_SRGB = 72,
|
||||||
|
DXGI_FORMAT_BC2_TYPELESS = 73,
|
||||||
|
DXGI_FORMAT_BC2_UNORM = 74,
|
||||||
|
DXGI_FORMAT_BC2_UNORM_SRGB = 75,
|
||||||
|
DXGI_FORMAT_BC3_TYPELESS = 76,
|
||||||
|
DXGI_FORMAT_BC3_UNORM = 77,
|
||||||
|
DXGI_FORMAT_BC3_UNORM_SRGB = 78,
|
||||||
|
DXGI_FORMAT_BC4_TYPELESS = 79,
|
||||||
|
DXGI_FORMAT_BC4_UNORM = 80,
|
||||||
|
DXGI_FORMAT_BC4_SNORM = 81,
|
||||||
|
DXGI_FORMAT_BC5_TYPELESS = 82,
|
||||||
|
DXGI_FORMAT_BC5_UNORM = 83,
|
||||||
|
DXGI_FORMAT_BC5_SNORM = 84,
|
||||||
|
DXGI_FORMAT_B5G6R5_UNORM = 85,
|
||||||
|
DXGI_FORMAT_B5G5R5A1_UNORM = 86,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM = 87,
|
||||||
|
DXGI_FORMAT_B8G8R8X8_UNORM = 88,
|
||||||
|
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
|
||||||
|
DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
|
||||||
|
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
|
||||||
|
DXGI_FORMAT_BC6H_TYPELESS = 94,
|
||||||
|
DXGI_FORMAT_BC6H_UF16 = 95,
|
||||||
|
DXGI_FORMAT_BC6H_SF16 = 96,
|
||||||
|
DXGI_FORMAT_BC7_TYPELESS = 97,
|
||||||
|
DXGI_FORMAT_BC7_UNORM = 98,
|
||||||
|
DXGI_FORMAT_BC7_UNORM_SRGB = 99,
|
||||||
|
DXGI_FORMAT_AYUV = 100,
|
||||||
|
DXGI_FORMAT_Y410 = 101,
|
||||||
|
DXGI_FORMAT_Y416 = 102,
|
||||||
|
DXGI_FORMAT_NV12 = 103,
|
||||||
|
DXGI_FORMAT_P010 = 104,
|
||||||
|
DXGI_FORMAT_P016 = 105,
|
||||||
|
DXGI_FORMAT_420_OPAQUE = 106,
|
||||||
|
DXGI_FORMAT_YUY2 = 107,
|
||||||
|
DXGI_FORMAT_Y210 = 108,
|
||||||
|
DXGI_FORMAT_Y216 = 109,
|
||||||
|
DXGI_FORMAT_NV11 = 110,
|
||||||
|
DXGI_FORMAT_AI44 = 111,
|
||||||
|
DXGI_FORMAT_IA44 = 112,
|
||||||
|
DXGI_FORMAT_P8 = 113,
|
||||||
|
DXGI_FORMAT_A8P8 = 114,
|
||||||
|
DXGI_FORMAT_B4G4R4A4_UNORM = 115,
|
||||||
|
DXGI_FORMAT_FORCE_UINT = 0xffffffffUL
|
||||||
|
} DXGI_FORMAT;
|
||||||
|
|
||||||
|
#define EncodeFourCC(x) ((((ui32_t)((x)[0])) ) | \
|
||||||
|
(((ui32_t)((x)[1])) << 8 ) | \
|
||||||
|
(((ui32_t)((x)[2])) << 16) | \
|
||||||
|
(((ui32_t)((x)[3])) << 24) )
|
||||||
|
|
||||||
|
|
||||||
|
void R_LoadDDS ( const char *filename, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips )
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
byte *b;
|
||||||
|
void *v;
|
||||||
|
} buffer;
|
||||||
|
int len;
|
||||||
|
ddsHeader_t *ddsHeader = NULL;
|
||||||
|
ddsHeaderDxt10_t *ddsHeaderDxt10 = NULL;
|
||||||
|
byte *data;
|
||||||
|
|
||||||
|
if (!picFormat)
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ERROR, "R_LoadDDS() called without picFormat parameter!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = 0;
|
||||||
|
if (height)
|
||||||
|
*height = 0;
|
||||||
|
if (picFormat)
|
||||||
|
*picFormat = GL_RGBA8;
|
||||||
|
if (numMips)
|
||||||
|
*numMips = 1;
|
||||||
|
|
||||||
|
*pic = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// load the file
|
||||||
|
//
|
||||||
|
len = ri.FS_ReadFile( ( char * ) filename, &buffer.v);
|
||||||
|
if (!buffer.b || len < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// reject files that are too small to hold even a header
|
||||||
|
//
|
||||||
|
if (len < 4 + sizeof(*ddsHeader))
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "File %s is too small to be a DDS file.\n", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// reject files that don't start with "DDS "
|
||||||
|
//
|
||||||
|
if (*((ui32_t *)(buffer.b)) != EncodeFourCC("DDS "))
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "File %s is not a DDS file.\n", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// parse header and dx10 header if available
|
||||||
|
//
|
||||||
|
ddsHeader = (ddsHeader_t *)(buffer.b + 4);
|
||||||
|
if ((ddsHeader->pixelFormatFlags & DDSPF_FOURCC) && ddsHeader->fourCC == EncodeFourCC("DX10"))
|
||||||
|
{
|
||||||
|
if (len < 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10))
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "File %s indicates a DX10 header it is too small to contain.\n", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ddsHeaderDxt10 = (ddsHeaderDxt10_t *)(buffer.b + 4 + sizeof(ddsHeader_t));
|
||||||
|
data = buffer.b + 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
|
||||||
|
len -= 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = buffer.b + 4 + sizeof(*ddsHeader);
|
||||||
|
len -= 4 + sizeof(*ddsHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = ddsHeader->width;
|
||||||
|
if (height)
|
||||||
|
*height = ddsHeader->height;
|
||||||
|
|
||||||
|
if (numMips)
|
||||||
|
{
|
||||||
|
if (ddsHeader->flags & _DDSFLAGS_MIPMAPCOUNT)
|
||||||
|
*numMips = ddsHeader->numMips;
|
||||||
|
else
|
||||||
|
*numMips = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: handle cube map
|
||||||
|
//if ((ddsHeader->caps2 & DDSCAPS2_CUBEMAP) == DDSCAPS2_CUBEMAP)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convert DXGI format/FourCC into OpenGL format
|
||||||
|
//
|
||||||
|
if (ddsHeaderDxt10)
|
||||||
|
{
|
||||||
|
switch (ddsHeaderDxt10->dxgiFormat)
|
||||||
|
{
|
||||||
|
case DXGI_FORMAT_BC1_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC1_UNORM:
|
||||||
|
// FIXME: check for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
|
||||||
|
*picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||||
|
// FIXME: check for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
|
||||||
|
*picFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC2_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC2_UNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
||||||
|
*picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC3_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC3_UNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
||||||
|
*picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC4_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC4_UNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_RED_RGTC1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC4_SNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC5_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC5_UNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_RG_RGTC2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC5_SNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC6H_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC6H_UF16:
|
||||||
|
*picFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC6H_SF16:
|
||||||
|
*picFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC7_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC7_UNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||||
|
*picFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||||
|
*picFormat = GL_SRGB8_ALPHA8_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_SNORM:
|
||||||
|
*picFormat = GL_RGBA8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ri.Printf(PRINT_ALL, "DDS File %s has unsupported DXGI format %d.", filename, ddsHeaderDxt10->dxgiFormat);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ddsHeader->pixelFormatFlags & DDSPF_FOURCC)
|
||||||
|
{
|
||||||
|
if (ddsHeader->fourCC == EncodeFourCC("DXT1"))
|
||||||
|
*picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("DXT2"))
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("DXT3"))
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("DXT4"))
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("DXT5"))
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("ATI1"))
|
||||||
|
*picFormat = GL_COMPRESSED_RED_RGTC1;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("BC4U"))
|
||||||
|
*picFormat = GL_COMPRESSED_RED_RGTC1;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("BC4S"))
|
||||||
|
*picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("ATI2"))
|
||||||
|
*picFormat = GL_COMPRESSED_RG_RGTC2;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("BC5U"))
|
||||||
|
*picFormat = GL_COMPRESSED_RG_RGTC2;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("BC5S"))
|
||||||
|
*picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "DDS File %s has unsupported FourCC.", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ddsHeader->pixelFormatFlags == (DDSPF_RGB | DDSPF_ALPHAPIXELS)
|
||||||
|
&& ddsHeader->rgbBitCount == 32
|
||||||
|
&& ddsHeader->rBitMask == 0x000000ff
|
||||||
|
&& ddsHeader->gBitMask == 0x0000ff00
|
||||||
|
&& ddsHeader->bBitMask == 0x00ff0000
|
||||||
|
&& ddsHeader->aBitMask == 0xff000000)
|
||||||
|
{
|
||||||
|
*picFormat = GL_RGBA8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "DDS File %s has unsupported RGBA format.", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*pic = ri.Malloc(len);
|
||||||
|
Com_Memcpy(*pic, data, len);
|
||||||
|
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth)
|
||||||
|
{
|
||||||
|
byte *data;
|
||||||
|
ddsHeader_t *ddsHeader;
|
||||||
|
int picSize, size;
|
||||||
|
|
||||||
|
if (!depth)
|
||||||
|
depth = 1;
|
||||||
|
|
||||||
|
picSize = width * height * depth * 4;
|
||||||
|
size = 4 + sizeof(*ddsHeader) + picSize;
|
||||||
|
data = ri.Malloc(size);
|
||||||
|
|
||||||
|
data[0] = 'D';
|
||||||
|
data[1] = 'D';
|
||||||
|
data[2] = 'S';
|
||||||
|
data[3] = ' ';
|
||||||
|
|
||||||
|
ddsHeader = (ddsHeader_t *)(data + 4);
|
||||||
|
memset(ddsHeader, 0, sizeof(ddsHeader_t));
|
||||||
|
|
||||||
|
ddsHeader->headerSize = 0x7c;
|
||||||
|
ddsHeader->flags = _DDSFLAGS_REQUIRED;
|
||||||
|
ddsHeader->height = height;
|
||||||
|
ddsHeader->width = width;
|
||||||
|
ddsHeader->always_0x00000020 = 0x00000020;
|
||||||
|
ddsHeader->caps = DDSCAPS_COMPLEX | DDSCAPS_REQUIRED;
|
||||||
|
|
||||||
|
if (depth == 6)
|
||||||
|
ddsHeader->caps2 = DDSCAPS2_CUBEMAP;
|
||||||
|
|
||||||
|
ddsHeader->pixelFormatFlags = DDSPF_RGB | DDSPF_ALPHAPIXELS;
|
||||||
|
ddsHeader->rgbBitCount = 32;
|
||||||
|
ddsHeader->rBitMask = 0x000000ff;
|
||||||
|
ddsHeader->gBitMask = 0x0000ff00;
|
||||||
|
ddsHeader->bBitMask = 0x00ff0000;
|
||||||
|
ddsHeader->aBitMask = 0xff000000;
|
||||||
|
|
||||||
|
Com_Memcpy(data + 4 + sizeof(*ddsHeader), pic, picSize);
|
||||||
|
|
||||||
|
ri.FS_WriteFile(filename, data, size);
|
||||||
|
|
||||||
|
ri.Free(data);
|
||||||
|
}
|
|
@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
#include "tr_dsa.h"
|
||||||
|
|
||||||
glconfig_t glConfig;
|
glconfig_t glConfig;
|
||||||
glRefConfig_t glRefConfig;
|
glRefConfig_t glRefConfig;
|
||||||
qboolean textureFilterAnisotropic = qfalse;
|
qboolean textureFilterAnisotropic = qfalse;
|
||||||
|
@ -86,10 +88,6 @@ cvar_t *r_novis;
|
||||||
cvar_t *r_nocull;
|
cvar_t *r_nocull;
|
||||||
cvar_t *r_facePlaneCull;
|
cvar_t *r_facePlaneCull;
|
||||||
cvar_t *r_showcluster;
|
cvar_t *r_showcluster;
|
||||||
cvar_t *r_staticlod;
|
|
||||||
cvar_t *r_lodscale;
|
|
||||||
cvar_t *r_lodcap;
|
|
||||||
cvar_t *r_lodviewmodelcap;
|
|
||||||
cvar_t *r_nocurves;
|
cvar_t *r_nocurves;
|
||||||
|
|
||||||
cvar_t *r_allowExtensions;
|
cvar_t *r_allowExtensions;
|
||||||
|
@ -101,19 +99,12 @@ cvar_t *r_ext_texture_env_add;
|
||||||
cvar_t *r_ext_texture_filter_anisotropic;
|
cvar_t *r_ext_texture_filter_anisotropic;
|
||||||
cvar_t *r_ext_max_anisotropy;
|
cvar_t *r_ext_max_anisotropy;
|
||||||
|
|
||||||
cvar_t *r_ext_draw_range_elements;
|
|
||||||
cvar_t *r_ext_multi_draw_arrays;
|
|
||||||
cvar_t *r_ext_framebuffer_object;
|
cvar_t *r_ext_framebuffer_object;
|
||||||
cvar_t *r_ext_texture_float;
|
cvar_t *r_ext_texture_float;
|
||||||
cvar_t *r_arb_half_float_pixel;
|
|
||||||
cvar_t *r_arb_half_float_vertex;
|
|
||||||
cvar_t *r_ext_framebuffer_multisample;
|
cvar_t *r_ext_framebuffer_multisample;
|
||||||
cvar_t *r_arb_seamless_cube_map;
|
cvar_t *r_arb_seamless_cube_map;
|
||||||
cvar_t *r_arb_vertex_type_2_10_10_10_rev;
|
|
||||||
cvar_t *r_arb_vertex_array_object;
|
cvar_t *r_arb_vertex_array_object;
|
||||||
|
cvar_t *r_ext_direct_state_access;
|
||||||
cvar_t *r_mergeMultidraws;
|
|
||||||
cvar_t *r_mergeLeafSurfaces;
|
|
||||||
|
|
||||||
cvar_t *r_cameraExposure;
|
cvar_t *r_cameraExposure;
|
||||||
|
|
||||||
|
@ -134,11 +125,6 @@ cvar_t *r_forceAutoExposure;
|
||||||
cvar_t *r_forceAutoExposureMin;
|
cvar_t *r_forceAutoExposureMin;
|
||||||
cvar_t *r_forceAutoExposureMax;
|
cvar_t *r_forceAutoExposureMax;
|
||||||
|
|
||||||
cvar_t *r_materialGamma;
|
|
||||||
cvar_t *r_lightGamma;
|
|
||||||
cvar_t *r_framebufferGamma;
|
|
||||||
cvar_t *r_tonemapGamma;
|
|
||||||
|
|
||||||
cvar_t *r_depthPrepass;
|
cvar_t *r_depthPrepass;
|
||||||
cvar_t *r_ssao;
|
cvar_t *r_ssao;
|
||||||
|
|
||||||
|
@ -146,14 +132,18 @@ cvar_t *r_normalMapping;
|
||||||
cvar_t *r_specularMapping;
|
cvar_t *r_specularMapping;
|
||||||
cvar_t *r_deluxeMapping;
|
cvar_t *r_deluxeMapping;
|
||||||
cvar_t *r_parallaxMapping;
|
cvar_t *r_parallaxMapping;
|
||||||
|
cvar_t *r_parallaxMapOffset;
|
||||||
|
cvar_t *r_parallaxMapShadows;
|
||||||
cvar_t *r_cubeMapping;
|
cvar_t *r_cubeMapping;
|
||||||
|
cvar_t *r_cubemapSize;
|
||||||
cvar_t *r_deluxeSpecular;
|
cvar_t *r_deluxeSpecular;
|
||||||
cvar_t *r_specularIsMetallic;
|
cvar_t *r_pbr;
|
||||||
cvar_t *r_baseNormalX;
|
cvar_t *r_baseNormalX;
|
||||||
cvar_t *r_baseNormalY;
|
cvar_t *r_baseNormalY;
|
||||||
cvar_t *r_baseParallax;
|
cvar_t *r_baseParallax;
|
||||||
cvar_t *r_baseSpecular;
|
cvar_t *r_baseSpecular;
|
||||||
cvar_t *r_baseGloss;
|
cvar_t *r_baseGloss;
|
||||||
|
cvar_t *r_glossType;
|
||||||
cvar_t *r_mergeLightmaps;
|
cvar_t *r_mergeLightmaps;
|
||||||
cvar_t *r_dlightMode;
|
cvar_t *r_dlightMode;
|
||||||
cvar_t *r_pshadowDist;
|
cvar_t *r_pshadowDist;
|
||||||
|
@ -162,13 +152,13 @@ cvar_t *r_imageUpsampleMaxSize;
|
||||||
cvar_t *r_imageUpsampleType;
|
cvar_t *r_imageUpsampleType;
|
||||||
cvar_t *r_genNormalMaps;
|
cvar_t *r_genNormalMaps;
|
||||||
cvar_t *r_forceSun;
|
cvar_t *r_forceSun;
|
||||||
cvar_t *r_forceSunMapLightScale;
|
|
||||||
cvar_t *r_forceSunLightScale;
|
cvar_t *r_forceSunLightScale;
|
||||||
cvar_t *r_forceSunAmbientScale;
|
cvar_t *r_forceSunAmbientScale;
|
||||||
cvar_t *r_sunlightMode;
|
cvar_t *r_sunlightMode;
|
||||||
cvar_t *r_drawSunRays;
|
cvar_t *r_drawSunRays;
|
||||||
cvar_t *r_sunShadows;
|
cvar_t *r_sunShadows;
|
||||||
cvar_t *r_shadowFilter;
|
cvar_t *r_shadowFilter;
|
||||||
|
cvar_t *r_shadowBlur;
|
||||||
cvar_t *r_shadowMapSize;
|
cvar_t *r_shadowMapSize;
|
||||||
cvar_t *r_shadowCascadeZNear;
|
cvar_t *r_shadowCascadeZNear;
|
||||||
cvar_t *r_shadowCascadeZFar;
|
cvar_t *r_shadowCascadeZFar;
|
||||||
|
@ -246,43 +236,6 @@ int max_polys;
|
||||||
cvar_t *r_maxpolyverts;
|
cvar_t *r_maxpolyverts;
|
||||||
int max_polyverts;
|
int max_polyverts;
|
||||||
|
|
||||||
|
|
||||||
cvar_t *r_uselod;
|
|
||||||
cvar_t *lod_LOD;
|
|
||||||
cvar_t *lod_minLOD;
|
|
||||||
cvar_t *lod_maxLOD;
|
|
||||||
cvar_t *lod_LOD_slider;
|
|
||||||
cvar_t *lod_curve_0_val;
|
|
||||||
cvar_t *lod_curve_1_val;
|
|
||||||
cvar_t *lod_curve_2_val;
|
|
||||||
cvar_t *lod_curve_3_val;
|
|
||||||
cvar_t *lod_curve_4_val;
|
|
||||||
cvar_t *lod_edit_0;
|
|
||||||
cvar_t *lod_edit_1;
|
|
||||||
cvar_t *lod_edit_2;
|
|
||||||
cvar_t *lod_edit_3;
|
|
||||||
cvar_t *lod_edit_4;
|
|
||||||
cvar_t *lod_curve_0_slider;
|
|
||||||
cvar_t *lod_curve_1_slider;
|
|
||||||
cvar_t *lod_curve_2_slider;
|
|
||||||
cvar_t *lod_curve_3_slider;
|
|
||||||
cvar_t *lod_curve_4_slider;
|
|
||||||
cvar_t *lod_pitch_val;
|
|
||||||
cvar_t *lod_zee_val;
|
|
||||||
cvar_t *lod_mesh;
|
|
||||||
cvar_t *lod_meshname;
|
|
||||||
cvar_t *lod_tikiname;
|
|
||||||
cvar_t *lod_metric;
|
|
||||||
cvar_t *lod_tris;
|
|
||||||
cvar_t *lod_position;
|
|
||||||
cvar_t *lod_save;
|
|
||||||
cvar_t *lod_tool;
|
|
||||||
|
|
||||||
cvar_t *r_showSkeleton;
|
|
||||||
cvar_t *r_numdebuglines;
|
|
||||||
|
|
||||||
int r_sequencenumber = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** InitOpenGL
|
** InitOpenGL
|
||||||
**
|
**
|
||||||
|
@ -293,8 +246,6 @@ int r_sequencenumber = 0;
|
||||||
*/
|
*/
|
||||||
static void InitOpenGL( void )
|
static void InitOpenGL( void )
|
||||||
{
|
{
|
||||||
char renderer_buffer[1024];
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// initialize OS specific portions of the renderer
|
// initialize OS specific portions of the renderer
|
||||||
//
|
//
|
||||||
|
@ -310,11 +261,10 @@ static void InitOpenGL( void )
|
||||||
{
|
{
|
||||||
GLint temp;
|
GLint temp;
|
||||||
|
|
||||||
GLimp_Init();
|
GLimp_Init( qfalse );
|
||||||
GLimp_InitExtraExtensions();
|
GLimp_InitExtraExtensions();
|
||||||
|
|
||||||
strcpy( renderer_buffer, glConfig.renderer_string );
|
glConfig.textureEnvAddAvailable = qtrue;
|
||||||
Q_strlwr( renderer_buffer );
|
|
||||||
|
|
||||||
// OpenGL driver constants
|
// OpenGL driver constants
|
||||||
qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
|
qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
|
||||||
|
@ -325,6 +275,22 @@ static void InitOpenGL( void )
|
||||||
{
|
{
|
||||||
glConfig.maxTextureSize = 0;
|
glConfig.maxTextureSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qglGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS, &temp );
|
||||||
|
glConfig.numTextureUnits = temp;
|
||||||
|
|
||||||
|
// reserve 160 components for other uniforms
|
||||||
|
qglGetIntegerv( GL_MAX_VERTEX_UNIFORM_COMPONENTS, &temp );
|
||||||
|
glRefConfig.glslMaxAnimatedBones = Com_Clamp( 0, IQM_MAX_JOINTS, ( temp - 160 ) / 16 );
|
||||||
|
if ( glRefConfig.glslMaxAnimatedBones < 12 ) {
|
||||||
|
glRefConfig.glslMaxAnimatedBones = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for GLSL function textureCubeLod()
|
||||||
|
if ( r_cubeMapping->integer && !QGL_VERSION_ATLEAST( 3, 0 ) ) {
|
||||||
|
ri.Printf( PRINT_WARNING, "WARNING: Disabled r_cubeMapping because it requires OpenGL 3.0\n" );
|
||||||
|
ri.Cvar_Set( "r_cubeMapping", "0" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// set default state
|
// set default state
|
||||||
|
@ -497,6 +463,7 @@ byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *pa
|
||||||
buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1);
|
buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1);
|
||||||
|
|
||||||
bufstart = PADP((intptr_t) buffer + *offset, packAlign);
|
bufstart = PADP((intptr_t) buffer + *offset, packAlign);
|
||||||
|
|
||||||
qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart);
|
qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart);
|
||||||
|
|
||||||
*offset = bufstart - buffer;
|
*offset = bufstart - buffer;
|
||||||
|
@ -874,85 +841,33 @@ void R_ScreenShotJPEG_f (void) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
RB_TakeVideoFrameCmd
|
R_ExportCubemaps
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
const void *RB_TakeVideoFrameCmd( const void *data )
|
void R_ExportCubemaps(void)
|
||||||
{
|
{
|
||||||
const videoFrameCommand_t *cmd;
|
exportCubemapsCommand_t *cmd;
|
||||||
byte *cBuf;
|
|
||||||
size_t memcount, linelen;
|
|
||||||
int padwidth, avipadwidth, padlen, avipadlen;
|
|
||||||
GLint packAlign;
|
|
||||||
|
|
||||||
// finish any 2D drawing if needed
|
cmd = R_GetCommandBuffer(sizeof(*cmd));
|
||||||
if(tess.numIndexes)
|
if (!cmd) {
|
||||||
RB_EndSurface();
|
return;
|
||||||
|
|
||||||
cmd = (const videoFrameCommand_t *)data;
|
|
||||||
|
|
||||||
qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign);
|
|
||||||
|
|
||||||
linelen = cmd->width * 3;
|
|
||||||
|
|
||||||
// Alignment stuff for glReadPixels
|
|
||||||
padwidth = PAD(linelen, packAlign);
|
|
||||||
padlen = padwidth - linelen;
|
|
||||||
// AVI line padding
|
|
||||||
avipadwidth = PAD(linelen, AVI_LINE_PADDING);
|
|
||||||
avipadlen = avipadwidth - linelen;
|
|
||||||
|
|
||||||
cBuf = PADP(cmd->captureBuffer, packAlign);
|
|
||||||
|
|
||||||
qglReadPixels(0, 0, cmd->width, cmd->height, GL_RGB,
|
|
||||||
GL_UNSIGNED_BYTE, cBuf);
|
|
||||||
|
|
||||||
memcount = padwidth * cmd->height;
|
|
||||||
|
|
||||||
// gamma correct
|
|
||||||
if(glConfig.deviceSupportsGamma)
|
|
||||||
R_GammaCorrect(cBuf, memcount);
|
|
||||||
|
|
||||||
if(cmd->motionJpeg)
|
|
||||||
{
|
|
||||||
memcount = RE_SaveJPGToBuffer(cmd->encodeBuffer, linelen * cmd->height,
|
|
||||||
r_aviMotionJpegQuality->integer,
|
|
||||||
cmd->width, cmd->height, cBuf, padlen);
|
|
||||||
ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, memcount);
|
|
||||||
}
|
}
|
||||||
else
|
cmd->commandId = RC_EXPORT_CUBEMAPS;
|
||||||
{
|
|
||||||
byte *lineend, *memend;
|
|
||||||
byte *srcptr, *destptr;
|
|
||||||
|
|
||||||
srcptr = cBuf;
|
|
||||||
destptr = cmd->encodeBuffer;
|
|
||||||
memend = srcptr + memcount;
|
|
||||||
|
|
||||||
// swap R and B and remove line paddings
|
|
||||||
while(srcptr < memend)
|
|
||||||
{
|
|
||||||
lineend = srcptr + linelen;
|
|
||||||
while(srcptr < lineend)
|
|
||||||
{
|
|
||||||
*destptr++ = srcptr[2];
|
|
||||||
*destptr++ = srcptr[1];
|
|
||||||
*destptr++ = srcptr[0];
|
|
||||||
srcptr += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
Com_Memset(destptr, '\0', avipadlen);
|
|
||||||
destptr += avipadlen;
|
|
||||||
|
|
||||||
srcptr += padlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, avipadwidth * cmd->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (const void *)(cmd + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
R_ExportCubemaps_f
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void R_ExportCubemaps_f(void)
|
||||||
|
{
|
||||||
|
R_ExportCubemaps();
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -964,21 +879,12 @@ void GL_SetDefaultState( void )
|
||||||
|
|
||||||
qglCullFace(GL_FRONT);
|
qglCullFace(GL_FRONT);
|
||||||
|
|
||||||
qglColor4f (1,1,1,1);
|
GL_BindNullTextures();
|
||||||
|
|
||||||
// initialize downstream texture unit if we're running
|
if (glRefConfig.framebufferObject)
|
||||||
// in a multitexture environment
|
GL_BindNullFramebuffers();
|
||||||
if ( qglActiveTextureARB ) {
|
|
||||||
GL_SelectTexture( 1 );
|
|
||||||
GL_TextureMode( r_textureMode->string );
|
|
||||||
GL_TexEnv( GL_MODULATE );
|
|
||||||
qglDisable( GL_TEXTURE_2D );
|
|
||||||
GL_SelectTexture( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
qglEnable(GL_TEXTURE_2D);
|
|
||||||
GL_TextureMode( r_textureMode->string );
|
GL_TextureMode( r_textureMode->string );
|
||||||
GL_TexEnv( GL_MODULATE );
|
|
||||||
|
|
||||||
//qglShadeModel( GL_SMOOTH );
|
//qglShadeModel( GL_SMOOTH );
|
||||||
qglDepthFunc( GL_LEQUAL );
|
qglDepthFunc( GL_LEQUAL );
|
||||||
|
@ -991,14 +897,13 @@ void GL_SetDefaultState( void )
|
||||||
glState.faceCulling = CT_TWO_SIDED;
|
glState.faceCulling = CT_TWO_SIDED;
|
||||||
glState.faceCullFront = qtrue;
|
glState.faceCullFront = qtrue;
|
||||||
|
|
||||||
glState.currentProgram = 0;
|
GL_BindNullProgram();
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
if (glRefConfig.vertexArrayObject)
|
if (glRefConfig.vertexArrayObject)
|
||||||
qglBindVertexArrayARB(0);
|
qglBindVertexArray(0);
|
||||||
|
|
||||||
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
qglBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
glState.currentVao = NULL;
|
glState.currentVao = NULL;
|
||||||
glState.vertexAttribsEnabled = 0;
|
glState.vertexAttribsEnabled = 0;
|
||||||
|
|
||||||
|
@ -1018,12 +923,6 @@ void GL_SetDefaultState( void )
|
||||||
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky
|
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *RE_GetGraphicsInfo() {
|
|
||||||
// FIXME: stub
|
|
||||||
// this is soooo annoying that ioquake3 represents 0,5% of mohaa and 1% of ubertools
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
R_PrintLongString
|
R_PrintLongString
|
||||||
|
@ -1046,6 +945,11 @@ void R_PrintLongString(const char *string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* RE_GetGraphicsInfo() {
|
||||||
|
// FIXME: unimplemented
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
GfxInfo_f
|
GfxInfo_f
|
||||||
|
@ -1068,10 +972,25 @@ void GfxInfo_f( void )
|
||||||
ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string );
|
ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string );
|
||||||
ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string );
|
ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string );
|
||||||
ri.Printf( PRINT_ALL, "GL_EXTENSIONS: " );
|
ri.Printf( PRINT_ALL, "GL_EXTENSIONS: " );
|
||||||
R_PrintLongString( glConfig.extensions_string );
|
// glConfig.extensions_string is a limited length so get the full list directly
|
||||||
|
if ( qglGetStringi )
|
||||||
|
{
|
||||||
|
GLint numExtensions;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
qglGetIntegerv( GL_NUM_EXTENSIONS, &numExtensions );
|
||||||
|
for ( i = 0; i < numExtensions; i++ )
|
||||||
|
{
|
||||||
|
ri.Printf( PRINT_ALL, "%s ", qglGetStringi( GL_EXTENSIONS, i ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
R_PrintLongString( (char *) qglGetString( GL_EXTENSIONS ) );
|
||||||
|
}
|
||||||
ri.Printf( PRINT_ALL, "\n" );
|
ri.Printf( PRINT_ALL, "\n" );
|
||||||
ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
|
ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
|
||||||
ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_UNITS_ARB: %d\n", glConfig.numTextureUnits );
|
ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_IMAGE_UNITS: %d\n", glConfig.numTextureUnits );
|
||||||
ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
|
ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
|
||||||
ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] );
|
ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] );
|
||||||
if ( glConfig.displayFrequency )
|
if ( glConfig.displayFrequency )
|
||||||
|
@ -1094,7 +1013,6 @@ void GfxInfo_f( void )
|
||||||
ri.Printf( PRINT_ALL, "texturemode: %s\n", r_textureMode->string );
|
ri.Printf( PRINT_ALL, "texturemode: %s\n", r_textureMode->string );
|
||||||
ri.Printf( PRINT_ALL, "picmip: %d\n", r_picmip->integer );
|
ri.Printf( PRINT_ALL, "picmip: %d\n", r_picmip->integer );
|
||||||
ri.Printf( PRINT_ALL, "texture bits: %d\n", r_texturebits->integer );
|
ri.Printf( PRINT_ALL, "texture bits: %d\n", r_texturebits->integer );
|
||||||
ri.Printf( PRINT_ALL, "multitexture: %s\n", enablestrings[qglActiveTextureARB != 0] );
|
|
||||||
ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] );
|
ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] );
|
||||||
ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] );
|
ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] );
|
||||||
ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression!=TC_NONE] );
|
ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression!=TC_NONE] );
|
||||||
|
@ -1115,6 +1033,16 @@ void GfxInfo_f( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qboolean R_SetMode(int mode) {
|
||||||
|
// FIXME: unimplemented
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_SetFullscreen(qboolean fullscreen, glconfig_t* config) {
|
||||||
|
// FIXME: unimplemented
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
GfxMemInfo_f
|
GfxMemInfo_f
|
||||||
|
@ -1167,46 +1095,6 @@ void GfxMemInfo_f( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
FarPlaneInfo_f
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
void FarPlaneInfo_f( void ) {
|
|
||||||
Com_Printf( "Current fog settings:\n" );
|
|
||||||
Com_Printf( "Distance: %i\n", ( signed int )tr.viewParms.farplane_distance );
|
|
||||||
Com_Printf(
|
|
||||||
"Color: %f %f %f\n",
|
|
||||||
tr.viewParms.farplane_color[ 0 ],
|
|
||||||
tr.viewParms.farplane_color[ 1 ],
|
|
||||||
tr.viewParms.farplane_color[ 2 ] );
|
|
||||||
|
|
||||||
if( tr.viewParms.farplane_cull ) {
|
|
||||||
Com_Printf( "Cull: on\n" );
|
|
||||||
} else {
|
|
||||||
Com_Printf( "Cull: off\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
R_SetMode
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
qboolean R_SetMode( int mode, glconfig_t *config ) {
|
|
||||||
// FIXME: stub..
|
|
||||||
return qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
R_SetFullscreen
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
void R_SetFullscreen( qboolean fullscreen, glconfig_t *config ) {
|
|
||||||
// FIXME: stub...
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
R_Register
|
R_Register
|
||||||
|
@ -1227,16 +1115,12 @@ void R_Register( void )
|
||||||
r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
|
|
||||||
r_ext_draw_range_elements = ri.Cvar_Get( "r_ext_draw_range_elements", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
|
||||||
r_ext_multi_draw_arrays = ri.Cvar_Get( "r_ext_multi_draw_arrays", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
|
||||||
r_ext_framebuffer_object = ri.Cvar_Get( "r_ext_framebuffer_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
r_ext_framebuffer_object = ri.Cvar_Get( "r_ext_framebuffer_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_arb_half_float_pixel = ri.Cvar_Get( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
|
||||||
r_arb_half_float_vertex = ri.Cvar_Get( "r_arb_half_float_vertex", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
|
||||||
r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( "r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
|
||||||
r_arb_vertex_array_object = ri.Cvar_Get( "r_arb_vertex_array_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
r_arb_vertex_array_object = ri.Cvar_Get( "r_arb_vertex_array_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
|
r_ext_direct_state_access = ri.Cvar_Get("r_ext_direct_state_access", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
|
|
||||||
r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
|
r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
|
||||||
"0", CVAR_ARCHIVE | CVAR_LATCH );
|
"0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
@ -1245,18 +1129,16 @@ void R_Register( void )
|
||||||
r_picmip = ri.Cvar_Get ("r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_picmip = ri.Cvar_Get ("r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH );
|
r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH );
|
||||||
|
|
||||||
r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH );
|
r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_ext_multisample = ri.Cvar_Get( "r_ext_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_ext_multisample = ri.Cvar_Get( "r_ext_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
|
||||||
r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_mode = ri.Cvar_Get( "r_mode", "5", CVAR_ARCHIVE | CVAR_LATCH );
|
r_mode = ri.Cvar_Get( "r_mode", "-2", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_fullscreen = ri.Cvar_Get( "r_fullscreen", "0", CVAR_ARCHIVE );
|
r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE );
|
||||||
r_noborder = ri.Cvar_Get("r_noborder", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
r_noborder = ri.Cvar_Get("r_noborder", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH );
|
r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_customheight = ri.Cvar_Get( "r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH );
|
r_customheight = ri.Cvar_Get( "r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
@ -1268,14 +1150,13 @@ void R_Register( void )
|
||||||
r_stereoEnabled = ri.Cvar_Get( "r_stereoEnabled", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
r_stereoEnabled = ri.Cvar_Get( "r_stereoEnabled", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
|
|
||||||
|
|
||||||
r_externalGLSL = ri.Cvar_Get( "r_externalGLSL", "0", CVAR_LATCH );
|
r_externalGLSL = ri.Cvar_Get( "r_externalGLSL", "0", CVAR_LATCH );
|
||||||
|
|
||||||
r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_floatLightmap = ri.Cvar_Get( "r_floatLightmap", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_floatLightmap = ri.Cvar_Get( "r_floatLightmap", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE );
|
r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE );
|
||||||
|
|
||||||
r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE );
|
||||||
r_forceToneMap = ri.Cvar_Get( "r_forceToneMap", "0", CVAR_CHEAT );
|
r_forceToneMap = ri.Cvar_Get( "r_forceToneMap", "0", CVAR_CHEAT );
|
||||||
r_forceToneMapMin = ri.Cvar_Get( "r_forceToneMapMin", "-8.0", CVAR_CHEAT );
|
r_forceToneMapMin = ri.Cvar_Get( "r_forceToneMapMin", "-8.0", CVAR_CHEAT );
|
||||||
r_forceToneMapAvg = ri.Cvar_Get( "r_forceToneMapAvg", "-2.0", CVAR_CHEAT );
|
r_forceToneMapAvg = ri.Cvar_Get( "r_forceToneMapAvg", "-2.0", CVAR_CHEAT );
|
||||||
|
@ -1286,12 +1167,7 @@ void R_Register( void )
|
||||||
r_forceAutoExposureMin = ri.Cvar_Get( "r_forceAutoExposureMin", "-2.0", CVAR_CHEAT );
|
r_forceAutoExposureMin = ri.Cvar_Get( "r_forceAutoExposureMin", "-2.0", CVAR_CHEAT );
|
||||||
r_forceAutoExposureMax = ri.Cvar_Get( "r_forceAutoExposureMax", "2.0", CVAR_CHEAT );
|
r_forceAutoExposureMax = ri.Cvar_Get( "r_forceAutoExposureMax", "2.0", CVAR_CHEAT );
|
||||||
|
|
||||||
r_cameraExposure = ri.Cvar_Get( "r_cameraExposure", "0", CVAR_CHEAT );
|
r_cameraExposure = ri.Cvar_Get( "r_cameraExposure", "1", CVAR_CHEAT );
|
||||||
|
|
||||||
r_materialGamma = ri.Cvar_Get( "r_materialGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
|
||||||
r_lightGamma = ri.Cvar_Get( "r_lightGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
|
||||||
r_framebufferGamma = ri.Cvar_Get( "r_framebufferGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
|
||||||
r_tonemapGamma = ri.Cvar_Get( "r_tonemapGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
|
||||||
|
|
||||||
r_depthPrepass = ri.Cvar_Get( "r_depthPrepass", "1", CVAR_ARCHIVE );
|
r_depthPrepass = ri.Cvar_Get( "r_depthPrepass", "1", CVAR_ARCHIVE );
|
||||||
r_ssao = ri.Cvar_Get( "r_ssao", "0", CVAR_LATCH | CVAR_ARCHIVE );
|
r_ssao = ri.Cvar_Get( "r_ssao", "0", CVAR_LATCH | CVAR_ARCHIVE );
|
||||||
|
@ -1300,14 +1176,18 @@ void R_Register( void )
|
||||||
r_specularMapping = ri.Cvar_Get( "r_specularMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_specularMapping = ri.Cvar_Get( "r_specularMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
r_parallaxMapOffset = ri.Cvar_Get( "r_parallaxMapOffset", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
r_parallaxMapShadows = ri.Cvar_Get( "r_parallaxMapShadows", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_deluxeSpecular = ri.Cvar_Get( "r_deluxeSpecular", "0.3", CVAR_ARCHIVE | CVAR_LATCH );
|
r_cubemapSize = ri.Cvar_Get( "r_cubemapSize", "128", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_deluxeSpecular = ri.Cvar_Get("r_deluxeSpecular", "0.3", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
|
r_pbr = ri.Cvar_Get("r_pbr", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_baseNormalY = ri.Cvar_Get( "r_baseNormalY", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_baseNormalY = ri.Cvar_Get( "r_baseNormalY", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_baseParallax = ri.Cvar_Get( "r_baseParallax", "0.05", CVAR_ARCHIVE | CVAR_LATCH );
|
r_baseParallax = ri.Cvar_Get( "r_baseParallax", "0.05", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_baseSpecular = ri.Cvar_Get( "r_baseSpecular", "0.04", CVAR_ARCHIVE | CVAR_LATCH );
|
r_baseSpecular = ri.Cvar_Get( "r_baseSpecular", "0.04", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_baseGloss = ri.Cvar_Get( "r_baseGloss", "0.3", CVAR_ARCHIVE | CVAR_LATCH );
|
r_baseGloss = ri.Cvar_Get( "r_baseGloss", "0.3", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
r_glossType = ri.Cvar_Get("r_glossType", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_dlightMode = ri.Cvar_Get( "r_dlightMode", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_dlightMode = ri.Cvar_Get( "r_dlightMode", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_pshadowDist = ri.Cvar_Get( "r_pshadowDist", "128", CVAR_ARCHIVE );
|
r_pshadowDist = ri.Cvar_Get( "r_pshadowDist", "128", CVAR_ARCHIVE );
|
||||||
r_mergeLightmaps = ri.Cvar_Get( "r_mergeLightmaps", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_mergeLightmaps = ri.Cvar_Get( "r_mergeLightmaps", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
@ -1317,7 +1197,6 @@ void R_Register( void )
|
||||||
r_genNormalMaps = ri.Cvar_Get( "r_genNormalMaps", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_genNormalMaps = ri.Cvar_Get( "r_genNormalMaps", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
|
||||||
r_forceSun = ri.Cvar_Get( "r_forceSun", "0", CVAR_CHEAT );
|
r_forceSun = ri.Cvar_Get( "r_forceSun", "0", CVAR_CHEAT );
|
||||||
r_forceSunMapLightScale = ri.Cvar_Get( "r_forceSunMapLightScale", "1.0", CVAR_CHEAT );
|
|
||||||
r_forceSunLightScale = ri.Cvar_Get( "r_forceSunLightScale", "1.0", CVAR_CHEAT );
|
r_forceSunLightScale = ri.Cvar_Get( "r_forceSunLightScale", "1.0", CVAR_CHEAT );
|
||||||
r_forceSunAmbientScale = ri.Cvar_Get( "r_forceSunAmbientScale", "0.5", CVAR_CHEAT );
|
r_forceSunAmbientScale = ri.Cvar_Get( "r_forceSunAmbientScale", "0.5", CVAR_CHEAT );
|
||||||
r_drawSunRays = ri.Cvar_Get( "r_drawSunRays", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_drawSunRays = ri.Cvar_Get( "r_drawSunRays", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
@ -1325,7 +1204,8 @@ void R_Register( void )
|
||||||
|
|
||||||
r_sunShadows = ri.Cvar_Get( "r_sunShadows", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_sunShadows = ri.Cvar_Get( "r_sunShadows", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_shadowFilter = ri.Cvar_Get( "r_shadowFilter", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_shadowFilter = ri.Cvar_Get( "r_shadowFilter", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_shadowMapSize = ri.Cvar_Get( "r_shadowMapSize", "1024", CVAR_ARCHIVE | CVAR_LATCH );
|
r_shadowBlur = ri.Cvar_Get("r_shadowBlur", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
|
r_shadowMapSize = ri.Cvar_Get("r_shadowMapSize", "1024", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "8", CVAR_ARCHIVE | CVAR_LATCH );
|
r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "8", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "1024", CVAR_ARCHIVE | CVAR_LATCH );
|
r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "1024", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
@ -1335,7 +1215,6 @@ void R_Register( void )
|
||||||
// temporary latched variables that can only change over a restart
|
// temporary latched variables that can only change over a restart
|
||||||
//
|
//
|
||||||
r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH );
|
r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH );
|
||||||
|
|
||||||
r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT );
|
r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT );
|
||||||
r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH );
|
r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH );
|
||||||
r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH );
|
r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH );
|
||||||
|
@ -1348,7 +1227,6 @@ void R_Register( void )
|
||||||
r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE );
|
r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE );
|
||||||
r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE );
|
r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE );
|
||||||
r_znear = ri.Cvar_Get( "r_znear", "4", CVAR_CHEAT );
|
r_znear = ri.Cvar_Get( "r_znear", "4", CVAR_CHEAT );
|
||||||
|
|
||||||
r_zproj = ri.Cvar_Get( "r_zproj", "64", CVAR_ARCHIVE );
|
r_zproj = ri.Cvar_Get( "r_zproj", "64", CVAR_ARCHIVE );
|
||||||
r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE );
|
r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE );
|
||||||
r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE );
|
r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE );
|
||||||
|
@ -1358,7 +1236,7 @@ void R_Register( void )
|
||||||
r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE );
|
r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE );
|
||||||
r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE );
|
r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE );
|
||||||
r_finish = ri.Cvar_Get ("r_finish", "0", CVAR_ARCHIVE);
|
r_finish = ri.Cvar_Get ("r_finish", "0", CVAR_ARCHIVE);
|
||||||
r_textureMode = ri.Cvar_Get( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE );
|
r_textureMode = ri.Cvar_Get( "r_textureMode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE );
|
||||||
r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0",
|
r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0",
|
||||||
CVAR_ARCHIVE | CVAR_LATCH );
|
CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_gamma = ri.Cvar_Get( "r_gamma", "1", CVAR_ARCHIVE );
|
r_gamma = ri.Cvar_Get( "r_gamma", "1", CVAR_ARCHIVE );
|
||||||
|
@ -1372,8 +1250,6 @@ void R_Register( void )
|
||||||
r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT );
|
r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT );
|
||||||
|
|
||||||
r_anaglyphMode = ri.Cvar_Get("r_anaglyphMode", "0", CVAR_ARCHIVE);
|
r_anaglyphMode = ri.Cvar_Get("r_anaglyphMode", "0", CVAR_ARCHIVE);
|
||||||
r_mergeMultidraws = ri.Cvar_Get("r_mergeMultidraws", "1", CVAR_ARCHIVE);
|
|
||||||
r_mergeLeafSurfaces = ri.Cvar_Get("r_mergeLeafSurfaces", "1", CVAR_ARCHIVE);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// temporary variables that can change at any time
|
// temporary variables that can change at any time
|
||||||
|
@ -1428,41 +1304,6 @@ void R_Register( void )
|
||||||
r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0);
|
r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0);
|
||||||
r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0);
|
r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0);
|
||||||
|
|
||||||
r_numdebuglines = ri.Cvar_Get( "r_numdebuglines", "0", 0 );
|
|
||||||
r_showSkeleton = ri.Cvar_Get( "r_showSkeleton", "0", 0 );
|
|
||||||
|
|
||||||
// lod
|
|
||||||
r_uselod = ri.Cvar_Get( "r_uselod", "1", CVAR_TEMP );
|
|
||||||
lod_LOD = ri.Cvar_Get( "lod_LOD", "0", CVAR_TEMP );
|
|
||||||
lod_minLOD = ri.Cvar_Get( "lod_minLOD", "1.0", CVAR_TEMP );
|
|
||||||
lod_maxLOD = ri.Cvar_Get( "lod_maxLOD", "0.3", CVAR_TEMP );
|
|
||||||
lod_LOD_slider = ri.Cvar_Get( "lod_LOD_slider", "0.5", CVAR_TEMP );
|
|
||||||
lod_edit_0 = ri.Cvar_Get( "lod_edit_0", "0", CVAR_TEMP );
|
|
||||||
lod_edit_1 = ri.Cvar_Get( "lod_edit_1", "0", CVAR_TEMP );
|
|
||||||
lod_edit_2 = ri.Cvar_Get( "lod_edit_2", "0", CVAR_TEMP );
|
|
||||||
lod_edit_3 = ri.Cvar_Get( "lod_edit_3", "0", CVAR_TEMP );
|
|
||||||
lod_edit_4 = ri.Cvar_Get( "lod_edit_4", "0", CVAR_TEMP );
|
|
||||||
lod_curve_0_val = ri.Cvar_Get( "lod_curve_0_val", "0", CVAR_TEMP );
|
|
||||||
lod_curve_1_val = ri.Cvar_Get( "lod_curve_1_val", "0", CVAR_TEMP );
|
|
||||||
lod_curve_2_val = ri.Cvar_Get( "lod_curve_2_val", "0", CVAR_TEMP );
|
|
||||||
lod_curve_3_val = ri.Cvar_Get( "lod_curve_3_val", "0", CVAR_TEMP );
|
|
||||||
lod_curve_4_val = ri.Cvar_Get( "lod_curve_4_val", "0", CVAR_TEMP );
|
|
||||||
lod_curve_0_slider = ri.Cvar_Get( "lod_curve_0_slider", "0", CVAR_TEMP );
|
|
||||||
lod_curve_1_slider = ri.Cvar_Get( "lod_curve_1_slider", "0", CVAR_TEMP );
|
|
||||||
lod_curve_2_slider = ri.Cvar_Get( "lod_curve_2_slider", "0", CVAR_TEMP );
|
|
||||||
lod_curve_3_slider = ri.Cvar_Get( "lod_curve_3_slider", "0", CVAR_TEMP );
|
|
||||||
lod_curve_4_slider = ri.Cvar_Get( "lod_curve_4_slider", "0", CVAR_TEMP );
|
|
||||||
lod_pitch_val = ri.Cvar_Get( "lod_pitch_val", "0", CVAR_TEMP );
|
|
||||||
lod_zee_val = ri.Cvar_Get( "lod_zee_val", "0", CVAR_TEMP );
|
|
||||||
lod_mesh = ri.Cvar_Get( "lod_mesh", "0", CVAR_TEMP );
|
|
||||||
lod_meshname = ri.Cvar_Get( "lod_meshname", "", CVAR_TEMP );
|
|
||||||
lod_tikiname = ri.Cvar_Get( "lod_tikiname", "", CVAR_TEMP );
|
|
||||||
lod_metric = ri.Cvar_Get( "lod_metric", "0.0", CVAR_TEMP );
|
|
||||||
lod_tris = ri.Cvar_Get( "lod_tris", "", CVAR_TEMP );
|
|
||||||
lod_save = ri.Cvar_Get( "lod_save", "0", CVAR_TEMP );
|
|
||||||
lod_position = ri.Cvar_Get( "lod_metric", "0 0 0", CVAR_TEMP );
|
|
||||||
lod_tool = ri.Cvar_Get( "lod_tool", "0", CVAR_TEMP );
|
|
||||||
|
|
||||||
// make sure all the commands added here are also
|
// make sure all the commands added here are also
|
||||||
// removed in R_Shutdown
|
// removed in R_Shutdown
|
||||||
ri.Cmd_AddCommand( "imagelist", R_ImageList_f );
|
ri.Cmd_AddCommand( "imagelist", R_ImageList_f );
|
||||||
|
@ -1475,6 +1316,7 @@ void R_Register( void )
|
||||||
ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
|
ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
|
||||||
ri.Cmd_AddCommand( "minimize", GLimp_Minimize );
|
ri.Cmd_AddCommand( "minimize", GLimp_Minimize );
|
||||||
ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f );
|
ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f );
|
||||||
|
ri.Cmd_AddCommand( "exportCubemaps", R_ExportCubemaps_f );
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_InitQueries(void)
|
void R_InitQueries(void)
|
||||||
|
@ -1483,7 +1325,7 @@ void R_InitQueries(void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (r_drawSunRays->integer)
|
if (r_drawSunRays->integer)
|
||||||
qglGenQueriesARB(ARRAY_LEN(tr.sunFlareQuery), tr.sunFlareQuery);
|
qglGenQueries(ARRAY_LEN(tr.sunFlareQuery), tr.sunFlareQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_ShutDownQueries(void)
|
void R_ShutDownQueries(void)
|
||||||
|
@ -1492,7 +1334,7 @@ void R_ShutDownQueries(void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (r_drawSunRays->integer)
|
if (r_drawSunRays->integer)
|
||||||
qglDeleteQueriesARB(ARRAY_LEN(tr.sunFlareQuery), tr.sunFlareQuery);
|
qglDeleteQueries(ARRAY_LEN(tr.sunFlareQuery), tr.sunFlareQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1512,8 +1354,8 @@ void R_Init( void ) {
|
||||||
Com_Memset( &backEnd, 0, sizeof( backEnd ) );
|
Com_Memset( &backEnd, 0, sizeof( backEnd ) );
|
||||||
Com_Memset( &tess, 0, sizeof( tess ) );
|
Com_Memset( &tess, 0, sizeof( tess ) );
|
||||||
|
|
||||||
//if(sizeof(glconfig_t) != 11332)
|
if(sizeof(glconfig_t) != 11332)
|
||||||
// ri.Error( ERR_FATAL, "Mod ABI incompatible: sizeof(glconfig_t) == %u != 11332", (unsigned int) sizeof(glconfig_t));
|
ri.Error( ERR_FATAL, "Mod ABI incompatible: sizeof(glconfig_t) == %u != 11332", (unsigned int) sizeof(glconfig_t));
|
||||||
|
|
||||||
// Swap_Init();
|
// Swap_Init();
|
||||||
|
|
||||||
|
@ -1567,8 +1409,6 @@ void R_Init( void ) {
|
||||||
backEndData = (backEndData_t *) ptr;
|
backEndData = (backEndData_t *) ptr;
|
||||||
backEndData->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData ));
|
backEndData->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData ));
|
||||||
backEndData->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys);
|
backEndData->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys);
|
||||||
backEndData->staticModels = NULL;
|
|
||||||
backEndData->staticModelData = NULL;
|
|
||||||
R_InitNextFrame();
|
R_InitNextFrame();
|
||||||
|
|
||||||
InitOpenGL();
|
InitOpenGL();
|
||||||
|
@ -1611,17 +1451,17 @@ void RE_Shutdown( qboolean destroyWindow ) {
|
||||||
|
|
||||||
ri.Printf( PRINT_ALL, "RE_Shutdown( %i )\n", destroyWindow );
|
ri.Printf( PRINT_ALL, "RE_Shutdown( %i )\n", destroyWindow );
|
||||||
|
|
||||||
ri.Cmd_RemoveCommand ("modellist");
|
ri.Cmd_RemoveCommand( "imagelist" );
|
||||||
ri.Cmd_RemoveCommand ("screenshotJPEG");
|
ri.Cmd_RemoveCommand( "shaderlist" );
|
||||||
ri.Cmd_RemoveCommand ("screenshot");
|
ri.Cmd_RemoveCommand( "skinlist" );
|
||||||
ri.Cmd_RemoveCommand ("imagelist");
|
ri.Cmd_RemoveCommand( "modellist" );
|
||||||
ri.Cmd_RemoveCommand ("shaderlist");
|
|
||||||
ri.Cmd_RemoveCommand ("skinlist");
|
|
||||||
ri.Cmd_RemoveCommand ("gfxinfo");
|
|
||||||
ri.Cmd_RemoveCommand("minimize");
|
|
||||||
ri.Cmd_RemoveCommand( "modelist" );
|
ri.Cmd_RemoveCommand( "modelist" );
|
||||||
ri.Cmd_RemoveCommand( "shaderstate" );
|
ri.Cmd_RemoveCommand( "screenshot" );
|
||||||
|
ri.Cmd_RemoveCommand( "screenshotJPEG" );
|
||||||
|
ri.Cmd_RemoveCommand( "gfxinfo" );
|
||||||
|
ri.Cmd_RemoveCommand( "minimize" );
|
||||||
ri.Cmd_RemoveCommand( "gfxmeminfo" );
|
ri.Cmd_RemoveCommand( "gfxmeminfo" );
|
||||||
|
ri.Cmd_RemoveCommand( "exportCubemaps" );
|
||||||
|
|
||||||
|
|
||||||
if ( tr.registered ) {
|
if ( tr.registered ) {
|
||||||
|
@ -1640,43 +1480,19 @@ void RE_Shutdown( qboolean destroyWindow ) {
|
||||||
if ( destroyWindow ) {
|
if ( destroyWindow ) {
|
||||||
GLimp_Shutdown();
|
GLimp_Shutdown();
|
||||||
|
|
||||||
Com_Memset(&glConfig, 0, sizeof(glConfig));
|
Com_Memset( &glConfig, 0, sizeof( glConfig ) );
|
||||||
textureFilterAnisotropic = qfalse;
|
Com_Memset( &glRefConfig, 0, sizeof( glRefConfig ) );
|
||||||
maxAnisotropy = 0;
|
textureFilterAnisotropic = qfalse;
|
||||||
displayAspect = 0.0f;
|
maxAnisotropy = 0;
|
||||||
haveClampToEdge = qfalse;
|
displayAspect = 0.0f;
|
||||||
|
haveClampToEdge = qfalse;
|
||||||
|
|
||||||
Com_Memset(&glState, 0, sizeof(glState));
|
Com_Memset( &glState, 0, sizeof( glState ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.registered = qfalse;
|
tr.registered = qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
RE_BeginRegistration
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
void RE_BeginRegistration( glconfig_t *glconfigOut ) {
|
|
||||||
|
|
||||||
ri.Hunk_Clear();
|
|
||||||
|
|
||||||
R_Init();
|
|
||||||
|
|
||||||
*glconfigOut = glConfig;
|
|
||||||
|
|
||||||
//R_SyncRenderThread();
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
r_sequencenumber++;
|
|
||||||
tr.viewCluster = -1; // force markleafs to regenerate
|
|
||||||
R_ClearFlares();
|
|
||||||
RE_ClearScene();
|
|
||||||
|
|
||||||
// FIXME: implement dcl...
|
|
||||||
//R_LevelMarksInit();
|
|
||||||
|
|
||||||
tr.registered = qtrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
|
@ -1687,21 +1503,13 @@ Touch all images to make sure they are resident
|
||||||
*/
|
*/
|
||||||
void RE_EndRegistration( void ) {
|
void RE_EndRegistration( void ) {
|
||||||
R_IssuePendingRenderCommands();
|
R_IssuePendingRenderCommands();
|
||||||
RB_ShowImages();
|
if (!ri.Sys_LowPhysicalMemory()) {
|
||||||
|
RB_ShowImages();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void RE_SetRenderTime(int t) {
|
||||||
=============
|
// FIXME: unimplemented
|
||||||
RE_SetRenderTime
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void RE_SetRenderTime( int t ) {
|
|
||||||
backEnd.refdef.floatTime = ( float )t / 1000.0;
|
|
||||||
// FIXME: update ghost textures ?
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *RE_GetShaderName( qhandle_t shader ) {
|
|
||||||
return tr.shaders[ shader ]->name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1730,89 +1538,77 @@ refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
|
||||||
|
|
||||||
// the RE_ functions are Renderer Entry points
|
// the RE_ functions are Renderer Entry points
|
||||||
|
|
||||||
re.Shutdown = RE_Shutdown;
|
re.Shutdown = RE_Shutdown;
|
||||||
|
|
||||||
re.FreeModels = RE_FreeModels;
|
re.FreeModels = RE_FreeModels;
|
||||||
re.BeginRegistration = RE_BeginRegistration;
|
re.BeginRegistration = RE_BeginRegistration;
|
||||||
re.EndRegistration = RE_EndRegistration;
|
re.EndRegistration = RE_EndRegistration;
|
||||||
re.RegisterModel = RE_RegisterModel;
|
re.RegisterModel = RE_RegisterModel;
|
||||||
re.SpawnEffectModel = RE_SpawnEffectModel;
|
re.SpawnEffectModel = RE_SpawnEffectModel;
|
||||||
re.RegisterServerModel = RE_RegisterServerModel;
|
re.RegisterServerModel = RE_RegisterServerModel;
|
||||||
re.UnregisterServerModel = RE_UnregisterServerModel;
|
re.UnregisterServerModel = RE_UnregisterServerModel;
|
||||||
re.RegisterShader = RE_RegisterShader;
|
re.RegisterShader = RE_RegisterShader;
|
||||||
re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
|
re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
|
||||||
re.LoadWorld = RE_LoadWorldMap;
|
re.LoadWorld = RE_LoadWorldMap;
|
||||||
re.PrintBSPFileSizes = RE_PrintBSPFileSizes;
|
re.PrintBSPFileSizes = RE_PrintBSPFileSizes;
|
||||||
re.MapVersion = RE_MapVersion;
|
re.MapVersion = RE_MapVersion;
|
||||||
re.LoadFont = R_LoadFont;
|
re.LoadFont = R_LoadFont;
|
||||||
re.SetWorldVisData = RE_SetWorldVisData;
|
re.SetWorldVisData = RE_SetWorldVisData;
|
||||||
|
|
||||||
re.BeginFrame = RE_BeginFrame;
|
re.BeginFrame = RE_BeginFrame;
|
||||||
re.EndFrame = RE_EndFrame;
|
re.EndFrame = RE_EndFrame;
|
||||||
|
|
||||||
re.MarkFragments = R_MarkFragments;
|
re.MarkFragments = R_MarkFragments;
|
||||||
re.MarkFragmentsForInlineModel = R_MarkFragmentsForInlineModel;
|
re.MarkFragmentsForInlineModel = R_MarkFragmentsForInlineModel;
|
||||||
re.GetInlineModelBounds = R_GetInlineModelBounds;
|
re.GetInlineModelBounds = R_GetInlineModelBounds;
|
||||||
re.GetLightingForDecal = R_GetLightingForDecal;
|
re.GetLightingForDecal = R_GetLightingForDecal;
|
||||||
re.GetLightingForSmoke = R_GetLightingForSmoke;
|
re.GetLightingForSmoke = R_GetLightingForSmoke;
|
||||||
re.R_GatherLightSources = R_GatherLightSources;
|
re.R_GatherLightSources = R_GatherLightSources;
|
||||||
re.ModelBounds = R_ModelBounds;
|
re.ModelBounds = R_ModelBounds;
|
||||||
re.ModelRadius = R_ModelRadius;
|
re.ModelRadius = R_ModelRadius;
|
||||||
|
|
||||||
re.ClearScene = RE_ClearScene;
|
re.ClearScene = RE_ClearScene;
|
||||||
re.AddRefEntityToScene = RE_AddRefEntityToScene;
|
re.AddRefEntityToScene = RE_AddRefEntityToScene;
|
||||||
re.AddRefSpriteToScene = RE_AddRefSpriteToScene;
|
re.AddRefSpriteToScene = RE_AddRefSpriteToScene;
|
||||||
re.AddPolyToScene = RE_AddPolyToScene;
|
re.AddPolyToScene = RE_AddPolyToScene;
|
||||||
re.AddTerrainMarkToScene = RE_AddTerrainMarkToScene;
|
re.AddTerrainMarkToScene = RE_AddTerrainMarkToScene;
|
||||||
re.AddLightToScene = RE_AddLightToScene;
|
re.AddLightToScene = RE_AddLightToScene;
|
||||||
re.AddAdditiveLightToScene = RE_AddAdditiveLightToScene;
|
re.RenderScene = RE_RenderScene;
|
||||||
re.RenderScene = RE_RenderScene;
|
re.GetRenderEntity = RE_GetRenderEntity;
|
||||||
re.GetRenderEntity = RE_GetRenderEntity;
|
|
||||||
|
|
||||||
re.SavePerformanceCounters = R_SavePerformanceCounters;
|
re.SavePerformanceCounters = R_SavePerformanceCounters;
|
||||||
|
|
||||||
re.R_Model_GetHandle = R_Model_GetHandle;
|
re.R_Model_GetHandle = R_Model_GetHandle;
|
||||||
re.SetColor = Draw_SetColor;
|
re.SetColor = Draw_SetColor;
|
||||||
re.DrawStretchPic = Draw_StretchPic;
|
re.DrawStretchPic = Draw_StretchPic;
|
||||||
re.DrawStretchRaw = RE_StretchRaw;
|
re.DrawStretchRaw = RE_StretchRaw;
|
||||||
re.DebugLine = R_DebugLine;
|
re.DebugLine = R_DebugLine;
|
||||||
re.DrawTilePic = Draw_TilePic;
|
re.DrawTilePic = Draw_TilePic;
|
||||||
re.DrawTilePicOffset = Draw_TilePicOffset;
|
re.DrawTilePicOffset = Draw_TilePicOffset;
|
||||||
re.DrawTrianglePic = Draw_TrianglePic;
|
re.DrawTrianglePic = Draw_TrianglePic;
|
||||||
re.DrawBox = DrawBox;
|
re.DrawBox = DrawBox;
|
||||||
re.AddBox = AddBox;
|
re.AddBox = AddBox;
|
||||||
re.Set2DWindow = Set2DWindow;
|
re.Set2DWindow = Set2DWindow;
|
||||||
re.Scissor = RE_Scissor;
|
re.Scissor = RE_Scissor;
|
||||||
re.DrawLineLoop = DrawLineLoop;
|
re.DrawLineLoop = DrawLineLoop;
|
||||||
re.DrawString = R_DrawString;
|
re.DrawString = R_DrawString;
|
||||||
re.GetFontHeight = R_GetFontHeight;
|
re.GetFontHeight = R_GetFontHeight;
|
||||||
re.GetFontStringWidth = R_GetFontStringWidth;
|
re.GetFontStringWidth = R_GetFontStringWidth;
|
||||||
re.SwipeBegin = RE_SwipeBegin;
|
re.SwipeBegin = RE_SwipeBegin;
|
||||||
re.SwipeEnd = RE_SwipeEnd;
|
re.SwipeEnd = RE_SwipeEnd;
|
||||||
re.SetRenderTime = RE_SetRenderTime;
|
re.SetRenderTime = RE_SetRenderTime;
|
||||||
re.Noise = R_NoiseGet4f;
|
re.Noise = R_NoiseGet4f;
|
||||||
|
|
||||||
re.SetMode = R_SetMode;
|
re.SetMode = R_SetMode;
|
||||||
re.SetFullscreen = R_SetFullscreen;
|
re.SetFullscreen = R_SetFullscreen;
|
||||||
|
|
||||||
re.GetShaderHeight = RE_GetShaderHeight;
|
re.GetShaderHeight = RE_GetShaderHeight;
|
||||||
re.GetShaderWidth = RE_GetShaderWidth;
|
re.GetShaderWidth = RE_GetShaderWidth;
|
||||||
re.GetGraphicsInfo = RE_GetGraphicsInfo;
|
re.GetGraphicsInfo = RE_GetGraphicsInfo;
|
||||||
re.ForceUpdatePose = RE_ForceUpdatePose;
|
re.ForceUpdatePose = RE_ForceUpdatePose;
|
||||||
re.TIKI_Orientation = RE_TIKI_Orientation;
|
re.TIKI_Orientation = RE_TIKI_Orientation;
|
||||||
re.TIKI_IsOnGround = RE_TIKI_IsOnGround;
|
re.TIKI_IsOnGround = RE_TIKI_IsOnGround;
|
||||||
re.SetFrameNumber = RE_SetFrameNumber;
|
re.SetFrameNumber = RE_SetFrameNumber;
|
||||||
|
|
||||||
re.RegisterFont = RE_RegisterFont;
|
|
||||||
|
|
||||||
// IneQuation
|
|
||||||
re.Text_Width = RE_Text_Width;
|
|
||||||
re.Text_Height = RE_Text_Height;
|
|
||||||
re.Text_Paint = RE_Text_Paint;
|
|
||||||
re.Text_PaintChar = RE_Text_PaintChar;
|
|
||||||
|
|
||||||
// su44
|
|
||||||
re.GetShaderName = RE_GetShaderName;
|
|
||||||
|
|
||||||
return &re;
|
return &re;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,6 @@ void R_DlightBmodel( bmodel_t *bmodel ) {
|
||||||
case SF_FACE:
|
case SF_FACE:
|
||||||
case SF_GRID:
|
case SF_GRID:
|
||||||
case SF_TRIANGLES:
|
case SF_TRIANGLES:
|
||||||
case SF_VAO_MESH:
|
|
||||||
((srfBspSurface_t *)surf->data)->dlightBits = mask;
|
((srfBspSurface_t *)surf->data)->dlightBits = mask;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -139,7 +138,7 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) {
|
||||||
float totalFactor;
|
float totalFactor;
|
||||||
|
|
||||||
if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
|
if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
|
||||||
// seperate lightOrigins are needed so an object that is
|
// separate lightOrigins are needed so an object that is
|
||||||
// sinking into the ground can still be lit, and so
|
// sinking into the ground can still be lit, and so
|
||||||
// multi-part models can be lit identically
|
// multi-part models can be lit identically
|
||||||
VectorCopy( ent->e.lightingOrigin, lightOrigin );
|
VectorCopy( ent->e.lightingOrigin, lightOrigin );
|
||||||
|
@ -201,10 +200,10 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (world->hdrLightGrid)
|
if (world->lightGrid16)
|
||||||
{
|
{
|
||||||
float *hdrData = world->hdrLightGrid + (int)(data - world->lightGridData) / 8 * 6;
|
uint16_t *data16 = world->lightGrid16 + (int)(data - world->lightGridData) / 8 * 6;
|
||||||
if (!(hdrData[0]+hdrData[1]+hdrData[2]+hdrData[3]+hdrData[4]+hdrData[5]) ) {
|
if (!(data16[0]+data16[1]+data16[2]+data16[3]+data16[4]+data16[5])) {
|
||||||
continue; // ignore samples in walls
|
continue; // ignore samples in walls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,18 +226,18 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) {
|
||||||
ent->directedLight[1] += factor * d4;
|
ent->directedLight[1] += factor * d4;
|
||||||
ent->directedLight[2] += factor * d5;
|
ent->directedLight[2] += factor * d5;
|
||||||
#else
|
#else
|
||||||
if (world->hdrLightGrid)
|
if (world->lightGrid16)
|
||||||
{
|
{
|
||||||
// FIXME: this is hideous
|
// FIXME: this is hideous
|
||||||
float *hdrData = world->hdrLightGrid + (int)(data - world->lightGridData) / 8 * 6;
|
uint16_t *data16 = world->lightGrid16 + (int)(data - world->lightGridData) / 8 * 6;
|
||||||
|
|
||||||
ent->ambientLight[0] += factor * hdrData[0];
|
ent->ambientLight[0] += factor * data16[0] / 257.0f;
|
||||||
ent->ambientLight[1] += factor * hdrData[1];
|
ent->ambientLight[1] += factor * data16[1] / 257.0f;
|
||||||
ent->ambientLight[2] += factor * hdrData[2];
|
ent->ambientLight[2] += factor * data16[2] / 257.0f;
|
||||||
|
|
||||||
ent->directedLight[0] += factor * hdrData[3];
|
ent->directedLight[0] += factor * data16[3] / 257.0f;
|
||||||
ent->directedLight[1] += factor * hdrData[4];
|
ent->directedLight[1] += factor * data16[4] / 257.0f;
|
||||||
ent->directedLight[2] += factor * hdrData[5];
|
ent->directedLight[2] += factor * data16[5] / 257.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -336,7 +335,7 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
|
||||||
// trace a sample point down to find ambient light
|
// trace a sample point down to find ambient light
|
||||||
//
|
//
|
||||||
if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
|
if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
|
||||||
// seperate lightOrigins are needed so an object that is
|
// separate lightOrigins are needed so an object that is
|
||||||
// sinking into the ground can still be lit, and so
|
// sinking into the ground can still be lit, and so
|
||||||
// multi-part models can be lit identically
|
// multi-part models can be lit identically
|
||||||
VectorCopy( ent->e.lightingOrigin, lightOrigin );
|
VectorCopy( ent->e.lightingOrigin, lightOrigin );
|
||||||
|
@ -357,7 +356,7 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// bonus items and view weapons have a fixed minimum add
|
// bonus items and view weapons have a fixed minimum add
|
||||||
if ( !r_hdr->integer /* ent->e.renderfx & RF_MINLIGHT */ ) {
|
if ( 1 /* ent->e.renderfx & RF_MINLIGHT */ ) {
|
||||||
// give everything a minimum light add
|
// give everything a minimum light add
|
||||||
ent->ambientLight[0] += tr.identityLight * 32;
|
ent->ambientLight[0] += tr.identityLight * 32;
|
||||||
ent->ambientLight[1] += tr.identityLight * 32;
|
ent->ambientLight[1] += tr.identityLight * 32;
|
||||||
|
@ -385,16 +384,42 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
|
||||||
VectorMA( lightDir, d, dir, lightDir );
|
VectorMA( lightDir, d, dir, lightDir );
|
||||||
}
|
}
|
||||||
|
|
||||||
// clamp ambient
|
// clamp lights
|
||||||
if ( !r_hdr->integer )
|
// FIXME: old renderer clamps (ambient + NL * directed) per vertex
|
||||||
|
// check if that's worth implementing
|
||||||
{
|
{
|
||||||
for ( i = 0 ; i < 3 ; i++ ) {
|
float r, g, b, max;
|
||||||
if ( ent->ambientLight[i] > tr.identityLightByte ) {
|
|
||||||
ent->ambientLight[i] = tr.identityLightByte;
|
r = ent->ambientLight[0];
|
||||||
}
|
g = ent->ambientLight[1];
|
||||||
|
b = ent->ambientLight[2];
|
||||||
|
|
||||||
|
max = MAX(MAX(r, g), b);
|
||||||
|
|
||||||
|
if (max > 255.0f)
|
||||||
|
{
|
||||||
|
max = 255.0f / max;
|
||||||
|
ent->ambientLight[0] *= max;
|
||||||
|
ent->ambientLight[1] *= max;
|
||||||
|
ent->ambientLight[2] *= max;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = ent->directedLight[0];
|
||||||
|
g = ent->directedLight[1];
|
||||||
|
b = ent->directedLight[2];
|
||||||
|
|
||||||
|
max = MAX(MAX(r, g), b);
|
||||||
|
|
||||||
|
if (max > 255.0f)
|
||||||
|
{
|
||||||
|
max = 255.0f / max;
|
||||||
|
ent->directedLight[0] *= max;
|
||||||
|
ent->directedLight[1] *= max;
|
||||||
|
ent->directedLight[2] *= max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( r_debugLight->integer ) {
|
if ( r_debugLight->integer ) {
|
||||||
LogLight( ent );
|
LogLight( ent );
|
||||||
}
|
}
|
||||||
|
@ -471,7 +496,7 @@ int R_CubemapForPoint( vec3_t point )
|
||||||
vec3_t diff;
|
vec3_t diff;
|
||||||
vec_t length;
|
vec_t length;
|
||||||
|
|
||||||
VectorSubtract(point, tr.cubemapOrigins[i], diff);
|
VectorSubtract(point, tr.cubemaps[i].origin, diff);
|
||||||
length = DotProduct(diff, diff);
|
length = DotProduct(diff, diff);
|
||||||
|
|
||||||
if (shortest > length)
|
if (shortest > length)
|
||||||
|
@ -484,34 +509,3 @@ int R_CubemapForPoint( vec3_t point )
|
||||||
|
|
||||||
return cubemapIndex + 1;
|
return cubemapIndex + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_GetLightingForDecal
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_GetLightingForDecal( vec3_t vLight, vec3_t vFacing, vec3_t vOrigin ) {
|
|
||||||
// FIXME: stub
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_GetLightingForSmoke
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_GetLightingForSmoke( vec3_t vLight, vec3_t vOrigin ) {
|
|
||||||
// FIXME: stub
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_GatherLightSources
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
int R_GatherLightSources( const vec3_t vPos, vec3_t *pvLightPos, vec3_t *pvLightIntensity, int iMaxLights ) {
|
|
||||||
// FIXME: stub
|
|
||||||
|
|
||||||
// i don't think this is useful because renderer_gl2 handles light differently
|
|
||||||
// thus, R_GatherLightSources is mainly used to create fake shadow
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -70,230 +70,11 @@ qboolean R_CompareVert(srfVert_t * v1, srfVert_t * v2, qboolean checkST)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
R_CalcNormalForTriangle
|
R_CalcTexDirs
|
||||||
|
|
||||||
|
Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
void R_CalcNormalForTriangle(vec3_t normal, const vec3_t v0, const vec3_t v1, const vec3_t v2)
|
|
||||||
{
|
|
||||||
vec3_t udir, vdir;
|
|
||||||
|
|
||||||
// compute the face normal based on vertex points
|
|
||||||
VectorSubtract(v2, v0, udir);
|
|
||||||
VectorSubtract(v1, v0, vdir);
|
|
||||||
CrossProduct(udir, vdir, normal);
|
|
||||||
|
|
||||||
VectorNormalize(normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
R_CalcTangentsForTriangle
|
|
||||||
http://members.rogers.com/deseric/tangentspace.htm
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void R_CalcTangentsForTriangle(vec3_t tangent, vec3_t bitangent,
|
|
||||||
const vec3_t v0, const vec3_t v1, const vec3_t v2,
|
|
||||||
const vec2_t t0, const vec2_t t1, const vec2_t t2)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
vec3_t planes[3];
|
|
||||||
vec3_t u, v;
|
|
||||||
|
|
||||||
for(i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
VectorSet(u, v1[i] - v0[i], t1[0] - t0[0], t1[1] - t0[1]);
|
|
||||||
VectorSet(v, v2[i] - v0[i], t2[0] - t0[0], t2[1] - t0[1]);
|
|
||||||
|
|
||||||
VectorNormalize(u);
|
|
||||||
VectorNormalize(v);
|
|
||||||
|
|
||||||
CrossProduct(u, v, planes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//So your tangent space will be defined by this :
|
|
||||||
//Normal = Normal of the triangle or Tangent X Bitangent (careful with the cross product,
|
|
||||||
// you have to make sure the normal points in the right direction)
|
|
||||||
//Tangent = ( dp(Fx(s,t)) / ds, dp(Fy(s,t)) / ds, dp(Fz(s,t)) / ds ) or ( -Bx/Ax, -By/Ay, - Bz/Az )
|
|
||||||
//Bitangent = ( dp(Fx(s,t)) / dt, dp(Fy(s,t)) / dt, dp(Fz(s,t)) / dt ) or ( -Cx/Ax, -Cy/Ay, -Cz/Az )
|
|
||||||
|
|
||||||
// tangent...
|
|
||||||
tangent[0] = -planes[0][1] / planes[0][0];
|
|
||||||
tangent[1] = -planes[1][1] / planes[1][0];
|
|
||||||
tangent[2] = -planes[2][1] / planes[2][0];
|
|
||||||
VectorNormalize(tangent);
|
|
||||||
|
|
||||||
// bitangent...
|
|
||||||
bitangent[0] = -planes[0][2] / planes[0][0];
|
|
||||||
bitangent[1] = -planes[1][2] / planes[1][0];
|
|
||||||
bitangent[2] = -planes[2][2] / planes[2][0];
|
|
||||||
VectorNormalize(bitangent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
R_CalcTangentSpace
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
|
|
||||||
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
|
|
||||||
{
|
|
||||||
vec3_t cp, u, v;
|
|
||||||
vec3_t faceNormal;
|
|
||||||
|
|
||||||
VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
|
|
||||||
VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
|
|
||||||
|
|
||||||
CrossProduct(u, v, cp);
|
|
||||||
if(fabs(cp[0]) > 10e-6)
|
|
||||||
{
|
|
||||||
tangent[0] = -cp[1] / cp[0];
|
|
||||||
bitangent[0] = -cp[2] / cp[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
u[0] = v1[1] - v0[1];
|
|
||||||
v[0] = v2[1] - v0[1];
|
|
||||||
|
|
||||||
CrossProduct(u, v, cp);
|
|
||||||
if(fabs(cp[0]) > 10e-6)
|
|
||||||
{
|
|
||||||
tangent[1] = -cp[1] / cp[0];
|
|
||||||
bitangent[1] = -cp[2] / cp[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
u[0] = v1[2] - v0[2];
|
|
||||||
v[0] = v2[2] - v0[2];
|
|
||||||
|
|
||||||
CrossProduct(u, v, cp);
|
|
||||||
if(fabs(cp[0]) > 10e-6)
|
|
||||||
{
|
|
||||||
tangent[2] = -cp[1] / cp[0];
|
|
||||||
bitangent[2] = -cp[2] / cp[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorNormalize(tangent);
|
|
||||||
VectorNormalize(bitangent);
|
|
||||||
|
|
||||||
// compute the face normal based on vertex points
|
|
||||||
if ( normal[0] == 0.0f && normal[1] == 0.0f && normal[2] == 0.0f )
|
|
||||||
{
|
|
||||||
VectorSubtract(v2, v0, u);
|
|
||||||
VectorSubtract(v1, v0, v);
|
|
||||||
CrossProduct(u, v, faceNormal);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VectorCopy(normal, faceNormal);
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorNormalize(faceNormal);
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
// Gram-Schmidt orthogonalize
|
|
||||||
//tangent[a] = (t - n * Dot(n, t)).Normalize();
|
|
||||||
VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent);
|
|
||||||
VectorNormalize(tangent);
|
|
||||||
|
|
||||||
// compute the cross product B=NxT
|
|
||||||
//CrossProduct(normal, tangent, bitangent);
|
|
||||||
#else
|
|
||||||
// normal, compute the cross product N=TxB
|
|
||||||
CrossProduct(tangent, bitangent, normal);
|
|
||||||
VectorNormalize(normal);
|
|
||||||
|
|
||||||
if(DotProduct(normal, faceNormal) < 0)
|
|
||||||
{
|
|
||||||
//VectorInverse(normal);
|
|
||||||
//VectorInverse(tangent);
|
|
||||||
//VectorInverse(bitangent);
|
|
||||||
|
|
||||||
// compute the cross product T=BxN
|
|
||||||
CrossProduct(bitangent, faceNormal, tangent);
|
|
||||||
|
|
||||||
// compute the cross product B=NxT
|
|
||||||
//CrossProduct(normal, tangent, bitangent);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VectorCopy(faceNormal, normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_CalcTangentSpaceFast(vec3_t tangent, vec3_t bitangent, vec3_t normal,
|
|
||||||
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
|
|
||||||
{
|
|
||||||
vec3_t cp, u, v;
|
|
||||||
vec3_t faceNormal;
|
|
||||||
|
|
||||||
VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
|
|
||||||
VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
|
|
||||||
|
|
||||||
CrossProduct(u, v, cp);
|
|
||||||
if(fabs(cp[0]) > 10e-6)
|
|
||||||
{
|
|
||||||
tangent[0] = -cp[1] / cp[0];
|
|
||||||
bitangent[0] = -cp[2] / cp[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
u[0] = v1[1] - v0[1];
|
|
||||||
v[0] = v2[1] - v0[1];
|
|
||||||
|
|
||||||
CrossProduct(u, v, cp);
|
|
||||||
if(fabs(cp[0]) > 10e-6)
|
|
||||||
{
|
|
||||||
tangent[1] = -cp[1] / cp[0];
|
|
||||||
bitangent[1] = -cp[2] / cp[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
u[0] = v1[2] - v0[2];
|
|
||||||
v[0] = v2[2] - v0[2];
|
|
||||||
|
|
||||||
CrossProduct(u, v, cp);
|
|
||||||
if(fabs(cp[0]) > 10e-6)
|
|
||||||
{
|
|
||||||
tangent[2] = -cp[1] / cp[0];
|
|
||||||
bitangent[2] = -cp[2] / cp[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorNormalizeFast(tangent);
|
|
||||||
VectorNormalizeFast(bitangent);
|
|
||||||
|
|
||||||
// compute the face normal based on vertex points
|
|
||||||
VectorSubtract(v2, v0, u);
|
|
||||||
VectorSubtract(v1, v0, v);
|
|
||||||
CrossProduct(u, v, faceNormal);
|
|
||||||
|
|
||||||
VectorNormalizeFast(faceNormal);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// normal, compute the cross product N=TxB
|
|
||||||
CrossProduct(tangent, bitangent, normal);
|
|
||||||
VectorNormalizeFast(normal);
|
|
||||||
|
|
||||||
if(DotProduct(normal, faceNormal) < 0)
|
|
||||||
{
|
|
||||||
VectorInverse(normal);
|
|
||||||
//VectorInverse(tangent);
|
|
||||||
//VectorInverse(bitangent);
|
|
||||||
|
|
||||||
CrossProduct(normal, tangent, bitangent);
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorCopy(faceNormal, normal);
|
|
||||||
#else
|
|
||||||
// Gram-Schmidt orthogonalize
|
|
||||||
//tangent[a] = (t - n * Dot(n, t)).Normalize();
|
|
||||||
VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent);
|
|
||||||
VectorNormalizeFast(tangent);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VectorCopy(faceNormal, normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
http://www.terathon.com/code/tangent.html
|
|
||||||
*/
|
|
||||||
void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
|
void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
|
||||||
const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3)
|
const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3)
|
||||||
{
|
{
|
||||||
|
@ -312,13 +93,21 @@ void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
|
||||||
t1 = w2[1] - w1[1];
|
t1 = w2[1] - w1[1];
|
||||||
t2 = w3[1] - w1[1];
|
t2 = w3[1] - w1[1];
|
||||||
|
|
||||||
r = 1.0f / (s1 * t2 - s2 * t1);
|
r = s1 * t2 - s2 * t1;
|
||||||
|
if (r) r = 1.0f / r;
|
||||||
|
|
||||||
VectorSet(sdir, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
|
VectorSet(sdir, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
|
||||||
VectorSet(tdir, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
|
VectorSet(tdir, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t normal, vec3_t sdir, vec3_t tdir)
|
/*
|
||||||
|
=============
|
||||||
|
R_CalcTangentSpace
|
||||||
|
|
||||||
|
Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
vec_t R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, const vec3_t normal, const vec3_t sdir, const vec3_t tdir)
|
||||||
{
|
{
|
||||||
vec3_t n_cross_t;
|
vec3_t n_cross_t;
|
||||||
vec_t n_dot_t, handedness;
|
vec_t n_dot_t, handedness;
|
||||||
|
@ -332,114 +121,13 @@ void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t norm
|
||||||
CrossProduct(normal, sdir, n_cross_t);
|
CrossProduct(normal, sdir, n_cross_t);
|
||||||
handedness = (DotProduct(n_cross_t, tdir) < 0.0f) ? -1.0f : 1.0f;
|
handedness = (DotProduct(n_cross_t, tdir) < 0.0f) ? -1.0f : 1.0f;
|
||||||
|
|
||||||
// Calculate bitangent
|
// Calculate orthogonal bitangent, if necessary
|
||||||
CrossProduct(normal, tangent, bitangent);
|
if (bitangent)
|
||||||
VectorScale(bitangent, handedness, bitangent);
|
CrossProduct(normal, tangent, bitangent);
|
||||||
|
|
||||||
|
return handedness;
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_CalcTBN2(vec3_t tangent, vec3_t bitangent, vec3_t normal,
|
|
||||||
const vec3_t v1, const vec3_t v2, const vec3_t v3, const vec2_t t1, const vec2_t t2, const vec2_t t3)
|
|
||||||
{
|
|
||||||
vec3_t v2v1;
|
|
||||||
vec3_t v3v1;
|
|
||||||
|
|
||||||
float c2c1_T;
|
|
||||||
float c2c1_B;
|
|
||||||
|
|
||||||
float c3c1_T;
|
|
||||||
float c3c1_B;
|
|
||||||
|
|
||||||
float denominator;
|
|
||||||
float scale1, scale2;
|
|
||||||
|
|
||||||
vec3_t T, B, N, C;
|
|
||||||
|
|
||||||
|
|
||||||
// Calculate the tangent basis for each vertex of the triangle
|
|
||||||
// UPDATE: In the 3rd edition of the accompanying article, the for-loop located here has
|
|
||||||
// been removed as it was redundant (the entire TBN matrix was calculated three times
|
|
||||||
// instead of just one).
|
|
||||||
//
|
|
||||||
// Please note, that this function relies on the fact that the input geometry are triangles
|
|
||||||
// and the tangent basis for each vertex thus is identical!
|
|
||||||
//
|
|
||||||
|
|
||||||
// Calculate the vectors from the current vertex to the two other vertices in the triangle
|
|
||||||
VectorSubtract(v2, v1, v2v1);
|
|
||||||
VectorSubtract(v3, v1, v3v1);
|
|
||||||
|
|
||||||
// The equation presented in the article states that:
|
|
||||||
// c2c1_T = V2.texcoord.x - V1.texcoord.x
|
|
||||||
// c2c1_B = V2.texcoord.y - V1.texcoord.y
|
|
||||||
// c3c1_T = V3.texcoord.x - V1.texcoord.x
|
|
||||||
// c3c1_B = V3.texcoord.y - V1.texcoord.y
|
|
||||||
|
|
||||||
// Calculate c2c1_T and c2c1_B
|
|
||||||
c2c1_T = t2[0] - t1[0];
|
|
||||||
c2c1_B = t2[1] - t2[1];
|
|
||||||
|
|
||||||
// Calculate c3c1_T and c3c1_B
|
|
||||||
c3c1_T = t3[0] - t1[0];
|
|
||||||
c3c1_B = t3[1] - t1[1];
|
|
||||||
|
|
||||||
denominator = c2c1_T * c3c1_B - c3c1_T * c2c1_B;
|
|
||||||
//if(ROUNDOFF(fDenominator) == 0.0f)
|
|
||||||
if(denominator == 0.0f)
|
|
||||||
{
|
|
||||||
// We won't risk a divide by zero, so set the tangent matrix to the identity matrix
|
|
||||||
VectorSet(tangent, 1, 0, 0);
|
|
||||||
VectorSet(bitangent, 0, 1, 0);
|
|
||||||
VectorSet(normal, 0, 0, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Calculate the reciprocal value once and for all (to achieve speed)
|
|
||||||
scale1 = 1.0f / denominator;
|
|
||||||
|
|
||||||
// T and B are calculated just as the equation in the article states
|
|
||||||
VectorSet(T, (c3c1_B * v2v1[0] - c2c1_B * v3v1[0]) * scale1,
|
|
||||||
(c3c1_B * v2v1[1] - c2c1_B * v3v1[1]) * scale1,
|
|
||||||
(c3c1_B * v2v1[2] - c2c1_B * v3v1[2]) * scale1);
|
|
||||||
|
|
||||||
VectorSet(B, (-c3c1_T * v2v1[0] + c2c1_T * v3v1[0]) * scale1,
|
|
||||||
(-c3c1_T * v2v1[1] + c2c1_T * v3v1[1]) * scale1,
|
|
||||||
(-c3c1_T * v2v1[2] + c2c1_T * v3v1[2]) * scale1);
|
|
||||||
|
|
||||||
// The normal N is calculated as the cross product between T and B
|
|
||||||
CrossProduct(T, B, N);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
VectorCopy(T, tangent);
|
|
||||||
VectorCopy(B, bitangent);
|
|
||||||
VectorCopy(N, normal);
|
|
||||||
#else
|
|
||||||
// Calculate the reciprocal value once and for all (to achieve speed)
|
|
||||||
scale2 = 1.0f / ((T[0] * B[1] * N[2] - T[2] * B[1] * N[0]) +
|
|
||||||
(B[0] * N[1] * T[2] - B[2] * N[1] * T[0]) +
|
|
||||||
(N[0] * T[1] * B[2] - N[2] * T[1] * B[0]));
|
|
||||||
|
|
||||||
// Calculate the inverse if the TBN matrix using the formula described in the article.
|
|
||||||
// We store the basis vectors directly in the provided TBN matrix: pvTBNMatrix
|
|
||||||
CrossProduct(B, N, C); tangent[0] = C[0] * scale2;
|
|
||||||
CrossProduct(N, T, C); tangent[1] = -C[0] * scale2;
|
|
||||||
CrossProduct(T, B, C); tangent[2] = C[0] * scale2;
|
|
||||||
VectorNormalize(tangent);
|
|
||||||
|
|
||||||
CrossProduct(B, N, C); bitangent[0] = -C[1] * scale2;
|
|
||||||
CrossProduct(N, T, C); bitangent[1] = C[1] * scale2;
|
|
||||||
CrossProduct(T, B, C); bitangent[2] = -C[1] * scale2;
|
|
||||||
VectorNormalize(bitangent);
|
|
||||||
|
|
||||||
CrossProduct(B, N, C); normal[0] = C[2] * scale2;
|
|
||||||
CrossProduct(N, T, C); normal[1] = -C[2] * scale2;
|
|
||||||
CrossProduct(T, B, C); normal[2] = C[2] * scale2;
|
|
||||||
VectorNormalize(normal);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
qboolean R_CalcTangentVectors(srfVert_t * dv[3])
|
qboolean R_CalcTangentVectors(srfVert_t * dv[3])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -455,7 +143,8 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
|
||||||
/* do each vertex */
|
/* do each vertex */
|
||||||
for(i = 0; i < 3; i++)
|
for(i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
vec3_t bitangent, nxt;
|
vec4_t tangent;
|
||||||
|
vec3_t normal, bitangent, nxt;
|
||||||
|
|
||||||
// calculate s tangent vector
|
// calculate s tangent vector
|
||||||
s = dv[i]->st[0] + 10.0f;
|
s = dv[i]->st[0] + 10.0f;
|
||||||
|
@ -464,12 +153,12 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
|
||||||
bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
|
bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
|
||||||
bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
|
bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
|
||||||
|
|
||||||
dv[i]->tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
|
tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
|
||||||
dv[i]->tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
|
tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
|
||||||
dv[i]->tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
|
tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
|
||||||
|
|
||||||
VectorSubtract(dv[i]->tangent, dv[i]->xyz, dv[i]->tangent);
|
VectorSubtract(tangent, dv[i]->xyz, tangent);
|
||||||
VectorNormalize(dv[i]->tangent);
|
VectorNormalize(tangent);
|
||||||
|
|
||||||
// calculate t tangent vector
|
// calculate t tangent vector
|
||||||
s = dv[i]->st[0];
|
s = dv[i]->st[0];
|
||||||
|
@ -486,8 +175,11 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
|
||||||
VectorNormalize(bitangent);
|
VectorNormalize(bitangent);
|
||||||
|
|
||||||
// store bitangent handedness
|
// store bitangent handedness
|
||||||
CrossProduct(dv[i]->normal, dv[i]->tangent, nxt);
|
R_VaoUnpackNormal(normal, dv[i]->normal);
|
||||||
dv[i]->tangent[3] = (DotProduct(nxt, bitangent) < 0.0f) ? -1.0f : 1.0f;
|
CrossProduct(normal, tangent, nxt);
|
||||||
|
tangent[3] = (DotProduct(nxt, bitangent) < 0.0f) ? -1.0f : 1.0f;
|
||||||
|
|
||||||
|
R_VaoPackTangent(dv[i]->tangent, tangent);
|
||||||
|
|
||||||
// debug code
|
// debug code
|
||||||
//% Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,
|
//% Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,
|
||||||
|
@ -496,7 +188,6 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
|
||||||
|
|
||||||
return qtrue;
|
return qtrue;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -865,59 +556,6 @@ void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms,
|
||||||
or->viewOrigin[2] = DotProduct( delta, or->axis[2] ) * axisLength;
|
or->viewOrigin[2] = DotProduct( delta, or->axis[2] ) * axisLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_RotateForStaticModel
|
|
||||||
|
|
||||||
Generates an orientation for a static model and viewParms
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_RotateForStaticModel( cStaticModelUnpacked_t *SM, const viewParms_t *viewParms,
|
|
||||||
orientationr_t *or ) {
|
|
||||||
float glMatrix[16];
|
|
||||||
vec3_t delta;
|
|
||||||
float tiki_scale;
|
|
||||||
|
|
||||||
tiki_scale = SM->tiki->load_scale * SM->scale;
|
|
||||||
|
|
||||||
VectorCopy( SM->origin, or->origin );
|
|
||||||
|
|
||||||
VectorCopy( SM->axis[0], or->axis[0] );
|
|
||||||
VectorCopy( SM->axis[1], or->axis[1] );
|
|
||||||
VectorCopy( SM->axis[2], or->axis[2] );
|
|
||||||
|
|
||||||
glMatrix[0] = or->axis[0][0] * tiki_scale;
|
|
||||||
glMatrix[4] = or->axis[1][0] * tiki_scale;
|
|
||||||
glMatrix[8] = or->axis[2][0] * tiki_scale;
|
|
||||||
glMatrix[12] = or->origin[0];
|
|
||||||
|
|
||||||
glMatrix[1] = or->axis[0][1] * tiki_scale;
|
|
||||||
glMatrix[5] = or->axis[1][1] * tiki_scale;
|
|
||||||
glMatrix[9] = or->axis[2][1] * tiki_scale;
|
|
||||||
glMatrix[13] = or->origin[1];
|
|
||||||
|
|
||||||
glMatrix[2] = or->axis[0][2] * tiki_scale;
|
|
||||||
glMatrix[6] = or->axis[1][2] * tiki_scale;
|
|
||||||
glMatrix[10] = or->axis[2][2] * tiki_scale;
|
|
||||||
glMatrix[14] = or->origin[2];
|
|
||||||
|
|
||||||
glMatrix[3] = 0;
|
|
||||||
glMatrix[7] = 0;
|
|
||||||
glMatrix[11] = 0;
|
|
||||||
glMatrix[15] = 1;
|
|
||||||
|
|
||||||
Mat4Copy(glMatrix, or->transformMatrix);
|
|
||||||
myGlMultMatrix( glMatrix, viewParms->world.modelMatrix, or->modelMatrix );
|
|
||||||
|
|
||||||
// calculate the viewer origin in the model's space
|
|
||||||
// needed for fog, specular, and environment mapping
|
|
||||||
VectorSubtract( viewParms->or.origin, or->origin, delta );
|
|
||||||
|
|
||||||
or->viewOrigin[0] = DotProduct( delta, or->axis[0] );
|
|
||||||
or->viewOrigin[1] = DotProduct( delta, or->axis[1] );
|
|
||||||
or->viewOrigin[2] = DotProduct( delta, or->axis[2] );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
R_RotateForViewer
|
R_RotateForViewer
|
||||||
|
@ -1455,6 +1093,7 @@ qboolean R_GetPortalOrientations( drawSurf_t *drawSurf, int entityNum,
|
||||||
VectorSubtract( vec3_origin, camera->axis[0], camera->axis[0] );
|
VectorSubtract( vec3_origin, camera->axis[0], camera->axis[0] );
|
||||||
VectorSubtract( vec3_origin, camera->axis[1], camera->axis[1] );
|
VectorSubtract( vec3_origin, camera->axis[1], camera->axis[1] );
|
||||||
|
|
||||||
|
// optionally rotate
|
||||||
if ( e->e.skinNum ) {
|
if ( e->e.skinNum ) {
|
||||||
d = e->e.skinNum;
|
d = e->e.skinNum;
|
||||||
VectorCopy( camera->axis[1], transformed );
|
VectorCopy( camera->axis[1], transformed );
|
||||||
|
@ -1552,11 +1191,10 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128
|
||||||
int i;
|
int i;
|
||||||
unsigned int pointOr = 0;
|
unsigned int pointOr = 0;
|
||||||
unsigned int pointAnd = (unsigned int)~0;
|
unsigned int pointAnd = (unsigned int)~0;
|
||||||
qboolean staticModel;
|
|
||||||
|
|
||||||
R_RotateForViewer();
|
R_RotateForViewer();
|
||||||
|
|
||||||
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed, &staticModel );
|
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
|
||||||
RB_BeginSurface( shader, fogNum, drawSurf->cubemapIndex);
|
RB_BeginSurface( shader, fogNum, drawSurf->cubemapIndex);
|
||||||
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
|
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
|
||||||
|
|
||||||
|
@ -1678,8 +1316,8 @@ qboolean R_MirrorViewBySurface (drawSurf_t *drawSurf, int entityNum) {
|
||||||
return qfalse; // bad portal, no portalentity
|
return qfalse; // bad portal, no portalentity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newParms.isMirror)
|
// Never draw viewmodels in portal or mirror views.
|
||||||
newParms.flags |= VPF_NOVIEWMODEL;
|
newParms.flags |= VPF_NOVIEWMODEL;
|
||||||
|
|
||||||
R_MirrorPoint (oldParms.or.origin, &surface, &camera, newParms.or.origin );
|
R_MirrorPoint (oldParms.or.origin, &surface, &camera, newParms.or.origin );
|
||||||
|
|
||||||
|
@ -1810,8 +1448,7 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,
|
||||||
// compared quickly during the qsorting process
|
// compared quickly during the qsorting process
|
||||||
tr.refdef.drawSurfs[index].sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT)
|
tr.refdef.drawSurfs[index].sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT)
|
||||||
| tr.shiftedEntityNum | ( fogIndex << QSORT_FOGNUM_SHIFT )
|
| tr.shiftedEntityNum | ( fogIndex << QSORT_FOGNUM_SHIFT )
|
||||||
| ( ( int )pshadowMap << QSORT_PSHADOW_SHIFT ) | ( int )dlightMap
|
| ((int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap;
|
||||||
| ( tr.shiftedIsStatic << QSORT_STATIC_SHIFT );
|
|
||||||
tr.refdef.drawSurfs[index].cubemapIndex = cubemap;
|
tr.refdef.drawSurfs[index].cubemapIndex = cubemap;
|
||||||
tr.refdef.drawSurfs[index].surface = surface;
|
tr.refdef.drawSurfs[index].surface = surface;
|
||||||
tr.refdef.numDrawSurfs++;
|
tr.refdef.numDrawSurfs++;
|
||||||
|
@ -1823,13 +1460,12 @@ R_DecomposeSort
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
|
void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
|
||||||
int *fogNum, int *dlightMap, int *pshadowMap, qboolean *staticModel ) {
|
int *fogNum, int *dlightMap, int *pshadowMap ) {
|
||||||
*fogNum = ( sort >> QSORT_FOGNUM_SHIFT ) & 31;
|
*fogNum = ( sort >> QSORT_FOGNUM_SHIFT ) & 31;
|
||||||
*shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1) ];
|
*shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1) ];
|
||||||
*entityNum = ( sort >> QSORT_REFENTITYNUM_SHIFT ) & REFENTITYNUM_MASK;
|
*entityNum = ( sort >> QSORT_REFENTITYNUM_SHIFT ) & REFENTITYNUM_MASK;
|
||||||
*pshadowMap = (sort >> QSORT_PSHADOW_SHIFT ) & 1;
|
*pshadowMap = (sort >> QSORT_PSHADOW_SHIFT ) & 1;
|
||||||
*dlightMap = sort & 1;
|
*dlightMap = sort & 1;
|
||||||
*staticModel = ( sort >> QSORT_STATIC_SHIFT ) & 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1844,7 +1480,6 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||||
int dlighted;
|
int dlighted;
|
||||||
int pshadowed;
|
int pshadowed;
|
||||||
int i;
|
int i;
|
||||||
qboolean staticModel;
|
|
||||||
|
|
||||||
//ri.Printf(PRINT_ALL, "firstDrawSurf %d numDrawSurfs %d\n", (int)(drawSurfs - tr.refdef.drawSurfs), numDrawSurfs);
|
//ri.Printf(PRINT_ALL, "firstDrawSurf %d numDrawSurfs %d\n", (int)(drawSurfs - tr.refdef.drawSurfs), numDrawSurfs);
|
||||||
|
|
||||||
|
@ -1868,7 +1503,7 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||||
// check for any pass through drawing, which
|
// check for any pass through drawing, which
|
||||||
// may cause another view to be rendered first
|
// may cause another view to be rendered first
|
||||||
for ( i = 0 ; i < numDrawSurfs ; i++ ) {
|
for ( i = 0 ; i < numDrawSurfs ; i++ ) {
|
||||||
R_DecomposeSort( (drawSurfs+i)->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed, &staticModel );
|
R_DecomposeSort( (drawSurfs+i)->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
|
||||||
|
|
||||||
if ( shader->sort > SS_PORTAL ) {
|
if ( shader->sort > SS_PORTAL ) {
|
||||||
break;
|
break;
|
||||||
|
@ -1920,8 +1555,6 @@ static void R_AddEntitySurface (int entityNum)
|
||||||
case RT_PORTALSURFACE:
|
case RT_PORTALSURFACE:
|
||||||
break; // don't draw anything
|
break; // don't draw anything
|
||||||
case RT_SPRITE:
|
case RT_SPRITE:
|
||||||
ri.Error( ERR_DROP, "R_AddEntitySurfaces: Sprite being added to entities, should be added to sprite list" );
|
|
||||||
break;
|
|
||||||
case RT_BEAM:
|
case RT_BEAM:
|
||||||
// self blood sprites, talk balloons, etc should not be drawn in the primary
|
// self blood sprites, talk balloons, etc should not be drawn in the primary
|
||||||
// view. We can't just do this check for all entities, because md3
|
// view. We can't just do this check for all entities, because md3
|
||||||
|
@ -1951,22 +1584,6 @@ static void R_AddEntitySurface (int entityNum)
|
||||||
}
|
}
|
||||||
R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0, 0 );
|
R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0, 0 );
|
||||||
break;
|
break;
|
||||||
case MOD_TIKI:
|
|
||||||
if( ( ent->e.renderfx & RF_THIRD_PERSON ) && !tr.viewParms.isPortal ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//if( !r_showSkeleton->integer ) {
|
|
||||||
R_AddSkelSurfaces( ent );
|
|
||||||
//} else {
|
|
||||||
// R_AddDrawSurf( ( void * )&entitySurface, tr.defaultShader, 0 /*fogNum*/, 0, 0, 0 );
|
|
||||||
//}
|
|
||||||
break;
|
|
||||||
case MOD_SPRITE:
|
|
||||||
if( ( ent->e.renderfx & RF_THIRD_PERSON ) && !tr.viewParms.isPortal ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
R_AddDrawSurf( &entitySurface, tr.currentModel->d.sprite->shader, 0, 0, 0, 0 );
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad modeltype" );
|
ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad modeltype" );
|
||||||
break;
|
break;
|
||||||
|
@ -1978,10 +1595,6 @@ static void R_AddEntitySurface (int entityNum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void R_AddSpriteSurface( int entityNum ) {
|
|
||||||
// FIXME: stub
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
R_AddEntitySurfaces
|
R_AddEntitySurfaces
|
||||||
|
@ -1998,22 +1611,6 @@ void R_AddEntitySurfaces (void) {
|
||||||
R_AddEntitySurface(i);
|
R_AddEntitySurface(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
R_AddSpriteSurfaces
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void R_AddSpriteSurfaces( void ) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if( !r_drawentities->integer ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( i = 0; i < tr.refdef.num_entities; i++ )
|
|
||||||
R_AddSpriteSurface( i );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================
|
====================
|
||||||
|
@ -2037,12 +1634,10 @@ void R_GenerateDrawSurfs( void ) {
|
||||||
R_SetFarClip();
|
R_SetFarClip();
|
||||||
}
|
}
|
||||||
|
|
||||||
R_AddTerrainMarkSurfaces();
|
|
||||||
R_AddEntitySurfaces();
|
|
||||||
R_AddSpriteSurfaces();
|
|
||||||
|
|
||||||
// we know the size of the clipping volume. Now set the rest of the projection matrix.
|
// we know the size of the clipping volume. Now set the rest of the projection matrix.
|
||||||
R_SetupProjectionZ (&tr.viewParms);
|
R_SetupProjectionZ (&tr.viewParms);
|
||||||
|
|
||||||
|
R_AddEntitySurfaces ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2087,115 +1682,20 @@ Visualization aid for movement clipping debugging
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
void R_DebugGraphics( void ) {
|
void R_DebugGraphics( void ) {
|
||||||
|
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ( !r_debugSurface->integer ) {
|
if ( !r_debugSurface->integer ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
R_IssuePendingRenderCommands();
|
||||||
|
|
||||||
GL_Bind( tr.whiteImage);
|
GL_BindToTMU(tr.whiteImage, TB_COLORMAP);
|
||||||
GL_Cull( CT_FRONT_SIDED );
|
GL_Cull( CT_FRONT_SIDED );
|
||||||
ri.CM_DrawDebugSurface( R_DebugPolygon );
|
ri.CM_DrawDebugSurface( R_DebugPolygon );
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CIRCLE_LENGTH 25
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_DebugCircle
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_DebugCircle( const vec3_t org, float radius, float r, float g, float b, float alpha, qboolean horizontal ) {
|
|
||||||
int i;
|
|
||||||
float ang;
|
|
||||||
debugline_t *line;
|
|
||||||
vec3_t forward, right;
|
|
||||||
vec3_t pos, lastpos;
|
|
||||||
|
|
||||||
if( !ri.DebugLines || !ri.numDebugLines ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( horizontal )
|
|
||||||
{
|
|
||||||
VectorSet( forward, 1, 0, 0 );
|
|
||||||
VectorSet( right, 0, 1, 0 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VectorCopy( tr.refdef.viewaxis[ 1 ], right );
|
|
||||||
VectorCopy( tr.refdef.viewaxis[ 2 ], forward );
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorClear( pos );
|
|
||||||
VectorClear( lastpos );
|
|
||||||
|
|
||||||
for( i = 0; i < CIRCLE_LENGTH; i++ ) {
|
|
||||||
VectorCopy( pos, lastpos );
|
|
||||||
|
|
||||||
ang = ( float )i * 0.0174532925199433f;
|
|
||||||
pos[ 0 ] = ( org[ 0 ] + sin( ang ) * radius * forward[ 0 ] ) +
|
|
||||||
cos( ang ) * radius * right[ 0 ];
|
|
||||||
pos[ 1 ] = ( org[ 1 ] + sin( ang ) * radius * forward[ 1 ] ) +
|
|
||||||
cos( ang ) * radius * right[ 1 ];
|
|
||||||
pos[ 2 ] = ( org[ 2 ] + sin( ang ) * radius * forward[ 2 ] ) +
|
|
||||||
cos( ang ) * radius * right[ 2 ];
|
|
||||||
|
|
||||||
if( i > 0 )
|
|
||||||
{
|
|
||||||
if( *ri.numDebugLines >= r_numdebuglines->integer ) {
|
|
||||||
ri.Printf( PRINT_ALL, "R_DebugCircle: Exceeded MAX_DEBUG_LINES\n" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
line = &( *ri.DebugLines )[ *ri.numDebugLines ];
|
|
||||||
( *ri.numDebugLines )++;
|
|
||||||
VectorCopy( lastpos, line->start );
|
|
||||||
VectorCopy( pos, line->end );
|
|
||||||
VectorSet( line->color, r, g, b );
|
|
||||||
line->alpha = alpha;
|
|
||||||
line->width = 1.0;
|
|
||||||
line->factor = 1;
|
|
||||||
line->pattern = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_DebugLine
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_DebugLine( const vec3_t start, const vec3_t end, float r, float g, float b, float alpha ) {
|
|
||||||
debugline_t *line;
|
|
||||||
|
|
||||||
if( !ri.DebugLines || !ri.numDebugLines ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( *ri.numDebugLines >= r_numdebuglines->integer ) {
|
|
||||||
ri.Printf( PRINT_ALL, "R_DebugLine: Exceeded MAX_DEBUG_LINES\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
line = &( *ri.DebugLines )[ *ri.numDebugLines ];
|
|
||||||
( *ri.numDebugLines )++;
|
|
||||||
VectorCopy( start, line->start );
|
|
||||||
VectorCopy( end, line->end );
|
|
||||||
VectorSet( line->color, r, g, b );
|
|
||||||
line->alpha = alpha;
|
|
||||||
line->width = 1.0;
|
|
||||||
line->factor = 1;
|
|
||||||
line->pattern = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_DrawDebugLines
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_DrawDebugLines( void ) {
|
|
||||||
// FIXME: stub
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
|
@ -2240,10 +1740,6 @@ void R_RenderView (viewParms_t *parms) {
|
||||||
|
|
||||||
R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, numDrawSurfs - firstDrawSurf );
|
R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, numDrawSurfs - firstDrawSurf );
|
||||||
|
|
||||||
if( r_showSkeleton->integer ) {
|
|
||||||
R_DebugSkeleton();
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw main system development information (surface outlines, etc)
|
// draw main system development information (surface outlines, etc)
|
||||||
R_DebugGraphics();
|
R_DebugGraphics();
|
||||||
}
|
}
|
||||||
|
@ -2338,7 +1834,7 @@ void R_RenderPshadowMaps(const refdef_t *fd)
|
||||||
{
|
{
|
||||||
trRefEntity_t *ent = &tr.refdef.entities[i];
|
trRefEntity_t *ent = &tr.refdef.entities[i];
|
||||||
|
|
||||||
if((ent->e.renderfx & RF_FIRST_PERSON) && !(ent->e.renderfx & RF_SHADOW))
|
if((ent->e.renderfx & (RF_FIRST_PERSON)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//if((ent->e.renderfx & RF_THIRD_PERSON))
|
//if((ent->e.renderfx & RF_THIRD_PERSON))
|
||||||
|
@ -2363,14 +1859,6 @@ void R_RenderPshadowMaps(const refdef_t *fd)
|
||||||
|
|
||||||
switch (model->type)
|
switch (model->type)
|
||||||
{
|
{
|
||||||
case MOD_TIKI:
|
|
||||||
{
|
|
||||||
dtiki_t *tiki = model->d.tiki;
|
|
||||||
|
|
||||||
radius = TIKI_GetRadiusInternal( tiki, ENTITYNUM_NONE, 1.0 );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2504,7 +1992,7 @@ void R_RenderPshadowMaps(const refdef_t *fd)
|
||||||
VectorScale(lightDir, -1.0f, shadow->lightViewAxis[0]);
|
VectorScale(lightDir, -1.0f, shadow->lightViewAxis[0]);
|
||||||
VectorSet(up, 0, 0, -1);
|
VectorSet(up, 0, 0, -1);
|
||||||
|
|
||||||
if ( abs(DotProduct(up, shadow->lightViewAxis[0])) > 0.9f )
|
if ( fabsf(DotProduct(up, shadow->lightViewAxis[0])) > 0.9f )
|
||||||
{
|
{
|
||||||
VectorSet(up, -1, 0, 0);
|
VectorSet(up, -1, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -2549,7 +2037,7 @@ void R_RenderPshadowMaps(const refdef_t *fd)
|
||||||
if (glRefConfig.framebufferObject)
|
if (glRefConfig.framebufferObject)
|
||||||
shadowParms.targetFbo = tr.pshadowFbos[i];
|
shadowParms.targetFbo = tr.pshadowFbos[i];
|
||||||
|
|
||||||
shadowParms.flags = VPF_SHADOWMAP | VPF_DEPTHSHADOW | VPF_NOVIEWMODEL;
|
shadowParms.flags = VPF_DEPTHSHADOW | VPF_NOVIEWMODEL;
|
||||||
shadowParms.zFar = shadow->lightRadius;
|
shadowParms.zFar = shadow->lightRadius;
|
||||||
|
|
||||||
VectorCopy(shadow->lightOrigin, shadowParms.or.origin);
|
VectorCopy(shadow->lightOrigin, shadowParms.or.origin);
|
||||||
|
@ -2747,7 +2235,7 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if too close to parallel to light direction
|
// Check if too close to parallel to light direction
|
||||||
if (abs(DotProduct(lightViewAxis[2], lightViewAxis[0])) > 0.9f)
|
if (fabsf(DotProduct(lightViewAxis[2], lightViewAxis[0])) > 0.9f)
|
||||||
{
|
{
|
||||||
if (level == 3 || lightViewIndependentOfCameraView)
|
if (level == 3 || lightViewIndependentOfCameraView)
|
||||||
{
|
{
|
||||||
|
@ -3000,11 +2488,10 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene )
|
||||||
{
|
{
|
||||||
refdef_t refdef;
|
refdef_t refdef;
|
||||||
viewParms_t parms;
|
viewParms_t parms;
|
||||||
float oldColorScale = tr.refdef.colorScale;
|
|
||||||
|
|
||||||
memset( &refdef, 0, sizeof( refdef ) );
|
memset( &refdef, 0, sizeof( refdef ) );
|
||||||
refdef.rdflags = 0;
|
refdef.rdflags = 0;
|
||||||
VectorCopy(tr.cubemapOrigins[cubemapIndex], refdef.vieworg);
|
VectorCopy(tr.cubemaps[cubemapIndex].origin, refdef.vieworg);
|
||||||
|
|
||||||
switch(cubemapSide)
|
switch(cubemapSide)
|
||||||
{
|
{
|
||||||
|
@ -3073,12 +2560,15 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene )
|
||||||
|
|
||||||
{
|
{
|
||||||
vec3_t ambient, directed, lightDir;
|
vec3_t ambient, directed, lightDir;
|
||||||
|
float scale;
|
||||||
|
|
||||||
R_LightForPoint(tr.refdef.vieworg, ambient, directed, lightDir);
|
R_LightForPoint(tr.refdef.vieworg, ambient, directed, lightDir);
|
||||||
tr.refdef.colorScale = 1.0f; //766.0f / (directed[0] + directed[1] + directed[2] + 1.0f);
|
scale = directed[0] + directed[1] + directed[2] + ambient[0] + ambient[1] + ambient[2] + 1.0f;
|
||||||
|
|
||||||
// only print message for first side
|
// only print message for first side
|
||||||
if (directed[0] + directed[1] + directed[2] == 0 && cubemapSide == 0)
|
if (scale < 1.0001f && cubemapSide == 0)
|
||||||
{
|
{
|
||||||
ri.Printf(PRINT_ALL, "cubemap %d (%f, %f, %f) is outside the lightgrid!\n", cubemapIndex, tr.refdef.vieworg[0], tr.refdef.vieworg[1], tr.refdef.vieworg[2]);
|
ri.Printf(PRINT_ALL, "cubemap %d %s (%f, %f, %f) is outside the lightgrid or inside a wall!\n", cubemapIndex, tr.cubemaps[cubemapIndex].name, tr.refdef.vieworg[0], tr.refdef.vieworg[1], tr.refdef.vieworg[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3115,12 +2605,6 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene )
|
||||||
|
|
||||||
R_RenderView(&parms);
|
R_RenderView(&parms);
|
||||||
|
|
||||||
if (subscene)
|
if (!subscene)
|
||||||
{
|
|
||||||
tr.refdef.colorScale = oldColorScale;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RE_EndScene();
|
RE_EndScene();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ R_MarkFragments
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
|
int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
|
||||||
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer, float fRadiusSquared ) {
|
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) {
|
||||||
int numsurfaces, numPlanes;
|
int numsurfaces, numPlanes;
|
||||||
int i, j, k, m, n;
|
int i, j, k, m, n;
|
||||||
surfaceType_t *surfaces[64];
|
surfaceType_t *surfaces[64];
|
||||||
|
@ -279,9 +279,6 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this crashes the mohaa client game dll...
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
//increment view count for double check prevention
|
//increment view count for double check prevention
|
||||||
tr.viewCount++;
|
tr.viewCount++;
|
||||||
|
|
||||||
|
@ -353,17 +350,21 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
|
||||||
// The offset is added in the vertex normal vector direction
|
// The offset is added in the vertex normal vector direction
|
||||||
// so all triangles will still fit together.
|
// so all triangles will still fit together.
|
||||||
// The 2 unit offset should avoid pretty much all LOD problems.
|
// The 2 unit offset should avoid pretty much all LOD problems.
|
||||||
|
vec3_t fNormal;
|
||||||
|
|
||||||
numClipPoints = 3;
|
numClipPoints = 3;
|
||||||
|
|
||||||
dv = cv->verts + m * cv->width + n;
|
dv = cv->verts + m * cv->width + n;
|
||||||
|
|
||||||
VectorCopy(dv[0].xyz, clipPoints[0][0]);
|
VectorCopy(dv[0].xyz, clipPoints[0][0]);
|
||||||
VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
|
R_VaoUnpackNormal(fNormal, dv[0].normal);
|
||||||
|
VectorMA(clipPoints[0][0], MARKER_OFFSET, fNormal, clipPoints[0][0]);
|
||||||
VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
|
VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
|
||||||
VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
|
R_VaoUnpackNormal(fNormal, dv[cv->width].normal);
|
||||||
|
VectorMA(clipPoints[0][1], MARKER_OFFSET, fNormal, clipPoints[0][1]);
|
||||||
VectorCopy(dv[1].xyz, clipPoints[0][2]);
|
VectorCopy(dv[1].xyz, clipPoints[0][2]);
|
||||||
VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
|
R_VaoUnpackNormal(fNormal, dv[1].normal);
|
||||||
|
VectorMA(clipPoints[0][2], MARKER_OFFSET, fNormal, clipPoints[0][2]);
|
||||||
// check the normal of this triangle
|
// check the normal of this triangle
|
||||||
VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
|
VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
|
||||||
VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
|
VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
|
||||||
|
@ -383,11 +384,14 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorCopy(dv[1].xyz, clipPoints[0][0]);
|
VectorCopy(dv[1].xyz, clipPoints[0][0]);
|
||||||
VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
|
R_VaoUnpackNormal(fNormal, dv[1].normal);
|
||||||
|
VectorMA(clipPoints[0][0], MARKER_OFFSET, fNormal, clipPoints[0][0]);
|
||||||
VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
|
VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
|
||||||
VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
|
R_VaoUnpackNormal(fNormal, dv[cv->width].normal);
|
||||||
|
VectorMA(clipPoints[0][1], MARKER_OFFSET, fNormal, clipPoints[0][1]);
|
||||||
VectorCopy(dv[cv->width+1].xyz, clipPoints[0][2]);
|
VectorCopy(dv[cv->width+1].xyz, clipPoints[0][2]);
|
||||||
VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width+1].normal, clipPoints[0][2]);
|
R_VaoUnpackNormal(fNormal, dv[cv->width + 1].normal);
|
||||||
|
VectorMA(clipPoints[0][2], MARKER_OFFSET, fNormal, clipPoints[0][2]);
|
||||||
// check the normal of this triangle
|
// check the normal of this triangle
|
||||||
VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
|
VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
|
||||||
VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
|
VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
|
||||||
|
@ -444,8 +448,10 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
|
||||||
{
|
{
|
||||||
for(j = 0; j < 3; j++)
|
for(j = 0; j < 3; j++)
|
||||||
{
|
{
|
||||||
|
vec3_t fNormal;
|
||||||
v = surf->verts[tri[j]].xyz;
|
v = surf->verts[tri[j]].xyz;
|
||||||
VectorMA(v, MARKER_OFFSET, surf->verts[tri[j]].normal, clipPoints[0][j]);
|
R_VaoUnpackNormal(fNormal, surf->verts[tri[j]].normal);
|
||||||
|
VectorMA(v, MARKER_OFFSET, fNormal, clipPoints[0][j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the fragments of this face
|
// add the fragments of this face
|
||||||
|
@ -463,12 +469,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
|
||||||
return returnedFragments;
|
return returnedFragments;
|
||||||
}
|
}
|
||||||
|
|
||||||
int R_MarkFragmentsForInlineModel( clipHandle_t bmodel, vec3_t vAngles, vec3_t vOrigin, int numPoints, vec3_t *points, vec3_t projection,
|
|
||||||
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer, float fRadiusSquared ) {
|
|
||||||
// FIXME: unimplemented
|
|
||||||
//return R_MarkFragments( numPoints, points, projection, maxPoints, pointBuffer, maxFragments, fragmentBuffer, fRadiusSquared );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
// tr_models.c -- model loading and caching
|
// tr_models.c -- model loading and caching
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
#include "tiki.h"
|
||||||
#include <vector.h>
|
#include <vector.h>
|
||||||
|
|
||||||
#define LL(x) x=LittleLong(x)
|
#define LL(x) x=LittleLong(x)
|
||||||
|
@ -34,10 +35,10 @@ model_t *R_GetModelByHandle( qhandle_t hModel ) {
|
||||||
|
|
||||||
// out of range gets the default model
|
// out of range gets the default model
|
||||||
if( hModel < 1 || hModel >= tr.numModels ) {
|
if( hModel < 1 || hModel >= tr.numModels ) {
|
||||||
return &tr.models[0];
|
return tr.models[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
mod = &tr.models[hModel];
|
mod = tr.models[hModel];
|
||||||
|
|
||||||
return mod;
|
return mod;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +77,7 @@ model_t *R_AllocModel( void ) {
|
||||||
|
|
||||||
for( i = 0; i < tr.numModels; i++ )
|
for( i = 0; i < tr.numModels; i++ )
|
||||||
{
|
{
|
||||||
if( !tr.models[ i ].name[ 0 ] ) {
|
if( !tr.models[ i ]->name[ 0 ] ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,9 +89,9 @@ model_t *R_AllocModel( void ) {
|
||||||
tr.numModels++;
|
tr.numModels++;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.models[ i ].index = i;
|
tr.models[ i ]->index = i;
|
||||||
|
|
||||||
return &tr.models[ i ];
|
return tr.models[ i ];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -101,11 +102,11 @@ void RE_FreeModels( void ) {
|
||||||
|
|
||||||
for( hModel = 0; hModel < tr.numModels; hModel++ )
|
for( hModel = 0; hModel < tr.numModels; hModel++ )
|
||||||
{
|
{
|
||||||
if( !tr.models[ hModel ].name[ 0 ] ) {
|
if( !tr.models[ hModel ]->name[ 0 ] ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
R_FreeModel( &tr.models[ hModel ] );
|
R_FreeModel( tr.models[ hModel ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,8 +146,8 @@ void RE_UnregisterServerModel( qhandle_t hModel ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( tr.models[ hModel ].serveronly ) {
|
if( tr.models[ hModel ]->serveronly ) {
|
||||||
R_FreeModel( &tr.models[ hModel ] );
|
R_FreeModel( tr.models[ hModel ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +175,7 @@ static qhandle_t R_RegisterModelInternal( const char *name, qboolean bBeginTiki,
|
||||||
// search the currently loaded models
|
// search the currently loaded models
|
||||||
//
|
//
|
||||||
for( hModel = 1; hModel < tr.numModels; hModel++ ) {
|
for( hModel = 1; hModel < tr.numModels; hModel++ ) {
|
||||||
mod = &tr.models[ hModel ];
|
mod = tr.models[ hModel ];
|
||||||
if( !strcmp( mod->name, name ) ) {
|
if( !strcmp( mod->name, name ) ) {
|
||||||
if( mod->type == MOD_BAD ) {
|
if( mod->type == MOD_BAD ) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -195,7 +196,6 @@ static qhandle_t R_RegisterModelInternal( const char *name, qboolean bBeginTiki,
|
||||||
|
|
||||||
|
|
||||||
// make sure the render thread is stopped
|
// make sure the render thread is stopped
|
||||||
//R_SyncRenderThread();
|
|
||||||
R_IssuePendingRenderCommands();
|
R_IssuePendingRenderCommands();
|
||||||
|
|
||||||
mod->serveronly = qtrue;
|
mod->serveronly = qtrue;
|
||||||
|
@ -272,8 +272,8 @@ qhandle_t RE_SpawnEffectModel( const char *szModel, vec3_t vPos, vec3_t *axis )
|
||||||
|
|
||||||
if( new_entity.hModel )
|
if( new_entity.hModel )
|
||||||
{
|
{
|
||||||
tr.models[ new_entity.hModel ].serveronly = qfalse;
|
tr.models[ new_entity.hModel ]->serveronly = qfalse;
|
||||||
ri.CG_ProcessInitCommands( tr.models[ new_entity.hModel ].d.tiki, &new_entity );
|
ri.CG_ProcessInitCommands( tr.models[ new_entity.hModel ]->d.tiki, &new_entity );
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_entity.hModel;
|
return new_entity.hModel;
|
||||||
|
@ -288,7 +288,7 @@ qhandle_t RE_RegisterModel( const char *name ) {
|
||||||
handle = R_RegisterModelInternal( name, qtrue, qtrue );
|
handle = R_RegisterModelInternal( name, qtrue, qtrue );
|
||||||
|
|
||||||
if( handle ) {
|
if( handle ) {
|
||||||
tr.models[ handle ].serveronly = qfalse;
|
tr.models[ handle ]->serveronly = qfalse;
|
||||||
}
|
}
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -323,7 +323,7 @@ void R_Modellist_f( void ) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for( i = 1; i < tr.numModels; i++ ) {
|
for( i = 1; i < tr.numModels; i++ ) {
|
||||||
ri.Printf( PRINT_ALL, "%s\n", tr.models[ i ].name );
|
ri.Printf( PRINT_ALL, "%s\n", tr.models[ i ]->name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +773,6 @@ void R_AddSkelSurfaces( trRefEntity_t *ent ) {
|
||||||
int mesh;
|
int mesh;
|
||||||
int iRadiusCull = 0;
|
int iRadiusCull = 0;
|
||||||
int num_tags;
|
int num_tags;
|
||||||
int cubemapIndex;
|
|
||||||
|
|
||||||
tiki = ent->e.tiki;
|
tiki = ent->e.tiki;
|
||||||
|
|
||||||
|
@ -873,8 +872,6 @@ void R_AddSkelSurfaces( trRefEntity_t *ent ) {
|
||||||
R_SetupEntityLighting( &tr.refdef, ent );
|
R_SetupEntityLighting( &tr.refdef, ent );
|
||||||
}
|
}
|
||||||
|
|
||||||
cubemapIndex = R_CubemapForPoint( ent->e.origin );
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// draw all meshes
|
// draw all meshes
|
||||||
//
|
//
|
||||||
|
@ -932,16 +929,16 @@ void R_AddSkelSurfaces( trRefEntity_t *ent ) {
|
||||||
if( ( *bsurf & 0x40 ) && ( dsurf->numskins > 1 ) ) {
|
if( ( *bsurf & 0x40 ) && ( dsurf->numskins > 1 ) ) {
|
||||||
int iShaderNum = ent->e.skinNum + ( *bsurf & 2 );
|
int iShaderNum = ent->e.skinNum + ( *bsurf & 2 );
|
||||||
|
|
||||||
R_AddDrawSurf( ( surfaceType_t * )surface, tr.shaders[ dsurf->hShader[ iShaderNum ] ], 0, qfalse, qfalse, cubemapIndex );
|
R_AddDrawSurf( ( surfaceType_t * )surface, tr.shaders[ dsurf->hShader[ iShaderNum ] ], 0, 0, 0, 0 );
|
||||||
R_AddDrawSurf( ( surfaceType_t * )surface, tr.shaders[ dsurf->hShader[ iShaderNum + 1 ] ], 0, qfalse, qfalse, cubemapIndex );
|
R_AddDrawSurf( ( surfaceType_t * )surface, tr.shaders[ dsurf->hShader[ iShaderNum + 1 ] ], 0, 0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
R_AddDrawSurf( ( surfaceType_t * )surface, shader, 0, qfalse, qtrue, cubemapIndex );
|
R_AddDrawSurf( ( surfaceType_t * )surface, shader, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( ent->e.customShader ) && ( ent->e.renderfx & RF_CUSTOMSHADERPASS ) ) {
|
if( ( ent->e.customShader ) && ( ent->e.renderfx & RF_CUSTOMSHADERPASS ) ) {
|
||||||
shader = R_GetShaderByHandle( ent->e.customShader );
|
shader = R_GetShaderByHandle( ent->e.customShader );
|
||||||
R_AddDrawSurf( ( surfaceType_t * )surface, shader, 0, qfalse, qfalse, cubemapIndex );
|
R_AddDrawSurf( ( surfaceType_t * )surface, shader, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1042,7 +1039,7 @@ LerpSkelMesh
|
||||||
*/
|
*/
|
||||||
static void LerpSkelMesh( skelSurfaceGame_t *sf ) {
|
static void LerpSkelMesh( skelSurfaceGame_t *sf ) {
|
||||||
float *outXyz;
|
float *outXyz;
|
||||||
uint32_t *outNormal;
|
int16_t *outNormal;
|
||||||
skeletorVertex_t *newVerts;
|
skeletorVertex_t *newVerts;
|
||||||
skeletorMorph_t *morph;
|
skeletorMorph_t *morph;
|
||||||
skelWeight_t *weight;
|
skelWeight_t *weight;
|
||||||
|
@ -1065,7 +1062,7 @@ static void LerpSkelMesh( skelSurfaceGame_t *sf ) {
|
||||||
newVerts = sf->pVerts;
|
newVerts = sf->pVerts;
|
||||||
|
|
||||||
outXyz = tess.xyz[ tess.numVertexes ];
|
outXyz = tess.xyz[ tess.numVertexes ];
|
||||||
outNormal = &tess.normal[ tess.numVertexes ];
|
outNormal = &tess.normal[ tess.numVertexes ][0];
|
||||||
|
|
||||||
bones = &TIKI_Skel_Bones[ backEnd.currentEntity->e.bonestart ];
|
bones = &TIKI_Skel_Bones[ backEnd.currentEntity->e.bonestart ];
|
||||||
morphs = &skeletorMorphCache[ backEnd.currentEntity->e.morphstart ];
|
morphs = &skeletorMorphCache[ backEnd.currentEntity->e.morphstart ];
|
||||||
|
@ -1224,7 +1221,7 @@ static void LerpSkelMesh( skelSurfaceGame_t *sf ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
R_VaoPackNormal( ( byte * )outNormal, normal );
|
R_VaoPackNormal(outNormal, normal);
|
||||||
|
|
||||||
VectorScale( out, scale, outXyz );
|
VectorScale( out, scale, outXyz );
|
||||||
|
|
||||||
|
@ -1246,8 +1243,6 @@ void RB_SkelMesh( skelSurfaceGame_t *sf ) {
|
||||||
int numVerts;
|
int numVerts;
|
||||||
int numIndexes;
|
int numIndexes;
|
||||||
|
|
||||||
RB_CheckVao( tess.vao );
|
|
||||||
|
|
||||||
numIndexes = sf->numTriangles * 3;
|
numIndexes = sf->numTriangles * 3;
|
||||||
|
|
||||||
RB_CHECKOVERFLOW( sf->numVerts, numIndexes );
|
RB_CHECKOVERFLOW( sf->numVerts, numIndexes );
|
||||||
|
@ -1264,8 +1259,8 @@ void RB_SkelMesh( skelSurfaceGame_t *sf ) {
|
||||||
numVerts = sf->numVerts;
|
numVerts = sf->numVerts;
|
||||||
vert = sf->pVerts;
|
vert = sf->pVerts;
|
||||||
for( j = 0; j < numVerts; j++ ) {
|
for( j = 0; j < numVerts; j++ ) {
|
||||||
tess.texCoords[ baseVertex + j ][ 0 ][ 0 ] = vert->texCoords[ 0 ];
|
tess.texCoords[ baseVertex + j ][ 0 ] = vert->texCoords[ 0 ];
|
||||||
tess.texCoords[ baseVertex + j ][ 0 ][ 1 ] = vert->texCoords[ 1 ];
|
tess.texCoords[ baseVertex + j ][ 1 ] = vert->texCoords[ 1 ];
|
||||||
vert = ( skeletorVertex_t * )( ( byte * )vert + sizeof( skeletorVertex_t ) + sizeof( skeletorMorph_t ) * vert->numMorphs + sizeof( skelWeight_t ) * vert->numWeights );
|
vert = ( skeletorVertex_t * )( ( byte * )vert + sizeof( skeletorVertex_t ) + sizeof( skeletorMorph_t ) * vert->numMorphs + sizeof( skelWeight_t ) * vert->numWeights );
|
||||||
// FIXME: fill in lightmapST for completeness?
|
// FIXME: fill in lightmapST for completeness?
|
||||||
}
|
}
|
||||||
|
@ -1426,7 +1421,7 @@ void R_DebugSkeleton( void ) {
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
R_IssuePendingRenderCommands();
|
||||||
|
|
||||||
GL_Bind( tr.whiteImage );
|
GL_BindToTMU(tr.whiteImage, TB_COLORMAP);
|
||||||
GL_State( 0x200 );
|
GL_State( 0x200 );
|
||||||
|
|
||||||
glDisableClientState( GL_COLOR_ARRAY );
|
glDisableClientState( GL_COLOR_ARRAY );
|
||||||
|
|
|
@ -82,7 +82,7 @@ void RB_ToneMap(FBO_t *hdrFbo, ivec4_t hdrBox, FBO_t *ldrFbo, ivec4_t ldrBox, in
|
||||||
// tonemap
|
// tonemap
|
||||||
color[0] =
|
color[0] =
|
||||||
color[1] =
|
color[1] =
|
||||||
color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value);
|
color[2] = pow(2, r_cameraExposure->value - autoExposure); //exp2(r_cameraExposure->value);
|
||||||
color[3] = 1.0f;
|
color[3] = 1.0f;
|
||||||
|
|
||||||
if (autoExposure)
|
if (autoExposure)
|
||||||
|
@ -183,7 +183,7 @@ void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float
|
||||||
FBO_Blit(tr.textureScratchFbo[0], NULL, blurTexScale, tr.textureScratchFbo[1], NULL, &tr.bokehShader, color, 0);
|
FBO_Blit(tr.textureScratchFbo[0], NULL, blurTexScale, tr.textureScratchFbo[1], NULL, &tr.bokehShader, color, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
FBO_Blit(tr.textureScratchFbo[1], NULL, NULL, dst, dstBox, &tr.textureColorShader, NULL, 0);
|
FBO_Blit(tr.textureScratchFbo[1], NULL, NULL, dst, dstBox, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
#else // higher quality blur, but slower
|
#else // higher quality blur, but slower
|
||||||
else if (blur > 1.0f)
|
else if (blur > 1.0f)
|
||||||
|
@ -217,7 +217,7 @@ void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float
|
||||||
FBO_Blit(tr.quarterFbo[0], NULL, blurTexScale, tr.quarterFbo[1], NULL, &tr.bokehShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
|
FBO_Blit(tr.quarterFbo[0], NULL, blurTexScale, tr.quarterFbo[1], NULL, &tr.bokehShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
FBO_Blit(tr.quarterFbo[1], NULL, NULL, dst, dstBox, &tr.textureColorShader, NULL, 0);
|
FBO_Blit(tr.quarterFbo[1], NULL, NULL, dst, dstBox, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -227,54 +227,40 @@ void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float
|
||||||
static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretch, float x, float y, float w, float h, float xcenter, float ycenter, float alpha)
|
static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretch, float x, float y, float w, float h, float xcenter, float ycenter, float alpha)
|
||||||
{
|
{
|
||||||
ivec4_t srcBox, dstBox;
|
ivec4_t srcBox, dstBox;
|
||||||
|
int srcWidth, srcHeight;
|
||||||
vec4_t color;
|
vec4_t color;
|
||||||
const float inc = 1.f / passes;
|
const float inc = 1.f / passes;
|
||||||
const float mul = powf(stretch, inc);
|
const float mul = powf(stretch, inc);
|
||||||
float scale;
|
float scale;
|
||||||
|
|
||||||
|
alpha *= inc;
|
||||||
|
VectorSet4(color, alpha, alpha, alpha, 1.0f);
|
||||||
|
|
||||||
|
srcWidth = srcFbo ? srcFbo->width : glConfig.vidWidth;
|
||||||
|
srcHeight = srcFbo ? srcFbo->height : glConfig.vidHeight;
|
||||||
|
|
||||||
|
VectorSet4(srcBox, 0, 0, srcWidth, srcHeight);
|
||||||
|
|
||||||
|
VectorSet4(dstBox, x, y, w, h);
|
||||||
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 0);
|
||||||
|
|
||||||
|
--passes;
|
||||||
|
scale = mul;
|
||||||
|
while (passes > 0)
|
||||||
{
|
{
|
||||||
vec2_t texScale;
|
float iscale = 1.f / scale;
|
||||||
|
float s0 = xcenter * (1.f - iscale);
|
||||||
|
float t0 = (1.0f - ycenter) * (1.f - iscale);
|
||||||
|
|
||||||
texScale[0] =
|
srcBox[0] = s0 * srcWidth;
|
||||||
texScale[1] = 1.0f;
|
srcBox[1] = t0 * srcHeight;
|
||||||
|
srcBox[2] = iscale * srcWidth;
|
||||||
alpha *= inc;
|
srcBox[3] = iscale * srcHeight;
|
||||||
VectorSet4(color, alpha, alpha, alpha, 1.0f);
|
|
||||||
|
|
||||||
VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
|
|
||||||
VectorSet4(dstBox, x, y, w, h);
|
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, 0);
|
|
||||||
|
|
||||||
--passes;
|
|
||||||
scale = mul;
|
|
||||||
while (passes > 0)
|
|
||||||
{
|
|
||||||
float iscale = 1.f / scale;
|
|
||||||
float s0 = xcenter * (1.f - iscale);
|
|
||||||
float t0 = (1.0f - ycenter) * (1.f - iscale);
|
|
||||||
float s1 = iscale + s0;
|
|
||||||
float t1 = iscale + t0;
|
|
||||||
|
|
||||||
if (srcFbo)
|
|
||||||
{
|
|
||||||
srcBox[0] = s0 * srcFbo->width;
|
|
||||||
srcBox[1] = t0 * srcFbo->height;
|
|
||||||
srcBox[2] = (s1 - s0) * srcFbo->width;
|
|
||||||
srcBox[3] = (t1 - t0) * srcFbo->height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
srcBox[0] = s0 * glConfig.vidWidth;
|
|
||||||
srcBox[1] = t0 * glConfig.vidHeight;
|
|
||||||
srcBox[2] = (s1 - s0) * glConfig.vidWidth;
|
|
||||||
srcBox[3] = (t1 - t0) * glConfig.vidHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
||||||
|
|
||||||
scale *= mul;
|
scale *= mul;
|
||||||
--passes;
|
--passes;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +282,7 @@ static qboolean RB_UpdateSunFlareVis(void)
|
||||||
for (iter=0 ; ; ++iter)
|
for (iter=0 ; ; ++iter)
|
||||||
{
|
{
|
||||||
GLint available = 0;
|
GLint available = 0;
|
||||||
qglGetQueryObjectivARB(tr.sunFlareQuery[tr.sunFlareQueryIndex], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
|
qglGetQueryObjectiv(tr.sunFlareQuery[tr.sunFlareQueryIndex], GL_QUERY_RESULT_AVAILABLE, &available);
|
||||||
if (available)
|
if (available)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -304,7 +290,7 @@ static qboolean RB_UpdateSunFlareVis(void)
|
||||||
ri.Printf(PRINT_DEVELOPER, "Waited %d iterations\n", iter);
|
ri.Printf(PRINT_DEVELOPER, "Waited %d iterations\n", iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
qglGetQueryObjectuivARB(tr.sunFlareQuery[tr.sunFlareQueryIndex], GL_QUERY_RESULT_ARB, &sampleCount);
|
qglGetQueryObjectuiv(tr.sunFlareQuery[tr.sunFlareQueryIndex], GL_QUERY_RESULT, &sampleCount);
|
||||||
return sampleCount > 0;
|
return sampleCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +315,7 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox)
|
||||||
// From RB_DrawSun()
|
// From RB_DrawSun()
|
||||||
{
|
{
|
||||||
float dist;
|
float dist;
|
||||||
mat4_t trans, model, mvp;
|
mat4_t trans, model;
|
||||||
|
|
||||||
Mat4Translation( backEnd.viewParms.or.origin, trans );
|
Mat4Translation( backEnd.viewParms.or.origin, trans );
|
||||||
Mat4Multiply( backEnd.viewParms.world.modelMatrix, trans, model );
|
Mat4Multiply( backEnd.viewParms.world.modelMatrix, trans, model );
|
||||||
|
@ -353,28 +339,16 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox)
|
||||||
// initialize quarter buffers
|
// initialize quarter buffers
|
||||||
{
|
{
|
||||||
float mul = 1.f;
|
float mul = 1.f;
|
||||||
vec2_t texScale;
|
|
||||||
ivec4_t rayBox, quarterBox;
|
ivec4_t rayBox, quarterBox;
|
||||||
|
int srcWidth = srcFbo ? srcFbo->width : glConfig.vidWidth;
|
||||||
texScale[0] =
|
int srcHeight = srcFbo ? srcFbo->height : glConfig.vidHeight;
|
||||||
texScale[1] = 1.0f;
|
|
||||||
|
|
||||||
VectorSet4(color, mul, mul, mul, 1);
|
VectorSet4(color, mul, mul, mul, 1);
|
||||||
|
|
||||||
if (srcFbo)
|
rayBox[0] = srcBox[0] * tr.sunRaysFbo->width / srcWidth;
|
||||||
{
|
rayBox[1] = srcBox[1] * tr.sunRaysFbo->height / srcHeight;
|
||||||
rayBox[0] = srcBox[0] * tr.sunRaysFbo->width / srcFbo->width;
|
rayBox[2] = srcBox[2] * tr.sunRaysFbo->width / srcWidth;
|
||||||
rayBox[1] = srcBox[1] * tr.sunRaysFbo->height / srcFbo->height;
|
rayBox[3] = srcBox[3] * tr.sunRaysFbo->height / srcHeight;
|
||||||
rayBox[2] = srcBox[2] * tr.sunRaysFbo->width / srcFbo->width;
|
|
||||||
rayBox[3] = srcBox[3] * tr.sunRaysFbo->height / srcFbo->height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rayBox[0] = srcBox[0] * tr.sunRaysFbo->width / glConfig.vidWidth;
|
|
||||||
rayBox[1] = srcBox[1] * tr.sunRaysFbo->height / glConfig.vidHeight;
|
|
||||||
rayBox[2] = srcBox[2] * tr.sunRaysFbo->width / glConfig.vidWidth;
|
|
||||||
rayBox[3] = srcBox[3] * tr.sunRaysFbo->height / glConfig.vidHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
quarterBox[0] = 0;
|
quarterBox[0] = 0;
|
||||||
quarterBox[1] = tr.quarterFbo[0]->height;
|
quarterBox[1] = tr.quarterFbo[0]->height;
|
||||||
|
@ -408,14 +382,10 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox)
|
||||||
// add result back on top of the main buffer
|
// add result back on top of the main buffer
|
||||||
{
|
{
|
||||||
float mul = 1.f;
|
float mul = 1.f;
|
||||||
vec2_t texScale;
|
|
||||||
|
|
||||||
texScale[0] =
|
|
||||||
texScale[1] = 1.0f;
|
|
||||||
|
|
||||||
VectorSet4(color, mul, mul, mul, 1);
|
VectorSet4(color, mul, mul, mul, 1);
|
||||||
|
|
||||||
FBO_Blit(tr.quarterFbo[0], NULL, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
FBO_Blit(tr.quarterFbo[0], NULL, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,31 +413,27 @@ static void RB_BlurAxis(FBO_t *srcFbo, FBO_t *dstFbo, float strength, qboolean h
|
||||||
{
|
{
|
||||||
ivec4_t srcBox, dstBox;
|
ivec4_t srcBox, dstBox;
|
||||||
vec4_t color;
|
vec4_t color;
|
||||||
vec2_t texScale;
|
|
||||||
|
|
||||||
texScale[0] =
|
|
||||||
texScale[1] = 1.0f;
|
|
||||||
|
|
||||||
VectorSet4(color, weights[0], weights[0], weights[0], 1.0f);
|
VectorSet4(color, weights[0], weights[0], weights[0], 1.0f);
|
||||||
VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
|
||||||
VectorSet4(dstBox, 0, 0, dstFbo->width, dstFbo->height);
|
VectorSet4(dstBox, 0, 0, dstFbo->width, dstFbo->height);
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, 0 );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 0);
|
||||||
|
|
||||||
VectorSet4(color, weights[1], weights[1], weights[1], 1.0f);
|
VectorSet4(color, weights[1], weights[1], weights[1], 1.0f);
|
||||||
dx = offsets[1] * xmul;
|
dx = offsets[1] * xmul;
|
||||||
dy = offsets[1] * ymul;
|
dy = offsets[1] * ymul;
|
||||||
VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
||||||
VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
||||||
|
|
||||||
VectorSet4(color, weights[2], weights[2], weights[2], 1.0f);
|
VectorSet4(color, weights[2], weights[2], weights[2], 1.0f);
|
||||||
dx = offsets[2] * xmul;
|
dx = offsets[2] * xmul;
|
||||||
dy = offsets[2] * ymul;
|
dy = offsets[2] * ymul;
|
||||||
VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
||||||
VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,10 +458,6 @@ void RB_GaussianBlur(float blur)
|
||||||
{
|
{
|
||||||
ivec4_t srcBox, dstBox;
|
ivec4_t srcBox, dstBox;
|
||||||
vec4_t color;
|
vec4_t color;
|
||||||
vec2_t texScale;
|
|
||||||
|
|
||||||
texScale[0] =
|
|
||||||
texScale[1] = 1.0f;
|
|
||||||
|
|
||||||
VectorSet4(color, 1, 1, 1, 1);
|
VectorSet4(color, 1, 1, 1, 1);
|
||||||
|
|
||||||
|
@ -504,10 +466,8 @@ void RB_GaussianBlur(float blur)
|
||||||
FBO_FastBlit(tr.quarterFbo[0], NULL, tr.textureScratchFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
FBO_FastBlit(tr.quarterFbo[0], NULL, tr.textureScratchFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
|
|
||||||
// set the alpha channel
|
// set the alpha channel
|
||||||
VectorSet4(srcBox, 0, 0, tr.whiteImage->width, tr.whiteImage->height);
|
|
||||||
VectorSet4(dstBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
|
|
||||||
qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||||
FBO_BlitFromTexture(tr.whiteImage, srcBox, texScale, tr.textureScratchFbo[0], dstBox, &tr.textureColorShader, color, GLS_DEPTHTEST_DISABLE);
|
FBO_BlitFromTexture(tr.whiteImage, NULL, NULL, tr.textureScratchFbo[0], NULL, NULL, color, GLS_DEPTHTEST_DISABLE);
|
||||||
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
|
||||||
// blur the tiny buffer horizontally and vertically
|
// blur the tiny buffer horizontally and vertically
|
||||||
|
@ -518,6 +478,6 @@ void RB_GaussianBlur(float blur)
|
||||||
VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
|
VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
|
||||||
VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
||||||
color[3] = factor;
|
color[3] = factor;
|
||||||
FBO_Blit(tr.textureScratchFbo[0], srcBox, texScale, NULL, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
|
FBO_Blit(tr.textureScratchFbo[0], srcBox, NULL, NULL, dstBox, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -30,9 +30,6 @@ int r_firstSceneDlight;
|
||||||
int r_numentities;
|
int r_numentities;
|
||||||
int r_firstSceneEntity;
|
int r_firstSceneEntity;
|
||||||
|
|
||||||
int r_numsprites;
|
|
||||||
int r_firstSceneSprite;
|
|
||||||
|
|
||||||
int r_numpolys;
|
int r_numpolys;
|
||||||
int r_firstScenePoly;
|
int r_firstScenePoly;
|
||||||
|
|
||||||
|
@ -56,9 +53,6 @@ void R_InitNextFrame( void ) {
|
||||||
r_numentities = 0;
|
r_numentities = 0;
|
||||||
r_firstSceneEntity = 0;
|
r_firstSceneEntity = 0;
|
||||||
|
|
||||||
r_numsprites = 0;
|
|
||||||
r_firstSceneSprite = 0;
|
|
||||||
|
|
||||||
r_numpolys = 0;
|
r_numpolys = 0;
|
||||||
r_firstScenePoly = 0;
|
r_firstScenePoly = 0;
|
||||||
|
|
||||||
|
@ -75,7 +69,6 @@ RE_ClearScene
|
||||||
void RE_ClearScene( void ) {
|
void RE_ClearScene( void ) {
|
||||||
r_firstSceneDlight = r_numdlights;
|
r_firstSceneDlight = r_numdlights;
|
||||||
r_firstSceneEntity = r_numentities;
|
r_firstSceneEntity = r_numentities;
|
||||||
r_firstSceneSprite = r_numsprites;
|
|
||||||
r_firstScenePoly = r_numpolys;
|
r_firstScenePoly = r_numpolys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,15 +109,15 @@ RE_AddPolyToScene
|
||||||
|
|
||||||
=====================
|
=====================
|
||||||
*/
|
*/
|
||||||
qboolean RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int renderfx ) {
|
void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) {
|
||||||
srfPoly_t *poly;
|
srfPoly_t *poly;
|
||||||
int i;
|
int i, j;
|
||||||
int fogIndex;
|
int fogIndex;
|
||||||
fog_t *fog;
|
fog_t *fog;
|
||||||
vec3_t bounds[2];
|
vec3_t bounds[2];
|
||||||
|
|
||||||
if ( !tr.registered ) {
|
if ( !tr.registered ) {
|
||||||
return qfalse;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !hShader ) {
|
if ( !hShader ) {
|
||||||
|
@ -134,106 +127,72 @@ qboolean RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *v
|
||||||
//return;
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( r_numpolyverts + numVerts > max_polyverts || r_numpolys >= max_polys ) {
|
for ( j = 0; j < numPolys; j++ ) {
|
||||||
/*
|
if ( r_numpolyverts + numVerts > max_polyverts || r_numpolys >= max_polys ) {
|
||||||
NOTE TTimo this was initially a PRINT_WARNING
|
/*
|
||||||
but it happens a lot with high fighting scenes and particles
|
NOTE TTimo this was initially a PRINT_WARNING
|
||||||
since we don't plan on changing the const and making for room for those effects
|
but it happens a lot with high fighting scenes and particles
|
||||||
simply cut this message to developer only
|
since we don't plan on changing the const and making for room for those effects
|
||||||
*/
|
simply cut this message to developer only
|
||||||
ri.Printf( PRINT_DEVELOPER, "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n");
|
*/
|
||||||
return qfalse;
|
ri.Printf( PRINT_DEVELOPER, "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n");
|
||||||
}
|
return;
|
||||||
|
|
||||||
poly = &backEndData->polys[r_numpolys];
|
|
||||||
poly->surfaceType = SF_POLY;
|
|
||||||
poly->hShader = hShader;
|
|
||||||
poly->numVerts = numVerts;
|
|
||||||
poly->verts = &backEndData->polyVerts[r_numpolyverts];
|
|
||||||
poly->renderfx = renderfx;
|
|
||||||
|
|
||||||
Com_Memcpy( poly->verts, verts, numVerts * sizeof( *verts ) );
|
|
||||||
|
|
||||||
if ( glConfig.hardwareType == GLHW_RAGEPRO ) {
|
|
||||||
poly->verts->modulate[0] = 255;
|
|
||||||
poly->verts->modulate[1] = 255;
|
|
||||||
poly->verts->modulate[2] = 255;
|
|
||||||
poly->verts->modulate[3] = 255;
|
|
||||||
}
|
|
||||||
// done.
|
|
||||||
r_numpolys++;
|
|
||||||
r_numpolyverts += numVerts;
|
|
||||||
|
|
||||||
// if no world is loaded
|
|
||||||
if ( tr.world == NULL ) {
|
|
||||||
fogIndex = 0;
|
|
||||||
}
|
|
||||||
// see if it is in a fog volume
|
|
||||||
else if ( tr.world->numfogs == 1 ) {
|
|
||||||
fogIndex = 0;
|
|
||||||
} else {
|
|
||||||
// find which fog volume the poly is in
|
|
||||||
VectorCopy( poly->verts[0].xyz, bounds[0] );
|
|
||||||
VectorCopy( poly->verts[0].xyz, bounds[1] );
|
|
||||||
for ( i = 1 ; i < poly->numVerts ; i++ ) {
|
|
||||||
AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
|
|
||||||
}
|
}
|
||||||
for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
|
|
||||||
fog = &tr.world->fogs[fogIndex];
|
poly = &backEndData->polys[r_numpolys];
|
||||||
if ( bounds[1][0] >= fog->bounds[0][0]
|
poly->surfaceType = SF_POLY;
|
||||||
&& bounds[1][1] >= fog->bounds[0][1]
|
poly->hShader = hShader;
|
||||||
&& bounds[1][2] >= fog->bounds[0][2]
|
poly->numVerts = numVerts;
|
||||||
&& bounds[0][0] <= fog->bounds[1][0]
|
poly->verts = &backEndData->polyVerts[r_numpolyverts];
|
||||||
&& bounds[0][1] <= fog->bounds[1][1]
|
|
||||||
&& bounds[0][2] <= fog->bounds[1][2] ) {
|
Com_Memcpy( poly->verts, &verts[numVerts*j], numVerts * sizeof( *verts ) );
|
||||||
break;
|
|
||||||
}
|
if ( glConfig.hardwareType == GLHW_RAGEPRO ) {
|
||||||
|
poly->verts->modulate[0] = 255;
|
||||||
|
poly->verts->modulate[1] = 255;
|
||||||
|
poly->verts->modulate[2] = 255;
|
||||||
|
poly->verts->modulate[3] = 255;
|
||||||
}
|
}
|
||||||
if ( fogIndex == tr.world->numfogs ) {
|
// done.
|
||||||
|
r_numpolys++;
|
||||||
|
r_numpolyverts += numVerts;
|
||||||
|
|
||||||
|
// if no world is loaded
|
||||||
|
if ( tr.world == NULL ) {
|
||||||
fogIndex = 0;
|
fogIndex = 0;
|
||||||
}
|
}
|
||||||
|
// see if it is in a fog volume
|
||||||
|
else if ( tr.world->numfogs == 1 ) {
|
||||||
|
fogIndex = 0;
|
||||||
|
} else {
|
||||||
|
// find which fog volume the poly is in
|
||||||
|
VectorCopy( poly->verts[0].xyz, bounds[0] );
|
||||||
|
VectorCopy( poly->verts[0].xyz, bounds[1] );
|
||||||
|
for ( i = 1 ; i < poly->numVerts ; i++ ) {
|
||||||
|
AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
|
||||||
|
}
|
||||||
|
for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
|
||||||
|
fog = &tr.world->fogs[fogIndex];
|
||||||
|
if ( bounds[1][0] >= fog->bounds[0][0]
|
||||||
|
&& bounds[1][1] >= fog->bounds[0][1]
|
||||||
|
&& bounds[1][2] >= fog->bounds[0][2]
|
||||||
|
&& bounds[0][0] <= fog->bounds[1][0]
|
||||||
|
&& bounds[0][1] <= fog->bounds[1][1]
|
||||||
|
&& bounds[0][2] <= fog->bounds[1][2] ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( fogIndex == tr.world->numfogs ) {
|
||||||
|
fogIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
poly->fogIndex = fogIndex;
|
||||||
}
|
}
|
||||||
poly->fogIndex = fogIndex;
|
|
||||||
|
|
||||||
return qtrue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
R_AddTerrainMarkSurfaces
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void R_AddTerrainMarkSurfaces( void ) {
|
|
||||||
// FIXME: stub
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
RE_AddTerrainMarkToScene
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void RE_AddTerrainMarkToScene( int iTerrainIndex, qhandle_t hShader, int numVerts, polyVert_t *verts, int renderfx ) {
|
|
||||||
// FIXME: stub
|
|
||||||
}
|
|
||||||
|
|
||||||
//=================================================================================
|
//=================================================================================
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
RE_GetRenderEntity
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
refEntity_t *RE_GetRenderEntity( int entityNumber ) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < r_numentities; i++ ) {
|
|
||||||
if( backEndData->entities[ i ].e.entityNumber == entityNumber ) {
|
|
||||||
return &backEndData->entities[ i ].e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=====================
|
=====================
|
||||||
|
@ -241,9 +200,8 @@ RE_AddRefEntityToScene
|
||||||
|
|
||||||
=====================
|
=====================
|
||||||
*/
|
*/
|
||||||
void RE_AddRefEntityToScene( const refEntity_t *ent, int parentEntityNumber ) {
|
void RE_AddRefEntityToScene( const refEntity_t *ent ) {
|
||||||
vec3_t cross;
|
vec3_t cross;
|
||||||
int i;
|
|
||||||
|
|
||||||
if ( !tr.registered ) {
|
if ( !tr.registered ) {
|
||||||
return;
|
return;
|
||||||
|
@ -264,18 +222,7 @@ void RE_AddRefEntityToScene( const refEntity_t *ent, int parentEntityNumber ) {
|
||||||
ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
|
ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
|
||||||
}
|
}
|
||||||
|
|
||||||
backEndData->entities[ r_numentities ].e = *ent;
|
backEndData->entities[r_numentities].e = *ent;
|
||||||
backEndData->entities[ r_numentities ].e.parentEntity = ENTITYNUM_NONE;
|
|
||||||
|
|
||||||
if( parentEntityNumber != ENTITYNUM_NONE ) {
|
|
||||||
for( i = r_firstSceneEntity; i < r_numentities; i++ ) {
|
|
||||||
if( backEndData->entities[ i ].e.entityNumber == parentEntityNumber ) {
|
|
||||||
backEndData->entities[ r_numentities ].e.parentEntity = parentEntityNumber;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
backEndData->entities[r_numentities].lightingCalculated = qfalse;
|
backEndData->entities[r_numentities].lightingCalculated = qfalse;
|
||||||
|
|
||||||
CrossProduct(ent->axis[0], ent->axis[1], cross);
|
CrossProduct(ent->axis[0], ent->axis[1], cross);
|
||||||
|
@ -284,48 +231,6 @@ void RE_AddRefEntityToScene( const refEntity_t *ent, int parentEntityNumber ) {
|
||||||
r_numentities++;
|
r_numentities++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
RE_AddRefEntityToScene
|
|
||||||
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void RE_AddRefSpriteToScene( const refEntity_t *ent ) {
|
|
||||||
refSprite_t *spr;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if ( !tr.registered ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( r_numsprites >= MAX_REFSPRITES ) {
|
|
||||||
ri.Printf(PRINT_DEVELOPER, "RE_AddRefSpriteToScene: Dropping refSprite, reached MAX_REFSPRITES\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( Q_isnan(ent->origin[0]) || Q_isnan(ent->origin[1]) || Q_isnan(ent->origin[2]) ) {
|
|
||||||
static qboolean firstTime = qtrue;
|
|
||||||
if (firstTime) {
|
|
||||||
firstTime = qfalse;
|
|
||||||
ri.Printf( PRINT_WARNING, "RE_AddRefSpriteToScene passed a refEntity which has an origin with a NaN component\n");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
spr = &backEndData->sprites[ r_numsprites ];
|
|
||||||
|
|
||||||
VectorCopy( ent->origin, spr->origin );
|
|
||||||
spr->surftype = SF_SPRITE;
|
|
||||||
spr->hModel = ent->hModel;
|
|
||||||
spr->scale = ent->scale;
|
|
||||||
spr->renderfx = ent->renderfx;
|
|
||||||
spr->shaderTime = ent->shaderTime;
|
|
||||||
AxisCopy( ent->axis, spr->axis );
|
|
||||||
|
|
||||||
for( i = 0; i < 4; i++ ) {
|
|
||||||
spr->shaderRGBA[ i ] = ent->shaderRGBA[ i ];
|
|
||||||
}
|
|
||||||
|
|
||||||
r_numsprites++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=====================
|
=====================
|
||||||
|
@ -364,7 +269,7 @@ RE_AddLightToScene
|
||||||
|
|
||||||
=====================
|
=====================
|
||||||
*/
|
*/
|
||||||
void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b, int type ) {
|
void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
|
||||||
RE_AddDynamicLightToScene( org, intensity, r, g, b, qfalse );
|
RE_AddDynamicLightToScene( org, intensity, r, g, b, qfalse );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,8 +286,6 @@ void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, flo
|
||||||
|
|
||||||
void RE_BeginScene(const refdef_t *fd)
|
void RE_BeginScene(const refdef_t *fd)
|
||||||
{
|
{
|
||||||
//Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
|
|
||||||
|
|
||||||
tr.refdef.x = fd->x;
|
tr.refdef.x = fd->x;
|
||||||
tr.refdef.y = fd->y;
|
tr.refdef.y = fd->y;
|
||||||
tr.refdef.width = fd->width;
|
tr.refdef.width = fd->width;
|
||||||
|
@ -424,37 +327,30 @@ void RE_BeginScene(const refdef_t *fd)
|
||||||
|
|
||||||
VectorCopy(tr.sunDirection, tr.refdef.sunDir);
|
VectorCopy(tr.sunDirection, tr.refdef.sunDir);
|
||||||
if ( (tr.refdef.rdflags & RDF_NOWORLDMODEL) || !(r_depthPrepass->value) ){
|
if ( (tr.refdef.rdflags & RDF_NOWORLDMODEL) || !(r_depthPrepass->value) ){
|
||||||
tr.refdef.colorScale = 1.0f;
|
|
||||||
VectorSet(tr.refdef.sunCol, 0, 0, 0);
|
VectorSet(tr.refdef.sunCol, 0, 0, 0);
|
||||||
VectorSet(tr.refdef.sunAmbCol, 0, 0, 0);
|
VectorSet(tr.refdef.sunAmbCol, 0, 0, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tr.refdef.colorScale = r_forceSun->integer ? r_forceSunMapLightScale->value : tr.mapLightScale;
|
float scale = (1 << r_mapOverBrightBits->integer) / 255.0f;
|
||||||
|
|
||||||
|
if (r_forceSun->integer)
|
||||||
|
VectorScale(tr.sunLight, scale * r_forceSunLightScale->value, tr.refdef.sunCol);
|
||||||
|
else
|
||||||
|
VectorScale(tr.sunLight, scale, tr.refdef.sunCol);
|
||||||
|
|
||||||
if (r_sunlightMode->integer == 1)
|
if (r_sunlightMode->integer == 1)
|
||||||
{
|
{
|
||||||
tr.refdef.sunCol[0] =
|
|
||||||
tr.refdef.sunCol[1] =
|
|
||||||
tr.refdef.sunCol[2] = 1.0f;
|
|
||||||
|
|
||||||
tr.refdef.sunAmbCol[0] =
|
tr.refdef.sunAmbCol[0] =
|
||||||
tr.refdef.sunAmbCol[1] =
|
tr.refdef.sunAmbCol[1] =
|
||||||
tr.refdef.sunAmbCol[2] = r_forceSun->integer ? r_forceSunAmbientScale->value : tr.sunShadowScale;
|
tr.refdef.sunAmbCol[2] = r_forceSun->integer ? r_forceSunAmbientScale->value : tr.sunShadowScale;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float scale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8);
|
|
||||||
if (r_forceSun->integer)
|
if (r_forceSun->integer)
|
||||||
{
|
|
||||||
VectorScale(tr.sunLight, scale * r_forceSunLightScale->value, tr.refdef.sunCol);
|
|
||||||
VectorScale(tr.sunLight, scale * r_forceSunAmbientScale->value, tr.refdef.sunAmbCol);
|
VectorScale(tr.sunLight, scale * r_forceSunAmbientScale->value, tr.refdef.sunAmbCol);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
VectorScale(tr.sunLight, scale, tr.refdef.sunCol);
|
|
||||||
VectorScale(tr.sunLight, scale * tr.sunShadowScale, tr.refdef.sunAmbCol);
|
VectorScale(tr.sunLight, scale * tr.sunShadowScale, tr.refdef.sunAmbCol);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +398,7 @@ void RE_BeginScene(const refdef_t *fd)
|
||||||
|
|
||||||
// derived info
|
// derived info
|
||||||
|
|
||||||
tr.refdef.floatTime = tr.refdef.time * 0.001f;
|
tr.refdef.floatTime = tr.refdef.time * 0.001;
|
||||||
|
|
||||||
tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
|
tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
|
||||||
tr.refdef.drawSurfs = backEndData->drawSurfs;
|
tr.refdef.drawSurfs = backEndData->drawSurfs;
|
||||||
|
@ -510,9 +406,6 @@ void RE_BeginScene(const refdef_t *fd)
|
||||||
tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
|
tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
|
||||||
tr.refdef.entities = &backEndData->entities[r_firstSceneEntity];
|
tr.refdef.entities = &backEndData->entities[r_firstSceneEntity];
|
||||||
|
|
||||||
tr.refdef.num_sprites = r_numsprites - r_firstSceneSprite;
|
|
||||||
tr.refdef.sprites = &backEndData->sprites[r_firstSceneSprite];
|
|
||||||
|
|
||||||
tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
|
tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
|
||||||
tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight];
|
tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight];
|
||||||
|
|
||||||
|
@ -522,9 +415,6 @@ void RE_BeginScene(const refdef_t *fd)
|
||||||
tr.refdef.num_pshadows = 0;
|
tr.refdef.num_pshadows = 0;
|
||||||
tr.refdef.pshadows = &backEndData->pshadows[0];
|
tr.refdef.pshadows = &backEndData->pshadows[0];
|
||||||
|
|
||||||
backEndData->staticModels = tr.refdef.staticModels;
|
|
||||||
backEndData->staticModelData = tr.refdef.staticModelData;
|
|
||||||
|
|
||||||
// turn off dynamic lighting globally by clearing all the
|
// turn off dynamic lighting globally by clearing all the
|
||||||
// dlights if it needs to be disabled or if vertex lighting is enabled
|
// dlights if it needs to be disabled or if vertex lighting is enabled
|
||||||
if ( r_dynamiclight->integer == 0 ||
|
if ( r_dynamiclight->integer == 0 ||
|
||||||
|
@ -543,12 +433,11 @@ void RE_BeginScene(const refdef_t *fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RE_EndScene()
|
void RE_EndScene(void)
|
||||||
{
|
{
|
||||||
// the next scene rendered in this frame will tack on after this one
|
// the next scene rendered in this frame will tack on after this one
|
||||||
r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
|
r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
|
||||||
r_firstSceneEntity = r_numentities;
|
r_firstSceneEntity = r_numentities;
|
||||||
r_firstSceneSprite = r_numsprites;
|
|
||||||
r_firstSceneDlight = r_numdlights;
|
r_firstSceneDlight = r_numdlights;
|
||||||
r_firstScenePoly = r_numpolys;
|
r_firstScenePoly = r_numpolys;
|
||||||
}
|
}
|
||||||
|
@ -583,9 +472,6 @@ void RE_RenderScene( const refdef_t *fd ) {
|
||||||
ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
|
ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
|
||||||
}
|
}
|
||||||
|
|
||||||
//R_VisDebug();
|
|
||||||
TIKI_Reset_Caches();
|
|
||||||
|
|
||||||
RE_BeginScene(fd);
|
RE_BeginScene(fd);
|
||||||
|
|
||||||
// SmileTheory: playing with shadow mapping
|
// SmileTheory: playing with shadow mapping
|
||||||
|
@ -603,7 +489,7 @@ void RE_RenderScene( const refdef_t *fd ) {
|
||||||
// playing with even more shadows
|
// playing with even more shadows
|
||||||
if(glRefConfig.framebufferObject && r_sunlightMode->integer && !( fd->rdflags & RDF_NOWORLDMODEL ) && (r_forceSun->integer || tr.sunShadows))
|
if(glRefConfig.framebufferObject && r_sunlightMode->integer && !( fd->rdflags & RDF_NOWORLDMODEL ) && (r_forceSun->integer || tr.sunShadows))
|
||||||
{
|
{
|
||||||
if (r_shadowCascadeZFar != 0)
|
if (r_shadowCascadeZFar->integer != 0)
|
||||||
{
|
{
|
||||||
R_RenderSunShadowMaps(fd, 0);
|
R_RenderSunShadowMaps(fd, 0);
|
||||||
R_RenderSunShadowMaps(fd, 1);
|
R_RenderSunShadowMaps(fd, 1);
|
||||||
|
|
|
@ -22,9 +22,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
// tr_shade.c
|
// tr_shade.c
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
#if idppc_altivec && !defined(MACOS_X)
|
|
||||||
#include <altivec.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
@ -41,42 +38,9 @@ R_DrawElements
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void R_DrawElementsVao( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex )
|
void R_DrawElements( int numIndexes, int firstIndex )
|
||||||
{
|
{
|
||||||
if (glRefConfig.drawRangeElements)
|
qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t)));
|
||||||
qglDrawRangeElementsEXT(GL_TRIANGLES, minIndex, maxIndex, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t)));
|
|
||||||
else
|
|
||||||
qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void R_DrawMultiElementsVao( int multiDrawPrimitives, glIndex_t *multiDrawMinIndex, glIndex_t *multiDrawMaxIndex,
|
|
||||||
GLsizei *multiDrawNumIndexes, glIndex_t **multiDrawFirstIndex)
|
|
||||||
{
|
|
||||||
if (glRefConfig.multiDrawArrays && multiDrawPrimitives > 1)
|
|
||||||
{
|
|
||||||
qglMultiDrawElementsEXT(GL_TRIANGLES, multiDrawNumIndexes, GL_INDEX_TYPE, (const GLvoid **)multiDrawFirstIndex, multiDrawPrimitives);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (glRefConfig.drawRangeElements)
|
|
||||||
{
|
|
||||||
for (i = 0; i < multiDrawPrimitives; i++)
|
|
||||||
{
|
|
||||||
qglDrawRangeElementsEXT(GL_TRIANGLES, multiDrawMinIndex[i], multiDrawMaxIndex[i], multiDrawNumIndexes[i], GL_INDEX_TYPE, multiDrawFirstIndex[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < multiDrawPrimitives; i++)
|
|
||||||
{
|
|
||||||
qglDrawElements(GL_TRIANGLES, multiDrawNumIndexes[i], GL_INDEX_TYPE, multiDrawFirstIndex[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,16 +62,7 @@ R_BindAnimatedImageToTMU
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
static void R_BindAnimatedImageToTMU( textureBundle_t *bundle, int tmu ) {
|
static void R_BindAnimatedImageToTMU( textureBundle_t *bundle, int tmu ) {
|
||||||
int index;
|
int64_t index;
|
||||||
|
|
||||||
if ( bundle->isVideoMap ) {
|
|
||||||
int oldtmu = glState.currenttmu;
|
|
||||||
GL_SelectTexture(tmu);
|
|
||||||
ri.CIN_RunCinematic(bundle->videoMapHandle);
|
|
||||||
ri.CIN_UploadCinematic(bundle->videoMapHandle);
|
|
||||||
GL_SelectTexture(oldtmu);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bundle->numImageAnimations <= 1 ) {
|
if ( bundle->numImageAnimations <= 1 ) {
|
||||||
GL_BindToTMU( bundle->image[0], tmu);
|
GL_BindToTMU( bundle->image[0], tmu);
|
||||||
|
@ -116,13 +71,18 @@ static void R_BindAnimatedImageToTMU( textureBundle_t *bundle, int tmu ) {
|
||||||
|
|
||||||
// it is necessary to do this messy calc to make sure animations line up
|
// it is necessary to do this messy calc to make sure animations line up
|
||||||
// exactly with waveforms of the same frequency
|
// exactly with waveforms of the same frequency
|
||||||
index = ftol(tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE);
|
index = tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE;
|
||||||
index >>= FUNCTABLE_SIZE2;
|
index >>= FUNCTABLE_SIZE2;
|
||||||
|
|
||||||
if ( index < 0 ) {
|
if ( index < 0 ) {
|
||||||
index = 0; // may happen with shader time offsets
|
index = 0; // may happen with shader time offsets
|
||||||
}
|
}
|
||||||
index %= bundle->numImageAnimations;
|
|
||||||
|
// Windows x86 doesn't load renderer DLL with 64 bit modulus
|
||||||
|
//index %= bundle->numImageAnimations;
|
||||||
|
while ( index >= bundle->numImageAnimations ) {
|
||||||
|
index -= bundle->numImageAnimations;
|
||||||
|
}
|
||||||
|
|
||||||
GL_BindToTMU( bundle->image[ index ], tmu );
|
GL_BindToTMU( bundle->image[ index ], tmu );
|
||||||
}
|
}
|
||||||
|
@ -136,7 +96,7 @@ Draws triangle outlines for debugging
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
static void DrawTris (shaderCommands_t *input) {
|
static void DrawTris (shaderCommands_t *input) {
|
||||||
GL_Bind( tr.whiteImage );
|
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
|
||||||
|
|
||||||
GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
|
GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
|
||||||
qglDepthRange( 0, 0 );
|
qglDepthRange( 0, 0 );
|
||||||
|
@ -150,15 +110,9 @@ static void DrawTris (shaderCommands_t *input) {
|
||||||
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
|
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
|
||||||
VectorSet4(color, 1, 1, 1, 1);
|
VectorSet4(color, 1, 1, 1, 1);
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_COLOR, color);
|
GLSL_SetUniformVec4(sp, UNIFORM_COLOR, color);
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 0);
|
||||||
|
|
||||||
if (input->multiDrawPrimitives)
|
R_DrawElements(input->numIndexes, input->firstIndex);
|
||||||
{
|
|
||||||
R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qglDepthRange( 0, 1 );
|
qglDepthRange( 0, 1 );
|
||||||
|
@ -192,17 +146,16 @@ void RB_BeginSurface( shader_t *shader, int fogNum, int cubemapIndex ) {
|
||||||
tess.numIndexes = 0;
|
tess.numIndexes = 0;
|
||||||
tess.firstIndex = 0;
|
tess.firstIndex = 0;
|
||||||
tess.numVertexes = 0;
|
tess.numVertexes = 0;
|
||||||
tess.multiDrawPrimitives = 0;
|
|
||||||
tess.shader = state;
|
tess.shader = state;
|
||||||
tess.fogNum = fogNum;
|
tess.fogNum = fogNum;
|
||||||
tess.cubemapIndex = cubemapIndex;
|
tess.cubemapIndex = cubemapIndex;
|
||||||
tess.dlightBits = 0; // will be OR'd in by surface functions
|
tess.dlightBits = 0; // will be OR'd in by surface functions
|
||||||
tess.vertexColorValid = r_vertexLight->integer != 0;
|
|
||||||
tess.pshadowBits = 0; // will be OR'd in by surface functions
|
tess.pshadowBits = 0; // will be OR'd in by surface functions
|
||||||
tess.xstages = state->stages;
|
tess.xstages = state->stages;
|
||||||
tess.numPasses = state->numUnfoggedPasses;
|
tess.numPasses = state->numUnfoggedPasses;
|
||||||
tess.currentStageIteratorFunc = state->optimalStageIteratorFunc;
|
tess.currentStageIteratorFunc = state->optimalStageIteratorFunc;
|
||||||
tess.useInternalVao = qtrue;
|
tess.useInternalVao = qtrue;
|
||||||
|
tess.useCacheVao = qfalse;
|
||||||
|
|
||||||
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
|
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
|
||||||
if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) {
|
if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) {
|
||||||
|
@ -378,7 +331,7 @@ static void ProjectDlightTexture( void ) {
|
||||||
vec4_t vector;
|
vec4_t vector;
|
||||||
|
|
||||||
if ( !( tess.dlightBits & ( 1 << l ) ) ) {
|
if ( !( tess.dlightBits & ( 1 << l ) ) ) {
|
||||||
continue; // this surface definately doesn't have any of this light
|
continue; // this surface definitely doesn't have any of this light
|
||||||
}
|
}
|
||||||
|
|
||||||
dl = &backEnd.refdef.dlights[l];
|
dl = &backEnd.refdef.dlights[l];
|
||||||
|
@ -415,7 +368,7 @@ static void ProjectDlightTexture( void ) {
|
||||||
vector[3] = scale;
|
vector[3] = scale;
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_DLIGHTINFO, vector);
|
GLSL_SetUniformVec4(sp, UNIFORM_DLIGHTINFO, vector);
|
||||||
|
|
||||||
GL_Bind( tr.dlightImage );
|
GL_BindToTMU( tr.dlightImage, TB_COLORMAP );
|
||||||
|
|
||||||
// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
|
// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
|
||||||
// where they aren't rendered
|
// where they aren't rendered
|
||||||
|
@ -426,15 +379,9 @@ static void ProjectDlightTexture( void ) {
|
||||||
GL_State( GLS_ATEST_GT_0 | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
|
GL_State( GLS_ATEST_GT_0 | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tess.multiDrawPrimitives)
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 1);
|
||||||
{
|
|
||||||
shaderCommands_t *input = &tess;
|
R_DrawElements(tess.numIndexes, tess.firstIndex);
|
||||||
R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
backEnd.pc.c_totalIndexes += tess.numIndexes;
|
backEnd.pc.c_totalIndexes += tess.numIndexes;
|
||||||
backEnd.pc.c_dlightIndexes += tess.numIndexes;
|
backEnd.pc.c_dlightIndexes += tess.numIndexes;
|
||||||
|
@ -445,6 +392,17 @@ static void ProjectDlightTexture( void ) {
|
||||||
|
|
||||||
static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor, int blend )
|
static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor, int blend )
|
||||||
{
|
{
|
||||||
|
qboolean isBlend = ((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_DST_COLOR)
|
||||||
|
|| ((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_ONE_MINUS_DST_COLOR)
|
||||||
|
|| ((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_SRC_COLOR)
|
||||||
|
|| ((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR);
|
||||||
|
|
||||||
|
qboolean is2DDraw = backEnd.currentEntity == &backEnd.entity2D;
|
||||||
|
|
||||||
|
float overbright = (isBlend || is2DDraw) ? 1.0f : (float)(1 << tr.overbrightBits);
|
||||||
|
|
||||||
|
fog_t *fog;
|
||||||
|
|
||||||
baseColor[0] =
|
baseColor[0] =
|
||||||
baseColor[1] =
|
baseColor[1] =
|
||||||
baseColor[2] =
|
baseColor[2] =
|
||||||
|
@ -455,31 +413,11 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
|
||||||
vertColor[2] =
|
vertColor[2] =
|
||||||
vertColor[3] = 0.0f;
|
vertColor[3] = 0.0f;
|
||||||
|
|
||||||
if( tess.vertexColorValid ) {
|
|
||||||
vec4_t *in = ( vec4_t * )&tess.vertexColors;
|
|
||||||
color4ub_t *out = tess.svars.colors;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < tess.numVertexes; i++, in++, out++ )
|
|
||||||
{
|
|
||||||
( *out )[ 0 ] = ( byte )( *in )[ i ] * 255;
|
|
||||||
( *out )[ 1 ] = ( byte )( *in )[ i + 1 ] * 255;
|
|
||||||
( *out )[ 2 ] = ( byte )( *in )[ i + 2 ] * 255;
|
|
||||||
( *out )[ 3 ] = ( byte )( *in )[ i + 3 ] * 255;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// rgbGen
|
// rgbGen
|
||||||
//
|
//
|
||||||
switch ( pStage->rgbGen )
|
switch ( pStage->rgbGen )
|
||||||
{
|
{
|
||||||
case CGEN_IDENTITY_LIGHTING:
|
|
||||||
baseColor[0] =
|
|
||||||
baseColor[1] =
|
|
||||||
baseColor[2] = tr.identityLight;
|
|
||||||
break;
|
|
||||||
case CGEN_EXACT_VERTEX:
|
case CGEN_EXACT_VERTEX:
|
||||||
case CGEN_EXACT_VERTEX_LIT:
|
case CGEN_EXACT_VERTEX_LIT:
|
||||||
baseColor[0] =
|
baseColor[0] =
|
||||||
|
@ -489,86 +427,49 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
|
||||||
|
|
||||||
vertColor[0] =
|
vertColor[0] =
|
||||||
vertColor[1] =
|
vertColor[1] =
|
||||||
vertColor[2] =
|
vertColor[2] = overbright;
|
||||||
vertColor[3] = 1.0f;
|
vertColor[3] = 1.0f;
|
||||||
break;
|
break;
|
||||||
case CGEN_LIGHTING_GRID:
|
|
||||||
baseColor[ 0 ] =
|
|
||||||
baseColor[ 1 ] =
|
|
||||||
baseColor[ 2 ] = RB_CalcLightGridColor();
|
|
||||||
break;
|
|
||||||
case CGEN_STATIC:
|
|
||||||
// FIXME: set light
|
|
||||||
break;
|
|
||||||
case CGEN_CONST:
|
case CGEN_CONST:
|
||||||
baseColor[0] = pStage->constantColor[0] / 255.0f;
|
baseColor[0] = pStage->constantColor[0] / 255.0f;
|
||||||
baseColor[1] = pStage->constantColor[1] / 255.0f;
|
baseColor[1] = pStage->constantColor[1] / 255.0f;
|
||||||
baseColor[2] = pStage->constantColor[2] / 255.0f;
|
baseColor[2] = pStage->constantColor[2] / 255.0f;
|
||||||
baseColor[3] = pStage->constantColor[3] / 255.0f;
|
baseColor[3] = pStage->constantColor[3] / 255.0f;
|
||||||
break;
|
break;
|
||||||
case CGEN_GLOBAL_COLOR:
|
|
||||||
baseColor[0] = backEnd.color2D[0];
|
|
||||||
baseColor[1] = backEnd.color2D[1];
|
|
||||||
baseColor[2] = backEnd.color2D[2];
|
|
||||||
baseColor[3] = backEnd.color2D[3];
|
|
||||||
break;
|
|
||||||
case CGEN_VERTEX:
|
case CGEN_VERTEX:
|
||||||
baseColor[0] =
|
case CGEN_VERTEX_LIT:
|
||||||
|
baseColor[0] =
|
||||||
baseColor[1] =
|
baseColor[1] =
|
||||||
baseColor[2] =
|
baseColor[2] =
|
||||||
baseColor[3] = 0.0f;
|
baseColor[3] = 0.0f;
|
||||||
|
|
||||||
vertColor[0] =
|
vertColor[0] =
|
||||||
vertColor[1] =
|
vertColor[1] =
|
||||||
vertColor[2] = tr.identityLight;
|
vertColor[2] =
|
||||||
vertColor[3] = 1.0f;
|
vertColor[3] = 1.0f;
|
||||||
break;
|
break;
|
||||||
case CGEN_VERTEX_LIT:
|
|
||||||
baseColor[0] =
|
|
||||||
baseColor[1] =
|
|
||||||
baseColor[2] =
|
|
||||||
baseColor[3] = 0.0f;
|
|
||||||
|
|
||||||
vertColor[0] =
|
|
||||||
vertColor[1] =
|
|
||||||
vertColor[2] =
|
|
||||||
vertColor[3] = tr.identityLight;
|
|
||||||
break;
|
|
||||||
case CGEN_ONE_MINUS_VERTEX:
|
case CGEN_ONE_MINUS_VERTEX:
|
||||||
baseColor[0] =
|
baseColor[0] =
|
||||||
baseColor[1] =
|
baseColor[1] =
|
||||||
baseColor[2] = tr.identityLight;
|
baseColor[2] = 1.0f;
|
||||||
|
|
||||||
vertColor[0] =
|
vertColor[0] =
|
||||||
vertColor[1] =
|
vertColor[1] =
|
||||||
vertColor[2] = -tr.identityLight;
|
vertColor[2] = -1.0f;
|
||||||
break;
|
break;
|
||||||
case CGEN_FOG:
|
case CGEN_FOG:
|
||||||
{
|
fog = tr.world->fogs + tess.fogNum;
|
||||||
fog_t *fog;
|
|
||||||
|
|
||||||
fog = tr.world->fogs + tess.fogNum;
|
baseColor[0] = ((unsigned char *)(&fog->colorInt))[0] / 255.0f;
|
||||||
|
baseColor[1] = ((unsigned char *)(&fog->colorInt))[1] / 255.0f;
|
||||||
baseColor[0] = ((unsigned char *)(&fog->colorInt))[0] / 255.0f;
|
baseColor[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f;
|
||||||
baseColor[1] = ((unsigned char *)(&fog->colorInt))[1] / 255.0f;
|
baseColor[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f;
|
||||||
baseColor[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f;
|
|
||||||
baseColor[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CGEN_WAVEFORM:
|
case CGEN_WAVEFORM:
|
||||||
baseColor[0] =
|
baseColor[0] =
|
||||||
baseColor[1] =
|
baseColor[1] =
|
||||||
baseColor[2] = RB_CalcWaveColorSingle( &pStage->rgbWave );
|
baseColor[2] = RB_CalcWaveColorSingle( &pStage->rgbWave );
|
||||||
break;
|
break;
|
||||||
case CGEN_MULTIPLY_BY_WAVEFORM:
|
|
||||||
{
|
|
||||||
float color = RB_CalcWaveColorSingle( &pStage->rgbWave );
|
|
||||||
|
|
||||||
baseColor[ 0 ] = color * ( pStage->colorConst[ 0 ] / 255.0 );
|
|
||||||
baseColor[ 1 ] = color * ( pStage->colorConst[ 1 ] / 255.0 );
|
|
||||||
baseColor[ 2 ] = color * ( pStage->colorConst[ 2 ] / 255.0 );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CGEN_ENTITY:
|
case CGEN_ENTITY:
|
||||||
if (backEnd.currentEntity)
|
if (backEnd.currentEntity)
|
||||||
{
|
{
|
||||||
|
@ -587,29 +488,13 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
|
||||||
baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
|
baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CGEN_SCOORD:
|
|
||||||
baseColor[ 0 ] =
|
|
||||||
baseColor[ 1 ] =
|
|
||||||
baseColor[ 2 ] = RB_CalcRGBFromTexCoords( pStage->alphaMin, pStage->alphaMax, pStage->alphaConstMin, pStage->alphaConst, 0.0, 1.0, ( float * ) tess.svars.texcoords );
|
|
||||||
break;
|
|
||||||
case CGEN_TCOORD:
|
|
||||||
baseColor[ 0 ] =
|
|
||||||
baseColor[ 1 ] =
|
|
||||||
baseColor[ 2 ] = RB_CalcRGBFromTexCoords( pStage->alphaMin, pStage->alphaMax, pStage->alphaConstMin, pStage->alphaConst, 1.0, 0.0, ( float * )tess.svars.texcoords );
|
|
||||||
break;
|
|
||||||
case CGEN_DOT:
|
|
||||||
baseColor[ 0 ] =
|
|
||||||
baseColor[ 1 ] =
|
|
||||||
baseColor[ 2 ] = RB_CalcRGBFromDot( pStage->alphaMin, pStage->alphaMax );
|
|
||||||
break;
|
|
||||||
case CGEN_ONE_MINUS_DOT:
|
|
||||||
baseColor[ 0 ] =
|
|
||||||
baseColor[ 1 ] =
|
|
||||||
baseColor[ 2 ] = RB_CalcRGBFromOneMinusDot( pStage->alphaMin, pStage->alphaMax );
|
|
||||||
break;
|
|
||||||
case CGEN_IDENTITY:
|
case CGEN_IDENTITY:
|
||||||
case CGEN_LIGHTING_SPHERICAL:
|
|
||||||
case CGEN_LIGHTING_DIFFUSE:
|
case CGEN_LIGHTING_DIFFUSE:
|
||||||
|
baseColor[0] =
|
||||||
|
baseColor[1] =
|
||||||
|
baseColor[2] = overbright;
|
||||||
|
break;
|
||||||
|
case CGEN_IDENTITY_LIGHTING:
|
||||||
case CGEN_BAD:
|
case CGEN_BAD:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -625,10 +510,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
|
||||||
baseColor[3] = pStage->constantColor[3] / 255.0f;
|
baseColor[3] = pStage->constantColor[3] / 255.0f;
|
||||||
vertColor[3] = 0.0f;
|
vertColor[3] = 0.0f;
|
||||||
break;
|
break;
|
||||||
case AGEN_GLOBAL_ALPHA:
|
|
||||||
baseColor[3] = backEnd.color2D[3];
|
|
||||||
vertColor[3] = 0.0f;
|
|
||||||
break;
|
|
||||||
case AGEN_WAVEFORM:
|
case AGEN_WAVEFORM:
|
||||||
baseColor[3] = RB_CalcWaveAlphaSingle( &pStage->alphaWave );
|
baseColor[3] = RB_CalcWaveAlphaSingle( &pStage->alphaWave );
|
||||||
vertColor[3] = 0.0f;
|
vertColor[3] = 0.0f;
|
||||||
|
@ -655,36 +536,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
|
||||||
baseColor[3] = 1.0f;
|
baseColor[3] = 1.0f;
|
||||||
vertColor[3] = -1.0f;
|
vertColor[3] = -1.0f;
|
||||||
break;
|
break;
|
||||||
case AGEN_DOT:
|
|
||||||
baseColor[ 3 ] = RB_CalcAlphaFromDot( pStage->alphaMin, pStage->alphaMax );
|
|
||||||
break;
|
|
||||||
case AGEN_DOT_VIEW:
|
|
||||||
baseColor[ 3 ] = RB_CalcAlphaFromDotView( pStage->alphaMin, pStage->alphaMax );
|
|
||||||
break;
|
|
||||||
case AGEN_ONE_MINUS_DOT:
|
|
||||||
baseColor[ 3 ] = RB_CalcAlphaFromOneMinusDot( pStage->alphaMin, pStage->alphaMax );
|
|
||||||
break;
|
|
||||||
case AGEN_ONE_MINUS_DOT_VIEW:
|
|
||||||
baseColor[ 3 ] = RB_CalcAlphaFromOneMinusDotView( pStage->alphaMin, pStage->alphaMax );
|
|
||||||
break;
|
|
||||||
case AGEN_SKYALPHA:
|
|
||||||
baseColor[ 3 ] = RB_CalcAlphaFromConstant( tr.refdef.sky_alpha * 255.0, pStage->alphaMax );
|
|
||||||
break;
|
|
||||||
case AGEN_ONE_MINUS_SKYALPHA:
|
|
||||||
baseColor[ 3 ] = RB_CalcAlphaFromConstant( ( 1.0 - tr.refdef.sky_alpha ) * 255.0, pStage->alphaMax );
|
|
||||||
break;
|
|
||||||
case AGEN_SCOORD:
|
|
||||||
baseColor[ 3 ] = RB_CalcAlphaFromTexCoords( pStage->alphaMin, pStage->alphaMax, pStage->alphaConstMin, pStage->alphaConst, 0.0, 1.0, ( float * )tess.svars.texcoords );
|
|
||||||
break;
|
|
||||||
case AGEN_TCOORD:
|
|
||||||
baseColor[ 3 ] = RB_CalcAlphaFromTexCoords( pStage->alphaMin, pStage->alphaMax, pStage->alphaConstMin, pStage->alphaConst, 1.0, 0.0, ( float * )tess.svars.texcoords );
|
|
||||||
break;
|
|
||||||
case AGEN_DIST_FADE:
|
|
||||||
// FIXME
|
|
||||||
break;
|
|
||||||
case AGEN_ONE_MINUS_DIST_FADE:
|
|
||||||
// FIXME
|
|
||||||
break;
|
|
||||||
case AGEN_IDENTITY:
|
case AGEN_IDENTITY:
|
||||||
case AGEN_LIGHTING_SPECULAR:
|
case AGEN_LIGHTING_SPECULAR:
|
||||||
case AGEN_PORTAL:
|
case AGEN_PORTAL:
|
||||||
|
@ -694,23 +545,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiply color by overbrightbits if this isn't a blend
|
|
||||||
if (tr.overbrightBits
|
|
||||||
&& !((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_DST_COLOR)
|
|
||||||
&& !((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_ONE_MINUS_DST_COLOR)
|
|
||||||
&& !((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_SRC_COLOR)
|
|
||||||
&& !((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR))
|
|
||||||
{
|
|
||||||
float scale = 1 << tr.overbrightBits;
|
|
||||||
|
|
||||||
baseColor[0] *= scale;
|
|
||||||
baseColor[1] *= scale;
|
|
||||||
baseColor[2] *= scale;
|
|
||||||
vertColor[0] *= scale;
|
|
||||||
vertColor[1] *= scale;
|
|
||||||
vertColor[2] *= scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: find some way to implement this.
|
// FIXME: find some way to implement this.
|
||||||
#if 0
|
#if 0
|
||||||
// if in greyscale rendering mode turn all color values into greyscale.
|
// if in greyscale rendering mode turn all color values into greyscale.
|
||||||
|
@ -828,7 +662,7 @@ static void ForwardDlight( void ) {
|
||||||
vec4_t texOffTurb;
|
vec4_t texOffTurb;
|
||||||
|
|
||||||
if ( !( tess.dlightBits & ( 1 << l ) ) ) {
|
if ( !( tess.dlightBits & ( 1 << l ) ) ) {
|
||||||
continue; // this surface definately doesn't have any of this light
|
continue; // this surface definitely doesn't have any of this light
|
||||||
}
|
}
|
||||||
|
|
||||||
dl = &backEnd.refdef.dlights[l];
|
dl = &backEnd.refdef.dlights[l];
|
||||||
|
@ -910,6 +744,7 @@ static void ForwardDlight( void ) {
|
||||||
// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
|
// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
|
||||||
// where they aren't rendered
|
// where they aren't rendered
|
||||||
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 0);
|
||||||
|
|
||||||
GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
|
GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
|
||||||
|
|
||||||
|
@ -948,11 +783,7 @@ static void ForwardDlight( void ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_dlightMode->integer >= 2)
|
if (r_dlightMode->integer >= 2)
|
||||||
{
|
GL_BindToTMU(tr.shadowCubemaps[l], TB_SHADOWMAP);
|
||||||
GL_SelectTexture(TB_SHADOWMAP);
|
|
||||||
GL_Bind(tr.shadowCubemaps[l]);
|
|
||||||
GL_SelectTexture(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
|
ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
|
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
|
||||||
|
@ -964,14 +795,7 @@ static void ForwardDlight( void ) {
|
||||||
// draw
|
// draw
|
||||||
//
|
//
|
||||||
|
|
||||||
if (input->multiDrawPrimitives)
|
R_DrawElements(input->numIndexes, input->firstIndex);
|
||||||
{
|
|
||||||
R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
backEnd.pc.c_totalIndexes += tess.numIndexes;
|
backEnd.pc.c_totalIndexes += tess.numIndexes;
|
||||||
backEnd.pc.c_dlightIndexes += tess.numIndexes;
|
backEnd.pc.c_dlightIndexes += tess.numIndexes;
|
||||||
|
@ -1002,7 +826,7 @@ static void ProjectPshadowVBOGLSL( void ) {
|
||||||
vec4_t vector;
|
vec4_t vector;
|
||||||
|
|
||||||
if ( !( tess.pshadowBits & ( 1 << l ) ) ) {
|
if ( !( tess.pshadowBits & ( 1 << l ) ) ) {
|
||||||
continue; // this surface definately doesn't have any of this shadow
|
continue; // this surface definitely doesn't have any of this shadow
|
||||||
}
|
}
|
||||||
|
|
||||||
ps = &backEnd.refdef.pshadows[l];
|
ps = &backEnd.refdef.pshadows[l];
|
||||||
|
@ -1033,6 +857,7 @@ static void ProjectPshadowVBOGLSL( void ) {
|
||||||
// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
|
// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
|
||||||
// where they aren't rendered
|
// where they aren't rendered
|
||||||
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
|
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 0);
|
||||||
|
|
||||||
GL_BindToTMU( tr.pshadowMaps[l], TB_DIFFUSEMAP );
|
GL_BindToTMU( tr.pshadowMaps[l], TB_DIFFUSEMAP );
|
||||||
|
|
||||||
|
@ -1040,14 +865,7 @@ static void ProjectPshadowVBOGLSL( void ) {
|
||||||
// draw
|
// draw
|
||||||
//
|
//
|
||||||
|
|
||||||
if (input->multiDrawPrimitives)
|
R_DrawElements(input->numIndexes, input->firstIndex);
|
||||||
{
|
|
||||||
R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
backEnd.pc.c_totalIndexes += tess.numIndexes;
|
backEnd.pc.c_totalIndexes += tess.numIndexes;
|
||||||
//backEnd.pc.c_dlightIndexes += tess.numIndexes;
|
//backEnd.pc.c_dlightIndexes += tess.numIndexes;
|
||||||
|
@ -1083,6 +901,8 @@ static void RB_FogPass( void ) {
|
||||||
|
|
||||||
if (glState.vertexAnimation)
|
if (glState.vertexAnimation)
|
||||||
index |= FOGDEF_USE_VERTEX_ANIMATION;
|
index |= FOGDEF_USE_VERTEX_ANIMATION;
|
||||||
|
else if (glState.boneAnimation)
|
||||||
|
index |= FOGDEF_USE_BONE_ANIMATION;
|
||||||
|
|
||||||
sp = &tr.fogShader[index];
|
sp = &tr.fogShader[index];
|
||||||
}
|
}
|
||||||
|
@ -1096,6 +916,11 @@ static void RB_FogPass( void ) {
|
||||||
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
|
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
|
||||||
|
|
||||||
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
|
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
|
||||||
|
|
||||||
|
if (glState.boneAnimation)
|
||||||
|
{
|
||||||
|
GLSL_SetUniformMat4BoneMatrix(sp, UNIFORM_BONEMATRIX, glState.boneMatrix, glState.boneAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
GLSL_SetUniformInt(sp, UNIFORM_DEFORMGEN, deformGen);
|
GLSL_SetUniformInt(sp, UNIFORM_DEFORMGEN, deformGen);
|
||||||
if (deformGen != DGEN_NONE)
|
if (deformGen != DGEN_NONE)
|
||||||
|
@ -1121,16 +946,9 @@ static void RB_FogPass( void ) {
|
||||||
} else {
|
} else {
|
||||||
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
|
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
|
||||||
}
|
}
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 0);
|
||||||
|
|
||||||
if (tess.multiDrawPrimitives)
|
R_DrawElements(tess.numIndexes, tess.firstIndex);
|
||||||
{
|
|
||||||
shaderCommands_t *input = &tess;
|
|
||||||
R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1144,9 +962,7 @@ static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input )
|
||||||
if (vertexAttribs & ATTR_NORMAL)
|
if (vertexAttribs & ATTR_NORMAL)
|
||||||
{
|
{
|
||||||
vertexAttribs |= ATTR_NORMAL2;
|
vertexAttribs |= ATTR_NORMAL2;
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
vertexAttribs |= ATTR_TANGENT2;
|
vertexAttribs |= ATTR_TANGENT2;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1163,6 +979,8 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
int deformGen;
|
int deformGen;
|
||||||
vec5_t deformParams;
|
vec5_t deformParams;
|
||||||
|
|
||||||
|
qboolean renderToCubemap = tr.renderCubeFbo && glState.currentFBO == tr.renderCubeFbo;
|
||||||
|
|
||||||
ComputeDeformValues(&deformGen, deformParams);
|
ComputeDeformValues(&deformGen, deformParams);
|
||||||
|
|
||||||
ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT);
|
ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT);
|
||||||
|
@ -1187,7 +1005,14 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
|
|
||||||
if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
|
if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
|
||||||
{
|
{
|
||||||
index |= LIGHTDEF_ENTITY;
|
if (glState.boneAnimation)
|
||||||
|
{
|
||||||
|
index |= LIGHTDEF_ENTITY_BONE_ANIMATION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index |= LIGHTDEF_ENTITY_VERTEX_ANIMATION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pStage->stateBits & GLS_ATEST_BITS)
|
if (pStage->stateBits & GLS_ATEST_BITS)
|
||||||
|
@ -1210,6 +1035,10 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
{
|
{
|
||||||
shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
|
shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
|
||||||
}
|
}
|
||||||
|
else if (glState.boneAnimation)
|
||||||
|
{
|
||||||
|
shaderAttribs |= GENERICDEF_USE_BONE_ANIMATION;
|
||||||
|
}
|
||||||
|
|
||||||
if (pStage->stateBits & GLS_ATEST_BITS)
|
if (pStage->stateBits & GLS_ATEST_BITS)
|
||||||
{
|
{
|
||||||
|
@ -1225,7 +1054,14 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
|
|
||||||
if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
|
if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
|
||||||
{
|
{
|
||||||
index |= LIGHTDEF_ENTITY;
|
if (glState.boneAnimation)
|
||||||
|
{
|
||||||
|
index |= LIGHTDEF_ENTITY_BONE_ANIMATION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index |= LIGHTDEF_ENTITY_VERTEX_ANIMATION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_sunlightMode->integer && (backEnd.viewParms.flags & VPF_USESUNLIGHT) && (index & LIGHTDEF_LIGHTTYPE_MASK))
|
if (r_sunlightMode->integer && (backEnd.viewParms.flags & VPF_USESUNLIGHT) && (index & LIGHTDEF_LIGHTTYPE_MASK))
|
||||||
|
@ -1233,9 +1069,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
index |= LIGHTDEF_USE_SHADOWMAP;
|
index |= LIGHTDEF_USE_SHADOWMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_lightmap->integer && index & LIGHTDEF_USE_LIGHTMAP)
|
if (r_lightmap->integer && ((index & LIGHTDEF_LIGHTTYPE_MASK) == LIGHTDEF_USE_LIGHTMAP))
|
||||||
{
|
{
|
||||||
index = LIGHTDEF_USE_LIGHTMAP;
|
index = LIGHTDEF_USE_TCGEN_AND_TCMOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp = &pStage->glslShaderGroup[index];
|
sp = &pStage->glslShaderGroup[index];
|
||||||
|
@ -1256,6 +1092,11 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin);
|
GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin);
|
||||||
|
|
||||||
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
|
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
|
||||||
|
|
||||||
|
if (glState.boneAnimation)
|
||||||
|
{
|
||||||
|
GLSL_SetUniformMat4BoneMatrix(sp, UNIFORM_BONEMATRIX, glState.boneMatrix, glState.boneAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
GLSL_SetUniformInt(sp, UNIFORM_DEFORMGEN, deformGen);
|
GLSL_SetUniformInt(sp, UNIFORM_DEFORMGEN, deformGen);
|
||||||
if (deformGen != DGEN_NONE)
|
if (deformGen != DGEN_NONE)
|
||||||
|
@ -1271,19 +1112,29 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_State( pStage->stateBits );
|
GL_State( pStage->stateBits );
|
||||||
|
if ((pStage->stateBits & GLS_ATEST_BITS) == GLS_ATEST_GT_0)
|
||||||
|
{
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 1);
|
||||||
|
}
|
||||||
|
else if ((pStage->stateBits & GLS_ATEST_BITS) == GLS_ATEST_LT_80)
|
||||||
|
{
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 2);
|
||||||
|
}
|
||||||
|
else if ((pStage->stateBits & GLS_ATEST_BITS) == GLS_ATEST_GE_80)
|
||||||
|
{
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
vec4_t baseColor;
|
vec4_t baseColor;
|
||||||
vec4_t vertColor;
|
vec4_t vertColor;
|
||||||
|
|
||||||
ComputeShaderColors( pStage, baseColor, vertColor, pStage->stateBits );
|
ComputeShaderColors(pStage, baseColor, vertColor, pStage->stateBits);
|
||||||
|
|
||||||
if ((backEnd.refdef.colorScale != 1.0f) && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL))
|
|
||||||
{
|
|
||||||
// use VectorScale to only scale first three values, not alpha
|
|
||||||
VectorScale(baseColor, backEnd.refdef.colorScale, baseColor);
|
|
||||||
VectorScale(vertColor, backEnd.refdef.colorScale, vertColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, baseColor);
|
GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, baseColor);
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_VERTCOLOR, vertColor);
|
GLSL_SetUniformVec4(sp, UNIFORM_VERTCOLOR, vertColor);
|
||||||
|
@ -1293,20 +1144,18 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
{
|
{
|
||||||
vec4_t vec;
|
vec4_t vec;
|
||||||
|
|
||||||
if( backEnd.currentEntity ) {
|
VectorScale(backEnd.currentEntity->ambientLight, 1.0f / 255.0f, vec);
|
||||||
VectorScale( backEnd.currentEntity->ambientLight, 1.0f / 255.0f, vec );
|
GLSL_SetUniformVec3(sp, UNIFORM_AMBIENTLIGHT, vec);
|
||||||
GLSL_SetUniformVec3( sp, UNIFORM_AMBIENTLIGHT, vec );
|
|
||||||
|
|
||||||
VectorScale( backEnd.currentEntity->directedLight, 1.0f / 255.0f, vec );
|
VectorScale(backEnd.currentEntity->directedLight, 1.0f / 255.0f, vec);
|
||||||
GLSL_SetUniformVec3( sp, UNIFORM_DIRECTEDLIGHT, vec );
|
GLSL_SetUniformVec3(sp, UNIFORM_DIRECTEDLIGHT, vec);
|
||||||
|
|
||||||
|
VectorCopy(backEnd.currentEntity->lightDir, vec);
|
||||||
|
vec[3] = 0.0f;
|
||||||
|
GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vec);
|
||||||
|
GLSL_SetUniformVec3(sp, UNIFORM_MODELLIGHTDIR, backEnd.currentEntity->modelLightDir);
|
||||||
|
|
||||||
VectorCopy( backEnd.currentEntity->lightDir, vec );
|
GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, 0.0f);
|
||||||
vec[ 3 ] = 0.0f;
|
|
||||||
GLSL_SetUniformVec4( sp, UNIFORM_LIGHTORIGIN, vec );
|
|
||||||
GLSL_SetUniformVec3( sp, UNIFORM_MODELLIGHTDIR, backEnd.currentEntity->modelLightDir );
|
|
||||||
|
|
||||||
GLSL_SetUniformFloat( sp, UNIFORM_LIGHTRADIUS, 0.0f );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pStage->alphaGen == AGEN_PORTAL)
|
if (pStage->alphaGen == AGEN_PORTAL)
|
||||||
|
@ -1326,25 +1175,51 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask);
|
GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
|
if (r_lightmap->integer)
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
|
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb);
|
|
||||||
|
|
||||||
GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
|
|
||||||
if (pStage->bundle[0].tcGen == TCGEN_VECTOR)
|
|
||||||
{
|
{
|
||||||
vec3_t vec;
|
vec4_t v;
|
||||||
|
VectorSet4(v, 1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, v);
|
||||||
|
VectorSet4(v, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, v);
|
||||||
|
|
||||||
VectorCopy(pStage->bundle[0].tcGenVectors[0], vec);
|
GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, TCGEN_LIGHTMAP);
|
||||||
GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR0, vec);
|
}
|
||||||
VectorCopy(pStage->bundle[0].tcGenVectors[1], vec);
|
else
|
||||||
GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR1, vec);
|
{
|
||||||
|
ComputeTexMods(pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb);
|
||||||
|
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
|
||||||
|
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb);
|
||||||
|
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
|
||||||
|
if (pStage->bundle[0].tcGen == TCGEN_VECTOR)
|
||||||
|
{
|
||||||
|
vec3_t vec;
|
||||||
|
|
||||||
|
VectorCopy(pStage->bundle[0].tcGenVectors[0], vec);
|
||||||
|
GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR0, vec);
|
||||||
|
VectorCopy(pStage->bundle[0].tcGenVectors[1], vec);
|
||||||
|
GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR1, vec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
|
GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
|
||||||
|
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_NORMALSCALE, pStage->normalScale);
|
GLSL_SetUniformVec4(sp, UNIFORM_NORMALSCALE, pStage->normalScale);
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_SPECULARSCALE, pStage->specularScale);
|
|
||||||
|
{
|
||||||
|
vec4_t specularScale;
|
||||||
|
Vector4Copy(pStage->specularScale, specularScale);
|
||||||
|
|
||||||
|
if (renderToCubemap)
|
||||||
|
{
|
||||||
|
// force specular to nonmetal if rendering cubemaps
|
||||||
|
if (r_pbr->integer)
|
||||||
|
specularScale[1] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLSL_SetUniformVec4(sp, UNIFORM_SPECULARSCALE, specularScale);
|
||||||
|
}
|
||||||
|
|
||||||
//GLSL_SetUniformFloat(sp, UNIFORM_MAPLIGHTSCALE, backEnd.refdef.mapLightScale);
|
//GLSL_SetUniformFloat(sp, UNIFORM_MAPLIGHTSCALE, backEnd.refdef.mapLightScale);
|
||||||
|
|
||||||
|
@ -1354,7 +1229,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
if ( backEnd.depthFill )
|
if ( backEnd.depthFill )
|
||||||
{
|
{
|
||||||
if (!(pStage->stateBits & GLS_ATEST_BITS))
|
if (!(pStage->stateBits & GLS_ATEST_BITS))
|
||||||
GL_BindToTMU( tr.whiteImage, 0 );
|
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
|
||||||
else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 )
|
else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 )
|
||||||
R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP );
|
R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP );
|
||||||
}
|
}
|
||||||
|
@ -1365,9 +1240,23 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
|
|
||||||
if (r_sunlightMode->integer && (backEnd.viewParms.flags & VPF_USESUNLIGHT) && (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK))
|
if (r_sunlightMode->integer && (backEnd.viewParms.flags & VPF_USESUNLIGHT) && (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK))
|
||||||
{
|
{
|
||||||
GL_BindToTMU(tr.screenShadowImage, TB_SHADOWMAP);
|
// FIXME: screenShadowImage is NULL if no framebuffers
|
||||||
|
if (tr.screenShadowImage)
|
||||||
|
GL_BindToTMU(tr.screenShadowImage, TB_SHADOWMAP);
|
||||||
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTAMBIENT, backEnd.refdef.sunAmbCol);
|
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTAMBIENT, backEnd.refdef.sunAmbCol);
|
||||||
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTCOLOR, backEnd.refdef.sunCol);
|
if (r_pbr->integer)
|
||||||
|
{
|
||||||
|
vec3_t color;
|
||||||
|
|
||||||
|
color[0] = backEnd.refdef.sunCol[0] * backEnd.refdef.sunCol[0];
|
||||||
|
color[1] = backEnd.refdef.sunCol[1] * backEnd.refdef.sunCol[1];
|
||||||
|
color[2] = backEnd.refdef.sunCol[2] * backEnd.refdef.sunCol[2];
|
||||||
|
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTCOLOR, color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTCOLOR, backEnd.refdef.sunCol);
|
||||||
|
}
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_PRIMARYLIGHTORIGIN, backEnd.refdef.sunDir);
|
GLSL_SetUniformVec4(sp, UNIFORM_PRIMARYLIGHTORIGIN, backEnd.refdef.sunDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1376,7 +1265,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
{
|
{
|
||||||
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
|
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
|
||||||
{
|
{
|
||||||
if (i == TB_LIGHTMAP)
|
if (i == TB_COLORMAP)
|
||||||
R_BindAnimatedImageToTMU( &pStage->bundle[TB_LIGHTMAP], i);
|
R_BindAnimatedImageToTMU( &pStage->bundle[TB_LIGHTMAP], i);
|
||||||
else
|
else
|
||||||
GL_BindToTMU( tr.whiteImage, i );
|
GL_BindToTMU( tr.whiteImage, i );
|
||||||
|
@ -1386,7 +1275,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
{
|
{
|
||||||
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
|
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
|
||||||
{
|
{
|
||||||
if (i == TB_LIGHTMAP)
|
if (i == TB_COLORMAP)
|
||||||
R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i);
|
R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i);
|
||||||
else
|
else
|
||||||
GL_BindToTMU( tr.whiteImage, i );
|
GL_BindToTMU( tr.whiteImage, i );
|
||||||
|
@ -1463,15 +1352,16 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
if (!(tr.viewParms.flags & VPF_NOCUBEMAPS) && input->cubemapIndex && r_cubeMapping->integer)
|
if (!(tr.viewParms.flags & VPF_NOCUBEMAPS) && input->cubemapIndex && r_cubeMapping->integer)
|
||||||
{
|
{
|
||||||
vec4_t vec;
|
vec4_t vec;
|
||||||
|
cubemap_t *cubemap = &tr.cubemaps[input->cubemapIndex - 1];
|
||||||
|
|
||||||
GL_BindToTMU( tr.cubemaps[input->cubemapIndex - 1], TB_CUBEMAP);
|
// FIXME: cubemap image could be NULL if cubemap isn't renderer or loaded
|
||||||
|
if (cubemap->image)
|
||||||
|
GL_BindToTMU( cubemap->image, TB_CUBEMAP);
|
||||||
|
|
||||||
vec[0] = tr.cubemapOrigins[input->cubemapIndex - 1][0] - backEnd.viewParms.or.origin[0];
|
VectorSubtract(cubemap->origin, backEnd.viewParms.or.origin, vec);
|
||||||
vec[1] = tr.cubemapOrigins[input->cubemapIndex - 1][1] - backEnd.viewParms.or.origin[1];
|
|
||||||
vec[2] = tr.cubemapOrigins[input->cubemapIndex - 1][2] - backEnd.viewParms.or.origin[2];
|
|
||||||
vec[3] = 1.0f;
|
vec[3] = 1.0f;
|
||||||
|
|
||||||
VectorScale4(vec, 1.0f / 1000.0f, vec);
|
VectorScale4(vec, 1.0f / cubemap->parallaxRadius, vec);
|
||||||
|
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_CUBEMAPINFO, vec);
|
GLSL_SetUniformVec4(sp, UNIFORM_CUBEMAPINFO, vec);
|
||||||
}
|
}
|
||||||
|
@ -1479,14 +1369,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
//
|
//
|
||||||
// draw
|
// draw
|
||||||
//
|
//
|
||||||
if (input->multiDrawPrimitives)
|
R_DrawElements(input->numIndexes, input->firstIndex);
|
||||||
{
|
|
||||||
R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// allow skipping out to show just lightmaps during development
|
// allow skipping out to show just lightmaps during development
|
||||||
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) )
|
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) )
|
||||||
|
@ -1508,7 +1391,16 @@ static void RB_RenderShadowmap( shaderCommands_t *input )
|
||||||
ComputeDeformValues(&deformGen, deformParams);
|
ComputeDeformValues(&deformGen, deformParams);
|
||||||
|
|
||||||
{
|
{
|
||||||
shaderProgram_t *sp = &tr.shadowmapShader;
|
shaderProgram_t *sp = &tr.shadowmapShader[0];
|
||||||
|
|
||||||
|
if (glState.vertexAnimation)
|
||||||
|
{
|
||||||
|
sp = &tr.shadowmapShader[SHADOWMAPDEF_USE_VERTEX_ANIMATION];
|
||||||
|
}
|
||||||
|
else if (glState.boneAnimation)
|
||||||
|
{
|
||||||
|
sp = &tr.shadowmapShader[SHADOWMAPDEF_USE_BONE_ANIMATION];
|
||||||
|
}
|
||||||
|
|
||||||
vec4_t vector;
|
vec4_t vector;
|
||||||
|
|
||||||
|
@ -1520,6 +1412,11 @@ static void RB_RenderShadowmap( shaderCommands_t *input )
|
||||||
|
|
||||||
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
|
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
|
||||||
|
|
||||||
|
if (glState.boneAnimation)
|
||||||
|
{
|
||||||
|
GLSL_SetUniformMat4BoneMatrix(sp, UNIFORM_BONEMATRIX, glState.boneMatrix, glState.boneAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
GLSL_SetUniformInt(sp, UNIFORM_DEFORMGEN, deformGen);
|
GLSL_SetUniformInt(sp, UNIFORM_DEFORMGEN, deformGen);
|
||||||
if (deformGen != DGEN_NONE)
|
if (deformGen != DGEN_NONE)
|
||||||
{
|
{
|
||||||
|
@ -1533,6 +1430,7 @@ static void RB_RenderShadowmap( shaderCommands_t *input )
|
||||||
GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, backEnd.viewParms.zFar);
|
GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, backEnd.viewParms.zFar);
|
||||||
|
|
||||||
GL_State( 0 );
|
GL_State( 0 );
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// do multitexture
|
// do multitexture
|
||||||
|
@ -1543,14 +1441,7 @@ static void RB_RenderShadowmap( shaderCommands_t *input )
|
||||||
// draw
|
// draw
|
||||||
//
|
//
|
||||||
|
|
||||||
if (input->multiDrawPrimitives)
|
R_DrawElements(input->numIndexes, input->firstIndex);
|
||||||
{
|
|
||||||
R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1682,10 +1573,11 @@ void RB_StageIteratorGeneric( void )
|
||||||
ProjectPshadowVBOGLSL();
|
ProjectPshadowVBOGLSL();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
//
|
||||||
// now do any dynamic lighting needed
|
// now do any dynamic lighting needed
|
||||||
//
|
//
|
||||||
if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE
|
if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE && r_lightmap->integer == 0
|
||||||
&& !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) {
|
&& !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) {
|
||||||
if (tess.shader->numUnfoggedPasses == 1 && tess.xstages[0]->glslShaderGroup == tr.lightallShader
|
if (tess.shader->numUnfoggedPasses == 1 && tess.xstages[0]->glslShaderGroup == tr.lightallShader
|
||||||
&& (tess.xstages[0]->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) && r_dlightMode->integer)
|
&& (tess.xstages[0]->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) && r_dlightMode->integer)
|
||||||
|
@ -1714,7 +1606,6 @@ void RB_StageIteratorGeneric( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** RB_EndSurface
|
** RB_EndSurface
|
||||||
*/
|
*/
|
||||||
|
@ -1744,6 +1635,12 @@ void RB_EndSurface( void ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tess.useCacheVao)
|
||||||
|
{
|
||||||
|
// upload indexes now
|
||||||
|
VaoCache_Commit();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// update performance counters
|
// update performance counters
|
||||||
//
|
//
|
||||||
|
@ -1770,7 +1667,6 @@ void RB_EndSurface( void ) {
|
||||||
tess.numIndexes = 0;
|
tess.numIndexes = 0;
|
||||||
tess.numVertexes = 0;
|
tess.numVertexes = 0;
|
||||||
tess.firstIndex = 0;
|
tess.firstIndex = 0;
|
||||||
tess.multiDrawPrimitives = 0;
|
|
||||||
|
|
||||||
GLimp_LogComment( "----------\n" );
|
GLimp_LogComment( "----------\n" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,12 +22,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
// tr_shade_calc.c
|
// tr_shade_calc.c
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
#if idppc_altivec && !defined(MACOS_X)
|
|
||||||
#include <altivec.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define WAVEVALUE( table, base, amplitude, phase, freq ) ((base) + table[ ftol( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
|
#define WAVEVALUE( table, base, amplitude, phase, freq ) ((base) + table[ ( (int64_t) ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
|
||||||
|
|
||||||
static float *TableForFunc( genFunc_t func )
|
static float *TableForFunc( genFunc_t func )
|
||||||
{
|
{
|
||||||
|
@ -116,16 +113,16 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
|
||||||
vec3_t offset;
|
vec3_t offset;
|
||||||
float scale;
|
float scale;
|
||||||
float *xyz = ( float * ) tess.xyz;
|
float *xyz = ( float * ) tess.xyz;
|
||||||
uint32_t *normal = tess.normal;
|
int16_t *normal = tess.normal[0];
|
||||||
float *table;
|
float *table;
|
||||||
|
|
||||||
if ( ds->deformationWave.frequency == 0 )
|
if ( ds->deformationWave.frequency == 0 )
|
||||||
{
|
{
|
||||||
scale = EvalWaveForm( &ds->deformationWave );
|
scale = EvalWaveForm( &ds->deformationWave );
|
||||||
|
|
||||||
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ )
|
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
|
||||||
{
|
{
|
||||||
R_VaoUnpackNormal(offset, *normal);
|
R_VaoUnpackNormal(offset, normal);
|
||||||
|
|
||||||
xyz[0] += offset[0] * scale;
|
xyz[0] += offset[0] * scale;
|
||||||
xyz[1] += offset[1] * scale;
|
xyz[1] += offset[1] * scale;
|
||||||
|
@ -136,7 +133,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
|
||||||
{
|
{
|
||||||
table = TableForFunc( ds->deformationWave.func );
|
table = TableForFunc( ds->deformationWave.func );
|
||||||
|
|
||||||
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ )
|
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
|
||||||
{
|
{
|
||||||
float off = ( xyz[0] + xyz[1] + xyz[2] ) * ds->deformationSpread;
|
float off = ( xyz[0] + xyz[1] + xyz[2] ) * ds->deformationSpread;
|
||||||
|
|
||||||
|
@ -145,7 +142,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
|
||||||
ds->deformationWave.phase + off,
|
ds->deformationWave.phase + off,
|
||||||
ds->deformationWave.frequency );
|
ds->deformationWave.frequency );
|
||||||
|
|
||||||
R_VaoUnpackNormal(offset, *normal);
|
R_VaoUnpackNormal(offset, normal);
|
||||||
|
|
||||||
xyz[0] += offset[0] * scale;
|
xyz[0] += offset[0] * scale;
|
||||||
xyz[1] += offset[1] * scale;
|
xyz[1] += offset[1] * scale;
|
||||||
|
@ -165,12 +162,12 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
|
||||||
int i;
|
int i;
|
||||||
float scale;
|
float scale;
|
||||||
float *xyz = ( float * ) tess.xyz;
|
float *xyz = ( float * ) tess.xyz;
|
||||||
uint32_t *normal = tess.normal;
|
int16_t *normal = tess.normal[0];
|
||||||
|
|
||||||
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ ) {
|
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) {
|
||||||
vec3_t fNormal;
|
vec3_t fNormal;
|
||||||
|
|
||||||
R_VaoUnpackNormal(fNormal, *normal);
|
R_VaoUnpackNormal(fNormal, normal);
|
||||||
|
|
||||||
scale = 0.98f;
|
scale = 0.98f;
|
||||||
scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
|
scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
|
||||||
|
@ -189,7 +186,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
|
||||||
|
|
||||||
VectorNormalizeFast( fNormal );
|
VectorNormalizeFast( fNormal );
|
||||||
|
|
||||||
R_VaoPackNormal((byte *)normal, fNormal);
|
R_VaoPackNormal(normal, fNormal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,17 +200,17 @@ void RB_CalcBulgeVertexes( deformStage_t *ds ) {
|
||||||
int i;
|
int i;
|
||||||
const float *st = ( const float * ) tess.texCoords[0];
|
const float *st = ( const float * ) tess.texCoords[0];
|
||||||
float *xyz = ( float * ) tess.xyz;
|
float *xyz = ( float * ) tess.xyz;
|
||||||
uint32_t *normal = tess.normal;
|
int16_t *normal = tess.normal[0];
|
||||||
float now;
|
double now;
|
||||||
|
|
||||||
now = backEnd.refdef.time * ds->bulgeSpeed * 0.001f;
|
now = backEnd.refdef.time * 0.001 * ds->bulgeSpeed;
|
||||||
|
|
||||||
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal++ ) {
|
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 2, normal += 4 ) {
|
||||||
int off;
|
int64_t off;
|
||||||
float scale;
|
float scale;
|
||||||
vec3_t fNormal;
|
vec3_t fNormal;
|
||||||
|
|
||||||
R_VaoUnpackNormal(fNormal, *normal);
|
R_VaoUnpackNormal(fNormal, normal);
|
||||||
|
|
||||||
off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now );
|
off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now );
|
||||||
|
|
||||||
|
@ -350,7 +347,7 @@ static void GlobalVectorToLocal( const vec3_t in, vec3_t out ) {
|
||||||
=====================
|
=====================
|
||||||
AutospriteDeform
|
AutospriteDeform
|
||||||
|
|
||||||
Assuming all the triangles for this shader are independant
|
Assuming all the triangles for this shader are independent
|
||||||
quads, rebuild them as forward facing sprites
|
quads, rebuild them as forward facing sprites
|
||||||
=====================
|
=====================
|
||||||
*/
|
*/
|
||||||
|
@ -384,6 +381,7 @@ static void AutospriteDeform( void ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( i = 0 ; i < oldVerts ; i+=4 ) {
|
for ( i = 0 ; i < oldVerts ; i+=4 ) {
|
||||||
|
vec4_t color;
|
||||||
// find the midpoint
|
// find the midpoint
|
||||||
xyz = tess.xyz[i];
|
xyz = tess.xyz[i];
|
||||||
|
|
||||||
|
@ -414,7 +412,8 @@ static void AutospriteDeform( void ) {
|
||||||
VectorScale(up, axisLength, up);
|
VectorScale(up, axisLength, up);
|
||||||
}
|
}
|
||||||
|
|
||||||
RB_AddQuadStamp( mid, left, up, tess.vertexColors[i] );
|
VectorScale4(tess.color[i], 1.0f / 65535.0f, color);
|
||||||
|
RB_AddQuadStamp( mid, left, up, color );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,8 +773,8 @@ void RB_CalcScaleTexMatrix( const float scale[2], float *matrix )
|
||||||
*/
|
*/
|
||||||
void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix )
|
void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix )
|
||||||
{
|
{
|
||||||
float timeScale = tess.shaderTime;
|
double timeScale = tess.shaderTime;
|
||||||
float adjustedScrollS, adjustedScrollT;
|
double adjustedScrollS, adjustedScrollT;
|
||||||
|
|
||||||
adjustedScrollS = scrollSpeed[0] * timeScale;
|
adjustedScrollS = scrollSpeed[0] * timeScale;
|
||||||
adjustedScrollT = scrollSpeed[1] * timeScale;
|
adjustedScrollT = scrollSpeed[1] * timeScale;
|
||||||
|
@ -803,9 +802,9 @@ void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix )
|
||||||
*/
|
*/
|
||||||
void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
|
void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
|
||||||
{
|
{
|
||||||
float timeScale = tess.shaderTime;
|
double timeScale = tess.shaderTime;
|
||||||
float degs;
|
double degs;
|
||||||
int index;
|
int64_t index;
|
||||||
float sinValue, cosValue;
|
float sinValue, cosValue;
|
||||||
|
|
||||||
degs = -degsPerSecond * timeScale;
|
degs = -degsPerSecond * timeScale;
|
||||||
|
@ -817,214 +816,3 @@ void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
|
||||||
matrix[0] = cosValue; matrix[2] = -sinValue; matrix[4] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
|
matrix[0] = cosValue; matrix[2] = -sinValue; matrix[4] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
|
||||||
matrix[1] = sinValue; matrix[3] = cosValue; matrix[5] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
|
matrix[1] = sinValue; matrix[3] = cosValue; matrix[5] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** RB_CalcLightGridColor
|
|
||||||
*/
|
|
||||||
float RB_CalcLightGridColor( void )
|
|
||||||
{
|
|
||||||
if( backEnd.currentEntity )
|
|
||||||
{
|
|
||||||
if( backEnd.currentEntity == &tr.worldEntity )
|
|
||||||
{
|
|
||||||
Com_Printf( "#### shader '%s' incorrectly uses rgbGen ligthingGrid or ligthingSpherical; was rgbGen vertex intended?\n", tess.shader->name );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return backEnd.currentEntity->iGridLighting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return backEnd.currentStaticModel->iGridLighting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** RB_CalcRGBFromTexCoords
|
|
||||||
*/
|
|
||||||
float RB_CalcRGBFromTexCoords( float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float *st )
|
|
||||||
{
|
|
||||||
float f = sWeight * tess.texCoords[ 0 ][ 0 ][ 0 ] + tWeight * tess.texCoords[ 0 ][ 0 ][ 1 ];
|
|
||||||
float _ff_;
|
|
||||||
|
|
||||||
f = ( ( alphaMax - alphaMin ) * f + alphaMin ) * 255.0;
|
|
||||||
|
|
||||||
_ff_ = f - ( float )( ~( ( int )( f - ( float )( unsigned char )alphaCap ) >> 31 ) & ( int )( f - ( float )( unsigned char )alphaCap ) );
|
|
||||||
_ff_ = ( float )( ( ~( ( int )( _ff_ - ( float )( unsigned char )alphaMinCap ) >> 31 ) & ( int )( _ff_ - ( float )( unsigned char )alphaMinCap ) ) + ( unsigned char )alphaMinCap );
|
|
||||||
|
|
||||||
return _ff_ / 255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** RB_CalcRGBFromDot
|
|
||||||
*/
|
|
||||||
float RB_CalcRGBFromDot( float alphaMin, float alphaMax )
|
|
||||||
{
|
|
||||||
vec3_t viewInModel;
|
|
||||||
float f;
|
|
||||||
float _ff_;
|
|
||||||
int fl;
|
|
||||||
|
|
||||||
VectorSubtract( backEnd.or.viewOrigin, tess.xyz[ 0 ], viewInModel );
|
|
||||||
VectorNormalizeFast( viewInModel );
|
|
||||||
|
|
||||||
f = DotProduct( tess.normal, viewInModel );
|
|
||||||
f = f * f;
|
|
||||||
|
|
||||||
_ff_ = ( ( alphaMax - alphaMin ) * f + alphaMin ) * 255.0;
|
|
||||||
_ff_ = _ff_ - ( ~( ( int )( _ff_ - 255.0 ) >> 31 ) & ( int )( _ff_ - 255.0 ) );
|
|
||||||
fl = ( ~( *( int * )&_ff_ >> 31 ) & *( int * )&_ff_ );
|
|
||||||
|
|
||||||
return *( float * )fl / 255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** RB_CalcRGBFromOneMinusDot
|
|
||||||
*/
|
|
||||||
float RB_CalcRGBFromOneMinusDot( float alphaMin, float alphaMax )
|
|
||||||
{
|
|
||||||
vec3_t viewInModel;
|
|
||||||
float f;
|
|
||||||
float _ff_;
|
|
||||||
int fl;
|
|
||||||
|
|
||||||
VectorSubtract( backEnd.or.viewOrigin, tess.xyz[ 0 ], viewInModel );
|
|
||||||
VectorNormalizeFast( viewInModel );
|
|
||||||
|
|
||||||
f = DotProduct( tess.normal, viewInModel );
|
|
||||||
f = 1.0 - f * f;
|
|
||||||
|
|
||||||
_ff_ = ( ( alphaMax - alphaMin ) * f + alphaMin ) * 255.0;
|
|
||||||
_ff_ = _ff_ - ( ~( ( int )( _ff_ - 255.0 ) >> 31 ) & ( int )( _ff_ - 255.0 ) );
|
|
||||||
fl = ( ~( *( int * )&_ff_ >> 31 ) & *( int * )&_ff_ );
|
|
||||||
|
|
||||||
return *( float * )fl / 255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** RB_CalcAlphaFromDot
|
|
||||||
*/
|
|
||||||
float RB_CalcAlphaFromDot( float alphaMin, float alphaMax )
|
|
||||||
{
|
|
||||||
vec3_t viewInModel;
|
|
||||||
float f;
|
|
||||||
float _ff_;
|
|
||||||
int fl;
|
|
||||||
|
|
||||||
VectorSubtract( backEnd.or.viewOrigin, tess.xyz[ 0 ], viewInModel );
|
|
||||||
VectorNormalizeFast( viewInModel );
|
|
||||||
|
|
||||||
f = DotProduct( tess.normal, viewInModel );
|
|
||||||
f = f * f;
|
|
||||||
|
|
||||||
_ff_ = ( ( alphaMax - alphaMin ) * f + alphaMin ) * 255.0;
|
|
||||||
_ff_ = _ff_ - ( ~( ( int )( _ff_ - 255.0 ) >> 31 ) & ( int )( _ff_ - 255.0 ) );
|
|
||||||
fl = ( ~( *( int * )&_ff_ >> 31 ) & *( int * )&_ff_ );
|
|
||||||
|
|
||||||
return *( float * )fl / 255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** RB_CalcAlphaFromOneMinusDot
|
|
||||||
*/
|
|
||||||
float RB_CalcAlphaFromOneMinusDot( float alphaMin, float alphaMax )
|
|
||||||
{
|
|
||||||
vec3_t viewInModel;
|
|
||||||
float f;
|
|
||||||
float _ff_;
|
|
||||||
int fl;
|
|
||||||
|
|
||||||
VectorSubtract( backEnd.or.viewOrigin, tess.xyz[ 0 ], viewInModel );
|
|
||||||
VectorNormalizeFast( viewInModel );
|
|
||||||
|
|
||||||
f = DotProduct( tess.normal, viewInModel );
|
|
||||||
f = 1.0 - f * f;
|
|
||||||
|
|
||||||
_ff_ = ( ( alphaMax - alphaMin ) * f + alphaMin ) * 255.0;
|
|
||||||
_ff_ = _ff_ - ( ~( ( int )( _ff_ - 255.0 ) >> 31 ) & ( int )( _ff_ - 255.0 ) );
|
|
||||||
fl = ( ~( *( int * )&_ff_ >> 31 ) & *( int * )&_ff_ );
|
|
||||||
|
|
||||||
return *( float * )fl / 255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** RB_CalcAlphaFromDotView
|
|
||||||
*/
|
|
||||||
float RB_CalcAlphaFromDotView( float alphaMin, float alphaMax )
|
|
||||||
{
|
|
||||||
vec3_t viewInModel;
|
|
||||||
vec3_t normal;
|
|
||||||
float f;
|
|
||||||
float _ff_;
|
|
||||||
int fl;
|
|
||||||
|
|
||||||
VectorCopy( tr.refdef.viewaxis[ 0 ], viewInModel );
|
|
||||||
VectorNormalizeFast( viewInModel );
|
|
||||||
|
|
||||||
f = DotProduct( tess.normal, viewInModel );
|
|
||||||
f = f * f;
|
|
||||||
|
|
||||||
R_VaoUnpackNormal( normal, tess.normal[ 0 ] );
|
|
||||||
|
|
||||||
Com_Printf( "normal: %f %f %f dot: %f i %d\n", normal[ 0 ], normal[ 1 ], normal[ 2 ], f, 0 );
|
|
||||||
|
|
||||||
_ff_ = ( ( alphaMax - alphaMin ) * f + alphaMin ) * 255.0;
|
|
||||||
_ff_ = _ff_ - ( ~( ( int )( _ff_ - 255.0 ) >> 31 ) & ( int )( _ff_ - 255.0 ) );
|
|
||||||
fl = ( ~( *( int * )&_ff_ >> 31 ) & *( int * )&_ff_ );
|
|
||||||
|
|
||||||
return *( float * )fl / 255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** RB_CalcAlphaFromOneMinusDotView
|
|
||||||
*/
|
|
||||||
float RB_CalcAlphaFromOneMinusDotView( float alphaMin, float alphaMax )
|
|
||||||
{
|
|
||||||
vec3_t viewInModel;
|
|
||||||
vec3_t normal;
|
|
||||||
float f;
|
|
||||||
float _ff_;
|
|
||||||
int fl;
|
|
||||||
|
|
||||||
VectorCopy( tr.refdef.viewaxis[ 0 ], viewInModel );
|
|
||||||
VectorNormalizeFast( viewInModel );
|
|
||||||
|
|
||||||
f = DotProduct( tess.normal, viewInModel );
|
|
||||||
f = 1.0 - f * f;
|
|
||||||
|
|
||||||
R_VaoUnpackNormal( normal, tess.normal[ 0 ] );
|
|
||||||
|
|
||||||
Com_Printf( "normal: %f %f %f dot: %f i %d\n", normal[ 0 ], normal[ 1 ], normal[ 2 ], f, 0 );
|
|
||||||
|
|
||||||
_ff_ = ( ( alphaMax - alphaMin ) * f + alphaMin ) * 255.0;
|
|
||||||
_ff_ = _ff_ - ( ~( ( int )( _ff_ - 255.0 ) >> 31 ) & ( int )( _ff_ - 255.0 ) );
|
|
||||||
fl = ( ~( *( int * )&_ff_ >> 31 ) & *( int * )&_ff_ );
|
|
||||||
|
|
||||||
return *( float * )fl / 255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** RB_CalcAlphaFromConstant
|
|
||||||
*/
|
|
||||||
float RB_CalcAlphaFromConstant( float alphaMin, float alphaMax )
|
|
||||||
{
|
|
||||||
return alphaMin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** RB_CalcAlphaFromTexCoords
|
|
||||||
*/
|
|
||||||
float RB_CalcAlphaFromTexCoords( float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float *st )
|
|
||||||
{
|
|
||||||
float f = sWeight * tess.texCoords[ 0 ][ 0 ][ 0 ] + tWeight * tess.texCoords[ 0 ][ 0 ][ 1 ];
|
|
||||||
float _ff_;
|
|
||||||
|
|
||||||
f = ( ( alphaMax - alphaMin ) * f + alphaMin ) * 255.0;
|
|
||||||
|
|
||||||
_ff_ = f - ( float )( ~( ( int )( f - ( float )( unsigned char )alphaCap ) >> 31 ) & ( int )( f - ( float )( unsigned char )alphaCap ) );
|
|
||||||
_ff_ = ( float )( ( ~( ( int )( _ff_ - ( float )( unsigned char )alphaMinCap ) >> 31 ) & ( int )( _ff_ - ( float )( unsigned char )alphaMinCap ) ) + ( unsigned char )alphaMinCap );
|
|
||||||
|
|
||||||
return _ff_ / 255.0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -603,8 +603,6 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
char *token;
|
char *token;
|
||||||
int depthMaskBits = GLS_DEPTHMASK_TRUE, blendSrcBits = 0, blendDstBits = 0, atestBits = 0, depthFuncBits = 0;
|
int depthMaskBits = GLS_DEPTHMASK_TRUE, blendSrcBits = 0, blendDstBits = 0, atestBits = 0, depthFuncBits = 0;
|
||||||
qboolean depthMaskExplicit = qfalse;
|
qboolean depthMaskExplicit = qfalse;
|
||||||
// IneQuation
|
|
||||||
int bundleNum = 0;
|
|
||||||
|
|
||||||
stage->active = qtrue;
|
stage->active = qtrue;
|
||||||
|
|
||||||
|
@ -635,16 +633,16 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
|
|
||||||
if ( !Q_stricmp( token, "$whiteimage" ) )
|
if ( !Q_stricmp( token, "$whiteimage" ) )
|
||||||
{
|
{
|
||||||
stage->bundle[bundleNum].image[0] = tr.whiteImage;
|
stage->bundle[0].image[0] = tr.whiteImage;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if ( !Q_stricmp( token, "$lightmap" ) )
|
else if ( !Q_stricmp( token, "$lightmap" ) )
|
||||||
{
|
{
|
||||||
stage->bundle[bundleNum].isLightmap = qtrue;
|
stage->bundle[0].isLightmap = qtrue;
|
||||||
if ( shader.lightmapIndex < 0 || !tr.lightmaps ) {
|
if ( shader.lightmapIndex < 0 || !tr.lightmaps ) {
|
||||||
stage->bundle[bundleNum].image[0] = tr.whiteImage;
|
stage->bundle[0].image[0] = tr.whiteImage;
|
||||||
} else {
|
} else {
|
||||||
stage->bundle[bundleNum].image[0] = tr.lightmaps[shader.lightmapIndex];
|
stage->bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -656,11 +654,11 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
stage->bundle[bundleNum].isLightmap = qtrue;
|
stage->bundle[0].isLightmap = qtrue;
|
||||||
if ( shader.lightmapIndex < 0 ) {
|
if ( shader.lightmapIndex < 0 ) {
|
||||||
stage->bundle[bundleNum].image[0] = tr.whiteImage;
|
stage->bundle[0].image[0] = tr.whiteImage;
|
||||||
} else {
|
} else {
|
||||||
stage->bundle[bundleNum].image[0] = tr.deluxemaps[shader.lightmapIndex];
|
stage->bundle[0].image[0] = tr.deluxemaps[shader.lightmapIndex];
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -689,9 +687,9 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
flags |= IMGFLAG_GENNORMALMAP;
|
flags |= IMGFLAG_GENNORMALMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
stage->bundle[bundleNum].image[0] = R_FindImageFile( token, type, flags );
|
stage->bundle[0].image[0] = R_FindImageFile( token, type, flags );
|
||||||
|
|
||||||
if ( !stage->bundle[bundleNum].image[0] )
|
if ( !stage->bundle[0].image[0] )
|
||||||
{
|
{
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
|
ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
|
||||||
return qfalse;
|
return qfalse;
|
||||||
|
@ -734,8 +732,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
stage->bundle[bundleNum].image[0] = R_FindImageFile( token, type, flags );
|
stage->bundle[0].image[0] = R_FindImageFile( token, type, flags );
|
||||||
if ( !stage->bundle[bundleNum].image[0] )
|
if ( !stage->bundle[0].image[0] )
|
||||||
{
|
{
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
|
ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
|
||||||
return qfalse;
|
return qfalse;
|
||||||
|
@ -746,13 +744,15 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
//
|
//
|
||||||
else if ( !Q_stricmp( token, "animMap" ) )
|
else if ( !Q_stricmp( token, "animMap" ) )
|
||||||
{
|
{
|
||||||
|
int totalImages = 0;
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
token = COM_ParseExt( text, qfalse );
|
||||||
if ( !token[0] )
|
if ( !token[0] )
|
||||||
{
|
{
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMap' keyword in shader '%s'\n", shader.name );
|
ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMap' keyword in shader '%s'\n", shader.name );
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
stage->bundle[bundleNum].imageAnimationSpeed = atof( token );
|
stage->bundle[0].imageAnimationSpeed = atof( token );
|
||||||
|
|
||||||
// parse up to MAX_IMAGE_ANIMATIONS animations
|
// parse up to MAX_IMAGE_ANIMATIONS animations
|
||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
|
@ -762,7 +762,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
if ( !token[0] ) {
|
if ( !token[0] ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
num = stage->bundle[bundleNum].numImageAnimations;
|
num = stage->bundle[0].numImageAnimations;
|
||||||
if ( num < MAX_IMAGE_ANIMATIONS ) {
|
if ( num < MAX_IMAGE_ANIMATIONS ) {
|
||||||
imgFlags_t flags = IMGFLAG_NONE;
|
imgFlags_t flags = IMGFLAG_NONE;
|
||||||
|
|
||||||
|
@ -772,28 +772,20 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
if (!shader.noPicMip)
|
if (!shader.noPicMip)
|
||||||
flags |= IMGFLAG_PICMIP;
|
flags |= IMGFLAG_PICMIP;
|
||||||
|
|
||||||
stage->bundle[bundleNum].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags );
|
stage->bundle[0].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags );
|
||||||
if ( !stage->bundle[bundleNum].image[num] )
|
if ( !stage->bundle[0].image[num] )
|
||||||
{
|
{
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
|
ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
stage->bundle[bundleNum].numImageAnimations++;
|
stage->bundle[0].numImageAnimations++;
|
||||||
}
|
}
|
||||||
|
totalImages++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "videoMap" ) )
|
if ( totalImages > MAX_IMAGE_ANIMATIONS ) {
|
||||||
{
|
ri.Printf( PRINT_WARNING, "WARNING: ignoring excess images for 'animMap' (found %d, max is %d) in shader '%s'\n",
|
||||||
token = COM_ParseExt( text, qfalse );
|
totalImages, MAX_IMAGE_ANIMATIONS, shader.name );
|
||||||
if ( !token[0] )
|
|
||||||
{
|
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMap' keyword in shader '%s'\n", shader.name );
|
|
||||||
return qfalse;
|
|
||||||
}
|
|
||||||
stage->bundle[bundleNum].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader));
|
|
||||||
if (stage->bundle[bundleNum].videoMapHandle != -1) {
|
|
||||||
stage->bundle[bundleNum].isVideoMap = qtrue;
|
|
||||||
stage->bundle[bundleNum].image[0] = tr.scratchImage[stage->bundle[bundleNum].videoMapHandle];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -866,9 +858,6 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
} else if ( !Q_stricmp( token, "blend" ) ) {
|
} else if ( !Q_stricmp( token, "blend" ) ) {
|
||||||
blendSrcBits = GLS_SRCBLEND_SRC_ALPHA;
|
blendSrcBits = GLS_SRCBLEND_SRC_ALPHA;
|
||||||
blendDstBits = GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
|
blendDstBits = GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
|
||||||
} else if( !Q_stricmp(token, "alphaadd" ) ) {
|
|
||||||
blendSrcBits = GLS_SRCBLEND_SRC_ALPHA;
|
|
||||||
blendDstBits = GLS_DSTBLEND_ONE;
|
|
||||||
} else {
|
} else {
|
||||||
// complex double blends
|
// complex double blends
|
||||||
blendSrcBits = NameToSrcBlendMode( token );
|
blendSrcBits = NameToSrcBlendMode( token );
|
||||||
|
@ -939,9 +928,18 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular reflectance in shader '%s'\n", shader.name );
|
ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular reflectance in shader '%s'\n", shader.name );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
stage->specularScale[0] =
|
|
||||||
stage->specularScale[1] =
|
if (r_pbr->integer)
|
||||||
stage->specularScale[2] = atof( token );
|
{
|
||||||
|
// interpret specularReflectance < 0.5 as nonmetal
|
||||||
|
stage->specularScale[1] = (atof(token) < 0.5f) ? 0.0f : 1.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stage->specularScale[0] =
|
||||||
|
stage->specularScale[1] =
|
||||||
|
stage->specularScale[2] = atof( token );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// specularExponent <value>
|
// specularExponent <value>
|
||||||
|
@ -959,17 +957,23 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
|
|
||||||
exponent = atof( token );
|
exponent = atof( token );
|
||||||
|
|
||||||
// Change shininess to gloss
|
if (r_pbr->integer)
|
||||||
// FIXME: assumes max exponent of 8192 and min of 1, must change here if altered in lightall_fp.glsl
|
stage->specularScale[0] = 1.0f - powf(2.0f / (exponent + 2.0), 0.25);
|
||||||
exponent = CLAMP(exponent, 1.0, 8192.0);
|
else
|
||||||
|
{
|
||||||
stage->specularScale[3] = log(exponent) / log(8192.0);
|
// Change shininess to gloss
|
||||||
|
// Assumes max exponent of 8190 and min of 0, must change here if altered in lightall_fp.glsl
|
||||||
|
exponent = CLAMP(exponent, 0.0f, 8190.0f);
|
||||||
|
stage->specularScale[3] = (log2f(exponent + 2.0f) - 1.0f) / 12.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// gloss <value>
|
// gloss <value>
|
||||||
//
|
//
|
||||||
else if (!Q_stricmp(token, "gloss"))
|
else if (!Q_stricmp(token, "gloss"))
|
||||||
{
|
{
|
||||||
|
float gloss;
|
||||||
|
|
||||||
token = COM_ParseExt(text, qfalse);
|
token = COM_ParseExt(text, qfalse);
|
||||||
if ( token[0] == 0 )
|
if ( token[0] == 0 )
|
||||||
{
|
{
|
||||||
|
@ -977,7 +981,38 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
stage->specularScale[3] = atof( token );
|
gloss = atof(token);
|
||||||
|
|
||||||
|
if (r_pbr->integer)
|
||||||
|
stage->specularScale[0] = 1.0f - exp2f(-3.0f * gloss);
|
||||||
|
else
|
||||||
|
stage->specularScale[3] = gloss;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// roughness <value>
|
||||||
|
//
|
||||||
|
else if (!Q_stricmp(token, "roughness"))
|
||||||
|
{
|
||||||
|
float roughness;
|
||||||
|
|
||||||
|
token = COM_ParseExt(text, qfalse);
|
||||||
|
if (token[0] == 0)
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_WARNING, "WARNING: missing parameter for roughness in shader '%s'\n", shader.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
roughness = atof(token);
|
||||||
|
|
||||||
|
if (r_pbr->integer)
|
||||||
|
stage->specularScale[0] = 1.0 - roughness;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (roughness >= 0.125)
|
||||||
|
stage->specularScale[3] = log2f(1.0f / roughness) / 3.0f;
|
||||||
|
else
|
||||||
|
stage->specularScale[3] = 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// parallaxDepth <value>
|
// parallaxDepth <value>
|
||||||
|
@ -1030,6 +1065,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// specularScale <rgb> <gloss>
|
// specularScale <rgb> <gloss>
|
||||||
|
// or specularScale <metallic> <smoothness> with r_pbr 1
|
||||||
// or specularScale <r> <g> <b>
|
// or specularScale <r> <g> <b>
|
||||||
// or specularScale <r> <g> <b> <gloss>
|
// or specularScale <r> <g> <b> <gloss>
|
||||||
//
|
//
|
||||||
|
@ -1056,10 +1092,20 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
token = COM_ParseExt(text, qfalse);
|
token = COM_ParseExt(text, qfalse);
|
||||||
if ( token[0] == 0 )
|
if ( token[0] == 0 )
|
||||||
{
|
{
|
||||||
// two values, rgb then gloss
|
if (r_pbr->integer)
|
||||||
stage->specularScale[3] = stage->specularScale[1];
|
{
|
||||||
stage->specularScale[1] =
|
// two values, metallic then smoothness
|
||||||
stage->specularScale[2] = stage->specularScale[0];
|
float smoothness = stage->specularScale[1];
|
||||||
|
stage->specularScale[1] = (stage->specularScale[0] < 0.5f) ? 0.0f : 1.0f;
|
||||||
|
stage->specularScale[0] = smoothness;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// two values, rgb then gloss
|
||||||
|
stage->specularScale[3] = stage->specularScale[1];
|
||||||
|
stage->specularScale[1] =
|
||||||
|
stage->specularScale[2] = stage->specularScale[0];
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1072,7 +1118,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
stage->specularScale[2] = atof( token );
|
stage->specularScale[3] = atof( token );
|
||||||
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -1092,18 +1138,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
ParseWaveForm( text, &stage->rgbWave );
|
ParseWaveForm( text, &stage->rgbWave );
|
||||||
stage->rgbGen = CGEN_WAVEFORM;
|
stage->rgbGen = CGEN_WAVEFORM;
|
||||||
}
|
}
|
||||||
else if ( !Q_stricmp( token, "colorwave" ) )
|
else if ( !Q_stricmp( token, "const" ) )
|
||||||
{
|
|
||||||
vec3_t color;
|
|
||||||
|
|
||||||
ParseVector( text, 3, color );
|
|
||||||
stage->constantColor[ 0 ] = 255 * color[ 0 ];
|
|
||||||
stage->constantColor[ 1 ] = 255 * color[ 1 ];
|
|
||||||
stage->constantColor[ 2 ] = 255 * color[ 2 ];
|
|
||||||
ParseWaveForm( text, &stage->rgbWave );
|
|
||||||
stage->rgbGen = CGEN_MULTIPLY_BY_WAVEFORM;
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "const" ) || !Q_stricmp( token, "constant" ) )
|
|
||||||
{
|
{
|
||||||
vec3_t color;
|
vec3_t color;
|
||||||
|
|
||||||
|
@ -1124,7 +1159,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
{
|
{
|
||||||
stage->rgbGen = CGEN_IDENTITY_LIGHTING;
|
stage->rgbGen = CGEN_IDENTITY_LIGHTING;
|
||||||
}
|
}
|
||||||
else if ( !Q_stricmp( token, "entity" ) || !Q_stricmp( token, "fromentity" ) )
|
else if ( !Q_stricmp( token, "entity" ) )
|
||||||
{
|
{
|
||||||
stage->rgbGen = CGEN_ENTITY;
|
stage->rgbGen = CGEN_ENTITY;
|
||||||
}
|
}
|
||||||
|
@ -1132,7 +1167,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
{
|
{
|
||||||
stage->rgbGen = CGEN_ONE_MINUS_ENTITY;
|
stage->rgbGen = CGEN_ONE_MINUS_ENTITY;
|
||||||
}
|
}
|
||||||
else if ( !Q_stricmp( token, "vertex" ) || !Q_stricmp( token, "fromclient" ) )
|
else if ( !Q_stricmp( token, "vertex" ) )
|
||||||
{
|
{
|
||||||
stage->rgbGen = CGEN_VERTEX;
|
stage->rgbGen = CGEN_VERTEX;
|
||||||
if ( stage->alphaGen == 0 ) {
|
if ( stage->alphaGen == 0 ) {
|
||||||
|
@ -1154,15 +1189,6 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
{
|
{
|
||||||
stage->rgbGen = CGEN_EXACT_VERTEX_LIT;
|
stage->rgbGen = CGEN_EXACT_VERTEX_LIT;
|
||||||
}
|
}
|
||||||
else if ( !Q_stricmp( token, "lightingGrid" ) )
|
|
||||||
{
|
|
||||||
stage->rgbGen = CGEN_LIGHTING_GRID;
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "lightingSpherical" ) )
|
|
||||||
{
|
|
||||||
//stage->rgbGen = CGEN_LIGHTING_SPHERICAL;
|
|
||||||
stage->rgbGen = CGEN_LIGHTING_DIFFUSE;
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "lightingDiffuse" ) )
|
else if ( !Q_stricmp( token, "lightingDiffuse" ) )
|
||||||
{
|
{
|
||||||
stage->rgbGen = CGEN_LIGHTING_DIFFUSE;
|
stage->rgbGen = CGEN_LIGHTING_DIFFUSE;
|
||||||
|
@ -1171,97 +1197,6 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
{
|
{
|
||||||
stage->rgbGen = CGEN_ONE_MINUS_VERTEX;
|
stage->rgbGen = CGEN_ONE_MINUS_VERTEX;
|
||||||
}
|
}
|
||||||
else if( !Q_stricmp( token, "global" ) )
|
|
||||||
{
|
|
||||||
stage->rgbGen = CGEN_GLOBAL_COLOR;
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "static" ) )
|
|
||||||
{
|
|
||||||
stage->rgbGen = CGEN_STATIC;
|
|
||||||
|
|
||||||
if( stage->alphaGen = AGEN_IDENTITY ) {
|
|
||||||
stage->alphaGen = AGEN_VERTEX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "sCoord" ) || !Q_stricmp( token, "tCoord" ) )
|
|
||||||
{
|
|
||||||
if( !Q_stricmp( token, "sCoord" ) ) {
|
|
||||||
stage->rgbGen = CGEN_SCOORD;
|
|
||||||
} else if( !Q_stricmp( token, "tCoord" ) ) {
|
|
||||||
stage->rgbGen = CGEN_TCOORD;
|
|
||||||
}
|
|
||||||
|
|
||||||
stage->alphaMin = 0.0;
|
|
||||||
stage->alphaMax = 1.0;
|
|
||||||
stage->alphaConstMin = 0;
|
|
||||||
stage->alphaConst = -1;
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMin = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMax = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaConstMin = ( byte )( atof( token ) * 255.0 );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaConst = ( byte )( atof( token ) * 255.0 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: missing rgbGen sCoord or tCoord parm 'max' in shader '%s'\n", shader.name );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "dot" ) )
|
|
||||||
{
|
|
||||||
shader.needsNormal = qtrue;
|
|
||||||
stage->alphaMin = 0.0;
|
|
||||||
stage->alphaMax = 1.0;
|
|
||||||
stage->rgbGen = CGEN_DOT;
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMin = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMax = atof( token );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "oneminusdot" ) )
|
|
||||||
{
|
|
||||||
shader.needsNormal = qtrue;
|
|
||||||
stage->alphaMin = 0.0;
|
|
||||||
stage->alphaMax = 1.0;
|
|
||||||
stage->rgbGen = CGEN_ONE_MINUS_DOT;
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMin = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMax = atof( token );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: unknown rgbGen parameter '%s' in shader '%s'\n", token, shader.name );
|
ri.Printf( PRINT_WARNING, "WARNING: unknown rgbGen parameter '%s' in shader '%s'\n", token, shader.name );
|
||||||
|
@ -1285,7 +1220,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
ParseWaveForm( text, &stage->alphaWave );
|
ParseWaveForm( text, &stage->alphaWave );
|
||||||
stage->alphaGen = AGEN_WAVEFORM;
|
stage->alphaGen = AGEN_WAVEFORM;
|
||||||
}
|
}
|
||||||
else if ( !Q_stricmp( token, "const" ) || !Q_stricmp( token, "constant" ) )
|
else if ( !Q_stricmp( token, "const" ) )
|
||||||
{
|
{
|
||||||
token = COM_ParseExt( text, qfalse );
|
token = COM_ParseExt( text, qfalse );
|
||||||
stage->constantColor[3] = 255 * atof( token );
|
stage->constantColor[3] = 255 * atof( token );
|
||||||
|
@ -1329,166 +1264,6 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
shader.portalRange = atof( token );
|
shader.portalRange = atof( token );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( !Q_stricmp( token, "distFade" ) )
|
|
||||||
{
|
|
||||||
stage->alphaGen = AGEN_DIST_FADE;
|
|
||||||
shader.fDistRange = 256;
|
|
||||||
shader.fDistNear = 256;
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
shader.fDistNear = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
shader.fDistRange = atof( token );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "oneMinusDistFade" ) )
|
|
||||||
{
|
|
||||||
stage->alphaGen = AGEN_ONE_MINUS_DIST_FADE;
|
|
||||||
shader.fDistRange = 256;
|
|
||||||
shader.fDistNear = 256;
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
shader.fDistNear = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
shader.fDistRange = atof( token );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "dot" ) )
|
|
||||||
{
|
|
||||||
shader.needsNormal = qtrue;
|
|
||||||
stage->alphaMin = 0.0;
|
|
||||||
stage->alphaMax = 1.0;
|
|
||||||
stage->alphaGen = AGEN_DOT;
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMin = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMax = atof( token );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "dotView" ) )
|
|
||||||
{
|
|
||||||
shader.needsNormal = qtrue;
|
|
||||||
stage->alphaMin = 0.0;
|
|
||||||
stage->alphaMax = 1.0;
|
|
||||||
stage->alphaGen = AGEN_DOT_VIEW;
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMin = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMax = atof( token );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "oneMinusDotView" ) )
|
|
||||||
{
|
|
||||||
shader.needsNormal = qtrue;
|
|
||||||
stage->alphaMin = 0.0;
|
|
||||||
stage->alphaMax = 1.0;
|
|
||||||
stage->alphaGen = AGEN_ONE_MINUS_DOT_VIEW;
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMin = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMax = atof( token );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "oneMinusDot" ) )
|
|
||||||
{
|
|
||||||
shader.needsNormal = qtrue;
|
|
||||||
stage->alphaMin = 0.0;
|
|
||||||
stage->alphaMax = 1.0;
|
|
||||||
stage->alphaGen = AGEN_ONE_MINUS_DOT;
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMin = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMax = atof( token );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "skyAlpha" ) )
|
|
||||||
{
|
|
||||||
stage->alphaGen = AGEN_SKYALPHA;
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "oneMinusSkyAlpha" ) )
|
|
||||||
{
|
|
||||||
stage->alphaGen = AGEN_ONE_MINUS_SKYALPHA;
|
|
||||||
}else if( !Q_stricmp( token, "sCoord" ) || !Q_stricmp( token, "tCoord" ) )
|
|
||||||
{
|
|
||||||
if( !Q_stricmp( token, "sCoord" ) ) {
|
|
||||||
stage->alphaGen = AGEN_SCOORD;
|
|
||||||
} else if( !Q_stricmp( token, "tCoord" ) ) {
|
|
||||||
stage->alphaGen = AGEN_TCOORD;
|
|
||||||
}
|
|
||||||
|
|
||||||
stage->alphaMin = 0.0;
|
|
||||||
stage->alphaMax = 1.0;
|
|
||||||
stage->alphaConstMin = 0;
|
|
||||||
stage->alphaConst = -1;
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMin = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaMax = atof( token );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaConstMin = ( byte )( atof( token ) * 255.0 );
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( token[ 0 ] )
|
|
||||||
{
|
|
||||||
stage->alphaConst = ( byte )( atof( token ) * 255.0 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: missing rgbGen sCoord or tCoord parm 'max' in shader '%s'\n", shader.name );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name );
|
ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name );
|
||||||
|
@ -1509,33 +1284,22 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
|
|
||||||
if ( !Q_stricmp( token, "environment" ) )
|
if ( !Q_stricmp( token, "environment" ) )
|
||||||
{
|
{
|
||||||
shader.needsNormal = qtrue;
|
stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED;
|
||||||
stage->bundle[bundleNum].tcGen = TCGEN_ENVIRONMENT_MAPPED;
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "environmentmodel" ) )
|
|
||||||
{
|
|
||||||
shader.needsNormal = qtrue;
|
|
||||||
stage->bundle[bundleNum].tcGen = TCGEN_ENVIRONMENT_MAPPED2;
|
|
||||||
}
|
|
||||||
else if ( !Q_stricmp( token, "sunreflection" ) )
|
|
||||||
{
|
|
||||||
shader.needsNormal = qtrue;
|
|
||||||
stage->bundle[bundleNum].tcGen = TCGEN_SUN_REFLECTION;
|
|
||||||
}
|
}
|
||||||
else if ( !Q_stricmp( token, "lightmap" ) )
|
else if ( !Q_stricmp( token, "lightmap" ) )
|
||||||
{
|
{
|
||||||
stage->bundle[bundleNum].tcGen = TCGEN_LIGHTMAP;
|
stage->bundle[0].tcGen = TCGEN_LIGHTMAP;
|
||||||
}
|
}
|
||||||
else if ( !Q_stricmp( token, "texture" ) || !Q_stricmp( token, "base" ) )
|
else if ( !Q_stricmp( token, "texture" ) || !Q_stricmp( token, "base" ) )
|
||||||
{
|
{
|
||||||
stage->bundle[bundleNum].tcGen = TCGEN_TEXTURE;
|
stage->bundle[0].tcGen = TCGEN_TEXTURE;
|
||||||
}
|
}
|
||||||
else if ( !Q_stricmp( token, "vector" ) )
|
else if ( !Q_stricmp( token, "vector" ) )
|
||||||
{
|
{
|
||||||
ParseVector( text, 3, stage->bundle[bundleNum].tcGenVectors[0] );
|
ParseVector( text, 3, stage->bundle[0].tcGenVectors[0] );
|
||||||
ParseVector( text, 3, stage->bundle[bundleNum].tcGenVectors[1] );
|
ParseVector( text, 3, stage->bundle[0].tcGenVectors[1] );
|
||||||
|
|
||||||
stage->bundle[bundleNum].tcGen = TCGEN_VECTOR;
|
stage->bundle[0].tcGen = TCGEN_VECTOR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1572,39 +1336,6 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// IneQuation: nextbundle implementation
|
|
||||||
else if( !Q_stricmp( token, "nextbundle" ) )
|
|
||||||
{
|
|
||||||
bundleNum++;
|
|
||||||
if( bundleNum >= NUM_TEXTURE_BUNDLES ) {
|
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: too many texture bundles in shader '%s'\n", shader.name );
|
|
||||||
return qfalse;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// IneQuation: this is not supposed to be here as it is a general shader param, but its absence breaks the Omaha water texture
|
|
||||||
else if( !Q_stricmp( token, "nopicmip" ) )
|
|
||||||
{
|
|
||||||
shader.noPicMip = qtrue;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// whether this shader param will be supported or not remains to be seen
|
|
||||||
else if( !Q_stricmp( token, "noDepthTest" ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "animMap" ) )
|
|
||||||
{
|
|
||||||
// wombat: TODO
|
|
||||||
if( !Q_stricmp( token, "animMapOnce" ) ) {
|
|
||||||
shader.flags |= 3;
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "animMapPhase" ) ) {
|
|
||||||
shader.flags |= 3;
|
|
||||||
stage->bundle[bundleNum].flags |= 1;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: unknown parameter '%s' in shader '%s'\n", token, shader.name );
|
ri.Printf( PRINT_WARNING, "WARNING: unknown parameter '%s' in shader '%s'\n", token, shader.name );
|
||||||
|
@ -2090,11 +1821,13 @@ static qboolean ParseShader( char **text )
|
||||||
|
|
||||||
if (isGL2Sun)
|
if (isGL2Sun)
|
||||||
{
|
{
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
tr.mapLightScale = atof(token);
|
|
||||||
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
token = COM_ParseExt( text, qfalse );
|
||||||
tr.sunShadowScale = atof(token);
|
tr.sunShadowScale = atof(token);
|
||||||
|
|
||||||
|
// parse twice, since older shaders may include mapLightScale before sunShadowScale
|
||||||
|
token = COM_ParseExt( text, qfalse );
|
||||||
|
if (token[0])
|
||||||
|
tr.sunShadowScale = atof(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkipRestOfLine( text );
|
SkipRestOfLine( text );
|
||||||
|
@ -2254,49 +1987,6 @@ static qboolean ParseShader( char **text )
|
||||||
ParseSort( text );
|
ParseSort( text );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// IneQuation: some general shader parms introduced in FAKK2
|
|
||||||
else if( !Q_stricmp( token, "spriteGen" ) )
|
|
||||||
{
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( !token[ 0 ] ) {
|
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: missing spriteGen parms in shader '%s'\n", shader.name );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if( !Q_stricmp( token, "parallel" ) ) {
|
|
||||||
shader.sprite.type = SPRITE_PARALLEL;
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "parallel_oriented" ) ) {
|
|
||||||
shader.sprite.type = SPRITE_PARALLEL_ORIENTED;
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "parallel_upright" ) ) {
|
|
||||||
shader.sprite.type = SPRITE_PARALLEL_UPRIGHT;
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "oriented" ) ) {
|
|
||||||
shader.sprite.type = SPRITE_ORIENTED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: invalid spriteGen parm '%s' in shader '%s'\n", token, shader.name );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "spriteScale" ) ) {
|
|
||||||
token = COM_ParseExt( text, qfalse );
|
|
||||||
if( !token[ 0 ] ) {
|
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: missing spriteScale parm in shader '%s'\n", shader.name );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
shader.sprite.scale = atof( token );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// force32bit, not needed anymore
|
|
||||||
else if( !Q_stricmp( token, "force32bit" ) )
|
|
||||||
{
|
|
||||||
shader.force32bit = qtrue;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if( !Q_stricmp( token, "noMerge" ) ) {
|
|
||||||
shader.flags |= 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: unknown general shader parameter '%s' in '%s'\n", token, shader.name );
|
ri.Printf( PRINT_WARNING, "WARNING: unknown general shader parameter '%s' in '%s'\n", token, shader.name );
|
||||||
|
@ -2425,12 +2115,10 @@ static void ComputeVertexAttribs(void)
|
||||||
{
|
{
|
||||||
shader.vertexAttribs |= ATTR_NORMAL;
|
shader.vertexAttribs |= ATTR_NORMAL;
|
||||||
|
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
if ((pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) && !(r_normalMapping->integer == 0 && r_specularMapping->integer == 0))
|
if ((pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) && !(r_normalMapping->integer == 0 && r_specularMapping->integer == 0))
|
||||||
{
|
{
|
||||||
shader.vertexAttribs |= ATTR_TANGENT;
|
shader.vertexAttribs |= ATTR_TANGENT;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK)
|
switch (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK)
|
||||||
{
|
{
|
||||||
|
@ -2529,7 +2217,7 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
|
||||||
defs |= LIGHTDEF_USE_LIGHT_VERTEX;
|
defs |= LIGHTDEF_USE_LIGHT_VERTEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_deluxeMapping->integer && tr.worldDeluxeMapping && lightmap)
|
if (r_deluxeMapping->integer && tr.worldDeluxeMapping && lightmap && shader.lightmapIndex >= 0)
|
||||||
{
|
{
|
||||||
//ri.Printf(PRINT_ALL, ", deluxemap");
|
//ri.Printf(PRINT_ALL, ", deluxemap");
|
||||||
diffuse->bundle[TB_DELUXEMAP] = lightmap->bundle[0];
|
diffuse->bundle[TB_DELUXEMAP] = lightmap->bundle[0];
|
||||||
|
@ -2552,12 +2240,24 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
|
||||||
{
|
{
|
||||||
char normalName[MAX_QPATH];
|
char normalName[MAX_QPATH];
|
||||||
image_t *normalImg;
|
image_t *normalImg;
|
||||||
imgFlags_t normalFlags = (diffuseImg->flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_NOLIGHTSCALE;
|
imgFlags_t normalFlags = (diffuseImg->flags & ~IMGFLAG_GENNORMALMAP) | IMGFLAG_NOLIGHTSCALE;
|
||||||
|
|
||||||
|
// try a normalheight image first
|
||||||
COM_StripExtension(diffuseImg->imgName, normalName, MAX_QPATH);
|
COM_StripExtension(diffuseImg->imgName, normalName, MAX_QPATH);
|
||||||
Q_strcat(normalName, MAX_QPATH, "_n");
|
Q_strcat(normalName, MAX_QPATH, "_nh");
|
||||||
|
|
||||||
normalImg = R_FindImageFile(normalName, IMGTYPE_NORMAL, normalFlags);
|
normalImg = R_FindImageFile(normalName, IMGTYPE_NORMALHEIGHT, normalFlags);
|
||||||
|
|
||||||
|
if (normalImg)
|
||||||
|
{
|
||||||
|
parallax = qtrue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// try a normal image ("_n" suffix)
|
||||||
|
normalName[strlen(normalName) - 1] = '\0';
|
||||||
|
normalImg = R_FindImageFile(normalName, IMGTYPE_NORMAL, normalFlags);
|
||||||
|
}
|
||||||
|
|
||||||
if (normalImg)
|
if (normalImg)
|
||||||
{
|
{
|
||||||
|
@ -2575,12 +2275,33 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
|
||||||
|
|
||||||
if (r_specularMapping->integer)
|
if (r_specularMapping->integer)
|
||||||
{
|
{
|
||||||
|
image_t *diffuseImg;
|
||||||
if (specular)
|
if (specular)
|
||||||
{
|
{
|
||||||
//ri.Printf(PRINT_ALL, ", specularmap %s", specular->bundle[0].image[0]->imgName);
|
//ri.Printf(PRINT_ALL, ", specularmap %s", specular->bundle[0].image[0]->imgName);
|
||||||
diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0];
|
diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0];
|
||||||
VectorCopy4(specular->specularScale, diffuse->specularScale);
|
VectorCopy4(specular->specularScale, diffuse->specularScale);
|
||||||
}
|
}
|
||||||
|
else if ((lightmap || useLightVector || useLightVertex) && (diffuseImg = diffuse->bundle[TB_DIFFUSEMAP].image[0]))
|
||||||
|
{
|
||||||
|
char specularName[MAX_QPATH];
|
||||||
|
image_t *specularImg;
|
||||||
|
imgFlags_t specularFlags = (diffuseImg->flags & ~IMGFLAG_GENNORMALMAP) | IMGFLAG_NOLIGHTSCALE;
|
||||||
|
|
||||||
|
COM_StripExtension(diffuseImg->imgName, specularName, MAX_QPATH);
|
||||||
|
Q_strcat(specularName, MAX_QPATH, "_s");
|
||||||
|
|
||||||
|
specularImg = R_FindImageFile(specularName, IMGTYPE_COLORALPHA, specularFlags);
|
||||||
|
|
||||||
|
if (specularImg)
|
||||||
|
{
|
||||||
|
diffuse->bundle[TB_SPECULARMAP] = diffuse->bundle[0];
|
||||||
|
diffuse->bundle[TB_SPECULARMAP].numImageAnimations = 0;
|
||||||
|
diffuse->bundle[TB_SPECULARMAP].image[0] = specularImg;
|
||||||
|
|
||||||
|
VectorSet4(diffuse->specularScale, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcgen || diffuse->bundle[0].numTexMods)
|
if (tcgen || diffuse->bundle[0].numTexMods)
|
||||||
|
@ -2685,6 +2406,8 @@ static int CollapseStagesToGLSL(void)
|
||||||
|
|
||||||
if (!skip)
|
if (!skip)
|
||||||
{
|
{
|
||||||
|
qboolean usedLightmap = qfalse;
|
||||||
|
|
||||||
for (i = 0; i < MAX_SHADER_STAGES; i++)
|
for (i = 0; i < MAX_SHADER_STAGES; i++)
|
||||||
{
|
{
|
||||||
shaderStage_t *pStage = &stages[i];
|
shaderStage_t *pStage = &stages[i];
|
||||||
|
@ -2743,7 +2466,16 @@ static int CollapseStagesToGLSL(void)
|
||||||
case ST_COLORMAP:
|
case ST_COLORMAP:
|
||||||
if (pStage2->bundle[0].tcGen == TCGEN_LIGHTMAP)
|
if (pStage2->bundle[0].tcGen == TCGEN_LIGHTMAP)
|
||||||
{
|
{
|
||||||
lightmap = pStage2;
|
int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
|
||||||
|
|
||||||
|
// Only add lightmap to blendfunc filter stage if it's the first time lightmap is used
|
||||||
|
// otherwise it will cause the shader to be darkened by the lightmap multiple times.
|
||||||
|
if (!usedLightmap || (blendBits != (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO)
|
||||||
|
&& blendBits != (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR)))
|
||||||
|
{
|
||||||
|
lightmap = pStage2;
|
||||||
|
usedLightmap = qtrue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2898,7 +2630,6 @@ sortedIndex.
|
||||||
*/
|
*/
|
||||||
static void FixRenderCommandList( int newShader ) {
|
static void FixRenderCommandList( int newShader ) {
|
||||||
renderCommandList_t *cmdList = &backEndData->commands;
|
renderCommandList_t *cmdList = &backEndData->commands;
|
||||||
qboolean staticModel;
|
|
||||||
|
|
||||||
if( cmdList ) {
|
if( cmdList ) {
|
||||||
const void *curCmd = cmdList->cmds;
|
const void *curCmd = cmdList->cmds;
|
||||||
|
@ -2932,7 +2663,7 @@ static void FixRenderCommandList( int newShader ) {
|
||||||
const drawSurfsCommand_t *ds_cmd = (const drawSurfsCommand_t *)curCmd;
|
const drawSurfsCommand_t *ds_cmd = (const drawSurfsCommand_t *)curCmd;
|
||||||
|
|
||||||
for( i = 0, drawSurf = ds_cmd->drawSurfs; i < ds_cmd->numDrawSurfs; i++, drawSurf++ ) {
|
for( i = 0, drawSurf = ds_cmd->drawSurfs; i < ds_cmd->numDrawSurfs; i++, drawSurf++ ) {
|
||||||
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap, &pshadowMap, &staticModel );
|
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap, &pshadowMap );
|
||||||
sortedIndex = (( drawSurf->sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1));
|
sortedIndex = (( drawSurf->sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1));
|
||||||
if( sortedIndex >= newShader ) {
|
if( sortedIndex >= newShader ) {
|
||||||
sortedIndex++;
|
sortedIndex++;
|
||||||
|
@ -3040,11 +2771,8 @@ static shader_t *GeneratePermanentShader( void ) {
|
||||||
|
|
||||||
for ( b = 0 ; b < NUM_TEXTURE_BUNDLES ; b++ ) {
|
for ( b = 0 ; b < NUM_TEXTURE_BUNDLES ; b++ ) {
|
||||||
size = newShader->stages[i]->bundle[b].numTexMods * sizeof( texModInfo_t );
|
size = newShader->stages[i]->bundle[b].numTexMods * sizeof( texModInfo_t );
|
||||||
|
newShader->stages[i]->bundle[b].texMods = ri.Hunk_Alloc( size );
|
||||||
if( size ) {
|
Com_Memcpy( newShader->stages[i]->bundle[b].texMods, stages[i].bundle[b].texMods, size );
|
||||||
newShader->stages[ i ]->bundle[ b ].texMods = ri.Hunk_Alloc( size );
|
|
||||||
Com_Memcpy( newShader->stages[ i ]->bundle[ b ].texMods, stages[ i ].bundle[ b ].texMods, size );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3062,7 +2790,7 @@ static shader_t *GeneratePermanentShader( void ) {
|
||||||
VertexLightingCollapse
|
VertexLightingCollapse
|
||||||
|
|
||||||
If vertex lighting is enabled, only render a single
|
If vertex lighting is enabled, only render a single
|
||||||
pass, trying to guess which is the correct one to best aproximate
|
pass, trying to guess which is the correct one to best approximate
|
||||||
what it is supposed to look like.
|
what it is supposed to look like.
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
|
@ -3166,10 +2894,17 @@ static void InitShader( const char *name, int lightmapIndex ) {
|
||||||
|
|
||||||
// default normal/specular
|
// default normal/specular
|
||||||
VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f);
|
VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
stages[i].specularScale[0] =
|
if (r_pbr->integer)
|
||||||
stages[i].specularScale[1] =
|
{
|
||||||
stages[i].specularScale[2] = r_baseSpecular->value;
|
stages[i].specularScale[0] = r_baseGloss->value;
|
||||||
stages[i].specularScale[3] = r_baseGloss->value;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stages[i].specularScale[0] =
|
||||||
|
stages[i].specularScale[1] =
|
||||||
|
stages[i].specularScale[2] = r_baseSpecular->value;
|
||||||
|
stages[i].specularScale[3] = r_baseGloss->value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3333,9 +3068,7 @@ static shader_t *FinishShader( void ) {
|
||||||
//
|
//
|
||||||
// look for multitexture potential
|
// look for multitexture potential
|
||||||
//
|
//
|
||||||
if ( qglActiveTextureARB ) {
|
stage = CollapseStagesToGLSL();
|
||||||
stage = CollapseStagesToGLSL();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) {
|
if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) {
|
||||||
if (vertexLightmap) {
|
if (vertexLightmap) {
|
||||||
|
@ -3418,7 +3151,7 @@ static char *FindShaderInShaderText( const char *shadername ) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// skip the definition
|
// skip the definition
|
||||||
SkipBracedSection( &p );
|
SkipBracedSection( &p, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3477,18 +3210,18 @@ be defined for every single image used in the game, three default
|
||||||
shader behaviors can be auto-created for any image:
|
shader behaviors can be auto-created for any image:
|
||||||
|
|
||||||
If lightmapIndex == LIGHTMAP_NONE, then the image will have
|
If lightmapIndex == LIGHTMAP_NONE, then the image will have
|
||||||
dynamic diffuse lighting applied to it, as apropriate for most
|
dynamic diffuse lighting applied to it, as appropriate for most
|
||||||
entity skin surfaces.
|
entity skin surfaces.
|
||||||
|
|
||||||
If lightmapIndex == LIGHTMAP_2D, then the image will be used
|
If lightmapIndex == LIGHTMAP_2D, then the image will be used
|
||||||
for 2D rendering unless an explicit shader is found
|
for 2D rendering unless an explicit shader is found
|
||||||
|
|
||||||
If lightmapIndex == LIGHTMAP_BY_VERTEX, then the image will use
|
If lightmapIndex == LIGHTMAP_BY_VERTEX, then the image will use
|
||||||
the vertex rgba modulate values, as apropriate for misc_model
|
the vertex rgba modulate values, as appropriate for misc_model
|
||||||
pre-lit surfaces.
|
pre-lit surfaces.
|
||||||
|
|
||||||
Other lightmapIndex values will have a lightmap stage created
|
Other lightmapIndex values will have a lightmap stage created
|
||||||
and src*dest blending applied with the texture, as apropriate for
|
and src*dest blending applied with the texture, as appropriate for
|
||||||
most world construction surfaces.
|
most world construction surfaces.
|
||||||
|
|
||||||
===============
|
===============
|
||||||
|
@ -3987,7 +3720,7 @@ static void ScanAndLoadShaderFiles( void )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!SkipBracedSectionEx(&p, 1))
|
if(!SkipBracedSection(&p, 1))
|
||||||
{
|
{
|
||||||
ri.Printf(PRINT_WARNING, "WARNING: Ignoring shader file %s. Shader \"%s\" on line %d missing closing brace.\n",
|
ri.Printf(PRINT_WARNING, "WARNING: Ignoring shader file %s. Shader \"%s\" on line %d missing closing brace.\n",
|
||||||
filename, shaderName, shaderLine);
|
filename, shaderName, shaderLine);
|
||||||
|
@ -4038,7 +3771,7 @@ static void ScanAndLoadShaderFiles( void )
|
||||||
hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
|
hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
|
||||||
shaderTextHashTableSizes[hash]++;
|
shaderTextHashTableSizes[hash]++;
|
||||||
size++;
|
size++;
|
||||||
SkipBracedSection(&p);
|
SkipBracedSection(&p, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
size += MAX_SHADERTEXT_HASH;
|
size += MAX_SHADERTEXT_HASH;
|
||||||
|
@ -4064,7 +3797,7 @@ static void ScanAndLoadShaderFiles( void )
|
||||||
hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
|
hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
|
||||||
shaderTextHashTable[hash][shaderTextHashTableSizes[hash]++] = oldp;
|
shaderTextHashTable[hash][shaderTextHashTableSizes[hash]++] = oldp;
|
||||||
|
|
||||||
SkipBracedSection(&p);
|
SkipBracedSection(&p, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -43,8 +43,8 @@ typedef struct {
|
||||||
|
|
||||||
static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
|
static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
|
||||||
static int numEdgeDefs[SHADER_MAX_VERTEXES];
|
static int numEdgeDefs[SHADER_MAX_VERTEXES];
|
||||||
static int facing[SHADER_MAX_INDEXES/3];
|
//static int facing[SHADER_MAX_INDEXES/3];
|
||||||
static vec3_t shadowXyz[SHADER_MAX_VERTEXES];
|
//static vec3_t shadowXyz[SHADER_MAX_VERTEXES];
|
||||||
|
|
||||||
void R_AddEdgeDef( int i1, int i2, int facing ) {
|
void R_AddEdgeDef( int i1, int i2, int facing ) {
|
||||||
int c;
|
int c;
|
||||||
|
@ -60,6 +60,8 @@ void R_AddEdgeDef( int i1, int i2, int facing ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_RenderShadowEdges( void ) {
|
void R_RenderShadowEdges( void ) {
|
||||||
|
// FIXME: implement this
|
||||||
|
#if 0
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -138,6 +140,7 @@ void R_RenderShadowEdges( void ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -153,6 +156,8 @@ triangleFromEdge[ v1 ][ v2 ]
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void RB_ShadowTessEnd( void ) {
|
void RB_ShadowTessEnd( void ) {
|
||||||
|
// FIXME: implement this
|
||||||
|
#if 0
|
||||||
int i;
|
int i;
|
||||||
int numTris;
|
int numTris;
|
||||||
vec3_t lightDir;
|
vec3_t lightDir;
|
||||||
|
@ -162,7 +167,7 @@ void RB_ShadowTessEnd( void ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorCopy( backEnd.currentEntity->lightDir, lightDir );
|
VectorCopy( backEnd.currentEntity->modelLightDir, lightDir );
|
||||||
|
|
||||||
// project vertexes away from light direction
|
// project vertexes away from light direction
|
||||||
for ( i = 0 ; i < tess.numVertexes ; i++ ) {
|
for ( i = 0 ; i < tess.numVertexes ; i++ ) {
|
||||||
|
@ -206,7 +211,7 @@ void RB_ShadowTessEnd( void ) {
|
||||||
|
|
||||||
// draw the silhouette edges
|
// draw the silhouette edges
|
||||||
|
|
||||||
GL_Bind( tr.whiteImage );
|
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
|
||||||
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
||||||
qglColor3f( 0.2f, 0.2f, 0.2f );
|
qglColor3f( 0.2f, 0.2f, 0.2f );
|
||||||
|
|
||||||
|
@ -230,6 +235,7 @@ void RB_ShadowTessEnd( void ) {
|
||||||
|
|
||||||
// reenable writing to the color buffer
|
// reenable writing to the color buffer
|
||||||
qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]);
|
qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -244,6 +250,8 @@ overlap and double darken.
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void RB_ShadowFinish( void ) {
|
void RB_ShadowFinish( void ) {
|
||||||
|
// FIXME: implement this
|
||||||
|
#if 0
|
||||||
if ( r_shadows->integer != 2 ) {
|
if ( r_shadows->integer != 2 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -253,10 +261,9 @@ void RB_ShadowFinish( void ) {
|
||||||
qglEnable( GL_STENCIL_TEST );
|
qglEnable( GL_STENCIL_TEST );
|
||||||
qglStencilFunc( GL_NOTEQUAL, 0, 255 );
|
qglStencilFunc( GL_NOTEQUAL, 0, 255 );
|
||||||
|
|
||||||
qglDisable (GL_CLIP_PLANE0);
|
|
||||||
GL_Cull( CT_TWO_SIDED );
|
GL_Cull( CT_TWO_SIDED );
|
||||||
|
|
||||||
GL_Bind( tr.whiteImage );
|
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
|
||||||
|
|
||||||
qglLoadIdentity ();
|
qglLoadIdentity ();
|
||||||
|
|
||||||
|
@ -275,54 +282,5 @@ void RB_ShadowFinish( void ) {
|
||||||
|
|
||||||
qglColor4f(1,1,1,1);
|
qglColor4f(1,1,1,1);
|
||||||
qglDisable( GL_STENCIL_TEST );
|
qglDisable( GL_STENCIL_TEST );
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
RB_ProjectionShadowDeform
|
|
||||||
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void RB_ProjectionShadowDeform( void ) {
|
|
||||||
// FIXME: unimplemented
|
|
||||||
#if 0
|
|
||||||
float *xyz;
|
|
||||||
int i;
|
|
||||||
float h;
|
|
||||||
vec3_t ground;
|
|
||||||
vec3_t light;
|
|
||||||
float groundDist;
|
|
||||||
float d;
|
|
||||||
vec3_t lightDir;
|
|
||||||
|
|
||||||
xyz = ( float * ) tess.xyz;
|
|
||||||
|
|
||||||
ground[0] = backEnd.or.axis[0][2];
|
|
||||||
ground[1] = backEnd.or.axis[1][2];
|
|
||||||
ground[2] = backEnd.or.axis[2][2];
|
|
||||||
|
|
||||||
groundDist = backEnd.or.origin[2] - backEnd.currentEntity->e.shadowPlane;
|
|
||||||
|
|
||||||
VectorCopy( backEnd.currentEntity->lightDir, lightDir );
|
|
||||||
d = DotProduct( lightDir, ground );
|
|
||||||
// don't let the shadows get too long or go negative
|
|
||||||
if ( d < 0.5 ) {
|
|
||||||
VectorMA( lightDir, (0.5 - d), ground, lightDir );
|
|
||||||
d = DotProduct( lightDir, ground );
|
|
||||||
}
|
|
||||||
d = 1.0 / d;
|
|
||||||
|
|
||||||
light[0] = lightDir[0] * d;
|
|
||||||
light[1] = lightDir[1] * d;
|
|
||||||
light[2] = lightDir[2] * d;
|
|
||||||
|
|
||||||
for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
|
|
||||||
h = DotProduct( xyz, ground ) + groundDist;
|
|
||||||
|
|
||||||
xyz[0] -= light[0] * h;
|
|
||||||
xyz[1] -= light[1] * h;
|
|
||||||
xyz[2] -= light[2] * h;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -366,15 +366,13 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
|
||||||
int s, t;
|
int s, t;
|
||||||
int firstVertex = tess.numVertexes;
|
int firstVertex = tess.numVertexes;
|
||||||
//int firstIndex = tess.numIndexes;
|
//int firstIndex = tess.numIndexes;
|
||||||
int minIndex = tess.minIndex;
|
|
||||||
int maxIndex = tess.maxIndex;
|
|
||||||
vec4_t color;
|
vec4_t color;
|
||||||
|
|
||||||
//tess.numVertexes = 0;
|
//tess.numVertexes = 0;
|
||||||
//tess.numIndexes = 0;
|
//tess.numIndexes = 0;
|
||||||
tess.firstIndex = tess.numIndexes;
|
tess.firstIndex = tess.numIndexes;
|
||||||
|
|
||||||
GL_Bind( image );
|
GL_BindToTMU( image, TB_COLORMAP );
|
||||||
GL_Cull( CT_TWO_SIDED );
|
GL_Cull( CT_TWO_SIDED );
|
||||||
|
|
||||||
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
|
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
|
||||||
|
@ -386,8 +384,8 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
|
||||||
tess.xyz[tess.numVertexes][2] = s_skyPoints[t][s][2];
|
tess.xyz[tess.numVertexes][2] = s_skyPoints[t][s][2];
|
||||||
tess.xyz[tess.numVertexes][3] = 1.0;
|
tess.xyz[tess.numVertexes][3] = 1.0;
|
||||||
|
|
||||||
tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0];
|
tess.texCoords[tess.numVertexes][0] = s_skyTexCoords[t][s][0];
|
||||||
tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1];
|
tess.texCoords[tess.numVertexes][1] = s_skyTexCoords[t][s][1];
|
||||||
|
|
||||||
tess.numVertexes++;
|
tess.numVertexes++;
|
||||||
|
|
||||||
|
@ -417,9 +415,6 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tess.minIndex = firstVertex;
|
|
||||||
tess.maxIndex = tess.numVertexes;
|
|
||||||
|
|
||||||
// FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
|
// FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
|
||||||
RB_UpdateTessVao(ATTR_POSITION | ATTR_TEXCOORD);
|
RB_UpdateTessVao(ATTR_POSITION | ATTR_TEXCOORD);
|
||||||
/*
|
/*
|
||||||
|
@ -448,7 +443,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
|
||||||
|
|
||||||
color[0] =
|
color[0] =
|
||||||
color[1] =
|
color[1] =
|
||||||
color[2] = backEnd.refdef.colorScale;
|
color[2] =
|
||||||
color[3] = 1.0f;
|
color[3] = 1.0f;
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, color);
|
GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, color);
|
||||||
|
|
||||||
|
@ -463,9 +458,11 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
|
||||||
|
|
||||||
VectorSet4(vector, 0.0, 0.0, 0.0, 0.0);
|
VectorSet4(vector, 0.0, 0.0, 0.0, 0.0);
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector);
|
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector);
|
||||||
|
|
||||||
|
GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
R_DrawElementsVao(tess.numIndexes - tess.firstIndex, tess.firstIndex, tess.minIndex, tess.maxIndex);
|
R_DrawElements(tess.numIndexes - tess.firstIndex, tess.firstIndex);
|
||||||
|
|
||||||
//qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(glIndex_t)));
|
//qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(glIndex_t)));
|
||||||
|
|
||||||
|
@ -475,8 +472,6 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
|
||||||
tess.numIndexes = tess.firstIndex;
|
tess.numIndexes = tess.firstIndex;
|
||||||
tess.numVertexes = firstVertex;
|
tess.numVertexes = firstVertex;
|
||||||
tess.firstIndex = 0;
|
tess.firstIndex = 0;
|
||||||
tess.minIndex = minIndex;
|
|
||||||
tess.maxIndex = maxIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawSkyBox( shader_t *shader )
|
static void DrawSkyBox( shader_t *shader )
|
||||||
|
@ -563,8 +558,8 @@ static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean ad
|
||||||
for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
|
for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
|
||||||
{
|
{
|
||||||
VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] );
|
VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] );
|
||||||
tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0];
|
tess.texCoords[tess.numVertexes][0] = s_skyTexCoords[t][s][0];
|
||||||
tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1];
|
tess.texCoords[tess.numVertexes][1] = s_skyTexCoords[t][s][1];
|
||||||
|
|
||||||
tess.numVertexes++;
|
tess.numVertexes++;
|
||||||
|
|
||||||
|
@ -871,6 +866,7 @@ void RB_StageIteratorSky( void ) {
|
||||||
mat4_t oldmodelview;
|
mat4_t oldmodelview;
|
||||||
|
|
||||||
GL_State( 0 );
|
GL_State( 0 );
|
||||||
|
GL_Cull( CT_FRONT_SIDED );
|
||||||
//qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
|
//qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 2015 the OpenMoHAA team
|
Copyright (C) 2023 the OpenMoHAA team
|
||||||
|
|
||||||
This file is part of OpenMoHAA source code.
|
This file is part of OpenMoHAA source code.
|
||||||
|
|
||||||
|
@ -20,15 +20,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
===========================================================================
|
===========================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// tr_terrain.c : Terrain rendering
|
// tr_sphere_shade.cpp -- sphere shade
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
/*
|
int R_GatherLightSources(const vec3_t vPos, vec3_t* pvLightPos, vec3_t* pvLightIntensity, int iMaxLights)
|
||||||
=============
|
{
|
||||||
R_AddTerrainSurfaces
|
// FIXME: unimplemented
|
||||||
=============
|
return 0;
|
||||||
*/
|
|
||||||
void R_AddTerrainSurfaces( void ) {
|
|
||||||
// FIXME
|
|
||||||
}
|
}
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
===========================================================================
|
|
||||||
Copyright (C) 2010 su44
|
|
||||||
|
|
||||||
This file is part of OpenMoHAA source code.
|
|
||||||
|
|
||||||
OpenMoHAA source code 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 2 of the License,
|
|
||||||
or (at your option) any later version.
|
|
||||||
|
|
||||||
OpenMoHAA source code 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.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenMoHAA source code; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
===========================================================================
|
|
||||||
*/
|
|
||||||
// tr_sprite.c - MoHAA sprite system
|
|
||||||
|
|
||||||
#include "tr_local.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
SPR_RegisterSprite
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
sprite_t *SPR_RegisterSprite(const char *name)
|
|
||||||
{
|
|
||||||
image_t *spriteImage;
|
|
||||||
shader_t *shader;
|
|
||||||
sprite_t *spr;
|
|
||||||
char shadername[256];
|
|
||||||
COM_StripExtension(name,shadername,sizeof(shadername));
|
|
||||||
shader = R_FindShader(shadername,-1,qfalse);
|
|
||||||
if(shader) {
|
|
||||||
spriteImage = 0;
|
|
||||||
if(shader->stages[0])
|
|
||||||
spriteImage = shader->stages[0]->bundle[0].image[0];
|
|
||||||
if ( !spriteImage ) {
|
|
||||||
ri.Printf(1, "Could not find image for sprite in shader %s\n", name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
spr = ri.Hunk_Alloc(sizeof(sprite_t));
|
|
||||||
spr->height = spriteImage->height;
|
|
||||||
spr->width = spriteImage->width;
|
|
||||||
spr->origin_x = spr->width * 0.5;
|
|
||||||
spr->origin_y = spr->height * 0.5;
|
|
||||||
spr->shader = shader;
|
|
||||||
spr->scale = spr->shader->sprite.scale;
|
|
||||||
return spr;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
RB_DrawSprite
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void RB_DrawSprite( const refSprite_t *spr ) {
|
|
||||||
// FIXME: stub
|
|
||||||
}
|
|
|
@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
// tr_staticmodels.cpp -- static model rendering
|
// tr_staticmodels.cpp -- static model rendering
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
#include "tiki.h"
|
||||||
|
|
||||||
#define MAX_STATIC_MODELS_SURFS 8192
|
#define MAX_STATIC_MODELS_SURFS 8192
|
||||||
|
|
||||||
|
@ -363,8 +364,6 @@ void R_AddStaticModelSurfaces( void ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.currentEntityNum = REFENTITYNUM_WORLD;
|
|
||||||
tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
|
|
||||||
tr.shiftedIsStatic = 0;
|
tr.shiftedIsStatic = 0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -385,89 +384,85 @@ void RB_StaticMesh( staticSurface_t *staticSurf ) {
|
||||||
int baseIndex, baseVertex;
|
int baseIndex, baseVertex;
|
||||||
short collapse[ 1000 ];
|
short collapse[ 1000 ];
|
||||||
|
|
||||||
RB_CheckVao( tess.vao );
|
tiki = backEnd.currentStaticModel->tiki;
|
||||||
|
surf = staticSurf->surface;
|
||||||
|
|
||||||
tiki = backEnd.currentStaticModel->tiki;
|
assert(surf->pStaticXyz);
|
||||||
surf = staticSurf->surface;
|
|
||||||
|
|
||||||
assert( surf->pStaticXyz );
|
meshNum = staticSurf->meshNum;
|
||||||
|
skelmodel = TIKI_GetSkel(tiki->mesh[meshNum]);
|
||||||
|
|
||||||
meshNum = staticSurf->meshNum;
|
// FIXME: LOD
|
||||||
skelmodel = TIKI_GetSkel( tiki->mesh[ meshNum ] );
|
render_count = surf->numVerts;
|
||||||
|
|
||||||
// FIXME: LOD
|
if (tess.numVertexes + render_count >= TIKI_MAX_VERTEXES ||
|
||||||
render_count = surf->numVerts;
|
tess.numIndexes + surf->numTriangles >= TIKI_MAX_TRIANGLES * 3) {
|
||||||
|
RB_CHECKOVERFLOW(render_count, surf->numTriangles);
|
||||||
|
}
|
||||||
|
|
||||||
if( tess.numVertexes + render_count >= TIKI_MAX_VERTEXES ||
|
collapse_map = surf->pCollapse;
|
||||||
tess.numIndexes + surf->numTriangles >= TIKI_MAX_TRIANGLES * 3 ) {
|
triangles = surf->pTriangles;
|
||||||
RB_CHECKOVERFLOW( render_count, surf->numTriangles );
|
indexes = surf->numTriangles * 3;
|
||||||
}
|
baseIndex = tess.numIndexes;
|
||||||
|
baseVertex = tess.numVertexes;
|
||||||
|
tess.numVertexes += render_count;
|
||||||
|
|
||||||
collapse_map = surf->pCollapse;
|
if (render_count == surf->numVerts)
|
||||||
triangles = surf->pTriangles;
|
{
|
||||||
indexes = surf->numTriangles * 3;
|
for (j = 0; j < indexes; j++) {
|
||||||
baseIndex = tess.numIndexes;
|
tess.indexes[baseIndex + j] = baseVertex + triangles[j];
|
||||||
baseVertex = tess.numVertexes;
|
}
|
||||||
tess.numVertexes += render_count;
|
tess.numIndexes += indexes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < render_count; i++) {
|
||||||
|
collapse[i] = i;
|
||||||
|
}
|
||||||
|
for (i = 0; i < surf->numVerts; i++) {
|
||||||
|
collapse[i] = collapse[collapse_map[i]];
|
||||||
|
}
|
||||||
|
|
||||||
if( render_count == surf->numVerts )
|
for (j = 0; j < indexes; j += 3)
|
||||||
{
|
{
|
||||||
for( j = 0; j < indexes; j++ ) {
|
if (collapse[triangles[j]] == collapse[triangles[j + 1]] ||
|
||||||
tess.indexes[ baseIndex + j ] = baseVertex + triangles[ j ];
|
collapse[triangles[j + 1]] == collapse[triangles[j + 2]] ||
|
||||||
}
|
collapse[triangles[j + 2]] == collapse[triangles[j]])
|
||||||
tess.numIndexes += indexes;
|
{
|
||||||
}
|
break;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
for( i = 0; i < render_count; i++ ) {
|
|
||||||
collapse[ i ] = i;
|
|
||||||
}
|
|
||||||
for( i = 0; i < surf->numVerts; i++ ) {
|
|
||||||
collapse[ i ] = collapse[ collapse_map[ i ] ];
|
|
||||||
}
|
|
||||||
|
|
||||||
for( j = 0; j < indexes; j += 3 )
|
tess.indexes[baseIndex + j] = baseVertex + collapse[triangles[j]];
|
||||||
{
|
tess.indexes[baseIndex + j + 1] = baseVertex + collapse[triangles[j + 1]];
|
||||||
if( collapse[ triangles[ j ] ] == collapse[ triangles[ j + 1 ] ] ||
|
tess.indexes[baseIndex + j + 2] = baseVertex + collapse[triangles[j + 2]];
|
||||||
collapse[ triangles[ j + 1 ] ] == collapse[ triangles[ j + 2 ] ] ||
|
}
|
||||||
collapse[ triangles[ j + 2 ] ] == collapse[ triangles[ j ] ] )
|
tess.numIndexes += j;
|
||||||
{
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tess.indexes[ baseIndex + j ] = baseVertex + collapse[ triangles[ j ] ];
|
for (j = 0; j < render_count; j++) {
|
||||||
tess.indexes[ baseIndex + j + 1 ] = baseVertex + collapse[ triangles[ j + 1 ] ];
|
Vector4Copy(surf->pStaticXyz[j], tess.xyz[baseVertex + j]);
|
||||||
tess.indexes[ baseIndex + j + 2 ] = baseVertex + collapse[ triangles[ j + 2 ] ];
|
Vector4Copy(surf->pStaticNormal[j], tess.normal[baseVertex + j]);
|
||||||
}
|
tess.texCoords[baseVertex + j][0] = surf->pStaticTexCoords[j][0][0];
|
||||||
tess.numIndexes += j;
|
tess.texCoords[baseVertex + j][1] = surf->pStaticTexCoords[j][0][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
for( j = 0; j < render_count; j++ ) {
|
if (backEndData->staticModels) {
|
||||||
Vector4Copy( surf->pStaticXyz[ j ], tess.xyz[ baseVertex + j ] );
|
color4ub_t* in = (color4ub_t*)&backEndData->staticModelData[backEnd.currentStaticModel->firstVertexData + staticSurf->ofsStaticData];
|
||||||
R_VaoPackNormal( ( byte * )&tess.normal[ baseVertex + j ], surf->pStaticNormal[ j ] );
|
|
||||||
tess.texCoords[ baseVertex + j ][ 0 ][ 0 ] = surf->pStaticTexCoords[ j ][ 0 ][ 0 ];
|
|
||||||
tess.texCoords[ baseVertex + j ][ 0 ][ 1 ] = surf->pStaticTexCoords[ j ][ 0 ][ 1 ];
|
|
||||||
}
|
|
||||||
|
|
||||||
if( backEndData->staticModels ) {
|
for (i = 0; i < render_count; i++, in++)
|
||||||
color4ub_t *in = ( color4ub_t * )&backEndData->staticModelData[ backEnd.currentStaticModel->firstVertexData + staticSurf->ofsStaticData ];
|
{
|
||||||
vec4_t *out = &tess.vertexColors[ baseVertex ];
|
tess.color[baseVertex + i][0] = (*in)[0] * 257;
|
||||||
|
tess.color[baseVertex + i][0] = (*in)[1] * 257;
|
||||||
for( i = 0; i < render_count; i++, in++, out++ )
|
tess.color[baseVertex + i][0] = (*in)[2] * 257;
|
||||||
{
|
tess.color[baseVertex + i][0] = 65535;
|
||||||
( *out )[ 0 ] = ( float )( *in )[ i ] / 255.0;
|
}
|
||||||
( *out )[ 1 ] = ( float )( *in )[ i + 1 ] / 255.0;
|
}
|
||||||
( *out )[ 2 ] = ( float )( *in )[ i + 2 ] / 255.0;
|
else {
|
||||||
( *out )[ 3 ] = 1.0;
|
for (i = 0; i < render_count; i++) {
|
||||||
}
|
tess.color[baseVertex + i][0] = 65535;
|
||||||
} else {
|
tess.color[baseVertex + i][1] = 65535;
|
||||||
for( i = 0; i < render_count; i++ ) {
|
tess.color[baseVertex + i][2] = 65535;
|
||||||
tess.vertexColors[ baseVertex + i ][ 0 ] = 1.0;
|
tess.color[baseVertex + i][3] = 65535;
|
||||||
tess.vertexColors[ baseVertex + i ][ 1 ] = 1.0;
|
}
|
||||||
tess.vertexColors[ baseVertex + i ][ 2 ] = 1.0;
|
}
|
||||||
tess.vertexColors[ baseVertex + i ][ 3 ] = 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tess.vertexColorValid = qtrue;
|
|
||||||
}
|
}
|
|
@ -23,8 +23,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
void QDECL Com_Printf( const char *msg, ... )
|
void QDECL Com_Printf( const char *msg, ... )
|
||||||
{
|
{
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
|
@ -48,5 +46,3 @@ void QDECL Com_Error( int level, const char *error, ... )
|
||||||
|
|
||||||
ri.Error(level, "%s", text);
|
ri.Error(level, "%s", text);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,43 +1,44 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 1999-2005 Id Software, Inc.
|
Copyright (C) 2023 the OpenMoHAA team
|
||||||
|
|
||||||
This file is part of Quake III Arena source code.
|
This file is part of OpenMoHAA source code.
|
||||||
|
|
||||||
Quake III Arena source code is free software; you can redistribute it
|
OpenMoHAA source code is free software; you can redistribute it
|
||||||
and/or modify it under the terms of the GNU General Public License as
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
published by the Free Software Foundation; either version 2 of the License,
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
or (at your option) any later version.
|
or (at your option) any later version.
|
||||||
|
|
||||||
Quake III Arena source code is distributed in the hope that it will be
|
OpenMoHAA source code is distributed in the hope that it will be
|
||||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Quake III Arena source code; if not, write to the Free Software
|
along with OpenMoHAA source code; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
===========================================================================
|
===========================================================================
|
||||||
*/
|
*/
|
||||||
// tr_swipe.cpp -- renderer swipe
|
|
||||||
|
// tr_swipe.cpp -- swipe rendering
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
void RE_SwipeBegin( float thistime, float life, qhandle_t shader ) {
|
void RB_DrawSwipeSurface(surfaceType_t* pswipe) {
|
||||||
// FIXME: stub
|
// FIXME: unimplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
void RE_SwipePoint( vec3_t point1, vec3_t point2, float time ) {
|
void RE_SwipeBegin(float thistime, float life, qhandle_t shader)
|
||||||
// FIXME: stub
|
{
|
||||||
|
// FIXME: unimplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
void RE_SwipeEnd( void ) {
|
void RE_SwipePoint(vec3_t point1, vec3_t point2, float time)
|
||||||
|
{
|
||||||
|
// FIXME: unimplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_AddSwipeSurfaces( void ) {
|
void RE_SwipeEnd()
|
||||||
// FIXME: stub
|
{
|
||||||
}
|
// FIXME: unimplemented
|
||||||
|
|
||||||
void RB_DrawSwipeSurface( surfaceType_t *pswipe ) {
|
|
||||||
// FIXME: stub
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,13 +100,12 @@ addTriangle
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
static void addTriangle( void ) {
|
static void addTriangle( void ) {
|
||||||
tess.texCoords[ tess.numVertexes ][ 0 ][ 0 ] = cntSt[ 0 ];
|
tess.texCoords[ tess.numVertexes ][ 0 ] = cntSt[ 0 ];
|
||||||
tess.texCoords[ tess.numVertexes ][ 0 ][ 1 ] = cntSt[ 1 ];
|
tess.texCoords[ tess.numVertexes ][ 1 ] = cntSt[ 1 ];
|
||||||
tess.vertexColors[ tess.numVertexes ][ 0 ] = cntColor[ 0 ];
|
tess.color[ tess.numVertexes ][ 0 ] = cntColor[ 0 ];
|
||||||
tess.vertexColors[ tess.numVertexes ][ 1 ] = cntColor[ 1 ];
|
tess.color[ tess.numVertexes ][ 1 ] = cntColor[ 1 ];
|
||||||
tess.vertexColors[ tess.numVertexes ][ 2 ] = cntColor[ 2 ];
|
tess.color[ tess.numVertexes ][ 2 ] = cntColor[ 2 ];
|
||||||
tess.vertexColors[ tess.numVertexes ][ 3 ] = cntColor[ 3 ];
|
tess.color[ tess.numVertexes ][ 3 ] = cntColor[ 3 ];
|
||||||
tess.vertexColorValid = qtrue;
|
|
||||||
tess.numVertexes++;
|
tess.numVertexes++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,27 +223,6 @@ void R_DebugRotatedBBox( const vec3_t org, vec3_t ang, vec3_t mins, vec3_t maxs,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
RB_Prepare2D
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
void RB_Prepare2D( void ) {
|
|
||||||
if( glRefConfig.framebufferObject )
|
|
||||||
{
|
|
||||||
if( !tr.renderFbo || backEnd.framePostProcessed )
|
|
||||||
{
|
|
||||||
FBO_Bind( NULL );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FBO_Bind( tr.renderFbo );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RB_SetGL2D();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
RE_GetShaderWidth
|
RE_GetShaderWidth
|
||||||
|
|
|
@ -23,167 +23,45 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
|
||||||
union pack10_u {
|
void R_VaoPackTangent(int16_t *out, vec4_t v)
|
||||||
struct {
|
|
||||||
signed int x:10;
|
|
||||||
signed int y:10;
|
|
||||||
signed int z:10;
|
|
||||||
signed int w:2;
|
|
||||||
} pack;
|
|
||||||
uint32_t i;
|
|
||||||
};
|
|
||||||
|
|
||||||
union pack8_u {
|
|
||||||
struct {
|
|
||||||
signed int x:8;
|
|
||||||
signed int y:8;
|
|
||||||
signed int z:8;
|
|
||||||
signed int w:8;
|
|
||||||
} pack;
|
|
||||||
uint32_t i;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int R_VaoPackTangent(byte *out, vec4_t v)
|
|
||||||
{
|
{
|
||||||
if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
|
out[0] = v[0] * 32767.0f + (v[0] > 0.0f ? 0.5f : -0.5f);
|
||||||
{
|
out[1] = v[1] * 32767.0f + (v[1] > 0.0f ? 0.5f : -0.5f);
|
||||||
union pack10_u *num = (union pack10_u *)out;
|
out[2] = v[2] * 32767.0f + (v[2] > 0.0f ? 0.5f : -0.5f);
|
||||||
|
out[3] = v[3] * 32767.0f + (v[3] > 0.0f ? 0.5f : -0.5f);
|
||||||
num->pack.x = v[0] * 511.0f;
|
|
||||||
num->pack.y = v[1] * 511.0f;
|
|
||||||
num->pack.z = v[2] * 511.0f;
|
|
||||||
num->pack.w = v[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
union pack8_u *num = (union pack8_u *)out;
|
|
||||||
|
|
||||||
num->pack.x = v[0] * 127.0f;
|
|
||||||
num->pack.y = v[1] * 127.0f;
|
|
||||||
num->pack.z = v[2] * 127.0f;
|
|
||||||
num->pack.w = v[3] * 127.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int R_VaoPackNormal(byte *out, vec3_t v)
|
void R_VaoPackNormal(int16_t *out, vec3_t v)
|
||||||
{
|
{
|
||||||
if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
|
out[0] = v[0] * 32767.0f + (v[0] > 0.0f ? 0.5f : -0.5f);
|
||||||
{
|
out[1] = v[1] * 32767.0f + (v[1] > 0.0f ? 0.5f : -0.5f);
|
||||||
union pack10_u *num = (union pack10_u *)out;
|
out[2] = v[2] * 32767.0f + (v[2] > 0.0f ? 0.5f : -0.5f);
|
||||||
|
out[3] = 0;
|
||||||
num->pack.x = v[0] * 511.0f;
|
|
||||||
num->pack.y = v[1] * 511.0f;
|
|
||||||
num->pack.z = v[2] * 511.0f;
|
|
||||||
num->pack.w = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
union pack8_u *num = (union pack8_u *)out;
|
|
||||||
|
|
||||||
num->pack.x = v[0] * 127.0f;
|
|
||||||
num->pack.y = v[1] * 127.0f;
|
|
||||||
num->pack.z = v[2] * 127.0f;
|
|
||||||
num->pack.w = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int R_VaoPackTexCoord(byte *out, vec2_t st)
|
void R_VaoPackColor(uint16_t *out, vec4_t c)
|
||||||
{
|
{
|
||||||
if (glRefConfig.packedTexcoordDataType == GL_HALF_FLOAT)
|
out[0] = c[0] * 65535.0f + 0.5f;
|
||||||
{
|
out[1] = c[1] * 65535.0f + 0.5f;
|
||||||
uint16_t *num = (uint16_t *)out;
|
out[2] = c[2] * 65535.0f + 0.5f;
|
||||||
|
out[3] = c[3] * 65535.0f + 0.5f;
|
||||||
*num++ = FloatToHalf(st[0]);
|
|
||||||
*num++ = FloatToHalf(st[1]);
|
|
||||||
|
|
||||||
return sizeof(*num) * 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float *num = (float *)out;
|
|
||||||
|
|
||||||
*num++ = st[0];
|
|
||||||
*num++ = st[1];
|
|
||||||
|
|
||||||
return sizeof(*num) * 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int R_VaoPackColors(byte *out, vec4_t color)
|
void R_VaoUnpackTangent(vec4_t v, int16_t *pack)
|
||||||
{
|
{
|
||||||
if (glRefConfig.packedTexcoordDataType == GL_HALF_FLOAT)
|
v[0] = pack[0] / 32767.0f;
|
||||||
{
|
v[1] = pack[1] / 32767.0f;
|
||||||
uint16_t *num = (uint16_t *)out;
|
v[2] = pack[2] / 32767.0f;
|
||||||
|
v[3] = pack[3] / 32767.0f;
|
||||||
*num++ = FloatToHalf(color[0]);
|
|
||||||
*num++ = FloatToHalf(color[1]);
|
|
||||||
*num++ = FloatToHalf(color[2]);
|
|
||||||
*num++ = FloatToHalf(color[3]);
|
|
||||||
|
|
||||||
return sizeof(*num) * 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float *num = (float *)out;
|
|
||||||
|
|
||||||
*num++ = color[0];
|
|
||||||
*num++ = color[1];
|
|
||||||
*num++ = color[2];
|
|
||||||
*num++ = color[3];
|
|
||||||
|
|
||||||
return sizeof(*num) * 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void R_VaoUnpackNormal(vec3_t v, int16_t *pack)
|
||||||
void R_VaoUnpackTangent(vec4_t v, uint32_t b)
|
|
||||||
{
|
{
|
||||||
if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
|
v[0] = pack[0] / 32767.0f;
|
||||||
{
|
v[1] = pack[1] / 32767.0f;
|
||||||
union pack10_u *num = (union pack10_u *)&b;
|
v[2] = pack[2] / 32767.0f;
|
||||||
|
|
||||||
v[0] = num->pack.x / 511.0f;
|
|
||||||
v[1] = num->pack.y / 511.0f;
|
|
||||||
v[2] = num->pack.z / 511.0f;
|
|
||||||
v[3] = num->pack.w;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
union pack8_u *num = (union pack8_u *)&b;
|
|
||||||
|
|
||||||
v[0] = num->pack.x / 127.0f;
|
|
||||||
v[1] = num->pack.y / 127.0f;
|
|
||||||
v[2] = num->pack.z / 127.0f;
|
|
||||||
v[3] = num->pack.w / 127.0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_VaoUnpackNormal(vec3_t v, uint32_t b)
|
|
||||||
{
|
|
||||||
if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
|
|
||||||
{
|
|
||||||
union pack10_u *num = (union pack10_u *)&b;
|
|
||||||
|
|
||||||
v[0] = num->pack.x / 511.0f;
|
|
||||||
v[1] = num->pack.y / 511.0f;
|
|
||||||
v[2] = num->pack.z / 511.0f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
union pack8_u *num = (union pack8_u *)&b;
|
|
||||||
|
|
||||||
v[0] = num->pack.x / 127.0f;
|
|
||||||
v[1] = num->pack.y / 127.0f;
|
|
||||||
v[2] = num->pack.z / 127.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Vao_SetVertexPointers(vao_t *vao)
|
void Vao_SetVertexPointers(vao_t *vao)
|
||||||
{
|
{
|
||||||
int attribIndex;
|
int attribIndex;
|
||||||
|
@ -196,9 +74,9 @@ void Vao_SetVertexPointers(vao_t *vao)
|
||||||
|
|
||||||
if (vAtb->enabled)
|
if (vAtb->enabled)
|
||||||
{
|
{
|
||||||
qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset));
|
qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset));
|
||||||
if (glRefConfig.vertexArrayObject || !(glState.vertexAttribsEnabled & attribBit))
|
if (glRefConfig.vertexArrayObject || !(glState.vertexAttribsEnabled & attribBit))
|
||||||
qglEnableVertexAttribArrayARB(attribIndex);
|
qglEnableVertexAttribArray(attribIndex);
|
||||||
|
|
||||||
if (!glRefConfig.vertexArrayObject || vao == tess.vao)
|
if (!glRefConfig.vertexArrayObject || vao == tess.vao)
|
||||||
glState.vertexAttribsEnabled |= attribBit;
|
glState.vertexAttribsEnabled |= attribBit;
|
||||||
|
@ -208,7 +86,7 @@ void Vao_SetVertexPointers(vao_t *vao)
|
||||||
// don't disable vertex attribs when using vertex array objects
|
// don't disable vertex attribs when using vertex array objects
|
||||||
// Vao_SetVertexPointers is only called during init when using VAOs, and vertex attribs start disabled anyway
|
// Vao_SetVertexPointers is only called during init when using VAOs, and vertex attribs start disabled anyway
|
||||||
if (!glRefConfig.vertexArrayObject && (glState.vertexAttribsEnabled & attribBit))
|
if (!glRefConfig.vertexArrayObject && (glState.vertexAttribsEnabled & attribBit))
|
||||||
qglDisableVertexAttribArrayARB(attribIndex);
|
qglDisableVertexAttribArray(attribIndex);
|
||||||
|
|
||||||
if (!glRefConfig.vertexArrayObject || vao == tess.vao)
|
if (!glRefConfig.vertexArrayObject || vao == tess.vao)
|
||||||
glState.vertexAttribsEnabled &= ~attribBit;
|
glState.vertexAttribsEnabled &= ~attribBit;
|
||||||
|
@ -229,15 +107,15 @@ vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *ind
|
||||||
switch (usage)
|
switch (usage)
|
||||||
{
|
{
|
||||||
case VAO_USAGE_STATIC:
|
case VAO_USAGE_STATIC:
|
||||||
glUsage = GL_STATIC_DRAW_ARB;
|
glUsage = GL_STATIC_DRAW;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VAO_USAGE_DYNAMIC:
|
case VAO_USAGE_DYNAMIC:
|
||||||
glUsage = GL_DYNAMIC_DRAW_ARB;
|
glUsage = GL_DYNAMIC_DRAW;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Com_Error(ERR_FATAL, "bad vaoUsage_t given: %i", usage);
|
ri.Error(ERR_FATAL, "bad vaoUsage_t given: %i", usage);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,25 +140,25 @@ vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *ind
|
||||||
|
|
||||||
if (glRefConfig.vertexArrayObject)
|
if (glRefConfig.vertexArrayObject)
|
||||||
{
|
{
|
||||||
qglGenVertexArraysARB(1, &vao->vao);
|
qglGenVertexArrays(1, &vao->vao);
|
||||||
qglBindVertexArrayARB(vao->vao);
|
qglBindVertexArray(vao->vao);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vao->vertexesSize = vertexesSize;
|
vao->vertexesSize = vertexesSize;
|
||||||
|
|
||||||
qglGenBuffersARB(1, &vao->vertexesVBO);
|
qglGenBuffers(1, &vao->vertexesVBO);
|
||||||
|
|
||||||
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO);
|
qglBindBuffer(GL_ARRAY_BUFFER, vao->vertexesVBO);
|
||||||
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexesSize, vertexes, glUsage);
|
qglBufferData(GL_ARRAY_BUFFER, vertexesSize, vertexes, glUsage);
|
||||||
|
|
||||||
|
|
||||||
vao->indexesSize = indexesSize;
|
vao->indexesSize = indexesSize;
|
||||||
|
|
||||||
qglGenBuffersARB(1, &vao->indexesIBO);
|
qglGenBuffers(1, &vao->indexesIBO);
|
||||||
|
|
||||||
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO);
|
qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO);
|
||||||
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage);
|
qglBufferData(GL_ELEMENT_ARRAY_BUFFER, indexesSize, indexes, glUsage);
|
||||||
|
|
||||||
|
|
||||||
glState.currentVao = vao;
|
glState.currentVao = vao;
|
||||||
|
@ -304,7 +182,7 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
|
||||||
int dataSize;
|
int dataSize;
|
||||||
int dataOfs;
|
int dataOfs;
|
||||||
|
|
||||||
int glUsage = GL_STATIC_DRAW_ARB;
|
int glUsage = GL_STATIC_DRAW;
|
||||||
|
|
||||||
if(!numVertexes || !numIndexes)
|
if(!numVertexes || !numIndexes)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -330,9 +208,7 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
|
||||||
// since these vertex attributes are never altered, interleave them
|
// since these vertex attributes are never altered, interleave them
|
||||||
vao->attribs[ATTR_INDEX_POSITION ].enabled = 1;
|
vao->attribs[ATTR_INDEX_POSITION ].enabled = 1;
|
||||||
vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
|
vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
|
vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
|
||||||
#endif
|
|
||||||
vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
|
vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
|
||||||
vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1;
|
vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1;
|
||||||
vao->attribs[ATTR_INDEX_COLOR ].enabled = 1;
|
vao->attribs[ATTR_INDEX_COLOR ].enabled = 1;
|
||||||
|
@ -347,30 +223,28 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
|
||||||
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
|
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
|
||||||
|
|
||||||
vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
|
vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
|
||||||
vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
|
vao->attribs[ATTR_INDEX_NORMAL ].type = GL_SHORT;
|
||||||
vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
|
vao->attribs[ATTR_INDEX_TANGENT ].type = GL_SHORT;
|
||||||
vao->attribs[ATTR_INDEX_TEXCOORD ].type = glRefConfig.packedTexcoordDataType;
|
vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
|
||||||
vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = glRefConfig.packedTexcoordDataType;
|
vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT;
|
||||||
vao->attribs[ATTR_INDEX_COLOR ].type = glRefConfig.packedColorDataType;
|
vao->attribs[ATTR_INDEX_COLOR ].type = GL_UNSIGNED_SHORT;
|
||||||
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;
|
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = GL_SHORT;
|
||||||
|
|
||||||
vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
|
vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
|
||||||
vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
|
vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
|
||||||
vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
|
vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
|
||||||
vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
|
vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
|
||||||
vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE;
|
vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE;
|
||||||
vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE;
|
vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_TRUE;
|
||||||
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
|
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
|
||||||
|
|
||||||
vao->attribs[ATTR_INDEX_POSITION ].offset = 0; dataSize = sizeof(verts[0].xyz);
|
vao->attribs[ATTR_INDEX_POSITION ].offset = 0; dataSize = sizeof(verts[0].xyz);
|
||||||
vao->attribs[ATTR_INDEX_NORMAL ].offset = dataSize; dataSize += sizeof(uint32_t);
|
vao->attribs[ATTR_INDEX_NORMAL ].offset = dataSize; dataSize += sizeof(verts[0].normal);
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
vao->attribs[ATTR_INDEX_TANGENT ].offset = dataSize; dataSize += sizeof(verts[0].tangent);
|
||||||
vao->attribs[ATTR_INDEX_TANGENT ].offset = dataSize; dataSize += sizeof(uint32_t);
|
vao->attribs[ATTR_INDEX_TEXCOORD ].offset = dataSize; dataSize += sizeof(verts[0].st);
|
||||||
#endif
|
vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = dataSize; dataSize += sizeof(verts[0].lightmap);
|
||||||
vao->attribs[ATTR_INDEX_TEXCOORD ].offset = dataSize; dataSize += glRefConfig.packedTexcoordDataSize;
|
vao->attribs[ATTR_INDEX_COLOR ].offset = dataSize; dataSize += sizeof(verts[0].color);
|
||||||
vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = dataSize; dataSize += glRefConfig.packedTexcoordDataSize;
|
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(verts[0].lightdir);
|
||||||
vao->attribs[ATTR_INDEX_COLOR ].offset = dataSize; dataSize += glRefConfig.packedColorDataSize;
|
|
||||||
vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(uint32_t);
|
|
||||||
|
|
||||||
vao->attribs[ATTR_INDEX_POSITION ].stride = dataSize;
|
vao->attribs[ATTR_INDEX_POSITION ].stride = dataSize;
|
||||||
vao->attribs[ATTR_INDEX_NORMAL ].stride = dataSize;
|
vao->attribs[ATTR_INDEX_NORMAL ].stride = dataSize;
|
||||||
|
@ -383,8 +257,8 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
|
||||||
|
|
||||||
if (glRefConfig.vertexArrayObject)
|
if (glRefConfig.vertexArrayObject)
|
||||||
{
|
{
|
||||||
qglGenVertexArraysARB(1, &vao->vao);
|
qglGenVertexArrays(1, &vao->vao);
|
||||||
qglBindVertexArrayARB(vao->vao);
|
qglBindVertexArray(vao->vao);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -400,41 +274,45 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
|
||||||
dataOfs += sizeof(verts[i].xyz);
|
dataOfs += sizeof(verts[i].xyz);
|
||||||
|
|
||||||
// normal
|
// normal
|
||||||
dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].normal);
|
memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal));
|
||||||
|
dataOfs += sizeof(verts[i].normal);
|
||||||
|
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
// tangent
|
// tangent
|
||||||
dataOfs += R_VaoPackTangent(data + dataOfs, verts[i].tangent);
|
memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent));
|
||||||
#endif
|
dataOfs += sizeof(verts[i].tangent);
|
||||||
|
|
||||||
// texcoords
|
// texcoords
|
||||||
dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].st);
|
memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st));
|
||||||
|
dataOfs += sizeof(verts[i].st);
|
||||||
|
|
||||||
// lightmap texcoords
|
// lightmap texcoords
|
||||||
dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].lightmap);
|
memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap));
|
||||||
|
dataOfs += sizeof(verts[i].lightmap);
|
||||||
|
|
||||||
// colors
|
// colors
|
||||||
dataOfs += R_VaoPackColors(data + dataOfs, verts[i].vertexColors);
|
memcpy(data + dataOfs, &verts[i].color, sizeof(verts[i].color));
|
||||||
|
dataOfs += sizeof(verts[i].color);
|
||||||
|
|
||||||
// light directions
|
// light directions
|
||||||
dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].lightdir);
|
memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir));
|
||||||
|
dataOfs += sizeof(verts[i].lightdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
vao->vertexesSize = dataSize;
|
vao->vertexesSize = dataSize;
|
||||||
|
|
||||||
qglGenBuffersARB(1, &vao->vertexesVBO);
|
qglGenBuffers(1, &vao->vertexesVBO);
|
||||||
|
|
||||||
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO);
|
qglBindBuffer(GL_ARRAY_BUFFER, vao->vertexesVBO);
|
||||||
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vao->vertexesSize, data, glUsage);
|
qglBufferData(GL_ARRAY_BUFFER, vao->vertexesSize, data, glUsage);
|
||||||
|
|
||||||
|
|
||||||
// create IBO
|
// create IBO
|
||||||
vao->indexesSize = numIndexes * sizeof(glIndex_t);
|
vao->indexesSize = numIndexes * sizeof(glIndex_t);
|
||||||
|
|
||||||
qglGenBuffersARB(1, &vao->indexesIBO);
|
qglGenBuffers(1, &vao->indexesIBO);
|
||||||
|
|
||||||
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO);
|
qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO);
|
||||||
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesSize, indexes, glUsage);
|
qglBufferData(GL_ELEMENT_ARRAY_BUFFER, vao->indexesSize, indexes, glUsage);
|
||||||
|
|
||||||
|
|
||||||
Vao_SetVertexPointers(vao);
|
Vao_SetVertexPointers(vao);
|
||||||
|
@ -480,20 +358,20 @@ void R_BindVao(vao_t * vao)
|
||||||
|
|
||||||
if (glRefConfig.vertexArrayObject)
|
if (glRefConfig.vertexArrayObject)
|
||||||
{
|
{
|
||||||
qglBindVertexArrayARB(vao->vao);
|
qglBindVertexArray(vao->vao);
|
||||||
|
|
||||||
// why you no save GL_ELEMENT_ARRAY_BUFFER binding, Intel?
|
// Intel Graphics doesn't save GL_ELEMENT_ARRAY_BUFFER binding with VAO binding.
|
||||||
if (1)
|
if (glRefConfig.intelGraphics || vao == tess.vao)
|
||||||
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO);
|
qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO);
|
||||||
|
|
||||||
// tess VAO always has buffers bound
|
// tess VAO always has buffers bound
|
||||||
if (vao == tess.vao)
|
if (vao == tess.vao)
|
||||||
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO);
|
qglBindBuffer(GL_ARRAY_BUFFER, vao->vertexesVBO);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO);
|
qglBindBuffer(GL_ARRAY_BUFFER, vao->vertexesVBO);
|
||||||
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO);
|
qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO);
|
||||||
|
|
||||||
// tess VAO doesn't have vertex pointers set until data is uploaded
|
// tess VAO doesn't have vertex pointers set until data is uploaded
|
||||||
if (vao != tess.vao)
|
if (vao != tess.vao)
|
||||||
|
@ -515,15 +393,15 @@ void R_BindNullVao(void)
|
||||||
{
|
{
|
||||||
if (glRefConfig.vertexArrayObject)
|
if (glRefConfig.vertexArrayObject)
|
||||||
{
|
{
|
||||||
qglBindVertexArrayARB(0);
|
qglBindVertexArray(0);
|
||||||
|
|
||||||
// why you no save GL_ELEMENT_ARRAY_BUFFER binding, Intel?
|
// why you no save GL_ELEMENT_ARRAY_BUFFER binding, Intel?
|
||||||
if (1) qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
if (1) qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
qglBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
glState.currentVao = NULL;
|
glState.currentVao = NULL;
|
||||||
}
|
}
|
||||||
|
@ -548,11 +426,10 @@ void R_InitVaos(void)
|
||||||
|
|
||||||
vertexesSize = sizeof(tess.xyz[0]);
|
vertexesSize = sizeof(tess.xyz[0]);
|
||||||
vertexesSize += sizeof(tess.normal[0]);
|
vertexesSize += sizeof(tess.normal[0]);
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
vertexesSize += sizeof(tess.tangent[0]);
|
vertexesSize += sizeof(tess.tangent[0]);
|
||||||
#endif
|
vertexesSize += sizeof(tess.color[0]);
|
||||||
vertexesSize += sizeof(tess.vertexColors[0]);
|
vertexesSize += sizeof(tess.texCoords[0]);
|
||||||
vertexesSize += sizeof(tess.texCoords[0][0]) * 2;
|
vertexesSize += sizeof(tess.lightCoords[0]);
|
||||||
vertexesSize += sizeof(tess.lightdir[0]);
|
vertexesSize += sizeof(tess.lightdir[0]);
|
||||||
vertexesSize *= SHADER_MAX_VERTEXES;
|
vertexesSize *= SHADER_MAX_VERTEXES;
|
||||||
|
|
||||||
|
@ -564,9 +441,7 @@ void R_InitVaos(void)
|
||||||
|
|
||||||
tess.vao->attribs[ATTR_INDEX_POSITION ].enabled = 1;
|
tess.vao->attribs[ATTR_INDEX_POSITION ].enabled = 1;
|
||||||
tess.vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
|
tess.vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1;
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
tess.vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
|
tess.vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1;
|
||||||
#endif
|
|
||||||
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
|
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1;
|
||||||
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1;
|
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1;
|
||||||
tess.vao->attribs[ATTR_INDEX_COLOR ].enabled = 1;
|
tess.vao->attribs[ATTR_INDEX_COLOR ].enabled = 1;
|
||||||
|
@ -581,57 +456,51 @@ void R_InitVaos(void)
|
||||||
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
|
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
|
||||||
|
|
||||||
tess.vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
|
tess.vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT;
|
||||||
tess.vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType;
|
tess.vao->attribs[ATTR_INDEX_NORMAL ].type = GL_SHORT;
|
||||||
tess.vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType;
|
tess.vao->attribs[ATTR_INDEX_TANGENT ].type = GL_SHORT;
|
||||||
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
|
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT;
|
||||||
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT;
|
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT;
|
||||||
tess.vao->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT;
|
tess.vao->attribs[ATTR_INDEX_COLOR ].type = GL_UNSIGNED_SHORT;
|
||||||
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;
|
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = GL_SHORT;
|
||||||
|
|
||||||
tess.vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
|
tess.vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE;
|
||||||
tess.vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
|
tess.vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE;
|
||||||
tess.vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
|
tess.vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE;
|
||||||
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
|
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE;
|
||||||
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE;
|
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE;
|
||||||
tess.vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE;
|
tess.vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_TRUE;
|
||||||
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
|
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
|
||||||
|
|
||||||
tess.vao->attribs[ATTR_INDEX_POSITION ].offset = offset; offset += sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES;
|
tess.vao->attribs[ATTR_INDEX_POSITION ].offset = offset; offset += sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES;
|
||||||
tess.vao->attribs[ATTR_INDEX_NORMAL ].offset = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES;
|
tess.vao->attribs[ATTR_INDEX_NORMAL ].offset = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES;
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
tess.vao->attribs[ATTR_INDEX_TANGENT ].offset = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES;
|
||||||
tess.vao->attribs[ATTR_INDEX_TANGENT ].offset = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES;
|
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].offset = offset; offset += sizeof(tess.texCoords[0]) * SHADER_MAX_VERTEXES;
|
||||||
#endif
|
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = offset; offset += sizeof(tess.lightCoords[0]) * SHADER_MAX_VERTEXES;
|
||||||
// these next two are actually interleaved
|
tess.vao->attribs[ATTR_INDEX_COLOR ].offset = offset; offset += sizeof(tess.color[0]) * SHADER_MAX_VERTEXES;
|
||||||
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].offset = offset;
|
|
||||||
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = offset + sizeof(tess.texCoords[0][0]);
|
|
||||||
offset += sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES;
|
|
||||||
|
|
||||||
tess.vao->attribs[ATTR_INDEX_COLOR ].offset = offset; offset += sizeof(tess.vertexColors[0]) * SHADER_MAX_VERTEXES;
|
|
||||||
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = offset;
|
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = offset;
|
||||||
|
|
||||||
tess.vao->attribs[ATTR_INDEX_POSITION ].stride = sizeof(tess.xyz[0]);
|
tess.vao->attribs[ATTR_INDEX_POSITION ].stride = sizeof(tess.xyz[0]);
|
||||||
tess.vao->attribs[ATTR_INDEX_NORMAL ].stride = sizeof(tess.normal[0]);
|
tess.vao->attribs[ATTR_INDEX_NORMAL ].stride = sizeof(tess.normal[0]);
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
tess.vao->attribs[ATTR_INDEX_TANGENT ].stride = sizeof(tess.tangent[0]);
|
tess.vao->attribs[ATTR_INDEX_TANGENT ].stride = sizeof(tess.tangent[0]);
|
||||||
#endif
|
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].stride = sizeof(tess.texCoords[0]);
|
||||||
tess.vao->attribs[ATTR_INDEX_COLOR ].stride = sizeof(tess.vertexColors[0]);
|
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].stride = sizeof(tess.lightCoords[0]);
|
||||||
tess.vao->attribs[ATTR_INDEX_TEXCOORD ].stride = sizeof(tess.texCoords[0][0]) * 2;
|
tess.vao->attribs[ATTR_INDEX_COLOR ].stride = sizeof(tess.color[0]);
|
||||||
tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].stride = sizeof(tess.texCoords[0][0]) * 2;
|
|
||||||
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = sizeof(tess.lightdir[0]);
|
tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = sizeof(tess.lightdir[0]);
|
||||||
|
|
||||||
tess.attribPointers[ATTR_INDEX_POSITION] = tess.xyz;
|
tess.attribPointers[ATTR_INDEX_POSITION] = tess.xyz;
|
||||||
tess.attribPointers[ATTR_INDEX_TEXCOORD] = tess.texCoords;
|
|
||||||
tess.attribPointers[ATTR_INDEX_NORMAL] = tess.normal;
|
tess.attribPointers[ATTR_INDEX_NORMAL] = tess.normal;
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
|
||||||
tess.attribPointers[ATTR_INDEX_TANGENT] = tess.tangent;
|
tess.attribPointers[ATTR_INDEX_TANGENT] = tess.tangent;
|
||||||
#endif
|
tess.attribPointers[ATTR_INDEX_TEXCOORD] = tess.texCoords;
|
||||||
tess.attribPointers[ATTR_INDEX_COLOR] = tess.vertexColors;
|
tess.attribPointers[ATTR_INDEX_LIGHTCOORD] = tess.lightCoords;
|
||||||
|
tess.attribPointers[ATTR_INDEX_COLOR] = tess.color;
|
||||||
tess.attribPointers[ATTR_INDEX_LIGHTDIRECTION] = tess.lightdir;
|
tess.attribPointers[ATTR_INDEX_LIGHTDIRECTION] = tess.lightdir;
|
||||||
|
|
||||||
Vao_SetVertexPointers(tess.vao);
|
Vao_SetVertexPointers(tess.vao);
|
||||||
|
|
||||||
R_BindNullVao();
|
R_BindNullVao();
|
||||||
|
|
||||||
|
VaoCache_Init();
|
||||||
|
|
||||||
GL_CheckErrors();
|
GL_CheckErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,16 +523,16 @@ void R_ShutdownVaos(void)
|
||||||
vao = tr.vaos[i];
|
vao = tr.vaos[i];
|
||||||
|
|
||||||
if(vao->vao)
|
if(vao->vao)
|
||||||
qglDeleteVertexArraysARB(1, &vao->vao);
|
qglDeleteVertexArrays(1, &vao->vao);
|
||||||
|
|
||||||
if(vao->vertexesVBO)
|
if(vao->vertexesVBO)
|
||||||
{
|
{
|
||||||
qglDeleteBuffersARB(1, &vao->vertexesVBO);
|
qglDeleteBuffers(1, &vao->vertexesVBO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(vao->indexesIBO)
|
if(vao->indexesIBO)
|
||||||
{
|
{
|
||||||
qglDeleteBuffersARB(1, &vao->indexesIBO);
|
qglDeleteBuffers(1, &vao->indexesIBO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,7 +606,7 @@ void RB_UpdateTessVao(unsigned int attribBits)
|
||||||
R_BindVao(tess.vao);
|
R_BindVao(tess.vao);
|
||||||
|
|
||||||
// orphan old vertex buffer so we don't stall on it
|
// orphan old vertex buffer so we don't stall on it
|
||||||
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, tess.vao->vertexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
|
qglBufferData(GL_ARRAY_BUFFER, tess.vao->vertexesSize, NULL, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
// if nothing to set, set everything
|
// if nothing to set, set everything
|
||||||
if(!(attribBits & ATTR_BITS))
|
if(!(attribBits & ATTR_BITS))
|
||||||
|
@ -745,14 +614,6 @@ void RB_UpdateTessVao(unsigned int attribBits)
|
||||||
|
|
||||||
attribUpload = attribBits;
|
attribUpload = attribBits;
|
||||||
|
|
||||||
if((attribUpload & ATTR_TEXCOORD) || (attribUpload & ATTR_LIGHTCOORD))
|
|
||||||
{
|
|
||||||
// these are interleaved, so we update both if either need it
|
|
||||||
// this translates to updating ATTR_TEXCOORD twice as large as it needs
|
|
||||||
attribUpload &= ~ATTR_LIGHTCOORD;
|
|
||||||
attribUpload |= ATTR_TEXCOORD;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++)
|
for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++)
|
||||||
{
|
{
|
||||||
uint32_t attribBit = 1 << attribIndex;
|
uint32_t attribBit = 1 << attribIndex;
|
||||||
|
@ -761,17 +622,17 @@ void RB_UpdateTessVao(unsigned int attribBits)
|
||||||
if (attribUpload & attribBit)
|
if (attribUpload & attribBit)
|
||||||
{
|
{
|
||||||
// note: tess has a VBO where stride == size
|
// note: tess has a VBO where stride == size
|
||||||
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, vAtb->offset, tess.numVertexes * vAtb->stride, tess.attribPointers[attribIndex]);
|
qglBufferSubData(GL_ARRAY_BUFFER, vAtb->offset, tess.numVertexes * vAtb->stride, tess.attribPointers[attribIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attribBits & attribBit)
|
if (attribBits & attribBit)
|
||||||
{
|
{
|
||||||
if (!glRefConfig.vertexArrayObject)
|
if (!glRefConfig.vertexArrayObject)
|
||||||
qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset));
|
qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset));
|
||||||
|
|
||||||
if (!(glState.vertexAttribsEnabled & attribBit))
|
if (!(glState.vertexAttribsEnabled & attribBit))
|
||||||
{
|
{
|
||||||
qglEnableVertexAttribArrayARB(attribIndex);
|
qglEnableVertexAttribArray(attribIndex);
|
||||||
glState.vertexAttribsEnabled |= attribBit;
|
glState.vertexAttribsEnabled |= attribBit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -779,15 +640,329 @@ void RB_UpdateTessVao(unsigned int attribBits)
|
||||||
{
|
{
|
||||||
if ((glState.vertexAttribsEnabled & attribBit))
|
if ((glState.vertexAttribsEnabled & attribBit))
|
||||||
{
|
{
|
||||||
qglDisableVertexAttribArrayARB(attribIndex);
|
qglDisableVertexAttribArray(attribIndex);
|
||||||
glState.vertexAttribsEnabled &= ~attribBit;
|
glState.vertexAttribsEnabled &= ~attribBit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// orphan old index buffer so we don't stall on it
|
// orphan old index buffer so we don't stall on it
|
||||||
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.vao->indexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
|
qglBufferData(GL_ELEMENT_ARRAY_BUFFER, tess.vao->indexesSize, NULL, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes);
|
qglBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: This sets a limit of 65536 verts/262144 indexes per static surface
|
||||||
|
// This is higher than the old vq3 limits but is worth noting
|
||||||
|
#define VAOCACHE_QUEUE_MAX_SURFACES (1 << 10)
|
||||||
|
#define VAOCACHE_QUEUE_MAX_VERTEXES (1 << 16)
|
||||||
|
#define VAOCACHE_QUEUE_MAX_INDEXES (VAOCACHE_QUEUE_MAX_VERTEXES * 4)
|
||||||
|
|
||||||
|
typedef struct queuedSurface_s
|
||||||
|
{
|
||||||
|
srfVert_t *vertexes;
|
||||||
|
int numVerts;
|
||||||
|
glIndex_t *indexes;
|
||||||
|
int numIndexes;
|
||||||
|
}
|
||||||
|
queuedSurface_t;
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
queuedSurface_t surfaces[VAOCACHE_QUEUE_MAX_SURFACES];
|
||||||
|
int numSurfaces;
|
||||||
|
|
||||||
|
srfVert_t vertexes[VAOCACHE_QUEUE_MAX_VERTEXES];
|
||||||
|
int vertexCommitSize;
|
||||||
|
|
||||||
|
glIndex_t indexes[VAOCACHE_QUEUE_MAX_INDEXES];
|
||||||
|
int indexCommitSize;
|
||||||
|
}
|
||||||
|
vcq;
|
||||||
|
|
||||||
|
#define VAOCACHE_MAX_SURFACES (1 << 16)
|
||||||
|
#define VAOCACHE_MAX_BATCHES (1 << 10)
|
||||||
|
|
||||||
|
// srfVert_t is 60 bytes
|
||||||
|
// assuming each vert is referenced 4 times, need 16 bytes (4 glIndex_t) per vert
|
||||||
|
// -> need about 4/15ths the space for indexes as vertexes
|
||||||
|
#if GL_INDEX_TYPE == GL_UNSIGNED_SHORT
|
||||||
|
#define VAOCACHE_VERTEX_BUFFER_SIZE (sizeof(srfVert_t) * USHRT_MAX)
|
||||||
|
#define VAOCACHE_INDEX_BUFFER_SIZE (sizeof(glIndex_t) * USHRT_MAX * 4)
|
||||||
|
#else // GL_UNSIGNED_INT
|
||||||
|
#define VAOCACHE_VERTEX_BUFFER_SIZE (16 * 1024 * 1024)
|
||||||
|
#define VAOCACHE_INDEX_BUFFER_SIZE (5 * 1024 * 1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct buffered_s
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
int size;
|
||||||
|
int bufferOffset;
|
||||||
|
}
|
||||||
|
buffered_t;
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
vao_t *vao;
|
||||||
|
buffered_t surfaceIndexSets[VAOCACHE_MAX_SURFACES];
|
||||||
|
int numSurfaces;
|
||||||
|
|
||||||
|
int batchLengths[VAOCACHE_MAX_BATCHES];
|
||||||
|
int numBatches;
|
||||||
|
|
||||||
|
int vertexOffset;
|
||||||
|
int indexOffset;
|
||||||
|
}
|
||||||
|
vc;
|
||||||
|
|
||||||
|
void VaoCache_Commit(void)
|
||||||
|
{
|
||||||
|
buffered_t *indexSet;
|
||||||
|
int *batchLength;
|
||||||
|
queuedSurface_t *surf, *end = vcq.surfaces + vcq.numSurfaces;
|
||||||
|
|
||||||
|
R_BindVao(vc.vao);
|
||||||
|
|
||||||
|
// Search for a matching batch
|
||||||
|
// FIXME: Use faster search
|
||||||
|
indexSet = vc.surfaceIndexSets;
|
||||||
|
batchLength = vc.batchLengths;
|
||||||
|
for (; batchLength < vc.batchLengths + vc.numBatches; batchLength++)
|
||||||
|
{
|
||||||
|
if (*batchLength == vcq.numSurfaces)
|
||||||
|
{
|
||||||
|
buffered_t *indexSet2 = indexSet;
|
||||||
|
for (surf = vcq.surfaces; surf < end; surf++, indexSet2++)
|
||||||
|
{
|
||||||
|
if (surf->indexes != indexSet2->data || (surf->numIndexes * sizeof(glIndex_t)) != indexSet2->size)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surf == end)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
indexSet += *batchLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If found, use it
|
||||||
|
if (indexSet < vc.surfaceIndexSets + vc.numSurfaces)
|
||||||
|
{
|
||||||
|
tess.firstIndex = indexSet->bufferOffset / sizeof(glIndex_t);
|
||||||
|
//ri.Printf(PRINT_ALL, "firstIndex %d numIndexes %d as %d\n", tess.firstIndex, tess.numIndexes, (int)(batchLength - vc.batchLengths));
|
||||||
|
//ri.Printf(PRINT_ALL, "vc.numSurfaces %d vc.numBatches %d\n", vc.numSurfaces, vc.numBatches);
|
||||||
|
}
|
||||||
|
// If not, rebuffer the batch
|
||||||
|
// FIXME: keep track of the vertexes so we don't have to reupload them every time
|
||||||
|
else
|
||||||
|
{
|
||||||
|
srfVert_t *dstVertex = vcq.vertexes;
|
||||||
|
glIndex_t *dstIndex = vcq.indexes;
|
||||||
|
|
||||||
|
batchLength = vc.batchLengths + vc.numBatches;
|
||||||
|
*batchLength = vcq.numSurfaces;
|
||||||
|
vc.numBatches++;
|
||||||
|
|
||||||
|
tess.firstIndex = vc.indexOffset / sizeof(glIndex_t);
|
||||||
|
vcq.vertexCommitSize = 0;
|
||||||
|
vcq.indexCommitSize = 0;
|
||||||
|
for (surf = vcq.surfaces; surf < end; surf++)
|
||||||
|
{
|
||||||
|
glIndex_t *srcIndex = surf->indexes;
|
||||||
|
int vertexesSize = surf->numVerts * sizeof(srfVert_t);
|
||||||
|
int indexesSize = surf->numIndexes * sizeof(glIndex_t);
|
||||||
|
int i, indexOffset = (vc.vertexOffset + vcq.vertexCommitSize) / sizeof(srfVert_t);
|
||||||
|
|
||||||
|
Com_Memcpy(dstVertex, surf->vertexes, vertexesSize);
|
||||||
|
dstVertex += surf->numVerts;
|
||||||
|
|
||||||
|
vcq.vertexCommitSize += vertexesSize;
|
||||||
|
|
||||||
|
indexSet = vc.surfaceIndexSets + vc.numSurfaces;
|
||||||
|
indexSet->data = surf->indexes;
|
||||||
|
indexSet->size = indexesSize;
|
||||||
|
indexSet->bufferOffset = vc.indexOffset + vcq.indexCommitSize;
|
||||||
|
vc.numSurfaces++;
|
||||||
|
|
||||||
|
for (i = 0; i < surf->numIndexes; i++)
|
||||||
|
*dstIndex++ = *srcIndex++ + indexOffset;
|
||||||
|
|
||||||
|
vcq.indexCommitSize += indexesSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ri.Printf(PRINT_ALL, "committing %d to %d, %d to %d as %d\n", vcq.vertexCommitSize, vc.vertexOffset, vcq.indexCommitSize, vc.indexOffset, (int)(batchLength - vc.batchLengths));
|
||||||
|
|
||||||
|
if (vcq.vertexCommitSize)
|
||||||
|
{
|
||||||
|
qglBindBuffer(GL_ARRAY_BUFFER, vc.vao->vertexesVBO);
|
||||||
|
qglBufferSubData(GL_ARRAY_BUFFER, vc.vertexOffset, vcq.vertexCommitSize, vcq.vertexes);
|
||||||
|
vc.vertexOffset += vcq.vertexCommitSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vcq.indexCommitSize)
|
||||||
|
{
|
||||||
|
qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vc.vao->indexesIBO);
|
||||||
|
qglBufferSubData(GL_ELEMENT_ARRAY_BUFFER, vc.indexOffset, vcq.indexCommitSize, vcq.indexes);
|
||||||
|
vc.indexOffset += vcq.indexCommitSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VaoCache_Init(void)
|
||||||
|
{
|
||||||
|
vc.vao = R_CreateVao("VaoCache", NULL, VAOCACHE_VERTEX_BUFFER_SIZE, NULL, VAOCACHE_INDEX_BUFFER_SIZE, VAO_USAGE_DYNAMIC);
|
||||||
|
|
||||||
|
vc.vao->attribs[ATTR_INDEX_POSITION].enabled = 1;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TEXCOORD].enabled = 1;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTCOORD].enabled = 1;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_NORMAL].enabled = 1;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TANGENT].enabled = 1;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_COLOR].enabled = 1;
|
||||||
|
|
||||||
|
vc.vao->attribs[ATTR_INDEX_POSITION].count = 3;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TEXCOORD].count = 2;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTCOORD].count = 2;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_NORMAL].count = 4;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TANGENT].count = 4;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_COLOR].count = 4;
|
||||||
|
|
||||||
|
vc.vao->attribs[ATTR_INDEX_POSITION].type = GL_FLOAT;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TEXCOORD].type = GL_FLOAT;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTCOORD].type = GL_FLOAT;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_NORMAL].type = GL_SHORT;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TANGENT].type = GL_SHORT;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = GL_SHORT;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_COLOR].type = GL_UNSIGNED_SHORT;
|
||||||
|
|
||||||
|
vc.vao->attribs[ATTR_INDEX_POSITION].normalized = GL_FALSE;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TEXCOORD].normalized = GL_FALSE;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTCOORD].normalized = GL_FALSE;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_NORMAL].normalized = GL_TRUE;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TANGENT].normalized = GL_TRUE;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
|
||||||
|
vc.vao->attribs[ATTR_INDEX_COLOR].normalized = GL_TRUE;
|
||||||
|
|
||||||
|
vc.vao->attribs[ATTR_INDEX_POSITION].offset = offsetof(srfVert_t, xyz);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TEXCOORD].offset = offsetof(srfVert_t, st);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTCOORD].offset = offsetof(srfVert_t, lightmap);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_NORMAL].offset = offsetof(srfVert_t, normal);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TANGENT].offset = offsetof(srfVert_t, tangent);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = offsetof(srfVert_t, lightdir);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_COLOR].offset = offsetof(srfVert_t, color);
|
||||||
|
|
||||||
|
vc.vao->attribs[ATTR_INDEX_POSITION].stride = sizeof(srfVert_t);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TEXCOORD].stride = sizeof(srfVert_t);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTCOORD].stride = sizeof(srfVert_t);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_NORMAL].stride = sizeof(srfVert_t);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_TANGENT].stride = sizeof(srfVert_t);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = sizeof(srfVert_t);
|
||||||
|
vc.vao->attribs[ATTR_INDEX_COLOR].stride = sizeof(srfVert_t);
|
||||||
|
|
||||||
|
Vao_SetVertexPointers(vc.vao);
|
||||||
|
|
||||||
|
vc.numSurfaces = 0;
|
||||||
|
vc.numBatches = 0;
|
||||||
|
vc.vertexOffset = 0;
|
||||||
|
vc.indexOffset = 0;
|
||||||
|
vcq.vertexCommitSize = 0;
|
||||||
|
vcq.indexCommitSize = 0;
|
||||||
|
vcq.numSurfaces = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VaoCache_BindVao(void)
|
||||||
|
{
|
||||||
|
R_BindVao(vc.vao);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VaoCache_CheckAdd(qboolean *endSurface, qboolean *recycleVertexBuffer, qboolean *recycleIndexBuffer, int numVerts, int numIndexes)
|
||||||
|
{
|
||||||
|
int vertexesSize = sizeof(srfVert_t) * numVerts;
|
||||||
|
int indexesSize = sizeof(glIndex_t) * numIndexes;
|
||||||
|
|
||||||
|
if (vc.vao->vertexesSize < vc.vertexOffset + vcq.vertexCommitSize + vertexesSize)
|
||||||
|
{
|
||||||
|
//ri.Printf(PRINT_ALL, "out of space in vertex cache: %d < %d + %d + %d\n", vc.vao->vertexesSize, vc.vertexOffset, vcq.vertexCommitSize, vertexesSize);
|
||||||
|
*recycleVertexBuffer = qtrue;
|
||||||
|
*recycleIndexBuffer = qtrue;
|
||||||
|
*endSurface = qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vc.vao->indexesSize < vc.indexOffset + vcq.indexCommitSize + indexesSize)
|
||||||
|
{
|
||||||
|
//ri.Printf(PRINT_ALL, "out of space in index cache\n");
|
||||||
|
*recycleIndexBuffer = qtrue;
|
||||||
|
*endSurface = qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vc.numSurfaces + vcq.numSurfaces >= VAOCACHE_MAX_SURFACES)
|
||||||
|
{
|
||||||
|
//ri.Printf(PRINT_ALL, "out of surfaces in index cache\n");
|
||||||
|
*recycleIndexBuffer = qtrue;
|
||||||
|
*endSurface = qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vc.numBatches >= VAOCACHE_MAX_BATCHES)
|
||||||
|
{
|
||||||
|
//ri.Printf(PRINT_ALL, "out of batches in index cache\n");
|
||||||
|
*recycleIndexBuffer = qtrue;
|
||||||
|
*endSurface = qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vcq.numSurfaces >= VAOCACHE_QUEUE_MAX_SURFACES)
|
||||||
|
{
|
||||||
|
//ri.Printf(PRINT_ALL, "out of queued surfaces\n");
|
||||||
|
*endSurface = qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VAOCACHE_QUEUE_MAX_VERTEXES * sizeof(srfVert_t) < vcq.vertexCommitSize + vertexesSize)
|
||||||
|
{
|
||||||
|
//ri.Printf(PRINT_ALL, "out of queued vertexes\n");
|
||||||
|
*endSurface = qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VAOCACHE_QUEUE_MAX_INDEXES * sizeof(glIndex_t) < vcq.indexCommitSize + indexesSize)
|
||||||
|
{
|
||||||
|
//ri.Printf(PRINT_ALL, "out of queued indexes\n");
|
||||||
|
*endSurface = qtrue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VaoCache_RecycleVertexBuffer(void)
|
||||||
|
{
|
||||||
|
qglBindBuffer(GL_ARRAY_BUFFER, vc.vao->vertexesVBO);
|
||||||
|
qglBufferData(GL_ARRAY_BUFFER, vc.vao->vertexesSize, NULL, GL_DYNAMIC_DRAW);
|
||||||
|
vc.vertexOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VaoCache_RecycleIndexBuffer(void)
|
||||||
|
{
|
||||||
|
qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vc.vao->indexesIBO);
|
||||||
|
qglBufferData(GL_ELEMENT_ARRAY_BUFFER, vc.vao->indexesSize, NULL, GL_DYNAMIC_DRAW);
|
||||||
|
vc.indexOffset = 0;
|
||||||
|
vc.numSurfaces = 0;
|
||||||
|
vc.numBatches = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VaoCache_InitQueue(void)
|
||||||
|
{
|
||||||
|
vcq.vertexCommitSize = 0;
|
||||||
|
vcq.indexCommitSize = 0;
|
||||||
|
vcq.numSurfaces = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VaoCache_AddSurface(srfVert_t *verts, int numVerts, glIndex_t *indexes, int numIndexes)
|
||||||
|
{
|
||||||
|
queuedSurface_t *queueEntry = vcq.surfaces + vcq.numSurfaces;
|
||||||
|
queueEntry->vertexes = verts;
|
||||||
|
queueEntry->numVerts = numVerts;
|
||||||
|
queueEntry->indexes = indexes;
|
||||||
|
queueEntry->numIndexes = numIndexes;
|
||||||
|
vcq.numSurfaces++;
|
||||||
|
|
||||||
|
vcq.vertexCommitSize += sizeof(srfVert_t) * numVerts;
|
||||||
|
vcq.indexCommitSize += sizeof(glIndex_t) * numIndexes;
|
||||||
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ static qboolean R_CullSurface( msurface_t *surf ) {
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( *surf->data == SF_GRID && r_nocurves->integer ) {
|
if ( r_nocurves->integer && *surf->data == SF_GRID ) {
|
||||||
return qtrue;
|
return qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +213,6 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
|
||||||
case SF_FACE:
|
case SF_FACE:
|
||||||
case SF_GRID:
|
case SF_GRID:
|
||||||
case SF_TRIANGLES:
|
case SF_TRIANGLES:
|
||||||
case SF_VAO_MESH:
|
|
||||||
((srfBspSurface_t *)surf->data)->dlightBits = dlightBits;
|
((srfBspSurface_t *)surf->data)->dlightBits = dlightBits;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -299,7 +298,6 @@ static int R_PshadowSurface( msurface_t *surf, int pshadowBits ) {
|
||||||
case SF_FACE:
|
case SF_FACE:
|
||||||
case SF_GRID:
|
case SF_GRID:
|
||||||
case SF_TRIANGLES:
|
case SF_TRIANGLES:
|
||||||
case SF_VAO_MESH:
|
|
||||||
((srfBspSurface_t *)surf->data)->pshadowBits = pshadowBits;
|
((srfBspSurface_t *)surf->data)->pshadowBits = pshadowBits;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -365,7 +363,7 @@ void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) {
|
||||||
|
|
||||||
pModel = R_GetModelByHandle( ent->e.hModel );
|
pModel = R_GetModelByHandle( ent->e.hModel );
|
||||||
|
|
||||||
bmodel = pModel->d.bmodel;
|
bmodel = pModel->bmodel;
|
||||||
|
|
||||||
clip = R_CullLocalBox( bmodel->bounds );
|
clip = R_CullLocalBox( bmodel->bounds );
|
||||||
if ( clip == CULL_OUT ) {
|
if ( clip == CULL_OUT ) {
|
||||||
|
@ -395,28 +393,17 @@ void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) {
|
||||||
=============================================================
|
=============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_GetInlineModelBounds
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_GetInlineModelBounds( int iIndex, vec3_t vMins, vec3_t vMaxs ) {
|
|
||||||
bmodel_t *bmodel = &tr.world->bmodels[ iIndex ];
|
|
||||||
|
|
||||||
VectorCopy( bmodel->bounds[ 0 ], vMins );
|
|
||||||
VectorCopy( bmodel->bounds[ 1 ], vMaxs );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
R_RecursiveWorldNode
|
R_RecursiveWorldNode
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits, int pshadowBits ) {
|
static void R_RecursiveWorldNode( mnode_t *node, uint32_t planeBits, uint32_t dlightBits, uint32_t pshadowBits ) {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
int newDlights[2];
|
uint32_t newDlights[2];
|
||||||
unsigned int newPShadows[2];
|
uint32_t newPShadows[2];
|
||||||
|
|
||||||
// if the node wasn't marked as potentially visible, exit
|
// if the node wasn't marked as potentially visible, exit
|
||||||
// pvs is skipped for depth shadows
|
// pvs is skipped for depth shadows
|
||||||
|
@ -572,43 +559,23 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits,
|
||||||
tr.viewParms.visBounds[1][2] = node->maxs[2];
|
tr.viewParms.visBounds[1][2] = node->maxs[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
// add merged and unmerged surfaces
|
// add surfaces
|
||||||
if (tr.world->viewSurfaces && !r_nocurves->integer)
|
view = tr.world->marksurfaces + node->firstmarksurface;
|
||||||
view = tr.world->viewSurfaces + node->firstmarksurface;
|
|
||||||
else
|
|
||||||
view = tr.world->marksurfaces + node->firstmarksurface;
|
|
||||||
|
|
||||||
c = node->nummarksurfaces;
|
c = node->nummarksurfaces;
|
||||||
while (c--) {
|
while (c--) {
|
||||||
// just mark it as visible, so we don't jump out of the cache derefencing the surface
|
// just mark it as visible, so we don't jump out of the cache derefencing the surface
|
||||||
surf = *view;
|
surf = *view;
|
||||||
if (surf < 0)
|
if (tr.world->surfacesViewCount[surf] != tr.viewCount)
|
||||||
{
|
{
|
||||||
if (tr.world->mergedSurfacesViewCount[-surf - 1] != tr.viewCount)
|
tr.world->surfacesViewCount[surf] = tr.viewCount;
|
||||||
{
|
tr.world->surfacesDlightBits[surf] = dlightBits;
|
||||||
tr.world->mergedSurfacesViewCount[-surf - 1] = tr.viewCount;
|
tr.world->surfacesPshadowBits[surf] = pshadowBits;
|
||||||
tr.world->mergedSurfacesDlightBits[-surf - 1] = dlightBits;
|
|
||||||
tr.world->mergedSurfacesPshadowBits[-surf - 1] = pshadowBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tr.world->mergedSurfacesDlightBits[-surf - 1] |= dlightBits;
|
|
||||||
tr.world->mergedSurfacesPshadowBits[-surf - 1] |= pshadowBits;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tr.world->surfacesViewCount[surf] != tr.viewCount)
|
tr.world->surfacesDlightBits[surf] |= dlightBits;
|
||||||
{
|
tr.world->surfacesPshadowBits[surf] |= pshadowBits;
|
||||||
tr.world->surfacesViewCount[surf] = tr.viewCount;
|
|
||||||
tr.world->surfacesDlightBits[surf] = dlightBits;
|
|
||||||
tr.world->surfacesPshadowBits[surf] = pshadowBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tr.world->surfacesDlightBits[surf] |= dlightBits;
|
|
||||||
tr.world->surfacesPshadowBits[surf] |= pshadowBits;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
view++;
|
view++;
|
||||||
}
|
}
|
||||||
|
@ -661,25 +628,6 @@ static const byte *R_ClusterPVS (int cluster) {
|
||||||
return tr.world->vis + cluster * tr.world->clusterBytes;
|
return tr.world->vis + cluster * tr.world->clusterBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_inPVS
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
qboolean R_inPVS( const vec3_t p1, const vec3_t p2 ) {
|
|
||||||
mnode_t *leaf;
|
|
||||||
byte *vis;
|
|
||||||
|
|
||||||
leaf = R_PointInLeaf( p1 );
|
|
||||||
vis = ri.CM_ClusterPVS( leaf->cluster ); // why not R_ClusterPVS ??
|
|
||||||
leaf = R_PointInLeaf( p2 );
|
|
||||||
|
|
||||||
if ( !(vis[leaf->cluster>>3] & (1<<(leaf->cluster&7))) ) {
|
|
||||||
return qfalse;
|
|
||||||
}
|
|
||||||
return qtrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
R_MarkLeaves
|
R_MarkLeaves
|
||||||
|
@ -772,7 +720,7 @@ R_AddWorldSurfaces
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
void R_AddWorldSurfaces (void) {
|
void R_AddWorldSurfaces (void) {
|
||||||
int planeBits, dlightBits, pshadowBits;
|
uint32_t planeBits, dlightBits, pshadowBits;
|
||||||
|
|
||||||
if ( !r_drawworld->integer ) {
|
if ( !r_drawworld->integer ) {
|
||||||
return;
|
return;
|
||||||
|
@ -793,12 +741,12 @@ void R_AddWorldSurfaces (void) {
|
||||||
ClearBounds( tr.viewParms.visBounds[0], tr.viewParms.visBounds[1] );
|
ClearBounds( tr.viewParms.visBounds[0], tr.viewParms.visBounds[1] );
|
||||||
|
|
||||||
// perform frustum culling and flag all the potentially visible surfaces
|
// perform frustum culling and flag all the potentially visible surfaces
|
||||||
if ( tr.refdef.num_dlights > 32 ) {
|
if ( tr.refdef.num_dlights > MAX_DLIGHTS ) {
|
||||||
tr.refdef.num_dlights = 32 ;
|
tr.refdef.num_dlights = MAX_DLIGHTS ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( tr.refdef.num_pshadows > 32 ) {
|
if ( tr.refdef.num_pshadows > MAX_DRAWN_PSHADOWS ) {
|
||||||
tr.refdef.num_pshadows = 32 ;
|
tr.refdef.num_pshadows = MAX_DRAWN_PSHADOWS;
|
||||||
}
|
}
|
||||||
|
|
||||||
planeBits = (tr.viewParms.flags & VPF_FARPLANEFRUSTUM) ? 31 : 15;
|
planeBits = (tr.viewParms.flags & VPF_FARPLANEFRUSTUM) ? 31 : 15;
|
||||||
|
@ -810,12 +758,12 @@ void R_AddWorldSurfaces (void) {
|
||||||
}
|
}
|
||||||
else if ( !(tr.viewParms.flags & VPF_SHADOWMAP) )
|
else if ( !(tr.viewParms.flags & VPF_SHADOWMAP) )
|
||||||
{
|
{
|
||||||
dlightBits = ( 1 << tr.refdef.num_dlights ) - 1;
|
dlightBits = ( 1ULL << tr.refdef.num_dlights ) - 1;
|
||||||
pshadowBits = ( 1 << tr.refdef.num_pshadows ) - 1;
|
pshadowBits = ( 1ULL << tr.refdef.num_pshadows ) - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dlightBits = ( 1 << tr.refdef.num_dlights ) - 1;
|
dlightBits = ( 1ULL << tr.refdef.num_dlights ) - 1;
|
||||||
pshadowBits = 0;
|
pshadowBits = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -836,18 +784,7 @@ void R_AddWorldSurfaces (void) {
|
||||||
R_AddWorldSurface( tr.world->surfaces + i, tr.world->surfacesDlightBits[i], tr.world->surfacesPshadowBits[i] );
|
R_AddWorldSurface( tr.world->surfaces + i, tr.world->surfacesDlightBits[i], tr.world->surfacesPshadowBits[i] );
|
||||||
tr.refdef.dlightMask |= tr.world->surfacesDlightBits[i];
|
tr.refdef.dlightMask |= tr.world->surfacesDlightBits[i];
|
||||||
}
|
}
|
||||||
for (i = 0; i < tr.world->numMergedSurfaces; i++)
|
|
||||||
{
|
|
||||||
if (tr.world->mergedSurfacesViewCount[i] != tr.viewCount)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
R_AddWorldSurface( tr.world->mergedSurfaces + i, tr.world->mergedSurfacesDlightBits[i], tr.world->mergedSurfacesPshadowBits[i] );
|
|
||||||
tr.refdef.dlightMask |= tr.world->mergedSurfacesDlightBits[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
tr.refdef.dlightMask = ~tr.refdef.dlightMask;
|
tr.refdef.dlightMask = ~tr.refdef.dlightMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
R_AddTerrainSurfaces();
|
|
||||||
R_AddStaticModelSurfaces();
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue