vid_gl_contex_gles cvar mostly works. Most of the shaders still have no program attached to them - pics+font have it disabled due to nvidia driver crashes, I wanna check if ATI crashes too.

Merged GL+D3D builds should work now too, but still not stable if you vid_restart too much.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3716 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2011-01-23 03:44:49 +00:00
parent 562f549357
commit 8fc0df0f44
20 changed files with 1328 additions and 622 deletions

View file

@ -2552,7 +2552,12 @@ void Surf_BuildLightmaps (void)
case QR_OPENGL:
/*favour bgra if the gpu supports it, otherwise use rgb only if it'll be used*/
lightmap_bgra = false;
if (gl_config.glversion >= 1.2)
if (gl_config.gles)
{
lightmap_bytes = 3;
lightmap_bgra = false;
}
else if (gl_config.glversion >= 1.2)
{
/*the more common case*/
lightmap_bytes = 4;

View file

@ -628,7 +628,7 @@ void GLV_CalcBlend (float *hw_blend)
}
else
{
if (/*j == CSHIFT_BONUS || j == CSHIFT_DAMAGE ||*/ gl_nohwblend.ival)
if (j == CSHIFT_BONUS || j == CSHIFT_DAMAGE || gl_nohwblend.ival)
blend = sw_blend;
else //powerup or contents?
blend = hw_blend;

View file

@ -1224,23 +1224,23 @@ void Matrix4_Projection2(float *proj, float fovx, float fovy, float neard)
proj[15] = 0;
}
void Matrix4_Orthographic(float *proj, float xmin, float xmax, float ymax, float ymin,
void Matrix4_Orthographic(float *proj, float xmin, float xmax, float ymin, float ymax,
float znear, float zfar)
{
proj[0] = 2/(xmax-xmin);
proj[4] = 0;
proj[8] = 0;
proj[12] = (xmax+xmin)/(xmax-xmin);
proj[12] = -(xmax+xmin)/(xmax-xmin);
proj[1] = 0;
proj[5] = 2/(ymax-ymin);
proj[9] = 0;
proj[13] = (ymax+ymin)/(ymax-ymin);
proj[13] = -(ymax+ymin)/(ymax-ymin);
proj[2] = 0;
proj[6] = 0;
proj[10] = -2/(zfar-znear);
proj[14] = (zfar+znear)/(zfar-znear);
proj[14] = -(zfar+znear)/(zfar-znear);
proj[3] = 0;
proj[7] = 0;

View file

@ -1231,6 +1231,19 @@ rendererinfo_t d3drendererinfo =
D3D9_SCR_UpdateScreen,
D3DBE_SelectMode,
D3DBE_DrawMesh_List,
D3DBE_DrawMesh_Single,
D3DBE_SubmitBatch,
D3DBE_GetTempBatch,
D3DBE_DrawWorld,
D3DBE_Init,
D3DBE_GenBrushModelVBO,
D3DBE_ClearVBO,
D3DBE_UploadAllLightmaps,
NULL,
D3DBE_LightCullModel,
"no more"
};

View file

@ -251,7 +251,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../d3d9;../libs/dxsdk9/include;../libs/dxsdk7/include"
AdditionalIncludeDirectories="../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../d3d9;../libs/dxsdk9/include;../libs/dxsdk7/include"
PreprocessorDefinitions="_DEBUG;D3DQUAKE;WIN32;_WINDOWS"
RuntimeLibrary="1"
FloatingPointModel="2"
@ -1478,7 +1478,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../libs/speex,..\client,../libs/freetype2/include,../common,../server,../gl,../sw,../qclib,../libs,../libs/dxsdk7/include"
AdditionalIncludeDirectories="../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../libs/dxsdk9/include;../libs/dxsdk7/include"
PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;GLQUAKE;USE_D3D;D3DQUAKE"
RuntimeLibrary="1"
FloatingPointModel="2"
@ -10972,14 +10972,6 @@
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|x64"
ExcludedFromBuild="true"
@ -10990,6 +10982,14 @@
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|x64"
ExcludedFromBuild="true"
@ -14105,23 +14105,8 @@
<File
RelativePath="..\client\snd_al.c"
>
<FileConfiguration
Name="MinGLDebug|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLDebug|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
@ -14135,20 +14120,6 @@
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|x64"
ExcludedFromBuild="true"
@ -14207,7 +14178,6 @@
</FileConfiguration>
<FileConfiguration
Name="MDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
@ -14221,13 +14191,6 @@
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\client\snd_directx.c"

View file

@ -15,7 +15,7 @@
#define LIGHTPASS_GLSL_SHARED "\
varying vec2 tcbase;\n\
varying vec3 lightvector;\n\
#if defined(SPECULAR) || defined(USEOFFSETMAPPING)\n\
#if defined(SPECULAR) || defined(OFFSETMAPPING)\n\
varying vec3 eyevector;\n\
#endif\n\
#ifdef PCF\n\
@ -29,7 +29,7 @@ uniform mat4 entmatrix;\n\
\
uniform vec3 lightposition;\n\
\
#if defined(SPECULAR) || defined(USEOFFSETMAPPING)\n\
#if defined(SPECULAR) || defined(OFFSETMAPPING)\n\
uniform vec3 eyeposition;\n\
#endif\n\
\
@ -44,7 +44,7 @@ void main (void)\n\
lightvector.y = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n\
lightvector.z = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n\
\
#if defined(SPECULAR)||defined(USEOFFSETMAPPING)\n\
#if defined(SPECULAR)||defined(OFFSETMAPPING)\n\
vec3 eyeminusvertex = eyeposition - gl_Vertex.xyz;\n\
eyevector.x = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n\
eyevector.y = -dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n\
@ -127,7 +127,7 @@ void main (void)\n\
#define LIGHTPASS_GLSL_FRAGMENT "\
#ifdef FRAGMENT_SHADER\n\
uniform sampler2D baset;\n\
#if defined(BUMP) || defined(SPECULAR) || defined(USEOFFSETMAPPING)\n\
#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n\
uniform sampler2D bumpt;\n\
#endif\n\
#ifdef SPECULAR\n\
@ -148,14 +148,14 @@ uniform sampler2DShadow shadowmap;\n\
uniform float lightradius;\n\
uniform vec3 lightcolour;\n\
\
#ifdef USEOFFSETMAPPING\n\
#ifdef OFFSETMAPPING\n\
uniform float offsetmapping_scale;\n\
#endif\n\
\
\
void main (void)\n\
{\n\
#ifdef USEOFFSETMAPPING\n\
#ifdef OFFSETMAPPING\n\
vec2 OffsetVector = normalize(eyevector).xy * offsetmapping_scale * vec2(1, -1);\n\
vec2 foo = tcbase;\n\
#define tcbase foo\n\
@ -320,12 +320,6 @@ static const char PCFPASS_SHADER[] = "\
extern cvar_t r_glsl_offsetmapping, r_noportals;
#ifdef _DEBUG
#define checkerror() if (qglGetError()) Con_Printf("Error detected at line %s:%i\n", __FILE__, __LINE__)
#else
#define checkerror()
#endif
static void BE_SendPassBlendAndDepth(unsigned int sbits);
void GLBE_SubmitBatch(batch_t *batch);
@ -354,6 +348,8 @@ struct {
texid_t curshadowmap;
unsigned int shaderbits;
unsigned int sha_attr;
int currentprogram;
vbo_t dummyvbo;
int currentvbo;
@ -361,6 +357,7 @@ struct {
mesh_t **meshes;
unsigned int meshcount;
float modelviewmatrix[16];
int pendingvertexvbo;
void *pendingvertexpointer;
@ -372,7 +369,7 @@ struct {
texid_t temptexture;
};
//exterior state
//exterior state (paramters)
struct {
backendmode_t mode;
unsigned int flags;
@ -516,6 +513,42 @@ void GL_BindType(int type, texid_t texnum)
bindTexFunc (type, texnum.num);
}
static void BE_EnableShaderAttributes(unsigned int newm)
{
unsigned int i;
if (newm == shaderstate.sha_attr)
return;
for (i = 0; i < 8; i++)
if ((newm^shaderstate.sha_attr) & (1u<<i))
{
if (newm & (1u<<i))
qglEnableVertexAttribArray(i);
else
qglDisableVertexAttribArray(i);
}
shaderstate.sha_attr = newm;
}
void GL_SelectProgram(int program)
{
if (shaderstate.currentprogram != program)
{
qglUseProgramObjectARB(program);
shaderstate.currentprogram = program;
}
}
static void GL_DeSelectProgram(void)
{
if (shaderstate.currentprogram != 0)
{
qglUseProgramObjectARB(0);
shaderstate.currentprogram = 0;
/*if disabling a program, we need to kill off custom attributes*/
BE_EnableShaderAttributes(0);
}
}
void GL_CullFace(unsigned int sflags)
{
#ifndef FORCESTATE
@ -607,7 +640,6 @@ static void RevertToKnownState(void)
GL_SelectVBO(0);
GL_SelectEBO(0);
checkerror();
while(shaderstate.lastpasstmus>0)
{
GL_SelectTexture(--shaderstate.lastpasstmus);
@ -617,7 +649,6 @@ static void RevertToKnownState(void)
GL_SelectTexture(0);
qglEnableClientState(GL_VERTEX_ARRAY);
checkerror();
GL_TexEnv(GL_REPLACE);
@ -845,8 +876,6 @@ void GLBE_Init(void)
int i;
double t;
checkerror();
be_maxpasses = gl_mtexarbable;
for (i = 0; i < FTABLE_SIZE; i++)
@ -882,7 +911,9 @@ void GLBE_Init(void)
shaderstate.shaderbits = ~0;
BE_SendPassBlendAndDepth(0);
qglEnableClientState(GL_VERTEX_ARRAY);
if (qglEnableClientState)
qglEnableClientState(GL_VERTEX_ARRAY);
currententity = &r_worldentity;
}
@ -1646,7 +1677,6 @@ static void GenerateColourMods(const shaderpass_t *pass)
qglDisableClientState(GL_COLOR_ARRAY);
qglColor4fv(scol);
qglShadeModel(GL_FLAT);
checkerror();
}
else
{
@ -1682,7 +1712,6 @@ static void GenerateColourMods(const shaderpass_t *pass)
ambientlight[2]*0.5+shadelight[2],
shaderstate.curentity->shaderRGBAf[3]);
qglShadeModel(GL_FLAT);
checkerror();
return;
}
}
@ -1982,7 +2011,7 @@ static void BE_SubmitMeshChain(void)
}
qglDrawRangeElements(GL_TRIANGLES, startv, endv, endi-starti, GL_INDEX_TYPE, shaderstate.sourcevbo->indicies + starti);
}
}
/*
if (qglUnlockArraysEXT)
qglUnlockArraysEXT();
@ -2008,10 +2037,8 @@ static void DrawPass(const shaderpass_t *pass)
if (i == lastpass)
return;
checkerror();
BE_SendPassBlendAndDepth(pass[i].shaderbits);
GenerateColourMods(pass+i);
checkerror();
tmu = 0;
for (; i < lastpass; i++)
{
@ -2023,10 +2050,8 @@ static void DrawPass(const shaderpass_t *pass)
continue;
GL_MBind(tmu, Shader_TextureForPass(pass+i));
checkerror();
BE_GeneratePassTC(pass, i);
checkerror();
if (tmu >= shaderstate.lastpasstmus)
{
qglEnable(GL_TEXTURE_2D);
@ -2058,10 +2083,8 @@ static void DrawPass(const shaderpass_t *pass)
GL_TexEnv(GL_MODULATE);
break;
}
checkerror();
tmu++;
}
checkerror();
for (i = tmu; i < shaderstate.lastpasstmus; i++)
{
@ -2073,62 +2096,72 @@ static void DrawPass(const shaderpass_t *pass)
GL_ApplyVertexPointer();
BE_SubmitMeshChain();
checkerror();
}
static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pass)
extern avec3_t shadevector, shadelight, ambientlight;
static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned int perm)
{
const shader_t *s = shader;
int i;
vec3_t param3;
float m16[16];
int r, g, b;
int perm;
perm = 0;
if (TEXVALID(shaderstate.curtexnums->bump) && s->programhandle[perm|PERMUTATION_BUMPMAP].glsl)
perm |= PERMUTATION_BUMPMAP;
if (TEXVALID(shaderstate.curtexnums->specular) && s->programhandle[perm|PERMUTATION_SPECULAR].glsl)
perm |= PERMUTATION_SPECULAR;
if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && s->programhandle[perm|PERMUTATION_OFFSET].glsl)
perm |= PERMUTATION_OFFSET;
GLSlang_UseProgram(s->programhandle[perm].glsl);
BE_SendPassBlendAndDepth(pass->shaderbits);
GenerateColourMods(pass);
for ( i = 0; i < pass->numMergedPasses; i++)
switch(p->type)
{
GL_MBind(i, Shader_TextureForPass(pass+i));
if (i >= shaderstate.lastpasstmus)
case SP_ATTR_VERTEX:
/*we still do vertex transforms for billboards and shadows and such*/
GL_SelectVBO(shaderstate.pendingvertexvbo);
qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vecV_t), shaderstate.pendingvertexpointer);
return 1u<<p->handle[perm];
case SP_ATTR_COLOUR:
if (shaderstate.sourcevbo->colours4f)
{
qglEnable(GL_TEXTURE_2D);
qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
GL_SelectVBO(shaderstate.curvertexvbo);
qglVertexAttribPointer(p->handle[perm], 4, GL_FLOAT, GL_FALSE, sizeof(vec4_t), shaderstate.sourcevbo->colours4f);
return 1u<<p->handle[perm];
}
BE_GeneratePassTC(pass, i);
}
for (; i < shaderstate.lastpasstmus; i++)
{
GL_SelectTexture(i);
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
qglDisable(GL_TEXTURE_2D);
}
shaderstate.lastpasstmus = pass->numMergedPasses;
for (i = 0; i < s->numprogparams; i++)
{
if (s->progparm[i].handle[perm] == -1)
continue; /*not in this permutation*/
switch(s->progparm[i].type)
else if (shaderstate.sourcevbo->colours4ub)
{
case SP_TIME:
qglUniform1fARB(s->progparm[i].handle[perm], shaderstate.curtime);
break;
case SP_ENTMATRIX:
GL_SelectVBO(shaderstate.curvertexvbo);
qglVertexAttribPointer(p->handle[perm], 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(byte_vec4_t), shaderstate.sourcevbo->colours4ub);
return 1u<<p->handle[perm];
}
break;
case SP_ATTR_TEXCOORD:
GL_SelectVBO(shaderstate.sourcevbo->vbotexcoord);
qglVertexAttribPointer(p->handle[perm], 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->texcoord);
return 1u<<p->handle[perm];
case SP_ATTR_LMCOORD:
GL_SelectVBO(shaderstate.sourcevbo->vbolmcoord);
qglVertexAttribPointer(p->handle[perm], 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord);
return 1u<<p->handle[perm];
case SP_ATTR_NORMALS:
GL_SelectVBO(shaderstate.sourcevbo->vbonormals);
qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->normals);
return 1u<<p->handle[perm];
case SP_ATTR_SNORMALS:
GL_SelectVBO(shaderstate.sourcevbo->vbosvector);
qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->svector);
return 1u<<p->handle[perm];
case SP_ATTR_TNORMALS:
GL_SelectVBO(shaderstate.sourcevbo->vbotvector);
qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->tvector);
return 1u<<p->handle[perm];
case SP_VIEWMATRIX:
qglUniformMatrix4fvARB(p->handle[perm], 1, false, r_refdef.m_view);
break;
case SP_PROJECTIONMATRIX:
qglUniformMatrix4fvARB(p->handle[perm], 1, false, r_refdef.m_projection);
break;
case SP_MODELVIEWMATRIX:
qglUniformMatrix4fvARB(p->handle[perm], 1, false, shaderstate.modelviewmatrix);
break;
case SP_MODELVIEWPROJECTIONMATRIX:
// qglUniformMatrix4fvARB(p->handle[perm], 1, false, r_refdef.);
break;
case SP_MODELMATRIX:
case SP_ENTMATRIX:
{
float m16[16];
Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin);
/* VectorCopy(shaderstate.curentity->axis[0], m16+0);
m16[3] = 0;
@ -2138,118 +2171,208 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas
m16[11] = 0;
VectorCopy(shaderstate.curentity->origin, m16+3);
m16[15] = 1;
*/
qglUniformMatrix4fvARB(s->progparm[i].handle[perm], 1, false, m16);
break;
case SP_ENTCOLOURS:
qglUniform4fvARB(s->progparm[i].handle[perm], 1, (GLfloat*)shaderstate.curentity->shaderRGBAf);
break;
case SP_TOPCOLOURS:
R_FetchTopColour(&r, &g, &b);
param3[0] = r/255.0f;
param3[1] = g/255.0f;
param3[2] = b/255.0f;
qglUniform3fvARB(s->progparm[i].handle[perm], 1, param3);
break;
case SP_BOTTOMCOLOURS:
R_FetchBottomColour(&r, &g, &b);
param3[0] = r/255.0f;
param3[1] = g/255.0f;
param3[2] = b/255.0f;
qglUniform3fvARB(s->progparm[i].handle[perm], 1, param3);
break;
case SP_RENDERTEXTURESCALE:
if (gl_config.arb_texture_non_power_of_two)
{
param3[0] = 1;
param3[1] = 1;
}
else
{
r = 1;
g = 1;
while (r < vid.pixelwidth)
r *= 2;
while (g < vid.pixelheight)
g *= 2;
param3[0] = vid.pixelwidth/(float)r;
param3[1] = vid.pixelheight/(float)g;
}
param3[2] = 1;
qglUniform3fvARB(s->progparm[i].handle[perm], 1, param3);
break;
case SP_LIGHTRADIUS:
qglUniform1fARB(s->progparm[i].handle[perm], shaderstate.lightradius);
break;
case SP_LIGHTCOLOUR:
qglUniform3fvARB(s->progparm[i].handle[perm], 1, shaderstate.lightcolours);
break;
case SP_EYEPOS:
{
#pragma message("is this correct?")
// vec3_t t1;
vec3_t t2;
Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin);
Matrix4_Transform3(m16, r_origin, t2);
// VectorSubtract(r_origin, shaderstate.curentity->origin, t1);
// Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2);
qglUniform3fvARB(s->progparm[i].handle[perm], 1, t2);
}
break;
case SP_LIGHTPOSITION:
{
#pragma message("is this correct?")
float inv[16];
// vec3_t t1;
vec3_t t2;
qboolean Matrix4_Invert(const float *m, float *out);
Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin);
Matrix4_Invert(m16, inv);
Matrix4_Transform3(inv, shaderstate.lightorg, t2);
// VectorSubtract(shaderstate.lightorg, shaderstate.curentity->origin, t1);
// Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2);
qglUniform3fvARB(s->progparm[i].handle[perm], 1, t2);
}
break;
case SP_CONSTI:
case SP_TEXTURE:
qglUniform1iARB(s->progparm[i].handle[perm], s->progparm[i].ival);
break;
case SP_CONSTF:
qglUniform1fARB(s->progparm[i].handle[perm], s->progparm[i].fval);
break;
case SP_CVARI:
qglUniform1iARB(s->progparm[i].handle[perm], ((cvar_t*)s->progparm[i].pval)->ival);
break;
case SP_CVARF:
qglUniform1fARB(s->progparm[i].handle[perm], ((cvar_t*)s->progparm[i].pval)->value);
break;
case SP_CVAR3F:
{
cvar_t *var = (cvar_t*)s->progparm[i].pval;
char *vs = var->string;
vs = COM_Parse(vs);
param3[0] = atof(com_token);
vs = COM_Parse(vs);
param3[1] = atof(com_token);
vs = COM_Parse(vs);
param3[2] = atof(com_token);
qglUniform3fvARB(s->progparm[i].handle[perm], 1, param3);
}
break;
default:
Host_EndGame("Bad shader program parameter type (%i)", s->progparm[i].type);
break;
*/
qglUniformMatrix4fvARB(p->handle[perm], 1, false, m16);
}
break;
case SP_ENTCOLOURS:
qglUniform4fvARB(p->handle[perm], 1, (GLfloat*)shaderstate.curentity->shaderRGBAf);
break;
case SP_TOPCOLOURS:
R_FetchTopColour(&r, &g, &b);
param3[0] = r/255.0f;
param3[1] = g/255.0f;
param3[2] = b/255.0f;
qglUniform3fvARB(p->handle[perm], 1, param3);
break;
case SP_BOTTOMCOLOURS:
R_FetchBottomColour(&r, &g, &b);
param3[0] = r/255.0f;
param3[1] = g/255.0f;
param3[2] = b/255.0f;
qglUniform3fvARB(p->handle[perm], 1, param3);
break;
case SP_RENDERTEXTURESCALE:
if (gl_config.arb_texture_non_power_of_two)
{
param3[0] = 1;
param3[1] = 1;
}
else
{
r = 1;
g = 1;
while (r < vid.pixelwidth)
r *= 2;
while (g < vid.pixelheight)
g *= 2;
param3[0] = vid.pixelwidth/(float)r;
param3[1] = vid.pixelheight/(float)g;
}
param3[2] = 1;
qglUniform3fvARB(p->handle[perm], 1, param3);
break;
case SP_LIGHTRADIUS:
qglUniform1fARB(p->handle[perm], shaderstate.lightradius);
break;
case SP_LIGHTCOLOUR:
qglUniform3fvARB(p->handle[perm], 1, shaderstate.lightcolours);
break;
case SP_EYEPOS:
{
float m16[16];
#pragma message("is this correct?")
// vec3_t t1;
vec3_t t2;
Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin);
Matrix4_Transform3(m16, r_origin, t2);
// VectorSubtract(r_origin, shaderstate.curentity->origin, t1);
// Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2);
qglUniform3fvARB(p->handle[perm], 1, t2);
}
break;
case SP_LIGHTPOSITION:
{
#pragma message("is this correct?")
float inv[16];
float m16[16];
// vec3_t t1;
vec3_t t2;
qboolean Matrix4_Invert(const float *m, float *out);
Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin);
Matrix4_Invert(m16, inv);
Matrix4_Transform3(inv, shaderstate.lightorg, t2);
// VectorSubtract(shaderstate.lightorg, shaderstate.curentity->origin, t1);
// Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2);
qglUniform3fvARB(p->handle[perm], 1, t2);
}
break;
case SP_TIME:
qglUniform1fARB(p->handle[perm], shaderstate.curtime);
break;
case SP_CONSTI:
case SP_TEXTURE:
qglUniform1iARB(p->handle[perm], p->ival);
break;
case SP_CONSTF:
qglUniform1fARB(p->handle[perm], p->fval);
break;
case SP_CVARI:
qglUniform1iARB(p->handle[perm], ((cvar_t*)p->pval)->ival);
break;
case SP_CVARF:
qglUniform1fARB(p->handle[perm], ((cvar_t*)p->pval)->value);
break;
case SP_CVAR3F:
{
cvar_t *var = (cvar_t*)p->pval;
char *vs = var->string;
vs = COM_Parse(vs);
param3[0] = atof(com_token);
vs = COM_Parse(vs);
param3[1] = atof(com_token);
vs = COM_Parse(vs);
param3[2] = atof(com_token);
qglUniform3fvARB(p->handle[perm], 1, param3);
}
break;
case SP_E_L_DIR:
qglUniform3fvARB(p->handle[perm], 1, shadevector);
break;
case SP_E_L_MUL:
qglUniform3fvARB(p->handle[perm], 1, shadelight);
break;
case SP_E_L_AMBIENT:
VectorMA(ambientlight, 1, shadelight, param3);
qglUniform3fvARB(p->handle[perm], 1, param3);
break;
default:
Host_EndGame("Bad shader program parameter type (%i)", p->type);
break;
}
GL_ApplyVertexPointer();
return 0;
}
static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pass)
{
const shader_t *s = shader;
int i;
unsigned int attr = 0;
int perm;
perm = 0;
/* if (TEXVALID(shaderstate.curtexnums->bump) && s->programhandle[perm|PERMUTATION_BUMPMAP].glsl)
perm |= PERMUTATION_BUMPMAP;
if (TEXVALID(shaderstate.curtexnums->specular) && s->programhandle[perm|PERMUTATION_SPECULAR].glsl)
perm |= PERMUTATION_SPECULAR;
if (TEXVALID(shaderstate.curtexnums->fullbright) && s->programhandle[perm|PERMUTATION_FULLBRIGHT].glsl)
perm |= PERMUTATION_FULLBRIGHT;
if (TEXVALID(shaderstate.curtexnums->loweroverlay) && s->programhandle[perm|PERMUTATION_LOWER].glsl)
perm |= PERMUTATION_LOWER;
if (TEXVALID(shaderstate.curtexnums->upperoverlay) && s->programhandle[perm|PERMUTATION_UPPER].glsl)
perm |= PERMUTATION_UPPER;
if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && s->programhandle[perm|PERMUTATION_OFFSET].glsl)
perm |= PERMUTATION_OFFSET;*/
GL_SelectProgram(s->programhandle[perm].glsl);
BE_SendPassBlendAndDepth(pass->shaderbits);
for (i = 0; i < s->numprogparams; i++)
{
if (s->progparm[i].handle[perm] == -1)
continue; /*not in this permutation*/
attr |= BE_Program_Set_Attribute(&s->progparm[i], perm);
}
if (s->flags & SHADER_NOBUILTINATTR)
{
qglDisableClientState(GL_COLOR_ARRAY);
qglDisableClientState(GL_VERTEX_ARRAY);
for (i = 0; i < pass->numMergedPasses; i++)
{
GL_MBind(i, Shader_TextureForPass(pass+i));
}
for (i = 0; i < shaderstate.lastpasstmus; i++)
{
GL_SelectTexture(i);
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
qglDisable(GL_TEXTURE_2D);
}
shaderstate.lastpasstmus = 0;
}
else
{
GenerateColourMods(pass);
for (i = 0; i < pass->numMergedPasses; i++)
{
GL_MBind(i, Shader_TextureForPass(pass+i));
if (i >= shaderstate.lastpasstmus)
{
qglEnable(GL_TEXTURE_2D);
qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
BE_GeneratePassTC(pass, i);
}
for (; i < shaderstate.lastpasstmus; i++)
{
GL_SelectTexture(i);
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
qglDisable(GL_TEXTURE_2D);
}
shaderstate.lastpasstmus = pass->numMergedPasses;
GL_ApplyVertexPointer();
}
BE_EnableShaderAttributes(attr);
BE_SubmitMeshChain();
GLSlang_UseProgram(0);
qglEnableClientState(GL_VERTEX_ARRAY);
}
#ifdef RTLIGHTS
@ -2372,12 +2495,14 @@ void GLBE_SelectMode(backendmode_t mode, unsigned int flags)
void GLBE_SelectEntity(entity_t *ent)
{
if (shaderstate.curentity && shaderstate.curentity->flags & Q2RF_DEPTHHACK)
if (shaderstate.curentity && shaderstate.curentity->flags & Q2RF_DEPTHHACK && qglDepthRange)
qglDepthRange (gldepthmin, gldepthmax);
shaderstate.curentity = ent;
currententity = ent;
R_RotateForEntity(shaderstate.curentity, shaderstate.curentity->model);
if (shaderstate.curentity->flags & Q2RF_DEPTHHACK)
R_RotateForEntity(shaderstate.modelviewmatrix, shaderstate.curentity, shaderstate.curentity->model);
if (qglLoadMatrixf)
qglLoadMatrixf(shaderstate.modelviewmatrix);
if (shaderstate.curentity->flags & Q2RF_DEPTHHACK && qglDepthRange)
qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
}
@ -2497,7 +2622,6 @@ static void DrawMeshes(void)
#endif
{
shaderstate.curcull = (shaderstate.curshader->flags & (SHADER_CULL_FRONT|SHADER_CULL_BACK));
if (shaderstate.curcull & SHADER_CULL_FRONT)
{
qglEnable(GL_CULL_FACE);
@ -2515,7 +2639,6 @@ static void DrawMeshes(void)
}
BE_PolyOffset(shaderstate.flags & BEF_PUSHDEPTH);
switch(shaderstate.mode)
{
case BEM_STENCIL:
@ -2533,6 +2656,7 @@ static void DrawMeshes(void)
break;
#endif
case BEM_DEPTHONLY:
GL_DeSelectProgram();
#pragma message("fixme: support alpha test")
GL_ApplyVertexPointer();
BE_SubmitMeshChain();
@ -2541,6 +2665,7 @@ static void DrawMeshes(void)
case BEM_DEPTHDARK:
if (shaderstate.curshader->flags & SHADER_HASLIGHTMAP)
{
GL_DeSelectProgram();
qglColor3f(0,0,0);
qglDisableClientState(GL_COLOR_ARRAY);
while(shaderstate.lastpasstmus>0)
@ -2560,9 +2685,14 @@ static void DrawMeshes(void)
case BEM_STANDARD:
default:
if (shaderstate.curshader->programhandle[0].glsl)
{
BE_RenderMeshProgram(shaderstate.curshader, shaderstate.curshader->passes);
}
else if (gl_config.nofixedfunc)
break;
else
{
GL_DeSelectProgram();
while (passno < shaderstate.curshader->numpasses)
{
p = &shaderstate.curshader->passes[passno];
@ -2604,6 +2734,7 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_
shaderstate.dummyvbo.svector = m->snormals_array;
shaderstate.dummyvbo.tvector = m->tnormals_array;
shaderstate.dummyvbo.colours4f = m->colors4f_array;
shaderstate.dummyvbo.colours4ub = m->colors4b_array;
shaderstate.meshcount = 1;
shaderstate.meshes = &m;
@ -2787,7 +2918,6 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist)
if (batch->shader->flags & SHADER_NODLIGHT)
if (shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_SMAPLIGHT)
continue;
if (batch->shader->flags & SHADER_SKY)
{
if (shaderstate.mode == BEM_STANDARD)
@ -2815,8 +2945,6 @@ void GLBE_SubmitMeshes (qboolean drawworld, batch_t **blist)
}
BE_SubmitMeshesSortList(blist[i]);
}
checkerror();
}
static void BE_UpdateLightmaps(void)
@ -2832,6 +2960,7 @@ static void BE_UpdateLightmaps(void)
lightmap[lm]->modified = false;
theRect = &lightmap[lm]->rectchange;
GL_Bind(lightmap_textures[lm]);
checkglerror();
switch (lightmap_bytes)
{
case 4:
@ -2854,7 +2983,7 @@ static void BE_UpdateLightmaps(void)
theRect->t = LMBLOCK_HEIGHT;
theRect->h = 0;
theRect->w = 0;
checkerror();
checkglerror();
if (lightmap[lm]->deluxmodified)
{
@ -2868,7 +2997,7 @@ static void BE_UpdateLightmaps(void)
theRect->t = LMBLOCK_HEIGHT;
theRect->h = 0;
theRect->w = 0;
checkerror();
checkglerror();
}
}
}
@ -2961,7 +3090,6 @@ void GLBE_DrawWorld (qbyte *vis)
shaderstate.wbatch = 0;
}
BE_GenModelBatches(batches);
shaderstate.curentity = NULL;
shaderstate.updatetime = cl.servertime;
@ -2973,7 +3101,6 @@ void GLBE_DrawWorld (qbyte *vis)
#endif
BE_UpdateLightmaps();
//make sure the world draws correctly
r_worldentity.shaderRGBAf[0] = 1;
r_worldentity.shaderRGBAf[1] = 1;
@ -2995,8 +3122,6 @@ void GLBE_DrawWorld (qbyte *vis)
else
BE_SelectMode(BEM_STANDARD, 0);
checkerror();
RSpeedRemark();
GLBE_SubmitMeshes(true, batches);
RSpeedEnd(RSPEED_WORLD);
@ -3007,7 +3132,6 @@ void GLBE_DrawWorld (qbyte *vis)
Sh_DrawLights(vis);
RSpeedEnd(RSPEED_STENCILSHADOWS);
#endif
checkerror();
BE_DrawPolys(false);

View file

@ -788,17 +788,21 @@ Setup as if the screen was 320*200
void GL_Set2D (void)
{
GL_SetShaderState2D(true);
Matrix4_Orthographic(r_refdef.m_projection, 0, vid.width, vid.height, 0, -99999, 99999);
Matrix4_Identity(r_refdef.m_view);
r_refdef.time = realtime;
/*flush that gl state*/
qglViewport (0, 0, vid.pixelwidth, vid.pixelheight);
qglMatrixMode(GL_PROJECTION);
qglLoadIdentity ();
qglOrtho (0, vid.width, vid.height, 0, -99999, 99999);
if (qglLoadMatrixf)
{
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
qglLoadIdentity ();
r_refdef.time = realtime;
qglMatrixMode(GL_MODELVIEW);
qglLoadMatrixf(r_refdef.m_view);
}
}

View file

@ -210,10 +210,14 @@ static fontplanes_t fontplanes;
static index_t font_indicies[FONT_CHAR_BUFFER*6];
static vecV_t font_coord[FONT_CHAR_BUFFER*4];
static vec2_t font_texcoord[FONT_CHAR_BUFFER*4];
static vbo_t font_buffer;
static mesh_t font_mesh;
static byte_vec4_t font_forecoloura[FONT_CHAR_BUFFER*4];
static byte_vec4_t font_backcoloura[FONT_CHAR_BUFFER*4];
static mesh_t font_foremesh;
static mesh_t font_backmesh;
static texid_t font_texture;
static int font_colourmask;
static byte_vec4_t font_forecolour;
static byte_vec4_t font_backcolour;
static struct font_s *curfont;
@ -223,13 +227,15 @@ void Font_Init(void)
int i;
fontplanes.defaultfont = r_nulltex;
font_buffer.indicies = font_indicies;
font_buffer.coord = font_coord;
font_buffer.texcoord = font_texcoord;
font_foremesh.indexes = font_indicies;
font_foremesh.xyz_array = font_coord;
font_foremesh.st_array = font_texcoord;
font_foremesh.colors4b_array = font_forecoloura;
font_mesh.indexes = font_buffer.indicies;
font_mesh.xyz_array = font_buffer.coord;
font_mesh.st_array = font_buffer.texcoord;
font_backmesh.indexes = font_indicies;
font_backmesh.xyz_array = font_coord;
font_backmesh.st_array = font_texcoord;
font_backmesh.colors4b_array = font_backcoloura;
for (i = 0; i < FONT_CHAR_BUFFER; i++)
{
@ -248,11 +254,12 @@ void Font_Init(void)
fontplanes.shader = R_RegisterShader("ftefont",
"{\n"
// "program default2d\n"
"nomipmaps\n"
"{\n"
"map $diffuse\n"
"rgbgen const\n"
"alphagen const\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"blendfunc blend\n"
"}\n"
"}\n"
@ -263,8 +270,8 @@ void Font_Init(void)
"nomipmaps\n"
"{\n"
"map $whiteimage\n"
"rgbgen const\n"
"alphagen const\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"blendfunc blend\n"
"}\n"
"}\n"
@ -276,48 +283,43 @@ void Font_Init(void)
//flush the font buffer, by drawing it to the screen
static void Font_Flush(void)
{
if (!font_mesh.numindexes)
if (!font_foremesh.numindexes)
return;
if (fontplanes.planechanged)
{
R_Upload(fontplanes.texnum[fontplanes.activeplane], NULL, TF_RGBA32, (void*)fontplanes.plane, NULL, PLANEWIDTH, PLANEHEIGHT, IF_NOPICMIP|IF_NOMIPMAP|IF_NOGAMMA);
fontplanes.planechanged = false;
}
font_mesh.istrifan = (font_mesh.numvertexes == 4);
font_foremesh.istrifan = (font_foremesh.numvertexes == 4);
if (font_colourmask & CON_NONCLEARBG)
{
fontplanes.backshader->defaulttextures.base = r_nulltex;
BE_DrawMesh_Single(fontplanes.backshader, &font_mesh, NULL, &fontplanes.backshader->defaulttextures);
font_backmesh.numindexes = font_foremesh.numindexes;
font_backmesh.numvertexes = font_foremesh.numvertexes;
font_backmesh.istrifan = font_foremesh.istrifan;
fontplanes.shader->defaulttextures.base = font_texture;
BE_DrawMesh_Single(fontplanes.shader, &font_mesh, NULL, &fontplanes.shader->defaulttextures);
BE_DrawMesh_Single(fontplanes.backshader, &font_backmesh, NULL, &fontplanes.backshader->defaulttextures);
}
else
{
fontplanes.shader->defaulttextures.base = font_texture;
BE_DrawMesh_Single(fontplanes.shader, &font_mesh, NULL, &fontplanes.shader->defaulttextures);
}
font_mesh.numindexes = 0;
font_mesh.numvertexes = 0;
fontplanes.shader->defaulttextures.base = font_texture;
BE_DrawMesh_Single(fontplanes.shader, &font_foremesh, NULL, &fontplanes.shader->defaulttextures);
font_foremesh.numindexes = 0;
font_foremesh.numvertexes = 0;
}
static int Font_BeginChar(texid_t tex)
{
int fvert;
if (font_mesh.numindexes == FONT_CHAR_BUFFER*6 || memcmp(&font_texture,&tex, sizeof(texid_t)))
if (font_foremesh.numindexes == FONT_CHAR_BUFFER*6 || memcmp(&font_texture,&tex, sizeof(texid_t)))
{
Font_Flush();
font_texture = tex;
}
fvert = font_mesh.numvertexes;
fvert = font_foremesh.numvertexes;
font_mesh.numindexes += 6;
font_mesh.numvertexes += 4;
font_foremesh.numindexes += 6;
font_foremesh.numvertexes += 4;
return fvert;
}
@ -1077,17 +1079,16 @@ void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end)
correct usage of this function thus requires calling this with 1111 before Font_EndString*/
void Font_ForceColour(float r, float g, float b, float a)
{
Font_Flush();
if (font_colourmask & CON_NONCLEARBG)
Font_Flush();
font_colourmask = CON_WHITEMASK;
/*force the colour to the requested one*/
fontplanes.shader->passes[0].rgbgen_func.args[0] = r;
fontplanes.shader->passes[0].rgbgen_func.args[1] = g;
fontplanes.shader->passes[0].rgbgen_func.args[2] = b;
fontplanes.shader->passes[0].alphagen_func.args[0] = a;
font_forecolour[0] = r*255;
font_forecolour[1] = g*255;
font_forecolour[2] = b*255;
font_forecolour[3] = a*255;
/*no background*/
fontplanes.backshader->passes[0].alphagen_func.args[0] = 0;
font_backcolour[3] = 0;
/*Any drawchars that are now drawn will get the forced colour*/
}
@ -1134,20 +1135,21 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
col = charcode & (CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA);
if (col != font_colourmask)
{
Font_Flush();
if ((col ^ font_colourmask) & CON_NONCLEARBG)
Font_Flush();
font_colourmask = col;
col = (charcode&CON_FGMASK)>>CON_FGSHIFT;
fontplanes.shader->passes[0].rgbgen_func.args[0] = consolecolours[col].fr;
fontplanes.shader->passes[0].rgbgen_func.args[1] = consolecolours[col].fg;
fontplanes.shader->passes[0].rgbgen_func.args[2] = consolecolours[col].fb;
fontplanes.shader->passes[0].alphagen_func.args[0] = (charcode & CON_HALFALPHA)?0.5:1;
font_forecolour[0] = consolecolours[col].fr*255;
font_forecolour[1] = consolecolours[col].fg*255;
font_forecolour[2] = consolecolours[col].fb*255;
font_forecolour[3] = (charcode & CON_HALFALPHA)?127:255;
col = (charcode&CON_BGMASK)>>CON_BGSHIFT;
fontplanes.backshader->passes[0].rgbgen_func.args[0] = consolecolours[col].fr;
fontplanes.backshader->passes[0].rgbgen_func.args[1] = consolecolours[col].fg;
fontplanes.backshader->passes[0].rgbgen_func.args[2] = consolecolours[col].fb;
fontplanes.backshader->passes[0].alphagen_func.args[0] = (charcode & CON_NONCLEARBG)?0.5:0;
font_backcolour[0] = consolecolours[col].fr*255;
font_backcolour[1] = consolecolours[col].fg*255;
font_backcolour[2] = consolecolours[col].fb*255;
font_backcolour[3] = (charcode & CON_NONCLEARBG)?127:0;
}
s0 = (float)c->bmx/PLANEWIDTH;
@ -1194,6 +1196,15 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
font_coord[v+3][0] = sx;
font_coord[v+3][1] = sy+sh;
*(int*)font_forecoloura[v+0] = *(int*)font_forecolour;
*(int*)font_forecoloura[v+1] = *(int*)font_forecolour;
*(int*)font_forecoloura[v+2] = *(int*)font_forecolour;
*(int*)font_forecoloura[v+3] = *(int*)font_forecolour;
*(int*)font_backcoloura[v+0] = *(int*)font_backcolour;
*(int*)font_backcoloura[v+1] = *(int*)font_backcolour;
*(int*)font_backcoloura[v+2] = *(int*)font_backcolour;
*(int*)font_backcoloura[v+3] = *(int*)font_backcolour;
return nextx;
}
@ -1236,20 +1247,21 @@ float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int ch
col = charcode & (CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA);
if (col != font_colourmask)
{
Font_Flush();
if ((col ^ font_colourmask) & CON_NONCLEARBG)
Font_Flush();
font_colourmask = col;
col = (charcode&CON_FGMASK)>>CON_FGSHIFT;
fontplanes.shader->passes[0].rgbgen_func.args[0] = consolecolours[col].fr;
fontplanes.shader->passes[0].rgbgen_func.args[1] = consolecolours[col].fg;
fontplanes.shader->passes[0].rgbgen_func.args[2] = consolecolours[col].fb;
fontplanes.shader->passes[0].alphagen_func.args[0] = (charcode & CON_HALFALPHA)?0.5:1;
font_forecolour[0] = consolecolours[col].fr*255;
font_forecolour[1] = consolecolours[col].fg*255;
font_forecolour[2] = consolecolours[col].fb*255;
font_forecolour[3] = (charcode & CON_HALFALPHA)?127:255;
col = (charcode&CON_BGMASK)>>CON_BGSHIFT;
fontplanes.backshader->passes[0].rgbgen_func.args[0] = consolecolours[col].fr;
fontplanes.backshader->passes[0].rgbgen_func.args[1] = consolecolours[col].fg;
fontplanes.backshader->passes[0].rgbgen_func.args[2] = consolecolours[col].fb;
fontplanes.backshader->passes[0].alphagen_func.args[0] = (charcode & CON_NONCLEARBG)?0.5:0;
font_backcolour[0] = consolecolours[col].fr*255;
font_backcolour[1] = consolecolours[col].fg*255;
font_backcolour[2] = consolecolours[col].fb*255;
font_backcolour[3] = (charcode & CON_NONCLEARBG)?127:0;
}
s0 = (float)c->bmx/PLANEWIDTH;
@ -1296,6 +1308,15 @@ float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int ch
font_coord[v+3][0] = sx;
font_coord[v+3][1] = sy+sh;
*(int*)font_forecoloura[v+0] = *(int*)font_forecolour;
*(int*)font_forecoloura[v+1] = *(int*)font_forecolour;
*(int*)font_forecoloura[v+2] = *(int*)font_forecolour;
*(int*)font_forecoloura[v+3] = *(int*)font_forecolour;
*(int*)font_backcoloura[v+0] = *(int*)font_backcolour;
*(int*)font_backcoloura[v+1] = *(int*)font_backcolour;
*(int*)font_backcoloura[v+2] = *(int*)font_backcolour;
*(int*)font_backcoloura[v+3] = *(int*)font_backcolour;
return nextx;
}

