// r_main.c
#include "quakedef.h"
-#include "cl_dyntexture.h"
#include "r_shadow.h"
#include "polygon.h"
#include "image.h"
{CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
};
-extern cvar_t v_glslgamma;
extern cvar_t v_glslgamma_2d;
extern qboolean v_flipped_state;
permutation |= SHADERPERMUTATION_GLOW;
else if (texturemode == GL_DECAL)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
- if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
+ if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
permutation |= SHADERPERMUTATION_GAMMARAMPS;
if (suppresstexalpha)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
R_Mesh_TexBind(GL20TU_FIRST , first );
R_Mesh_TexBind(GL20TU_SECOND, second);
if (permutation & SHADERPERMUTATION_GAMMARAMPS)
- R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
+ R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
#endif
break;
case RENDERPATH_D3D10:
}
}
-extern qboolean r_shadow_usingdeferredprepass;
-extern rtexture_t *r_shadow_attenuationgradienttexture;
-extern rtexture_t *r_shadow_attenuation2dtexture;
-extern rtexture_t *r_shadow_attenuation3dtexture;
-extern qboolean r_shadow_usingshadowmap2d;
-extern qboolean r_shadow_usingshadowmaportho;
-extern float r_shadow_modelshadowmap_texturescale[4];
-extern float r_shadow_modelshadowmap_parameters[4];
-extern float r_shadow_lightshadowmap_texturescale[4];
-extern float r_shadow_lightshadowmap_parameters[4];
-extern qboolean r_shadow_shadowmapvsdct;
-extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
-extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
-extern rtexture_t *r_shadow_shadowmapvsdcttexture;
-extern matrix4x4_t r_shadow_shadowmapmatrix;
-extern int r_shadow_prepass_width;
-extern int r_shadow_prepass_height;
-extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
-extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
-extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
-extern rtexture_t *r_shadow_prepasslightingspeculartexture;
-
#define BLENDFUNC_ALLOWS_COLORMOD 1
#define BLENDFUNC_ALLOWS_FOG 2
#define BLENDFUNC_ALLOWS_FOG_HACK0 4
if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
break;
- if (!item) {
- rtexture_t *dyntexture;
- // check whether its a dynamic texture
- dyntexture = CL_GetDynTexture( basename );
- if (!add && !dyntexture)
+ if (!item)
+ {
+ if (!add)
return NULL;
item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
memset(item, 0, sizeof(*item));
strlcpy(item->basename, basename, sizeof(item->basename));
- item->base = dyntexture; // either NULL or dyntexture handle
item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
item->comparewidth = comparewidth;
item->compareheight = compareheight;
}
else if (textureflags & TEXF_FORCE_RELOAD)
{
- rtexture_t *dyntexture;
- // check whether its a dynamic texture
- dyntexture = CL_GetDynTexture( basename );
- if (!add && !dyntexture)
+ if (!add)
return NULL;
R_SkinFrame_PurgeSkinFrame(item);
}
- else if( item->base == NULL )
- {
- rtexture_t *dyntexture;
- // check whether its a dynamic texture
- // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
- dyntexture = CL_GetDynTexture( basename );
- item->base = dyntexture; // either NULL or dyntexture handle
- }
R_SkinFrame_MarkUsed(item);
return item;
}
extern cvar_t gl_picmip;
-skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
+skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
{
int j;
unsigned char *pixels;
if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
{
basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
+ if (basepixels == NULL && fallbacknotexture)
+ basepixels = Image_GenerateNoTexture();
if (basepixels == NULL)
return NULL;
}
Con_Printf("loading embedded 8bit image \"%s\"\n", name);
skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
- if (textureflags & TEXF_ALPHA)
+ if ((textureflags & TEXF_ALPHA) && alphapalette)
{
for (i = 0;i < width * height;i++)
{
return skinframe;
}
+skinframe_t *R_SkinFrame_LoadNoTexture(void)
+{
+ int x, y;
+ static unsigned char pix[16][16][4];
+
+ if (cls.state == ca_dedicated)
+ return NULL;
+
+ // this makes a light grey/dark grey checkerboard texture
+ if (!pix[0][0][3])
+ {
+ for (y = 0; y < 16; y++)
+ {
+ for (x = 0; x < 16; x++)
+ {
+ if ((y < 8) ^ (x < 8))
+ {
+ pix[y][x][0] = 128;
+ pix[y][x][1] = 128;
+ pix[y][x][2] = 128;
+ pix[y][x][3] = 255;
+ }
+ else
+ {
+ pix[y][x][0] = 64;
+ pix[y][x][1] = 64;
+ pix[y][x][2] = 64;
+ pix[y][x][3] = 255;
+ }
+ }
+ }
+ }
+
+ return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
+}
+
+skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
+{
+ skinframe_t *skinframe;
+ if (cls.state == ca_dedicated)
+ return NULL;
+ // if already loaded just return it, otherwise make a new skinframe
+ skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
+ if (skinframe->base)
+ return skinframe;
+ textureflags &= ~TEXF_FORCE_RELOAD;
+ skinframe->stain = NULL;
+ skinframe->merged = NULL;
+ skinframe->base = NULL;
+ skinframe->pants = NULL;
+ skinframe->shirt = NULL;
+ skinframe->nmap = NULL;
+ skinframe->gloss = NULL;
+ skinframe->glow = NULL;
+ skinframe->fog = NULL;
+ skinframe->reflect = NULL;
+ skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
+ // if no data was provided, then clearly the caller wanted to get a blank skinframe
+ if (!tex)
+ return NULL;
+ if (developer_loading.integer)
+ Con_Printf("loading 32bit skin \"%s\"\n", name);
+ skinframe->base = skinframe->merged = tex;
+ Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
+ return skinframe;
+}
+
//static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
typedef struct suffixinfo_s
{
*outheight = (int)ceil(height * scale);
}
-void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
+void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
{
const float *customclipplane = NULL;
float plane[4];
- int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
+ int /*rtwidth,*/ rtheight;
if (r_refdef.view.useclipplane && allowwaterclippingplane)
{
- // LordHavoc: couldn't figure out how to make this approach the
+ // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
}
- //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
- rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
+ //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
+ rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
- R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
if (!r_refdef.view.useperspective)
- R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
+ R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
else if (vid.stencil && r_useinfinitefarclip.integer)
- R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
+ R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
else
- R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
- R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
+ R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
+ R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
R_SetViewport(&r_refdef.view.viewport);
if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
{
}
}
-void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
+void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
{
r_viewport_t viewport;
CHECKGLERROR
// GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
- R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
- R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
+ R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
+ R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
R_SetViewport(&viewport);
GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
GL_Color(1, 1, 1, 1);
CHECKGLERROR
}
-void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
+void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
{
DrawQ_Finish();
- R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
+ R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
}
-void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
+void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
{
DrawQ_Finish();
- R_SetupView(true, fbo, depthtexture, colortexture);
+ R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
GL_Color(1, 1, 1, 1);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
}
-void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
-void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
-
static void R_Water_StartFrame(void)
{
int i;
extern cvar_t r_drawparticles;
extern cvar_t r_drawdecals;
-static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
+static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
{
int myscissor[4];
r_refdef_view_t originalview;
r_refdef_view_t myview;
int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
+ int waterx, watery;
r_waterstate_waterplane_t *p;
vec3_t visorigin;
qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
char vabuf[1024];
originalview = r_refdef.view;
+ waterx = usewaterfbo ? 0 : x;
+ watery = usewaterfbo ? 0 : y;
// lowquality hack, temporarily shut down some cvars and restore afterwards
qualityreduction = r_water_lowquality.integer;
// render views
r_refdef.view = originalview;
r_refdef.view.showdebug = false;
+ r_refdef.view.x = waterx;
+ r_refdef.view.y = watery;
r_refdef.view.width = r_fb.water.waterwidth;
r_refdef.view.height = r_fb.water.waterheight;
r_refdef.view.useclipplane = true;
r_refdef.view = myview;
if(r_water_scissormode.integer)
{
- R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
+ R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
}
}
r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
- R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
+ R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
+ if (p->fbo_reflection)
+ GL_ScissorTest(false);
R_ClearScreen(r_refdef.fogenabled);
+ if (p->fbo_reflection)
+ GL_ScissorTest(true);
if(r_water_scissormode.integer & 2)
R_View_UpdateWithScissor(myscissor);
else
R_AnimCache_CacheVisibleEntities();
if(r_water_scissormode.integer & 1)
GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
- R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
+ R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
if (!p->fbo_reflection)
- R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
r_fb.water.hideplayer = false;
}
r_refdef.view = myview;
if(r_water_scissormode.integer)
{
- R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
+ R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
}
PlaneClassify(&r_refdef.view.clipplane);
- R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
+ R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
+ if (p->fbo_refraction)
+ GL_ScissorTest(false);
R_ClearScreen(r_refdef.fogenabled);
+ if (p->fbo_refraction)
+ GL_ScissorTest(true);
if(r_water_scissormode.integer & 2)
R_View_UpdateWithScissor(myscissor);
else
R_AnimCache_CacheVisibleEntities();
if(r_water_scissormode.integer & 1)
GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
- R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
+ R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
if (!p->fbo_refraction)
- R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
r_fb.water.hideplayer = false;
}
else if (p->materialflags & MATERIALFLAG_CAMERA)
VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
+ r_refdef.view.x = waterx;
+ r_refdef.view.y = watery;
r_refdef.view.width = r_fb.water.camerawidth;
r_refdef.view.height = r_fb.water.cameraheight;
r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
r_fb.water.hideplayer = false;
- R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
+ R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera, waterx, watery, r_fb.water.camerawidth, r_fb.water.cameraheight);
+ if (p->fbo_camera)
+ GL_ScissorTest(false);
R_ClearScreen(r_refdef.fogenabled);
+ if (p->fbo_camera)
+ GL_ScissorTest(true);
R_View_Update();
R_AnimCache_CacheVisibleEntities();
- R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
+ R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera, waterx, watery, r_fb.water.camerawidth, r_fb.water.cameraheight);
if (!p->fbo_camera)
- R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ R_Mesh_CopyToTexture(p->texture_camera, 0, 0, waterx, watery, r_fb.water.camerawidth, r_fb.water.cameraheight);
r_fb.water.hideplayer = false;
}
if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
r_fb.water.renderingscene = false;
r_refdef.view = originalview;
- R_ResetViewRendering3D(fbo, depthtexture, colortexture);
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture, x, y, width, height);
if (!r_fb.water.depthtexture)
R_ClearScreen(r_refdef.fogenabled);
R_View_Update();
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
+ return; // don't bother
case RENDERPATH_GLES2:
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
Cvar_SetValueQuick(&r_damageblur, 0);
}
- if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
+ if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
&& !r_bloom.integer
&& (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
&& !useviewfbo
// set up a texcoord array for the full resolution screen image
// (we have to keep this around to copy back during final render)
r_fb.screentexcoord2f[0] = 0;
- r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
+ r_fb.screentexcoord2f[1] = 1.0f;
r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
- r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
+ r_fb.screentexcoord2f[3] = 1.0f;
r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
- r_fb.screentexcoord2f[5] = 0;
+ r_fb.screentexcoord2f[5] = 1.0f - (float)viewheight / (float)r_fb.screentextureheight;
r_fb.screentexcoord2f[6] = 0;
- r_fb.screentexcoord2f[7] = 0;
-
- if(r_fb.fbo)
- {
- for (i = 1;i < 8;i += 2)
- {
- r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
- }
- }
+ r_fb.screentexcoord2f[7] = 1.0f - (float)viewheight / (float)r_fb.screentextureheight;
// set up a texcoord array for the reduced resolution bloom image
// (which will be additive blended over the screen image)
break;
}
- R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
+ R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_fb.fbo ? 0 : r_refdef.view.x, r_fb.fbo ? 0 : r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
if (r_fb.fbo)
r_refdef.view.clear = true;
}
}
-static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
+static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
{
dpuint64 permutation;
float uservecs[4][4];
permutation =
(r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
| (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
- | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
+ | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
| (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
| ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
// apply the blur
- R_ResetViewRendering2D(fbo, depthtexture, colortexture);
+ R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
{
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
{
// apply a color tint to the whole view
- R_ResetViewRendering2D(0, NULL, NULL);
+ R_ResetViewRendering2D(0, NULL, NULL, viewx, viewy, viewwidth, viewheight);
GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
R_SetupShader_Generic_NoTexture(false, true);
if (r_glsl_postprocess_uservec4_enable.integer)
sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
- R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
+ // render to the screen fbo
+ R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
GL_Color(1, 1, 1, 1);
GL_BlendFunc(GL_ONE, GL_ZERO);
if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
{
// apply a color tint to the whole view
- R_ResetViewRendering2D(0, NULL, NULL);
+ R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
R_SetupShader_Generic_NoTexture(false, true);
case RENDERPATH_D3D11:
case RENDERPATH_SOFT:
case RENDERPATH_GLES2:
- if(v_glslgamma.integer && !vid_gammatables_trivial)
+ if(!vid_gammatables_trivial)
{
if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
{
*/
int dpsoftrast_test;
extern cvar_t r_shadow_bouncegrid;
-void R_RenderView(void)
+void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
{
matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
- int fbo;
- rtexture_t *depthtexture;
- rtexture_t *colortexture;
+ int viewfbo = 0;
+ rtexture_t *viewdepthtexture = NULL;
+ rtexture_t *viewcolortexture = NULL;
+ int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
dpsoftrast_test = r_test.integer;
r_fb.water.enabled = false;
r_fb.water.numwaterplanes = 0;
- R_RenderScene(0, NULL, NULL);
+ R_RenderScene(fbo, depthtexture, colortexture, x, y, width, height);
r_refdef.view.matrix = originalmatrix;
R_Shadow_UpdateWorldLightSelection();
+ // this will set up r_fb.fbo
R_Bloom_StartFrame();
// apply bloom brightness offset
if(r_fb.bloomtexture[0])
r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
- R_Water_StartFrame();
+ // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
+ if (r_fb.fbo)
+ {
+ viewfbo = r_fb.fbo;
+ viewdepthtexture = r_fb.depthtexture;
+ viewcolortexture = r_fb.colortexture;
+ viewx = 0;
+ viewy = 0;
+ viewwidth = width;
+ viewheight = height;
+ }
- // now we probably have an fbo to render into
- fbo = r_fb.fbo;
- depthtexture = r_fb.depthtexture;
- colortexture = r_fb.colortexture;
+ R_Water_StartFrame();
CHECKGLERROR
if (r_timereport_active)
R_TimeReport("viewsetup");
- R_ResetViewRendering3D(fbo, depthtexture, colortexture);
+ R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
+
+ // clear the whole fbo every frame - otherwise the driver will consider
+ // it to be an inter-frame texture and stall in multi-gpu configurations
+ if (viewfbo)
+ GL_ScissorTest(false);
+ R_ClearScreen(r_refdef.fogenabled);
+ if (r_timereport_active)
+ R_TimeReport("viewclear");
- if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
- {
- R_ClearScreen(r_refdef.fogenabled);
- if (r_timereport_active)
- R_TimeReport("viewclear");
- }
r_refdef.view.clear = true;
r_refdef.view.showdebug = true;
r_fb.water.numwaterplanes = 0;
if (r_fb.water.enabled)
- R_RenderWaterPlanes(fbo, depthtexture, colortexture);
-
- R_RenderScene(fbo, depthtexture, colortexture);
+ R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
+
+ // for the actual view render we use scissoring a fair amount, so scissor
+ // test needs to be on
+ if (viewfbo)
+ GL_ScissorTest(true);
+ GL_Scissor(viewx, viewy, viewwidth, viewheight);
+ R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
r_fb.water.numwaterplanes = 0;
- R_BlendView(fbo, depthtexture, colortexture);
+ // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
+ GL_ScissorTest(false);
+
+ // R_BlendView will render the viewfbo image into the provided fbo using
+ // the postprocess shader (including gamma correction and sRGB)
+ R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
if (r_timereport_active)
R_TimeReport("blendview");
- GL_Scissor(0, 0, vid.width, vid.height);
- GL_ScissorTest(false);
-
r_refdef.view.matrix = originalmatrix;
CHECKGLERROR
}
-void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
+void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
{
if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
{
if (r_fb.water.numwaterplanes)
{
- R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
+ R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
if (r_timereport_active)
R_TimeReport("waterscenes");
}
extern cvar_t cl_decals_newsystem;
extern qboolean r_shadow_usingdeferredprepass;
extern int r_shadow_shadowmapatlas_modelshadows_size;
-void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
+void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
{
qboolean shadowmapping = false;
if (skyrendermasked && skyrenderlater)
{
// we have to force off the water clipping plane while rendering sky
- R_SetupView(false, fbo, depthtexture, colortexture);
+ R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
R_Sky();
- R_SetupView(true, fbo, depthtexture, colortexture);
+ R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
if (r_timereport_active)
R_TimeReport("sky");
}
}
+ // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
+ r_shadow_viewfbo = viewfbo;
+ r_shadow_viewdepthtexture = viewdepthtexture;
+ r_shadow_viewcolortexture = viewcolortexture;
+ r_shadow_viewx = viewx;
+ r_shadow_viewy = viewy;
+ r_shadow_viewwidth = viewwidth;
+ r_shadow_viewheight = viewheight;
+
R_Shadow_PrepareModelShadows();
- R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
+ R_Shadow_PrepareLights();
if (r_timereport_active)
R_TimeReport("preparelights");
if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
{
- R_ResetViewRendering3D(fbo, depthtexture, colortexture);
+ R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
R_Shadow_DrawModelShadows();
- R_ResetViewRendering3D(fbo, depthtexture, colortexture);
+ R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
// don't let sound skip if going slow
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
{
- R_ResetViewRendering3D(fbo, depthtexture, colortexture);
+ R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
R_Shadow_DrawModelShadows();
- R_ResetViewRendering3D(fbo, depthtexture, colortexture);
+ R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
// don't let sound skip if going slow
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
R_TimeReport("explosions");
}
- if (cl.csqc_loaded)
- VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
-
if (r_refdef.view.showdebug)
{
if (cl_locs_show.integer)
t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
{
- // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale
- t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT;
+ // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
+ t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
for (q = 0; q < 3; q++)
{
t->render_glowmod[q] = rsurface.entity->glowmod[q];
for (q = 0; q < 3; q++)
{
t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
- t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale;
- t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
+ t->render_modellight_lightdir[q] = q == 2;
+ t->render_modellight_ambient[q] = 0;
t->render_modellight_diffuse[q] = 0;
t->render_modellight_specular[q] = 0;
t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
}
}
+ if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
+ {
+ // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
+ // attribute, we punt it to the lightmap path and hope for the best,
+ // but lighting doesn't work.
+ //
+ // FIXME: this is fine for effects but CSQC polygons should be subject
+ // to lighting.
+ t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
+ for (q = 0; q < 3; q++)
+ {
+ t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
+ t->render_modellight_lightdir[q] = q == 2;
+ t->render_modellight_ambient[q] = 0;
+ t->render_modellight_diffuse[q] = 0;
+ t->render_modellight_specular[q] = 0;
+ t->render_lightmap_ambient[q] = 0;
+ t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
+ t->render_lightmap_specular[q] = 0;
+ t->render_rtlight_diffuse[q] = 0;
+ t->render_rtlight_specular[q] = 0;
+ }
+ }
+
for (q = 0; q < 3; q++)
{
t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
{
+ int i, j;
// transparent sky would be ridiculous
if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
return;
skyrenderlater = true;
RSurf_SetupDepthAndCulling();
GL_DepthMask(true);
- // LordHavoc: HalfLife maps have freaky skypolys so don't use
+
+ // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
+ if (r_sky_scissor.integer)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
+ for (i = 0; i < texturenumsurfaces; i++)
+ {
+ const msurface_t *surf = texturesurfacelist[i];
+ const float *v;
+ float p[3];
+ float mins[3], maxs[3];
+ int scissor[4];
+ for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
+ {
+ Matrix4x4_Transform(&rsurface.matrix, v, p);
+ if (j > 0)
+ {
+ if (mins[0] > p[0]) mins[0] = p[0];
+ if (mins[1] > p[1]) mins[1] = p[1];
+ if (mins[2] > p[2]) mins[2] = p[2];
+ if (maxs[0] < p[0]) maxs[0] = p[0];
+ if (maxs[1] < p[1]) maxs[1] = p[1];
+ if (maxs[2] < p[2]) maxs[2] = p[2];
+ }
+ else
+ {
+ VectorCopy(p, mins);
+ VectorCopy(p, maxs);
+ }
+ }
+ if (!R_ScissorForBBox(mins, maxs, scissor))
+ {
+ if (skyscissor[2])
+ {
+ if (skyscissor[0] > scissor[0])
+ {
+ skyscissor[2] += skyscissor[0] - scissor[0];
+ skyscissor[0] = scissor[0];
+ }
+ if (skyscissor[1] > scissor[1])
+ {
+ skyscissor[3] += skyscissor[1] - scissor[1];
+ skyscissor[1] = scissor[1];
+ }
+ if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
+ skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
+ if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
+ skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
+ }
+ else
+ Vector4Copy(scissor, skyscissor);
+ }
+ }
+ }
+
+ // LadyHavoc: HalfLife maps have freaky skypolys so don't use
// skymasking on them, and Quake3 never did sky masking (unlike
// software Quake and software Quake2), so disable the sky masking
// in Quake3 maps as it causes problems with q3map2 sky tricks,
// and skymasking also looks very bad when noclipping outside the
// level, so don't use it then either.
- if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
+ if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
{
R_Mesh_ResetTextureState();
if (skyrendermasked)
{
R_SetupShader_DepthOrShadow(false, false, false);
// depth-only (masking)
- GL_ColorMask(0,0,0,0);
+ 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);