~ubuntu-branches/ubuntu/hardy/sauerbraten/hardy-backports

« back to all changes in this revision

Viewing changes to engine/renderva.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bruno "Fuddl" Kleinert, Bruno "Fuddl" Kleinert, Cyril Brulebois
  • Date: 2007-08-26 17:45:25 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826174525-uiv5yjjk092m95cl
Tags: 0.0.20070819.dfsg-1
[ Bruno "Fuddl" Kleinert ]
* Update the Debian menu file to the latest menu structure
* Remove 10_save_and_load_maps_from_home_directory.dpatch (Upstream solved
  this in this release) (Closes: #426691)
* Remove 10_search_home_for_config.dpatch (Upstream solved this in this
  release)
* Add 10_fix_clean_target.dpatch to avoid calling autotools in clean target
* Add NEWS.Debian

[ Cyril Brulebois ]
* Added XS-Vcs-Svn and XS-Vcs-Browser fields in the control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
#include "pch.h"
4
4
#include "engine.h"
5
5
 
 
6
void drawvatris(vtxarray *va, GLsizei numindices, const GLvoid *indices, ushort minvert = 0, ushort maxvert = 0)
 
7
{
 
8
    if(!minvert && !maxvert) { minvert = va->minvert; maxvert = va->maxvert; }
 
9
    if(hasDRE) glDrawRangeElements_(GL_TRIANGLES, minvert, maxvert, numindices, GL_UNSIGNED_SHORT, indices);
 
10
    else glDrawElements(GL_TRIANGLES, numindices, GL_UNSIGNED_SHORT, indices);
 
11
    glde++;
 
12
}
 
13
 
6
14
///////// view frustrum culling ///////////////////////
7
15
 
8
16
plane vfcP[5];  // perpindictular vectors to view frustrum bounding planes
116
124
    vfcP[2].toplane(vec(yaw, pitch + pitchd), camera); // top plane
117
125
    vfcP[3].toplane(vec(yaw, pitch - pitchd), camera); // bottom plane
118
126
    vfcP[4].toplane(vec(yaw, pitch), camera);          // near/far planes
119
 
    vfcDfog = getvar("fog");
 
127
    extern int fog;
 
128
    vfcDfog = fog;
120
129
}
121
130
 
122
131
plane oldvfcP[5];
179
188
    }
180
189
}
181
190
 
182
 
void setupTMU()
183
 
{
184
 
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
185
 
    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT,  GL_MODULATE);
186
 
    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT,  GL_PREVIOUS_EXT);
187
 
    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
188
 
    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT,  GL_TEXTURE);
189
 
    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
190
 
}
191
 
 
192
191
///////// occlusion queries /////////////
193
192
 
194
193
#define MAXQUERY 2048
234
233
    loopi(2) loopj(queryframes[i].max) queryframes[i].queries[j].owner = NULL;
235
234
}
236
235
 
 
236
void clearqueries()
 
237
{
 
238
    loopi(2)
 
239
    {
 
240
        queryframe &qf = queryframes[i];
 
241
        loopj(qf.max) glDeleteQueries_(1, &qf.queries[j].id);
 
242
        qf.cur = qf.max = 0;
 
243
    }
 
244
}
 
245
 
237
246
VAR(oqfrags, 0, 8, 64);
238
247
VAR(oqreflect, 0, 4, 64);
239
248
 
350
359
        case TRIGGER_RESETTING: anim = ANIM_TRIGGER|ANIM_REVERSE; basetime = e.lasttrigger; break;
351
360
    }
352
361
    mapmodelinfo &mmi = getmminfo(e.attr2);
353
 
    if(&mmi) rendermodel(e.color, e.dir, mmi.name, anim, 0, mmi.tex, e.o.x, e.o.y, e.o.z, (float)((e.attr1+7)-(e.attr1+7)%15), 0, 10.0f, basetime, NULL, MDL_CULL_VFC | MDL_CULL_DIST);
 
362
    if(&mmi) rendermodel(e.color, e.dir, mmi.name, anim, 0, mmi.tex, e.o, (float)((e.attr1+7)-(e.attr1+7)%15), 0, 0, basetime, NULL, MDL_CULL_VFC | MDL_CULL_DIST);
354
363
}
355
364
 
356
365
extern int reflectdist;
387
396
           e.visible = true;
388
397
        }
389
398
    }
390
 
    loopv(mms)
 
399
    if(mms.length())
391
400
    {
392
 
        octaentities *oe = mms[i];
393
 
        loopv(oe->mapmodels)
 
401
        startmodelbatches();
 
402
        loopv(mms)
394
403
        {
395
 
           extentity &e = *ents[oe->mapmodels[i]];
396
 
           if(!e.visible) continue;
397
 
           rendermapmodel(e);
398
 
           e.visible = false;
 
404
            octaentities *oe = mms[i];
 
405
            loopv(oe->mapmodels)
 
406
            {
 
407
                extentity &e = *ents[oe->mapmodels[i]];
 
408
                if(!e.visible) continue;
 
409
                rendermapmodel(e);
 
410
                e.visible = false;
 
411
            }
399
412
        }
 
413
        endmodelbatches();
400
414
    }
401
415
    if(reflected) restorevfcP();
402
416
}
410
424
    findvisiblemms(ents);
411
425
 
412
426
    static int skipoq = 0;
 
427
    bool doquery = hasOQ && oqfrags && oqmm;
413
428
 
414
429
    renderedmms.setsizenodelete(0);
415
 
 
416
 
    for(octaentities *oe = visiblemms; oe; oe = oe->next)
417
 
    {
418
 
        bool occluded = oe->distance < 0;
419
 
        if(!occluded)
420
 
        {
421
 
            bool hasmodels = false;
422
 
            loopv(oe->mapmodels)
423
 
            {
424
 
                const extentity &e = *ents[oe->mapmodels[i]];
425
 
                if(!e.visible || (e.attr3 && e.triggerstate == TRIGGER_DISAPPEARED)) continue;
426
 
                hasmodels = true;
427
 
                break;
428
 
            }
429
 
            if(!hasmodels) continue;
430
 
        }
431
 
 
432
 
        if(!hasOQ || !oqfrags || !oqmm || !oe->distance) oe->query = NULL;
433
 
        else if(!occluded && (++skipoq % oqmm)) oe->query = NULL;
434
 
        else oe->query = newquery(oe);
435
 
 
436
 
        if(oe->query)
437
 
        {
438
 
            if(occluded)
439
 
            {
440
 
                glDepthMask(GL_FALSE);
441
 
                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
442
 
            }
443
 
            startquery(oe->query);
444
 
        }
445
 
        if(!occluded || oe->query)
446
 
        {
447
 
            ivec bbmin(oe->o), bbmax(oe->o);
448
 
            bbmin.add(oe->size);
449
 
            bool rendered = false;
450
 
            loopv(oe->mapmodels)
451
 
            {
452
 
                extentity &e = *ents[oe->mapmodels[i]];
453
 
                if(e.attr3 && e.triggerstate == TRIGGER_DISAPPEARED) continue;
454
 
                if(occluded)
455
 
                {
456
 
                    ivec bo, br;
457
 
                    if(getentboundingbox(e, bo, br))
458
 
                    {
459
 
                        loopj(3)
460
 
                        {
461
 
                            bbmin[j] = min(bbmin[j], bo[j]);
462
 
                            bbmax[j] = max(bbmax[j], bo[j]+br[j]);
463
 
                        }
464
 
                    }
465
 
                }
466
 
                else if(e.visible)
467
 
                {
468
 
                    if(!rendered) { renderedmms.add(oe); rendered = true; }
469
 
                    rendermapmodel(e);
470
 
                    e.visible = false;
471
 
                }
472
 
            }
473
 
            if(occluded)
474
 
            {
475
 
                loopj(3)
476
 
                {
477
 
                    bbmin[j] = max(bbmin[j], oe->o[j]);
478
 
                    bbmax[j] = min(bbmax[j], oe->o[j]+oe->size);
479
 
                }
480
 
                drawbb(bbmin, bbmax.sub(bbmin));
481
 
            }
482
 
        }
483
 
        if(oe->query)
484
 
        {
485
 
            endquery(oe->query);
486
 
            if(occluded)
487
 
            {
488
 
                glDepthMask(GL_TRUE);
489
 
                glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
490
 
            }
491
 
        }
 
430
    startmodelbatches();
 
431
    for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance>=0)
 