View file

@ -570,6 +570,7 @@ void R_DrawHLModel(entity_t *curent)
int b, m, v;
short *skins;
int bgroup, cbone, lastbone;
float mat[16];
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//general model
@ -613,7 +614,8 @@ void R_DrawHLModel(entity_t *curent)
qglColor4f(difuse[0]/255+ambient[0]/255, difuse[1]/255+ambient[1]/255, difuse[2]/255+ambient[2]/255, curent->shaderRGBAf[3]);
}
R_RotateForEntity (curent, curent->model);
R_RotateForEntity (mat, curent, curent->model);
qglLoadMatrixf(mat);
cbone = 0;
for (bgroup = 0; bgroup < FS_COUNT; bgroup++)

View file

@ -233,6 +233,7 @@ typedef struct vbo_s
int vbocolours;
vec4_t *colours4f;
byte_vec4_t *colours4ub;
} vbo_t;
void GL_SelectVBO(int vbo);
void GL_SelectEBO(int vbo);

View file

@ -27,12 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "shader.h"
#include "gl_draw.h"
#ifdef _DEBUG
#define checkerror() if (qglGetError()) Con_Printf("Error detected at line %s:%i\n", __FILE__, __LINE__)
#else
#define checkerror()
#endif
void R_RenderBrushPoly (msurface_t *fa);
#define PROJECTION_DISTANCE 200
@ -389,7 +383,7 @@ void GL_SetupSceneProcessingTextures (void)
GL_Bind(scenepp_texture_warp);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexImage2D(GL_TEXTURE_2D, 0, 3, PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, pp_warp_tex);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, pp_warp_tex);
// TODO: init edge texture - this is ampscale * 2, with ampscale calculated
// init warp texture - this specifies offset in
@ -436,9 +430,8 @@ void GL_SetupSceneProcessingTextures (void)
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, pp_edge_tex);
}
void R_RotateForEntity (const entity_t *e, const model_t *mod)
void R_RotateForEntity (float *modelview, const entity_t *e, const model_t *mod)
{
float mv[16];
float m[16];
m[0] = e->axis[0][0];
@ -520,13 +513,11 @@ void R_RotateForEntity (const entity_t *e, const model_t *mod)
/*FIXME: no bob*/
float simpleview[16];
Matrix4_ModelViewMatrix(simpleview, vec3_origin, vec3_origin);
Matrix4_Multiply(simpleview, m, mv);
qglLoadMatrixf(mv);
Matrix4_Multiply(simpleview, m, modelview);
}
else
{
Matrix4_Multiply(r_refdef.m_view, m, mv);
qglLoadMatrixf(mv);
Matrix4_Multiply(r_refdef.m_view, m, modelview);
}
}
@ -1089,19 +1080,25 @@ void R_SetupGL (void)
Matrix4_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg);
}
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
qglLoadMatrixf(r_refdef.m_view);
if (gl_dither.ival)
if (qglLoadMatrixf)
{
qglEnable(GL_DITHER);
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
qglLoadMatrixf(r_refdef.m_view);
}
else
if (!gl_config.gles)
{
qglDisable(GL_DITHER);
if (gl_dither.ival)
{
qglEnable(GL_DITHER);
}
else
{
qglDisable(GL_DITHER);
}
}
}
@ -1418,7 +1415,8 @@ void R_Clear (void)
gldepthmax = 1;
gldepthfunc=GL_LEQUAL;
}
qglDepthRange (gldepthmin, gldepthmax);
if (qglDepthRange)
qglDepthRange (gldepthmin, gldepthmax);
}
#if 0

