Version 13 of the VBO and GLSL patch

This commit is contained in:
Richard Allen 2011-04-11 17:59:37 +00:00
parent 8153444877
commit 1d54461fbf
19 changed files with 1487 additions and 242 deletions

View file

@ -70,6 +70,7 @@ void GL_SelectTexture( int unit )
return;
}
#if 0
if ( unit == 0 )
{
qglActiveTextureARB( GL_TEXTURE0_ARB );
@ -92,6 +93,13 @@ void GL_SelectTexture( int unit )
} else {
ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit );
}
#else
qglActiveTextureARB( GL_TEXTURE0_ARB + unit );
if (!(glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer && glRefConfig.glsl && r_arb_shader_objects->integer))
{
qglClientActiveTextureARB( GL_TEXTURE0_ARB + unit );
}
#endif
glState.currenttmu = unit;
}
@ -1021,13 +1029,16 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
if (glRefConfig.glsl && r_arb_shader_objects->integer)
{
shaderProgram_t *sp = &tr.textureOnlyShader;
shaderProgram_t *sp = &tr.textureColorShader;
vec4_t color;
GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, TEXTUREONLY_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
VectorSet4(color, 1, 1, 1, 1);
GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);
}
else
{
@ -1481,3 +1492,4 @@ void RB_RenderThread( void ) {
}

View file

@ -255,6 +255,7 @@ static void R_LoadLightmaps( lump_t *l ) {
//int BIGNUM=16;
byte *fatbuffer;
byte *fatbuffer2;
int xoff, yoff, x, y;
//float scale = 0.9f;
@ -273,6 +274,9 @@ static void R_LoadLightmaps( lump_t *l ) {
// create all the lightmaps
numLightmaps = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3);
numLightmaps >>= (tr.worldDeluxeMapping ? 1 : 0);
if(numLightmaps == 1)
{
//FIXME: HACK: maps with only one lightmap turn up fullbright for some reason.
@ -304,18 +308,33 @@ static void R_LoadLightmaps( lump_t *l ) {
// This is going to be huge (4, 16, or 64MB), so don't use ri.Malloc()
fatbuffer = ri.Hunk_AllocateTempMemory(sizeof(byte) * tr.fatLightmapSize * tr.fatLightmapSize * 4);
Com_Memset(fatbuffer, 128, tr.fatLightmapSize * tr.fatLightmapSize * 4);
if (tr.worldDeluxeMapping)
{
tr.deluxemaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low );
fatbuffer2 = ri.Hunk_AllocateTempMemory(sizeof(byte) * tr.fatLightmapSize * tr.fatLightmapSize * 4);
Com_Memset(fatbuffer2, 128, tr.fatLightmapSize * tr.fatLightmapSize * 4);
}
for(i = 0; i < numLightmaps; i++)
{
// expand the 24 bit on-disk to 32 bit
buf_p = buf + i * LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3;
if (tr.worldDeluxeMapping)
{
buf_p = buf + (i * 2) * LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3;
}
else
{
buf_p = buf + i * LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3;
}
xoff = i % tr.fatLightmapStep;
yoff = i / tr.fatLightmapStep;
//if (tr.radbumping==qfalse)
if(1)
// if (tr.worldLightmapping)
{
for(y = 0; y < LIGHTMAP_SIZE; y++)
{
@ -332,32 +351,39 @@ static void R_LoadLightmaps( lump_t *l ) {
}
}
}
/*else
{
//We need to darken the lightmaps a little bit when mixing radbump and fallback path rendering
//because radbump will be darker due to the error introduced by using 3 basis vector probes for lighting instead of surf normal.
for ( y = 0 ; y < LIGHTMAP_SIZE ; y++ )
{
for ( x = 0 ; x < LIGHTMAP_SIZE ; x++ )
{
int index = (x+(y*tr.fatLightmapSize))+((xoff*LIGHTMAP_SIZE)+(yoff*tr.fatLightmapSize*LIGHTMAP_SIZE));
fatbuffer[(index*4)+0 ]=(byte)(((float)buf_p[((x+(y*LIGHTMAP_SIZE))*3)+0])*scale);
fatbuffer[(index*4)+1 ]=(byte)(((float)buf_p[((x+(y*LIGHTMAP_SIZE))*3)+1])*scale);
fatbuffer[(index*4)+2 ]=(byte)(((float)buf_p[((x+(y*LIGHTMAP_SIZE))*3)+2])*scale);
fatbuffer[(index*4)+3 ]=255;
}
}
} */
if (tr.worldDeluxeMapping)
{
buf_p = buf + (i * 2 + 1) * LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3;
for(y = 0; y < LIGHTMAP_SIZE; y++)
{
for(x = 0; x < LIGHTMAP_SIZE; x++)
{
int index =
(x + (y * tr.fatLightmapSize)) + ((xoff * LIGHTMAP_SIZE) + (yoff * tr.fatLightmapSize * LIGHTMAP_SIZE));
fatbuffer2[(index * 4) + 0] = buf_p[((x + (y * LIGHTMAP_SIZE)) * 3) + 0];
fatbuffer2[(index * 4) + 1] = buf_p[((x + (y * LIGHTMAP_SIZE)) * 3) + 1];
fatbuffer2[(index * 4) + 2] = buf_p[((x + (y * LIGHTMAP_SIZE)) * 3) + 2];
fatbuffer2[(index * 4) + 3] = 255;
}
}
}
}
//memset(fatbuffer,128,tr.fatLightmapSize*tr.fatLightmapSize*4);
tr.fatLightmap = R_CreateImage(va("_fatlightmap%d", 0), fatbuffer, tr.fatLightmapSize, tr.fatLightmapSize, qfalse, qfalse, GL_CLAMP_TO_EDGE );
tr.lightmaps[0] = tr.fatLightmap;
ri.Hunk_FreeTempMemory(fatbuffer);
if (tr.worldDeluxeMapping)
{
tr.fatDeluxemap = R_CreateImage(va("_fatdeluxemap%d", 0), fatbuffer2, tr.fatLightmapSize, tr.fatLightmapSize, qfalse, qfalse, GL_CLAMP_TO_EDGE );
tr.deluxemaps[0] = tr.fatDeluxemap;
ri.Hunk_FreeTempMemory(fatbuffer2);
}
#endif
}
@ -366,7 +392,7 @@ static float FatPackU(float input, int lightmapnum)
{
if(tr.fatLightmapSize > 0)
{
int x = lightmapnum % tr.fatLightmapStep;
int x = (lightmapnum >> (tr.worldDeluxeMapping ? 1 : 0)) % tr.fatLightmapStep;
return (input / ((float)tr.fatLightmapStep)) + ((1.0 / ((float)tr.fatLightmapStep)) * (float)x);
}
@ -378,7 +404,7 @@ static float FatPackV(float input, int lightmapnum)
{
if(tr.fatLightmapSize > 0)
{
int y = lightmapnum / ((float)tr.fatLightmapStep);
int y = (lightmapnum >> (tr.worldDeluxeMapping ? 1 : 0)) / tr.fatLightmapStep;
return (input / ((float)tr.fatLightmapStep)) + ((1.0 / ((float)tr.fatLightmapStep)) * (float)y);
}
@ -575,6 +601,68 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int
cv->plane.type = PlaneTypeForNormal( cv->plane.normal );
surf->data = (surfaceType_t *)cv;
// Tr3B - calc tangent spaces
#if 0
{
float *v;
const float *v0, *v1, *v2;
const float *t0, *t1, *t2;
vec3_t tangent;
vec3_t bitangent;
vec3_t normal;
for(i = 0; i < numVerts; i++)
{
VectorClear(cv->verts[i].tangent);
VectorClear(cv->verts[i].bitangent);
VectorClear(cv->verts[i].normal);
}
for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
{
v0 = cv->verts[tri->indexes[0]].xyz;
v1 = cv->verts[tri->indexes[1]].xyz;
v2 = cv->verts[tri->indexes[2]].xyz;
t0 = cv->verts[tri->indexes[0]].st;
t1 = cv->verts[tri->indexes[1]].st;
t2 = cv->verts[tri->indexes[2]].st;
R_CalcTangentSpace(tangent, bitangent, normal, v0, v1, v2, t0, t1, t2);
for(j = 0; j < 3; j++)
{
v = cv->verts[tri->indexes[j]].tangent;
VectorAdd(v, tangent, v);
v = cv->verts[tri->indexes[j]].bitangent;
VectorAdd(v, bitangent, v);
v = cv->verts[tri->indexes[j]].normal;
VectorAdd(v, normal, v);
}
}
for(i = 0; i < numVerts; i++)
{
VectorNormalize(cv->verts[i].tangent);
VectorNormalize(cv->verts[i].bitangent);
VectorNormalize(cv->verts[i].normal);
}
}
#else
{
srfVert_t *dv[3];
for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
{
dv[0] = &cv->verts[tri->indexes[0]];
dv[1] = &cv->verts[tri->indexes[1]];
dv[2] = &cv->verts[tri->indexes[2]];
R_CalcTangentVectors(dv);
}
}
#endif
}
@ -740,6 +828,84 @@ static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, i
ri.Printf(PRINT_WARNING, "Surface has bad triangles, originally shader %s %d tris %d verts, now %d tris\n", surf->shader->name, numTriangles, numVerts, numTriangles - badTriangles);
cv->numTriangles -= badTriangles;
}
// Tr3B - calc tangent spaces
#if 0
{
float *v;
const float *v0, *v1, *v2;
const float *t0, *t1, *t2;
vec3_t tangent;
vec3_t bitangent;
vec3_t normal;
for(i = 0; i < numVerts; i++)
{
VectorClear(cv->verts[i].tangent);
VectorClear(cv->verts[i].bitangent);
VectorClear(cv->verts[i].normal);
}
for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
{
v0 = cv->verts[tri->indexes[0]].xyz;
v1 = cv->verts[tri->indexes[1]].xyz;
v2 = cv->verts[tri->indexes[2]].xyz;
t0 = cv->verts[tri->indexes[0]].st;
t1 = cv->verts[tri->indexes[1]].st;
t2 = cv->verts[tri->indexes[2]].st;
#if 1
R_CalcTangentSpace(tangent, bitangent, normal, v0, v1, v2, t0, t1, t2);
#else
R_CalcNormalForTriangle(normal, v0, v1, v2);
R_CalcTangentsForTriangle2(tangent, bitangent, v0, v1, v2, t0, t1, t2);
#endif
for(j = 0; j < 3; j++)
{
v = cv->verts[tri->indexes[j]].tangent;
VectorAdd(v, tangent, v);
v = cv->verts[tri->indexes[j]].bitangent;
VectorAdd(v, bitangent, v);
v = cv->verts[tri->indexes[j]].normal;
VectorAdd(v, normal, v);
}
}
for(i = 0; i < numVerts; i++)
{
float dot;
//VectorNormalize(cv->verts[i].tangent);
VectorNormalize(cv->verts[i].bitangent);
VectorNormalize(cv->verts[i].normal);
// Gram-Schmidt orthogonalize
dot = DotProduct(cv->verts[i].normal, cv->verts[i].tangent);
VectorMA(cv->verts[i].tangent, -dot, cv->verts[i].normal, cv->verts[i].tangent);
VectorNormalize(cv->verts[i].tangent);
//dot = DotProduct(cv->verts[i].normal, cv->verts[i].tangent);
//VectorMA(cv->verts[i].tangent, -dot, cv->verts[i].normal, cv->verts[i].tangent);
//VectorNormalize(cv->verts[i].tangent);
}
}
#else
{
srfVert_t *dv[3];
for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
{
dv[0] = &cv->verts[tri->indexes[0]];
dv[1] = &cv->verts[tri->indexes[1]];
dv[2] = &cv->verts[tri->indexes[2]];
R_CalcTangentVectors(dv);
}
}
#endif
}
#endif
@ -1525,10 +1691,10 @@ static void CopyVert(const srfVert_t * in, srfVert_t * out)
for(j = 0; j < 3; j++)
{
out->xyz[j] = in->xyz[j];
//out->tangent[j] = in->tangent[j];
//out->binormal[j] = in->binormal[j];
out->normal[j] = in->normal[j];
out->xyz[j] = in->xyz[j];
out->tangent[j] = in->tangent[j];
out->bitangent[j] = in->bitangent[j];
out->normal[j] = in->normal[j];
//out->lightDirection[j] = in->lightDirection[j];
}
@ -1794,12 +1960,12 @@ static void R_CreateWorldVBO(void)
}
s_worldData.vbo = R_CreateVBO2(va("bspModelMesh_vertices %i", 0), numVerts, optimizedVerts,
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BINORMAL |
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT |
ATTR_NORMAL | ATTR_COLOR | GLCS_LIGHTCOLOR | ATTR_LIGHTDIRECTION);
#else
s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts,
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_NORMAL | ATTR_COLOR,
VBO_USAGE_STATIC);
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT |
ATTR_NORMAL | ATTR_COLOR, VBO_USAGE_STATIC);
#endif
s_worldData.ibo = R_CreateIBO2(va("staticBspModel0_IBO %i", 0), numTriangles, triangles, VBO_USAGE_STATIC);
@ -2488,6 +2654,20 @@ void R_LoadEntities( lump_t *l ) {
sscanf(value, "%f %f %f", &w->lightGridSize[0], &w->lightGridSize[1], &w->lightGridSize[2] );
continue;
}
// check for deluxe mapping provided by NetRadiant's q3map2
//FIXME: xmap2?
if(!Q_stricmp(keyname, "_q3map2_cmdline"))
{
ri.Printf(PRINT_ALL, "wtf? %s %s\n", keyname, value);
s = strstr(value, "-deluxe");
if(s)
{
ri.Printf(PRINT_ALL, "map features directional light mapping\n");
tr.worldDeluxeMapping = qtrue;
}
continue;
}
}
}
@ -2938,6 +3118,7 @@ void RE_LoadWorldMap( const char *name ) {
}
// load into heap
R_LoadEntities( &header->lumps[LUMP_ENTITIES] );
R_LoadShaders( &header->lumps[LUMP_SHADERS] );
R_LoadLightmaps( &header->lumps[LUMP_LIGHTMAPS] );
R_LoadPlanes (&header->lumps[LUMP_PLANES]);
@ -2947,7 +3128,6 @@ void RE_LoadWorldMap( const char *name ) {
R_LoadNodesAndLeafs (&header->lumps[LUMP_NODES], &header->lumps[LUMP_LEAFS]);
R_LoadSubmodels (&header->lumps[LUMP_MODELS]);
R_LoadVisibility( &header->lumps[LUMP_VISIBILITY] );
R_LoadEntities( &header->lumps[LUMP_ENTITIES] );
R_LoadLightGrid( &header->lumps[LUMP_LIGHTGRID] );
// create static VBOS from the world
@ -2975,3 +3155,4 @@ void RE_LoadWorldMap( const char *name ) {
ri.FS_FreeFile( buffer.v );
}

View file

@ -214,6 +214,85 @@ static int neighbors[8][2] = {
}
static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int numTriangles,
srfTriangle_t triangles[SHADER_MAX_TRIANGLES])
{
int i, j;
srfVert_t *dv[3];
static srfVert_t ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
srfTriangle_t *tri;
// FIXME: use more elegant way
for(i = 0; i < width; i++)
{
for(j = 0; j < height; j++)
{
dv[0] = &ctrl2[j * width + i];
*dv[0] = ctrl[j][i];
}
}
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
dv[0] = &ctrl2[tri->indexes[0]];
dv[1] = &ctrl2[tri->indexes[1]];
dv[2] = &ctrl2[tri->indexes[2]];
R_CalcTangentVectors(dv);
}
#if 0
for(i = 0; i < (width * height); i++)
{
dv0 = &ctrl2[i];
VectorNormalize(dv0->normal);
#if 0
VectorNormalize(dv0->tangent);
VectorNormalize(dv0->bitangent);
#else
d = DotProduct(dv0->tangent, dv0->normal);
VectorMA(dv0->tangent, -d, dv0->normal, dv0->tangent);
VectorNormalize(dv0->tangent);
d = DotProduct(dv0->bitangent, dv0->normal);
VectorMA(dv0->bitangent, -d, dv0->normal, dv0->bitangent);
VectorNormalize(dv0->bitangent);
#endif
}
#endif
#if 0
// do another extra smoothing for normals to avoid flat shading
for(i = 0; i < (width * height); i++)
{
for(j = 0; j < (width * height); j++)
{
if(R_CompareVert(&ctrl2[i], &ctrl2[j], qfalse))
{
VectorAdd(ctrl2[i].normal, ctrl2[j].normal, ctrl2[i].normal);
}
}
VectorNormalize(ctrl2[i].normal);
}
#endif
for(i = 0; i < width; i++)
{
for(j = 0; j < height; j++)
{
dv[0] = &ctrl2[j * width + i];
dv[1] = &ctrl[j][i];
VectorCopy(dv[0]->tangent, dv[1]->tangent);
VectorCopy(dv[0]->bitangent, dv[1]->bitangent);
}
}
}
static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
srfTriangle_t triangles[SHADER_MAX_TRIANGLES])
{
@ -589,6 +668,7 @@ srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
// calculate normals
MakeMeshNormals( width, height, ctrl );
MakeMeshTangentVectors(width, height, ctrl, numTriangles, triangles);
return R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
}

