GLSL vertex shader for alias model lighting and lerping

This commit is contained in:
Eric Wasylishen 2014-10-22 20:20:05 -06:00
parent cfea94ddc2
commit fd3c4d2613
8 changed files with 645 additions and 5 deletions

View file

@ -287,6 +287,7 @@ void BuildTris (void)
alltris += pheader->numtris;
}
void GL_MakeAliasModelDisplayLists_VBO (void);
/*
================
@ -346,5 +347,218 @@ 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
Original code by MH from RMQEngine
================
*/
void GL_MakeAliasModelDisplayLists_VBO (void)
{
int i, j;
int maxverts_vbo;
trivertx_t *verts;
aliasmesh_t *desc;
unsigned short *indexes;
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
Original code by MH from RMQEngine
================
*/
void GLMesh_LoadVertexBuffers (void)
{
int j;
qmodel_t *m;
int totalindexes = 0;
int totalvbosize = 0;
byte *vbodata;
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);
vbodata = GL_MapBufferFunc (GL_ARRAY_BUFFER, GL_READ_WRITE);
// 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 *) (vbodata + m->vboxyzofs + (f * 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
}
}
st = (meshst_t *) (vbodata + m->vbostofs);
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_UnmapBufferFunc (GL_ARRAY_BUFFER);
GL_BindBufferFunc (GL_ELEMENT_ARRAY_BUFFER, 0);
GL_BindBufferFunc (GL_ARRAY_BUFFER, 0);
}

View file

@ -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
//

View file

@ -274,6 +274,7 @@ void R_NewMap (void)
GL_BuildLightmaps ();
GL_BuildVBOs ();
GLMesh_LoadVertexBuffers ();
r_framecount = 0; //johnfitz -- paranoid?
r_visframecount = 0; //johnfitz -- paranoid?

View file