432
    {
 
433
        loopv(oe->mapmodels)
 
434
        {
 
435
            extentity &e = *ents[oe->mapmodels[i]];
 
436
            if(!e.visible || (e.attr3 && e.triggerstate == TRIGGER_DISAPPEARED)) continue;
 
437
            if(renderedmms.empty() || renderedmms.last()!=oe)
 
438
            {
 
439
                renderedmms.add(oe);
 
440
                oe->query = doquery && oe->distance>0 && !(++skipoq%oqmm) ? newquery(oe) : NULL;
 
441
                if(oe->query) startmodelquery(oe->query);
 
442
            }        
 
443
            rendermapmodel(e);
 
444
            e.visible = false;
 
445
        }
 
446
        if(renderedmms.length() && renderedmms.last()==oe && oe->query) endmodelquery();
 
447
    }
 
448
    endmodelbatches();
 
449
 
 
450
    bool colormask = true;
 
451
    for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance<0)
 
452
    {
 
453
        oe->query = doquery ? newquery(oe) : NULL;
 
454
        if(!oe->query) continue;
 
455
        if(colormask)
 
456
        {
 
457
            glDepthMask(GL_FALSE);
 
458
            glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
 
459
            nocolorshader->set();
 
460
            colormask = false;
 
461
        }
 
462
        startquery(oe->query);
 
463
        drawbb(oe->bbmin, ivec(oe->bbmax).sub(oe->bbmin));
 
464
        endquery(oe->query);
 
465
    }
 
466
    if(!colormask)
 
467
    {
 
468
        glDepthMask(GL_TRUE);
 
469
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
492
470
    }
493
471
}
494
472
 
553
531
        }
554
532
        if(vbufchanged) glVertexPointer(3, floatvtx ? GL_FLOAT : GL_SHORT, VTXSIZE, &(va->vbuf[0].x));
555
533
 
556
 
        glDrawElements(GL_TRIANGLES, 3*lod.tris, GL_UNSIGNED_SHORT, lod.ebuf);
557
 
        glde++;
 
534
        drawvatris(va, 3*lod.tris, lod.ebuf);
558
535
        xtravertsva += va->verts;
559
536
    }
560
537
 
597
574
    GLfloat fogc[4] = {1, 1, 1, 1};
598
575
    glFogfv(GL_FOG_COLOR, fogc);
599
576
 
600
 
    GLfloat s[4] = { 0.0055f, 0, 0.0033f, 0 };
601
 
    GLfloat t[4] = { 0, 0.0055f, 0.0033f, 0 };
 
577
    GLfloat s[4] = { 0.011f, 0, 0.0066f, 0 };
 
578
    GLfloat t[4] = { 0, 0.011f, 0.0066f, 0 };
602
579
    loopk(3)
603
580
    {
604
 
        s[k] *= 100.0f/causticscale;
605
 
        t[k] *= 100.0f/causticscale;
 
581
        s[k] *= 100.0f/(causticscale<<VVEC_FRAC);
 
582
        t[k] *= 100.0f/(causticscale<<VVEC_FRAC);
606
583
    }
607
584
 
608
585
    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
671
648
        }
672
649
        if(vbufchanged) glVertexPointer(3, floatvtx ? GL_FLOAT : GL_SHORT, VTXSIZE, &(va->vbuf[0].x));
673
650
 
674
 
        glDrawElements(GL_TRIANGLES, 3*lod.tris, GL_UNSIGNED_SHORT, lod.ebuf);
675
 
        glde++;
 
651
        drawvatris(va, 3*lod.tris, lod.ebuf);
676
652
        xtravertsva += va->verts;
677
653
    }
678
654
 
701
677
    glFogfv(GL_FOG_COLOR, oldfogc);
702
678
}
703
679
 
 
680
VARP(maxdynlights, 0, MAXDYNLIGHTS, MAXDYNLIGHTS);
 
681
VARP(dynlightdist, 0, 1024, 10000);
 
682
 
 
683
struct dynlight
 
684
{
 
685
    vec o;
 
686
    float radius, dist;
 
687
    vec color;
 
688
    int fade, peak, expire;
 
689
 
 
690
    float calcradius() const
 
691
    {
 
692
        return peak>0 && expire-lastmillis>fade ? (radius/peak)*(peak-(expire-lastmillis-fade)) : radius;
 
693
    }
 
694
    
 
695
    float intensity() const
 
696
    {
 
697
        if(fade + peak)
 
698
        {
 
699
            int remaining = expire - lastmillis;
 
700
            return remaining > fade ? 1.0f - float(remaining - fade)/peak : float(remaining)/fade;
 
701
        }
 
702
        return 1.0f;
 
703
    }
 
704
};
 
705
 
 
706
vector<dynlight> dynlights;
 
707
vector<dynlight *> closedynlights, visibledynlights;
 
708
 
 
709
void adddynlight(const vec &o, float radius, const vec &color, int fade, int peak)
 
710
{
 
711
    if(o.dist(camera1->o) > dynlightdist) return;
 
712
 
 
713
    int insert = 0, expire = fade + peak + lastmillis;
 
714
    loopvrev(dynlights) if(expire>=dynlights[i].expire) { insert = i+1; break; }
 
715
    dynlight d;
 
716
    d.o = o;
 
717
    d.radius = radius;
 
718
    d.color = color;
 
719
    d.fade = fade;
 
720
    d.peak = peak;
 
721
    d.expire = expire;
 
722
    dynlights.insert(insert, d);
 
723
}
 
724
 
 
725
void cleardynlights()
 
726
{
 
727
    int faded = -1;
 
728
    loopv(dynlights) if(lastmillis<dynlights[i].expire) { faded = i; break; }
 
729
    if(faded<0) dynlights.setsizenodelete(0);
 
730
    else if(faded>0) dynlights.remove(0, faded);
 
731
}
 
732
 
 
733
int limitdynlights()
 
734
{
 
735
    closedynlights.setsizenodelete(0);
 
736
    if(maxdynlights) loopvj(dynlights)
 
737
    {
 
738
        dynlight &d = dynlights[j];
 
739
        d.dist = camera1->o.dist(d.o) - d.calcradius();
 
740
        if(d.dist>dynlightdist || isvisiblesphere(d.radius, d.o) >= VFC_FOGGED) continue;
 
741
        int insert = 0;
 
742
        loopvrev(closedynlights) if(d.dist >= closedynlights[i]->dist) { insert = i+1; break; }
 
743
        if(closedynlights.length()>=maxdynlights)
 
744
        {
 
745
            if(insert+1>=maxdynlights) continue;
 
746
            closedynlights.drop();
 
747
        }
 
748
        closedynlights.insert(insert, &d);
 
749
    }
 
750
    return closedynlights.length();
 
751
}
 