View file

@ -122,4 +122,4 @@ void VectorLerp( vec3_t a, vec3_t b, float lerp, vec3_t c)
c[0] = a[0] * (1.0f - lerp) + b[0] * lerp;
c[1] = a[1] * (1.0f - lerp) + b[1] * lerp;
c[2] = a[2] * (1.0f - lerp) + b[2] * lerp;
}
}

View file

@ -527,3 +527,4 @@ void RB_RenderFlares (void) {
GL_SetModelviewMatrix(oldmodelview);
}

View file

@ -87,60 +87,57 @@ static const char *fallbackGenericShader_vp =
"ot(position.xyz, TCGenVector0.xyz);\r\n\t\ttex.t = dot(position.xyz, TCGenV"
"ector1.xyz);\r\n\t}\r\n\t\r\n\treturn tex;\r\n}\r\n#endif\r\n\r\nvoid main("
")\r\n{\r\n\tvec4 position;\r\n\tvec3 normal;\r\n\tvec4 tex;\r\n\r\n#if defi"
"ned(USE_VERTEX_ANIMATION)\r\n\tif (u_VertexLerp > 0.0)\r\n\t{\r\n\t\tpositi"
"on = mix(attr_Position, attr_Position2, u_VertexLerp);\r\n\t\tnormal = mix("
"attr_Normal, attr_Normal2, u_VertexLerp);\r\n\t\tnormal = normalize(normal)"
";\r\n\t}\r\n\telse\r\n#endif\r\n\t{\r\n\t\tposition = attr_Position;\r\n\t"
"\tnormal = attr_Normal;\r\n\t}\r\n\r\n#if defined(USE_DEFORM_VERTEXES)\r\n"
"\tposition = DeformPosition(position, normal, attr_TexCoord0.st);\r\n#endif"
"\r\n\r\n\tgl_Position = u_ModelViewProjectionMatrix * position;\r\n\r\n\r\n"
"\ttex = vec4(1.0, 1.0, 1.0, 0.0);\r\n\r\n#if defined(USE_TCGEN)\r\n\ttex.st"
" = GenTexCoords(u_TCGen0, position, normal, u_Texture0Matrix, u_TCGen0Vecto"
"r0, u_TCGen0Vector1);\r\n#else\r\n\ttex.st = attr_TexCoord0.st;\r\n#endif\r"
"\n \r\n\tvar_Tex1 = (u_Texture0Matrix * tex).st;\r\n\r\n\tif (u_Texture0"
"Matrix[3][0] != 0)\r\n\t{\r\n\t\tvar_Tex1.s += sin(((position.x + position."
"z) * 1.0 / 128.0 * 0.125 + u_Texture0Matrix[3][1]) * 2.0 * M_PI) * u_Textur"
"e0Matrix[3][0];\r\n\t\tvar_Tex1.t += sin((position.y * 1.0 / 128.0 * 0.125 "
"+ u_Texture0Matrix[3][1]) * 2.0 * M_PI) * u_Texture0Matrix[3][0];\r\n\t}\r"
"\n\r\n\tvar_Tex2 = attr_TexCoord1.st;\r\n\r\n\tif (u_ColorGen == CGEN_IDENT"
"ITY)\r\n\t{\r\n\t\tvar_Color.rgb = vec3(1.0);\r\n\t}\r\n\telse if (u_ColorG"
"en == CGEN_LIGHTING_DIFFUSE)\r\n\t{\r\n\t\tfloat incoming = dot(attr_Normal"
", u_LightDir);\r\n\r\n\t\tif (incoming <= 0)\r\n\t\t{\r\n\t\t\tvar_Color.rg"
"b = u_AmbientLight;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvar_Color.rgb = "
"min(u_AmbientLight + u_DirectedLight * incoming, vec3(1));\r\n\t\t}\r\n\t}"
"\r\n\telse if (u_ColorGen == CGEN_EXACT_VERTEX)\r\n\t{\r\n\t\tvar_Color.rgb"
" = attr_Color.rgb;\r\n\t}\r\n\telse if (u_ColorGen == CGEN_VERTEX)\r\n\t{\r"
"\n\t\tvar_Color.rgb = attr_Color.rgb * u_Color.rgb;\r\n\t}\r\n\telse if (u_"
"ColorGen == CGEN_ONE_MINUS_VERTEX)\r\n\t{\r\n\t\tvar_Color.rgb = (vec3(1.0)"
" - attr_Color.rgb) * u_Color.rgb;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvar_Color."
"rgb = u_Color.rgb;\r\n\t}\r\n\r\n\tif (u_AlphaGen == AGEN_IDENTITY)\r\n\t{"
"\r\n\t\tvar_Color.a = 1.0;\r\n\t}\r\n\telse if (u_AlphaGen == AGEN_LIGHTING"
"_SPECULAR)\r\n\t{\r\n\t\tvec3 lightDir = vec3(-960.0, -1980.0, 96.0) - posi"
"tion.xyz;\r\n\t\tlightDir = normalize(lightDir);\r\n\r\n\t\tfloat d = dot(a"
"ttr_Normal, lightDir);\r\n\t\tvec3 reflected = attr_Normal * 2.0 * d - ligh"
"tDir;\r\n\r\n\t\tvec3 viewer = u_ViewOrigin - position.xyz;\r\n\t\tfloat il"
"ength = 1.0 / length(viewer);\r\n\r\n\t\tfloat l = dot(reflected, viewer);"
"\r\n\t\tl *= ilength;\r\n\r\n\t\tif (l < 0.0)\r\n\t\t{\r\n\t\t\tvar_Color.a"
" = 0.0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tl = l*l;\r\n\t\t\tl = l*l;\r"
"\n\t\t\tvar_Color.a = min(l, 1.0);\r\n\t\t}\r\n\t}\r\n\telse if (u_AlphaGen"
" == AGEN_VERTEX)\r\n\t{\r\n\t\tvar_Color.a = attr_Color.a;\r\n\t}\r\n\telse"
" if (u_AlphaGen == AGEN_ONE_MINUS_VERTEX)\r\n\t{\r\n\t\tvar_Color.a = 1.0 -"
" attr_Color.a;\r\n\t}\r\n\telse if (u_AlphaGen == AGEN_PORTAL)\r\n\t{\r\n\t"
"\tfloat len;\r\n\t\tvec3 v;\r\n\r\n\t\tv = position.xyz - u_ViewOrigin;\r\n"
"\t\tlen = length(v);\r\n\r\n\t\tlen /= u_PortalRange;\r\n\r\n\t\tvar_Color."
"a = clamp(len, 0.0, 1.0);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvar_Color.a = u_Co"
"lor.a;\r\n\t}\r\n\r\n#if defined (USE_FOG)\r\n\tif (u_FogAdjustColors != AC"
"FF_NONE) \r\n\t{\r\n\t\tfloat s = dot(position.xyz, u_FogDistance.xyz) + u_"
"FogDistance.a;\r\n\t\tfloat t = dot(position.xyz, u_FogDepth.xyz) + u_FogDe"
"pth.a;\r\n\t\t\r\n\t\tif (s < 0.0 || t < 0.0 || (u_FogEyeT < 0.0 && t < 1.0"
") )\r\n\t\t{\r\n\t\t\ts = 0.0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (u"
"_FogEyeT < 0.0)\r\n\t\t\t{\r\n\t\t\t\ts *= t / (t - u_FogEyeT);\r\n\t\t\t}"
"\r\n\r\n\t\t\ts *= 8.0;\r\n\t\t\t\t \r\n\t\t\ts = clamp(s, 0.0, 1.0);\r\n"
"\r\n\t\t\ts = 1.0 - sqrt(s);\r\n\t\t}\r\n\t\t\r\n\t\tif (u_FogAdjustColors "
"== ACFF_MODULATE_RGB)\r\n\t\t{\r\n\t\t\tvar_Color.xyz *= s;\r\n\t\t}\r\n\t"
"\telse if (u_FogAdjustColors == ACFF_MODULATE_ALPHA)\r\n\t\t{\r\n\t\t\tvar_"
"Color.a *= s;\r\n\t\t}\r\n\t\telse if (u_FogAdjustColors == ACFF_MODULATE_R"
"GBA)\r\n\t\t{\r\n\t\t\tvar_Color *= s;\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r\n";
"ned(USE_VERTEX_ANIMATION)\r\n\tposition = mix(attr_Position, attr_Position2"
", u_VertexLerp);\r\n\tnormal = normalize(mix(attr_Normal, attr_Normal2, u_V"
"ertexLerp));\r\n#else\r\n\tposition = attr_Position;\r\n\tnormal = attr_Nor"
"mal;\r\n#endif\r\n\r\n#if defined(USE_DEFORM_VERTEXES)\r\n\tposition = Defo"
"rmPosition(position, normal, attr_TexCoord0.st);\r\n#endif\r\n\r\n\tgl_Posi"
"tion = u_ModelViewProjectionMatrix * position;\r\n\r\n\r\n\ttex = vec4(1.0,"
" 1.0, 1.0, 0.0);\r\n\r\n#if defined(USE_TCGEN)\r\n\ttex.st = GenTexCoords(u"
"_TCGen0, position, normal, u_Texture0Matrix, u_TCGen0Vector0, u_TCGen0Vecto"
"r1);\r\n#else\r\n\ttex.st = attr_TexCoord0.st;\r\n#endif\r\n \r\n\tvar_T"
"ex1 = (u_Texture0Matrix * tex).st;\r\n\r\n\tvar_Tex1.s += sin(((position.x "
"+ position.z) * 1.0 / 128.0 * 0.125 + u_Texture0Matrix[3][1]) * 2.0 * M_PI)"
" * u_Texture0Matrix[3][0];\r\n\tvar_Tex1.t += sin((position.y * 1.0 / 128.0"
" * 0.125 + u_Texture0Matrix[3][1]) * 2.0 * M_PI) * u_Texture0Matrix[3][0];"
"\r\n\r\n\tvar_Tex2 = attr_TexCoord1.st;\r\n\t\r\n\tvar_Color = u_Color;\r\n"
"\r\n\tif (u_ColorGen == CGEN_LIGHTING_DIFFUSE)\r\n\t{\r\n\t\tfloat incoming"
" = max(dot(normal, u_LightDir), 0.0);\r\n\r\n\t\tvar_Color.rgb = min(u_Dire"
"ctedLight * incoming + u_AmbientLight, 1.0);\r\n\t}\r\n\telse if (u_ColorGe"
"n == CGEN_EXACT_VERTEX)\r\n\t{\r\n\t\tvar_Color.rgb = attr_Color.rgb;\r\n\t"
"}\r\n\telse if (u_ColorGen == CGEN_VERTEX)\r\n\t{\r\n\t\tvar_Color.rgb *= a"
"ttr_Color.rgb;\r\n\t}\r\n\telse if (u_ColorGen == CGEN_ONE_MINUS_VERTEX)\r"
"\n\t{\r\n\t\tvar_Color.rgb *= (vec3(1.0) - attr_Color.rgb);\r\n\t}\r\n\r\n"
"\tif (u_AlphaGen == AGEN_LIGHTING_SPECULAR)\r\n\t{\r\n#if 0 // phong specul"
"ar\r\n\t\tvec3 lightDir = vec3(-960.0, -1980.0, 96.0) - position.xyz;\r\n\t"
"\tlightDir = normalize(lightDir);\r\n\r\n\t\tfloat d = dot(normal, lightDir"
");\r\n\t\tvec3 reflected = normal * 2.0 * d - lightDir;\r\n\r\n\t\tvec3 vie"
"wer = u_ViewOrigin - position.xyz;\r\n\t\tfloat ilength = 1.0 / length(view"
"er);\r\n\r\n\t\tfloat l = dot(reflected, viewer);\r\n\t\tl *= ilength;\r\n"
"\r\n\t\tif (l < 0.0)\r\n\t\t{\r\n\t\t\tvar_Color.a = 0.0;\r\n\t\t}\r\n\t\te"
"lse\r\n\t\t{\r\n\t\t\tl = l*l;\r\n\t\t\tl = l*l;\r\n\t\t\tvar_Color.a = min"
"(l, 1.0);\r\n\t\t}\r\n#else // blinn specular\r\n\t\tvec3 lightDir = normal"
"ize(vec3(-960.0, -1980.0, 96.0) - position.xyz);\r\n\t\tvec3 viewer = norma"
"lize(u_ViewOrigin - position.xyz);\r\n\t\tvec3 halfangle = normalize(lightD"
"ir + viewer);\r\n\t\t\r\n\t\tvar_Color.a = pow(max(dot(normal, halfangle), "
"0.0), 4.0);\r\n#endif\r\n\t}\r\n\telse if (u_AlphaGen == AGEN_VERTEX)\r\n\t"
"{\r\n\t\tvar_Color.a = attr_Color.a;\r\n\t}\r\n\telse if (u_AlphaGen == AGE"
"N_ONE_MINUS_VERTEX)\r\n\t{\r\n\t\tvar_Color.a = 1.0 - attr_Color.a;\r\n\t}"
"\r\n\telse if (u_AlphaGen == AGEN_PORTAL)\r\n\t{\r\n\t\tfloat alpha = lengt"
"h(position.xyz - u_ViewOrigin) / u_PortalRange;\r\n\r\n\t\tvar_Color.a = mi"
"n(alpha, 1.0);\r\n\t}\r\n\telse if (u_AlphaGen == AGEN_FRESNEL)\r\n\t{\r\n"
"\t\tvec3 viewer = normalize(u_ViewOrigin - position.xyz);\r\n\t\t\r\n\t\tva"
"r_Color.a = dot(viewer, normal);\r\n\t}\r\n\r\n#if defined (USE_FOG)\r\n\ti"
"f (u_FogAdjustColors != ACFF_NONE) \r\n\t{\r\n\t\tfloat s = max(dot(positio"
"n.xyz, u_FogDistance.xyz) + u_FogDistance.a, 0.0);\r\n\t\tfloat t = max(dot"
"(position.xyz, u_FogDepth.xyz) + u_FogDepth.a, 0.0);\r\n\t\t\r\n\t\tif (t >"
"= 1.0)\r\n\t\t{\r\n\t\t\ts *= t / (t - min(u_FogEyeT, 0.0));\r\n\t\t}\r\n\t"
"\t\r\n\t\ts = 1.0 - sqrt(min(s * 8.0, 1.0));\r\n\t\r\n\t\tif (u_FogAdjustCo"
"lors == ACFF_MODULATE_RGB)\r\n\t\t{\r\n\t\t\tvar_Color.xyz *= s;\r\n\t\t}\r"
"\n\t\telse if (u_FogAdjustColors == ACFF_MODULATE_ALPHA)\r\n\t\t{\r\n\t\t\t"
"var_Color.a *= s;\r\n\t\t}\r\n\t\telse if (u_FogAdjustColors == ACFF_MODULA"
"TE_RGBA)\r\n\t\t{\r\n\t\t\tvar_Color *= s;\r\n\t\t}\r\n\t}\r\n#endif\r\n}\r"
"\n";
static const char *fallbackGenericShader_fp =
"uniform sampler2D u_Texture0Map;\r\nuniform sampler2D u_Texture1Map;\r\nuni"
@ -177,17 +174,17 @@ static const char *fallbackLightmappedShader_fp =
"\n\tcolor = texture2D(u_Texture0Map, var_Tex1);\r\n\tlight = texture2D(u_Te"
"xture1Map, var_Tex2);\r\n\r\n\tgl_FragColor = color * light;\r\n}\r\n";
static const char *fallbackTextureOnlyShader_vp =
static const char *fallbackTextureColorShader_vp =
"#version 120\r\n\r\nattribute vec4 attr_Position;\r\nattribute vec4 attr_Te"
"xCoord0;\r\n\r\nuniform mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying "
"vec2 var_Tex1;\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelView"
"ProjectionMatrix * attr_Position;\r\n\tvar_Tex1 = attr_TexCoord0.st;\r\n}\r"
"\n";
static const char *fallbackTextureOnlyShader_fp =
"#version 120\r\n\r\nuniform sampler2D u_Texture0Map;\r\n\r\nvarying vec2"
" var_Tex1;\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_FragColor = texture2"
"D(u_Texture0Map, var_Tex1);\r\n}\r\n";
static const char *fallbackTextureColorShader_fp =
"#version 120\r\n\r\nuniform sampler2D u_Texture0Map;\r\nuniform vec4 u"
"_Color;\r\n\r\nvarying vec2 var_Tex1;\r\n\r\n\r\nvoid main()\r\n{\r"
"\n\tgl_FragColor = texture2D(u_Texture0Map, var_Tex1) * u_Color;\r\n}\r\n";
static const char *fallbackFogPassShader_vp =
"attribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\nattribute"
@ -234,19 +231,16 @@ static const char *fallbackFogPassShader_vp =
"\n\r\n\r\nvoid\tmain()\r\n{\r\n\tvec4 position;\r\n\tvec3 normal;\r\n\r\n//"
"#if defined(USE_VERTEX_ANIMATION)\r\n\tif (u_VertexLerp > 0.0)\r\n\t{\r\n\t"
"\tposition = mix(attr_Position, attr_Position2, u_VertexLerp);\r\n\t\tnorma"
"l = mix(attr_Normal, attr_Normal2, u_VertexLerp);\r\n\t\tnormal = normalize"
"(normal);\r\n\t}\r\n\telse\r\n//#endif\r\n\t{\r\n\t\tposition = attr_Positi"
"on;\r\n\t\tnormal = attr_Normal;\r\n\t}\r\n\r\n//#if defined(USE_DEFORM_VER"
"TEXES)\r\n\tposition = DeformPosition(position, normal, attr_TexCoord0.st);"
"\r\n//#endif\r\n\r\n\tgl_Position = u_ModelViewProjectionMatrix * position;"
"\r\n\r\n\t{\r\n\t\tfloat s = dot(position.xyz, u_FogDistance.xyz) + u_FogDi"
"stance.a;\r\n\t\tfloat t = dot(position.xyz, u_FogDepth.xyz) + u_FogDepth.a"
";\r\n\r\n\t\tif (s < 0.0 || t < 0.0 || (u_FogEyeT < 0.0 && t < 1.0) )\r\n\t"
"\t{\r\n\t\t\ts = 0.0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (u_FogEyeT "
"< 0.0)\r\n\t\t\t{\r\n\t\t\t\ts *= t / (t - u_FogEyeT);\r\n\t\t\t}\r\n\r\n\t"
"\t\ts *= 8.0;\r\n\t\t \r\n\t\t\ts = clamp(s, 0.0, 1.0);\r\n\r\n\t\t\ts = s"
"qrt(s);\r\n\t\t}\r\n\r\n\t\tvar_Color.xyz = u_Color.xyz;\r\n\t\tvar_Color.a"
" = u_Color.a * s;\r\n\t}\r\n}\r\n";
"l = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));\r\n\t}\r\n\tel"
"se\r\n//#endif\r\n\t{\r\n\t\tposition = attr_Position;\r\n\t\tnormal = attr"
"_Normal;\r\n\t}\r\n\r\n//#if defined(USE_DEFORM_VERTEXES)\r\n\tposition = D"
"eformPosition(position, normal, attr_TexCoord0.st);\r\n//#endif\r\n\r\n\tgl"
"_Position = u_ModelViewProjectionMatrix * position;\r\n\r\n\tfloat s = max("
"dot(position.xyz, u_FogDistance.xyz) + u_FogDistance.a, 0.0);\r\n\tfloat t "
"= max(dot(position.xyz, u_FogDepth.xyz) + u_FogDepth.a, 0.0);\r\n\t\r\n\tif"
" (t >= 1.0)\r\n\t{\r\n\t\ts *= t / (t - min(u_FogEyeT, 0.0));\r\n\t}\r\n\t"
"\r\n\ts = sqrt(min(s * 8.0, 1.0));\r\n\t\r\n\tvar_Color.xyz = u_Color.xyz;"
"\r\n\tvar_Color.a = u_Color.a * s;\r\n}\r\n";
static const char *fallbackFogPassShader_fp =
"varying vec4 var_Color;\r\n\r\n\r\nvoid\tmain()\r\n{\r\n\tgl_FragCo"
@ -291,28 +285,73 @@ static const char *fallbackDlightShader_vp =
" = (M_PI * 0.25) * st.x * bulgeWidth + now;\r\n\t\tfloat scale = sin(off) *"
" bulgeHeight;\r\n\t\tvec3 offset = normal * scale;\r\n\r\n\t\tdeformed.xyz "
"+= offset;\r\n\t}\r\n\r\n\treturn deformed;\r\n}\r\n\r\n\r\nvoid main()\r\n"
"{\r\n\tvec4 position;\r\n\tvec3 normal;\r\n\tvec3 dist;\r\n\tvec2 tex;\r\n"
"\tfloat dlightmod;\r\n\r\n\tif (u_VertexLerp > 0.0)\r\n\t{\r\n\t\tposition "
"= mix(attr_Position, attr_Position2, u_VertexLerp);\r\n\t\tnormal = mix(att"
"r_Normal, attr_Normal2, u_VertexLerp);\r\n\t\tnormal = normalize(normal);\r"
"\n\t}\r\n\telse\r\n\t{\r\n\t\tposition = attr_Position;\r\n\t\tnormal = att"
"r_Normal;\r\n\t}\r\n\r\n\tposition = DeformPosition(position, normal, attr_"
"TexCoord0.st);\r\n\r\n\tgl_Position = u_ModelViewProjectionMatrix * positio"
"n;\r\n\t\r\n\t\r\n\ttex = vec2(0);\r\n\t\r\n\tdist = u_DlightInfo.xyz - pos"
"ition.xyz;\t\r\n\tdlightmod = 0;\r\n\r\n\tif (!(dot(dist, normal) < 0))\r\n"
"\t{\r\n\t\tfloat diffz = abs(dist.z);\r\n\t\tfloat radius = 1.0 / u_DlightI"
"nfo.a;\r\n \r\n\t\tif (diffz <= radius)\r\n\t\t{\r\n\t\t\ttex = vec2(0.5"
") + dist.xy * u_DlightInfo.a;\r\n\r\n\t\t\tif (diffz < radius * 0.5)\r\n\t"
"\t\t{\r\n\t\t\t\tdlightmod = 1.0;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t"
"\t\t\tdlightmod = 2.0 * (radius - diffz) * u_DlightInfo.a;\r\n\t\t\t}\r\n\t"
"\t}\r\n\t}\r\n\r\n\tvar_Tex1 = tex;\r\n\tvar_Color.rgb = u_Color.rgb * dlig"
"htmod;\r\n\tvar_Color.a = u_Color.a;\r\n}\r\n";
"{\r\n\tvec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);\r"
"\n\tvec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));"
"\r\n\r\n\tposition = DeformPosition(position, normal, attr_TexCoord0.st);\r"
"\n\r\n\tgl_Position = u_ModelViewProjectionMatrix * position;\r\n\t\r\n\tve"
"c2 tex = vec2(0);\r\n\t\r\n\tvec3 dist = u_DlightInfo.xyz - position.xyz;\t"
"\r\n\tfloat dlightmod = 0;\r\n\r\n\tif (dot(dist, normal) > 0)\r\n\t{\r\n\t"
"\tfloat diffz = abs(dist.z);\r\n\t\tfloat radius = 1.0 / u_DlightInfo.a;\r"
"\n \r\n\t\tif (diffz <= radius)\r\n\t\t{\r\n\t\t\ttex = vec2(0.5) + dist"
".xy * u_DlightInfo.a;\r\n\r\n\t\t\tif (diffz < radius * 0.5)\r\n\t\t\t{\r\n"
"\t\t\t\tdlightmod = 1.0;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tdli"
"ghtmod = 2.0 * (radius - diffz) * u_DlightInfo.a;\r\n\t\t\t}\r\n\t\t}\r\n\t"
"}\r\n\r\n\tvar_Tex1 = tex;\r\n\tvar_Color.rgb = u_Color.rgb * dlightmod;\r"
"\n\tvar_Color.a = u_Color.a;\r\n}\r\n";
static const char *fallbackDlightShader_fp =
"uniform sampler2D u_Texture0Map;\r\n\r\nvarying vec2 var_Tex1;\r\nvary"
"ing vec4 var_Color;\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 color;\r\n\r"
"\n\tcolor = texture2D(u_Texture0Map, var_Tex1);\r\n\r\n\tcolor *= var_Color"
";\r\n\r\n\tgl_FragColor = color;\r\n}\r\n";
"ing vec4 var_Color;\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = text"
"ure2D(u_Texture0Map, var_Tex1);\r\n\r\n\tgl_FragColor = color * var_Color;"
"\n}\n";
static const char *fallbackDeluxemappedShader_vp =
"#version 120\r\n\r\n#ifndef M_PI\r\n#define M_PI 3.14159265358979323846f\r"
"\n#endif\r\n\r\nattribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoo"
"rd0;\r\nattribute vec4 attr_TexCoord1;\r\nattribute vec4 attr_Tangent;\r\na"
"ttribute vec4 attr_Bitangent;\r\nattribute vec4 attr_Normal;\r\n\r\nuniform"
" mat4 u_Texture0Matrix;\r\nuniform mat4 u_ModelViewProjectionMatrix;\r"
"\n\r\nvarying vec2 var_Tex1;\r\nvarying vec2 var_Tex2;\r\nvarying vec3 "
" var_Position;\r\n\r\nvarying vec3 var_Tangent;\r\nvarying vec3 var_Bi"
"tangent;\r\nvarying vec3 var_Normal;\r\n\r\nvoid main()\r\n{\r\n\tvec4 te"
"x = vec4(1, 1, 1, 0);\r\n\r\n\tgl_Position = u_ModelViewProjectionMatrix * "
"attr_Position;\r\n\r\n\ttex.st = attr_TexCoord0.st;\r\n\r\n\tvar_Tex1 = (u_"
"Texture0Matrix * tex).st;\r\n\r\n\tif (u_Texture0Matrix[3][0] != 0)\r\n\t{"
"\r\n\t\tvar_Tex1.s += sin(((attr_Position.x + attr_Position.z) * 1.0 / 128."
"0 * 0.125 + u_Texture0Matrix[3][1]) * 2.0 * M_PI) * u_Texture0Matrix[3][0];"
"\r\n\t\tvar_Tex1.t += sin((attr_Position.y * 1.0 / 128.0 * 0.125 + u_Textur"
"e0Matrix[3][1]) * 2.0 * M_PI) * u_Texture0Matrix[3][0];\r\n\t}\r\n\r\n\tvar"
"_Tex2 = attr_TexCoord1.st;\r\n\r\n\tvar_Tangent = attr_Tangent.xyz;\r\n\t"
"var_Bitangent = attr_Bitangent.xyz;\r\n\tvar_Normal = attr_Normal.xyz;\r"
"\n\t\r\n\tvar_Position = attr_Position.xyz;\r\n}\r\n";
static const char *fallbackDeluxemappedShader_fp =
"#version 120\r\n\r\nuniform sampler2D u_Texture0Map;\r\nuniform sampler2D u"
"_Texture1Map;\r\nuniform sampler2D u_Texture2Map;\r\nuniform sampler2D u_Te"
"xture3Map;\r\nuniform sampler2D u_Texture4Map;\r\n\r\nuniform vec3 u_V"
"iewOrigin;\r\n\r\nvarying vec2 var_Tex1;\r\nvarying vec2 var_Tex2"
";\r\nvarying vec3 var_Position;\r\n\r\nvarying vec3 var_Tangent;"
"\r\nvarying vec3 var_Bitangent;\r\nvarying vec3 var_Normal;\r\n\r"
"\nvoid\tmain()\r\n{\r\n\tvec3 SampleToView = normalize(u_ViewOrigin - var_P"
"osition);\r\n\r\n\tmat3 tangentToWorld;\r\n\ttangentToWorld = mat3(var_Tang"
"ent.xyz, var_Bitangent.xyz, var_Normal.xyz);\r\n\r\n\tmat3 worldToTangent;"
"\r\n\tworldToTangent = mat3(tangentToWorld[0][0], tangentToWorld[1][0], tan"
"gentToWorld[2][0],\r\n\t\ttangentToWorld[0][1], tangentToWorld[1][1], tange"
"ntToWorld[2][1], \r\n\t\ttangentToWorld[0][2], tangentToWorld[1][2], tangen"
"tToWorld[2][2]);\r\n\t\t\t\t\t\t\t\t\t\r\n\tfloat height = 0.02 * texture2D"
"(u_Texture2Map, var_Tex1).a - (0.02 / 2.0);\r\n\t\r\n\tvec2 offsetDir = nor"
"malize(worldToTangent * SampleToView).st;\r\n\tvec2 finalTex = var_Tex1 + o"
"ffsetDir * height;\r\n\t\r\n\tvec4 diffuse = texture2D(u_Texture0Map, fina"
"lTex);\r\n\tvec4 lightmap = texture2D(u_Texture1Map, var_Tex2);\r\n\tvec4 n"
"ormal = texture2D(u_Texture2Map, finalTex);\r\n\tvec4 deluxe = texture2"
"D(u_Texture3Map, var_Tex2);\r\n\tvec4 specular = texture2D(u_Texture4Map, f"
"inalTex);\r\n\r\n\tvec3 worldNormal = tangentToWorld * normalize(2.0 * nor"
"mal.xyz - vec3(1.0));\r\n\tvec3 worldLight = normalize(2.0 * deluxe.xyz -"
" vec3(1.0));\r\n\tvec3 HalfAngle = normalize(worldLight + SampleToView);"
"\r\n\t\r\n\tdiffuse.rgb *= lightmap.rgb * max(dot(worldNormal, worldLight),"
" 0.0);\r\n\tspecular.rgb *= lightmap.rgb * pow(max(dot(worldNormal, HalfAng"
"le), 0.0), 16.0);\r\n\t\t\r\n\tgl_FragColor = diffuse;\r\n\tgl_FragColor.rg"
"b += specular.rgb;\r\n}\r\n";
static void GLSL_PrintInfoLog(GLhandleARB object, qboolean developerOnly)
@ -488,12 +527,14 @@ static int GLSL_CompileGPUShader(GLhandleARB program, GLhandleARB *prevShader, c
"#define AGEN_ONE_MINUS_VERTEX %i\n"
"#define AGEN_LIGHTING_SPECULAR %i\n"
"#define AGEN_PORTAL %i\n"
"#define AGEN_FRESNEL %i\n"
"#endif\n",
AGEN_IDENTITY,
AGEN_VERTEX,
AGEN_ONE_MINUS_VERTEX,
AGEN_LIGHTING_SPECULAR,
AGEN_PORTAL));
AGEN_PORTAL,
AGEN_FRESNEL));
Q_strcat(bufferExtra, sizeof(bufferExtra),
va("#ifndef alphaTest_t\n"
@ -616,8 +657,6 @@ static int GLSL_LoadGPUShader(GLhandleARB program, GLhandleARB *prevShader, cons
size = ri.FS_ReadFile(filename, (void **)&buffer);
if(!buffer)
{
//ri.Error(ERR_DROP, "Couldn't load %s", filename);
ri.Printf(PRINT_ALL, "Couldn't load %s, size %d\n", filename, size);
return 0;
}
@ -771,13 +810,12 @@ static int GLSL_InitGPUShader(shaderProgram_t * program, const char *name, int a
if (!(GLSL_LoadGPUShader(program->program, &program->vertexShader, name, GL_VERTEX_SHADER_ARB, extra, addHeader)))
{
ri.Printf(PRINT_ALL, "GLSL_InitGPUShader: Unable to load \"%s\" as GL_VERTEX_SHADER_ARB\n", name);
if (fallback_vp)
{
ri.Printf(PRINT_ALL, "compiling fallback...\n");
if (!GLSL_CompileGPUShader(program->program, &program->vertexShader, fallback_vp, strlen(fallback_vp), GL_VERTEX_SHADER_ARB, extra, addHeader))
{
ri.Printf(PRINT_ALL, "Fallback failed!\n");
ri.Printf(PRINT_ALL, "GLSL_InitGPUShader: Unable to load \"%s\" as GL_VERTEX_SHADER_ARB\n", name);
qglDeleteObjectARB(program->program);
return 0;
}
@ -793,13 +831,12 @@ static int GLSL_InitGPUShader(shaderProgram_t * program, const char *name, int a
{
if(!(GLSL_LoadGPUShader(program->program, &program->fragmentShader, name, GL_FRAGMENT_SHADER_ARB, extra, addHeader)))
{
ri.Printf(PRINT_ALL, "GLSL_InitGPUShader: Unable to load \"%s\" as GL_FRAGMENT_SHADER_ARB\n", name);
if (fallback_fp)
{
ri.Printf(PRINT_ALL, "compiling fallback...\n");
if (!GLSL_CompileGPUShader(program->program, &program->fragmentShader, fallback_fp, strlen(fallback_fp), GL_FRAGMENT_SHADER_ARB, extra, addHeader))
{
ri.Printf(PRINT_ALL, "Fallback failed!\n");
ri.Printf(PRINT_ALL, "GLSL_InitGPUShader: Unable to load \"%s\" as GL_FRAGMENT_SHADER_ARB\n", name);
qglDeleteObjectARB(program->program);
return 0;
}
@ -830,8 +867,8 @@ static int GLSL_InitGPUShader(shaderProgram_t * program, const char *name, int a
if(attribs & ATTR_TANGENT)
qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT, "attr_Tangent");
if(attribs & ATTR_BINORMAL)
qglBindAttribLocationARB(program->program, ATTR_INDEX_BINORMAL, "attr_Binormal");
if(attribs & ATTR_BITANGENT)
qglBindAttribLocationARB(program->program, ATTR_INDEX_BITANGENT, "attr_Bitangent");
if(attribs & ATTR_NORMAL)
qglBindAttribLocationARB(program->program, ATTR_INDEX_NORMAL, "attr_Normal");
@ -925,8 +962,6 @@ void GLSL_FinishGPUShader(shaderProgram_t *program)
}
}
ri.Printf(PRINT_ALL, "size %d\n", size);
program->uniformBuffer = ri.Malloc(size);
}
@ -955,6 +990,8 @@ void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value)
return;
}
*compare = value;
qglUniform1iARB(uniforms[uniformNum], value);
}
@ -976,6 +1013,8 @@ void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat valu
{
return;
}
*compare = value;
qglUniform1fARB(uniforms[uniformNum], value);
}
@ -999,6 +1038,9 @@ void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t
return;
}
compare[0] = v[0];
compare[1] = v[1];
qglUniform2fARB(uniforms[uniformNum], v[0], v[1]);
}
@ -1021,6 +1063,8 @@ void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t
return;
}
VectorCopy(v, compare);
qglUniform3fARB(uniforms[uniformNum], v[0], v[1], v[2]);
}
@ -1043,6 +1087,8 @@ void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t
return;
}
VectorCopy4(v, compare);
qglUniform4fARB(uniforms[uniformNum], v[0], v[1], v[2], v[3]);
}
@ -1065,6 +1111,8 @@ void GLSL_SetUniformMatrix16(shaderProgram_t *program, int uniformNum, const mat
return;
}
Matrix16Copy(matrix, compare);
qglUniformMatrix4fvARB(uniforms[uniformNum], 1, GL_FALSE, matrix);
}
@ -1233,18 +1281,19 @@ void GLSL_InitGPUShaders(void)
attribs = ATTR_POSITION | ATTR_TEXCOORD;
if (!GLSL_InitGPUShader(&tr.textureOnlyShader, "textureonly", attribs, qtrue, NULL, qfalse, fallbackTextureOnlyShader_vp, fallbackTextureOnlyShader_fp, TEXTUREONLY_UNIFORM_COUNT))
if (!GLSL_InitGPUShader(&tr.textureColorShader, "texturecolor", attribs, qtrue, NULL, qfalse, fallbackTextureColorShader_vp, fallbackTextureColorShader_fp, TEXTURECOLOR_UNIFORM_COUNT))
{
ri.Error(ERR_FATAL, "Could not load textureonly shader!\n");
ri.Error(ERR_FATAL, "Could not load texturecolor shader!\n");
}
GLSL_AddUniform(&tr.textureOnlyShader, TEXTUREONLY_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
GLSL_AddUniform(&tr.textureOnlyShader, TEXTUREONLY_UNIFORM_TEXTURE0MAP, "u_Texture0Map", GLSL_INT);
GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_TEXTURE0MAP, "u_Texture0Map", GLSL_INT);
GLSL_FinishGPUShader(&tr.textureOnlyShader);
GLSL_FinishGPUShader(&tr.textureColorShader);
qglUseProgramObjectARB(tr.textureOnlyShader.program);
GLSL_SetUniformInt(&tr.textureOnlyShader, TEXTUREONLY_UNIFORM_TEXTURE0MAP, 0);
qglUseProgramObjectARB(tr.textureColorShader.program);
GLSL_SetUniformInt(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_TEXTURE0MAP, 0);
qglUseProgramObjectARB(0);
@ -1290,6 +1339,34 @@ void GLSL_InitGPUShaders(void)
GLSL_FinishGPUShader(&tr.dlightShader);
attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_NORMAL | ATTR_COLOR | ATTR_TANGENT | ATTR_BITANGENT;
if (!GLSL_InitGPUShader(&tr.deluxemappedShader, "deluxemapped", attribs, qtrue, extradefines, qfalse, fallbackDeluxemappedShader_vp, fallbackDeluxemappedShader_fp, GENERIC_UNIFORM_COUNT))
{
ri.Error(ERR_FATAL, "Could not load generic shader!\n");
}
GLSL_AddUniform(&tr.deluxemappedShader, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
GLSL_AddUniform(&tr.deluxemappedShader, GENERIC_UNIFORM_MODELMATRIX, "u_ModelMatrix", GLSL_MAT16);
GLSL_AddUniform(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE0MATRIX, "u_Texture0Matrix", GLSL_MAT16);
GLSL_AddUniform(&tr.deluxemappedShader, GENERIC_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3);
GLSL_AddUniform(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE0MAP, "u_Texture0Map", GLSL_INT);
GLSL_AddUniform(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE1MAP, "u_Texture1Map", GLSL_INT);
GLSL_AddUniform(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE2MAP, "u_Texture2Map", GLSL_INT);
GLSL_AddUniform(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE3MAP, "u_Texture3Map", GLSL_INT);
GLSL_AddUniform(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE4MAP, "u_Texture4Map", GLSL_INT);
GLSL_FinishGPUShader(&tr.deluxemappedShader);
qglUseProgramObjectARB(tr.deluxemappedShader.program);
GLSL_SetUniformInt(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE0MAP, 0);
GLSL_SetUniformInt(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE1MAP, 1);
GLSL_SetUniformInt(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE2MAP, 2);
GLSL_SetUniformInt(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE3MAP, 3);
GLSL_SetUniformInt(&tr.deluxemappedShader, GENERIC_UNIFORM_TEXTURE4MAP, 4);
qglUseProgramObjectARB(0);
endTime = ri.Milliseconds();
ri.Printf(PRINT_ALL, "GLSL shaders load time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
@ -1307,6 +1384,8 @@ void GLSL_ShutdownGPUShaders(void)
qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION2);
qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL);
qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL2);
qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR);
GLSL_BindNullProgram();
@ -1315,10 +1394,11 @@ void GLSL_ShutdownGPUShaders(void)
GLSL_DeleteGPUShader(&tr.genericShader[i]);
}
GLSL_DeleteGPUShader(&tr.textureOnlyShader);
GLSL_DeleteGPUShader(&tr.textureColorShader);
GLSL_DeleteGPUShader(&tr.lightmappedShader);
GLSL_DeleteGPUShader(&tr.fogShader);
GLSL_DeleteGPUShader(&tr.dlightShader);
GLSL_DeleteGPUShader(&tr.deluxemappedShader);
glState.currentProgram = 0;
qglUseProgramObjectARB(0);
@ -1431,6 +1511,34 @@ void GLSL_VertexAttribsState(uint32_t stateBits)
}
}
if(diff & ATTR_TANGENT)
{
if(stateBits & ATTR_TANGENT)
{
GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n");
qglEnableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
}
else
{
GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n");
qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
}
}
if(diff & ATTR_BITANGENT)
{
if(stateBits & ATTR_BITANGENT)
{
GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BITANGENT )\n");
qglEnableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
}
else
{
GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BITANGENT )\n");
qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
}
}
if(diff & ATTR_COLOR)
{
if(stateBits & ATTR_COLOR)
@ -1519,6 +1627,22 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
glState.vertexAttribPointersSet |= ATTR_NORMAL;
}
if((attribBits & ATTR_TANGENT) && !(glState.vertexAttribPointersSet & ATTR_TANGENT))
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT )\n");
qglVertexAttribPointerARB(ATTR_INDEX_TANGENT, 3, GL_FLOAT, 0, glState.currentVBO->stride_tangent, BUFFER_OFFSET(glState.currentVBO->ofs_tangent + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal)); // FIXME
glState.vertexAttribPointersSet |= ATTR_TANGENT;
}
if((attribBits & ATTR_BITANGENT) && !(glState.vertexAttribPointersSet & ATTR_BITANGENT))
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BITANGENT )\n");
qglVertexAttribPointerARB(ATTR_INDEX_BITANGENT, 3, GL_FLOAT, 0, glState.currentVBO->stride_bitangent, BUFFER_OFFSET(glState.currentVBO->ofs_bitangent + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal)); // FIXME
glState.vertexAttribPointersSet |= ATTR_BITANGENT;
}
if((attribBits & ATTR_COLOR) && !(glState.vertexAttribPointersSet & ATTR_COLOR))
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_COLOR )\n");
@ -1551,7 +1675,23 @@ shaderProgram_t *GLSL_GetGenericShaderProgram()
if (tess.fogNum)
{
shaderAttribs |= GLSLDEF_USE_FOG;
int stage;
for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
{
shaderStage_t *pStage = tess.xstages[stage];
if ( !pStage )
{
break;
}
if ( pStage->adjustColorsForFog)
{
shaderAttribs |= GLSLDEF_USE_FOG;
break;
}
}
}
// swapping these two out causes the worse case frame time to increase due to too many context switches

