X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=3d35a29cd23703a144e66142e0ca0518a951b120;hb=944af47a3f467931c9102d745ad60d54c4c18c27;hp=12be21aa5b6555315dc939a2db233a49523101a8;hpb=b6f04e7a3b73a2b2449add51f1e48097c0feec8c;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index 12be21aa..3d35a29c 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "r_shadow.h" #include "polygon.h" +#include "image.h" mempool_t *r_main_mempool; rtexturepool_t *r_main_texturepool; @@ -34,6 +35,7 @@ r_view_t r_view; r_viewcache_t r_viewcache; cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" }; +cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"}; cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"}; cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"}; cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"}; @@ -51,7 +53,7 @@ cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", " cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"}; cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"}; cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"}; -cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"}; +cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"}; cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"}; cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"}; cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"}; @@ -147,9 +149,6 @@ r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX]; // currently selected permutation r_glsl_permutation_t *r_glsl_permutation; -// temporary variable used by a macro -int fogtableindex; - // vertex coordinates for a quad that covers the screen exactly const static float r_screenvertex3f[12] = { @@ -202,31 +201,16 @@ void FOG_clear(void) r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f; } -// FIXME: move this to client? -void FOG_registercvars(void) +float FogPoint_World(const vec3_t p) { - int x; - double r, alpha; - - if (gamemode == GAME_NEHAHRA) - { - Cvar_RegisterVariable (&gl_fogenable); - Cvar_RegisterVariable (&gl_fogdensity); - Cvar_RegisterVariable (&gl_fogred); - Cvar_RegisterVariable (&gl_foggreen); - Cvar_RegisterVariable (&gl_fogblue); - Cvar_RegisterVariable (&gl_fogstart); - Cvar_RegisterVariable (&gl_fogend); - } + int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier); + return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)]; +} - r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH); - for (x = 0;x < FOGTABLEWIDTH;x++) - { - alpha = exp(r / ((double)x*(double)x)); - if (x == FOGTABLEWIDTH - 1) - alpha = 1; - r_refdef.fogtable[x] = bound(0, alpha, 1); - } +float FogPoint_Model(const vec3_t p) +{ + int fogmasktableindex = (int)(VectorDistance((p), rsurface_modelorg) * r_refdef.fogmasktabledistmultiplier); + return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)]; } static void R_BuildBlankTextures(void) @@ -352,25 +336,19 @@ static void R_BuildNormalizationCube(void) static void R_BuildFogTexture(void) { int x, b; - double r, alpha; #define FOGWIDTH 64 unsigned char data1[FOGWIDTH][4]; //unsigned char data2[FOGWIDTH][4]; - r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH); for (x = 0;x < FOGWIDTH;x++) { - alpha = exp(r / ((double)x*(double)x)); - if (x == FOGWIDTH - 1) - alpha = 1; - b = (int)(256.0 * alpha); - b = bound(0, b, 255); - data1[x][0] = 255 - b; - data1[x][1] = 255 - b; - data1[x][2] = 255 - b; + b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255); + data1[x][0] = b; + data1[x][1] = b; + data1[x][2] = b; data1[x][3] = 255; - //data2[x][0] = b; - //data2[x][1] = b; - //data2[x][2] = b; + //data2[x][0] = 255 - b; + //data2[x][1] = 255 - b; + //data2[x][2] = 255 - b; //data2[x][3] = 255; } r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL); @@ -511,50 +489,55 @@ static const char *builtinshaderstring = "uniform myhalf SpecularScale;\n" "uniform myhalf SpecularPower;\n" "\n" +"#ifdef USEOFFSETMAPPING\n" "vec2 OffsetMapping(vec2 TexCoord)\n" "{\n" -" vec3 eyedir = vec3(normalize(EyeVector));\n" -" float depthbias = 1.0 - eyedir.z; // should this be a -?\n" -" depthbias = 1.0 - depthbias * depthbias;\n" -"\n" "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n" " // 14 sample relief mapping: linear search and then binary search\n" -" //vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n" -" //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n" -" vec3 OffsetVector = vec3(eyedir.xy * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n" -" vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n" -" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n" -" TexCoord = RT.xy;\n" +" // this basically steps forward a small amount repeatedly until it finds\n" +" // itself inside solid, then jitters forward and back using decreasing\n" +" // amounts to find the impact\n" +" //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n" +" //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n" +" vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n" +" vec3 RT = vec3(TexCoord, 1);\n" +" OffsetVector *= 0.1;\n" +" RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n" +" RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n" +" RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n" +" RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n" +" RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n" +" RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n" +" RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n" +" RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n" +" RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n" +" RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n" +" RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n" +" RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n" +" RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n" +" RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n" +" return RT.xy;\n" "#else\n" " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n" -" //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n" -" //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n" -" vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n" -" //TexCoord += OffsetVector * 3.0;\n" +" // this basically moves forward the full distance, and then backs up based\n" +" // on height of samples\n" +" //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n" +" //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n" +" vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n" +" TexCoord += OffsetVector;\n" +" OffsetVector *= 0.333;\n" " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n" " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n" " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n" -"#endif\n" " return TexCoord;\n" +"#endif\n" "}\n" +"#endif\n" "\n" "void main(void)\n" "{\n" -" // apply offsetmapping\n" "#ifdef USEOFFSETMAPPING\n" +" // apply offsetmapping\n" " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n" "#define TexCoord TexCoordOffset\n" "#endif\n" @@ -581,17 +564,17 @@ static const char *builtinshaderstring = " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n" "\n" " // calculate directional shading\n" -" color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, length(CubeVector))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n" +" color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n" "#else\n" "#ifdef USEDIFFUSE\n" " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n" " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n" "\n" " // calculate directional shading\n" -" color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, length(CubeVector))) * color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n" +" color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n" "#else\n" " // calculate directionless shading\n" -" color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, length(CubeVector)));\n" +" color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n" "#endif\n" "#endif\n" "\n" @@ -657,8 +640,7 @@ static const char *builtinshaderstring = "\n" "#ifdef USEFOG\n" " // apply fog\n" -" myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n" -" color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n" +" color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n" "#endif\n" "\n" " color.rgb *= SceneBrightness;\n" @@ -900,10 +882,10 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl // lightmapped wall shaderfilename = "glsl/default.glsl"; permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER; - if (r_glsl_deluxemapping.integer >= 1 && rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping) + if (r_glsl_deluxemapping.integer >= 1 && rsurface_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping) { // deluxemapping (light direction texture) - if (rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace) + if (rsurface_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace) permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE; else permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE; @@ -1053,8 +1035,351 @@ void R_SwitchSurfaceShader(int permutation) } } +#define SKINFRAME_HASH 1024 + +struct +{ + int loadsequence; // incremented each level change + memexpandablearray_t array; + skinframe_t *hash[SKINFRAME_HASH]; +} +r_skinframe; + +void R_SkinFrame_PrepareForPurge(void) +{ + r_skinframe.loadsequence++; + // wrap it without hitting zero + if (r_skinframe.loadsequence >= 200) + r_skinframe.loadsequence = 1; +} + +void R_SkinFrame_MarkUsed(skinframe_t *skinframe) +{ + if (!skinframe) + return; + // mark the skinframe as used for the purging code + skinframe->loadsequence = r_skinframe.loadsequence; +} + +void R_SkinFrame_Purge(void) +{ + int i; + skinframe_t *s; + for (i = 0;i < SKINFRAME_HASH;i++) + { + for (s = r_skinframe.hash[i];s;s = s->next) + { + if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence) + { + if (s->base == r_texture_notexture) s->base = NULL; + if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL; + if (s->merged == s->base) s->merged = NULL; + if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL; + if (s->merged) R_FreeTexture(s->merged);s->merged = NULL; + if (s->base ) R_FreeTexture(s->base );s->base = NULL; + if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL; + if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL; + if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL; + if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL; + if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL; + if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL; + s->loadsequence = 0; + } + } + } +} + +skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add) +{ + skinframe_t *item; + int hashindex; + char basename[MAX_QPATH]; + + Image_StripImageExtension(name, basename, sizeof(basename)); + + hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1); + for (item = r_skinframe.hash[hashindex];item;item = item->next) + if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc) + break; + if (!item) + { + if (!add) + return NULL; + item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array); + memset(item, 0, sizeof(*item)); + strlcpy(item->basename, basename, sizeof(item->basename)); + item->textureflags = textureflags; + item->comparewidth = comparewidth; + item->compareheight = compareheight; + item->comparecrc = comparecrc; + item->next = r_skinframe.hash[hashindex]; + r_skinframe.hash[hashindex] = item; + } + R_SkinFrame_MarkUsed(item); + return item; +} + +skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags) +{ + // FIXME: it should be possible to disable loading various layers using + // cvars, to prevent wasted loading time and memory usage if the user does + // not want them + qboolean loadnormalmap = true; + qboolean loadgloss = true; + qboolean loadpantsandshirt = true; + qboolean loadglow = true; + int j; + unsigned char *pixels; + unsigned char *bumppixels; + unsigned char *basepixels = NULL; + int basepixels_width; + int basepixels_height; + skinframe_t *skinframe; + + if (cls.state == ca_dedicated) + return NULL; + + // return an existing skinframe if already loaded + // if loading of the first image fails, don't make a new skinframe as it + // would cause all future lookups of this to be missing + skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false); + if (skinframe && skinframe->base) + return skinframe; + + basepixels = loadimagepixels(name, false, 0, 0); + if (basepixels == NULL) + return NULL; + + // we've got some pixels to store, so really allocate this new texture now + if (!skinframe) + skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true); + skinframe->stain = NULL; + skinframe->merged = NULL; + skinframe->base = r_texture_notexture; + skinframe->pants = NULL; + skinframe->shirt = NULL; + skinframe->nmap = r_texture_blanknormalmap; + skinframe->gloss = NULL; + skinframe->glow = NULL; + skinframe->fog = NULL; + + basepixels_width = image_width; + basepixels_height = image_height; + skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL); + + if (textureflags & TEXF_ALPHA) + { + for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4) + if (basepixels[j] < 255) + break; + if (j < basepixels_width * basepixels_height * 4) + { + // has transparent pixels + pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4); + for (j = 0;j < image_width * image_height * 4;j += 4) + { + pixels[j+0] = 255; + pixels[j+1] = 255; + pixels[j+2] = 255; + pixels[j+3] = basepixels[j+3]; + } + skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL); + Mem_Free(pixels); + } + } + + // _norm is the name used by tenebrae and has been adopted as standard + if (loadnormalmap) + { + if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL) + { + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL); + Mem_Free(pixels); + pixels = NULL; + } + else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL) + { + pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4); + Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL); + Mem_Free(pixels); + Mem_Free(bumppixels); + } + else if (r_shadow_bumpscale_basetexture.value > 0) + { + pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4); + Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL); + Mem_Free(pixels); + } + } + // _luma is supported for tenebrae compatibility + // (I think it's a very stupid name, but oh well) + // _glow is the preferred name + if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;} + if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;} + if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;} + if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;} + + if (basepixels) + Mem_Free(basepixels); + + return skinframe; +} + +static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force) +{ + int i; + if (!force) + { + for (i = 0;i < width*height;i++) + if (((unsigned char *)&palette[in[i]])[3] > 0) + break; + if (i == width*height) + return NULL; + } + return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette); +} + +skinframe_t *R_SkinFrame_LoadInternal(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height, int bitsperpixel, const unsigned int *palette, const unsigned int *alphapalette) +{ + int i; + unsigned char *temp1, *temp2; + skinframe_t *skinframe; + + if (cls.state == ca_dedicated) + return NULL; + + // if already loaded just return it, otherwise make a new skinframe + skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true); + if (skinframe && skinframe->base) + return skinframe; + + skinframe->stain = NULL; + skinframe->merged = NULL; + skinframe->base = r_texture_notexture; + skinframe->pants = NULL; + skinframe->shirt = NULL; + skinframe->nmap = r_texture_blanknormalmap; + skinframe->gloss = NULL; + skinframe->glow = NULL; + skinframe->fog = NULL; + + // if no data was provided, then clearly the caller wanted to get a blank skinframe + if (!skindata) + return NULL; + + if (bitsperpixel == 32) + { + if (r_shadow_bumpscale_basetexture.value > 0) + { + temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); + temp2 = temp1 + width * height * 4; + Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); + skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL); + Mem_Free(temp1); + } + skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL); + if (textureflags & TEXF_ALPHA) + { + for (i = 3;i < width * height * 4;i += 4) + if (skindata[i] < 255) + break; + if (i < width * height * 4) + { + unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4); + memcpy(fogpixels, skindata, width * height * 4); + for (i = 0;i < width * height * 4;i += 4) + fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255; + skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL); + Mem_Free(fogpixels); + } + } + } + else if (bitsperpixel == 8) + { + if (r_shadow_bumpscale_basetexture.value > 0) + { + temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); + temp2 = temp1 + width * height * 4; + if (bitsperpixel == 32) + Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); + else + { + // use either a custom palette or the quake palette + Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete); + Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); + } + skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL); + Mem_Free(temp1); + } + // use either a custom palette, or the quake palette + skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), textureflags, true); // all + if (!palette && loadglowtexture) + skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow + if (!palette && loadpantsandshirt) + { + skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants + skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt + } + if (skinframe->pants || skinframe->shirt) + skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors + if (textureflags & TEXF_ALPHA) + { + // if not using a custom alphapalette, use the quake one + if (!alphapalette) + alphapalette = palette_alpha; + for (i = 0;i < width * height;i++) + if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255) + break; + if (i < width * height) + skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask + } + } + + return skinframe; +} + +skinframe_t *R_SkinFrame_LoadMissing(void) +{ + skinframe_t *skinframe; + + if (cls.state == ca_dedicated) + return NULL; + + skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true); + skinframe->stain = NULL; + skinframe->merged = NULL; + skinframe->base = r_texture_notexture; + skinframe->pants = NULL; + skinframe->shirt = NULL; + skinframe->nmap = r_texture_blanknormalmap; + skinframe->gloss = NULL; + skinframe->glow = NULL; + skinframe->fog = NULL; + + return skinframe; +} + void gl_main_start(void) { + int x; + double r, alpha; + + r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH); + for (x = 0;x < FOGMASKTABLEWIDTH;x++) + { + alpha = 1 - exp(r / ((double)x*(double)x)); + if (x == FOGMASKTABLEWIDTH - 1) + alpha = 0; + r_refdef.fogmasktable[x] = bound(0, alpha, 1); + } + + // set up r_skinframe loading system for textures + memset(&r_skinframe, 0, sizeof(r_skinframe)); + r_skinframe.loadsequence = 1; + Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256); + r_main_texturepool = R_AllocTexturePool(); R_BuildBlankTextures(); R_BuildNoTexture(); @@ -1071,6 +1396,10 @@ void gl_main_start(void) void gl_main_shutdown(void) { + // clear out the r_skinframe state + Mem_ExpandableArray_FreeArray(&r_skinframe.array); + memset(&r_skinframe, 0, sizeof(r_skinframe)); + if (r_svbsp.nodes) Mem_Free(r_svbsp.nodes); memset(&r_svbsp, 0, sizeof (r_svbsp)); @@ -1114,8 +1443,19 @@ void GL_Main_Init(void) r_main_mempool = Mem_AllocPool("Renderer", 0, NULL); Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed"); - FOG_registercvars(); // FIXME: move this fog stuff to client? + // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable + if (gamemode == GAME_NEHAHRA) + { + Cvar_RegisterVariable (&gl_fogenable); + Cvar_RegisterVariable (&gl_fogdensity); + Cvar_RegisterVariable (&gl_fogred); + Cvar_RegisterVariable (&gl_foggreen); + Cvar_RegisterVariable (&gl_fogblue); + Cvar_RegisterVariable (&gl_fogstart); + Cvar_RegisterVariable (&gl_fogend); + } Cvar_RegisterVariable(&r_nearclip); + Cvar_RegisterVariable(&r_showbboxes); Cvar_RegisterVariable(&r_showsurfaces); Cvar_RegisterVariable(&r_showtris); Cvar_RegisterVariable(&r_shownormals); @@ -1361,14 +1701,14 @@ static void R_View_UpdateEntityVisible (void) for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs)); + r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs)); } if(r_cullentities_trace.integer) { for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->model && (ent->model->name[0] == '*'))) + if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*'))) { if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs)) ent->last_trace_visibility = realtime; @@ -1604,6 +1944,7 @@ void R_ResetViewRendering2D(void) GL_AlphaTest(false); GL_ScissorTest(false); GL_DepthMask(false); + GL_DepthRange(0, 1); GL_DepthTest(false); R_Mesh_Matrix(&identitymatrix); R_Mesh_ResetTextureState(); @@ -1636,6 +1977,7 @@ void R_ResetViewRendering3D(void) GL_AlphaTest(false); GL_ScissorTest(true); GL_DepthMask(true); + GL_DepthRange(0, 1); GL_DepthTest(true); R_Mesh_Matrix(&identitymatrix); R_Mesh_ResetTextureState(); @@ -2126,7 +2468,7 @@ void R_UpdateVariables(void) // (0.9986 * 256 == 255.6) r_refdef.fogrange = 400 / r_refdef.fog_density; r_refdef.fograngerecip = 1.0f / r_refdef.fogrange; - r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip; + r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip; // fog color was already set } else @@ -2182,6 +2524,7 @@ extern void VM_CL_AddPolygonsToMeshQueue (void); extern void R_DrawPortals (void); extern cvar_t cl_locs_show; static void R_DrawLocs(void); +static void R_DrawEntityBBoxes(void); void R_RenderScene(void) { // don't let sound skip if going slow @@ -2286,6 +2629,13 @@ void R_RenderScene(void) R_TimeReport("portals"); } + if (r_showbboxes.value > 0) + { + R_DrawEntityBBoxes(); + if (r_timereport_active) + R_TimeReport("bboxes"); + } + if (gl_support_fragment_shader) { qglUseProgramObjectARB(0);CHECKGLERROR @@ -2313,17 +2663,27 @@ void R_RenderScene(void) R_ResetViewRendering2D(); } -/* +static const int bboxelements[36] = +{ + 5, 1, 3, 5, 3, 7, + 6, 2, 0, 6, 0, 4, + 7, 3, 2, 7, 2, 6, + 4, 0, 1, 4, 1, 5, + 4, 5, 7, 4, 7, 6, + 1, 0, 2, 1, 2, 3, +}; + void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca) { int i; - float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4]; + float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4]; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthMask(false); - GL_DepthTest(true); + GL_DepthRange(0, 1); R_Mesh_Matrix(&identitymatrix); + R_Mesh_ResetTextureState(); - vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; + vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; // vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2]; vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2]; vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2]; @@ -2331,24 +2691,73 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2]; vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2]; vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2]; - R_FillColors(color, 8, cr, cg, cb, ca); + R_FillColors(color4f, 8, cr, cg, cb, ca); if (r_refdef.fogenabled) { - for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4) + for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4) { - f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin)); - f1 = 1 - f2; + f1 = FogPoint_World(v); + f2 = 1 - f1; c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2; c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2; c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2; } } R_Mesh_VertexPointer(vertex3f, 0, 0); - R_Mesh_ColorPointer(color, 0, 0); + R_Mesh_ColorPointer(color4f, 0, 0); R_Mesh_ResetTextureState(); - R_Mesh_Draw(8, 12, 0, 0); + R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0); +} + +static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) +{ + int i; + float color[4]; + prvm_edict_t *edict; + // this function draws bounding boxes of server entities + if (!sv.active) + return; + SV_VM_Begin(); + for (i = 0;i < numsurfaces;i++) + { + edict = PRVM_EDICT_NUM(surfacelist[i]); + switch ((int)edict->fields.server->solid) + { + case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break; + case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break; + case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break; + case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break; + case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break; + default: Vector4Set(color, 0, 0, 0, 0.50);break; + } + color[3] *= r_showbboxes.value; + color[3] = bound(0, color[3], 1); + GL_DepthTest(!r_showdisabledepthtest.integer); + GL_CullFace(GL_BACK); + R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]); + } + SV_VM_End(); +} + +static void R_DrawEntityBBoxes(void) +{ + int i; + prvm_edict_t *edict; + vec3_t center; + // this function draws bounding boxes of server entities + if (!sv.active) + return; + SV_VM_Begin(); + for (i = 0;i < prog->num_edicts;i++) + { + edict = PRVM_EDICT_NUM(i); + if (edict->priv.server->free) + continue; + VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center); + R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL); + } + SV_VM_End(); } -*/ int nomodelelements[24] = { @@ -2406,6 +2815,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); } + GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1); GL_DepthTest(!(ent->effects & EF_NODEPTHTEST)); GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces R_Mesh_VertexPointer(nomodelvertex3f, 0, 0); @@ -2415,8 +2825,8 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight memcpy(color4f, nomodelcolor4f, sizeof(float[6*4])); R_Mesh_ColorPointer(color4f, 0, 0); Matrix4x4_OriginFromMatrix(&ent->matrix, org); - f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin)); - f1 = 1 - f2; + f1 = FogPoint_World(org); + f2 = 1 - f1; for (i = 0, c = color4f;i < 6;i++, c += 4) { c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2); @@ -2480,18 +2890,18 @@ void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, flo float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1}; -void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca) +void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca) { - float fog = 0.0f, ifog; + float fog = 1.0f; float vertex3f[12]; if (r_refdef.fogenabled) - fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin)); - ifog = 1 - fog; + fog = FogPoint_World(origin); R_Mesh_Matrix(&identitymatrix); GL_BlendFunc(blendfunc1, blendfunc2); GL_DepthMask(false); + GL_DepthRange(0, depthshort ? 0.0625 : 1); GL_DepthTest(!depthdisable); vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1; @@ -2513,13 +2923,14 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_ R_Mesh_TexBind(0, R_GetTexture(texture)); R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0); // FIXME: fixed function path can't properly handle r_view.colorscale > 1 - GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca); + GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca); R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA) { R_Mesh_TexBind(0, R_GetTexture(fogtexture)); GL_BlendFunc(blendfunc1, GL_ONE); + fog = 1 - fog; GL_Color(r_refdef.fogcolor[0] * fog * r_view.colorscale, r_refdef.fogcolor[1] * fog * r_view.colorscale, r_refdef.fogcolor[2] * fog * r_view.colorscale, ca); R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); } @@ -2696,9 +3107,9 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) // pick a new currentskinframe if the material is animated if (t->numskinframes >= 2) - t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes); + t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes]; if (t->backgroundnumskinframes >= 2) - t->backgroundcurrentskinframe = t->backgroundskinframes + ((int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes); + t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes]; t->currentmaterialflags = t->basematerialflags; t->currentalpha = ent->alpha; @@ -2707,18 +3118,20 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) if (!(ent->flags & RENDER_LIGHT)) t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; if (ent->effects & EF_ADDITIVE) - t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW; + t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; else if (t->currentalpha < 1) - t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW; + t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; if (ent->effects & EF_DOUBLESIDED) t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE; if (ent->effects & EF_NODEPTHTEST) - t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_NOSHADOW; + t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE; + if (ent->flags & RENDER_VIEWMODEL) + t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE; if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0) t->currenttexmatrix = r_waterscrollmatrix; else t->currenttexmatrix = identitymatrix; - if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)) t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND; t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f); @@ -2879,20 +3292,39 @@ void R_Mesh_ResizeArrays(int newvertices) } float *rsurface_modelvertex3f; +int rsurface_modelvertex3f_bufferobject; +size_t rsurface_modelvertex3f_bufferoffset; float *rsurface_modelsvector3f; +int rsurface_modelsvector3f_bufferobject; +size_t rsurface_modelsvector3f_bufferoffset; float *rsurface_modeltvector3f; +int rsurface_modeltvector3f_bufferobject; +size_t rsurface_modeltvector3f_bufferoffset; float *rsurface_modelnormal3f; +int rsurface_modelnormal3f_bufferobject; +size_t rsurface_modelnormal3f_bufferoffset; float *rsurface_vertex3f; +int rsurface_vertex3f_bufferobject; +size_t rsurface_vertex3f_bufferoffset; float *rsurface_svector3f; +int rsurface_svector3f_bufferobject; +size_t rsurface_svector3f_bufferoffset; float *rsurface_tvector3f; +int rsurface_tvector3f_bufferobject; +size_t rsurface_tvector3f_bufferoffset; float *rsurface_normal3f; +int rsurface_normal3f_bufferobject; +size_t rsurface_normal3f_bufferoffset; float *rsurface_lightmapcolor4f; +int rsurface_lightmapcolor4f_bufferobject; +size_t rsurface_lightmapcolor4f_bufferoffset; vec3_t rsurface_modelorg; qboolean rsurface_generatedvertex; const entity_render_t *rsurface_entity; const model_t *rsurface_model; texture_t *rsurface_texture; -qboolean rsurface_uselightmaptexture; +rtexture_t *rsurface_lightmaptexture; +rtexture_t *rsurface_deluxemaptexture; rsurfmode_t rsurface_mode; int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model @@ -2905,7 +3337,8 @@ void RSurf_CleanUp(void) } GL_AlphaTest(false); rsurface_mode = RSURFMODE_NONE; - rsurface_uselightmaptexture = false; + rsurface_lightmaptexture = NULL; + rsurface_deluxemaptexture = NULL; rsurface_texture = NULL; } @@ -2919,14 +3352,30 @@ void RSurf_ActiveWorldEntity(void) R_Mesh_Matrix(&identitymatrix); VectorCopy(r_view.origin, rsurface_modelorg); rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f; + rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo; + rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f; rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f; + rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo; + rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f; rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f; + rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo; + rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f; rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f; + rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo; + rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f; rsurface_generatedvertex = false; rsurface_vertex3f = rsurface_modelvertex3f; + rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject; + rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset; rsurface_svector3f = rsurface_modelsvector3f; + rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject; + rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset; rsurface_tvector3f = rsurface_modeltvector3f; + rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject; + rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset; rsurface_normal3f = rsurface_modelnormal3f; + rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject; + rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset; } void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents) @@ -2964,20 +3413,44 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface_modelnormal3f = NULL; Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL); } + rsurface_modelvertex3f_bufferobject = 0; + rsurface_modelvertex3f_bufferoffset = 0; + rsurface_modelsvector3f_bufferobject = 0; + rsurface_modelsvector3f_bufferoffset = 0; + rsurface_modeltvector3f_bufferobject = 0; + rsurface_modeltvector3f_bufferoffset = 0; + rsurface_modelnormal3f_bufferobject = 0; + rsurface_modelnormal3f_bufferoffset = 0; rsurface_generatedvertex = true; } else { rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f; + rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo; + rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f; rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f; + rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo; + rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f; rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f; + rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo; + rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f; rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f; + rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo; + rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f; rsurface_generatedvertex = false; } rsurface_vertex3f = rsurface_modelvertex3f; + rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject; + rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset; rsurface_svector3f = rsurface_modelsvector3f; + rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject; + rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset; rsurface_tvector3f = rsurface_modeltvector3f; + rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject; + rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset; rsurface_normal3f = rsurface_modelnormal3f; + rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject; + rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset; } void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist) @@ -2992,12 +3465,18 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta if (generatenormals && !rsurface_modelnormal3f) { rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f; + rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject = 0; + rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset = 0; Mod_BuildNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelnormal3f, r_smoothnormals_areaweighting.integer); } if (generatetangents && !rsurface_modelsvector3f) { rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f; + rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject = 0; + rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset = 0; rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f; + rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject = 0; + rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset = 0; Mod_BuildTextureVectorsFromNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_modelnormal3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f, r_smoothnormals_areaweighting.integer); } } @@ -3045,18 +3524,34 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_array_deformednormal3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformedsvector3f, rsurface_array_deformedtvector3f, r_smoothnormals_areaweighting.integer); } rsurface_vertex3f = rsurface_array_deformedvertex3f; + rsurface_vertex3f_bufferobject = 0; + rsurface_vertex3f_bufferoffset = 0; rsurface_svector3f = rsurface_array_deformedsvector3f; + rsurface_svector3f_bufferobject = 0; + rsurface_svector3f_bufferoffset = 0; rsurface_tvector3f = rsurface_array_deformedtvector3f; + rsurface_tvector3f_bufferobject = 0; + rsurface_tvector3f_bufferoffset = 0; rsurface_normal3f = rsurface_array_deformednormal3f; + rsurface_normal3f_bufferobject = 0; + rsurface_normal3f_bufferoffset = 0; } else { - rsurface_vertex3f = rsurface_modelvertex3f; + rsurface_vertex3f = rsurface_modelvertex3f; + rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject; + rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset; rsurface_svector3f = rsurface_modelsvector3f; + rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject; + rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset; rsurface_tvector3f = rsurface_modeltvector3f; - rsurface_normal3f = rsurface_modelnormal3f; + rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject; + rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset; + rsurface_normal3f = rsurface_modelnormal3f; + rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject; + rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset; } - R_Mesh_VertexPointer(rsurface_vertex3f, 0, 0); + R_Mesh_VertexPointer(rsurface_vertex3f, rsurface_vertex3f_bufferobject, rsurface_vertex3f_bufferoffset); } void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist) @@ -3072,7 +3567,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel if (texturenumsurfaces == 1) { GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), 0, 0); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle)); } else if (r_batchmode.integer == 2) { @@ -3085,7 +3580,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel j = i + 1; if (surface->num_triangles > MAXBATCHTRIANGLES) { - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), 0, 0); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle)); continue; } memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3])); @@ -3119,122 +3614,16 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex; numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle; GL_LockArrays(surface->num_firstvertex, numvertices); - R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), 0, 0); - } - } - else - { - for (i = 0;i < texturenumsurfaces;i++) - { - surface = texturesurfacelist[i]; - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), 0, 0); - } - } -} - -static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit) -{ - int i; - int j; - const msurface_t *surface = texturesurfacelist[0]; - const msurface_t *surface2; - int firstvertex; - int endvertex; - int numvertices; - int numtriangles; - // TODO: lock all array ranges before render, rather than on each surface - if (texturenumsurfaces == 1) - { - R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture)); - if (deluxemaptexunit >= 0) - R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture)); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), 0, 0); - } - else if (r_batchmode.integer == 2) - { - #define MAXBATCHTRIANGLES 4096 - int batchtriangles = 0; - int batchelements[MAXBATCHTRIANGLES*3]; - for (i = 0;i < texturenumsurfaces;i = j) - { - surface = texturesurfacelist[i]; - R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture)); - if (deluxemaptexunit >= 0) - R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture)); - j = i + 1; - if (surface->num_triangles > MAXBATCHTRIANGLES) - { - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), 0, 0); - continue; - } - memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3])); - batchtriangles = surface->num_triangles; - firstvertex = surface->num_firstvertex; - endvertex = surface->num_firstvertex + surface->num_vertices; - for (;j < texturenumsurfaces;j++) - { - surface2 = texturesurfacelist[j]; - if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES) - break; - memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3])); - batchtriangles += surface2->num_triangles; - firstvertex = min(firstvertex, surface2->num_firstvertex); - endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices); - } - surface2 = texturesurfacelist[j-1]; - numvertices = endvertex - firstvertex; - R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0); - } - } - else if (r_batchmode.integer == 1) - { -#if 0 - Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name); - for (i = 0;i < texturenumsurfaces;i = j) - { - surface = texturesurfacelist[i]; - for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++) - if (texturesurfacelist[j] != surface2) - break; - Con_Printf(" %i", j - i); - } - Con_Printf("\n"); - Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name); -#endif - for (i = 0;i < texturenumsurfaces;i = j) - { - surface = texturesurfacelist[i]; - R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture)); - if (deluxemaptexunit >= 0) - R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture)); - for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++) - if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture) - break; -#if 0 - Con_Printf(" %i", j - i); -#endif - surface2 = texturesurfacelist[j-1]; - numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex; - numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle; - GL_LockArrays(surface->num_firstvertex, numvertices); - R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), 0, 0); + R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle)); } -#if 0 - Con_Printf("\n"); -#endif } else { for (i = 0;i < texturenumsurfaces;i++) { surface = texturesurfacelist[i]; - R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture)); - if (deluxemaptexunit >= 0) - R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture)); GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), 0, 0); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle)); } } } @@ -3252,7 +3641,7 @@ static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **te { float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale; GL_Color(f, f, f, 1); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)), 0, 0); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * (j + surface->num_firsttriangle))); } } } @@ -3264,7 +3653,7 @@ static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **te int k = (int)(((size_t)surface) / sizeof(msurface_t)); GL_Color((k & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_view.colorscale, 1); GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), 0, 0); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle)); } } } @@ -3283,7 +3672,7 @@ static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **t const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4) { - f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg)); + f = FogPoint_Model(v); c2[0] = c[0] * f; c2[1] = c[1] * f; c2[2] = c[2] * f; @@ -3298,7 +3687,7 @@ static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **t const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4) { - f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg)); + f = FogPoint_Model(v); c2[0] = f; c2[1] = f; c2[2] = f; @@ -3307,6 +3696,8 @@ static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **t } } rsurface_lightmapcolor4f = rsurface_array_color4f; + rsurface_lightmapcolor4f_bufferobject = 0; + rsurface_lightmapcolor4f_bufferoffset = 0; } static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a) @@ -3328,17 +3719,22 @@ static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t * } } rsurface_lightmapcolor4f = rsurface_array_color4f; + rsurface_lightmapcolor4f_bufferobject = 0; + rsurface_lightmapcolor4f_bufferoffset = 0; } static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) { // TODO: optimize rsurface_lightmapcolor4f = NULL; + rsurface_lightmapcolor4f_bufferobject = 0; + rsurface_lightmapcolor4f_bufferoffset = 0; if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist); if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a); - R_Mesh_ColorPointer(rsurface_lightmapcolor4f, 0, 0); + R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset); GL_Color(r, g, b, a); - RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1); + R_Mesh_TexBind(0, R_GetTexture(rsurface_lightmaptexture)); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) @@ -3346,9 +3742,11 @@ static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **text // TODO: optimize applyfog && applycolor case // just apply fog if necessary, and tint the fog color array if necessary rsurface_lightmapcolor4f = NULL; + rsurface_lightmapcolor4f_bufferobject = 0; + rsurface_lightmapcolor4f_bufferoffset = 0; if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist); if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a); - R_Mesh_ColorPointer(rsurface_lightmapcolor4f, 0, 0); + R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset); GL_Color(r, g, b, a); RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } @@ -3398,12 +3796,18 @@ static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t } } rsurface_lightmapcolor4f = rsurface_array_color4f; + rsurface_lightmapcolor4f_bufferobject = 0; + rsurface_lightmapcolor4f_bufferoffset = 0; } else + { rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f; + rsurface_lightmapcolor4f_bufferobject = rsurface_model->surfmesh.vbo; + rsurface_lightmapcolor4f_bufferoffset = rsurface_model->surfmesh.vbooffset_lightmapcolor4f; + } if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist); if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a); - R_Mesh_ColorPointer(rsurface_lightmapcolor4f, 0, 0); + R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset); GL_Color(r, g, b, a); RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } @@ -3452,6 +3856,8 @@ static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t a = 1; applycolor = false; rsurface_lightmapcolor4f = rsurface_array_color4f; + rsurface_lightmapcolor4f_bufferobject = 0; + rsurface_lightmapcolor4f_bufferoffset = 0; } else { @@ -3459,16 +3865,19 @@ static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t g = ambientcolor[1]; b = ambientcolor[2]; rsurface_lightmapcolor4f = NULL; + rsurface_lightmapcolor4f_bufferobject = 0; + rsurface_lightmapcolor4f_bufferoffset = 0; } if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist); if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a); - R_Mesh_ColorPointer(rsurface_lightmapcolor4f, 0, 0); + R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset); GL_Color(r, g, b, a); RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist) { + GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1); GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST)); GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces if (rsurface_mode != RSURFMODE_SHOWSURFACES) @@ -3486,7 +3895,7 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurfa static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist) { // transparent sky would be ridiculous - if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + if ((rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)) return; if (rsurface_mode != RSURFMODE_SKY) { @@ -3503,6 +3912,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te // restore entity matrix R_Mesh_Matrix(&rsurface_entity->matrix); } + GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1); GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST)); GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces GL_DepthMask(true); @@ -3553,11 +3963,11 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist); else RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist); - R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f, 0, 0); - R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f, 0, 0); - R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f, 0, 0); - R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f, 0, 0); - R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f, 0, 0); + R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordtexture2f); + R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f, rsurface_svector3f_bufferobject, rsurface_svector3f_bufferoffset); + R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f, rsurface_tvector3f_bufferobject, rsurface_tvector3f_bufferoffset); + R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f, rsurface_normal3f_bufferobject, rsurface_normal3f_bufferoffset); + R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordlightmap2f); if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) { @@ -3566,11 +3976,11 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap)); R_Mesh_ColorPointer(NULL, 0, 0); } - else if (rsurface_uselightmaptexture) + else if (rsurface_lightmaptexture) { - R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture)); + R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture)); if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) - R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture)); + R_Mesh_TexBind(8, R_GetTexture(rsurface_deluxemaptexture)); R_Mesh_ColorPointer(NULL, 0, 0); } else @@ -3578,14 +3988,17 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t R_Mesh_TexBind(7, R_GetTexture(r_texture_white)); if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap)); - R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f, 0, 0); + R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_lightmapcolor4f); } - if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) - RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1); - else - RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); - if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + if (rsurface_lightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) + { + R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture)); + if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) + R_Mesh_TexBind(8, R_GetTexture(rsurface_deluxemaptexture)); + } + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); + if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)) { } } @@ -3643,14 +4056,18 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **t memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(r_texture_white); m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f; + m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo; + m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f; m.tex[1] = R_GetTexture(layer->texture); m.texmatrix[1] = layer->texmatrix; m.texrgbscale[1] = layertexrgbscale; m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f; + m.pointer_texcoord_bufferobject[1] = rsurface_model->surfmesh.vbo; + m.pointer_texcoord_bufferoffset[1] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f; R_Mesh_TextureState(&m); if (rsurface_lightmode == 2) RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); - else if (rsurface_uselightmaptexture) + else if (rsurface_lightmaptexture) RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); else RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); @@ -3661,6 +4078,8 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **t m.texmatrix[0] = layer->texmatrix; m.texrgbscale[0] = layertexrgbscale; m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f; + m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo; + m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f; R_Mesh_TextureState(&m); RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog); break; @@ -3672,6 +4091,8 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **t m.tex[0] = R_GetTexture(layer->texture); m.texmatrix[0] = layer->texmatrix; m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f; + m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo; + m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f; } R_Mesh_TextureState(&m); // generate a color array for the fog pass @@ -3683,7 +4104,7 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **t const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) { - f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg)); + f = 1 - FogPoint_Model(v); c[0] = layercolor[0]; c[1] = layercolor[1]; c[2] = layercolor[2]; @@ -3742,10 +4163,12 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(r_texture_white); m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f; + m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo; + m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f; R_Mesh_TextureState(&m); if (rsurface_lightmode == 2) RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false); - else if (rsurface_uselightmaptexture) + else if (rsurface_lightmaptexture) RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false); else RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false); @@ -3756,6 +4179,8 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t m.tex[0] = R_GetTexture(layer->texture); m.texmatrix[0] = layer->texmatrix; m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f; + m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo; + m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f; R_Mesh_TextureState(&m); RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false); } @@ -3766,6 +4191,8 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t m.tex[0] = R_GetTexture(layer->texture); m.texmatrix[0] = layer->texmatrix; m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f; + m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo; + m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f; R_Mesh_TextureState(&m); if (rsurface_lightmode == 2) RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog); @@ -3779,6 +4206,8 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t m.tex[0] = R_GetTexture(layer->texture); m.texmatrix[0] = layer->texmatrix; m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f; + m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo; + m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f; R_Mesh_TextureState(&m); RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog); break; @@ -3791,6 +4220,8 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t m.tex[0] = R_GetTexture(layer->texture); m.texmatrix[0] = layer->texmatrix; m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f; + m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo; + m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f; R_Mesh_TextureState(&m); } else @@ -3803,7 +4234,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) { - f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg)); + f = 1 - FogPoint_Model(v); c[0] = layer->color[0]; c[1] = layer->color[1]; c[2] = layer->color[2]; @@ -3838,6 +4269,7 @@ static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **textur R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist); else if (rsurface_texture->currentnumlayers) { + GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1); GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST)); GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2); @@ -3882,7 +4314,8 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const texture = surface->texture; R_UpdateTextureInfo(ent, texture); rsurface_texture = texture->currentframe; - rsurface_uselightmaptexture = surface->lightmaptexture != NULL; + rsurface_lightmaptexture = surface->lightmaptexture; + rsurface_deluxemaptexture = surface->deluxemaptexture; // scan ahead until we find a different texture endsurface = min(i + 1024, numsurfaces); texturenumsurfaces = 0; @@ -3890,7 +4323,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const for (;j < endsurface;j++) { surface = rsurface_model->data_surfaces + surfacelist[j]; - if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL)) + if (texture != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture) break; texturesurfacelist[texturenumsurfaces++] = surface; } @@ -3916,7 +4349,8 @@ void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask // use skin 1 instead) texture = surfacelist[i]->texture; rsurface_texture = texture->currentframe; - rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL; + rsurface_lightmaptexture = surfacelist[i]->lightmaptexture; + rsurface_deluxemaptexture = surfacelist[i]->deluxemaptexture; if (!(rsurface_texture->currentmaterialflags & flagsmask)) { // if this texture is not the kind we want, skip ahead to the next one @@ -3924,7 +4358,7 @@ void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask ; continue; } - if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED) + if (rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) { // transparent surfaces get pushed off into the transparent queue const msurface_t *surface = surfacelist[i]; @@ -3937,7 +4371,7 @@ void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask else { // simply scan ahead until we find a different texture or lightmap state - for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++) + for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_lightmaptexture == surfacelist[j]->lightmaptexture;j++) ; // render the range of surfaces R_DrawTextureSurfaceList(j - i, surfacelist + i); @@ -3974,6 +4408,7 @@ void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, in CHECKGLERROR GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthMask(false); + GL_DepthRange(0, 1); GL_DepthTest(true); GL_CullFace(GL_NONE); R_Mesh_Matrix(&identitymatrix); @@ -4032,6 +4467,7 @@ void R_DrawCollisionBrushes(entity_render_t *ent) R_Mesh_ResetTextureState(); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); GL_DepthMask(false); + GL_DepthRange(0, 1); GL_DepthTest(!r_showdisabledepthtest.integer); qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++) @@ -4051,6 +4487,7 @@ void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean model_t *model = ent->model; vec3_t v; CHECKGLERROR + GL_DepthRange(0, 1); GL_DepthTest(!r_showdisabledepthtest.integer); GL_DepthMask(true); GL_BlendFunc(GL_ONE, GL_ZERO); @@ -4077,9 +4514,10 @@ void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean qglBegin(GL_LINES); for (k = 0;k < surface->num_triangles;k++, elements += 3) { - qglArrayElement(elements[0]);qglArrayElement(elements[1]); - qglArrayElement(elements[1]);qglArrayElement(elements[2]); - qglArrayElement(elements[2]);qglArrayElement(elements[0]); +#define GLVERTEXELEMENT(n) qglVertex3f(rsurface_vertex3f[elements[n]*3+0], rsurface_vertex3f[elements[n]*3+1], rsurface_vertex3f[elements[n]*3+2]) + GLVERTEXELEMENT(0);GLVERTEXELEMENT(1); + GLVERTEXELEMENT(1);GLVERTEXELEMENT(2); + GLVERTEXELEMENT(2);GLVERTEXELEMENT(0); } qglEnd(); CHECKGLERROR @@ -4160,7 +4598,8 @@ void R_DrawWorldSurfaces(qboolean skysurfaces) flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL); f = 0; t = NULL; - rsurface_uselightmaptexture = false; + rsurface_lightmaptexture = NULL; + rsurface_deluxemaptexture = NULL; rsurface_texture = NULL; numsurfacelist = 0; j = model->firstmodelsurface; @@ -4246,7 +4685,8 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces) flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL); f = 0; t = NULL; - rsurface_uselightmaptexture = false; + rsurface_lightmaptexture = NULL; + rsurface_deluxemaptexture = NULL; rsurface_texture = NULL; numsurfacelist = 0; surface = model->data_surfaces + model->firstmodelsurface;