752
 
 
753
void dynlightreaching(const vec &target, vec &color, vec &dir)
 
754
{
 
755
    vec dyncolor(0, 0, 0);//, dyndir(0, 0, 0);
 
756
    loopv(dynlights)
 
757
    {
 
758
        dynlight &d = dynlights[i];
 
759
        vec ray(d.o);
 
760
        ray.sub(target);
 
761
        float mag = ray.magnitude(), radius = d.calcradius();
 
762
        if(radius<=0 || mag >= radius) continue;
 
763
        float intensity = d.intensity()*(1 - mag/radius);
 
764
        dyncolor.add(vec(d.color).mul(intensity));
 
765
        //dyndir.add(ray.mul(intensity/mag));
 
766
    }
 
767
#if 0
 
768
    if(!dyndir.iszero())
 
769
    {
 
770
        dyndir.normalize();
 
771
        float x = dyncolor.magnitude(), y = color.magnitude();
 
772
        if(x+y>0)
 
773
        {
 
774
            dir.mul(x);
 
775
            dyndir.mul(y); 
 
776
            dir.add(dyndir).div(x+y);
 
777
            if(dir.iszero()) dir = vec(0, 0, 1);
 
778
            else dir.normalize();
 
779
        }
 
780
    }
 
781
#endif
 
782
    color.add(dyncolor);
 
783
}    
 
784
 
 
785
void setdynlights(vtxarray *va)
 
786
{
 
787
    visibledynlights.setsizenodelete(0);
 
788
    loopv(closedynlights)
 
789
    {
 
790
        dynlight &d = *closedynlights[i];
 
791
        if(d.o.dist_to_bb(va->min, va->max) < d.calcradius()) visibledynlights.add(&d);
 
792
    }
 
793
    if(visibledynlights.empty()) return;
 
794
 
 
795
    static string vertexparams[MAXDYNLIGHTS] = { "" }, pixelparams[MAXDYNLIGHTS] = { "" };
 
796
    if(!*vertexparams[0]) loopi(MAXDYNLIGHTS)
 
797
    {
 
798
        s_sprintf(vertexparams[i])("dynlight%dpos", i);
 
799
        s_sprintf(pixelparams[i])("dynlight%dcolor", i);
 
800
    }
 
801
 
 
802
    loopv(visibledynlights)
 
803
    {
 
804
        dynlight &d = *visibledynlights[i];
 
805
        setenvparamfv(vertexparams[i], SHPARAM_VERTEX, 10+i, vec4(d.o, 1).sub(ivec(va->x, va->y, va->z).mask(~VVEC_INT_MASK).tovec()).mul(1<<VVEC_FRAC).v);
 
806
        vec color(d.color);
 
807
        color.mul(2*d.intensity());
 
808
        float radius = d.calcradius();
 
809
        setenvparamf(pixelparams[i], SHPARAM_PIXEL, 10+i, color.x, color.y, color.z, -1.0f/(radius*radius*(1<<(2*VVEC_FRAC))));
 
810
    }
 
811
}
 
812
 
704
813
float orientation_tangent [3][4] = { {  0,1, 0,0 }, { 1,0, 0,0 }, { 1,0,0,0 }};
705
814
float orientation_binormal[3][4] = { {  0,0,-1,0 }, { 0,0,-1,0 }, { 0,1,0,0 }};
706
815
 
750
859
    endquery(query);
751
860
}
752
861
 
753
 
void renderva(renderstate &cur, vtxarray *va, lodlevel &lod, bool zfill = false)
754
 
{
 
862
enum
 
863
{
 
864
    RENDERPASS_LIGHTMAP = 0,
 
865
    RENDERPASS_COLOR,
 
866
    RENDERPASS_Z,
 
867
    RENDERPASS_GLOW
 
868
};
 
869
 
 
870
void renderva(renderstate &cur, vtxarray *va, lodlevel &lod, int pass = RENDERPASS_LIGHTMAP)
 
871
{
 
872
    if(pass==RENDERPASS_GLOW)
 
873
    {
 
874
        bool noglow = true;
 
875
        loopi(lod.texs)
 
876
        {
 
877
            Slot &slot = lookuptexture(lod.eslist[i].texture);
 
878
            loopvj(slot.sts)
 
879
            {
 
880
                Slot::Tex &t = slot.sts[j];
 
881
                if(t.type==TEX_GLOW && t.combined<0) noglow = false;
 
882
            }
 
883
        }
 
884
        if(noglow) return;
 
885
    }
 
886
 
755
887
    setorigin(va);
756
888
    bool vbufchanged = true;
757
889
    if(hasVBO)
771
903
    if(vbufchanged) glVertexPointer(3, floatvtx ? GL_FLOAT : GL_SHORT, VTXSIZE, &(va->vbuf[0].x));
772
904
    if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
773
905
 
774
 
    if(zfill)
 
906
    if(pass==RENDERPASS_Z)
775
907
    {
776
908
        if(cur.colormask) { cur.colormask = false; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); }
777
909
        extern int apple_glsldepth_bug;
778
910
        if(renderpath!=R_GLSLANG || !apple_glsldepth_bug) 
779
911
        {
780
912
            nocolorshader->set();
781
 
            glDrawElements(GL_TRIANGLES, 3*lod.tris, GL_UNSIGNED_SHORT, lod.ebuf);
 
913
            drawvatris(va, 3*lod.tris, lod.ebuf);
782
914
        }
783
915
        else
784
916
        {
792
924
                if(lastslot && (slot.shader->type&SHADER_GLSLANG) != (lastslot->shader->type&SHADER_GLSLANG) && offset > lastdraw)
793
925
                {
794
926
                    (lastslot->shader->type&SHADER_GLSLANG ? nocolorglslshader : nocolorshader)->set();
795
 
                    glDrawElements(GL_TRIANGLES, offset - lastdraw, GL_UNSIGNED_SHORT, lod.ebuf + lastdraw);
 
927
                    drawvatris(va, offset-lastdraw, lod.ebuf+lastdraw);
796
928
                    lastdraw = offset;
797
929
                }
798
930
                lastslot = &slot;
801
933
            if(offset > lastdraw)
802
934
            {
803
935
                (lastslot->shader->type&SHADER_GLSLANG ? nocolorglslshader : nocolorshader)->set();
804
 
                glDrawElements(GL_TRIANGLES, offset - lastdraw, GL_UNSIGNED_SHORT, lod.ebuf + lastdraw);
 
936
                drawvatris(va, offset-lastdraw, lod.ebuf+lastdraw);
805
937
            }
806
938
        }
807
 
        glde++;
808
939
        xtravertsva += va->verts;
809
940
        return;
810
941
    }
811
942
 
812
 
    if(refracting)
 
943
    if(refracting && renderpath!=R_FIXEDFUNCTION)
813
944
    {
814
945
        float fogplane = refracting - (va->z & ~VVEC_INT_MASK);
815
946
        if(cur.fogplane!=fogplane)
816
947
        {
817
948
            cur.fogplane = fogplane;
818
 
            setfogplane(0.5f, fogplane);
 
949
            setfogplane(1.0f/(1<<VVEC_FRAC), fogplane);
819
950
        }
820
951
    }
821
952
    if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); }
822
953
 
