1 #include "engine.h"
2 
3 Texture *sky[6] = { 0, 0, 0, 0, 0, 0 }, *clouds[6] = { 0, 0, 0, 0, 0, 0 };
4 
loadsky(const char * basename,Texture * texs[6])5 void loadsky(const char *basename, Texture *texs[6])
6 {
7 	bool fail = false;
8 	loopi(6)
9 	{
10 		const char *side = cubemapsides[i].name;
11 		defformatstring(name)("%s_%s", basename, side);
12 		if((texs[i] = textureload(name, 3, true, false)) == notexture)
13 		{
14 			conoutf("\frcould not load sky texture %s_%s", basename, side);
15 			fail = true;
16 		}
17 	}
18 }
19 
20 Texture *cloudoverlay = NULL;
21 
loadskyoverlay(const char * basename)22 Texture *loadskyoverlay(const char *basename)
23 {
24 	Texture *t = textureload(basename, 0, true, false);
25 	if(t == notexture) conoutf("\frcould not load sky overlay texture %s", basename);
26 	return t;
27 }
28 
29 HVARW(skybgcolour, 0, 0x000000, 0xFFFFFF);
30 VARW(skybgglare, 0, 0, 1);
31 
32 SVARFW(skybox, "", { if(skybox[0]) loadsky(skybox, sky); });
33 FVARW(skyblend, 0, 1.0f, 1);
34 VARW(skyglare, 0, 1, 1);
35 HVARW(skycolour, 0, 0xFFFFFF, 0xFFFFFF);
36 FVARW(spinsky, -720, 0, 720);
37 VARW(yawsky, 0, 0, 360);
38 
39 SVARFW(cloudbox, "", { if(cloudbox[0]) loadsky(cloudbox, clouds); });
40 FVARW(cloudblend, 0, 1.0f, 1);
41 VARW(cloudglare, 0, 0, 1);
42 HVARW(cloudcolour, 0, 0xFFFFFF, 0xFFFFFF);
43 FVARW(spinclouds, -720, 0, 720);
44 VARW(yawclouds, 0, 0, 360);
45 
46 SVARFW(cloudlayer, "", { if(cloudlayer[0]) cloudoverlay = loadskyoverlay(cloudlayer); });
47 FVARW(cloudlayerblend, 0, 1.0f, 1);
48 VARW(cloudlayerglare, 0, 0, 1);
49 HVARW(cloudlayercolour, 0, 0xFFFFFF, 0xFFFFFF);
50 FVARW(cloudscrollx, -16, 0, 16);
51 FVARW(cloudscrolly, -16, 0, 16);
52 FVARW(cloudscale, 0, 1, 64);
53 FVARW(spincloudlayer, -720, 0, 720);
54 VARW(yawcloudlayer, 0, 0, 360);
55 FVARW(cloudheight, -1, 0.2f, 1);
56 FVARW(cloudfade, 0, 0.2f, 1);
57 VARW(cloudsubdiv, 4, 16, 64);
58 
59 FVARW(cloudclip, 0, 0.5f, 1);
60 
draw_envbox_face(float s0,float t0,int x0,int y0,int z0,float s1,float t1,int x1,int y1,int z1,float s2,float t2,int x2,int y2,int z2,float s3,float t3,int x3,int y3,int z3,GLuint texture)61 void draw_envbox_face(float s0, float t0, int x0, int y0, int z0,
62 					  float s1, float t1, int x1, int y1, int z1,
63 					  float s2, float t2, int x2, int y2, int z2,
64 					  float s3, float t3, int x3, int y3, int z3,
65 					  GLuint texture)
66 {
67 	glBindTexture(GL_TEXTURE_2D, texture);
68 	glBegin(GL_QUADS);
69 	glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
70 	glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
71 	glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
72 	glTexCoord2f(s0, t0); glVertex3f(x0, y0, z0);
73 	glEnd();
74 	xtraverts += 4;
75 }
76 
draw_envbox_quad(int x0,int y0,int z0,int x1,int y1,int z1,int x2,int y2,int z2,int x3,int y3,int z3)77 void draw_envbox_quad(int x0, int y0, int z0,
78 					  int x1, int y1, int z1,
79 					  int x2, int y2, int z2,
80 					  int x3, int y3, int z3)
81 {
82 	glBegin(GL_QUADS);
83 	glVertex3f(x3, y3, z3);
84 	glVertex3f(x2, y2, z2);
85 	glVertex3f(x1, y1, z1);
86 	glVertex3f(x0, y0, z0);
87 	glEnd();
88 	xtraverts += 4;
89 }
90 
draw_envbox(int w,float zclip=0.0f,int faces=0x3F,Texture ** sky=NULL)91 void draw_envbox(int w, float zclip = 0.0f, int faces = 0x3F, Texture **sky = NULL)
92 {
93 	float vclip = 1-zclip;
94 	int z = int(ceil(2*w*(vclip-0.5f)));
95 
96 	if(faces&0x01)
97 		draw_envbox_face(0.0f, 0.0f, -w, -w, -w,
98 						 1.0f, 0.0f, -w,  w, -w,
99 						 1.0f, vclip, -w,  w,  z,
100 						 0.0f, vclip, -w, -w,  z, sky && sky[0] ? sky[0]->id : notexture->id);
101 
102 	if(faces&0x02)
103 		draw_envbox_face(1.0f, vclip, +w, -w,  z,
104 						 0.0f, vclip, +w,  w,  z,
105 						 0.0f, 0.0f, +w,  w, -w,
106 						 1.0f, 0.0f, +w, -w, -w, sky && sky[1] ? sky[1]->id : notexture->id);
107 
108 	if(faces&0x04)
109 		draw_envbox_face(1.0f, vclip, -w, -w,  z,
110 						 0.0f, vclip,  w, -w,  z,
111 						 0.0f, 0.0f,  w, -w, -w,
112 						 1.0f, 0.0f, -w, -w, -w, sky && sky[2] ? sky[2]->id : notexture->id);
113 
114 	if(faces&0x08)
115 		draw_envbox_face(1.0f, vclip, +w,  w,  z,
116 						 0.0f, vclip, -w,  w,  z,
117 						 0.0f, 0.0f, -w,  w, -w,
118 						 1.0f, 0.0f, +w,  w, -w, sky && sky[3] ? sky[3]->id : notexture->id);
119 
120 	if(!zclip && faces&0x10)
121 		draw_envbox_face(0.0f, 1.0f, -w,  w,  w,
122 						 0.0f, 0.0f, +w,  w,  w,
123 						 1.0f, 0.0f, +w, -w,  w,
124 						 1.0f, 1.0f, -w, -w,  w, sky && sky[4] ? sky[4]->id : notexture->id);
125 
126 	if(faces&0x20)
127 		draw_envbox_face(0.0f, 1.0f, +w,  w, -w,
128 						 0.0f, 0.0f, -w,  w, -w,
129 						 1.0f, 0.0f, -w, -w, -w,
130 						 1.0f, 1.0f, +w, -w, -w, sky && sky[5] ? sky[5]->id : notexture->id);
131 }
132 
draw_envbox_bg(int w)133 void draw_envbox_bg(int w)
134 {
135 	draw_envbox_quad(-w, -w, -w, -w, w, -w, -w, w, w, -w, -w, w);
136 	draw_envbox_quad(+w, -w, w, +w, w, w, +w, w, -w, +w, -w, -w);
137 	draw_envbox_quad(-w, -w, w, w, -w, w, w, -w, -w, -w, -w, -w);
138 	draw_envbox_quad(+w, w, w, -w, w, w, -w, w, -w, +w, w, -w);
139 	draw_envbox_quad(-w, w, w, +w, w, w, +w, -w, w, -w, -w, w);
140 	draw_envbox_quad(+w, w, -w, -w, w, -w, -w, -w, -w, +w, -w, -w);
141 }
142 
draw_env_overlay(int w,Texture * overlay=NULL,int colour=0xFFFFFF,float a=1.f,float tx=0,float ty=0)143 void draw_env_overlay(int w, Texture *overlay = NULL, int colour = 0xFFFFFF, float a = 1.f, float tx = 0, float ty = 0)
144 {
145 	float z = -w*cloudheight, tsz = 0.5f*(1-cloudfade)/cloudscale, psz = w*(1-cloudfade);
146 	glBindTexture(GL_TEXTURE_2D, overlay ? overlay->id : notexture->id);
147 	float r = (colour>>16)/255.0f, g = ((colour>>8)&255)/255.0f, b = (colour&255)/255.0f;
148 	glColor4f(r, g, b, a);
149 	glBegin(GL_POLYGON);
150 	loopi(cloudsubdiv)
151 	{
152 		vec p(1, 1, 0);
153 		p.rotate_around_z((-2.0f*M_PI*i)/cloudsubdiv);
154 		glTexCoord2f(tx + p.x*tsz, ty + p.y*tsz); glVertex3f(p.x*psz, p.y*psz, z);
155 	}
156 	glEnd();
157 	float tsz2 = 0.5f/cloudscale;
158 	glBegin(GL_QUAD_STRIP);
159 	loopi(cloudsubdiv+1)
160 	{
161 		vec p(1, 1, 0);
162 		p.rotate_around_z((-2.0f*M_PI*i)/cloudsubdiv);
163 		glColor4f(r, g, b, a);
164 		glTexCoord2f(tx + p.x*tsz, ty + p.y*tsz); glVertex3f(p.x*psz, p.y*psz, z);
165 		glColor4f(r, g, b, 0);
166 		glTexCoord2f(tx + p.x*tsz2, ty + p.y*tsz2); glVertex3f(p.x*w, p.y*w, z);
167 	}
168 	glEnd();
169 }
170 
171 static struct domevert
172 {
173     vec pos;
174     uchar color[4];
175 
domevertdomevert176     domevert() {}
domevertdomevert177     domevert(const vec &pos, float alpha) : pos(pos)
178     {
179         memcpy(color, fogcolor.v, 3);
180         color[3] = uchar(alpha*255);
181     }
domevertdomevert182     domevert(const domevert &v0, const domevert &v1) : pos(vec(v0.pos).add(v1.pos).normalize())
183     {
184         memcpy(color, v0.color, 4);
185         if(v0.pos.z != v1.pos.z) color[3] += uchar((v1.color[3] - v0.color[3]) * (pos.z - v0.pos.z) / (v1.pos.z - v0.pos.z));
186     }
187 } *domeverts = NULL;
188 static GLushort *domeindices = NULL;
189 static int domenumverts = 0, domenumindices = 0, domecapindices = 0;
190 static GLuint domevbuf = 0, domeebuf = 0;
191 static bvec domecolor(0, 0, 0);
192 static float domeminalpha = 0, domemaxalpha = 0, domecapsize = -1;
193 
194 static void subdivide(int depth, int face);
195 
genface(int depth,int i1,int i2,int i3)196 static void genface(int depth, int i1, int i2, int i3)
197 {
198     int face = domenumindices; domenumindices += 3;
199     domeindices[face]   = i3;
200     domeindices[face+1] = i2;
201     domeindices[face+2] = i1;
202     subdivide(depth, face);
203 }
204 
subdivide(int depth,int face)205 static void subdivide(int depth, int face)
206 {
207     if(depth-- <= 0) return;
208     int idx[6];
209     loopi(3) idx[i] = domeindices[face+2-i];
210     loopi(3)
211     {
212         int vert = domenumverts++;
213         domeverts[vert] = domevert(domeverts[idx[i]], domeverts[idx[(i+1)%3]]); //push on to unit sphere
214         idx[3+i] = vert;
215         domeindices[face+2-i] = vert;
216     }
217     subdivide(depth, face);
218     loopi(3) genface(depth, idx[i], idx[3+i], idx[3+(i+2)%3]);
219 }
220 
sortdomecap(const GLushort * x,const GLushort * y)221 static int sortdomecap(const GLushort *x, const GLushort *y)
222 {
223     const vec &xv = domeverts[*x].pos, &yv = domeverts[*y].pos;
224     if(xv.y < 0)
225     {
226         if(yv.y >= 0 || xv.x < yv.x) return -1;
227         if(xv.x > yv.x) return 1;
228     }
229     else if(yv.y < 0 || xv.x < yv.x) return 1;
230     else if(xv.x > yv.x) return -1;
231     return 0;
232 }
233 
initdome(float minalpha=0.0f,float maxalpha=1.0f,float capsize=-1,int hres=16,int depth=2)234 static void initdome(float minalpha = 0.0f, float maxalpha = 1.0f, float capsize = -1, int hres = 16, int depth = 2)
235 {
236     const int tris = hres << (2*depth);
237     domenumverts = domenumindices = domecapindices = 0;
238     DELETEA(domeverts);
239     DELETEA(domeindices);
240     domeverts = new domevert[tris+1 + (capsize >= 0 ? 1 : 0)];
241     domeindices = new GLushort[(tris + (capsize >= 0 ? hres<<depth : 0))*3];
242     domeverts[domenumverts++] = domevert(vec(0.0f, 0.0f, 1.0f), minalpha); //build initial 'hres' sided pyramid
243     loopi(hres)
244     {
245         float angle = 2*M_PI*float(i)/hres;
246         domeverts[domenumverts++] = domevert(vec(cosf(angle), sinf(angle), 0.0f), maxalpha);
247     }
248     loopi(hres) genface(depth, 0, i+1, 1+(i+1)%hres);
249 
250     if(capsize >= 0)
251     {
252         GLushort *domecap = &domeindices[domenumindices];
253         int domecapverts = 0;
254         loopi(domenumverts) if(!domeverts[i].pos.z) domecap[domecapverts++] = i;
255         domeverts[domenumverts++] = domevert(vec(0.0f, 0.0f, -capsize), maxalpha);
256         quicksort(domecap, domecapverts, sortdomecap);
257         loopi(domecapverts)
258         {
259             int n = domecapverts-1-i;
260             domecap[n*3] = domecap[n];
261             domecap[n*3+1] = domecap[(n+1)%domecapverts];
262             domecap[n*3+2] = domenumverts-1;
263             domecapindices += 3;
264         }
265     }
266 
267     if(hasVBO)
268     {
269         if(!domevbuf) glGenBuffers_(1, &domevbuf);
270         glBindBuffer_(GL_ARRAY_BUFFER_ARB, domevbuf);
271         glBufferData_(GL_ARRAY_BUFFER_ARB, domenumverts*sizeof(domevert), domeverts, GL_STATIC_DRAW_ARB);
272         DELETEA(domeverts);
273 
274         if(!domeebuf) glGenBuffers_(1, &domeebuf);
275         glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER_ARB, domeebuf);
276         glBufferData_(GL_ELEMENT_ARRAY_BUFFER_ARB, (domenumindices + domecapindices)*sizeof(GLushort), domeindices, GL_STATIC_DRAW_ARB);
277         DELETEA(domeindices);
278     }
279 }
280 
deletedome()281 static void deletedome()
282 {
283     domenumverts = domenumindices = 0;
284     if(domevbuf) { glDeleteBuffers_(1, &domevbuf); domevbuf = 0; }
285     if(domeebuf) { glDeleteBuffers_(1, &domeebuf); domeebuf = 0; }
286     DELETEA(domeverts);
287     DELETEA(domeindices);
288 }
289 
290 FVARW(fogdomeheight, -1, -0.5f, 1);
291 FVARW(fogdomemin, 0, 0, 1);
292 FVARW(fogdomemax, 0, 0, 1);
293 VARW(fogdomecap, 0, 0, 1);
294 
drawdome()295 static void drawdome()
296 {
297     float capsize = fogdomecap && fogdomeheight < 1 ? (1 + fogdomeheight) / (1 - fogdomeheight) : -1;
298     if(!domenumverts || domecolor != fogcolor || domeminalpha != fogdomemin || domemaxalpha != fogdomemax || domecapsize != capsize)
299     {
300         initdome(min(fogdomemin, fogdomemax), fogdomemax, capsize);
301         domecolor = fogcolor;
302         domeminalpha = fogdomemin;
303         domemaxalpha = fogdomemax;
304         domecapsize = capsize;
305     }
306 
307     if(hasVBO)
308     {
309         glBindBuffer_(GL_ARRAY_BUFFER_ARB, domevbuf);
310         glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER_ARB, domeebuf);
311     }
312 
313     glEnableClientState(GL_VERTEX_ARRAY);
314     glEnableClientState(GL_COLOR_ARRAY);
315     glVertexPointer(3, GL_FLOAT, sizeof(domevert), &domeverts->pos);
316     glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(domevert), &domeverts->color);
317 
318     if(hasDRE) glDrawRangeElements_(GL_TRIANGLES, 0, domenumverts-1, domenumindices + fogdomecap*domecapindices, GL_UNSIGNED_SHORT, domeindices);
319     else glDrawElements(GL_TRIANGLES, domenumindices + fogdomecap*domecapindices, GL_UNSIGNED_SHORT, domeindices);
320     xtraverts += domenumverts;
321     glde++;
322 
323     glDisableClientState(GL_VERTEX_ARRAY);
324     glDisableClientState(GL_COLOR_ARRAY);
325 
326     if(hasVBO)
327     {
328         glBindBuffer_(GL_ARRAY_BUFFER_ARB, 0);
329         glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
330     }
331 }
332 
cleanupsky()333 void cleanupsky()
334 {
335     deletedome();
336 }
337 
338 VARP(sparklyfix, 0, 0, 1);
339 VAR(showsky, 0, 1, 1);
340 VAR(clipsky, 0, 1, 1);
341 
drawskylimits(bool explicitonly)342 bool drawskylimits(bool explicitonly)
343 {
344 	nocolorshader->set();
345 
346 	glDisable(GL_TEXTURE_2D);
347 	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
348 	bool rendered = rendersky(explicitonly);
349 	glColorMask(COLORMASK, GL_TRUE);
350 	glEnable(GL_TEXTURE_2D);
351 
352 	return rendered;
353 }
354 
drawskyoutline()355 void drawskyoutline()
356 {
357 	notextureshader->set();
358 
359 	glDisable(GL_TEXTURE_2D);
360 	glDepthMask(GL_FALSE);
361 	extern int wireframe;
362 	if(!wireframe)
363 	{
364 		enablepolygonoffset(GL_POLYGON_OFFSET_LINE);
365 		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
366 	}
367 	glColor3f(0.5f, 0.0f, 0.5f);
368 	rendersky(true);
369 	if(!wireframe)
370 	{
371 		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
372 		disablepolygonoffset(GL_POLYGON_OFFSET_LINE);
373 	}
374 	glDepthMask(GL_TRUE);
375 	glEnable(GL_TEXTURE_2D);
376 
377 	if(!glaring) defaultshader->set();
378 }
379 
380 VAR(clampsky, 0, 1, 1);
381 
yawskyfaces(int faces,int yaw=0,float spin=0)382 static int yawskyfaces(int faces, int yaw = 0, float spin = 0)
383 {
384 	if(spin || yaw%90) return faces&0x0F ? faces | 0x0F : faces;
385 	static const int faceidxs[3][4] =
386 	{
387 		{ 3, 2, 0, 1 },
388 		{ 1, 0, 3, 2 },
389 		{ 2, 3, 1, 0 }
390 	};
391 	yaw /= 90;
392 	if(yaw < 1 || yaw > 3) return faces;
393 	const int *idxs = faceidxs[yaw - 1];
394 	return (faces & ~0x0F) | (((faces>>idxs[0])&1)<<0) | (((faces>>idxs[1])&1)<<1) | (((faces>>idxs[2])&1)<<2) | (((faces>>idxs[3])&1)<<3);
395 }
396 
drawskybox(int farplane,bool limited)397 void drawskybox(int farplane, bool limited)
398 {
399 	extern int renderedskyfaces, renderedskyclip; // , renderedsky, renderedexplicitsky;
400 	bool alwaysrender = editmode || !insideworld(camera1->o) || reflecting,
401 		 explicitonly = false;
402 	if(limited)
403 	{
404 		explicitonly = alwaysrender || !sparklyfix || refracting;
405 		if(!drawskylimits(explicitonly) && !alwaysrender) return;
406 		extern int ati_skybox_bug;
407 		if(!alwaysrender && !renderedskyfaces && !ati_skybox_bug) explicitonly = false;
408 	}
409 	else if(!alwaysrender)
410 	{
411 		extern vtxarray *visibleva;
412 		renderedskyfaces = 0;
413 		renderedskyclip = INT_MAX;
414 		for(vtxarray *va = visibleva; va; va = va->next)
415 		{
416 			if(va->occluded >= OCCLUDE_BB && va->skyfaces&0x80) continue;
417 			renderedskyfaces |= va->skyfaces&0x3F;
418 			if(!(va->skyfaces&0x1F) || camera1->o.z < va->skyclip) renderedskyclip = min(renderedskyclip, va->skyclip);
419 			else renderedskyclip = 0;
420 		}
421 		if(!renderedskyfaces) return;
422 	}
423 
424 	if(alwaysrender)
425 	{
426 		renderedskyfaces = 0x3F;
427 		renderedskyclip = 0;
428 	}
429 
430 	float skyclip = clipsky ? max(renderedskyclip-1, 0) : 0;
431 	if(reflectz<hdr.worldsize && reflectz>skyclip) skyclip = reflectz;
432 
433 	if(renderpath!=R_FIXEDFUNCTION || !fogging) glDisable(GL_FOG);
434 
435 	if(limited)
436 	{
437 		if(explicitonly) glDisable(GL_DEPTH_TEST);
438 		else glDepthFunc(GL_GEQUAL);
439 	}
440 	else glDepthFunc(GL_LEQUAL);
441 
442 	glDepthMask(GL_FALSE);
443 
444 	if(clampsky) glDepthRange(1, 1);
445 
446 	bool blendsky = !skybox[0] || !sky[0] || sky[0]->bpp >= 4;
447 
448 	if((!glaring || skybgglare) && blendsky)
449 	{
450 		glDisable(GL_TEXTURE_2D);
451 		notextureshader->set();
452 
453 		glPushMatrix();
454 		glLoadIdentity();
455 		glRotatef(camera1->roll, 0, 0, 1);
456 		glRotatef(camera1->pitch, -1, 0, 0);
457 		glRotatef(camera1->yaw, 0, 1, 0);
458 		glRotatef(90, 1, 0, 0);
459 		if(reflecting) glScalef(1, 1, -1);
460 		glColor3f((skybgcolour>>16)/255.0f, ((skybgcolour>>8)&255)/255.0f, (skybgcolour&255)/255.0f);
461 		draw_envbox_bg(farplane/2);
462 		glPopMatrix();
463 
464 		glEnable(GL_TEXTURE_2D);
465 	}
466 
467 	if(glaring)
468 	{
469 		static Shader *skyboxglareshader = NULL;
470 		if(!skyboxglareshader) skyboxglareshader = lookupshaderbyname("skyboxglare");
471 		skyboxglareshader->set();
472 	}
473 	else defaultshader->set();
474 
475 	if((!glaring || skyglare) && skybox[0])
476 	{
477 		if(fading) glColorMask(COLORMASK, GL_FALSE);
478 
479 		if(blendsky)
480 		{
481 			glEnable(GL_BLEND);
482 			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
483 		}
484 
485 		glPushMatrix();
486 		glLoadIdentity();
487 		glRotatef(camera1->roll, 0, 0, 1);
488 		glRotatef(camera1->pitch, -1, 0, 0);
489 		glRotatef(camera1->yaw+spinsky*lastmillis/1000.0f+yawsky, 0, 1, 0);
490 		glRotatef(90, 1, 0, 0);
491 		if(reflecting) glScalef(1, 1, -1);
492 		glColor4f((skycolour>>16)/255.0f, ((skycolour>>8)&255)/255.0f, (skycolour&255)/255.0f, skyblend);
493 		draw_envbox(farplane/2, skyclip ? 0.5f + 0.5f*(skyclip-camera1->o.z)/float(hdr.worldsize) : 0, yawskyfaces(renderedskyfaces, yawsky, spinsky), sky);
494 		glPopMatrix();
495 
496 		if(blendsky) glDisable(GL_BLEND);
497 	}
498 
499 	if((!glaring || cloudglare) && cloudbox[0])
500 	{
501 		if(fading) glColorMask(COLORMASK, GL_FALSE);
502 
503 		glEnable(GL_BLEND);
504 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
505 
506 		glPushMatrix();
507 		glLoadIdentity();
508 		glRotatef(camera1->roll, 0, 0, 1);
509 		glRotatef(camera1->pitch, -1, 0, 0);
510 		glRotatef(camera1->yaw+spinclouds*lastmillis/1000.0f+yawclouds, 0, 1, 0);
511 		glRotatef(90, 1, 0, 0);
512 		if(reflecting) glScalef(1, 1, -1);
513 		glColor4f((cloudcolour>>16)/255.0f, ((cloudcolour>>8)&255)/255.0f, (cloudcolour&255)/255.0f, cloudblend);
514 		draw_envbox(farplane/2, skyclip ? 0.5f + 0.5f*(skyclip-camera1->o.z)/float(hdr.worldsize) : cloudclip, yawskyfaces(renderedskyfaces, yawclouds, spinclouds), clouds);
515 		glPopMatrix();
516 
517 		glDisable(GL_BLEND);
518 	}
519 
520 	if((!glaring || cloudlayerglare) && cloudlayer[0] && cloudheight && renderedskyfaces&(cloudheight < 0 ? 0x1F : 0x2F))
521 	{
522 		if(fading) glColorMask(COLORMASK, GL_FALSE);
523 
524 		glDisable(GL_CULL_FACE);
525 
526 		glEnable(GL_BLEND);
527 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
528 
529 		glPushMatrix();
530 		glLoadIdentity();
531 		glRotatef(camera1->roll, 0, 0, 1);
532 		glRotatef(camera1->pitch, -1, 0, 0);
533 		glRotatef(camera1->yaw+spincloudlayer*lastmillis/1000.0f+yawcloudlayer, 0, 1, 0);
534 		glRotatef(90, 1, 0, 0);
535 		if(reflecting) glScalef(1, 1, -1);
536 		draw_env_overlay(farplane/2, cloudoverlay, cloudlayercolour, cloudlayerblend, cloudscrollx * lastmillis/1000.0f, cloudscrolly * lastmillis/1000.0f);
537 		glPopMatrix();
538 
539 		glDisable(GL_BLEND);
540 
541 		glEnable(GL_CULL_FACE);
542 	}
543 
544     if(!glaring && fogdomemax)
545     {
546         if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
547 
548         notextureshader->set();
549         glDisable(GL_TEXTURE_2D);
550 
551         glEnable(GL_BLEND);
552         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
553 
554         glPushMatrix();
555         glLoadIdentity();
556         glRotatef(camera1->roll, 0, 0, 1);
557         glRotatef(camera1->pitch, -1, 0, 0);
558         glRotatef(camera1->yaw, 0, 1, 0);
559         glRotatef(90, 1, 0, 0);
560         if(reflecting) glScalef(1, 1, -1);
561         glTranslatef(0, 0, -farplane*fogdomeheight*0.5f);
562         glScalef(farplane/2, farplane/2, -farplane*(0.5f - fogdomeheight*0.5f));
563         drawdome();
564         glPopMatrix();
565 
566         glDisable(GL_BLEND);
567         glEnable(GL_TEXTURE_2D);
568     }
569 
570 	if(clampsky) glDepthRange(0, 1);
571 
572 	glDepthMask(GL_TRUE);
573 
574 	if(limited)
575 	{
576 		if(explicitonly) glEnable(GL_DEPTH_TEST);
577 		else glDepthFunc(GL_LESS);
578 		if(!reflecting && !refracting && !envmapping && editmode && showsky) drawskyoutline();
579 	}
580 	else glDepthFunc(GL_LESS);
581 
582 	if(renderpath!=R_FIXEDFUNCTION || !fogging) glEnable(GL_FOG);
583 }
584 
585 VARNW(skytexture, useskytexture, 0, 1, 1);
586 
587 int explicitsky = 0;
588 double skyarea = 0;
589 
limitsky()590 bool limitsky()
591 {
592 	return (explicitsky && (useskytexture || editmode)) || (sparklyfix && skyarea / (double(hdr.worldsize)*double(hdr.worldsize)*6) < 0.9);
593 }
594 
595