00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00049 #include "omicron/internal.h"
00050 #include "omicron/render.h"
00051 #include "omicron/texture.h"
00052 #include "omicron/gui.h"
00053 #include "omicron/list.h"
00054 #include "omicron/input.h"
00055
00056
00057
00058
00059
00060
00061
00062 renderer_c::renderer_c()
00063 {
00064 SafeDelete(gv.renderer);
00065
00066 if (gv.init.nogfx)
00067 return;
00068
00069 gv.renderer = this;
00070
00071 _log_printf(MSG_DEBUG, "- renderer_c::renderer_c() -------------");
00072
00073 isinrender = false;
00074
00075 _log_printf(MSG_DEBUG, "Creating texture manager");
00076
00077 new texture_manager_c;
00078
00079
00080 gv.lights = new light_t[8];
00081 gv.lightcount = 0;
00082
00083
00084 glAlphaFunc(GL_GREATER, 0.5);
00085
00086
00087 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
00088 glHint(GL_FOG_HINT, GL_NICEST);
00089 glShadeModel(GL_SMOOTH);
00090
00091 glEnable(GL_NORMALIZE);
00092
00093 glClearDepth(1.0f);
00094 viewDepth = 10000;
00095
00096 state.autoclear = 1;
00097 state.bgcolor = 0;
00098 state.texwrapu = 0;
00099 state.texwrapv = 0;
00100 state.texminfilter = TF_LINEAR_MIPMAP_LINEAR;
00101 state.texmagfilter = TF_LINEAR_MIPMAP_LINEAR;
00102 state.blendtype = BT_OPAQUE;
00103 state.zbuffertype = ZB_LESSEQUAL;
00104
00105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00107
00108
00109 gv.shaders = new list_c<shader_t>;
00110
00111 use_shader(shader_create_simple(BT_BLEND, INVALID_INDEX));
00112
00113
00114 gv.texman->load("textures/common/notfound");
00115
00116 notfoundshader = shader_create_simple(BT_OPAQUE, TEXTURE_NOTFOUND);
00117 sprintf(notfoundshader->name, "noshader");
00118
00119
00120 viewPos = vec3_c( 0, -1, 0);
00121 viewTarget = vec3_c( 0, 0, 0);
00122 viewUp = vec3_c( 0, 0, 1);
00123
00124 #if defined(WIN32)
00125 if (extgl_Extensions.NV_vertex_array_range)
00126 {
00127 drawvertcount = 1000;
00128 #if defined(WIN32)
00129 drawverts = (vertex_t*)wglAllocateMemoryNV(sizeof(vertex_t)*(drawvertcount), 0.2f, 0.2f, 0.5f);
00130 #else
00131 drawverts = (vertex_t*)glXAllocateMemoryNV(sizeof(vertex_t)*(drawvertcount), 0.2f, 0.2f, 0.5f);
00132 #endif
00133 glVertexArrayRangeNV(sizeof(vertex_t)*(drawvertcount), drawverts);
00134 }
00135 else
00136 #endif
00137 {
00138 drawvertcount = 100000;
00139 drawverts = new vertex_t[drawvertcount];
00140 }
00141
00142 if (query_glext("GL_EXT_VERTEX_ARRAY"))
00143 {
00144 glVertexPointer (3, GL_FLOAT, sizeof(vertex_t), drawverts->xyz );
00145 glNormalPointer (GL_FLOAT, sizeof(vertex_t), drawverts->normal );
00146 glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(vertex_t), &drawverts->diffuse );
00147 glTexCoordPointer (2, GL_FLOAT, sizeof(vertex_t), drawverts->uv[0] );
00148
00149 glEnable(GL_VERTEX_ARRAY);
00150 glEnable(GL_NORMAL_ARRAY);
00151 glEnable(GL_TEXTURE_COORD_ARRAY);
00152 glEnable(GL_COLOR_ARRAY);
00153 }
00154
00155
00156 state.currentcolor = COLOR_WHITE;
00157 state.targettexture = INVALID_INDEX;
00158 state.lightmap = INVALID_INDEX;
00159 state.spheremapping = false;
00160 state.fog = false;
00161
00162 if (query_glext("GL_NV_FOG_DISTANCE"))
00163 glFogf(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
00164
00165 if (query_glext("GL_EXT_TEXTURE_FILTER_ANISOTROPIC"))
00166 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
00167
00168 reset_charmode();
00169
00170 glEnable(GL_NORMALIZE);
00171 glPixelZoom(1,-1);
00172
00173 fov = 90;
00174
00175 glEnable(GL_TEXTURE_2D);
00176
00177
00178 _log_printf(MSG_DEBUG, "----------------------------------------");
00179 }
00180
00181
00182
00183
00184 renderer_c::~renderer_c()
00185 {
00186 AssertThis;
00187
00188 _log_printf(MSG_DEBUG, "- renderer_c::~renderer_c()-------------");
00189
00190
00191 _log_printf(MSG_DEBUG, "Destroying all shaders...");
00192
00193 shader_t *shader;
00194
00195 if (gv.shaders)
00196 {
00197 shader = (shader_t*)gv.shaders->get_first();
00198
00199 while(shader)
00200 {
00201 SafeDelete(shader);
00202 shader = (shader_t*)gv.shaders->get_next();
00203 }
00204 }
00205 SafeDelete(gv.shaders);
00206
00207
00208 SafeDelete(gv.texman);
00209 SafeArrayDelete(gv.lights);
00210
00211 #if defined(WIN32)
00212 if (query_glext("GL_NV_VERTEX_ARRAY_RANGE"))
00213 {
00214 #if defined(WIN32)
00215 if (drawverts)
00216 wglFreeMemoryNV(drawverts);
00217 #else
00218 if (drawverts)
00219 glXFreeMemoryNV(drawverts);
00220 #endif
00221 }
00222 else
00223 #endif
00224 {
00225 SafeArrayDelete(drawverts);
00226 }
00227
00228 _log_printf(MSG_DEBUG, "----------------------------------------");
00229 }
00230
00231
00232 bool renderer_c::query_glext(const char *name)
00233 {
00234 _log_printf(0, "%s", name);
00235
00236 if (strstr((char*)glGetString(GL_EXTENSIONS), name))
00237 return true;
00238
00239 _log_printf(0, "not supported...");
00240
00241 return false;
00242 }
00243
00244
00245
00246
00247 void renderer_c::view_3d()
00248 {
00249 AssertThis;
00250
00251
00252
00253 if (fov >= 180.0f)
00254 fov = 179.9f;
00255
00256 glMatrixMode(GL_PROJECTION);
00257 glLoadIdentity();
00258 gluPerspective(fov/gv.aspect, gv.aspect, 1,
00259 gv.renderer->get_viewdepth());
00260
00261 glMatrixMode(GL_MODELVIEW);
00262 glLoadIdentity();
00263
00264 gluLookAt(viewPos[0], viewPos[1], viewPos[2],
00265 viewTarget[0], viewTarget[1], viewTarget[2],
00266 viewUp[0], viewUp[1], viewUp[2]);
00267
00268 float matmdl[16];
00269
00270 glGetFloatv(GL_MODELVIEW_MATRIX, matmdl);
00271
00272 viewDir.set ( -matmdl[2], -matmdl[6], -matmdl[10]);
00273 viewUp2.set ( matmdl[1], matmdl[5], matmdl[9] );
00274 viewRight.set ( -matmdl[0], -matmdl[4], -matmdl[8] );
00275
00276 make_frustum();
00277
00278
00279 }
00280
00281
00282
00283
00284
00285
00286
00287 void renderer_c::view_2d
00288 (
00289 float width,
00290 float height
00291 )
00292 {
00293 AssertThis;
00294
00295 glMatrixMode(GL_TEXTURE);
00296 glLoadIdentity();
00297
00298 glMatrixMode(GL_PROJECTION);
00299 glLoadIdentity();
00300 gluOrtho2D ( 0, 0, width, height );
00301 glScalef ( 2.0/width, 2.0/height, 1 );
00302 glTranslatef ( -width/2.0, -height/2.0, 1 );
00303
00304 glMatrixMode(GL_MODELVIEW);
00305 glLoadIdentity();
00306
00307 viewWidth = width;
00308 viewHeight = height;
00309 }
00310
00311
00312
00313
00314
00315 void renderer_c::render()
00316 {
00317 AssertThis;
00318
00319 if (gv.init.nogfx)
00320 return;
00321
00322 if (isinrender)
00323 {
00324 _log_printf(MSG_WARNING, "renderer_c::render() called from within itself!");
00325 return;
00326 }
00327
00328 isinrender = true;
00329
00330
00331 gv.frame++;
00332
00333 if (state.autoclear)
00334 {
00335 vec4_t c;
00336 color_to_vec(state.bgcolor, c);
00337 glClearColor(V4TOFS(c));
00338 glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
00339 }
00340
00341 if (gv.iface)
00342 gv.iface->render();
00343
00344 if (gv.gui)
00345 {
00346 view_2d(gv.init.hres, gv.init.vres);
00347 gv.gui->draw();
00348 }
00349
00350 #if defined(WIN32)
00351 SwapBuffers(gv.hdc);
00352 #else
00353 glXSwapBuffers(gv.init.dpy, gv.init.wnd);
00354 #endif
00355
00356 isinrender = false;
00357 }
00358
00359
00360
00361
00362
00363 void renderer_c::render_verts
00364 (
00365 const vertex_t *_verts,
00366 ulong count,
00367 ushort type
00368 )
00369 {
00370 AssertThis;
00371 AssertReturn1(_verts);
00372
00373 if (!state.currentshader)
00374 return;
00375
00376 const shader_t *currentshader = state.currentshader;
00377
00378 use_vertices(_verts, count);
00379 glMatrixMode(GL_TEXTURE);
00380
00381 bool fog = state.fog;
00382
00383 #if defined(WIN32)
00384 if (query_glext("GL_EXT_COMPILED_VERTEX_ARRAY"))
00385 glLockArraysEXT(0, count);
00386 #endif
00387
00388 if (query_glext("GL_NV_VERTEX_ARRAY_RANGE"))
00389 glEnableClientState(GL_VERTEX_ARRAY_RANGE_NV);
00390
00391 for (ushort pass=0; pass<currentshader->passcount; pass++)
00392 {
00393 if (!pass || currentshader->passes[pass-1].matrix)
00394 glLoadIdentity();
00395
00396 set_fog(fog && currentshader->passes[pass].fog);
00397
00398 if (currentshader->passes[pass].ignorediffuse)
00399 {
00400 for (ulong v=0; v<count; v++)
00401 drawverts[v].diffuse = COLOR_WHITE;
00402 }
00403 else if (pass && currentshader->passes[pass-1].ignorediffuse)
00404 {
00405 for (ulong v=0; v<count; v++)
00406 drawverts[v].diffuse = _verts[v].diffuse;
00407 }
00408
00409 if (currentshader->passes[pass].color)
00410 {
00411 float frac = shader_get_waveform_frac(¤tshader->passes[pass].colorwave);
00412
00413 color_t ci = color_interpolate(
00414 currentshader->passes[pass].color1,
00415 currentshader->passes[pass].color2,
00416 frac);
00417
00418 vec4_t color, c1;
00419
00420 if (ci != COLOR_WHITE)
00421 {
00422 if (!ci)
00423 {
00424 for (ulong v=0; v<count; v++)
00425 drawverts[v].diffuse = 0;
00426 }
00427 else
00428 {
00429 color_to_vec(ci, c1);
00430
00431 color[0] = state.currentcolorvec[0] * c1[0];
00432 color[1] = state.currentcolorvec[1] * c1[1];
00433 color[2] = state.currentcolorvec[2] * c1[2];
00434 color[3] = state.currentcolorvec[3] * c1[3];
00435
00436 for (ulong v=0; v<count; v++)
00437 {
00438 color_to_vec(_verts[v].diffuse, c1);
00439 drawverts[v].diffuse = color_from_floats(
00440 color[0] * c1[0],
00441 color[1] * c1[1],
00442 color[2] * c1[2],
00443 color[3] * c1[3]
00444 );
00445 }
00446 }
00447 }
00448 }
00449 else if (state.currentcolor != 0xFFFFFFFF)
00450 {
00451 vec4_t c1;
00452
00453 for (ulong v=0; v<count; v++)
00454 {
00455 color_to_vec(_verts[v].diffuse, c1);
00456 drawverts[v].diffuse = color_from_floats(
00457 state.currentcolorvec[0] * c1[0],
00458 state.currentcolorvec[1] * c1[1],
00459 state.currentcolorvec[2] * c1[2],
00460 state.currentcolorvec[3] * c1[3]
00461 );
00462 }
00463 }
00464
00465 set_texture_params(currentshader->passes[pass].minfilter,
00466 currentshader->passes[pass].magfilter,
00467 currentshader->passes[pass].texwrapu,
00468 currentshader->passes[pass].texwrapv);
00469
00470
00471 set_spheremapping(currentshader->passes[pass].shiny);
00472
00473 if (currentshader->passes[pass].matrix)
00474 {
00475 if (currentshader->passes[pass].soffsetx ||
00476 currentshader->passes[pass].soffsety)
00477 glTranslatef(currentshader->passes[pass].soffsetx,
00478 currentshader->passes[pass].soffsety,
00479 0);
00480
00481 if (currentshader->passes[pass].scalex!=1 ||
00482 currentshader->passes[pass].scaley!=1)
00483 glScalef (currentshader->passes[pass].scalex,
00484 currentshader->passes[pass].scaley*
00485 (currentshader->passes[pass].shiny?-1:1),
00486 1);
00487
00488 if (currentshader->passes[pass].angle)
00489 glRotatef (currentshader->passes[pass].angle,0,0,1);
00490 }
00491
00492 if (currentshader->dynamic)
00493 {
00494 if (currentshader->passes[pass].scalewavex.type != WF_NONE ||
00495 currentshader->passes[pass].scalewavey.type != WF_NONE)
00496 {
00497 float x = shader_get_waveform_frac(¤tshader->passes[pass].scalewavex);
00498 float y = shader_get_waveform_frac(¤tshader->passes[pass].scalewavey);
00499 glScalef (x,y,1);
00500 }
00501
00502 if (currentshader->passes[pass].rotation)
00503 glRotatef (gv.time*currentshader->passes[pass].rotation,0,0,1);
00504
00505 if (currentshader->passes[pass].scrollx || currentshader->passes[pass].scrolly ||
00506 currentshader->passes[pass].offsetx || currentshader->passes[pass].offsety)
00507 glTranslatef(gv.time*currentshader->passes[pass].scrollx+currentshader->passes[pass].offsetx,
00508 gv.time*currentshader->passes[pass].scrolly+currentshader->passes[pass].offsety,
00509 0);
00510 }
00511
00512 gv.texman->set(currentshader->passes[pass].texture);
00513 set_blending(currentshader->passes[pass].blendtype);
00514
00515 push_vertices(type, count);
00516 }
00517
00518 #if defined(WIN32)
00519 if (query_glext("GL_EXT_COMPILED_VERTEX_ARRAY"))
00520 glUnlockArraysEXT();
00521 #endif
00522
00523 if (query_glext("GL_NV_VERTEX_ARRAY_RANGE"))
00524 glDisableClientState(GL_VERTEX_ARRAY_RANGE_NV);
00525 }
00526
00527
00528
00529
00530
00531 void renderer_c::clear_color()
00532 {
00533 AssertThis;
00534
00535 glClear(GL_COLOR_BUFFER_BIT);
00536 }
00537
00538
00539
00540
00541 void renderer_c::clear_depth()
00542 {
00543 AssertThis;
00544
00545 glClear(GL_DEPTH_BUFFER_BIT);
00546 }
00547
00548
00549
00550
00551 void renderer_c::render_quad
00552 (
00553 const vertex_t *verts
00554 )
00555 {
00556 AssertThis;
00557
00558 render_verts( verts, 4, PT_TRIANGLEFAN );
00559 }
00560
00561
00562
00563
00564 void renderer_c::render_line_vec
00565 (
00566 const vec3_t v1,
00567 const vec3_t v2
00568 )
00569 {
00570 AssertThis;
00571
00572 vertex_t verts[2];
00573
00574
00575 vertex_set( &verts[0], v1[0], v1[1], v1[2], 0, 0 );
00576 vertex_set( &verts[1], v2[0], v2[1], v2[2], 0, 0 );
00577
00578 render_verts(verts, 2, PT_LINESTRIP);
00579 }
00580
00581
00582
00583
00584
00585
00586 void renderer_c::render_line2d
00587 (
00588 float x,
00589 float y,
00590 float x2,
00591 float y2
00592 )
00593 {
00594 AssertThis;
00595
00596 vec3_c v1,v2;
00597
00598 v1.set(x, y, 0);
00599 v2.set(x2, y2, 0);
00600
00601 render_line_vec(v1,v2);
00602 }
00603
00604 void renderer_c::make_frustum()
00605 {
00606 float fovx = fov/2;
00607 float fovy = fov/2/gv.aspect;
00608
00609
00610
00611
00612 vec3_c tmp;
00613
00614 tmp = viewRight;
00615 tmp.rotate_vec(-fovx, viewUp2).copy(viewFrustum[0].n);
00616
00617 tmp = viewRight;
00618 tmp.rotate_vec(180+fovx, viewUp2).copy(viewFrustum[1].n);
00619
00620 tmp = viewUp2;
00621 tmp.rotate_vec(fovy, viewRight).copy(viewFrustum[2].n);
00622
00623 tmp = viewUp2;
00624 tmp.rotate_vec(180-fovy, viewRight).copy(viewFrustum[3].n);
00625
00626 viewDir.normalize().copy(viewFrustum[4].n);
00627
00628 tmp = viewDir * -1;
00629 tmp.copy(viewFrustum[5].n);
00630
00631 for (ulong i=0; i<6; i++)
00632 viewFrustum[i].d = viewPos.dot(viewFrustum[i].n);
00633
00634 viewFrustum[5].d-=viewDepth;
00635 }
00636
00637 void renderer_c::need_vertices(ulong count)
00638 {
00639 if (count<=drawvertcount)
00640 return;
00641
00642 drawvertcount = count;
00643
00644 #if defined(WIN32)
00645 if (query_glext("GL_NV_VERTEX_ARRAY_RANGE"))
00646 {
00647 #if defined(WIN32)
00648 if (drawverts)
00649 wglFreeMemoryNV(drawverts);
00650
00651 drawverts = (vertex_t*)wglAllocateMemoryNV(sizeof(vertex_t)*(drawvertcount = count), 0.2f, 0.2f, 0.5f);
00652 #else
00653 if (drawverts)
00654 glXFreeMemoryNV(drawverts);
00655
00656 drawverts = (vertex_t*)glXAllocateMemoryNV(sizeof(vertex_t)*(drawvertcount = count), 0.2f, 0.2f, 0.5f);
00657 #endif
00658 glVertexArrayRangeNV(sizeof(vertex_t)*(drawvertcount), drawverts);
00659 }
00660 else
00661 #endif
00662 {
00663 SafeArrayDelete(drawverts);
00664 drawverts = new vertex_t[drawvertcount];
00665 }
00666 }
00667
00668 void renderer_c::use_vertices(const vertex_t *verts, ulong count)
00669 {
00670 need_vertices(count);
00671 memcpy(drawverts, verts, count*sizeof(vertex_t));
00672
00673 if (query_glext("GL_EXT_VERTEX_ARRAY"))
00674 {
00675 glVertexPointer (3, GL_FLOAT, sizeof(vertex_t), drawverts->xyz );
00676 glNormalPointer (GL_FLOAT, sizeof(vertex_t), drawverts->normal );
00677 glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(vertex_t), &drawverts->diffuse );
00678 glTexCoordPointer (2, GL_FLOAT, sizeof(vertex_t), drawverts->uv[0] );
00679 }
00680 }
00681
00682 void renderer_c::push_vertices(ushort ptype, ulong count)
00683 {
00684 GLuint pttype = GL_POINTS;
00685
00686 switch(ptype)
00687 {
00688 case PT_POINTS: pttype = GL_POINTS; break;
00689 case PT_LINES: pttype = GL_LINES; break;
00690 case PT_LINESTRIP: pttype = GL_LINE_STRIP; break;
00691 case PT_LINELOOP: pttype = GL_LINE_LOOP; break;
00692 case PT_TRIANGLES: pttype = GL_TRIANGLES; break;
00693 case PT_TRIANGLESTRIP: pttype = GL_TRIANGLE_STRIP; break;
00694 case PT_TRIANGLEFAN: pttype = GL_TRIANGLE_FAN; break;
00695 case PT_QUADS: pttype = GL_QUADS; break;
00696 }
00697
00698 if (!query_glext("GL_EXT_VERTEX_ARRAY"))
00699 {
00700 glBegin(pttype);
00701
00702 for (ulong i=0; i<count; i++)
00703 {
00704 vec4_t v;
00705
00706 color_to_vec(drawverts[i].diffuse, v);
00707
00708 glColor4f(V4TOFS(v));
00709 glTexCoord2f(V2TOFS(drawverts[i].uv[0]));
00710 glVertex3fv(drawverts[i].xyz);
00711 }
00712
00713 glEnd();
00714 }
00715 else
00716 glDrawArrays(pttype, 0, count);
00717 }