mempool_t *r_main_mempool;
rtexturepool_t *r_main_texturepool;
+static int r_frame = 0; // used only by R_GetCurrentTexture
+
//
// screen size info
//
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)"};
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)"};
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)"};
cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
-cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
+cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
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
{
int bloomtexturewidth, bloomtextureheight;
rtexture_t *texture_bloom;
- r_glsl_bloomshader_t *shader;
-
// arrays for rendering the screen passes
float screentexcoord2f[8];
float bloomtexcoord2f[8];
}
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;
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];
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)
"\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"
+"//#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"
+"#ifdef MODE_DEPTH_OR_SHADOW\n"
+"\n"
+"# ifdef VERTEX_SHADER\n"
+"void main(void)\n"
+"{\n"
+" gl_Position = ftransform();\n"
+"}\n"
+"# endif\n"
+"\n"
+"#else\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"
+" gl_FrontColor = gl_Color;\n"
+"# ifdef USEDIFFUSE\n"
+" gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
+"# endif\n"
+"# ifdef USESPECULAR\n"
+" gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
+"# endif\n"
+" gl_Position = ftransform();\n"
+"}\n"
+"# endif\n"
+"# ifdef FRAGMENT_SHADER\n"
+"\n"
+"# ifdef USEDIFFUSE\n"
+"uniform sampler2D Texture_First;\n"
+"# endif\n"
+"# ifdef USESPECULAR\n"
+"uniform sampler2D Texture_Second;\n"
+"# endif\n"
+"\n"
+"void main(void)\n"
+"{\n"
+" gl_FragColor = gl_Color;\n"
+"# ifdef USEDIFFUSE\n"
+" gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
+"# endif\n"
+"\n"
+"# ifdef USESPECULAR\n"
+" vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
+"# endif\n"
+"# ifdef USECOLORMAPPING\n"
+" gl_FragColor *= tex2;\n"
+"# endif\n"
+"# ifdef USEGLOW\n"
+" gl_FragColor += tex2;\n"
+"# endif\n"
+"# ifdef USEVERTEXTEXTUREBLEND\n"
+" gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
+"# endif\n"
+"}\n"
+"# endif\n"
+"\n"
+"#else // !MODE_GENERIC\n"
"\n"
"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"
"uniform vec3 EyePosition;\n"
"uniform vec3 LightDir;\n"
"\n"
-"// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
+"// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
"\n"
"void main(void)\n"
"{\n"
" vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
" //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
" vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
-" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
+" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
" gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
"}\n"
"\n"
-"#else // MODE_WATER\n"
+"#else // !MODE_WATER\n"
"#ifdef MODE_REFRACTION\n"
"\n"
"// refraction pass\n"
" gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
"}\n"
"\n"
-"#else // MODE_REFRACTION\n"
+"#else // !MODE_REFRACTION\n"
"void main(void)\n"
"{\n"
"#ifdef USEOFFSETMAPPING\n"
" 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"
" 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"
" 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"
" // 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"
" // 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(normalize(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"
" // 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"
"\n"
" gl_FragColor = vec4(color);\n"
"}\n"
-"#endif // MODE_REFRACTION\n"
-"#endif // MODE_WATER\n"
+"#endif // !MODE_REFRACTION\n"
+"#endif // !MODE_WATER\n"
"\n"
"#endif // FRAGMENT_SHADER\n"
+"\n"
+"#endif // !MODE_GENERIC\n"
+"#endif // !MODE_POSTPROCESS\n"
+"#endif // !MODE_DEPTH_OR_SHADOW\n"
;
typedef struct shaderpermutationinfo_s
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;
{"#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)
SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
// NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
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"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
// 0 if compilation failed
int program;
// 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;
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;
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;
}
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;
qglUseProgramObjectARB(p->program);CHECKGLERROR
// look up all the uniform variable names we care about, so we don't
// 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");
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);
if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
CHECKGLERROR
- qglUseProgramObjectARB(0);CHECKGLERROR
if (developer.integer)
Con_Printf("GLSL shader %s compiled.\n", permutationname);
}
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)
{
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");
Con_Printf("glsl/default.glsl written\n");
}
+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)
+ {
+ r_glsl_permutation = perm;
+ if (!r_glsl_permutation->program)
+ {
+ if (!r_glsl_permutation->compiled)
+ R_GLSL_CompilePermutation(mode, permutation);
+ if (!r_glsl_permutation->program)
+ {
+ // remove features until we find a valid permutation
+ int i;
+ for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
+ {
+ // reduce i more quickly whenever it would not remove any bits
+ int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
+ if (!(permutation & j))
+ continue;
+ permutation -= j;
+ r_glsl_permutation = &r_glsl_permutations[mode][permutation];
+ if (!r_glsl_permutation->compiled)
+ R_GLSL_CompilePermutation(mode, permutation);
+ if (r_glsl_permutation->program)
+ break;
+ }
+ if (i >= SHADERPERMUTATION_COUNT)
+ {
+ Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
+ Cvar_SetValueQuick(&r_glsl, 0);
+ R_GLSL_Restart_f(); // unload shaders
+ return; // no bit left to clear
+ }
+ }
+ }
+ CHECKGLERROR
+ qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
+ }
+}
+
+void R_SetupGenericShader(qboolean usetexture)
+{
+ if (gl_support_fragment_shader)
+ {
+ if (r_glsl.integer && r_glsl_usegeneric.integer)
+ R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
+ else if (r_glsl_permutation)
+ {
+ r_glsl_permutation = NULL;
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ }
+ }
+}
+
+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 | (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;
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ }
+ }
+ if (!r_glsl_permutation)
+ {
+ if (texturemode == GL_DECAL && gl_combine.integer)
+ texturemode = GL_INTERPOLATE_ARB;
+ R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
+ }
+}
+
+void R_SetupDepthOrShadowShader(void)
+{
+ if (gl_support_fragment_shader)
+ {
+ if (r_glsl.integer && r_glsl_usegeneric.integer)
+ R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
+ else if (r_glsl_permutation)
+ {
+ r_glsl_permutation = NULL;
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ }
+ }
+}
+
extern rtexture_t *r_shadow_attenuationgradienttexture;
extern rtexture_t *r_shadow_attenuation2dtexture;
extern rtexture_t *r_shadow_attenuation3dtexture;
-int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
+void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
{
// select a permutation of the lighting shader appropriate to this
// combination of texture, entity, light source, and fogging, only use the
// 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;
- r_glsl_permutation = NULL;
+ unsigned int mode = 0;
// TODO: implement geometry-shader based shadow volumes someday
if (r_glsl_offsetmapping.integer)
{
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;
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)
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;
}
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;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
}
- r_glsl_permutation = &r_glsl_permutations[mode][permutation];
- if (!r_glsl_permutation->program)
- {
- if (!r_glsl_permutation->compiled)
- R_GLSL_CompilePermutation(mode, permutation);
- if (!r_glsl_permutation->program)
- {
- // remove features until we find a valid permutation
- int i;
- for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
- {
- // reduce i more quickly whenever it would not remove any bits
- int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
- if (!(permutation & j))
- continue;
- permutation -= j;
- r_glsl_permutation = &r_glsl_permutations[mode][permutation];
- if (!r_glsl_permutation->compiled)
- R_GLSL_CompilePermutation(mode, permutation);
- if (r_glsl_permutation->program)
- break;
- }
- if (i >= SHADERPERMUTATION_COUNT)
- {
- Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
- Cvar_SetValueQuick(&r_glsl, 0);
- return 0; // no bit left to clear
- }
- }
- }
- CHECKGLERROR
- qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
+ if(permutation & SHADERPERMUTATION_SPECULAR)
+ if(r_shadow_glossexact.integer)
+ permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
+ R_SetupShader_SetPermutation(mode, permutation);
if (mode == SHADERMODE_LIGHTSOURCE)
{
if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
}
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)
{
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
- return permutation;
}
#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)
{
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
int basepixels_height;
skinframe_t *skinframe;
+ *has_alpha = false;
+
if (cls.state == ca_dedicated)
return NULL;
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);
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)
{
}
}
+ 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;
}
{
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);
}
{
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);
}
}
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;
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);
}
}
+ 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;
}
{
int i;
unsigned char *temp1, *temp2;
+ unsigned int *palette;
skinframe_t *skinframe;
if (cls.state == ca_dedicated)
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;
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);
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)
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;
}
if (cls.state == ca_dedicated)
return NULL;
- skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
+ skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
skinframe->stain = NULL;
skinframe->merged = NULL;
skinframe->base = r_texture_notexture;
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));
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));
r_refdef.fogmasktable_density = 0;
}
+extern rtexture_t *loadingscreentexture;
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));
Mem_Free(r_svbsp.nodes);
memset(&r_svbsp, 0, sizeof (r_svbsp));
R_FreeTexturePool(&r_main_texturepool);
+ loadingscreentexture = NULL;
r_texture_blanknormalmap = NULL;
r_texture_white = NULL;
r_texture_grey128 = NULL;
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));
Cvar_RegisterVariable (&gl_skyclip);
}
Cvar_RegisterVariable(&r_depthfirst);
+ Cvar_RegisterVariable(&r_useinfinitefarclip);
Cvar_RegisterVariable(&r_nearclip);
Cvar_RegisterVariable(&r_showbboxes);
Cvar_RegisterVariable(&r_showsurfaces);
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);
Cvar_RegisterVariable(&r_water_clippingplanebias);
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);
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
//==================================================================================
+static void R_View_UpdateEntityLighting (void)
+{
+ int i;
+ entity_render_t *ent;
+ vec3_t tempdiffusenormal;
+
+ for (i = 0;i < r_refdef.scene.numentities;i++)
+ {
+ ent = r_refdef.scene.entities[i];
+
+ // skip unseen models
+ if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
+ continue;
+
+ // skip bsp models
+ if (ent->model && ent->model->brush.num_leafs)
+ {
+ // TODO: use modellight for r_ambient settings on world?
+ VectorSet(ent->modellight_ambient, 0, 0, 0);
+ VectorSet(ent->modellight_diffuse, 0, 0, 0);
+ VectorSet(ent->modellight_lightdir, 0, 0, 1);
+ continue;
+ }
+
+ // fetch the lighting from the worldmodel data
+ VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
+ VectorClear(ent->modellight_diffuse);
+ VectorClear(tempdiffusenormal);
+ if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
+ {
+ vec3_t org;
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+ r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
+ }
+ else // highly rare
+ VectorSet(ent->modellight_ambient, 1, 1, 1);
+
+ // move the light direction into modelspace coordinates for lighting code
+ Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
+ if(VectorLength2(ent->modellight_lightdir) == 0)
+ VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
+ VectorNormalize(ent->modellight_lightdir);
+ }
+}
+
static void R_View_UpdateEntityVisible (void)
{
int i, renderimask;
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)
{
{
int i;
double slopex, slopey;
+ vec3_t forward, left, up, origin;
- // break apart the view matrix into vectors for various purposes
- Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
- VectorNegate(r_refdef.view.left, r_refdef.view.right);
+ // we can't trust r_refdef.view.forward and friends in reflected scenes
+ Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
#if 0
r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
{
slopex = 1.0 / r_refdef.view.frustum_x;
slopey = 1.0 / r_refdef.view.frustum_y;
- VectorMA(r_refdef.view.forward, -slopex, r_refdef.view.left, r_refdef.view.frustum[0].normal);
- VectorMA(r_refdef.view.forward, slopex, r_refdef.view.left, r_refdef.view.frustum[1].normal);
- VectorMA(r_refdef.view.forward, -slopey, r_refdef.view.up , r_refdef.view.frustum[2].normal);
- VectorMA(r_refdef.view.forward, slopey, r_refdef.view.up , r_refdef.view.frustum[3].normal);
- VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
+ VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
+ VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
+ VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
+ VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
+ VectorCopy(forward, r_refdef.view.frustum[4].normal);
// Leaving those out was a mistake, those were in the old code, and they
// fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
VectorNormalize(r_refdef.view.frustum[3].normal);
// calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
- VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, -1024 * slopex, r_refdef.view.left, -1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[0]);
- VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, 1024 * slopex, r_refdef.view.left, -1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[1]);
- VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, -1024 * slopex, r_refdef.view.left, 1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[2]);
- VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, 1024 * slopex, r_refdef.view.left, 1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[3]);
+ VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
+ VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
+ VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
+ VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
}
else
{
- VectorScale(r_refdef.view.left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
- VectorScale(r_refdef.view.left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
- VectorScale(r_refdef.view.up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
- VectorScale(r_refdef.view.up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
- VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
+ VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
+ VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
+ VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
+ VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
+ VectorCopy(forward, r_refdef.view.frustum[4].normal);
r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
// Quake2 has it disabled as well.
// rotate R_VIEWFORWARD right by FOV_X/2 degrees
- //RotatePointAroundVector( r_refdef.view.frustum[0].normal, r_refdef.view.up, r_refdef.view.forward, -(90 - r_refdef.fov_x / 2));
+ //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
//r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
//PlaneClassify(&frustum[0]);
// rotate R_VIEWFORWARD left by FOV_X/2 degrees
- //RotatePointAroundVector( r_refdef.view.frustum[1].normal, r_refdef.view.up, r_refdef.view.forward, (90 - r_refdef.fov_x / 2));
+ //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
//r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
//PlaneClassify(&frustum[1]);
// rotate R_VIEWFORWARD up by FOV_X/2 degrees
- //RotatePointAroundVector( r_refdef.view.frustum[2].normal, r_refdef.view.left, r_refdef.view.forward, -(90 - r_refdef.fov_y / 2));
+ //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
//r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
//PlaneClassify(&frustum[2]);
// rotate R_VIEWFORWARD down by FOV_X/2 degrees
- //RotatePointAroundVector( r_refdef.view.frustum[3].normal, r_refdef.view.left, r_refdef.view.forward, (90 - r_refdef.fov_y / 2));
+ //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
//r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
//PlaneClassify(&frustum[3]);
// nearclip plane
- //VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
+ //VectorCopy(forward, r_refdef.view.frustum[4].normal);
//r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
//PlaneClassify(&frustum[4]);
}
R_View_SetFrustum();
R_View_WorldVisibility(r_refdef.view.useclipplane);
R_View_UpdateEntityVisible();
+ R_View_UpdateEntityLighting();
}
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);
void R_ResetViewRendering2D(void)
{
- if (gl_support_fragment_shader)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
-
DrawQ_Finish();
// GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
+ R_SetupGenericShader(true);
}
void R_ResetViewRendering3D(void)
{
- if (gl_support_fragment_shader)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
-
DrawQ_Finish();
// GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
GL_CullFace(r_refdef.view.cullface_back);
+ 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);
+void R_RenderScene(void);
+void R_RenderWaterPlanes(void);
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)
{
r_waterstate.numwaterplanes = 0;
}
-static void R_Water_AddWaterPlane(msurface_t *surface)
+void R_Water_AddWaterPlane(msurface_t *surface)
{
int triangleindex, planeindex;
const int *e;
vec3_t vert[3];
vec3_t normal;
vec3_t center;
+ mplane_t plane;
r_waterstate_waterplane_t *p;
+ texture_t *t = R_GetCurrentTexture(surface->texture);
// just use the first triangle with a valid normal for any decisions
VectorClear(normal);
for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
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 (!(t->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)
{
// 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;
}
// merge this surface's materialflags into the waterplane
- p->materialflags |= surface->texture->currentframe->currentmaterialflags;
+ p->materialflags |= t->currentmaterialflags;
// merge this surface's PVS into the waterplane
VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
static void R_Water_ProcessPlanes(void)
{
r_refdef_view_t originalview;
+ r_refdef_view_t myview;
int planeindex;
r_waterstate_waterplane_t *p;
}
// render views
+ r_refdef.view = originalview;
+ r_refdef.view.showdebug = false;
+ r_refdef.view.width = r_waterstate.waterwidth;
+ r_refdef.view.height = r_waterstate.waterheight;
+ r_refdef.view.useclipplane = true;
+ myview = r_refdef.view;
+ r_waterstate.renderingscene = true;
for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
{
- r_refdef.view.showdebug = false;
- r_refdef.view.width = r_waterstate.waterwidth;
- r_refdef.view.height = r_waterstate.waterheight;
- r_refdef.view.useclipplane = true;
- r_waterstate.renderingscene = true;
-
// render the normal view scene and copy into texture
// (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
{
+ r_refdef.view = myview;
r_refdef.view.clipplane = p->plane;
VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
PlaneClassify(&r_refdef.view.clipplane);
- R_RenderScene(false);
+ R_ResetViewRendering3D();
+ R_ClearScreen(r_refdef.fogenabled);
+ R_View_Update();
+ R_RenderScene();
// copy view into the screen texture
R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
{
+ r_refdef.view = myview;
// render reflected scene and copy into texture
Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
+ // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
+ Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
r_refdef.view.clipplane = p->plane;
// reverse the cullface settings for this render
r_refdef.view.cullface_front = GL_FRONT;
R_ResetViewRendering3D();
R_ClearScreen(r_refdef.fogenabled);
- if (r_timereport_active)
- R_TimeReport("viewclear");
-
- R_RenderScene(false);
+ R_View_Update();
+ R_RenderScene();
R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
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_ResetViewRendering3D();
- R_ClearScreen(r_refdef.fogenabled);
- if (r_timereport_active)
- R_TimeReport("viewclear");
}
-
- r_refdef.view = originalview;
- r_refdef.view.clear = true;
- r_waterstate.renderingscene = false;
}
+ r_waterstate.renderingscene = false;
+ r_refdef.view = originalview;
+ R_ResetViewRendering3D();
+ R_ClearScreen(r_refdef.fogenabled);
+ R_View_Update();
return;
error:
r_refdef.view = originalview;
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)
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)
// 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;
// (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));
-
- // 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
R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
+ R_SetupGenericShader(true);
// we have a bloom image in the framebuffer
CHECKGLERROR
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
//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);
}
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);
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);
r_refdef.view.showdebug = false;
r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
+ R_ResetViewRendering3D();
+
R_ClearScreen(r_refdef.fogenabled);
if (r_timereport_active)
R_TimeReport("HDRclear");
+ R_View_Update();
+ if (r_timereport_active)
+ R_TimeReport("visibility");
+
r_waterstate.numwaterplanes = 0;
- R_RenderScene(r_waterstate.enabled);
+ if (r_waterstate.enabled)
+ R_RenderWaterPlanes();
+
r_refdef.view.showdebug = true;
+ R_RenderScene();
+ r_waterstate.numwaterplanes = 0;
R_ResetViewRendering2D();
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
R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
+ R_SetupGenericShader(true);
GL_Color(1, 1, 1, 1);
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
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
if (r_textureunits.integer >= 2 && gl_combine.integer)
{
- R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
+ R_SetupGenericTwoTextureShader(GL_ADD);
R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
}
else
{
- R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+ R_SetupGenericShader(true);
+ 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))
R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
+ 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);
}
}
-void R_RenderScene(qboolean addwaterplanes);
-
matrix4x4_t r_waterscrollmatrix;
void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
{
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)
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;
}
// 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
}
else
r_refdef.fogenabled = false;
+
+ 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 rampbgr[RAMPWIDTH][4];
+ int i;
+
+ r_texture_gammaramps_serial = vid_gammatables_serial;
+
+ VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
+ for(i = 0; i < RAMPWIDTH; ++i)
+ {
+ rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
+ rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
+ rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
+ rampbgr[i][3] = 0;
+ }
+ if (r_texture_gammaramps)
+ {
+ R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
+ }
+ else
+ {
+ r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[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
+ r_refdef.scene = r_scenes_store[ r_currentscenetype ];
+ }
+}
+
+/*
+================
+R_GetScenePointer
+================
+*/
+r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
+{
+ // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
+ if( scenetype == r_currentscenetype ) {
+ return &r_refdef.scene;
+ } else {
+ return &r_scenes_store[ scenetype ];
+ }
}
/*
*/
void R_RenderView(void)
{
- if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
+ r_frame++; // used only by R_GetCurrentTexture
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+
+ 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();
+
+ 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;
+ // break apart the view matrix into vectors for various purposes
+ // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
+ // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
+ Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
+ VectorNegate(r_refdef.view.left, r_refdef.view.right);
+ // make an inverted copy of the view matrix for tracking sprites
+ Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+
R_Shadow_UpdateWorldLightSelection();
R_Bloom_StartFrame();
}
r_refdef.view.clear = true;
- r_refdef.view.showdebug = true;
-
// this produces a bloom texture to be used in R_BlendView() later
if (r_hdr.integer)
R_HDR_RenderBloomTexture();
+ r_refdef.view.showdebug = true;
+
+ R_View_Update();
+ if (r_timereport_active)
+ R_TimeReport("visibility");
+
+ r_waterstate.numwaterplanes = 0;
+ if (r_waterstate.enabled)
+ R_RenderWaterPlanes();
+
+ R_RenderScene();
r_waterstate.numwaterplanes = 0;
- R_RenderScene(r_waterstate.enabled);
R_BlendView();
if (r_timereport_active)
CHECKGLERROR
}
-extern void R_DrawLightningBeams (void);
-extern void VM_CL_AddPolygonsToMeshQueue (void);
-extern void R_DrawPortals (void);
-extern cvar_t cl_locs_show;
-static void R_DrawLocs(void);
-static void R_DrawEntityBBoxes(void);
-void R_RenderScene(qboolean addwaterplanes)
+void R_RenderWaterPlanes(void)
{
- Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
- R_UpdateFogColor();
-
- if (addwaterplanes)
+ if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
{
- R_ResetViewRendering3D();
-
- R_View_Update();
+ r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
if (r_timereport_active)
- R_TimeReport("watervis");
-
- if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
- {
- r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
- if (r_timereport_active)
- R_TimeReport("waterworld");
- }
+ R_TimeReport("waterworld");
+ }
- // don't let sound skip if going slow
- if (r_refdef.scene.extraupdate)
- S_ExtraUpdate ();
+ // don't let sound skip if going slow
+ if (r_refdef.scene.extraupdate)
+ S_ExtraUpdate ();
- R_DrawModelsAddWaterPlanes();
- if (r_timereport_active)
- R_TimeReport("watermodels");
+ R_DrawModelsAddWaterPlanes();
+ if (r_timereport_active)
+ R_TimeReport("watermodels");
+ if (r_waterstate.numwaterplanes)
+ {
R_Water_ProcessPlanes();
if (r_timereport_active)
R_TimeReport("waterscenes");
}
+}
- R_ResetViewRendering3D();
+extern void R_DrawLightningBeams (void);
+extern void VM_CL_AddPolygonsToMeshQueue (void);
+extern void R_DrawPortals (void);
+extern cvar_t cl_locs_show;
+static void R_DrawLocs(void);
+static void R_DrawEntityBBoxes(void);
+void R_RenderScene(void)
+{
+ r_refdef.stats.renders++;
+
+ R_UpdateFogColor();
// don't let sound skip if going slow
if (r_refdef.scene.extraupdate)
R_SkyStartFrame();
- R_View_Update();
- if (r_timereport_active)
- R_TimeReport("visibility");
-
Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
if (cl.csqc_vidvars.drawworld)
R_TimeReport("explosions");
}
- if (gl_support_fragment_shader)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
+ R_SetupGenericShader(true);
VM_CL_AddPolygonsToMeshQueue();
if (r_refdef.view.showdebug)
}
}
- if (gl_support_fragment_shader)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
+ R_SetupGenericShader(true);
R_MeshQueue_RenderTransparent();
if (r_timereport_active)
R_TimeReport("drawtrans");
- if (gl_support_fragment_shader)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
+ R_SetupGenericShader(true);
- if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
+ if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0))
{
r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
if (r_timereport_active)
R_TimeReport("modeldebug");
}
- if (gl_support_fragment_shader)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
+ R_SetupGenericShader(true);
if (cl.csqc_vidvars.drawworld)
{
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,
R_Mesh_VertexPointer(vertex3f, 0, 0);
R_Mesh_ColorPointer(color4f, 0, 0);
R_Mesh_ResetTextureState();
- R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
+ R_SetupGenericShader(false);
+ 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)
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++)
{
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)
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,
GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
+ R_SetupGenericShader(false);
R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
if (r_refdef.fogenabled)
{
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)
void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
{
+ // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
float fog = 1.0f;
float vertex3f[12];
R_Mesh_Matrix(&identitymatrix);
GL_BlendFunc(blendfunc1, blendfunc2);
- if(v_flipped_state)
- {
- scalex1 = -scalex1;
- scalex2 = -scalex2;
- GL_CullFace(r_refdef.view.cullface_front);
- }
- else
- GL_CullFace(r_refdef.view.cullface_back);
+ GL_CullFace(GL_NONE);
GL_DepthMask(false);
GL_DepthRange(0, depthshort ? 0.0625 : 1);
R_Mesh_VertexPointer(vertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
+ R_SetupGenericShader(true);
R_Mesh_TexBind(0, R_GetTexture(texture));
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)
{
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);
}
}
return (float)(parms[0] + parms[1] * f);
}
-void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
+texture_t *R_GetCurrentTexture(texture_t *t)
{
+ int w, h, idx;
int i;
- model_t *model = ent->model;
+ const entity_render_t *ent = rsurface.entity;
+ dp_model_t *model = ent->model;
float f;
float tcmat[12];
q3shaderinfo_layer_tcmod_t *tcmod;
+ if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
+ return t->currentframe;
+ t->update_lastrenderframe = r_frame;
+ t->update_lastrenderentity = (void *)ent;
+
// switch to an alternate material if this is a q1bsp animated material
{
texture_t *texture = t;
{
// use an alternate animation if the entity's frame is not 0,
// and only if the texture has an alternate animation
- if (ent->frame2 != 0 && t->anim_total[1])
+ if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
else
t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
}
// 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];
if (t->currentskinframe == NULL)
- t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
+ t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
}
else if (t->numskinframes >= 2)
- t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
+ t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
if (t->backgroundnumskinframes >= 2)
- t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
+ t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
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;
t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
if (ent->flags & RENDER_VIEWMODEL)
t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
+ if (t->backgroundnumskinframes)
+ t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
{
if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
}
else
- {
- if (t->backgroundnumskinframes)
- t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
- }
- // make sure that the waterscroll matrix is used on water surfaces when
// 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++)
{
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;
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);
// 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]);
+ }
}
-}
-void R_UpdateAllTextureInfo(entity_render_t *ent)
-{
- int i;
- if (ent->model)
- for (i = 0;i < ent->model->num_texturesperskin;i++)
- R_UpdateTextureInfo(ent, ent->model->data_textures + i);
+ return t->currentframe;
}
rsurfacestate_t rsurface;
rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
}
-void RSurf_CleanUp(void)
-{
- CHECKGLERROR
- if (rsurface.mode == RSURFMODE_GLSL)
- {
- qglUseProgramObjectARB(0);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.entity == r_refdef.scene.worldentity)
+ // return;
+ rsurface.entity = r_refdef.scene.worldentity;
if (rsurface.array_size < model->surfmesh.num_vertices)
R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
rsurface.matrix = identitymatrix;
VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
- rsurface.frameblend[0].frame = 0;
+ memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
rsurface.frameblend[0].lerp = 1;
- rsurface.frameblend[1].frame = 0;
- rsurface.frameblend[1].lerp = 0;
- rsurface.frameblend[2].frame = 0;
- rsurface.frameblend[2].lerp = 0;
- rsurface.frameblend[3].frame = 0;
- rsurface.frameblend[3].lerp = 0;
rsurface.basepolygonfactor = r_refdef.polygonfactor;
rsurface.basepolygonoffset = r_refdef.polygonoffset;
rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
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;
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.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
+ // return;
+ rsurface.entity = (entity_render_t *)ent;
if (rsurface.array_size < model->surfmesh.num_vertices)
R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
rsurface.matrix = ent->matrix;
VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
- rsurface.frameblend[0] = ent->frameblend[0];
- rsurface.frameblend[1] = ent->frameblend[1];
- rsurface.frameblend[2] = ent->frameblend[2];
- rsurface.frameblend[3] = ent->frameblend[3];
+ memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
rsurface.basepolygonfactor = r_refdef.polygonfactor;
rsurface.basepolygonoffset = r_refdef.polygonoffset;
if (ent->model->brush.submodel)
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].subframe != 0))
{
if (wanttangents)
{
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)
{
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
{
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;
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;
v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
#if 0
- Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonBegin(NULL, 0);
Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
#if 0
- Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonBegin(NULL, 0);
Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
CrossProduct(up, forward, newright);
VectorNormalize(newright);
#if 0
- Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonBegin(NULL, 0);
Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
Debug_PolygonEnd();
#endif
#if 0
- Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonBegin(NULL, 0);
Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
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)
{
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]));
}
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)
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
{
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);
}
}
}
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);
}
}
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)
{
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]));
}
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)
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");
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);
}
}
}
{
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);
}
}
}
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)
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;
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
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++)
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;
// 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++)
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);
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)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
- rsurface.mode = RSURFMODE_SKY;
- }
+ R_SetupGenericShader(false);
if (skyrendernow)
{
skyrendernow = false;
R_Mesh_ResetTextureState();
if (skyrendermasked)
{
+ R_SetupDepthOrShadowShader();
// depth-only (masking)
GL_ColorMask(0,0,0,0);
// just to make sure that braindead drivers don't draw
}
else
{
+ R_SetupGenericShader(false);
// fog sky
GL_BlendFunc(GL_ONE, GL_ZERO);
}
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));
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);
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
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))
{
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;
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++)
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)
{
}
}
-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;
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++)
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;
}
}
-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);
- 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);
- 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();
+ }
+
+ 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);
- 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_DrawWorldTextureSurfaceList(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
+}
+
+static void R_DrawModelTextureSurfaceList(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)
// 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);
j = i + 1;
surface = rsurface.modelsurfaces + surfacelist[i];
texture = surface->texture;
- R_UpdateTextureInfo(ent, texture);
- rsurface.texture = texture->currentframe;
+ rsurface.texture = R_GetCurrentTexture(texture);
rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
// scan ahead until we find a different texture
endsurface = min(i + 1024, numsurfaces);
texturesurfacelist[texturenumsurfaces++] = surface;
}
// render the range of surfaces
- R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
+ if (ent == r_refdef.scene.worldentity)
+ R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
+ else
+ R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
}
-
- RSurf_CleanUp();
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+ GL_AlphaTest(false);
}
-void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
+static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
{
- 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)
+ const entity_render_t *queueentity = r_refdef.scene.worldentity;
+ CHECKGLERROR
+ if (depthonly)
{
- for (i = 0;i < numsurfaces;i++)
- if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
- R_Water_AddWaterPlane(surfacelist[i]);
+ 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_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
}
+ CHECKGLERROR
+}
+
+void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
+{
+ int i, j;
+ texture_t *texture;
// break the surface list down into batches by texture and use of lightmapping
for (i = 0;i < numsurfaces;i = j)
{
// if a model has 2 skins and it is on skin 1, then skin 0 tells us to
// use skin 1 instead)
texture = surfacelist[i]->texture;
- rsurface.texture = texture->currentframe;
+ rsurface.texture = R_GetCurrentTexture(texture);
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)
+ // 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_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
+ }
+}
+
+static void R_ProcessModelTextureSurfaceList(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++)
{
- // transparent surfaces get pushed off into the transparent queue
- const msurface_t *surface = surfacelist[i];
- if (depthonly)
- continue;
+ 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, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
+ R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
}
- else
+ }
+ else
+ {
+ // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
+ R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
+ }
+ CHECKGLERROR
+}
+
+void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
+{
+ int i, j;
+ texture_t *texture;
+ // break the surface list down into batches by texture and use of lightmapping
+ for (i = 0;i < numsurfaces;i = j)
+ {
+ j = i + 1;
+ // texture is the base texture pointer, rsurface.texture is the
+ // current frame/skin the texture is directing us to use (for example
+ // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
+ // use skin 1 instead)
+ texture = surfacelist[i]->texture;
+ rsurface.texture = R_GetCurrentTexture(texture);
+ rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
+ if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
{
- // 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++)
+ // if this texture is not the kind we want, skip ahead to the next one
+ for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
;
- // render the range of surfaces
- R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
+ continue;
}
+ // 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_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
}
}
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,
R_Mesh_VertexPointer(vertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
+ R_SetupGenericShader(false);
i = surfacelist[0];
GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
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)
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();
+ R_SetupGenericShader(false);
GL_DepthRange(0, 1);
GL_DepthTest(!r_showdisabledepthtest.integer);
GL_DepthMask(false);
{
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++)
{
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);
}
}
}
{
if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
continue;
- rsurface.texture = surface->texture->currentframe;
+ rsurface.texture = R_GetCurrentTexture(surface->texture);
if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
{
RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
else
GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
+ R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
+ qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
+ 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);
+ qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
CHECKGLERROR
+ }
+ if (r_shownormals.value < 0)
+ {
qglBegin(GL_LINES);
- for (k = 0;k < surface->num_triangles;k++, elements += 3)
+ for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
{
-#define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
- GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
- GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
- GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
+ VectorCopy(rsurface.vertex3f + l * 3, v);
+ GL_Color(r_refdef.view.colorscale, 0, 0, 1);
+ qglVertex3f(v[0], v[1], v[2]);
+ VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
+ GL_Color(r_refdef.view.colorscale, 1, 1, 1);
+ qglVertex3f(v[0], v[1], v[2]);
}
qglEnd();
CHECKGLERROR
}
extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
-void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
+int r_maxsurfacelist = 0;
+msurface_t **r_surfacelist = NULL;
+void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, 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)
+ if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
{
model_brush_lightstyleinfo_t *style;
for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
{
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 = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
if (debug)
{
R_DrawDebugModel(r_refdef.scene.worldentity);
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
return;
}
t = NULL;
rsurface.uselightmaptexture = false;
rsurface.texture = NULL;
+ rsurface.rtlight = NULL;
numsurfacelist = 0;
- j = model->firstmodelsurface;
- endj = j + model->nummodelsurfaces;
- while (j < endj)
+ // add visible surfaces to draw list
+ for (i = 0;i < model->nummodelsurfaces;i++)
+ {
+ j = model->sortedmodelsurfaces[i];
+ if (r_refdef.viewcache.world_surfacevisible[j])
+ r_surfacelist[numsurfacelist++] = surfaces + j;
+ }
+ // update lightmaps if needed
+ if (update)
+ for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
+ if (r_refdef.viewcache.world_surfacevisible[j])
+ if (update[j])
+ R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
+ // don't do anything if there were no surfaces
+ if (!numsurfacelist)
+ {
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+ return;
+ }
+ R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
+ GL_AlphaTest(false);
+
+ // add to stats if desired
+ if (r_speeds.integer && !skysurfaces && !depthonly)
{
- // 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++)
- {
- // process this surface
- surface = model->data_surfaces + j;
- // 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(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_refdef.stats.world_surfaces += numsurfacelist;
+ for (j = 0;j < numsurfacelist;j++)
+ r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
}
- r_refdef.stats.world_surfaces += numsurfacelist;
- if (numsurfacelist)
- R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
- RSurf_CleanUp();
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
-void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
+void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, 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)
+ if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
{
model_brush_lightstyleinfo_t *style;
for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
{
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 = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
if (debug)
{
R_DrawDebugModel(ent);
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
return;
}
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
+ for (i = 0;i < model->nummodelsurfaces;i++)
+ r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
+ // don't do anything if there were no surfaces
+ if (!numsurfacelist)
{
- // 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;
- }
- }
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+ return;
+ }
+ // update lightmaps if needed
+ if (update)
+ for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
+ if (update[j])
+ R_BuildLightMap(ent, surfaces + j);
+ R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
+ GL_AlphaTest(false);
+
+ // add to stats if desired
+ if (r_speeds.integer && !skysurfaces && !depthonly)
+ {
+ 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();
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}