823
 
    if(refracting ? va->z+va->size<=refracting-waterfog : va->curvfc==VFC_FOGGED)
 
954
    if(refracting && renderpath!=R_FIXEDFUNCTION ? va->z+va->size<=refracting-waterfog : va->curvfc==VFC_FOGGED)
824
955
    {
 
956
        // this case is never reached if called from rendergeommultipass()
825
957
        static Shader *fogshader = NULL;
826
958
        if(!fogshader) fogshader = lookupshaderbyname("fogworld");
827
959
        fogshader->set();
829
961
        if(cur.texture)
830
962
        {
831
963
            cur.texture = false;
832
 
            if(renderpath!=R_FIXEDFUNCTION) glDisableClientState(GL_COLOR_ARRAY);
833
 
            glDisable(GL_TEXTURE_2D);
834
 
            glActiveTexture_(GL_TEXTURE1_ARB);
835
 
            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
836
 
            glDisable(GL_TEXTURE_2D);
837
 
            glActiveTexture_(GL_TEXTURE0_ARB);
 
964
            glDisable(GL_TEXTURE_2D);
 
965
            if(pass==RENDERPASS_LIGHTMAP)
 
966
            {
 
967
                if(renderpath!=R_FIXEDFUNCTION) glDisableClientState(GL_COLOR_ARRAY);
 
968
                glActiveTexture_(GL_TEXTURE1_ARB);
 
969
                glClientActiveTexture_(GL_TEXTURE1_ARB);
 
970
                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 
971
                glDisable(GL_TEXTURE_2D);
 
972
                glActiveTexture_(GL_TEXTURE0_ARB);
 
973
                glClientActiveTexture_(GL_TEXTURE0_ARB);
 
974
            }
838
975
        }
839
 
        glDrawElements(GL_TRIANGLES, 3*lod.tris, GL_UNSIGNED_SHORT, lod.ebuf);
840
 
        glde++;
 
976
 
 
977
        drawvatris(va, 3*lod.tris, lod.ebuf);
841
978
        vtris += lod.tris;
842
979
        vverts += va->verts;
843
980
        return;
846
983
    if(!cur.texture)
847
984
    {
848
985
        cur.texture = true;
849
 
        if(renderpath!=R_FIXEDFUNCTION) glEnableClientState(GL_COLOR_ARRAY);
850
 
        glEnable(GL_TEXTURE_2D);
851
 
        glActiveTexture_(GL_TEXTURE1_ARB);
852
 
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
853
 
        glEnable(GL_TEXTURE_2D);
854
 
        glActiveTexture_(GL_TEXTURE0_ARB);
855
 
        vbufchanged = true;
 
986
        glEnable(GL_TEXTURE_2D);
 
987
        if(pass==RENDERPASS_LIGHTMAP)
 
988
        {
 
989
            if(renderpath!=R_FIXEDFUNCTION) glEnableClientState(GL_COLOR_ARRAY);
 
990
            glActiveTexture_(GL_TEXTURE1_ARB);
 
991
            glClientActiveTexture_(GL_TEXTURE1_ARB);
 
992
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
993
            glEnable(GL_TEXTURE_2D);
 
994
            glActiveTexture_(GL_TEXTURE0_ARB);
 
995
            glClientActiveTexture_(GL_TEXTURE0_ARB);
 
996
            vbufchanged = true;
 
997
        }
856
998
    }
857
999
 
858
 
    if(renderpath!=R_FIXEDFUNCTION) 
859
 
    { 
 
1000
    if(pass==RENDERPASS_LIGHTMAP && renderpath!=R_FIXEDFUNCTION)
 
1001
    {
860
1002
        if(vbufchanged) glColorPointer(3, GL_UNSIGNED_BYTE, VTXSIZE, floatvtx ? &(((fvertex *)va->vbuf)[0].n) : &(va->vbuf[0].n));
861
 
        setenvparamfv("camera", SHPARAM_VERTEX, 4, vec4(camera1->o, 1).sub(ivec(va->x, va->y, va->z).mask(~VVEC_INT_MASK).tovec()).mul(2).v);
 
1003
        setenvparamfv("camera", SHPARAM_VERTEX, 4, vec4(camera1->o, 1).sub(ivec(va->x, va->y, va->z).mask(~VVEC_INT_MASK).tovec()).mul(1<<VVEC_FRAC).v);
 
1004
 
 
1005
        setdynlights(va);
862
1006
    }
863
1007
 
864
 
    if(vbufchanged)
 
1008
    if(vbufchanged && pass==RENDERPASS_LIGHTMAP)
865
1009
    {
866
1010
        glClientActiveTexture_(GL_TEXTURE1_ARB);
867
1011
        glTexCoordPointer(2, GL_SHORT, VTXSIZE, floatvtx ? &(((fvertex *)va->vbuf)[0].u) : &(va->vbuf[0].u));
870
1014
 
871
1015
    ushort *ebuf = lod.ebuf;
872
1016
    int lastlm = -1, lastxs = -1, lastys = -1, lastl = -1, lastenvmap = -1, envmapped = 0;
 
1017
    bool mtglow = false;
873
1018
    float lastscale = -1;
874
1019
    Slot *lastslot = NULL;
875
1020
    loopi(lod.texs)
879
1024
        Shader *s = slot.shader;
880
1025
 
881
1026
        extern vector<GLuint> lmtexids;
882
 
        int lmid = lod.eslist[i].lmid, curlm = lmtexids[lmid];
883
 
        if(renderpath!=R_FIXEDFUNCTION)
 
1027
        int lmid = lod.eslist[i].lmid, curlm = pass==RENDERPASS_LIGHTMAP ? lmtexids[lmid] : -1;
 
1028
        if(s && renderpath!=R_FIXEDFUNCTION && pass==RENDERPASS_LIGHTMAP)
884
1029
        {
885
1030
            int tmu = 2;
886
1031
            if(s->type&SHADER_NORMALSLMS)
895
1040
            if(s->type&SHADER_ENVMAP)
896
1041
            {
897
1042
                int envmap = lod.eslist[i].envmap;
898
 
                if((!lastslot || s->type!=lastslot->shader->type || envmap!=lastenvmap) && hasCM)
 
1043
                if((!lastslot || s->type!=lastslot->shader->type || (envmap==EMID_CUSTOM ? &slot!=lastslot : envmap!=lastenvmap)) && hasCM)
899
1044
                {
900
1045
                    glActiveTexture_(GL_TEXTURE0_ARB+tmu);
901
1046
                    if(!(envmapped & (1<<tmu)))
903
1048
                        glEnable(GL_TEXTURE_CUBE_MAP_ARB);
904
1049
                        envmapped |= 1<<tmu;
905
1050
                    }
906
 
                    glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, lookupenvmap(envmap));
 
1051
                    GLuint emtex = 0;
 
1052
                    if(envmap==EMID_CUSTOM) loopvj(slot.sts)
 
1053
                    {
 
1054
                        Slot::Tex &t = slot.sts[j];
 
1055
                        if(t.type==TEX_ENVMAP && t.t) { emtex = t.t->gl; break; }
 
1056
                    }
 
1057
                    if(!emtex) emtex = lookupenvmap(envmap);
 
1058
                    glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, emtex);
907
1059
                    lastenvmap = envmap;
908
1060
                }
909
1061
                tmu++;
910
1062
            }
911
1063
            glActiveTexture_(GL_TEXTURE0_ARB);
912
1064
        }
913
 
        if(curlm!=lastlm)
 
