]> icculus.org git repositories - divverent/darkplaces.git/blob - r_light.c
added GL_CullFace(GL_NONE); in sky rendering in an attempt to fix
[divverent/darkplaces.git] / r_light.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_light.c
21
22 #include "quakedef.h"
23 #include "cl_collision.h"
24 #include "r_shadow.h"
25
26 cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "1", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
27 cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
28
29 static rtexture_t *lightcorona;
30 static rtexturepool_t *lighttexturepool;
31
32 void r_light_start(void)
33 {
34         float dx, dy;
35         int x, y, a;
36         unsigned char pixels[32][32][4];
37         lighttexturepool = R_AllocTexturePool();
38         for (y = 0;y < 32;y++)
39         {
40                 dy = (y - 15.5f) * (1.0f / 16.0f);
41                 for (x = 0;x < 32;x++)
42                 {
43                         dx = (x - 15.5f) * (1.0f / 16.0f);
44                         a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2)));
45                         a = bound(0, a, 255);
46                         pixels[y][x][0] = a;
47                         pixels[y][x][1] = a;
48                         pixels[y][x][2] = a;
49                         pixels[y][x][3] = 255;
50                 }
51         }
52         lightcorona = R_LoadTexture2D(lighttexturepool, "lightcorona", 32, 32, &pixels[0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
53 }
54
55 void r_light_shutdown(void)
56 {
57         lighttexturepool = NULL;
58         lightcorona = NULL;
59 }
60
61 void r_light_newmap(void)
62 {
63         int i;
64         for (i = 0;i < MAX_LIGHTSTYLES;i++)
65                 r_refdef.lightstylevalue[i] = 264;              // normal light value
66 }
67
68 void R_Light_Init(void)
69 {
70         Cvar_RegisterVariable(&r_coronas);
71         Cvar_RegisterVariable(&gl_flashblend);
72         R_RegisterModule("R_Light", r_light_start, r_light_shutdown, r_light_newmap);
73 }
74
75 void R_DrawCoronas(void)
76 {
77         int i, lnum, flag;
78         float cscale, scale;
79         dlight_t *light;
80         rtlight_t *rtlight;
81         if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer)
82                 return;
83         R_Mesh_Matrix(&identitymatrix);
84         flag = r_refdef.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
85         // FIXME: these traces should scan all render entities instead of cl.world
86         for (lnum = 0, light = r_shadow_worldlightchain;light;light = light->next, lnum++)
87         {
88                 rtlight = &light->rtlight;
89                 if (!(rtlight->flags & flag))
90                         continue;
91                 if (rtlight->corona * r_coronas.value <= 0)
92                         continue;
93                 if (r_shadow_debuglight.integer >= 0 && r_shadow_debuglight.integer != lnum)
94                         continue;
95                 cscale = rtlight->corona * r_coronas.value* 0.25f;
96                 scale = rtlight->radius * rtlight->coronasizescale;
97                 if (VectorDistance2(rtlight->shadoworigin, r_view.origin) < 16.0f * 16.0f)
98                         continue;
99                 if (CL_Move(r_view.origin, vec3_origin, vec3_origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
100                         continue;
101                 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);
102         }
103         for (i = 0;i < r_refdef.numlights;i++)
104         {
105                 rtlight = &r_refdef.lights[i];
106                 if (!(rtlight->flags & flag))
107                         continue;
108                 if (rtlight->corona <= 0)
109                         continue;
110                 if (VectorDistance2(rtlight->shadoworigin, r_view.origin) < 32.0f * 32.0f)
111                         continue;
112                 if (gl_flashblend.integer)
113                 {
114                         cscale = rtlight->corona * 1.0f;
115                         scale = rtlight->radius * rtlight->coronasizescale * 2.0f;
116                 }
117                 else
118                 {
119                         cscale = rtlight->corona * r_coronas.value* 0.25f;
120                         scale = rtlight->radius * rtlight->coronasizescale;
121                 }
122                 if (VectorLength(rtlight->color) * cscale < (1.0f / 256.0f))
123                         continue;
124                 if (CL_Move(r_view.origin, vec3_origin, vec3_origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
125                         continue;
126                 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);
127         }
128 }
129
130 /*
131 =============================================================================
132
133 LIGHT SAMPLING
134
135 =============================================================================
136 */
137
138 void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, int dynamic)
139 {
140         VectorClear(diffusecolor);
141         VectorClear(diffusenormal);
142
143         if (!r_fullbright.integer && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
144         {
145                 ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = r_ambient.value * (2.0f / 128.0f);
146                 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
147         }
148         else
149                 VectorSet(ambientcolor, 1, 1, 1);
150
151         if (dynamic)
152         {
153                 int i;
154                 float f, v[3];
155                 rtlight_t *light;
156                 for (i = 0;i < r_refdef.numlights;i++)
157                 {
158                         light = &r_refdef.lights[i];
159                         Matrix4x4_Transform(&light->matrix_worldtolight, p, v);
160                         f = 1 - VectorLength2(v);
161                         if (f > 0 && CL_Move(p, vec3_origin, vec3_origin, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
162                                 VectorMA(ambientcolor, f, light->currentcolor, ambientcolor);
163                 }
164         }
165 }