mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2025-02-09 01:01:07 +00:00
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
This commit is contained in:
parent
f4768566a1
commit
112c8b68b8
9 changed files with 939 additions and 24 deletions
229
Quake/gl_mesh.c
229
Quake/gl_mesh.c
|
@ -287,6 +287,7 @@ void BuildTris (void)
|
|||
alltris += pheader->numtris;
|
||||
}
|
||||
|
||||
void GL_MakeAliasModelDisplayLists_VBO (void);
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -346,5 +347,233 @@ void GL_MakeAliasModelDisplayLists (qmodel_t *m, aliashdr_t *hdr)
|
|||
for (i=0 ; i<paliashdr->numposes ; i++)
|
||||
for (j=0 ; j<numorder ; j++)
|
||||
*verts++ = poseverts[i][vertexorder[j]];
|
||||
|
||||
// ericw
|
||||
GL_MakeAliasModelDisplayLists_VBO ();
|
||||
}
|
||||
|
||||
unsigned int r_meshindexbuffer = 0;
|
||||
unsigned int r_meshvertexbuffer = 0;
|
||||
|
||||
/*
|
||||
================
|
||||
GL_MakeAliasModelDisplayLists_VBO
|
||||
|
||||
Saves data needed to build the VBO for this model on the hunk. Afterwards this
|
||||
is copied to Mod_Extradata.
|
||||
|
||||
Original code by MH from RMQEngine
|
||||
================
|
||||
*/
|
||||
void GL_MakeAliasModelDisplayLists_VBO (void)
|
||||
{
|
||||
int i, j;
|
||||
int maxverts_vbo;
|
||||
trivertx_t *verts;
|
||||
unsigned short *indexes;
|
||||
aliasmesh_t *desc;
|
||||
|
||||
if (!GLAlias_SupportsShaders())
|
||||
return;
|
||||
|
||||
// first, copy the verts onto the hunk
|
||||
verts = (trivertx_t *) Hunk_Alloc (paliashdr->numposes * paliashdr->numverts * sizeof(trivertx_t));
|
||||
paliashdr->vertexes = (byte *)verts - (byte *)paliashdr;
|
||||
for (i=0 ; i<paliashdr->numposes ; i++)
|
||||
for (j=0 ; j<paliashdr->numverts ; j++)
|
||||
verts[i*paliashdr->numverts + j] = poseverts[i][j];
|
||||
|
||||
// there can never be more than this number of verts and we just put them all on the hunk
|
||||
maxverts_vbo = pheader->numtris * 3;
|
||||
desc = (aliasmesh_t *) Hunk_Alloc (sizeof (aliasmesh_t) * maxverts_vbo);
|
||||
|
||||
// there will always be this number of indexes
|
||||
indexes = (unsigned short *) Hunk_Alloc (sizeof (unsigned short) * maxverts_vbo);
|
||||
|
||||
pheader->indexes = (intptr_t) indexes - (intptr_t) pheader;
|
||||
pheader->meshdesc = (intptr_t) desc - (intptr_t) pheader;
|
||||
pheader->numindexes = 0;
|
||||
pheader->numverts_vbo = 0;
|
||||
|
||||
for (i = 0; i < pheader->numtris; i++)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
int v;
|
||||
|
||||
// index into hdr->vertexes
|
||||
unsigned short vertindex = triangles[i].vertindex[j];
|
||||
|
||||
// basic s/t coords
|
||||
int s = stverts[vertindex].s;
|
||||
int t = stverts[vertindex].t;
|
||||
|
||||
// check for back side and adjust texcoord s
|
||||
if (!triangles[i].facesfront && stverts[vertindex].onseam) s += pheader->skinwidth / 2;
|
||||
|
||||
// see does this vert already exist
|
||||
for (v = 0; v < pheader->numverts_vbo; v++)
|
||||
{
|
||||
// it could use the same xyz but have different s and t
|
||||
if (desc[v].vertindex == vertindex && (int) desc[v].st[0] == s && (int) desc[v].st[1] == t)
|
||||
{
|
||||
// exists; emit an index for it
|
||||
indexes[pheader->numindexes++] = v;
|
||||
|
||||
// no need to check any more
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (v == pheader->numverts_vbo)
|
||||
{
|
||||
// doesn't exist; emit a new vert and index
|
||||
indexes[pheader->numindexes++] = pheader->numverts_vbo;
|
||||
|
||||
desc[pheader->numverts_vbo].vertindex = vertindex;
|
||||
desc[pheader->numverts_vbo].st[0] = s;
|
||||
desc[pheader->numverts_vbo++].st[1] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define NUMVERTEXNORMALS 162
|
||||
extern float r_avertexnormals[NUMVERTEXNORMALS][3];
|
||||
|
||||
GLuint r_meshvbo = 0;
|
||||
GLuint r_meshindexesvbo = 0;
|
||||
|
||||
/*
|
||||
================
|
||||
GLMesh_LoadVertexBuffers
|
||||
|
||||
Loop over all precached alias models, and upload them into one big VBO plus
|
||||
an GL_ELEMENT_ARRAY_BUFFER for the vertex indices.
|
||||
|
||||
Original code by MH from RMQEngine
|
||||
================
|
||||
*/
|
||||
void GLMesh_LoadVertexBuffers (void)
|
||||
{
|
||||
int j;
|
||||
qmodel_t *m;
|
||||
int totalindexes = 0;
|
||||
int totalvbosize = 0;
|
||||
|
||||
if (!GLAlias_SupportsShaders())
|
||||
return;
|
||||
|
||||
// pass 1 - count the sizes we need
|
||||
for (j = 1; j < MAX_MODELS; j++)
|
||||
{
|
||||
aliashdr_t *hdr;
|
||||
|
||||
if (!(m = cl.model_precache[j])) break;
|
||||
if (m->type != mod_alias) continue;
|
||||
|
||||
hdr = Mod_Extradata (m);
|
||||
|
||||
// ericw -- RMQEngine stored these vbo*ofs values in aliashdr_t, but we must not
|
||||
// mutate Mod_Extradata since it might be reloaded from disk, so I moved them to qmodel_t
|
||||
// (test case: roman1.bsp from arwop, 64mb heap)
|
||||
m->vboindexofs = (totalindexes * sizeof (unsigned short));
|
||||
totalindexes += hdr->numindexes;
|
||||
|
||||
m->vboxyzofs = totalvbosize;
|
||||
totalvbosize += (hdr->numposes * hdr->numverts_vbo * sizeof (meshxyz_t)); // ericw -- what RMQEngine called nummeshframes is called numposes in QuakeSpasm
|
||||
|
||||
m->vbostofs = totalvbosize;
|
||||
totalvbosize += (hdr->numverts_vbo * sizeof (meshst_t));
|
||||
}
|
||||
|
||||
if (!totalindexes) return;
|
||||
if (!totalvbosize) return;
|
||||
|
||||
// pass 2 - create the buffers
|
||||
GL_DeleteBuffersFunc (1, &r_meshindexesvbo);
|
||||
GL_GenBuffersFunc (1, &r_meshindexesvbo);
|
||||
GL_BindBufferFunc (GL_ELEMENT_ARRAY_BUFFER, r_meshindexesvbo);
|
||||
GL_BufferDataFunc (GL_ELEMENT_ARRAY_BUFFER, totalindexes * sizeof (unsigned short), NULL, GL_STATIC_DRAW);
|
||||
|
||||
GL_DeleteBuffersFunc (1, &r_meshvbo);
|
||||
GL_GenBuffersFunc (1, &r_meshvbo);
|
||||
GL_BindBufferFunc (GL_ARRAY_BUFFER, r_meshvbo);
|
||||
GL_BufferDataFunc (GL_ARRAY_BUFFER, totalvbosize, NULL, GL_STATIC_DRAW);
|
||||
|
||||
// pass 3 - fill in the buffers
|
||||
for (j = 1; j < MAX_MODELS; j++)
|
||||
{
|
||||
int f;
|
||||
aliashdr_t *hdr;
|
||||
aliasmesh_t *desc;
|
||||
meshst_t *st;
|
||||
float hscale, vscale;
|
||||
|
||||
if (!(m = cl.model_precache[j])) break;
|
||||
if (m->type != mod_alias) continue;
|
||||
|
||||
hdr = Mod_Extradata (m);
|
||||
desc = (aliasmesh_t *) ((byte *) hdr + hdr->meshdesc);
|
||||
|
||||
//johnfitz -- padded skins
|
||||
hscale = (float)hdr->skinwidth/(float)TexMgr_PadConditional(hdr->skinwidth);
|
||||
vscale = (float)hdr->skinheight/(float)TexMgr_PadConditional(hdr->skinheight);
|
||||
//johnfitz
|
||||
|
||||
GL_BufferSubDataFunc (GL_ELEMENT_ARRAY_BUFFER,
|
||||
m->vboindexofs,
|
||||
hdr->numindexes * sizeof (unsigned short),
|
||||
((byte *) hdr + hdr->indexes));
|
||||
|
||||
for (f = 0; f < hdr->numposes; f++) // ericw -- what RMQEngine called nummeshframes is called numposes in QuakeSpasm
|
||||
{
|
||||
int v;
|
||||
meshxyz_t *xyz = (meshxyz_t *) malloc (hdr->numverts_vbo * sizeof (meshxyz_t));
|
||||
trivertx_t *tv = (trivertx_t *) ((byte *) hdr + hdr->vertexes + (hdr->numverts * sizeof(trivertx_t) * f));
|
||||
|
||||
for (v = 0; v < hdr->numverts_vbo; v++)
|
||||
{
|
||||
trivertx_t trivert = tv[desc[v].vertindex];
|
||||
|
||||
xyz[v].xyz[0] = trivert.v[0];
|
||||
xyz[v].xyz[1] = trivert.v[1];
|
||||
xyz[v].xyz[2] = trivert.v[2];
|
||||
xyz[v].xyz[3] = 1; // need w 1 for 4 byte vertex compression
|
||||
|
||||
// map the normal coordinates in [-1..1] to [-127..127] and store in an unsigned char.
|
||||
// this introduces some error (less than 0.004), but the normals were very coarse
|
||||
// to begin with
|
||||
xyz[v].normal[0] = 127 * r_avertexnormals[trivert.lightnormalindex][0];
|
||||
xyz[v].normal[1] = 127 * r_avertexnormals[trivert.lightnormalindex][1];
|
||||
xyz[v].normal[2] = 127 * r_avertexnormals[trivert.lightnormalindex][2];
|
||||
xyz[v].normal[3] = 0; // unused; for 4-byte alignment
|
||||
}
|
||||
|
||||
GL_BufferSubDataFunc (GL_ARRAY_BUFFER,
|
||||
m->vboxyzofs + (f * hdr->numverts_vbo * sizeof (meshxyz_t)),
|
||||
hdr->numverts_vbo * sizeof (meshxyz_t),
|
||||
xyz);
|
||||
|
||||
free (xyz);
|
||||
}
|
||||
|
||||
st = (meshst_t *) malloc (hdr->numverts_vbo * sizeof (meshst_t));
|
||||
|
||||
for (f = 0; f < hdr->numverts_vbo; f++)
|
||||
{
|
||||
st[f].st[0] = hscale * ((float) desc[f].st[0] + 0.5f) / (float) hdr->skinwidth;
|
||||
st[f].st[1] = vscale * ((float) desc[f].st[1] + 0.5f) / (float) hdr->skinheight;
|
||||
}
|
||||
|
||||
GL_BufferSubDataFunc (GL_ARRAY_BUFFER,
|
||||
m->vbostofs,
|
||||
hdr->numverts_vbo * sizeof (meshst_t),
|
||||
st);
|
||||
|
||||
free (st);
|
||||
}
|
||||
|
||||
// invalidate the cached bindings
|
||||
GL_ClearBufferBindings ();
|
||||
}
|
||||
|
|
|
@ -282,6 +282,26 @@ Alias models are position independent, so the cache manager can move them.
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
//-- from RMQEngine
|
||||
// split out to keep vertex sizes down
|
||||
typedef struct aliasmesh_s
|
||||
{
|
||||
float st[2];
|
||||
unsigned short vertindex;
|
||||
} aliasmesh_t;
|
||||
|
||||
typedef struct meshxyz_s
|
||||
{
|
||||
byte xyz[4];
|
||||
signed char normal[4];
|
||||
} meshxyz_t;
|
||||
|
||||
typedef struct meshst_s
|
||||
{
|
||||
float st[2];
|
||||
} meshst_t;
|
||||
//--
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int firstpose;
|
||||
|
@ -332,6 +352,14 @@ typedef struct {
|
|||
int flags;
|
||||
float size;
|
||||
|
||||
//ericw -- used to populate vbo
|
||||
int numverts_vbo; // number of verts with unique x,y,z,s,t
|
||||
intptr_t meshdesc; // offset into extradata: numverts_vbo aliasmesh_t
|
||||
int numindexes;
|
||||
intptr_t indexes; // offset into extradata: numindexes unsigned shorts
|
||||
intptr_t vertexes; // offset into extradata: numposes*vertsperframe trivertx_t
|
||||
//ericw --
|
||||
|
||||
int numposes;
|
||||
int poseverts;
|
||||
int posedata; // numposes*poseverts trivert_t
|
||||
|
@ -449,6 +477,14 @@ typedef struct qmodel_s
|
|||
|
||||
int bspversion;
|
||||
|
||||
//
|
||||
// alias model
|
||||
//
|
||||
|
||||
int vboindexofs; // offset in vbo of the hdr->numindexes unsigned shorts
|
||||
int vboxyzofs; // offset in vbo of hdr->numposes*hdr->numverts_vbo meshxyz_t
|
||||
int vbostofs; // offset in vbo of hdr->numverts_vbo meshst_t
|
||||
|
||||
//
|
||||
// additional model data
|
||||
//
|
||||
|
|
|
@ -447,6 +447,11 @@ void R_SetupView (void)
|
|||
//
|
||||
//==============================================================================
|
||||
|
||||
static int R_EntitySortFunc(const void *a, const void *b)
|
||||
{
|
||||
return (*(entity_t **)a)->model - (*(entity_t **)b)->model;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_DrawEntitiesOnList
|
||||
|
@ -454,15 +459,21 @@ R_DrawEntitiesOnList
|
|||
*/
|
||||
void R_DrawEntitiesOnList (qboolean alphapass) //johnfitz -- added parameter
|
||||
{
|
||||
entity_t *entities_sorted[MAX_VISEDICTS];
|
||||
int i;
|
||||
|
||||
if (!r_drawentities.value)
|
||||
return;
|
||||
|
||||
//ericw -- draw the entities sorted by model, to eliminate redundant texture binding
|
||||
memcpy (entities_sorted, cl_visedicts, cl_numvisedicts * sizeof(entity_t *));
|
||||
qsort (entities_sorted, cl_numvisedicts, sizeof(entity_t *), R_EntitySortFunc);
|
||||
//ericw --
|
||||
|
||||
//johnfitz -- sprites are not a special case
|
||||
for (i=0 ; i<cl_numvisedicts ; i++)
|
||||
{
|
||||
currententity = cl_visedicts[i];
|
||||
currententity = entities_sorted[i];
|
||||
|
||||
//johnfitz -- if alphapass is true, draw only alpha entites this time
|
||||
//if alphapass is false, draw only nonalpha entities this time
|
||||
|
|
183
Quake/gl_rmisc.c
183
Quake/gl_rmisc.c
|
@ -274,6 +274,7 @@ void R_NewMap (void)
|
|||
|
||||
GL_BuildLightmaps ();
|
||||
GL_BuildVBOs ();
|
||||
GLMesh_LoadVertexBuffers ();
|
||||
|
||||
r_framecount = 0; //johnfitz -- paranoid?
|
||||
r_visframecount = 0; //johnfitz -- paranoid?
|
||||
|
@ -320,3 +321,185 @@ void R_TimeRefresh_f (void)
|
|||
void D_FlushCaches (void)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ qboolean gl_anisotropy_able = false; //johnfitz
|
|||
float gl_max_anisotropy; //johnfitz
|
||||
qboolean gl_texture_NPOT = false; //ericw
|
||||
qboolean gl_vbo_able = false; //ericw
|
||||
qboolean gl_glsl_able = false; //ericw
|
||||
GLint gl_max_texture_units = 0; //ericw
|
||||
|
||||
PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc = NULL; //johnfitz
|
||||
|
@ -107,9 +108,34 @@ PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc = NULL; //johnfitz
|
|||
PFNGLCLIENTACTIVETEXTUREARBPROC GL_ClientActiveTextureFunc = NULL; //ericw
|
||||
PFNGLBINDBUFFERARBPROC GL_BindBufferFunc = NULL; //ericw
|
||||
PFNGLBUFFERDATAARBPROC GL_BufferDataFunc = NULL; //ericw
|
||||
PFNGLBUFFERSUBDATAARBPROC GL_BufferSubDataFunc = NULL; //ericw
|
||||
PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc = NULL; //ericw
|
||||
PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc = NULL; //ericw
|
||||
|
||||
QS_PFNGLCREATESHADERPROC GL_CreateShaderFunc = NULL; //ericw
|
||||
QS_PFNGLDELETESHADERPROC GL_DeleteShaderFunc = NULL; //ericw
|
||||
QS_PFNGLDELETEPROGRAMPROC GL_DeleteProgramFunc = NULL; //ericw
|
||||
QS_PFNGLSHADERSOURCEPROC GL_ShaderSourceFunc = NULL; //ericw
|
||||
QS_PFNGLCOMPILESHADERPROC GL_CompileShaderFunc = NULL; //ericw
|
||||
QS_PFNGLGETSHADERIVPROC GL_GetShaderivFunc = NULL; //ericw
|
||||
QS_PFNGLGETSHADERINFOLOGPROC GL_GetShaderInfoLogFunc = NULL; //ericw
|
||||
QS_PFNGLGETPROGRAMIVPROC GL_GetProgramivFunc = NULL; //ericw
|
||||
QS_PFNGLGETPROGRAMINFOLOGPROC GL_GetProgramInfoLogFunc = NULL; //ericw
|
||||
QS_PFNGLCREATEPROGRAMPROC GL_CreateProgramFunc = NULL; //ericw
|
||||
QS_PFNGLATTACHSHADERPROC GL_AttachShaderFunc = NULL; //ericw
|
||||
QS_PFNGLLINKPROGRAMPROC GL_LinkProgramFunc = NULL; //ericw
|
||||
QS_PFNGLBINDATTRIBLOCATIONFUNC GL_BindAttribLocationFunc = NULL; //ericw
|
||||
QS_PFNGLUSEPROGRAMPROC GL_UseProgramFunc = NULL; //ericw
|
||||
QS_PFNGLGETATTRIBLOCATIONPROC GL_GetAttribLocationFunc = NULL; //ericw
|
||||
QS_PFNGLVERTEXATTRIBPOINTERPROC GL_VertexAttribPointerFunc = NULL; //ericw
|
||||
QS_PFNGLENABLEVERTEXATTRIBARRAYPROC GL_EnableVertexAttribArrayFunc = NULL; //ericw
|
||||
QS_PFNGLDISABLEVERTEXATTRIBARRAYPROC GL_DisableVertexAttribArrayFunc = NULL; //ericw
|
||||
QS_PFNGLGETUNIFORMLOCATIONPROC GL_GetUniformLocationFunc = NULL; //ericw
|
||||
QS_PFNGLUNIFORM1IPROC GL_Uniform1iFunc = NULL; //ericw
|
||||
QS_PFNGLUNIFORM1FPROC GL_Uniform1fFunc = NULL; //ericw
|
||||
QS_PFNGLUNIFORM3FPROC GL_Uniform3fFunc = NULL; //ericw
|
||||
QS_PFNGLUNIFORM4FPROC GL_Uniform4fFunc = NULL; //ericw
|
||||
|
||||
//====================================
|
||||
|
||||
//johnfitz -- new cvars
|
||||
|
@ -659,6 +685,7 @@ static void VID_Restart (void)
|
|||
GL_Init ();
|
||||
TexMgr_ReloadImages ();
|
||||
GL_BuildVBOs ();
|
||||
GLMesh_LoadVertexBuffers ();
|
||||
GL_SetupState ();
|
||||
|
||||
//warpimages needs to be recalculated
|
||||
|
@ -824,9 +851,10 @@ static void GL_CheckExtensions (void)
|
|||
{
|
||||
GL_BindBufferFunc = (PFNGLBINDBUFFERARBPROC) SDL_GL_GetProcAddress("glBindBufferARB");
|
||||
GL_BufferDataFunc = (PFNGLBUFFERDATAARBPROC) SDL_GL_GetProcAddress("glBufferDataARB");
|
||||
GL_BufferSubDataFunc = (PFNGLBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glBufferSubDataARB");
|
||||
GL_DeleteBuffersFunc = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB");
|
||||
GL_GenBuffersFunc = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB");
|
||||
if (GL_BindBufferFunc && GL_BufferDataFunc && GL_DeleteBuffersFunc && GL_GenBuffersFunc)
|
||||
if (GL_BindBufferFunc && GL_BufferDataFunc && GL_BufferSubDataFunc && GL_DeleteBuffersFunc && GL_GenBuffersFunc)
|
||||
{
|
||||
Con_Printf("FOUND: ARB_vertex_buffer_object\n");
|
||||
gl_vbo_able = true;
|
||||
|
@ -994,6 +1022,73 @@ static void GL_CheckExtensions (void)
|
|||
{
|
||||
Con_Warning ("texture_non_power_of_two not supported\n");
|
||||
}
|
||||
|
||||
// GLSL
|
||||
//
|
||||
if (COM_CheckParm("-noglsl"))
|
||||
Con_Warning ("GLSL disabled at command line\n");
|
||||
else if (gl_version_major >= 2)
|
||||
{
|
||||
GL_CreateShaderFunc = (QS_PFNGLCREATESHADERPROC) SDL_GL_GetProcAddress("glCreateShader");
|
||||
GL_DeleteShaderFunc = (QS_PFNGLDELETESHADERPROC) SDL_GL_GetProcAddress("glDeleteShader");
|
||||
GL_DeleteProgramFunc = (QS_PFNGLDELETEPROGRAMPROC) SDL_GL_GetProcAddress("glDeleteProgram");
|
||||
GL_ShaderSourceFunc = (QS_PFNGLSHADERSOURCEPROC) SDL_GL_GetProcAddress("glShaderSource");
|
||||
GL_CompileShaderFunc = (QS_PFNGLCOMPILESHADERPROC) SDL_GL_GetProcAddress("glCompileShader");
|
||||
GL_GetShaderivFunc = (QS_PFNGLGETSHADERIVPROC) SDL_GL_GetProcAddress("glGetShaderiv");
|
||||
GL_GetShaderInfoLogFunc = (QS_PFNGLGETSHADERINFOLOGPROC) SDL_GL_GetProcAddress("glGetShaderInfoLog");
|
||||
GL_GetProgramivFunc = (QS_PFNGLGETPROGRAMIVPROC) SDL_GL_GetProcAddress("glGetProgramiv");
|
||||
GL_GetProgramInfoLogFunc = (QS_PFNGLGETPROGRAMINFOLOGPROC) SDL_GL_GetProcAddress("glGetProgramInfoLog");
|
||||
GL_CreateProgramFunc = (QS_PFNGLCREATEPROGRAMPROC) SDL_GL_GetProcAddress("glCreateProgram");
|
||||
GL_AttachShaderFunc = (QS_PFNGLATTACHSHADERPROC) SDL_GL_GetProcAddress("glAttachShader");
|
||||
GL_LinkProgramFunc = (QS_PFNGLLINKPROGRAMPROC) SDL_GL_GetProcAddress("glLinkProgram");
|
||||
GL_BindAttribLocationFunc = (QS_PFNGLBINDATTRIBLOCATIONFUNC) SDL_GL_GetProcAddress("glBindAttribLocation");
|
||||
GL_UseProgramFunc = (QS_PFNGLUSEPROGRAMPROC) SDL_GL_GetProcAddress("glUseProgram");
|
||||
GL_GetAttribLocationFunc = (QS_PFNGLGETATTRIBLOCATIONPROC) SDL_GL_GetProcAddress("glGetAttribLocation");
|
||||
GL_VertexAttribPointerFunc = (QS_PFNGLVERTEXATTRIBPOINTERPROC) SDL_GL_GetProcAddress("glVertexAttribPointer");
|
||||
GL_EnableVertexAttribArrayFunc = (QS_PFNGLENABLEVERTEXATTRIBARRAYPROC) SDL_GL_GetProcAddress("glEnableVertexAttribArray");
|
||||
GL_DisableVertexAttribArrayFunc = (QS_PFNGLDISABLEVERTEXATTRIBARRAYPROC) SDL_GL_GetProcAddress("glDisableVertexAttribArray");
|
||||
GL_GetUniformLocationFunc = (QS_PFNGLGETUNIFORMLOCATIONPROC) SDL_GL_GetProcAddress("glGetUniformLocation");
|
||||
GL_Uniform1iFunc = (QS_PFNGLUNIFORM1IPROC) SDL_GL_GetProcAddress("glUniform1i");
|
||||
GL_Uniform1fFunc = (QS_PFNGLUNIFORM1FPROC) SDL_GL_GetProcAddress("glUniform1f");
|
||||
GL_Uniform3fFunc = (QS_PFNGLUNIFORM3FPROC) SDL_GL_GetProcAddress("glUniform3f");
|
||||
GL_Uniform4fFunc = (QS_PFNGLUNIFORM4FPROC) SDL_GL_GetProcAddress("glUniform4f");
|
||||
|
||||
if (GL_CreateShaderFunc &&
|
||||
GL_DeleteShaderFunc &&
|
||||
GL_DeleteProgramFunc &&
|
||||
GL_ShaderSourceFunc &&
|
||||
GL_CompileShaderFunc &&
|
||||
GL_GetShaderivFunc &&
|
||||
GL_GetShaderInfoLogFunc &&
|
||||
GL_GetProgramivFunc &&
|
||||
GL_GetProgramInfoLogFunc &&
|
||||
GL_CreateProgramFunc &&
|
||||
GL_AttachShaderFunc &&
|
||||
GL_LinkProgramFunc &&
|
||||
GL_BindAttribLocationFunc &&
|
||||
GL_UseProgramFunc &&
|
||||
GL_GetAttribLocationFunc &&
|
||||
GL_VertexAttribPointerFunc &&
|
||||
GL_EnableVertexAttribArrayFunc &&
|
||||
GL_DisableVertexAttribArrayFunc &&
|
||||
GL_GetUniformLocationFunc &&
|
||||
GL_Uniform1iFunc &&
|
||||
GL_Uniform1fFunc &&
|
||||
GL_Uniform3fFunc &&
|
||||
GL_Uniform4fFunc)
|
||||
{
|
||||
Con_Printf("FOUND: GLSL\n");
|
||||
gl_glsl_able = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Warning ("GLSL not available\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Warning ("OpenGL version < 2, GLSL not available\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1065,6 +1160,10 @@ static void GL_Init (void)
|
|||
Cbuf_AddText ("gl_clear 1");
|
||||
}
|
||||
//johnfitz
|
||||
|
||||
R_DeleteShaders ();
|
||||
GLAlias_CreateShaders ();
|
||||
GL_ClearBufferBindings ();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -165,11 +165,65 @@ extern qboolean gl_anisotropy_able;
|
|||
//ericw -- VBO
|
||||
extern PFNGLBINDBUFFERARBPROC GL_BindBufferFunc;
|
||||
extern PFNGLBUFFERDATAARBPROC GL_BufferDataFunc;
|
||||
extern PFNGLBUFFERSUBDATAARBPROC GL_BufferSubDataFunc;
|
||||
extern PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc;
|
||||
extern PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc;
|
||||
extern qboolean gl_vbo_able;
|
||||
//ericw
|
||||
|
||||
//ericw -- GLSL
|
||||
|
||||
// SDL 1.2 has a bug where it doesn't provide these typedefs on OS X!
|
||||
typedef GLuint (APIENTRYP QS_PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (APIENTRYP QS_PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP QS_PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP QS_PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
typedef void (APIENTRYP QS_PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP QS_PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP QS_PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef void (APIENTRYP QS_PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP QS_PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef GLuint (APIENTRYP QS_PFNGLCREATEPROGRAMPROC) (void);
|
||||
typedef void (APIENTRYP QS_PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP QS_PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP QS_PFNGLBINDATTRIBLOCATIONFUNC) (GLuint program, GLuint index, const GLchar *name);
|
||||
typedef void (APIENTRYP QS_PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||
typedef GLint (APIENTRYP QS_PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP QS_PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
typedef void (APIENTRYP QS_PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef void (APIENTRYP QS_PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef GLint (APIENTRYP QS_PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP QS_PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
|
||||
typedef void (APIENTRYP QS_PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
|
||||
typedef void (APIENTRYP QS_PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
|
||||
typedef void (APIENTRYP QS_PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||
|
||||
extern QS_PFNGLCREATESHADERPROC GL_CreateShaderFunc;
|
||||
extern QS_PFNGLDELETESHADERPROC GL_DeleteShaderFunc;
|
||||
extern QS_PFNGLDELETEPROGRAMPROC GL_DeleteProgramFunc;
|
||||
extern QS_PFNGLSHADERSOURCEPROC GL_ShaderSourceFunc;
|
||||
extern QS_PFNGLCOMPILESHADERPROC GL_CompileShaderFunc;
|
||||
extern QS_PFNGLGETSHADERIVPROC GL_GetShaderivFunc;
|
||||
extern QS_PFNGLGETSHADERINFOLOGPROC GL_GetShaderInfoLogFunc;
|
||||
extern QS_PFNGLGETPROGRAMIVPROC GL_GetProgramivFunc;
|
||||
extern QS_PFNGLGETPROGRAMINFOLOGPROC GL_GetProgramInfoLogFunc;
|
||||
extern QS_PFNGLCREATEPROGRAMPROC GL_CreateProgramFunc;
|
||||
extern QS_PFNGLATTACHSHADERPROC GL_AttachShaderFunc;
|
||||
extern QS_PFNGLLINKPROGRAMPROC GL_LinkProgramFunc;
|
||||
extern QS_PFNGLBINDATTRIBLOCATIONFUNC GL_BindAttribLocationFunc;
|
||||
extern QS_PFNGLUSEPROGRAMPROC GL_UseProgramFunc;
|
||||
extern QS_PFNGLGETATTRIBLOCATIONPROC GL_GetAttribLocationFunc;
|
||||
extern QS_PFNGLVERTEXATTRIBPOINTERPROC GL_VertexAttribPointerFunc;
|
||||
extern QS_PFNGLENABLEVERTEXATTRIBARRAYPROC GL_EnableVertexAttribArrayFunc;
|
||||
extern QS_PFNGLDISABLEVERTEXATTRIBARRAYPROC GL_DisableVertexAttribArrayFunc;
|
||||
extern QS_PFNGLGETUNIFORMLOCATIONPROC GL_GetUniformLocationFunc;
|
||||
extern QS_PFNGLUNIFORM1IPROC GL_Uniform1iFunc;
|
||||
extern QS_PFNGLUNIFORM1FPROC GL_Uniform1fFunc;
|
||||
extern QS_PFNGLUNIFORM3FPROC GL_Uniform3fFunc;
|
||||
extern QS_PFNGLUNIFORM4FPROC GL_Uniform4fFunc;
|
||||
extern qboolean gl_glsl_able;
|
||||
// ericw --
|
||||
|
||||
//ericw -- NPOT texture support
|
||||
extern qboolean gl_texture_NPOT;
|
||||
|
||||
|
@ -233,6 +287,11 @@ extern int gl_warpimagesize; //johnfitz -- for water warp
|
|||
|
||||
extern qboolean r_drawflat_cheatsafe, r_fullbright_cheatsafe, r_lightmap_cheatsafe, r_drawworld_cheatsafe; //johnfitz
|
||||
|
||||
typedef struct glsl_attrib_binding_s {
|
||||
const char *name;
|
||||
GLuint attrib;
|
||||
} glsl_attrib_binding_t;
|
||||
|
||||
//johnfitz -- fog functions called from outside gl_fog.c
|
||||
void Fog_ParseServerMessage (void);
|
||||
float *Fog_GetColor (void);
|
||||
|
@ -275,6 +334,7 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
|
|||
void R_RenderDlights (void);
|
||||
void GL_BuildLightmaps (void);
|
||||
void GL_BuildVBOs (void);
|
||||
void GLMesh_LoadVertexBuffers (void);
|
||||
void R_RebuildAllLightmaps (void);
|
||||
|
||||
int R_LightPoint (vec3_t p);
|
||||
|
@ -289,6 +349,11 @@ void R_DrawBrushModel_ShowTris (entity_t *e);
|
|||
void R_DrawAliasModel_ShowTris (entity_t *e);
|
||||
void R_DrawParticles_ShowTris (void);
|
||||
|
||||
GLuint GL_CreateProgram (const GLchar *vertSource, const GLchar *fragSource, int numbindings, const glsl_attrib_binding_t *bindings);
|
||||
void R_DeleteShaders (void);
|
||||
|
||||
qboolean GLAlias_SupportsShaders (void);
|
||||
void GLAlias_CreateShaders (void);
|
||||
void GL_DrawAliasShadow (entity_t *e);
|
||||
void DrawGLTriangleFan (glpoly_t *p);
|
||||
void DrawGLPoly (glpoly_t *p);
|
||||
|
@ -308,5 +373,7 @@ void R_ChainSurface (msurface_t *surf, texchain_t chain);
|
|||
void R_DrawTextureChains (qmodel_t *model, entity_t *ent, texchain_t chain);
|
||||
void R_DrawWorld_Water (void);
|
||||
|
||||
void GL_BindBuffer (GLenum target, GLuint buffer);
|
||||
void GL_ClearBufferBindings ();
|
||||
#endif /* __GLQUAKE_H */
|
||||
|
||||
|
|
275
Quake/r_alias.c
275
Quake/r_alias.c
|
@ -50,7 +50,7 @@ float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
|
|||
extern vec3_t lightspot;
|
||||
|
||||
float *shadedots = r_avertexnormal_dots[0];
|
||||
|
||||
vec3_t shadevector;
|
||||
float entalpha; //johnfitz
|
||||
|
||||
qboolean overbright; //johnfitz
|
||||
|
@ -67,6 +67,256 @@ typedef struct {
|
|||
} lerpdata_t;
|
||||
//johnfitz
|
||||
|
||||
static GLuint r_alias_program;
|
||||
|
||||
// uniforms used in vert shader
|
||||
static GLuint blendLoc;
|
||||
static GLuint shadevectorLoc;
|
||||
static GLuint lightColorLoc;
|
||||
|
||||
// uniforms used in frag shader
|
||||
static GLuint texLoc;
|
||||
static GLuint fullbrightTexLoc;
|
||||
static GLuint useFullbrightTexLoc;
|
||||
static GLuint useOverbrightLoc;
|
||||
|
||||
static const GLint pose1VertexAttrIndex = 0;
|
||||
static const GLint pose1NormalAttrIndex = 1;
|
||||
static const GLint pose2VertexAttrIndex = 2;
|
||||
static const GLint pose2NormalAttrIndex = 3;
|
||||
static const GLint texCoordsAttrIndex = 4;
|
||||
|
||||
extern GLuint r_meshvbo;
|
||||
extern GLuint r_meshindexesvbo;
|
||||
|
||||
/*
|
||||
=============
|
||||
GLARB_GetXYZOffset
|
||||
|
||||
Returns the offset of the first vertex's meshxyz_t.xyz in the vbo for the given
|
||||
model and pose.
|
||||
=============
|
||||
*/
|
||||
static void *GLARB_GetXYZOffset (aliashdr_t *hdr, int pose)
|
||||
{
|
||||
meshxyz_t dummy;
|
||||
int xyzoffs = ((char*)&dummy.xyz - (char*)&dummy);
|
||||
return (void *) (currententity->model->vboxyzofs + (hdr->numverts_vbo * pose * sizeof (meshxyz_t)) + xyzoffs);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
GLARB_GetNormalOffset
|
||||
|
||||
Returns the offset of the first vertex's meshxyz_t.normal in the vbo for the
|
||||
given model and pose.
|
||||
=============
|
||||
*/
|
||||
static void *GLARB_GetNormalOffset (aliashdr_t *hdr, int pose)
|
||||
{
|
||||
meshxyz_t dummy;
|
||||
int normaloffs = ((char*)&dummy.normal - (char*)&dummy);
|
||||
return (void *)(currententity->model->vboxyzofs + (hdr->numverts_vbo * pose * sizeof (meshxyz_t)) + normaloffs);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
GLAlias_SupportsShaders
|
||||
|
||||
Returns whether OpenGL has the capabilities we need for the shader path.
|
||||
=============
|
||||
*/
|
||||
qboolean GLAlias_SupportsShaders (void)
|
||||
{
|
||||
return gl_glsl_able && gl_vbo_able && gl_max_texture_units >= 3;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
GLAlias_GetUniformLocation
|
||||
=============
|
||||
*/
|
||||
static GLint GLAlias_GetUniformLocation (const char *name)
|
||||
{
|
||||
GLint location;
|
||||
location = GL_GetUniformLocationFunc(r_alias_program, name);
|
||||
if (location == -1)
|
||||
{
|
||||
Con_Warning("GL_GetUniformLocationFunc %s failed", name);
|
||||
r_alias_program = 0;
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
GLAlias_CreateShaders
|
||||
=============
|
||||
*/
|
||||
void GLAlias_CreateShaders (void)
|
||||
{
|
||||
const glsl_attrib_binding_t bindings[] = {
|
||||
{ "TexCoords", texCoordsAttrIndex },
|
||||
{ "Pose1Vert", pose1VertexAttrIndex },
|
||||
{ "Pose1Normal", pose1NormalAttrIndex },
|
||||
{ "Pose2Vert", pose2VertexAttrIndex },
|
||||
{ "Pose2Normal", pose2NormalAttrIndex }
|
||||
};
|
||||
|
||||
const GLchar *vertSource = \
|
||||
"#version 110\n"
|
||||
"\n"
|
||||
"uniform float Blend;\n"
|
||||
"uniform vec3 ShadeVector;\n"
|
||||
"uniform vec4 LightColor;\n"
|
||||
"attribute vec4 TexCoords; // only xy are used \n"
|
||||
"attribute vec4 Pose1Vert;\n"
|
||||
"attribute vec3 Pose1Normal;\n"
|
||||
"attribute vec4 Pose2Vert;\n"
|
||||
"attribute vec3 Pose2Normal;\n"
|
||||
"float r_avertexnormal_dot(vec3 vertexnormal) // from MH \n"
|
||||
"{\n"
|
||||
" float dot = dot(vertexnormal, ShadeVector);\n"
|
||||
" // wtf - this reproduces anorm_dots within as reasonable a degree of tolerance as the >= 0 case\n"
|
||||
" if (dot < 0.0)\n"
|
||||
" return 1.0 + dot * (13.0 / 44.0);\n"
|
||||
" else\n"
|
||||
" return 1.0 + dot;\n"
|
||||
"}\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_TexCoord[0] = TexCoords;\n"
|
||||
" vec4 lerpedVert = mix(Pose1Vert, Pose2Vert, Blend);\n"
|
||||
" gl_Position = gl_ModelViewProjectionMatrix * lerpedVert;\n"
|
||||
" float dot1 = r_avertexnormal_dot(Pose1Normal);\n"
|
||||
" float dot2 = r_avertexnormal_dot(Pose2Normal);\n"
|
||||
" gl_FrontColor = LightColor * vec4(vec3(mix(dot1, dot2, Blend)), 1.0);\n"
|
||||
" // fog\n"
|
||||
" vec3 ecPosition = vec3(gl_ModelViewMatrix * lerpedVert);\n"
|
||||
" gl_FogFragCoord = abs(ecPosition.z);\n"
|
||||
"}\n";
|
||||
|
||||
const GLchar *fragSource = \
|
||||
"#version 110\n"
|
||||
"\n"
|
||||
"uniform sampler2D Tex;\n"
|
||||
"uniform sampler2D FullbrightTex;\n"
|
||||
"uniform bool UseFullbrightTex;\n"
|
||||
"uniform bool UseOverbright;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 result = texture2D(Tex, gl_TexCoord[0].xy);\n"
|
||||
" result *= gl_Color;\n"
|
||||
" if (UseOverbright)\n"
|
||||
" result.rgb *= 2.0;\n"
|
||||
" if (UseFullbrightTex)\n"
|
||||
" result += texture2D(FullbrightTex, gl_TexCoord[0].xy);\n"
|
||||
" result = clamp(result, 0.0, 1.0);\n"
|
||||
" // apply GL_EXP2 fog (from the orange book)\n"
|
||||
" float fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);\n"
|
||||
" fog = clamp(fog, 0.0, 1.0);\n"
|
||||
" result = vec4(mix(gl_Fog.color.rgb, result.rgb, fog), result.a);\n"
|
||||
" gl_FragColor = result;\n"
|
||||
"}\n";
|
||||
|
||||
if (!GLAlias_SupportsShaders())
|
||||
return;
|
||||
|
||||
r_alias_program = GL_CreateProgram (vertSource, fragSource, sizeof(bindings)/sizeof(bindings[0]), bindings);
|
||||
|
||||
if (r_alias_program != 0)
|
||||
{
|
||||
// get uniform locations
|
||||
blendLoc = GLAlias_GetUniformLocation ("Blend");
|
||||
shadevectorLoc = GLAlias_GetUniformLocation ("ShadeVector");
|
||||
lightColorLoc = GLAlias_GetUniformLocation ("LightColor");
|
||||
texLoc = GLAlias_GetUniformLocation("Tex");
|
||||
fullbrightTexLoc = GLAlias_GetUniformLocation("FullbrightTex");
|
||||
useFullbrightTexLoc = GLAlias_GetUniformLocation("UseFullbrightTex");
|
||||
useOverbrightLoc = GLAlias_GetUniformLocation("UseOverbright");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
GL_DrawAliasFrame_GLSL -- ericw
|
||||
|
||||
Optimized alias model drawing codepath.
|
||||
Compared to the original GL_DrawAliasFrame, this makes 1 draw call,
|
||||
no vertex data is uploaded (it's already in the r_meshvbo and r_meshindexesvbo
|
||||
static VBOs), and lerping and lighting is done in the vertex shader.
|
||||
|
||||
Supports optional overbright, optional fullbright pixels.
|
||||
|
||||
Based on code by MH from RMQEngine
|
||||
=============
|
||||
*/
|
||||
void GL_DrawAliasFrame_GLSL (aliashdr_t *paliashdr, lerpdata_t lerpdata, gltexture_t *tx, gltexture_t *fb)
|
||||
{
|
||||
float blend;
|
||||
|
||||
if (lerpdata.pose1 != lerpdata.pose2)
|
||||
{
|
||||
blend = lerpdata.blend;
|
||||
}
|
||||
else // poses the same means either 1. the entity has paused its animation, or 2. r_lerpmodels is disabled
|
||||
{
|
||||
blend = 0;
|
||||
}
|
||||
|
||||
GL_UseProgramFunc (r_alias_program);
|
||||
|
||||
GL_BindBuffer (GL_ARRAY_BUFFER, r_meshvbo);
|
||||
GL_BindBuffer (GL_ELEMENT_ARRAY_BUFFER, r_meshindexesvbo);
|
||||
|
||||
GL_EnableVertexAttribArrayFunc (texCoordsAttrIndex);
|
||||
GL_EnableVertexAttribArrayFunc (pose1VertexAttrIndex);
|
||||
GL_EnableVertexAttribArrayFunc (pose2VertexAttrIndex);
|
||||
GL_EnableVertexAttribArrayFunc (pose1NormalAttrIndex);
|
||||
GL_EnableVertexAttribArrayFunc (pose2NormalAttrIndex);
|
||||
|
||||
GL_VertexAttribPointerFunc (texCoordsAttrIndex, 2, GL_FLOAT, GL_FALSE, 0, (void *)(intptr_t)currententity->model->vbostofs);
|
||||
GL_VertexAttribPointerFunc (pose1VertexAttrIndex, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof (meshxyz_t), GLARB_GetXYZOffset (paliashdr, lerpdata.pose1));
|
||||
GL_VertexAttribPointerFunc (pose2VertexAttrIndex, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof (meshxyz_t), GLARB_GetXYZOffset (paliashdr, lerpdata.pose2));
|
||||
// GL_TRUE to normalize the signed bytes to [-1 .. 1]
|
||||
GL_VertexAttribPointerFunc (pose1NormalAttrIndex, 4, GL_BYTE, GL_TRUE, sizeof (meshxyz_t), GLARB_GetNormalOffset (paliashdr, lerpdata.pose1));
|
||||
GL_VertexAttribPointerFunc (pose2NormalAttrIndex, 4, GL_BYTE, GL_TRUE, sizeof (meshxyz_t), GLARB_GetNormalOffset (paliashdr, lerpdata.pose2));
|
||||
|
||||
// set uniforms
|
||||
GL_Uniform1fFunc (blendLoc, blend);
|
||||
GL_Uniform3fFunc (shadevectorLoc, shadevector[0], shadevector[1], shadevector[2]);
|
||||
GL_Uniform4fFunc (lightColorLoc, lightcolor[0], lightcolor[1], lightcolor[2], entalpha);
|
||||
GL_Uniform1iFunc (texLoc, 0);
|
||||
GL_Uniform1iFunc (fullbrightTexLoc, 1);
|
||||
GL_Uniform1iFunc (useFullbrightTexLoc, (fb != NULL) ? 1 : 0);
|
||||
GL_Uniform1fFunc (useOverbrightLoc, overbright ? 1 : 0);
|
||||
|
||||
// set textures
|
||||
GL_SelectTexture (GL_TEXTURE0);
|
||||
GL_Bind (tx);
|
||||
|
||||
if (fb)
|
||||
{
|
||||
GL_SelectTexture (GL_TEXTURE1);
|
||||
GL_Bind (fb);
|
||||
}
|
||||
|
||||
// draw
|
||||
glDrawElements (GL_TRIANGLES, paliashdr->numindexes, GL_UNSIGNED_SHORT, (void *)(intptr_t)currententity->model->vboindexofs);
|
||||
|
||||
// clean up
|
||||
GL_DisableVertexAttribArrayFunc (texCoordsAttrIndex);
|
||||
GL_DisableVertexAttribArrayFunc (pose1VertexAttrIndex);
|
||||
GL_DisableVertexAttribArrayFunc (pose2VertexAttrIndex);
|
||||
GL_DisableVertexAttribArrayFunc (pose1NormalAttrIndex);
|
||||
GL_DisableVertexAttribArrayFunc (pose2NormalAttrIndex);
|
||||
|
||||
GL_UseProgramFunc (0);
|
||||
GL_SelectTexture (GL_TEXTURE0);
|
||||
|
||||
rs_aliaspasses += paliashdr->numtris;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
GL_DrawAliasFrame -- johnfitz -- rewritten to support colored light, lerping, entalpha, multitexture, and r_drawflat
|
||||
|
@ -319,6 +569,8 @@ void R_SetupAliasLighting (entity_t *e)
|
|||
vec3_t dist;
|
||||
float add;
|
||||
int i;
|
||||
int quantizedangle;
|
||||
float radiansangle;
|
||||
|
||||
R_LightPoint (e->origin);
|
||||
|
||||
|
@ -375,8 +627,19 @@ void R_SetupAliasLighting (entity_t *e)
|
|||
lightcolor[2] = 256.0f;
|
||||
}
|
||||
|
||||
shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
|
||||
VectorScale(lightcolor, 1.0f / 200.0f, lightcolor);
|
||||
quantizedangle = ((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1);
|
||||
|
||||
//ericw -- shadevector is passed to the shader to compute shadedots inside the
|
||||
//shader, see GLAlias_CreateShaders()
|
||||
radiansangle = (quantizedangle / 16.0) * 2.0 * 3.14159;
|
||||
shadevector[0] = cos(-radiansangle);
|
||||
shadevector[1] = sin(-radiansangle);
|
||||
shadevector[2] = 1;
|
||||
VectorNormalize(shadevector);
|
||||
//ericw --
|
||||
|
||||
shadedots = r_avertexnormal_dots[quantizedangle];
|
||||
VectorScale (lightcolor, 1.0f / 200.0f, lightcolor);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -500,6 +763,12 @@ void R_DrawAliasModel (entity_t *e)
|
|||
GL_DrawAliasFrame (paliashdr, lerpdata);
|
||||
glEnable (GL_TEXTURE_2D);
|
||||
}
|
||||
// call fast path if possible. if the shader compliation failed for some reason,
|
||||
// r_alias_program will be 0.
|
||||
else if (GLAlias_SupportsShaders() && (r_alias_program != 0))
|
||||
{
|
||||
GL_DrawAliasFrame_GLSL (paliashdr, lerpdata, tx, fb);
|
||||
}
|
||||
else if (overbright)
|
||||
{
|
||||
if (gl_texture_env_combine && gl_mtexable && gl_texture_env_add && fb) //case 1: everything in one pass
|
||||
|
|
|
@ -959,7 +959,7 @@ void GL_BuildLightmaps (void)
|
|||
=============================================================
|
||||
*/
|
||||
|
||||
static GLuint gl_bmodel_vbo = 0;
|
||||
GLuint gl_bmodel_vbo = 0;
|
||||
|
||||
/*
|
||||
==================
|
||||
|
@ -1021,23 +1021,9 @@ void GL_BuildVBOs (void)
|
|||
GL_BindBufferFunc (GL_ARRAY_BUFFER, gl_bmodel_vbo);
|
||||
GL_BufferDataFunc (GL_ARRAY_BUFFER, varray_bytes, varray, GL_STATIC_DRAW);
|
||||
free (varray);
|
||||
|
||||
// setup vertex array. this will need to move if we use vertex arrays for other things
|
||||
glVertexPointer (3, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0));
|
||||
glEnableClientState (GL_VERTEX_ARRAY);
|
||||
|
||||
GL_ClientActiveTextureFunc (GL_TEXTURE0_ARB);
|
||||
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 3);
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
GL_ClientActiveTextureFunc (GL_TEXTURE1_ARB);
|
||||
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 5);
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// TMU 2 is for fullbrights; same texture coordinates as TMU 0
|
||||
GL_ClientActiveTextureFunc (GL_TEXTURE2_ARB);
|
||||
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 3);
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// invalidate the cached bindings
|
||||
GL_ClearBufferBindings ();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -779,6 +779,8 @@ void R_DrawLightmapChains (void)
|
|||
}
|
||||
}
|
||||
|
||||
extern GLuint gl_bmodel_vbo;
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawTextureChains_Multitexture_VBO -- ericw
|
||||
|
@ -796,6 +798,27 @@ void R_DrawTextureChains_Multitexture_VBO (qmodel_t *model, entity_t *ent, texch
|
|||
int lastlightmap;
|
||||
gltexture_t *fullbright = NULL;
|
||||
|
||||
// Bind the buffers
|
||||
GL_BindBuffer (GL_ARRAY_BUFFER, gl_bmodel_vbo);
|
||||
GL_BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); // indices come from client memory!
|
||||
|
||||
// Setup vertex array pointers
|
||||
glVertexPointer (3, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0));
|
||||
glEnableClientState (GL_VERTEX_ARRAY);
|
||||
|
||||
GL_ClientActiveTextureFunc (GL_TEXTURE0_ARB);
|
||||
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 3);
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
GL_ClientActiveTextureFunc (GL_TEXTURE1_ARB);
|
||||
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 5);
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// TMU 2 is for fullbrights; same texture coordinates as TMU 0
|
||||
GL_ClientActiveTextureFunc (GL_TEXTURE2_ARB);
|
||||
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 3);
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// Setup TMU 1 (lightmap)
|
||||
GL_SelectTexture (GL_TEXTURE1_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
|
||||
|
@ -804,7 +827,7 @@ void R_DrawTextureChains_Multitexture_VBO (qmodel_t *model, entity_t *ent, texch
|
|||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, gl_overbright.value ? 2.0f : 1.0f);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
|
||||
// Setup TMU 2 (fullbrights)
|
||||
GL_SelectTexture (GL_TEXTURE2_ARB);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
|
||||
|
@ -873,6 +896,18 @@ void R_DrawTextureChains_Multitexture_VBO (qmodel_t *model, entity_t *ent, texch
|
|||
|
||||
GL_SelectTexture (GL_TEXTURE0_ARB);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
// Disable client state
|
||||
glDisableClientState (GL_VERTEX_ARRAY);
|
||||
|
||||
GL_ClientActiveTextureFunc (GL_TEXTURE0_ARB);
|
||||
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
GL_ClientActiveTextureFunc (GL_TEXTURE1_ARB);
|
||||
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
GL_ClientActiveTextureFunc (GL_TEXTURE2_ARB);
|
||||
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue