Subversion Repositories gelsvn

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
594 jab 1
/* ----------------------------------------------------------------------- *
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
3
 * Copyright (C) the authors and DTU Informatics
4
 * For license and list of authors, see ../../doc/intro.pdf
5
 * ----------------------------------------------------------------------- */
6
 
396 jab 7
#include "IDBufferWireFrameRenderer.h"
594 jab 8
 
9
#include <CGLA/Vec4f.h>
10
#include <CGLA/Vec2f.h>
11
#include <CGLA/Vec3f.h>
396 jab 12
#include <HMesh/Manifold.h>
594 jab 13
#include <HMesh/AttributeVector.h>
14
 
396 jab 15
#include <GLGraphics/draw.h>
16
 
594 jab 17
#include "glsl_shader.h"
18
 
396 jab 19
using namespace std;
20
using namespace CGLA;
21
using namespace GLGraphics;
22
using namespace HMesh;
23
 
24
namespace
25
{
594 jab 26
    string line_atten_frag = 
27
        "uniform int ATTEN_MODE;\n"
28
        "uniform float THICKNESS;\n"
29
        "uniform sampler2DRect IDMAP;\n"
30
        "uniform float TRANSITION;\n"
31
        "\n"
32
        "varying vec3 _id;\n"
33
        "varying vec2 p_2d_0;\n"
34
        "varying vec2 p_2d_1;\n"
35
        "\n"
36
        "const int LINEAR_ATTENUATION = 1;\n"
37
        "const int HERMITE_ATTENUATION = 2;\n"
38
        "\n"
39
        "const float HERMITE_COL_ATTEN_BIAS = 0.25;\n"
40
        "const float LINEAR_COL_ATTEN_BIAS = 0.4;\n"
41
        "const float HERMITE_ATTEN_BEGIN = 0.75;\n"
42
        "const float HERMITE_ATTEN_END = 1.0;\n"
43
        "\n"
44
        "void main(void)\n"
45
        "{\n"
46
        "	vec2 dir = (p_2d_1-p_2d_0);\n"
47
        "	float sq_len01 = dot(dir,dir);\n"
48
        "	vec2 v0 = (gl_FragCoord.xy)-p_2d_0;\n"
49
        "	vec2 v1 = (gl_FragCoord.xy)-p_2d_1;\n"
50
        "	float t = dot(dir, v0);\n"
51
        "	float d;\n"
52
        "	\n"
53
        "	if(t<=0.0)\n"
54
        "			d = length(v0);\n"
55
        "	else if(t>= sq_len01)\n"
56
        "			d = length(v1);\n"
57
        "	else\n"
58
        "			d = length(dir * t / sq_len01 - v0);\n"
59
        "	\n"
60
        "	vec3 iddiff = texture2DRect(IDMAP,gl_FragCoord.xy).xyz - _id;\n"
61
        " 	if(dot(iddiff, iddiff)<1e-6)\n"
62
        "		gl_FragDepth = 0.0;\n"
63
        "	else	\n"
64
        "		gl_FragDepth = gl_FragCoord.z;\n"
65
        "	\n"
66
        "	\n"
67
        "	float t1 = THICKNESS;\n"
68
        "	if(ATTEN_MODE == HERMITE_ATTENUATION)\n"
69
        "		{\n"
70
        "			float width_atten = smoothstep(HERMITE_ATTEN_END,HERMITE_ATTEN_BEGIN,\n"
71
        "																		 gl_FragCoord.z);\n"
72
        "			t1 *= width_atten;\n"
73
        "		}\n"
74
        "	else if(ATTEN_MODE == LINEAR_ATTENUATION)\n"
75
        "		{\n"
76
        "			float width_atten = 1.0-gl_FragCoord.z;\n"
77
        "			t1 *= width_atten;\n"
78
        "		}			\n"
79
        "	float t2 = t1+TRANSITION;\n"
80
        "\n"
81
        "	float I;\n"
82
        "	if(d<t1) \n"
83
        "			I = 1.0;\n"
84
        "	else\n"
85
        "	{\n"
86
        "			float x = (d-t1);\n"
87
        "			I = exp2(-x*x*2);\n"
88
        "	}\n"
89
        " 	gl_FragColor.rgb = gl_Color.rgb;\n"
90
        "	gl_FragColor.a = I;\n"
91
        "}\n";
92
 
93
    string line_frag = 
94
        "uniform sampler2DRect IDMAP;\n"
95
        "uniform float TRANSITION;\n"
96
        "	\n"
97
        "varying vec3 _id;\n"
98
        "varying vec2 p_2d_0;\n"
99
        "varying vec2 p_2d_1;\n"
100
        "\n"
101
        "void main(void)\n"
102
        "{\n"
103
        "	vec2 dir = (p_2d_1-p_2d_0);\n"
104
        "	float sq_len01 = dot(dir,dir);\n"
105
        "	vec2 v0 = gl_FragCoord.xy-p_2d_0;\n"
106
        "	vec2 v1 = gl_FragCoord.xy-p_2d_1;\n"
107
        "	float t = dot(dir, v0);\n"
108
        "	float sq_d;\n"
109
        "	\n"
110
        "	if(t<=0.0)\n"
111
        "		sq_d = dot(v0,v0);\n"
112
        "	else if(t>= sq_len01)\n"
113
        "		sq_d = dot(v1,v1);\n"
114
        "	else\n"
115
        "		{\n"
116
        "			float area = (v0.x*v1.y - v0.y * v1.x);\n"
117
        "			sq_d = area*area/sq_len01;\n"
118
        "		}\n"
119
        "\n"
120
        "	vec3 iddiff = texture2DRect(IDMAP,gl_FragCoord.xy).xyz -_id;\n"
121
        "	if(dot(iddiff, iddiff)<1e-6)\n"
122
        "		gl_FragDepth = 0.0;\n"
123
        " 	else	\n"
124
        " 		gl_FragDepth = gl_FragCoord.z;\n"
125
        "	\n"
126
        "	gl_FragColor.a = exp2(-sq_d*2.0);\n"
127
        "	gl_FragColor.rgb = gl_Color.rgb;\n"
128
        "}\n";
129
 
130
    string line_vert = 
131
        "uniform float THICKNESS;\n"
132
        "uniform vec2 WIN_SCALE;\n"
133
        "uniform vec2 INV_WIN_SCALE;\n"
134
        "uniform float TRANSITION;\n"
135
        "\n"
136
        "attribute vec4 id;\n"
137
        "attribute vec4 opp_vertex;\n"
138
        "attribute vec2 displace;\n"
139
        "\n"
140
        "varying vec3 _id;\n"
141
        "varying vec2 p_2d_0;\n"
142
        "varying vec2 p_2d_1;\n"
143
        "\n"
144
        "\n"
145
        "void main(void)\n"
146
        "{\n"
147
        "	vec4 p0 = gl_ModelViewProjectionMatrix * opp_vertex;\n"
148
        "	float w0 = p0.w; \n"
149
        "\n"
150
        "	vec4 p1 = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
151
        "	float w1 = p1.w;\n"
152
        "		\n"
153
        "	p_2d_0 = (p0.xy/w0+vec2(1,1)) * WIN_SCALE;\n"
154
        "	p_2d_1 = (p1.xy/w1+vec2(1,1)) * WIN_SCALE;\n"
155
        "	\n"
156
        "	vec2 a = normalize(p_2d_1 - p_2d_0);\n"
157
        "	vec2 a_h = vec2(-a.y, a.x);\n"
158
        "	vec2 scale = (TRANSITION+THICKNESS)*INV_WIN_SCALE;\n"
159
        "\n"
160
        "	gl_Position = (displace.x>0.0) ? p1 : p0;\n"
161
        "	vec2 offset = a * displace.x + a_h * displace.y;\n"
162
        "	gl_Position.xy += scale * gl_Position.w * offset;\n"
163
        "\n"
164
        "	_id = id.rgb;\n"
165
        "	gl_FrontColor = gl_Color;\n"
166
        "	gl_FrontSecondaryColor = gl_SecondaryColor;\n"
167
        "}\n";
168
 
396 jab 169
}
170
 
171
namespace GLGraphics
172
{
594 jab 173
    IDBufferWireframeRenderer::~IDBufferWireframeRenderer()
174
    {
175
        glDeleteShader(vs);	
176
        glDeleteShader(fs);
177
        glDeleteProgram(line_prog);
178
        glDeleteTextures(1, &idmap);
179
        glDeleteBuffers(1, &vertex_buffername);
180
        glDeleteBuffers(1, &colors_buffername);
181
 
182
        glDeleteBuffers(1, &line_id_attrib);
183
        glDeleteBuffers(1, &line_vertex_pos);
184
        glDeleteBuffers(1, &line_disp_attrib);			
185
        glDeleteBuffers(1, &line_opp_attrib);
186
    }
187
 
188
    IDBufferWireframeRenderer::IDBufferWireframeRenderer(int _XSZ, int _YSZ,
189
        HMesh::Manifold& _mesh, 
190
        float _thickness, 
191
        float _transition, 
192
        int atten_mode): 
193
    mesh(&_mesh), XSZ(_XSZ), YSZ(_YSZ), thickness(_thickness), transition(_transition)
194
    {
195
 
196
        if(atten_mode == 0 && thickness == 0.0)
197
        {
198
            vs = create_glsl_shader(GL_VERTEX_SHADER, line_vert);
199
            fs = create_glsl_shader(GL_FRAGMENT_SHADER, line_frag);
396 jab 200
        }
594 jab 201
        else
202
        {
203
            vs = create_glsl_shader(GL_VERTEX_SHADER, line_vert);
204
            fs = create_glsl_shader(GL_FRAGMENT_SHADER, line_atten_frag);
205
        }
396 jab 206
 
594 jab 207
        line_prog = glCreateProgram();
208
        glAttachShader(line_prog, vs);
209
        glAttachShader(line_prog, fs);
210
        glLinkProgram(line_prog);
211
        glUseProgram(line_prog);
396 jab 212
 
594 jab 213
        glUniform1f(glGetUniformLocation(line_prog,"THICKNESS"), 
214
            thickness);
215
        glUniform1f(glGetUniformLocation(line_prog,"TRANSITION"), 
216
            transition);
217
        glUniform1i(glGetUniformLocation(line_prog,"ATTEN_MODE"),
218
            atten_mode);
219
        glUniform2f(glGetUniformLocation(line_prog,"WIN_SCALE"), 
220
            XSZ/2.0, YSZ/2.0);
221
        glUniform2f(glGetUniformLocation(line_prog,"INV_WIN_SCALE"), 
222
            2.0/XSZ, 2.0/YSZ);
223
        glUniform1i(glGetUniformLocation(line_prog,"IDMAP"), 0);
224
 
225
        id_attrib = glGetAttribLocation(line_prog, "id");
226
        popp_attrib = glGetAttribLocation(line_prog, "opp_vertex");
227
        disp_attrib = glGetAttribLocation(line_prog, "displace");
228
        glUseProgram(0);
229
 
230
        glGenTextures(1, &idmap);
231
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, idmap);
232
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
233
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
234
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S,GL_CLAMP);
235
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T,GL_CLAMP);
236
 
237
        //create the texture
238
        glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, XSZ, YSZ,
239
            0, GL_RGB, GL_FLOAT, 0);
240
 
241
 
242
        glGenBuffers(1, &vertex_buffername);
243
        glGenBuffers(1, &colors_buffername);
244
 
245
        glGenBuffers(1, &line_id_attrib);
246
        glGenBuffers(1, &line_vertex_pos);
247
        glGenBuffers(1, &line_disp_attrib);
248
        glGenBuffers(1, &line_opp_attrib);
249
 
250
        triangles = static_cast<int>(mesh->no_faces());
251
        vector<Vec3f> verts;
252
        vector<Vec3f> cols;
253
 
254
        unsigned int k = 0;
255
        for(FaceIDIterator f = mesh->faces_begin(); f != mesh->faces_end(); ++f, ++k){
256
            Vec3uc idv(id_get(k));
257
            Vec3f idvec(idv[0]/255.0, idv[1]/255.0, idv[2]/255.0);
258
            for(Walker w = mesh->walker(*f); !w.full_circle(); w = w.circulate_face_ccw()){
259
                cols.push_back(idvec);
260
                verts.push_back(Vec3f(mesh->pos(w.vertex())));
261
            }
262
        }
263
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffername);
264
        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*verts.size(),