1065
        if(curlm!=lastlm && pass==RENDERPASS_LIGHTMAP)
914
1066
        {
915
1067
            glActiveTexture_(GL_TEXTURE1_ARB);
916
1068
            glBindTexture(GL_TEXTURE_2D, curlm);
919
1071
        }
920
1072
        if(&slot!=lastslot)
921
1073
        {
922
 
            glBindTexture(GL_TEXTURE_2D, tex->gl);
923
 
            s->set(&slot);
924
 
            if(renderpath!=R_FIXEDFUNCTION)
925
 
            {
 
1074
            if(pass==RENDERPASS_LIGHTMAP || pass==RENDERPASS_COLOR) glBindTexture(GL_TEXTURE_2D, tex->gl);
 
1075
            if(renderpath==R_FIXEDFUNCTION)
 
1076
            {
 
1077
                bool noglow = true;
 
1078
                if(pass==RENDERPASS_GLOW || maxtmus>=3) loopvj(slot.sts)
 
1079
                {
 
1080
                    Slot::Tex &t = slot.sts[j];
 
1081
                    if(t.type==TEX_GLOW && t.combined<0)
 
1082
                    {
 
1083
                        if(pass==RENDERPASS_LIGHTMAP)
 
1084
                        {
 
1085
                            glActiveTexture_(GL_TEXTURE2_ARB);
 
1086
                            if(!mtglow) { glEnable(GL_TEXTURE_2D); mtglow = true; }
 
1087
                        }
 
1088
                        glBindTexture(GL_TEXTURE_2D, t.t->gl);
 
1089
                        noglow = false;
 
1090
                    }
 
1091
                }
 
1092
                if(pass==RENDERPASS_GLOW && noglow) 
 
1093
                {
 
1094
                    loopl(3) ebuf += lod.eslist[i].length[l];
 
1095
                    continue;
 
1096
                }
 
1097
                else if(mtglow)
 
1098
                {
 
1099
                    if(noglow) { glActiveTexture_(GL_TEXTURE2_ARB); glDisable(GL_TEXTURE_2D); mtglow = false; }
 
1100
                    glActiveTexture_(GL_TEXTURE0_ARB);
 
1101
                }
 
1102
            }
 
1103
            else if(pass==RENDERPASS_LIGHTMAP && s)
 
1104
            {
 
1105
                if(visibledynlights.empty()) s->set(&slot);
 
1106
                else s->variant(visibledynlights.length()-1)->set(&slot);
 
1107
 
926
1108
                int tmu = 2;
927
1109
                if(s->type&SHADER_NORMALSLMS) tmu++;
928
1110
                if(s->type&SHADER_ENVMAP) tmu++;
929
1111
                loopvj(slot.sts)
930
1112
                {
931
1113
                    Slot::Tex &t = slot.sts[j];
932
 
                    if(t.type==TEX_DIFFUSE || t.combined>=0) continue;
 
1114
                    if(t.type==TEX_DIFFUSE || t.type==TEX_ENVMAP || t.combined>=0) continue;
933
1115
                    glActiveTexture_(GL_TEXTURE0_ARB+tmu++);
934
1116
                    glBindTexture(GL_TEXTURE_2D, t.t->gl);
935
1117
                }
940
1122
 
941
1123
        float scale = slot.sts[0].scale;
942
1124
        if(!scale) scale = 1;
943
 
        loopl(3) if (lod.eslist[i].length[l])
 
1125
        loopl(3) if(lod.eslist[i].length[l])
944
1126
        {
945
 
            if(lastl!=l || lastxs!=tex->xs || lastys!=tex->ys || lastscale!=scale || s->type&SHADER_GLSLANG)
 
1127
            if(lastl!=l || lastxs!=tex->xs || lastys!=tex->ys || lastscale!=scale || (s && s->type&SHADER_GLSLANG))
946
1128
            {
947
1129
                static int si[] = { 1, 0, 0 };
948
1130
                static int ti[] = { 2, 2, 1 };
966
1148
                        glEnable(GL_TEXTURE_GEN_S);
967
1149
                        glEnable(GL_TEXTURE_GEN_T);
968
1150
                    }
 
1151
    
 
1152
                    if(mtglow)
 
1153
                    {
 
1154
                        glActiveTexture_(GL_TEXTURE2_ARB);
 
1155
                        glTexGenfv(GL_S, GL_OBJECT_PLANE, s);
 
1156
                        glTexGenfv(GL_T, GL_OBJECT_PLANE, t);
 
1157
                        glActiveTexture_(GL_TEXTURE0_ARB);
 
1158
                    }
969
1159
                }
970
1160
                else
971
1161
                {
980
1170
                lastscale = scale;
981
1171
            }
982
1172
 
983
 
            if(s->type&SHADER_NORMALSLMS && renderpath!=R_FIXEDFUNCTION)
 
1173
            if(pass==RENDERPASS_LIGHTMAP && s && s->type&SHADER_NORMALSLMS && renderpath!=R_FIXEDFUNCTION)
984
1174
            {
985
1175
                setlocalparamfv("orienttangent", SHPARAM_VERTEX, 2, orientation_tangent[l]);
986
1176
                setlocalparamfv("orientbinormal", SHPARAM_VERTEX, 3, orientation_binormal[l]);
987
1177
            }
988
1178
 
989
 
            glDrawElements(GL_TRIANGLES, lod.eslist[i].length[l], GL_UNSIGNED_SHORT, ebuf);
 
1179
            drawvatris(va, lod.eslist[i].length[l], ebuf, lod.eslist[i].minvert[l], lod.eslist[i].maxvert[l]);
990
1180
            ebuf += lod.eslist[i].length[l];  // Advance to next array.
991
 
            glde++;
992
1181
        }
993
1182
    }
994
1183
 
 
1184
    if(mtglow)
 
1185
    {
 
1186
        glActiveTexture_(GL_TEXTURE2_ARB); 
 
1187
        glDisable(GL_TEXTURE_2D);
 
1188
    }
995
1189
    if(envmapped)
996
1190
    {
997
1191
        loopi(4) if(envmapped&(1<<i))
999
1193
            glActiveTexture_(GL_TEXTURE0_ARB+i);
1000
1194
            glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1001
1195
        }
1002
 
        glActiveTexture_(GL_TEXTURE0_ARB);
1003
1196
    }
 
1197
    if(mtglow || envmapped) glActiveTexture_(GL_TEXTURE0_ARB);
1004
1198
 
1005
1199
    vtris += lod.tris;
1006
1200
    vverts += va->verts;
1008
1202
 
1009
1203
VAR(oqdist, 0, 256, 1024);
1010
1204
VAR(zpass, 0, 1, 1);
 
1205
VAR(glowpass, 0, 1, 1);
1011
1206
 
1012
1207
extern int ati_texgen_bug;
1013
1208
 
 
1209
static void setuptexgen()
 
1210
{
 
1211
    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
 
1212
    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
 
1213
    glEnable(GL_TEXTURE_GEN_S);
 
1214
    glEnable(GL_TEXTURE_GEN_T);
 
1215
    if(ati_texgen_bug) glEnable(GL_TEXTURE_GEN_R);     // should not be needed, but apparently makes some ATI drivers happy
 
1216
}
 
1217
 
 
1218
static void disabletexgen()
 
1219
{
 
1220
    glDisable(GL_TEXTURE_GEN_S);
 
1221
    glDisable(GL_TEXTURE_GEN_T);
 
1222
    if(ati_texgen_bug) glDisable(GL_TEXTURE_GEN_R);
 
1223
}
 
