1 //-----------------------------------------------------------------------------
2 // Render
3 //-----------------------------------------------------------------------------
4
5 #include "render.h"
6 #include "commands.h"
7 #include "console.h"
8 #include "logfile.h"
9 #include "overlay.h"
10 #include "camera.h"
11 #include "client.h"
12 #include "timer.h"
13 #include "vars.h"
14 #include "math.h"
15 #include "surfaceflags.h"
16 #include "mem.h"
17 #include "system.h"
18 #include <assert.h>
19
20 #include "glsetup/glutils.h"
21 #ifdef WIN32
22 #include "glsetup/glext.h"
23 #else
24 #define GLX_GLXEXT_LEGACY
25 #include <GL/glx.h>
26 #include <GL/glext.h>
27 #endif
28
29 PFNGLLOCKARRAYSEXTPROC glLockArraysEXT;
30 PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT;
31
32 #ifdef WIN32
33 PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
34 PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB;
35 #define lglGetProcAddress(p) wglGetProcAddress(p)
36
37 // size of float may change from one platform to one other
38 #define XYZ_OFFSET 16 // 4 * sizeof(float)
39 #else
40 #define lglGetProcAddress(p) glXGetProcAddressARB((byte*) p);
41
42 // size of float may change from one platform to one other
43 #define XYZ_OFFSET 16 // 4 * sizeof(float)
44 #endif
45
46 Var gl_vendor("gl_vendor", "", VF_SYSTEM);
47 Var gl_renderer("gl_renderer", "", VF_SYSTEM);
48 Var gl_version("gl_version", "", VF_SYSTEM);
49 Var gl_extensions("gl_extensions", "", VF_SYSTEM);
50 Var gl_maxTextureSize("gl_maxTextureSize", 0, VF_SYSTEM);
51 Var gl_maxTextureUnits("gl_maxTextureUnits", 0, VF_SYSTEM);
52 Var r_ext_compiledVertexArray("r_ext_compiled_vertex_array", 0, VF_SYSTEM);
53 Var r_ext_multitexture("r_ext_multitexture", 0, VF_SYSTEM);
54 Var r_ext_texture_edge_clamp("r_ext_texture_edge_clamp", 0, VF_SYSTEM);
55 Var r_usedTextureUnits("r_usedTextureUnits", 0, VF_SYSTEM);
56 Var r_vertexLight("r_vertexLight", 0, VF_PERSISTENT);
57 Var r_texturebits("r_texturebits", 0);
58 Var r_clear("r_clear", 0, VF_PERSISTENT);
59 Var r_filter("r_filter", 1, VF_PERSISTENT);
60 Var r_quality("r_quality", 2, VF_PERSISTENT | VF_LATCH);
61 Var r_picmip("r_picmip", 0, VF_PERSISTENT | VF_LATCH);
62 Var gl_dither("gl_dither", 1, VF_PERSISTENT);
63 Var v_overbrightbits("v_overbrightbits", 3, VF_LATCH);
64 Var v_gamma("v_gamma", 1.3375f, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
65 Var r_nolightmap("r_nolightmap", 0);
66 Var r_noshader("r_noshader", 0);
67 Var r_novertexcolor("r_novertexcolor", 0);
68 Var r_nocull("r_nocull", 0);
69 Var r_nodeform("r_nodeform", 0);
70 Var r_nofog("r_nofog", 0);
71 Var v_fullscreen("v_fullscreen", 0, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
72 Var v_colorBits("v_colorBits", 32, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
73 Var v_hz("v_hz", 60, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
74 Var v_height("v_height", 480, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
75 Var v_width("v_width", 640, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
76 Var v_left("v_left", 0, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
77 Var v_top("v_top", 0, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
78 Var v_aspect("v_aspect", (float)4/3, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
79 Var v_depthBits("v_depthBits", 32, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
80 Var v_stencilBits("v_stencilBits", 0, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
81 Var v_lightness("v_lightness", 0.0f, VF_LATCH);
82 Var v_mode("v_mode", 0, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
83 Var r_subdivision("r_subdivision", 2, VF_LATCH | VF_PERSISTENT);
84 Var r_curvefactor("r_curvefactor", 6, VF_LATCH | VF_PERSISTENT);
85 Var wnd_handle("wnd_handle", 0);
86 Var sys_buffersize("sys_buffersize", 0, VF_SYSTEM); // size of dynamic buffer
87 Var sys_maxelems("sys_maxelems", 0, VF_SYSTEM); // number of elements
88 Var v_camnear("v_camnear", 4);
89 Var v_camfar("v_camfar", 50000);
90
cmd_setclearcolor(int argc,char * argv[])91 void cmd_setclearcolor(int argc, char *argv[])
92 {
93 if (argc > 4)
94 {
95 glClearColor((float) atof(argv[1]), (float) atof(argv[2]), (float) atof(argv[3]), (float) atof(argv[4]));
96 }
97 else gConsole->Insertln("usage: %s <value> <value> <value> <value>", argv[0]);
98 }
99
100 Shader * State::curr_shader = NULL;
101 Shader * State::curr_effect = NULL;
102 int State::curr_depthFunc = GL_LEQUAL;
103 int State::curr_depthWrite = true;
104 int State::curr_blenddst = GL_ONE;
105 int State::curr_blendsrc = GL_ZERO;
106 int State::curr_culling = CULL_NONE;
107 int State::curr_alphaFunc;
108 int State::curr_polygonmode = GL_FILL;
109 int State::skipping = 0;
110 int State::curr_texture[];
111 int State::curr_lightmap = ~0;
112 int State::pass = 0;
113 int State::last_tcgen[MAX_TEXTURE_UNITS];
114
115 GLboolean lighting, texture, depthtest;
116 int texture_unit;
117
118 // buffer states
119 enum
120 {
121 BF_EMPTY,
122 BF_FILLING,
123 BF_LOCKED
124 };
125
126 // Constructor
Render()127 Render::Render()
128 {
129 ready = 0;
130
131 fogtexture.mem = NULL;
132
133 swapbuffersfunc = NULL;
134
135 gridpass = 0;
136
137 for (int i = 0; i < MAX_TEXTURE_UNITS; ++i)
138 {
139 buffer[i].st = NULL;
140 buffer[i].c = NULL;
141 }
142 input.c = NULL;
143 input.elems = NULL;
144 input.fog = NULL;
145 input.lm_st = NULL;
146 input.normal = NULL;
147 input.numelems = 0;
148 input.numverts = 0;
149 input.tex_st = NULL;
150 input.xyz = NULL;
151
152 current_camera = NULL;
153
154 // Registering variables
155 gVars->RegisterVar(gl_vendor);
156 gVars->RegisterVar(gl_renderer);
157 gVars->RegisterVar(gl_version);
158 gVars->RegisterVar(gl_extensions);
159 gVars->RegisterVar(gl_maxTextureSize);
160 gVars->RegisterVar(gl_maxTextureUnits);
161 gVars->RegisterVar(gl_dither);
162 gVars->RegisterVar(r_ext_compiledVertexArray);
163 gVars->RegisterVar(r_ext_multitexture);
164 gVars->RegisterVar(r_ext_texture_edge_clamp);
165 gVars->RegisterVar(r_usedTextureUnits);
166 gVars->RegisterVar(r_vertexLight);
167 gVars->RegisterVar(r_texturebits);
168 gVars->RegisterVar(r_quality);
169 gVars->RegisterVar(r_picmip);
170 gVars->RegisterVar(r_nolightmap);
171 gVars->RegisterVar(r_noshader);
172 gVars->RegisterVar(r_novertexcolor);
173 gVars->RegisterVar(r_filter);
174 gVars->RegisterVar(r_nocull);
175 gVars->RegisterVar(r_nofog);
176 gVars->RegisterVar(v_depthBits);
177 gVars->RegisterVar(v_stencilBits);
178 gVars->RegisterVar(v_mode);
179 gVars->RegisterVar(wnd_handle);
180 gVars->RegisterVar(v_overbrightbits);
181 gVars->RegisterVar(v_gamma);
182 gVars->RegisterVar(v_lightness);
183 gVars->RegisterVar(r_nodeform);
184 gVars->RegisterVar(r_clear);
185 gVars->RegisterVar(v_aspect);
186 gVars->RegisterVar(v_fullscreen);
187 gVars->RegisterVar(v_hz);
188 gVars->RegisterVar(v_colorBits);
189 gVars->RegisterVar(v_height);
190 gVars->RegisterVar(v_width);
191 gVars->RegisterVar(v_top);
192 gVars->RegisterVar(v_left);
193 gVars->RegisterVar(r_subdivision);
194 gVars->RegisterVar(r_curvefactor);
195 gVars->RegisterVar(sys_buffersize);
196 gVars->RegisterVar(sys_maxelems);
197 gVars->RegisterVar(v_camnear);
198 gVars->RegisterVar(v_camfar);
199
200 gCommands->AddCommand("setclearcolor", cmd_setclearcolor, "Define the clear color (need to be enabled with r_clear variable).");
201 }
202
203 // Destructor
~Render(void)204 Render::~Render(void)
205 {
206 for (int i = 0; i < MAX_TEXTURE_UNITS; ++i)
207 {
208 if (buffer[i].st) cake_free(buffer[i].st);
209 if (buffer[i].c) cake_free(buffer[i].c);
210 }
211 if (input.xyz) cake_free(input.xyz); input.xyz = NULL;
212 if (input.tex_st) cake_free(input.tex_st); input.tex_st = NULL;
213 if (input.lm_st) cake_free(input.lm_st); input.lm_st = NULL;
214 if (input.normal) cake_free(input.normal); input.normal = NULL;
215 if (input.c) cake_free(input.c); input.c = NULL;
216 if (input.fog) cake_free(input.fog); input.fog = NULL;
217 if (input.elems) cake_free(input.elems); input.elems = NULL;
218
219 sys_buffersize = 0;
220 sys_maxelems = 0;
221
222 if (fogtexture.mem) delete [] fogtexture.mem;
223 fogtexture.mem = NULL;
224
225 // Unregister variables
226 gVars->UnregisterVar(gl_vendor);
227 gVars->UnregisterVar(gl_renderer);
228 gVars->UnregisterVar(gl_version);
229 gVars->UnregisterVar(gl_extensions);
230 gVars->UnregisterVar(gl_maxTextureSize);
231 gVars->UnregisterVar(gl_maxTextureUnits);
232 gVars->UnregisterVar(gl_dither);
233 gVars->UnregisterVar(r_ext_compiledVertexArray);
234 gVars->UnregisterVar(r_ext_multitexture);
235 gVars->UnregisterVar(r_ext_texture_edge_clamp);
236 gVars->UnregisterVar(r_usedTextureUnits);
237 gVars->UnregisterVar(r_vertexLight);
238 gVars->UnregisterVar(r_texturebits);
239 gVars->UnregisterVar(r_clear);
240 gVars->UnregisterVar(r_quality);
241 gVars->UnregisterVar(r_picmip);
242 gVars->UnregisterVar(r_nolightmap);
243 gVars->UnregisterVar(r_noshader);
244 gVars->UnregisterVar(r_novertexcolor);
245 gVars->UnregisterVar(r_filter);
246 gVars->UnregisterVar(r_nocull);
247 gVars->UnregisterVar(r_nofog);
248 gVars->UnregisterVar(v_fullscreen);
249 gVars->UnregisterVar(v_width);
250 gVars->UnregisterVar(v_height);
251 gVars->UnregisterVar(v_top);
252 gVars->UnregisterVar(v_left);
253 gVars->UnregisterVar(v_aspect);
254 gVars->UnregisterVar(v_colorBits);
255 gVars->UnregisterVar(v_hz);
256 gVars->UnregisterVar(v_depthBits);
257 gVars->UnregisterVar(v_stencilBits);
258 gVars->UnregisterVar(v_gamma);
259 gVars->UnregisterVar(v_mode);
260 gVars->UnregisterVar(wnd_handle);
261 gVars->UnregisterVar(v_overbrightbits);
262 gVars->UnregisterVar(v_lightness);
263 gVars->UnregisterVar(r_nodeform);
264 gVars->UnregisterVar(r_subdivision);
265 gVars->UnregisterVar(r_curvefactor);
266 gVars->UnregisterVar(sys_buffersize);
267 gVars->UnregisterVar(sys_maxelems);
268 gVars->UnregisterVar(v_camnear);
269 gVars->UnregisterVar(v_camfar);
270 gCommands->RemoveCommand("setclearcolor");
271 }
272
273 // Initialize the render
Init(swapcommand_t func)274 int Render::Init(swapcommand_t func)
275 {
276 // Initializing driver
277 int temp;
278
279 swapbuffersfunc = func;
280
281 gConsole->Insertln("<br/><b>^6----- Initializing driver -------------------------------------</b>");
282
283 // Creates buffers
284 gConsole->Insertln("<b>Creating buffers...</b>");
285 IncreaseBuffer(BUFFER_SIZE_BLOC<<3);
286 IncreaseElems(ELEMS_BLOC<<2);
287 //IncreaseBuffer(1000000);
288 //IncreaseElems(4000000);
289
290 // get driver infos
291 gVars->SetKeyValue("gl_vendor", (char*)glGetString(GL_VENDOR));
292 gVars->SetKeyValue("gl_renderer", (char*)glGetString(GL_RENDERER));
293 gVars->SetKeyValue("gl_version", (char*)glGetString(GL_VERSION));
294 gVars->SetKeyValue("gl_extensions", (char*)glGetString(GL_EXTENSIONS));
295
296 // Check float size
297 if (4*sizeof(float) != XYZ_OFFSET)
298 ThrowException(DEFAULT_EXCEPTION, "gRender->Init - float should be 4 bytes wide");
299
300 // Report some infos
301 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &temp);
302 CheckGLError(5);
303 gl_maxTextureSize = temp;
304
305 // Initialize extensions:
306
307 // compiled vertex array
308 if (CheckExtension("GL_EXT_compiled_vertex_array"))
309 {
310 glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) lglGetProcAddress("glLockArraysEXT");
311 glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) lglGetProcAddress("glUnlockArraysEXT");
312 r_ext_compiledVertexArray = 1;
313 CheckGLError(2);
314 }
315 else
316 {
317 r_ext_compiledVertexArray = 0;
318 gConsole->Insertln("^1Compiled vertex array extension (GL_EXT_compiled_vertex_array) not supported");
319 }
320
321 // multitexture
322 if (CheckExtension("GL_ARB_multitexture"))
323 {
324 r_ext_multitexture = 1;
325
326 #ifdef WIN32
327 glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) lglGetProcAddress("glActiveTextureARB");
328 glClientActiveTextureARB= (PFNGLCLIENTACTIVETEXTUREARBPROC) lglGetProcAddress("glClientActiveTextureARB");
329 #endif
330 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &temp);
331 gl_maxTextureUnits = temp;
332 r_usedTextureUnits = min(temp, MAX_TEXTURE_UNITS);
333 CheckGLError(3);
334 }
335 else
336 {
337 r_ext_multitexture = 0;
338 gl_maxTextureUnits = 1;
339 r_usedTextureUnits = 1;
340 gConsole->Insertln("^1ARB multitexture extension (GL_ARB_multitexture) not supported");
341 }
342
343 // texture clamp
344 if (CheckExtension("EXT_texture_edge_clamp"))
345 {
346 r_ext_texture_edge_clamp = 1;
347 }
348 else
349 {
350 r_ext_texture_edge_clamp = 0;
351 gConsole->Insertln("^1Texture edge clamp extension (EXT_texture_edge_clamp) not supported");
352 }
353
354 // Display OpenGL infos
355 gConsole->Insertln("<b>OpenGL Driver Infos :</b>");
356 gConsole->Insertln("\tgl_vendor :"); gConsole->Insertln("\t\t%s", gl_vendor.svalue);
357 gConsole->Insertln("\tgl_renderer :"); gConsole->Insertln("\t\t%s", gl_renderer.svalue);
358 gConsole->Insertln("\tgl_version :"); gConsole->Insertln("\t\t%s", gl_version.svalue);
359 gConsole->Insertln("\tgl_extensions :");
360
361 char *exts = gl_extensions.svalue;
362 char buffer[4096] = {'\0'};
363 char tmp[2] = {'\0'};
364 int lexts = (int) strlen(exts);
365 for (int i = 0; i < lexts; ++i)
366 {
367 if (exts[i] == ' ' && i != lexts-1)
368 {
369 gConsole->Insertln("\t\t%s", buffer);
370 memset(buffer, '\0', 4096);
371 }
372 else
373 {
374 tmp[0] = exts[i]; tmp[1] = '\0';
375 strcat(buffer, tmp);
376 }
377 }
378 gConsole->Insertln("\t\t%s", buffer);
379 gConsole->Insertln("\tgl_max_texture_size : %s", gVars->StringForKey("gl_maxTextureSize"));
380 gConsole->Insertln("\tgl_max_texture_units : %s (used : %s)",
381 gVars->StringForKey("gl_maxTextureUnits"), gVars->StringForKey("r_usedTextureUnits"));
382
383 // Generate fog map
384 CreateFogTexture(&fogtexture);
385 //WriteBitmapFile("fogtexture.bmp", FOG_TEXTURE_WIDTH, FOG_TEXTURE_HEIGHT, FOG_TEXTURE_BPP, fogtexture.mem);
386
387 // Initialize state
388 State::SetInitialState(r_ext_multitexture.ivalue);
389
390 //_controlfp(_PC_24, _MCW_PC);
391 state = BF_EMPTY;
392 input.numverts = 0;
393 input.numelems = 0;
394
395 ready = 1;
396
397 return 1;
398 }
399
Shut(void)400 void Render::Shut(void)
401 {
402 ready = 0;
403
404 State::setDepthWrite(GL_TRUE); // must be true before clearing!
405 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
406 CheckGLError();
407
408 /** @test order? */
409 //wglMakeCurrent(0,0); // -> generate an opengl error (0x502)
410 //HGLRC app_rc = wglGetCurrentContext();
411 //wglDeleteContext(app_rc);
412 //CheckGLError(3);
413 }
414
IncreaseBuffer(unsigned int newsize)415 void Render::IncreaseBuffer(unsigned int newsize)
416 {
417 if (newsize <= (unsigned) sys_buffersize.ivalue) return;
418
419 int i;
420
421 if (sys_buffersize.ivalue)
422 {
423 for (i = 0; i < MAX_TEXTURE_UNITS; ++i)
424 {
425 buffer[i].st = (float*) cake_realloc(buffer[i].st, (newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.buffer.st");
426 buffer[i].c = (byte*) cake_realloc(buffer[i].c, (newsize<<2)*sizeof(byte), "gRender->IncreaseBuffer.buffer.c");
427 }
428 input.xyz = (float*) cake_realloc(input.xyz, (newsize<<2)*sizeof(float), "gRender->IncreaseBuffer.xyz");
429 input.tex_st = (float*) cake_realloc(input.tex_st, (newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.tex_st");
430 input.lm_st = (float*) cake_realloc(input.lm_st, (newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.lm_st");
431 input.normal = (float*) cake_realloc(input.normal, (newsize<<2)*sizeof(float), "gRender->IncreaseBuffer.normal");
432 input.c = (byte*) cake_realloc(input.c, (newsize<<2)*sizeof(byte), "gRender->IncreaseBuffer.c");
433 #if MODIF_FOG
434 input.fog = (cplane_t**) cake_realloc(input.fog, newsize*sizeof(cplane_t*), "gRender->IncreaseBuffer.fog");
435 #else
436 input.fog = (float*) cake_realloc(input.fog, 5*newsize*sizeof(float), "gRender->IncreaseBuffer.fog");
437 #endif
438 }
439 else
440 {
441 for (i = 0; i < MAX_TEXTURE_UNITS; ++i)
442 {
443 buffer[i].st = (float*) cake_malloc((newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.buffer.st");
444 buffer[i].c = (byte*) cake_malloc((newsize<<2)*sizeof(byte), "gRender->IncreaseBuffer.buffer.c");
445 }
446 input.xyz = (float*) cake_malloc((newsize<<2)*sizeof(float), "gRender->IncreaseBuffer.xyz");
447 input.tex_st = (float*) cake_malloc((newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.tex_st");
448 input.lm_st = (float*) cake_malloc((newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.lm_st");
449 input.normal = (float*) cake_malloc((newsize<<2)*sizeof(float), "gRender->IncreaseBuffer.normal");
450 input.c = (byte*) cake_malloc((newsize<<2)*sizeof(byte), "gRender->IncreaseBuffer.c");
451 #if MODIF_FOG
452 input.fog = (cplane_t**) cake_malloc(newsize*sizeof(cplane_t*), "gRender->IncreaseBuffer.fog");
453 #else
454 input.fog = (float*) cake_malloc(5*newsize*sizeof(float), "gRender->IncreaseBuffer.fog");
455 #endif
456 }
457
458 sys_buffersize = (int) newsize;
459
460 // Check for memory fails
461 bool failed = false;
462 for (i = 0; i < MAX_TEXTURE_UNITS; ++i)
463 if (!buffer[i].st || !buffer[i].c)
464 {
465 failed = true;
466 break;
467 }
468
469 failed = (!failed && (!input.xyz || !input.tex_st || !input.lm_st || !input.normal || !input.c || !input.fog));
470
471 if (failed)
472 {
473 if (gConsole) gConsole->Insertln("^1gRender->IncreaseBuffer: Cannot allocate required size");
474 else if (gLogFile) gLogFile->Insert("^1gRender->IncreaseBuffer: Cannot allocate required size\n");
475 }
476 else if (gLogFile) gLogFile->Insert("\tInput buffer increased to %d.\n", newsize);
477 }
478
IncreaseElems(unsigned int newsize)479 void Render::IncreaseElems(unsigned int newsize)
480 {
481 if (newsize <= (unsigned) sys_maxelems.ivalue) return;
482
483 if (sys_maxelems.ivalue)
484 input.elems = (unsigned int*) cake_realloc(input.elems, newsize*sizeof(unsigned int), "gRender->IncreaseElems.elems");
485 else
486 input.elems = (unsigned int*) cake_malloc(newsize*sizeof(unsigned int), "gRender->IncreaseElems.elems");
487
488 sys_maxelems = (int) newsize;
489
490 if (!input.elems)
491 {
492 if (gConsole) gConsole->Insertln("^1gRender->IncreaseElems: Cannot allocate required size");
493 else if (gLogFile) gLogFile->Insert("^1gRender->IncreaseElems: Cannot allocate required size\n");
494 }
495 else if (gLogFile) gLogFile->Insert("\tElems buffer increased to %d.\n", newsize);
496 }
497
SetWindowSettings(GLsizei w,GLsizei h,GLint c,GLint f)498 void Render::SetWindowSettings(GLsizei w, GLsizei h, GLint c, GLint f)
499 {
500 if (w > 0) v_width = w;
501 if (h > 0) v_height = h;
502 if (c > 0) v_colorBits = c;
503 if (f > 0) v_hz = f;
504
505 gConsole->Resize(v_width.ivalue - 2*gConsole->GetLeft(), (int) (v_height.ivalue/2));
506 }
507
GetWidth(void)508 int Render::GetWidth(void)
509 {
510 return v_width.ivalue;
511 }
512
GetHeight(void)513 int Render::GetHeight(void)
514 {
515 return v_height.ivalue;
516 }
517
GetTop(void)518 int Render::GetTop(void)
519 {
520 return v_top.ivalue;
521 }
522
GetLeft(void)523 int Render::GetLeft(void)
524 {
525 return v_left.ivalue;
526 }
527
CreateFogTexture(texinfo * t)528 void Render::CreateFogTexture(texinfo *t)
529 {
530 t->num = -1;
531 t->width = FOG_TEXTURE_WIDTH;
532 t->height = FOG_TEXTURE_HEIGHT;
533 t->bpp = FOG_TEXTURE_BPP;
534 t->mem = new byte[FOG_TEXTURE_WIDTH*FOG_TEXTURE_HEIGHT*FOG_TEXTURE_BPP];
535
536 float tw = 1.0f / ((float)t->width - 1.0f);
537 float th = 1.0f / ((float)t->height - 1.0f);
538 float tx = 0.0f;
539 float ty = 0.0f;
540 float a;
541 for (int y = 1; y < t->height; ++y, ty += th)
542 {
543 tx = 0.0f;
544 for (int x = 0; x < t->width; ++x, tx += tw)
545 {
546 //a = tx * 255.0f; // LINEAR
547 // squared fog-thickness proportional to linear distance seems to be best looking
548 a = sqrtf(tx) * 255.0f; //SQUARE
549 if (a > 255.0f) a = 255.0f;
550 for (int i = 0; i < t->bpp; ++i)
551 t->mem[(y*t->width+x)*t->bpp+i] = (byte) a;
552 }
553 }
554
555 for (int x = 0; x < t->width*t->bpp; ++x)
556 {
557 t->mem[x] = 0;
558 }
559
560 RegisterTexInfo(t, LF_NOMIPMAP|LF_NOPICMIP|LF_CLAMP);
561 }
562
563
564 //-----------------------------------------------------------------------------
565 // Drawing
566 //-----------------------------------------------------------------------------
567
568 // Begin Frame
BeginFrame(void)569 int Render::BeginFrame(void)
570 {
571 State::setDepthWrite(GL_TRUE); // must be true before clearing!
572
573 if (r_clear.ivalue)
574 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
575 else
576 glClear(GL_DEPTH_BUFFER_BIT);
577
578 State::setPolygonMode(GL_FILL);
579
580 glEnable(GL_TEXTURE_2D);
581
582 CheckGLError(3);
583
584 state = BF_EMPTY;
585
586 Timer::Refresh(); // update the timer for the new frame
587
588 // initialize counters
589 num_tris = 0;
590 num_flush = 0;
591 num_verts = 0;
592 num_apicalls = 0;
593
594 return 1;
595 }
596
597 // Ends Frame
EndFrame(void)598 int Render::EndFrame(void)
599 {
600 // Flush all the buffers
601 if (state != BF_EMPTY) Flush();
602
603 return 1;
604 }
605
606 // Determine if an extension is supported, must be called after a valid
607 // context has been created
CheckExtension(char * extName)608 bool Render::CheckExtension(char *extName)
609 {
610 char *extensions = (char *) glGetString(GL_EXTENSIONS);
611 CheckGLError();
612 if (strstr(extensions, extName)) return true;
613 return false;
614 }
615
616 // Register Texinfo by loading the texture into video memory
RegisterTexInfo(texinfo * tex,int flags)617 int Render::RegisterTexInfo(texinfo *tex, int flags)
618 {
619 int picmip = (flags & LF_NOPICMIP)?0:r_picmip.ivalue;
620 if (picmip < 0) picmip = 0;
621 int newwidth = (1 << Log2(tex->width)) >> picmip;
622 int newheight = (1 << Log2(tex->height)) >> picmip;
623 if (newwidth <= 0) newwidth = 1;
624 if (newheight <= 0) newheight = 1;
625 int format, outformat;
626 float fform;
627 byte *mem = tex->mem;
628
629 if (tex->num != ~0) return 1; // FIXME: �1?
630
631 switch (tex->bpp)
632 {
633 case 1:
634 format = GL_ALPHA;
635 outformat = GL_ALPHA;
636 break;
637 case 2:
638 format = GL_LUMINANCE_ALPHA; // do I support that??
639 outformat = GL_LUMINANCE_ALPHA;
640 break;
641 case 3:
642 format = GL_RGB;
643 fform = r_texturebits.fvalue;
644 switch ((int) fform)
645 {
646 // FIXME: float to int conversion !!!
647 case 16:
648 outformat = GL_RGB5;
649 break;
650 case 32:
651 outformat = GL_RGB8;
652 break;
653 default:
654 outformat = GL_RGB;
655 break;
656 }
657 break;
658 case 4:
659 format = GL_RGBA;
660 fform = r_texturebits.fvalue;
661 switch ((int)fform)
662 {
663 // FIXME: float to int conversion !!!
664 case 16:
665 outformat = GL_RGBA4;
666 break;
667 case 32:
668 outformat = GL_RGBA8;
669 break;
670 default:
671 outformat = GL_RGBA;
672 break;
673 }
674 break;
675 default:
676 format = GL_RGB;
677 outformat = GL_RGB;
678 break;
679 }
680
681 if (newheight > gl_maxTextureSize.ivalue) newheight = gl_maxTextureSize.ivalue;
682 if (newwidth > gl_maxTextureSize.ivalue) newwidth = gl_maxTextureSize.ivalue;
683
684 if (tex->height != newheight || tex->width != newwidth)
685 {
686 mem = (byte *) cake_malloc(newheight*newwidth*tex->bpp, "gRender->RegisterTexInfo.mem");
687 ScaleImage(format, tex->width, tex->height, tex->mem, newwidth, newheight, mem);
688 }
689
690 glGenTextures(1, (GLuint*) &tex->num);
691 glBindTexture(GL_TEXTURE_2D, tex->num);
692 CheckGLError(2);
693
694 if (flags & LF_NOMIPMAP)
695 {
696 glTexImage2D(GL_TEXTURE_2D, 0, outformat, newwidth, newheight, 0, format, GL_UNSIGNED_BYTE, mem);
697 CheckGLError();
698 }
699 else
700 BuildMipmaps(outformat, newwidth, newheight, format, mem);
701
702 if (flags & LF_CLAMP)
703 {
704 if (r_ext_texture_edge_clamp.ivalue)
705 {
706 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
707 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
708 }
709 else
710 {
711 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
712 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
713 }
714 }
715 else
716 {
717 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
718 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
719 }
720 CheckGLError(2);
721
722 //float filter = Import.cvars->ValueForKey("gl_filter");
723
724 if (r_filter.ivalue == 0)
725 {
726 // nearest
727 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
728 if (flags & LF_NOMIPMAP)
729 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
730 else
731 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
732 CheckGLError(2);
733 }
734 else if (r_filter.ivalue == 2)
735 {
736 // trilinear
737 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
738 if (flags & LF_NOMIPMAP)
739 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
740 else
741 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
742 CheckGLError(2);
743 }
744 else /*if (r_filter.ivalue == 1)*/
745 {
746 // bilinear
747 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
748 if (flags & LF_NOMIPMAP)
749 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
750 else
751 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
752 CheckGLError(2);
753 }
754
755 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); CheckGLError();
756 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); CheckGLError();
757
758 if (mem != tex->mem) cake_free(mem);
759 return 1;
760 }
761
762 // Deletes texture memory
UnregisterTexInfo(texinfo * tex)763 void Render::UnregisterTexInfo(texinfo *tex)
764 {
765 glDeleteTextures(1, (GLuint*) &tex->num);
766 CheckGLError();
767 }
768
769 // Sets the given render state
SetRenderState(Shader * s,int lightmap,Shader * e)770 void Render::SetRenderState(Shader *s, int lightmap, Shader *e)
771 {
772 // FIXME: If State::curr_shader is NULL, State::skipping will be true. Then this
773 // will have as consequence that Flushing will be aborted and reported to next
774 // time where State::curr_shader is not NULL and faces that are already in input
775 // struct may have wrong shader when rendered. So what is better ? Render them
776 // with wrong shader or not render them at all ?
777 if (state != BF_EMPTY) Flush();
778
779 State::curr_shader = s;
780
781 if (r_nolightmap.ivalue) State::curr_lightmap = ~0;
782 else State::curr_lightmap = lightmap;
783
784 State::curr_effect = e;
785
786 State::skipping = (!s || s->surface_flags & SURF_SKIP || s->surface_flags & SURF_NODRAW);
787 }
788
InitializeViewPort(void)789 void Render::InitializeViewPort(void)
790 {
791 if (state != BF_EMPTY) Flush();
792
793 glViewport(0, 0, v_width.ivalue, v_height.ivalue);
794 glScissor(0, 0, v_width.ivalue, v_height.ivalue);
795
796 glMatrixMode(GL_MODELVIEW);
797 glLoadIdentity();
798 glMatrixMode(GL_PROJECTION);
799 glLoadIdentity();
800
801 glOrtho(0, v_width.ivalue, v_height.ivalue, 0, 0.0f, 1.0f);
802
803 CheckGLError(7);
804
805 // Initializing state
806 State::setBlend(GL_ONE, GL_ZERO);
807 State::setAlphaFunc(GL_ALWAYS, 0);
808 State::setDepthFunc(GL_LEQUAL);
809 State::setDepthWrite(GL_TRUE);
810 State::setCulling(CULL_NONE);
811 }
812
813 // Write vertexes in the input, Flush when full
PushTriangles(Surface * surf,int * visible)814 void Render::PushTriangles(Surface *surf, int *visible)
815 {
816 if (!surf) return;
817 if (State::skipping) return;
818
819 int level = surf->currentlevel;
820 if (level < 0 || level >= surf->levels)
821 {
822 gConsole->Insertln("^1ERROR: Invalid surface level !");
823 return;
824 }
825 if (surf->numelems[level] == 0 || surf->numverts[level] == 0) return;
826
827 // Force flushing before resizing buffer to avoid problems
828 if (input.numverts + surf->numverts[level] >= sys_buffersize.ivalue ||
829 input.numelems + surf->numelems[level] >= sys_maxelems.ivalue)
830 ForceFlush();
831
832 // Check buffers overflow
833 while (input.numverts + surf->numverts[level] >= sys_buffersize.ivalue)
834 IncreaseBuffer(input.numverts + surf->numverts[level] + BUFFER_SIZE_BLOC);
835
836 while (input.numelems + surf->numelems[level] >= sys_maxelems.ivalue)
837 IncreaseElems(input.numelems + surf->numelems[level] + ELEMS_BLOC);
838
839 float * xyz;
840 float * st;
841 vertex_t * v;
842 int i;
843
844 state = BF_FILLING; // filling the buffer
845
846 // adding elements to input data
847 if (visible)
848 {
849 for (i = 0; i < surf->numelems[level]; ++i)
850 if (visible[i])
851 input.elems[input.numelems++] = input.numverts + surf->firstelem[level][i];
852 }
853 else
854 {
855 for (i = 0; i < surf->numelems[level]; ++i)
856 input.elems[input.numelems++] = input.numverts + surf->firstelem[level][i];
857 }
858
859 // vertices
860 xyz = &input.xyz[input.numverts<<2];
861 v = surf->firstvert[level], i = surf->numverts[level];
862 do
863 {
864 VectorCopy(v->v_point, xyz);
865 xyz += 4; // 4 coordinates for a vertex
866 ++v;
867 } while (--i);
868
869 // texture coordinates
870 st = &input.tex_st[input.numverts<<1];
871 v = surf->firstvert[level], i = surf->numverts[level];
872 do
873 {
874 TexcoordCopy(v->tex_st, st);
875 st += 2; // 2 coordinates s & t
876 ++v;
877 } while (--i);
878
879 if (State::curr_shader->flags & SF_HASLIGHTMAP)
880 {
881 st = &input.lm_st[input.numverts<<1];
882 v = surf->firstvert[level], i = surf->numverts[level];
883 do
884 {
885 TexcoordCopy(v->lm_st, st);
886 st += 2;
887 ++v;
888 } while (--i);
889 }
890
891 if (State::curr_shader->flags & SF_USENORMALS)
892 {
893 float *n = &input.normal[input.numverts<<2];
894 v = surf->firstvert[level], i = surf->numverts[level];
895 do
896 {
897 VectorCopy(v->v_norm, n);
898 n += 4;
899 ++v;
900 } while (--i);
901 }
902
903 if (State::curr_shader->flags & SF_HASCOLORS)
904 {
905 byte *c = &input.c[input.numverts<<2];
906 v = surf->firstvert[level], i = surf->numverts[level];
907 do
908 {
909 ColorCopy(v->colour, c);
910 c += 4;
911 ++v;
912 } while (--i);
913 }
914
915 SetVertexCoords(surf, level); // Apply vertex coordinates transformations for the surface
916
917 #if MODIF_FOG
918 // Get fog plane pointer
919 //if (surf->fogplane)
920 {
921 cplane_t** f = &input.fog[input.numverts];
922 i = surf->numverts[level];
923 do
924 {
925 *f++ = surf->fogplane;
926 } while(--i);
927 }
928 #else
929 // Store triangle normal and distance in input data (for fog)
930 float *f = &input.fog[input.numverts * 5];
931 i = surf->numverts[level];
932 do
933 {
934 memcpy(f, surf->fog, 5*sizeof(float));
935 f += 5;
936 } while (--i);
937 #endif
938
939 input.numverts += surf->numverts[level];
940 }
941
942 // Flush a buffer setting the appropriate state
Flush(void)943 void Render::Flush(void)
944 {
945 Shader* s = State::curr_shader;
946
947 if (!input.numelems /*|| !s->num_layers*/) return;
948 if (State::skipping) return;
949
950 // set buffer states:
951 state = BF_LOCKED;
952 buffer[0].st_content = -1; // the buffers are always dirty the first time.
953 buffer[1].st_content = -1;
954 buffer[0].c_content = -1;
955 buffer[1].c_content = -1;
956
957 if (!gridpass)
958 {
959 State::SetupShader();
960
961 // select render path
962 if (r_vertexLight.ivalue)
963 FlushVertexLit();
964 else if (r_ext_compiledVertexArray.ivalue)
965 {
966 if (r_ext_multitexture.ivalue && (s->flags & SF_MULTITEX))
967 FlushMtxCVA();
968 else if (s->num_layers == 1)
969 FlushSingleCVA();
970 else
971 FlushGenericCVA();
972 }
973 else
974 {
975 if (r_ext_multitexture.ivalue && (s->flags & SF_MULTITEX))
976 FlushMtx();
977 else if (s->num_layers == 1)
978 FlushSingle();
979 else
980 FlushGeneric();
981 }
982
983 if (!r_nofog.ivalue &&
984 State::curr_effect &&
985 State::curr_effect->content_flags & CONTENTS_FOG)
986 {
987 // Render fog pass
988 Layer *l = State::curr_effect->fog_params.layer;
989 if (l)
990 {
991 glMatrixMode(GL_TEXTURE);
992 glPushMatrix();
993 SetTextureCoordinates(0, l);
994 SetVertexColors(0, l);
995 State::BindTexture(l, 0);
996 State::setState(l);
997 // glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
998 if (r_ext_compiledVertexArray.ivalue)
999 {
1000 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1001 glDisableClientState(GL_COLOR_ARRAY);
1002 glLockArraysEXT(0, input.numverts);
1003 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1004 glEnableClientState(GL_COLOR_ARRAY);
1005 glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1006 glUnlockArraysEXT();
1007 CheckGLError(7);
1008 }
1009 else
1010 {
1011 Stripmine(input.numelems, input.elems);
1012 }
1013 glPopMatrix();
1014 CheckGLError(3);
1015 }
1016 }
1017 }
1018 else
1019 {
1020 if (r_ext_compiledVertexArray.ivalue) FlushGridCVA();
1021 else FlushGrid();
1022 }
1023
1024 // update counters
1025 num_tris += input.numelems/3;
1026 num_verts += input.numverts;
1027 ++num_flush;
1028
1029 // clear buffer state:
1030 state = BF_EMPTY;
1031 input.numelems = 0;
1032 input.numverts = 0;
1033 }
1034
ForceFlush(void)1035 void Render::ForceFlush(void)
1036 {
1037 if (state != BF_EMPTY) Flush(); // Flush all the buffers
1038 }
1039
1040 // Flush multitexture faces using CVAs
FlushMtxCVA(void)1041 void Render::FlushMtxCVA(void)
1042 {
1043 glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1044
1045 glDisableClientState(GL_TEXTURE_COORD_ARRAY); // don't allow to cache this!
1046 glDisableClientState(GL_COLOR_ARRAY);
1047 glLockArraysEXT(0, input.numverts);
1048 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1049 glEnableClientState(GL_COLOR_ARRAY);
1050
1051 Layer *l;
1052
1053 for (State::pass = 0; State::pass < State::curr_shader->num_layers; ++State::pass)
1054 {
1055 l = State::curr_shader->layer[State::pass];
1056
1057 SetTextureCoordinates(0, l);
1058 SetVertexColors(0, l);
1059
1060 State::BindTexture(l, 0);
1061 State::setState(l);
1062
1063 if (l->flags & LF_MULTITEX)
1064 {
1065 l = State::curr_shader->layer[++State::pass];
1066
1067 glActiveTextureARB(GL_TEXTURE1_ARB);
1068 glClientActiveTextureARB(GL_TEXTURE1_ARB);
1069 glEnable(GL_TEXTURE_2D);
1070 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1071
1072 SetTextureCoordinates(1, l);
1073
1074 State::BindTexture(l, 1);
1075
1076 glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1077
1078 glDisable(GL_TEXTURE_2D);
1079 glActiveTextureARB(GL_TEXTURE0_ARB);
1080 glClientActiveTextureARB(GL_TEXTURE0_ARB);
1081 CheckGLError(8);
1082 }
1083 else
1084 {
1085 glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1086 CheckGLError();
1087 }
1088 }
1089
1090 glUnlockArraysEXT();
1091 CheckGLError(7);
1092 }
1093
1094 // Flush multitexture faces with lightmap
FlushMtx(void)1095 void Render::FlushMtx(void)
1096 {
1097 glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1098 CheckGLError();
1099
1100 Layer *l;
1101
1102 for (State::pass = 0; State::pass < State::curr_shader->num_layers; ++State::pass)
1103 {
1104 l = State::curr_shader->layer[State::pass];
1105
1106 SetTextureCoordinates(0, l);
1107 SetVertexColors(0, l);
1108
1109 State::BindTexture(l, 0);
1110 State::setState(l);
1111 if (l->flags & LF_MULTITEX)
1112 {
1113 l = State::curr_shader->layer[++State::pass];
1114
1115 glActiveTextureARB(GL_TEXTURE1_ARB);
1116 glClientActiveTextureARB(GL_TEXTURE1_ARB);
1117 glEnable(GL_TEXTURE_2D);
1118 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1119
1120 SetTextureCoordinates(1, l);
1121
1122 State::BindTexture(l, 1);
1123
1124 glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1125
1126 glDisable(GL_TEXTURE_2D);
1127 glActiveTextureARB(GL_TEXTURE0_ARB);
1128 glClientActiveTextureARB(GL_TEXTURE0_ARB);
1129 CheckGLError(8);
1130 }
1131 else
1132 {
1133 Stripmine(input.numelems, input.elems);
1134 }
1135 }
1136 }
1137
1138 // Flush faces without lightmap using CVAs
FlushGenericCVA(void)1139 void Render::FlushGenericCVA(void)
1140 {
1141 glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1142
1143 glDisableClientState(GL_TEXTURE_COORD_ARRAY); // don't allow to cache this!
1144 glDisableClientState(GL_COLOR_ARRAY);
1145 glLockArraysEXT(0, input.numverts);
1146 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1147 glEnableClientState(GL_COLOR_ARRAY);
1148
1149 Layer *l;
1150
1151 for (State::pass = 0; State::pass < State::curr_shader->num_layers; ++State::pass)
1152 {
1153 l = State::curr_shader->layer[State::pass];
1154
1155 SetTextureCoordinates(0, l);
1156 SetVertexColors(0, l);
1157
1158 State::BindTexture(l, 0);
1159 State::setState(l);
1160 glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1161 }
1162
1163 glUnlockArraysEXT();
1164 CheckGLError(7+State::curr_shader->num_layers);
1165 }
1166
1167 // Flush faces without lightmap
FlushGeneric(void)1168 void Render::FlushGeneric(void)
1169 {
1170 glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1171 CheckGLError();
1172
1173 Layer *l;
1174
1175 for (State::pass = 0; State::pass < State::curr_shader->num_layers; ++State::pass)
1176 {
1177 l = State::curr_shader->layer[State::pass];
1178
1179 SetTextureCoordinates(0, l);
1180 SetVertexColors(0, l);
1181
1182 State::BindTexture(l, 0);
1183 State::setState(l);
1184 Stripmine(input.numelems, input.elems);
1185 }
1186 }
1187
1188 // Flush faces with a single layer using CVAs
FlushSingleCVA(void)1189 void Render::FlushSingleCVA(void)
1190 {
1191 glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1192 glLockArraysEXT(0, input.numverts);
1193
1194 State::pass = 0;
1195 Layer *l = State::curr_shader->layer[0];
1196
1197 SetTextureCoordinates(0, l);
1198 SetVertexColors(0, l);
1199
1200 State::BindTexture(l, 0);
1201 State::setState(l);
1202 glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1203 glUnlockArraysEXT();
1204 CheckGLError(4);
1205 }
1206
1207 // Flush faces with a single layer without using CVAs
FlushSingle(void)1208 void Render::FlushSingle(void)
1209 {
1210 glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1211 CheckGLError();
1212
1213 State::pass = 0;
1214 Layer *l = State::curr_shader->layer[0];
1215
1216 SetTextureCoordinates(0, l);
1217 SetVertexColors(0, l);
1218
1219 State::BindTexture(l, 0);
1220 State::setState(l);
1221 Stripmine(input.numelems, input.elems);
1222 }
1223
FlushGridCVA(void)1224 void Render::FlushGridCVA(void)
1225 {
1226 State::setBlend(GL_ONE, GL_ZERO);
1227 State::setAlphaFunc(GL_ALWAYS);
1228
1229 glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1230 glLockArraysEXT(0, input.numverts);
1231
1232 glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer[0].c);
1233 memset(buffer[0].c, 255, (input.numverts<<2));
1234 glColor4f(1.f, 1.f, 1.f, 1.f);
1235
1236 glGetBooleanv(GL_TEXTURE_2D, &texture);
1237 glGetBooleanv(GL_LIGHTING, &lighting);
1238 glGetBooleanv(GL_DEPTH_TEST, &depthtest);
1239
1240 State::setPolygonMode(GL_LINE);
1241
1242 glDisable(GL_TEXTURE_2D);
1243 glDisable(GL_LIGHTING);
1244 glDisable(GL_DEPTH_TEST);
1245
1246 glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1247
1248 if (texture) { glEnable(GL_TEXTURE_2D); CheckGLError(); }
1249 if (lighting) { glEnable(GL_LIGHTING); CheckGLError(); }
1250 if (depthtest) { glEnable(GL_DEPTH_TEST); CheckGLError(); }
1251
1252 State::setPolygonMode(GL_FILL);
1253
1254 glUnlockArraysEXT();
1255 CheckGLError(12);
1256 }
1257
FlushGrid(void)1258 void Render::FlushGrid(void)
1259 {
1260 State::setBlend(GL_ONE, GL_ZERO);
1261 State::setAlphaFunc(GL_ALWAYS);
1262
1263 glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1264
1265 glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer[0].c);
1266 memset(buffer[0].c, 255, (input.numverts<<2));
1267 glColor4f(1.f, 1.f, 1.f, 1.f);
1268
1269 glGetBooleanv(GL_TEXTURE_2D, &texture);
1270 glGetBooleanv(GL_LIGHTING, &lighting);
1271 glGetBooleanv(GL_DEPTH_TEST, &depthtest);
1272
1273 State::setPolygonMode(GL_LINE);
1274
1275 glDisable(GL_TEXTURE_2D);
1276 glDisable(GL_LIGHTING);
1277 glDisable(GL_DEPTH_TEST);
1278
1279 glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1280
1281 if (texture) { glEnable(GL_TEXTURE_2D); CheckGLError(); }
1282 if (lighting) { glEnable(GL_LIGHTING); CheckGLError(); }
1283 if (depthtest) { glEnable(GL_DEPTH_TEST); CheckGLError(); }
1284
1285 State::setPolygonMode(GL_FILL);
1286
1287 CheckGLError(12);
1288 }
1289
1290 // FIXME: this is only experimental
FlushVertexLit(void)1291 void Render::FlushVertexLit(void)
1292 {
1293 Layer *l;
1294
1295 glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1296 CheckGLError();
1297
1298 State::pass = 0;
1299 if (State::curr_shader->layer[0]->flags & LF_LIGHTMAP)
1300 {
1301 l = State::curr_shader->layer[++State::pass];
1302
1303 SetTextureCoordinates(0, l);
1304
1305 // glColorPointer(4, GL_UNSIGNED_BYTE, 0, &input.c); CheckGLError();
1306
1307 State::BindTexture(l, 0);
1308
1309 if (State::curr_blendsrc != GL_ONE || State::curr_blenddst != GL_ZERO)
1310 {
1311 glDisable(GL_BLEND);
1312 CheckGLError();
1313 State::curr_blenddst = l->blenddst;
1314 State::curr_blendsrc = l->blendsrc;
1315 }
1316
1317 Stripmine(input.numelems, input.elems);
1318 ++State::pass;
1319 }
1320
1321 for (; State::pass < State::curr_shader->num_layers; ++State::pass)
1322 {
1323 l = State::curr_shader->layer[State::pass];
1324 if (l->flags & LF_LIGHTMAP) continue;
1325
1326 SetTextureCoordinates(0, l);
1327 SetVertexColors(0, l);
1328
1329 State::BindTexture(l, 0);
1330 State::setState(l);
1331 Stripmine(input.numelems, input.elems);
1332 }
1333 }
1334
SwapBuffers(void)1335 void Render::SwapBuffers(void)
1336 {
1337 if (state != BF_EMPTY) Flush();
1338
1339 if (!swapbuffersfunc)
1340 ThrowException(NULL_POINTER, "Undefined swap function pointer for render.");
1341 swapbuffersfunc();
1342 }
1343
1344 // that have been taken from aftershock: (FIXME: can I use it?)
Stripmine(int numelems,unsigned int * elems)1345 void Render::Stripmine(int numelems, unsigned int *elems)
1346 {
1347 bool toggle;
1348 int elem = 0;
1349 unsigned int a, b;
1350
1351 while (elem < numelems)
1352 {
1353 toggle = true;
1354 glBegin(GL_TRIANGLE_STRIP);
1355
1356 glArrayElement(elems[elem++]);
1357 b = elems[elem++]; glArrayElement(b);
1358 a = elems[elem++]; glArrayElement(a);
1359
1360 while (elem < numelems)
1361 {
1362 if (a != elems[elem] || b != elems[elem+1]) break;
1363 if (toggle) { b = elems[elem+2]; glArrayElement(b); }
1364 else { a = elems[elem+2]; glArrayElement(a); }
1365 elem += 3;
1366 toggle = !toggle;
1367 CheckGLError(1);
1368 }
1369 glEnd();
1370 CheckGLError(5);
1371 }
1372 }
1373
SetVertexCoords(Surface * surf,int level)1374 void Render::SetVertexCoords(Surface *surf, int level)
1375 {
1376 if (!State::curr_shader->num_deforms || r_nodeform.ivalue) return;
1377
1378 float args[5], startoff = 0.f, off, wavesize = 1.f, inc;
1379 const float speed = 2;
1380
1381 for (int i = 0; i < MAX_DEFORMS; ++i)
1382 {
1383 switch (State::curr_shader->deformVertexes[i].type)
1384 {
1385 case DEFORMVERTEXES_WAVE:
1386 {
1387 float *xyz = &input.xyz[input.numverts<<2];
1388 vertex_t *v = surf->firstvert[level];
1389 int nverts = surf->numverts[level];
1390 vec3_t p;
1391
1392 args[0] = State::curr_shader->deformVertexes[i].params[0]; // sin
1393 wavesize = State::curr_shader->deformVertexes[i].params[1];
1394 args[1] = State::curr_shader->deformVertexes[i].params[2];
1395 args[2] = State::curr_shader->deformVertexes[i].params[3];
1396 args[4] = State::curr_shader->deformVertexes[i].params[5];
1397 startoff = State::curr_shader->deformVertexes[i].params[4];
1398
1399 do
1400 {
1401 p[0] = *xyz; p[1] = *(xyz+1); p[2] = *(xyz+2);
1402 off = (p[0]+p[1]+p[2])/wavesize;
1403 args[3] = startoff + off;
1404 inc = State::Eval(&args[0]);
1405 *xyz = p[0]+inc*v->v_norm[0];
1406 *(xyz+1) = p[1]+inc*v->v_norm[1];
1407 *(xyz+2) = p[2]+inc*v->v_norm[2];
1408 ++v;
1409 xyz += 4;
1410 } while (--nverts);
1411 }
1412 break;
1413 case DEFORMVERTEXES_NORMAL:
1414 {
1415 float *normal = &input.normal[input.numverts<<2];
1416 float *xyz = &input.xyz[input.numverts<<2];
1417 vertex_t *v = surf->firstvert[level];
1418 int nverts = surf->numverts[level];
1419 vec3_t p, n;
1420
1421 args[0] = FUNC_SIN;
1422 args[2] = State::curr_shader->deformVertexes[i].params[0];
1423 args[4] = State::curr_shader->deformVertexes[i].params[1];
1424 float lat, lng, sinlng;
1425
1426 do
1427 {
1428 p[0] = *xyz; p[1] = *(xyz+1); p[2] = *(xyz+2);
1429 n[0] = *normal; n[1] = *(normal+1); n[2] = *(normal+2);
1430 #if 1
1431 // diesel method
1432 args[1] = atan2f(p[2], -p[0]);
1433 args[3] = p[0]+p[1];
1434 lat = State::Eval(&args[0]);
1435
1436 args[1] = acosf(n[1]);
1437 args[3] = p[2]+p[1];
1438 lng = State::Eval(&args[0]);
1439
1440 sinlng = FastSin(lng);
1441 *(normal ) = -FastCos(lat)*sinlng;
1442 *(normal+1) = FastCos(lng);
1443 *(normal+2) = FastSin(lat)*sinlng;
1444 #else
1445 // another method (real method is not known ;)
1446 off = (p[0]+p[1]+p[2])/(speed*wavesize);
1447 args[3] = startoff + off;
1448 inc = State::Eval(&args[0]);
1449 *(normal ) = n[0]+inc*v->v_norm[0];
1450 *(normal+1) = n[1]+inc*v->v_norm[1];
1451 *(normal+2) = n[2]+inc*v->v_norm[2];
1452 #endif
1453 ++v;
1454 normal += 4;
1455 xyz += 4;
1456 } while (--nverts);
1457 }
1458 break;
1459 case DEFORMVERTEXES_BULGE:
1460 {
1461 if (surf->facetype != FACETYPE_PATCH) break; // are bulge applied on other face types ?
1462 float *xyz = &input.xyz[input.numverts<<2];
1463 float *st = &input.tex_st[input.numverts<<1];
1464 vertex_t *v = surf->firstvert[level];
1465 int nverts = surf->numverts[level];
1466
1467 args[0] = FUNC_SIN; // sin
1468 args[1] = 0;
1469 args[2] = State::curr_shader->deformVertexes[i].params[1];
1470 args[4] = 1/(speed*State::curr_shader->deformVertexes[i].params[0]);
1471
1472 do
1473 {
1474 args[3] = *st*speed*State::curr_shader->deformVertexes[i].params[2];
1475 inc = State::Eval(&args[0]);
1476 *xyz += inc*v->v_norm[0];
1477 *(xyz+1) += inc*v->v_norm[1];
1478 *(xyz+2) += inc*v->v_norm[2];
1479 ++v;
1480 xyz += 4;
1481 st += 2;
1482 } while (--nverts);
1483 }
1484 break;
1485 case DEFORMVERTEXES_MOVE:
1486 {
1487 float *xyz = &input.xyz[input.numverts<<2];
1488 vertex_t *v = surf->firstvert[level];
1489 int nverts = surf->numverts[level];
1490
1491 args[0] = State::curr_shader->deformVertexes[i].params[0]; // sin
1492 args[1] = State::curr_shader->deformVertexes[i].params[4];
1493 args[2] = State::curr_shader->deformVertexes[i].params[5];
1494 args[3] = State::curr_shader->deformVertexes[i].params[6];
1495 args[4] = State::curr_shader->deformVertexes[i].params[7];
1496
1497 do
1498 {
1499 inc = State::Eval(&args[0]);
1500 *xyz += inc*State::curr_shader->deformVertexes[i].params[1];
1501 *(xyz+1) += inc*State::curr_shader->deformVertexes[i].params[2];
1502 *(xyz+2) += inc*State::curr_shader->deformVertexes[i].params[3];
1503 ++v;
1504 xyz += 4;
1505 } while (--nverts);
1506 }
1507 break;
1508 case DEFORMVERTEXES_AUTOSPRITE:
1509 {
1510 float *xyz = &input.xyz[input.numverts<<2], p[3], d[3], *xyzB;
1511 vertex_t *v = surf->firstvert[level], *vB;
1512 int nverts = surf->numverts[level], incr, nvertsB;
1513 vec3_t middle;
1514
1515 while (nverts)
1516 {
1517 // Compute middle of quad
1518 incr = 4;
1519 xyzB = xyz;
1520 vB = v;
1521 nvertsB = nverts;
1522
1523 middle[0] = middle[1] = middle[2] = 0.f;
1524
1525 do
1526 {
1527 middle[0] += *xyz;
1528 middle[1] += *(xyz+1);
1529 middle[2] += *(xyz+2);
1530 ++v;
1531 xyz += 4;
1532 } while (--nverts && --incr);
1533 VectorScale(middle, 0.25f, middle);
1534
1535 // Rotate each vertex
1536 incr = 4;
1537 xyz = xyzB;
1538 v = vB;
1539 nverts = nvertsB;
1540 do
1541 {
1542 p[0] = *xyz -middle[0];
1543 p[2] = *(xyz+1)-middle[1];
1544 p[1] = *(xyz+2)-middle[2];
1545 MultVect3x3(current_camera->rotation, p, d);
1546 *xyz = d[0]+middle[0];
1547 *(xyz+1) = d[1]+middle[1];
1548 *(xyz+2) = d[2]+middle[2];
1549 ++v;
1550 xyz += 4;
1551 } while (--nverts && --incr);
1552 }
1553 }
1554 break;
1555 case DEFORMVERTEXES_AUTOSPRITE2:
1556 {
1557 float *xyz = &input.xyz[input.numverts<<2], p[3], d[3], *xyzB;
1558 vertex_t *v = surf->firstvert[level], *vB;
1559 int nverts = surf->numverts[level], incr, nvertsB;
1560 vec3_t middle;
1561
1562 float m[9], temp[16];
1563
1564 while (nverts)
1565 {
1566 // Compute middle of quad
1567 incr = 4;
1568 xyzB = xyz;
1569 vB = v;
1570 nvertsB = nverts;
1571
1572 middle[0] = middle[1] = middle[2] = 0.f;
1573
1574 do
1575 {
1576 middle[0] += *xyz;
1577 middle[1] += *(xyz+1);
1578 middle[2] += *(xyz+2);
1579
1580 ++v;
1581 xyz += 4;
1582 } while (--nverts && --incr);
1583 VectorScale(middle, 0.25f, middle);
1584
1585 glMatrixMode(GL_MODELVIEW);
1586 glPushMatrix();
1587 glLoadIdentity();
1588 glRotatef(-90, 1, 0, 0);
1589 if (surf->autosprite2_axis == 0)
1590 {
1591 // @todo Terminate this stuff
1592 }
1593 else if (surf->autosprite2_axis == 2)
1594 {
1595 glRotatef(-current_camera->rot[1], 0, 0, 1);
1596 CheckGLError();
1597 }
1598 glGetFloatv(GL_MODELVIEW_MATRIX, temp);
1599 glPopMatrix();
1600 CheckGLError(6);
1601
1602 m[0] = temp[0];
1603 m[1] = temp[1];
1604 m[2] = temp[2];
1605 m[3] = temp[4];
1606 m[4] = temp[5];
1607 m[5] = temp[6];
1608 m[6] = temp[8];
1609 m[7] = temp[9];
1610 m[8] = temp[10];
1611
1612 // Rotate each vertex
1613 incr = 4;
1614 xyz = xyzB;
1615 v = vB;
1616 nverts = nvertsB;
1617 do
1618 {
1619 p[0] = *xyz -middle[0];
1620 p[2] = *(xyz+1)-middle[1];
1621 p[1] = *(xyz+2)-middle[2];
1622 MultVect3x3(m, p, d);
1623 *xyz = d[0]+middle[0];
1624 *(xyz+1) = d[1]+middle[1];
1625 *(xyz+2) = d[2]+middle[2];
1626 ++v;
1627 xyz += 4;
1628 } while (--nverts && --incr);
1629 }
1630 }
1631 break;
1632 // case DEFORMVERTEXES_NONE:
1633 // break;
1634 default:
1635 break;
1636 }
1637 }
1638 }
1639
SetTextureCoordinates(int tmu,Layer * l)1640 void Render::SetTextureCoordinates(int tmu, Layer *l)
1641 {
1642 glTexCoordPointer(2, GL_FLOAT, 0, buffer[tmu].st);
1643 CheckGLError();
1644
1645 if (r_noshader.ivalue)
1646 {
1647 memcpy(buffer[tmu].st, input.lm_st, sizeof(float)*(input.numverts<<1));
1648 return;
1649 }
1650
1651 // if the contents are the same, and the buffer isn't dirty don't fill it again.
1652 if (buffer[tmu].st_content != l->tcGen || buffer[tmu].st_content == -1)
1653 {
1654 buffer[tmu].st_content = l->tcGen;
1655
1656 switch (l->tcGen)
1657 {
1658 case TCGEN_LIGHTMAP:
1659 memcpy(buffer[tmu].st, input.lm_st, sizeof(float)*(input.numverts<<1));
1660 break;
1661 case TCGEN_ENVIRONMENT:
1662 {
1663 vec3_t dir, pos;
1664 vec_t m[16];
1665 glMatrixMode(GL_MODELVIEW);
1666 glGetFloatv(GL_MODELVIEW_MATRIX, m);
1667 vec3_t trans;
1668 // Invert the matrix
1669 VectorCopy(&m[12], trans);
1670 m[12] = -DotProduct(trans, &m[0]);
1671 m[13] = -DotProduct(trans, &m[4]);
1672 m[14] = -DotProduct(trans, &m[8]);
1673 float t = m[1];
1674 m[1] = m[4];
1675 m[4] = t;
1676 t = m[2];
1677 m[2] = m[8];
1678 m[8] = t;
1679 t = m[9];
1680 m[9] = m[6];
1681 m[6] = t;
1682 VectorCopy(&m[12], pos);
1683 for (int i = 0; i < input.numverts; ++i)
1684 {
1685 VectorSub(pos, &input.xyz[i<<2], dir);
1686
1687 FastNormVect3(dir);
1688
1689 buffer[tmu].st[ i<<1 ] = dir[2]-input.normal[(i<<2)+2];
1690 buffer[tmu].st[(i<<1)+1] = dir[1]-input.normal[(i<<2)+1];
1691 }
1692 }
1693 break;
1694 case TCGEN_VECTOR:
1695 case TCGEN_BASE:
1696 memcpy(buffer[tmu].st, input.tex_st, sizeof(float)*(input.numverts<<1));
1697 break;
1698 case TCGEN_FOG:
1699 #if MODIF_FOG
1700 {
1701 cplane_t** f = input.fog;
1702 float *xyz = input.xyz;
1703 byte *c = input.c;
1704 float fogdistance, inormu, d1, d2, d3;
1705 byte r, g, b, a = 255;
1706 vec3_t d, u, v;
1707 cplane_t* fogplane = NULL;
1708
1709 if (State::curr_effect)
1710 {
1711 // Get and set the fog parameters in effect shader
1712 r = (int)(255.f*State::curr_effect->fog_params.params[0]);
1713 g = (int)(255.f*State::curr_effect->fog_params.params[1]);
1714 b = (int)(255.f*State::curr_effect->fog_params.params[2]);
1715 fogdistance = State::curr_effect->fog_params.params[4];
1716 }
1717 else
1718 {
1719 // Get and set the fog parameters in current shader
1720 r = (int)(255.f*State::curr_shader->fog_params.params[0]);
1721 g = (int)(255.f*State::curr_shader->fog_params.params[1]);
1722 b = (int)(255.f*State::curr_shader->fog_params.params[2]);
1723 fogdistance = State::curr_shader->fog_params.params[4];
1724 }
1725
1726 for (int i = 0; i < input.numverts; ++i, ++f, c += 4, xyz += 4)
1727 {
1728 if (*f) fogplane = *f;
1729 else __asm int 3; // @bug Search why fogplane is NULL sometimes !!
1730 if (!fogplane) continue;
1731
1732 v[0] = *(xyz+0);
1733 v[1] = *(xyz+1);
1734 v[2] = *(xyz+2);
1735
1736 d[0] = v[0] - (current_camera->pos[0] + v_camnear.fvalue*current_camera->eyedir[0]);
1737 d[1] = v[1] - (current_camera->pos[1] + v_camnear.fvalue*current_camera->eyedir[1]);
1738 d[2] = v[2] - (current_camera->pos[2] + v_camnear.fvalue*current_camera->eyedir[2]);
1739 VectorCopy(current_camera->eyedir, u);
1740 inormu = InverseSqrt(u[0]*u[0]+u[1]*u[1]+u[2]*u[2]);
1741 VectorScale(u, inormu, u);
1742
1743 d1 = PointDistance(current_camera->pos, fogplane);
1744
1745 if (d1 < 0)
1746 {
1747 // the viewer is below the fog-surface (inside the fog volume)
1748 buffer[tmu].st[ i<<1 ] = DotProduct(d, u);
1749 buffer[tmu].st[(i<<1)+1] = -PointDistance(v, fogplane);
1750 }
1751 else
1752 {
1753 d2 = PointDistance(v, fogplane);
1754 buffer[tmu].st[(i<<1)+1] = -d2;
1755 if (d2 < 0.0f)
1756 {
1757 d3 = d2/(d2-d1);
1758 d3 *= DotProduct(d, u);
1759 buffer[tmu].st[i<<1] = d3;
1760 }
1761 else
1762 {
1763 buffer[tmu].st[i<<1] = 0.0f;
1764 }
1765 }
1766
1767 *(c+0) = r;
1768 *(c+1) = g;
1769 *(c+2) = b;
1770 *(c+3) = a;
1771 }
1772
1773 glTranslatef(0, 1.5f/(float)FOG_TEXTURE_HEIGHT, 0);
1774 glScalef(1.0f/fogdistance, 1.0f/fogdistance, 1.0f); // map [0.0, fogdistance] to [0.0, 1.0]
1775 CheckGLError(2);
1776 }
1777 #else
1778 {
1779 float *f = input.fog;
1780 float *xyz = input.xyz;
1781 byte *c = input.c;
1782 cplane_t fogplane;
1783 float fogdistance, inormu, d1, d2, d3;
1784 byte r, g, b, a = 255;
1785 vec3_t d, u, v;
1786
1787 // default plane
1788 fogplane.normal[0] = 0;
1789 fogplane.normal[1] = 0;
1790 fogplane.normal[2] = 1;
1791 fogplane.dist = 0;
1792 fogplane.type = 3;
1793
1794 if (State::curr_effect)
1795 {
1796 // Get and set the fog parameters in effect shader
1797 r = (int)(255.f*State::curr_effect->fog_params.params[0]);
1798 g = (int)(255.f*State::curr_effect->fog_params.params[1]);
1799 b = (int)(255.f*State::curr_effect->fog_params.params[2]);
1800 fogdistance = State::curr_effect->fog_params.params[4];
1801 }
1802 else
1803 {
1804 // Get and set the fog parameters in current shader
1805 r = (int)(255.f*State::curr_shader->fog_params.params[0]);
1806 g = (int)(255.f*State::curr_shader->fog_params.params[1]);
1807 b = (int)(255.f*State::curr_shader->fog_params.params[2]);
1808 fogdistance = State::curr_shader->fog_params.params[4];
1809 }
1810
1811 for (int i = 0; i < input.numverts; ++i)
1812 {
1813 if (fogplane.type < 4)
1814 {
1815 fogplane.normal[0] = *(f+0);
1816 fogplane.normal[1] = *(f+1);
1817 fogplane.normal[2] = *(f+2);
1818 fogplane.dist = *(f+3);
1819 fogplane.type = (unsigned int) *(f+4);
1820 }
1821 //else gConsole->Insertln("invalid vertex associated fog plane");
1822
1823 v[0] = *(xyz+0);
1824 v[1] = *(xyz+1);
1825 v[2] = *(xyz+2);
1826
1827 d[0] = v[0] - current_camera->pos[0];
1828 d[1] = v[1] - current_camera->pos[1];
1829 d[2] = v[2] - current_camera->pos[2];
1830 VectorCopy(current_camera->forward, u);
1831 inormu = 1.f / (float) sqrt(u[0]*u[0]+u[1]*u[1]+u[2]*u[2]);
1832 VectorScale(u, inormu, u);
1833
1834 d1 = PointDistance(current_camera->pos, &fogplane);
1835
1836 if (d1 < 0)
1837 {
1838 // the viewer is below the fog-surface (inside the fog volume)
1839 buffer[tmu].st[ i<<1 ] = DotProduct(d, u);
1840 buffer[tmu].st[(i<<1)+1] = -PointDistance(v, &fogplane);
1841 }
1842 else
1843 {
1844 d2 = PointDistance(v, &fogplane);
1845 buffer[tmu].st[(i<<1)+1] = -d2;
1846 if (d2 < 0.0f)
1847 {
1848 d3 = d2/(d2-d1);
1849 d3 *= DotProduct(d, u);
1850 buffer[tmu].st[i<<1] = d3;
1851 }
1852 else
1853 {
1854 buffer[tmu].st[i<<1] = 0.0f;
1855 }
1856 }
1857
1858 *(c+0) = r;
1859 *(c+1) = g;
1860 *(c+2) = b;
1861 *(c+3) = a;
1862
1863 c += 4;
1864 f += 5;
1865 xyz += 4;
1866 }
1867
1868 glTranslatef(0, 1.5f/(float)FOG_TEXTURE_HEIGHT, 0);
1869 glScalef(1.0f/fogdistance, 1.0f/fogdistance, 1.0f); // map [0.0, fogdistance] to [0.0, 1.0]
1870 CheckGLError(2);
1871 }
1872 #endif
1873 break;
1874 default:
1875 break;
1876 }
1877 }
1878
1879 if (l->tcMod)
1880 {
1881 buffer[tmu].st_content = -1; // texcoord transforms always destroy the content
1882
1883 int i;
1884 float *st, t1, t2;
1885
1886 for (funclist *f = l->tcMod; f; f = f->next)
1887 {
1888 st = buffer[tmu].st;
1889 switch (f->func)
1890 {
1891 case TCMOD_ROTATE:
1892 {
1893 float angulo = -f->p[0]*(float)Timer::fTime/M_180_PI;
1894 float sint = FastSin(angulo);
1895 float cost = FastCos(angulo);
1896 for (i = 0; i < input.numverts; ++i, st += 2)
1897 {
1898 t1 = cost * (st[0] - 0.5f) - sint * (st[1] - 0.5f) + 0.5f;
1899 t2 = cost * (st[1] - 0.5f) + sint * (st[0] - 0.5f) + 0.5f;
1900 st[0] = t1;
1901 st[1] = t2;
1902 }
1903 }
1904 break;
1905 case TCMOD_SCALE:
1906 {
1907 for (i = 0; i < input.numverts; ++i, st += 2)
1908 {
1909 st[0] = (st[0]/*-0.5f*/) * f->p[0]/* + 0.5f*/;
1910 st[1] = (st[1]/*-0.5f*/) * f->p[1]/* + 0.5f*/;
1911 }
1912 }
1913 break;
1914 case TCMOD_SCROLL:
1915 {
1916 t1 = f->p[0]*(float)Timer::fTime;
1917 t2 = f->p[1]*(float)Timer::fTime;
1918 t1 -= floorf(t1);
1919 t2 -= floorf(t2);
1920 for (i = 0; i < input.numverts; ++i, st += 2)
1921 {
1922 st[0] += t1;
1923 st[1] += t2;
1924 }
1925 }
1926 break;
1927 case TCMOD_STRETCH:
1928 {
1929 float factor = 1/State::Eval(f->p);
1930 for (i = 0; i < input.numverts; ++i, st += 2)
1931 {
1932 st[0] = (st[0] - 0.5f) * factor + 0.5f;
1933 st[1] = (st[1] - 0.5f) * factor + 0.5f;
1934 }
1935 }
1936 break;
1937 case TCMOD_TRANSFORM:
1938 {
1939 for (i = 0; i < input.numverts; ++i, st += 2)
1940 {
1941 t1 = st[0];
1942 t2 = st[1];
1943 st[0] = t1*f->p[0] + t2*f->p[2] + f->p[4];
1944 st[1] = t2*f->p[1] + t1*f->p[3] + f->p[5];
1945 }
1946 }
1947 break;
1948 case TCMOD_TURB:
1949 {
1950 t1 = f->p[2] + (float)Timer::fTime * f->p[3];
1951 t2 = f->p[1];
1952 for (i = 0; i < input.numverts; ++i, st += 2)
1953 {
1954 st[0] += FastSin(st[0]*t2+t1)*t2;
1955 st[1] += FastSin(st[1]*t2+t1)*t2;
1956 }
1957 }
1958 break;
1959 default:
1960 break;
1961 }
1962 }
1963 }
1964 }
1965
SetVertexColors(int tmu,Layer * l)1966 void Render::SetVertexColors(int tmu, Layer *l)
1967 {
1968 if (r_novertexcolor.ivalue)
1969 {
1970 memset(buffer[tmu].c, 255, (input.numverts<<2));
1971 return;
1972 }
1973
1974 if (State::curr_shader->num_layers)
1975 {
1976 glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer[tmu].c);
1977 CheckGLError();
1978
1979 // if (buffer[tmu].c_content == -1 || buffer[tmu].c_content != l->rgbGen)
1980 // {
1981 // buffer[tmu].c_content = l->rgbGen;
1982
1983 switch (l->rgbGen)
1984 {
1985 case RGBGEN_NONE:
1986 case RGBGEN_IDENTITY:
1987 memset(buffer[tmu].c, 255, (input.numverts<<2));
1988 break;
1989 case RGBGEN_IDENTITY_LIGHTING:
1990 {
1991 for (int i = 0; i < input.numverts; ++i)
1992 {
1993 buffer[tmu].c[(i<<2) ] = 127;
1994 buffer[tmu].c[(i<<2)+1] = 127;
1995 buffer[tmu].c[(i<<2)+2] = 127;
1996 buffer[tmu].c[(i<<2)+3] = 255;
1997 }
1998 }
1999 break;
2000 case RGBGEN_VERTEX:
2001 case RGBGEN_EXACTVERTEX:
2002 memcpy(buffer[tmu].c, input.c, input.numverts<<2);
2003 break;
2004 case RGBGEN_ONE_MINUS_VERTEX:
2005 {
2006 for (int i = 0; i < input.numverts; ++i)
2007 {
2008 buffer[tmu].c[(i<<2) ] = 255 - input.c[(i<<2)];
2009 buffer[tmu].c[(i<<2)+1] = 255 - input.c[(i<<2)+1];
2010 buffer[tmu].c[(i<<2)+2] = 255 - input.c[(i<<2)+2];
2011 buffer[tmu].c[(i<<2)+3] = 255;
2012 }
2013 }
2014 break;
2015 case RGBGEN_LIGHTING_DIFFUSE:
2016 memcpy(buffer[tmu].c, input.c, input.numverts<<2);
2017 break;
2018 case RGBGEN_WAVE:
2019 {
2020 int c = (int) (255.0f*State::Eval(l->rgbGenParams));
2021 if (c < 0) c = 0;
2022 if (c > 255) c = 255;
2023 buffer[tmu].c_content = -1;
2024 for (int i = 0; i < input.numverts; ++i)
2025 {
2026 buffer[tmu].c[(i<<2) ] = c;
2027 buffer[tmu].c[(i<<2)+1] = c;
2028 buffer[tmu].c[(i<<2)+2] = c;
2029 buffer[tmu].c[(i<<2)+3] = 255;
2030 }
2031 }
2032 break;
2033 case RGBGEN_FOG:
2034 memcpy(buffer[tmu].c, input.c, input.numverts<<2);
2035 break;
2036 default: // TODO: finish other rgbgen types
2037 memcpy(buffer[tmu].c, input.c, input.numverts<<2);
2038 break;
2039 }
2040
2041 switch (l->alphaGen)
2042 {
2043 case ALPHAGEN_IDENTITY:
2044 {
2045 for (int i = 0; i < input.numverts; ++i)
2046 buffer[tmu].c[(i<<2)+3] = 255;
2047 }
2048 break;
2049 case ALPHAGEN_CONST:
2050 {
2051 // TODO: implement const support
2052 }
2053 break;
2054 case ALPHAGEN_WAVE:
2055 {
2056 int c = (int) (255.0f*State::Eval(l->alphaGenParams));
2057 if (c < 0) c = 0;
2058 if (c > 255) c = 255;
2059 for (int i = 0; i < input.numverts; ++i)
2060 buffer[tmu].c[(i<<2)+3] = c;
2061 }
2062 break;
2063 case ALPHAGEN_PORTAL:
2064 {/*
2065 VectorAdd ( vertexArray[0], currententity->cam.pos, v );
2066 VectorSubtract ( r_origin, v, t );
2067 a = VectorLength ( t ) * (1.0 / 255.0);
2068 clamp ( a, 0.0f, 1.0f );
2069 b = FloatToByte ( a );
2070
2071 for ( i = 0; i < numColors; i++, bArray += 4 ) {
2072 bArray[3] = b;
2073 }*/
2074 }
2075 break;
2076 case ALPHAGEN_VERTEX:
2077 {
2078 for (int i = 0; i < input.numverts; ++i)
2079 buffer[tmu].c[(i<<2)+3] = input.c[(i<<2)+3];
2080 }
2081 break;
2082
2083 case ALPHAGEN_ENTITY:
2084 {/*
2085 for (int i = 0; i < input.numverts; ++i)
2086 buffer[tmu].c[(i<<2)+3] = currententity->color[3];
2087 }*/
2088 }
2089 break;
2090 case ALPHAGEN_SPECULAR:
2091 {/*
2092 VectorSubtract ( r_origin, currententity->cam.pos, t );
2093
2094 if (!Matrix3_Compare (currententity->axis, axis_identity) ) {
2095 Matrix3_Multiply_Vec3 ( currententity->axis, t, v );
2096 } else {
2097 VectorCopy ( t, v );
2098 }
2099
2100 for (i = 0; i < numColors; i++, bArray += 4 ) {
2101 VectorSubtract ( v, vertexArray[i], t );
2102 a = DotProduct( t, normalsArray[i] ) * rSqrt ( DotProduct(t,t) );
2103 a = a * a * a * a * a;
2104 bArray[3] = FloatToByte ( bound (0.0f, a, 1.0f) );
2105 }*/
2106 }
2107 break;
2108 default:
2109 break;
2110 }
2111 // }
2112 }
2113 else
2114 {
2115 memcpy(buffer[tmu].c, input.c, input.numverts<<2);
2116 }
2117 }
2118
Perspective(float fov,float aspect)2119 void Render::Perspective(float fov, float aspect)
2120 {
2121 float xmin, xmax, ymin, ymax;
2122 float one_deltax, one_deltay, one_deltaz, doubleznear;
2123 float m[16];
2124
2125 xmax = v_camnear.fvalue * FastTan(fov/2.f);
2126 xmin = -xmax;
2127
2128 ymax = xmax / aspect;
2129 ymin = -ymax;
2130
2131 //glFrustum(xmin, xmax, ymin, ymax, zNear, zFar); CheckGLError();
2132
2133 doubleznear = 2.f * v_camnear.fvalue;
2134 one_deltax = (xmax - xmin);
2135 one_deltay = (ymax - ymin);
2136 one_deltaz = (v_camfar.fvalue - v_camnear.fvalue);
2137
2138 m[0] = (float) (doubleznear / one_deltax);
2139 m[1] = 0.f;
2140 m[2] = 0.f;
2141 m[3] = 0.f;
2142 m[4] = 0.f;
2143 m[5] = (float) (doubleznear / one_deltay);
2144 m[6] = 0.f;
2145 m[7] = 0.f;
2146 m[8] = (float) ((xmax + xmin) / one_deltax);
2147 m[9] = (float) ((ymax + ymin) / one_deltay);
2148 m[10] = (float) (-(v_camfar.fvalue + v_camnear.fvalue) / one_deltaz);
2149 m[11] = -1.f;
2150 m[12] = 0.f;
2151 m[13] = 0.f;
2152 m[14] = (float) (-(v_camfar.fvalue * doubleznear) / one_deltaz);
2153 m[15] = 0.f;
2154
2155 glLoadMatrixf(m);
2156 CheckGLError();
2157 }
2158
DumpGLState(void)2159 void Render::DumpGLState(void)
2160 {
2161 GLboolean bool_buffer;
2162 GLfloat float_buffer;
2163 GLint int_buffer;
2164
2165 gLogFile->OpenFile();
2166
2167 // blending
2168 gConsole->Insertln("State report:");
2169 glGetBooleanv(GL_BLEND, &bool_buffer);
2170 gConsole->Insertln("\tblending: %s", bool_buffer?"enabled":"disabled");
2171 glGetIntegerv(GL_BLEND_SRC, &int_buffer);
2172 gConsole->Insertln("\t\tblend src: 0x%x", int_buffer);
2173 if (int_buffer != State::curr_blendsrc) gConsole->Insertln("\t\t\t-> ^1state mismatch (%d)", State::curr_blendsrc);
2174 glGetIntegerv(GL_BLEND_DST, &int_buffer);
2175 gConsole->Insertln("\t\tblend dst: 0x%x", int_buffer);
2176 if (int_buffer != State::curr_blenddst) gConsole->Insertln("\t\t\t-> ^1state mismatch (%d)", State::curr_blenddst);
2177
2178 // culling
2179 glGetBooleanv(GL_CULL_FACE, &bool_buffer);
2180 gConsole->Insertln("\tculling: %s", bool_buffer?"enabled":"disabled");
2181 if (State::curr_culling == CULL_NONE && bool_buffer) gConsole->Insertln("\t\t-> ^1state mismatch (%d)", State::curr_culling);
2182 glGetIntegerv(GL_CULL_FACE_MODE, &int_buffer);
2183 gConsole->Insertln("\t\tculling face mode: 0x%x", int_buffer);
2184 if (State::curr_culling != CULL_NONE &&
2185 ((State::curr_culling == CULL_FRONT && int_buffer != GL_FRONT) ||
2186 (State::curr_culling == CULL_BACK && int_buffer != GL_BACK)))
2187 gConsole->Insertln("\t\t\t-> ^1state mismatch (%d)", State::curr_culling);
2188
2189 // depth
2190 glGetBooleanv(GL_DEPTH_TEST, &bool_buffer);
2191 gConsole->Insertln("\tdepth test: %s", bool_buffer?"enabled":"disabled");
2192 glGetBooleanv(GL_DEPTH_WRITEMASK, &bool_buffer);
2193 gConsole->Insertln("\t\tdepthwrite mask: %s", bool_buffer?"enabled":"disabled");
2194 if (bool_buffer != State::curr_depthWrite) gConsole->Insertln("\t\t-> ^1state mismatch (%s)", State::curr_depthWrite?"enabled":"disabled");
2195 glGetIntegerv(GL_DEPTH_FUNC, &int_buffer);
2196 gConsole->Insertln("\t\tdepth func: 0x%x", int_buffer);
2197 if (int_buffer != State::curr_depthFunc) gConsole->Insertln("\t\t\t-> ^1state mismatch (%d)", State::curr_depthFunc);
2198
2199 // fog
2200 glGetBooleanv(GL_FOG, &bool_buffer);
2201 gConsole->Insertln("\tfog: %s", bool_buffer?"enabled":"disabled");
2202 glGetFloatv(GL_FOG_DENSITY, &float_buffer);
2203 gConsole->Insertln("\t\tfog density: %f", float_buffer);
2204 glGetFloatv(GL_FOG_START, &float_buffer);
2205 gConsole->Insertln("\t\tfog start: %f", float_buffer);
2206 glGetFloatv(GL_FOG_END, &float_buffer);
2207 gConsole->Insertln("\t\tfog end: %f", float_buffer);
2208 glGetIntegerv(GL_FOG_MODE, &int_buffer);
2209 gConsole->Insertln("\t\tfog mode: 0x%x", int_buffer);
2210
2211 // lighting
2212 glGetBooleanv(GL_LIGHTING, &bool_buffer);
2213 gConsole->Insertln("\tlighting: %s", bool_buffer?"enabled":"disabled");
2214
2215 // 1D texturing
2216 glGetBooleanv(GL_TEXTURE_1D, &bool_buffer);
2217 gConsole->Insertln("\t1D texturing: %s", bool_buffer?"enabled":"disabled");
2218
2219 // 2D texturing
2220 glGetBooleanv(GL_TEXTURE_2D, &bool_buffer);
2221 gConsole->Insertln("\t2D texturing: %s", bool_buffer?"enabled":"disabled");
2222
2223 // render mode
2224 glGetIntegerv(GL_RENDER_MODE, &int_buffer);
2225 gConsole->Insertln("\trendering mode: 0x%x", int_buffer);
2226
2227 CheckGLError(18);
2228
2229 gLogFile->CloseFile();
2230 }
2231
CheckGLError(int ncalls)2232 void Render::CheckGLError(int ncalls)
2233 {
2234 // FIXME: Should we stop or throw an exception in release mode ?
2235 #ifdef _DEBUG
2236 GLenum glerr = glGetError();
2237 if (glerr)
2238 {
2239 /*
2240 GL_NO_ERROR 0
2241 GL_INVALID_ENUM 0x0500
2242 GL_INVALID_VALUE 0x0501
2243 GL_INVALID_OPERATION 0x0502
2244 GL_STACK_OVERFLOW 0x0503
2245 GL_STACK_UNDERFLOW 0x0504
2246 GL_OUT_OF_MEMORY 0x0505
2247 */
2248 char errDescr[32] = { '\0' };
2249 switch (glerr)
2250 {
2251 case GL_INVALID_ENUM: sprintf(errDescr, "GL_INVALID_ENUM"); break;
2252 case GL_INVALID_VALUE: sprintf(errDescr, "GL_INVALID_VALUE"); break;
2253 case GL_INVALID_OPERATION: sprintf(errDescr, "GL_INVALID_OPERATION"); break;
2254 case GL_STACK_OVERFLOW: sprintf(errDescr, "GL_STACK_OVERFLOW"); break;
2255 case GL_STACK_UNDERFLOW: sprintf(errDescr, "GL_STACK_UNDERFLOW"); break;
2256 case GL_OUT_OF_MEMORY: sprintf(errDescr, "GL_OUT_OF_MEMORY"); break;
2257 default : sprintf(errDescr, "UNDEFINED_ERROR"); break;
2258 }
2259
2260 gLogFile->Insert("^1OpenGL error detected: %s\n", errDescr);
2261
2262 //__asm int 3;
2263 }
2264 #endif
2265 num_apicalls += ncalls;
2266 }
2267
2268 //-----------------------------------------------------------------------------
2269 // State
2270 //-----------------------------------------------------------------------------
2271
SetInitialState(int multitexture)2272 void State::SetInitialState(int multitexture)
2273 {
2274 // client state:
2275 glEnableClientState(GL_VERTEX_ARRAY);
2276 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2277
2278 // texturing:
2279 glEnable(GL_TEXTURE_2D);
2280 curr_texture[0] = -1;
2281
2282 // second texture unit
2283 if (multitexture)
2284 {
2285 glActiveTextureARB(GL_TEXTURE1_ARB);
2286 glClientActiveTextureARB(GL_TEXTURE1_ARB);
2287 glDisable(GL_TEXTURE_2D);
2288 glActiveTextureARB(GL_TEXTURE0_ARB);
2289 glClientActiveTextureARB(GL_TEXTURE0_ARB);
2290 curr_texture[1] = -1;
2291 gRender->CheckGLError(5);
2292 }
2293
2294 // backface culling:
2295 glEnable(GL_CULL_FACE);
2296 glCullFace(GL_BACK);
2297 curr_culling = CULL_BACK;
2298
2299 // color:
2300 glShadeModel(GL_SMOOTH);
2301 glEnableClientState(GL_COLOR_ARRAY);
2302
2303 if (gl_dither.ivalue) glEnable(GL_DITHER);
2304 else glDisable(GL_DITHER);
2305
2306 // blending:
2307 glDisable(GL_BLEND);
2308 curr_blendsrc = GL_ONE;
2309 curr_blenddst = GL_ZERO;
2310
2311 // alpha func
2312 glDisable(GL_ALPHA_TEST);
2313 glAlphaFunc(GL_ALWAYS, 1.0f);
2314
2315 // depth test:
2316 glEnable(GL_DEPTH_TEST);
2317 glDepthFunc(GL_LEQUAL);
2318 glDepthMask(GL_TRUE);
2319 curr_depthFunc = GL_LEQUAL;
2320 curr_depthWrite = true;
2321
2322 glEnable(GL_SCISSOR_TEST);
2323 glDisable(GL_POLYGON_OFFSET_FILL);
2324 glPolygonOffset(-1.f, -2.f);
2325 State::setPolygonMode(GL_FILL);
2326
2327 switch (r_quality.ivalue)
2328 {
2329 case 0:
2330 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
2331 break;
2332 case 1:
2333 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
2334 break;
2335 case 2:
2336 default:
2337 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
2338 break;
2339 }
2340
2341 glReadBuffer(GL_BACK);
2342 glDrawBuffer(GL_BACK);
2343
2344 // clearing:
2345 glClearColor(0.2f, 0.3f, 0.4f, 1.0f);
2346 glClearDepth(1.0f);
2347
2348 gRender->CheckGLError(21);
2349 }
2350
2351 // not done
SetDefaultState(void)2352 void State::SetDefaultState(void)
2353 {
2354 pass = 0;
2355 }
2356
2357 // binds the texture of the given layer
BindTexture(Layer * l,int unit)2358 void State::BindTexture(Layer *l, int unit)
2359 {
2360 int num;
2361
2362 if (l->flags & LF_LIGHTMAP || r_noshader.ivalue)
2363 {
2364 if (curr_lightmap != ~0) num = curr_lightmap;
2365 else return;
2366 }
2367 else if (!l->map) return; // FIXME: that happens???
2368 else if (l->num_maps > 1)
2369 {
2370 int frame = ((int) floor(Timer::fTime*l->anim_speed)) % l->num_maps;
2371 clamp(frame, 0, l->num_maps-1);
2372 num = l->map[frame]->num;
2373 }
2374 else if (l->map[0]) num = l->map[0]->num;
2375 else return; // FIXME: that happens???
2376
2377 if (State::curr_texture[unit] != num)
2378 {
2379 glBindTexture(GL_TEXTURE_2D, num);
2380 gRender->CheckGLError();
2381 State::curr_texture[unit] = num;
2382 }
2383 }
2384
2385 // set the appropiate state to render the layer
setState(Layer * l)2386 void State::setState(Layer *l)
2387 {
2388 State::setBlend(l->blendsrc, l->blenddst);
2389
2390 State::setAlphaFunc(l->alphafunc, l->alphafuncref);
2391
2392 State::setDepthWrite(l->depthWrite);
2393 State::setDepthFunc(l->depthFunc);
2394 }
2395
SetupShader(void)2396 void State::SetupShader(void)
2397 {
2398 State::setCulling(State::curr_shader->cull);
2399
2400 if (State::curr_shader->flags & SF_POLYGONOFFSET)
2401 glEnable(GL_POLYGON_OFFSET_FILL);
2402 else
2403 glDisable(GL_POLYGON_OFFSET_FILL);
2404 gRender->CheckGLError();
2405 }
2406
2407 // evaluates a deform function
Eval(float * p)2408 float State::Eval(float *p)
2409 {
2410 float x, y = 0;
2411
2412 // Evaluate a number of time based periodic functions
2413 // y = p[1] + p[2] * func((time + p[3]) * p[4])
2414
2415 x = ((float)Timer::fTime + p[3]) * p[4]; //x = (Timer::fTime) * p[4] + p[3];
2416 x -= floorf(x); // normalized
2417
2418 switch ((int) (p[0]))
2419 {
2420 case FUNC_SIN:
2421 y = FastSin(x * M_TWO_PI);
2422 break;
2423 case FUNC_SQUARE:
2424 if (x < 0.5f) y = 1.0f;
2425 else y = -1.0f;
2426 break;
2427 case FUNC_SAWTOOTH:
2428 y = x;
2429 break;
2430 case FUNC_INVERSESAWTOOTH:
2431 y = 1.0f - x;
2432 break;
2433 case FUNC_TRIANGLE:
2434 if (x < 0.5f) y = 4.0f * x - 1.0f;
2435 else y = -4.0f * x + 3.0f;
2436 break;
2437 case FUNC_NOISE:
2438 y = (((float)rand()+(float)rand())/2.f)/(float)RAND_MAX;
2439 break;
2440 default:
2441 break;
2442 }
2443
2444 return y * p[2] + p[1];
2445 }
2446
setDepthFunc(int val)2447 void State::setDepthFunc(int val)
2448 {
2449 if (State::curr_depthFunc != val)
2450 {
2451 if (val == GL_NEVER) glDisable(GL_DEPTH_TEST);
2452 else if (State::curr_depthFunc == GL_NEVER) glEnable(GL_DEPTH_TEST);
2453 glDepthFunc(val);
2454 gRender->CheckGLError(2);
2455 State::curr_depthFunc = val;
2456 }
2457 }
setDepthWrite(int val)2458 void State::setDepthWrite(int val)
2459 {
2460 if (State::curr_depthWrite != val)
2461 {
2462 glDepthMask(val);
2463 gRender->CheckGLError();
2464 State::curr_depthWrite = val;
2465 }
2466 }
2467
setBlend(int src,int dst)2468 void State::setBlend(int src, int dst)
2469 {
2470 if (State::curr_blendsrc != src || State::curr_blenddst != dst)
2471 {
2472 if (src == GL_ONE && dst == GL_ZERO)
2473 glDisable(GL_BLEND);
2474 else
2475 {
2476 if (State::curr_blendsrc == GL_ONE && State::curr_blenddst == GL_ZERO)
2477 {
2478 glEnable(GL_BLEND);
2479 gRender->CheckGLError();
2480 }
2481 glBlendFunc(src, dst);
2482 }
2483 State::curr_blenddst = dst;
2484 State::curr_blendsrc = src;
2485 gRender->CheckGLError();
2486 }
2487 }
2488
setCulling(int val)2489 void State::setCulling(int val)
2490 {
2491 if (r_nocull.ivalue)
2492 {
2493 if (State::curr_culling != CULL_NONE)
2494 {
2495 State::curr_culling = CULL_NONE;
2496 glDisable(GL_CULL_FACE);
2497 gRender->CheckGLError();
2498 }
2499 }
2500 else if (val != State::curr_culling)
2501 {
2502 if (val)
2503 {
2504 glEnable(GL_CULL_FACE);
2505 if (val < 0) glCullFace(GL_FRONT);
2506 else glCullFace(GL_BACK);
2507 gRender->CheckGLError(2);
2508 }
2509 else
2510 {
2511 glDisable(GL_CULL_FACE);
2512 gRender->CheckGLError();
2513 }
2514 State::curr_culling = val;
2515 }
2516 }
2517
setAlphaFunc(int func,float funcref)2518 void State::setAlphaFunc(int func, float funcref)
2519 {
2520 if (func != State::curr_alphaFunc)
2521 {
2522 if (func == GL_ALWAYS)
2523 {
2524 glDisable(GL_ALPHA_TEST);
2525 gRender->CheckGLError();
2526 }
2527 else
2528 {
2529 glEnable(GL_ALPHA_TEST);
2530 glAlphaFunc(func, funcref);
2531 gRender->CheckGLError(2);
2532 }
2533 State::curr_alphaFunc = func;
2534 }
2535 }
2536
setPolygonMode(int val)2537 void State::setPolygonMode(int val)
2538 {
2539 if (val != State::curr_polygonmode)
2540 {
2541 switch (val)
2542 {
2543 case GL_POINT:
2544 glEnable(GL_POLYGON_OFFSET_POINT);
2545 glDisable(GL_POLYGON_OFFSET_LINE);
2546 glDisable(GL_POLYGON_OFFSET_FILL);
2547 break;
2548 case GL_LINE:
2549 glDisable(GL_POLYGON_OFFSET_POINT);
2550 glEnable(GL_POLYGON_OFFSET_LINE);
2551 glDisable(GL_POLYGON_OFFSET_FILL);
2552 break;
2553 case GL_FILL:
2554 glDisable(GL_POLYGON_OFFSET_POINT);
2555 glDisable(GL_POLYGON_OFFSET_LINE);
2556 glEnable(GL_POLYGON_OFFSET_FILL);
2557 break;
2558 default:
2559 return; // invalid enum
2560 }
2561
2562 if (State::curr_culling == CULL_BACK)
2563 glPolygonMode(GL_BACK, val);
2564 else if (State::curr_culling == CULL_FRONT)
2565 glPolygonMode(GL_FRONT, val);
2566 else
2567 glPolygonMode(GL_FRONT_AND_BACK, val);
2568
2569 gRender->CheckGLError();
2570 State::curr_polygonmode = val;
2571 }
2572 }
2573