265
            (float*)&verts[0],GL_STATIC_DRAW);
266
 
267
 
268
 
269
        glBindBuffer(GL_ARRAY_BUFFER, colors_buffername);
270
        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*cols.size(),
271
            (float*)&cols[0],GL_STATIC_DRAW);
272
 
273
 
274
        vector<Vec3f> line_ids;
275
        vector<Vec3f> vertex_positions;
276
        vector<Vec2f> displacements;
277
        vector<Vec3f> opposite_positions;
278
 
279
 
280
        quads = 0;
281
        unsigned int i = 0;
282
        for(FaceIDIterator f = mesh->faces_begin(); f != mesh->faces_end(); ++f,++i){
283
            for(Walker w = mesh->walker(*f); !w.full_circle(); w = w.circulate_face_ccw()){
284
                ++quads;
285
                Vec3uc idv(id_get(i));
286
                Vec3f v0(mesh->pos(w.next().vertex()));
287
                Vec3f v1(mesh->pos(w.next().opp().vertex()));
288
                Vec3f idvec(idv[0]/255.0, idv[1]/255.0, idv[2]/255.0);
289
 
290
                line_ids.push_back(idvec);
291
                opposite_positions.push_back(v0);
292
                displacements.push_back(Vec2f(1,-1));
293
                vertex_positions.push_back(v1);
294
 
295
 
296
                line_ids.push_back(idvec);
297
                opposite_positions.push_back(v0);
298
                displacements.push_back(Vec2f(1, 1));
299
                vertex_positions.push_back(v1);
300
 
301
 
302
                line_ids.push_back(idvec);
303
                opposite_positions.push_back(v0);
304
                displacements.push_back(Vec2f(-1,1));
305
                vertex_positions.push_back(v1);
306
 
307
 
308
                line_ids.push_back(idvec);
309
                opposite_positions.push_back(v0);
310
                displacements.push_back(Vec2f(-1,-1));
311
                vertex_positions.push_back(v1);
312
            }
313
        }
314
 
315
        glBindBuffer(GL_ARRAY_BUFFER, line_id_attrib);
316
 
317
        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*line_ids.size(),
318
            (float*)&line_ids[0],GL_STATIC_DRAW);
319
 
320
        glBindBuffer(GL_ARRAY_BUFFER, line_opp_attrib);
321
        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*opposite_positions.size(),
322
            (float*)&opposite_positions[0],GL_STATIC_DRAW);
323
 
324
        glBindBuffer(GL_ARRAY_BUFFER, line_disp_attrib);
325
        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*displacements.size(),
326
            (float*)&displacements[0],GL_STATIC_DRAW);
327
 
328
        glBindBuffer(GL_ARRAY_BUFFER, line_vertex_pos);
329
        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*vertex_positions.size(),
330
            (float*)&vertex_positions[0],GL_STATIC_DRAW);
331
 
332
 
333
 
334
    }
335
 
336
 
337
    void IDBufferWireframeRenderer::draw(const Vec3f& color, const Vec3f& clear_color)
