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_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
-cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
+cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
+cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
-cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
+cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
+cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
-cvar_t r_hdr_bloomintensity = {CVAR_SAVE, "r_hdr_bloomintensity", "0.5", "amount of bloom"};
cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
-rtexture_t *r_bloom_texture_screen;
-rtexture_t *r_bloom_texture_bloom;
+typedef struct r_glsl_bloomshader_s
+{
+ int program;
+ int loc_Texture_Bloom;
+}
+r_glsl_bloomshader_t;
+
+static struct r_bloomstate_s
+{
+ qboolean enabled;
+ qboolean hdr;
+
+ int bloomwidth, bloomheight;
+
+ int screentexturewidth, screentextureheight;
+ rtexture_t *texture_screen;
+
+ int bloomtexturewidth, bloomtextureheight;
+ rtexture_t *texture_bloom;
+
+ r_glsl_bloomshader_t *shader;
+
+ // arrays for rendering the screen passes
+ float screentexcoord2f[8];
+ float bloomtexcoord2f[8];
+ float offsettexcoord2f[8];
+}
+r_bloomstate;
+
rtexture_t *r_texture_blanknormalmap;
rtexture_t *r_texture_white;
rtexture_t *r_texture_black;
// temporary variable used by a macro
int fogtableindex;
+// vertex coordinates for a quad that covers the screen exactly
+const static float r_screenvertex3f[12] =
+{
+ 0, 0, 0,
+ 1, 0, 0,
+ 1, 1, 0,
+ 0, 1, 0
+};
+
+extern void R_DrawModelShadows(void);
+
void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
{
int i;
permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
}
}
- if (rsurface_texture->skin.glow)
+ if (rsurface_texture->currentskinframe->glow)
permutation |= SHADERPERMUTATION_GLOW;
}
if (specularscale > 0)
if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
}
- if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
+ if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
//if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
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(rsurface_texture->skin.pants));
- if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
+ if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
+ if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
//if (r_glsl_permutation->loc_Texture_Lightmap >= 0) 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));
- if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
+ if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
if (r_glsl_permutation->loc_FogColor >= 0)
if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
if (r_glsl_permutation->loc_Color_Pants >= 0)
{
- if (rsurface_texture->skin.pants)
+ if (rsurface_texture->currentskinframe->pants)
qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
else
qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
}
if (r_glsl_permutation->loc_Color_Shirt >= 0)
{
- if (rsurface_texture->skin.shirt)
+ if (rsurface_texture->currentskinframe->shirt)
qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
else
qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
void gl_main_start(void)
{
r_main_texturepool = R_AllocTexturePool();
- r_bloom_texture_screen = NULL;
- r_bloom_texture_bloom = NULL;
R_BuildBlankTextures();
R_BuildNoTexture();
if (gl_texturecubemap)
R_BuildNormalizationCube();
}
R_BuildFogTexture();
+ memset(&r_bloomstate, 0, sizeof(r_bloomstate));
memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
}
void gl_main_shutdown(void)
{
R_FreeTexturePool(&r_main_texturepool);
- r_bloom_texture_screen = NULL;
- r_bloom_texture_bloom = NULL;
r_texture_blanknormalmap = NULL;
r_texture_white = NULL;
r_texture_black = NULL;
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
+ memset(&r_bloomstate, 0, sizeof(r_bloomstate));
R_GLSL_Restart_f();
}
Cvar_RegisterVariable(&r_wateralpha);
Cvar_RegisterVariable(&r_dynamic);
Cvar_RegisterVariable(&r_fullbright);
+ Cvar_RegisterVariable(&r_shadows);
+ Cvar_RegisterVariable(&r_shadows_throwdistance);
Cvar_RegisterVariable(&r_q1bsp_skymasking);
Cvar_RegisterVariable(&r_textureunits);
Cvar_RegisterVariable(&r_glsl);
Cvar_RegisterVariable(&r_lerpmodels);
Cvar_RegisterVariable(&r_waterscroll);
Cvar_RegisterVariable(&r_bloom);
- Cvar_RegisterVariable(&r_bloom_intensity);
+ Cvar_RegisterVariable(&r_bloom_colorscale);
+ Cvar_RegisterVariable(&r_bloom_brighten);
Cvar_RegisterVariable(&r_bloom_blur);
Cvar_RegisterVariable(&r_bloom_resolution);
- Cvar_RegisterVariable(&r_bloom_power);
+ Cvar_RegisterVariable(&r_bloom_colorexponent);
+ Cvar_RegisterVariable(&r_bloom_colorsubtract);
Cvar_RegisterVariable(&r_hdr);
Cvar_RegisterVariable(&r_hdr_scenebrightness);
- Cvar_RegisterVariable(&r_hdr_bloomintensity);
Cvar_RegisterVariable(&r_hdr_glowintensity);
Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
Cvar_RegisterVariable(&developer_texturelogging);
static void R_UpdateEntityLighting(entity_render_t *ent)
{
vec3_t tempdiffusenormal;
+
+ // fetch the lighting from the worldmodel data
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);
+ VectorClear(tempdiffusenormal);
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);
+ {
+ vec3_t org;
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+ r_refdef.worldmodel->brush.LightPoint(r_refdef.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);
VectorNormalize(ent->modellight_lightdir);
+
+ // scale ambient and directional light contributions according to rendering variables
ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
for (i = 0;i < r_refdef.numentities;i++)
{
ent = r_refdef.entities[i];
- r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST);
+ r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
}
}
+
+ // update entity lighting (even on hidden entities for r_shadows)
+ for (i = 0;i < r_refdef.numentities;i++)
+ R_UpdateEntityLighting(r_refdef.entities[i]);
}
// only used if skyrendermasked, and normally returns false
R_View_UpdateEntityVisible();
}
-void R_ResetViewRendering(void)
+void R_SetupView(const matrix4x4_t *matrix)
+{
+ if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
+ GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
+ else
+ GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
+
+ GL_SetupView_Orientation_FromEntity(matrix);
+}
+
+void R_ResetViewRendering2D(void)
{
if (gl_support_fragment_shader)
{
qglUseProgramObjectARB(0);CHECKGLERROR
}
+ DrawQ_Finish();
+
// 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);CHECKGLERROR
GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
+ GL_Color(1, 1, 1, 1);
GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_AlphaTest(false);
+ GL_ScissorTest(false);
+ GL_DepthMask(false);
+ GL_DepthTest(false);
+ R_Mesh_Matrix(&identitymatrix);
+ R_Mesh_ResetTextureState();
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
+ qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+ qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+ qglStencilMask(~0);CHECKGLERROR
+ 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
+}
+
+void R_ResetViewRendering3D(void)
+{
+ if (gl_support_fragment_shader)
+ {
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ }
+
+ DrawQ_Finish();
+
+ // 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);CHECKGLERROR
+ R_SetupView(&r_view.matrix);
+ GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
+ GL_Color(1, 1, 1, 1);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_AlphaTest(false);
GL_ScissorTest(true);
GL_DepthMask(true);
GL_DepthTest(true);
R_Mesh_Matrix(&identitymatrix);
R_Mesh_ResetTextureState();
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
+ qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+ qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+ qglStencilMask(~0);CHECKGLERROR
+ 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_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 myhvec2 hvec2\n"
+"#define myhvec3 hvec3\n"
+"#define myhvec4 hvec4\n"
+"#else\n"
+"#define myhalf float\n"
+"#define myhvec2 vec2\n"
+"#define myhvec3 vec3\n"
+"#define myhvec4 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;
+" myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
+" for (x = -BLUR_X;x <= BLUR_X;x++)
+" color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
+" color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
+" color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
+" color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
+
+" gl_FragColor = vec4(color);\n"
+"}\n"
+"\n"
+"#endif // FRAGMENT_SHADER\n"
+*/
+
void R_RenderScene(void);
-void R_Bloom_MakeTexture(qboolean darken)
+void R_Bloom_StartFrame(void)
{
- int screenwidth, screenheight;
- int screentexturewidth, screentextureheight;
- int bloomtexturewidth, bloomtextureheight;
- int bloomwidth, bloomheight, x, range;
- float xoffset, yoffset, r;
- float vertex3f[12];
- float texcoord2f[3][8];
+ int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
// set bloomwidth and bloomheight to the bloom resolution that will be
// used (often less than the screen resolution for faster rendering)
- bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
- bloomheight = bound(1, bloomwidth * r_view.height / r_view.width, r_view.height);
+ r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
+ r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
+ r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
- // set the (poorly named) screenwidth and screenheight variables to
- // a power of 2 at least as large as the screen, these will define the
- // size of the texture to allocate
- for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
- for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
+ // calculate desired texture sizes
+ if (gl_support_arb_texture_non_power_of_two)
+ {
+ screentexturewidth = r_view.width;
+ screentextureheight = r_view.height;
+ bloomtexturewidth = r_bloomstate.bloomwidth;
+ bloomtextureheight = r_bloomstate.bloomheight;
+ }
+ else
+ {
+ for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
+ for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
+ for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
+ for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
+ }
- r_refdef.stats.bloom++;
+ if (r_hdr.integer)
+ {
+ screentexturewidth = screentextureheight = 0;
+ }
+ else if (r_bloom.integer)
+ {
+ }
+ else
+ {
+ screentexturewidth = screentextureheight = 0;
+ 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
- // TODO: reallocate these when size settings change
- if (!r_bloom_texture_screen)
- r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
- if (!r_bloom_texture_bloom)
- r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
-
- screentexturewidth = R_TextureWidth(r_bloom_texture_screen);
- screentextureheight = R_TextureHeight(r_bloom_texture_screen);
- bloomtexturewidth = R_TextureWidth(r_bloom_texture_bloom);
- bloomtextureheight = R_TextureHeight(r_bloom_texture_bloom);
-
- // vertex coordinates for a quad that covers the screen exactly
- 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 (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
+ {
+ if (r_bloomstate.texture_screen)
+ R_FreeTexture(r_bloomstate.texture_screen);
+ r_bloomstate.texture_screen = NULL;
+ r_bloomstate.screentexturewidth = screentexturewidth;
+ r_bloomstate.screentextureheight = screentextureheight;
+ if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
+ r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+ }
+ if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
+ {
+ if (r_bloomstate.texture_bloom)
+ R_FreeTexture(r_bloomstate.texture_bloom);
+ r_bloomstate.texture_bloom = NULL;
+ r_bloomstate.bloomtexturewidth = bloomtexturewidth;
+ r_bloomstate.bloomtextureheight = bloomtextureheight;
+ if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
+ r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+ }
// set up a texcoord array for the full resolution screen image
// (we have to keep this around to copy back during final render)
- texcoord2f[0][0] = 0;
- texcoord2f[0][1] = (float)r_view.height / (float)screentextureheight;
- texcoord2f[0][2] = (float)r_view.width / (float)screentexturewidth;
- texcoord2f[0][3] = (float)r_view.height / (float)screentextureheight;
- texcoord2f[0][4] = (float)r_view.width / (float)screentexturewidth;
- texcoord2f[0][5] = 0;
- texcoord2f[0][6] = 0;
- texcoord2f[0][7] = 0;
+ r_bloomstate.screentexcoord2f[0] = 0;
+ r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
+ r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
+ r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
+ r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
+ r_bloomstate.screentexcoord2f[5] = 0;
+ r_bloomstate.screentexcoord2f[6] = 0;
+ r_bloomstate.screentexcoord2f[7] = 0;
// set up a texcoord array for the reduced resolution bloom image
// (which will be additive blended over the screen image)
- texcoord2f[1][0] = 0;
- texcoord2f[1][1] = (float)bloomheight / (float)bloomtextureheight;
- texcoord2f[1][2] = (float)bloomwidth / (float)bloomtexturewidth;
- texcoord2f[1][3] = (float)bloomheight / (float)bloomtextureheight;
- texcoord2f[1][4] = (float)bloomwidth / (float)bloomtexturewidth;
- texcoord2f[1][5] = 0;
- texcoord2f[1][6] = 0;
- texcoord2f[1][7] = 0;
-
- R_ResetViewRendering();
- GL_DepthTest(false);
- R_Mesh_VertexPointer(vertex3f);
- R_Mesh_ColorPointer(NULL);
+ 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[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
+ 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;
+}
- R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
- R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
+void R_Bloom_CopyScreenTexture(float colorscale)
+{
+ r_refdef.stats.bloom++;
+
+ R_ResetViewRendering2D();
+ R_Mesh_VertexPointer(r_screenvertex3f);
+ R_Mesh_ColorPointer(NULL);
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
// copy view into the screen texture
GL_ActiveTexture(0);
// now scale it down to the bloom texture size
CHECKGLERROR
- qglViewport(r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
+ qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_Color(1, 1, 1, 1);
+ GL_Color(colorscale, colorscale, colorscale, 1);
// TODO: optimize with multitexture or GLSL
R_Mesh_Draw(0, 4, 2, polygonelements);
- r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
+ r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
- if (darken)
- {
- // raise to a power of itself to darken it (this leaves the really
- // bright stuff bright, and everything else becomes very dark)
- // render multiple times with a multiply blendfunc to raise to a power
- GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
- for (x = 1;x < r_bloom_power.integer;x++)
- {
- R_Mesh_Draw(0, 4, 2, polygonelements);
- r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
- }
- }
+ // we now have a bloom image in the framebuffer
+ // copy it into the bloom image texture for later processing
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
+ GL_ActiveTexture(0);
+ CHECKGLERROR
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+}
- // we now have a darkened bloom image in the framebuffer
- // copy it into the bloom image texture for more processing
- R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
- R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
+void R_Bloom_CopyHDRTexture(void)
+{
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
+}
- // blend on at multiple vertical offsets to achieve a vertical blur
- // TODO: do offset blends using GLSL
- range = r_bloom_blur.integer * bloomwidth / 320;
- GL_BlendFunc(GL_ONE, GL_ZERO);
- for (x = -range;x <= range;x++)
- {
- 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
- 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)
- r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
- if (r < 0.01f)
- continue;
+void R_Bloom_MakeTexture(void)
+{
+ int x, range, dir;
+ float xoffset, yoffset, r;
+
+ r_refdef.stats.bloom++;
+
+ R_ResetViewRendering2D();
+ R_Mesh_VertexPointer(r_screenvertex3f);
+ R_Mesh_ColorPointer(NULL);
+
+ // we have a bloom image in the framebuffer
+ CHECKGLERROR
+ qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
+
+ for (x = 1;x < r_bloom_colorexponent.value;)
+ {
+ x *= 2;
+ r = bound(0, r_bloom_colorexponent.value / x, 1);
+ GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
GL_Color(r, r, r, 1);
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
R_Mesh_Draw(0, 4, 2, polygonelements);
- r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
- GL_BlendFunc(GL_ONE, GL_ONE);
+ r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+
+ // copy the vertically blurred bloom view to a texture
+ GL_ActiveTexture(0);
+ CHECKGLERROR
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
}
- // copy the vertically blurred bloom view to a texture
- GL_ActiveTexture(0);
- CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
+ range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
- // blend the vertically blurred image at multiple offsets horizontally
- // to finish the blur effect
- // TODO: do offset blends using GLSL
- range = r_bloom_blur.integer * bloomwidth / 320;
- GL_BlendFunc(GL_ONE, GL_ZERO);
- for (x = -range;x <= range;x++)
- {
- 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
- 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)
- r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
- if (r < 0.01f)
- continue;
- GL_Color(r, r, r, 1);
+ for (dir = 0;dir < 2;dir++)
+ {
+ // blend on at multiple vertical offsets to achieve a vertical blur
+ // TODO: do offset blends using GLSL
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ for (x = -range;x <= range;x++)
+ {
+ if (!dir){xoffset = 0;yoffset = x;}
+ else {xoffset = x;yoffset = 0;}
+ xoffset /= (float)r_bloomstate.bloomtexturewidth;
+ yoffset /= (float)r_bloomstate.bloomtextureheight;
+ // compute a texcoord array with the specified x and y offset
+ r_bloomstate.offsettexcoord2f[0] = xoffset+0;
+ r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
+ r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
+ r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
+ r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
+ r_bloomstate.offsettexcoord2f[5] = yoffset+0;
+ r_bloomstate.offsettexcoord2f[6] = xoffset+0;
+ r_bloomstate.offsettexcoord2f[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)
+ //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
+ //r = (dir ? 1.0f : r_bloom_brighten.value)/(range*2+1);
+ r = (dir ? 1.0f : r_bloom_brighten.value)/(range*2+1)*(1 - x*x/(float)(range*range));
+ GL_Color(r, r, r, 1);
+ R_Mesh_Draw(0, 4, 2, polygonelements);
+ r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+ GL_BlendFunc(GL_ONE, GL_ONE);
+ }
+
+ // copy the vertically blurred bloom view to a texture
+ GL_ActiveTexture(0);
+ CHECKGLERROR
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+ }
+
+ // apply subtract last
+ // (just like it would be in a GLSL shader)
+ if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
+ {
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
+ GL_Color(1, 1, 1, 1);
R_Mesh_Draw(0, 4, 2, polygonelements);
- r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
+ r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+
GL_BlendFunc(GL_ONE, GL_ONE);
- }
+ qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
+ R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
+ GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
+ R_Mesh_Draw(0, 4, 2, polygonelements);
+ r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+ qglBlendEquationEXT(GL_FUNC_ADD_EXT);
- // copy the blurred bloom view to a texture
- GL_ActiveTexture(0);
- CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
+ // copy the darkened bloom view to a texture
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
+ GL_ActiveTexture(0);
+ CHECKGLERROR
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+ }
}
void R_HDR_RenderBloomTexture(void)
oldwidth = r_view.width;
oldheight = r_view.height;
- r_view.width = bound(1, r_bloom_resolution.integer, min(r_view.width, gl_max_texture_size));
- r_view.height = r_view.width * oldheight / oldwidth;
+ r_view.width = r_bloomstate.bloomwidth;
+ r_view.height = r_bloomstate.bloomheight;
// TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
- // FIXME: change global lightmapintensity and light intensity according to r_hdr_bloomintensity cvar
- // FIXME: change global lightmapintensity and light intensity according to r_hdr_scenebrightness cvar
// TODO: add exposure compensation features
+ // TODO: add fp16 framebuffer support
- r_view.colorscale = r_hdr_bloomintensity.value * r_hdr_scenebrightness.value;
+ r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
R_RenderScene();
- R_ResetViewRendering();
+ R_ResetViewRendering2D();
+
+ R_Bloom_CopyHDRTexture();
+ R_Bloom_MakeTexture();
- R_Bloom_MakeTexture(false);
+ R_ResetViewRendering3D();
R_ClearScreen();
if (r_timereport_active)
R_TimeReport("clear");
+
// restore the view settings
r_view.width = oldwidth;
r_view.height = oldheight;
-
- // go back to full view area
- R_ResetViewRendering();
}
static void R_BlendView(void)
{
- int screenwidth, screenheight;
- int bloomwidth, bloomheight;
- qboolean dobloom;
- qboolean dohdr;
- qboolean doblend;
- 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
- // size of the texture to allocate
- for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
- for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
-
- doblend = r_refdef.viewblend[3] >= 0.01f;
- dobloom = !r_hdr.integer && r_bloom.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512;
- dohdr = r_hdr.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512;
-
- if (!dobloom && !dohdr && !doblend)
- return;
-
- // vertex coordinates for a quad that covers the screen exactly
- 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;
-
- // set bloomwidth and bloomheight to the bloom resolution that will be
- // used (often less than the screen resolution for faster rendering)
- bloomwidth = min(r_view.width, r_bloom_resolution.integer);
- 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)
- 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)
- 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;
-
- if (dohdr)
+ if (r_bloomstate.enabled && r_bloomstate.hdr)
{
// render high dynamic range bloom effect
// the bloom texture was made earlier this render, so we just need to
// blend it onto the screen...
- R_ResetViewRendering();
- GL_DepthTest(false);
- R_Mesh_VertexPointer(vertex3f);
+ R_ResetViewRendering2D();
+ R_Mesh_VertexPointer(r_screenvertex3f);
R_Mesh_ColorPointer(NULL);
GL_Color(1, 1, 1, 1);
GL_BlendFunc(GL_ONE, GL_ONE);
- R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
- R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
R_Mesh_Draw(0, 4, 2, polygonelements);
r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
}
- if (dobloom)
+ else if (r_bloomstate.enabled)
{
// render simple bloom effect
+ // copy the screen and shrink it and darken it for the bloom process
+ R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
// make the bloom texture
- R_Bloom_MakeTexture(true);
+ R_Bloom_MakeTexture();
// put the original screen image back in place and blend the bloom
// texture on it
- R_ResetViewRendering();
- GL_DepthTest(false);
- R_Mesh_VertexPointer(vertex3f);
+ R_ResetViewRendering2D();
+ R_Mesh_VertexPointer(r_screenvertex3f);
R_Mesh_ColorPointer(NULL);
GL_Color(1, 1, 1, 1);
GL_BlendFunc(GL_ONE, GL_ZERO);
// do both in one pass if possible
- R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
- R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
if (r_textureunits.integer >= 2 && gl_combine.integer)
{
R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
- R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
- R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
+ R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
+ R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
}
else
{
r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
// now blend on the bloom texture
GL_BlendFunc(GL_ONE, GL_ONE);
- R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
- R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
}
R_Mesh_Draw(0, 4, 2, polygonelements);
r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
}
- if (doblend)
+ if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
{
// apply a color tint to the whole view
- R_ResetViewRendering();
- GL_DepthTest(false);
- R_Mesh_VertexPointer(vertex3f);
+ R_ResetViewRendering2D();
+ R_Mesh_VertexPointer(r_screenvertex3f);
R_Mesh_ColorPointer(NULL);
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]);
void R_UpdateVariables(void)
{
- int i;
-
R_Textures_Frame();
r_refdef.farclip = 4096;
}
else
r_refdef.fogenabled = false;
-
- // update some cached entity properties...
- for (i = 0;i < r_refdef.numentities;i++)
- {
- entity_render_t *ent = r_refdef.entities[i];
- // some of the renderer still relies on origin...
- Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
- // some of the renderer still relies on scale...
- ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
- R_UpdateEntityLighting(ent);
- }
}
/*
if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
return; //Host_Error ("R_RenderView: NULL worldmodel");
+ R_Shadow_UpdateWorldLightSelection();
+
CHECKGLERROR
- GL_ScissorTest(true);
- GL_DepthMask(true);
if (r_timereport_active)
R_TimeReport("setup");
if (r_timereport_active)
R_TimeReport("visibility");
- R_ResetViewRendering();
+ R_ResetViewRendering3D();
R_ClearScreen();
if (r_timereport_active)
R_TimeReport("clear");
+ R_Bloom_StartFrame();
+
// this produces a bloom texture to be used in R_BlendView() later
if (r_hdr.integer)
R_HDR_RenderBloomTexture();
extern void R_DrawPortals (void);
void R_RenderScene(void)
{
- DrawQ_Finish();
-
// don't let sound skip if going slow
if (r_refdef.extraupdate)
S_ExtraUpdate ();
- CHECKGLERROR
- if (gl_support_fragment_shader)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
- qglDepthFunc(GL_LEQUAL);CHECKGLERROR
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
- qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
-
- R_ResetViewRendering();
+ R_ResetViewRendering3D();
R_MeshQueue_BeginScene();
- if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
- GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
- else
- GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
-
- GL_SetupView_Orientation_FromEntity(&r_view.matrix);
-
- R_Shadow_UpdateWorldLightSelection();
-
R_SkyStartFrame();
Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
if (r_refdef.extraupdate)
S_ExtraUpdate ();
+ if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
+ {
+ R_DrawModelShadows();
+
+ R_ResetViewRendering3D();
+
+ // don't let sound skip if going slow
+ if (r_refdef.extraupdate)
+ S_ExtraUpdate ();
+ }
+
R_ShadowVolumeLighting(false);
if (r_timereport_active)
R_TimeReport("rtlights");
if (r_refdef.extraupdate)
S_ExtraUpdate ();
- CHECKGLERROR
- if (gl_support_fragment_shader)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
- qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
+ R_ResetViewRendering2D();
}
/*
GL_DepthMask(true);
}
GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
+ GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
R_Mesh_VertexPointer(nomodelvertex3f);
if (r_refdef.fogenabled)
{
+ vec3_t org;
memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
R_Mesh_ColorPointer(color4f);
- f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+ f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
f1 = 1 - f2;
for (i = 0, c = color4f;i < 6;i++, c += 4)
{
void R_DrawNoModel(entity_render_t *ent)
{
+ vec3_t org;
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
//if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
- R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
+ R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
//else
// R_DrawNoModelCallback(ent, 0);
}
void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
{
+ model_t *model = ent->model;
+
// FIXME: identify models using a better check than ent->model->brush.shadowmesh
//int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
+ // switch to an alternate material if this is a q1bsp animated material
{
texture_t *texture = t;
- model_t *model = ent->model;
int s = ent->skinnum;
if ((unsigned int)s >= (unsigned int)model->numskins)
s = 0;
texture->currentframe = t;
}
+ // pick a new currentskinframe if the material is animated
+ if (t->numskinframes >= 2)
+ t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
+
t->currentmaterialflags = t->basematerialflags;
t->currentalpha = ent->alpha;
- if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
+ if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
t->currentalpha *= r_wateralpha.value;
if (!(ent->flags & RENDER_LIGHT))
t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
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->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
t->glosstexture = r_texture_white;
- t->specularpower = 8;
+ t->specularpower = r_shadow_glossexponent.value;
t->specularscale = 0;
if (r_shadow_gloss.integer > 0)
{
- if (t->skin.gloss)
+ if (t->currentskinframe->gloss)
{
if (r_shadow_glossintensity.value > 0)
{
- t->glosstexture = t->skin.gloss;
+ t->glosstexture = t->currentskinframe->gloss;
t->specularscale = r_shadow_glossintensity.value;
}
}
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->skin.merged) ? t->skin.merged : t->skin.base;
+ 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, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
- if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
- if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
+ 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] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
+ 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] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
}
else
{
R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
if (r_ambient.value >= (1.0f/64.0f))
R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
- if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
+ 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->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
if (r_ambient.value >= (1.0f/64.0f))
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
}
- if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
+ 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->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
if (r_ambient.value >= (1.0f/64.0f))
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
}
}
- if (t->skin.glow != NULL)
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
+ 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->currentalpha);
if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
{
// if this is opaque use alpha blend which will darken the earlier
// 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->skin.fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
+ 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.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
}
}
}
texture_t *rsurface_glsl_texture;
qboolean rsurface_glsl_uselightmap;
+void RSurf_CleanUp(void)
+{
+ CHECKGLERROR
+ if (rsurface_mode == RSURFMODE_GLSL)
+ {
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ }
+ GL_AlphaTest(false);
+ rsurface_mode = RSURFMODE_NONE;
+ rsurface_lightmaptexture = NULL;
+ rsurface_texture = NULL;
+ rsurface_glsl_texture = NULL;
+ rsurface_glsl_uselightmap = false;
+}
+
void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
{
+ RSurf_CleanUp();
Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
rsurface_entity = ent;
rsurface_model = ent->model;
rsurface_svector3f = rsurface_modelsvector3f;
rsurface_tvector3f = rsurface_modeltvector3f;
rsurface_normal3f = rsurface_modelnormal3f;
- rsurface_mode = RSURFMODE_NONE;
- rsurface_lightmaptexture = NULL;
- rsurface_texture = NULL;
- rsurface_glsl_texture = NULL;
- rsurface_glsl_uselightmap = false;
-}
-
-void RSurf_CleanUp(void)
-{
- CHECKGLERROR
- if (rsurface_mode == RSURFMODE_GLSL)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
- GL_AlphaTest(false);
- rsurface_mode = RSURFMODE_NONE;
- rsurface_lightmaptexture = NULL;
- rsurface_texture = NULL;
- rsurface_glsl_texture = NULL;
- rsurface_glsl_uselightmap = false;
}
void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
rsurface_tvector3f = rsurface_array_deformedtvector3f;
rsurface_normal3f = rsurface_array_deformednormal3f;
}
+ else
+ {
+ rsurface_vertex3f = rsurface_modelvertex3f;
+ rsurface_svector3f = rsurface_modelsvector3f;
+ rsurface_tvector3f = rsurface_modeltvector3f;
+ rsurface_normal3f = rsurface_modelnormal3f;
+ }
R_Mesh_VertexPointer(rsurface_vertex3f);
}
r_refdef.stats.entities_surfaces += texturenumsurfaces;
CHECKGLERROR
GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
- if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
- {
- qglDisable(GL_CULL_FACE);CHECKGLERROR
- }
+ GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
if (r_showsurfaces.integer)
R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
}
CHECKGLERROR
GL_LockArrays(0, 0);
- if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
- {
- qglEnable(GL_CULL_FACE);CHECKGLERROR
- }
}
#define BATCHSIZE 256
if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
{
if (batchcount > 0)
- R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
+ if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
+ R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
batchcount = 0;
t = surface->texture;
rsurface_lightmaptexture = surface->lightmaptexture;
R_UpdateTextureInfo(ent, t);
rsurface_texture = t->currentframe;
}
- if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
- continue; // transparent sky is too difficult
texturesurfacelist[batchcount++] = surface;
}
if (batchcount > 0)
- R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
+ if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
+ R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
RSurf_CleanUp();
}
const int *elements;
vec3_t v;
CHECKGLERROR
- GL_DepthTest(true);
+ GL_DepthTest(!r_showdisabledepthtest.integer);
GL_DepthMask(true);
- if (r_showdisabledepthtest.integer)
- {
- qglDepthFunc(GL_ALWAYS);CHECKGLERROR
- }
GL_BlendFunc(GL_ONE, GL_ZERO);
R_Mesh_ColorPointer(NULL);
R_Mesh_ResetTextureState();
}
}
rsurface_texture = NULL;
- if (r_showdisabledepthtest.integer)
- {
- qglDepthFunc(GL_LEQUAL);CHECKGLERROR
- }
}
}
-