From f385aa2807c045fd9ca117fb3fc1f3516fbd7c0e Mon Sep 17 00:00:00 2001 From: Richard Allen Date: Wed, 20 Jul 2011 19:17:44 +0000 Subject: [PATCH] vbos-glsl patch version 18 --- reaction/code/renderer/qgl.h | 33 + reaction/code/renderer/tr_bsp.c | 350 ++++---- reaction/code/renderer/tr_glsl.c | 1221 +++++++++++++++------------- reaction/code/renderer/tr_image.c | 327 +++++++- reaction/code/renderer/tr_init.c | 60 +- reaction/code/renderer/tr_local.h | 21 +- reaction/code/renderer/tr_main.c | 12 +- reaction/code/renderer/tr_scene.c | 2 +- reaction/code/renderer/tr_shade.c | 284 +++++-- reaction/code/renderer/tr_shader.c | 82 +- reaction/code/sdl/sdl_glimp.c | 36 + 11 files changed, 1552 insertions(+), 876 deletions(-) diff --git a/reaction/code/renderer/qgl.h b/reaction/code/renderer/qgl.h index 21a65ac1..a8717e08 100644 --- a/reaction/code/renderer/qgl.h +++ b/reaction/code/renderer/qgl.h @@ -120,6 +120,39 @@ ADD_ALL_EXTENSION_FUNCTIONS #undef HANDLE_EXT_FUNC +// GL_ARB_texture_compression +extern void (APIENTRY * qglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, + GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +extern void (APIENTRY * qglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, + GLint border, GLsizei imageSize, const GLvoid *data); +extern void (APIENTRY * qglCompressedTexImage1DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, + GLsizei imageSize, const GLvoid *data); +extern void (APIENTRY * qglCompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +extern void (APIENTRY * qglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, + GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +extern void (APIENTRY * qglCompressedTexSubImage1DARB)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, + GLsizei imageSize, const GLvoid *data); +extern void (APIENTRY * qglGetCompressedTexImageARB)(GLenum target, GLint lod, + GLvoid *img); + +// GL_NVX_gpu_memory_info +#ifndef GL_NVX_gpu_memory_info +#define GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 +#define GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 +#define GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 +#define GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A +#define GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B +#endif + +// GL_ATI_meminfo +#ifndef GL_ATI_meminfo +#define VBO_FREE_MEMORY_ATI 0x87FB +#define TEXTURE_FREE_MEMORY_ATI 0x87FC +#define RENDERBUFFER_FREE_MEMORY_ATI 0x87FD +#endif + + #if defined(WIN32) // WGL_ARB_create_context #ifndef WGL_ARB_create_context diff --git a/reaction/code/renderer/tr_bsp.c b/reaction/code/renderer/tr_bsp.c index 618b3bfc..ebf3c7fb 100644 --- a/reaction/code/renderer/tr_bsp.c +++ b/reaction/code/renderer/tr_bsp.c @@ -40,7 +40,7 @@ int c_subdivisions; int c_gridVerts; //=============================================================================== -#if 1 + static void HSVtoRGB( float h, float s, float v, float rgb[3] ) { int i; @@ -168,14 +168,19 @@ R_LoadLightmaps */ #define LIGHTMAP_SIZE 128 static void R_LoadLightmaps( lump_t *l ) { -#if 0 byte *buf, *buf_p; int len; byte image[LIGHTMAP_SIZE*LIGHTMAP_SIZE*4]; - int i, j; + int i, j, numLightmaps; float maxIntensity = 0; double sumIntensity = 0; + if (r_mergeLightmaps->integer) + { + tr.fatLightmapSize = 4096; + tr.fatLightmapStep = 32; + } + len = l->filelen; if ( !len ) { return; @@ -185,96 +190,9 @@ static void R_LoadLightmaps( lump_t *l ) { // we are about to upload textures R_SyncRenderThread(); - // create all the lightmaps - tr.numLightmaps = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3); - if ( tr.numLightmaps == 1 ) { - //FIXME: HACK: maps with only one lightmap turn up fullbright for some reason. - //this avoids this, but isn't the correct solution. - tr.numLightmaps++; - } - - // if we are in r_vertexLight mode, we don't need the lightmaps at all - if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) { - return; - } - - tr.lightmaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low ); - for ( i = 0 ; i < tr.numLightmaps ; i++ ) { - // expand the 24 bit on-disk to 32 bit - buf_p = buf + i * LIGHTMAP_SIZE*LIGHTMAP_SIZE * 3; - - if ( r_lightmap->integer == 2 ) - { // color code by intensity as development tool (FIXME: check range) - for ( j = 0; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) - { - float r = buf_p[j*3+0]; - float g = buf_p[j*3+1]; - float b = buf_p[j*3+2]; - float intensity; - float out[3] = {0.0, 0.0, 0.0}; - - intensity = 0.33f * r + 0.685f * g + 0.063f * b; - - if ( intensity > 255 ) - intensity = 1.0f; - else - intensity /= 255.0f; - - if ( intensity > maxIntensity ) - maxIntensity = intensity; - - HSVtoRGB( intensity, 1.00, 0.50, out ); - - image[j*4+0] = out[0] * 255; - image[j*4+1] = out[1] * 255; - image[j*4+2] = out[2] * 255; - image[j*4+3] = 255; - - sumIntensity += intensity; - } - } else { - for ( j = 0 ; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) { - R_ColorShiftLightingBytes( &buf_p[j*3], &image[j*4] ); - image[j*4+3] = 255; - } - } - tr.lightmaps[i] = R_CreateImage( va("*lightmap%d",i), image, - LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, GL_CLAMP_TO_EDGE ); - } - - if ( r_lightmap->integer == 2 ) { - ri.Printf( PRINT_ALL, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) ); - } -#else - int len; - int numLightmaps; - int i; - byte *buf, *buf_p; - - //int BIGSIZE=2048; - //int BIGNUM=16; - - byte *fatbuffer; - byte *fatbuffer2; - int xoff, yoff, x, y; - //float scale = 0.9f; - - tr.fatLightmapSize = 4096; - tr.fatLightmapStep = 32; - - len = l->filelen; - if(!len) - { - return; - } - buf = fileBase + l->fileofs; - - // we are about to upload textures - R_SyncRenderThread(); - // create all the lightmaps numLightmaps = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3); - + if (tr.worldDeluxeMapping) { numLightmaps >>= 1; @@ -286,7 +204,7 @@ static void R_LoadLightmaps( lump_t *l ) { //this avoids this, but isn't the correct solution. numLightmaps++; } - else if(numLightmaps >= tr.fatLightmapStep * tr.fatLightmapStep ) + else if (r_mergeLightmaps->integer && numLightmaps >= tr.fatLightmapStep * tr.fatLightmapStep ) { // FIXME: fat light maps don't support more than 1024 light maps ri.Printf(PRINT_WARNING, "WARNING: number of lightmaps > %d\n", tr.fatLightmapStep * tr.fatLightmapStep); @@ -294,34 +212,50 @@ static void R_LoadLightmaps( lump_t *l ) { } // use a fat lightmap of an appropriate size - if(numLightmaps < 65) + + if (r_mergeLightmaps->integer) { - tr.fatLightmapSize = 1024; - tr.fatLightmapStep = 8; + if(numLightmaps < 65) + { + tr.fatLightmapSize = 1024; + tr.fatLightmapStep = 8; + } + else if(numLightmaps < 256) + { + tr.fatLightmapSize = 2048; + tr.fatLightmapStep = 16; + } + + // allocate one fat lightmap + tr.numLightmaps = 1; } - else if(numLightmaps < 256) + else { - tr.fatLightmapSize = 2048; - tr.fatLightmapStep = 16; + tr.numLightmaps = numLightmaps; } - // allocate one fat lightmap - tr.numLightmaps = 1; tr.lightmaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low ); - // 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) + if (tr.worldDeluxeMapping || r_deluxeMapping->integer == 2) { 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); + } + + if (r_mergeLightmaps->integer) + { + tr.fatLightmap = R_CreateImage(va("_fatlightmap%d", 0), NULL, tr.fatLightmapSize, tr.fatLightmapSize, qfalse, qfalse, GL_CLAMP_TO_EDGE ); + tr.lightmaps[0] = tr.fatLightmap; + + if (tr.worldDeluxeMapping || r_deluxeMapping->integer == 2) + { + tr.fatDeluxemap = R_CreateImage(va("_fatdeluxemap%d", 0), NULL, tr.fatLightmapSize, tr.fatLightmapSize, qfalse, qfalse, GL_CLAMP_TO_EDGE ); + tr.deluxemaps[0] = tr.fatDeluxemap; + } } for(i = 0; i < numLightmaps; i++) { + int xoff = 0, yoff = 0; // expand the 24 bit on-disk to 32 bit if (tr.worldDeluxeMapping) @@ -333,25 +267,57 @@ static void R_LoadLightmaps( lump_t *l ) { buf_p = buf + i * LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3; } - - xoff = i % tr.fatLightmapStep; - yoff = i / tr.fatLightmapStep; + if (r_mergeLightmaps->integer) + { + xoff = (i % tr.fatLightmapStep) * LIGHTMAP_SIZE; + yoff = (i / tr.fatLightmapStep) * LIGHTMAP_SIZE; + } // if (tr.worldLightmapping) { - for(y = 0; y < LIGHTMAP_SIZE; y++) - { - for(x = 0; x < LIGHTMAP_SIZE; x++) + if ( r_lightmap->integer == 2 ) + { // color code by intensity as development tool (FIXME: check range) + for ( j = 0; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) { - int index = - (x + (y * tr.fatLightmapSize)) + ((xoff * LIGHTMAP_SIZE) + (yoff * tr.fatLightmapSize * LIGHTMAP_SIZE)); - fatbuffer[(index * 4) + 0] = buf_p[((x + (y * LIGHTMAP_SIZE)) * 3) + 0]; - fatbuffer[(index * 4) + 1] = buf_p[((x + (y * LIGHTMAP_SIZE)) * 3) + 1]; - fatbuffer[(index * 4) + 2] = buf_p[((x + (y * LIGHTMAP_SIZE)) * 3) + 2]; - fatbuffer[(index * 4) + 3] = 255; + float r = buf_p[j*3+0]; + float g = buf_p[j*3+1]; + float b = buf_p[j*3+2]; + float intensity; + float out[3] = {0.0, 0.0, 0.0}; - R_ColorShiftLightingBytes(&fatbuffer[(index * 4) + 0], &fatbuffer[(index * 4) + 0]); + intensity = 0.33f * r + 0.685f * g + 0.063f * b; + + if ( intensity > 255 ) + intensity = 1.0f; + else + intensity /= 255.0f; + + if ( intensity > maxIntensity ) + maxIntensity = intensity; + + HSVtoRGB( intensity, 1.00, 0.50, out ); + + image[j*4+0] = out[0] * 255; + image[j*4+1] = out[1] * 255; + image[j*4+2] = out[2] * 255; + image[j*4+3] = 255; + + sumIntensity += intensity; } + } else { + for ( j = 0 ; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) { + R_ColorShiftLightingBytes( &buf_p[j*3], &image[j*4] ); + image[j*4+3] = 255; + } + } + + if (r_mergeLightmaps->integer) + { + R_UpdateSubImage(tr.fatLightmap, image, xoff, yoff, LIGHTMAP_SIZE, LIGHTMAP_SIZE); + } + else + { + tr.lightmaps[i] = R_CreateImage( va("*lightmap%d",i), image, LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, GL_CLAMP_TO_EDGE ); } } @@ -359,34 +325,120 @@ static void R_LoadLightmaps( lump_t *l ) { { buf_p = buf + (i * 2 + 1) * LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3; - for(y = 0; y < LIGHTMAP_SIZE; y++) + for ( j = 0 ; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) { + image[j*4+0] = buf_p[j*3+0]; + image[j*4+1] = buf_p[j*3+1]; + image[j*4+2] = buf_p[j*3+2]; + image[j*4+3] = 255; + } + + if (r_mergeLightmaps->integer) { - 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; - } + R_UpdateSubImage(tr.fatDeluxemap, image, xoff, yoff, LIGHTMAP_SIZE, LIGHTMAP_SIZE); + } + else + { + tr.deluxemaps[i] = R_CreateImage( va("*deluxemap%d",i), image, LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, GL_CLAMP_TO_EDGE ); } } + else if ( r_deluxeMapping->integer == 2 ) + { + // approximate a deluxe map using magic. + for ( j = 0 ; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) { + int x, y, dx, dy, dz, count, value; + + x = j % LIGHTMAP_SIZE; + y = j / LIGHTMAP_SIZE; + + value = buf_p[j*3+0] + buf_p[j*3+1] + buf_p[j*3+2]; + + dx = 0; + count = 0; + if (x > 0) + { + int k = j - 1; + + dx += value - buf_p[k*3+0] + buf_p[k*3+1] + buf_p[k*3+2]; + count++; + } + + if (x < LIGHTMAP_SIZE - 1) + { + int k = j + 1; + + dx += buf_p[k*3+0] + buf_p[k*3+1] + buf_p[k*3+2] - value; + count++; + } + + if (count) + { + dx /= count; + } + + dy = 0; + count = 0; + if (y > 0) + { + int k = j - LIGHTMAP_SIZE; + + dy += value - (buf_p[k*3+0] + buf_p[k*3+1] + buf_p[k*3+2]); + count++; + } + + if (y < LIGHTMAP_SIZE - 1) + { + int k = j + LIGHTMAP_SIZE; + + dy += buf_p[k*3+0] + buf_p[k*3+1] + buf_p[k*3+2] - value; + count++; + } + + if (count) + { + dy /= count; + } + + dx /= 3; + dy /= 3; + + if (dx < -255) + dx = -255; + + if (dx > 255) + dx = 255; + + if (dy < -255) + dy = -255; + + if (dy > 255) + dy = 255; + + dz = sqrt(255*255 - dx*dx - dy*dy); + + dx = dx / 2 + 127; + dy = dy / 2 + 127; + dz = dz / 2 + 127; + + image[j*4+0] = dx; + image[j*4+1] = dy; + image[j*4+2] = dz; + image[j*4+3] = 255; + } + + if (r_mergeLightmaps->integer) + { + R_UpdateSubImage(tr.fatDeluxemap, image, xoff, yoff, LIGHTMAP_SIZE, LIGHTMAP_SIZE); + } + else + { + tr.deluxemaps[i] = R_CreateImage( va("*deluxemap%d",i), image, LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, GL_CLAMP_TO_EDGE ); + } + } + } + + if ( r_lightmap->integer == 2 ) { + ri.Printf( PRINT_ALL, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) ); } - - 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 } @@ -417,13 +469,16 @@ static float FatPackV(float input, int lightmapnum) static int FatLightmap(int lightmapnum) { + if (lightmapnum < 0) + return lightmapnum; + if (tr.fatLightmapSize > 0) { - if (lightmapnum < 0) - return lightmapnum; - return 0; } + + if (tr.worldDeluxeMapping) + return lightmapnum >> 1; return lightmapnum; } @@ -909,7 +964,6 @@ static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, i } #endif } -#endif #if 1 /* diff --git a/reaction/code/renderer/tr_glsl.c b/reaction/code/renderer/tr_glsl.c index 3c2bfad2..b7d77504 100644 --- a/reaction/code/renderer/tr_glsl.c +++ b/reaction/code/renderer/tr_glsl.c @@ -25,7 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA void GLSL_BindNullProgram(void); // FIXME: Do something that isn't this messy -static const char *fallbackGenericShader_vp = +static const char *fallbackGenericShader_vp = "attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\nattribut" "e vec4 attr_TexCoord1;\r\nattribute vec3 attr_Normal;\r\nattribute vec4 att" "r_Color;\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nattribute vec4 attr_Po" @@ -34,101 +34,95 @@ static const char *fallbackGenericShader_vp = "GEN)\r\nuniform int u_TCGen0;\r\nuniform vec3 u_TCGen0Vector0;\r\nunif" "orm vec3 u_TCGen0Vector1;\r\n#endif\r\n\r\n#if defined(USE_FOG)\r\nunifor" "m vec4 u_FogDistance;\r\nuniform vec4 u_FogDepth;\r\nuniform float u_F" -"ogEyeT;\r\nuniform int u_FogAdjustColors;\r\n#endif\r\n\r\n#if defined(U" -"SE_DEFORM_VERTEXES)\r\nuniform int u_DeformGen;\r\nuniform float u_Defo" -"rmParams[5];\r\n#endif\r\n\r\nuniform float u_Time;\r\n\r\nuniform mat4 " -"u_ModelViewProjectionMatrix;\r\nuniform vec4 u_Color;\r\n\r\n#if defined(" -"USE_RGBAGEN)\r\nuniform int u_ColorGen;\r\nuniform int u_AlphaGen;\r" -"\nuniform vec3 u_AmbientLight;\r\nuniform vec3 u_DirectedLight;\r\nunif" -"orm vec4 u_LightOrigin;\r\nuniform float u_PortalRange;\r\n#endif\r\n\r" -"\n#if defined(USE_VERTEX_ANIMATION)\r\nuniform float u_VertexLerp;\r\n#end" -"if\r\n\r\nvarying vec2 var_DiffuseTex;\r\nvarying vec2 var_LightTex;\r" -"\nvarying vec4 var_Color;\r\n\r\nvec2 DoTexMatrix(vec2 st, vec3 position," -" mat4 texMatrix)\r\n{\r\n\tfloat amplitude = texMatrix[3][0];\r\n\tfloat ph" -"ase = texMatrix[3][1];\r\n\tvec2 st2 = (texMatrix * vec4(st, 1.0, 0.0)).st;" -"\r\n\r\n\tvec3 offsetPos = position.xyz / 1024.0;\r\n\toffsetPos.x += offse" -"tPos.z;\r\n\r\n\tvec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * " -"M_PI);\r\n\t\r\n\treturn st2 + texOffset * amplitude;\r\n}\r\n\r\n#if defin" -"ed(USE_DEFORM_VERTEXES)\r\nfloat triangle(float x)\r\n{\r\n\treturn max(1.0" -" - abs(x), 0);\r\n}\r\n\r\nfloat sawtooth(float x)\r\n{\r\n\treturn x - flo" -"or(x);\r\n}\r\n\r\nvec4 DeformPosition(const vec4 pos, const vec3 normal, c" -"onst vec2 st)\r\n{\r\n\tfloat base = u_DeformParams[0];\r\n\tfloat amp" -"litude = u_DeformParams[1];\r\n\tfloat phase = u_DeformParams[2];\r\n\t" -"float frequency = u_DeformParams[3];\r\n\tfloat spread = u_DeformParams[" -"4];\r\n\t\r\n\tif (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase *= M_PI *" -" 0.25 * st.x;\r\n\t}\r\n\telse // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWT" -"OOTH)\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * spread;\r\n\t}\r\n\r" -"\n\tfloat value = phase + (u_Time * frequency);\r\n\tfloat func;\r\n\r\n\ti" -"f (u_DeformGen == DGEN_WAVE_SIN)\r\n\t{\r\n\t\tfunc = sin(value * 2.0 * M_P" -"I);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SQUARE)\r\n\t{\r\n\t\tfun" -"c = sign(sin(value * 2.0 * M_PI));\r\n\t}\r\n\telse if (u_DeformGen == DGEN" -"_WAVE_TRIANGLE)\r\n\t{\r\n\t\tfunc = triangle(value);\r\n\t}\r\n\telse if (" -"u_DeformGen == DGEN_WAVE_SAWTOOTH)\r\n\t{\r\n\t\tfunc = sawtooth(value);\r" -"\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_INVERSE_SAWTOOTH)\r\n\t{\r\n\t" -"\tfunc = (1.0 - sawtooth(value));\r\n\t}\r\n\telse if (u_DeformGen == DGEN_" -"BULGE)\r\n\t{\r\n\t\tfunc = sin(value);\r\n\t}\r\n\t\r\n\tvec4 deformed = p" -"os;\r\n\tdeformed.xyz += normal * (base + func * amplitude);\r\n\r\n\tretur" -"n deformed;\r\n}\r\n#endif\r\n\r\n#if defined(USE_TCGEN)\r\nvec2 GenTexCoor" -"ds(int TCGen, vec4 position, vec3 normal, vec3 TCGenVector0, vec3 TCGenVect" -"or1)\r\n{\r\n\tvec2 tex = attr_TexCoord0.st;\r\n\r\n\tif (TCGen == TCGEN_LI" -"GHTMAP)\r\n\t{\r\n\t\ttex = attr_TexCoord1.st;\r\n\t}\r\n\telse if (TCGen =" -"= TCGEN_ENVIRONMENT_MAPPED)\r\n\t{\r\n\t\tvec3 viewer = normalize(u_ViewOri" -"gin - position.xyz);\r\n\t\tvec3 reflected = normal * 2.0 * dot(normal, vie" -"wer) - viewer;\r\n\r\n\t\ttex.s = 0.5 + reflected.y * 0.5;\r\n\t\ttex.t = 0" -".5 - reflected.z * 0.5;\r\n\t}\r\n\telse if (TCGen == TCGEN_VECTOR)\r\n\t{" -"\r\n\t\ttex.s = dot(position.xyz, TCGenVector0);\r\n\t\ttex.t = dot(positio" -"n.xyz, TCGenVector1);\r\n\t}\r\n\t\r\n\treturn tex;\r\n}\r\n#endif\r\n\r\nv" -"oid main()\r\n{\r\n#if defined(USE_VERTEX_ANIMATION)\r\n\tvec4 position = m" -"ix(attr_Position, attr_Position2, u_VertexLerp);\r\n\tvec3 normal = normali" -"ze(mix(attr_Normal, attr_Normal2, u_VertexLerp));\r\n#else\r\n\tvec4 positi" -"on = attr_Position;\r\n\tvec3 normal = attr_Normal;\r\n#endif\r\n\r\n#if de" -"fined(USE_DEFORM_VERTEXES)\r\n\tposition = DeformPosition(position, normal," -" attr_TexCoord0.st);\r\n#endif\r\n\r\n\tgl_Position = u_ModelViewProjection" -"Matrix * position;\r\n\r\n#if defined(USE_TCGEN)\r\n\tvec2 tex = GenTexCoor" -"ds(u_TCGen0, position, normal, u_TCGen0Vector0, u_TCGen0Vector1);\r\n#else" -"\r\n\tvec2 tex = attr_TexCoord0.st;\r\n#endif\r\n\tvar_DiffuseTex = DoTexMa" -"trix(tex, position.xyz, u_DiffuseTexMatrix);\r\n\r\n\tvar_LightTex = attr_T" -"exCoord1.st;\r\n\t\r\n\tvar_Color = u_Color;\r\n\r\n#if defined(USE_RGBAGEN" -")\r\n\tif (u_ColorGen == CGEN_LIGHTING_DIFFUSE)\r\n\t{\r\n\t\tfloat incomin" -"g = max(dot(normal, u_LightOrigin.xyz), 0.0);\r\n\r\n\t\tvar_Color.rgb = mi" -"n(u_DirectedLight * incoming + u_AmbientLight, 1.0);\r\n\t}\r\n\telse if (u" -"_ColorGen == CGEN_EXACT_VERTEX)\r\n\t{\r\n\t\tvar_Color.rgb = attr_Color.rg" -"b;\r\n\t}\r\n\telse if (u_ColorGen == CGEN_VERTEX)\r\n\t{\r\n\t\tvar_Color." -"rgb *= attr_Color.rgb;\r\n\t}\r\n\telse if (u_ColorGen == CGEN_ONE_MINUS_VE" -"RTEX)\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\t\tvec3 lightD" -"ir = normalize(vec3(-960.0, -1980.0, 96.0) - position.xyz);\r\n\t\tvec3 vie" -"wer = normalize(u_ViewOrigin - position.xyz);\r\n\t\tvec3 halfangle = norma" -"lize(lightDir + viewer);\r\n\t\t\r\n\t\tvar_Color.a = pow(max(dot(normal, h" -"alfangle), 0.0), 8.0);\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 == A" -"GEN_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 = leng" -"th(position.xyz - u_ViewOrigin) / u_PortalRange;\r\n\r\n\t\tvar_Color.a = m" -"in(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#endif\r\n\r\n#if defined (USE_F" -"OG)\r\n\tfloat s = dot(position.xyz, u_FogDistance.xyz) + u_FogDistance.w;" -"\r\n\tfloat t = dot(position.xyz, u_FogDepth.xyz) + u_FogDepth.w;\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\telse\r\n\t{\r\n\t\ts *= max(t + sign(u_FogEyeT), 0.0);\r\n\t}\r\n\t\r\n" -"\ts = 1.0 - sqrt(clamp(s * 8.0, 0.0, 1.0));\r\n\r\n\tif (u_FogAdjustColors " -"== ACFF_MODULATE_RGB)\r\n\t{\r\n\t\tvar_Color.rgb *= s;\r\n\t}\r\n\telse if" -" (u_FogAdjustColors == ACFF_MODULATE_ALPHA)\r\n\t{\r\n\t\tvar_Color.a *= s;" -"\r\n\t}\r\n\telse if (u_FogAdjustColors == ACFF_MODULATE_RGBA)\r\n\t{\r\n\t" -"\tvar_Color *= s;\r\n\t}\r\n#endif\r\n}\r\n"; +"ogEyeT;\r\nuniform vec4 u_FogColorMask;\r\n#endif\r\n\r\n#if defined(USE_" +"DEFORM_VERTEXES)\r\nuniform int u_DeformGen;\r\nuniform float u_DeformP" +"arams[5];\r\n#endif\r\n\r\nuniform float u_Time;\r\n\r\nuniform mat4 u_M" +"odelViewProjectionMatrix;\r\nuniform vec4 u_BaseColor;\r\nuniform vec4 " +"u_VertColor;\r\n\r\n#if defined(USE_RGBAGEN)\r\nuniform int u_ColorGen;" +"\r\nuniform int u_AlphaGen;\r\nuniform vec3 u_AmbientLight;\r\nuniform" +" vec3 u_DirectedLight;\r\nuniform vec4 u_LightOrigin;\r\nuniform float " +" u_PortalRange;\r\n#endif\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nunifo" +"rm float u_VertexLerp;\r\n#endif\r\n\r\nvarying vec2 var_DiffuseTex;\r\n" +"#if defined(USE_LIGHTMAP)\r\nvarying vec2 var_LightTex;\r\n#endif\r\nvary" +"ing vec4 var_Color;\r\n\r\nvec2 DoTexMatrix(vec2 st, vec3 position, mat4 " +"texMatrix)\r\n{\r\n\tfloat amplitude = texMatrix[3][0];\r\n\tfloat phase = " +"texMatrix[3][1];\r\n\tvec2 st2 = (texMatrix * vec4(st, 1.0, 0.0)).st;\r\n\r" +"\n\tvec3 offsetPos = position.xyz / 1024.0;\r\n\toffsetPos.x += offsetPos.z" +";\r\n\r\n\tvec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * M_PI);" +"\r\n\t\r\n\treturn st2 + texOffset * amplitude;\r\n}\r\n\r\n#if defined(USE" +"_DEFORM_VERTEXES)\r\nfloat triangle(float x)\r\n{\r\n\treturn max(1.0 - abs" +"(x), 0);\r\n}\r\n\r\nfloat sawtooth(float x)\r\n{\r\n\treturn x - floor(x);" +"\r\n}\r\n\r\nvec4 DeformPosition(const vec4 pos, const vec3 normal, const v" +"ec2 st)\r\n{\r\n\tfloat base = u_DeformParams[0];\r\n\tfloat amplitude" +" = u_DeformParams[1];\r\n\tfloat phase = u_DeformParams[2];\r\n\tfloat " +"frequency = u_DeformParams[3];\r\n\tfloat spread = u_DeformParams[4];\r" +"\n\t\r\n\tif (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase *= M_PI * 0.25" +" * st.x;\r\n\t}\r\n\telse // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)" +"\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * spread;\r\n\t}\r\n\r\n\tf" +"loat value = phase + (u_Time * frequency);\r\n\tfloat func;\r\n\r\n\tif (u_" +"DeformGen == DGEN_WAVE_SIN)\r\n\t{\r\n\t\tfunc = sin(value * 2.0 * M_PI);\r" +"\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SQUARE)\r\n\t{\r\n\t\tfunc = s" +"ign(sin(value * 2.0 * M_PI));\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE" +"_TRIANGLE)\r\n\t{\r\n\t\tfunc = triangle(value);\r\n\t}\r\n\telse if (u_Def" +"ormGen == DGEN_WAVE_SAWTOOTH)\r\n\t{\r\n\t\tfunc = sawtooth(value);\r\n\t}" +"\r\n\telse if (u_DeformGen == DGEN_WAVE_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tfun" +"c = (1.0 - sawtooth(value));\r\n\t}\r\n\telse if (u_DeformGen == DGEN_BULGE" +")\r\n\t{\r\n\t\tfunc = sin(value);\r\n\t}\r\n\t\r\n\tvec4 deformed = pos;\r" +"\n\tdeformed.xyz += normal * (base + func * amplitude);\r\n\r\n\treturn def" +"ormed;\r\n}\r\n#endif\r\n\r\n#if defined(USE_TCGEN)\r\nvec2 GenTexCoords(in" +"t TCGen, vec4 position, vec3 normal, vec3 TCGenVector0, vec3 TCGenVector1)" +"\r\n{\r\n\tvec2 tex = attr_TexCoord0.st;\r\n\r\n\tif (TCGen == TCGEN_LIGHTM" +"AP)\r\n\t{\r\n\t\ttex = attr_TexCoord1.st;\r\n\t}\r\n\telse if (TCGen == TC" +"GEN_ENVIRONMENT_MAPPED)\r\n\t{\r\n\t\tvec3 viewer = normalize(u_ViewOrigin " +"- position.xyz);\r\n\t\tvec3 reflected = normal * 2.0 * dot(normal, viewer)" +" - viewer;\r\n\r\n\t\ttex.s = 0.5 + reflected.y * 0.5;\r\n\t\ttex.t = 0.5 -" +" reflected.z * 0.5;\r\n\t}\r\n\telse if (TCGen == TCGEN_VECTOR)\r\n\t{\r\n" +"\t\ttex.s = dot(position.xyz, TCGenVector0);\r\n\t\ttex.t = dot(position.xy" +"z, TCGenVector1);\r\n\t}\r\n\t\r\n\treturn tex;\r\n}\r\n#endif\r\n\r\nvoid " +"main()\r\n{\r\n#if defined(USE_VERTEX_ANIMATION)\r\n\tvec4 position = mix(a" +"ttr_Position, attr_Position2, u_VertexLerp);\r\n\tvec3 normal = normalize(m" +"ix(attr_Normal, attr_Normal2, u_VertexLerp));\r\n#else\r\n\tvec4 position =" +" attr_Position;\r\n\tvec3 normal = attr_Normal;\r\n#endif\r\n\r\n#if define" +"d(USE_DEFORM_VERTEXES)\r\n\tposition = DeformPosition(position, normal, att" +"r_TexCoord0.st);\r\n#endif\r\n\r\n\tgl_Position = u_ModelViewProjectionMatr" +"ix * position;\r\n\r\n#if defined(USE_TCGEN)\r\n\tvec2 tex = GenTexCoords(u" +"_TCGen0, position, normal, u_TCGen0Vector0, u_TCGen0Vector1);\r\n#else\r\n" +"\tvec2 tex = attr_TexCoord0.st;\r\n#endif\r\n\tvar_DiffuseTex = DoTexMatrix" +"(tex, position.xyz, u_DiffuseTexMatrix);\r\n\r\n#if defined(USE_LIGHTMAP)\r" +"\n\tvar_LightTex = attr_TexCoord1.st;\r\n#endif\r\n\r\n\tvar_Color = u_Base" +"Color + u_VertColor * attr_Color;\r\n\r\n#if defined(USE_RGBAGEN)\r\n\tif (" +"u_ColorGen == CGEN_LIGHTING_DIFFUSE)\r\n\t{\r\n\t\tfloat incoming = max(dot" +"(normal, u_LightOrigin.xyz), 0.0);\r\n\r\n\t\tvar_Color.rgb = min(u_Directe" +"dLight * incoming + u_AmbientLight, 1.0);\r\n\t}\r\n\t\r\n\tvec3 toView = u" +"_ViewOrigin - position.xyz;\r\n\r\n\tif (u_AlphaGen == AGEN_LIGHTING_SPECUL" +"AR)\r\n\t{\r\n\t\tvec3 lightDir = normalize(vec3(-960.0, -1980.0, 96.0) - p" +"osition.xyz);\r\n\t\tvec3 viewer = normalize(toView);\r\n\t\tvec3 halfangle" +" = normalize(lightDir + viewer);\r\n\t\t\r\n\t\tvar_Color.a = pow(max(dot(n" +"ormal, halfangle), 0.0), 8.0);\r\n\t}\r\n\telse if (u_AlphaGen == AGEN_PORT" +"AL)\r\n\t{\r\n\t\tfloat alpha = length(toView) / u_PortalRange;\r\n\r\n\t\t" +"var_Color.a = min(alpha, 1.0);\r\n\t}\r\n\telse if (u_AlphaGen == AGEN_FRES" +"NEL)\r\n\t{\r\n\t\tvec3 viewer = normalize(toView);\r\n\t\t\r\n\t\tvar_Colo" +"r.a = 0.10 + 0.90 * pow(1.0 - dot(normal, viewer), 5);\r\n\t}\r\n#endif\r\n" +"\r\n#if defined (USE_FOG)\r\n\tfloat s = dot(position.xyz, u_FogDistance.xy" +"z) + u_FogDistance.w;\r\n\tfloat t = dot(position.xyz, u_FogDepth.xyz) + u_" +"FogDepth.w;\r\n\t\r\n\tif (t >= 1.0)\r\n\t{\r\n\t\ts *= t / (t - min(u_FogE" +"yeT, 0.0));\r\n\t}\r\n\telse\r\n\t{\r\n\t\ts *= max(t + sign(u_FogEyeT), 0." +"0);\r\n\t}\r\n\t\r\n\ts = 1.0 - sqrt(clamp(s * 8.0, 0.0, 1.0));\r\n\t\r\n\t" +"var_Color *= u_FogColorMask * s - (u_FogColorMask - vec4(1.0));\r\n#endif\r" +"\n}\r\n"; -static const char *fallbackGenericShader_fp = -"uniform sampler2D u_DiffuseMap;\r\nuniform sampler2D u_LightMap;\r\nuniform" -" int u_Texture1Env;\r\n\r\nvarying vec2 var_DiffuseTex;\r\nvaryi" -"ng vec2 var_LightTex;\r\nvarying vec4 var_Color;\r\n\r\n\r\nvoid " -"main()\r\n{\r\n\tvec4 color = texture2D(u_DiffuseMap, var_DiffuseTex);\r\n" -"\r\n#if defined(USE_LIGHTMAP)\r\n\tvec4 color2 = texture2D(u_LightMap, va" -"r_LightTex);\r\n\r\n\tif (u_Texture1Env == TEXENV_MODULATE)\r\n\t{\r\n\t\tc" -"olor *= color2;\r\n\t}\r\n\telse if (u_Texture1Env == TEXENV_ADD)\r\n\t{\r" -"\n\t\tcolor += color2;\r\n\t}\r\n\telse if (u_Texture1Env == TEXENV_REPLACE" -")\r\n\t{\r\n\t\tcolor = color2;\r\n\t}\r\n#endif\r\n\r\n\tgl_FragColor = co" -"lor * var_Color;\r\n}\r\n"; +static const char *fallbackGenericShader_fp = +"uniform sampler2D u_DiffuseMap;\r\n\r\n#if defined(USE_LIGHTMAP)\r\nuniform" +" sampler2D u_LightMap;\r\n#endif\r\n\r\nuniform int u_Texture1Env;\r" +"\n\r\nvarying vec2 var_DiffuseTex;\r\n\r\n#if defined(USE_LIGHTMAP)\r" +"\nvarying vec2 var_LightTex;\r\n#endif\r\n\r\nvarying vec4 var_Co" +"lor;\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = texture2D(u_DiffuseMap," +" var_DiffuseTex);\r\n\r\n#if defined(USE_LIGHTMAP)\r\n\tvec4 color2 = textu" +"re2D(u_LightMap, var_LightTex);\r\n\r\n\tif (u_Texture1Env == TEXENV_MODU" +"LATE)\r\n\t{\r\n\t\tcolor *= color2;\r\n\t}\r\n\telse if (u_Texture1Env == " +"TEXENV_ADD)\r\n\t{\r\n\t\tcolor += color2;\r\n\t}\r\n\telse if (u_Texture1E" +"nv == TEXENV_REPLACE)\r\n\t{\r\n\t\tcolor = color2;\r\n\t}\r\n#endif\r\n\r" +"\n\tgl_FragColor = color * var_Color;\r\n}\r\n"; static const char *fallbackTextureColorShader_vp = "#version 120\r\n\r\nattribute vec4 attr_Position;\r\nattribute vec4 attr_Te" @@ -149,46 +143,45 @@ static const char *fallbackFogPassShader_vp = "\r\nuniform vec4 u_FogDistance;\r\nuniform vec4 u_FogDepth;\r\nunifor" "m float u_FogEyeT;\r\n\r\n//#if defined(USE_DEFORM_VERTEXES)\r\nuniform i" "nt u_DeformGen;\r\nuniform float u_DeformParams[5];\r\n//#endif\r\n\r" -"\nuniform float u_Time;\r\nuniform vec4 u_Color;\r\nuniform mat4 u_" -"ModelViewProjectionMatrix;\r\n\r\n//#if defined(USE_VERTEX_ANIMATION)\r\nun" -"iform float u_VertexLerp;\r\n//#endif\r\n\r\nvarying vec4 var_Color;\r" -"\nvarying float var_Scale;\r\n\r\n\r\nfloat triangle(float x)\r\n{\r\n\tr" -"eturn max(1.0 - abs(x), 0);\r\n}\r\n\r\nfloat sawtooth(float x)\r\n{\r\n\tr" -"eturn x - floor(x);\r\n}\r\n\r\nvec4 DeformPosition(const vec4 pos, const v" -"ec3 normal, const vec2 st)\r\n{\r\n\tif (u_DeformGen == 0)\r\n\t{\r\n\t\tre" -"turn pos;\r\n\t}\r\n\r\n\tfloat base = u_DeformParams[0];\r\n\tfloat a" -"mplitude = u_DeformParams[1];\r\n\tfloat phase = u_DeformParams[2];\r\n" -"\tfloat frequency = u_DeformParams[3];\r\n\tfloat spread = u_DeformParam" -"s[4];\r\n\t\t\r\n\tif (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)\r\n\t{\r" -"\n\t\tphase += (pos.x + pos.y + pos.z) * spread;\r\n\t}\r\n\telse if (u_Def" -"ormGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase *= M_PI * 0.25 * st.x;\r\n\t}\r\n" -"\r\n\tfloat value = phase + (u_Time * frequency);\r\n\tfloat func;\r\n\r\n" -"\tif (u_DeformGen == DGEN_WAVE_SIN)\r\n\t{\r\n\t\tfunc = sin(value * 2.0 * " -"M_PI);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SQUARE)\r\n\t{\r\n\t\t" -"func = sign(sin(value * 2.0 * M_PI));\r\n\t}\r\n\telse if (u_DeformGen == D" -"GEN_WAVE_TRIANGLE)\r\n\t{\r\n\t\tfunc = triangle(value);\r\n\t}\r\n\telse i" -"f (u_DeformGen == DGEN_WAVE_SAWTOOTH)\r\n\t{\r\n\t\tfunc = sawtooth(value);" -"\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_INVERSE_SAWTOOTH)\r\n\t{\r\n" -"\t\tfunc = (1.0 - sawtooth(value));\r\n\t}\r\n\telse if (u_DeformGen == DGE" -"N_BULGE)\r\n\t{\r\n\t\tfunc = sin(value);\r\n\t}\r\n\r\n\tvec4 deformed = p" -"os;\r\n\tdeformed.xyz += normal * (base + func * amplitude);\r\n\r\n\tretur" -"n deformed;\r\n\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvec4 position = mix(attr_" -"Position, attr_Position2, u_VertexLerp);\r\n\tvec3 normal = normalize(mix(a" -"ttr_Normal, attr_Normal2, u_VertexLerp));\r\n\r\n\tposition = DeformPositio" -"n(position, normal, attr_TexCoord0.st);\r\n\r\n\tgl_Position = u_ModelViewP" -"rojectionMatrix * position;\r\n\r\n\tfloat s = dot(position.xyz, u_FogDista" -"nce.xyz) + u_FogDistance.w;\r\n\tfloat t = dot(position.xyz, u_FogDepth.xyz" -") + u_FogDepth.w;\r\n\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\telse\r\n\t{\r\n\t\ts *= max(t + sign(u_FogEyeT)" -", 0.0);\r\n\t}\r\n\t\r\n\tvar_Color = u_Color;\r\n\tvar_Scale = clamp(s * 8" -".0, 0.0, 1.0);\r\n}\r\n"; +"\nuniform float u_Time;\r\nuniform mat4 u_ModelViewProjectionMatrix;\r" +"\n\r\n//#if defined(USE_VERTEX_ANIMATION)\r\nuniform float u_VertexLerp;" +"\r\n//#endif\r\n\r\nvarying float var_Scale;\r\n\r\n\r\nfloat triangle(fl" +"oat x)\r\n{\r\n\treturn max(1.0 - abs(x), 0);\r\n}\r\n\r\nfloat sawtooth(fl" +"oat x)\r\n{\r\n\treturn x - floor(x);\r\n}\r\n\r\nvec4 DeformPosition(const" +" vec4 pos, const vec3 normal, const vec2 st)\r\n{\r\n\tif (u_DeformGen == 0" +")\r\n\t{\r\n\t\treturn pos;\r\n\t}\r\n\r\n\tfloat base = u_DeformParam" +"s[0];\r\n\tfloat amplitude = u_DeformParams[1];\r\n\tfloat phase = u_De" +"formParams[2];\r\n\tfloat frequency = u_DeformParams[3];\r\n\tfloat spread " +"= u_DeformParams[4];\r\n\t\t\r\n\tif (u_DeformGen <= DGEN_WAVE_INVERSE_S" +"AWTOOTH)\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * spread;\r\n\t}\r" +"\n\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase *= M_PI * 0.25 " +"* st.x;\r\n\t}\r\n\r\n\tfloat value = phase + (u_Time * frequency);\r\n\tfl" +"oat func;\r\n\r\n\tif (u_DeformGen == DGEN_WAVE_SIN)\r\n\t{\r\n\t\tfunc = s" +"in(value * 2.0 * M_PI);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SQUAR" +"E)\r\n\t{\r\n\t\tfunc = sign(sin(value * 2.0 * M_PI));\r\n\t}\r\n\telse if " +"(u_DeformGen == DGEN_WAVE_TRIANGLE)\r\n\t{\r\n\t\tfunc = triangle(value);\r" +"\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SAWTOOTH)\r\n\t{\r\n\t\tfunc =" +" sawtooth(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_INVERSE_SAW" +"TOOTH)\r\n\t{\r\n\t\tfunc = (1.0 - sawtooth(value));\r\n\t}\r\n\telse if (u" +"_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tfunc = sin(value);\r\n\t}\r\n\r\n\t" +"vec4 deformed = pos;\r\n\tdeformed.xyz += normal * (base + func * amplitude" +");\r\n\r\n\treturn deformed;\r\n\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvec4 pos" +"ition = mix(attr_Position, attr_Position2, u_VertexLerp);\r\n\tvec3 normal " +"= normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));\r\n\r\n\tpositio" +"n = DeformPosition(position, normal, attr_TexCoord0.st);\r\n\r\n\tgl_Positi" +"on = u_ModelViewProjectionMatrix * position;\r\n\r\n\tfloat s = dot(positio" +"n.xyz, u_FogDistance.xyz) + u_FogDistance.w;\r\n\tfloat t = dot(position.xy" +"z, u_FogDepth.xyz) + u_FogDepth.w;\r\n\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\telse\r\n\t{\r\n\t\ts *= max(t " +"+ sign(u_FogEyeT), 0.0);\r\n\t}\r\n\r\n\tvar_Scale = clamp(s * 8.0, 0.0, 1." +"0);\r\n}\r\n"; static const char *fallbackFogPassShader_fp = -"varying vec4 var_Color;\r\n\r\nvarying float var_Scale;\r\n\r\nvoid main()" -"\r\n{\r\n\tgl_FragColor = var_Color;\r\n\tgl_FragColor.a *= sqrt(var_Scale)" -";\r\n}\r\n"; +"uniform vec4 u_Color;\r\n\r\nvarying float var_Scale;\r\n\r\nvoid main()\r" +"\n{\r\n\tgl_FragColor = u_Color;\r\n\tgl_FragColor.a *= sqrt(var_Scale);\r" +"\n}\r\n"; -static const char *fallbackDlightallShader_vp = +static const char *fallbackDlightShader_vp = "attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\nattribut" "e vec3 attr_Normal;\r\n\r\nuniform vec4 u_DlightInfo;\r\n\r\nuniform int " " u_DeformGen;\r\nuniform float u_DeformParams[5];\r\n\r\nuniform float " @@ -224,54 +217,58 @@ static const char *fallbackDlightallShader_vp = ", 0.0, 1.0);\r\n\r\n\tvar_Tex1 = tex;\r\n\tvar_Color = u_Color;\r\n\tvar_Co" "lor.rgb *= dlightmod;\r\n}\r\n"; -static const char *fallbackDlightallShader_fp = +static const char *fallbackDlightShader_fp = "uniform sampler2D u_DiffuseMap;\r\n\r\nvarying vec2 var_Tex1;\r\nvaryi" "ng vec4 var_Color;\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = textu" "re2D(u_DiffuseMap, var_Tex1);\r\n\r\n\tgl_FragColor = color * var_Color;\r" "\n}\r\n"; static const char *fallbackLightallShader_vp = -"attribute vec4 attr_TexCoord0;\r\nattribute vec4 attr_TexCoord1;\r\n\r\natt" -"ribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\n\r\n#if define" -"d(USE_NORMALMAP)\r\nattribute vec3 attr_Tangent;\r\nattribute vec3 attr_Bit" -"angent;\r\n#endif\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nattribute vec" -"4 attr_Position2;\r\nattribute vec3 attr_Normal2;\r\n #if defined(USE_NORM" -"ALMAP)\r\nattribute vec3 attr_Tangent2;\r\nattribute vec3 attr_Bitangent2;" -"\r\n #endif\r\n#endif\r\n\r\nuniform mat4 u_DiffuseTexMatrix;\r\nuniform" -" vec3 u_ViewOrigin;\r\nuniform mat4 u_ModelViewProjectionMatrix;\r\n\r" -"\n#if defined(USE_MODELMATRIX)\r\nuniform mat4 u_ModelMatrix;\r\n#endif\r" -"\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nuniform float u_VertexLerp;\r\n" -"#endif\r\n\r\nvarying vec2 var_DiffuseTex;\r\nvarying vec2 var_LightTex" -";\r\n\r\nvarying vec3 var_Position;\r\nvarying vec3 var_Normal;\r\n\r\n" -"#if defined(USE_NORMALMAP)\r\nvarying vec3 var_Tangent;\r\nvarying vec3 " -" var_Bitangent;\r\n#endif\r\n\r\nvec2 DoTexMatrix(vec2 st, vec3 position, m" -"at4 texMatrix)\r\n{\r\n\tvec2 st2 = (texMatrix * vec4(st, 1, 0)).st;\r\n\r" -"\n\tvec3 offsetPos = position.xyz / 1024.0;\r\n\toffsetPos.x += offsetPos.z" -";\r\n\r\n\tvec2 texOffset = sin((offsetPos.xy + vec2(texMatrix[3][1])) * 2." -"0 * M_PI);\r\n\t\r\n\treturn st2 + texOffset * texMatrix[3][0];\r\n}\r\n\r" -"\nvoid main()\r\n{\r\n#if defined(USE_VERTEX_ANIMATION)\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 #if def" -"ined(USE_NORMALMAP)\r\n\tvec3 tangent = normalize(mix(attr_Tangent, att" -"r_Tangent2, u_VertexLerp));\r\n\tvec3 bitangent = normalize(mix(attr_Bita" -"ngent, attr_Bitangent2, u_VertexLerp));\r\n #endif\r\n#else\r\n\tvec4 posi" -"tion = attr_Position;\r\n\tvec3 normal = attr_Normal;\r\n #if defined(" -"USE_NORMALMAP)\r\n vec3 tangent = attr_Tangent;\r\n vec3 bi" -"tangent = attr_Bitangent;\r\n #endif\r\n#endif\r\n\r\n\tgl_Position = u_Mo" -"delViewProjectionMatrix * position;\r\n\r\n#if defined(TCGEN_ENVIRONMENT)\r" -"\n\tvec2 tex;\r\n\tvec3 viewer = normalize(u_ViewOrigin - position.xyz);\r" -"\n\tvec3 reflected = normal * 2.0 * dot(normal, viewer) - viewer;\r\n\r\n\t" -"tex.s = 0.5 + reflected.y * 0.5;\r\n\ttex.t = 0.5 - reflected.z * 0.5;\r\n#" -"else\r\n\tvec2 tex = attr_TexCoord0.st;\r\n#endif\r\n\r\n\tvar_DiffuseTex =" -" DoTexMatrix(tex, position.xyz, u_DiffuseTexMatrix);\r\n\r\n\tvar_LightTex " -"= attr_TexCoord1.st;\r\n\r\n#if defined(USE_MODELMATRIX)\r\n\tvar_Position " -" = (u_ModelMatrix * position).xyz;\r\n\tvar_Normal = (u_ModelMatrix * ve" -"c4(normal, 0.0)).xyz;\r\n\r\n #if defined(USE_NORMALMAP)\r\n\tvar_Tangent " -" = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;\r\n\tvar_Bitangent = (u_Model" -"Matrix * vec4(bitangent, 0.0)).xyz;\r\n #endif\r\n#else\r\n\tvar_Position " -" = position.xyz;\r\n\tvar_Normal = normal;\r\n\r\n #if defined(USE_NORM" -"ALMAP)\r\n\tvar_Tangent = tangent;\r\n\tvar_Bitangent = bitangent;\r\n #" -"endif\r\n#endif\r\n}\r\n"; +"attribute vec4 attr_TexCoord0;\r\n#if defined(USE_LIGHTMAP)\r\nattribute ve" +"c4 attr_TexCoord1;\r\n#endif\r\nattribute vec4 attr_Color;\r\n\r\nattribute" +" vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\n\r\n#if defined(USE_" +"NORMALMAP)\r\nattribute vec3 attr_Tangent;\r\nattribute vec3 attr_Bitangent" +";\r\n#endif\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nattribute vec4 attr" +"_Position2;\r\nattribute vec3 attr_Normal2;\r\n #if defined(USE_NORMALMAP)" +"\r\nattribute vec3 attr_Tangent2;\r\nattribute vec3 attr_Bitangent2;\r\n #" +"endif\r\n#endif\r\n\r\nuniform mat4 u_DiffuseTexMatrix;\r\nuniform vec3 " +" u_ViewOrigin;\r\nuniform mat4 u_ModelViewProjectionMatrix;\r\nuniform ve" +"c4 u_BaseColor;\r\nuniform vec4 u_VertColor;\r\n\r\n#if defined(USE_MOD" +"ELMATRIX)\r\nuniform mat4 u_ModelMatrix;\r\n#endif\r\n\r\n#if defined(USE" +"_VERTEX_ANIMATION)\r\nuniform float u_VertexLerp;\r\n#endif\r\n\r\nvarying" +" vec2 var_DiffuseTex;\r\n\r\n#if defined(USE_LIGHTMAP)\r\nvarying vec2 " +"var_LightTex;\r\n#endif\r\n\r\nvarying vec4 var_Color;\r\n\r\nvarying vec" +"3 var_Position;\r\nvarying vec3 var_Normal;\r\n\r\n#if defined(USE_NORM" +"ALMAP)\r\nvarying vec3 var_Tangent;\r\nvarying vec3 var_Bitangent;\r\n#" +"endif\r\n\r\nvec2 DoTexMatrix(vec2 st, vec3 position, mat4 texMatrix)\r\n{" +"\r\n\tvec2 st2 = (texMatrix * vec4(st, 1, 0)).st;\r\n\r\n\tvec3 offsetPos =" +" position.xyz / 1024.0;\r\n\toffsetPos.x += offsetPos.z;\r\n\r\n\tvec2 texO" +"ffset = sin((offsetPos.xy + vec2(texMatrix[3][1])) * 2.0 * M_PI);\r\n\t\r\n" +"\treturn st2 + texOffset * texMatrix[3][0];\r\n}\r\n\r\nvoid main()\r\n{\r" +"\n#if defined(USE_VERTEX_ANIMATION)\r\n\tvec4 position = mix(attr_Position" +", attr_Position2, u_VertexLerp);\r\n\tvec3 normal = normalize(mix(attr_N" +"ormal, attr_Normal2, u_VertexLerp));\r\n #if defined(USE_NORMALMAP)" +"\r\n\tvec3 tangent = normalize(mix(attr_Tangent, attr_Tangent2, u_Ver" +"texLerp));\r\n\tvec3 bitangent = normalize(mix(attr_Bitangent, attr_Bitange" +"nt2, u_VertexLerp));\r\n #endif\r\n#else\r\n\tvec4 position = attr_Positi" +"on;\r\n\tvec3 normal = attr_Normal;\r\n #if defined(USE_NORMALMAP)\r\n " +" vec3 tangent = attr_Tangent;\r\n vec3 bitangent = attr_Bita" +"ngent;\r\n #endif\r\n#endif\r\n\r\n\tgl_Position = u_ModelViewProjectionMa" +"trix * position;\r\n\r\n#if defined(TCGEN_ENVIRONMENT)\r\n\tvec2 tex;\r\n\t" +"vec3 viewer = normalize(u_ViewOrigin - position.xyz);\r\n\tvec3 reflected =" +" normal * 2.0 * dot(normal, viewer) - viewer;\r\n\r\n\ttex.s = 0.5 + reflec" +"ted.y * 0.5;\r\n\ttex.t = 0.5 - reflected.z * 0.5;\r\n#else\r\n\tvec2 tex =" +" attr_TexCoord0.st;\r\n#endif\r\n\r\n\tvar_DiffuseTex = DoTexMatrix(tex, po" +"sition.xyz, u_DiffuseTexMatrix);\r\n\r\n#if defined(USE_LIGHTMAP)\r\n\tvar_" +"LightTex = attr_TexCoord1.st;\r\n#endif\r\n\t\r\n\tvar_Color = u_BaseColor " +"+ u_VertColor * attr_Color;\r\n\r\n#if defined(USE_MODELMATRIX)\r\n\tvar_Po" +"sition = (u_ModelMatrix * position).xyz;\r\n\tvar_Normal = (u_ModelMatr" +"ix * vec4(normal, 0.0)).xyz;\r\n\r\n #if defined(USE_NORMALMAP)\r\n\tvar_T" +"angent = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;\r\n\tvar_Bitangent = (" +"u_ModelMatrix * vec4(bitangent, 0.0)).xyz;\r\n #endif\r\n#else\r\n\tvar_Po" +"sition = position.xyz;\r\n\tvar_Normal = normal;\r\n\r\n #if defined(U" +"SE_NORMALMAP)\r\n\tvar_Tangent = tangent;\r\n\tvar_Bitangent = bitangent;" +"\r\n #endif\r\n#endif\r\n}\r\n"; static const char *fallbackLightallShader_fp = "uniform sampler2D u_DiffuseMap;\r\n\r\n#if defined(USE_LIGHTMAP)\r\nuniform" @@ -280,82 +277,92 @@ static const char *fallbackLightallShader_fp = "iform sampler2D u_DeluxeMap;\r\n#endif\r\n\r\n#if defined(USE_SPECULARMAP)" "\r\nuniform sampler2D u_SpecularMap;\r\n#endif\r\n\r\n#if defined(USE_SHADO" "WMAP)\r\nuniform samplerCube u_ShadowMap;\r\n#endif\r\n\r\nuniform vec3 " -" u_ViewOrigin;\r\nuniform vec4 u_Color;\r\n\r\n#if defined(USE_LIGHT_" -"VECTOR)\r\nuniform vec3 u_DirectedLight;\r\nuniform vec3 u_Ambien" -"tLight;\r\nuniform vec4 u_LightOrigin;\r\nuniform float u_LightRad" -"ius;\r\n#endif\r\n\r\n#if defined(USE_SPECULARMAP)\r\nuniform float u_S" -"pecularReflectance;\r\n#endif\r\n\r\nvarying vec2 var_DiffuseTex;\r\nv" -"arying vec2 var_LightTex;\r\n\r\nvarying vec3 var_Position;\r\n\r" -"\n#if defined(USE_NORMALMAP)\r\nvarying vec3 var_Tangent;\r\nvarying v" -"ec3 var_Bitangent;\r\n#endif\r\n\r\nvarying vec3 var_Normal;\r\n" -"\r\n\r\nfloat RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap" -")\r\n{\r\n\tconst int linearSearchSteps = 5;\r\n\tconst int binarySearchSte" -"ps = 5;\r\n\r\n\tfloat depthStep = 1.0 / float(linearSearchSteps);\r\n\r\n" -"\t// current size of search window\r\n\tfloat size = depthStep;\r\n\r\n\t//" -" current depth position\r\n\tfloat depth = 0.0;\r\n\r\n\t// best match foun" -"d (starts with last position 1.0)\r\n\tfloat bestDepth = 1.0;\r\n\r\n\t// s" -"earch front to back for first point inside object\r\n\tfor(int i = 0; i < l" -"inearSearchSteps - 1; ++i)\r\n\t{\r\n\t\tdepth += size;\r\n\t\t\r\n\t\tvec4" -" t = texture2D(normalMap, dp + ds * depth);\r\n\r\n\t\tif(bestDepth > 0.996" -")\t\t// if no depth found yet\r\n\t\t\tif(depth >= t.w)\r\n\t\t\t\tbestDept" -"h = depth;\t// store best depth\r\n\t}\r\n\r\n\tdepth = bestDepth;\r\n\t\r" -"\n\t// recurse around first point (depth) for closest match\r\n\tfor(int i " -"= 0; i < binarySearchSteps; ++i)\r\n\t{\r\n\t\tsize *= 0.5;\r\n\r\n\t\tvec4" -" t = texture2D(normalMap, dp + ds * depth);\r\n\t\t\r\n\t\tif(depth >= t.w)" -"\r\n\t\t{\r\n\t\t\tbestDepth = depth;\r\n\t\t\tdepth -= 2.0 * size;\r\n\t\t" -"}\r\n\r\n\t\tdepth += size;\r\n\t}\r\n\r\n\treturn bestDepth;\r\n}\r\n\r\nv" -"oid main()\r\n{\r\n#if defined(USE_LIGHTMAP)\r\n\tvec3 directedLight = text" -"ure2D(u_LightMap, var_LightTex).rgb;\r\n #if defined(USE_DELUXEMAP)\r\n\tv" -"ec3 worldLight = 2.0 * texture2D(u_DeluxeMap, var_LightTex).xyz - vec3(1.0)" -";\r\n #endif\r\n#endif\r\n\r\n#if defined(USE_LIGHT_VECTOR)\r\n\tvec3 worl" -"dLight = u_LightOrigin.xyz - (var_Position * u_LightOrigin.w);\t\r\n #if d" -"efined(USE_INVSQRLIGHT)\r\n\tfloat intensity = 1.0 / dot(worldLight, worldL" -"ight);\r\n #else\r\n\tfloat intensity = clamp((1.0 - dot(worldLight, world" -"Light) / (u_LightRadius * u_LightRadius)) * 1.07, 0.0, 1.0);\r\n #endif\r" -"\n #if defined(USE_SHADOWMAP)\r\n \tvec3 dist3 = textureCube(u_ShadowMap," -" worldLight).rgb;\r\n\tfloat dist = dot(dist3, vec3(1.0 / (256.0 * 256.0), " -"1.0 / 256.0, 1.0)) * u_LightRadius;\r\n\r\n\tintensity *= max(sign(dist - l" -"ength(worldLight)), 0.0);\r\n #endif\r\n\tvec3 directedLight = u_DirectedL" -"ight * intensity;\r\n\tvec3 ambientLight = u_AmbientLight;\r\n#endif\r\n\r" -"\n#if !(defined(USE_LIGHTMAP) && defined(USE_DELUXEMAP)) && !defined(USE_LI" -"GHT_VECTOR)\r\n\tvec3 worldLight = var_Normal;\r\n#endif\r\n\r\n\tvec3 Samp" -"leToView = normalize(u_ViewOrigin - var_Position);\r\n\tvec2 texOffset = ve" -"c2(0.0);\r\n\r\n#if defined(USE_NORMALMAP)\r\n\tmat3 tangentToWorld = mat3(" -"var_Tangent.xyz, var_Bitangent.xyz, var_Normal.xyz);\r\n\r\n #if defined(U" -"SE_PARALLAXMAP)\r\n\tvec3 offsetDir = normalize(SampleToView * tangentToWor" -"ld);\r\n #if 0\r\n\tfloat dist = 0.02 * texture2D(u_NormalMap, var_Diffu" -"seTex).w - (0.02 / 2.0);\r\n #else\r\n\toffsetDir.xy *= 0.05 / offsetDir" -".z;\r\n\tfloat dist = RayIntersectDisplaceMap(var_DiffuseTex, offsetDir.xy," -" u_NormalMap);\r\n #endif\t\r\n\ttexOffset = offsetDir.xy * dist;\r\n #" -"endif\r\n \r\n\tvec3 normal = texture2D(u_NormalMap, var_DiffuseTex + texO" -"ffset).xyz;\r\n\tvec3 worldNormal = tangentToWorld * (2.0 * normal.xyz - ve" -"c3(1.0));\r\n#else\r\n\tvec3 worldNormal = var_Normal;\r\n#endif\r\n\r\n\tv" -"ec4 diffuse = texture2D(u_DiffuseMap, var_DiffuseTex + texOffset) * u_Color" -";\r\n\t\r\n\tworldNormal = normalize(worldNormal);\r\n\tworldLight = normal" -"ize(worldLight);\r\n\r\n#if defined(USE_LIGHTMAP) && defined(USE_DELUXEMAP)" -"\r\n\tdirectedLight /= max(dot(normalize(var_Normal), worldLight), 0.004);" -"\r\n#endif\r\n\r\n#if (defined(USE_LIGHTMAP) && defined(USE_DELUXEMAP)) || " -"defined(USE_LIGHT_VECTOR)\r\n\tfloat NL = max(dot(worldNormal, worldLight)" -", 0.0);\r\n#else\r\n\tfloat NL = 1.0;\r\n#endif\r\n\t\t\r\n#if defined(US" -"E_SPECULARMAP)\r\n\tvec4 specular = texture2D(u_SpecularMap, var_DiffuseTex" -" + texOffset);\r\n\tfloat shininess = specular.a * 255 + 1.0;\r\n\tfloat fz" -"ero = u_SpecularReflectance;\r\n\r\n\tvec3 halfAngle = normalize(worldLight" -" + SampleToView);\r\n\r\n\tfloat EH = max(dot(SampleToView, halfAngle), " -"0.0);\r\n\tfloat NE = max(dot(worldNormal, SampleToView), 0.0);\r\n\tfloat" -" NH = max(dot(worldNormal, halfAngle), 0.0);\r\n\r\n\tfloat factor = 0." -"1248582 * shininess + 0.2691817;\r\n\tfloat fspec = fzero + (1.0 - fzero) *" -" pow(1.0 - EH, 5);\r\n\r\n #if defined(USE_LIGHTMAP)\r\n\tdiffuse.rgb *= m" -"in(NL * (1.0 - fzero), 1.0) * directedLight;\r\n #endif\r\n #if defined(U" -"SE_LIGHT_VECTOR)\r\n\tdiffuse.rgb *= min(directedLight * NL * (1.0 - fzero)" -" + ambientLight, 1.0);\r\n #endif\r\n\tspecular.rgb *= min(factor * fspec " -"* pow(NH, shininess) / max(NL, NE), 1.0);\r\n #if defined(USE_LIGHTMAP) ||" -" defined(USE_LIGHT_VECTOR)\r\n\tspecular.rgb *= min(directedLight, 1.0);\r" -"\n #endif\r\n#else\r\n #if defined(USE_LIGHTMAP)\r\n #if defined(USE_D" -"ELUXEMAP)\r\n\tdiffuse.rgb *= directedLight * NL;\r\n #else\r\n\tdiffuse" -".rgb *= directedLight;\r\n #endif\r\n #endif\r\n #if defined(USE_LIGHT" -"_VECTOR)\r\n\tdiffuse.rgb *= min(directedLight * NL + ambientLight, 1.0);\r" -"\n #endif\r\n#endif\r\n\r\n\tgl_FragColor = diffuse;\r\n\r\n#if defined(US" -"E_SPECULARMAP)\r\n\tgl_FragColor.rgb += specular.rgb;\r\n#endif\r\n}\r\n"; +" u_ViewOrigin;\r\n\r\n#if defined(USE_LIGHT_VECTOR)\r\nuniform vec3 u" +"_DirectedLight;\r\nuniform vec3 u_AmbientLight;\r\nuniform vec4 u" +"_LightOrigin;\r\nuniform float u_LightRadius;\r\n#endif\r\n\r\n#if defi" +"ned(USE_SPECULARMAP)\r\nuniform float u_SpecularReflectance;\r\n#endif" +"\r\n\r\nvarying vec2 var_DiffuseTex;\r\n#if defined(USE_LIGHTMAP)\r\nv" +"arying vec2 var_LightTex;\r\n#endif\r\nvarying vec4 var_Color;\r" +"\n\r\nvarying vec3 var_Position;\r\n\r\n#if defined(USE_NORMALMAP)\r\n" +"varying vec3 var_Tangent;\r\nvarying vec3 var_Bitangent;\r\n#endi" +"f\r\n\r\nvarying vec3 var_Normal;\r\n\r\n\r\nfloat RayIntersectDisplac" +"eMap(vec2 dp, vec2 ds, sampler2D normalMap)\r\n{\r\n\tconst int linearSearc" +"hSteps = 5;\r\n\tconst int binarySearchSteps = 5;\r\n\r\n\tfloat depthStep " +"= 1.0 / float(linearSearchSteps);\r\n\r\n\t// current size of search window" +"\r\n\tfloat size = depthStep;\r\n\r\n\t// current depth position\r\n\tfloat" +" depth = 0.0;\r\n\r\n\t// best match found (starts with last position 1.0)" +"\r\n\tfloat bestDepth = 1.0;\r\n\r\n\t// search front to back for first poi" +"nt inside object\r\n\tfor(int i = 0; i < linearSearchSteps - 1; ++i)\r\n\t{" +"\r\n\t\tdepth += size;\r\n\t\t\r\n\t\tvec4 t = texture2D(normalMap, dp + ds" +" * depth);\r\n\r\n\t\tif(bestDepth > 0.996)\t\t// if no depth found yet\r\n" +"\t\t\tif(depth >= t.w)\r\n\t\t\t\tbestDepth = depth;\t// store best depth\r" +"\n\t}\r\n\r\n\tdepth = bestDepth;\r\n\t\r\n\t// recurse around first point " +"(depth) for closest match\r\n\tfor(int i = 0; i < binarySearchSteps; ++i)\r" +"\n\t{\r\n\t\tsize *= 0.5;\r\n\r\n\t\tvec4 t = texture2D(normalMap, dp + ds " +"* depth);\r\n\t\t\r\n\t\tif(depth >= t.w)\r\n\t\t{\r\n\t\t\tbestDepth = dep" +"th;\r\n\t\t\tdepth -= 2.0 * size;\r\n\t\t}\r\n\r\n\t\tdepth += size;\r\n\t}" +"\r\n\r\n\treturn bestDepth;\r\n}\r\n\r\nvoid main()\r\n{\r\n#if defined(USE" +"_LIGHTMAP)\r\n\tvec3 directedLight = texture2D(u_LightMap, var_LightTex).rg" +"b;\r\n #if defined(USE_DELUXEMAP)\r\n\tvec3 worldLight = 2.0 * texture2D(u" +"_DeluxeMap, var_LightTex).xyz - vec3(1.0);\r\n #endif\r\n#endif\r\n\r\n#if" +" defined(USE_LIGHT_VECTOR)\r\n\tvec3 worldLight = u_LightOrigin.xyz - (var_" +"Position * u_LightOrigin.w);\t\r\n #if defined(USE_INVSQRLIGHT)\r\n\tfloat" +" intensity = 1.0 / dot(worldLight, worldLight);\r\n #else\r\n\tfloat inten" +"sity = clamp((1.0 - dot(worldLight, worldLight) / (u_LightRadius * u_LightR" +"adius)) * 1.07, 0.0, 1.0);\r\n #endif\r\n #if defined(USE_SHADOWMAP)\r\n " +" \tvec3 dist3 = textureCube(u_ShadowMap, worldLight).rgb;\r\n\tfloat dist =" +" dot(dist3, vec3(1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0)) * u_LightRadius;" +"\r\n\r\n\tintensity *= max(sign(dist - length(worldLight)), 0.0);\r\n #end" +"if\r\n\tvec3 directedLight = u_DirectedLight * intensity;\r\n\tvec3 ambient" +"Light = u_AmbientLight;\r\n#endif\r\n\r\n#if !(defined(USE_LIGHTMAP) && de" +"fined(USE_DELUXEMAP)) && !defined(USE_LIGHT_VECTOR)\r\n\tvec3 worldLight = " +"var_Normal;\r\n#endif\r\n\r\n\tvec3 SampleToView = normalize(u_ViewOrigin -" +" var_Position);\r\n\tvec2 texOffset = vec2(0.0);\r\n\t\r\n\tfloat ambientDi" +"ff = 1.0;\r\n\r\n#if defined(USE_NORMALMAP)\r\n\tmat3 tangentToWorld = mat3" +"(var_Tangent.xyz, var_Bitangent.xyz, var_Normal.xyz);\r\n\r\n #if defined(" +"USE_PARALLAXMAP)\r\n\tvec3 offsetDir = normalize(SampleToView * tangentToWo" +"rld);\r\n #if 0\r\n\tfloat dist = 0.02 * texture2D(u_NormalMap, var_Diff" +"useTex).w - (0.02 / 2.0);\r\n #else\r\n\toffsetDir.xy *= 0.02 / offsetDi" +"r.z;\r\n\tfloat dist = RayIntersectDisplaceMap(var_DiffuseTex, offsetDir.xy" +", u_NormalMap);\r\n #endif\t\r\n\ttexOffset = offsetDir.xy * dist;\r\n " +"#endif\r\n \r\n\tvec3 normal = texture2D(u_NormalMap, var_DiffuseTex + tex" +"Offset).xyz;\r\n\tvec3 worldNormal = tangentToWorld * (2.0 * normal.xyz - v" +"ec3(1.0));\r\n #if defined(r_normalAmbient)\r\n\tambientDiff = 0.248965 * " +"normal.z + 0.069673;\r\n #endif\r\n#else\r\n\tvec3 worldNormal = var_Norma" +"l;\r\n#endif\r\n\r\n\tvec4 diffuse = texture2D(u_DiffuseMap, var_DiffuseTex" +" + texOffset);\r\n\t\r\n\tworldNormal = normalize(worldNormal);\r\n\tworldL" +"ight = normalize(worldLight);\r\n\r\n#if defined(USE_LIGHTMAP)\r\n #if def" +"ined(USE_DELUXEMAP)\r\n\tdirectedLight /= max(dot(normalize(var_Normal), wo" +"rldLight), 0.004);\r\n #endif\r\n \r\n #if defined(r_normalAmbient)\r\n" +"\tvec3 ambientLight = directedLight * r_normalAmbient;\r\n\tdirectedLight -" +"= ambientLight;\r\n #else\r\n\tvec3 ambientLight = vec3(0);\r\n #endif\r" +"\n#endif\r\n\r\n#if defined(r_normalAmbient) && (defined(USE_LIGHTMAP) || d" +"efined(USE_LIGHT_VECTOR))\r\n\tambientLight *= 3.138357;\r\n#endif\r\n\r\n#" +"if (defined(USE_LIGHTMAP) && defined(USE_DELUXEMAP)) || defined(USE_LIGHT_V" +"ECTOR)\r\n\tfloat NL = max(dot(worldNormal, worldLight), 0.0);\r\n#else" +"\r\n\tfloat NL = 1.0;\r\n#endif\r\n\r\n#if defined(USE_SPECULARMAP) && (def" +"ined(USE_LIGHTMAP) || defined(USE_LIGHT_VECTOR))\r\n\tvec4 specular = textu" +"re2D(u_SpecularMap, var_DiffuseTex + texOffset);\r\n\tfloat shininess = spe" +"cular.a * 255 + 1.0;\r\n\tfloat fzero = u_SpecularReflectance;\r\n\r\n\tvec" +"3 halfAngle = normalize(worldLight + SampleToView);\r\n\r\n\tfloat EH = max" +"(dot(SampleToView, halfAngle), 0.0);\r\n\tfloat NE = max(dot(worldNormal" +", SampleToView), 0.0001);\r\n\tfloat NH = max(dot(worldNormal, halfAngle)" +", 0.0);\r\n\r\n\tfloat factor = 0.1248582 * shininess + 0.2691817;\r\n\t" +"float fspec = fzero + (1.0 - fzero) * pow(1.0 - EH, 5);\r\n\r\n\tdiffuse.rg" +"b *= min((directedLight * NL + ambientLight) * (1.0 - fzero) , 1.0);\r\n\t" +"\r\n\tfloat directedSpec = factor * fspec * pow(NH, shininess) / max(NL, NE" +");\r\n\r\n #if defined(r_normalAmbient)\r\n #if defined(USE_NORMALMAP)" +"\r\n\tfloat ambientSpec = pow(normal.z, shininess);\r\n #else\r\n\tfloat" +" ambientSpec = 1.0f;\r\n #endif\r\n\r\n\tambientSpec *= factor * fzero *" +" 8.05438 / (shininess + 19.0);\r\n\tambientSpec += 0.04389 / (shininess * s" +"hininess);\r\n\t\r\n\tspecular.rgb *= min(directedSpec * directedLight + am" +"bientSpec * ambientLight, 1.0);\r\n #else\r\n\tspecular.rgb *= min(directe" +"dSpec * directedLight, 1.0);\r\n #endif\r\n#else\r\n #if (defined(USE_LIG" +"HTMAP) || defined(USE_LIGHT_VECTOR))\r\n\tdiffuse.rgb *= min(directedLight " +"* NL + ambientDiff * ambientLight, 1.0);\r\n #endif\r\n#endif\r\n\r\n\tgl_" +"FragColor = diffuse;\r\n\r\n#if defined(USE_SPECULARMAP) && (defined(USE_LI" +"GHTMAP) || defined(USE_LIGHT_VECTOR))\r\n\tgl_FragColor.rgb += specular.rgb" +";\r\n#endif\r\n\r\n\tgl_FragColor *= var_Color;\r\n}\r\n"; static const char *fallbackShadowfillShader_vp = "attribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\nattribute" @@ -424,17 +431,17 @@ static const char *fallbackPshadowShader_fp = "stMap(sampler2D texMap, vec2 uv, float scale)\r\n{\r\n\tvec3 distv = textur" "e2D(texMap, uv).xyz;\r\n\treturn dot(distv, vec3(1.0 / (256.0 * 256.0), 1.0" " / 256.0, 1.0)) * scale;\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvec2 st;\r\n\t\r" -"\n\tvec3 lightToPos = u_LightOrigin.xyz - var_Position;\r\n\t\r\n\tst.s = d" -"ot(u_LightUp, lightToPos);\r\n\tst.t = dot(u_LightRight, lightToPos);\t\r\n" +"\n\tvec3 lightToPos = var_Position - u_LightOrigin.xyz;\r\n\t\r\n\tst.s = -" +"dot(u_LightRight, lightToPos);\r\n\tst.t = dot(u_LightUp, lightToPos);\r\n" "\t\r\n\tst = st * 0.5 + vec2(0.5);\r\n\r\n#if defined(USE_SOLID_PSHADOWS)\r" "\n\tfloat intensity = max(sign(u_LightRadius - length(lightToPos)), 0.0);\r" "\n#else\r\n\tfloat intensity = clamp((1.0 - dot(lightToPos, lightToPos) / (" "u_LightRadius * u_LightRadius)) * 2.0, 0.0, 1.0);\r\n#endif\r\n\t\r\n\tfloa" "t lightDist = length(lightToPos);\r\n\tfloat dist;\r\n\r\n#if defined(USE_D" "ISCARD)\r\n\tif (dot(u_LightForward, lightToPos) <= 0.0)\r\n\t{\r\n\t\tdisc" -"ard;\r\n\t}\r\n\r\n\tif (dot(var_Normal, lightToPos) <= 0.0)\r\n\t{\r\n\t\t" -"discard;\r\n\t}\r\n#else\r\n\tintensity *= max(sign(dot(u_LightForward, lig" -"htToPos)), 0.0);\r\n\tintensity *= max(sign(dot(var_Normal, lightToPos)), 0" +"ard;\r\n\t}\r\n\r\n\tif (dot(var_Normal, lightToPos) > 0.0)\r\n\t{\r\n\t\td" +"iscard;\r\n\t}\r\n#else\r\n\tintensity *= max(sign(dot(u_LightForward, ligh" +"tToPos)), 0.0);\r\n\tintensity *= max(sign(-dot(var_Normal, lightToPos)), 0" ".0);\r\n#endif\r\n\t\r\n#if defined(USE_PCF)\r\n\tfloat part;\r\n\t\r\n\tdi" "st = sampleDistMap(u_ShadowMap, st + vec2(-1.0/256.0, -1.0/256.0), u_LightR" "adius);\r\n\tpart = max(sign(lightDist - dist), 0.0);\r\n\r\n\tdist = samp" @@ -509,193 +516,145 @@ static void GLSL_PrintShaderSource(GLhandleARB object) ri.Free(msg); } -static int GLSL_CompileGPUShader(GLhandleARB program, GLhandleARB *prevShader, const GLcharARB *buffer, int size, GLenum shaderType, const GLcharARB *extra, qboolean addHeader) +static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, char *dest, int size ) +{ + float fbufWidthScale, fbufHeightScale; + + dest[0] = '\0'; + + // HACK: abuse the GLSL preprocessor to turn GLSL 1.20 shaders into 1.30 ones + if(0) //(glConfig.driverType == GLDRV_OPENGL3) + { + Q_strcat(dest, size, "#version 130\n"); + + if(shaderType == GL_VERTEX_SHADER_ARB) + { + Q_strcat(dest, size, "#define attribute in\n"); + Q_strcat(dest, size, "#define varying out\n"); + } + else + { + Q_strcat(dest, size, "#define varying in\n"); + + Q_strcat(dest, size, "out vec4 out_Color;\n"); + Q_strcat(dest, size, "#define gl_FragColor out_Color\n"); + } + } + else + { + Q_strcat(dest, size, "#version 120\n"); + } + + // HACK: add some macros to avoid extra uniforms and save speed and code maintenance + //Q_strcat(dest, size, + // va("#ifndef r_SpecularExponent\n#define r_SpecularExponent %f\n#endif\n", r_specularExponent->value)); + //Q_strcat(dest, size, + // va("#ifndef r_SpecularScale\n#define r_SpecularScale %f\n#endif\n", r_specularScale->value)); + //Q_strcat(dest, size, + // va("#ifndef r_NormalScale\n#define r_NormalScale %f\n#endif\n", r_normalScale->value)); + + + Q_strcat(dest, size, "#ifndef M_PI\n#define M_PI 3.14159265358979323846f\n#endif\n"); + + //Q_strcat(dest, size, va("#ifndef MAX_SHADOWMAPS\n#define MAX_SHADOWMAPS %i\n#endif\n", MAX_SHADOWMAPS)); + + Q_strcat(dest, size, + va("#ifndef deformGen_t\n" + "#define deformGen_t\n" + "#define DGEN_WAVE_SIN %i\n" + "#define DGEN_WAVE_SQUARE %i\n" + "#define DGEN_WAVE_TRIANGLE %i\n" + "#define DGEN_WAVE_SAWTOOTH %i\n" + "#define DGEN_WAVE_INVERSE_SAWTOOTH %i\n" + "#define DGEN_BULGE %i\n" + "#define DGEN_MOVE %i\n" + "#endif\n", + DGEN_WAVE_SIN, + DGEN_WAVE_SQUARE, + DGEN_WAVE_TRIANGLE, + DGEN_WAVE_SAWTOOTH, + DGEN_WAVE_INVERSE_SAWTOOTH, + DGEN_BULGE, + DGEN_MOVE)); + + Q_strcat(dest, size, + va("#ifndef tcGen_t\n" + "#define tcGen_t\n" + "#define TCGEN_LIGHTMAP %i\n" + "#define TCGEN_TEXTURE %i\n" + "#define TCGEN_ENVIRONMENT_MAPPED %i\n" + "#define TCGEN_FOG %i\n" + "#define TCGEN_VECTOR %i\n" + "#endif\n", + TCGEN_LIGHTMAP, + TCGEN_TEXTURE, + TCGEN_ENVIRONMENT_MAPPED, + TCGEN_FOG, + TCGEN_VECTOR)); + + Q_strcat(dest, size, + va("#ifndef colorGen_t\n" + "#define colorGen_t\n" + "#define CGEN_LIGHTING_DIFFUSE %i\n" + "#endif\n", + CGEN_LIGHTING_DIFFUSE)); + + Q_strcat(dest, size, + va("#ifndef alphaGen_t\n" + "#define alphaGen_t\n" + "#define AGEN_LIGHTING_SPECULAR %i\n" + "#define AGEN_PORTAL %i\n" + "#define AGEN_FRESNEL %i\n" + "#endif\n", + AGEN_LIGHTING_SPECULAR, + AGEN_PORTAL, + AGEN_FRESNEL)); + + Q_strcat(dest, size, + va("#ifndef alphaTest_t\n" + "#define alphaTest_t\n" + "#define ATEST_GT_0 %i\n" + "#define ATEST_LT_128 %i\n" + "#define ATEST_GE_128 %i\n" + "#endif\n", + ATEST_GT_0, + ATEST_LT_128, + ATEST_GE_128)); + + Q_strcat(dest, size, + va("#ifndef texenv_t\n" + "#define texenv_t\n" + "#define TEXENV_MODULATE %i\n" + "#define TEXENV_ADD %i\n" + "#define TEXENV_REPLACE %i\n" + "#endif\n", + GL_MODULATE, + GL_ADD, + GL_REPLACE)); + + fbufWidthScale = 1.0f / ((float)glConfig.vidWidth); + fbufHeightScale = 1.0f / ((float)glConfig.vidHeight); + Q_strcat(dest, size, + va("#ifndef r_FBufScale\n#define r_FBufScale vec2(%f, %f)\n#endif\n", fbufWidthScale, fbufHeightScale)); + + if (extra) + { + Q_strcat(dest, size, extra); + } + + // OK we added a lot of stuff but if we do something bad in the GLSL shaders then we want the proper line + // so we have to reset the line counting + Q_strcat(dest, size, "#line 0\n"); +} + +static int GLSL_CompileGPUShader(GLhandleARB program, GLhandleARB *prevShader, const GLcharARB *buffer, int size, GLenum shaderType) { GLint compiled; GLhandleARB shader; shader = qglCreateShaderObjectARB(shaderType); - if (addHeader) - { - static char bufferExtra[32000]; - int sizeExtra; - - char *bufferFinal = NULL; - int sizeFinal; - - float fbufWidthScale, fbufHeightScale; - - Com_Memset(bufferExtra, 0, sizeof(bufferExtra)); - - // HACK: abuse the GLSL preprocessor to turn GLSL 1.20 shaders into 1.30 ones - if(0) //(glConfig.driverType == GLDRV_OPENGL3) - { - Q_strcat(bufferExtra, sizeof(bufferExtra), "#version 130\n"); - - if(shaderType == GL_VERTEX_SHADER_ARB) - { - Q_strcat(bufferExtra, sizeof(bufferExtra), "#define attribute in\n"); - Q_strcat(bufferExtra, sizeof(bufferExtra), "#define varying out\n"); - } - else - { - Q_strcat(bufferExtra, sizeof(bufferExtra), "#define varying in\n"); - - Q_strcat(bufferExtra, sizeof(bufferExtra), "out vec4 out_Color;\n"); - Q_strcat(bufferExtra, sizeof(bufferExtra), "#define gl_FragColor out_Color\n"); - } - } - else - { - Q_strcat(bufferExtra, sizeof(bufferExtra), "#version 120\n"); - } - - // HACK: add some macros to avoid extra uniforms and save speed and code maintenance - //Q_strcat(bufferExtra, sizeof(bufferExtra), - // va("#ifndef r_SpecularExponent\n#define r_SpecularExponent %f\n#endif\n", r_specularExponent->value)); - //Q_strcat(bufferExtra, sizeof(bufferExtra), - // va("#ifndef r_SpecularScale\n#define r_SpecularScale %f\n#endif\n", r_specularScale->value)); - //Q_strcat(bufferExtra, sizeof(bufferExtra), - // va("#ifndef r_NormalScale\n#define r_NormalScale %f\n#endif\n", r_normalScale->value)); - - - Q_strcat(bufferExtra, sizeof(bufferExtra), "#ifndef M_PI\n#define M_PI 3.14159265358979323846f\n#endif\n"); - - //Q_strcat(bufferExtra, sizeof(bufferExtra), va("#ifndef MAX_SHADOWMAPS\n#define MAX_SHADOWMAPS %i\n#endif\n", MAX_SHADOWMAPS)); - - Q_strcat(bufferExtra, sizeof(bufferExtra), - va("#ifndef deformGen_t\n" - "#define deformGen_t\n" - "#define DGEN_WAVE_SIN %i\n" - "#define DGEN_WAVE_SQUARE %i\n" - "#define DGEN_WAVE_TRIANGLE %i\n" - "#define DGEN_WAVE_SAWTOOTH %i\n" - "#define DGEN_WAVE_INVERSE_SAWTOOTH %i\n" - "#define DGEN_BULGE %i\n" - "#define DGEN_MOVE %i\n" - "#endif\n", - DGEN_WAVE_SIN, - DGEN_WAVE_SQUARE, - DGEN_WAVE_TRIANGLE, - DGEN_WAVE_SAWTOOTH, - DGEN_WAVE_INVERSE_SAWTOOTH, - DGEN_BULGE, - DGEN_MOVE)); - - Q_strcat(bufferExtra, sizeof(bufferExtra), - va("#ifndef tcGen_t\n" - "#define tcGen_t\n" - "#define TCGEN_LIGHTMAP %i\n" - "#define TCGEN_TEXTURE %i\n" - "#define TCGEN_ENVIRONMENT_MAPPED %i\n" - "#define TCGEN_FOG %i\n" - "#define TCGEN_VECTOR %i\n" - "#endif\n", - TCGEN_LIGHTMAP, - TCGEN_TEXTURE, - TCGEN_ENVIRONMENT_MAPPED, - TCGEN_FOG, - TCGEN_VECTOR)); - - Q_strcat(bufferExtra, sizeof(bufferExtra), - va("#ifndef colorGen_t\n" - "#define colorGen_t\n" - "#define CGEN_IDENTITY %i\n" - "#define CGEN_VERTEX %i\n" - "#define CGEN_ONE_MINUS_VERTEX %i\n" - "#define CGEN_EXACT_VERTEX %i\n" - "#define CGEN_LIGHTING_DIFFUSE %i\n" - "#endif\n", - CGEN_IDENTITY, - CGEN_VERTEX, - CGEN_ONE_MINUS_VERTEX, - CGEN_EXACT_VERTEX, - CGEN_LIGHTING_DIFFUSE)); - - Q_strcat(bufferExtra, sizeof(bufferExtra), - va("#ifndef alphaGen_t\n" - "#define alphaGen_t\n" - "#define AGEN_IDENTITY %i\n" - "#define AGEN_VERTEX %i\n" - "#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_FRESNEL)); - - Q_strcat(bufferExtra, sizeof(bufferExtra), - va("#ifndef alphaTest_t\n" - "#define alphaTest_t\n" - "#define ATEST_GT_0 %i\n" - "#define ATEST_LT_128 %i\n" - "#define ATEST_GE_128 %i\n" - "#endif\n", - ATEST_GT_0, - ATEST_LT_128, - ATEST_GE_128)); - - Q_strcat(bufferExtra, sizeof(bufferExtra), - va("#ifndef acff_t\n" - "#define acff_t\n" - "#define ACFF_NONE %i\n" - "#define ACFF_MODULATE_RGB %i\n" - "#define ACFF_MODULATE_RGBA %i\n" - "#define ACFF_MODULATE_ALPHA %i\n" - "#endif\n", - ACFF_NONE, - ACFF_MODULATE_RGB, - ACFF_MODULATE_RGBA, - ACFF_MODULATE_ALPHA)); - - Q_strcat(bufferExtra, sizeof(bufferExtra), - va("#ifndef texenv_t\n" - "#define texenv_t\n" - "#define TEXENV_MODULATE %i\n" - "#define TEXENV_ADD %i\n" - "#define TEXENV_REPLACE %i\n" - "#endif\n", - GL_MODULATE, - GL_ADD, - GL_REPLACE)); - - fbufWidthScale = 1.0f / ((float)glConfig.vidWidth); - fbufHeightScale = 1.0f / ((float)glConfig.vidHeight); - Q_strcat(bufferExtra, sizeof(bufferExtra), - va("#ifndef r_FBufScale\n#define r_FBufScale vec2(%f, %f)\n#endif\n", fbufWidthScale, fbufHeightScale)); - - if (extra) - { - Q_strcat(bufferExtra, sizeof(bufferExtra), extra); - } - - // OK we added a lot of stuff but if we do something bad in the GLSL shaders then we want the proper line - // so we have to reset the line counting - Q_strcat(bufferExtra, sizeof(bufferExtra), "#line 0\n"); - - sizeExtra = strlen(bufferExtra); - sizeFinal = sizeExtra + size; - - bufferFinal = ri.Hunk_AllocateTempMemory(size + sizeExtra); - - strcpy(bufferFinal, bufferExtra); - Q_strcat(bufferFinal, sizeFinal, buffer); - - qglShaderSourceARB(shader, 1, (const GLcharARB **)&bufferFinal, &sizeFinal); - - ri.Hunk_FreeTempMemory(bufferFinal); - } - else - { - int sizeFinal = size; - qglShaderSourceARB(shader, 1, (const GLcharARB **)&buffer, &sizeFinal); - } + qglShaderSourceARB(shader, 1, (const GLcharARB **)&buffer, &size); // compile shader qglCompileShaderARB(shader); @@ -728,12 +687,85 @@ static int GLSL_CompileGPUShader(GLhandleARB program, GLhandleARB *prevShader, c } -static int GLSL_LoadGPUShader(GLhandleARB program, GLhandleARB *prevShader, const char *name, GLenum shaderType, const GLcharARB *extra, qboolean addHeader) +static void GLSL_DumpText(const char *shaderText, int size, const char *name, GLenum shaderType) +{ + int i, l, inc; + ri.Printf(PRINT_ALL, "static const char *fallback%sShader_%s =\n\"", name, shaderType == GL_VERTEX_SHADER_ARB ? "vp" : "fp"); + l = 0; + + for (i = 0; i < size; i++) + { + switch (shaderText[i]) + { + case '\a': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + case '\v': + case '"': + case '\\': + inc = 2; + break; + default: + inc = 1; + break; + } + + l += inc; + + if (l >= 76) + { + ri.Printf(PRINT_ALL, "\"\n\""); + l = inc; + } + + switch (shaderText[i]) + { + case '\a': + ri.Printf(PRINT_ALL, "\\a"); + break; + case '\b': + ri.Printf(PRINT_ALL, "\\b"); + break; + case '\f': + ri.Printf(PRINT_ALL, "\\f"); + break; + case '\n': + ri.Printf(PRINT_ALL, "\\n"); + break; + case '\r': + ri.Printf(PRINT_ALL, "\\r"); + break; + case '\t': + ri.Printf(PRINT_ALL, "\\t"); + break; + case '\v': + ri.Printf(PRINT_ALL, "\\v"); + break; + case '"': + ri.Printf(PRINT_ALL, "\\\""); + break; + case '\\': + ri.Printf(PRINT_ALL, "\\\\"); + break; + default: + ri.Printf(PRINT_ALL, "%c", shaderText[i]); + break; + } + } + ri.Printf(PRINT_ALL, "\";\n\n"); +} + +static int GLSL_LoadGPUShaderText(const char *name, const char *fallback, + GLenum shaderType, char *dest, int destSize, qboolean dump) { char filename[MAX_QPATH]; GLcharARB *buffer = NULL; + const GLcharARB *shaderText = NULL; int size; - int result; + int result; if(shaderType == GL_VERTEX_SHADER_ARB) { @@ -748,85 +780,40 @@ static int GLSL_LoadGPUShader(GLhandleARB program, GLhandleARB *prevShader, cons size = ri.FS_ReadFile(filename, (void **)&buffer); if(!buffer) { - return 0; - } - -#if 0 // for dumping - { - int i, l, inc; - - ri.Printf(PRINT_ALL, "%s:\n\"", filename); - l = 0; - - for (i = 0; i < size; i++) + if (fallback) { - switch (buffer[i]) - { - case '\a': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - case '\v': - case '"': - case '\\': - inc = 2; - break; - default: - inc = 1; - break; - } - - l += inc; - - if (l >= 76) - { - ri.Printf(PRINT_ALL, "\"\n\""); - l = inc; - } - - switch (buffer[i]) - { - case '\a': - ri.Printf(PRINT_ALL, "\\a"); - break; - case '\b': - ri.Printf(PRINT_ALL, "\\b"); - break; - case '\f': - ri.Printf(PRINT_ALL, "\\f"); - break; - case '\n': - ri.Printf(PRINT_ALL, "\\n"); - break; - case '\r': - ri.Printf(PRINT_ALL, "\\r"); - break; - case '\t': - ri.Printf(PRINT_ALL, "\\t"); - break; - case '\v': - ri.Printf(PRINT_ALL, "\\v"); - break; - case '"': - ri.Printf(PRINT_ALL, "\\\""); - break; - case '\\': - ri.Printf(PRINT_ALL, "\\\\"); - break; - default: - ri.Printf(PRINT_ALL, "%c", buffer[i]); - break; - } + ri.Printf(PRINT_DEVELOPER, "couldn't load, using fallback\n"); + shaderText = fallback; + size = strlen(shaderText); + } + else + { + ri.Printf(PRINT_DEVELOPER, "couldn't load!\n"); + return 0; } - ri.Printf(PRINT_ALL, "\"\n"); } -#endif + else + { + shaderText = buffer; + } - result = GLSL_CompileGPUShader(program, prevShader, buffer, size, shaderType, extra, addHeader); + if (dump) + GLSL_DumpText(shaderText, size, name, shaderType); - ri.FS_FreeFile(buffer); + if (size > destSize) + { + result = 0; + } + else + { + Q_strncpyz(dest, shaderText, size + 1); + result = 1; + } + + if (buffer) + { + ri.FS_FreeFile(buffer); + } return result; } @@ -884,14 +871,13 @@ static void GLSL_ShowProgramUniforms(GLhandleARB program) qglUseProgramObjectARB(0); } -static int GLSL_InitGPUShader(shaderProgram_t * program, const char *name, int attribs, qboolean fragmentShader, const GLcharARB *extra, qboolean addHeader, - const char *fallback_vp, const char *fallback_fp, int numUniforms) +static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int attribs, const char *vpCode, const char *fpCode, int numUniforms) { ri.Printf(PRINT_DEVELOPER, "------- GPU shader -------\n"); if(strlen(name) >= MAX_QPATH) { - ri.Error(ERR_DROP, "GLSL_InitGPUShader: \"%s\" is too long\n", name); + ri.Error(ERR_DROP, "GLSL_InitGPUShader2: \"%s\" is too long\n", name); } Q_strncpyz(program->name, name, sizeof(program->name)); @@ -899,44 +885,20 @@ static int GLSL_InitGPUShader(shaderProgram_t * program, const char *name, int a program->program = qglCreateProgramObjectARB(); program->attribs = attribs; - if (!(GLSL_LoadGPUShader(program->program, &program->vertexShader, name, GL_VERTEX_SHADER_ARB, extra, addHeader))) + if (!(GLSL_CompileGPUShader(program->program, &program->vertexShader, vpCode, strlen(vpCode), GL_VERTEX_SHADER_ARB))) { - if (fallback_vp) - { - ri.Printf(PRINT_DEVELOPER, "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, "GLSL_InitGPUShader: Unable to load \"%s\" as GL_VERTEX_SHADER_ARB\n", name); - qglDeleteObjectARB(program->program); - return 0; - } - } - else - { - qglDeleteObjectARB(program->program); - return 0; - } + ri.Printf(PRINT_ALL, "GLSL_InitGPUShader2: Unable to load \"%s\" as GL_VERTEX_SHADER_ARB\n", name); + qglDeleteObjectARB(program->program); + return 0; } - if(fragmentShader) + if(fpCode) { - if(!(GLSL_LoadGPUShader(program->program, &program->fragmentShader, name, GL_FRAGMENT_SHADER_ARB, extra, addHeader))) + if(!(GLSL_CompileGPUShader(program->program, &program->fragmentShader, fpCode, strlen(fpCode), GL_FRAGMENT_SHADER_ARB))) { - if (fallback_fp) - { - ri.Printf(PRINT_DEVELOPER, "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, "GLSL_InitGPUShader: Unable to load \"%s\" as GL_FRAGMENT_SHADER_ARB\n", name); - qglDeleteObjectARB(program->program); - return 0; - } - } - else - { - qglDeleteObjectARB(program->program); - return 0; - } + ri.Printf(PRINT_ALL, "GLSL_InitGPUShader2: Unable to load \"%s\" as GL_FRAGMENT_SHADER_ARB\n", name); + qglDeleteObjectARB(program->program); + return 0; } } @@ -1011,6 +973,58 @@ static int GLSL_InitGPUShader(shaderProgram_t * program, const char *name, int a return 1; } +static int GLSL_InitGPUShader(shaderProgram_t * program, const char *name, + int attribs, qboolean fragmentShader, const GLcharARB *extra, qboolean addHeader, + const char *fallback_vp, const char *fallback_fp, int numUniforms) +{ + char vpCode[32000]; + char fpCode[32000]; + char *postHeader; + int size; + int result; + + size = sizeof(vpCode); + if (addHeader) + { + GLSL_GetShaderHeader(GL_VERTEX_SHADER_ARB, extra, vpCode, size); + postHeader = &vpCode[strlen(vpCode)]; + size -= strlen(vpCode); + } + else + { + postHeader = &vpCode[0]; + } + + if (!GLSL_LoadGPUShaderText(name, fallback_vp, GL_VERTEX_SHADER_ARB, postHeader, size, qfalse)) + { + return 0; + } + + if (fragmentShader) + { + size = sizeof(fpCode); + if (addHeader) + { + GLSL_GetShaderHeader(GL_FRAGMENT_SHADER_ARB, extra, fpCode, size); + postHeader = &fpCode[strlen(fpCode)]; + size -= strlen(fpCode); + } + else + { + postHeader = &fpCode[0]; + } + + if (!GLSL_LoadGPUShaderText(name, fallback_fp, GL_FRAGMENT_SHADER_ARB, postHeader, size, qfalse)) + { + return 0; + } + } + + result = GLSL_InitGPUShader2(program, name, attribs, vpCode, fragmentShader ? fpCode : NULL, numUniforms); + + return result; +} + // intentionally deceiving the user here, not actually setting the names but getting their indexes. void GLSL_AddUniform(shaderProgram_t *program, int uniformNum, const char *name, int type) { @@ -1291,7 +1305,7 @@ void GLSL_InitGPUShaders(void) int i; char extradefines[1024]; int attribs; - int numShaders = 0; + int numGenShaders = 0, numLightShaders = 0, numEtcShaders = 0; ri.Printf(PRINT_ALL, "------- GLSL_InitGPUShaders -------\n"); @@ -1326,6 +1340,7 @@ void GLSL_InitGPUShaders(void) if (i & GENERICDEF_USE_LIGHTMAP) Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n"); + if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackGenericShader_vp, fallbackGenericShader_fp, GENERIC_UNIFORM_COUNT)) { ri.Error(ERR_FATAL, "Could not load generic shader!\n"); @@ -1336,8 +1351,18 @@ void GLSL_InitGPUShaders(void) GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_COLORGEN, "u_ColorGen", GLSL_INT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_ALPHAGEN, "u_AlphaGen", GLSL_INT); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_BASECOLOR, "u_BaseColor", GLSL_VEC4); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VERTCOLOR, "u_VertColor", GLSL_VEC4); + + if (i & GENERICDEF_USE_RGBAGEN) + { + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_COLORGEN, "u_ColorGen", GLSL_INT); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_ALPHAGEN, "u_AlphaGen", GLSL_INT); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_AMBIENTLIGHT, "u_AmbientLight", GLSL_VEC3); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIRECTEDLIGHT, "u_DirectedLight", GLSL_VEC3); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_PORTALRANGE, "u_PortalRange", GLSL_FLOAT); + } if (i & GENERICDEF_USE_TCGEN) { @@ -1348,10 +1373,10 @@ void GLSL_InitGPUShaders(void) if (i & GENERICDEF_USE_FOG) { - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGADJUSTCOLORS, "u_FogAdjustColors", GLSL_INT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGDISTANCE, "u_FogDistance", GLSL_VEC4); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGDEPTH, "u_FogDepth", GLSL_VEC4); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGEYET, "u_FogEyeT", GLSL_FLOAT); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGCOLORMASK, "u_FogColorMask", GLSL_VEC4); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGDISTANCE, "u_FogDistance", GLSL_VEC4); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGDEPTH, "u_FogDepth", GLSL_VEC4); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGEYET, "u_FogEyeT", GLSL_FLOAT); } if (i & GENERICDEF_USE_DEFORM_VERTEXES) @@ -1360,19 +1385,14 @@ void GLSL_InitGPUShaders(void) GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5); } - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TIME, "u_Time", GLSL_FLOAT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_COLOR, "u_Color", GLSL_VEC4); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_AMBIENTLIGHT, "u_AmbientLight", GLSL_VEC3); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIRECTEDLIGHT, "u_DirectedLight", GLSL_VEC3); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TIME, "u_Time", GLSL_FLOAT); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3); GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSETEXMATRIX, "u_DiffuseTexMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TEXTURE1ENV, "u_Texture1Env", GLSL_INT); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TEXTURE1ENV, "u_Texture1Env", GLSL_INT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSEMAP, "u_DiffuseMap", GLSL_INT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTMAP, "u_LightMap", GLSL_INT); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSEMAP, "u_DiffuseMap", GLSL_INT); + GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTMAP, "u_LightMap", GLSL_INT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_PORTALRANGE, "u_PortalRange", GLSL_FLOAT); if (i & GENERICDEF_USE_VERTEX_ANIMATION) { @@ -1386,7 +1406,7 @@ void GLSL_InitGPUShaders(void) GLSL_SetUniformInt(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTMAP, TB_LIGHTMAP); qglUseProgramObjectARB(0); - numShaders++; + numGenShaders++; } @@ -1407,7 +1427,7 @@ void GLSL_InitGPUShaders(void) GLSL_SetUniformInt(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); - numShaders++; + numEtcShaders++; attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD; @@ -1429,12 +1449,12 @@ void GLSL_InitGPUShaders(void) GLSL_FinishGPUShader(&tr.fogShader); - numShaders++; + numEtcShaders++; attribs = ATTR_POSITION | ATTR_NORMAL | ATTR_TEXCOORD; - if (!GLSL_InitGPUShader(&tr.dlightallShader, "dlight", attribs, qtrue, NULL, qtrue, fallbackDlightallShader_vp, fallbackDlightallShader_fp, DLIGHT_UNIFORM_COUNT)) + if (!GLSL_InitGPUShader(&tr.dlightallShader, "dlight", attribs, qtrue, NULL, qtrue, fallbackDlightShader_vp, fallbackDlightShader_fp, DLIGHT_UNIFORM_COUNT)) { ri.Error(ERR_FATAL, "Could not load dlight shader!\n"); } @@ -1452,7 +1472,7 @@ void GLSL_InitGPUShaders(void) GLSL_SetUniformInt(&tr.dlightallShader, DLIGHT_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); - numShaders++; + numEtcShaders++; for (i = 0; i < LIGHTDEF_COUNT; i++) @@ -1463,26 +1483,26 @@ void GLSL_InitGPUShaders(void) if (!(i & LIGHTDEF_USE_NORMALMAP) && (i & LIGHTDEF_USE_PARALLAXMAP)) continue; - +#if 0 if ((i & LIGHTDEF_USE_LIGHTMAP) && (i & LIGHTDEF_ENTITY)) continue; if ((i & LIGHTDEF_USE_DELUXEMAP) && (i & LIGHTDEF_ENTITY)) continue; - +#endif if ((i & LIGHTDEF_USE_LIGHTMAP) && (i & LIGHTDEF_USE_LIGHT_VECTOR)) continue; if ((i & LIGHTDEF_USE_DELUXEMAP) && (i & LIGHTDEF_USE_LIGHT_VECTOR)) continue; - attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_NORMAL; + attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR | ATTR_NORMAL; extradefines[0] = '\0'; if (r_normalAmbient->value > 0.003f) Q_strcat(extradefines, 1024, va("#define r_normalAmbient %f\n", r_normalAmbient->value)); - if (r_dlightShadows->integer) + if (r_dlightMode->integer >= 2) Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); if (i & LIGHTDEF_USE_LIGHTMAP) @@ -1506,8 +1526,15 @@ void GLSL_InitGPUShaders(void) Q_strcat(extradefines, 1024, "#define USE_SPECULARMAP\n"); if (i & LIGHTDEF_USE_DELUXEMAP && r_deluxeMapping->integer) + { Q_strcat(extradefines, 1024, "#define USE_DELUXEMAP\n"); + if (r_deluxeMapping->integer == 2 && i & LIGHTDEF_USE_NORMALMAP) + { + Q_strcat(extradefines, 1024, "#define DELUXEMAP_IS_LOCAL\n"); + } + } + if (i & LIGHTDEF_USE_PARALLAXMAP && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer) Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n"); @@ -1524,7 +1551,7 @@ void GLSL_InitGPUShaders(void) attribs |= ATTR_TANGENT2 | ATTR_BITANGENT2; } } - + if (!GLSL_InitGPUShader(&tr.lightallShader[i], "lightall", attribs, qtrue, extradefines, qtrue, fallbackLightallShader_vp, fallbackLightallShader_fp, GENERIC_UNIFORM_COUNT)) { ri.Error(ERR_FATAL, "Could not load lightall shader!\n"); @@ -1551,7 +1578,8 @@ void GLSL_InitGPUShaders(void) GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARREFLECTANCE, "u_SpecularReflectance", GLSL_FLOAT); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_COLOR, "u_Color", GLSL_VEC4); + GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_BASECOLOR, "u_BaseColor", GLSL_VEC4); + GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTCOLOR, "u_VertColor", GLSL_VEC4); GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT); GLSL_FinishGPUShader(&tr.lightallShader[i]); @@ -1565,7 +1593,7 @@ void GLSL_InitGPUShaders(void) GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, TB_SHADOWMAP); qglUseProgramObjectARB(0); - numShaders++; + numLightShaders++; } @@ -1588,7 +1616,7 @@ void GLSL_InitGPUShaders(void) GLSL_FinishGPUShader(&tr.shadowmapShader); - numShaders++; + numEtcShaders++; attribs = ATTR_POSITION | ATTR_NORMAL; @@ -1614,12 +1642,38 @@ void GLSL_InitGPUShaders(void) GLSL_SetUniformInt(&tr.pshadowShader, PSHADOW_UNIFORM_SHADOWMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); - numShaders++; - + numEtcShaders++; endTime = ri.Milliseconds(); - ri.Printf(PRINT_ALL, "loaded %i GLSL shaders in %5.2f seconds\n", numShaders, (endTime - startTime) / 1000.0); + ri.Printf(PRINT_ALL, "loaded %i GLSL shaders (%i gen %i light %i etc) in %5.2f seconds\n", + numGenShaders + numLightShaders + numEtcShaders, numGenShaders, numLightShaders, + numEtcShaders, (endTime - startTime) / 1000.0); + + if (0) + { + GLSL_LoadGPUShaderText("Generic", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); + GLSL_LoadGPUShaderText("Generic", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); + + GLSL_LoadGPUShaderText("TextureColor", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); + GLSL_LoadGPUShaderText("TextureColor", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); + + GLSL_LoadGPUShaderText("FogPass", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); + GLSL_LoadGPUShaderText("FogPass", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); + + GLSL_LoadGPUShaderText("Dlight", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); + GLSL_LoadGPUShaderText("Dlight", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); + + GLSL_LoadGPUShaderText("Lightall", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); + GLSL_LoadGPUShaderText("Lightall", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); + + GLSL_LoadGPUShaderText("Shadowfill", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); + GLSL_LoadGPUShaderText("Shadowfill", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); + + GLSL_LoadGPUShaderText("Pshadow", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); + GLSL_LoadGPUShaderText("Pshadow", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); + } + } void GLSL_ShutdownGPUShaders(void) @@ -1987,10 +2041,7 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) switch (pStage->rgbGen) { - case CGEN_EXACT_VERTEX: case CGEN_LIGHTING_DIFFUSE: - case CGEN_VERTEX: - case CGEN_ONE_MINUS_VERTEX: shaderAttribs |= GENERICDEF_USE_RGBAGEN; break; default: @@ -2000,8 +2051,6 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) switch (pStage->alphaGen) { case AGEN_LIGHTING_SPECULAR: - case AGEN_VERTEX: - case AGEN_ONE_MINUS_VERTEX: case AGEN_PORTAL: case AGEN_FRESNEL: shaderAttribs |= GENERICDEF_USE_RGBAGEN; diff --git a/reaction/code/renderer/tr_image.c b/reaction/code/renderer/tr_image.c index 50f195f7..4ed337ed 100644 --- a/reaction/code/renderer/tr_image.c +++ b/reaction/code/renderer/tr_image.c @@ -679,6 +679,10 @@ static void Upload32( unsigned *data, } else { + if ( glConfig.textureCompression == TC_S3TC_ARB ) + { + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + } if ( r_texturebits->integer == 16 ) { internalFormat = GL_RGBA4; @@ -784,7 +788,156 @@ done: if ( resampledBuffer != 0 ) ri.Hunk_FreeTempMemory( resampledBuffer ); } - + + +static void EmptyTexture( int width, int height, qboolean mipmap, + qboolean picmip, qboolean lightMap, int *format, int *pUploadWidth, + int *pUploadHeight ) +{ + int samples; + int scaled_width, scaled_height; + GLenum internalFormat = GL_RGB; + + // + // convert to exact power of 2 sizes + // + for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) + ; + for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) + ; + if ( r_roundImagesDown->integer && scaled_width > width ) + scaled_width >>= 1; + if ( r_roundImagesDown->integer && scaled_height > height ) + scaled_height >>= 1; + + if ( scaled_width != width || scaled_height != height ) { + width = scaled_width; + height = scaled_height; + } + + // + // perform optional picmip operation + // + if ( picmip ) { + scaled_width >>= r_picmip->integer; + scaled_height >>= r_picmip->integer; + } + + // + // clamp to minimum size + // + if (scaled_width < 1) { + scaled_width = 1; + } + if (scaled_height < 1) { + scaled_height = 1; + } + + // + // clamp to the current upper OpenGL limit + // scale both axis down equally so we don't have to + // deal with a half mip resampling + // + while ( scaled_width > glConfig.maxTextureSize + || scaled_height > glConfig.maxTextureSize ) { + scaled_width >>= 1; + scaled_height >>= 1; + } + + // + // scan the texture for each channel's max values + // and verify if the alpha channel is being used or not + // + samples = 3; + + if(lightMap) + { + if(r_greyscale->integer) + internalFormat = GL_LUMINANCE; + else + internalFormat = GL_RGB; + } + else + { + samples = 4; + + if(r_greyscale->integer) + { + if(r_texturebits->integer == 16) + internalFormat = GL_LUMINANCE8_ALPHA8; + else if(r_texturebits->integer == 32) + internalFormat = GL_LUMINANCE16_ALPHA16; + else + internalFormat = GL_LUMINANCE_ALPHA; + } + else + { + if ( glConfig.textureCompression == TC_S3TC_ARB ) + { + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + } + if ( r_texturebits->integer == 16 ) + { + internalFormat = GL_RGBA4; + } + else if ( r_texturebits->integer == 32 ) + { + internalFormat = GL_RGBA8; + } + else + { + internalFormat = GL_RGBA; + } + } + } + + *pUploadWidth = scaled_width; + *pUploadHeight = scaled_height; + *format = internalFormat; + + qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); + + if (mipmap) + { + int miplevel; + + miplevel = 0; + while (scaled_width > 1 || scaled_height > 1) + { + scaled_width >>= 1; + scaled_height >>= 1; + if (scaled_width < 1) + scaled_width = 1; + if (scaled_height < 1) + scaled_height = 1; + miplevel++; + + qglTexImage2D (GL_TEXTURE_2D, miplevel, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); + } + } + + if (mipmap) + { + if ( glRefConfig.textureFilterAnisotropic ) + qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + (GLint)Com_Clamp( 1, glRefConfig.maxAnisotropy, r_ext_max_anisotropy->integer ) ); + + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + } + else + { + if ( glRefConfig.textureFilterAnisotropic ) + qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 ); + + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + } + + GL_CheckErrors(); +} + + static image_t *R_AllocImage(const char* name, int width, int height, qboolean mipmap, qboolean allowPicmip, int glWrapClampMode) { image_t *image; @@ -874,23 +1027,28 @@ image_t *R_CreateImage2( const char *name, const byte *pic, int width, int heigh { GL_Bind(image); - Upload32( (unsigned *)pic, image->width, image->height, - image->mipmap, - allowPicmip, - isLightmap, - &image->internalFormat, - &image->uploadWidth, - &image->uploadHeight ); + if (pic) + { + Upload32( (unsigned *)pic, image->width, image->height, image->mipmap, + allowPicmip, isLightmap, &image->internalFormat, &image->uploadWidth, + &image->uploadHeight ); + } + else + { + EmptyTexture(image->width, image->height, image->mipmap, allowPicmip, + isLightmap, &image->internalFormat, &image->uploadWidth, + &image->uploadHeight ); + } qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode ); } - qglBindTexture( GL_TEXTURE_2D, 0 ); + GL_SelectTexture( 0 ); - if ( image->TMU == 1 ) { - GL_SelectTexture( 0 ); - } + hash = generateHashValue(name); + image->next = hashTable[hash]; + hashTable[hash] = image; return image; } @@ -907,6 +1065,149 @@ image_t *R_CreateCubeImage( const char *name, const byte *pic, int width, int he return R_CreateImage2( name, pic, width, height, mipmap, allowPicmip, glWrapClampMode, qtrue); } +void R_UpdateSubImage( image_t *image, const byte *pic, int x, int y, int width, int height) +{ + unsigned *scaledBuffer = NULL; + unsigned *resampledBuffer = NULL; + int scaled_width, scaled_height, scaled_x, scaled_y; + unsigned *data = (unsigned *)pic; + + // + // convert to exact power of 2 sizes + // + for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) + ; + for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) + ; + if ( r_roundImagesDown->integer && scaled_width > width ) + scaled_width >>= 1; + if ( r_roundImagesDown->integer && scaled_height > height ) + scaled_height >>= 1; + + if ( scaled_width != width || scaled_height != height ) { + resampledBuffer = ri.Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 ); + ResampleTexture ( data, width, height, resampledBuffer, scaled_width, scaled_height); + data = resampledBuffer; + x = x * scaled_width / width; + y = y * scaled_height / height; + width = scaled_width; + height = scaled_height; + } + +// + // perform optional picmip operation + // + if ( image->allowPicmip ) { + scaled_width >>= r_picmip->integer; + scaled_height >>= r_picmip->integer; + } + + // + // clamp to minimum size + // + if (scaled_width < 1) { + scaled_width = 1; + } + if (scaled_height < 1) { + scaled_height = 1; + } + + // + // clamp to the current upper OpenGL limit + // scale both axis down equally so we don't have to + // deal with a half mip resampling + // + while ( scaled_width > glConfig.maxTextureSize + || scaled_height > glConfig.maxTextureSize ) { + scaled_width >>= 1; + scaled_height >>= 1; + } + + scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); + + if ( qglActiveTextureARB ) { + GL_SelectTexture( image->TMU ); + } + + GL_Bind(image); + + // copy or resample data as appropriate for first MIP level + if ( ( scaled_width == width ) && + ( scaled_height == height ) ) { + if (!image->mipmap) + { + scaled_x = x * scaled_width / width; + scaled_y = y * scaled_height / height; + qglTexSubImage2D( GL_TEXTURE_2D, 0, scaled_x, scaled_y, scaled_width, scaled_height, GL_RGBA, GL_UNSIGNED_BYTE, data ); + + GL_CheckErrors(); + goto done; + } + Com_Memcpy (scaledBuffer, data, width*height*4); + } + else + { + // use the normal mip-mapping function to go down from here + while ( width > scaled_width || height > scaled_height ) { + R_MipMap( (byte *)data, width, height ); + width >>= 1; + height >>= 1; + x >>= 1; + y >>= 1; + if ( width < 1 ) { + width = 1; + } + if ( height < 1 ) { + height = 1; + } + } + Com_Memcpy( scaledBuffer, data, width * height * 4 ); + } + + R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, !image->mipmap ); + + scaled_x = x * scaled_width / width; + scaled_y = y * scaled_height / height; + qglTexSubImage2D( GL_TEXTURE_2D, 0, scaled_x, scaled_y, scaled_width, scaled_height, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer ); + + if (image->mipmap) + { + int miplevel; + + miplevel = 0; + while (scaled_width > 1 || scaled_height > 1) + { + R_MipMap( (byte *)scaledBuffer, scaled_width, scaled_height ); + scaled_width >>= 1; + scaled_height >>= 1; + if (scaled_width < 1) + scaled_width = 1; + if (scaled_height < 1) + scaled_height = 1; + miplevel++; + + if ( r_colorMipLevels->integer ) { + R_BlendOverTexture( (byte *)scaledBuffer, scaled_width * scaled_height, mipBlendColors[miplevel] ); + } + + scaled_x = x * scaled_width / width; + scaled_y = y * scaled_height / height; + qglTexSubImage2D( GL_TEXTURE_2D, 0, scaled_x, scaled_y, scaled_width, scaled_height, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer ); + } + } + +done: + + GL_SelectTexture( 0 ); + + GL_CheckErrors(); + + if ( scaledBuffer != 0 ) + ri.Hunk_FreeTempMemory( scaledBuffer ); + if ( resampledBuffer != 0 ) + ri.Hunk_FreeTempMemory( resampledBuffer ); +} + //=================================================================== typedef struct @@ -1252,7 +1553,7 @@ void R_CreateBuiltinImages( void ) { if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer && glRefConfig.glsl && r_arb_shader_objects->integer) { - if (r_dlightShadows->integer) + if (r_dlightMode->integer >= 2) { for( x = 0; x < MAX_DLIGHTS; x++) { diff --git a/reaction/code/renderer/tr_init.c b/reaction/code/renderer/tr_init.c index 2fa25379..f10a409e 100644 --- a/reaction/code/renderer/tr_init.c +++ b/reaction/code/renderer/tr_init.c @@ -32,6 +32,7 @@ float displayAspect = 0.0f; glstate_t glState; static void GfxInfo_f( void ); +static void GfxMemInfo_f( void ); cvar_t *r_flareSize; cvar_t *r_flareFade; @@ -107,7 +108,8 @@ cvar_t *r_deluxeMapping; cvar_t *r_parallaxMapping; cvar_t *r_normalAmbient; cvar_t *r_recalcMD3Normals; -cvar_t *r_dlightShadows; +cvar_t *r_mergeLightmaps; +cvar_t *r_dlightMode; cvar_t *r_pshadowDist; cvar_t *r_ignoreGLErrors; @@ -1039,6 +1041,58 @@ void GfxInfo_f( void ) } } +/* +================ +GfxMemInfo_f +================ +*/ +void GfxMemInfo_f( void ) +{ + switch (glRefConfig.memInfo) + { + case MI_NONE: + { + ri.Printf(PRINT_ALL, "No extension found for GPU memory info.\n"); + } + break; + case MI_NVX: + { + int value; + + qglGetIntegerv(GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &value); + ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX: %ikb\n", value); + + qglGetIntegerv(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &value); + ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX: %ikb\n", value); + + qglGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &value); + ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX: %ikb\n", value); + + qglGetIntegerv(GPU_MEMORY_INFO_EVICTION_COUNT_NVX, &value); + ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_EVICTION_COUNT_NVX: %i\n", value); + + qglGetIntegerv(GPU_MEMORY_INFO_EVICTED_MEMORY_NVX, &value); + ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_EVICTED_MEMORY_NVX: %ikb\n", value); + } + break; + case MI_ATI: + { + // GL_ATI_meminfo + int value[4]; + + qglGetIntegerv(VBO_FREE_MEMORY_ATI, &value[0]); + ri.Printf(PRINT_ALL, "VBO_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]); + + qglGetIntegerv(TEXTURE_FREE_MEMORY_ATI, &value[0]); + ri.Printf(PRINT_ALL, "TEXTURE_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]); + + qglGetIntegerv(RENDERBUFFER_FREE_MEMORY_ATI, &value[0]); + ri.Printf(PRINT_ALL, "RENDERBUFFER_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]); + } + break; + } +} + /* =============== R_Register @@ -1098,9 +1152,10 @@ void R_Register( void ) r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_normalAmbient = ri.Cvar_Get( "r_normalAmbient", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_dlightShadows = ri.Cvar_Get( "r_dlightShadows", "0", CVAR_ARCHIVE | CVAR_LATCH ); + r_dlightMode = ri.Cvar_Get( "r_dlightMode", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_pshadowDist = ri.Cvar_Get( "r_pshadowDist", "128", CVAR_ARCHIVE ); r_recalcMD3Normals = ri.Cvar_Get( "r_recalcMD3Normals", "0", CVAR_ARCHIVE | CVAR_LATCH ); + r_mergeLightmaps = ri.Cvar_Get( "r_mergeLightmaps", "1", CVAR_ARCHIVE | CVAR_LATCH ); // // temporary latched variables that can only change over a restart @@ -1210,6 +1265,7 @@ void R_Register( void ) ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f ); ri.Cmd_AddCommand( "screenshotJPEG", R_ScreenShotJPEG_f ); ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f ); + ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f ); } void R_InitQueries(void) diff --git a/reaction/code/renderer/tr_local.h b/reaction/code/renderer/tr_local.h index 3254891a..4709b244 100644 --- a/reaction/code/renderer/tr_local.h +++ b/reaction/code/renderer/tr_local.h @@ -56,11 +56,11 @@ typedef unsigned int glIndex_t; #define MAX_STATES_PER_SHADER 32 #define MAX_STATE_NAME 32 + #define MAX_VISCOUNTS 5 #define MAX_VBOS 4096 #define MAX_IBOS 4096 - typedef struct dlight_s { vec3_t origin; vec3_t color; // range from 0.0 to 1.0, should be color normalized @@ -821,7 +821,8 @@ enum GENERIC_UNIFORM_DEFORMPARAMS, GENERIC_UNIFORM_COLORGEN, GENERIC_UNIFORM_ALPHAGEN, - GENERIC_UNIFORM_COLOR, + GENERIC_UNIFORM_BASECOLOR, + GENERIC_UNIFORM_VERTCOLOR, GENERIC_UNIFORM_AMBIENTLIGHT, GENERIC_UNIFORM_DIRECTEDLIGHT, GENERIC_UNIFORM_LIGHTORIGIN, @@ -830,7 +831,7 @@ enum GENERIC_UNIFORM_FOGDISTANCE, GENERIC_UNIFORM_FOGDEPTH, GENERIC_UNIFORM_FOGEYET, - GENERIC_UNIFORM_FOGADJUSTCOLORS, + GENERIC_UNIFORM_FOGCOLORMASK, GENERIC_UNIFORM_MODELMATRIX, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, GENERIC_UNIFORM_TIME, @@ -1514,7 +1515,7 @@ the bits are allocated as follows: #if (QSORT_SHADERNUM_SHIFT+SHADERNUM_BITS) > 32 #error "Need to update sorting, too many bits." #endif -#define QSORT_PSHADOW_SHIFT 1 +#define QSORT_PSHADOW_SHIFT 1 extern int gl_filter_min, gl_filter_max; @@ -1560,6 +1561,12 @@ typedef struct { matrix_t modelviewProjection; } glstate_t; +typedef enum { + MI_NONE, + MI_NVX, + MI_ATI +} memInfo_t; + // We can't change glConfig_t without breaking DLL/vms compatibility, so // store extensions we have here. typedef struct { @@ -1585,6 +1592,8 @@ typedef struct { qboolean shaderObjects; qboolean vertexShader; qboolean glsl; + + memInfo_t memInfo; } glRefConfig_t; @@ -1934,9 +1943,10 @@ extern cvar_t *r_specularMapping; extern cvar_t *r_deluxeMapping; extern cvar_t *r_parallaxMapping; extern cvar_t *r_normalAmbient; -extern cvar_t *r_dlightShadows; +extern cvar_t *r_dlightMode; extern cvar_t *r_pshadowDist; extern cvar_t *r_recalcMD3Normals; +extern cvar_t *r_mergeLightmaps; extern cvar_t *r_greyscale; @@ -2073,6 +2083,7 @@ image_t *R_FindImageFile( const char *name, qboolean mipmap, qboolean allowPicm image_t *R_CreateImage( const char *name, const byte *pic, int width, int height, qboolean mipmap , qboolean allowPicmip, int wrapClampMode ); +void R_UpdateSubImage( image_t *image, const byte *pic, int x, int y, int width, int height); qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode ); void R_SetColorMappings( void ); diff --git a/reaction/code/renderer/tr_main.c b/reaction/code/renderer/tr_main.c index fc5133d1..751e5de9 100644 --- a/reaction/code/renderer/tr_main.c +++ b/reaction/code/renderer/tr_main.c @@ -2347,7 +2347,7 @@ void R_RenderPshadowMaps(const refdef_t *fd) { trRefEntity_t fakeEnt; pshadow_t *shadow = &tr.refdef.pshadows[i]; - vec3_t right; + vec3_t up; vec3_t lightDir; #if 0 @@ -2367,16 +2367,16 @@ void R_RenderPshadowMaps(const refdef_t *fd) VectorMA(shadow->viewOrigin, shadow->viewRadius, lightDir, shadow->lightOrigin); - // make up a projection, spin doesn't matter + // make up a projection, up doesn't matter VectorScale(lightDir, -1.0f, shadow->lightViewAxis[0]); - VectorSet(right, 0, 0, -1); + VectorSet(up, 0, 0, -1); - if ( abs(DotProduct(right, shadow->lightViewAxis[0])) > 0.9f ) + if ( abs(DotProduct(up, shadow->lightViewAxis[0])) > 0.9f ) { - VectorSet(right, -1, 0, 0); + VectorSet(up, -1, 0, 0); } - CrossProduct(shadow->lightViewAxis[0], right, shadow->lightViewAxis[1]); + CrossProduct(shadow->lightViewAxis[0], up, shadow->lightViewAxis[1]); VectorNormalize(shadow->lightViewAxis[1]); CrossProduct(shadow->lightViewAxis[0], shadow->lightViewAxis[1], shadow->lightViewAxis[2]); diff --git a/reaction/code/renderer/tr_scene.c b/reaction/code/renderer/tr_scene.c index 14105603..0d353e81 100644 --- a/reaction/code/renderer/tr_scene.c +++ b/reaction/code/renderer/tr_scene.c @@ -404,7 +404,7 @@ void RE_RenderScene( const refdef_t *fd ) { tr.sceneCount++; // SmileTheory: playing with shadow mapping - if (!( fd->rdflags & RDF_NOWORLDMODEL ) && tr.refdef.num_dlights && r_dlightShadows->integer + if (!( fd->rdflags & RDF_NOWORLDMODEL ) && tr.refdef.num_dlights && r_dlightMode->integer >= 2 && glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer && glRefConfig.glsl && r_arb_shader_objects->integer) { diff --git a/reaction/code/renderer/tr_shade.c b/reaction/code/renderer/tr_shade.c index 15fe74b6..f0ed8ef8 100644 --- a/reaction/code/renderer/tr_shade.c +++ b/reaction/code/renderer/tr_shade.c @@ -1192,7 +1192,8 @@ static void ProjectDlightTextureVBOGLSL( void ) { } -static qboolean ComputeHelperColor( shaderStage_t *pStage, vec4_t color); +static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor ); +static void ComputeFogColorMask( shaderStage_t *pStage, vec4_t fogColorMask ); static void ComputeFogValues(vec4_t fogDistanceVector, vec4_t fogDepthVector, float *eyeT) { @@ -1334,18 +1335,26 @@ static void ForwardDlightVBOGLSL( void ) { } if ( input->fogNum ) { + vec4_t fogColorMask; + GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDISTANCE, fogDistanceVector); GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDEPTH, fogDepthVector); GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_FOGEYET, eyeT); - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_FOGADJUSTCOLORS, pStage->adjustColorsForFog); - } - else - { - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_FOGADJUSTCOLORS, 0); + + ComputeFogColorMask(pStage, fogColorMask); + + GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGCOLORMASK, fogColorMask); } - if (ComputeHelperColor(pStage, vector)) - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_COLOR, vector); + { + vec4_t baseColor; + vec4_t vertColor; + + ComputeShaderColors(pStage, baseColor, vertColor); + + GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, baseColor); + GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, vertColor); + } if (pStage->alphaGen == AGEN_PORTAL) { @@ -1384,7 +1393,7 @@ static void ForwardDlightVBOGLSL( void ) { if (pStage->bundle[TB_SPECULARMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP); - if (r_dlightShadows->integer) + if (r_dlightMode->integer >= 2) { GL_SelectTexture(TB_SHADOWMAP); GL_BindCubemap(tr.shadowCubemaps[l]); @@ -1416,7 +1425,6 @@ static void ForwardDlightVBOGLSL( void ) { static void ProjectPshadowVBOGLSL( void ) { int l; vec3_t origin; - float scale; float radius; int deformGen; @@ -1442,7 +1450,6 @@ static void ProjectPshadowVBOGLSL( void ) { ps = &backEnd.refdef.pshadows[l]; VectorCopy( ps->lightOrigin, origin ); radius = ps->lightRadius; - scale = 1.0f / radius; sp = &tr.pshadowShader; @@ -1454,15 +1461,15 @@ static void ProjectPshadowVBOGLSL( void ) { vector[3] = 1.0f; GLSL_SetUniformVec4(sp, PSHADOW_UNIFORM_LIGHTORIGIN, vector); - VectorScale(ps->lightViewAxis[0], -1.0f / ps->viewRadius, vector); + VectorScale(ps->lightViewAxis[0], 1.0f / ps->viewRadius, vector); GLSL_SetUniformVec3(sp, PSHADOW_UNIFORM_LIGHTFORWARD, vector); VectorScale(ps->lightViewAxis[1], 1.0f / ps->viewRadius, vector); - GLSL_SetUniformVec3(sp, PSHADOW_UNIFORM_LIGHTUP, vector); - - VectorScale(ps->lightViewAxis[2], -1.0f / ps->viewRadius, vector); GLSL_SetUniformVec3(sp, PSHADOW_UNIFORM_LIGHTRIGHT, vector); + VectorScale(ps->lightViewAxis[2], 1.0f / ps->viewRadius, vector); + GLSL_SetUniformVec3(sp, PSHADOW_UNIFORM_LIGHTUP, vector); + GLSL_SetUniformFloat(sp, PSHADOW_UNIFORM_LIGHTRADIUS, radius); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light @@ -1811,43 +1818,78 @@ static void ComputeColors( shaderStage_t *pStage ) } } -static qboolean ComputeHelperColor( shaderStage_t *pStage, vec4_t color) +static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor ) { - qboolean set = qfalse; - - color[0] = - color[1] = - color[2] = - color[3] = 1.0f; - // // rgbGen // switch ( pStage->rgbGen ) { case CGEN_IDENTITY: - set = qtrue; + baseColor[0] = + baseColor[1] = + baseColor[2] = + baseColor[3] = 1.0f; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 0.0f; break; case CGEN_IDENTITY_LIGHTING: - color[0] = - color[1] = - color[2] = - color[3] = tr.identityLight; // FIXME: Code was like this in quake 3, is this a bug? - set = qtrue; + baseColor[0] = + baseColor[1] = + baseColor[2] = tr.identityLight; + baseColor[3] = 1.0f; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 0.0f; + break; + case CGEN_EXACT_VERTEX: + baseColor[0] = + baseColor[1] = + baseColor[2] = + baseColor[3] = 0.0f; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 1.0f; break; case CGEN_CONST: - color[0] = pStage->constantColor[0] / 255.0f; - color[1] = pStage->constantColor[1] / 255.0f; - color[2] = pStage->constantColor[2] / 255.0f; - color[3] = pStage->constantColor[3] / 255.0f; - set = qtrue; + baseColor[0] = pStage->constantColor[0] / 255.0f; + baseColor[1] = pStage->constantColor[1] / 255.0f; + baseColor[2] = pStage->constantColor[2] / 255.0f; + baseColor[3] = pStage->constantColor[3] / 255.0f; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 0.0f; break; case CGEN_VERTEX: + baseColor[0] = + baseColor[1] = + baseColor[2] = + baseColor[3] = 0.0f; + + vertColor[0] = + vertColor[1] = + vertColor[2] = tr.identityLight; + vertColor[3] = 1.0f; + break; case CGEN_ONE_MINUS_VERTEX: - color[0] = - color[1] = - color[2] = tr.identityLight; - set = qtrue; + baseColor[0] = + baseColor[1] = + baseColor[2] = tr.identityLight; + baseColor[3] = 1.0f; + + vertColor[0] = + vertColor[1] = + vertColor[2] = -tr.identityLight; + vertColor[3] = 0.0f; break; case CGEN_FOG: { @@ -1855,12 +1897,16 @@ static qboolean ComputeHelperColor( shaderStage_t *pStage, vec4_t color) fog = tr.world->fogs + tess.fogNum; - color[0] = ((unsigned char *)(&fog->colorInt))[0] / 255.0f; - color[1] = ((unsigned char *)(&fog->colorInt))[1] / 255.0f; - color[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f; - color[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f; + baseColor[0] = ((unsigned char *)(&fog->colorInt))[0] / 255.0f; + baseColor[1] = ((unsigned char *)(&fog->colorInt))[1] / 255.0f; + baseColor[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f; + baseColor[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f; } - set = qtrue; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 0.0f; break; case CGEN_WAVEFORM: { @@ -1881,35 +1927,56 @@ static qboolean ComputeHelperColor( shaderStage_t *pStage, vec4_t color) glow = 1; } - color[0] = - color[1] = - color[2] = glow; + baseColor[0] = + baseColor[1] = + baseColor[2] = glow; + baseColor[3] = 1.0f; } - set = qtrue; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 0.0f; break; case CGEN_ENTITY: if (backEnd.currentEntity) { - color[0] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[0] / 255.0f; - color[1] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[1] / 255.0f; - color[2] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f; - color[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; + baseColor[0] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[0] / 255.0f; + baseColor[1] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[1] / 255.0f; + baseColor[2] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f; + baseColor[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; } - set = qtrue; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 0.0f; break; case CGEN_ONE_MINUS_ENTITY: if (backEnd.currentEntity) { - color[0] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[0] / 255.0f; - color[1] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[1] / 255.0f; - color[2] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f; - color[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; + baseColor[0] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[0] / 255.0f; + baseColor[1] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[1] / 255.0f; + baseColor[2] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f; + baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; } - set = qtrue; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 0.0f; break; case CGEN_LIGHTING_DIFFUSE: - case CGEN_EXACT_VERTEX: case CGEN_BAD: + baseColor[0] = + baseColor[1] = + baseColor[2] = + baseColor[3] = 1.0f; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 0.0f; break; } @@ -1919,15 +1986,14 @@ static qboolean ComputeHelperColor( shaderStage_t *pStage, vec4_t color) switch ( pStage->alphaGen ) { case AGEN_SKIP: - set = qtrue; break; case AGEN_IDENTITY: - color[3] = 1.0f; - set = qtrue; + baseColor[3] = 1.0f; + vertColor[3] = 0.0f; break; case AGEN_CONST: - color[3] = pStage->constantColor[3] / 255.0f; - set = qtrue; + baseColor[3] = pStage->constantColor[3] / 255.0f; + vertColor[3] = 0.0f; break; case AGEN_WAVEFORM: // From RB_CalcWaveAlpha @@ -1935,37 +2001,41 @@ static qboolean ComputeHelperColor( shaderStage_t *pStage, vec4_t color) float glow; waveForm_t *wf = &pStage->alphaWave; glow = EvalWaveFormClamped( wf ); - color[3] = glow; + baseColor[3] = glow; } - set = qtrue; + vertColor[3] = 0.0f; break; case AGEN_ENTITY: if (backEnd.currentEntity) { - color[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; + baseColor[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; } - set = qtrue; + vertColor[3] = 0.0f; break; case AGEN_ONE_MINUS_ENTITY: if (backEnd.currentEntity) { - color[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; + baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; } - set = qtrue; + vertColor[3] = 0.0f; + break; + case AGEN_VERTEX: + baseColor[3] = 0.0f; + vertColor[3] = 1.0f; + break; + case AGEN_ONE_MINUS_VERTEX: + baseColor[3] = 1.0f; + vertColor[3] = -1.0f; break; case AGEN_LIGHTING_SPECULAR: - case AGEN_VERTEX: - case AGEN_ONE_MINUS_VERTEX: case AGEN_PORTAL: case AGEN_FRESNEL: // Done entirely in vertex program + baseColor[3] = 1.0f; + vertColor[3] = 0.0f; break; } - // - // pStage->adjustColorsForFog is done in the vertex program now - // - // FIXME: find some way to implement this. #if 0 // if in greyscale rendering mode turn all color values into greyscale. @@ -1980,10 +2050,40 @@ static qboolean ComputeHelperColor( shaderStage_t *pStage, vec4_t color) } } #endif - - return set; } +static void ComputeFogColorMask( shaderStage_t *pStage, vec4_t fogColorMask ) +{ + switch(pStage->adjustColorsForFog) + { + case ACFF_MODULATE_RGB: + fogColorMask[0] = + fogColorMask[1] = + fogColorMask[2] = 1.0f; + fogColorMask[3] = 0.0f; + break; + case ACFF_MODULATE_ALPHA: + fogColorMask[0] = + fogColorMask[1] = + fogColorMask[2] = 0.0f; + fogColorMask[3] = 1.0f; + break; + case ACFF_MODULATE_RGBA: + fogColorMask[0] = + fogColorMask[1] = + fogColorMask[2] = + fogColorMask[3] = 1.0f; + break; + default: + fogColorMask[0] = + fogColorMask[1] = + fogColorMask[2] = + fogColorMask[3] = 0.0f; + break; + } +} + + /* =============== ComputeColorMatrix @@ -2684,10 +2784,17 @@ static void RB_IterateStagesGenericVBOGLSL( shaderCommands_t *input ) if (pStage->glslShaderGroup) { int index = pStage->glslShaderIndex; + + if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) + { + index |= LIGHTDEF_ENTITY; + } + if (r_lightmap->integer && index & LIGHTDEF_USE_LIGHTMAP) { index = LIGHTDEF_USE_LIGHTMAP; } + sp = &pStage->glslShaderGroup[index]; if (pStage->glslShaderGroup == tr.lightallShader) @@ -2725,13 +2832,15 @@ static void RB_IterateStagesGenericVBOGLSL( shaderCommands_t *input ) GL_State( pStage->stateBits ); { - vec4_t color; + vec4_t baseColor; + vec4_t vertColor; - if (ComputeHelperColor(pStage, color)) - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_COLOR, color); + ComputeShaderColors(pStage, baseColor, vertColor); + + GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, baseColor); + GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, vertColor); } - if (pStage->rgbGen == CGEN_LIGHTING_DIFFUSE) { vec4_t vec; @@ -2759,11 +2868,11 @@ static void RB_IterateStagesGenericVBOGLSL( shaderCommands_t *input ) if ( input->fogNum ) { - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_FOGADJUSTCOLORS, pStage->adjustColorsForFog); - } - else - { - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_FOGADJUSTCOLORS, 0); + vec4_t fogColorMask; + + ComputeFogColorMask(pStage, fogColorMask); + + GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGCOLORMASK, fogColorMask); } ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); @@ -3164,7 +3273,8 @@ void RB_StageIteratorGenericVBO( void ) && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) { if (glRefConfig.glsl && r_arb_shader_objects->integer) { - if (tess.shader->numUnfoggedPasses == 1 && tess.xstages[0]->glslShaderGroup == tr.lightallShader) + if (tess.shader->numUnfoggedPasses == 1 && tess.xstages[0]->glslShaderGroup == tr.lightallShader + && r_dlightMode->integer) { ForwardDlightVBOGLSL(); } diff --git a/reaction/code/renderer/tr_shader.c b/reaction/code/renderer/tr_shader.c index ecc35dbe..c216a255 100644 --- a/reaction/code/renderer/tr_shader.c +++ b/reaction/code/renderer/tr_shader.c @@ -658,6 +658,27 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); return qfalse; } + + //if ( r_autoFindNormalMap->integer ) + { + char filename[MAX_QPATH]; + + COM_StripExtension(token, filename, sizeof(filename)); + Q_strcat(filename, sizeof(filename), "_normal"); + + stage->bundle[TB_NORMALMAP].image[0] = R_FindImageFile( filename, !shader.noMipMaps, !shader.noPicMip, GL_REPEAT ); + } + + //if ( r_autoFindSpecularMap->integer ) + { + char filename[MAX_QPATH]; + + COM_StripExtension(token, filename, sizeof(filename)); + Q_strcat(filename, sizeof(filename), "_specular"); + + stage->bundle[TB_SPECULARMAP].image[0] = R_FindImageFile( filename, !shader.noMipMaps, !shader.noPicMip, GL_REPEAT ); + stage->specularReflectance = 0.04f; + } } } // @@ -2089,7 +2110,7 @@ static qboolean CollapseMultitexture( void ) { static void CollapseStagesToLightall(shaderStage_t *diffuse, shaderStage_t *normal, shaderStage_t *specular, shaderStage_t *lightmap, - qboolean isWorld, qboolean parallax, qboolean environment) + qboolean useLightVector, qboolean parallax, qboolean environment) { int defs = 0; @@ -2105,14 +2126,12 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse, defs |= LIGHTDEF_USE_LIGHTMAP; } - if (tr.worldDeluxeMapping && lightmap) + if ((tr.worldDeluxeMapping || r_deluxeMapping->integer == 2) && lightmap) { //ri.Printf(PRINT_ALL, ", deluxemap"); diffuse->bundle[TB_DELUXEMAP] = lightmap->bundle[0]; diffuse->bundle[TB_DELUXEMAP].image[0] = tr.deluxemaps[shader.lightmapIndex]; defs |= LIGHTDEF_USE_DELUXEMAP; - if (parallax) - defs |= LIGHTDEF_USE_PARALLAXMAP; } if (normal) @@ -2120,6 +2139,15 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse, //ri.Printf(PRINT_ALL, ", normalmap %s", normal->bundle[0].image[0]->imgName); diffuse->bundle[TB_NORMALMAP] = normal->bundle[0]; defs |= LIGHTDEF_USE_NORMALMAP; + if (parallax) + defs |= LIGHTDEF_USE_PARALLAXMAP; + } + else if (diffuse->bundle[TB_NORMALMAP].image[0]) + { + image_t *tmpImg = diffuse->bundle[TB_NORMALMAP].image[0]; + diffuse->bundle[TB_NORMALMAP] = diffuse->bundle[TB_DIFFUSEMAP]; + diffuse->bundle[TB_NORMALMAP].image[0] = tmpImg; + defs |= LIGHTDEF_USE_NORMALMAP; } if (specular) @@ -2129,10 +2157,17 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse, diffuse->specularReflectance = specular->specularReflectance; defs |= LIGHTDEF_USE_SPECULARMAP; } - - if (!isWorld) + else if (diffuse->bundle[TB_SPECULARMAP].image[0]) { - defs |= LIGHTDEF_ENTITY | LIGHTDEF_USE_LIGHT_VECTOR; + image_t *tmpImg = diffuse->bundle[TB_SPECULARMAP].image[0]; + diffuse->bundle[TB_SPECULARMAP] = diffuse->bundle[TB_DIFFUSEMAP]; + diffuse->bundle[TB_SPECULARMAP].image[0] = tmpImg; + defs |= LIGHTDEF_USE_SPECULARMAP; + } + + if (useLightVector) + { + defs |= LIGHTDEF_USE_LIGHT_VECTOR; } if (environment) @@ -2193,6 +2228,12 @@ static qboolean CollapseStagesToGLSL(void) if (!pStage->active) continue; + if (pStage->adjustColorsForFog) + { + skip = qtrue; + break; + } + if (pStage->bundle[0].isLightmap) { int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); @@ -2216,22 +2257,9 @@ static qboolean CollapseStagesToGLSL(void) break; } - switch(pStage->rgbGen) - { - //case CGEN_LIGHTING_DIFFUSE: - case CGEN_EXACT_VERTEX: - case CGEN_VERTEX: - case CGEN_ONE_MINUS_VERTEX: - skip = qtrue; - break; - default: - break; - } switch(pStage->alphaGen) { case AGEN_LIGHTING_SPECULAR: - case AGEN_VERTEX: - case AGEN_ONE_MINUS_VERTEX: case AGEN_PORTAL: case AGEN_FRESNEL: skip = qtrue; @@ -2248,7 +2276,7 @@ static qboolean CollapseStagesToGLSL(void) { shaderStage_t *pStage = &stages[i]; shaderStage_t *diffuse, *normal, *specular, *lightmap; - qboolean parallax, environment, world; + qboolean parallax, environment, entity; if (!pStage->active) continue; @@ -2261,13 +2289,13 @@ static qboolean CollapseStagesToGLSL(void) if (pStage->bundle[0].isLightmap) continue; - diffuse = NULL; + diffuse = pStage; normal = NULL; parallax = qfalse; specular = NULL; lightmap = NULL; - // find matching normal, specular, and lightmap for this diffuse stage + // we have a diffuse map, find matching normal, specular, and lightmap for (j = i + 1; j < MAX_SHADER_STAGES; j++) { shaderStage_t *pStage2 = &stages[j]; @@ -2311,21 +2339,19 @@ static qboolean CollapseStagesToGLSL(void) } } - diffuse = pStage; - environment = qfalse; if (diffuse->bundle[0].tcGen == TCGEN_ENVIRONMENT_MAPPED) { environment = qtrue; } - world = qtrue; + entity = qfalse; if (diffuse->rgbGen == CGEN_LIGHTING_DIFFUSE) { - world = qfalse; + entity = qtrue; } - CollapseStagesToLightall(diffuse, normal, specular, lightmap, world, parallax, environment); + CollapseStagesToLightall(diffuse, normal, specular, lightmap, entity, parallax, environment); } // deactivate lightmap stages diff --git a/reaction/code/sdl/sdl_glimp.c b/reaction/code/sdl/sdl_glimp.c index c5876275..2475098e 100644 --- a/reaction/code/sdl/sdl_glimp.c +++ b/reaction/code/sdl/sdl_glimp.c @@ -209,6 +209,23 @@ ADD_ALL_EXTENSION_FUNCTIONS; #undef HANDLE_EXT_FUNC +// GL_ARB_texture_compression +void (APIENTRY * qglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, + GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +void (APIENTRY * qglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, + GLint border, GLsizei imageSize, const GLvoid *data); +void (APIENTRY * qglCompressedTexImage1DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, + GLsizei imageSize, const GLvoid *data); +void (APIENTRY * qglCompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +void (APIENTRY * qglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, + GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +void (APIENTRY * qglCompressedTexSubImage1DARB)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, + GLsizei imageSize, const GLvoid *data); +void (APIENTRY * qglGetCompressedTexImageARB)(GLenum target, GLint lod, + GLvoid *img); + + #if defined(WIN32) // WGL_ARB_create_context HGLRC(APIENTRY * qwglCreateContextAttribsARB) (HDC hdC, HGLRC hShareContext, const int *attribList); @@ -744,6 +761,14 @@ static void GLimp_InitExtensions( void ) { glConfig.textureCompression = TC_S3TC_ARB; ri.Printf( PRINT_ALL, "...using GL_EXT_texture_compression_s3tc\n" ); + + qglCompressedTexImage3DARB = SDL_GL_GetProcAddress( "glCompressedTexImage3DARB" ); + qglCompressedTexImage2DARB = SDL_GL_GetProcAddress( "glCompressedTexImage2DARB" ); + qglCompressedTexImage1DARB = SDL_GL_GetProcAddress( "glCompressedTexImage1DARB" ); + qglCompressedTexSubImage3DARB = SDL_GL_GetProcAddress( "glCompressedTexSubImage3DARB" ); + qglCompressedTexSubImage2DARB = SDL_GL_GetProcAddress( "glCompressedTexSubImage2DARB" ); + qglCompressedTexSubImage1DARB = SDL_GL_GetProcAddress( "glCompressedTexSubImage1DARB" ); + qglGetCompressedTexImageARB = SDL_GL_GetProcAddress( "glGetCompressedTexImageARB" ); } else { @@ -1182,6 +1207,17 @@ static void GLimp_InitExtensions( void ) (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer); + glRefConfig.memInfo = MI_NONE; + + if( GLimp_HaveExtension( "GL_NVX_gpu_memory_info")) + { + glRefConfig.memInfo = MI_NVX; + } + else if( GLimp_HaveExtension( "GL_ATI_meminfo")) + { + glRefConfig.memInfo = MI_ATI; + } + } #define R_MODE_FALLBACK 3 // 640 * 480