X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=gl_rmain.c;h=9d83c1f1efc1c9575f3e7a775b68da84248278d4;hp=3d95e9fc29807614e89de73afa54d4d1e82600e2;hb=f5c01d29320e5e45965d995a164291c2cc071578;hpb=3fe0ee89f506f39375a5abe5c0ff170de037614a diff --git a/gl_rmain.c b/gl_rmain.c index 3d95e9fc..9d83c1f1 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -33,7 +33,8 @@ rtexturepool_t *r_main_texturepool; // r_refdef_t r_refdef; -cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"}; +cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"}; +cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"}; 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)"}; @@ -57,12 +58,13 @@ cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders 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)"}; -cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"}; +cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows DOWN, otherwise use the model lighting"}; cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"}; cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"}; cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"}; cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"}; cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"}; +cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"}; cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"}; cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"}; @@ -76,11 +78,16 @@ cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the re cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"}; cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"}; +cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"}; +cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"}; cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"}; cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"}; cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"}; -cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"}; -cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"}; +cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"}; +cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"}; +cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"}; +cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"}; +cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"}; cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"}; cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"}; @@ -120,14 +127,9 @@ cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rot cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"}; cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"}; -extern qboolean v_flipped_state; +extern cvar_t v_glslgamma; -typedef struct r_glsl_bloomshader_s -{ - int program; - int loc_Texture_Bloom; -} -r_glsl_bloomshader_t; +extern qboolean v_flipped_state; static struct r_bloomstate_s { @@ -142,8 +144,6 @@ static struct r_bloomstate_s int bloomtexturewidth, bloomtextureheight; rtexture_t *texture_bloom; - r_glsl_bloomshader_t *shader; - // arrays for rendering the screen passes float screentexcoord2f[8]; float bloomtexcoord2f[8]; @@ -151,36 +151,7 @@ static struct r_bloomstate_s } r_bloomstate; -typedef struct r_waterstate_waterplane_s -{ - rtexture_t *texture_refraction; - rtexture_t *texture_reflection; - mplane_t plane; - int materialflags; // combined flags of all water surfaces on this plane - unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps - qboolean pvsvalid; -} -r_waterstate_waterplane_t; - -#define MAX_WATERPLANES 16 - -static struct r_waterstate_s -{ - qboolean enabled; - - qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces - - int waterwidth, waterheight; - int texturewidth, textureheight; - - int maxwaterplanes; // same as MAX_WATERPLANES - int numwaterplanes; - r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES]; - - float screenscale[2]; - float screencenter[2]; -} -r_waterstate; +r_waterstate_t r_waterstate; // shadow volume bsp struct with automatically growing nodes buffer svbsp_t r_svbsp; @@ -193,8 +164,14 @@ rtexture_t *r_texture_notexture; rtexture_t *r_texture_whitecube; rtexture_t *r_texture_normalizationcube; rtexture_t *r_texture_fogattenuation; +rtexture_t *r_texture_gammaramps; +unsigned int r_texture_gammaramps_serial; //rtexture_t *r_texture_fogintensity; +unsigned int r_queries[R_MAX_OCCLUSION_QUERIES]; +unsigned int r_numqueries; +unsigned int r_maxqueries; + char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH]; skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD]; @@ -269,7 +246,7 @@ float FogPoint_World(const vec3_t p) float FogPoint_Model(const vec3_t p) { - return FogForDistance(VectorDistance((p), rsurface.modelorg)); + return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix)); } static void R_BuildBlankTextures(void) @@ -476,8 +453,73 @@ static const char *builtinshaderstring = "# endif\n" "\n" "#else\n" -"#ifdef MODE_GENERIC\n" "\n" +"#ifdef MODE_POSTPROCESS\n" +"# ifdef VERTEX_SHADER\n" +"void main(void)\n" +"{\n" +" gl_FrontColor = gl_Color;\n" +" gl_Position = ftransform();\n" +" gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n" +"#ifdef USEGLOW\n" +" gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n" +"#endif\n" +"}\n" +"# endif\n" +"# ifdef FRAGMENT_SHADER\n" +"\n" +"uniform sampler2D Texture_First;\n" +"#ifdef USEGLOW\n" +"uniform sampler2D Texture_Second;\n" +"#endif\n" +"#ifdef USEGAMMARAMPS\n" +"uniform sampler2D Texture_GammaRamps;\n" +"#endif\n" +"#ifdef USEVERTEXTEXTUREBLEND\n" +"uniform vec4 TintColor;\n" +"#endif\n" +"#ifdef USECOLORMOD\n" +"uniform vec3 Gamma;\n" +"#endif\n" +"//uncomment these if you want to use them:\n" +"uniform vec4 UserVec1;\n" +"// uniform vec4 UserVec2;\n" +"// uniform vec4 UserVec3;\n" +"// uniform vec4 UserVec4;\n" +"// uniform float ClientTime;\n" +"uniform vec2 PixelSize;\n" +"void main(void)\n" +"{\n" +" gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n" +"#ifdef USEGLOW\n" +" gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n" +"#endif\n" +"#ifdef USEVERTEXTEXTUREBLEND\n" +" gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n" +"#endif\n" +"\n" +"#ifdef USEPOSTPROCESSING\n" +"// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n" +"// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n" +" gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n" +" gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n" +" gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n" +" gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n" +" gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n" +" gl_FragColor /= (1 + 5 * UserVec1.y);\n" +"#endif\n" +"\n" +"#ifdef USEGAMMARAMPS\n" +" gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n" +" gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n" +" gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n" +"#endif\n" +"}\n" +"# endif\n" +"\n" +"\n" +"#else\n" +"#ifdef MODE_GENERIC\n" "# ifdef VERTEX_SHADER\n" "void main(void)\n" "{\n" @@ -517,7 +559,7 @@ static const char *builtinshaderstring = " gl_FragColor += tex2;\n" "# endif\n" "# ifdef USEVERTEXTEXTUREBLEND\n" -" gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n" +" gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n" "# endif\n" "}\n" "# endif\n" @@ -527,38 +569,35 @@ static const char *builtinshaderstring = "varying vec2 TexCoord;\n" "varying vec2 TexCoordLightmap;\n" "\n" -"//#ifdef MODE_LIGHTSOURCE\n" +"#ifdef MODE_LIGHTSOURCE\n" "varying vec3 CubeVector;\n" -"//#endif\n" +"#endif\n" "\n" -"//#ifdef MODE_LIGHTSOURCE\n" +"#ifdef MODE_LIGHTSOURCE\n" "varying vec3 LightVector;\n" -"//#else\n" -"//# ifdef MODE_LIGHTDIRECTION\n" -"//varying vec3 LightVector;\n" -"//# endif\n" -"//#endif\n" +"#endif\n" +"#ifdef MODE_LIGHTDIRECTION\n" +"varying vec3 LightVector;\n" +"#endif\n" "\n" "varying vec3 EyeVector;\n" -"//#ifdef USEFOG\n" +"#ifdef USEFOG\n" "varying vec3 EyeVectorModelSpace;\n" -"//#endif\n" +"#endif\n" "\n" "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n" "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n" "varying vec3 VectorR; // direction of R texcoord (surface normal)\n" "\n" -"//#ifdef MODE_WATER\n" +"#ifdef MODE_WATER\n" "varying vec4 ModelViewProjectionPosition;\n" -"//#else\n" -"//# ifdef MODE_REFRACTION\n" -"//varying vec4 ModelViewProjectionPosition;\n" -"//# else\n" -"//# ifdef USEREFLECTION\n" -"//varying vec4 ModelViewProjectionPosition;\n" -"//# endif\n" -"//# endif\n" -"//#endif\n" +"#endif\n" +"#ifdef MODE_REFRACTION\n" +"varying vec4 ModelViewProjectionPosition;\n" +"#endif\n" +"#ifdef USEREFLECTION\n" +"varying vec4 ModelViewProjectionPosition;\n" +"#endif\n" "\n" "\n" "\n" @@ -819,7 +858,8 @@ static const char *builtinshaderstring = " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n" " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n" " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n" -" color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n" +" color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n" +" color.a = 1.0;\n" " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n" "#endif\n" "\n" @@ -831,7 +871,7 @@ static const char *builtinshaderstring = " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n" "# endif\n" "# else\n" -" myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n" +" myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n" "# ifdef USESPECULAR\n" " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n" "# endif\n" @@ -852,10 +892,16 @@ static const char *builtinshaderstring = " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n" "# endif\n" "# ifdef USESPECULAR\n" +"# ifndef USEEXACTSPECULARMATH\n" " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n" "\n" +"# endif\n" " // calculate directional shading\n" +"# ifdef USEEXACTSPECULARMATH\n" +" color.rgb = 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(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n" +"# else\n" " color.rgb = 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)) * glosscolor);\n" +"# endif\n" "# else\n" "# ifdef USEDIFFUSE\n" " // calculate directional shading\n" @@ -880,13 +926,17 @@ static const char *builtinshaderstring = " // directional model lighting\n" "# ifdef USEDIFFUSE\n" " // get the light normal\n" -" myhalf3 diffusenormal = myhalf3(LightVector);\n" +" myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n" "# endif\n" "# ifdef USESPECULAR\n" " // calculate directional shading\n" " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n" +"# ifdef USEEXACTSPECULARMATH\n" +" color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n" +"# else\n" " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n" " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n" +"# endif\n" "# else\n" "# ifdef USEDIFFUSE\n" "\n" @@ -905,13 +955,29 @@ static const char *builtinshaderstring = " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n" "\n" " // get the light normal\n" -" myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n" -" myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n" -" // calculate directional shading\n" -" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n" +" myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n" +" myhalf3 diffusenormal;\n" +" diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n" +" diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n" +" diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n" +" // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n" +" // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n" +" // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n" +" // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n" +" // to map the luxels to coordinates on the draw surfaces), which also causes\n" +" // deluxemaps to be wrong because light contributions from the wrong side of the surface\n" +" // are added up. To prevent divisions by zero or strong exaggerations, a max()\n" +" // nudge is done here at expense of some additional fps. This is ONLY needed for\n" +" // deluxemaps, tangentspace deluxemap avoid this problem by design.\n" +" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n" +" // 0.25 supports up to 75.5 degrees normal/deluxe angle\n" "# ifdef USESPECULAR\n" +"# ifdef USEEXACTSPECULARMATH\n" +" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n" +"# else\n" " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n" " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n" +"# endif\n" "# endif\n" "\n" " // apply lightmap color\n" @@ -925,12 +991,16 @@ static const char *builtinshaderstring = " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n" "\n" " // get the light normal\n" -" myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n" -" // calculate directional shading\n" -" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n" +" myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n" +" // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n" +" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n" "# ifdef USESPECULAR\n" +"# ifdef USEEXACTSPECULARMATH\n" +" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n" +"# else\n" " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n" " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n" +"# endif\n" "# endif\n" "\n" " // apply lightmap color\n" @@ -998,6 +1068,7 @@ static const char *builtinshaderstring = "#endif // FRAGMENT_SHADER\n" "\n" "#endif // !MODE_GENERIC\n" +"#endif // !MODE_POSTPROCESS\n" "#endif // !MODE_DEPTH_OR_SHADOW\n" ; @@ -1028,11 +1099,14 @@ typedef enum shaderpermutation_e SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects - SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface - SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface - SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!) - SHADERPERMUTATION_LIMIT = 1<<11, // size of permutations array - SHADERPERMUTATION_COUNT = 11 // size of shaderpermutationinfo array + SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, // (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation + SHADERPERMUTATION_REFLECTION = 1<<9, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface + SHADERPERMUTATION_OFFSETMAPPING = 1<<10, // adjust texcoords to roughly simulate a displacement mapped surface + SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!) + SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only) + SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing + SHADERPERMUTATION_LIMIT = 1<<14, // size of permutations array + SHADERPERMUTATION_COUNT = 14 // size of shaderpermutationinfo array } shaderpermutation_t; @@ -1047,15 +1121,19 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#define USECUBEFILTER\n", " cubefilter"}, {"#define USEGLOW\n", " glow"}, {"#define USESPECULAR\n", " specular"}, + {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"}, {"#define USEREFLECTION\n", " reflection"}, {"#define USEOFFSETMAPPING\n", " offsetmapping"}, {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"}, + {"#define USEGAMMARAMPS\n", " gammaramps"}, + {"#define USEPOSTPROCESSING\n", " postprocessing"}, }; // this enum is multiplied by SHADERPERMUTATION_MODEBASE typedef enum shadermode_e { SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture + SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess) SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp) SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp) @@ -1074,6 +1152,7 @@ shadermode_t; shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] = { {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"}, + {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"}, {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"}, {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"}, {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"}, @@ -1095,6 +1174,7 @@ typedef struct r_glsl_permutation_s // locations of detected uniforms in program object, or -1 if not found int loc_Texture_First; int loc_Texture_Second; + int loc_Texture_GammaRamps; int loc_Texture_Normal; int loc_Texture_Color; int loc_Texture_Gloss; @@ -1131,6 +1211,7 @@ typedef struct r_glsl_permutation_s int loc_SpecularColor; int loc_LightDir; int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost + int loc_GammaCoeff; // 1 / gamma int loc_DistortScaleRefractReflect; int loc_ScreenScaleRefractReflect; int loc_ScreenCenterRefractReflect; @@ -1138,6 +1219,12 @@ typedef struct r_glsl_permutation_s int loc_ReflectColor; int loc_ReflectFactor; int loc_ReflectOffset; + int loc_UserVec1; + int loc_UserVec2; + int loc_UserVec3; + int loc_UserVec4; + int loc_ClientTime; + int loc_PixelSize; } r_glsl_permutation_t; @@ -1160,13 +1247,13 @@ static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice) } else if (!strcmp(filename, "glsl/default.glsl")) { - shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1); + shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1); memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1); } return shaderstring; } -static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t permutation) +static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation) { int i; shadermodeinfo_t *modeinfo = shadermodeinfo + mode; @@ -1247,6 +1334,7 @@ static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t per // have to look them up every time we set them p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First"); p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second"); + p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps"); p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal"); p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color"); p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss"); @@ -1290,9 +1378,17 @@ static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t per p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor"); p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor"); p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset"); + p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff"); + p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1"); + p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2"); + p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3"); + p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4"); + p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime"); + p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize"); // initialize the samplers to refer to the texture units we use if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST); if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND); + if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS); if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL); if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR); if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS); @@ -1328,8 +1424,8 @@ static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t per void R_GLSL_Restart_f(void) { - shadermode_t mode; - shaderpermutation_t permutation; + unsigned int mode; + unsigned int permutation; for (mode = 0;mode < SHADERMODE_COUNT;mode++) for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++) if (r_glsl_permutations[mode][permutation].program) @@ -1341,7 +1437,7 @@ void R_GLSL_DumpShader_f(void) { int i; - qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false); + qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false); if(!file) { Con_Printf("failed to write to glsl/default.glsl\n"); @@ -1361,7 +1457,7 @@ void R_GLSL_DumpShader_f(void) Con_Printf("glsl/default.glsl written\n"); } -void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation) +void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation) { r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation]; if (r_glsl_permutation != perm) @@ -1421,7 +1517,7 @@ void R_SetupGenericTwoTextureShader(int texturemode) if (gl_support_fragment_shader) { if (r_glsl.integer && r_glsl_usegeneric.integer) - R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)))); + R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)))); else if (r_glsl_permutation) { r_glsl_permutation = NULL; @@ -1460,7 +1556,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f // minimum features necessary to avoid wasting rendering time in the // fragment shader on features that are not being used unsigned int permutation = 0; - shadermode_t mode = 0; + unsigned int mode = 0; // TODO: implement geometry-shader based shadow volumes someday if (r_glsl_offsetmapping.integer) { @@ -1501,7 +1597,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f mode = SHADERMODE_FLATCOLOR; if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (rsurface.texture->currentskinframe->glow) + if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) permutation |= SHADERPERMUTATION_GLOW; if (r_refdef.fogenabled) permutation |= SHADERPERMUTATION_FOG; @@ -1524,7 +1620,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f mode = SHADERMODE_LIGHTDIRECTION; if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (rsurface.texture->currentskinframe->glow) + if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) permutation |= SHADERPERMUTATION_GLOW; permutation |= SHADERPERMUTATION_DIFFUSE; if (specularscale > 0) @@ -1544,7 +1640,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f mode = SHADERMODE_LIGHTDIRECTION; if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (rsurface.texture->currentskinframe->glow) + if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) permutation |= SHADERPERMUTATION_GLOW; if (r_refdef.fogenabled) permutation |= SHADERPERMUTATION_FOG; @@ -1589,7 +1685,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (rsurface.texture->currentskinframe->glow) + if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) permutation |= SHADERPERMUTATION_GLOW; if (r_refdef.fogenabled) permutation |= SHADERPERMUTATION_FOG; @@ -1600,6 +1696,9 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) permutation |= SHADERPERMUTATION_REFLECTION; } + if(permutation & SHADERPERMUTATION_SPECULAR) + if(r_shadow_glossexact.integer) + permutation |= SHADERPERMUTATION_EXACTSPECULARMATH; R_SetupShader_SetPermutation(mode, permutation); if (mode == SHADERMODE_LIGHTSOURCE) { @@ -1634,12 +1733,12 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f } else { - if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f); + if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f); if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity); if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale); } if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]); - if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value); + if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value); // additive passes are only darkened by fog, not tinted if (r_glsl_permutation->loc_FogColor >= 0) { @@ -1684,21 +1783,29 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f else qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0); } - if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip); - if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower); + if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix)); + if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH) + { + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25); + } + else + { + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower); + } if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value); CHECKGLERROR } #define SKINFRAME_HASH 1024 -struct +typedef struct { int loadsequence; // incremented each level change memexpandablearray_t array; skinframe_t *hash[SKINFRAME_HASH]; } -r_skinframe; +r_skinframe_t; +r_skinframe_t r_skinframe; void R_SkinFrame_PrepareForPurge(void) { @@ -1810,7 +1917,42 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid return item; } -skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain) +#define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \ + { \ + unsigned long long avgcolor[5], wsum; \ + int pix, comp, w; \ + avgcolor[0] = 0; \ + avgcolor[1] = 0; \ + avgcolor[2] = 0; \ + avgcolor[3] = 0; \ + avgcolor[4] = 0; \ + wsum = 0; \ + for(pix = 0; pix < cnt; ++pix) \ + { \ + w = 0; \ + for(comp = 0; comp < 3; ++comp) \ + w += getpixel; \ + if(w) /* ignore perfectly black pixels because that is better for model skins */ \ + { \ + ++wsum; \ + /* comp = 3; -- not needed, comp is always 3 when we get here */ \ + w = getpixel; \ + for(comp = 0; comp < 3; ++comp) \ + avgcolor[comp] += getpixel * w; \ + avgcolor[3] += w; \ + } \ + /* comp = 3; -- not needed, comp is always 3 when we get here */ \ + avgcolor[4] += getpixel; \ + } \ + if(avgcolor[3] == 0) /* no pixels seen? even worse */ \ + avgcolor[3] = 1; \ + skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \ + skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \ + skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \ + skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \ + } + +skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha) { // FIXME: it should be possible to disable loading various layers using // cvars, to prevent wasted loading time and memory usage if the user does @@ -1827,6 +1969,8 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole int basepixels_height; skinframe_t *skinframe; + *has_alpha = false; + if (cls.state == ca_dedicated) return NULL; @@ -1841,6 +1985,9 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole if (basepixels == NULL) return NULL; + if (developer_loading.integer) + Con_Printf("loading skin \"%s\"\n", name); + // 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); @@ -1866,6 +2013,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole if (j < basepixels_width * basepixels_height * 4) { // has transparent pixels + *has_alpha = true; pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4); for (j = 0;j < image_width * image_height * 4;j += 4) { @@ -1879,12 +2027,15 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole } } + R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]); + //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]); + // _norm is the name used by tenebrae and has been adopted as standard if (loadnormalmap) { if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL) { - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); Mem_Free(pixels); pixels = NULL; } @@ -1892,7 +2043,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4); Image_HeightmapToNormalmap_BGRA(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_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); Mem_Free(pixels); Mem_Free(bumppixels); } @@ -1900,7 +2051,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4); Image_HeightmapToNormalmap_BGRA(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_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); Mem_Free(pixels); } } @@ -1918,6 +2069,12 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole return skinframe; } +skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain) +{ + qboolean has_alpha; + return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha); +} + 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; @@ -1961,6 +2118,9 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co if (!skindata) return NULL; + if (developer_loading.integer) + Con_Printf("loading 32bit skin \"%s\"\n", name); + if (r_shadow_bumpscale_basetexture.value > 0) { temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); @@ -1986,6 +2146,9 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co } } + R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]); + //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]); + return skinframe; } @@ -1993,6 +2156,7 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i { int i; unsigned char *temp1, *temp2; + unsigned int *palette; skinframe_t *skinframe; if (cls.state == ca_dedicated) @@ -2003,6 +2167,8 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i if (skinframe && skinframe->base) return skinframe; + palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)); + skinframe->stain = NULL; skinframe->merged = NULL; skinframe->base = r_texture_notexture; @@ -2017,6 +2183,9 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i if (!skindata) return NULL; + if (developer_loading.integer) + Con_Printf("loading quake skin \"%s\"\n", name); + if (r_shadow_bumpscale_basetexture.value > 0) { temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); @@ -2028,7 +2197,7 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i 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), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all + skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all if (loadglowtexture) skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow if (loadpantsandshirt) @@ -2047,6 +2216,9 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask } + R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]); + //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]); + return skinframe; } @@ -2068,11 +2240,20 @@ skinframe_t *R_SkinFrame_LoadMissing(void) skinframe->glow = NULL; skinframe->fog = NULL; + skinframe->avgcolor[0] = rand() / RAND_MAX; + skinframe->avgcolor[1] = rand() / RAND_MAX; + skinframe->avgcolor[2] = rand() / RAND_MAX; + skinframe->avgcolor[3] = 1; + return skinframe; } void gl_main_start(void) { + r_numqueries = 0; + r_maxqueries = 0; + memset(r_queries, 0, sizeof(r_queries)); + memset(r_qwskincache, 0, sizeof(r_qwskincache)); memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe)); @@ -2090,6 +2271,7 @@ void gl_main_start(void) R_BuildNormalizationCube(); } r_texture_fogattenuation = NULL; + r_texture_gammaramps = NULL; //r_texture_fogintensity = NULL; memset(&r_bloomstate, 0, sizeof(r_bloomstate)); memset(&r_waterstate, 0, sizeof(r_waterstate)); @@ -2101,6 +2283,13 @@ void gl_main_start(void) void gl_main_shutdown(void) { + if (r_maxqueries) + qglDeleteQueriesARB(r_maxqueries, r_queries); + + r_numqueries = 0; + r_maxqueries = 0; + memset(r_queries, 0, sizeof(r_queries)); + memset(r_qwskincache, 0, sizeof(r_qwskincache)); memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe)); @@ -2119,6 +2308,7 @@ void gl_main_shutdown(void) r_texture_whitecube = NULL; r_texture_normalizationcube = NULL; r_texture_fogattenuation = NULL; + r_texture_gammaramps = NULL; //r_texture_fogintensity = NULL; memset(&r_bloomstate, 0, sizeof(r_bloomstate)); memset(&r_waterstate, 0, sizeof(r_waterstate)); @@ -2169,6 +2359,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable (&gl_skyclip); } Cvar_RegisterVariable(&r_depthfirst); + Cvar_RegisterVariable(&r_useinfinitefarclip); Cvar_RegisterVariable(&r_nearclip); Cvar_RegisterVariable(&r_showbboxes); Cvar_RegisterVariable(&r_showsurfaces); @@ -2198,12 +2389,19 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_polygonoffset_submodel_factor); Cvar_RegisterVariable(&r_polygonoffset_submodel_offset); Cvar_RegisterVariable(&r_fog_exp2); + Cvar_RegisterVariable(&r_drawfog); Cvar_RegisterVariable(&r_textureunits); Cvar_RegisterVariable(&r_glsl); + Cvar_RegisterVariable(&r_glsl_contrastboost); + Cvar_RegisterVariable(&r_glsl_deluxemapping); Cvar_RegisterVariable(&r_glsl_offsetmapping); Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping); Cvar_RegisterVariable(&r_glsl_offsetmapping_scale); - Cvar_RegisterVariable(&r_glsl_deluxemapping); + Cvar_RegisterVariable(&r_glsl_postprocess); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec1); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec2); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec3); + Cvar_RegisterVariable(&r_glsl_postprocess_uservec4); Cvar_RegisterVariable(&r_glsl_usegeneric); Cvar_RegisterVariable(&r_water); Cvar_RegisterVariable(&r_water_resolutionmultiplier); @@ -2223,7 +2421,6 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_bloom_colorsubtract); Cvar_RegisterVariable(&r_hdr); Cvar_RegisterVariable(&r_hdr_scenebrightness); - Cvar_RegisterVariable(&r_glsl_contrastboost); Cvar_RegisterVariable(&r_hdr_glowintensity); Cvar_RegisterVariable(&r_hdr_range); Cvar_RegisterVariable(&r_smoothnormals_areaweighting); @@ -2278,6 +2475,22 @@ GL_Init extern char *ENGINE_EXTENSIONS; void GL_Init (void) { + gl_renderer = (const char *)qglGetString(GL_RENDERER); + gl_vendor = (const char *)qglGetString(GL_VENDOR); + gl_version = (const char *)qglGetString(GL_VERSION); + gl_extensions = (const char *)qglGetString(GL_EXTENSIONS); + + if (!gl_extensions) + gl_extensions = ""; + if (!gl_platformextensions) + gl_platformextensions = ""; + + Con_Printf("GL_VENDOR: %s\n", gl_vendor); + Con_Printf("GL_RENDERER: %s\n", gl_renderer); + Con_Printf("GL_VERSION: %s\n", gl_version); + Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions); + Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions); + VID_CheckExtensions(); // LordHavoc: report supported extensions @@ -2400,11 +2613,14 @@ static void R_View_UpdateEntityVisible (void) if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs) { // worldmodel can check visibility + memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities); for (i = 0;i < r_refdef.scene.numentities;i++) { ent = r_refdef.scene.entities[i]; - r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs)); - + if (!(ent->flags & renderimask)) + if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE))) + if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs)) + r_refdef.viewcache.entityvisible[i] = true; } if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight) { @@ -2697,7 +2913,7 @@ void R_SetupView(qboolean allowwaterclippingplane) { if (!r_refdef.view.useperspective) GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip); - else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows) + else if (gl_stencil && r_useinfinitefarclip.integer) GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip); else GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip); @@ -2773,67 +2989,6 @@ void R_ResetViewRendering3D(void) R_SetupGenericShader(true); } -/* - R_Bloom_SetupShader( -"// bloom shader\n" -"// written by Forest 'LordHavoc' Hale\n" -"\n" -"// common definitions between vertex shader and fragment shader:\n" -"\n" -"#ifdef __GLSL_CG_DATA_TYPES\n" -"#define myhalf half\n" -"#define myhalf2 half2\n" -"#define myhalf3 half3\n" -"#define myhalf4 half4\n" -"#else\n" -"#define myhalf float\n" -"#define myhalf2 vec2\n" -"#define myhalf3 vec3\n" -"#define myhalf4 vec4\n" -"#endif\n" -"\n" -"varying vec2 ScreenTexCoord;\n" -"varying vec2 BloomTexCoord;\n" -"\n" -"\n" -"\n" -"\n" -"// vertex shader specific:\n" -"#ifdef VERTEX_SHADER\n" -"\n" -"void main(void)\n" -"{\n" -" ScreenTexCoord = vec2(gl_MultiTexCoord0);\n" -" BloomTexCoord = vec2(gl_MultiTexCoord1);\n" -" // transform vertex to camera space, using ftransform to match non-VS\n" -" // rendering\n" -" gl_Position = ftransform();\n" -"}\n" -"\n" -"#endif // VERTEX_SHADER\n" -"\n" -"\n" -"\n" -"\n" -"// fragment shader specific:\n" -"#ifdef FRAGMENT_SHADER\n" -"\n" -"void main(void)\n" -"{\n" -" int x, y; -" myhalf3 color = myhalf3(texture2D(Texture_Screen, ScreenTexCoord));\n" -" for (x = -BLUR_X;x <= BLUR_X;x++) -" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n" -" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n" -" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n" -" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n" - -" gl_FragColor = vec4(color);\n" -"}\n" -"\n" -"#endif // FRAGMENT_SHADER\n" -*/ - void R_RenderScene(qboolean addwaterplanes); static void R_Water_StartFrame(void) @@ -2849,7 +3004,7 @@ static void R_Water_StartFrame(void) // calculate desired texture sizes // can't use water if the card does not support the texture size - if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size) + if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer) texturewidth = textureheight = waterwidth = waterheight = 0; else if (gl_support_arb_texture_non_power_of_two) { @@ -2904,6 +3059,7 @@ static void R_Water_AddWaterPlane(msurface_t *surface) vec3_t vert[3]; vec3_t normal; vec3_t center; + mplane_t plane; r_waterstate_waterplane_t *p; // just use the first triangle with a valid normal for any decisions VectorClear(normal); @@ -2917,6 +3073,21 @@ static void R_Water_AddWaterPlane(msurface_t *surface) break; } + VectorCopy(normal, plane.normal); + VectorNormalize(plane.normal); + plane.dist = DotProduct(vert[0], plane.normal); + PlaneClassify(&plane); + if (PlaneDiff(r_refdef.view.origin, &plane) < 0) + { + // skip backfaces (except if nocullface is set) + if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE)) + return; + VectorNegate(plane.normal, plane.normal); + plane.dist *= -1; + PlaneClassify(&plane); + } + + // find a matching plane if there is one for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++) if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1) @@ -2929,17 +3100,7 @@ static void R_Water_AddWaterPlane(msurface_t *surface) { // store the new plane r_waterstate.numwaterplanes++; - VectorCopy(normal, p->plane.normal); - VectorNormalize(p->plane.normal); - p->plane.dist = DotProduct(vert[0], p->plane.normal); - PlaneClassify(&p->plane); - // flip the plane if it does not face the viewer - if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0) - { - VectorNegate(p->plane.normal, p->plane.normal); - p->plane.dist *= -1; - PlaneClassify(&p->plane); - } + p->plane = plane; // clear materialflags and pvs p->materialflags = 0; p->pvsvalid = false; @@ -3070,6 +3231,8 @@ void R_Bloom_StartFrame(void) r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width); r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width; r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height); + r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size); + r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size); // calculate desired texture sizes if (gl_support_arb_texture_non_power_of_two) @@ -3087,33 +3250,16 @@ void R_Bloom_StartFrame(void) for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2); } - if (r_hdr.integer) - { - screentexturewidth = screentextureheight = 0; - } - else if (r_bloom.integer) + if ((r_hdr.integer || r_bloom.integer) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size)) { + Cvar_SetValueQuick(&r_hdr, 0); + Cvar_SetValueQuick(&r_bloom, 0); } - else - { + + if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer) screentexturewidth = screentextureheight = 0; + if (!r_hdr.integer && !r_bloom.integer) bloomtexturewidth = bloomtextureheight = 0; - } - - if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size) - { - // can't use bloom if the parameters are too weird - // can't use bloom if the card does not support the texture size - if (r_bloomstate.texture_screen) - R_FreeTexture(r_bloomstate.texture_screen); - if (r_bloomstate.texture_bloom) - R_FreeTexture(r_bloomstate.texture_bloom); - memset(&r_bloomstate, 0, sizeof(r_bloomstate)); - return; - } - - r_bloomstate.enabled = true; - r_bloomstate.hdr = r_hdr.integer != 0; // allocate textures as needed if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight) @@ -3140,10 +3286,10 @@ void R_Bloom_StartFrame(void) // set up a texcoord array for the full resolution screen image // (we have to keep this around to copy back during final render) r_bloomstate.screentexcoord2f[0] = 0; - r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight; - r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth; - r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight; - r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth; + r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight; + r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth; + r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight; + r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth; r_bloomstate.screentexcoord2f[5] = 0; r_bloomstate.screentexcoord2f[6] = 0; r_bloomstate.screentexcoord2f[7] = 0; @@ -3152,38 +3298,34 @@ void R_Bloom_StartFrame(void) // (which will be additive blended over the screen image) r_bloomstate.bloomtexcoord2f[0] = 0; r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight; - r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; + r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight; - r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; + r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; r_bloomstate.bloomtexcoord2f[5] = 0; r_bloomstate.bloomtexcoord2f[6] = 0; r_bloomstate.bloomtexcoord2f[7] = 0; + + if (r_hdr.integer || r_bloom.integer) + { + r_bloomstate.enabled = true; + r_bloomstate.hdr = r_hdr.integer != 0; + } } -void R_Bloom_CopyScreenTexture(float colorscale) +void R_Bloom_CopyBloomTexture(float colorscale) { r_refdef.stats.bloom++; - R_ResetViewRendering2D(); - R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); - R_Mesh_ColorPointer(NULL, 0, 0); - R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0); - R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen)); - R_SetupGenericShader(true); - - // copy view into the screen texture - GL_ActiveTexture(0); - CHECKGLERROR - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR - r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height; - - // now scale it down to the bloom texture size + // scale down screen texture to the bloom texture size CHECKGLERROR qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(colorscale, colorscale, colorscale, 1); // TODO: optimize with multitexture or GLSL - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_SetupGenericShader(true); + R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0); + R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen)); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; // we now have a bloom image in the framebuffer @@ -3228,7 +3370,7 @@ void R_Bloom_MakeTexture(void) GL_Color(r, r, r, 1); R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; // copy the vertically blurred bloom view to a texture @@ -3272,7 +3414,7 @@ void R_Bloom_MakeTexture(void) //r = (dir ? 1.0f : brighten)/(range*2+1); r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range)); GL_Color(r, r, r, 1); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; GL_BlendFunc(GL_ONE, GL_ONE); } @@ -3292,7 +3434,7 @@ void R_Bloom_MakeTexture(void) R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0); GL_Color(1, 1, 1, 1); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; GL_BlendFunc(GL_ONE, GL_ONE); @@ -3300,7 +3442,7 @@ void R_Bloom_MakeTexture(void) R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0); GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; qglBlendEquationEXT(GL_FUNC_ADD_EXT); @@ -3358,7 +3500,88 @@ void R_HDR_RenderBloomTexture(void) static void R_BlendView(void) { - if (r_bloomstate.enabled && r_bloomstate.hdr) + if (r_bloomstate.texture_screen) + { + // copy view into the screen texture + R_ResetViewRendering2D(); + R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); + R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen)); + GL_ActiveTexture(0);CHECKGLERROR + qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR + r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height; + } + + if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom)) + { + unsigned int permutation = + (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0) + | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0) + | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0) + | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0); + + if (r_bloomstate.texture_bloom && !r_bloomstate.hdr) + { + // render simple bloom effect + // copy the screen and shrink it and darken it for the bloom process + R_Bloom_CopyBloomTexture(r_bloom_colorscale.value); + // make the bloom texture + R_Bloom_MakeTexture(); + } + + R_ResetViewRendering2D(); + R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); + GL_Color(1, 1, 1, 1); + GL_BlendFunc(GL_ONE, GL_ZERO); + R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation); + R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen)); + R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0); + R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom)); + R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0); + if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) + R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps)); + if (r_glsl_permutation->loc_TintColor >= 0) + qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); + if (r_glsl_permutation->loc_ClientTime >= 0) + qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time); + if (r_glsl_permutation->loc_PixelSize >= 0) + qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight); + if (r_glsl_permutation->loc_UserVec1 >= 0) + { + float a=0, b=0, c=0, d=0; +#if _MSC_VER >= 1400 +#define sscanf sscanf_s +#endif + sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d); + qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d); + } + if (r_glsl_permutation->loc_UserVec2 >= 0) + { + float a=0, b=0, c=0, d=0; + sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d); + qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d); + } + if (r_glsl_permutation->loc_UserVec3 >= 0) + { + float a=0, b=0, c=0, d=0; + sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d); + qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d); + } + if (r_glsl_permutation->loc_UserVec4 >= 0) + { + float a=0, b=0, c=0, d=0; + sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d); + qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d); + } + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); + r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height; + return; + } + + + + if (r_bloomstate.texture_bloom && r_bloomstate.hdr) { // render high dynamic range bloom effect // the bloom texture was made earlier this render, so we just need to @@ -3371,14 +3594,14 @@ static void R_BlendView(void) GL_BlendFunc(GL_ONE, GL_ONE); R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height; } - else if (r_bloomstate.enabled) + else if (r_bloomstate.texture_bloom) { // render simple bloom effect // copy the screen and shrink it and darken it for the bloom process - R_Bloom_CopyScreenTexture(r_bloom_colorscale.value); + R_Bloom_CopyBloomTexture(r_bloom_colorscale.value); // make the bloom texture R_Bloom_MakeTexture(); // put the original screen image back in place and blend the bloom @@ -3400,14 +3623,14 @@ static void R_BlendView(void) else { R_SetupGenericShader(true); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height; // now blend on the bloom texture GL_BlendFunc(GL_ONE, GL_ONE); R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0); } - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height; } if (r_refdef.viewblend[3] >= (1.0f / 256.0f)) @@ -3419,7 +3642,7 @@ static void R_BlendView(void) R_SetupGenericShader(false); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); } } @@ -3458,9 +3681,11 @@ void R_UpdateVariables(void) { R_Textures_Frame(); + r_refdef.scene.ambient = r_ambient.value; + r_refdef.farclip = 4096; if (r_refdef.scene.worldmodel) - r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs); + r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2; r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f); if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1) @@ -3470,17 +3695,17 @@ void R_UpdateVariables(void) r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1); r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1); - r_refdef.rtworld = r_shadow_realtime_world.integer; - r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil; - r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer; - r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil; - r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1; + r_refdef.scene.rtworld = r_shadow_realtime_world.integer; + r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil; + r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer; + r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil; + r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1; if (r_showsurfaces.integer) { - r_refdef.rtworld = false; - r_refdef.rtworldshadows = false; - r_refdef.rtdlight = false; - r_refdef.rtdlightshadows = false; + r_refdef.scene.rtworld = false; + r_refdef.scene.rtworldshadows = false; + r_refdef.scene.rtdlight = false; + r_refdef.scene.rtdlightshadows = false; r_refdef.lightmapintensity = 0; } @@ -3516,7 +3741,7 @@ void R_UpdateVariables(void) // R_UpdateFogColor(); // why? R_RenderScene does it anyway - if (r_refdef.fog_density) + if (r_refdef.fog_density && r_drawfog.integer) { r_refdef.fogenabled = true; // this is the point where the fog reaches 0.9986 alpha, which we @@ -3536,18 +3761,53 @@ void R_UpdateVariables(void) } else r_refdef.fogenabled = false; -} -static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT; -static r_refdef_scene_t r_scenes_store[ RST_COUNT ]; -/* -================ -R_SelectScene -================ -*/ -void R_SelectScene( r_refdef_scene_type_t scenetype ) { - if( scenetype != r_currentscenetype ) { - // store the old scenetype + if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial) + { + if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial) + { + // build GLSL gamma texture +#define RAMPWIDTH 256 + unsigned short ramp[RAMPWIDTH * 3]; + unsigned char ramprgb[RAMPWIDTH][4]; + int i; + + r_texture_gammaramps_serial = vid_gammatables_serial; + + VID_BuildGammaTables(&ramp[0], RAMPWIDTH); + for(i = 0; i < RAMPWIDTH; ++i) + { + ramprgb[i][0] = ramp[i] >> 8; + ramprgb[i][1] = ramp[i + RAMPWIDTH] >> 8; + ramprgb[i][2] = ramp[i + 2 * RAMPWIDTH] >> 8; + ramprgb[i][3] = 0; + } + if (r_texture_gammaramps) + { + R_UpdateTexture(r_texture_gammaramps, &ramprgb[0][0], 0, 0, RAMPWIDTH, 1); + } + else + { + r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &ramprgb[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL); + } + } + } + else + { + // remove GLSL gamma texture + } +} + +static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT; +static r_refdef_scene_t r_scenes_store[ RST_COUNT ]; +/* +================ +R_SelectScene +================ +*/ +void R_SelectScene( r_refdef_scene_type_t scenetype ) { + if( scenetype != r_currentscenetype ) { + // store the old scenetype r_scenes_store[ r_currentscenetype ] = r_refdef.scene; r_currentscenetype = scenetype; // move in the new scene @@ -3577,7 +3837,24 @@ R_RenderView */ void R_RenderView(void) { - if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/) + if (r_refdef.view.isoverlay) + { + // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas] + GL_Clear( GL_DEPTH_BUFFER_BIT ); + R_TimeReport("depthclear"); + + r_refdef.view.showdebug = false; + + r_waterstate.enabled = false; + r_waterstate.numwaterplanes = 0; + + R_RenderScene(false); + + CHECKGLERROR + return; + } + + if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/) return; //Host_Error ("R_RenderView: NULL worldmodel"); r_refdef.view.colorscale = r_hdr_scenebrightness.value; @@ -3830,7 +4107,7 @@ void R_RenderScene(qboolean addwaterplanes) R_ResetViewRendering2D(); } -static const int bboxelements[36] = +static const unsigned short bboxelements[36] = { 5, 1, 3, 5, 3, 7, 6, 2, 0, 6, 0, 4, @@ -3875,7 +4152,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa R_Mesh_ColorPointer(color4f, 0, 0); R_Mesh_ResetTextureState(); R_SetupGenericShader(false); - R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0); + R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0); } static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) @@ -3883,10 +4160,16 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh int i; float color[4]; prvm_edict_t *edict; + prvm_prog_t *prog_save = prog; + // this function draws bounding boxes of server entities if (!sv.active) return; + + GL_CullFace(GL_NONE); R_SetupGenericShader(false); + + prog = 0; SV_VM_Begin(); for (i = 0;i < numsurfaces;i++) { @@ -3907,6 +4190,7 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]); } SV_VM_End(); + prog = prog_save; } static void R_DrawEntityBBoxes(void) @@ -3914,22 +4198,32 @@ static void R_DrawEntityBBoxes(void) int i; prvm_edict_t *edict; vec3_t center; + prvm_prog_t *prog_save = prog; + // this function draws bounding boxes of server entities if (!sv.active) return; + + prog = 0; SV_VM_Begin(); for (i = 0;i < prog->num_edicts;i++) { edict = PRVM_EDICT_NUM(i); if (edict->priv.server->free) continue; + // exclude the following for now, as they don't live in world coordinate space and can't be solid: + if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0) + continue; + if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0) + 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(); + prog = prog_save; } -int nomodelelements[24] = +unsigned short nomodelelements[24] = { 5, 2, 0, 5, 1, 2, @@ -4017,7 +4311,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight else R_Mesh_ColorPointer(nomodelcolor4f, 0, 0); R_Mesh_ResetTextureState(); - R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0); + R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0); } void R_DrawNoModel(entity_render_t *ent) @@ -4109,7 +4403,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_ R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0); // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA) { @@ -4117,7 +4411,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_ GL_BlendFunc(blendfunc1, GL_ONE); fog = 1 - fog; GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca); - R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0); + R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); } } @@ -4270,12 +4564,19 @@ static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) { + int w, h, idx; int i; - model_t *model = ent->model; + dp_model_t *model = ent->model; float f; float tcmat[12]; q3shaderinfo_layer_tcmod_t *tcmod; + if (t->basematerialflags & MATERIALFLAG_NODRAW) + { + t->currentmaterialflags = MATERIALFLAG_NODRAW; + return; + } + // switch to an alternate material if this is a q1bsp animated material { texture_t *texture = t; @@ -4304,12 +4605,13 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) } // update currentskinframe to be a qw skin or animation frame - if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients) + if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) { if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin)) { strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i])); - Con_DPrintf("loading skins/%s\n", r_qwskincache[i]); + if (developer_loading.integer) + Con_Printf("loading skins/%s\n", r_qwskincache[i]); r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0); } t->currentskinframe = r_qwskincache_skinframe[i]; @@ -4324,16 +4626,10 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) t->currentmaterialflags = t->basematerialflags; t->currentalpha = ent->alpha; if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer)) - { t->currentalpha *= r_wateralpha.value; - /* - * FIXME what is this supposed to do? - // if rendering refraction/reflection, disable transparency - if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA))) - t->currentmaterialflags |= MATERIALFLAG_WATERSHADER; - */ - } - if(!r_waterstate.enabled) + if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) + t->currentalpha *= t->r_water_wateralpha; + if(!r_waterstate.enabled || r_refdef.view.isoverlay) t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION); if (!(ent->flags & RENDER_LIGHT)) t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; @@ -4366,7 +4662,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER); // there is no tcmod - if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0) + if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL) t->currenttexmatrix = r_waterscrollmatrix; for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++) @@ -4376,7 +4672,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) { case Q3TCMOD_COUNT: case Q3TCMOD_NONE: - if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0) + if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL) matrix = r_waterscrollmatrix; else matrix = identitymatrix; @@ -4397,6 +4693,14 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) case Q3TCMOD_SCROLL: Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0); break; + case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures) + w = (int) tcmod->parms[0]; + h = (int) tcmod->parms[1]; + f = r_refdef.scene.time / (tcmod->parms[2] * w * h); + f = f - floor(f); + idx = (int) floor(f * w * h); + Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0); + break; case Q3TCMOD_STRETCH: f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms); Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f); @@ -4453,109 +4757,103 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) // lightmaps mode looks bad with dlights using actual texturing, so turn // off the colormap and glossmap, but leave the normalmap on as it still // accurately represents the shading involved - if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED)) + if (gl_lightmaps.integer) { - t->basetexture = r_texture_white; + t->basetexture = r_texture_grey128; + t->backgroundbasetexture = NULL; t->specularscale = 0; + t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE)); } Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha); VectorClear(t->dlightcolor); t->currentnumlayers = 0; - if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW)) + if (t->currentmaterialflags & MATERIALFLAG_WALL) { - if (!(t->currentmaterialflags & MATERIALFLAG_SKY)) + int layerflags = 0; + int blendfunc1, blendfunc2, depthmask; + if (t->currentmaterialflags & MATERIALFLAG_ADD) { - int blendfunc1, blendfunc2, depthmask; - if (t->currentmaterialflags & MATERIALFLAG_ADD) - { - blendfunc1 = GL_SRC_ALPHA; - blendfunc2 = GL_ONE; - } - else if (t->currentmaterialflags & MATERIALFLAG_ALPHA) - { - blendfunc1 = GL_SRC_ALPHA; - blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - } - else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) - { - blendfunc1 = t->customblendfunc[0]; - blendfunc2 = t->customblendfunc[1]; - } - else - { - blendfunc1 = GL_ONE; - blendfunc2 = GL_ZERO; - } - depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED); - if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL)) + blendfunc1 = GL_SRC_ALPHA; + blendfunc2 = GL_ONE; + } + else if (t->currentmaterialflags & MATERIALFLAG_ALPHA) + { + blendfunc1 = GL_SRC_ALPHA; + blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) + { + blendfunc1 = t->customblendfunc[0]; + blendfunc2 = t->customblendfunc[1]; + } + else + { + blendfunc1 = GL_ONE; + blendfunc2 = GL_ZERO; + } + depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED); + if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED)) + layerflags |= TEXTURELAYERFLAG_FOGDARKEN; + if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) + { + // fullbright is not affected by r_refdef.lightmapintensity + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]); + if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); + if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); + } + else + { + vec3_t ambientcolor; + float colorscale; + // set the color tint used for lights affecting this surface + VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]); + colorscale = 2; + // q3bsp has no lightmap updates, so the lightstylevalue that + // would normally be baked into the lightmap must be + // applied to the color + // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright) + if (ent->model->type == mod_brushq3) + colorscale *= r_refdef.scene.rtlightstylevalue[0]; + colorscale *= r_refdef.lightmapintensity; + VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor); + VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor); + // basic lit geometry + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]); + // add pants/shirt if needed + if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); + if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); + // now add ambient passes if needed + if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f)) { - rtexture_t *currentbasetexture; - int layerflags = 0; - if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED)) - layerflags |= TEXTURELAYERFLAG_FOGDARKEN; - currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base; - if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) - { - // fullbright is not affected by r_refdef.lightmapintensity - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]); - if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); - if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); - } - else - { - vec3_t ambientcolor; - float colorscale; - // set the color tint used for lights affecting this surface - VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]); - colorscale = 2; - // q3bsp has no lightmap updates, so the lightstylevalue that - // would normally be baked into the lightmap must be - // applied to the color - // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright) - if (ent->model->type == mod_brushq3) - colorscale *= r_refdef.scene.rtlightstylevalue[0]; - colorscale *= r_refdef.lightmapintensity; - VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor); - VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor); - // basic lit geometry - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]); - // add pants/shirt if needed - if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); - if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); - // now add ambient passes if needed - if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f)) - { - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]); - if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]); - if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]); - } - } - if (t->currentskinframe->glow != NULL) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]); - if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD)) - { - // if this is opaque use alpha blend which will darken the earlier - // passes cheaply. - // - // if this is an alpha blended material, all the earlier passes - // were darkened by fog already, so we only need to add the fog - // color ontop through the fog mask texture - // - // if this is an additive blended material, all the earlier passes - // were darkened by fog already, and we should not add fog color - // (because the background was not darkened, there is no fog color - // that was lost behind it). - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]); - } + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]); + if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]); + if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]); } } + if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]); + if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD)) + { + // if this is opaque use alpha blend which will darken the earlier + // passes cheaply. + // + // if this is an alpha blended material, all the earlier passes + // were darkened by fog already, so we only need to add the fog + // color ontop through the fog mask texture + // + // if this is an additive blended material, all the earlier passes + // were darkened by fog already, and we should not add fog color + // (because the background was not darkened, there is no fog color + // that was lost behind it). + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]); + } } } @@ -4591,19 +4889,9 @@ void R_Mesh_ResizeArrays(int newvertices) rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31; } -void RSurf_CleanUp(void) -{ - CHECKGLERROR - GL_AlphaTest(false); - rsurface.mode = RSURFMODE_NONE; - rsurface.uselightmaptexture = false; - rsurface.texture = NULL; -} - void RSurf_ActiveWorldEntity(void) { - model_t *model = r_refdef.scene.worldmodel; - RSurf_CleanUp(); + dp_model_t *model = r_refdef.scene.worldmodel; if (rsurface.array_size < model->surfmesh.num_vertices) R_Mesh_ResizeArrays(model->surfmesh.num_vertices); rsurface.matrix = identitymatrix; @@ -4647,7 +4935,9 @@ void RSurf_ActiveWorldEntity(void) rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo; rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f; rsurface.modelelement3i = model->surfmesh.data_element3i; - rsurface.modelelement3i_bufferobject = model->surfmesh.ebo; + rsurface.modelelement3s = model->surfmesh.data_element3s; + rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i; + rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s; rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets; rsurface.modelnum_vertices = model->surfmesh.num_vertices; rsurface.modelnum_triangles = model->surfmesh.num_triangles; @@ -4670,8 +4960,7 @@ void RSurf_ActiveWorldEntity(void) void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents) { - model_t *model = ent->model; - RSurf_CleanUp(); + dp_model_t *model = ent->model; if (rsurface.array_size < model->surfmesh.num_vertices) R_Mesh_ResizeArrays(model->surfmesh.num_vertices); rsurface.matrix = ent->matrix; @@ -4699,7 +4988,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value; rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value; } - if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0)) + if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0)) { if (wanttangents) { @@ -4707,7 +4996,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.modelsvector3f = rsurface.array_modelsvector3f; rsurface.modeltvector3f = rsurface.array_modeltvector3f; rsurface.modelnormal3f = rsurface.array_modelnormal3f; - Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f); + model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f); } else if (wantnormals) { @@ -4715,7 +5004,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.modelsvector3f = NULL; rsurface.modeltvector3f = NULL; rsurface.modelnormal3f = rsurface.array_modelnormal3f; - Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL); + model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL); } else { @@ -4723,7 +5012,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.modelsvector3f = NULL; rsurface.modeltvector3f = NULL; rsurface.modelnormal3f = NULL; - Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL); + model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL); } rsurface.modelvertex3f_bufferobject = 0; rsurface.modelvertex3f_bufferoffset = 0; @@ -4761,7 +5050,9 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo; rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f; rsurface.modelelement3i = model->surfmesh.data_element3i; - rsurface.modelelement3i_bufferobject = model->surfmesh.ebo; + rsurface.modelelement3s = model->surfmesh.data_element3s; + rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i; + rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s; rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets; rsurface.modelnum_vertices = model->surfmesh.num_vertices; rsurface.modelnum_triangles = model->surfmesh.num_triangles; @@ -5215,7 +5506,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.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } else if (r_batchmode.integer == 2) { @@ -5228,7 +5519,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.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); continue; } memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3])); @@ -5247,7 +5538,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel } surface2 = texturesurfacelist[j-1]; numvertices = endvertex - firstvertex; - R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0); + R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0); } } else if (r_batchmode.integer == 1) @@ -5262,7 +5553,7 @@ 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.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } else @@ -5271,7 +5562,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel { surface = texturesurfacelist[i]; GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } } @@ -5325,7 +5616,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black)); } GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } @@ -5346,7 +5637,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa 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.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } else if (r_batchmode.integer == 2) { @@ -5362,7 +5653,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa j = i + 1; if (surface->num_triangles > MAXBATCHTRIANGLES) { - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); continue; } memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3])); @@ -5381,7 +5672,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa } surface2 = texturesurfacelist[j-1]; numvertices = endvertex - firstvertex; - R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0); + R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0); } } else if (r_batchmode.integer == 1) @@ -5415,7 +5706,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa 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.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } #if 0 Con_Printf("\n"); @@ -5430,7 +5721,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa 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.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } } @@ -5448,7 +5739,7 @@ static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **te { float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale; GL_Color(f, f, f, 1); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface.modelelement3i + 3 * (j + surface->num_firsttriangle)), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * (j + surface->num_firsttriangle))); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } } @@ -5460,11 +5751,32 @@ 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_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1); GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle)); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject); } } } +static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist) +{ + int texturesurfaceindex; + int i; + float *v, *c2; + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + 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) + { + c2[0] = 0.5; + c2[1] = 0.5; + c2[2] = 0.5; + c2[3] = 1; + } + } + rsurface.lightmapcolor4f = rsurface.array_color4f; + rsurface.lightmapcolor4f_bufferobject = 0; + rsurface.lightmapcolor4f_bufferoffset = 0; +} + static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist) { int texturesurfaceindex; @@ -5507,6 +5819,32 @@ static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **t rsurface.lightmapcolor4f_bufferoffset = 0; } +static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist) +{ + int texturesurfaceindex; + int i; + float f; + float *v, *c, *c2; + if (!rsurface.lightmapcolor4f) + return; + // generate color arrays for the surfaces in this list + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + 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 = FogPoint_Model(v); + c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f); + c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f); + c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f); + c2[3] = c[3]; + } + } + 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) { int texturesurfaceindex; @@ -5530,6 +5868,29 @@ static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t * rsurface.lightmapcolor4f_bufferoffset = 0; } +static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist) +{ + int texturesurfaceindex; + int i; + float *c, *c2; + if (!rsurface.lightmapcolor4f) + return; + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; + for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4) + { + c2[0] = c[0] + r_refdef.scene.ambient / 128.0; + c2[1] = c[1] + r_refdef.scene.ambient / 128.0; + c2[2] = c[2] + r_refdef.scene.ambient / 128.0; + c2[3] = c[3]; + } + } + 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 @@ -5563,7 +5924,7 @@ static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t int i; float *c; // TODO: optimize - if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples) + if (texturesurfacelist[0]->lightmapinfo) { // generate color arrays for the surfaces in this list for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) @@ -5618,12 +5979,12 @@ static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } -static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) +static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor) { int texturesurfaceindex; int i; float f; - float *v, *c, *c2; + float *v, *c, *c2, alpha; vec3_t ambientcolor; vec3_t diffusecolor; vec3_t lightdir; @@ -5631,13 +5992,14 @@ static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t // model lighting VectorCopy(rsurface.modellight_lightdir, lightdir); f = 0.5f * r_refdef.lightmapintensity; - ambientcolor[0] = rsurface.modellight_ambient[0] * r * f; - ambientcolor[1] = rsurface.modellight_ambient[1] * g * f; - ambientcolor[2] = rsurface.modellight_ambient[2] * b * f; - diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f; - diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f; - diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f; - if (VectorLength2(diffusecolor) > 0) + ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f; + ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f; + ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f; + diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f; + diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f; + diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f; + alpha = *a; + if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f) { // generate color arrays for the surfaces in this list for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) @@ -5654,27 +6016,32 @@ static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t VectorMA(ambientcolor, f, diffusecolor, c); else VectorCopy(ambientcolor, c); - c[3] = a; + c[3] = alpha; } } - r = 1; - g = 1; - b = 1; - a = 1; - applycolor = false; + *r = 1; + *g = 1; + *b = 1; + *a = 1; rsurface.lightmapcolor4f = rsurface.array_color4f; rsurface.lightmapcolor4f_bufferobject = 0; rsurface.lightmapcolor4f_bufferoffset = 0; + *applycolor = false; } else { - r = ambientcolor[0]; - g = ambientcolor[1]; - b = ambientcolor[2]; + *r = ambientcolor[0]; + *g = ambientcolor[1]; + *b = ambientcolor[2]; rsurface.lightmapcolor4f = NULL; rsurface.lightmapcolor4f_bufferobject = 0; rsurface.lightmapcolor4f_bufferoffset = 0; } +} + +static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) +{ + RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor); 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, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset); @@ -5693,32 +6060,12 @@ void RSurf_SetupDepthAndCulling(void) GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back); } -static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist) -{ - RSurf_SetupDepthAndCulling(); - if (rsurface.mode != RSURFMODE_SHOWSURFACES) - { - rsurface.mode = RSURFMODE_SHOWSURFACES; - GL_DepthMask(true); - GL_BlendFunc(GL_ONE, GL_ZERO); - R_Mesh_ColorPointer(NULL, 0, 0); - R_Mesh_ResetTextureState(); - } - RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); - RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist); -} - static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist) { // transparent sky would be ridiculous if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) return; - if (rsurface.mode != RSURFMODE_SKY) - { - if (rsurface.mode == RSURFMODE_GLSL) - R_SetupGenericShader(false); - rsurface.mode = RSURFMODE_SKY; - } + R_SetupGenericShader(false); if (skyrendernow) { skyrendernow = false; @@ -5762,20 +6109,15 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te if (skyrendermasked) GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1); } + R_Mesh_ResetTextureState(); + GL_Color(1, 1, 1, 1); } -static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist) +static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth) { if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))) return; - if (rsurface.mode != RSURFMODE_GLSL) - { - rsurface.mode = RSURFMODE_GLSL; - R_Mesh_ResetTextureState(); - GL_Color(1, 1, 1, 1); - } - R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix); R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap)); R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture)); @@ -5788,8 +6130,11 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture)); R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow)); } - R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants)); - R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt)); + if(rsurface.texture->colormapping) + { + R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants)); + R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt)); + } R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation)); if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)) R_Mesh_ColorPointer(NULL, 0, 0); @@ -5817,10 +6162,10 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset); RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1); } + GL_LockArrays(0, 0); GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); GL_DepthMask(false); - GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)) R_Mesh_ColorPointer(NULL, 0, 0); else @@ -5846,6 +6191,12 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t GL_DepthMask(true); GL_AlphaTest(false); } + else + { + GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); + GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); + } if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) { @@ -5861,9 +6212,10 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t else RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); } + GL_LockArrays(0, 0); } -static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist) +static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth) { // OpenGL 1.3 path - anything not completely ancient int texturesurfaceindex; @@ -5872,8 +6224,6 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **t rmeshstate_t m; int layerindex; const texturelayer_t *layer; - if (rsurface.mode != RSURFMODE_MULTIPASS) - rsurface.mode = RSURFMODE_MULTIPASS; RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist); for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++) @@ -5890,7 +6240,7 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **t qglDepthFunc(GL_EQUAL);CHECKGLERROR } } - GL_DepthMask(layer->depthmask); + GL_DepthMask(layer->depthmask && writedepth); GL_BlendFunc(layer->blendfunc1, layer->blendfunc2); if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) { @@ -5987,7 +6337,7 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **t } } -static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist) +static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth) { // OpenGL 1.1 - crusty old voodoo path int texturesurfaceindex; @@ -5995,8 +6345,6 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t rmeshstate_t m; int layerindex; const texturelayer_t *layer; - if (rsurface.mode != RSURFMODE_MULTIPASS) - rsurface.mode = RSURFMODE_MULTIPASS; RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist); for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++) @@ -6011,7 +6359,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t qglDepthFunc(GL_EQUAL);CHECKGLERROR } } - GL_DepthMask(layer->depthmask); + GL_DepthMask(layer->depthmask && writedepth); GL_BlendFunc(layer->blendfunc1, layer->blendfunc2); R_Mesh_ColorPointer(NULL, 0, 0); applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0; @@ -6118,117 +6466,121 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **t } } -static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly) +static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth) { - if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW) - return; - rsurface.rtlight = NULL; - CHECKGLERROR - if (depthonly) + float c[4]; + + GL_AlphaTest(false); + R_Mesh_ColorPointer(NULL, 0, 0); + R_Mesh_ResetTextureState(); + R_SetupGenericShader(false); + + if(rsurface.texture && rsurface.texture->currentskinframe) + memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c)); + else { - if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST))) - return; - if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))) - return; - if (rsurface.mode != RSURFMODE_MULTIPASS) - rsurface.mode = RSURFMODE_MULTIPASS; - if (r_depthfirst.integer == 3) - { - int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces); - if (!r_refdef.view.showdebug) - GL_Color(0, 0, 0, 1); - else - GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1); - } - else - { - GL_ColorMask(0,0,0,0); - GL_Color(1,1,1,1); - } - RSurf_SetupDepthAndCulling(); - GL_DepthTest(true); - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(true); - GL_AlphaTest(false); - R_Mesh_ColorPointer(NULL, 0, 0); - R_Mesh_ResetTextureState(); - RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); - R_SetupDepthOrShadowShader(); - RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); - GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1); + c[0] = 1; + c[1] = 0; + c[2] = 1; + c[3] = 1; } - else if (r_depthfirst.integer == 3) - return; - else if (!r_refdef.view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer)) + + if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt) { - GL_Color(0, 0, 0, 1); - R_SetupGenericShader(false); - RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); + c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7); + c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7); + c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7); } - else if (r_showsurfaces.integer) + + // brighten it up (as texture value 127 means "unlit") + c[0] *= 2 * r_refdef.view.colorscale; + c[1] *= 2 * r_refdef.view.colorscale; + c[2] *= 2 * r_refdef.view.colorscale; + + if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA) + c[3] *= r_wateralpha.value; + + if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1) + { + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); + } + else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD) + { + GL_BlendFunc(GL_ONE, GL_ONE); + GL_DepthMask(false); + } + else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) + { + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead + GL_DepthMask(false); + } + else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) + { + GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]); + GL_DepthMask(false); + } + else { - if (rsurface.mode != RSURFMODE_MULTIPASS) - rsurface.mode = RSURFMODE_MULTIPASS; - RSurf_SetupDepthAndCulling(); - GL_DepthTest(true); GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(writedepth); - GL_Color(1,1,1,1); - GL_AlphaTest(false); - R_Mesh_ColorPointer(NULL, 0, 0); - R_Mesh_ResetTextureState(); - R_SetupGenericShader(false); + } + + rsurface.lightmapcolor4f = NULL; + + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) + { RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); - R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist); + + rsurface.lightmapcolor4f = NULL; + rsurface.lightmapcolor4f_bufferobject = 0; + rsurface.lightmapcolor4f_bufferoffset = 0; } - else if (gl_lightmaps.integer) + else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) { - rmeshstate_t m; - if (rsurface.mode != RSURFMODE_MULTIPASS) - rsurface.mode = RSURFMODE_MULTIPASS; - GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1); - GL_DepthTest(true); - GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back); - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(writedepth); - GL_Color(1,1,1,1); - GL_AlphaTest(false); - R_Mesh_ColorPointer(NULL, 0, 0); - R_SetupGenericShader(true); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(r_texture_white); - m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f; - m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject; - m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset; - R_Mesh_TextureState(&m); - RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist); - if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) - RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false); - else if (rsurface.uselightmaptexture) - 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); + qboolean applycolor = true; + float one = 1.0; + + RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist); + + r_refdef.lightmapintensity = 1; + RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor); + r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all } - else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) - R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist); - else if (rsurface.texture->currentnumlayers) + else { - // write depth for anything we skipped on the depth-only pass earlier - if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) - writedepth = true; - RSurf_SetupDepthAndCulling(); - GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); - GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); - GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); - if (r_glsl.integer && gl_support_fragment_shader) - R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist); - else if (gl_combine.integer && r_textureunits.integer >= 2) - R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist); - else - R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist); + RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); + + rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f; + rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject; + rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset; } + + if(!rsurface.lightmapcolor4f) + RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist); + + RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist); + RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]); + if(r_refdef.fogenabled) + RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist); + + R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); +} + +static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth) +{ + CHECKGLERROR + RSurf_SetupDepthAndCulling(); + if (r_showsurfaces.integer == 3) + R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth); + else if (r_glsl.integer && gl_support_fragment_shader) + R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth); + else if (gl_combine.integer && r_textureunits.integer >= 2) + R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth); + else + R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth); CHECKGLERROR - GL_LockArrays(0, 0); } static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) @@ -6244,7 +6596,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const // to a model, knowing that they are meaningless otherwise if (ent == r_refdef.scene.worldentity) RSurf_ActiveWorldEntity(); - else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f)) + else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f)) RSurf_ActiveModelEntity(ent, false, false); else RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader); @@ -6269,16 +6621,82 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const texturesurfacelist[texturenumsurfaces++] = surface; } // render the range of surfaces - R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false); + R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false); } + GL_AlphaTest(false); +} - RSurf_CleanUp(); +static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity) +{ + CHECKGLERROR + if (depthonly) + { + if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST))) + return; + if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))) + return; + RSurf_SetupDepthAndCulling(); + RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); + } + else if (r_showsurfaces.integer && !r_refdef.view.showdebug) + { + RSurf_SetupDepthAndCulling(); + GL_AlphaTest(false); + R_Mesh_ColorPointer(NULL, 0, 0); + R_Mesh_ResetTextureState(); + R_SetupGenericShader(false); + RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); + GL_DepthMask(true); + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_Color(0, 0, 0, 1); + GL_DepthTest(writedepth); + RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist); + } + else if (r_showsurfaces.integer && r_showsurfaces.integer != 3) + { + RSurf_SetupDepthAndCulling(); + GL_AlphaTest(false); + R_Mesh_ColorPointer(NULL, 0, 0); + R_Mesh_ResetTextureState(); + R_SetupGenericShader(false); + RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist); + GL_DepthMask(true); + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthTest(true); + RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist); + } + else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) + R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist); + else if (!rsurface.texture->currentnumlayers) + return; + else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity) + { + // transparent surfaces get pushed off into the transparent queue + int surfacelistindex; + const msurface_t *surface; + vec3_t tempcenter, center; + for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++) + { + surface = texturesurfacelist[surfacelistindex]; + tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f; + tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f; + tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f; + Matrix4x4_Transform(&rsurface.matrix, tempcenter, center); + R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight); + } + } + else + { + // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier + R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)); + } + CHECKGLERROR } void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes) { int i, j; - vec3_t tempcenter, center; texture_t *texture; // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one if (addwaterplanes) @@ -6299,33 +6717,18 @@ void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surf texture = surfacelist[i]->texture; rsurface.texture = texture->currentframe; rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL; - if (!(rsurface.texture->currentmaterialflags & flagsmask)) + if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)) { // if this texture is not the kind we want, skip ahead to the next one for (;j < numsurfaces && texture == surfacelist[j]->texture;j++) ; continue; } - if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) - { - // transparent surfaces get pushed off into the transparent queue - const msurface_t *surface = surfacelist[i]; - if (depthonly) - continue; - tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f; - tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f; - tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f; - Matrix4x4_Transform(&rsurface.matrix, tempcenter, center); - R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight); - } - 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++) - ; - // render the range of surfaces - R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly); - } + // 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++) + ; + // render the range of surfaces + R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent); } } @@ -6339,7 +6742,7 @@ float locboxvertex3f[6*4*3] = 1,0,0, 0,0,0, 0,1,0, 1,1,0 }; -int locboxelement3i[6*2*3] = +unsigned short locboxelements[6*2*3] = { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, @@ -6390,7 +6793,7 @@ void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, in for (j = 0;j < 3;j++, i++) vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i]; - R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0); + R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0); } void R_DrawLocs(void) @@ -6412,10 +6815,10 @@ void R_DrawDebugModel(entity_render_t *ent) const int *elements; q3mbrush_t *brush; msurface_t *surface; - model_t *model = ent->model; + dp_model_t *model = ent->model; vec3_t v; - flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL; + flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL; R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); @@ -6434,7 +6837,7 @@ void R_DrawDebugModel(entity_render_t *ent) { R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0); GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value); - R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0); + R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0); } } for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++) @@ -6443,7 +6846,7 @@ void R_DrawDebugModel(entity_render_t *ent) { R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0); GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value); - R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0); + R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0); } } } @@ -6537,20 +6940,32 @@ void R_DrawDebugModel(entity_render_t *ent) } extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface); +int r_maxsurfacelist = 0; +msurface_t **r_surfacelist = NULL; void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug) { int i, j, endj, f, flagsmask; - msurface_t *surface; texture_t *t; - model_t *model = r_refdef.scene.worldmodel; - const int maxsurfacelist = 1024; + dp_model_t *model = r_refdef.scene.worldmodel; + msurface_t *surfaces; + unsigned char *update; int numsurfacelist = 0; - msurface_t *surfacelist[1024]; if (model == NULL) return; + if (r_maxsurfacelist < model->num_surfaces) + { + r_maxsurfacelist = model->num_surfaces; + if (r_surfacelist) + Mem_Free(r_surfacelist); + r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist)); + } + RSurf_ActiveWorldEntity(); + surfaces = model->data_surfaces; + update = model->brushq1.lightmapupdateflags; + // update light styles on this submodel if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0) { @@ -6559,17 +6974,16 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep { if (style->value != r_refdef.scene.lightstylevalue[style->style]) { - msurface_t *surfaces = model->data_surfaces; int *list = style->surfacelist; style->value = r_refdef.scene.lightstylevalue[style->style]; for (j = 0;j < style->numsurfaces;j++) - surfaces[list[j]].cached_dlight = true; + update[list[j]] = true; } } } R_UpdateAllTextureInfo(r_refdef.scene.worldentity); - flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL)); + flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL); if (debug) { @@ -6581,65 +6995,75 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep t = NULL; rsurface.uselightmaptexture = false; rsurface.texture = NULL; + rsurface.rtlight = NULL; numsurfacelist = 0; + // add visible surfaces to draw list j = model->firstmodelsurface; endj = j + model->nummodelsurfaces; - while (j < endj) + if (update) { - // quickly skip over non-visible surfaces - for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++) - ; - // quickly iterate over visible surfaces - for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++) + for (;j < endj;j++) { - // process this surface - surface = model->data_surfaces + j; - // if this surface fits the criteria, add it to the list - if (surface->num_triangles) + if (r_refdef.viewcache.world_surfacevisible[j]) { - // if lightmap parameters changed, rebuild lightmap texture - if (surface->cached_dlight) - R_BuildLightMap(r_refdef.scene.worldentity, surface); - // add face to draw list - surfacelist[numsurfacelist++] = surface; - r_refdef.stats.world_triangles += surface->num_triangles; - if (numsurfacelist >= maxsurfacelist) - { - r_refdef.stats.world_surfaces += numsurfacelist; - R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - numsurfacelist = 0; - } + r_surfacelist[numsurfacelist++] = surfaces + j; + // update lightmap if needed + if (update[j]) + R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j); } } } - r_refdef.stats.world_surfaces += numsurfacelist; - if (numsurfacelist) - R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - RSurf_CleanUp(); + else + for (;j < endj;j++) + if (r_refdef.viewcache.world_surfacevisible[j]) + r_surfacelist[numsurfacelist++] = surfaces + j; + // don't do anything if there were no surfaces + if (!numsurfacelist) + return; + R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); + GL_AlphaTest(false); + + // add to stats if desired + if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes) + { + r_refdef.stats.world_surfaces += numsurfacelist; + for (j = 0;j < numsurfacelist;j++) + r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles; + } } void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug) { - int i, j, f, flagsmask; - msurface_t *surface, *endsurface; + int i, j, endj, f, flagsmask; texture_t *t; - model_t *model = ent->model; - const int maxsurfacelist = 1024; + dp_model_t *model = ent->model; + msurface_t *surfaces; + unsigned char *update; int numsurfacelist = 0; - msurface_t *surfacelist[1024]; if (model == NULL) return; + if (r_maxsurfacelist < model->num_surfaces) + { + r_maxsurfacelist = model->num_surfaces; + if (r_surfacelist) + Mem_Free(r_surfacelist); + r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist)); + } + // if the model is static it doesn't matter what value we give for // wantnormals and wanttangents, so this logic uses only rules applicable // to a model, knowing that they are meaningless otherwise if (ent == r_refdef.scene.worldentity) RSurf_ActiveWorldEntity(); - else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f)) + else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f)) RSurf_ActiveModelEntity(ent, false, false); else RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly); + surfaces = model->data_surfaces; + update = model->brushq1.lightmapupdateflags; + // update light styles if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0) { @@ -6648,17 +7072,16 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr { if (style->value != r_refdef.scene.lightstylevalue[style->style]) { - msurface_t *surfaces = model->data_surfaces; int *list = style->surfacelist; style->value = r_refdef.scene.lightstylevalue[style->style]; for (j = 0;j < style->numsurfaces;j++) - surfaces[list[j]].cached_dlight = true; + update[list[j]] = true; } } } R_UpdateAllTextureInfo(ent); - flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL)); + flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL); if (debug) { @@ -6670,30 +7093,30 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr t = NULL; rsurface.uselightmaptexture = false; rsurface.texture = NULL; + rsurface.rtlight = NULL; numsurfacelist = 0; - surface = model->data_surfaces + model->firstmodelsurface; - endsurface = surface + model->nummodelsurfaces; - for (;surface < endsurface;surface++) + // add visible surfaces to draw list + j = model->firstmodelsurface; + endj = j + model->nummodelsurfaces; + for (;j < endj;j++) + r_surfacelist[numsurfacelist++] = surfaces + j; + // don't do anything if there were no surfaces + if (!numsurfacelist) + return; + // update lightmaps if needed + if (update) + for (j = model->firstmodelsurface;j < endj;j++) + if (update[j]) + R_BuildLightMap(ent, surfaces + j); + R_QueueSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); + GL_AlphaTest(false); + + // add to stats if desired + if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes) { - // if this surface fits the criteria, add it to the list - if (surface->num_triangles) - { - // if lightmap parameters changed, rebuild lightmap texture - if (surface->cached_dlight) - R_BuildLightMap(ent, surface); - // add face to draw list - surfacelist[numsurfacelist++] = surface; - r_refdef.stats.entities_triangles += surface->num_triangles; - if (numsurfacelist >= maxsurfacelist) - { - r_refdef.stats.entities_surfaces += numsurfacelist; - R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - numsurfacelist = 0; - } - } + r_refdef.stats.entities++; + r_refdef.stats.entities_surfaces += numsurfacelist; + for (j = 0;j < numsurfacelist;j++) + r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles; } - r_refdef.stats.entities_surfaces += numsurfacelist; - if (numsurfacelist) - R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - RSurf_CleanUp(); }