Initial sauer
[SauerbratenRemote.git] / src / engine / material.cpp
blob4a64719fb8aeeb94420e1927598151fc0d52abe5
1 #include "pch.h"
2 #include "engine.h"
4 struct QuadNode
6 int x, y, size;
7 uint filled;
8 QuadNode *child[4];
10 QuadNode(int x, int y, int size) : x(x), y(y), size(size), filled(0) { loopi(4) child[i] = 0; }
12 void clear()
14 loopi(4) DELETEP(child[i]);
17 ~QuadNode()
19 clear();
22 void insert(int mx, int my, int msize)
24 if(size == msize)
26 filled = 0xF;
27 return;
29 int csize = size>>1, i = 0;
30 if(mx >= x+csize) i |= 1;
31 if(my >= y+csize) i |= 2;
32 if(csize == msize)
34 filled |= (1 << i);
35 return;
37 if(!child[i]) child[i] = new QuadNode(i&1 ? x+csize : x, i&2 ? y+csize : y, csize);
38 child[i]->insert(mx, my, msize);
39 loopj(4) if(child[j])
41 if(child[j]->filled == 0xF)
43 DELETEP(child[j]);
44 filled |= (1 << j);
49 void genmatsurf(uchar mat, uchar orient, int x, int y, int z, int size, materialsurface *&matbuf)
51 materialsurface &m = *matbuf++;
52 m.material = mat;
53 m.orient = orient;
54 m.csize = size;
55 m.rsize = size;
56 int dim = dimension(orient);
57 m.o[C[dim]] = x;
58 m.o[R[dim]] = y;
59 m.o[dim] = z;
62 void genmatsurfs(uchar mat, uchar orient, int z, materialsurface *&matbuf)
64 if(filled == 0xF) genmatsurf(mat, orient, x, y, z, size, matbuf);
65 else if(filled)
67 int csize = size>>1;
68 loopi(4) if(filled & (1 << i))
69 genmatsurf(mat, orient, i&1 ? x+csize : x, i&2 ? y+csize : y, z, csize, matbuf);
71 loopi(4) if(child[i]) child[i]->genmatsurfs(mat, orient, z, matbuf);
75 void renderwaterfall(materialsurface &m, Texture *tex, float scale, float offset, uchar mat)
77 float xf = 8.0f/(tex->xs*scale);
78 float yf = 8.0f/(tex->ys*scale);
79 float d = 16.0f*lastmillis;
80 int dim = dimension(m.orient),
81 csize = C[dim]==2 ? m.rsize : m.csize,
82 rsize = R[dim]==2 ? m.rsize : m.csize;
83 float t = lastmillis;
84 switch(mat)
86 case MAT_WATER:
87 t /= renderpath!=R_FIXEDFUNCTION ? 600.0f : 300.0f;
88 d /= 1000.0f;
89 break;
90 case MAT_LAVA:
91 t /= 2000.0f;
92 d /= 3000.0f;
93 break;
95 float wave = m.ends&2 ? (vertwater ? WATER_AMPLITUDE*sinf(t)-WATER_OFFSET : -WATER_OFFSET) : 0;
96 loopi(4)
98 vec v(m.o.tovec());
99 v[dim] += dimcoord(m.orient) ? -offset : offset;
100 if(i==1 || i==2) v[dim^1] += csize;
101 if(i<=1) v.z += rsize;
102 if(m.ends&(i<=1 ? 2 : 1)) v.z += i<=1 ? wave : -WATER_OFFSET-WATER_AMPLITUDE;
103 glTexCoord2f(xf*v[dim^1], yf*(v.z+d));
104 glVertex3fv(v.v);
107 xtraverts += 4;
110 void drawmaterial(int orient, int x, int y, int z, int csize, int rsize, float offset)
112 int dim = dimension(orient), c = C[dim], r = R[dim];
113 loopi(4)
115 int coord = fv[orient][i];
116 vec v(x, y, z);
117 v[c] += cubecoords[coord][c]/8*csize;
118 v[r] += cubecoords[coord][r]/8*rsize;
119 v[dim] += dimcoord(orient) ? -offset : offset;
120 glVertex3fv(v.v);
122 xtraverts += 4;
125 struct material
127 const char *name;
128 uchar id;
129 } materials[] =
131 {"air", MAT_AIR},
132 {"water", MAT_WATER},
133 {"clip", MAT_CLIP},
134 {"glass", MAT_GLASS},
135 {"noclip", MAT_NOCLIP},
136 {"lava", MAT_LAVA},
137 {"aiclip", MAT_AICLIP}
140 int findmaterial(const char *name)
142 loopi(sizeof(materials)/sizeof(material))
144 if(!strcmp(materials[i].name, name)) return materials[i].id;
146 return -1;
149 int visiblematerial(cube &c, int orient, int x, int y, int z, int size)
151 if(c.ext) switch(c.ext->material)
153 case MAT_AIR:
154 break;
156 case MAT_LAVA:
157 case MAT_WATER:
158 if(visibleface(c, orient, x, y, z, size, c.ext->material))
159 return (orient != O_BOTTOM ? MATSURF_VISIBLE : MATSURF_EDIT_ONLY);
160 break;
162 case MAT_GLASS:
163 if(visibleface(c, orient, x, y, z, size, MAT_GLASS))
164 return MATSURF_VISIBLE;
165 break;
167 default:
168 if(visibleface(c, orient, x, y, z, size, c.ext->material))
169 return MATSURF_EDIT_ONLY;
170 break;
172 return MATSURF_NOT_VISIBLE;
175 void genmatsurfs(cube &c, int cx, int cy, int cz, int size, vector<materialsurface> &matsurfs)
177 loopi(6)
179 int vis = visiblematerial(c, i, cx, cy, cz, size);
180 if(vis != MATSURF_NOT_VISIBLE)
182 materialsurface m;
183 m.material = (vis == MATSURF_EDIT_ONLY ? c.ext->material+MAT_EDIT : c.ext->material);
184 m.orient = i;
185 m.o = ivec(cx, cy, cz);
186 m.csize = m.rsize = size;
187 if(dimcoord(i)) m.o[dimension(i)] += size;
188 matsurfs.add(m);
193 static int mergematcmp(const materialsurface *x, const materialsurface *y)
195 int dim = dimension(x->orient), c = C[dim], r = R[dim];
196 if(x->o[r] + x->rsize < y->o[r] + y->rsize) return -1;
197 if(x->o[r] + x->rsize > y->o[r] + y->rsize) return 1;
198 if(x->o[c] < y->o[c]) return -1;
199 if(x->o[c] > y->o[c]) return 1;
200 return 0;
203 static int mergematr(materialsurface *m, int sz, materialsurface &n)
205 int dim = dimension(n.orient), c = C[dim], r = R[dim];
206 for(int i = sz-1; i >= 0; --i)
208 if(m[i].o[r] + m[i].rsize < n.o[r]) break;
209 if(m[i].o[r] + m[i].rsize == n.o[r] && m[i].o[c] == n.o[c] && m[i].csize == n.csize)
211 n.o[r] = m[i].o[r];
212 n.rsize += m[i].rsize;
213 memmove(&m[i], &m[i+1], (sz - (i+1)) * sizeof(materialsurface));
214 return 1;
217 return 0;
220 static int mergematc(materialsurface &m, materialsurface &n)
222 int dim = dimension(n.orient), c = C[dim], r = R[dim];
223 if(m.o[r] == n.o[r] && m.rsize == n.rsize && m.o[c] + m.csize == n.o[c])
225 n.o[c] = m.o[c];
226 n.csize += m.csize;
227 return 1;
229 return 0;
232 static int mergemat(materialsurface *m, int sz, materialsurface &n)
234 for(bool merged = false; sz; merged = true)
236 int rmerged = mergematr(m, sz, n);
237 sz -= rmerged;
238 if(!rmerged && merged) break;
239 if(!sz) break;
240 int cmerged = mergematc(m[sz-1], n);
241 sz -= cmerged;
242 if(!cmerged) break;
244 m[sz++] = n;
245 return sz;
248 static int mergemats(materialsurface *m, int sz)
250 qsort(m, sz, sizeof(materialsurface), (int (__cdecl *)(const void *, const void *))mergematcmp);
252 int nsz = 0;
253 loopi(sz) nsz = mergemat(m, nsz, m[i]);
254 return nsz;
257 static int optmatcmp(const materialsurface *x, const materialsurface *y)
259 if(x->material < y->material) return -1;
260 if(x->material > y->material) return 1;
261 if(x->orient > y->orient) return -1;
262 if(x->orient < y->orient) return 1;
263 int dim = dimension(x->orient), xc = x->o[dim], yc = y->o[dim];
264 if(xc < yc) return -1;
265 if(xc > yc) return 1;
266 return 0;
269 VARF(optmats, 0, 1, 1, allchanged());
271 int optimizematsurfs(materialsurface *matbuf, int matsurfs)
273 qsort(matbuf, matsurfs, sizeof(materialsurface), (int (__cdecl *)(const void*, const void*))optmatcmp);
274 if(!optmats) return matsurfs;
275 materialsurface *cur = matbuf, *end = matbuf+matsurfs;
276 while(cur < end)
278 materialsurface *start = cur++;
279 int dim = dimension(start->orient);
280 while(cur < end &&
281 cur->material == start->material &&
282 cur->orient == start->orient &&
283 cur->o[dim] == start->o[dim])
284 ++cur;
285 if(!isliquid(start->material) || start->orient != O_TOP || !vertwater)
287 if(start!=matbuf) memmove(matbuf, start, (cur-start)*sizeof(materialsurface));
288 matbuf += mergemats(matbuf, cur-start);
290 else if(cur-start>=4)
292 QuadNode vmats(0, 0, hdr.worldsize);
293 loopi(cur-start) vmats.insert(start[i].o[C[dim]], start[i].o[R[dim]], start[i].csize);
294 vmats.genmatsurfs(start->material, start->orient, start->o[dim], matbuf);
296 else
298 if(start!=matbuf) memmove(matbuf, start, (cur-start)*sizeof(materialsurface));
299 matbuf += cur-start;
302 return matsurfs - (end-matbuf);
305 extern vector<vtxarray *> valist;
307 struct waterinfo
309 materialsurface *m;
310 double depth, area;
313 void setupmaterials()
315 int hasmat = 0;
316 vector<waterinfo> water;
317 hashtable<ivec, int> watersets;
318 unionfind uf;
319 loopv(valist)
321 vtxarray *va = valist[i];
322 lodlevel &lod = va->l0;
323 loopj(lod.matsurfs)
325 materialsurface &m = lod.matbuf[j];
326 if(m.material==MAT_WATER && m.orient==O_TOP)
328 m.index = water.length();
329 loopvk(water)
331 materialsurface &n = *water[k].m;
332 if(m.o.z!=n.o.z) continue;
333 if(n.o.x+n.rsize==m.o.x || m.o.x+m.rsize==n.o.x)
335 if(n.o.y+n.csize>m.o.y && n.o.y<m.o.y+m.csize) uf.unite(m.index, n.index);
337 else if(n.o.y+n.csize==m.o.y || m.o.y+m.csize==n.o.y)
339 if(n.o.x+n.rsize>m.o.x && n.o.x<m.o.x+m.rsize) uf.unite(m.index, n.index);
342 waterinfo &wi = water.add();
343 wi.m = &m;
344 vec center(m.o.x+m.rsize/2, m.o.y+m.csize/2, m.o.z-WATER_OFFSET);
345 m.light = brightestlight(center, vec(0, 0, 1));
346 float depth = raycube(center, vec(0, 0, -1), 10000);
347 wi.depth = double(depth)*m.rsize*m.csize;
348 wi.area = m.rsize*m.csize;
350 else if(isliquid(m.material) && m.orient!=O_BOTTOM && m.orient!=O_TOP)
352 m.ends = 0;
353 int dim = dimension(m.orient), coord = dimcoord(m.orient);
354 ivec o(m.o);
355 o.z -= 1;
356 o[dim] += coord ? 1 : -1;
357 int minc = o[dim^1], maxc = minc + (C[dim]==2 ? m.rsize : m.csize);
358 while(o[dim^1] < maxc)
360 cube &c = lookupcube(o.x, o.y, o.z);
361 if(c.ext && isliquid(c.ext->material)) { m.ends |= 1; break; }
362 o[dim^1] += lusize;
364 o[dim^1] = minc;
365 o.z += R[dim]==2 ? m.rsize : m.csize;
366 o[dim] -= coord ? 2 : -2;
367 while(o[dim^1] < maxc)
369 cube &c = lookupcube(o.x, o.y, o.z);
370 if(visiblematerial(c, O_TOP, lu.x, lu.y, lu.z, lusize)) { m.ends |= 2; break; }
371 o[dim^1] += lusize;
374 else if(m.material==MAT_GLASS)
376 if(!hasCM) m.envmap = EMID_NONE;
377 else
379 int dim = dimension(m.orient);
380 vec center(m.o.tovec());
381 center[R[dim]] += m.rsize/2;
382 center[C[dim]] += m.csize/2;
383 m.envmap = closestenvmap(center);
386 hasmat |= 1<<m.material;
389 loopv(water)
391 int root = uf.find(i);
392 if(i==root) continue;
393 materialsurface &m = *water[i].m, &n = *water[root].m;
394 if(m.light && (!m.light->attr1 || !n.light || (n.light->attr1 && m.light->attr1 > n.light->attr1))) n.light = m.light;
395 water[root].depth += water[i].depth;
396 water[root].area += water[i].area;
398 loopv(water)
400 int root = uf.find(i);
401 water[i].m->light = water[root].m->light;
402 water[i].m->depth = (short)(water[root].depth/water[root].area);
404 if(hasmat&(1<<MAT_WATER))
406 extern void loadcaustics();
407 loadcaustics();
408 lookuptexture(-MAT_WATER);
410 if(hasmat&(1<<MAT_LAVA)) lookuptexture(-MAT_LAVA);
413 VARP(showmat, 0, 1, 1);
415 static int sortdim[3];
416 static ivec sortorigin;
418 static int vismatcmp(const materialsurface ** xm, const materialsurface ** ym)
420 const materialsurface &x = **xm, &y = **ym;
421 int xdim = dimension(x.orient), ydim = dimension(y.orient);
422 loopi(3)
424 int dim = sortdim[i], xmin, xmax, ymin, ymax;
425 xmin = xmax = x.o[dim];
426 if(dim==C[xdim]) xmax += x.csize;
427 else if(dim==R[xdim]) xmax += x.rsize;
428 ymin = ymax = y.o[dim];
429 if(dim==C[ydim]) ymax += y.csize;
430 else if(dim==R[ydim]) ymax += y.rsize;
431 if(xmax > ymin && ymax > xmin) continue;
432 int c = sortorigin[dim];
433 if(c > xmin && c < xmax) return 1;
434 if(c > ymin && c < ymax) return -1;
435 xmin = abs(xmin - c);
436 xmax = abs(xmax - c);
437 ymin = abs(ymin - c);
438 ymax = abs(ymax - c);
439 if(max(xmin, xmax) <= min(ymin, ymax)) return 1;
440 else if(max(ymin, ymax) <= min(xmin, xmax)) return -1;
442 if(x.material < y.material) return 1;
443 if(x.material > y.material) return -1;
444 return 0;
447 extern vtxarray *visibleva, *reflectedva;
449 void sortmaterials(vector<materialsurface *> &vismats, float zclip, bool refract)
451 bool reflected = zclip && !refract && camera1->o.z >= zclip;
452 sortorigin = ivec(camera1->o);
453 if(reflected) sortorigin.z = int(zclip - (camera1->o.z - zclip));
454 vec dir;
455 vecfromyawpitch(camera1->yaw, reflected ? -camera1->pitch : camera1->pitch, 1, 0, dir);
456 loopi(3) { dir[i] = fabs(dir[i]); sortdim[i] = i; }
457 if(dir[sortdim[2]] > dir[sortdim[1]]) swap(int, sortdim[2], sortdim[1]);
458 if(dir[sortdim[1]] > dir[sortdim[0]]) swap(int, sortdim[1], sortdim[0]);
459 if(dir[sortdim[2]] > dir[sortdim[1]]) swap(int, sortdim[2], sortdim[1]);
461 for(vtxarray *va = reflected ? reflectedva : visibleva; va; va = reflected ? va->rnext : va->next)
463 lodlevel &lod = va->l0;
464 if(!lod.matsurfs || va->occluded >= OCCLUDE_BB) continue;
465 if(zclip && (refract ? va->z >= zclip : va->z+va->size <= zclip)) continue;
466 loopi(lod.matsurfs)
468 materialsurface &m = lod.matbuf[i];
469 if(!editmode || !showmat)
471 if(m.material==MAT_WATER && m.orient==O_TOP) continue;
472 if(m.material>=MAT_EDIT) continue;
474 vismats.add(&m);
477 vismats.sort(vismatcmp);
480 void rendermatgrid(vector<materialsurface *> &vismats)
482 glEnable(GL_POLYGON_OFFSET_LINE);
483 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
484 static uchar cols[MAT_EDIT][3] =
486 { 0, 0, 0 }, // MAT_AIR - no edit volume,
487 { 0, 0, 85 }, // MAT_WATER - blue,
488 { 85, 0, 0 }, // MAT_CLIP - red,
489 { 0, 85, 85 }, // MAT_GLASS - cyan,
490 { 0, 85, 0 }, // MAT_NOCLIP - green
491 { 85, 40, 0 }, // MAT_LAVA - orange
492 { 85, 85, 0 }, // MAT_AICLIP - yellow
494 int lastmat = -1;
495 glBegin(GL_QUADS);
496 loopv(vismats)
498 materialsurface &m = *vismats[i];
499 int curmat = m.material >= MAT_EDIT ? m.material-MAT_EDIT : m.material;
500 if(curmat != lastmat)
502 lastmat = curmat;
503 glColor3ubv(cols[curmat]);
505 drawmaterial(m.orient, m.o.x, m.o.y, m.o.z, m.csize, m.rsize, -0.1f);
507 glEnd();
508 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
509 glDisable(GL_POLYGON_OFFSET_LINE);
512 VARP(glassenv, 0, 1, 1);
514 void drawglass(int orient, int x, int y, int z, int csize, int rsize, float offset)
516 int dim = dimension(orient), c = C[dim], r = R[dim];
517 loopi(4)
519 int coord = fv[orient][i];
520 vec v(x, y, z);
521 v[c] += cubecoords[coord][c]/8*csize;
522 v[r] += cubecoords[coord][r]/8*rsize;
523 v[dim] += dimcoord(orient) ? -offset : offset;
525 vec reflect(v);
526 reflect.sub(camera1->o);
527 reflect[dim] = -reflect[dim];
529 glTexCoord3f(-reflect.y, reflect.z, reflect.x);
530 glVertex3fv(v.v);
532 xtraverts += 4;
535 void rendermaterials(float zclip, bool refract)
537 vector<materialsurface *> vismats;
538 sortmaterials(vismats, zclip, refract);
539 if(vismats.empty()) return;
541 glDisable(GL_CULL_FACE);
543 Slot &wslot = lookuptexture(-MAT_WATER), &lslot = lookuptexture(-MAT_LAVA);
544 uchar wcol[4] = { 128, 128, 128, 192 };
545 if(hdr.watercolour[0] || hdr.watercolour[1] || hdr.watercolour[2]) memcpy(wcol, hdr.watercolour, 3);
546 int lastorient = -1, lastmat = -1;
547 GLenum textured = GL_TEXTURE_2D;
548 bool begin = false, depth = true, blended = false, overbright = false;
549 ushort envmapped = EMID_NONE;
550 vec normal(0, 0, 0);
552 static float zerofog[4] = { 0, 0, 0, 1 };
553 float oldfogc[4];
554 glGetFloatv(GL_FOG_COLOR, oldfogc);
555 int lastfogtype = 1;
556 loopv(vismats)
558 materialsurface &m = *vismats[editmode && showmat ? vismats.length()-1-i : i];
559 int curmat = !editmode || !showmat || m.material>=MAT_EDIT ? m.material : m.material+MAT_EDIT;
560 if(lastmat!=curmat || lastorient!=m.orient || (curmat==MAT_GLASS && envmapped && m.envmap != envmapped))
562 int fogtype = lastfogtype;
563 switch(curmat)
565 case MAT_WATER:
566 if(lastmat==MAT_WATER && lastorient!=O_TOP && m.orient!=O_TOP) break;
567 if(begin) { glEnd(); begin = false; }
568 if(lastmat!=MAT_WATER || (lastorient==O_TOP)!=(m.orient==O_TOP))
570 if(depth) { glDepthMask(GL_FALSE); depth = false; }
571 if(!blended) { glEnable(GL_BLEND); blended = true; }
572 if(overbright) { resettmu(0); overbright = false; }
573 if(m.orient==O_TOP)
575 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
576 glColor4ubv(wcol);
578 else
580 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
581 glColor3f(wcol[0]/255.0f, wcol[1]/255.0f, wcol[2]/255.0f);
583 foggedshader->set();
584 fogtype = 0;
586 if(textured!=GL_TEXTURE_2D)
588 if(textured) glDisable(textured);
589 glEnable(GL_TEXTURE_2D);
590 textured = GL_TEXTURE_2D;
592 glBindTexture(GL_TEXTURE_2D, wslot.sts[m.orient==O_TOP ? 0 : 1].t->gl);
593 break;
595 case MAT_LAVA:
596 if(lastmat==MAT_LAVA && lastorient!=O_TOP && m.orient!=O_TOP) break;
597 if(begin) { glEnd(); begin = false; }
598 if(lastmat!=MAT_LAVA)
600 if(!depth) { glDepthMask(GL_TRUE); depth = true; }
601 if(blended) { glDisable(GL_BLEND); blended = false; }
602 if(renderpath==R_FIXEDFUNCTION && !overbright) { setuptmu(0, "C * T x 2"); overbright = true; }
603 float t = lastmillis/2000.0f;
604 t -= int(t);
605 t = 1.0f - fabs(t-0.5f);
606 glColor3f(t, t, t);
607 static Shader *lavashader = NULL;
608 if(!lavashader) lavashader = lookupshaderbyname("lava");
609 lavashader->set();
610 fogtype = 1;
612 if(textured!=GL_TEXTURE_2D)
614 if(textured) glDisable(textured);
615 glEnable(GL_TEXTURE_2D);
616 textured = GL_TEXTURE_2D;
618 glBindTexture(GL_TEXTURE_2D, lslot.sts[m.orient==O_TOP ? 0 : 1].t->gl);
619 break;
621 case MAT_GLASS:
622 if(m.envmap!=EMID_NONE && glassenv && (lastmat!=MAT_GLASS || lastorient!=m.orient))
623 normal = vec(dimension(m.orient)==0 ? dimcoord(m.orient)*2-1 : 0,
624 dimension(m.orient)==1 ? dimcoord(m.orient)*2-1 : 0,
625 dimension(m.orient)==2 ? dimcoord(m.orient)*2-1 : 0);
626 if((m.envmap==EMID_NONE || !glassenv || (envmapped==m.envmap && textured==GL_TEXTURE_CUBE_MAP_ARB)) && lastmat==MAT_GLASS) break;
627 if(begin) { glEnd(); begin = false; }
628 if(m.envmap!=EMID_NONE && glassenv)
630 if(textured!=GL_TEXTURE_CUBE_MAP_ARB)
632 if(textured) glDisable(textured);
633 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
634 textured = GL_TEXTURE_CUBE_MAP_ARB;
636 if(envmapped!=m.envmap)
638 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, lookupenvmap(m.envmap));
639 if(envmapped==EMID_NONE && renderpath!=R_FIXEDFUNCTION)
640 setenvparamf("camera", SHPARAM_VERTEX, 0, camera1->o.x, camera1->o.y, camera1->o.z);
641 envmapped = m.envmap;
644 if(lastmat!=MAT_GLASS)
646 if(!blended) { glEnable(GL_BLEND); blended = true; }
647 if(overbright) { resettmu(0); overbright = false; }
648 if(depth) { glDepthMask(GL_FALSE); depth = false; }
649 if(m.envmap!=EMID_NONE && glassenv)
651 if(renderpath==R_FIXEDFUNCTION)
653 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
654 glColor4f(0.8f, 0.9f, 1.0f, 0.25f);
655 fogtype = 1;
657 else
659 glBlendFunc(GL_ONE, GL_SRC_ALPHA);
660 glColor3f(0, 0.5f, 1.0f);
662 static Shader *glassshader = NULL;
663 if(!glassshader) glassshader = lookupshaderbyname("glass");
664 glassshader->set();
666 else
668 if(textured)
670 glDisable(textured);
671 textured = 0;
673 glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
674 glColor3f(0.3f, 0.15f, 0.0f);
675 foggednotextureshader->set();
676 fogtype = 0;
679 break;
681 default:
683 if(lastmat==curmat) break;
684 if(lastmat<MAT_EDIT)
686 if(begin) { glEnd(); begin = false; }
687 if(!depth) { glDepthMask(GL_TRUE); depth = true; }
688 if(!blended) { glEnable(GL_BLEND); blended = true; }
689 if(overbright) { resettmu(0); overbright = false; }
690 glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
691 if(textured) { glDisable(GL_TEXTURE_2D); textured = 0; }
692 foggednotextureshader->set();
693 fogtype = 0;
695 static uchar blendcols[MAT_EDIT][3] =
697 { 0, 0, 0 }, // MAT_AIR - no edit volume,
698 { 255, 128, 0 }, // MAT_WATER - blue,
699 { 0, 255, 255 }, // MAT_CLIP - red,
700 { 255, 0, 0 }, // MAT_GLASS - cyan,
701 { 255, 0, 255 }, // MAT_NOCLIP - green
702 { 0, 128, 255 }, // MAT_LAVA - orange
703 { 0, 0, 255 }, // MAT_AICLIP - yellow
705 glColor3ubv(blendcols[curmat >= MAT_EDIT ? curmat-MAT_EDIT : curmat]);
706 break;
709 lastmat = curmat;
710 lastorient = m.orient;
711 if(fogtype!=lastfogtype)
713 glFogfv(GL_FOG_COLOR, fogtype ? oldfogc : zerofog);
714 lastfogtype = fogtype;
717 switch(curmat)
719 case MAT_WATER:
720 if(m.orient!=O_TOP)
722 if(!begin) { glBegin(GL_QUADS); begin = true; }
723 renderwaterfall(m, wslot.sts[1].t, wslot.sts[1].scale ? wslot.sts[1].scale : 1, 0.1f, MAT_WATER);
725 break;
727 case MAT_LAVA:
728 if(m.orient==O_TOP)
730 if(!vertwater && !begin) { glBegin(GL_QUADS); begin = true; }
731 renderlava(m, lslot.sts[0].t, lslot.sts[0].scale ? lslot.sts[0].scale : 1);
733 else
735 if(!begin) { glBegin(GL_QUADS); begin = true; }
736 renderwaterfall(m, lslot.sts[1].t, lslot.sts[1].scale ? lslot.sts[1].scale : 1, 0.1f, MAT_LAVA);
738 break;
740 case MAT_GLASS:
741 if(!begin) { glBegin(GL_QUADS); begin = true; }
742 if(m.envmap!=EMID_NONE && glassenv)
744 if(renderpath!=R_FIXEDFUNCTION) glNormal3fv(normal.v);
745 drawglass(m.orient, m.o.x, m.o.y, m.o.z, m.csize, m.rsize, 0.1f);
747 else drawmaterial(m.orient, m.o.x, m.o.y, m.o.z, m.csize, m.rsize, 0.1f);
748 break;
750 default:
751 if(!begin) { glBegin(GL_QUADS); begin = true; }
752 drawmaterial(m.orient, m.o.x, m.o.y, m.o.z, m.csize, m.rsize, -0.1f);
753 break;
757 if(begin) glEnd();
758 if(!depth) glDepthMask(GL_TRUE);
759 if(blended) glDisable(GL_BLEND);
760 if(overbright) resettmu(0);
761 if(!lastfogtype) glFogfv(GL_FOG_COLOR, oldfogc);
762 if(editmode && showmat)
764 foggednotextureshader->set();
765 rendermatgrid(vismats);
768 glEnable(GL_CULL_FACE);
769 if(textured!=GL_TEXTURE_2D)
771 if(textured) glDisable(textured);
772 glEnable(GL_TEXTURE_2D);