View file

@ -306,7 +306,7 @@ void GLBE_UploadAllLightmaps(void)
lightmap[i]->lightmaps);
break;
case 3:
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
LMBLOCK_WIDTH, LMBLOCK_WIDTH, 0, (lightmap_bgra?GL_BGR_EXT:GL_RGB), GL_UNSIGNED_BYTE,
lightmap[i]->lightmaps);
break;

View file

@ -708,23 +708,48 @@ static void Shader_EntityMergable ( shader_t *shader, shaderpass_t *pass, char *
shader->flags |= SHADER_ENTITY_MERGABLE;
}
static void Shader_LoadProgram(shader_t *shader, char *vert, char *frag, int qrtype)
/*program text is already loaded, this function parses the 'header' of it to see which permutations it provides, and how many times we need to recompile it*/
static void Shader_LoadPermutations(union programhandle_u *handle, char *script, int qrtype)
{
static char *permutationdefines[PERMUTATIONS] = {
"",
char *permutationdefines[PERMUTATIONS];
static char *permutationname[] =
{
"#define BUMP\n",
"#define SPECULAR\n",
"#define SPECULAR\n#define BUMP\n",
"#define USEOFFSETMAPPING\n",
"#define USEOFFSETMAPPING\n#define BUMP\n",
"#define USEOFFSETMAPPING\n#define SPECULAR\n",
"#define USEOFFSETMAPPING\n#define SPECULAR\n#define BUMP\n"
"#define FULLBRIGHT\n",
"#define LOWER\n",
"#define UPPER\n",
"#define OFFSETMAPPING\n",
NULL
};
int p;
unsigned int nopermutation = ~0u;
int p, n, pn;
char *end;
if (!frag)
frag = vert;
for(;;)
{
while (*script == ' ' || *script == '\r' || *script == '\n' || *script == '\t')
script++;
if (!strncmp(script, "!!permu", 7))
{
script += 7;
while (*script == ' ' || *script == '\r' || *script == '\n' || *script == '\t')
script++;
end = script;
while ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_')
end++;
for (p = 0; permutationname[p]; p++)
{
if (!strncmp(permutationname[p]+8, script, end - script) && permutationname[p][8+end-script] == '\n')
nopermutation &= ~(1u<<p);
}
script = end;
}
else
break;
};
memset(handle, 0, sizeof(*handle)*PERMUTATIONS);
for (p = 0; p < PERMUTATIONS; p++)
{
if (qrenderer != qrtype)
@ -732,10 +757,519 @@ static void Shader_LoadProgram(shader_t *shader, char *vert, char *frag, int qrt
}
#ifdef GLQUAKE
else if (qrenderer == QR_OPENGL)
shader->programhandle[p].glsl = GLSlang_CreateProgram(permutationdefines[p], (char *)vert, (char *)frag);
{
if (nopermutation & p)
{
continue;
}
pn = 0;
for (n = 0; permutationname[n]; n++)
{
if (p & (1u<<n))
permutationdefines[pn++] = permutationname[n];
}
permutationdefines[pn++] = NULL;
handle[p].glsl = GLSlang_CreateProgram(permutationdefines, script, script);
}
#endif
}
}
typedef struct sgeneric_s
{
struct sgeneric_s *next;
char name[MAX_QPATH];
union programhandle_u handle[PERMUTATIONS];
} sgeneric_t;
static sgeneric_t *sgenerics;
struct sbuiltin_s
{
int qrtype;
int apiver;
char name[MAX_QPATH];
char *body;
} sbuiltins[] =
{
{QR_OPENGL/*ES*/, 100, "default2d",
"#version 100\n"
"#ifdef VERTEX_SHADER\n"
"uniform mat4 m_view;\n"
"uniform mat4 m_projection;\n"
"attribute vec3 v_position;\n"
"attribute vec2 v_texcoord;\n"
"attribute vec4 v_colour;\n"
"varying vec2 tc;\n"
"varying vec4 vc;\n"
"void main (void)\n"
"{\n"
" tc = v_texcoord;\n"
" vc = v_colour;\n"
" gl_Position = m_projection * m_view * vec4(v_position, 1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"in vec2 tc;\n"
"varying vec4 vc;\n"
"void main (void)\n"
"{\n"
" gl_FragColor = texture2D(s_t0, tc) * vc;\n"
"}\n"
"#endif\n"
},
{QR_OPENGL, 110, "default2d",
"#version 110\n"
"#ifdef VERTEX_SHADER\n"
"uniform mat4 m_view;\n"
"uniform mat4 m_projection;\n"
"attribute vec3 v_position;\n"
"attribute vec2 v_texcoord;\n"
"attribute vec4 v_colour;\n"
"varying vec2 tc;\n"
"varying vec4 vc;\n"
"void main (void)\n"
"{\n"
" tc = v_texcoord;\n"
" vc = v_colour;\n"
" gl_Position = m_projection * m_view * vec4(v_position, 1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"in vec2 tc;\n"
"varying vec4 vc;\n"
"void main (void)\n"
"{\n"
" gl_FragColor = texture2D(s_t0, tc) * vc;\n"
"}\n"
"#endif\n"
},
{QR_OPENGL, 130, "defaultwall",
"#version 130\n"
"#ifdef VERTEX_SHADER\n"
"uniform mat4 m_modelview;\n"
"uniform mat4 m_projection;\n"
"in vec3 v_position;\n"
"in vec2 v_texcoord;\n"
"in vec2 v_lmcoord;\n"
"out vec2 tc, lm;\n"
"void main (void)\n"
"{\n"
" tc = v_texcoord;\n"
" lm = v_lmcoord;\n"
" gl_Position = m_projection * m_modelview * vec4(v_position, 1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n" /*tex_diffuse*/
"uniform sampler2D s_t1;\n" /*tex_lightmap*/
//"uniform sampler2D s_t2;\n" /*tex_normalmap*/
//"uniform sampler2D s_t3;\n" /*tex_deluxmap*/
//"uniform sampler2D s_t4;\n" /*tex_fullbright*/
"in vec2 tc, lm;\n"
"void main (void)\n"
"{\n"
" gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm);\n"
"}\n"
"#endif\n"
},
{QR_OPENGL/*ES*/, 100, "defaultwall",
"!!permu FULLBRIGHT\n"
"#version 100\n"
"#ifdef VERTEX_SHADER\n"
"uniform mat4 m_modelview;\n"
"uniform mat4 m_projection;\n"
"attribute vec3 v_position;\n"
"attribute vec2 v_texcoord;\n"
"attribute vec2 v_lmcoord;\n"
"varying vec2 tc, lm;\n"
"void main (void)\n"
"{\n"
" tc = v_texcoord;\n"
" lm = v_lmcoord;\n"
" gl_Position = m_projection * m_modelview * vec4(v_position, 1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n" /*tex_diffuse*/
"uniform sampler2D s_t1;\n" /*tex_lightmap*/
//"uniform sampler2D s_t2;\n" /*tex_normalmap*/
//"uniform sampler2D s_t3;\n" /*tex_deluxmap*/
"#ifdef FULLBRIGHT\n"
"uniform sampler2D s_t4;\n" /*tex_fullbright*/
"#endif\n"
"varying vec2 tc, lm;\n"
"void main (void)\n"
"{\n"
" gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm);\n"
"#ifdef FULLBRIGHT\n"
" gl_FragColor += texture2D(s_t4, tc);\n"
"#endif\n"
"}\n"
"#endif\n"
},
{QR_OPENGL/*ES*/, 100, "defaultwarp",
"#version 100\n"
"varying vec2 tc;\n"
"#ifdef VERTEX_SHADER\n"
"uniform mat4 m_modelview;\n"
"uniform mat4 m_projection;\n"
"attribute vec3 v_position;\n"
"attribute vec2 v_texcoord;\n"
"void main (void)\n"
"{\n"
" tc = v_texcoord;\n"
" gl_Position = m_projection * m_modelview * vec4(v_position, 1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D watertexture;\n"
"uniform float e_time;\n"
"uniform float wateralpha;\n"
"void main (void)\n"
"{\n"
" vec2 ntc;\n"
" ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n"
" ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n"
" vec3 ts = vec3(texture2D(watertexture, ntc));\n"
" gl_FragColor = vec4(ts, wateralpha);\n"
"}\n"
"#endif\n"
},
{QR_OPENGL, 110, "defaultwarp",
"#version 110\n"
"varying vec2 tc;\n"
"#ifdef VERTEX_SHADER\n"
"void main (void)\n"
"{\n"
" tc = gl_MultiTexCoord0.st;\n"
" gl_Position = ftransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"uniform float e_time;\n"
"uniform float wateralpha;\n"
"void main (void)\n"
"{\n"
" vec2 ntc;\n"
" ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n"
" ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n"
" vec3 ts = vec3(texture2D(s_t0, ntc));\n"
" gl_FragColor = vec4(ts, wateralpha);\n"
"}\n"
"#endif\n"
},
{QR_OPENGL/*ES*/, 100, "defaultsky",
"#version 100\n"
"#ifdef VERTEX_SHADER\n"
"uniform mat4 m_modelview;\n"
"uniform mat4 m_projection;\n"
"attribute vec3 v_position;\n"
"varying vec3 pos;\n"
"void main (void)\n"
"{\n"
" pos = v_position.xyz;\n"
" gl_Position = m_projection * m_modelview * vec4(v_position, 1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"uniform float e_time;\n"
"uniform vec3 eyepos;\n"
"varying vec3 pos;\n"
"void main (void)\n"
"{\n"
" vec2 tccoord;\n"
" vec3 dir = pos - eyepos;\n"
" dir.z *= 3.0;\n"
" dir.xy /= 0.5*length(dir);\n"
" tccoord = (dir.xy + e_time*0.03125);\n"
" vec3 solid = vec3(texture2D(s_t0, tccoord));\n"
" tccoord = (dir.xy + e_time*0.0625);\n"
" vec4 clouds = texture2D(s_t1, tccoord);\n"
" gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n"
// " gl_FragColor.rgb = solid.rgb;/*gl_FragColor.g = clouds.r;*/gl_FragColor.b = clouds.a;\n"
"}\n"
"#endif\n"
},
{QR_OPENGL, 110, "defaultsky",
"#version 110\n"
"#ifdef VERTEX_SHADER\n"
"varying vec3 pos;\n"
"void main (void)\n"
"{\n"
" pos = gl_Vertex.xyz;\n"
" gl_Position = ftransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform float e_time;\n"
"uniform vec3 eyepos;\n"
"varying vec3 pos;\n"
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"void main (void)\n"
"{\n"
" vec2 tccoord;\n"
" vec3 dir = pos - eyepos;\n"
" dir.z *= 3.0;\n"
" dir.xy /= 0.5*length(dir);\n"
" tccoord = (dir.xy + e_time*0.03125);\n"
" vec3 solid = vec3(texture2D(s_t0, tccoord));\n"
" tccoord = (dir.xy + e_time*0.0625);\n"
" vec4 clouds = texture2D(s_t1, tccoord);\n"
" gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n"
// " gl_FragColor.rgb = solid.rgb;/*gl_FragColor.g = clouds.r;*/gl_FragColor.b = clouds.a;\n"
"}\n"
"#endif\n"
},
{QR_OPENGL/*ES*/, 100, "defaultskin",
"!!permu FULLBRIGHT\n"
"!!permu LOWER\n"
"!!permu UPPER\n"
"#version 100\n"
"#ifdef VERTEX_SHADER\n"
"uniform mat4 m_modelview;\n"
"uniform mat4 m_projection;\n"
"attribute vec3 v_position;\n"
"attribute vec2 v_texcoord;\n"
"varying vec2 tc;\n"
"attribute vec3 v_normal;\n"
"uniform vec3 e_light_dir;\n"
"uniform vec3 e_light_mul;\n"
"uniform vec3 e_light_ambient;\n"
"varying vec3 light;\n"
"void main (void)\n"
"{\n"
" light = e_light_ambient + (dot(v_normal,e_light_dir)*e_light_mul);\n"
" tc = v_texcoord;\n"
" gl_Position = m_projection * m_modelview * vec4(v_position, 1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n" /*tex_diffuse*/
"#ifdef LOWER\n"
"uniform sampler2D s_t1;\n" /*tex_lower*/
"uniform vec3 e_lowercolour;\n"
"#endif\n"
"#ifdef UPPER\n"
"uniform sampler2D s_t2;\n" /*tex_upper*/
"uniform vec3 e_uppercolour;\n"
"#endif\n"
"#ifdef FULLBRIGHT\n"
"uniform sampler2D s_t3;\n" /*tex_fullbright*/
"#endif\n"
"varying vec2 tc;\n"
"varying vec3 light;\n"
"void main (void)\n"
"{\n"
" gl_FragColor = texture2D(s_t0, tc);\n"
"#ifdef UPPER\n"
" gl_FragColor.rgb += texture2D(s_t2, tc).rgb*e_uppercolour;\n"
"#endif\n"
"#ifdef LOWER\n"
" gl_FragColor.rgb += texture2D(s_t1, tc).rgb*e_lowercolour;\n"
"#endif\n"
" gl_FragColor.rgb *= light;\n"
"#ifdef FULLBRIGHT\n"
" gl_FragColor += texture2D(s_t3, tc);\n"
"#endif\n"
"}\n"
"#endif\n"
},
{QR_NONE}
};
static sgeneric_t *sgenerics;
static void Shader_FlushGenerics(void)
{
sgeneric_t *g;
while (sgenerics)
{
g = sgenerics;
sgenerics = g->next;
free(g);
}
}
static void Shader_LoadGeneric(union programhandle_u *shader, char *name, int qrtype)
{
unsigned int i;
void *file;
sgeneric_t *g;
for (g = sgenerics; g; g = g->next)
{
if (!strcmp(name, g->name))
{
memcpy(shader, g->handle, sizeof(g->handle));
return;
}
}
if (strlen(name) >= sizeof(g->name))
return; /*name overflow*/
g = malloc(sizeof(*g));
strcpy(g->name, name);
g->next = sgenerics;
sgenerics = g;
FS_LoadFile(name, &file);
if (file)
{
Shader_LoadPermutations(g->handle, file, qrtype);
FS_FreeFile(file);
}
else
{
memset(g->handle, 0, sizeof(g->handle));
for (i = 0; *sbuiltins[i].name; i++)
{
if (sbuiltins[i].qrtype == qrenderer && !strcmp(sbuiltins[i].name, name))
{
#ifdef GLQUAKE
if (gl_config.gles)
{
if (sbuiltins[i].apiver != 100)
continue;
}
else
{
if (sbuiltins[i].apiver == 100)
continue;
}
#endif
Shader_LoadPermutations(g->handle, sbuiltins[i].body, sbuiltins[i].qrtype);
break;
}
}
}
memcpy(shader, g->handle, sizeof(g->handle));
}
static void Shader_ProgAutoFields(shader_t *shader)
{
unsigned int i, p;
qboolean found;
int uniformloc;
static struct
{
char *name;
enum shaderprogparmtype_e ptype;
} u[] =
{
/*vertex attributes*/
{"v_position", SP_ATTR_VERTEX},
{"v_colour", SP_ATTR_COLOUR},
{"v_texcoord", SP_ATTR_TEXCOORD},
{"v_lmcoord", SP_ATTR_LMCOORD},
{"v_normal", SP_ATTR_NORMALS},
{"v_svector", SP_ATTR_SNORMALS},
{"v_tvector", SP_ATTR_TNORMALS},
/*matricies*/
{"m_model", SP_MODELMATRIX},
{"m_view", SP_VIEWMATRIX},
{"m_modelview", SP_MODELVIEWMATRIX},
{"m_projection", SP_PROJECTIONMATRIX},
{"m_modelviewprojection", SP_MODELVIEWPROJECTIONMATRIX},
/*ent properties*/
{"e_time", SP_TIME},
{"e_colour", SP_ENTCOLOURS},
{"e_topcolour", SP_TOPCOLOURS},
{"e_bottomcolour", SP_BOTTOMCOLOURS},
{"e_light_dir", SP_E_L_DIR},
{"e_light_mul", SP_E_L_MUL},
{"e_light_ambient", SP_E_L_AMBIENT},
{NULL}
};
shader->numprogparams = 0;
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
{
if (gl_config.nofixedfunc)
shader->flags |= SHADER_NOBUILTINATTR;
for (p = 0; p < PERMUTATIONS; p++)
{
if (!shader->programhandle[p].glsl)
continue;
GLSlang_UseProgram(shader->programhandle[p].glsl);
for (i = 0; i < 8; i++)
{
uniformloc = qglGetUniformLocationARB(shader->programhandle[p].glsl, va("s_t%i", i));
if (uniformloc != -1)
qglUniform1iARB(uniformloc, i);
}
}
for (i = 0; u[i].name; i++)
{
found = false;
for (p = 0; p < PERMUTATIONS; p++)
{
if (!shader->programhandle[p].glsl)
continue;
GLSlang_UseProgram(shader->programhandle[p].glsl);
if (u[i].ptype >= SP_FIRSTUNIFORM)
uniformloc = qglGetUniformLocationARB(shader->programhandle[p].glsl, u[i].name);
else
uniformloc = qglGetAttribLocationARB(shader->programhandle[p].glsl, u[i].name);
if (uniformloc != -1)
found = true;
shader->progparm[shader->numprogparams].handle[p] = uniformloc;
}
if (found)
{
shader->progparm[shader->numprogparams].type = u[i].ptype;
shader->numprogparams++;
if (u[i].ptype < SP_FIRSTUNIFORM)
shader->flags |= SHADER_NOBUILTINATTR;
}
}
GLSlang_UseProgram(0);
}
#endif
}
static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **ptr, int qrtype)
{
@ -746,78 +1280,55 @@ static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **p
}
where BLAH is both vertex+frag with #ifdefs
or
program vert frag
program fname
on one line.
*/
void *vert, *frag;
char *token;
char *programbody;
char *start, *end;
token = *ptr;
while (*token == ' ' || *token == '\t' || *token == '\r')
token++;
if (*token == '\n')
end = *ptr;
while (*end == ' ' || *end == '\t' || *end == '\r')
end++;
if (*end == '\n')
{
int count;
token++;
while (*token == ' ' || *token == '\t')
token++;
if (*token != '{')
end++;
while (*end == ' ' || *end == '\t')
end++;
if (*end != '{')
{
Con_Printf("shader \"%s\" missing program string\n", shader->name);
}
else
{
token++;
frag = token;
for (count = 1; *token; token++)
end++;
start = end;
for (count = 1; *end; end++)
{
if (*token == '}')
if (*end == '}')
{
count--;
if (!count)
break;
}
else if (*token == '{')
else if (*end == '{')
count++;
}
vert = BZ_Malloc(token - (char*)frag + 1);
memcpy(vert, frag, token-(char*)frag);
((char*)vert)[token-(char*)frag] = 0;
frag = NULL;
*ptr = token+1;
programbody = BZ_Malloc(end - start + 1);
memcpy(programbody, start, end-start);
programbody[end-start] = 0;
*ptr = end+1;/*skip over it all*/
Shader_LoadProgram(shader, vert, frag, qrtype);
Shader_LoadPermutations(shader->programhandle, programbody, qrtype);
Shader_ProgAutoFields(shader);
BZ_Free(vert);
return;
BZ_Free(programbody);
}
}
vert = Shader_ParseString(ptr);
if (!strcmp(vert, "default"))
{
extern char *defaultglsl2program;
frag = Shader_ParseString(ptr);
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
Shader_LoadProgram(shader, defaultglsl2program, defaultglsl2program, qrtype);
#endif
return;
}
FS_LoadFile(vert, &vert);
frag = Shader_ParseString(ptr);
if (!frag)
frag = NULL;
else
FS_LoadFile(frag, &frag);
Shader_LoadProgram(shader, vert, frag, qrtype);
if (vert)
FS_FreeFile(vert);
if (frag)
FS_FreeFile(frag);
Shader_LoadGeneric(shader->programhandle, Shader_ParseString(ptr), qrtype);
Shader_ProgAutoFields(shader);
}
static void Shader_GLSLProgramName (shader_t *shader, shaderpass_t *pass, char **ptr)
@ -838,6 +1349,7 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p
enum shaderprogparmtype_e parmtype = SP_BAD;
char *token;
qboolean silent = false;
char *forcename = NULL;
token = Shader_ParseString(ptr);
if (!Q_stricmp(token, "opt"))
@ -910,7 +1422,10 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p
else
Con_Printf("shader %s: parameter type \"%s\" not known\n", shader->name, token);
token = Shader_ParseSensString(ptr);
if (forcename)
token = forcename;
else
token = Shader_ParseSensString(ptr);
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
@ -933,7 +1448,10 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p
if (!shader->programhandle[p].glsl)
continue;
GLSlang_UseProgram(shader->programhandle[p].glsl);
uniformloc = qglGetUniformLocationARB(shader->programhandle[p].glsl, token);
if (parmtype >= SP_FIRSTUNIFORM)
uniformloc = qglGetUniformLocationARB(shader->programhandle[p].glsl, token);
else
uniformloc = qglGetAttribLocationARB(shader->programhandle[p].glsl, token);
shader->progparm[shader->numprogparams].handle[p] = uniformloc;
if (uniformloc != -1)
{
@ -964,7 +1482,7 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p
}
}
if (!foundone && !silent)
Con_Printf("shader %s: param without uniform \"%s\"\n", shader->name, token);
Con_Printf("shader %s: param \"%s\" not found\n", shader->name, token);
else
shader->numprogparams++;
@ -1633,6 +2151,7 @@ qboolean Shader_Init (void)
memset(shader_active_hash_mem, 0, Hash_BytesForBuckets(1024));
Hash_InitTable(&shader_active_hash, 1024, shader_active_hash_mem);
Shader_FlushGenerics();
shader_rescan_needed = true;
Shader_NeedReload();
Shader_DoReload();
@ -1773,7 +2292,7 @@ void Shader_Free (shader_t *shader)
for (p = 0; p < PERMUTATIONS; p++)
{
if (shader->programhandle[p].glsl)
GLSlang_DeleteObject(shader->programhandle[p].glsl);
qglDeleteProgramObject_(shader->programhandle[p].glsl);
}
}
#endif
@ -2517,24 +3036,22 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args)
"}\n"
"}\n"
);
/* if (0&&!builtin && gl_config.arb_shader_objects)
#ifdef GLQUAKE
if (!builtin && gl_config.arb_shader_objects && gl_config.nofixedfunc)
{
builtin = (
"{\n"
"program default\n"
"param texture 0 tex_diffuse\n"
"program defaultwall\n"
/*"param texture 0 tex_diffuse\n"
"param texture 1 tex_lightmap\n"
"param texture 2 tex_normalmap\n"
"param texture 3 tex_deluxmap\n"
"param texture 4 tex_fullbright\n"
"param texture 4 tex_fullbright\n"*/
"{\n"
"map $diffuse\n"
"tcgen base\n"
"}\n"
"{\n"
"map $lightmap\n"
"tcgen lightmap\n"
"}\n"
"{\n"
"map $normalmap\n"
@ -2548,7 +3065,7 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args)
"}\n"
);
}
*/
#endif
if (!builtin)
builtin = (
"{\n"
@ -2763,44 +3280,14 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args)
{
builtin = (
"{\n"
"sort blend\n"
"program\n"
"{\n"
"#ifdef VERTEX_SHADER\n"
"varying vec3 pos;\n"
"varying vec2 tc;\n"
"void main (void)\n"
"{\n"
" tc = gl_MultiTexCoord0.st;\n"
" gl_Position = ftransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D watertexture;\n"
"uniform float time;\n"
"uniform float wateralpha;\n"
"varying vec2 tc;\n"
"void main (void)\n"
"{\n"
" vec2 ntc;\n"
" ntc.s = tc.s + sin(tc.t+time)*0.125;\n"
" ntc.t = tc.t + sin(tc.s+time)*0.125;\n"
" vec3 ts = vec3(texture2D(watertexture, ntc));\n"
" gl_FragColor = vec4(ts, wateralpha);\n"
"}\n"
"#endif\n"
"}\n"
"param time time\n"
"param texture 0 watertexture\n"
"sort blend\n" /*make sure it always has the same sort order, so switching on/off wateralpha doesn't break stuff*/
"program defaultwarp\n"
"if r_wateralpha != 1\n"
"[\n"
"param cvarf r_wateralpha wateralpha\n"
"{\n"
"map $diffuse\n"
"tcmod turb 0 0 3 0.1\n"
"blendfunc gl_src_alpha gl_one_minus_src_alpha\n"
"}\n"
"]\n"
@ -2809,6 +3296,7 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args)
"param constf 1 wateralpha\n"
"{\n"
"map $diffuse\n"
"tcmod turb 0 0 3 0.1\n"
"}\n"
"]\n"
"surfaceparm nodlight\n"
@ -2883,50 +3371,8 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args)
builtin = (
"{\n"
"sort sky\n"
"program\n"
"{\n"
"#ifdef VERTEX_SHADER\n"
"varying vec3 pos;\n"
"void main (void)\n"
"{\n"
" pos = gl_Vertex.xyz;\n"
" gl_Position = ftransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D solidt;\n"
"uniform sampler2D transt;\n"
"uniform float time;\n"
"uniform vec3 eyepos;\n"
"varying vec3 pos;\n"
"void main (void)\n"
"{\n"
" vec2 tccoord;\n"
" vec3 dir = pos - eyepos;\n"
" dir.z *= 3.0;\n"
" dir.xy /= 0.5*length(dir);\n"
" tccoord = (dir.xy + time*0.03125);\n"
" vec3 solid = vec3(texture2D(solidt, tccoord));\n"
" tccoord = (dir.xy + time*0.0625);\n"
" vec4 clouds = texture2D(transt, tccoord);\n"
" gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n"
// " gl_FragColor.rgb = solid.rgb;/*gl_FragColor.g = clouds.r;*/gl_FragColor.b = clouds.a;\n"
"}\n"
"#endif\n"
"}\n"
"param time time\n"
"program defaultsky\n"
"param eyepos eyepos\n"
"param texture 0 solidt\n"
"param texture 1 transt\n"
"surfaceparm nodlight\n"
//"skyparms - 512 -\n"
"{\n"
@ -3075,6 +3521,7 @@ void Shader_DefaultSkin(char *shortname, shader_t *s, const void *args)
{
Shader_DefaultScript(shortname, s,
"{\n"
"program defaultskin\n"
"{\n"
"map $diffuse\n"
"rgbgen lightingDiffuse\n"
@ -3130,6 +3577,7 @@ void Shader_Default2D(char *shortname, shader_t *s, const void *genargs)
{
Shader_DefaultScript(shortname, s,
"{\n"
// "program default2d\n"
"nomipmaps\n"
"{\n"
"clampmap $diffuse\n"
@ -3291,13 +3739,47 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
if (ruleset_allow_shaders.ival)
{
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects)
if (qrenderer == QR_OPENGL)
{
if (Shader_ParseShader(va("%s_glsl", shortname), shortname, s))
if (gl_config.gles && gl_config.glversion >= 2)
{
s->generator = defaultgen;
s->genargs = genargs;
return f;
if (Shader_ParseShader(va("%s_gles2", shortname), shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
return f;
}
}
if (gl_config.glversion >= 3)
{
if (Shader_ParseShader(va("%s_glsl3", shortname), shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
return f;
}
}
if (gl_config.arb_shader_objects)
{
if (Shader_ParseShader(va("%s_glsl", shortname), shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
return f;
}
}
}
#endif
#ifdef D3DQUAKE
if (qrenderer == QR_DIRECT3D)
{
{
if (Shader_ParseShader(va("%s_hlsl", shortname), shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
return f;
}
}
}
#endif

View file

@ -10,12 +10,6 @@
#define nearplane (16)
#if 1//def _DEBUG
#define checkerror() if (qglGetError()) Con_Printf("Error detected at line %s:%i\n", __FILE__, __LINE__)
#else
#define checkerror()
#endif
static int shadow_fbo_id;
static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour);
@ -1288,8 +1282,6 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p
// qglDepthRange(0, 1);
checkerror();
if (l->fov)
qglViewport (0, 0, smsize, smsize);
else
@ -1335,8 +1327,6 @@ checkerror();
R_SetFrustum(proj, mvm);
checkerror();
if (smesh)
for (tno = 0; tno < smesh->numsurftextures; tno++)
{
@ -1372,8 +1362,6 @@ checkerror();
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
checkerror();
}
void Sh_Shutdown(void)
@ -1396,20 +1384,14 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis)
if (!TEXVALID(l->stexture))
{
l->stexture = GL_AllocNewTexture(smsize, smsize);
checkerror();
GL_Bind(l->stexture);
checkerror();
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize, smsize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
// qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize, smsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
checkerror();
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
checkerror();
}
smesh = SHM_BuildShadowVolumeMesh(l, lvis, NULL);
@ -1550,7 +1532,6 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
t[13] = bp[7];
t[14] = bp[11];
t[15] = bp[15];
checkerror();
bench.numlights++;
@ -1565,7 +1546,6 @@ checkerror();
GL_SelectTexture(0);
checkerror();
ve = 0;
BE_SelectDLight(l, colour);
@ -1577,9 +1557,6 @@ checkerror();
qglMatrixMode(GL_TEXTURE);
qglLoadIdentity();
qglMatrixMode(GL_MODELVIEW);
checkerror();
}
@ -1873,8 +1850,6 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
}
bench.numlights++;
checkerror();
BE_SelectDLight(dl, colour);
BE_SelectMode(BEM_STENCIL, 0);
@ -2008,8 +1983,6 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
qglPopMatrix();
#endif
checkerror();
PPL_RevertToKnownState();
BE_SelectMode(BEM_LIGHT, 0);
@ -2018,7 +1991,6 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
qglDisable(GL_STENCIL_TEST);
qglStencilFunc( GL_ALWAYS, 0, ~0 );
checkerror();
return true;
}

View file

@ -4,12 +4,6 @@
#include "gl_draw.h"
#include "shader.h"
#ifdef _DEBUG
#define checkerror() if (qglGetError()) Con_Printf("Error detected at line %s:%i\n", __FILE__, __LINE__)
#else
#define checkerror()
#endif
//standard 1.1 opengl calls
void (APIENTRY *qglAlphaFunc) (GLenum func, GLclampf ref);
void (APIENTRY *qglBegin) (GLenum mode);
@ -138,17 +132,27 @@ PFNGLGENPROGRAMSARBPROC qglGenProgramsARB;
FTEPFNGLLOCKARRAYSEXTPROC qglLockArraysEXT;
FTEPFNGLUNLOCKARRAYSEXTPROC qglUnlockArraysEXT;
//glslang - arb_shader_objects
/*glslang - arb_shader_objects
gl core uses different names/distinctions from the extension
*/
FTEPFNGLCREATEPROGRAMOBJECTARBPROC qglCreateProgramObjectARB;
FTEPFNGLDELETEOBJECTARBPROC qglDeleteObjectARB;
FTEPFNGLDELETEOBJECTARBPROC qglDeleteProgramObject_;
FTEPFNGLDELETEOBJECTARBPROC qglDeleteShaderObject_;
FTEPFNGLUSEPROGRAMOBJECTARBPROC qglUseProgramObjectARB;
FTEPFNGLCREATESHADEROBJECTARBPROC qglCreateShaderObjectARB;
FTEPFNGLSHADERSOURCEARBPROC qglShaderSourceARB;
FTEPFNGLCOMPILESHADERARBPROC qglCompileShaderARB;
FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetObjectParameterivARB;
FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetShaderParameteriv_;
FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetProgramParameteriv_;
FTEPFNGLATTACHOBJECTARBPROC qglAttachObjectARB;
FTEPFNGLGETINFOLOGARBPROC qglGetInfoLogARB;
FTEPFNGLGETINFOLOGARBPROC qglGetShaderInfoLog_;
FTEPFNGLGETINFOLOGARBPROC qglGetProgramInfoLog_;
FTEPFNGLLINKPROGRAMARBPROC qglLinkProgramARB;
FTEPFNGLBINDATTRIBLOCATIONARBPROC qglBindAttribLocationARB;
FTEPFNGLGETATTRIBLOCATIONARBPROC qglGetAttribLocationARB;
FTEPFNGLVERTEXATTRIBPOINTER qglVertexAttribPointer;
FTEPFNGLENABLEVERTEXATTRIBARRAY qglEnableVertexAttribArray;
FTEPFNGLDISABLEVERTEXATTRIBARRAY qglDisableVertexAttribArray;
FTEPFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB;
FTEPFNGLUNIFORMMATRIX4FVARBPROC qglUniformMatrix4fvARB;
FTEPFNGLUNIFORM4FARBPROC qglUniform4fARB;
@ -331,12 +335,22 @@ void APIENTRY GL_BindBufferARBStub(GLenum target, GLuint id)
#define getglcore getglfunction
#define getglext(name) getglfunction(name)
void GL_CheckExtensions (void *(*getglfunction) (char *name))
void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
{
extern cvar_t gl_bump;
memset(&gl_config, 0, sizeof(gl_config));
gl_config.glversion = ver;
if (!strncmp(gl_version, "OpenGL ES", 9))
gl_config.gles = true;
else
gl_config.gles = false;
gl_config.nofixedfunc = (gl_config.gles && gl_config.glversion >= 2) /*||
(!gl_config.gles && gl_config.glversion >= 3 && noncompat)*/;
//multitexture
gl_mtexable = false;
gl_mtexarbable = 0;
@ -406,7 +420,14 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
// if (GL_CheckExtension("GL_SGIS_generate_mipmap")) //a suprising number of implementations have this broken.
// gl_config.sgis_generate_mipmap = true;
if (GL_CheckExtension("GL_ARB_multitexture") && !COM_CheckParm("-noamtex"))
if (gl_config.gles)
{
qglActiveTextureARB = (void *) getglext("glActiveTexture");
qglSelectTextureSGIS = qglActiveTextureARB;
mtexid0 = GL_TEXTURE0_ARB;
mtexid1 = GL_TEXTURE1_ARB;
}
else if (GL_CheckExtension("GL_ARB_multitexture") && !COM_CheckParm("-noamtex"))
{ //ARB multitexture is the popular choice.
qglActiveTextureARB = (void *) getglext("glActiveTextureARB");
qglClientActiveTextureARB = (void *) getglext("glClientActiveTextureARB");
@ -534,15 +555,23 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
{
gl_config.arb_shader_objects = true;
qglCreateProgramObjectARB = (void *)getglext("glCreateProgramObjectARB");
qglDeleteObjectARB = (void *)getglext("glDeleteObjectARB");
qglDeleteProgramObject_ = (void *)getglext("glDeleteObjectARB");
qglDeleteShaderObject_ = (void *)getglext("glDeleteObjectARB");
qglUseProgramObjectARB = (void *)getglext("glUseProgramObjectARB");
qglCreateShaderObjectARB = (void *)getglext("glCreateShaderObjectARB");
qglShaderSourceARB = (void *)getglext("glShaderSourceARB");
qglCompileShaderARB = (void *)getglext("glCompileShaderARB");
qglGetObjectParameterivARB = (void *)getglext("glGetObjectParameterivARB");
qglGetProgramParameteriv_ = (void *)getglext("glGetObjectParameterivARB");
qglGetShaderParameteriv_ = (void *)getglext("glGetObjectParameterivARB");
qglAttachObjectARB = (void *)getglext("glAttachObjectARB");
qglGetInfoLogARB = (void *)getglext("glGetInfoLogARB");
qglGetProgramInfoLog_ = (void *)getglext("glGetInfoLogARB");
qglGetShaderInfoLog_ = (void *)getglext("glGetInfoLogARB");
qglLinkProgramARB = (void *)getglext("glLinkProgramARB");
qglBindAttribLocationARB = (void *)getglext("glBindAttribLocationARB");
qglGetAttribLocationARB = (void *)getglext("glGetAttribLocationARB");
qglVertexAttribPointer = (void *)getglext("glVertexAttribPointerARB");
qglEnableVertexAttribArray = (void *)getglext("glEnableVertexAttribArrayARB");
qglDisableVertexAttribArray = (void *)getglext("glDisableVertexAttribArrayARB");
qglGetUniformLocationARB = (void *)getglext("glGetUniformLocationARB");
qglUniformMatrix4fvARB = (void *)getglext("glUniformMatrix4fvARB");
qglUniform4fARB = (void *)getglext("glUniform4fARB");
@ -552,6 +581,36 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglUniform1iARB = (void *)getglext("glUniform1iARB");
qglUniform1fARB = (void *)getglext("glUniform1fARB");
}
else if (gl_config.gles && gl_config.glversion >= 2)
{
gl_config.arb_shader_objects = true;
qglCreateProgramObjectARB = (void *)getglext( "glCreateProgram");
qglDeleteProgramObject_ = (void *)getglext( "glDeleteProgram");
qglDeleteShaderObject_ = (void *)getglext( "glDeleteShader");
qglUseProgramObjectARB = (void *)getglext( "glUseProgram");
qglCreateShaderObjectARB = (void *)getglext( "glCreateShader");
qglGetProgramParameteriv_ = (void *)getglext( "glGetProgramiv");
qglGetShaderParameteriv_ = (void *)getglext( "glGetShaderiv");
qglAttachObjectARB = (void *)getglext( "glAttachShader");
qglGetProgramInfoLog_ = (void *)getglext( "glGetProgramInfoLog");
qglGetShaderInfoLog_ = (void *)getglext( "glGetShaderInfoLog");
qglShaderSourceARB = (void *)getglext("glShaderSource");
qglCompileShaderARB = (void *)getglext("glCompileShader");
qglLinkProgramARB = (void *)getglext("glLinkProgram");
qglBindAttribLocationARB = (void *)getglext("glBindAttribLocation");
qglGetAttribLocationARB = (void *)getglext("glGetAttribLocation");
qglVertexAttribPointer = (void *)getglext("glVertexAttribPointer");
qglEnableVertexAttribArray = (void *)getglext("glEnableVertexAttribArray");
qglDisableVertexAttribArray = (void *)getglext("glDisableVertexAttribArray");
qglGetUniformLocationARB = (void *)getglext("glGetUniformLocation");
qglUniformMatrix4fvARB = (void *)getglext("glUniformMatrix4fv");
qglUniform4fARB = (void *)getglext("glUniform4f");
qglUniform4fvARB = (void *)getglext("glUniform4fv");
qglUniform3fARB = (void *)getglext("glUniform3f");
qglUniform3fvARB = (void *)getglext("glUniform3fv");
qglUniform1iARB = (void *)getglext("glUniform1i");
qglUniform1fARB = (void *)getglext("glUniform1f");
}
if (GL_CheckExtension("GL_EXT_framebuffer_object"))
{
@ -586,41 +645,43 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
// glslang helper api function definitions
// type should be GL_FRAGMENT_SHADER_ARB or GL_VERTEX_SHADER_ARB
GLhandleARB GLSlang_CreateShader (char *precompilerconstants, char *shadersource, GLenum shadertype)
GLhandleARB GLSlang_CreateShader (char **precompilerconstants, char *shadersource, GLenum shadertype)
{
GLhandleARB shader;
GLint compiled;
char str[1024];
int loglen;
char *prstrings[4];
char *prstrings[3+16];
int strings = 0;
prstrings[0] = "#define ENGINE_"DISTRIBUTION"\n";
prstrings[strings++] = "#define ENGINE_"DISTRIBUTION"\n";
switch (shadertype)
{
case GL_FRAGMENT_SHADER_ARB:
prstrings[1] = "#define FRAGMENT_SHADER\n";
prstrings[strings++] = "#define FRAGMENT_SHADER\n";
break;
case GL_VERTEX_SHADER_ARB:
prstrings[1] = "#define VERTEX_SHADER\n";
prstrings[strings++] = "#define VERTEX_SHADER\n";
break;
default:
prstrings[1] = "#define UNKNOWN_SHADER\n";
prstrings[strings++] = "#define UNKNOWN_SHADER\n";
break;
}
prstrings[2] = precompilerconstants;
prstrings[3] = shadersource;
while(*precompilerconstants)
prstrings[strings++] = *precompilerconstants++;
prstrings[strings++] = shadersource;
shader = qglCreateShaderObjectARB(shadertype);
qglShaderSourceARB(shader, 4, (const GLcharARB**)prstrings, NULL);
qglShaderSourceARB(shader, strings, (const GLcharARB**)prstrings, NULL);
qglCompileShaderARB(shader);
qglGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
qglGetShaderParameteriv_(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
if(!compiled)
{
Con_DPrintf("Shader source:\n%s%s%s\n", prstrings[0], prstrings[1], prstrings[2], prstrings[3]);
qglGetInfoLogARB(shader, sizeof(str), NULL, str);
qglDeleteObjectARB(shader);
qglGetShaderInfoLog_(shader, sizeof(str), NULL, str);
qglDeleteShaderObject_(shader);
switch (shadertype)
{
case GL_FRAGMENT_SHADER_ARB:
@ -638,10 +699,10 @@ GLhandleARB GLSlang_CreateShader (char *precompilerconstants, char *shadersource
if (developer.ival)
{
qglGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &loglen);
qglGetShaderParameteriv_(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &loglen);
if (loglen)
{
qglGetInfoLogARB(shader, sizeof(str), NULL, str);
qglGetShaderInfoLog_(shader, sizeof(str), NULL, str);
if (strstr(str, "WARNING"))
{
Con_Printf("Shader source:\n%s%s%s\n", prstrings[0], prstrings[1], prstrings[2], prstrings[3]);
@ -663,21 +724,25 @@ GLhandleARB GLSlang_CreateProgramObject (GLhandleARB vert, GLhandleARB frag)
qglAttachObjectARB(program, vert);
qglAttachObjectARB(program, frag);
qglBindAttribLocationARB(program, 0, "v_position");
qglBindAttribLocationARB(program, 1, "v_colour");
qglBindAttribLocationARB(program, 2, "v_texcoord");
qglBindAttribLocationARB(program, 3, "v_lmcoord");
qglBindAttribLocationARB(program, 4, "v_normal");
qglBindAttribLocationARB(program, 5, "v_snormal");
qglBindAttribLocationARB(program, 6, "v_tnormal");
qglLinkProgramARB(program);
//flag the source objects for deletion, they'll only be deleted when they're no longer attached to anything
qglDeleteObjectARB(vert);
qglDeleteObjectARB(frag);
qglGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linked);
qglGetProgramParameteriv_(program, GL_OBJECT_LINK_STATUS_ARB, &linked);
if(!linked)
{
qglGetInfoLogARB(program, sizeof(str), NULL, str);
qglGetProgramInfoLog_(program, sizeof(str), NULL, str);
Con_Printf("Program link error: %s\n", str);
return (GLhandleARB)0;
}
return program;
}
@ -696,7 +761,7 @@ bucket_t *compiledshadersbuckets[64];
static hashtable_t compiledshaderstable;
#endif
GLhandleARB GLSlang_CreateProgram(char *precompilerconstants, char *vert, char *frag)
GLhandleARB GLSlang_CreateProgram(char **precompilerconstants, char *vert, char *frag)
{
GLhandleARB handle;
GLhandleARB vs;
@ -705,12 +770,13 @@ GLhandleARB GLSlang_CreateProgram(char *precompilerconstants, char *vert, char *
unsigned int hashkey;
struct compiledshaders_s *cs;
#endif
char *nullconstants = NULL;
if (!gl_config.arb_shader_objects)
return 0;
if (!precompilerconstants)
precompilerconstants = "";
precompilerconstants = &nullconstants;
#if HASHPROGRAMS
hashkey = Hash_Key(precompilerconstants, ~0) ^ Hash_Key(frag, ~0);
@ -731,13 +797,14 @@ GLhandleARB GLSlang_CreateProgram(char *precompilerconstants, char *vert, char *
vs = GLSlang_CreateShader(precompilerconstants, vert, GL_VERTEX_SHADER_ARB);
fs = GLSlang_CreateShader(precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB);
if (!vs || !fs)
handle = 0;
else
handle = GLSlang_CreateProgramObject(vs, fs);
//delete ignores 0s.
qglDeleteObjectARB(vs);
qglDeleteObjectARB(fs);
qglDeleteShaderObject_(vs);
qglDeleteShaderObject_(fs);
#if HASHPROGRAMS
cs = Z_Malloc(sizeof(*cs) + strlen(precompilerconstants)+1+strlen(vert)+1+strlen(frag)+1);
@ -903,13 +970,16 @@ void GL_Init(void *(*getglfunction) (char *name))
qglGetIntegerv(GL_MINOR_VERSION, &gl_minor_version);
if (qglGetError())
{
gl_config.glversion = atof(gl_version);
gl_major_version = 1;
gl_minor_version = 1;
}
else
{
gl_config.glversion = gl_major_version + (gl_minor_version/10.f);
/*GL_MAJOR_VERSION not supported? try and parse (es-aware)*/
const char *s;
for (s = gl_version; *s && (*s < '0' || *s > '9'); s++)
;
gl_major_version = atoi(s);
while(*s >= '0' && *s <= '9')
s++;
if (*s == '.')
s++;
gl_minor_version = atoi(s);
}
qglGetIntegerv(GL_NUM_EXTENSIONS, &gl_num_extensions);
if (!qglGetError() && gl_num_extensions)
@ -917,14 +987,13 @@ void GL_Init(void *(*getglfunction) (char *name))
int i;
if (developer.value)
{
Con_Printf ("GL_EXTENSIONS:");
Con_Printf ("GL_EXTENSIONS:\n");
for (i = 0; i < gl_num_extensions; i++)
{
Con_Printf (" %s", qglGetStringi(GL_EXTENSIONS, i));
if ((i & 15) == 15)
Con_Printf("\n");
Con_Printf("\n");
}
Con_Printf ("\n");
Con_Printf ("end of list\n");
}
else
Con_Printf ("GL_EXTENSIONS: %i extensions\n", gl_num_extensions);
@ -940,20 +1009,35 @@ void GL_Init(void *(*getglfunction) (char *name))
Sys_Error("no extensions\n");
}
GL_CheckExtensions (getglfunction);
GL_CheckExtensions (getglfunction, gl_major_version + (gl_minor_version/10.f));
if (gl_config.gles && gl_config.glversion >= 2)
{
/*no matricies in gles, so don't try!*/
qglLoadMatrixf = NULL;
qglPolygonMode = NULL;
qglShadeModel = NULL;
qglDepthRange = NULL;
qglEnableClientState = NULL;
qglDisableClientState = NULL;
qglDrawRangeElements = GL_DrawRangeElementsEmul;
}
qglClearColor (0,0,0,0); //clear to black so that it looks a little nicer on start.
qglClear(GL_COLOR_BUFFER_BIT);
qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
qglShadeModel (GL_FLAT);
if (qglPolygonMode)
qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
if (qglShadeModel)
qglShadeModel (GL_FLAT);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
checkerror();
#ifdef DEBUG
if (qglDebugMessageEnableAMD)
qglDebugMessageEnableAMD(0, 0, 0, NULL, true);
@ -965,8 +1049,6 @@ void GL_Init(void *(*getglfunction) (char *name))
#if HASHPROGRAMS
Hash_InitTable(&compiledshaderstable, sizeof(compiledshadersbuckets)/Hash_BytesForBuckets(1), compiledshadersbuckets);
#endif
checkerror();
}
unsigned int d_8to24rgbtable[256];
@ -1071,3 +1153,4 @@ rendererinfo_t openglrendererinfo = {
};
#endif

View file

@ -152,12 +152,6 @@ void ClearAllStates (void);
void VID_UpdateWindowStatus (HWND hWnd);
void GL_Init(void *(*getglfunction) (char *name));
#ifdef _DEBUG
#define checkerror() if (qglGetError()) Con_Printf("Error detected at line %s:%i\n", __FILE__, __LINE__)
#else
#define checkerror()
#endif
typedef void (APIENTRY *lp3DFXFUNC) (int, int, int, int, int, const void*);
lp3DFXFUNC qglColorTableEXT;
qboolean is8bit = false;
@ -946,10 +940,10 @@ qboolean VID_AttachGL (rendererstate_t *info)
Con_SafePrintf(CON_ERROR "wglMakeCurrent failed\n"); //green to make it show.
return false;
}
/*
if (developer.ival)
{
char *(WINAPI *wglGetExtensionsString)(void) = NULL;
char *(WINAPI *wglGetExtensionsString)(HDC hdc) = NULL;
if (!wglGetExtensionsString)
wglGetExtensionsString = getglfunc("wglGetExtensionsString");
if (!wglGetExtensionsString)
@ -957,9 +951,9 @@ qboolean VID_AttachGL (rendererstate_t *info)
if (!wglGetExtensionsString)
wglGetExtensionsString = getglfunc("wglGetExtensionsStringEXT");
if (wglGetExtensionsString)
Con_SafePrintf("WGL extensions: %s\n", wglGetExtensionsString());
Con_SafePrintf("WGL extensions: %s\n", wglGetExtensionsString(maindc));
}
*/
qwglCreateContextAttribsARB = getglfunc("wglCreateContextAttribsARB");
#ifdef _DEBUG
//attempt to promote that to opengl3.
@ -969,18 +963,23 @@ qboolean VID_AttachGL (rendererstate_t *info)
int attribs[9];
char *mv;
int i = 0;
char *ver;
mv = vid_gl_context_version.string;
ver = vid_gl_context_version.string;
if (!*ver && vid_gl_context_es2.ival)
ver = "2.0";
mv = ver;
while (*mv)
{
if (*mv++ == '.')
break;
}
if (*vid_gl_context_version.string)
if (*ver)
{
attribs[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
attribs[i++] = (int)vid_gl_context_version.value;
attribs[i++] = atoi(ver);
}
if (*mv)
{
@ -1031,8 +1030,10 @@ qboolean VID_AttachGL (rendererstate_t *info)
else
{
DWORD error = GetLastError();
if (error == ERROR_INVALID_VERSION_ARB)
if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
Con_Printf("Unsupported OpenGL context version (%s).\n", vid_gl_context_version.string);
else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
Con_Printf("Unsupported OpenGL profile (%s).\n", vid_gl_context_es2.ival?"gles":(vid_gl_context_compatibility.ival?"compat":"core"));
else
Con_Printf("Unknown error creating an OpenGL (%s) Context.\n", vid_gl_context_version.string);
}
@ -1043,8 +1044,6 @@ qboolean VID_AttachGL (rendererstate_t *info)
TRACE(("dbg: VID_AttachGL: GL_Init\n"));
GL_Init(getglfunc);
checkerror();
qwglChoosePixelFormatARB = getglfunc("wglChoosePixelFormatARB");
qwglSwapIntervalEXT = getglfunc("wglSwapIntervalEXT");
@ -1061,8 +1060,6 @@ qboolean VID_AttachGL (rendererstate_t *info)
if (!qGetDeviceGammaRamp) qGetDeviceGammaRamp = (void*)GetDeviceGammaRamp;
if (!qSetDeviceGammaRamp) qSetDeviceGammaRamp = (void*)SetDeviceGammaRamp;
checkerror();
return true;
}

View file

@ -89,7 +89,7 @@ void R_DrawSkyChain (batch_t *batch)
return;
}
#ifdef GLQUAKE
if (*r_fastsky.string)
if (*r_fastsky.string && qrenderer == QR_OPENGL)
{
R_CalcSkyChainBounds(batch);

View file

@ -88,6 +88,11 @@ typedef void (APIENTRYP FTEPFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB
typedef void (APIENTRYP FTEPFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
typedef void (APIENTRYP FTEPFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
typedef void (APIENTRYP FTEPFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
typedef void (APIENTRYP FTEPFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, GLcharARB *name);
typedef GLint (APIENTRYP FTEPFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
typedef void (APIENTRYP FTEPFNGLVERTEXATTRIBPOINTER) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
typedef void (APIENTRYP FTEPFNGLENABLEVERTEXATTRIBARRAY) (GLuint index);
typedef void (APIENTRYP FTEPFNGLDISABLEVERTEXATTRIBARRAY) (GLuint index);
typedef GLint (APIENTRYP FTEPFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
typedef void (APIENTRYP FTEPFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
typedef void (APIENTRYP FTEPFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, GLfloat *value);
@ -113,6 +118,8 @@ qboolean GL_CheckExtension(char *extname);
typedef struct {
float glversion;
qboolean nofixedfunc;
qboolean gles;
qboolean tex_env_combine;
qboolean nv_tex_env_combine4;
qboolean env_add;
@ -305,7 +312,7 @@ void GL_Set2D (void);
//
qboolean R_ShouldDraw(entity_t *e);
#ifdef GLQUAKE
void R_RotateForEntity (const entity_t *e, const model_t *mod);
void R_RotateForEntity (float *modelviewmatrix, const entity_t *e, const model_t *mod);
void GL_InitSceneProcessingShaders (void);
void GL_SetupSceneProcessingTextures (void);
@ -752,15 +759,23 @@ extern PFNGLGENPROGRAMSARBPROC qglGenProgramsARB;
//glslang - arb_shader_objects
extern FTEPFNGLCREATEPROGRAMOBJECTARBPROC qglCreateProgramObjectARB;
extern FTEPFNGLDELETEOBJECTARBPROC qglDeleteObjectARB;
extern FTEPFNGLDELETEOBJECTARBPROC qglDeleteProgramObject_;
extern FTEPFNGLDELETEOBJECTARBPROC qglDeleteShaderObject_;
extern FTEPFNGLUSEPROGRAMOBJECTARBPROC qglUseProgramObjectARB;
extern FTEPFNGLCREATESHADEROBJECTARBPROC qglCreateShaderObjectARB;
extern FTEPFNGLSHADERSOURCEARBPROC qglShaderSourceARB;
extern FTEPFNGLCOMPILESHADERARBPROC qglCompileShaderARB;
extern FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetObjectParameterivARB;
extern FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetProgramParameteriv_;
extern FTEPFNGLGETOBJECTPARAMETERIVARBPROC qglGetShaderParameteriv_;
extern FTEPFNGLATTACHOBJECTARBPROC qglAttachObjectARB;
extern FTEPFNGLGETINFOLOGARBPROC qglGetInfoLogARB;
extern FTEPFNGLGETINFOLOGARBPROC qglGetProgramInfoLog_;
extern FTEPFNGLGETINFOLOGARBPROC qglGetShaderInfoLog_;
extern FTEPFNGLLINKPROGRAMARBPROC qglLinkProgramARB;
extern FTEPFNGLBINDATTRIBLOCATIONARBPROC qglBindAttribLocationARB;
extern FTEPFNGLGETATTRIBLOCATIONARBPROC qglGetAttribLocationARB;
extern FTEPFNGLVERTEXATTRIBPOINTER qglVertexAttribPointer;
extern FTEPFNGLENABLEVERTEXATTRIBARRAY qglEnableVertexAttribArray;
extern FTEPFNGLDISABLEVERTEXATTRIBARRAY qglDisableVertexAttribArray;
extern FTEPFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB;
extern FTEPFNGLUNIFORMMATRIX4FVARBPROC qglUniformMatrix4fvARB;
extern FTEPFNGLUNIFORM4FARBPROC qglUniform4fARB;
@ -771,12 +786,19 @@ extern FTEPFNGLUNIFORM1IARBPROC qglUniform1iARB;
extern FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB;
//glslang helper api
GLhandleARB GLSlang_CreateProgram (char *precompilerconstants, char *vert, char *frag);
GLhandleARB GLSlang_CreateProgram (char **precompilerconstants, char *vert, char *frag);
GLint GLSlang_GetUniformLocation (int prog, char *name);
#define GLSlang_UseProgram(prog) qglUseProgramObjectARB(prog);
#define GLSlang_SetUniform1i(uni, parm0) qglUniform1iARB(uni, parm0);
#define GLSlang_SetUniform1f(uni, parm0) qglUniform1fARB(uni, parm0);
#define GLSlang_DeleteObject(object) qglDeleteObjectARB(object);
void GL_SelectProgram(int program);
#define GLSlang_UseProgram(prog) GL_SelectProgram(prog)
#define GLSlang_SetUniform1i(uni, parm0) qglUniform1iARB(uni, parm0)
#define GLSlang_SetUniform1f(uni, parm0) qglUniform1fARB(uni, parm0)
#ifdef _DEBUG
#define checkglerror() do {int i=qglGetError(); if (i) Con_Printf("GL Error %i detected at line %s:%i\n", i, __FILE__, __LINE__);}while(0)
#else
#define checkglerror()
#endif
extern FTEPFNGLLOCKARRAYSEXTPROC qglLockArraysEXT;

View file

@ -4148,9 +4148,7 @@ rendererinfo_t d3dfglrendererinfo = {
GLSCR_UpdateScreen,
/*backend*/
NULL,
NULL,
/*backend*/
NULL,
NULL,
NULL,

View file

@ -233,29 +233,48 @@ enum{
PERMUTATION_GENERIC = 0,
PERMUTATION_BUMPMAP = 1,
PERMUTATION_SPECULAR = 2,
PERMUTATION_BUMP_SPEC,
PERMUTATION_OFFSET = 4,
PERMUTATION_OFFSET_BUMP,
PERMUTATION_OFFSET_SPEC,
PERMUTATION_OFFSET_BUMP_SPEC,
PERMUTATION_FULLBRIGHT = 4,
PERMUTATION_LOWER = 8,
PERMUTATION_UPPER = 16,
PERMUTATION_OFFSET = 32,
PERMUTATIONS
PERMUTATIONS = 64
};
typedef struct {
enum shaderprogparmtype_e {
SP_BAD,
SP_BAD, //never set (hopefully)
SP_ATTR_VERTEX,
SP_ATTR_COLOUR,
SP_ATTR_TEXCOORD,
SP_ATTR_LMCOORD,
SP_ATTR_NORMALS,
SP_ATTR_SNORMALS,
SP_ATTR_TNORMALS,
SP_FIRSTUNIFORM, //never set
/*entity properties*/
SP_ENTCOLOURS,
SP_TOPCOLOURS,
SP_BOTTOMCOLOURS,
SP_TIME,
SP_E_L_DIR, /*these light values are non-dynamic light as in classic quake*/
SP_E_L_MUL,
SP_E_L_AMBIENT,
SP_EYEPOS,
SP_ENTMATRIX,
SP_VIEWMATRIX,
SP_MODELMATRIX,
SP_MODELVIEWMATRIX,
SP_PROJECTIONMATRIX,
SP_MODELVIEWPROJECTIONMATRIX,
SP_RENDERTEXTURESCALE, /*multiplier for currentrender->texcoord*/
SP_LIGHTRADIUS,
SP_LIGHTRADIUS, /*these light values are realtime lighting*/
SP_LIGHTCOLOUR,
SP_LIGHTPOSITION,
@ -277,7 +296,10 @@ typedef struct {
};
} shaderprogparm_t;
union programhandle_u
{
int glsl;
};
typedef struct {
float factor;
float unit;
@ -321,12 +343,11 @@ struct shader_s
SHADER_NODLIGHT = 1 << 15, //from surfaceflags
SHADER_HASLIGHTMAP = 1 << 16,
SHADER_HASTOPBOTTOM = 1 << 17
SHADER_HASTOPBOTTOM = 1 << 17,
SHADER_NOBUILTINATTR = 1 << 18 /*using custom glsl attributes so don't feed it builtins*/
} flags;
union {
int glsl;
} programhandle[PERMUTATIONS];
union programhandle_u programhandle[PERMUTATIONS];
int numprogparams;
shaderprogparm_t progparm[SHADER_PROGPARMS_MAX];