338
    {
339
        // push those attributes we change.
340
        glPushAttrib(GL_COLOR_BUFFER_BIT|
341
            GL_CURRENT_BIT|
342
            GL_TRANSFORM_BIT|
343
            GL_DEPTH_BUFFER_BIT);
344
 
345
        // Store information about whether we use lighting
346
        GLboolean lights_on;
347
        glGetBooleanv(GL_LIGHTING, &lights_on);
348
 
349
        // Store color information
350
        Vec4f current_color;
351
        glGetFloatv(GL_CURRENT_COLOR, &current_color[0]);
352
 
353
        // Store the current draw buffer 
354
        GLint _currentDrawbuf;
355
        glGetIntegerv(GL_DRAW_BUFFER, &_currentDrawbuf); 
356
 
357
        // Enable depth testing
358
        glEnable(GL_DEPTH_TEST);
359
 
360
        // ------------------------------
361
        // Pass 1: Draw the ID map
362
        // Each polygon has a unique ID which is coded as a colour and drawn
363
        // into the ID buffer
364
        glDisable(GL_LIGHTING);
365
        glClearColor(0,0,0,0);
366
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
367
 
368
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffername);
369
        glVertexPointer(3,GL_FLOAT,0,static_cast<char*>(0));
370
        glEnableClientState(GL_VERTEX_ARRAY);
371
 
372
        glBindBuffer(GL_ARRAY_BUFFER, colors_buffername);
373
        glColorPointer(3,GL_FLOAT,0,static_cast<char*>(0));
374
        glEnableClientState(GL_COLOR_ARRAY);
375
 
376
        int vertex_idx = 0;
377
        for(FaceIDIterator f = mesh->faces_begin(); f != mesh->faces_end(); ++f){
378
            glBegin(GL_POLYGON);
379
            for(Walker w = mesh->walker(*f); !w.full_circle(); w = w.circulate_face_ccw())
380
                 glArrayElement(vertex_idx++);
381
            glEnd();
382
        }
383
        glFinish();
384
        glDisableClientState(GL_COLOR_ARRAY);
385
        glDisableClientState(GL_VERTEX_ARRAY);
386
 
387
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, idmap);
388
        glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0,0,0,0,XSZ, YSZ);
389
 
390
        // Clear color buffer but retain depth buffer.
391
        glClear(GL_COLOR_BUFFER_BIT);
392
 
393
        // Enable blending for all subsequent passes
394
        glEnable(GL_BLEND);
395
 
396
        // ------------------------------
397
        // PASS 3: Draw lines using ID map texture.
398
        // For each polygon, all edges are drawn as prefiltered
399
        // lines. A given fragment belonging to a line will be written
400
        // to the framebuffer if either of the following three conditions are met
401
        // - its ID matches the contents of the ID  buffer for the corresponding 
402
        // pixel (in the ID buffer)
403
        // - The ID of the corresponding pixel is 0 - meaning we are outside.
404
        // - The depth test is passed.
405
        // The final condition ensures that line pixels which are on an interior
406
        // contour will be drawn.
407
        //
408
        // If the line fragment is written into the framebuffer - two values are
409
        // actually written: The colour of the line and an alpha value which
410
        // corresponds to the value of the filter function.
411
        //
412
        // During this pass, blending is enabled and the blending equation is set
413
        // to max. Since the alpha values are the values of the filter (large if 
414
        // close to line) this means that we replace a pixel value with an 
415
        // incoming fragment if the incoming fragment is closer to a line
416
        // than the pixel value.
417
        //
418
        // The depth values are not changed during this pass.
419
        glEnable(GL_TEXTURE_RECTANGLE_ARB);
420
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, idmap);
421
        glDepthMask(GL_FALSE);
422
        glBlendEquation(GL_MAX);
423
        glUseProgram(line_prog);
424
        glColor3fv(color.get());
425
        glSecondaryColor3fv(clear_color.get());
426
 
427
        float lw;
428
        glGetFloatv(GL_LINE_WIDTH, &lw);
429
        glLineWidth(ceil(2.0*(thickness+transition)));
430
 
431
 
432
        glBindBuffer(GL_ARRAY_BUFFER, line_id_attrib);
433
        glVertexAttribPointer(id_attrib, 3,GL_FLOAT,GL_FALSE,0,static_cast<char*>(0));
434
        glEnableVertexAttribArray(id_attrib);
435
 
436
 
437
        glBindBuffer(GL_ARRAY_BUFFER, line_disp_attrib);
438
        glVertexAttribPointer(disp_attrib, 2,GL_FLOAT,GL_FALSE,0,static_cast<char*>(0));
439
        glEnableVertexAttribArray(disp_attrib);
