From e2f3aafe7b60f54c50f29d0358132034cfb21e07 Mon Sep 17 00:00:00 2001 From: havoc Date: Mon, 3 Dec 2007 10:47:57 +0000 Subject: [PATCH] the light has been defeated by the shadow (r_light moved into r_shadow) overhauled gl_draw.c draw_generate* code and embedded images cleaned up and improved r_editlights light sprite handling git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7756 d7cf8633-e32d-0410-b094-e92efae38249 --- client.h | 3 - darkplaces-dedicated.dsp | 8 - darkplaces-sdl.dsp | 8 - darkplaces.dsp | 8 - gl_draw.c | 343 +++++++++++++++++++++++---------------- gl_rmain.c | 2 - makefile.inc | 1 - palette.c | 14 ++ palette.h | 1 + r_light.c | 165 ------------------- r_light.h | 9 - r_shadow.c | 281 +++++++++++++++++++++++++------- r_shadow.h | 5 +- render.h | 2 - sbar.c | 5 +- 15 files changed, 448 insertions(+), 407 deletions(-) delete mode 100644 r_light.c delete mode 100644 r_light.h diff --git a/client.h b/client.h index 8fe6d94a..2628dce5 100644 --- a/client.h +++ b/client.h @@ -1313,9 +1313,6 @@ void Debug_PolygonEnd(void); extern qboolean sb_showscores; -#define NUMCROSSHAIRS 32 -extern cachepic_t *r_crosshairs[NUMCROSSHAIRS+1]; - float FogPoint_World(const vec3_t p); float FogPoint_Model(const vec3_t p); diff --git a/darkplaces-dedicated.dsp b/darkplaces-dedicated.dsp index c8323cae..28068dd3 100644 --- a/darkplaces-dedicated.dsp +++ b/darkplaces-dedicated.dsp @@ -322,10 +322,6 @@ SOURCE=.\r_lerpanim.c # End Source File # Begin Source File -SOURCE=.\r_light.c -# End Source File -# Begin Source File - SOURCE=.\r_lightning.c # End Source File # Begin Source File @@ -642,10 +638,6 @@ SOURCE=.\r_lerpanim.h # End Source File # Begin Source File -SOURCE=.\r_light.h -# End Source File -# Begin Source File - SOURCE=.\r_modules.h # End Source File # Begin Source File diff --git a/darkplaces-sdl.dsp b/darkplaces-sdl.dsp index 102013be..0aa1f65b 100644 --- a/darkplaces-sdl.dsp +++ b/darkplaces-sdl.dsp @@ -318,10 +318,6 @@ SOURCE=.\r_lerpanim.c # End Source File # Begin Source File -SOURCE=.\r_light.c -# End Source File -# Begin Source File - SOURCE=.\r_lightning.c # End Source File # Begin Source File @@ -662,10 +658,6 @@ SOURCE=.\r_lerpanim.h # End Source File # Begin Source File -SOURCE=.\r_light.h -# End Source File -# Begin Source File - SOURCE=.\r_modules.h # End Source File # Begin Source File diff --git a/darkplaces.dsp b/darkplaces.dsp index 7f279dd9..cb5ce85c 100644 --- a/darkplaces.dsp +++ b/darkplaces.dsp @@ -330,10 +330,6 @@ SOURCE=.\r_lerpanim.c # End Source File # Begin Source File -SOURCE=.\r_light.c -# End Source File -# Begin Source File - SOURCE=.\r_lightning.c # End Source File # Begin Source File @@ -682,10 +678,6 @@ SOURCE=.\r_lerpanim.h # End Source File # Begin Source File -SOURCE=.\r_light.h -# End Source File -# Begin Source File - SOURCE=.\r_modules.h # End Source File # Begin Source File diff --git a/gl_draw.c b/gl_draw.c index cfdb61e3..a6b98684 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -30,8 +30,6 @@ dp_font_t dp_fonts[MAX_FONTS] = {{0}}; cvar_t r_textshadow = {CVAR_SAVE, "r_textshadow", "0", "draws a shadow on all text to improve readability (note: value controls offset, 1 = 1 pixel, 1.5 = 1.5 pixels, etc)"}; cvar_t r_textbrightness = {CVAR_SAVE, "r_textbrightness", "0", "additional brightness for text color codes (0 keeps colors as is, 1 makes them all white)"}; -cachepic_t *r_crosshairs[NUMCROSSHAIRS+1]; - //============================================================================= /* Support Routines */ @@ -101,51 +99,67 @@ static rtexture_t *draw_generateconchars(void) return R_LoadTexture2D(drawtexturepool, "conchars", 256, 256, &buffer[0][0], TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PRECACHE, NULL); } -static char *pointerimage = - "333333332......." - "26777761........" - "2655541........." - "265541.........." - "2654561........." - "26414561........" - "251.14561......." - "21...14561......" - "1.....141......." - ".......1........" +static rtexture_t *draw_generateditherpattern(void) +{ + int x, y; + unsigned char pixels[8][8]; + for (y = 0;y < 8;y++) + for (x = 0;x < 8;x++) + pixels[y][x] = ((x^y) & 4) ? 254 : 0; + return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, pixels[0], TEXTYPE_PALETTE, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL); +} + +typedef struct embeddedpic_s +{ + const char *name; + int width; + int height; + const char *pixels; +} +embeddedpic_t; + +static embeddedpic_t embeddedpics[] = +{ + { + "gfx/prydoncursor001", 16, 16, + "477777774......." + "77.....6........" + "7.....6........." + "7....6.........." + "7.....6........." + "7..6...6........" + "7.6.6...6......." + "76...6...6......" + "4.....6.6......." + ".......6........" "................" "................" "................" "................" "................" "................" -; - -static rtexture_t *draw_generatemousepointer(void) -{ - int i; - unsigned char buffer[256][4]; - for (i = 0;i < 256;i++) + }, { - if (pointerimage[i] == '.') - { - buffer[i][0] = 0; - buffer[i][1] = 0; - buffer[i][2] = 0; - buffer[i][3] = 0; - } - else - { - buffer[i][0] = (pointerimage[i] - '0') * 16; - buffer[i][1] = (pointerimage[i] - '0') * 16; - buffer[i][2] = (pointerimage[i] - '0') * 16; - buffer[i][3] = 255; - } - } - return R_LoadTexture2D(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PRECACHE, NULL); -} - -static char *crosshairtexdata[NUMCROSSHAIRS] = -{ + "ui/mousepointer", 16, 16, + "477777774......." + "77.....6........" + "7.....6........." + "7....6.........." + "7.....6........." + "7..6...6........" + "7.6.6...6......." + "76...6...6......" + "4.....6.6......." + ".......6........" + "................" + "................" + "................" + "................" + "................" + "................" + }, + { + "gfx/crosshair1", 16, 16, "................" "................" "................" @@ -162,7 +176,9 @@ static char *crosshairtexdata[NUMCROSSHAIRS] = "................" "................" "................" - , + }, + { + "gfx/crosshair2", 16, 16, "................" "................" "................" @@ -179,7 +195,9 @@ static char *crosshairtexdata[NUMCROSSHAIRS] = "................" "................" "................" - , + }, + { + "gfx/crosshair3", 16, 16, "................" ".......77......." ".......77......." @@ -196,7 +214,9 @@ static char *crosshairtexdata[NUMCROSSHAIRS] = ".......77......." ".......77......." "................" - , + }, + { + "gfx/crosshair4", 16, 16, "................" "................" "................" @@ -213,87 +233,173 @@ static char *crosshairtexdata[NUMCROSSHAIRS] = "........7......." "........7......." "................" - , - "................" + }, + { + "gfx/crosshair5", 8, 8, + "........" + "........" + "....7..." + "........" + "..7.7.7." + "........" + "....7..." + "........" + }, + { + "gfx/crosshair6", 2, 2, + "77" + "77" + }, + { + "gfx/crosshair7", 16, 16, "................" + ".3............3." + "..5...2332...5.." + "...7.3....3.7..." + "....7......7...." + "...3.7....7.3..." + "..2...7..7...2.." + "..3..........3.." + "..3..........3.." + "..2...7..7...2.." + "...3.7....7.3..." + "....7......7...." + "...7.3....3.7..." + "..5...2332...5.." + ".3............3." "................" + }, + { + "gfx/editlights/cursor", 16, 16, "................" + ".3............3." + "..5...2332...5.." + "...7.3....3.7..." + "....7......7...." + "...3.7....7.3..." + "..2...7..7...2.." + "..3..........3.." + "..3..........3.." + "..2...7..7...2.." + "...3.7....7.3..." + "....7......7...." + "...7.3....3.7..." + "..5...2332...5.." + ".3............3." "................" - "........7......." + }, + { + "gfx/editlights/light", 16, 16, "................" - "........4......." - ".....7.4.4.7...." - "........4......." "................" - "........7......." + "......1111......" + "....11233211...." + "...1234554321..." + "...1356776531..." + "..124677776421.." + "..135777777531.." + "..135777777531.." + "..124677776421.." + "...1356776531..." + "...1234554321..." + "....11233211...." + "......1111......" "................" "................" + }, + { + "gfx/editlights/noshadow", 16, 16, "................" "................" - , + "......1111......" + "....11233211...." + "...1234554321..." + "...1356226531..." + "..12462..26421.." + "..1352....2531.." + "..1352....2531.." + "..12462..26421.." + "...1356226531..." + "...1234554321..." + "....11233211...." + "......1111......" "................" "................" + }, + { + "gfx/editlights/selection", 16, 16, "................" + ".777752..257777." + ".742........247." + ".72..........27." + ".7............7." + ".5............5." + ".2............2." "................" "................" + ".2............2." + ".5............5." + ".7............7." + ".72..........27." + ".742........247." + ".777752..257777." "................" + }, + { + "gfx/editlights/cubemaplight", 16, 16, "................" - ".......55......." - ".......55......." "................" + "......2772......" + "....27755772...." + "..277533335772.." + "..753333333357.." + "..777533335777.." + "..735775577537.." + "..733357753337.." + "..733337733337.." + "..753337733357.." + "..277537735772.." + "....27777772...." + "......2772......" "................" "................" + }, + { + "gfx/editlights/cubemapnoshadowlight", 16, 16, "................" "................" + "......2772......" + "....27722772...." + "..2772....2772.." + "..72........27.." + "..7772....2777.." + "..7.27722772.7.." + "..7...2772...7.." + "..7....77....7.." + "..72...77...27.." + "..2772.77.2772.." + "....27777772...." + "......2772......" "................" "................" + }, + {NULL, 0, 0, NULL} }; -static rtexture_t *draw_generatecrosshair(int num) +static rtexture_t *draw_generatepic(const char *name) { - int i; - char *in; - unsigned char data[16*16][4]; - in = crosshairtexdata[num]; - for (i = 0;i < 16*16;i++) - { - if (in[i] == '.') - { - data[i][0] = 255; - data[i][1] = 255; - data[i][2] = 255; - data[i][3] = 0; - } - else - { - data[i][0] = data[i][1] = data[i][2] = (unsigned char) ((int) (in[i] - '0') * 127 / 7 + 128); - data[i][3] = 255; - } - } - return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num+1), 16, 16, &data[0][0], TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PRECACHE, NULL); + embeddedpic_t *p; + for (p = embeddedpics;p->name;p++) + if (!strcmp(name, p->name)) + return R_LoadTexture2D(drawtexturepool, p->name, p->width, p->height, (const unsigned char *)p->pixels, TEXTYPE_PALETTE, TEXF_ALPHA | TEXF_PRECACHE, palette_bgra_embeddedpic); + if (!strcmp(name, "gfx/conchars")) + return draw_generateconchars(); + if (!strcmp(name, "gfx/colorcontrol/ditherpattern")) + return draw_generateditherpattern(); + Con_Printf("Draw_CachePic: failed to load %s\n", name); + return r_texture_notexture; } -static rtexture_t *draw_generateditherpattern(void) -{ -#if 1 - int x, y; - unsigned char data[8*8*4]; - for (y = 0;y < 8;y++) - { - for (x = 0;x < 8;x++) - { - data[(y*8+x)*4+0] = data[(y*8+x)*4+1] = data[(y*8+x)*4+2] = ((x^y) & 4) ? 255 : 0; - data[(y*8+x)*4+3] = 255; - } - } - return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, data, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL); -#else - unsigned char data[16]; - memset(data, 255, sizeof(data)); - data[0] = data[1] = data[2] = data[12] = data[13] = data[14] = 0; - return R_LoadTexture2D(drawtexturepool, "ditherpattern", 2, 2, data, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL); -#endif -} /* ================ @@ -342,7 +448,7 @@ static cachepic_t *Draw_CachePic_Compression (const char *path, qboolean persist flags = TEXF_ALPHA; if (persistent) flags |= TEXF_PRECACHE; - if (!strcmp(path, "gfx/colorcontrol/ditherpattern")) + if (strcmp(path, "gfx/colorcontrol/ditherpattern")) flags |= TEXF_CLAMP; if(allow_compression && gl_texturecompression_2d.integer) flags |= TEXF_COMPRESS; @@ -400,48 +506,10 @@ static cachepic_t *Draw_CachePic_Compression (const char *path, qboolean persist } } - // if it's not found on disk, check if it's one of the builtin images + // if it's not found on disk, generate an image if (pic->tex == NULL) { - if (pic->tex == NULL && !strcmp(path, "gfx/conchars")) - pic->tex = draw_generateconchars(); - if (pic->tex == NULL && !strcmp(path, "ui/mousepointer")) - pic->tex = draw_generatemousepointer(); - if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001")) - pic->tex = draw_generatemousepointer(); - if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1")) - pic->tex = draw_generatecrosshair(0); - if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2")) - pic->tex = draw_generatecrosshair(1); - if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3")) - pic->tex = draw_generatecrosshair(2); - if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4")) - pic->tex = draw_generatecrosshair(3); - if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5")) - pic->tex = draw_generatecrosshair(4); - if (pic->tex == NULL && !strcmp(path, "gfx/crosshair6")) - pic->tex = draw_generatecrosshair(5); - if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern")) - pic->tex = draw_generateditherpattern(); - // default textures for light sprites - // todo: improve them - if (pic->tex == NULL && !strcmp(path, "gfx/editlights/cursor")) - pic->tex = draw_generatecrosshair(0); - if (pic->tex == NULL && !strcmp(path, "gfx/editlights/light")) - pic->tex = draw_generatecrosshair(0); - if (pic->tex == NULL && !strcmp(path, "gfx/editlights/noshadow")) - pic->tex = draw_generatecrosshair(0); - if (pic->tex == NULL && !strcmp(path, "gfx/editlights/cubemap")) - pic->tex = draw_generatecrosshair(0); - if (pic->tex == NULL && !strcmp(path, "gfx/editlights/selection")) - pic->tex = draw_generatecrosshair(0); - if (pic->tex == NULL) - { - // don't complain about missing gfx/crosshair images - if (strncmp(path, "gfx/crosshair", 13)) - Con_Printf("Draw_CachePic: failed to load %s\n", path); - pic->tex = r_texture_notexture; - } + pic->tex = draw_generatepic(path); pic->width = R_TextureWidth(pic->tex); pic->height = R_TextureHeight(pic->tex); } @@ -625,9 +693,6 @@ static void gl_draw_start(void) for(i = 0; i < MAX_FONTS; ++i) LoadFont(false, va("gfx/font_%s", dp_fonts[i].title), &dp_fonts[i]); - for (i = 1;i <= NUMCROSSHAIRS;i++) - r_crosshairs[i] = Draw_CachePic(va("gfx/crosshair%i", i), true); - // draw the loading screen so people have something to see in the newly opened window SCR_UpdateLoadingScreen(true); } diff --git a/gl_rmain.c b/gl_rmain.c index 376e2336..57b95387 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -1998,7 +1998,6 @@ extern void GL_Main_Init(void); extern void R_Shadow_Init(void); extern void R_Sky_Init(void); extern void GL_Surf_Init(void); -extern void R_Light_Init(void); extern void R_Particles_Init(void); extern void R_Explosion_Init(void); extern void gl_backend_init(void); @@ -2016,7 +2015,6 @@ void Render_Init(void) R_Sky_Init(); GL_Surf_Init(); Sbar_Init(); - R_Light_Init(); R_Particles_Init(); R_Explosion_Init(); R_LightningBeams_Init(); diff --git a/makefile.inc b/makefile.inc index 36aa7833..1b6a9506 100644 --- a/makefile.inc +++ b/makefile.inc @@ -118,7 +118,6 @@ OBJ_COMMON= \ prvm_exec.o \ r_explosion.o \ r_lerpanim.o \ - r_light.o \ r_lightning.o \ r_modules.o \ r_shadow.o \ diff --git a/palette.c b/palette.c index e73e8192..89193b87 100644 --- a/palette.c +++ b/palette.c @@ -19,6 +19,7 @@ unsigned int palette_bgra_onlyfullbrights[256]; unsigned int palette_bgra_pantsaswhite[256]; unsigned int palette_bgra_shirtaswhite[256]; unsigned int palette_bgra_transparent[256]; +unsigned int palette_bgra_embeddedpic[256]; // John Carmack said the quake palette.lmp can be considered public domain because it is not an important asset to id, so I include it here as a fallback if no external palette file is found. unsigned char host_quakepal[768] = @@ -204,6 +205,12 @@ void Palette_Load(void) fs_offset_t filesize; unsigned char *palfile; unsigned char texturegammaramp[256]; + union + { + unsigned char b[4]; + unsigned int i; + } + bgra; gamma = 1; scale = 1; @@ -279,6 +286,13 @@ void Palette_Load(void) if(palfile) Mem_Free(palfile); + memset(palette_bgra_embeddedpic, 0, sizeof(palette_bgra_embeddedpic)); + for (i = '1';i <= '7';i++) + { + Vector4Set(bgra.b, 255, 255, 255, (i - '0') * 255 / 7); + palette_bgra_embeddedpic[i] = bgra.i; + } + Palette_SetupSpecialPalettes(); } diff --git a/palette.h b/palette.h index e7603bb9..11058772 100644 --- a/palette.h +++ b/palette.h @@ -18,6 +18,7 @@ extern unsigned int palette_bgra_onlyfullbrights[256]; extern unsigned int palette_bgra_pantsaswhite[256]; extern unsigned int palette_bgra_shirtaswhite[256]; extern unsigned int palette_bgra_transparent[256]; +extern unsigned int palette_bgra_embeddedpic[256]; // used by hardware gamma functions in vid_* files void BuildGammaTable8(float prescale, float gamma, float scale, float base, unsigned char *out, int rampsize); diff --git a/r_light.c b/r_light.c deleted file mode 100644 index 8fd4a01d..00000000 --- a/r_light.c +++ /dev/null @@ -1,165 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_light.c - -#include "quakedef.h" -#include "cl_collision.h" -#include "r_shadow.h" - -cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "1", "brightness of corona flare effects around certain lights, 0 disables corona effects"}; -cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"}; - -static rtexture_t *lightcorona; -static rtexturepool_t *lighttexturepool; - -void r_light_start(void) -{ - float dx, dy; - int x, y, a; - unsigned char pixels[32][32][4]; - lighttexturepool = R_AllocTexturePool(); - for (y = 0;y < 32;y++) - { - dy = (y - 15.5f) * (1.0f / 16.0f); - for (x = 0;x < 32;x++) - { - dx = (x - 15.5f) * (1.0f / 16.0f); - a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2))); - a = bound(0, a, 255); - pixels[y][x][0] = a; - pixels[y][x][1] = a; - pixels[y][x][2] = a; - pixels[y][x][3] = 255; - } - } - lightcorona = R_LoadTexture2D(lighttexturepool, "lightcorona", 32, 32, &pixels[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE, NULL); -} - -void r_light_shutdown(void) -{ - lighttexturepool = NULL; - lightcorona = NULL; -} - -void r_light_newmap(void) -{ - int i; - for (i = 0;i < MAX_LIGHTSTYLES;i++) - r_refdef.lightstylevalue[i] = 256; // normal light value -} - -void R_Light_Init(void) -{ - Cvar_RegisterVariable(&r_coronas); - Cvar_RegisterVariable(&gl_flashblend); - R_RegisterModule("R_Light", r_light_start, r_light_shutdown, r_light_newmap); -} - -void R_DrawCoronas(void) -{ - int i, lnum, flag; - float cscale, scale; - dlight_t *light; - rtlight_t *rtlight; - if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer) - return; - R_Mesh_Matrix(&identitymatrix); - flag = r_refdef.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; - // FIXME: these traces should scan all render entities instead of cl.world - for (lnum = 0, light = r_shadow_worldlightchain;light;light = light->next, lnum++) - { - rtlight = &light->rtlight; - if (!(rtlight->flags & flag)) - continue; - if (rtlight->corona * r_coronas.value <= 0) - continue; - if (r_shadow_debuglight.integer >= 0 && r_shadow_debuglight.integer != lnum) - continue; - cscale = rtlight->corona * r_coronas.value* 0.25f; - scale = rtlight->radius * rtlight->coronasizescale; - if (VectorDistance2(rtlight->shadoworigin, r_view.origin) < 16.0f * 16.0f) - continue; - if (CL_Move(r_view.origin, vec3_origin, vec3_origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1) - continue; - R_DrawSprite(GL_ONE, GL_ONE, lightcorona, NULL, true, false, rtlight->shadoworigin, r_view.right, r_view.up, scale, -scale, -scale, scale, rtlight->color[0] * cscale, rtlight->color[1] * cscale, rtlight->color[2] * cscale, 1); - } - for (i = 0;i < r_refdef.numlights;i++) - { - rtlight = &r_refdef.lights[i]; - if (!(rtlight->flags & flag)) - continue; - if (rtlight->corona <= 0) - continue; - if (VectorDistance2(rtlight->shadoworigin, r_view.origin) < 32.0f * 32.0f) - continue; - if (gl_flashblend.integer) - { - cscale = rtlight->corona * 1.0f; - scale = rtlight->radius * rtlight->coronasizescale * 2.0f; - } - else - { - cscale = rtlight->corona * r_coronas.value* 0.25f; - scale = rtlight->radius * rtlight->coronasizescale; - } - if (VectorLength(rtlight->color) * cscale < (1.0f / 256.0f)) - continue; - if (CL_Move(r_view.origin, vec3_origin, vec3_origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1) - continue; - R_DrawSprite(GL_ONE, GL_ONE, lightcorona, NULL, true, false, rtlight->shadoworigin, r_view.right, r_view.up, scale, -scale, -scale, scale, rtlight->color[0] * cscale, rtlight->color[1] * cscale, rtlight->color[2] * cscale, 1); - } -} - -/* -============================================================================= - -LIGHT SAMPLING - -============================================================================= -*/ - -void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, int dynamic) -{ - VectorClear(diffusecolor); - VectorClear(diffusenormal); - - if (!r_fullbright.integer && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint) - { - ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = r_ambient.value * (2.0f / 128.0f); - r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, p, ambientcolor, diffusecolor, diffusenormal); - } - else - VectorSet(ambientcolor, 1, 1, 1); - - if (dynamic) - { - int i; - float f, v[3]; - rtlight_t *light; - for (i = 0;i < r_refdef.numlights;i++) - { - light = &r_refdef.lights[i]; - Matrix4x4_Transform(&light->matrix_worldtolight, p, v); - f = 1 - VectorLength2(v); - if (f > 0 && CL_Move(p, vec3_origin, vec3_origin, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1) - VectorMA(ambientcolor, f, light->currentcolor, ambientcolor); - } - } -} diff --git a/r_light.h b/r_light.h deleted file mode 100644 index 7af2aadc..00000000 --- a/r_light.h +++ /dev/null @@ -1,9 +0,0 @@ - -#ifndef R_LIGHT_H -#define R_LIGHT_H - -void R_DrawCoronas(void); -void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, int dynamic); - -#endif - diff --git a/r_shadow.c b/r_shadow.c index fedb6003..9d103b0f 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -194,6 +194,7 @@ rtexturepool_t *r_shadow_texturepool; rtexture_t *r_shadow_attenuationgradienttexture; rtexture_t *r_shadow_attenuation2dtexture; rtexture_t *r_shadow_attenuation3dtexture; +rtexture_t *r_shadow_lightcorona; // lights are reloaded when this changes char r_shadow_mapname[MAX_QPATH]; @@ -232,6 +233,8 @@ cvar_t r_shadow_culltriangles = {0, "r_shadow_culltriangles", "1", "performs mor cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"}; cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"}; cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1", "use 3D voxel textures for spherical attenuation rather than cylindrical (does not affect r_glsl lighting)"}; +cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "1", "brightness of corona flare effects around certain lights, 0 disables corona effects"}; +cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"}; cvar_t gl_ext_separatestencil = {0, "gl_ext_separatestencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"}; cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"}; cvar_t r_editlights = {0, "r_editlights", "0", "enables .rtlights file editing mode"}; @@ -253,7 +256,7 @@ static float r_shadow_attenlinearscale; // r_shadow_lightattenuationlinearscale static float r_shadow_attentable[ATTENTABLESIZE+1]; rtlight_t *r_shadow_compilingrtlight; -dlight_t *r_shadow_worldlightchain; +static memexpandablearray_t r_shadow_worldlightsarray; dlight_t *r_shadow_selectedlight; dlight_t r_shadow_bufferlight; vec3_t r_editlights_cursorlocation; @@ -283,11 +286,11 @@ static void R_Shadow_MakeTextures(void); // VorteX: custom editor light sprites #define EDLIGHTSPRSIZE 8 -#define EDLIGHTSELECTSPRSIZE 12 cachepic_t *r_editlights_sprcursor; cachepic_t *r_editlights_sprlight; cachepic_t *r_editlights_sprnoshadowlight; -cachepic_t *r_editlights_sprcubemap; +cachepic_t *r_editlights_sprcubemaplight; +cachepic_t *r_editlights_sprcubemapnoshadowlight; cachepic_t *r_editlights_sprselection; void r_shadow_start(void) @@ -453,6 +456,8 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_polygonfactor); Cvar_RegisterVariable(&r_shadow_polygonoffset); Cvar_RegisterVariable(&r_shadow_texture3d); + Cvar_RegisterVariable(&r_coronas); + Cvar_RegisterVariable(&gl_flashblend); Cvar_RegisterVariable(&gl_ext_separatestencil); Cvar_RegisterVariable(&gl_ext_stenciltwoside); if (gamemode == GAME_TENEBRAE) @@ -462,7 +467,7 @@ void R_Shadow_Init(void) } Cmd_AddCommand("r_shadow_help", R_Shadow_Help_f, "prints documentation on console commands and variables used by realtime lighting and shadowing system"); R_Shadow_EditLights_Init(); - r_shadow_worldlightchain = NULL; + Mem_ExpandableArray_NewArray(&r_shadow_worldlightsarray, r_main_mempool, sizeof(dlight_t), 128); maxshadowtriangles = 0; shadowelements = NULL; maxshadowvertices = 0; @@ -916,6 +921,28 @@ void R_Shadow_RenderVolume(int numvertices, int numtriangles, const float *verte CHECKGLERROR } +static void R_Shadow_MakeTextures_MakeCorona(void) +{ + float dx, dy; + int x, y, a; + unsigned char pixels[32][32][4]; + for (y = 0;y < 32;y++) + { + dy = (y - 15.5f) * (1.0f / 16.0f); + for (x = 0;x < 32;x++) + { + dx = (x - 15.5f) * (1.0f / 16.0f); + a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2))); + a = bound(0, a, 255); + pixels[y][x][0] = a; + pixels[y][x][1] = a; + pixels[y][x][2] = a; + pixels[y][x][3] = 255; + } + } + r_shadow_lightcorona = R_LoadTexture2D(r_shadow_texturepool, "lightcorona", 32, 32, &pixels[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE, NULL); +} + static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z) { float dist = sqrt(x*x+y*y+z*z); @@ -963,11 +990,14 @@ static void R_Shadow_MakeTextures(void) r_shadow_attenuation3dtexture = NULL; Mem_Free(data); + R_Shadow_MakeTextures_MakeCorona(); + // Editor light sprites r_editlights_sprcursor = Draw_CachePic("gfx/editlights/cursor", true); r_editlights_sprlight = Draw_CachePic("gfx/editlights/light", true); r_editlights_sprnoshadowlight = Draw_CachePic("gfx/editlights/noshadow", true); - r_editlights_sprcubemap = Draw_CachePic("gfx/editlights/cubemap", true); + r_editlights_sprcubemaplight = Draw_CachePic("gfx/editlights/cubemaplight", true); + r_editlights_sprcubemapnoshadowlight = Draw_CachePic("gfx/editlights/cubemapnoshadowlight", true); r_editlights_sprselection = Draw_CachePic("gfx/editlights/selection", true); } @@ -2496,9 +2526,15 @@ void R_RTLight_Uncompile(rtlight_t *rtlight) void R_Shadow_UncompileWorldLights(void) { + size_t lightindex; dlight_t *light; - for (light = r_shadow_worldlightchain;light;light = light->next) + for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++) + { + light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (!light) + continue; R_RTLight_Uncompile(&light->rtlight); + } } void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight) @@ -3054,7 +3090,9 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible) void R_Shadow_DrawLightSprites(void); void R_ShadowVolumeLighting(qboolean visible) { - int lnum, flag; + int flag; + int lnum; + size_t lightindex; dlight_t *light; if (r_refdef.worldmodel && strncmp(r_refdef.worldmodel->name, r_shadow_mapname, sizeof(r_shadow_mapname))) @@ -3068,14 +3106,20 @@ void R_ShadowVolumeLighting(qboolean visible) flag = r_refdef.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; if (r_shadow_debuglight.integer >= 0) { - for (lnum = 0, light = r_shadow_worldlightchain;light;lnum++, light = light->next) - if (lnum == r_shadow_debuglight.integer && (light->flags & flag)) - R_DrawRTLight(&light->rtlight, visible); + lightindex = r_shadow_debuglight.integer; + light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (light && (light->flags & flag)) + R_DrawRTLight(&light->rtlight, visible); } else - for (lnum = 0, light = r_shadow_worldlightchain;light;lnum++, light = light->next) - if (light->flags & flag) + { + for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++) + { + light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (light && (light->flags & flag)) R_DrawRTLight(&light->rtlight, visible); + } + } if (r_refdef.rtdlight) for (lnum = 0;lnum < r_refdef.numlights;lnum++) R_DrawRTLight(&r_refdef.lights[lnum], visible); @@ -3171,6 +3215,66 @@ void R_DrawModelShadows(void) R_Shadow_RenderMode_End(); } +void R_DrawCoronas(void) +{ + int i, flag; + float cscale, scale; + size_t lightindex; + dlight_t *light; + rtlight_t *rtlight; + if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer) + return; + R_Mesh_Matrix(&identitymatrix); + flag = r_refdef.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; + // FIXME: these traces should scan all render entities instead of cl.world + for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++) + { + light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (!light) + continue; + rtlight = &light->rtlight; + if (!(rtlight->flags & flag)) + continue; + if (rtlight->corona * r_coronas.value <= 0) + continue; + if (r_shadow_debuglight.integer >= 0 && r_shadow_debuglight.integer != (int)lightindex) + continue; + cscale = rtlight->corona * r_coronas.value* 0.25f; + scale = rtlight->radius * rtlight->coronasizescale; + if (VectorDistance2(rtlight->shadoworigin, r_view.origin) < 16.0f * 16.0f) + continue; + if (CL_Move(r_view.origin, vec3_origin, vec3_origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1) + continue; + R_DrawSprite(GL_ONE, GL_ONE, r_shadow_lightcorona, NULL, true, false, rtlight->shadoworigin, r_view.right, r_view.up, scale, -scale, -scale, scale, rtlight->color[0] * cscale, rtlight->color[1] * cscale, rtlight->color[2] * cscale, 1); + } + for (i = 0;i < r_refdef.numlights;i++) + { + rtlight = &r_refdef.lights[i]; + if (!(rtlight->flags & flag)) + continue; + if (rtlight->corona <= 0) + continue; + if (VectorDistance2(rtlight->shadoworigin, r_view.origin) < 32.0f * 32.0f) + continue; + if (gl_flashblend.integer) + { + cscale = rtlight->corona * 1.0f; + scale = rtlight->radius * rtlight->coronasizescale * 2.0f; + } + else + { + cscale = rtlight->corona * r_coronas.value* 0.25f; + scale = rtlight->radius * rtlight->coronasizescale; + } + if (VectorLength(rtlight->color) * cscale < (1.0f / 256.0f)) + continue; + if (CL_Move(r_view.origin, vec3_origin, vec3_origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1) + continue; + R_DrawSprite(GL_ONE, GL_ONE, r_shadow_lightcorona, NULL, true, false, rtlight->shadoworigin, r_view.right, r_view.up, scale, -scale, -scale, scale, rtlight->color[0] * cscale, rtlight->color[1] * cscale, rtlight->color[2] * cscale, 1); + } +} + + //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"}; typedef struct suffixinfo_s @@ -3294,11 +3398,7 @@ void R_Shadow_FreeCubemaps(void) dlight_t *R_Shadow_NewWorldLight(void) { - dlight_t *light; - light = (dlight_t *)Mem_Alloc(r_main_mempool, sizeof(dlight_t)); - light->next = r_shadow_worldlightchain; - r_shadow_worldlightchain = light; - return light; + return (dlight_t *)Mem_ExpandableArray_AllocRecord(&r_shadow_worldlightsarray); } void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags) @@ -3339,19 +3439,22 @@ void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, ve void R_Shadow_FreeWorldLight(dlight_t *light) { - dlight_t **lightpointer; + if (r_shadow_selectedlight == light) + r_shadow_selectedlight = NULL; R_RTLight_Uncompile(&light->rtlight); - for (lightpointer = &r_shadow_worldlightchain;*lightpointer && *lightpointer != light;lightpointer = &(*lightpointer)->next); - if (*lightpointer != light) - Sys_Error("R_Shadow_FreeWorldLight: light not linked into chain"); - *lightpointer = light->next; - Mem_Free(light); + Mem_ExpandableArray_FreeRecord(&r_shadow_worldlightsarray, light); } void R_Shadow_ClearWorldLights(void) { - while (r_shadow_worldlightchain) - R_Shadow_FreeWorldLight(r_shadow_worldlightchain); + size_t lightindex; + dlight_t *light; + for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++) + { + light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (light) + R_Shadow_FreeWorldLight(light); + } r_shadow_selectedlight = NULL; R_Shadow_FreeCubemaps(); } @@ -3368,62 +3471,69 @@ void R_Shadow_SelectLight(dlight_t *light) void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { // this is never batched (there can be only one) - R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_editlights_sprcursor->tex, NULL, false, false, r_editlights_cursorlocation, r_view.right, r_view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE, 1, 1, 1, 0.5f); + R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, r_editlights_sprcursor->tex, r_editlights_sprcursor->tex, false, false, r_editlights_cursorlocation, r_view.right, r_view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE, 1, 1, 1, 1); } void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { float intensity; - float scaling; + float s; vec3_t spritecolor; + cachepic_t *pic; // this is never batched (due to the ent parameter changing every time) // so numsurfaces == 1 and surfacelist[0] == lightnumber const dlight_t *light = (dlight_t *)ent; - intensity = 1; - scaling = 1; - if (light->selected) - scaling = 1.25 + 0.25*sin(realtime * M_PI * 1.5); - // vortex: get sprites color (solve 0 0 0 colored light being invisible here) - spritecolor[0] = max(0.1, light->color[0]); - spritecolor[1] = max(0.1, light->color[1]); - spritecolor[2] = max(0.1, light->color[2]); + s = EDLIGHTSPRSIZE; + intensity = 0.5f; + VectorScale(light->color, intensity, spritecolor); + if (VectorLength(spritecolor) < 0.1732f) + VectorSet(spritecolor, 0.1f, 0.1f, 0.1f); + if (VectorLength(spritecolor) > 1.0f) + VectorNormalize(spritecolor); // draw light sprite - if (!light->shadow) - { - intensity *= 0.5f; - R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_editlights_sprnoshadowlight->tex, NULL, false, false, light->origin, r_view.right, r_view.up, EDLIGHTSPRSIZE*scaling, -EDLIGHTSPRSIZE*scaling, -EDLIGHTSPRSIZE*scaling, EDLIGHTSPRSIZE*scaling, spritecolor[0]*intensity, spritecolor[1]*intensity, spritecolor[2]*intensity, 1); - } + if (light->cubemapname[0] && !light->shadow) + pic = r_editlights_sprcubemapnoshadowlight; + else if (light->cubemapname[0]) + pic = r_editlights_sprcubemaplight; + else if (!light->shadow) + pic = r_editlights_sprnoshadowlight; else - R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_editlights_sprlight->tex, NULL, false, false, light->origin, r_view.right, r_view.up, EDLIGHTSELECTSPRSIZE*scaling, -EDLIGHTSELECTSPRSIZE*scaling, -EDLIGHTSELECTSPRSIZE*scaling, EDLIGHTSELECTSPRSIZE*scaling, spritecolor[0]*intensity, spritecolor[1]*intensity, spritecolor[2]*intensity, 1); - // draw cubemap sprite over light - if (light->cubemapname[0]) - R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_editlights_sprcubemap->tex, NULL, false, false, light->origin, r_view.right, r_view.up, EDLIGHTSPRSIZE*scaling, -EDLIGHTSPRSIZE*scaling, -EDLIGHTSPRSIZE*scaling, EDLIGHTSPRSIZE*scaling, spritecolor[0]*intensity, spritecolor[1]*intensity, spritecolor[2]*intensity, 1); + pic = r_editlights_sprlight; + R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, pic->tex, pic->tex, false, false, light->origin, r_view.right, r_view.up, s, -s, -s, s, spritecolor[0], spritecolor[1], spritecolor[2], 1); // draw selection sprite if light is selected if (light->selected) - R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_editlights_sprselection->tex, NULL, false, false, light->origin, r_view.right, r_view.up, EDLIGHTSPRSIZE*scaling, -EDLIGHTSPRSIZE*scaling, -EDLIGHTSPRSIZE*scaling, EDLIGHTSPRSIZE*scaling, spritecolor[0]*intensity, spritecolor[1]*intensity, spritecolor[2]*intensity, 1); + R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, r_editlights_sprselection->tex, r_editlights_sprselection->tex, false, false, light->origin, r_view.right, r_view.up, s, -s, -s, s, 1, 1, 1, 1); // VorteX todo: add normalmode/realtime mode light overlay sprites? } void R_Shadow_DrawLightSprites(void) { - int i; + size_t lightindex; dlight_t *light; - - for (i = 0, light = r_shadow_worldlightchain;light;i++, light = light->next) - R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 1+(i % 5), &light->rtlight); + for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++) + { + light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (light) + R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight); + } R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL); } void R_Shadow_SelectLightInView(void) { float bestrating, rating, temp[3]; - dlight_t *best, *light; + dlight_t *best; + size_t lightindex; + dlight_t *light; best = NULL; bestrating = 0; - for (light = r_shadow_worldlightchain;light;light = light->next) + for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++) { + light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (!light) + continue; VectorSubtract(light->origin, r_view.origin, temp); rating = (DotProduct(temp, r_view.forward) / sqrt(DotProduct(temp, temp))); if (rating >= 0.95) @@ -3534,12 +3644,13 @@ void R_Shadow_LoadWorldLights(void) void R_Shadow_SaveWorldLights(void) { + size_t lightindex; dlight_t *light; size_t bufchars, bufmaxchars; char *buf, *oldbuf; char name[MAX_QPATH]; char line[MAX_INPUTLINE]; - if (!r_shadow_worldlightchain) + if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)) return; if (r_refdef.worldmodel == NULL) { @@ -3550,8 +3661,11 @@ void R_Shadow_SaveWorldLights(void) strlcat (name, ".rtlights", sizeof (name)); bufchars = bufmaxchars = 0; buf = NULL; - for (light = r_shadow_worldlightchain;light;light = light->next) + for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++) { + light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (!light) + continue; if (light->coronasizescale != 0.25f || light->ambientscale != 0 || light->diffusescale != 1 || light->specularscale != 1 || light->flags != LIGHTFLAG_REALTIMEMODE) sprintf(line, "%s%f %f %f %f %f %f %f %d \"%s\" %f %f %f %f %f %f %f %f %i\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius, light->color[0], light->color[1], light->color[2], light->style, light->cubemapname, light->corona, light->angles[0], light->angles[1], light->angles[2], light->coronasizescale, light->ambientscale, light->diffusescale, light->specularscale, light->flags); else if (light->cubemapname[0] || light->corona || light->angles[0] || light->angles[1] || light->angles[2]) @@ -3901,10 +4015,10 @@ void R_Shadow_EditLights_Reload_f(void) strlcpy(r_shadow_mapname, r_refdef.worldmodel->name, sizeof(r_shadow_mapname)); R_Shadow_ClearWorldLights(); R_Shadow_LoadWorldLights(); - if (r_shadow_worldlightchain == NULL) + if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)) { R_Shadow_LoadLightsFile(); - if (r_shadow_worldlightchain == NULL) + if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)) R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(); } } @@ -4262,6 +4376,7 @@ void R_Shadow_EditLights_Edit_f(void) void R_Shadow_EditLights_EditAll_f(void) { + size_t lightindex; dlight_t *light; if (!r_editlights.integer) @@ -4270,8 +4385,11 @@ void R_Shadow_EditLights_EditAll_f(void) return; } - for (light = r_shadow_worldlightchain;light;light = light->next) + for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++) { + light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (!light) + continue; R_Shadow_SelectLight(light); R_Shadow_EditLights_Edit_f(); } @@ -4280,6 +4398,7 @@ void R_Shadow_EditLights_EditAll_f(void) void R_Shadow_EditLights_DrawSelectedLightProperties(void) { int lightnumber, lightcount; + size_t lightindex; dlight_t *light; float x, y; char temp[256]; @@ -4290,11 +4409,17 @@ void R_Shadow_EditLights_DrawSelectedLightProperties(void) DrawQ_Pic(x-5, y-5, NULL, 250, 155, 0, 0, 0, 0.75, 0); lightnumber = -1; lightcount = 0; - for (lightcount = 0, light = r_shadow_worldlightchain;light;lightcount++, light = light->next) + for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++) + { + light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (!light) + continue; if (light == r_shadow_selectedlight) - lightnumber = lightcount; + lightnumber = lightindex; + lightcount++; + } sprintf(temp, "Cursor origin: %.0f %.0f %.0f", r_editlights_cursorlocation[0], r_editlights_cursorlocation[1], r_editlights_cursorlocation[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false);y += 8; - sprintf(temp, "Total lights : %i", lightcount); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false);y += 8; + sprintf(temp, "Total lights : %i active (%i total)", lightcount, (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false);y += 8; y += 8; if (r_shadow_selectedlight == NULL) return; @@ -4484,3 +4609,41 @@ void R_Shadow_EditLights_Init(void) Cmd_AddCommand("r_editlights_pasteinfo", R_Shadow_EditLights_PasteInfo_f, "apply the stored properties onto the selected light (making it exactly identical except for origin)"); } + + +/* +============================================================================= + +LIGHT SAMPLING + +============================================================================= +*/ + +void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, int dynamic) +{ + VectorClear(diffusecolor); + VectorClear(diffusenormal); + + if (!r_fullbright.integer && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint) + { + ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = r_ambient.value * (2.0f / 128.0f); + r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, p, ambientcolor, diffusecolor, diffusenormal); + } + else + VectorSet(ambientcolor, 1, 1, 1); + + if (dynamic) + { + int i; + float f, v[3]; + rtlight_t *light; + for (i = 0;i < r_refdef.numlights;i++) + { + light = &r_refdef.lights[i]; + Matrix4x4_Transform(&light->matrix_worldtolight, p, v); + f = 1 - VectorLength2(v); + if (f > 0 && CL_Move(p, vec3_origin, vec3_origin, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1) + VectorMA(ambientcolor, f, light->currentcolor, ambientcolor); + } + } +} diff --git a/r_shadow.h b/r_shadow.h index b77be839..d868dddf 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -59,8 +59,6 @@ extern matrix4x4_t matrix_attenuationz; rtexture_t *R_Shadow_Cubemap(const char *basename); -extern dlight_t *r_shadow_worldlightchain; - void R_Shadow_UpdateWorldLightSelection(void); extern rtlight_t *r_shadow_compilingrtlight; @@ -70,6 +68,7 @@ void R_RTLight_Compile(rtlight_t *rtlight); void R_RTLight_Uncompile(rtlight_t *rtlight); void R_ShadowVolumeLighting(qboolean visible); +void R_DrawCoronas(void); int *R_Shadow_ResizeShadowElements(int numtris); @@ -80,4 +79,6 @@ extern int *shadowmarklist; extern int shadowmarkcount; void R_Shadow_PrepareShadowMark(int numtris); +void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, int dynamic); + #endif diff --git a/render.h b/render.h index a204f779..d60e8e40 100644 --- a/render.h +++ b/render.h @@ -174,8 +174,6 @@ extern cvar_t r_test; #include "gl_backend.h" -#include "r_light.h" - extern rtexture_t *r_texture_blanknormalmap; extern rtexture_t *r_texture_white; extern rtexture_t *r_texture_grey128; diff --git a/sbar.c b/sbar.c index 149d5a5b..ec29774e 100644 --- a/sbar.c +++ b/sbar.c @@ -1580,8 +1580,11 @@ void Sbar_Draw (void) Sbar_ShowFPS(); - if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer])) + if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && !cl.intermission && !r_letterbox.value) + { + pic = Draw_CachePic(va("gfx/crosshair%i", crosshair.integer), true); DrawQ_Pic((vid_conwidth.integer - pic->width * crosshair_size.value) * 0.5f, (vid_conheight.integer - pic->height * crosshair_size.value) * 0.5f, pic, pic->width * crosshair_size.value, pic->height * crosshair_size.value, crosshair_color_red.value, crosshair_color_green.value, crosshair_color_blue.value, crosshair_color_alpha.value, 0); + } if (cl_prydoncursor.integer) DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid_conwidth.integer, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid_conheight.integer, Draw_CachePic(va("gfx/prydoncursor%03i", cl_prydoncursor.integer), true), 0, 0, 1, 1, 1, 1, 0); -- 2.39.2