1224
 
1014
1225
void setupTMUs()
1015
1226
{
1016
 
    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1017
 
    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1018
 
    glEnable(GL_TEXTURE_GEN_S);
1019
 
    glEnable(GL_TEXTURE_GEN_T);
1020
 
    if(ati_texgen_bug) glEnable(GL_TEXTURE_GEN_R);     // should not be needed, but apparently makes some ATI drivers happy
1021
 
 
1022
 
    if(renderpath!=R_FIXEDFUNCTION) glEnableClientState(GL_COLOR_ARRAY);
1023
 
 
1024
 
    setupTMU();
 
1227
    glColor3f(1, 1, 1);
 
1228
 
 
1229
    setuptexgen();
 
1230
 
 
1231
    if(nolights) return;
 
1232
 
 
1233
    setuptmu(0, "= T");
1025
1234
 
1026
1235
    glActiveTexture_(GL_TEXTURE1_ARB);
1027
1236
    glClientActiveTexture_(GL_TEXTURE1_ARB);
1028
1237
 
1029
 
    glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f);
 
1238
    setuptmu(1, "P * T x 2");
1030
1239
 
1031
1240
    glEnable(GL_TEXTURE_2D);
1032
 
    setupTMU();
1033
1241
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1034
1242
 
1035
1243
    glMatrixMode(GL_TEXTURE);
1037
1245
    glScalef(1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f);
1038
1246
    glMatrixMode(GL_MODELVIEW);
1039
1247
 
 
1248
    if(renderpath==R_FIXEDFUNCTION && maxtmus>=3)
 
1249
    {
 
1250
        glActiveTexture_(GL_TEXTURE2_ARB);
 
1251
        setuptexgen();
 
1252
 
 
1253
        setuptmu(2, "P + T");
 
1254
    }
 
1255
        
1040
1256
    glActiveTexture_(GL_TEXTURE0_ARB);
1041
1257
    glClientActiveTexture_(GL_TEXTURE0_ARB);
1042
 
 
 
1258
    
1043
1259
    if(renderpath!=R_FIXEDFUNCTION)
1044
1260
    {
 
1261
        glEnableClientState(GL_COLOR_ARRAY);
1045
1262
        loopi(8-2) { glActiveTexture_(GL_TEXTURE2_ARB+i); glEnable(GL_TEXTURE_2D); }
1046
1263
        glActiveTexture_(GL_TEXTURE0_ARB);
1047
1264
        setenvparamf("ambient", SHPARAM_PIXEL, 5, hdr.ambient/255.0f, hdr.ambient/255.0f, hdr.ambient/255.0f);
1048
 
        setenvparamf("millis", SHPARAM_VERTEX, 6, lastmillis/1000.0f, lastmillis/1000.0f, lastmillis/1000.0f, 0);
 
1265
        setenvparamf("millis", SHPARAM_VERTEX, 6, lastmillis/1000.0f, lastmillis/1000.0f, lastmillis/1000.0f);
1049
1266
    }
1050
 
 
1051
 
    glColor4f(1, 1, 1, 1);
1052
1267
}
1053
1268
 
1054
 
void cleanupTMUs()
 
1269
void cleanupTMU0()
1055
1270
{
1056
 
    if(hasVBO) 
 
1271
    glEnable(GL_TEXTURE_2D);
 
1272
 
 
1273
    disabletexgen();
 
1274
 
 
1275
    if(hasVBO)
1057
1276
    {
1058
1277
        glBindBuffer_(GL_ARRAY_BUFFER_ARB, 0);
1059
1278
        glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1063
1282
    {
1064
1283
        glDisableClientState(GL_COLOR_ARRAY);
1065
1284
        loopi(8-2) { glActiveTexture_(GL_TEXTURE2_ARB+i); glDisable(GL_TEXTURE_2D); }
 
1285
        glActiveTexture_(GL_TEXTURE0_ARB);
1066
1286
    }
1067
1287
 
 
1288
    if(!nolights) resettmu(0);
 
1289
}
 
1290
 
 
1291
void cleanupTMU1()
 
1292
{
 
1293
    if(nolights) return;
 
1294
 
1068
1295
    glActiveTexture_(GL_TEXTURE1_ARB);
1069
1296
    glClientActiveTexture_(GL_TEXTURE1_ARB);
1070
1297
 
1071
 
    glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f);
1072
 
 
 
1298
    resettmu(1);
1073
1299
    glDisable(GL_TEXTURE_2D);
1074
1300
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 
1301
    glMatrixMode(GL_TEXTURE);
 
1302
    glLoadIdentity();
 
1303
    glMatrixMode(GL_MODELVIEW);
1075
1304
 
 
1305
    if(renderpath==R_FIXEDFUNCTION && maxtmus>=3)
 
1306
    {
 
1307
        glActiveTexture_(GL_TEXTURE2_ARB);
 
1308
        resettmu(2);
 
1309
        disabletexgen();
 
1310
        glDisable(GL_TEXTURE_2D);
 
1311
    }
 
1312
        
1076
1313
    glActiveTexture_(GL_TEXTURE0_ARB);
1077
1314
    glClientActiveTexture_(GL_TEXTURE0_ARB);
1078
 
    glEnable(GL_TEXTURE_2D);
1079
 
 
1080
 
    glDisable(GL_TEXTURE_GEN_S);
1081
 
    glDisable(GL_TEXTURE_GEN_T);
1082
 
    if(ati_texgen_bug) glDisable(GL_TEXTURE_GEN_R);
1083
1315
}
1084
1316
 
1085
1317
#ifdef SHOWVA
1086
1318
VAR(showva, 0, 0, 1);
1087
1319
#endif
1088
1320
 
 
1321
#define FIRSTVA (reflecting && !refracting && camera1->o.z >= reflecting ? reflectedva : visibleva)
 
1322
#define NEXTVA (reflecting && !refracting && camera1->o.z >= reflecting ? va->rnext : va->next)
 
1323
 
 
1324
void rendergeommultipass(renderstate &cur, int pass)
 
1325
{
 
1326
    cur.vbufGL = 0;
 
1327
    for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
 
1328
    {
 
1329
        lodlevel &lod = va->curlod ? va->l1 : va->l0;
 
1330
        if(!lod.texs || va->occluded >= OCCLUDE_GEOM) continue;
 
1331
        if(refracting || (reflecting && camera1->o.z < reflecting))
 
1332
        {    
 
1333
            if(va->curvfc == VFC_FOGGED || (refracting && camera1->o.z >= refracting ? va->min.z > refracting : va->max.z <= refracting)) continue;
 
1334
            if((!hasOQ || !oqfrags) && va->distance > reflectdist) break;
 
1335
        }
 
1336
        else if(reflecting)
 
1337
        {
 
1338
            if(va->max.z <= reflecting || (va->rquery && checkquery(va->rquery))) continue;
 
1339
            if(va->rquery && checkquery(va->rquery)) continue;
 
1340
        }
 
1341
        if(refracting && renderpath!=R_FIXEDFUNCTION ? va->z+va->size<=refracting-waterfog : va->curvfc==VFC_FOGGED) continue;
 
1342
        renderva(cur, va, lod, pass);
 
1343
    }
 
1344
}
 
1345
 