440
 
441
 
442
        glBindBuffer(GL_ARRAY_BUFFER, line_opp_attrib);
443
        glVertexAttribPointer(popp_attrib, 3,GL_FLOAT,GL_FALSE,0,static_cast<char*>(0));
444
        glEnableVertexAttribArray(popp_attrib);
445
 
446
 
447
        glBindBuffer(GL_ARRAY_BUFFER, line_vertex_pos);
448
        glVertexPointer(3,GL_FLOAT,0,static_cast<char*>(0));
449
        glEnableClientState(GL_VERTEX_ARRAY);
450
 
451
        glDrawArrays(GL_QUADS, 0, quads*4);
452
 
453
        glDisableVertexAttribArray(id_attrib);
454
        glDisableVertexAttribArray(disp_attrib);
455
        glDisableVertexAttribArray(popp_attrib);
456
        glDisableClientState(GL_VERTEX_ARRAY);
457
 
458
 
459
        glLineWidth(lw);
460
 
461
        glUseProgram(0);
462
        glDisable(GL_TEXTURE_RECTANGLE_ARB);
463
        glDepthMask(GL_TRUE);
464
 
465
        // ------------------------------
466
        // Pass 4: Draw with shading
467
        // In this pass we draw the shaded model. At this point, the framebuffer
468
        // contains alpha values and line colours and also depth values.
469
        //
470
        // The depth test is set to `equal' and the shaded fragments from the 
471
        // filled polygons are combined with the line colours using the alpha 
472
        // values already stored in the frame buffer.
473
        //
474
        // The framebuffer lines along the contour also need to be blended. 
475
        // Hence, a screen filling quad is drawn. 
476
        glDepthFunc(GL_LEQUAL);
477
        glBlendEquation(GL_FUNC_ADD);
478
        glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA, 
479
            GL_ZERO, GL_ONE);
480
        if(lights_on)
481
        {
482
            glEnable(GL_LIGHTING);
483
            glEnable(GL_LIGHT0);
484
        }else
485
            glColor4fv(current_color.get());
486
 
487
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffername);
488
        glVertexPointer(3,GL_FLOAT,0,static_cast<char*>(0));
489
        glEnableClientState(GL_VERTEX_ARRAY);
490
 
491
        vertex_idx = 0;
492
        for(FaceIDIterator f = mesh->faces_begin(); f != mesh->faces_end(); ++f){
493
			Vec3f n(normal(*mesh, *f));
494
            glNormal3fv(n.get());
495
            glBegin(GL_POLYGON);
496
            for(Walker w = mesh->walker(*f); !w.full_circle(); w = w.circulate_face_ccw())
497
                 glArrayElement(vertex_idx++);
498
            glEnd();
499
        }
500
        glDisableClientState(GL_VERTEX_ARRAY);
501
 
502
 
503
        glDisable(GL_LIGHTING);
504
 
505
 
506
        double mvmat[16];
507
        glGetDoublev(GL_MODELVIEW_MATRIX, mvmat);
508
        double prjmat[16];
509
        glGetDoublev(GL_PROJECTION_MATRIX, prjmat);
510
        glMatrixMode(GL_PROJECTION);
511
        glLoadIdentity();
512
        glMatrixMode(GL_MODELVIEW);
513
        glLoadIdentity();
514
        glColor3fv(clear_color.get());
515
        glBegin(GL_QUADS);
516
        glVertex3f(-1,-1,1);
517
        glVertex3f( 1,-1,1);
518
        glVertex3f( 1, 1,1);
519
        glVertex3f(-1, 1,1);
520
        glEnd();
521
 
522
 
523
 
524
        glMatrixMode(GL_PROJECTION);
525
        glLoadMatrixd(prjmat);
526
        glMatrixMode(GL_MODELVIEW);
527
        glLoadMatrixd(mvmat);
528
 
529
        glPopAttrib();
530
        if(lights_on)
531
            glEnable(GL_LIGHTING);
532
 
533
        //			cout << gluErrorString(glGetError()) << endl;
534
    }
396 jab 535
}