@ -95,6 +95,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
@ -102,9 +103,32 @@ 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
PFNGLMAPBUFFERARBPROC GL_MapBufferFunc = NULL; //ericw
PFNGLUNMAPBUFFERARBPROC GL_UnmapBufferFunc = NULL; //ericw
PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc = NULL; //ericw
PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc = NULL; //ericw
QS_PFNGLCREATESHADERPROC GL_CreateShaderFunc = 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_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_PFNGLUNIFORM1FPROC GL_Uniform1fFunc = NULL; //ericw
QS_PFNGLUNIFORM3FPROC GL_Uniform3fFunc = NULL; //ericw
QS_PFNGLUNIFORM4FPROC GL_Uniform4fFunc = NULL; //ericw
//====================================
//johnfitz -- new cvars
@ -654,6 +678,7 @@ static void VID_Restart (void)
GL_Init ();
TexMgr_ReloadImages ();
GL_BuildVBOs ();
GLMesh_LoadVertexBuffers ();
GL_SetupState ();
//warpimages needs to be recalculated
@ -819,9 +844,12 @@ 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_MapBufferFunc = (PFNGLMAPBUFFERARBPROC) SDL_GL_GetProcAddress("glMapBufferARB");
GL_UnmapBufferFunc = (PFNGLUNMAPBUFFERARBPROC) SDL_GL_GetProcAddress("glUnmapBufferARB");
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_MapBufferFunc && GL_UnmapBufferFunc && GL_DeleteBuffersFunc && GL_GenBuffersFunc)
{
Con_Printf("FOUND: ARB_vertex_buffer_object\n");
gl_vbo_able = true;
@ -989,6 +1017,63 @@ 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)
Con_Warning ("OpenGL version < 2, skipping GLSL check\n");
else
{
GL_CreateShaderFunc = (QS_PFNGLCREATESHADERPROC) SDL_GL_GetProcAddress("glCreateShader");
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_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_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_ShaderSourceFunc &&
GL_CompileShaderFunc &&
GL_GetShaderivFunc &&
GL_GetShaderInfoLogFunc &&
GL_GetProgramivFunc &&
GL_GetProgramInfoLogFunc &&
GL_CreateProgramFunc &&
GL_AttachShaderFunc &&
GL_LinkProgramFunc &&
GL_UseProgramFunc &&
GL_GetAttribLocationFunc &&
GL_VertexAttribPointerFunc &&
GL_EnableVertexAttribArrayFunc &&
GL_DisableVertexAttribArrayFunc &&
GL_GetUniformLocationFunc &&
GL_Uniform1fFunc &&
GL_Uniform3fFunc &&
GL_Uniform4fFunc)
{
Con_Printf("FOUND: GLSL\n");
gl_glsl_able = true;
}
else
{
Con_Warning ("GLSL not available\n");
}
}
}
/*
@ -1050,6 +1135,8 @@ static void GL_Init (void)
Cbuf_AddText ("gl_clear 1");
}
//johnfitz
GLAlias_CreateShaders (); //ericw
}
/*

View file

@ -167,11 +167,59 @@ extern qboolean gl_anisotropy_able;
//ericw -- VBO
extern PFNGLBINDBUFFERARBPROC GL_BindBufferFunc;
extern PFNGLBUFFERDATAARBPROC GL_BufferDataFunc;
extern PFNGLBUFFERSUBDATAARBPROC GL_BufferSubDataFunc;
extern PFNGLMAPBUFFERARBPROC GL_MapBufferFunc;
extern PFNGLUNMAPBUFFERARBPROC GL_UnmapBufferFunc;
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_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_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_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_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_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_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;
@ -277,6 +325,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);
@ -291,6 +340,8 @@ void R_DrawBrushModel_ShowTris (entity_t *e);
void R_DrawAliasModel_ShowTris (entity_t *e);
void R_DrawParticles_ShowTris (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);

View file

@ -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,215 @@ typedef struct {
} lerpdata_t;
//johnfitz
extern GLuint r_meshvbo;
extern GLuint r_meshindexesvbo;
static GLuint shader;
static GLuint program;
static GLuint blendLoc;
static GLuint shadevectorLoc;
static GLuint lightColorLoc;
static GLint pose1VertexAttrIndex;
static GLint pose1NormalAttrIndex;
static GLint pose2VertexAttrIndex;
static GLint pose2NormalAttrIndex;
qboolean GLAlias_SupportsShaders (void)
{
return gl_glsl_able && gl_vbo_able && gl_max_texture_units >= 3;
}
void GLAlias_CreateShaders (void)
{
GLint status;
const GLchar *source = \
"#version 110\n"
"\n"
"uniform float Blend;\n"
"uniform vec3 ShadeVector;\n"
"uniform vec4 LightColor;\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] = gl_MultiTexCoord0;\n"
" gl_TexCoord[1] = gl_MultiTexCoord0;\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";
if (!GLAlias_SupportsShaders())
return;
shader = GL_CreateShaderFunc(GL_VERTEX_SHADER);
GL_ShaderSourceFunc(shader, 1, &source, NULL);
GL_CompileShaderFunc(shader);
GL_GetShaderivFunc(shader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
static char infolog[65536];
GL_GetShaderInfoLogFunc (shader, 65536, NULL, infolog);
printf("Shader info log: %s\n", infolog);
Sys_Error("Shader failed to compile");
}
// create program
program = GL_CreateProgramFunc();
GL_AttachShaderFunc(program, shader);
GL_LinkProgramFunc(program);
GL_GetProgramivFunc(program, GL_LINK_STATUS, &status);
if (status != GL_TRUE)
{
Sys_Error("Program failed to link");
}
// get uniform location
blendLoc = GL_GetUniformLocationFunc(program, "Blend");
if (blendLoc == -1)
{
Sys_Error("GL_GetUniformLocationFunc Blend failed");
}
shadevectorLoc = GL_GetUniformLocationFunc(program, "ShadeVector");
if (shadevectorLoc == -1)
{
Sys_Error("GL_GetUniformLocationFunc shadevector failed");
}
lightColorLoc = GL_GetUniformLocationFunc(program, "LightColor");
if (lightColorLoc == -1)
{
Sys_Error("GL_GetUniformLocationFunc LightColor failed");
}
// get attributes
pose1VertexAttrIndex = GL_GetAttribLocationFunc(program, "Pose1Vert");
pose1NormalAttrIndex = GL_GetAttribLocationFunc(program, "Pose1Normal");
pose2VertexAttrIndex = GL_GetAttribLocationFunc(program, "Pose2Vert");
pose2NormalAttrIndex = GL_GetAttribLocationFunc(program, "Pose2Normal");
}
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);
}
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);
}
/*
=============
GL_DrawAliasFrame_GLSL -- ericw
Based on code by MH from RMQEngine
=============
*/
void GL_DrawAliasFrame_GLSL (aliashdr_t *paliashdr, lerpdata_t lerpdata)
{
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(program);
GL_BindBufferFunc (GL_ARRAY_BUFFER_ARB, r_meshvbo);
GL_BindBufferFunc (GL_ELEMENT_ARRAY_BUFFER_ARB, r_meshindexesvbo);
GL_VertexAttribPointerFunc (pose1VertexAttrIndex, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof (meshxyz_t), GLARB_GetXYZOffset (paliashdr, lerpdata.pose1));
GL_EnableVertexAttribArrayFunc (pose1VertexAttrIndex);
GL_VertexAttribPointerFunc (pose2VertexAttrIndex, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof (meshxyz_t), GLARB_GetXYZOffset (paliashdr, lerpdata.pose2));
GL_EnableVertexAttribArrayFunc (pose2VertexAttrIndex);
GL_ClientActiveTextureFunc (GL_TEXTURE0_ARB);
glTexCoordPointer (2, GL_FLOAT, 0, (void *)(intptr_t)currententity->model->vbostofs);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
GL_ClientActiveTextureFunc (GL_TEXTURE1_ARB);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
GL_ClientActiveTextureFunc (GL_TEXTURE2_ARB);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
// GL_TRUE to normalize the signed bytes to [-1 .. 1]
GL_VertexAttribPointerFunc (pose1NormalAttrIndex, 3, GL_BYTE, GL_TRUE, sizeof (meshxyz_t), GLARB_GetNormalOffset (paliashdr, lerpdata.pose1));
GL_EnableVertexAttribArrayFunc (pose1NormalAttrIndex);
GL_VertexAttribPointerFunc (pose2NormalAttrIndex, 3, GL_BYTE, GL_TRUE, sizeof (meshxyz_t), GLARB_GetNormalOffset (paliashdr, lerpdata.pose2));
GL_EnableVertexAttribArrayFunc (pose2NormalAttrIndex);
// 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);
// draw
glDrawElements (GL_TRIANGLES, paliashdr->numindexes, GL_UNSIGNED_SHORT, (void *)(intptr_t)currententity->model->vboindexofs);
// clean up
GL_DisableVertexAttribArrayFunc (pose1VertexAttrIndex);
GL_DisableVertexAttribArrayFunc (pose2VertexAttrIndex);
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);
GL_DisableVertexAttribArrayFunc (pose1NormalAttrIndex);
GL_DisableVertexAttribArrayFunc (pose2NormalAttrIndex);
GL_UseProgramFunc (0);
rs_aliaspasses += paliashdr->numtris;
}
/*
=============
GL_DrawAliasFrame -- johnfitz -- rewritten to support colored light, lerping, entalpha, multitexture, and r_drawflat
@ -82,6 +291,13 @@ void GL_DrawAliasFrame (aliashdr_t *paliashdr, lerpdata_t lerpdata)
float blend, iblend;
qboolean lerping;
// call fast path if possible
if (GLAlias_SupportsShaders() && !r_drawflat_cheatsafe && shading)
{
GL_DrawAliasFrame_GLSL (paliashdr, lerpdata);
return;
}
if (lerpdata.pose1 != lerpdata.pose2)
{
lerping = true;
@ -319,7 +535,9 @@ void R_SetupAliasLighting (entity_t *e)
vec3_t dist;
float add;
int i;
int quantizedangle;
float radiansangle;
R_LightPoint (e->origin);
//add dlights
@ -374,8 +592,19 @@ void R_SetupAliasLighting (entity_t *e)
lightcolor[1] = 256.0f;
lightcolor[2] = 256.0f;
}
quantizedangle = ((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1);
shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
// ericw -- passed to shader, used to reproduce shadedots table lookup
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);
}

View file

@ -959,7 +959,7 @@ void GL_BuildLightmaps (void)
=============================================================
*/
static GLuint gl_bmodel_vbo = 0;
GLuint gl_bmodel_vbo = 0;
/*
==================

View file

@ -779,6 +779,8 @@ void R_DrawLightmapChains (void)
}
}
extern GLuint gl_bmodel_vbo;
/*
================
R_DrawTextureChains_Multitexture_VBO -- ericw
@ -796,6 +798,26 @@ void R_DrawTextureChains_Multitexture_VBO (qmodel_t *model, entity_t *ent, texch
int lastlightmap;
gltexture_t *fullbright = NULL;
GL_BindBufferFunc (GL_ARRAY_BUFFER_ARB, gl_bmodel_vbo);
GL_BindBufferFunc (GL_ELEMENT_ARRAY_BUFFER_ARB, 0); // so we pull them from client memory!
// 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);
// Setup TMU 1 (lightmap)
GL_SelectTexture (GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);