View file

@ -1208,6 +1208,18 @@ void R_CreateBuiltinImages( void ) {
Com_Memset( data, 255, sizeof( data ) );
tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT );
// black image, for no specular
for (x=0 ; x<DEFAULT_SIZE ; x++) {
for (y=0 ; y<DEFAULT_SIZE ; y++) {
data[y][x][0] =
data[y][x][1] =
data[y][x][2] = 0;
data[y][x][3] = 255;
}
}
tr.blackImage = R_CreateImage("*black", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT );
// with overbright bits active, we need an image which is some fraction of full color,
// for default lightmaps, etc
for (x=0 ; x<DEFAULT_SIZE ; x++) {
@ -1638,3 +1650,4 @@ void R_SkinList_f( void ) {
ri.Printf (PRINT_ALL, "------------------\n");
}

View file

@ -175,13 +175,19 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
byte *data;
int lat, lng;
vec3_t normal;
qboolean ignore;
#if idppc
float d0, d1, d2, d3, d4, d5;
#endif
factor = 1.0;
data = gridData;
ignore = qfalse;
for ( j = 0 ; j < 3 ; j++ ) {
if ( i & (1<<j) ) {
if ((pos[j] + 1) >= tr.world->lightGridBounds[j] - 1)
{
ignore = qtrue; // ignore values outside lightgrid
}
factor *= frac[j];
data += gridStep[j];
} else {
@ -189,7 +195,7 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
}
}
if ( !(data[0]+data[1]+data[2]) ) {
if ( ignore || !(data[0]+data[1]+data[2]+data[3]+data[4]+data[5]) ) {
continue; // ignore samples in walls
}
totalFactor += factor;

View file

@ -136,11 +136,15 @@ typedef struct VBO_s
uint32_t ofs_st;
uint32_t ofs_lightmap;
uint32_t ofs_vertexcolor;
uint32_t ofs_tangent;
uint32_t ofs_bitangent;
uint32_t stride_xyz;
uint32_t stride_normal;
uint32_t stride_st;
uint32_t stride_lightmap;
uint32_t stride_vertexcolor;
uint32_t stride_tangent;
uint32_t stride_bitangent;
uint32_t size_xyz;
uint32_t size_normal;
@ -257,7 +261,8 @@ typedef enum {
AGEN_LIGHTING_SPECULAR,
AGEN_WAVEFORM,
AGEN_PORTAL,
AGEN_CONST
AGEN_CONST,
AGEN_FRESNEL
} alphaGen_t;
typedef enum {
@ -382,9 +387,39 @@ typedef struct {
qboolean isVideoMap;
} textureBundle_t;
#define NUM_TEXTURE_BUNDLES 2
enum
{
TB_COLORMAP = 0,
TB_DIFFUSEMAP = 0,
TB_LIGHTMAP,
TB_NORMALMAP,
TB_DELUXEMAP,
TB_SPECULARMAP,
NUM_TEXTURE_BUNDLES = 5
};
typedef enum
{
// material shader stage types
ST_COLORMAP = 0, // vanilla Q3A style shader treatening
ST_DIFFUSEMAP = 0, // treat color and diffusemap the same
ST_NORMALMAP,
ST_SPECULARMAP,
ST_GLSL
} stageType_t;
typedef enum
{
COLLAPSE_none,
COLLAPSE_genericMulti,
COLLAPSE_lighting_DB,
COLLAPSE_lighting_DBS,
COLLAPSE_reflection_CB
} collapseType_t;
typedef struct {
stageType_t type;
qboolean active;
textureBundle_t bundle[NUM_TEXTURE_BUNDLES];
@ -402,6 +437,8 @@ typedef struct {
acff_t adjustColorsForFog;
qboolean isDetail;
struct shaderProgram_s *glslShader;
} shaderStage_t;
struct shaderCommands_s;
@ -537,7 +574,7 @@ enum
ATTR_INDEX_TEXCOORD0 = 1,
ATTR_INDEX_TEXCOORD1 = 2,
ATTR_INDEX_TANGENT = 3,
ATTR_INDEX_BINORMAL = 4,
ATTR_INDEX_BITANGENT = 4,
ATTR_INDEX_NORMAL = 5,
ATTR_INDEX_COLOR = 6,
ATTR_INDEX_PAINTCOLOR = 7,
@ -548,7 +585,7 @@ enum
// GPU vertex animations
ATTR_INDEX_POSITION2 = 11,
ATTR_INDEX_TANGENT2 = 12,
ATTR_INDEX_BINORMAL2 = 13,
ATTR_INDEX_BITANGENT2 = 13,
ATTR_INDEX_NORMAL2 = 14
};
@ -635,7 +672,7 @@ enum
ATTR_TEXCOORD = 0x0002,
ATTR_LIGHTCOORD = 0x0004,
ATTR_TANGENT = 0x0008,
ATTR_BINORMAL = 0x0010,
ATTR_BITANGENT = 0x0010,
ATTR_NORMAL = 0x0020,
ATTR_COLOR = 0x0040,
ATTR_PAINTCOLOR = 0x0080,
@ -646,7 +683,7 @@ enum
// for .md3 interpolation
ATTR_POSITION2 = 0x0800,
ATTR_TANGENT2 = 0x1000,
ATTR_BINORMAL2 = 0x2000,
ATTR_BITANGENT2 = 0x2000,
ATTR_NORMAL2 = 0x4000,
ATTR_DEFAULT = ATTR_POSITION,
@ -654,7 +691,7 @@ enum
ATTR_TEXCOORD |
ATTR_LIGHTCOORD |
ATTR_TANGENT |
ATTR_BINORMAL |
ATTR_BITANGENT |
ATTR_NORMAL |
ATTR_COLOR |
ATTR_PAINTCOLOR |
@ -663,7 +700,7 @@ enum
ATTR_BONE_WEIGHTS |
ATTR_POSITION2 |
ATTR_TANGENT2 |
ATTR_BINORMAL2 |
ATTR_BITANGENT2 |
ATTR_NORMAL2
};
@ -720,9 +757,10 @@ enum
enum
{
TEXTUREONLY_UNIFORM_MODELVIEWPROJECTIONMATRIX = 0,
TEXTUREONLY_UNIFORM_TEXTURE0MAP,
TEXTUREONLY_UNIFORM_COUNT
TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX = 0,
TEXTURECOLOR_UNIFORM_TEXTURE0MAP,
TEXTURECOLOR_UNIFORM_COLOR,
TEXTURECOLOR_UNIFORM_COUNT
};
@ -762,6 +800,9 @@ enum
{
GENERIC_UNIFORM_TEXTURE0MAP = 0,
GENERIC_UNIFORM_TEXTURE1MAP,
GENERIC_UNIFORM_TEXTURE2MAP,
GENERIC_UNIFORM_TEXTURE3MAP,
GENERIC_UNIFORM_TEXTURE4MAP,
GENERIC_UNIFORM_TEXTURE0MATRIX,
GENERIC_UNIFORM_TEXTURE1ENV,
GENERIC_UNIFORM_VIEWORIGIN,
@ -783,6 +824,7 @@ enum
GENERIC_UNIFORM_FOGDEPTH,
GENERIC_UNIFORM_FOGEYET,
GENERIC_UNIFORM_FOGADJUSTCOLORS,
GENERIC_UNIFORM_MODELMATRIX,
GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX,
GENERIC_UNIFORM_TIME,
GENERIC_UNIFORM_VERTEXLERP,
@ -953,6 +995,8 @@ typedef struct
vec2_t st;
vec2_t lightmap;
vec3_t normal;
vec3_t tangent;
vec3_t bitangent;
color4ub_t vertexColors;
#if DEBUG_OPTIMIZEVERTICES
@ -960,7 +1004,7 @@ typedef struct
#endif
} srfVert_t;
#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
typedef struct
{
@ -1552,6 +1596,7 @@ typedef struct {
int frameSceneNum; // zeroed at RE_BeginFrame
qboolean worldMapLoaded;
qboolean worldDeluxeMapping;
world_t *world;
const byte *externalVisData; // from RE_SetWorldVisData, shared with CM_Load
@ -1562,6 +1607,7 @@ typedef struct {
image_t *dlightImage; // inverse-quare highlight for projective adding
image_t *flareImage;
image_t *whiteImage; // full of 0xff
image_t *blackImage; // full of 0x000000ff
image_t *identityLightImage; // full of tr.identityLightByte
shader_t *defaultShader;
@ -1573,8 +1619,10 @@ typedef struct {
int numLightmaps;
image_t **lightmaps;
image_t **deluxemaps;
image_t *fatLightmap;
image_t *fatDeluxemap;
int fatLightmapSize;
int fatLightmapStep;
@ -1590,9 +1638,10 @@ typedef struct {
shaderProgram_t genericShader[GLSLDEF_COUNT];
shaderProgram_t lightmappedShader;
shaderProgram_t textureOnlyShader;
shaderProgram_t textureColorShader;
shaderProgram_t fogShader;
shaderProgram_t dlightShader;
shaderProgram_t deluxemappedShader;
// -----------------------------------------
@ -1830,8 +1879,9 @@ void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int fogIndex, int dlightMap );
void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles);
void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts);
qboolean R_CalcTangentVectors(srfVert_t * dv[3]);
void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles);
void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts);
#define CULL_IN 0 // completely unclipped
#define CULL_CLIP 1 // clipped by one or more planes
@ -2004,6 +2054,8 @@ typedef struct shaderCommands_s
glIndex_t indexes[SHADER_MAX_INDEXES] QALIGN(16);
vec4_t xyz[SHADER_MAX_VERTEXES] QALIGN(16);
vec4_t normal[SHADER_MAX_VERTEXES] QALIGN(16);
vec4_t tangent[SHADER_MAX_VERTEXES] QALIGN(16);
vec4_t bitangent[SHADER_MAX_VERTEXES] QALIGN(16);
vec2_t texCoords[SHADER_MAX_VERTEXES][2] QALIGN(16);
color4ub_t vertexColors[SHADER_MAX_VERTEXES] QALIGN(16);
//int vertexDlightBits[SHADER_MAX_VERTEXES] QALIGN(16);

View file

@ -43,6 +43,446 @@ refimport_t ri;
// point at this for their sorting surface
surfaceType_t entitySurface = SF_ENTITY;
/*
================
R_CompareVert
================
*/
qboolean R_CompareVert(srfVert_t * v1, srfVert_t * v2, qboolean checkST)
{
int i;
for(i = 0; i < 3; i++)
{
if(floor(v1->xyz[i] + 0.1) != floor(v2->xyz[i] + 0.1))
{
return qfalse;
}
if(checkST && ((v1->st[0] != v2->st[0]) || (v1->st[1] != v2->st[1])))
{
return qfalse;
}
}
return qtrue;
}
/*
=============
R_CalcNormalForTriangle
=============
*/
void R_CalcNormalForTriangle(vec3_t normal, const vec3_t v0, const vec3_t v1, const vec3_t v2)
{
vec3_t udir, vdir;
// compute the face normal based on vertex points
VectorSubtract(v2, v0, udir);
VectorSubtract(v1, v0, vdir);
CrossProduct(udir, vdir, normal);
VectorNormalize(normal);
}
/*
=============
R_CalcTangentsForTriangle
http://members.rogers.com/deseric/tangentspace.htm
=============
*/
void R_CalcTangentsForTriangle(vec3_t tangent, vec3_t bitangent,
const vec3_t v0, const vec3_t v1, const vec3_t v2,
const vec2_t t0, const vec2_t t1, const vec2_t t2)
{
int i;
vec3_t planes[3];
vec3_t u, v;
for(i = 0; i < 3; i++)
{
VectorSet(u, v1[i] - v0[i], t1[0] - t0[0], t1[1] - t0[1]);
VectorSet(v, v2[i] - v0[i], t2[0] - t0[0], t2[1] - t0[1]);
VectorNormalize(u);
VectorNormalize(v);
CrossProduct(u, v, planes[i]);
}
//So your tangent space will be defined by this :
//Normal = Normal of the triangle or Tangent X Bitangent (careful with the cross product,
// you have to make sure the normal points in the right direction)
//Tangent = ( dp(Fx(s,t)) / ds, dp(Fy(s,t)) / ds, dp(Fz(s,t)) / ds ) or ( -Bx/Ax, -By/Ay, - Bz/Az )
//Bitangent = ( dp(Fx(s,t)) / dt, dp(Fy(s,t)) / dt, dp(Fz(s,t)) / dt ) or ( -Cx/Ax, -Cy/Ay, -Cz/Az )
// tangent...
tangent[0] = -planes[0][1] / planes[0][0];
tangent[1] = -planes[1][1] / planes[1][0];
tangent[2] = -planes[2][1] / planes[2][0];
VectorNormalize(tangent);
// bitangent...
bitangent[0] = -planes[0][2] / planes[0][0];
bitangent[1] = -planes[1][2] / planes[1][0];
bitangent[2] = -planes[2][2] / planes[2][0];
VectorNormalize(bitangent);
}
/*
=============
R_CalcTangentSpace
=============
*/
void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
{
vec3_t cp, u, v;
vec3_t faceNormal;
VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[0] = -cp[1] / cp[0];
bitangent[0] = -cp[2] / cp[0];
}
u[0] = v1[1] - v0[1];
v[0] = v2[1] - v0[1];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[1] = -cp[1] / cp[0];
bitangent[1] = -cp[2] / cp[0];
}
u[0] = v1[2] - v0[2];
v[0] = v2[2] - v0[2];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[2] = -cp[1] / cp[0];
bitangent[2] = -cp[2] / cp[0];
}
VectorNormalize(tangent);
VectorNormalize(bitangent);
// compute the face normal based on vertex points
VectorSubtract(v2, v0, u);
VectorSubtract(v1, v0, v);
CrossProduct(u, v, faceNormal);
VectorNormalize(faceNormal);
#if 1
// Gram-Schmidt orthogonalize
//tangent[a] = (t - n * Dot(n, t)).Normalize();
VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent);
VectorNormalize(tangent);
// compute the cross product B=NxT
//CrossProduct(normal, tangent, bitangent);
#else
// normal, compute the cross product N=TxB
CrossProduct(tangent, bitangent, normal);
VectorNormalize(normal);
if(DotProduct(normal, faceNormal) < 0)
{
//VectorInverse(normal);
//VectorInverse(tangent);
//VectorInverse(bitangent);
// compute the cross product T=BxN
CrossProduct(bitangent, faceNormal, tangent);
// compute the cross product B=NxT
//CrossProduct(normal, tangent, bitangent);
}
#endif
VectorCopy(faceNormal, normal);
}
void R_CalcTangentSpaceFast(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
{
vec3_t cp, u, v;
vec3_t faceNormal;
VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[0] = -cp[1] / cp[0];
bitangent[0] = -cp[2] / cp[0];
}
u[0] = v1[1] - v0[1];
v[0] = v2[1] - v0[1];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[1] = -cp[1] / cp[0];
bitangent[1] = -cp[2] / cp[0];
}
u[0] = v1[2] - v0[2];
v[0] = v2[2] - v0[2];
CrossProduct(u, v, cp);
if(fabs(cp[0]) > 10e-6)
{
tangent[2] = -cp[1] / cp[0];
bitangent[2] = -cp[2] / cp[0];
}
VectorNormalizeFast(tangent);
VectorNormalizeFast(bitangent);
// compute the face normal based on vertex points
VectorSubtract(v2, v0, u);
VectorSubtract(v1, v0, v);
CrossProduct(u, v, faceNormal);
VectorNormalizeFast(faceNormal);
#if 0
// normal, compute the cross product N=TxB
CrossProduct(tangent, bitangent, normal);
VectorNormalizeFast(normal);
if(DotProduct(normal, faceNormal) < 0)
{
VectorInverse(normal);
//VectorInverse(tangent);
//VectorInverse(bitangent);
CrossProduct(normal, tangent, bitangent);
}
VectorCopy(faceNormal, normal);
#else
// Gram-Schmidt orthogonalize
//tangent[a] = (t - n * Dot(n, t)).Normalize();
VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent);
VectorNormalizeFast(tangent);
#endif
VectorCopy(faceNormal, normal);
}
/*
http://www.terathon.com/code/tangent.html
*/
void R_CalcTBN(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v1, const vec3_t v2, const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3)
{
vec3_t u, v;
float x1, x2, y1, y2, z1, z2;
float s1, s2, t1, t2;
float r, dot;
x1 = v2[0] - v1[0];
x2 = v3[0] - v1[0];
y1 = v2[1] - v1[1];
y2 = v3[1] - v1[1];
z1 = v2[2] - v1[2];
z2 = v3[2] - v1[2];
s1 = w2[0] - w1[0];
s2 = w3[0] - w1[0];
t1 = w2[1] - w1[1];
t2 = w3[1] - w1[1];
r = 1.0f / (s1 * t2 - s2 * t1);
VectorSet(tangent, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
VectorSet(bitangent, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
// compute the face normal based on vertex points
VectorSubtract(v3, v1, u);
VectorSubtract(v2, v1, v);
CrossProduct(u, v, normal);
VectorNormalize(normal);
// Gram-Schmidt orthogonalize
//tangent[a] = (t - n * Dot(n, t)).Normalize();
dot = DotProduct(normal, tangent);
VectorMA(tangent, -dot, normal, tangent);
VectorNormalize(tangent);
// B=NxT
//CrossProduct(normal, tangent, bitangent);
}
void R_CalcTBN2(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v1, const vec3_t v2, const vec3_t v3, const vec2_t t1, const vec2_t t2, const vec2_t t3)
{
vec3_t v2v1;
vec3_t v3v1;
float c2c1_T;
float c2c1_B;
float c3c1_T;
float c3c1_B;
float denominator;
float scale1, scale2;
vec3_t T, B, N, C;
// Calculate the tangent basis for each vertex of the triangle
// UPDATE: In the 3rd edition of the accompanying article, the for-loop located here has
// been removed as it was redundant (the entire TBN matrix was calculated three times
// instead of just one).
//
// Please note, that this function relies on the fact that the input geometry are triangles
// and the tangent basis for each vertex thus is identical!
//
// Calculate the vectors from the current vertex to the two other vertices in the triangle
VectorSubtract(v2, v1, v2v1);
VectorSubtract(v3, v1, v3v1);
// The equation presented in the article states that:
// c2c1_T = V2.texcoord.x V1.texcoord.x
// c2c1_B = V2.texcoord.y V1.texcoord.y
// c3c1_T = V3.texcoord.x V1.texcoord.x
// c3c1_B = V3.texcoord.y V1.texcoord.y
// Calculate c2c1_T and c2c1_B
c2c1_T = t2[0] - t1[0];
c2c1_B = t2[1] - t2[1];
// Calculate c3c1_T and c3c1_B
c3c1_T = t3[0] - t1[0];
c3c1_B = t3[1] - t1[1];
denominator = c2c1_T * c3c1_B - c3c1_T * c2c1_B;
//if(ROUNDOFF(fDenominator) == 0.0f)
if(denominator == 0.0f)
{
// We won't risk a divide by zero, so set the tangent matrix to the identity matrix
VectorSet(tangent, 1, 0, 0);
VectorSet(bitangent, 0, 1, 0);
VectorSet(normal, 0, 0, 1);
}
else
{
// Calculate the reciprocal value once and for all (to achieve speed)
scale1 = 1.0f / denominator;
// T and B are calculated just as the equation in the article states
VectorSet(T, (c3c1_B * v2v1[0] - c2c1_B * v3v1[0]) * scale1,
(c3c1_B * v2v1[1] - c2c1_B * v3v1[1]) * scale1,
(c3c1_B * v2v1[2] - c2c1_B * v3v1[2]) * scale1);
VectorSet(B, (-c3c1_T * v2v1[0] + c2c1_T * v3v1[0]) * scale1,
(-c3c1_T * v2v1[1] + c2c1_T * v3v1[1]) * scale1,
(-c3c1_T * v2v1[2] + c2c1_T * v3v1[2]) * scale1);
// The normal N is calculated as the cross product between T and B
CrossProduct(T, B, N);
#if 0
VectorCopy(T, tangent);
VectorCopy(B, bitangent);
VectorCopy(N, normal);
#else
// Calculate the reciprocal value once and for all (to achieve speed)
scale2 = 1.0f / ((T[0] * B[1] * N[2] - T[2] * B[1] * N[0]) +
(B[0] * N[1] * T[2] - B[2] * N[1] * T[0]) +
(N[0] * T[1] * B[2] - N[2] * T[1] * B[0]));
// Calculate the inverse if the TBN matrix using the formula described in the article.
// We store the basis vectors directly in the provided TBN matrix: pvTBNMatrix
CrossProduct(B, N, C); tangent[0] = C[0] * scale2;
CrossProduct(N, T, C); tangent[1] = -C[0] * scale2;
CrossProduct(T, B, C); tangent[2] = C[0] * scale2;
VectorNormalize(tangent);
CrossProduct(B, N, C); bitangent[0] = -C[1] * scale2;
CrossProduct(N, T, C); bitangent[1] = C[1] * scale2;
CrossProduct(T, B, C); bitangent[2] = -C[1] * scale2;
VectorNormalize(bitangent);
CrossProduct(B, N, C); normal[0] = C[2] * scale2;
CrossProduct(N, T, C); normal[1] = -C[2] * scale2;
CrossProduct(T, B, C); normal[2] = C[2] * scale2;
VectorNormalize(normal);
#endif
}
}
qboolean R_CalcTangentVectors(srfVert_t * dv[3])
{
int i;
float bb, s, t;
vec3_t bary;
/* calculate barycentric basis for the triangle */
bb = (dv[1]->st[0] - dv[0]->st[0]) * (dv[2]->st[1] - dv[0]->st[1]) - (dv[2]->st[0] - dv[0]->st[0]) * (dv[1]->st[1] - dv[0]->st[1]);
if(fabs(bb) < 0.00000001f)
return qfalse;
/* do each vertex */
for(i = 0; i < 3; i++)
{
// calculate s tangent vector
s = dv[i]->st[0] + 10.0f;
t = dv[i]->st[1];
bary[0] = ((dv[1]->st[0] - s) * (dv[2]->st[1] - t) - (dv[2]->st[0] - s) * (dv[1]->st[1] - t)) / bb;
bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
dv[i]->tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
dv[i]->tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
dv[i]->tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
VectorSubtract(dv[i]->tangent, dv[i]->xyz, dv[i]->tangent);
VectorNormalize(dv[i]->tangent);
// calculate t tangent vector
s = dv[i]->st[0];
t = dv[i]->st[1] + 10.0f;
bary[0] = ((dv[1]->st[0] - s) * (dv[2]->st[1] - t) - (dv[2]->st[0] - s) * (dv[1]->st[1] - t)) / bb;
bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
dv[i]->bitangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
dv[i]->bitangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
dv[i]->bitangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
VectorSubtract(dv[i]->bitangent, dv[i]->xyz, dv[i]->bitangent);
VectorNormalize(dv[i]->bitangent);
// debug code
//% Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,
//% stv[ i ][ 0 ], stv[ i ][ 1 ], stv[ i ][ 2 ], ttv[ i ][ 0 ], ttv[ i ][ 1 ], ttv[ i ][ 2 ] );
}
return qtrue;
}
/*
=================
R_FindSurfaceTriangleWithEdge
@ -1607,3 +2047,4 @@ void R_RenderView (viewParms_t *parms) {

View file

@ -456,3 +456,4 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
return returnedFragments;
}

View file

@ -431,3 +431,4 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
}

View file

@ -1309,3 +1309,4 @@ void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) {
VectorCopy( frame->bounds[1], maxs );
}

View file

@ -300,13 +300,16 @@ static void DrawTris (shaderCommands_t *input) {
{
if (glRefConfig.glsl && r_arb_shader_objects->integer)
{
shaderProgram_t *sp = &tr.textureOnlyShader;
shaderProgram_t *sp = &tr.textureColorShader;
vec4_t color;
GLSL_VertexAttribsState(ATTR_POSITION);
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, TEXTUREONLY_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
VectorSet4(color, 1, 1, 1, 1);
GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);
if (input->multiDrawPrimitives)
{
R_DrawMultiElementsVBO(input->multiDrawPrimitives, (const GLvoid **)input->multiDrawFirstIndex, input->multiDrawNumIndexes);
@ -1541,6 +1544,9 @@ static void ComputeColors( shaderStage_t *pStage )
}
}
break;
case AGEN_FRESNEL:
// FIXME: implement me!
break;
}
//
@ -1755,6 +1761,9 @@ static void ComputeHelperColor( shaderStage_t *pStage, vec4_t color)
case AGEN_PORTAL:
// Done entirely in vertex program
break;
case AGEN_FRESNEL:
// Done entirely in vertex program
break;
}
//
@ -2065,6 +2074,9 @@ static void ComputeColorMatrix( shaderStage_t *pStage, float *outmatrix, qboolea
}
#endif
break;
case AGEN_FRESNEL:
// FIXME: implement me!
break;
}
// FIXME: find some way to implement this stuff.
@ -2448,16 +2460,17 @@ static void RB_IterateStagesGenericVBOGLSL( shaderCommands_t *input )
{
int stage;
matrix_t matrix;
shaderProgram_t *sp = GLSL_GetGenericShaderProgram();
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_VIEWORIGIN, backEnd.or.viewOrigin);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
int deformGen;
vec4_t deformWave;
vec3_t deformBulge;
float deformSpread;
vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
float eyeT;
// u_DeformGen
deformGen = DGEN_NONE;
if(!ShaderRequiresCPUDeforms(input->shader))
{
deformStage_t *ds;
@ -2468,46 +2481,28 @@ static void RB_IterateStagesGenericVBOGLSL( shaderCommands_t *input )
switch (ds->deformation)
{
case DEFORM_WAVE:
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, ds->deformationWave.func);
deformGen = ds->deformationWave.func;
{
vec4_t v;
waveForm_t *wf = &ds->deformationWave;
VectorSet4(v, wf->base, wf->amplitude, wf->phase, wf->frequency);
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_DEFORMWAVE, v);
VectorSet4(deformWave, wf->base, wf->amplitude, wf->phase, wf->frequency);
}
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_DEFORMSPREAD, ds->deformationSpread);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime);
deformSpread = ds->deformationSpread;
break;
case DEFORM_BULGE:
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, DGEN_BULGE);
{
vec3_t v;
VectorSet(v, ds->bulgeWidth, ds->bulgeHeight, ds->bulgeSpeed);
GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_DEFORMBULGE, v);
}
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime);
deformGen = DGEN_BULGE;
VectorSet(deformBulge, ds->bulgeWidth, ds->bulgeHeight, ds->bulgeSpeed);
break;
default:
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, DGEN_NONE);
break;
}
}
else
{
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, DGEN_NONE);
}
if ( input->fogNum ) {
fog_t *fog;
vec3_t local;
vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
float eyeT;
fog = tr.world->fogs + tess.fogNum;
@ -2534,27 +2529,65 @@ static void RB_IterateStagesGenericVBOGLSL( shaderCommands_t *input )
} else {
eyeT = 1; // non-surface fog always has eye inside
}
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDISTANCE, fogDistanceVector);
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDEPTH, fogDepthVector);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_FOGEYET, eyeT);
}
for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
{
shaderStage_t *pStage = input->xstages[stage];
qboolean setcolor = qfalse;
shaderProgram_t *sp;
if ( !pStage )
{
break;
}
if (pStage->glslShader)
{
sp = pStage->glslShader;
}
else
{
sp = GLSL_GetGenericShaderProgram();
}
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_VIEWORIGIN, backEnd.or.viewOrigin);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, deformGen);
switch(deformGen)
{
case DGEN_WAVE_SIN:
case DGEN_WAVE_SQUARE:
case DGEN_WAVE_TRIANGLE:
case DGEN_WAVE_SAWTOOTH:
case DGEN_WAVE_INVERSE_SAWTOOTH:
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_DEFORMWAVE, deformWave);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_DEFORMSPREAD, deformSpread);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime);
break;
case DGEN_BULGE:
GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_DEFORMBULGE, deformBulge);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime);
break;
default:
break;
}
if ( input->fogNum ) {
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDISTANCE, fogDistanceVector);
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDEPTH, fogDepthVector);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_FOGEYET, eyeT);
}
GL_State( pStage->stateBits );
switch (pStage->rgbGen)
{
case CGEN_IDENTITY:
case CGEN_EXACT_VERTEX:
case CGEN_LIGHTING_DIFFUSE:
break;
@ -2564,11 +2597,11 @@ static void RB_IterateStagesGenericVBOGLSL( shaderCommands_t *input )
switch (pStage->alphaGen)
{
case AGEN_IDENTITY:
case AGEN_LIGHTING_SPECULAR:
case AGEN_VERTEX:
case AGEN_ONE_MINUS_VERTEX:
case AGEN_PORTAL:
case AGEN_FRESNEL:
break;
default:
setcolor = qtrue;
@ -2617,7 +2650,37 @@ static void RB_IterateStagesGenericVBOGLSL( shaderCommands_t *input )
//
// do multitexture
//
if ( pStage->bundle[1].image[0] != 0 )
if ( pStage->glslShader )
{
int i;
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELMATRIX, backEnd.or.modelMatrix);
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
{
if (pStage->bundle[i].image[0])
{
R_BindAnimatedImageToTMU( &pStage->bundle[i], i);
}
}
ComputeTexMatrix( pStage, 0, matrix );
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_TEXTURE0MATRIX, matrix);
//
// draw
//
if (input->multiDrawPrimitives)
{
R_DrawMultiElementsVBO(input->multiDrawPrimitives, (const GLvoid **)input->multiDrawFirstIndex, input->multiDrawNumIndexes);
}
else
{
R_DrawElementsVBO(input->numIndexes, input->firstIndex);
}
}
else if ( pStage->bundle[1].image[0] != 0 )
{
DrawMultitexturedVBOGLSL( sp, input, stage );
}
@ -3281,3 +3344,4 @@ void RB_EndSurface( void ) {
GLimp_LogComment( "----------\n" );
}

View file

@ -1334,3 +1334,4 @@ void RB_CalcDiffuseColor( unsigned char *colors )
RB_CalcDiffuseColor_scalar( colors );
}

View file

@ -634,6 +634,22 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
}
continue;
}
else if ( !Q_stricmp( token, "$deluxemap" ) )
{
if (!tr.worldDeluxeMapping)
{
ri.Printf( PRINT_WARNING, "WARNING: shader '%s' wants a deluxe map in a map compiled without them\n", shader.name );
return qfalse;
}
stage->bundle[0].isLightmap = qtrue;
if ( shader.lightmapIndex < 0 ) {
stage->bundle[0].image[0] = tr.whiteImage;
} else {
stage->bundle[0].image[0] = tr.deluxemaps[shader.lightmapIndex];
}
continue;
}
else
{
stage->bundle[0].image[0] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_REPEAT );
@ -800,6 +816,36 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
}
}
//
// stage <type>
//
else if(!Q_stricmp(token, "stage"))
{
token = COM_ParseExt(text, qfalse);
if(token[0] == 0)
{
ri.Printf(PRINT_WARNING, "WARNING: missing parameters for stage in shader '%s'\n", shader.name);
continue;
}
if(!Q_stricmp(token, "diffuseMap"))
{
stage->type = ST_DIFFUSEMAP;
}
else if(!Q_stricmp(token, "normalMap") || !Q_stricmp(token, "bumpMap"))
{
stage->type = ST_NORMALMAP;
}
else if(!Q_stricmp(token, "specularMap"))
{
stage->type = ST_SPECULARMAP;
}
else
{
ri.Printf(PRINT_WARNING, "WARNING: unknown stage parameter '%s' in shader '%s'\n", token, shader.name);
continue;
}
}
//
// rgbGen
//
else if ( !Q_stricmp( token, "rgbGen" ) )
@ -929,6 +975,10 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
shader.portalRange = atof( token );
}
}
else if ( !Q_stricmp( token, "fresnel" ) )
{
stage->alphaGen = AGEN_FRESNEL;
}
else
{
ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name );
@ -1807,11 +1857,16 @@ static void ComputeVertexAttribs(void)
break;
}
for (i = 0; i < 2; i++)
if (pStage->glslShader)
{
if (i == 1 && ( pStage->bundle[1].image[0] == 0 ))
shader.vertexAttribs |= ATTR_NORMAL | ATTR_BITANGENT | ATTR_TANGENT;
}
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
{
if ( pStage->bundle[i].image[0] == 0 )
{
break;
continue;
}
switch(pStage->bundle[i].tcGen)
@ -1850,6 +1905,7 @@ static void ComputeVertexAttribs(void)
switch(pStage->alphaGen)
{
case AGEN_LIGHTING_SPECULAR:
case AGEN_FRESNEL:
shader.vertexAttribs |= ATTR_NORMAL;
break;
@ -1858,6 +1914,10 @@ static void ComputeVertexAttribs(void)
shader.vertexAttribs |= ATTR_COLOR;
break;
case CGEN_LIGHTING_DIFFUSE:
shader.vertexAttribs |= ATTR_NORMAL;
break;
default:
break;
}
@ -2020,6 +2080,117 @@ static qboolean CollapseMultitexture( void ) {
return qtrue;
}
static qboolean CollapseStagesToGLSL(void)
{
int i, numStages;
shaderStage_t *diffuse, *lightmap, *normal, *specular;
diffuse = NULL;
lightmap = NULL;
normal = NULL;
specular = NULL;
// find all the stages that are important
for (i = 0; i < MAX_SHADER_STAGES; i++)
{
shaderStage_t *pStage = &stages[i];
int blendbits;
if (!pStage->active)
continue;
blendbits = pStage->stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS);
if (pStage->bundle[0].isLightmap &&
(blendbits == (GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO) ||
blendbits == (GLS_SRCBLEND_ZERO | GLS_DSTBLEND_SRC_COLOR)))
{
lightmap = pStage;
}
else
{
switch (pStage->type)
{
case ST_DIFFUSEMAP:
diffuse = pStage;
break;
case ST_NORMALMAP:
normal = pStage;
break;
case ST_SPECULARMAP:
specular = pStage;
break;
default:
break;
}
}
}
// if we've got these, use deluxemapped shader
if (diffuse && lightmap && normal)
{
if (tr.worldDeluxeMapping)
{
// reuse diffuse, mark others inactive
diffuse->type = ST_GLSL;
diffuse->glslShader = &tr.deluxemappedShader;
diffuse->bundle[TB_LIGHTMAP] = lightmap->bundle[0];
diffuse->bundle[TB_NORMALMAP] = normal->bundle[0];
if (specular)
{
diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0];
}
else
{
diffuse->bundle[TB_SPECULARMAP] = diffuse->bundle[0];
diffuse->bundle[TB_SPECULARMAP].image[0] = tr.blackImage;
}
diffuse->bundle[TB_DELUXEMAP] = lightmap->bundle[0];
diffuse->bundle[TB_DELUXEMAP].image[0] = tr.deluxemaps[shader.lightmapIndex];
lightmap->active = qfalse;
normal->active = qfalse;
if (specular)
{
specular->active = qfalse;
}
}
else
{
// no deluxe mapping, turn off normal and specular
normal->active = qfalse;
specular->active = qfalse;
}
}
// condense stages
numStages = 0;
for (i = 0; i < MAX_SHADER_STAGES; i++)
{
if (!stages[i].active)
continue;
if (i == numStages)
{
numStages++;
continue;
}
stages[numStages] = stages[i];
stages[i].active = qfalse;
numStages++;
}
if (numStages == i && i == 2 && CollapseMultitexture())
numStages--;
return numStages;
}
/*
=============
@ -2435,9 +2606,7 @@ static shader_t *FinishShader( void ) {
//
// look for multitexture potential
//
if ( stage > 1 && CollapseMultitexture() ) {
stage--;
}
stage = CollapseStagesToGLSL();
if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) {
if (vertexLightmap) {

View file

@ -389,7 +389,6 @@ static void DrawSkySideVBO( struct image_s *image, const int mins[2], const int
int s, t;
//int firstVertex = tess.numVertexes;
//int firstIndex = tess.numIndexes;
matrix_t matrix;
vec4_t color;
tess.numVertexes = 0;
@ -443,27 +442,18 @@ static void DrawSkySideVBO( struct image_s *image, const int mins[2], const int
if (glRefConfig.glsl && r_arb_shader_objects->integer)
{
shaderProgram_t *sp = GLSL_GetGenericShaderProgram();
shaderProgram_t *sp = &tr.textureColorShader;
GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_FOGADJUSTCOLORS, 0);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, DGEN_NONE);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TCGEN0, TCGEN_TEXTURE);
Matrix16Identity(matrix);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_TEXTURE0MATRIX, matrix);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TEXTURE1ENV, 0);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_COLORGEN, CGEN_CONST);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_ALPHAGEN, AGEN_CONST);
GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
color[0] = tr.identityLight;
color[1] = tr.identityLight;
color[2] = tr.identityLight;
color[3] = 1.0f;
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_COLOR, color);
GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);
}
else
{
@ -985,3 +975,4 @@ void RB_StageIteratorSky( void ) {
backEnd.skyRenderedThisView = qtrue;
}

View file

@ -218,12 +218,15 @@ void RB_InstantQuad(vec4_t quadVerts[4])
if (glRefConfig.glsl && r_arb_shader_objects->integer)
{
shaderProgram_t *sp = &tr.textureOnlyShader;
shaderProgram_t *sp = &tr.textureColorShader;
vec4_t color;
GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, TEXTUREONLY_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
VectorSet4(color, 1, 1, 1, 1);
GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);
}
else
{
@ -335,7 +338,7 @@ static void RB_SurfaceHelper( int numVerts, srfVert_t *verts, int numTriangles,
int i;
srfTriangle_t *tri;
srfVert_t *dv;
float *xyz, *normal, *texCoords;
float *xyz, *normal, *tangent, *bitangent, *texCoords;
glIndex_t *index;
byte *color;
qboolean needsNormal;
@ -354,6 +357,8 @@ static void RB_SurfaceHelper( int numVerts, srfVert_t *verts, int numTriangles,
dv = verts;
xyz = tess.xyz[ tess.numVertexes ];
normal = tess.normal[ tess.numVertexes ];
tangent = tess.tangent[ tess.numVertexes ];
bitangent = tess.bitangent[ tess.numVertexes ];
texCoords = tess.texCoords[ tess.numVertexes ][0];
color = tess.vertexColors[ tess.numVertexes ];
needsNormal = tess.shader->vertexAttribs & ATTR_NORMAL;
@ -367,6 +372,12 @@ static void RB_SurfaceHelper( int numVerts, srfVert_t *verts, int numTriangles,
normal[0] = dv->normal[0];
normal[1] = dv->normal[1];
normal[2] = dv->normal[2];
tangent[0] = dv->tangent[0];
tangent[1] = dv->tangent[1];
tangent[2] = dv->tangent[2];
bitangent[0] = dv->bitangent[0];
bitangent[1] = dv->bitangent[1];
bitangent[2] = dv->bitangent[2];
}
texCoords[0] = dv->st[0];
@ -514,7 +525,6 @@ static void RB_SurfaceBeam( void )
vec3_t direction, normalized_direction;
vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
vec3_t oldorigin, origin;
matrix_t matrix;
vec4_t color;
e = &backEnd.currentEntity->e;
@ -576,27 +586,18 @@ static void RB_SurfaceBeam( void )
if (glRefConfig.glsl && r_arb_shader_objects->integer)
{
shaderProgram_t *sp = GLSL_GetGenericShaderProgram();
shaderProgram_t *sp = &tr.textureColorShader;
GLSL_VertexAttribsState(ATTR_POSITION);
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_FOGADJUSTCOLORS, 0);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, DGEN_NONE);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TCGEN0, TCGEN_IDENTITY);
Matrix16Identity(matrix);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_TEXTURE0MATRIX, matrix);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TEXTURE1ENV, 0);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_COLORGEN, CGEN_CONST);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_ALPHAGEN, AGEN_CONST);
GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
color[0] = 1.0f;
color[1] = 0.0f;
color[2] = 0.0f;
color[3] = 1.0f;
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_COLOR, color);
GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);
}
else
{
@ -1295,7 +1296,7 @@ static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
int i, j;
float *xyz;
float *texCoords;
float *normal;
float *normal, *tangent, *bitangent;
unsigned char *color;
srfVert_t *dv;
int rows, irows, vrows;
@ -1377,6 +1378,8 @@ static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
xyz = tess.xyz[numVertexes];
normal = tess.normal[numVertexes];
tangent = tess.tangent[numVertexes];
bitangent = tess.bitangent[numVertexes];
texCoords = tess.texCoords[numVertexes][0];
color = ( unsigned char * ) &tess.vertexColors[numVertexes];
//vDlightBits = &tess.vertexDlightBits[numVertexes];
@ -1398,6 +1401,12 @@ static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
normal[0] = dv->normal[0];
normal[1] = dv->normal[1];
normal[2] = dv->normal[2];
tangent[0] = dv->tangent[0];
tangent[1] = dv->tangent[1];
tangent[2] = dv->tangent[2];
bitangent[0] = dv->bitangent[0];
bitangent[1] = dv->bitangent[1];
bitangent[2] = dv->bitangent[2];
}
* ( unsigned int * ) color = * ( unsigned int * ) dv->vertexColors;
//*vDlightBits++ = dlightBits;

View file

@ -147,6 +147,18 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
dataSize += sizeof(verts[0].normal);
}
if(stateBits & ATTR_TANGENT)
{
vbo->ofs_tangent = dataSize;
dataSize += sizeof(verts[0].tangent);
}
if(stateBits & ATTR_BITANGENT)
{
vbo->ofs_bitangent = dataSize;
dataSize += sizeof(verts[0].bitangent);
}
if(stateBits & ATTR_TEXCOORD)
{
vbo->ofs_st = dataSize;
@ -167,6 +179,8 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
vbo->stride_xyz = dataSize;
vbo->stride_normal = dataSize;
vbo->stride_tangent = dataSize;
vbo->stride_bitangent = dataSize;
vbo->stride_st = dataSize;
vbo->stride_lightmap = dataSize;
vbo->stride_vertexcolor = dataSize;
@ -192,6 +206,20 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
dataOfs += sizeof(verts[i].normal);
}
// tangent
if(stateBits & ATTR_TANGENT)
{
memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent));
dataOfs += sizeof(verts[i].tangent);
}
// bitangent
if(stateBits & ATTR_BITANGENT)
{
memcpy(data + dataOfs, &verts[i].bitangent, sizeof(verts[i].bitangent));
dataOfs += sizeof(verts[i].bitangent);
}
// vertex texcoords
if(stateBits & ATTR_TEXCOORD)
{
@ -224,6 +252,16 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
dataSize += sizeof(verts[0].normal);
}
if(stateBits & ATTR_TANGENT)
{
dataSize += sizeof(verts[0].tangent);
}
if(stateBits & ATTR_BITANGENT)
{
dataSize += sizeof(verts[0].bitangent);
}
if(stateBits & ATTR_TEXCOORD)
{
dataSize += sizeof(verts[0].st);
@ -246,12 +284,16 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
vbo->ofs_xyz = 0;
vbo->ofs_normal = 0;
vbo->ofs_tangent = 0;
vbo->ofs_bitangent = 0;
vbo->ofs_st = 0;
vbo->ofs_lightmap = 0;
vbo->ofs_vertexcolor = 0;
vbo->stride_xyz = sizeof(verts[0].xyz);
vbo->stride_normal = sizeof(verts[0].normal);
vbo->stride_tangent = sizeof(verts[0].tangent);
vbo->stride_bitangent = sizeof(verts[0].bitangent);
vbo->stride_vertexcolor = sizeof(verts[0].vertexColors);
vbo->stride_st = sizeof(verts[0].st);
vbo->stride_lightmap = sizeof(verts[0].lightmap);
@ -277,6 +319,28 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
}
}
// tangent
if(stateBits & ATTR_TANGENT)
{
vbo->ofs_tangent = dataOfs;
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent));
dataOfs += sizeof(verts[i].tangent);
}
}
// bitangent
if(stateBits & ATTR_BITANGENT)
{
vbo->ofs_bitangent = dataOfs;
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].bitangent, sizeof(verts[i].bitangent));
dataOfs += sizeof(verts[i].bitangent);
}
}
// vertex texcoords
if(stateBits & ATTR_TEXCOORD)
{
@ -591,6 +655,8 @@ void R_InitVBOs(void)
dataSize = sizeof(tess.xyz[0]);
dataSize += sizeof(tess.normal[0]);
dataSize += sizeof(tess.tangent[0]);
dataSize += sizeof(tess.bitangent[0]);
dataSize += sizeof(tess.vertexColors[0]);
dataSize += sizeof(tess.texCoords[0][0]) * 2;
dataSize *= SHADER_MAX_VERTEXES;
@ -603,15 +669,19 @@ void R_InitVBOs(void)
ri.Free(data);
tess.vbo->ofs_xyz = 0;
tess.vbo->ofs_normal = tess.vbo->ofs_xyz + sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES;
tess.vbo->ofs_normal = tess.vbo->ofs_xyz + sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES;
tess.vbo->ofs_tangent = tess.vbo->ofs_normal + sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES;
tess.vbo->ofs_bitangent = tess.vbo->ofs_tangent + sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES;
// these next two are actually interleaved
tess.vbo->ofs_st = tess.vbo->ofs_normal + sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES;
tess.vbo->ofs_lightmap = tess.vbo->ofs_st + sizeof(tess.texCoords[0][0]);
tess.vbo->ofs_st = tess.vbo->ofs_bitangent + sizeof(tess.bitangent[0]) * SHADER_MAX_VERTEXES;
tess.vbo->ofs_lightmap = tess.vbo->ofs_st + sizeof(tess.texCoords[0][0]);
tess.vbo->ofs_vertexcolor = tess.vbo->ofs_st + sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES;
tess.vbo->ofs_vertexcolor = tess.vbo->ofs_st + sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES;
tess.vbo->stride_xyz = sizeof(tess.xyz[0]);
tess.vbo->stride_normal = sizeof(tess.normal[0]);
tess.vbo->stride_tangent = sizeof(tess.tangent[0]);
tess.vbo->stride_bitangent = sizeof(tess.bitangent[0]);
tess.vbo->stride_vertexcolor = sizeof(tess.vertexColors[0]);
tess.vbo->stride_st = sizeof(tess.texCoords[0][0]) * 2;
tess.vbo->stride_lightmap = sizeof(tess.texCoords[0][0]) * 2;
@ -760,6 +830,16 @@ void RB_UpdateVBOs(unsigned int attribBits)
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal);
}
if(attribBits & ATTR_TANGENT)
{
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent);
}
if(attribBits & ATTR_BITANGENT)
{
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]), tess.bitangent);
}
if(attribBits & ATTR_COLOR)
{
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors);
@ -770,6 +850,8 @@ void RB_UpdateVBOs(unsigned int attribBits)
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]), tess.bitangent);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors);
}