#include "quakedef.h"
#include "image.h"
#include "jpeg.h"
+#include "cl_collision.h"
cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1"};
cvar_t gl_mesh_testarrayelement = {0, "gl_mesh_testarrayelement", "0"};
void SCR_ScreenShot_f (void);
-// these are externally accessible
-int r_lightmapscalebit;
-float r_colorscale;
-
static matrix4x4_t backend_viewmatrix;
static matrix4x4_t backend_modelmatrix;
static matrix4x4_t backend_modelviewmatrix;
{
}
+cvar_t scr_zoomwindow = {CVAR_SAVE, "scr_zoomwindow", "0"};
+cvar_t scr_zoomwindow_viewsizex = {CVAR_SAVE, "scr_zoomwindow_viewsizex", "20"};
+cvar_t scr_zoomwindow_viewsizey = {CVAR_SAVE, "scr_zoomwindow_viewsizey", "20"};
+cvar_t scr_zoomwindow_fov = {CVAR_SAVE, "scr_zoomwindow_fov", "20"};
+
void gl_backend_init(void)
{
int i;
Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
Cvar_RegisterVariable(&gl_mesh_testarrayelement);
Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
- R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
-}
-void GL_SetupView_ViewPort (int x, int y, int width, int height)
-{
- if (!r_render.integer)
- return;
+ Cvar_RegisterVariable(&scr_zoomwindow);
+ Cvar_RegisterVariable(&scr_zoomwindow_viewsizex);
+ Cvar_RegisterVariable(&scr_zoomwindow_viewsizey);
+ Cvar_RegisterVariable(&scr_zoomwindow_fov);
- // y is weird beause OpenGL is bottom to top, we use top to bottom
- qglViewport(x, vid.realheight - (y + height), width, height);
- CHECKGLERROR
+ R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
}
void GL_SetupView_Orientation_Identity (void)
memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
}
-void GL_SetupView_Orientation_FromEntity (vec3_t origin, vec3_t angles)
+void GL_SetupView_Orientation_FromEntity(matrix4x4_t *matrix)
{
- Matrix4x4_CreateRotate(&backend_viewmatrix, -90, 1, 0, 0);
- Matrix4x4_ConcatRotate(&backend_viewmatrix, 90, 0, 0, 1);
- Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
- Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
- Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
- Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
+ matrix4x4_t tempmatrix, basematrix;
+ Matrix4x4_Invert_Simple(&tempmatrix, matrix);
+ Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
+ Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
+ Matrix4x4_Concat(&backend_viewmatrix, &basematrix, &tempmatrix);
+ //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
+ //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
+ //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
+ //Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
}
m[ 7] = 0;
m[ 8] = 0;
m[ 9] = 0;
- m[10] = -1 * nudge;
- m[11] = -1 * nudge;
+ m[10] = -nudge;
+ m[11] = -1;
m[12] = 0;
m[13] = 0;
m[14] = -2 * zNear * nudge;
int blendfunc2;
int blend;
GLboolean depthmask;
+ int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
int depthtest;
+ int scissortest;
int unit;
int clientunit;
gltextureunit_t units[MAX_TEXTUREUNITS];
gl_state.blendfunc2 = GL_ZERO;
gl_state.blend = false;
gl_state.depthmask = GL_TRUE;
+ gl_state.colormask = 15;
gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
gl_state.lockrange_first = 0;
gl_state.lockrange_count = 0;
CHECKGLERROR
+ qglColorMask(1, 1, 1, 1);
qglEnable(GL_CULL_FACE);CHECKGLERROR
qglCullFace(GL_FRONT);CHECKGLERROR
qglEnable(GL_DEPTH_TEST);CHECKGLERROR
{
if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
{
+ if (r_showtrispass)
+ return;
qglBlendFunc(gl_state.blendfunc1 = blendfunc1, gl_state.blendfunc2 = blendfunc2);CHECKGLERROR
if (gl_state.blendfunc2 == GL_ZERO)
{
{
if (gl_state.depthmask != state)
{
+ if (r_showtrispass)
+ return;
qglDepthMask(gl_state.depthmask = state);CHECKGLERROR
}
}
{
if (gl_state.depthtest != state)
{
+ if (r_showtrispass)
+ return;
gl_state.depthtest = state;
if (gl_state.depthtest)
{
}
}
+void GL_ColorMask(int r, int g, int b, int a)
+{
+ int state = r*8 + g*4 + b*2 + a*1;
+ if (gl_state.colormask != state)
+ {
+ if (r_showtrispass)
+ return;
+ gl_state.colormask = state;
+ qglColorMask(r, g, b, a);CHECKGLERROR
+ }
+}
+
void GL_VertexPointer(const float *p)
{
if (gl_state.pointer_vertex != p)
{
if (gl_state.pointer_color != p)
{
+ if (r_showtrispass)
+ return;
CHECKGLERROR
if (!gl_state.pointer_color)
{
{
if (gl_state.pointer_color || gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca)
{
+ if (r_showtrispass)
+ return;
GL_ColorPointer(NULL);
gl_state.color4f[0] = cr;
gl_state.color4f[1] = cg;
}
}
+void GL_ShowTrisColor(float cr, float cg, float cb, float ca)
+{
+ if (!r_showtrispass)
+ return;
+ r_showtrispass = false;
+ GL_Color(cr * r_showtris.value, cg * r_showtris.value, cb * r_showtris.value, ca);
+ r_showtrispass = true;
+}
+
+
void GL_LockArrays(int first, int count)
{
if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
}
}
+void GL_Scissor (int x, int y, int width, int height)
+{
+ CHECKGLERROR
+ qglScissor(x, vid.realheight - (y + height),width,height);
+ CHECKGLERROR
+}
+
+void GL_ScissorTest(int state)
+{
+ if(gl_state.scissortest == state)
+ return;
+
+ CHECKGLERROR
+ if((gl_state.scissortest = state))
+ qglEnable(GL_SCISSOR_TEST);
+ else
+ qglDisable(GL_SCISSOR_TEST);
+ CHECKGLERROR
+}
+
+void GL_Clear(int mask)
+{
+ if (r_showtrispass)
+ return;
+ qglClear(mask);CHECKGLERROR
+}
+
void GL_TransformToScreen(const vec4_t in, vec4_t out)
{
vec4_t temp;
Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
iw = 1.0f / out[3];
- out[0] = r_refdef.x + (out[0] * iw + 1.0f) * r_refdef.width * 0.5f;
- out[1] = r_refdef.y + (out[1] * iw + 1.0f) * r_refdef.height * 0.5f;
+ out[0] = r_view_x + (out[0] * iw + 1.0f) * r_view_width * 0.5f;
+ out[1] = r_view_y + (out[1] * iw + 1.0f) * r_view_height * 0.5f;
out[2] = out[2] * iw;
}
Con_Printf("R_Mesh_Draw(%d, %d, %08p);\n", numverts, numtriangles, elements);
return;
}
+ if (r_showtrispass)
+ {
+ R_Mesh_Draw_ShowTris(numverts, numtriangles, elements);
+ return;
+ }
c_meshs++;
c_meshelements += numelements;
CHECKGLERROR
{
int i;
BACKENDACTIVECHECK
- CHECKGLERROR
+ CHECKGLERROR
GL_LockArrays(0, 0);
- CHECKGLERROR
+ CHECKGLERROR
for (i = backendunits - 1;i >= 0;i--)
{
GL_SetupTextureState();
}
+ if (r_showtrispass)
+ return;
for (i = 0, unit = gl_state.units;i < backendunits;i++, unit++)
{
if (unit->t1d != m->tex1d[i])
{
GL_ActiveTexture(i);
unit->combinergb = combinergb;
- if (gl_combine.integer)
+ if (gl_combine.integer)
{
qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
}
}
}
+void R_Mesh_Draw_ShowTris(int numverts, int numtriangles, const int *elements)
+{
+ qglBegin(GL_LINES);
+ for (;numtriangles;numtriangles--, elements += 3)
+ {
+ qglArrayElement(elements[0]);qglArrayElement(elements[1]);
+ qglArrayElement(elements[1]);qglArrayElement(elements[2]);
+ qglArrayElement(elements[2]);qglArrayElement(elements[0]);
+ }
+ qglEnd();
+ CHECKGLERROR
+}
+
/*
==============================================================================
qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height, qboolean jpeg)
{
qboolean ret;
- int i, j;
qbyte *buffer;
if (!r_render.integer)
qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
CHECKGLERROR
- // LordHavoc: compensate for v_overbrightbits when using hardware gamma
- if (v_hwgamma.integer)
- {
- for (i = 0;i < width * height * 3;i++)
- {
- j = buffer[i] << v_overbrightbits.integer;
- buffer[i] = (qbyte) (bound(0, j, 255));
- }
- }
-
if (jpeg)
ret = JPEG_SaveImage_preflipped (filename, width, height, buffer);
else
qglClearStencil(128);CHECKGLERROR
}
// clear the screen
- qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));CHECKGLERROR
+ GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));
// set dithering mode
if (gl_dither.integer)
{
}
}
+/*
+====================
+CalcFov
+====================
+*/
+float CalcFov (float fov_x, float width, float height)
+{
+ // calculate vision size and alter by aspect, then convert back to angle
+ return atan (height / (width / tan(fov_x/360*M_PI))) * 360 / M_PI;
+}
+
/*
==================
SCR_UpdateScreen
{
if (gl_delayfinish.integer)
{
- VID_Finish ();
-
+ R_Mesh_Finish();
+ R_TimeReport("meshfinish");
+ VID_Finish();
R_TimeReport("finish");
}
+ R_Mesh_Start();
+
if (r_textureunits.integer > gl_textureunits)
Cvar_SetValueQuick(&r_textureunits, gl_textureunits);
if (r_textureunits.integer < 1)
if (gl_combine.integer && (!gl_combine_extension || r_textureunits.integer < 2))
Cvar_SetValueQuick(&gl_combine, 0);
- // lighting scale
- r_colorscale = 1.0f / (float) (1 << v_overbrightbits.integer);
-
- // lightmaps only
- r_lightmapscalebit = v_overbrightbits.integer;
- if (gl_combine.integer && r_textureunits.integer > 1)
- r_lightmapscalebit += 2;
-
+showtris:
R_TimeReport("setup");
R_ClearScreen();
R_TimeReport("clear");
if (scr_conlines < vid.conheight && cls.signon == SIGNONS)
+ {
+ float size;
+ int contents;
+
+ // bound viewsize
+ if (scr_viewsize.value < 30)
+ Cvar_Set ("viewsize","30");
+ if (scr_viewsize.value > 120)
+ Cvar_Set ("viewsize","120");
+
+ // bound field of view
+ if (scr_fov.value < 1)
+ Cvar_Set ("fov","1");
+ if (scr_fov.value > 170)
+ Cvar_Set ("fov","170");
+
+ // intermission is always full screen
+ if (cl.intermission)
+ {
+ size = 1;
+ sb_lines = 0;
+ }
+ else
+ {
+ if (scr_viewsize.value >= 120)
+ sb_lines = 0; // no status bar at all
+ else if (scr_viewsize.value >= 110)
+ sb_lines = 24; // no inventory
+ else
+ sb_lines = 24+16+8;
+ size = scr_viewsize.value * (1.0 / 100.0);
+ size = min(size, 1);
+ }
+
+ r_refdef.width = vid.realwidth * size;
+ r_refdef.height = vid.realheight * size;
+ r_refdef.x = (vid.realwidth - r_refdef.width)/2;
+ r_refdef.y = (vid.realheight - r_refdef.height)/2;
+
+ // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
+ r_refdef.fov_x = scr_fov.value * cl.viewzoom;
+ r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height);
+
+ if (cl.worldmodel)
+ {
+ Mod_CheckLoaded(cl.worldmodel);
+ contents = CL_PointSuperContents(r_vieworigin);
+ if (contents & SUPERCONTENTS_LIQUIDSMASK)
+ {
+ r_refdef.fov_x *= (sin(cl.time * 4.7) * 0.015 + 0.985);
+ r_refdef.fov_y *= (sin(cl.time * 3.0) * 0.015 + 0.985);
+ }
+ }
+
R_RenderView();
+ if (scr_zoomwindow.integer)
+ {
+ float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
+ float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
+ r_refdef.width = vid.realwidth * sizex;
+ r_refdef.height = vid.realheight * sizey;
+ r_refdef.x = (vid.realwidth - r_refdef.width)/2;
+ r_refdef.y = 0;
+ r_refdef.fov_x = scr_zoomwindow_fov.value;
+ r_refdef.fov_y = CalcFov(r_refdef.fov_x, r_refdef.width, r_refdef.height);
+
+ R_RenderView();
+ }
+ }
+
// draw 2D stuff
R_DrawQueue();
+ if (r_showtrispass)
+ r_showtrispass = false;
+ else if (r_showtris.value > 0)
+ {
+ rmeshstate_t m;
+ GL_BlendFunc(GL_ONE, GL_ONE);
+ GL_DepthTest(GL_FALSE);
+ GL_DepthMask(GL_FALSE);
+ memset(&m, 0, sizeof(m));
+ R_Mesh_State_Texture(&m);
+ r_showtrispass = true;
+ GL_ShowTrisColor(0.2,0.2,0.2,1);
+ goto showtris;
+ }
+
if (gl_delayfinish.integer)
{
// tell driver to commit it's partially full geometry queue to the rendering queue
}
else
{
- VID_Finish ();
-
+ R_Mesh_Finish();
+ R_TimeReport("meshfinish");
+ VID_Finish();
R_TimeReport("finish");
}
}