]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_backend.c
made r_showtris transparent (quite faint actually), color coded different types of...
[xonotic/darkplaces.git] / gl_backend.c
index cb450bde6c68950a1a817ce2d2e6f92af2241031..f4ccc39f4f7d6d8d0d1c8e847eead00014912613 100644 (file)
@@ -2,6 +2,7 @@
 #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"};
@@ -72,9 +73,6 @@ int c_meshs, c_meshelements;
 
 void SCR_ScreenShot_f (void);
 
-// these are externally accessible
-int r_lightmapscalebit;
-
 static matrix4x4_t backend_viewmatrix;
 static matrix4x4_t backend_modelmatrix;
 static matrix4x4_t backend_modelviewmatrix;
@@ -189,6 +187,11 @@ static void gl_backend_newmap(void)
 {
 }
 
+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;
@@ -213,17 +216,13 @@ void gl_backend_init(void)
        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)
@@ -232,14 +231,17 @@ 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));
 }
 
@@ -284,8 +286,8 @@ void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, dou
        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;
@@ -343,6 +345,7 @@ static struct
        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;
@@ -425,6 +428,7 @@ void GL_Backend_ResetState(void)
        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;
@@ -433,6 +437,7 @@ void GL_Backend_ResetState(void)
 
        CHECKGLERROR
 
+       qglColorMask(1, 1, 1, 1);
        qglEnable(GL_CULL_FACE);CHECKGLERROR
        qglCullFace(GL_FRONT);CHECKGLERROR
        qglEnable(GL_DEPTH_TEST);CHECKGLERROR
@@ -482,6 +487,8 @@ void GL_BlendFunc(int blendfunc1, int blendfunc2)
 {
        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)
                {
@@ -517,6 +524,8 @@ void GL_DepthMask(int state)
 {
        if (gl_state.depthmask != state)
        {
+               if (r_showtrispass)
+                       return;
                qglDepthMask(gl_state.depthmask = state);CHECKGLERROR
        }
 }
@@ -525,6 +534,8 @@ void GL_DepthTest(int state)
 {
        if (gl_state.depthtest != state)
        {
+               if (r_showtrispass)
+                       return;
                gl_state.depthtest = state;
                if (gl_state.depthtest)
                {
@@ -537,6 +548,18 @@ void GL_DepthTest(int state)
        }
 }
 
+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)
@@ -552,6 +575,8 @@ void GL_ColorPointer(const float *p)
 {
        if (gl_state.pointer_color != p)
        {
+               if (r_showtrispass)
+                       return;
                CHECKGLERROR
                if (!gl_state.pointer_color)
                {
@@ -573,6 +598,8 @@ void GL_Color(float cr, float cg, float cb, float ca)
 {
        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;
@@ -584,6 +611,16 @@ void GL_Color(float cr, float cg, float cb, float ca)
        }
 }
 
+void GL_ShowTrisColor(float cr, float cg, float cb, float ca)
+{
+       if (!r_showtrispass)
+               return;
+       r_showtrispass = false;
+       GL_Color(cr,cg,cb,ca);
+       r_showtrispass = true;
+}
+
+
 void GL_LockArrays(int first, int count)
 {
        if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
@@ -609,7 +646,7 @@ void GL_LockArrays(int first, int count)
 void GL_Scissor (int x, int y, int width, int height)
 {
        CHECKGLERROR
-       qglScissor(x, vid.realheight - (y + height),width,height);      
+       qglScissor(x, vid.realheight - (y + height),width,height);
        CHECKGLERROR
 }
 
@@ -617,7 +654,7 @@ void GL_ScissorTest(int state)
 {
        if(gl_state.scissortest == state)
                return;
-       
+
        CHECKGLERROR
        if((gl_state.scissortest = state))
                qglEnable(GL_SCISSOR_TEST);
@@ -626,6 +663,13 @@ void GL_ScissorTest(int state)
        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;
@@ -633,8 +677,8 @@ void GL_TransformToScreen(const vec4_t in, vec4_t out)
        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;
 }
 
@@ -670,6 +714,11 @@ void R_Mesh_Draw(int numverts, int numtriangles, const int *elements)
                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
@@ -795,9 +844,9 @@ void R_Mesh_Finish(void)
 {
        int i;
        BACKENDACTIVECHECK
-               CHECKGLERROR
+       CHECKGLERROR
        GL_LockArrays(0, 0);
-               CHECKGLERROR
+       CHECKGLERROR
 
        for (i = backendunits - 1;i >= 0;i--)
        {
@@ -870,6 +919,8 @@ void R_Mesh_State_Texture(const rmeshstate_t *m)
                GL_SetupTextureState();
        }
 
+       if (r_showtrispass)
+               return;
        for (i = 0, unit = gl_state.units;i < backendunits;i++, unit++)
        {
                if (unit->t1d != m->tex1d[i])
@@ -939,7 +990,7 @@ void R_Mesh_State_Texture(const rmeshstate_t *m)
                {
                        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
                        }
@@ -1003,6 +1054,19 @@ void R_Mesh_State_Texture(const rmeshstate_t *m)
        }
 }
 
+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
+}
+
 /*
 ==============================================================================
 
@@ -1049,7 +1113,7 @@ void R_ClearScreen(void)
                        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)
                {
@@ -1062,6 +1126,17 @@ void R_ClearScreen(void)
        }
 }
 
+/*
+====================
+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
@@ -1074,11 +1149,14 @@ void SCR_UpdateScreen (void)
 {
        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)
@@ -1087,11 +1165,7 @@ void SCR_UpdateScreen (void)
        if (gl_combine.integer && (!gl_combine_extension || r_textureunits.integer < 2))
                Cvar_SetValueQuick(&gl_combine, 0);
 
-       // lightmaps only
-       r_lightmapscalebit = 0;
-       if (gl_combine.integer && r_textureunits.integer > 1)
-               r_lightmapscalebit += 2;
-
+showtris:
        R_TimeReport("setup");
 
        R_ClearScreen();
@@ -1099,11 +1173,95 @@ void SCR_UpdateScreen (void)
        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.integer)
+       {
+               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
@@ -1112,8 +1270,9 @@ void SCR_UpdateScreen (void)
        }
        else
        {
-               VID_Finish ();
-
+               R_Mesh_Finish();
+               R_TimeReport("meshfinish");
+               VID_Finish();
                R_TimeReport("finish");
        }
 }