1 static struct flaretype
3 int type
; /* flaretex index, 0..5, -1 for 6+random shine */
4 float loc
; /* postion on axis */
5 float scale
; /* texture scaling */
6 uchar alpha
; /* color alpha */
9 {2, 1.30f
, 0.04f
, 153}, //flares
10 {3, 1.00f
, 0.10f
, 102},
11 {1, 0.50f
, 0.20f
, 77},
12 {3, 0.20f
, 0.05f
, 77},
13 {0, 0.00f
, 0.04f
, 77},
14 {5, -0.25f
, 0.07f
, 127},
15 {5, -0.40f
, 0.02f
, 153},
16 {5, -0.60f
, 0.04f
, 102},
17 {5, -1.00f
, 0.03f
, 51},
18 {-1, 1.00f
, 0.30f
, 255}, //shine - red, green, blue
19 {-2, 1.00f
, 0.20f
, 255},
20 {-3, 1.00f
, 0.25f
, 255}
31 VAR(flarelights
, 0, 0, 1);
32 VARP(flarecutoff
, 0, 1000, 10000);
33 VARP(flaresize
, 20, 100, 500);
35 struct flarerenderer
: partrenderer
37 int maxflares
, numflares
;
38 unsigned int shinetime
;
41 flarerenderer(const char *texname
, int maxflares
)
42 : partrenderer(texname
, PT_FLARE
, 0, 0), maxflares(maxflares
), shinetime(0)
44 flares
= new flare
[maxflares
];
51 void newflare(vec
&o
, const vec
¢er
, uchar r
, uchar g
, uchar b
, float mod
, float size
, bool sun
, bool sparkle
)
53 if(numflares
>= maxflares
) return;
54 vec target
; //occlusion check (neccessary as depth testing is turned off)
55 if(!raycubelos(o
, camera1
->o
, target
)) return;
56 flare
&f
= flares
[numflares
++];
60 f
.color
[0] = uchar(r
*mod
);
61 f
.color
[1] = uchar(g
*mod
);
62 f
.color
[2] = uchar(b
*mod
);
66 void addflare(vec
&o
, uchar r
, uchar g
, uchar b
, bool sun
, bool sparkle
)
68 //frustrum + fog check
69 if(isvisiblesphere(0.0f
, o
) > (sun
?VFC_FOGGED
:VFC_FULL_VISIBLE
)) return;
70 //find closest point between camera line of sight and flare pos
72 vecfromyawpitch(camera1
->yaw
, camera1
->pitch
, 1, 0, viewdir
);
73 vec flaredir
= vec(o
).sub(camera1
->o
);
74 vec center
= viewdir
.mul(flaredir
.dot(viewdir
)).add(camera1
->o
);
79 size
= flaredir
.magnitude() * flaresize
/ 100.0f
;
83 mod
= (flarecutoff
-vec(o
).sub(center
).squaredlen())/flarecutoff
;
84 if(mod
< 0.0f
) return;
85 size
= flaresize
/ 5.0f
;
87 newflare(o
, center
, r
, g
, b
, mod
, size
, sun
, sparkle
);
90 void makelightflares()
92 numflares
= 0; //regenerate flarelist each frame
93 shinetime
= lastmillis
/10;
95 if(editmode
|| !flarelights
) return;
97 const vector
<extentity
*> &ents
= et
->getents();
99 vecfromyawpitch(camera1
->yaw
, camera1
->pitch
, 1, 0, viewdir
);
100 extern const vector
<int> &checklightcache(int x
, int y
);
101 const vector
<int> &lights
= checklightcache(int(camera1
->o
.x
), int(camera1
->o
.y
));
104 entity
&e
= *ents
[lights
[i
]];
105 if(e
.type
!= ET_LIGHT
) continue;
106 bool sun
= (e
.attr1
==0);
107 float radius
= float(e
.attr1
);
108 vec flaredir
= vec(e
.o
).sub(camera1
->o
);
109 float len
= flaredir
.magnitude();
110 if(!sun
&& (len
> radius
)) continue;
111 if(isvisiblesphere(0.0f
, e
.o
) > (sun
?VFC_FOGGED
:VFC_FULL_VISIBLE
)) continue;
112 vec center
= vec(viewdir
).mul(flaredir
.dot(viewdir
)).add(camera1
->o
);
117 size
= len
* flaresize
/ 100.0f
;
121 mod
= (radius
-len
)/radius
;
122 size
= flaresize
/ 5.0f
;
124 newflare(e
.o
, center
, e
.attr2
, e
.attr3
, e
.attr4
, mod
, size
, sun
, sun
);
135 return (numflares
!= 0) && !glaring
&& !reflecting
&& !refracting
;
140 bool fog
= glIsEnabled(GL_FOG
)==GL_TRUE
;
141 if(fog
) glDisable(GL_FOG
);
142 defaultshader
->set();
143 glDisable(GL_DEPTH_TEST
);
144 if(!tex
) tex
= textureload(texname
);
145 glBindTexture(GL_TEXTURE_2D
, tex
->id
);
150 vec center
= f
->center
;
151 vec axis
= vec(f
->o
).sub(center
);
152 uchar color
[4] = {f
->color
[0], f
->color
[1], f
->color
[2], 255};
153 loopj(f
->sparkle
?12:9)
155 const flaretype
&ft
= flaretypes
[j
];
156 vec o
= vec(axis
).mul(ft
.loc
).add(center
);
157 float sz
= ft
.scale
* f
->size
;
159 if(ft
.type
< 0) //sparkles - always done last
161 shinetime
= (shinetime
+ 1) % 10;
166 color
[-ft
.type
-1] = f
->color
[-ft
.type
-1]; //only want a single channel
170 const float tsz
= 0.25; //flares are aranged in 4x4 grid
171 float tx
= tsz
*(tex
&0x03);
172 float ty
= tsz
*((tex
>>2)&0x03);
173 glTexCoord2f(tx
, ty
+tsz
); glVertex3f(o
.x
+(-camright
.x
+camup
.x
)*sz
, o
.y
+(-camright
.y
+camup
.y
)*sz
, o
.z
+(-camright
.z
+camup
.z
)*sz
);
174 glTexCoord2f(tx
+tsz
, ty
+tsz
); glVertex3f(o
.x
+( camright
.x
+camup
.x
)*sz
, o
.y
+( camright
.y
+camup
.y
)*sz
, o
.z
+( camright
.z
+camup
.z
)*sz
);
175 glTexCoord2f(tx
+tsz
, ty
); glVertex3f(o
.x
+( camright
.x
-camup
.x
)*sz
, o
.y
+( camright
.y
-camup
.y
)*sz
, o
.z
+( camright
.z
-camup
.z
)*sz
);
176 glTexCoord2f(tx
, ty
); glVertex3f(o
.x
+(-camright
.x
-camup
.x
)*sz
, o
.y
+(-camright
.y
-camup
.y
)*sz
, o
.z
+(-camright
.z
-camup
.z
)*sz
);
180 glEnable(GL_DEPTH_TEST
);
181 if(fog
) glEnable(GL_FOG
);
184 //square per round hole - use addflare(..) instead
185 particle
*addpart(const vec
&o
, const vec
&d
, int fade
, int color
, float size
) { return NULL
; }
187 static flarerenderer
flares("packages/particles/lensflares.png", 64);