1089
1346
void rendergeom()
1090
1347
{
1091
1348
    glEnableClientState(GL_VERTEX_ARRAY);
1092
1349
 
1093
 
    if(!zpass) setupTMUs();
1094
 
 
1095
 
    flipqueries();
1096
 
 
1097
 
    vtris = vverts = 0;
 
1350
    if(!reflecting && !refracting)
 
1351
    {
 
1352
        flipqueries();
 
1353
        vtris = vverts = 0;
 
1354
    }
 
1355
 
 
1356
    bool doOQ = !refracting && (reflecting ? camera1->o.z >= reflecting && hasOQ && oqfrags && oqreflect : zpass!=0);
 
1357
    if(!doOQ) setupTMUs();
 
1358
 
 
1359
    limitdynlights();
1098
1360
 
1099
1361
    glPushMatrix();
1100
1362
 
1101
1363
    resetorigin();
1102
1364
 
1103
1365
    renderstate cur;
1104
 
    for(vtxarray *va = visibleva; va; va = va->next)
 
1366
    for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
1105
1367
    {
1106
1368
        lodlevel &lod = va->curlod ? va->l1 : va->l0;
1107
1369
        if(!lod.texs) continue;
1108
 
        if(hasOQ && oqfrags && (zpass || va->distance > oqdist) && !insideva(va, camera1->o))
 
1370
        if(refracting || (reflecting && camera1->o.z < reflecting))
 
1371
        {
 
1372
            if(va->curvfc == VFC_FOGGED || (refracting && camera1->o.z >= refracting ? va->min.z > refracting : va->max.z <= reflecting) || va->occluded >= OCCLUDE_GEOM) continue;
 
1373
            if((!hasOQ || !oqfrags) && va->distance > reflectdist) break;
 
1374
        }
 
1375
        else if(reflecting)
 
1376
        {
 
1377
            if(va->max.z <= reflecting) continue;
 
1378
            if(doOQ)
 
1379
            {
 
1380
                va->rquery = newquery(&va->rquery);
 
1381
                if(!va->rquery) continue;
 
1382
                if(va->occluded >= OCCLUDE_BB || va->curvfc == VFC_NOT_VISIBLE)
 
1383
                {
 
1384
                    renderquery(cur, va->rquery, va);
 
1385
                    continue;
 
1386
                }
 
1387
            }
 
1388
        }
 
1389
        else if(hasOQ && oqfrags && (zpass || va->distance > oqdist) && !insideva(va, camera1->o))
1109
1390
        {
1110
1391
            if(!zpass && va->query && va->query->owner == va) 
1111
1392
                va->occluded = checkquery(va->query) ? min(va->occluded+1, OCCLUDE_BB) : OCCLUDE_NOTHING;
1135
1416
            va->occluded = OCCLUDE_NOTHING;
1136
1417
        }
1137
1418
 
1138
 
 
1139
 
        if(va->query) startquery(va->query);
1140
 
 
1141
 
        renderva(cur, va, lod, zpass!=0);
1142
 
 
1143
 
        if(va->query) endquery(va->query);
 
1419
        if(!refracting)
 
1420
        {
 
1421
            if(!reflecting) { if(va->query) startquery(va->query); }
 
1422
            else if(camera1->o.z >= reflecting && va->rquery) startquery(va->rquery);
 
1423
        }
 
1424
 
 
1425
        renderva(cur, va, lod, doOQ ? RENDERPASS_Z : (nolights ? RENDERPASS_COLOR : RENDERPASS_LIGHTMAP));
 
1426
 
 
1427
        if(!refracting)
 
1428
        {
 
1429
            if(!reflecting) { if(va->query) endquery(va->query); }
 
1430
            else if(camera1->o.z >= reflecting && va->rquery) endquery(va->rquery);
 
1431
        }
1144
1432
    }
1145
1433
 
1146
1434
    if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); }
1147
1435
    if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
1148
1436
 
1149
 
    if(zpass) 
 
1437
    if(doOQ)
1150
1438
    {
1151
1439
        setupTMUs();
1152
1440
        glDepthFunc(GL_LEQUAL);
1154
1442
        int showvas = 0;
1155
1443
#endif
1156
1444
        cur.vbufGL = 0;
1157
 
        for(vtxarray *va = visibleva; va; va = va->next)
 
1445
        for(vtxarray **prevva = &FIRSTVA, *va = FIRSTVA; va; prevva = &NEXTVA, va = NEXTVA)
1158
1446
        {
1159
1447
            lodlevel &lod = va->curlod ? va->l1 : va->l0;
1160
1448
            if(!lod.texs) continue;
1161
 
            if(va->parent && va->parent->occluded >= OCCLUDE_BB && (!va->parent->query || va->parent->query->fragments >= 0)) 
 
1449
            if(reflecting)
 
1450
            {
 
1451
                if(va->max.z <= reflecting) continue;
 
1452
                if(va->rquery && checkquery(va->rquery))
 
1453
                {
 
1454
                    if(va->occluded >= OCCLUDE_BB || va->curvfc == VFC_NOT_VISIBLE) *prevva = va->rnext;
 
1455
                    continue;
 
1456
                }
 
1457
            }
 
1458
            else if(va->parent && va->parent->occluded >= OCCLUDE_BB && (!va->parent->query || va->parent->query->fragments >= 0)) 
1162
1459
            {
1163
1460
                va->query = NULL;
1164
1461
                va->occluded = OCCLUDE_BB;
1182
1479
                else glColor3f(1, 1, 1);
1183
1480
            }
1184
1481
#endif
1185
 
            renderva(cur, va, lod);
 
1482
            renderva(cur, va, lod, nolights ? RENDERPASS_COLOR : RENDERPASS_LIGHTMAP);
1186
1483
        }
1187
1484
        glDepthFunc(GL_LESS);
1188
1485
    }
1189
1486
 
 
1487
    cleanupTMU1();
 
1488
 
 
1489
#define START_ADDITIVE_PASS \
 
1490
    glDepthFunc(GL_LEQUAL); \
 
1491
    glDepthMask(GL_FALSE); \
 
1492
    glEnable(GL_BLEND); \
 
1493
    glBlendFunc(GL_ONE, GL_ONE); \
 
1494
    GLfloat oldfogc[4]; \
 
1495
    glGetFloatv(GL_FOG_COLOR, oldfogc); \
 
1496
    static GLfloat zerofog[4] = { 0, 0, 0, 1 }; \
 
1497
    glFogfv(GL_FOG_COLOR, zerofog);
 
1498
 
 
1499
#define END_ADDITIVE_PASS \
 
1500
    glFogfv(GL_FOG_COLOR, oldfogc); \
 
1501
    glDisable(GL_BLEND); \
 
1502
    glDepthFunc(GL_LESS); \
 
1503
    glDepthMask(GL_TRUE);
 
1504
 
 
1505
    if(renderpath==R_FIXEDFUNCTION && maxtmus<3 && glowpass)
 
1506
    {
 
1507
        START_ADDITIVE_PASS
 
1508
 
 
1509
        rendergeommultipass(cur, RENDERPASS_GLOW);
 
1510
 
 
1511
        END_ADDITIVE_PASS
 
1512
    }
 
1513
 
1190
1514
    glPopMatrix();
1191
 
    cleanupTMUs();
 
1515
    cleanupTMU0();
1192
1516
}
1193
1517
 
1194
1518
void findreflectedvas(vector<vtxarray *> &vas, float z, bool refract, bool vfc = true)
1225
1549
 
