2019-11-24 20:45:15 -08:00
|
|
|
/*
|
|
|
|
Copyright (C) 1996-2001 Id Software, Inc.
|
|
|
|
Copyright (C) 2002-2009 John Fitzgibbons and others
|
|
|
|
Copyright (C) 2007-2008 Kristian Duske
|
|
|
|
Copyright (C) 2010-2014 QuakeSpasm developers
|
|
|
|
|
|
|
|
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
// r_misc.c
|
|
|
|
|
|
|
|
#include "quakedef.h"
|
|
|
|
|
|
|
|
//johnfitz -- new cvars
|
|
|
|
extern cvar_t r_stereo;
|
|
|
|
extern cvar_t r_stereodepth;
|
|
|
|
extern cvar_t r_clearcolor;
|
|
|
|
extern cvar_t r_drawflat;
|
|
|
|
extern cvar_t r_flatlightstyles;
|
|
|
|
extern cvar_t gl_fullbrights;
|
|
|
|
extern cvar_t gl_farclip;
|
|
|
|
extern cvar_t gl_overbright;
|
|
|
|
extern cvar_t gl_overbright_models;
|
|
|
|
extern cvar_t r_waterquality;
|
|
|
|
extern cvar_t r_oldwater;
|
|
|
|
extern cvar_t r_waterwarp;
|
|
|
|
extern cvar_t r_oldskyleaf;
|
|
|
|
extern cvar_t r_drawworld;
|
|
|
|
extern cvar_t r_showtris;
|
|
|
|
extern cvar_t r_showbboxes;
|
|
|
|
extern cvar_t r_lerpmodels;
|
|
|
|
extern cvar_t r_lerpmove;
|
|
|
|
extern cvar_t r_nolerp_list;
|
|
|
|
extern cvar_t r_noshadow_list;
|
|
|
|
//johnfitz
|
|
|
|
extern cvar_t gl_zfix; // QuakeSpasm z-fighting fix
|
|
|
|
|
|
|
|
extern gltexture_t *playertextures[MAX_SCOREBOARD]; //johnfitz
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_Overbright_f -- johnfitz
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
static void GL_Overbright_f(cvar_t *var)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 13:20:03 -08:00
|
|
|
(void)var;
|
2019-11-25 17:40:18 -08:00
|
|
|
R_RebuildAllLightmaps();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_Fullbrights_f -- johnfitz
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
static void GL_Fullbrights_f(cvar_t *var)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 13:20:03 -08:00
|
|
|
(void)var;
|
2019-11-25 17:40:18 -08:00
|
|
|
TexMgr_ReloadNobrightImages();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_SetClearColor_f -- johnfitz
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
static void R_SetClearColor_f(cvar_t *var)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
byte *rgb;
|
|
|
|
int32_t s;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 13:20:03 -08:00
|
|
|
(void)var;
|
2019-11-25 16:49:58 -08:00
|
|
|
s = (int32_t)r_clearcolor.value & 0xFF;
|
2019-11-24 20:45:15 -08:00
|
|
|
rgb = (byte*)(d_8to24table + s);
|
2019-11-25 17:40:18 -08:00
|
|
|
glClearColor(rgb[0] / 255.0, rgb[1] / 255.0, rgb[2] / 255.0, 0);
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_Novis_f -- johnfitz
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
static void R_VisChanged(cvar_t *var)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 16:49:58 -08:00
|
|
|
extern int32_t vis_changed;
|
2019-11-25 13:20:03 -08:00
|
|
|
(void)var;
|
2019-11-24 20:45:15 -08:00
|
|
|
vis_changed = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_Model_ExtraFlags_List_f -- johnfitz -- called when r_nolerp_list or r_noshadow_list cvar changes
|
|
|
|
===============
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
static void R_Model_ExtraFlags_List_f(cvar_t *var)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 13:20:03 -08:00
|
|
|
(void)var;
|
2019-11-25 16:49:58 -08:00
|
|
|
int32_t i;
|
2019-11-25 17:40:18 -08:00
|
|
|
for(i = 0; i < MAX_MODELS; i++)
|
|
|
|
Mod_SetExtraFlags(cl.model_precache[i]);
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_SetWateralpha_f -- ericw
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
static void R_SetWateralpha_f(cvar_t *var)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
map_wateralpha = var->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_SetLavaalpha_f -- ericw
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
static void R_SetLavaalpha_f(cvar_t *var)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
map_lavaalpha = var->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_SetTelealpha_f -- ericw
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
static void R_SetTelealpha_f(cvar_t *var)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
map_telealpha = var->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_SetSlimealpha_f -- ericw
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
static void R_SetSlimealpha_f(cvar_t *var)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
map_slimealpha = var->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_WaterAlphaForSurfface -- ericw
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
float GL_WaterAlphaForSurface(msurface_t *fa)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(fa->flags & SURF_DRAWLAVA)
|
2019-11-24 20:45:15 -08:00
|
|
|
return map_lavaalpha > 0 ? map_lavaalpha : map_wateralpha;
|
2019-11-25 17:40:18 -08:00
|
|
|
else if(fa->flags & SURF_DRAWTELE)
|
2019-11-24 20:45:15 -08:00
|
|
|
return map_telealpha > 0 ? map_telealpha : map_wateralpha;
|
2019-11-25 17:40:18 -08:00
|
|
|
else if(fa->flags & SURF_DRAWSLIME)
|
2019-11-24 20:45:15 -08:00
|
|
|
return map_slimealpha > 0 ? map_slimealpha : map_wateralpha;
|
|
|
|
else
|
|
|
|
return map_wateralpha;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_Init
|
|
|
|
===============
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
void R_Init(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
extern cvar_t gl_finish;
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
|
|
|
|
Cmd_AddCommand("pointfile", R_ReadPointFile_f);
|
|
|
|
|
|
|
|
Cvar_RegisterVariable(&r_norefresh);
|
|
|
|
Cvar_RegisterVariable(&r_lightmap);
|
|
|
|
Cvar_RegisterVariable(&r_fullbright);
|
|
|
|
Cvar_RegisterVariable(&r_drawentities);
|
|
|
|
Cvar_RegisterVariable(&r_drawviewmodel);
|
|
|
|
Cvar_RegisterVariable(&r_shadows);
|
|
|
|
Cvar_RegisterVariable(&r_wateralpha);
|
|
|
|
Cvar_SetCallback(&r_wateralpha, R_SetWateralpha_f);
|
|
|
|
Cvar_RegisterVariable(&r_dynamic);
|
|
|
|
Cvar_RegisterVariable(&r_novis);
|
|
|
|
Cvar_SetCallback(&r_novis, R_VisChanged);
|
|
|
|
Cvar_RegisterVariable(&r_speeds);
|
|
|
|
Cvar_RegisterVariable(&r_pos);
|
|
|
|
|
|
|
|
Cvar_RegisterVariable(&gl_finish);
|
|
|
|
Cvar_RegisterVariable(&gl_clear);
|
|
|
|
Cvar_RegisterVariable(&gl_cull);
|
|
|
|
Cvar_RegisterVariable(&gl_smoothmodels);
|
|
|
|
Cvar_RegisterVariable(&gl_affinemodels);
|
|
|
|
Cvar_RegisterVariable(&gl_polyblend);
|
|
|
|
Cvar_RegisterVariable(&gl_flashblend);
|
|
|
|
Cvar_RegisterVariable(&gl_playermip);
|
|
|
|
Cvar_RegisterVariable(&gl_nocolors);
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
//johnfitz -- new cvars
|
2019-11-25 17:40:18 -08:00
|
|
|
Cvar_RegisterVariable(&r_stereo);
|
|
|
|
Cvar_RegisterVariable(&r_stereodepth);
|
|
|
|
Cvar_RegisterVariable(&r_clearcolor);
|
|
|
|
Cvar_SetCallback(&r_clearcolor, R_SetClearColor_f);
|
|
|
|
Cvar_RegisterVariable(&r_waterquality);
|
|
|
|
Cvar_RegisterVariable(&r_oldwater);
|
|
|
|
Cvar_RegisterVariable(&r_waterwarp);
|
|
|
|
Cvar_RegisterVariable(&r_drawflat);
|
|
|
|
Cvar_RegisterVariable(&r_flatlightstyles);
|
|
|
|
Cvar_RegisterVariable(&r_oldskyleaf);
|
|
|
|
Cvar_SetCallback(&r_oldskyleaf, R_VisChanged);
|
|
|
|
Cvar_RegisterVariable(&r_drawworld);
|
|
|
|
Cvar_RegisterVariable(&r_showtris);
|
|
|
|
Cvar_RegisterVariable(&r_showbboxes);
|
|
|
|
Cvar_RegisterVariable(&gl_farclip);
|
|
|
|
Cvar_RegisterVariable(&gl_fullbrights);
|
|
|
|
Cvar_RegisterVariable(&gl_overbright);
|
|
|
|
Cvar_SetCallback(&gl_fullbrights, GL_Fullbrights_f);
|
|
|
|
Cvar_SetCallback(&gl_overbright, GL_Overbright_f);
|
|
|
|
Cvar_RegisterVariable(&gl_overbright_models);
|
|
|
|
Cvar_RegisterVariable(&r_lerpmodels);
|
|
|
|
Cvar_RegisterVariable(&r_lerpmove);
|
|
|
|
Cvar_RegisterVariable(&r_nolerp_list);
|
|
|
|
Cvar_SetCallback(&r_nolerp_list, R_Model_ExtraFlags_List_f);
|
|
|
|
Cvar_RegisterVariable(&r_noshadow_list);
|
|
|
|
Cvar_SetCallback(&r_noshadow_list, R_Model_ExtraFlags_List_f);
|
2019-11-24 20:45:15 -08:00
|
|
|
//johnfitz
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
Cvar_RegisterVariable(&gl_zfix); // QuakeSpasm z-fighting fix
|
|
|
|
Cvar_RegisterVariable(&r_lavaalpha);
|
|
|
|
Cvar_RegisterVariable(&r_telealpha);
|
|
|
|
Cvar_RegisterVariable(&r_slimealpha);
|
|
|
|
Cvar_RegisterVariable(&r_scale);
|
|
|
|
Cvar_SetCallback(&r_lavaalpha, R_SetLavaalpha_f);
|
|
|
|
Cvar_SetCallback(&r_telealpha, R_SetTelealpha_f);
|
|
|
|
Cvar_SetCallback(&r_slimealpha, R_SetSlimealpha_f);
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
R_InitParticles();
|
|
|
|
R_SetClearColor_f(&r_clearcolor); //johnfitz
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
Sky_Init(); //johnfitz
|
|
|
|
Fog_Init(); //johnfitz
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_TranslatePlayerSkin -- johnfitz -- rewritten. also, only handles new colors, not new skins
|
|
|
|
===============
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
void R_TranslatePlayerSkin(int32_t playernum)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
int32_t top, bottom;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
top = (cl.scores[playernum].colors & 0xf0) >> 4;
|
|
|
|
bottom = cl.scores[playernum].colors & 15;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
//FIXME: if gl_nocolors is on, then turned off, the textures may be out of sync with the scoreboard colors.
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!gl_nocolors.value)
|
|
|
|
if(playertextures[playernum])
|
|
|
|
TexMgr_ReloadImage(playertextures[playernum], top, bottom);
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_TranslateNewPlayerSkin -- johnfitz -- split off of TranslatePlayerSkin -- this is called when
|
|
|
|
the skin or model actually changes, instead of just new colors
|
|
|
|
added bug fix from bengt jardup
|
|
|
|
===============
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
void R_TranslateNewPlayerSkin(int32_t playernum)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
char name[64];
|
|
|
|
byte *pixels;
|
|
|
|
aliashdr_t *paliashdr;
|
|
|
|
int32_t skinnum;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
//get correct texture pixels
|
2019-11-25 17:40:18 -08:00
|
|
|
currententity = &cl_entities[1 + playernum];
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!currententity->model || currententity->model->type != mod_alias)
|
2019-11-24 20:45:15 -08:00
|
|
|
return;
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
paliashdr = (aliashdr_t *)Mod_Extradata(currententity->model);
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
skinnum = currententity->skinnum;
|
|
|
|
|
|
|
|
//TODO: move these tests to the place where skinnum gets received from the server
|
2019-11-25 17:40:18 -08:00
|
|
|
if(skinnum < 0 || skinnum >= paliashdr->numskins)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 16:56:15 -08:00
|
|
|
Con_DPrintf("(%" PRIi32 "): Invalid player skin #%" PRIi32 "\n", playernum, skinnum);
|
2019-11-24 20:45:15 -08:00
|
|
|
skinnum = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pixels = (byte *)paliashdr + paliashdr->texels[skinnum]; // This is not a persistent place!
|
|
|
|
|
|
|
|
//upload new image
|
2019-11-25 16:56:15 -08:00
|
|
|
q_snprintf(name, sizeof(name), "player_%" PRIi32 "", playernum);
|
2019-11-25 17:40:18 -08:00
|
|
|
playertextures[playernum] = TexMgr_LoadImage(currententity->model, name, paliashdr->skinwidth, paliashdr->skinheight,
|
|
|
|
SRC_INDEXED, pixels, paliashdr->gltextures[skinnum][0]->source_file, paliashdr->gltextures[skinnum][0]->source_offset, TEXPREF_PAD | TEXPREF_OVERWRITE);
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
//now recolor it
|
2019-11-25 17:40:18 -08:00
|
|
|
R_TranslatePlayerSkin(playernum);
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_NewGame -- johnfitz -- handle a game switch
|
|
|
|
===============
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
void R_NewGame(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 16:49:58 -08:00
|
|
|
int32_t i;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
//clear playertexture pointers (the textures themselves were freed by texmgr_newgame)
|
2019-11-25 17:40:18 -08:00
|
|
|
for(i = 0; i < MAX_SCOREBOARD; i++)
|
2019-11-24 20:45:15 -08:00
|
|
|
playertextures[i] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_ParseWorldspawn
|
|
|
|
|
|
|
|
called at map load
|
|
|
|
=============
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
static void R_ParseWorldspawn(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
char key[128], value[4096];
|
|
|
|
const char *data;
|
|
|
|
|
|
|
|
map_wateralpha = r_wateralpha.value;
|
|
|
|
map_lavaalpha = r_lavaalpha.value;
|
|
|
|
map_telealpha = r_telealpha.value;
|
|
|
|
map_slimealpha = r_slimealpha.value;
|
|
|
|
|
|
|
|
data = COM_Parse(cl.worldmodel->entities);
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!data)
|
2019-11-24 20:45:15 -08:00
|
|
|
return; // error
|
2019-11-25 17:40:18 -08:00
|
|
|
if(com_token[0] != '{')
|
2019-11-24 20:45:15 -08:00
|
|
|
return; // error
|
2019-11-25 17:40:18 -08:00
|
|
|
while(1)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
data = COM_Parse(data);
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!data)
|
2019-11-24 20:45:15 -08:00
|
|
|
return; // error
|
2019-11-25 17:40:18 -08:00
|
|
|
if(com_token[0] == '}')
|
2019-11-24 20:45:15 -08:00
|
|
|
break; // end of worldspawn
|
2019-11-25 17:40:18 -08:00
|
|
|
if(com_token[0] == '_')
|
2019-11-24 20:45:15 -08:00
|
|
|
strcpy(key, com_token + 1);
|
|
|
|
else
|
|
|
|
strcpy(key, com_token);
|
2019-11-25 17:40:18 -08:00
|
|
|
while(key[strlen(key) - 1] == ' ') // remove trailing spaces
|
|
|
|
key[strlen(key) - 1] = 0;
|
2019-11-24 20:45:15 -08:00
|
|
|
data = COM_Parse(data);
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!data)
|
2019-11-24 20:45:15 -08:00
|
|
|
return; // error
|
|
|
|
strcpy(value, com_token);
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!strcmp("wateralpha", key))
|
2019-11-24 20:45:15 -08:00
|
|
|
map_wateralpha = atof(value);
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!strcmp("lavaalpha", key))
|
2019-11-24 20:45:15 -08:00
|
|
|
map_lavaalpha = atof(value);
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!strcmp("telealpha", key))
|
2019-11-24 20:45:15 -08:00
|
|
|
map_telealpha = atof(value);
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!strcmp("slimealpha", key))
|
2019-11-24 20:45:15 -08:00
|
|
|
map_slimealpha = atof(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_NewMap
|
|
|
|
===============
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
void R_NewMap(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
int32_t i;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
for(i = 0 ; i < 256 ; i++)
|
|
|
|
d_lightstylevalue[i] = 264; // normal light value
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
// clear out efrags in case the level hasn't been reloaded
|
|
|
|
// FIXME: is this one short?
|
2019-11-25 17:40:18 -08:00
|
|
|
for(i = 0 ; i < cl.worldmodel->numleafs ; i++)
|
2019-11-24 20:45:15 -08:00
|
|
|
cl.worldmodel->leafs[i].efrags = NULL;
|
|
|
|
|
|
|
|
r_viewleaf = NULL;
|
2019-11-25 17:40:18 -08:00
|
|
|
R_ClearParticles();
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_BuildLightmaps();
|
|
|
|
GL_BuildBModelVertexBuffer();
|
2019-11-24 20:45:15 -08:00
|
|
|
//ericw -- no longer load alias models into a VBO here, it's done in Mod_LoadAliasModel
|
|
|
|
|
|
|
|
r_framecount = 0; //johnfitz -- paranoid?
|
|
|
|
r_visframecount = 0; //johnfitz -- paranoid?
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
Sky_NewMap(); //johnfitz -- skybox in worldspawn
|
|
|
|
Fog_NewMap(); //johnfitz -- global fog in worldspawn
|
|
|
|
R_ParseWorldspawn(); //ericw -- wateralpha, lavaalpha, telealpha, slimealpha in worldspawn
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
load_subdivide_size = gl_subdivide_size.value; //johnfitz -- is this the right place to set this?
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_TimeRefresh_f
|
|
|
|
|
|
|
|
For program optimization
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
void R_TimeRefresh_f(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
int32_t i;
|
|
|
|
float start, stop, time;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(cls.state != ca_connected)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
Con_Printf("Not connected to a server\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
start = Sys_DoubleTime();
|
|
|
|
for(i = 0; i < 128; i++)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
GL_BeginRendering(&glx, &gly, &glwidth, &glheight);
|
2019-11-25 17:40:18 -08:00
|
|
|
r_refdef.viewangles[1] = i / 128.0 * 360.0;
|
|
|
|
R_RenderView();
|
|
|
|
GL_EndRendering();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
glFinish();
|
|
|
|
stop = Sys_DoubleTime();
|
|
|
|
time = stop - start;
|
|
|
|
Con_Printf("%f seconds (%f fps)\n", time, 128 / time);
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
void D_FlushCaches(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static GLuint gl_programs[16];
|
2019-11-25 16:49:58 -08:00
|
|
|
static int32_t gl_num_programs;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
static bool GL_CheckShader(GLuint shader)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
GLint status;
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_GetShaderivFunc(shader, GL_COMPILE_STATUS, &status);
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(status != GL_TRUE)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
char infolog[1024];
|
|
|
|
|
|
|
|
memset(infolog, 0, sizeof(infolog));
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_GetShaderInfoLogFunc(shader, sizeof(infolog), NULL, infolog);
|
2019-11-25 13:20:03 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
Con_Warning("GLSL program failed to compile: %s", infolog);
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
static bool GL_CheckProgram(GLuint program)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
GLint status;
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_GetProgramivFunc(program, GL_LINK_STATUS, &status);
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(status != GL_TRUE)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
char infolog[1024];
|
|
|
|
|
|
|
|
memset(infolog, 0, sizeof(infolog));
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_GetProgramInfoLogFunc(program, sizeof(infolog), NULL, infolog);
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
Con_Warning("GLSL program failed to link: %s", infolog);
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
GL_GetUniformLocation
|
|
|
|
=============
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
GLint GL_GetUniformLocation(GLuint *programPtr, const char *name)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
GLint location;
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!programPtr)
|
2019-11-24 20:45:15 -08:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
location = GL_GetUniformLocationFunc(*programPtr, name);
|
2019-11-25 17:40:18 -08:00
|
|
|
if(location == -1)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
Con_Warning("GL_GetUniformLocationFunc %s failed\n", name);
|
|
|
|
*programPtr = 0;
|
|
|
|
}
|
|
|
|
return location;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_CreateProgram
|
|
|
|
|
|
|
|
Compiles and returns GLSL program.
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
GLuint GL_CreateProgram(const GLchar *vertSource, const GLchar *fragSource, int32_t numbindings, const glsl_attrib_binding_t *bindings)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 16:49:58 -08:00
|
|
|
int32_t i;
|
2019-11-24 20:45:15 -08:00
|
|
|
GLuint program, vertShader, fragShader;
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!gl_glsl_able)
|
2019-11-24 20:45:15 -08:00
|
|
|
return 0;
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
vertShader = GL_CreateShaderFunc(GL_VERTEX_SHADER);
|
|
|
|
GL_ShaderSourceFunc(vertShader, 1, &vertSource, NULL);
|
|
|
|
GL_CompileShaderFunc(vertShader);
|
|
|
|
if(!GL_CheckShader(vertShader))
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_DeleteShaderFunc(vertShader);
|
2019-11-24 20:45:15 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
fragShader = GL_CreateShaderFunc(GL_FRAGMENT_SHADER);
|
|
|
|
GL_ShaderSourceFunc(fragShader, 1, &fragSource, NULL);
|
|
|
|
GL_CompileShaderFunc(fragShader);
|
|
|
|
if(!GL_CheckShader(fragShader))
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_DeleteShaderFunc(vertShader);
|
|
|
|
GL_DeleteShaderFunc(fragShader);
|
2019-11-24 20:45:15 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
program = GL_CreateProgramFunc();
|
|
|
|
GL_AttachShaderFunc(program, vertShader);
|
|
|
|
GL_DeleteShaderFunc(vertShader);
|
|
|
|
GL_AttachShaderFunc(program, fragShader);
|
|
|
|
GL_DeleteShaderFunc(fragShader);
|
2019-11-25 13:20:03 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
for(i = 0; i < numbindings; i++)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_BindAttribLocationFunc(program, bindings[i].attrib, bindings[i].name);
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
2019-11-25 13:20:03 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_LinkProgramFunc(program);
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!GL_CheckProgram(program))
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_DeleteProgramFunc(program);
|
2019-11-24 20:45:15 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-26 18:06:48 -08:00
|
|
|
if(gl_num_programs == arraysizeof(gl_programs))
|
2019-11-25 17:40:18 -08:00
|
|
|
Host_Error("gl_programs overflow");
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
gl_programs[gl_num_programs] = program;
|
|
|
|
gl_num_programs++;
|
|
|
|
|
|
|
|
return program;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_DeleteShaders
|
|
|
|
|
|
|
|
Deletes any GLSL programs that have been created.
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
void R_DeleteShaders(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 16:49:58 -08:00
|
|
|
int32_t i;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!gl_glsl_able)
|
2019-11-24 20:45:15 -08:00
|
|
|
return;
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
for(i = 0; i < gl_num_programs; i++)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_DeleteProgramFunc(gl_programs[i]);
|
2019-11-24 20:45:15 -08:00
|
|
|
gl_programs[i] = 0;
|
|
|
|
}
|
|
|
|
gl_num_programs = 0;
|
|
|
|
}
|
|
|
|
GLuint current_array_buffer, current_element_array_buffer;
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_BindBuffer
|
|
|
|
|
|
|
|
glBindBuffer wrapper
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
void GL_BindBuffer(GLenum target, GLuint buffer)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
GLuint *cache;
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!gl_vbo_able)
|
2019-11-24 20:45:15 -08:00
|
|
|
return;
|
2019-11-25 13:20:03 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
switch(target)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
case GL_ARRAY_BUFFER:
|
|
|
|
cache = ¤t_array_buffer;
|
|
|
|
break;
|
|
|
|
case GL_ELEMENT_ARRAY_BUFFER:
|
|
|
|
cache = ¤t_element_array_buffer;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Host_Error("GL_BindBuffer: unsupported target %" PRIi32 "", (int32_t)target);
|
|
|
|
return;
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
2019-11-25 13:20:03 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(*cache != buffer)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
*cache = buffer;
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_BindBufferFunc(target, *cache);
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_ClearBufferBindings
|
|
|
|
|
|
|
|
This must be called if you do anything that could make the cached bindings
|
|
|
|
invalid (e.g. manually binding, destroying the context).
|
|
|
|
====================
|
|
|
|
*/
|
2019-11-25 17:40:18 -08:00
|
|
|
void GL_ClearBufferBindings()
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!gl_vbo_able)
|
2019-11-24 20:45:15 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
current_array_buffer = 0;
|
|
|
|
current_element_array_buffer = 0;
|
2019-11-25 17:40:18 -08:00
|
|
|
GL_BindBufferFunc(GL_ARRAY_BUFFER, 0);
|
|
|
|
GL_BindBufferFunc(GL_ELEMENT_ARRAY_BUFFER, 0);
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|