]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
fix bugs with crosshair_static 0 mode when the player is an EF_NODRAW entity
[xonotic/darkplaces.git] / gl_rmain.c
index 4b16a4bf16407b981650c8862b79ca076d05f4a9..ac00b38660c94c89fdebdc738fca2f5f86761c3f 100644 (file)
@@ -72,6 +72,7 @@ matrix4x4_t r_view_matrix;
 refdef_t r_refdef;
 
 cvar_t r_showtris = {0, "r_showtris", "0"};
+cvar_t r_shownormals = {0, "r_shownormals", "0"};
 cvar_t r_drawentities = {0, "r_drawentities","1"};
 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
 cvar_t r_speeds = {0, "r_speeds","0"};
@@ -118,6 +119,8 @@ rtexture_t *r_texture_black;
 rtexture_t *r_texture_notexture;
 rtexture_t *r_texture_whitecube;
 rtexture_t *r_texture_normalizationcube;
+rtexture_t *r_texture_fogattenuation;
+rtexture_t *r_texture_fogintensity;
 
 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
 {
@@ -148,6 +151,11 @@ void R_FillColors(float *out, int verts, float r, float g, float b, float a)
 
 vec3_t fogcolor;
 vec_t fogdensity;
+vec_t fogrange;
+vec_t fograngerecip;
+int fogtableindex;
+vec_t fogtabledistmultiplier;
+float fogtable[FOGTABLEWIDTH];
 float fog_density, fog_red, fog_green, fog_blue;
 qboolean fogenabled;
 qboolean oldgl_fogenable;
@@ -182,6 +190,12 @@ void R_UpdateFog(void)
        {
                fogenabled = true;
                fogdensity = -4000.0f / (fog_density * fog_density);
+               // this is the point where the fog reaches 0.9986 alpha, which we
+               // consider a good enough cutoff point for the texture
+               // (0.9986 * 256 == 255.6)
+               fogrange = 400 / fog_density;
+               fograngerecip = 1.0f / fogrange;
+               fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
                // fog color was already set
        }
        else
@@ -205,6 +219,9 @@ void FOG_clear(void)
 // FIXME: move this to client?
 void FOG_registercvars(void)
 {
+       int x;
+       double r, alpha;
+
        if (gamemode == GAME_NEHAHRA)
        {
                Cvar_RegisterVariable (&gl_fogenable);
@@ -215,11 +232,20 @@ void FOG_registercvars(void)
                Cvar_RegisterVariable (&gl_fogstart);
                Cvar_RegisterVariable (&gl_fogend);
        }
+
+       r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
+       for (x = 0;x < FOGTABLEWIDTH;x++)
+       {
+               alpha = exp(r / ((double)x*(double)x));
+               if (x == FOGTABLEWIDTH - 1)
+                       alpha = 1;
+               fogtable[x] = bound(0, alpha, 1);
+       }
 }
 
 static void R_BuildBlankTextures(void)
 {
-       qbyte data[4];
+       unsigned char data[4];
        data[0] = 128; // normal X
        data[1] = 128; // normal Y
        data[2] = 255; // normal Z
@@ -240,7 +266,7 @@ static void R_BuildBlankTextures(void)
 static void R_BuildNoTexture(void)
 {
        int x, y;
-       qbyte pix[16][16][4];
+       unsigned char pix[16][16][4];
        // this makes a light grey/dark grey checkerboard texture
        for (y = 0;y < 16;y++)
        {
@@ -267,7 +293,7 @@ static void R_BuildNoTexture(void)
 
 static void R_BuildWhiteCube(void)
 {
-       qbyte data[6*1*1*4];
+       unsigned char data[6*1*1*4];
        data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
        data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
        data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
@@ -283,7 +309,7 @@ static void R_BuildNormalizationCube(void)
        vec3_t v;
        vec_t s, t, intensity;
 #define NORMSIZE 64
-       qbyte data[6][NORMSIZE][NORMSIZE][4];
+       unsigned char data[6][NORMSIZE][NORMSIZE][4];
        for (side = 0;side < 6;side++)
        {
                for (y = 0;y < NORMSIZE;y++)
@@ -337,6 +363,34 @@ static void R_BuildNormalizationCube(void)
        r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
 }
 
+static void R_BuildFogTexture(void)
+{
+       int x, b;
+       double r, alpha;
+#define FOGWIDTH 64
+       unsigned char data1[FOGWIDTH][4];
+       unsigned char data2[FOGWIDTH][4];
+       r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
+       for (x = 0;x < FOGWIDTH;x++)
+       {
+               alpha = exp(r / ((double)x*(double)x));
+               if (x == FOGWIDTH - 1)
+                       alpha = 1;
+               b = (int)(256.0 * alpha);
+               b = bound(0, b, 255);
+               data1[x][0] = 255 - b;
+               data1[x][1] = 255 - b;
+               data1[x][2] = 255 - b;
+               data1[x][3] = 255;
+               data2[x][0] = b;
+               data2[x][1] = b;
+               data2[x][2] = b;
+               data2[x][3] = 255;
+       }
+       r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
+       r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
+}
+
 void gl_main_start(void)
 {
        r_main_texturepool = R_AllocTexturePool();
@@ -349,6 +403,7 @@ void gl_main_start(void)
                R_BuildWhiteCube();
                R_BuildNormalizationCube();
        }
+       R_BuildFogTexture();
 }
 
 void gl_main_shutdown(void)
@@ -377,7 +432,7 @@ void gl_main_newmap(void)
                if (l >= 0 && !strcmp(entname + l, ".bsp"))
                {
                        strcpy(entname + l, ".ent");
-                       if ((entities = (char *)FS_LoadFile(entname, tempmempool, true)))
+                       if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
                        {
                                CL_ParseEntityLump(entities);
                                Mem_Free(entities);
@@ -395,6 +450,7 @@ void GL_Main_Init(void)
 // FIXME: move this to client?
        FOG_registercvars();
        Cvar_RegisterVariable(&r_showtris);
+       Cvar_RegisterVariable(&r_shownormals);
        Cvar_RegisterVariable(&r_drawentities);
        Cvar_RegisterVariable(&r_drawviewmodel);
        Cvar_RegisterVariable(&r_speeds);
@@ -692,9 +748,21 @@ static void R_SetFrustum(void)
 
 static void R_BlendView(void)
 {
+       int screenwidth, screenheight;
+       qboolean dobloom;
+       qboolean doblend;
        rmeshstate_t m;
 
-       if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
+       // 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_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;
+
+       if (!dobloom && !doblend)
                return;
 
        GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
@@ -706,16 +774,11 @@ static void R_BlendView(void)
        varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
        varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
        varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
-       if (r_bloom.integer && 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)
        {
-               int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
+               int bloomwidth, bloomheight, x, dobloomblend, range;
                float xoffset, yoffset, r;
                renderstats.bloom++;
-               // 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);
                // allocate textures as needed
                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);
@@ -886,7 +949,7 @@ static void R_BlendView(void)
                        renderstats.bloom_drawpixels += r_view_width * r_view_height;
                }
        }
-       if (r_refdef.viewblend[3] >= 0.01f)
+       if (doblend)
        {
                // apply a color tint to the whole view
                memset(&m, 0, sizeof(m));
@@ -1091,8 +1154,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa
        {
                for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
                {
-                       VectorSubtract(v, r_vieworigin, diff);
-                       f2 = exp(fogdensity/DotProduct(diff, diff));
+                       f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
                        f1 = 1 - f2;
                        c[0] = c[0] * f1 + fogcolor[0] * f2;
                        c[1] = c[1] * f1 + fogcolor[1] * f2;
@@ -1143,7 +1205,7 @@ void R_DrawNoModelCallback(const void *calldata1, int calldata2)
 {
        const entity_render_t *ent = (entity_render_t *)calldata1;
        int i;
-       float f1, f2, *c, diff[3];
+       float f1, f2, *c;
        float color4f[6*4];
        rmeshstate_t m;
        R_Mesh_Matrix(&ent->matrix);
@@ -1171,8 +1233,7 @@ void R_DrawNoModelCallback(const void *calldata1, int calldata2)
        {
                memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
                m.pointer_color = color4f;
-               VectorSubtract(ent->origin, r_vieworigin, diff);
-               f2 = exp(fogdensity/DotProduct(diff, diff));
+               f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
                f1 = 1 - f2;
                for (i = 0, c = color4f;i < 6;i++, c += 4)
                {
@@ -1235,16 +1296,14 @@ void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, flo
 
 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
 
-void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
+void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
 {
-       float diff[3];
+       float fog = 0.0f, ifog;
        rmeshstate_t m;
 
        if (fogenabled)
-       {
-               VectorSubtract(origin, r_vieworigin, diff);
-               ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
-       }
+               fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
+       ifog = 1 - fog;
 
        R_Mesh_Matrix(&r_identitymatrix);
        GL_BlendFunc(blendfunc1, blendfunc2);
@@ -1269,8 +1328,16 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depth
        m.pointer_texcoord[0] = spritetexcoord2f;
        m.pointer_vertex = varray_vertex3f;
        R_Mesh_State(&m);
-       GL_Color(cr, cg, cb, ca);
+       GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
        R_Mesh_Draw(0, 4, 2, polygonelements);
+
+       if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
+       {
+               R_Mesh_TexBind(0, R_GetTexture(fogtexture));
+               GL_BlendFunc(blendfunc1, GL_ONE);
+               GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
+               R_Mesh_Draw(0, 4, 2, polygonelements);
+       }
 }
 
 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
@@ -1611,7 +1678,6 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface
        int i;
        float f;
        float *v, *c, *c2;
-       vec3_t diff;
        if (lightmode >= 2)
        {
                // model lighting
@@ -1648,7 +1714,7 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface
                {
                        for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
                        {
-                               const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
+                               const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
                                if (lm)
                                {
                                        float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
@@ -1689,8 +1755,7 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface
                {
                        for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
                        {
-                               VectorSubtract(v, modelorg, diff);
-                               f = 1 - exp(fogdensity/DotProduct(diff, diff));
+                               f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
                                c2[0] = c[0] * f;
                                c2[1] = c[1] * f;
                                c2[2] = c[2] * f;
@@ -1701,8 +1766,7 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface
                {
                        for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
                        {
-                               VectorSubtract(v, modelorg, diff);
-                               f = 1 - exp(fogdensity/DotProduct(diff, diff));
+                               f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
                                c2[0] = f;
                                c2[1] = f;
                                c2[2] = f;
@@ -1726,7 +1790,6 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface
        GL_Color(r, g, b, a);
 }
 
-
 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
 {
        int texturesurfaceindex;
@@ -1943,7 +2006,6 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                {
                                        int i;
-                                       float diff[3];
                                        float f, *v, *c;
                                        surface = texturesurfacelist[texturesurfaceindex];
                                        RSurf_SetVertexPointer(ent, texture, surface, modelorg);
@@ -1952,8 +2014,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                        R_Mesh_ColorPointer(varray_color4f);
                                        for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
                                        {
-                                               VectorSubtract(v, modelorg, diff);
-                                               f = exp(fogdensity/DotProduct(diff, diff));
+                                               f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
                                                c[0] = layercolor[0];
                                                c[1] = layercolor[1];
                                                c[2] = layercolor[2];
@@ -1987,6 +2048,54 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                }
                        }
                }
+               if (r_shownormals.integer && !r_showtrispass)
+               {
+                       int j, k;
+                       float v[3];
+                       GL_DepthTest(true);
+                       GL_DepthMask(texture->currentlayers->depthmask);
+                       GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
+                       memset(&m, 0, sizeof(m));
+                       R_Mesh_State(&m);
+                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                       {
+                               surface = texturesurfacelist[texturesurfaceindex];
+                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                               if (!rsurface_svector3f)
+                               {
+                                       rsurface_svector3f = varray_svector3f;
+                                       rsurface_tvector3f = varray_tvector3f;
+                                       rsurface_normal3f = varray_normal3f;
+                                       Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
+                               }
+                               GL_Color(1, 0, 0, 1);
+                               qglBegin(GL_LINES);
+                               for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
+                               {
+                                       VectorCopy(rsurface_vertex3f + k * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                                       VectorMA(v, 8, rsurface_svector3f + k * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                               }
+                               GL_Color(0, 0, 1, 1);
+                               for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
+                               {
+                                       VectorCopy(rsurface_vertex3f + k * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                                       VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                               }
+                               GL_Color(0, 1, 0, 1);
+                               for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
+                               {
+                                       VectorCopy(rsurface_vertex3f + k * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                                       VectorMA(v, 8, rsurface_normal3f + k * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                               }
+                               qglEnd();
+                       }
+               }
        }
        if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
                qglEnable(GL_CULL_FACE);