pixelcity/Texture.cpp

895 lines
27 KiB
C++

/*-----------------------------------------------------------------------------
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 <windows.h>
#include <stdio.h>
#include <math.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#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;
}