/*----------------------------------------------------------------------------- Texture.cpp 2009 Shamus Young ------------------------------------------------------------------------------- This procedurally builds all of the textures. I apologize in advance for the apalling state of this module. It's the victim of iterative and experimental development. It has cruft, poorly named functions, obscure code, poorly named variables, and is badly organized. Even the formatting sucks in places. Its only saving grace is that it works. -----------------------------------------------------------------------------*/ #define RANDOM_COLOR_SHIFT ((float)(RandomVal (10)) / 50.0f) #define RANDOM_COLOR_VAL ((float)(RandomVal (256)) / 256.0f) #define RANDOM_COLOR_LIGHT ((float)(200 + RandomVal (56)) / 256.0f) #define SKY_BANDS (sizeof (sky_pos) / sizeof (int)) #define PREFIX_COUNT (sizeof (prefix) / sizeof (char*)) #define SUFFIX_COUNT (sizeof (suffix) / sizeof (char*)) #define NAME_COUNT (sizeof (name) / sizeof (char*)) #include #include #include #include #include #include #include "gltypes.h" #include "building.h" #include "camera.h" #include "car.h" #include "light.h" #include "macro.h" #include "random.h" #include "render.h" #include "sky.h" #include "texture.h" #include "world.h" #include "win.h" static char* prefix[] = { "i", "Green ", "Mega", "Super ", "Omni", "e", "Hyper", "Global ", "Vital", "Next ", "Pacific ", "Metro", "Unity ", "G-", "Trans", "Infinity ", "Superior ", "Monolith ", "Best ", "Atlantic ", "First ", "Union ", "National ", }; static char* name[] = { "Biotic", "Info", "Data", "Solar", "Aerospace", "Motors", "Nano", "Online", "Circuits", "Energy", "Med", "Robotic", "Exports", "Security", "Systems", "Financial", "Industrial", "Media", "Materials", "Foods", "Networks", "Shipping", "Tools", "Medical", "Publishing", "Enterprises", "Audio", "Health", "Bank", "Imports", "Apparel", "Petroleum", "Studios", }; static char* suffix[] = { "Corp", " Inc.", "Co", "World", ".Com", " USA", " Ltd.", "Net", " Tech", " Labs", " Mfg.", " UK", " Unlimited", " One", " LLC" }; class CTexture { public: int _my_id; unsigned _glid; int _desired_size; int _size; int _half; int _segment_size; bool _ready; bool _masked; bool _mipmap; bool _clamp; public: CTexture* _next; CTexture (int id, int size, bool mipmap, bool clamp, bool masked); void Clear () { _ready = false; } void Rebuild (); void DrawWindows (); }; static CTexture* head; static bool textures_done; static GLrgba horizon_color; static GLrgba cloud_color; static bool prefix_used[PREFIX_COUNT]; static bool name_used[NAME_COUNT]; static bool suffix_used[SUFFIX_COUNT]; static int build_time; /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ void drawrect_simple (int left, int top, int right, int bottom, GLrgba color) { glColor3fv (&color.red); glBegin (GL_QUADS); glVertex2i (left, top); glVertex2i (right, top); glVertex2i (right, bottom); glVertex2i (left, bottom); glEnd (); } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ void drawrect_simple (int left, int top, int right, int bottom, GLrgba color1, GLrgba color2) { glColor3fv (&color1.red); glBegin (GL_TRIANGLE_FAN); glVertex2i ((left + right) / 2, (top + bottom) / 2); glColor3fv (&color2.red); glVertex2i (left, top); glVertex2i (right, top); glVertex2i (right, bottom); glVertex2i (left, bottom); glVertex2i (left, top); glEnd (); } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ void drawrect (int left, int top, int right, int bottom, GLrgba color) { float average; float hue; int potential; int repeats; int height; int i, j; bool bright; GLrgba color_noise; glDisable (GL_CULL_FACE); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_BLEND); glLineWidth (1.0f); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor3fv (&color.red); if (left == right) { //in low resolution, a "rect" might be 1 pixel wide glBegin (GL_LINES); glVertex2i (left, top); glVertex2i (left, bottom); glEnd (); } if (top == bottom) { //in low resolution, a "rect" might be 1 pixel wide glBegin (GL_LINES); glVertex2i (left, top); glVertex2i (right, top); glEnd (); } else { // draw one of those fancy 2-dimensional rectangles glBegin (GL_QUADS); glVertex2i (left, top); glVertex2i (right, top); glVertex2i (right, bottom); glVertex2i (left, bottom); glEnd (); average = (color.red + color.blue + color.green) / 3.0f; bright = average > 0.5f; potential = (int)(average * 255.0f); if (bright) { glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBegin (GL_POINTS); for (i = left + 1; i < right - 1; i++) { for (j = top + 1; j < bottom - 1; j++) { glColor4i (255, 0, RandomVal (potential), 255); hue = 0.2f + (float)RandomVal (100) / 300.0f + (float)RandomVal (100) / 300.0f + (float)RandomVal (100) / 300.0f; color_noise = glRgbaFromHsl (hue, 0.3f, 0.5f); color_noise.alpha = (float)RandomVal (potential) / 144.0f; glColor4f (RANDOM_COLOR_VAL, RANDOM_COLOR_VAL, RANDOM_COLOR_VAL, (float)RandomVal (potential) / 144.0f); glColor4fv (&color_noise.red); glVertex2i (i, j); } } glEnd (); } repeats = RandomVal (6) + 1; height = (bottom - top) + (RandomVal (3) - 1) + (RandomVal(3) - 1); for (i = left; i < right; i++) { if (RandomVal (3) == 0) repeats = RandomVal (4) + 1; if (RandomVal (6) == 0) { height = bottom - top; height = RandomVal (height); height = RandomVal (height); height = RandomVal (height); height = ((bottom - top) + height) / 2; } for (j = 0; j < 1; j++) { glBegin (GL_LINES); glColor4f (0, 0, 0, (float)RandomVal (256) / 256.0f); glVertex2i (i, bottom - height); glColor4f (0, 0, 0, (float)RandomVal (256) / 256.0f); glVertex2i (i, bottom); glEnd (); } } } } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ static void window (int x, int y, int size, int id, GLrgba color) { int margin; int half; int i; margin = size / 3; half = size / 2; //color = (color * 0.9f) + glRgba (RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT); //glColor3fv (&color.red); switch (id) { case TEXTURE_BUILDING1: //filled, 1-pixel frame drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color); break; case TEXTURE_BUILDING2: //vertical drawrect (x + margin, y + 1, x + size - margin, y + size - 1, color); break; case TEXTURE_BUILDING3: //side-by-side pair drawrect (x + 1, y + 1, x + half - 1, y + size - margin, color); drawrect (x + half + 1, y + 1, x + size - 1, y + size - margin, color); break; case TEXTURE_BUILDING4: //windows with blinds drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color); i = RandomVal (size - 2); drawrect (x + 1, y + 1, x + size - 1, y + i + 1, color * 0.3f); break; case TEXTURE_BUILDING5: //vert stripes drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color); drawrect (x + margin, y + 1, x + margin, y + size - 1, color * 0.7f); drawrect (x + size - margin - 1, y + 1, x + size - margin - 1, y + size - 1, color * 0.3f); break; case TEXTURE_BUILDING6: //wide horz line drawrect (x + 1, y + 1, x + size - 1, y + size - margin, color); break; case TEXTURE_BUILDING7: //4-pane drawrect (x + 2, y + 1, x + size - 1, y + size - 1, color); drawrect (x + 2, y + half, x + size - 1, y + half, color * 0.2f); drawrect (x + half, y + 1, x + half, y + size - 1, color * 0.2f); break; case TEXTURE_BUILDING8: // Single narrow window drawrect (x + half - 1, y + 1, x + half + 1, y + size - margin, color); break; case TEXTURE_BUILDING9: //horizontal drawrect (x + 1, y + margin, x + size - 1, y + size - margin - 1, color); break; } } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ static void do_bloom (CTexture* t) { LIMIT_INTERVAL (10); glBindTexture(GL_TEXTURE_2D, 0); glViewport(0, 0, t->_size , t->_size); glCullFace (GL_BACK); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask (true); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_DEPTH_TEST); glEnable (GL_CULL_FACE); glCullFace (GL_BACK); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_FOG); glFogf (GL_FOG_START, RenderFogDistance () / 2); glFogf (GL_FOG_END, RenderFogDistance ()); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glClearColor (0.0f, 0.0f, 0.0f, 0.0f); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable (GL_TEXTURE_2D); EntityRender (); CarRender (); LightRender (); glBindTexture(GL_TEXTURE_2D, t->_glid); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); glCopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, t->_size, t->_size, 0); } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ CTexture::CTexture (int id, int size, bool mipmap, bool clamp, bool masked) { glGenTextures (1, &_glid); _my_id = id; _mipmap = mipmap; _clamp = clamp; _masked = masked; _desired_size = size; _size = size; _half = size / 2; _segment_size = size / SEGMENTS_PER_TEXTURE; _ready = false; _next = head; head = this; } /*----------------------------------------------------------------------------- This draws all of the windows on a building texture. lit_density controls how many lights are on. (1 in n chance that the light is on. Higher values mean less lit windows. run_length controls how often it will consider changing the lit / unlit status. 1 produces a complete scatter, higher numbers make long strings of lights. -----------------------------------------------------------------------------*/ void CTexture::DrawWindows () { int x, y; int run; int run_length; int lit_density; GLrgba color; bool lit; //color = glRgbaUnique (_my_id); for (y = 0; y < SEGMENTS_PER_TEXTURE; y++) { //Every few floors we change the behavior if (!(y % 8)) { run = 0; run_length = RandomVal (9) + 2; lit_density = 2 + RandomVal(2) + RandomVal(2); lit = false; } for (x = 0; x < SEGMENTS_PER_TEXTURE; x++) { //if this run is over reroll lit and start a new one if (run < 1) { run = RandomVal (run_length); lit = RandomVal (lit_density) == 0; //if (lit) //color = glRgba (0.5f + (float)(RandomVal () % 128) / 256.0f) + glRgba (RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT); } if (lit) color = glRgba (0.5f + (float)(RandomVal () % 128) / 256.0f) + glRgba (RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT); else color = glRgba ((float)(RandomVal () % 40) / 256.0f); window (x * _segment_size, y * _segment_size, _segment_size, _my_id, color); run--; } } } /*----------------------------------------------------------------------------- Here is where ALL of the procedural textures are created. It's filled with obscure logic, magic numbers, and messy code. Part of this is because there is a lot of "art" being done here, and lots of numbers that could be endlessly tweaked. Also because I'm lazy. -----------------------------------------------------------------------------*/ void CTexture::Rebuild () { int i, j; int x, y; int name_num, prefix_num, suffix_num; int max_size; float radius; GLvector2 pos; GLrgba color; bool use_framebuffer; unsigned char* bits; unsigned start; int lapsed; start = GetTickCount (); glBindTexture(GL_TEXTURE_2D, _glid); glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, _size, _size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (_clamp) { glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } //Since we make textures by drawing into the viewport, we can't make them bigger //than the current view. _size = _desired_size; max_size = RenderMaxTextureSize (); while (_size > max_size) _size /= 2; //Set up our viewport so that drawing into our texture will be as easy //as possible. We make the viewport and projection simply match the given //texture size. glViewport(0, 0, _size , _size); glMatrixMode (GL_PROJECTION); glLoadIdentity (); glOrtho (0, _size, _size, 0, 0.1f, 2048); glMatrixMode (GL_MODELVIEW); glPushMatrix (); glLoadIdentity(); glDisable (GL_CULL_FACE); glBindTexture(GL_TEXTURE_2D, 0); glTranslatef(0, 0, -10.0f); glClearColor (0, 0, 0, _masked ? 0.0f : 1.0f); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); use_framebuffer = true; glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); switch (_my_id) { case TEXTURE_GROUND: unsigned char icolor[4]; char cell; //memset (buffer, 0, 1024 * 1024 * 4); bits = new unsigned char[_size * _size * 4]; ZeroMemory (bits, sizeof (bits)); icolor[3] = 255; for (x = 0; x < _size; x++) { for (y = 0; y < _size; y++) { cell = WorldCell (x, y); memset (icolor, 0, 3); if (cell & CLAIM_ROAD) icolor[0] = icolor[1] = icolor[2] = 12; if (cell == CLAIM_WALK) icolor[0] = icolor[1] = icolor[2] = 64; icolor[0] += (unsigned char)RandomVal (4); icolor[1] += (unsigned char)RandomVal (4); icolor[2] += (unsigned char)RandomVal (4); if (1) { //use this to make the road lanes visible if (cell & MAP_ROAD_EAST) icolor[0] += 128; if (cell & MAP_ROAD_WEST) icolor[1] += 128; if (cell & MAP_ROAD_NORTH) icolor[2] += 128; if (cell & MAP_ROAD_SOUTH) { icolor[1] += 64; icolor[2] += 64; } } memcpy (&bits[(x + y * _size) * 4], &icolor[0], 4); } } glBindTexture(GL_TEXTURE_2D, _glid); glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, _size, _size, 0, GL_RGBA, GL_UNSIGNED_BYTE, bits); use_framebuffer = false; delete bits; break; case TEXTURE_LATTICE: glLineWidth (2.0f); glColor3f (0,0,0); glBegin (GL_LINES); glVertex2i (0, 0); glVertex2i (_size, _size);//diagonal glVertex2i (0, 0); glVertex2i (0, _size);//vertical glVertex2i (0, 0); glVertex2i (_size, 0);//vertical glEnd (); glBegin (GL_LINE_STRIP); glVertex2i (0, 0); for (i = 0; i < _size; i += 9) { if (i % 2) glVertex2i (0, i); else glVertex2i (i, i); } for (i = 0; i < _size; i += 9) { if (i % 2) glVertex2i (i, 0); else glVertex2i (i, i); } glEnd (); break; case TEXTURE_SOFT_CIRCLE: //Make a simple circle of light, bright in the center and fading out glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); radius = ((float)_half) - 3; glBegin (GL_TRIANGLE_FAN); glColor4f (1, 1, 1, 1); glVertex2i (_half, _half); glColor4f (0, 0, 0, 0); for (i = 0; i <= 360; i++) { pos.x = sinf ((float)i * DEGREES_TO_RADIANS) * radius; pos.y = cosf ((float)i * DEGREES_TO_RADIANS) * radius; glVertex2i (_half + (int)pos.x, _half + (int)pos.y); } glEnd (); break; case TEXTURE_LIGHT: // glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); radius = ((float)_half) - 3; for (j = 0; j < 2; j++) { glBegin (GL_TRIANGLE_FAN); glColor4f (1, 1, 1, 1); glVertex2i (_half, _half); if (!j) radius = ((float)_half / 2); else radius = 8; glColor4f (1, 1, 1, 0); for (i = 0; i <= 360; i++) { pos.x = sinf ((float)i * DEGREES_TO_RADIANS) * radius; pos.y = cosf ((float)i * DEGREES_TO_RADIANS) * radius; glVertex2i (_half + (int)pos.x, _half + (int)pos.y); } glEnd (); } break; case TEXTURE_HEADLIGHT: //Make a simple circle of light, bright in the center and fading out radius = ((float)_half) - 20; x = _half - 20; y = _half; glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBegin (GL_TRIANGLE_FAN); glColor4f (0.8f, 0.8f, 0.8f, 0.6f); glVertex2i (_half - 5, y); glColor4f (0, 0, 0, 0); for (i = 0; i <= 360; i += 36) { pos.x = sinf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius; pos.y = cosf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius; glVertex2i (x + (int)pos.x, _half + (int)pos.y); } glEnd (); x = _half + 20; glBegin (GL_TRIANGLE_FAN); glColor4f (0.8f, 0.8f, 0.8f, 0.6f); glVertex2i (_half + 5, y); glColor4f (0, 0, 0, 0); for (i = 0; i <= 360; i += 36) { pos.x = sinf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius; pos.y = cosf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius; glVertex2i (x + (int)pos.x, _half + (int)pos.y); } glEnd (); x = _half - 6; drawrect_simple (x - 3, y - 2, x + 2, y + 2, glRgba (1.0f)); x = _half + 6; drawrect_simple (x - 2, y - 2, x + 3, y + 2, glRgba (1.0f)); break; case TEXTURE_LOGOS: i = 0; glDepthMask (false); glDisable (GL_BLEND); name_num = RandomVal (NAME_COUNT); prefix_num = RandomVal (PREFIX_COUNT); suffix_num = RandomVal (SUFFIX_COUNT); glColor3f (1,1,1); while (i < _size) { //randomly use a prefix OR suffix, but not both. Too verbose. if (COIN_FLIP) RenderPrint (2, _size - i - LOGO_PIXELS / 4, RandomVal(), glRgba (1.0f), "%s%s", prefix[prefix_num], name[name_num]); else RenderPrint (2, _size - i - LOGO_PIXELS / 4, RandomVal(), glRgba (1.0f), "%s%s", name[name_num], suffix[suffix_num]); name_num = (name_num + 1) % NAME_COUNT; prefix_num = (prefix_num + 1) % PREFIX_COUNT; suffix_num = (suffix_num + 1) % SUFFIX_COUNT; i += LOGO_PIXELS; } break; case TEXTURE_CLOUDS: int width, height; int offset; float scale; for (i = _size - 30; i > 5; i -= 1) { x = RandomVal (_size); y = i; scale = 1.0f - ((float)y / (float)_size); width = RandomVal (_half / 2) + (int)((float)_half * scale) / 2; scale = 1.0f - (float)y / (float)_size; height = (int)((float)(width) * scale); height = MAX (height, 4); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable (GL_CULL_FACE); glEnable (GL_TEXTURE_2D); glBindTexture (GL_TEXTURE_2D, TextureId (TEXTURE_SOFT_CIRCLE)); glDepthMask (false); glBegin (GL_QUADS); for (offset = -_size; offset <= _size; offset += _size) { for (scale = 1.0f; scale > 0.0f; scale -= 0.25f) { int width_adjust; int height_adjust; float inv_scale; inv_scale = 1.0f - (scale); if (scale < 0.4f) color = cloud_color; else color = glRgba (0.0f); color.alpha = 1.0f; glColor4fv (&color.red); width_adjust = (int)((float)width / 2.0f + (int)(inv_scale * ((float)width / 2.0f))); height_adjust = height + (int)(scale * (float)height * 0.99f); glTexCoord2f (0, 0); glVertex2i (offset + x - width_adjust, y + height - height_adjust); glTexCoord2f (0, 1); glVertex2i (offset + x - width_adjust, y + height); glTexCoord2f (1, 1); glVertex2i (offset + x + width_adjust, y + height); glTexCoord2f (1, 0); glVertex2i (offset + x + width_adjust, y + height - height_adjust); } } glEnd (); } break; case TEXTURE_TRIM: int margin; y = 0; margin = MAX (TRIM_PIXELS / 4, 1); for (x = 0; x < _size; x += TRIM_PIXELS) drawrect_simple (x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f)); y += TRIM_PIXELS; for (x = 0; x < _size; x += TRIM_PIXELS * 2) drawrect_simple (x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f)); y += TRIM_PIXELS; for (x = 0; x < _size; x += TRIM_PIXELS * 3) drawrect_simple (x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f)); y += TRIM_PIXELS; for (x = 0; x < _size; x += TRIM_PIXELS) drawrect_simple (x + margin, y + margin * 2, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f)); break; case TEXTURE_SKY: glDisable (GL_BLEND); glBegin (GL_QUAD_STRIP); glColor3f (0,0,0); glVertex2i (0, _half); glVertex2i (_size, _half); glColor3fv (&horizon_color.red); glVertex2i (0, _size - 2); glVertex2i (_size, _size - 2); glEnd (); //Draw a bunch of little faux-buildings on the horizon. for (i = 0; i < _size; i += 5) drawrect (i, _size - RandomVal (8) - RandomVal (8) - RandomVal (8), i + RandomVal (9), _size, glRgba (0.0f)); break; default: //building textures DrawWindows (); break; } glPopMatrix (); //Now blit the finished image into our texture if (use_framebuffer) { glBindTexture(GL_TEXTURE_2D, _glid); glCopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, _size, _size, 0); } if (_mipmap) { bits = (unsigned char*)malloc (_size * _size * 4); glGetTexImage (GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, bits); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, _size, _size, GL_RGBA, GL_UNSIGNED_BYTE, bits); free (bits); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); } else glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); //cleanup and restore the viewport RenderResize (); _ready = true; lapsed = GetTickCount () - start; build_time += lapsed; } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ unsigned TextureId (int id) { for (CTexture* t = head; t; t = t->_next) { if (t->_my_id == id) return t->_glid; } return 0; } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ unsigned TextureRandomBuilding (int index) { index = abs (index) % BUILDING_COUNT; return TextureId (TEXTURE_BUILDING1 + index); } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ void TextureReset (void) { float hue, sat; textures_done = false; build_time = 0; for (CTexture* t = head; t; t = t->_next) t->Clear (); hue = 0.5f + (float)RandomVal (20) / 100.0f; sat = 0.1f + (float)RandomVal (80) / 100.0f; horizon_color = glRgbaFromHsl (hue, sat, 0.15f); cloud_color = glRgbaFromHsl (hue, 0.15f, 0.1f); ZeroMemory (prefix_used, sizeof (prefix_used)); ZeroMemory (name_used, sizeof (name_used)); ZeroMemory (suffix_used, sizeof (suffix_used)); } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ bool TextureReady () { return textures_done; } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ void TextureUpdate (void) { if (textures_done) { if (!RenderBloom ()) return; CTexture* t; for (t = head; t; t = t->_next) { if (t->_my_id != TEXTURE_BLOOM) continue; do_bloom (t); return; } } for (CTexture* t = head; t; t = t->_next) { if (!t->_ready) { t->Rebuild(); return; } } textures_done = true; } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ void TextureTerm (void) { CTexture* t; while (head) { t = head->_next; free (head); head = t; } } /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ void TextureInit (void) { new CTexture (TEXTURE_SKY, 512, true, false, false); new CTexture (TEXTURE_CLOUDS, 256, true, false, true); new CTexture (TEXTURE_LATTICE, 128, true, true, true); new CTexture (TEXTURE_LIGHT, 128, false, false, true); new CTexture (TEXTURE_SOFT_CIRCLE, 128, false, false, true); new CTexture (TEXTURE_HEADLIGHT, 128, false, false, true); new CTexture (TEXTURE_TRIM, TRIM_RESOLUTION, true, false, false); if (SHOW_DEBUG_GROUND) new CTexture (TEXTURE_GROUND, 1024, false, false, false); new CTexture (TEXTURE_LOGOS, LOGO_RESOLUTION, true, false, true); for (int i = TEXTURE_BUILDING1; i <= TEXTURE_BUILDING9; i++) new CTexture (i, 512, true, false, false); new CTexture (TEXTURE_BLOOM, 512, true, false, false); int names = PREFIX_COUNT * NAME_COUNT + SUFFIX_COUNT * NAME_COUNT; }