diff --git a/reaction/code/renderer/tr_backend.c b/reaction/code/renderer/tr_backend.c index 1d3bf0b2..aaa335d5 100644 --- a/reaction/code/renderer/tr_backend.c +++ b/reaction/code/renderer/tr_backend.c @@ -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 ) { } + diff --git a/reaction/code/renderer/tr_bsp.c b/reaction/code/renderer/tr_bsp.c index 419200aa..b0110286 100644 --- a/reaction/code/renderer/tr_bsp.c +++ b/reaction/code/renderer/tr_bsp.c @@ -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 ); } + diff --git a/reaction/code/renderer/tr_curve.c b/reaction/code/renderer/tr_curve.c index 3b61424a..784beb5f 100644 --- a/reaction/code/renderer/tr_curve.c +++ b/reaction/code/renderer/tr_curve.c @@ -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); } diff --git a/reaction/code/renderer/tr_extramath.c b/reaction/code/renderer/tr_extramath.c index b1a1b47a..6e3f1afa 100644 --- a/reaction/code/renderer/tr_extramath.c +++ b/reaction/code/renderer/tr_extramath.c @@ -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; -} \ No newline at end of file +} diff --git a/reaction/code/renderer/tr_flares.c b/reaction/code/renderer/tr_flares.c index 030d150f..aa556b0a 100644 --- a/reaction/code/renderer/tr_flares.c +++ b/reaction/code/renderer/tr_flares.c @@ -527,3 +527,4 @@ void RB_RenderFlares (void) { GL_SetModelviewMatrix(oldmodelview); } + diff --git a/reaction/code/renderer/tr_glsl.c b/reaction/code/renderer/tr_glsl.c index c4a336c7..16dd2239 100644 --- a/reaction/code/renderer/tr_glsl.c +++ b/reaction/code/renderer/tr_glsl.c @@ -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 diff --git a/reaction/code/renderer/tr_image.c b/reaction/code/renderer/tr_image.c index 5d79f826..27359872 100644 --- a/reaction/code/renderer/tr_image.c +++ b/reaction/code/renderer/tr_image.c @@ -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= 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; diff --git a/reaction/code/renderer/tr_local.h b/reaction/code/renderer/tr_local.h index d3031ea1..9df6e94d 100644 --- a/reaction/code/renderer/tr_local.h +++ b/reaction/code/renderer/tr_local.h @@ -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); diff --git a/reaction/code/renderer/tr_main.c b/reaction/code/renderer/tr_main.c index c0380420..f2af6ca7 100644 --- a/reaction/code/renderer/tr_main.c +++ b/reaction/code/renderer/tr_main.c @@ -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) { + diff --git a/reaction/code/renderer/tr_marks.c b/reaction/code/renderer/tr_marks.c index de1b1c68..b74e0722 100644 --- a/reaction/code/renderer/tr_marks.c +++ b/reaction/code/renderer/tr_marks.c @@ -456,3 +456,4 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio return returnedFragments; } + diff --git a/reaction/code/renderer/tr_mesh.c b/reaction/code/renderer/tr_mesh.c index 047de981..3d5e37e0 100644 --- a/reaction/code/renderer/tr_mesh.c +++ b/reaction/code/renderer/tr_mesh.c @@ -431,3 +431,4 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) { } + diff --git a/reaction/code/renderer/tr_model.c b/reaction/code/renderer/tr_model.c index 10fb911d..72c23c05 100644 --- a/reaction/code/renderer/tr_model.c +++ b/reaction/code/renderer/tr_model.c @@ -1309,3 +1309,4 @@ void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) { VectorCopy( frame->bounds[1], maxs ); } + diff --git a/reaction/code/renderer/tr_shade.c b/reaction/code/renderer/tr_shade.c index 002f87f9..295529d9 100644 --- a/reaction/code/renderer/tr_shade.c +++ b/reaction/code/renderer/tr_shade.c @@ -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" ); } + diff --git a/reaction/code/renderer/tr_shade_calc.c b/reaction/code/renderer/tr_shade_calc.c index 6a047d11..984556d8 100644 --- a/reaction/code/renderer/tr_shade_calc.c +++ b/reaction/code/renderer/tr_shade_calc.c @@ -1334,3 +1334,4 @@ void RB_CalcDiffuseColor( unsigned char *colors ) RB_CalcDiffuseColor_scalar( colors ); } + diff --git a/reaction/code/renderer/tr_shader.c b/reaction/code/renderer/tr_shader.c index 6af592c4..6476a303 100644 --- a/reaction/code/renderer/tr_shader.c +++ b/reaction/code/renderer/tr_shader.c @@ -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 + // + 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) { diff --git a/reaction/code/renderer/tr_sky.c b/reaction/code/renderer/tr_sky.c index 43899362..c76d3c88 100644 --- a/reaction/code/renderer/tr_sky.c +++ b/reaction/code/renderer/tr_sky.c @@ -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; } + diff --git a/reaction/code/renderer/tr_surface.c b/reaction/code/renderer/tr_surface.c index b8ad5a86..e17d48af 100644 --- a/reaction/code/renderer/tr_surface.c +++ b/reaction/code/renderer/tr_surface.c @@ -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; diff --git a/reaction/code/renderer/tr_vbo.c b/reaction/code/renderer/tr_vbo.c index a4b0d2be..b485df83 100644 --- a/reaction/code/renderer/tr_vbo.c +++ b/reaction/code/renderer/tr_vbo.c @@ -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); }