qboolean r_rtdlightshadows;
-// forces all rendering to draw triangle outlines
-int r_showtrispass;
-
// view origin
vec3_t r_vieworigin;
vec3_t r_viewforward;
int r_view_height;
int r_view_depth;
matrix4x4_t r_view_matrix;
-
+float r_polygonfactor;
+float r_polygonoffset;
+float r_shadowpolygonfactor;
+float r_shadowpolygonoffset;
//
// screen size info
//
refdef_t r_refdef;
cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
+cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
-cvar_t r_showtris_polygonoffset = {0, "r_showtris_polygonoffset", "-10", "nudges triangle outlines in hardware depth units, used to make outlines appear infront of walls"};
cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
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 = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
-cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "enables offset mapping effect (also known as parallax mapping or sometimes as virtual displacement mapping, not as good as relief mapping or silohuette mapping but much faster), can cause strange artifacts on many textures, requires bumpmaps for depth information (normalmaps can have depth information as alpha channel, but most do not)"};
-cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "-0.04", "how deep the offset mapping effect is, and whether it is inward or outward"};
-cvar_t r_glsl_offsetmapping_bias = {0, "r_glsl_offsetmapping_bias", "0.04", "pushes the effect closer/further"};
+cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
+cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
+cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
cvar_t r_glsl_usehalffloat = {0, "r_glsl_usehalffloat", "0", "use half and hvec variables in GLSL shader for a speed gain (NVIDIA only)"};
cvar_t r_glsl_surfacenormalize = {0, "r_glsl_surfacenormalize", "1", "normalize bumpmap texels in GLSL shader, produces a more rounded look on small bumps and dents"};
+cvar_t r_glsl_deluxemapping = {0, "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_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
"#endif\n"
"\n"
"varying vec2 TexCoord;\n"
+"#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
+"varying vec2 TexCoordLightmap;\n"
+"#endif\n"
"\n"
-"#ifdef USELIGHTSOURCE\n"
+"#ifdef MODE_LIGHTSOURCE\n"
"varying myhvec3 CubeVector;\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
"varying vec3 LightVector;\n"
"#endif\n"
"\n"
"varying vec3 EyeVector;\n"
"#endif\n"
"\n"
+"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
+"varying myhvec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
+"varying myhvec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
+"varying myhvec3 VectorR; // direction of R texcoord (surface normal)\n"
+"#endif\n"
+"\n"
"\n"
"\n"
"\n"
"// vertex shader specific:\n"
"#ifdef VERTEX_SHADER\n"
"\n"
-"#ifdef USELIGHTSOURCE\n"
+"#ifdef MODE_LIGHTSOURCE\n"
"uniform vec3 LightPosition;\n"
"#endif\n"
"\n"
"uniform vec3 EyePosition;\n"
"#endif\n"
"\n"
+"#ifdef MODE_LIGHTDIRECTION\n"
+"uniform myhvec3 LightDir;\n"
+"#endif\n"
+"\n"
"// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
"\n"
"void main(void)\n"
"{\n"
" // copy the surface texcoord\n"
" TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
+"#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
+" TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
+"#endif\n"
+" gl_FrontColor = gl_Color;\n"
"\n"
-"#ifdef USELIGHTSOURCE\n"
+"#ifdef MODE_LIGHTSOURCE\n"
" // transform vertex position into light attenuation/cubemap space\n"
" // (-1 to +1 across the light box)\n"
" CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
" LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
"#endif\n"
"\n"
+"#ifdef MODE_LIGHTDIRECTION\n"
+" LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
+" LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
+" LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
+"#endif\n"
+"\n"
"#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
" // transform unnormalized eye direction into tangent space\n"
" vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
" EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
"#endif\n"
"\n"
+"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
+" VectorS = gl_MultiTexCoord1.xyz;\n"
+" VectorT = gl_MultiTexCoord2.xyz;\n"
+" VectorR = gl_MultiTexCoord3.xyz;\n"
+"#endif\n"
+"\n"
" // transform vertex to camera space, using ftransform to match non-VS\n"
" // rendering\n"
" gl_Position = ftransform();\n"
"uniform myhalf OffsetMapping_Bias;\n"
"#endif\n"
"\n"
-"#if defined(USELIGHTSOURCE) || defined(USEDELUXEMAPPING)\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE) || defined(MODE_LIGHTDIRECTION) || defined(USEOFFSETMAPPING)\n"
"uniform sampler2D Texture_Normal;\n"
"#endif\n"
"\n"
+"#ifdef MODE_LIGHTDIRECTION\n"
+"uniform myhvec3 AmbientColor;\n"
+"uniform myhvec3 DiffuseColor;\n"
+"uniform myhvec3 SpecularColor;\n"
+"#endif\n"
+"\n"
"uniform sampler2D Texture_Color;\n"
"\n"
+"#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
+"uniform sampler2D Texture_Lightmap;\n"
+"#endif\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
+"uniform sampler2D Texture_Deluxemap;\n"
+"#endif\n"
+"\n"
+"#ifdef USEGLOW\n"
+"uniform sampler2D Texture_Glow;\n"
+"#endif\n"
+"\n"
"#ifdef USECOLORMAPPING\n"
"uniform sampler2D Texture_Pants;\n"
"uniform sampler2D Texture_Shirt;\n"
"#endif\n"
"\n"
"#ifdef USEFOG\n"
+"uniform myhvec3 FogColor;\n"
"uniform myhalf FogRangeRecip;\n"
"uniform sampler2D Texture_FogMask;\n"
"#endif\n"
"\n"
+"#ifdef USEEASTEREGG\n"
+"void main(void)\n"
+"{\n"
+" gl_FragColor = myhvec4(0, 0, 0, 1);;\n"
+" int i;\n"
+" float o;\n"
+" vec2 p = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
+" vec2 c = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
+" for (i = 0;i < 1000 && dot(p,p) < 4.0;i = i + 1)\n"
+" {\n"
+" o = p.x * p.x - p.y * p.y;\n"
+" p.y = 2.0 * p.x * p.y;\n"
+" p.x = o;\n"
+" p += c;\n"
+" }\n"
+" o = float(i) * 0.314;\n"
+" if (i < 1000)\n"
+" gl_FragColor = vec4(cos(o), sin(o), sin(o * 0.2), 1);\n"
+"}\n"
+"#else // USEEASTEREGG\n"
+"\n"
+"\n"
+"\n"
"void main(void)\n"
"{\n"
" // apply offsetmapping\n"
"#ifdef USEOFFSETMAPPING\n"
-" // this is 3 sample because of ATI Radeon 9500-9800/X300 limits\n"
-" myhvec2 OffsetVector = normalize(EyeVector).xy * vec2(-0.333, 0.333);\n"
-" myhvec2 TexCoordOffset = TexCoord + OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).w);\n"
-" TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
-" TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
+" myhvec2 TexCoordOffset = TexCoord;\n"
"#define TexCoord TexCoordOffset\n"
+"\n"
+" myhvec3 eyedir = myhvec3(normalize(EyeVector));\n"
+" myhalf depthbias = 1.0 - eyedir.z; // should this be a -?\n"
+" depthbias = 1.0 - depthbias * depthbias;\n"
+"\n"
+"#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
+" // 14 sample relief mapping: linear search and then binary search\n"
+" myhvec3 OffsetVector = myhvec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * myhvec2(-0.1, 0.1), -0.1);\n"
+" vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
+" if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
+" TexCoord = RT.xy;\n"
+"#else\n"
+" // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
+" myhvec2 OffsetVector = myhvec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * myhvec2(-0.333, 0.333));\n"
+" TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
+" TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
+" TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
+"#endif\n"
"#endif\n"
"\n"
" // combine the diffuse textures (base, pants, shirt)\n"
"\n"
"\n"
"\n"
-"#ifdef USELIGHTSOURCE\n"
+"#ifdef MODE_LIGHTSOURCE\n"
" // light source\n"
"\n"
" // get the surface normal and light normal\n"
"\n"
"\n"
"\n"
+"#elif defined(MODE_LIGHTDIRECTION)\n"
+" // directional model lighting\n"
+"\n"
+" // get the surface normal and light normal\n"
+"#ifdef SURFACENORMALIZE\n"
+" myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
"#else\n"
-"#ifdef USEDELUXEMAPPING\n"
-" // deluxemap lightmapping\n"
+" myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
+"#endif\n"
+" myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
+"\n"
+"\n"
+" // calculate directional shading\n"
+" color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
+"#ifdef USESPECULAR\n"
+" myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
+" color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
+"#endif\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
+" // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
"\n"
" // get the surface normal and light normal\n"
"#ifdef SURFACENORMALIZE\n"
" myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
-" myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)));\n"
"#else\n"
" myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
-" myhvec3 diffusenormal = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
"#endif\n"
+" myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
+" myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
"\n"
" // calculate directional shading\n"
-" color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
+" myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
"#ifdef USESPECULAR\n"
" myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
-" color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
+" tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
"#endif\n"
"\n"
" // apply lightmap color\n"
-" color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
+" color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
"\n"
"\n"
"\n"
"\n"
+"#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
+" // deluxemap lightmapping using light vectors in tangentspace\n"
+"\n"
+" // get the surface normal and light normal\n"
+"#ifdef SURFACENORMALIZE\n"
+" myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
+" myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
"#else\n"
-" // apply lightmap color\n"
-" color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale;\n"
+" myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
+" myhvec3 diffusenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
"#endif\n"
+"\n"
+" // calculate directional shading\n"
+" myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
+"#ifdef USESPECULAR\n"
+" myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
+" tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
"#endif\n"
"\n"
+" // apply lightmap color\n"
+" color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
+"\n"
"\n"
"\n"
"\n"
+"#else // MODE none (lightmap)\n"
+" // apply lightmap color\n"
+" color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
+"#endif // MODE\n"
+"\n"
+"#ifdef USEGLOW\n"
+" color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord));\n"
+"#endif\n"
+"\n"
"#ifdef USEFOG\n"
" // apply fog\n"
-" myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0)).x;\n"
-" color.rgb = color.rgb * (1 - fog) + FogColor * fog;\n"
+" myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
+" color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
"#endif\n"
"\n"
-" gl_FragColor = color;\n"
+" gl_FragColor = color * gl_Color;\n"
"}\n"
+"#endif // !USEEASTEREGG\n"
"\n"
"#endif\n"
;
-// the loaded GLSL shader file for compiling shader permutations as needed
-static char *shaderstring = NULL;
-
void R_GLSL_CompilePermutation(int permutation)
{
r_glsl_permutation_t *p = r_glsl_permutations + permutation;
int vertstrings_count;
int fragstrings_count;
+ char *shaderstring;
const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
char permutationname[256];
vertstrings_count = 1;
fragstrings_count = 1;
permutationname[0] = 0;
- if (permutation & SHADERPERMUTATION_DELUXEMAPPING)
+ if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
{
- vertstrings_list[vertstrings_count++] = "#define USEDELUXEMAP\n";
- fragstrings_list[fragstrings_count++] = "#define USEDELUXEMAP\n";
- strlcat(permutationname, " deluxemap", sizeof(permutationname));
+ vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
+ fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
+ strlcat(permutationname, " lightsource", sizeof(permutationname));
}
- if (permutation & SHADERPERMUTATION_LIGHTSOURCE)
+ if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
{
- vertstrings_list[vertstrings_count++] = "#define USELIGHTSOURCE\n";
- fragstrings_list[fragstrings_count++] = "#define USELIGHTSOURCE\n";
- strlcat(permutationname, " lightsource", sizeof(permutationname));
+ vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
+ fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
+ strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
+ }
+ if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
+ {
+ vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
+ fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
+ strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
+ }
+ if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
+ {
+ vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
+ fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
+ strlcat(permutationname, " lightdirection", sizeof(permutationname));
+ }
+ if (permutation & SHADERPERMUTATION_GLOW)
+ {
+ vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
+ fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
+ strlcat(permutationname, " glow", sizeof(permutationname));
}
if (permutation & SHADERPERMUTATION_COLORMAPPING)
{
fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
strlcat(permutationname, " offsetmapping", sizeof(permutationname));
}
+ if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
+ {
+ vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
+ fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
+ strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
+ }
if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
{
vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
strlcat(permutationname, " halffloat", sizeof(permutationname));
}
+ shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
if (shaderstring)
{
+ Con_DPrintf("GLSL shader text loaded from disk\n");
vertstrings_list[vertstrings_count++] = shaderstring;
fragstrings_list[fragstrings_count++] = shaderstring;
}
p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
+ p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
+ p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
+ p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
- p->loc_OffsetMapping_Bias = qglGetUniformLocationARB(p->program, "OffsetMapping_Bias");
- if (p->loc_Texture_Normal) qglUniform1iARB(p->loc_Texture_Normal, 0);
- if (p->loc_Texture_Color) qglUniform1iARB(p->loc_Texture_Color, 1);
- if (p->loc_Texture_Gloss) qglUniform1iARB(p->loc_Texture_Gloss, 2);
- if (p->loc_Texture_Cube) qglUniform1iARB(p->loc_Texture_Cube, 3);
- if (p->loc_Texture_FogMask) qglUniform1iARB(p->loc_Texture_FogMask, 4);
- if (p->loc_Texture_Pants) qglUniform1iARB(p->loc_Texture_Pants, 5);
- if (p->loc_Texture_Shirt) qglUniform1iARB(p->loc_Texture_Shirt, 6);
- if (p->loc_Texture_Lightmap) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
- if (p->loc_Texture_Deluxemap) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
+ p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
+ p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
+ p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
+ p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
+ if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
+ if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
+ if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
+ if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
+ if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
+ if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
+ if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
+ if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
+ if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
+ if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
qglUseProgramObjectARB(0);
CHECKGLERROR
}
else
Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
+ if (shaderstring)
+ Mem_Free(shaderstring);
}
-void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
+void R_GLSL_Restart_f(void)
+{
+ int i;
+ for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
+ if (r_glsl_permutations[i].program)
+ GL_Backend_FreeProgram(r_glsl_permutations[i].program);
+ memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
+}
+
+void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
{
// 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
int permutation = 0;
+ float specularscale = texture->specularscale;
r_glsl_permutation = NULL;
if (r_shadow_rtlight)
- permutation |= SHADERPERMUTATION_LIGHTSOURCE;
- else if (false)
- permutation |= SHADERPERMUTATION_DELUXEMAPPING;
+ {
+ permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
+ specularscale *= r_shadow_rtlight->specularscale;
+ if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+ permutation |= SHADERPERMUTATION_CUBEFILTER;
+ }
+ else
+ {
+ if (modellighting)
+ permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
+ else if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
+ {
+ if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
+ permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
+ else
+ permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
+ }
+ else if (r_glsl_deluxemapping.integer >= 2) // fake mode
+ permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
+ if (texture->skin.glow)
+ permutation |= SHADERPERMUTATION_GLOW;
+ }
+ if (specularscale > 0)
+ permutation |= SHADERPERMUTATION_SPECULAR;
if (fogenabled)
permutation |= SHADERPERMUTATION_FOG;
- if ((dopants || doshirt))
+ if (texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if (specularscale > 0)
- permutation |= SHADERPERMUTATION_SPECULAR;
- if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
- permutation |= SHADERPERMUTATION_CUBEFILTER;
if (r_glsl_offsetmapping.integer)
+ {
permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
if (r_glsl_surfacenormalize.integer)
permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
if (r_glsl_usehalffloat.integer)
CHECKGLERROR
qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
- if (r_shadow_rtlight)
+ if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
+ {
R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
- if (r_glsl_permutation->loc_Texture_Normal) R_Mesh_TexBind(0, R_GetTexture(normalmaptexture));
- if (r_glsl_permutation->loc_Texture_Color) R_Mesh_TexBind(1, R_GetTexture(basetexture));
- if (r_glsl_permutation->loc_FogColor)
+ //if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
+ if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
+ if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
+ if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
+ if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
+ if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
+ }
+ else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
+ {
+ if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
+ {
+ if (r_glsl_permutation->loc_AmbientColor >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
+ if (r_glsl_permutation->loc_DiffuseColor >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
+ if (r_glsl_permutation->loc_SpecularColor >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
+ if (r_glsl_permutation->loc_LightDir >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
+ }
+ else
+ {
+ if (r_glsl_permutation->loc_AmbientColor >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
+ if (r_glsl_permutation->loc_DiffuseColor >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
+ if (r_glsl_permutation->loc_SpecularColor >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
+ if (r_glsl_permutation->loc_LightDir >= 0)
+ qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
+ }
+ }
+ else
+ {
+ if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
+ if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
+ if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_lightmapintensity * specularscale * 2.0f);
+ }
+ if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
+ if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
+ if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
+ if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
+ if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
+ if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
+ if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
+ if (r_glsl_permutation->loc_FogColor >= 0)
{
// additive passes are only darkened by fog, not tinted
if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
else
qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
}
- if (r_glsl_permutation->loc_LightPosition) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
- if (r_glsl_permutation->loc_EyePosition) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, r_shadow_entityeyeorigin[0], r_shadow_entityeyeorigin[1], r_shadow_entityeyeorigin[2]);
- if (r_glsl_permutation->loc_LightColor) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
- if (r_glsl_permutation->loc_Texture_Pants) R_Mesh_TexBind(5, R_GetTexture(pantstexture));
- if (r_glsl_permutation->loc_Texture_Shirt) R_Mesh_TexBind(6, R_GetTexture(shirttexture));
- if (r_glsl_permutation->loc_Color_Pants) qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
- if (r_glsl_permutation->loc_Color_Shirt) qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
- if (r_glsl_permutation->loc_FogRangeRecip) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
- if (r_glsl_permutation->loc_AmbientScale) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
- if (r_glsl_permutation->loc_DiffuseScale) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
- if (r_glsl_permutation->loc_Texture_Gloss) R_Mesh_TexBind(2, R_GetTexture(glosstexture));
- if (r_glsl_permutation->loc_SpecularPower) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, 8);
- if (r_glsl_permutation->loc_SpecularScale) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
- if (r_glsl_permutation->loc_OffsetMapping_Scale) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
- if (r_glsl_permutation->loc_OffsetMapping_Bias) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
+ if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
+ if (r_glsl_permutation->loc_Color_Pants >= 0)
+ {
+ if (texture->skin.pants)
+ qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
+ else
+ qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
+ }
+ if (r_glsl_permutation->loc_Color_Shirt >= 0)
+ {
+ if (texture->skin.shirt)
+ qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
+ else
+ qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
+ }
+ if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
+ if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
+ if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
CHECKGLERROR
}
R_BuildNormalizationCube();
}
R_BuildFogTexture();
- shaderstring = NULL;
- if (gl_support_fragment_shader)
- {
- shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
- if (shaderstring)
- Con_Printf("GLSL shader text loaded from disk\n");
- // if we couldn't load the shader file, fall back to builtin shader
- if (!shaderstring)
- {
- if (shaderstring)
- Con_Printf("GLSL shader text loaded from fallback\n");
- shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
- strcpy(shaderstring, builtinshaderstring);
- }
- }
- if (shaderstring)
- Con_Printf("GLSL shader text loaded\n");
memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
}
void gl_main_shutdown(void)
{
- int i;
R_FreeTexturePool(&r_main_texturepool);
r_bloom_texture_screen = NULL;
r_bloom_texture_bloom = NULL;
r_texture_black = NULL;
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
- if (shaderstring)
- Mem_Free(shaderstring);
- shaderstring = NULL;
- for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
- if (r_glsl_permutations[i].program)
- GL_Backend_FreeProgram(r_glsl_permutations[i].program);
- memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
+ R_GLSL_Restart_f();
}
extern void CL_ParseEntityLump(char *entitystring);
{
r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
+ Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
FOG_registercvars(); // FIXME: move this fog stuff to client?
Cvar_RegisterVariable(&r_nearclip);
+ Cvar_RegisterVariable(&r_showsurfaces);
Cvar_RegisterVariable(&r_showtris);
- Cvar_RegisterVariable(&r_showtris_polygonoffset);
Cvar_RegisterVariable(&r_shownormals);
Cvar_RegisterVariable(&r_showlighting);
Cvar_RegisterVariable(&r_showshadowvolumes);
Cvar_RegisterVariable(&r_textureunits);
Cvar_RegisterVariable(&r_glsl);
Cvar_RegisterVariable(&r_glsl_offsetmapping);
+ Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
- Cvar_RegisterVariable(&r_glsl_offsetmapping_bias);
Cvar_RegisterVariable(&r_glsl_usehalffloat);
Cvar_RegisterVariable(&r_glsl_surfacenormalize);
+ Cvar_RegisterVariable(&r_glsl_deluxemapping);
Cvar_RegisterVariable(&r_lerpsprites);
Cvar_RegisterVariable(&r_lerpmodels);
Cvar_RegisterVariable(&r_waterscroll);
//==================================================================================
+static void R_UpdateEntityLighting(entity_render_t *ent)
+{
+ vec3_t tempdiffusenormal;
+ VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
+ VectorClear(ent->modellight_diffuse);
+ VectorClear(ent->modellight_lightdir);
+ if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
+ r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
+ else // highly rare
+ VectorSet(ent->modellight_ambient, 1, 1, 1);
+ Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
+ VectorNormalize(ent->modellight_lightdir);
+ ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
+ ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
+ ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
+ ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
+ ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
+ ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
+}
+
static void R_MarkEntities (void)
{
int i, renderimask;
ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
{
- R_UpdateEntLights(ent);
ent->visframe = r_framecount;
+ R_UpdateEntityLighting(ent);
}
}
}
ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
{
- R_UpdateEntLights(ent);
ent->visframe = r_framecount;
+ R_UpdateEntityLighting(ent);
}
}
}
qboolean dobloom;
qboolean doblend;
rmeshstate_t m;
+ float vertex3f[12];
+ float texcoord2f[3][8];
// set the (poorly named) screenwidth and screenheight variables to
// a power of 2 at least as large as the screen, these will define the
GL_DepthTest(false);
R_Mesh_Matrix(&identitymatrix);
// vertex coordinates for a quad that covers the screen exactly
- varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
- varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
- varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
- varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
+ vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
+ vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
+ vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
+ vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
if (dobloom)
{
int bloomwidth, bloomheight, x, dobloomblend, range;
bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
// set up a texcoord array for the full resolution screen image
// (we have to keep this around to copy back during final render)
- varray_texcoord2f[0][0] = 0;
- varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
- varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
- varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
- varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
- varray_texcoord2f[0][5] = 0;
- varray_texcoord2f[0][6] = 0;
- varray_texcoord2f[0][7] = 0;
+ texcoord2f[0][0] = 0;
+ texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
+ texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
+ texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
+ texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
+ texcoord2f[0][5] = 0;
+ texcoord2f[0][6] = 0;
+ texcoord2f[0][7] = 0;
// set up a texcoord array for the reduced resolution bloom image
// (which will be additive blended over the screen image)
- varray_texcoord2f[1][0] = 0;
- varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
- varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
- varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
- varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
- varray_texcoord2f[1][5] = 0;
- varray_texcoord2f[1][6] = 0;
- varray_texcoord2f[1][7] = 0;
+ texcoord2f[1][0] = 0;
+ texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
+ texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
+ texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
+ texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
+ texcoord2f[1][5] = 0;
+ texcoord2f[1][6] = 0;
+ texcoord2f[1][7] = 0;
memset(&m, 0, sizeof(m));
- m.pointer_vertex = varray_vertex3f;
- m.pointer_texcoord[0] = varray_texcoord2f[0];
+ m.pointer_vertex = vertex3f;
+ m.pointer_texcoord[0] = texcoord2f[0];
m.tex[0] = R_GetTexture(r_bloom_texture_screen);
R_Mesh_State(&m);
// copy view into the full resolution screen image texture
// we now have a darkened bloom image in the framebuffer, copy it into
// the bloom image texture for more processing
memset(&m, 0, sizeof(m));
- m.pointer_vertex = varray_vertex3f;
+ m.pointer_vertex = vertex3f;
m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
- m.pointer_texcoord[0] = varray_texcoord2f[2];
+ m.pointer_texcoord[0] = texcoord2f[2];
R_Mesh_State(&m);
GL_ActiveTexture(0);
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
// compute a texcoord array with the specified x and y offset
- varray_texcoord2f[2][0] = xoffset+0;
- varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
- varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
- varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
- varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
- varray_texcoord2f[2][5] = yoffset+0;
- varray_texcoord2f[2][6] = xoffset+0;
- varray_texcoord2f[2][7] = yoffset+0;
+ texcoord2f[2][0] = xoffset+0;
+ texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
+ texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
+ texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
+ texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
+ texcoord2f[2][5] = yoffset+0;
+ texcoord2f[2][6] = xoffset+0;
+ texcoord2f[2][7] = yoffset+0;
// this r value looks like a 'dot' particle, fading sharply to
// black at the edges
// (probably not realistic but looks good enough)
xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
// compute a texcoord array with the specified x and y offset
- varray_texcoord2f[2][0] = xoffset+0;
- varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
- varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
- varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
- varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
- varray_texcoord2f[2][5] = yoffset+0;
- varray_texcoord2f[2][6] = xoffset+0;
- varray_texcoord2f[2][7] = yoffset+0;
+ texcoord2f[2][0] = xoffset+0;
+ texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
+ texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
+ texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
+ texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
+ texcoord2f[2][5] = yoffset+0;
+ texcoord2f[2][6] = xoffset+0;
+ texcoord2f[2][7] = yoffset+0;
// this r value looks like a 'dot' particle, fading sharply to
// black at the edges
// (probably not realistic but looks good enough)
// put the original screen image back in place and blend the bloom
// texture on it
memset(&m, 0, sizeof(m));
- m.pointer_vertex = varray_vertex3f;
+ m.pointer_vertex = vertex3f;
m.tex[0] = R_GetTexture(r_bloom_texture_screen);
- m.pointer_texcoord[0] = varray_texcoord2f[0];
+ m.pointer_texcoord[0] = texcoord2f[0];
#if 0
dobloomblend = false;
#else
dobloomblend = false;
m.texcombinergb[1] = GL_ADD;
m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
- m.pointer_texcoord[1] = varray_texcoord2f[1];
+ m.pointer_texcoord[1] = texcoord2f[1];
}
else
dobloomblend = true;
if (dobloomblend)
{
memset(&m, 0, sizeof(m));
- m.pointer_vertex = varray_vertex3f;
+ m.pointer_vertex = vertex3f;
m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
- m.pointer_texcoord[0] = varray_texcoord2f[1];
+ m.pointer_texcoord[0] = texcoord2f[1];
R_Mesh_State(&m);
GL_BlendFunc(GL_ONE, GL_ONE);
GL_Color(1,1,1,1);
{
// apply a color tint to the whole view
memset(&m, 0, sizeof(m));
- m.pointer_vertex = varray_vertex3f;
+ m.pointer_vertex = vertex3f;
R_Mesh_State(&m);
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_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
+ r_polygonfactor = 0;
+ r_polygonoffset = 0;
+ r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
+ r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
+ if (r_showsurfaces.integer)
+ {
+ r_rtworld = false;
+ r_rtworldshadows = false;
+ r_rtdlight = false;
+ r_rtdlightshadows = false;
+ r_lightmapintensity = 0;
+ }
// GL is weird because it's bottom to top, r_view_y is top to bottom
qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
R_TimeReport("setup");
qglDepthFunc(GL_LEQUAL);
- qglPolygonOffset(0, 0);
+ qglPolygonOffset(r_polygonfactor, r_polygonoffset);
qglEnable(GL_POLYGON_OFFSET_FILL);
R_RenderScene();
- qglPolygonOffset(0, 0);
+ qglPolygonOffset(r_polygonfactor, r_polygonoffset);
qglDisable(GL_POLYGON_OFFSET_FILL);
R_BlendView();
r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
+ r_polygonfactor = 0;
+ r_polygonoffset = 0;
+ r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
+ r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
+ if (r_showsurfaces.integer)
+ {
+ r_rtworld = false;
+ r_rtworldshadows = false;
+ r_rtdlight = false;
+ r_rtdlightshadows = false;
+ r_lightmapintensity = 0;
+ }
// GL is weird because it's bottom to top, r_view_y is top to bottom
qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
void CSQC_R_RenderScene (void)
{
qglDepthFunc(GL_LEQUAL);
- qglPolygonOffset(0, 0);
+ qglPolygonOffset(r_polygonfactor, r_polygonoffset);
qglEnable(GL_POLYGON_OFFSET_FILL);
R_RenderScene();
- qglPolygonOffset(0, 0);
+ qglPolygonOffset(r_polygonfactor, r_polygonoffset);
qglDisable(GL_POLYGON_OFFSET_FILL);
R_BlendView();
r_framecount++;
+ if (gl_support_fragment_shader)
+ qglUseProgramObjectARB(0);
+
R_MeshQueue_BeginScene();
R_SetFrustum();
R_Shadow_UpdateWorldLightSelection();
- for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
+ if (cl.csqc_vidvars.drawworld)
{
- if (r_showtrispass)
- {
- rmeshstate_t m;
- r_showtrispass = 0;
- GL_BlendFunc(GL_ONE, GL_ONE);
- GL_DepthTest(!r_showdisabledepthtest.integer);
- GL_DepthMask(GL_FALSE);
- memset(&m, 0, sizeof(m));
- R_Mesh_State(&m);
- //qglEnable(GL_LINE_SMOOTH);
- qglEnable(GL_POLYGON_OFFSET_LINE);
- qglPolygonOffset(0, r_showtris_polygonoffset.value);
- r_showtrispass = 1;
- }
-
- if (cl.csqc_vidvars.drawworld)
- {
- // don't let sound skip if going slow
- if (r_refdef.extraupdate)
- S_ExtraUpdate ();
-
- if (r_showtrispass)
- GL_ShowTrisColor(0.025, 0.025, 0, 1);
- if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
- {
- r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
- if (r_timereport_active)
- R_TimeReport("worldsky");
- }
-
- if (R_DrawBrushModelsSky() && r_timereport_active)
- R_TimeReport("bmodelsky");
-
- if (r_showtrispass)
- GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
- if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
- {
- r_refdef.worldmodel->Draw(r_refdef.worldentity);
- if (r_timereport_active)
- R_TimeReport("world");
- }
- }
-
// don't let sound skip if going slow
if (r_refdef.extraupdate)
S_ExtraUpdate ();
- if (r_showtrispass)
- GL_ShowTrisColor(0, 0.015, 0, 1);
-
- R_DrawModels();
- if (r_timereport_active)
- R_TimeReport("models");
+ if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
+ {
+ r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
+ if (r_timereport_active)
+ R_TimeReport("worldsky");
+ }
- // don't let sound skip if going slow
- if (r_refdef.extraupdate)
- S_ExtraUpdate ();
+ if (R_DrawBrushModelsSky() && r_timereport_active)
+ R_TimeReport("bmodelsky");
- if (r_showtrispass)
- GL_ShowTrisColor(0, 0, 0.033, 1);
- R_ShadowVolumeLighting(false);
- if (r_timereport_active)
- R_TimeReport("rtlights");
+ if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
+ {
+ r_refdef.worldmodel->Draw(r_refdef.worldentity);
+ if (r_timereport_active)
+ R_TimeReport("world");
+ }
+ }
- // don't let sound skip if going slow
- if (r_refdef.extraupdate)
- S_ExtraUpdate ();
+ // don't let sound skip if going slow
+ if (r_refdef.extraupdate)
+ S_ExtraUpdate ();
- if (r_showtrispass)
- GL_ShowTrisColor(0.1, 0, 0, 1);
+ R_DrawModels();
+ if (r_timereport_active)
+ R_TimeReport("models");
- if (cl.csqc_vidvars.drawworld)
- {
- R_DrawLightningBeams();
- if (r_timereport_active)
- R_TimeReport("lightning");
+ // don't let sound skip if going slow
+ if (r_refdef.extraupdate)
+ S_ExtraUpdate ();
- R_DrawParticles();
- if (r_timereport_active)
- R_TimeReport("particles");
+ R_ShadowVolumeLighting(false);
+ if (r_timereport_active)
+ R_TimeReport("rtlights");
- R_DrawExplosions();
- if (r_timereport_active)
- R_TimeReport("explosions");
- }
+ // don't let sound skip if going slow
+ if (r_refdef.extraupdate)
+ S_ExtraUpdate ();
- R_MeshQueue_RenderTransparent();
+ if (cl.csqc_vidvars.drawworld)
+ {
+ R_DrawLightningBeams();
if (r_timereport_active)
- R_TimeReport("drawtrans");
+ R_TimeReport("lightning");
- if (cl.csqc_vidvars.drawworld)
- {
- R_DrawCoronas();
- if (r_timereport_active)
- R_TimeReport("coronas");
- }
- if(cl.csqc_vidvars.drawcrosshair)
- {
- R_DrawWorldCrosshair();
- if (r_timereport_active)
- R_TimeReport("crosshair");
- }
+ R_DrawParticles();
+ if (r_timereport_active)
+ R_TimeReport("particles");
- VM_AddPolygonsToMeshQueue();
+ R_DrawExplosions();
+ if (r_timereport_active)
+ R_TimeReport("explosions");
+ }
- R_MeshQueue_Render();
+ R_MeshQueue_RenderTransparent();
+ if (r_timereport_active)
+ R_TimeReport("drawtrans");
- if (r_showtrispass)
- {
- //qglDisable(GL_LINE_SMOOTH);
- qglDisable(GL_POLYGON_OFFSET_LINE);
- }
+ if (cl.csqc_vidvars.drawworld)
+ {
+ R_DrawCoronas();
+ if (r_timereport_active)
+ R_TimeReport("coronas");
+ }
+ if(cl.csqc_vidvars.drawcrosshair)
+ {
+ R_DrawWorldCrosshair();
+ if (r_timereport_active)
+ R_TimeReport("crosshair");
}
- r_showtrispass = 0;
+ VM_AddPolygonsToMeshQueue();
+
+ R_MeshQueue_Render();
R_MeshQueue_EndScene();
// don't let sound skip if going slow
if (r_refdef.extraupdate)
S_ExtraUpdate ();
+
+ if (gl_support_fragment_shader)
+ qglUseProgramObjectARB(0);
}
/*
{
float fog = 0.0f, ifog;
rmeshstate_t m;
+ float vertex3f[12];
if (fogenabled)
fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
GL_DepthMask(false);
GL_DepthTest(!depthdisable);
- varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
- varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
- varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
- varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
- varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
- varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
- varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
- varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
- varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
- varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
- varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
- varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
+ vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
+ vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
+ vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
+ vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
+ vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
+ vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
+ vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
+ vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
+ vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
+ vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
+ vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
+ vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
memset(&m, 0, sizeof(m));
m.tex[0] = R_GetTexture(texture);
m.pointer_texcoord[0] = spritetexcoord2f;
- m.pointer_vertex = varray_vertex3f;
+ m.pointer_vertex = vertex3f;
R_Mesh_State(&m);
GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
R_Mesh_Draw(0, 4, 2, polygonelements);
}
}
+static void R_DrawCollisionBrush(colbrushf_t *brush)
+{
+ int i;
+ rmeshstate_t m;
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = brush->points->v;
+ R_Mesh_State(&m);
+ i = (int)(((size_t)brush) / sizeof(colbrushf_t));
+ GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
+ GL_LockArrays(0, brush->numpoints);
+ R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
+ GL_LockArrays(0, 0);
+}
+
+static void R_DrawCollisionSurface(entity_render_t *ent, msurface_t *surface)
+{
+ int i;
+ rmeshstate_t m;
+ if (!surface->num_collisiontriangles)
+ return;
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = surface->data_collisionvertex3f;
+ R_Mesh_State(&m);
+ i = (int)(((size_t)surface) / sizeof(msurface_t));
+ GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
+ GL_LockArrays(0, surface->num_collisionvertices);
+ R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
+ GL_LockArrays(0, 0);
+}
+
static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
{
texturelayer_t *layer;
t->currenttexmatrix = r_waterscrollmatrix;
else
t->currenttexmatrix = identitymatrix;
+
+ t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
+ t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
+ t->glosstexture = r_texture_white;
+ t->specularpower = 8;
+ t->specularscale = 0;
+ if (r_shadow_gloss.integer > 0)
+ {
+ if (t->skin.gloss)
+ {
+ if (r_shadow_glossintensity.value > 0)
+ {
+ t->glosstexture = t->skin.gloss;
+ t->specularscale = r_shadow_glossintensity.value;
+ }
+ }
+ else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
+ t->specularscale = r_shadow_gloss2intensity.value;
+ }
+
t->currentnumlayers = 0;
if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
{
if (gl_lightmaps.integer)
R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
- else if (t->currentmaterialflags & MATERIALFLAG_SKY)
- {
- // transparent sky would be ridiculous
- if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
- R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
- }
- else
+ else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
{
int blendfunc1, blendfunc2, depthmask;
if (t->currentmaterialflags & MATERIALFLAG_ADD)
R_UpdateTextureInfo(ent, ent->model->data_textures + i);
}
+int rsurface_array_size = 0;
+float *rsurface_array_vertex3f = NULL;
+float *rsurface_array_svector3f = NULL;
+float *rsurface_array_tvector3f = NULL;
+float *rsurface_array_normal3f = NULL;
+float *rsurface_array_color4f = NULL;
+float *rsurface_array_texcoord3f = NULL;
+
+void R_Mesh_ResizeArrays(int newvertices)
+{
+ if (rsurface_array_size >= newvertices)
+ return;
+ if (rsurface_array_vertex3f)
+ Mem_Free(rsurface_array_vertex3f);
+ rsurface_array_size = (newvertices + 1023) & ~1023;
+ rsurface_array_vertex3f = Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[19]));
+ rsurface_array_svector3f = rsurface_array_vertex3f + rsurface_array_size * 3;
+ rsurface_array_tvector3f = rsurface_array_vertex3f + rsurface_array_size * 6;
+ rsurface_array_normal3f = rsurface_array_vertex3f + rsurface_array_size * 9;
+ rsurface_array_color4f = rsurface_array_vertex3f + rsurface_array_size * 12;
+ rsurface_array_texcoord3f = rsurface_array_vertex3f + rsurface_array_size * 16;
+}
+
float *rsurface_vertex3f;
float *rsurface_svector3f;
float *rsurface_tvector3f;
void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
{
+ if (rsurface_array_size < surface->groupmesh->num_vertices)
+ R_Mesh_ResizeArrays(surface->groupmesh->num_vertices);
if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
{
- rsurface_vertex3f = varray_vertex3f;
+ rsurface_vertex3f = rsurface_array_vertex3f;
Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
{
- rsurface_svector3f = varray_svector3f;
- rsurface_tvector3f = varray_tvector3f;
- rsurface_normal3f = varray_normal3f;
+ rsurface_svector3f = rsurface_array_svector3f;
+ rsurface_tvector3f = rsurface_array_tvector3f;
+ rsurface_normal3f = rsurface_array_normal3f;
Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
}
else
rsurface_tvector3f = NULL;
if (generatenormals)
{
- rsurface_normal3f = varray_normal3f;
+ rsurface_normal3f = rsurface_array_normal3f;
Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
}
else
VectorSet(up, 0, 0, 1);
}
for (i = 0;i < 4;i++)
- VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
+ VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
}
- rsurface_vertex3f = varray_vertex3f;
- rsurface_svector3f = varray_svector3f;
- rsurface_tvector3f = varray_tvector3f;
- rsurface_normal3f = varray_normal3f;
+ rsurface_vertex3f = rsurface_array_vertex3f;
+ rsurface_svector3f = rsurface_array_svector3f;
+ rsurface_tvector3f = rsurface_array_tvector3f;
+ rsurface_normal3f = rsurface_array_normal3f;
Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
}
R_Mesh_VertexPointer(rsurface_vertex3f);
}
+static void RSurf_Draw(const msurface_t *surface)
+{
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+}
+
static void RSurf_DrawLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
{
int i;
float f;
float *v, *c, *c2;
- RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode == 2, false);
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
if (lightmode >= 2)
{
// model lighting
- vec4_t ambientcolor4f;
+ vec3_t ambientcolor;
vec3_t diffusecolor;
- vec3_t diffusenormal;
- if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
+ vec3_t lightdir;
+ VectorCopy(ent->modellight_lightdir, lightdir);
+ ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
+ ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
+ ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
+ diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
+ diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
+ diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
+ if (VectorLength2(diffusecolor) > 0)
{
- rsurface_lightmapcolor4f = varray_color4f;
- R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, surface->groupmesh->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, rsurface_lightmapcolor4f + 4 * surface->num_firstvertex);
+ int numverts = surface->num_vertices;
+ v = rsurface_vertex3f + 3 * surface->num_firstvertex;
+ c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
+ c = rsurface_array_color4f + 4 * surface->num_firstvertex;
+ // q3-style directional shading
+ for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
+ {
+ if ((f = DotProduct(c2, lightdir)) > 0)
+ VectorMA(ambientcolor, f, diffusecolor, c);
+ else
+ VectorCopy(ambientcolor, c);
+ c[3] = a;
+ }
r = 1;
g = 1;
b = 1;
a = 1;
applycolor = false;
+ rsurface_lightmapcolor4f = rsurface_array_color4f;
}
else
{
- r = ambientcolor4f[0];
- g = ambientcolor4f[1];
- b = ambientcolor4f[2];
- a = ambientcolor4f[3];
+ r = ambientcolor[0];
+ g = ambientcolor[1];
+ b = ambientcolor[2];
rsurface_lightmapcolor4f = NULL;
}
}
{
if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
{
- for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
+ for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
{
if (surface->lightmapinfo->samples)
{
else
VectorClear(c);
}
- rsurface_lightmapcolor4f = varray_color4f;
+ rsurface_lightmapcolor4f = rsurface_array_color4f;
}
else
rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
{
if (rsurface_lightmapcolor4f)
{
- for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
+ for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
{
f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
c2[0] = c[0] * f;
}
else
{
- for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
+ for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
{
f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
c2[0] = f;
c2[3] = 1;
}
}
- rsurface_lightmapcolor4f = varray_color4f;
+ rsurface_lightmapcolor4f = rsurface_array_color4f;
}
if (applycolor && rsurface_lightmapcolor4f)
{
- for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
+ 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;
c2[1] = c[1] * g;
c2[2] = c[2] * b;
c2[3] = c[3] * a;
}
- rsurface_lightmapcolor4f = varray_color4f;
+ rsurface_lightmapcolor4f = rsurface_array_color4f;
}
R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
GL_Color(r, g, b, a);
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
- GL_LockArrays(0, 0);
-}
-
-static void RSurf_Draw(const msurface_t *surface)
-{
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
- GL_LockArrays(0, 0);
+ RSurf_Draw(surface);
}
static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
rmeshstate_t m;
if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
return;
+ r_shadow_rtlight = NULL;
renderstats.entities_surfaces += texturenumsurfaces;
// FIXME: identify models using a better check than ent->model->brush.shadowmesh
lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
qglDisable(GL_CULL_FACE);
- if (texture->currentnumlayers)
+ if (texture->currentmaterialflags & MATERIALFLAG_SKY)
+ {
+ // transparent sky would be ridiculous
+ if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ {
+ if (skyrendernow)
+ {
+ skyrendernow = false;
+ R_Sky();
+ // restore entity matrix
+ R_Mesh_Matrix(&ent->matrix);
+ }
+ GL_DepthMask(true);
+ // LordHavoc: HalfLife maps have freaky skypolys...
+ // LordHavoc: Quake3 never did sky masking (unlike software Quake
+ // and Quake2), so disable the sky masking in Quake3 maps as it
+ // causes problems with q3map2 sky tricks
+ if (!ent->model->brush.ishlbsp && ent->model->type != mod_brushq3)
+ {
+ GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
+ memset(&m, 0, sizeof(m));
+ R_Mesh_State(&m);
+ if (skyrendermasked)
+ {
+ // depth-only (masking)
+ GL_ColorMask(0,0,0,0);
+ // just to make sure that braindead drivers don't draw
+ // anything despite that colormask...
+ GL_BlendFunc(GL_ZERO, GL_ONE);
+ }
+ else
+ {
+ // fog sky
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ }
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
+ RSurf_Draw(surface);
+ }
+ if (skyrendermasked)
+ GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ }
+ }
+ }
+ else if (r_glsl.integer && gl_support_fragment_shader)
+ {
+ if (texture->currentmaterialflags & MATERIALFLAG_ADD)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ }
+ else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GL_DepthMask(false);
+ }
+ else
+ {
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthMask(true);
+ }
+
+ memset(&m, 0, sizeof(m));
+ R_Mesh_State(&m);
+ GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
+ R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
+ if (!r_glsl_permutation)
+ return;
+ if (lightmode == 2)
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
+ R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
+ R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
+ RSurf_Draw(surface);
+ }
+ }
+ else
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
+ R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
+ R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
+ R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
+ if (surface->lightmaptexture)
+ {
+ R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
+ R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
+ R_Mesh_ColorPointer(NULL);
+ }
+ else
+ {
+ R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
+ R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
+ R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
+ }
+ RSurf_Draw(surface);
+ }
+ }
+ qglUseProgramObjectARB(0);
+ }
+ else if (texture->currentnumlayers)
{
int layerindex;
texturelayer_t *layer;
applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
switch (layer->type)
{
- case TEXTURELAYERTYPE_SKY:
- if (skyrendernow)
- {
- skyrendernow = false;
- if (skyrendermasked)
- {
- R_Sky();
- // restore entity matrix and GL_Color
- R_Mesh_Matrix(&ent->matrix);
- GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
- }
- }
- // LordHavoc: HalfLife maps have freaky skypolys...
- //if (!ent->model->brush.ishlbsp)
- {
- if (skyrendermasked)
- {
- // depth-only (masking)
- GL_ColorMask(0,0,0,0);
- // just to make sure that braindead drivers don't draw anything
- // despite that colormask...
- GL_BlendFunc(GL_ZERO, GL_ONE);
- }
- else
- {
- // fog sky
- GL_BlendFunc(GL_ONE, GL_ZERO);
- }
- memset(&m, 0, sizeof(m));
- R_Mesh_State(&m);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
- RSurf_Draw(surface);
- }
- if (skyrendermasked)
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
- }
- break;
case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
memset(&m, 0, sizeof(m));
m.tex[1] = R_GetTexture(layer->texture);
m.texmatrix[1] = layer->texmatrix;
m.texrgbscale[1] = layertexrgbscale;
- m.pointer_color = varray_color4f;
+ m.pointer_color = rsurface_array_color4f;
R_Mesh_State(&m);
if (lightmode == 2)
{
memset(&m, 0, sizeof(m));
m.tex[0] = R_GetTexture(layer->texture);
m.texmatrix[0] = layer->texmatrix;
- m.pointer_color = varray_color4f;
+ m.pointer_color = rsurface_array_color4f;
m.texrgbscale[0] = layertexrgbscale;
R_Mesh_State(&m);
if (lightmode == 2)
memset(&m, 0, sizeof(m));
m.tex[0] = R_GetTexture(layer->texture);
m.texmatrix[0] = layer->texmatrix;
- m.pointer_color = varray_color4f;
+ m.pointer_color = rsurface_array_color4f;
m.texrgbscale[0] = layertexrgbscale;
R_Mesh_State(&m);
for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
m.tex[0] = R_GetTexture(layer->texture);
m.texmatrix[0] = layer->texmatrix;
m.texrgbscale[0] = layertexrgbscale;
- m.pointer_color = varray_color4f;
+ m.pointer_color = rsurface_array_color4f;
R_Mesh_State(&m);
if (lightmode == 2)
{
memset(&m, 0, sizeof(m));
m.tex[0] = R_GetTexture(layer->texture);
m.texmatrix[0] = layer->texmatrix;
- m.pointer_color = varray_color4f;
+ m.pointer_color = rsurface_array_color4f;
m.texrgbscale[0] = layertexrgbscale;
R_Mesh_State(&m);
for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
if (layer->texture)
R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
- R_Mesh_ColorPointer(varray_color4f);
- for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
+ R_Mesh_ColorPointer(rsurface_array_color4f);
+ for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
{
f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
c[0] = layercolor[0];
}
}
}
- if (r_shownormals.integer && !r_showtrispass)
- {
- int j, k;
- float v[3];
- GL_DepthTest(!r_showdisabledepthtest.integer);
- GL_DepthMask(texture->currentlayers->depthmask);
- GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
- memset(&m, 0, sizeof(m));
- R_Mesh_State(&m);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
- GL_Color(1, 0, 0, 1);
- qglBegin(GL_LINES);
- for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
- {
- VectorCopy(rsurface_vertex3f + k * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, 8, rsurface_svector3f + k * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- }
- GL_Color(0, 0, 1, 1);
- for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
- {
- VectorCopy(rsurface_vertex3f + k * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- }
- GL_Color(0, 1, 0, 1);
- for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
- {
- VectorCopy(rsurface_vertex3f + k * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, 8, rsurface_normal3f + k * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- }
- qglEnd();
- }
- }
}
if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
qglEnable(GL_CULL_FACE);
t = NULL;
texture = NULL;
numsurfacelist = 0;
- if (ent == r_refdef.worldentity)
+ if (r_showsurfaces.integer)
+ {
+ rmeshstate_t m;
+ GL_DepthTest(true);
+ GL_DepthMask(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ memset(&m, 0, sizeof(m));
+ R_Mesh_State(&m);
+ for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+ {
+ if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
+ continue;
+ texture = surface->texture->currentframe;
+ if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
+ {
+ int k = (int)(((size_t)surface) / sizeof(msurface_t));
+ GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
+ RSurf_Draw(surface);
+ renderstats.entities_triangles += surface->num_triangles;
+ }
+ renderstats.entities_surfaces++;
+ }
+ }
+ else if (ent == r_refdef.worldentity)
{
for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
{
}
if (numsurfacelist)
R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
- if (!r_showtrispass)
- renderstats.entities_triangles += counttriangles;
+ renderstats.entities_triangles += counttriangles;
+ if (gl_support_fragment_shader)
+ qglUseProgramObjectARB(0);
+
+ if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
+ {
+ int i;
+ msurface_t *surface;
+ q3mbrush_t *brush;
+ R_Mesh_Matrix(&ent->matrix);
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ GL_DepthTest(!r_showdisabledepthtest.integer);
+ qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);
+ for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
+ if (brush->colbrushf && brush->colbrushf->numtriangles)
+ R_DrawCollisionBrush(brush->colbrushf);
+ for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
+ if (surface->num_collisiontriangles)
+ R_DrawCollisionSurface(ent, surface);
+ qglPolygonOffset(r_polygonfactor, r_polygonoffset);
+ }
+
+ if (r_showtris.integer || r_shownormals.integer)
+ {
+ int k, l;
+ const int *elements;
+ rmeshstate_t m;
+ vec3_t v;
+ GL_DepthTest(true);
+ GL_DepthMask(true);
+ if (r_showdisabledepthtest.integer)
+ qglDepthFunc(GL_ALWAYS);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ memset(&m, 0, sizeof(m));
+ R_Mesh_State(&m);
+ for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+ {
+ if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
+ continue;
+ texture = surface->texture->currentframe;
+ if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
+ {
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, r_shownormals.integer != 0);
+ if (r_showtris.integer)
+ {
+ if (!texture->currentlayers->depthmask)
+ GL_Color(r_showtris.value, 0, 0, 1);
+ else if (ent == r_refdef.worldentity)
+ GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
+ else
+ GL_Color(0, r_showtris.value, 0, 1);
+ elements = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);
+ qglBegin(GL_LINES);
+ for (k = 0;k < surface->num_triangles;k++, elements += 3)
+ {
+ qglArrayElement(elements[0]);qglArrayElement(elements[1]);
+ qglArrayElement(elements[1]);qglArrayElement(elements[2]);
+ qglArrayElement(elements[2]);qglArrayElement(elements[0]);
+ }
+ qglEnd();
+ }
+ if (r_shownormals.integer)
+ {
+ GL_Color(r_shownormals.value, 0, 0, 1);
+ qglBegin(GL_LINES);
+ for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
+ {
+ VectorCopy(rsurface_vertex3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ VectorMA(v, 8, rsurface_svector3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ }
+ qglEnd();
+ GL_Color(0, 0, r_shownormals.value, 1);
+ qglBegin(GL_LINES);
+ for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
+ {
+ VectorCopy(rsurface_vertex3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ }
+ qglEnd();
+ GL_Color(0, r_shownormals.value, 0, 1);
+ qglBegin(GL_LINES);
+ for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
+ {
+ VectorCopy(rsurface_vertex3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ VectorMA(v, 8, rsurface_normal3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ }
+ qglEnd();
+ }
+ }
+ }
+ if (r_showdisabledepthtest.integer)
+ qglDepthFunc(GL_LEQUAL);
+ }
}