2010-02-15 23:26:55 +00:00
|
|
|
/*
|
|
|
|
Copyright (C) 1996-2001 Id Software, Inc.
|
|
|
|
Copyright (C) 2002-2009 John Fitzgibbons and others
|
|
|
|
Copyright (C) 2007-2008 Kristian Duske
|
2014-09-22 08:55:46 +00:00
|
|
|
Copyright (C) 2010-2014 QuakeSpasm developers
|
2010-02-15 23:26:55 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
//johnfitz
|
2011-08-24 07:47:29 +00:00
|
|
|
extern cvar_t gl_zfix; // QuakeSpasm z-fighting fix
|
|
|
|
|
2010-02-15 23:26:55 +00:00
|
|
|
extern gltexture_t *playertextures[MAX_SCOREBOARD]; //johnfitz
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_Overbright_f -- johnfitz
|
|
|
|
====================
|
|
|
|
*/
|
2011-12-24 14:04:01 +00:00
|
|
|
static void GL_Overbright_f (cvar_t *var)
|
2010-02-15 23:26:55 +00:00
|
|
|
{
|
|
|
|
R_RebuildAllLightmaps ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_Fullbrights_f -- johnfitz
|
|
|
|
====================
|
|
|
|
*/
|
2011-12-24 14:04:01 +00:00
|
|
|
static void GL_Fullbrights_f (cvar_t *var)
|
2010-02-15 23:26:55 +00:00
|
|
|
{
|
|
|
|
TexMgr_ReloadNobrightImages ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_SetClearColor_f -- johnfitz
|
|
|
|
====================
|
|
|
|
*/
|
2011-12-24 14:04:01 +00:00
|
|
|
static void R_SetClearColor_f (cvar_t *var)
|
2010-02-15 23:26:55 +00:00
|
|
|
{
|
|
|
|
byte *rgb;
|
|
|
|
int s;
|
|
|
|
|
|
|
|
s = (int)r_clearcolor.value & 0xFF;
|
|
|
|
rgb = (byte*)(d_8to24table + s);
|
|
|
|
glClearColor (rgb[0]/255.0,rgb[1]/255.0,rgb[2]/255.0,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_Novis_f -- johnfitz
|
|
|
|
====================
|
|
|
|
*/
|
2011-12-24 14:04:01 +00:00
|
|
|
static void R_VisChanged (cvar_t *var)
|
2010-02-15 23:26:55 +00:00
|
|
|
{
|
|
|
|
extern int vis_changed;
|
|
|
|
vis_changed = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-12-24 14:04:01 +00:00
|
|
|
===============
|
|
|
|
R_NoLerpList_f -- johnfitz -- called when r_nolerp_list cvar changes
|
|
|
|
===============
|
2010-02-15 23:26:55 +00:00
|
|
|
*/
|
2011-12-24 14:04:01 +00:00
|
|
|
static void R_NoLerpList_f (cvar_t *var)
|
2010-02-15 23:26:55 +00:00
|
|
|
{
|
2011-12-24 14:04:01 +00:00
|
|
|
int i;
|
|
|
|
for (i=0; i < MAX_MODELS; i++)
|
|
|
|
Mod_SetExtraFlags (cl.model_precache[i]);
|
2010-02-15 23:26:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_Init
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void R_Init (void)
|
|
|
|
{
|
|
|
|
extern cvar_t gl_finish;
|
|
|
|
|
|
|
|
Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
|
|
|
|
Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
|
|
|
|
|
2011-12-28 22:01:33 +00:00
|
|
|
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_RegisterVariable (&r_dynamic);
|
|
|
|
Cvar_RegisterVariable (&r_novis);
|
|
|
|
Cvar_SetCallback (&r_novis, R_VisChanged);
|
|
|
|
Cvar_RegisterVariable (&r_speeds);
|
|
|
|
|
|
|
|
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);
|
2010-02-15 23:26:55 +00:00
|
|
|
|
|
|
|
//johnfitz -- new cvars
|
2011-12-28 22:01:33 +00: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_NoLerpList_f);
|
2010-02-15 23:26:55 +00:00
|
|
|
//johnfitz
|
|
|
|
|
2011-12-28 22:01:33 +00:00
|
|
|
Cvar_RegisterVariable (&gl_zfix); // QuakeSpasm z-fighting fix
|
2011-08-24 07:47:29 +00:00
|
|
|
|
2010-02-15 23:26:55 +00:00
|
|
|
R_InitParticles ();
|
2011-12-24 14:04:01 +00:00
|
|
|
R_SetClearColor_f (&r_clearcolor); //johnfitz
|
2010-02-15 23:26:55 +00:00
|
|
|
|
|
|
|
Sky_Init (); //johnfitz
|
|
|
|
Fog_Init (); //johnfitz
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_TranslatePlayerSkin -- johnfitz -- rewritten. also, only handles new colors, not new skins
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void R_TranslatePlayerSkin (int playernum)
|
|
|
|
{
|
|
|
|
int top, bottom;
|
|
|
|
|
|
|
|
top = (cl.scores[playernum].colors & 0xf0)>>4;
|
|
|
|
bottom = cl.scores[playernum].colors &15;
|
|
|
|
|
|
|
|
//FIXME: if gl_nocolors is on, then turned off, the textures may be out of sync with the scoreboard colors.
|
|
|
|
if (!gl_nocolors.value)
|
|
|
|
if (playertextures[playernum])
|
|
|
|
TexMgr_ReloadImage (playertextures[playernum], top, bottom);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
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
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void R_TranslateNewPlayerSkin (int playernum)
|
|
|
|
{
|
|
|
|
char name[64];
|
|
|
|
byte *pixels;
|
|
|
|
aliashdr_t *paliashdr;
|
|
|
|
int skinnum;
|
|
|
|
|
|
|
|
//get correct texture pixels
|
|
|
|
currententity = &cl_entities[1+playernum];
|
|
|
|
|
|
|
|
if (!currententity->model || currententity->model->type != mod_alias)
|
|
|
|
return;
|
|
|
|
|
|
|
|
paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
|
|
|
|
|
|
|
|
skinnum = currententity->skinnum;
|
|
|
|
|
|
|
|
//TODO: move these tests to the place where skinnum gets received from the server
|
|
|
|
if (skinnum < 0 || skinnum >= paliashdr->numskins)
|
|
|
|
{
|
|
|
|
Con_DPrintf("(%d): Invalid player skin #%d\n", playernum, skinnum);
|
|
|
|
skinnum = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pixels = (byte *)paliashdr + paliashdr->texels[skinnum]; // This is not a persistent place!
|
|
|
|
|
|
|
|
//upload new image
|
2011-12-27 10:50:42 +00:00
|
|
|
q_snprintf(name, sizeof(name), "player_%i", playernum);
|
2010-02-15 23:26:55 +00: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);
|
|
|
|
|
|
|
|
//now recolor it
|
|
|
|
R_TranslatePlayerSkin (playernum);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_NewGame -- johnfitz -- handle a game switch
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void R_NewGame (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
//clear playertexture pointers (the textures themselves were freed by texmgr_newgame)
|
|
|
|
for (i=0; i<MAX_SCOREBOARD; i++)
|
|
|
|
playertextures[i] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_NewMap
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void R_NewMap (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0 ; i<256 ; i++)
|
|
|
|
d_lightstylevalue[i] = 264; // normal light value
|
|
|
|
|
|
|
|
// clear out efrags in case the level hasn't been reloaded
|
|
|
|
// FIXME: is this one short?
|
|
|
|
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
|
|
|
|
cl.worldmodel->leafs[i].efrags = NULL;
|
|
|
|
|
|
|
|
r_viewleaf = NULL;
|
|
|
|
R_ClearParticles ();
|
|
|
|
|
|
|
|
GL_BuildLightmaps ();
|
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
|
|
|
GL_BuildVBOs ();
|
Alias model rendering fast-path using OpenGL 2.
In GL_MakeAliasModelDisplayLists, after saving the standerd triangle strips and fans onto the hunk, if the system is GL2 capable, we also save a second version of the mdl on the hunk designed to be loaded into a VBO (GL_MakeAliasModelDisplayLists_VBO). In R_NewMap, and on video mode changes, we call GLMesh_LoadVertexBuffers which loops over all precached mdl's and loads the data into a pair of VBO's (vertices and vertex indices).
Finally, in R_DrawAliasModel, assuming no rendering options are disabling the fast-path (r_drawflat 1, r_lightmap 1, or r_fullbright 1 would disable it), we call GL_DrawAliasFrame_GLSL, which sets up all of the bindings and draws the (possibly lerped) mdl in one glDrawElements call.
Special thanks to MH for some of the code from RMQEngine and the general concept.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1151 af15c1b1-3010-417e-b628-4374ebc0bcbd
2015-01-20 18:59:15 +00:00
|
|
|
GLMesh_LoadVertexBuffers ();
|
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
|
|
|
|
2010-02-15 23:26:55 +00:00
|
|
|
r_framecount = 0; //johnfitz -- paranoid?
|
|
|
|
r_visframecount = 0; //johnfitz -- paranoid?
|
|
|
|
|
|
|
|
Sky_NewMap (); //johnfitz -- skybox in worldspawn
|
|
|
|
Fog_NewMap (); //johnfitz -- global fog in worldspawn
|
|
|
|
|
|
|
|
load_subdivide_size = gl_subdivide_size.value; //johnfitz -- is this the right place to set this?
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_TimeRefresh_f
|
|
|
|
|
|
|
|
For program optimization
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
void R_TimeRefresh_f (void)
|
|
|
|
{
|
2012-04-22 07:55:56 +00:00
|
|
|
int i;
|
2010-02-15 23:26:55 +00:00
|
|
|
float start, stop, time;
|
|
|
|
|
2012-04-22 07:55:56 +00:00
|
|
|
if (cls.state != ca_connected)
|
|
|
|
{
|
|
|
|
Con_Printf("Not connected to a server\n");
|
|
|
|
return;
|
|
|
|
}
|
2010-02-15 23:26:55 +00:00
|
|
|
|
2011-12-12 16:01:01 +00:00
|
|
|
start = Sys_DoubleTime ();
|
2012-04-22 07:55:56 +00:00
|
|
|
for (i = 0; i < 128; i++)
|
2010-02-15 23:26:55 +00:00
|
|
|
{
|
2012-04-22 07:55:56 +00:00
|
|
|
GL_BeginRendering(&glx, &gly, &glwidth, &glheight);
|
2010-02-15 23:26:55 +00:00
|
|
|
r_refdef.viewangles[1] = i/128.0*360.0;
|
|
|
|
R_RenderView ();
|
2012-04-22 07:55:56 +00:00
|
|
|
GL_EndRendering ();
|
2010-02-15 23:26:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
glFinish ();
|
2011-12-12 16:01:01 +00:00
|
|
|
stop = Sys_DoubleTime ();
|
2010-02-15 23:26:55 +00:00
|
|
|
time = stop-start;
|
|
|
|
Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
|
|
|
|
}
|
|
|
|
|
|
|
|
void D_FlushCaches (void)
|
|
|
|
{
|
|
|
|
}
|
Alias model rendering fast-path using OpenGL 2.
In GL_MakeAliasModelDisplayLists, after saving the standerd triangle strips and fans onto the hunk, if the system is GL2 capable, we also save a second version of the mdl on the hunk designed to be loaded into a VBO (GL_MakeAliasModelDisplayLists_VBO). In R_NewMap, and on video mode changes, we call GLMesh_LoadVertexBuffers which loops over all precached mdl's and loads the data into a pair of VBO's (vertices and vertex indices).
Finally, in R_DrawAliasModel, assuming no rendering options are disabling the fast-path (r_drawflat 1, r_lightmap 1, or r_fullbright 1 would disable it), we call GL_DrawAliasFrame_GLSL, which sets up all of the bindings and draws the (possibly lerped) mdl in one glDrawElements call.
Special thanks to MH for some of the code from RMQEngine and the general concept.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1151 af15c1b1-3010-417e-b628-4374ebc0bcbd
2015-01-20 18:59:15 +00:00
|
|
|
|
|
|
|
static GLuint gl_programs[16];
|
|
|
|
static int gl_num_programs;
|
|
|
|
|
|
|
|
static qboolean GL_CheckShader (GLuint shader)
|
|
|
|
{
|
|
|
|
GLint status;
|
|
|
|
GL_GetShaderivFunc (shader, GL_COMPILE_STATUS, &status);
|
|
|
|
|
|
|
|
if (status != GL_TRUE)
|
|
|
|
{
|
|
|
|
char infolog[1024];
|
|
|
|
|
|
|
|
memset(infolog, 0, sizeof(infolog));
|
|
|
|
GL_GetShaderInfoLogFunc (shader, sizeof(infolog), NULL, infolog);
|
|
|
|
|
|
|
|
Con_Warning ("GLSL program failed to compile: %s", infolog);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static qboolean GL_CheckProgram (GLuint program)
|
|
|
|
{
|
|
|
|
GLint status;
|
|
|
|
GL_GetProgramivFunc (program, GL_LINK_STATUS, &status);
|
|
|
|
|
|
|
|
if (status != GL_TRUE)
|
|
|
|
{
|
|
|
|
char infolog[1024];
|
|
|
|
|
|
|
|
memset(infolog, 0, sizeof(infolog));
|
|
|
|
GL_GetProgramInfoLogFunc (program, sizeof(infolog), NULL, infolog);
|
|
|
|
|
|
|
|
Con_Warning ("GLSL program failed to link: %s", infolog);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-01-25 20:29:30 +00:00
|
|
|
/*
|
|
|
|
=============
|
|
|
|
GL_GetUniformLocation
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
GLint GL_GetUniformLocation (GLuint *programPtr, const char *name)
|
|
|
|
{
|
|
|
|
GLint location;
|
|
|
|
|
|
|
|
if (!programPtr)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
location = GL_GetUniformLocationFunc(*programPtr, name);
|
|
|
|
if (location == -1)
|
|
|
|
{
|
|
|
|
Con_Warning("GL_GetUniformLocationFunc %s failed\n", name);
|
|
|
|
*programPtr = 0;
|
|
|
|
}
|
|
|
|
return location;
|
|
|
|
}
|
Alias model rendering fast-path using OpenGL 2.
In GL_MakeAliasModelDisplayLists, after saving the standerd triangle strips and fans onto the hunk, if the system is GL2 capable, we also save a second version of the mdl on the hunk designed to be loaded into a VBO (GL_MakeAliasModelDisplayLists_VBO). In R_NewMap, and on video mode changes, we call GLMesh_LoadVertexBuffers which loops over all precached mdl's and loads the data into a pair of VBO's (vertices and vertex indices).
Finally, in R_DrawAliasModel, assuming no rendering options are disabling the fast-path (r_drawflat 1, r_lightmap 1, or r_fullbright 1 would disable it), we call GL_DrawAliasFrame_GLSL, which sets up all of the bindings and draws the (possibly lerped) mdl in one glDrawElements call.
Special thanks to MH for some of the code from RMQEngine and the general concept.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1151 af15c1b1-3010-417e-b628-4374ebc0bcbd
2015-01-20 18:59:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_CreateProgram
|
|
|
|
|
|
|
|
Compiles and returns GLSL program.
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
GLuint GL_CreateProgram (const GLchar *vertSource, const GLchar *fragSource, int numbindings, const glsl_attrib_binding_t *bindings)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
GLuint program, vertShader, fragShader;
|
|
|
|
|
|
|
|
if (!GLAlias_SupportsShaders())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
vertShader = GL_CreateShaderFunc (GL_VERTEX_SHADER);
|
|
|
|
GL_ShaderSourceFunc (vertShader, 1, &vertSource, NULL);
|
|
|
|
GL_CompileShaderFunc (vertShader);
|
|
|
|
if (!GL_CheckShader (vertShader))
|
|
|
|
{
|
|
|
|
GL_DeleteShaderFunc (vertShader);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fragShader = GL_CreateShaderFunc (GL_FRAGMENT_SHADER);
|
|
|
|
GL_ShaderSourceFunc (fragShader, 1, &fragSource, NULL);
|
|
|
|
GL_CompileShaderFunc (fragShader);
|
|
|
|
if (!GL_CheckShader (fragShader))
|
|
|
|
{
|
|
|
|
GL_DeleteShaderFunc (vertShader);
|
|
|
|
GL_DeleteShaderFunc (fragShader);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
program = GL_CreateProgramFunc ();
|
|
|
|
GL_AttachShaderFunc (program, vertShader);
|
|
|
|
GL_DeleteShaderFunc (vertShader);
|
|
|
|
GL_AttachShaderFunc (program, fragShader);
|
|
|
|
GL_DeleteShaderFunc (fragShader);
|
|
|
|
|
|
|
|
for (i = 0; i < numbindings; i++)
|
|
|
|
{
|
|
|
|
GL_BindAttribLocationFunc (program, bindings[i].attrib, bindings[i].name);
|
|
|
|
}
|
|
|
|
|
|
|
|
GL_LinkProgramFunc (program);
|
|
|
|
|
|
|
|
if (!GL_CheckProgram (program))
|
|
|
|
{
|
|
|
|
GL_DeleteProgramFunc (program);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (gl_num_programs == (sizeof(gl_programs)/sizeof(GLuint)))
|
|
|
|
Host_Error ("gl_programs overflow");
|
|
|
|
|
|
|
|
gl_programs[gl_num_programs] = program;
|
|
|
|
gl_num_programs++;
|
|
|
|
|
|
|
|
return program;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
R_DeleteShaders
|
|
|
|
|
|
|
|
Deletes any GLSL programs that have been created.
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
void R_DeleteShaders (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!GLAlias_SupportsShaders())
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < gl_num_programs; i++)
|
|
|
|
{
|
|
|
|
GL_DeleteProgramFunc (gl_programs[i]);
|
|
|
|
gl_programs[i] = 0;
|
|
|
|
}
|
|
|
|
gl_num_programs = 0;
|
|
|
|
}
|
|
|
|
GLuint current_array_buffer, current_element_array_buffer;
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_BindBuffer
|
|
|
|
|
|
|
|
glBindBuffer wrapper
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
void GL_BindBuffer (GLenum target, GLuint buffer)
|
|
|
|
{
|
|
|
|
GLuint *cache;
|
|
|
|
|
|
|
|
if (!gl_vbo_able)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (target)
|
|
|
|
{
|
|
|
|
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 %d", (int)target);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*cache != buffer)
|
|
|
|
{
|
|
|
|
*cache = buffer;
|
|
|
|
GL_BindBufferFunc (target, *cache);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GL_ClearBufferBindings
|
|
|
|
|
|
|
|
This must be called if you do anything that could make the cached bindings
|
|
|
|
invalid (e.g. manually binding, destroying the context).
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
void GL_ClearBufferBindings ()
|
|
|
|
{
|
|
|
|
if (!gl_vbo_able)
|
|
|
|
return;
|
|
|
|
|
|
|
|
current_array_buffer = 0;
|
|
|
|
current_element_array_buffer = 0;
|
|
|
|
GL_BindBufferFunc (GL_ARRAY_BUFFER, 0);
|
|
|
|
GL_BindBufferFunc (GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
|
|
}
|