1226
1550
void renderreflectedgeom(float z, bool refract)
1227
1551
{
1228
 
    glEnableClientState(GL_VERTEX_ARRAY);
1229
 
    setupTMUs();
1230
 
    glPushMatrix();
1231
 
 
1232
 
    resetorigin();
1233
 
 
1234
 
    renderstate cur;
1235
1552
    if(!refract && camera1->o.z >= z)
1236
1553
    {
1237
1554
        reflectvfcP(z);
1238
1555
        reflectedva = NULL;
1239
1556
        findreflectedvas(varoot, z, refract);
1240
 
        bool doOQ = hasOQ && oqfrags && oqreflect;
1241
 
        for(vtxarray *va = reflectedva; va; va = va->rnext)
1242
 
        {
1243
 
            lodlevel &lod = va->curlod ? va->l1 : va->l0;
1244
 
            if(!lod.texs || va->max.z <= z) continue;
1245
 
            if(doOQ)
1246
 
            {
1247
 
                va->rquery = newquery(&va->rquery);
1248
 
                if(!va->rquery) continue;
1249
 
                if(va->occluded >= OCCLUDE_BB || va->curvfc == VFC_NOT_VISIBLE)
1250
 
                {
1251
 
                    renderquery(cur, va->rquery, va);
1252
 
                    continue;
1253
 
                }
1254
 
            }
1255
 
            if(va->rquery) startquery(va->rquery);
1256
 
            renderva(cur, va, lod, doOQ);
1257
 
            if(va->rquery) endquery(va->rquery);
1258
 
        }            
1259
 
        if(doOQ)
1260
 
        {
1261
 
            glDepthFunc(GL_LEQUAL);
1262
 
            if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); }
1263
 
            if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
1264
 
            cur.vbufGL = 0;
1265
 
            for(vtxarray **prevva = &reflectedva, *va = reflectedva; va; prevva = &va->rnext, va = va->rnext)
1266
 
            {
1267
 
                lodlevel &lod = va->curlod ? va->l1 : va->l0;
1268
 
                if(!lod.texs || va->max.z <= z) continue;
1269
 
                if(va->rquery && checkquery(va->rquery)) 
1270
 
                {
1271
 
                    if(va->occluded >= OCCLUDE_BB || va->curvfc == VFC_NOT_VISIBLE) *prevva = va->rnext;
1272
 
                    continue;
1273
 
                }
1274
 
                renderva(cur, va, lod);
1275
 
            }
1276
 
            glDepthFunc(GL_LESS);
1277
 
        }
 
1557
        rendergeom();
1278
1558
        restorevfcP();
1279
1559
    }
1280
 
    else
1281
 
    {
1282
 
        for(vtxarray *va = visibleva; va; va = va->next)
1283
 
        {
1284
 
            lodlevel &lod = va->curlod ? va->l1 : va->l0;
1285
 
            if(!lod.texs) continue;
1286
 
            if(va->curvfc == VFC_FOGGED || (refract && camera1->o.z >= z ? va->min.z > z : va->max.z <= z) || va->occluded >= OCCLUDE_GEOM) continue;
1287
 
            if((!hasOQ || !oqfrags) && va->distance > reflectdist) break;
1288
 
            renderva(cur, va, lod);
1289
 
        }
1290
 
    }
1291
 
 
1292
 
    glPopMatrix();
1293
 
    cleanupTMUs();
1294
 
}
 
1560
    else rendergeom();
 
1561
}                
1295
1562
 
1296
1563
static GLuint skyvbufGL, skyebufGL;
1297
1564
 
1316
1583
    }
1317
1584
    if(vbufchanged) glVertexPointer(3, floatvtx ? GL_FLOAT : GL_SHORT, VTXSIZE, &(va->vbuf[0].x));
1318
1585
 
1319
 
    glDrawElements(GL_TRIANGLES, explicitonly  ? lod.explicitsky : lod.sky+lod.explicitsky, GL_UNSIGNED_SHORT, explicitonly ? lod.skybuf+lod.sky : lod.skybuf);
1320
 
    glde++;
 
1586
    drawvatris(va, explicitonly ? lod.explicitsky : lod.sky+lod.explicitsky, explicitonly ? lod.skybuf+lod.sky : lod.skybuf);
1321
1587
 
1322
1588
    if(!explicitonly) xtraverts += lod.sky/3;
1323
1589
    xtraverts += lod.explicitsky/3;
1324
1590
}
1325
1591
 
1326
 
void renderreflectedskyvas(vector<vtxarray *> &vas, float z, bool vfc = true)
 
1592
int renderreflectedskyvas(vector<vtxarray *> &vas, float z, bool vfc = true)
1327
1593
{
 
1594
    int rendered = 0;
1328
1595
    loopv(vas)
1329
1596
    {
1330
1597
        vtxarray *va = vas[i];
1331
1598
        lodlevel &lod = va->curlod ? va->l1 : va->l0;
1332
1599
        if((vfc && va->curvfc == VFC_FULL_VISIBLE) && va->occluded >= OCCLUDE_BB) continue;
1333
1600
        if(va->z+va->size <= z || isvisiblecube(vec(va->x, va->y, va->z), va->size) == VFC_NOT_VISIBLE) continue;
1334
 
        if(lod.sky+lod.explicitsky) renderskyva(va, lod);
1335
 
        if(va->children->length()) renderreflectedskyvas(*va->children, z, vfc && va->curvfc != VFC_NOT_VISIBLE);
 
1601
        if(lod.sky+lod.explicitsky) 
 
1602
        {
 
1603
            renderskyva(va, lod);
 
1604
            rendered++;
 
1605
        }
 
1606
        if(va->children->length()) rendered += renderreflectedskyvas(*va->children, z, vfc && va->curvfc != VFC_NOT_VISIBLE);
1336
1607
    }
 
1608
    return rendered;
1337
1609
}
1338
1610
 
1339
 
void rendersky(bool explicitonly, float zreflect)
 
1611
bool rendersky(bool explicitonly, float zreflect)
1340
1612
{
1341
1613
    glEnableClientState(GL_VERTEX_ARRAY);
1342
1614
 
1345
1617
    resetorigin();
1346
1618
 
1347
1619
    skyvbufGL = skyebufGL = 0;
1348
 
 
 
1620
 
 
1621
    int rendered = 0;
1349
1622
    if(zreflect)
1350
1623
    {
1351
1624
        reflectvfcP(zreflect);
1352
 
        renderreflectedskyvas(varoot, zreflect);
 
1625
        rendered = renderreflectedskyvas(varoot, zreflect);
1353
1626
        restorevfcP();
1354
1627
    }
1355
1628
    else for(vtxarray *va = visibleva; va; va = va->next)
1358
1631
        if(va->occluded >= OCCLUDE_BB || !(explicitonly ? lod.explicitsky : lod.sky+lod.explicitsky)) continue;
1359
1632
 
1360
1633
        renderskyva(va, lod, explicitonly);
 
1634
        rendered++;
1361
1635
    }
1362
1636
 
1363
1637
    glPopMatrix();
1364
1638
 
1365
 
    if(hasVBO)
1366
 
    {
1367
 
        glBindBuffer_(GL_ARRAY_BUFFER_ARB, 0);
1368
 
        glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1369
 
    }
 
1639
    if(skyvbufGL) glBindBuffer_(GL_ARRAY_BUFFER_ARB, 0);
 
1640
    if(skyebufGL) glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
 
1641
 
1370
1642
    glDisableClientState(GL_VERTEX_ARRAY);
 
1643
 
 
1644
    return rendered>0;
1371
1645
}
1372
1646