Added new "fade-in" mode that constructs city of wire & primitives and slowly fades to texture view. It's slow & wasteful, and added mostly for experimentation purposes. Enable it by setting LOADING_SCREEN to 0 in win.h.

This commit is contained in:
Shamus Young 2009-05-08 08:22:02 +00:00
parent e9c6ff35f3
commit 7bc7366e32
9 changed files with 157 additions and 104 deletions

View File

@ -52,6 +52,7 @@ static int polycount;
static int compile_x;
static int compile_y;
static int compile_count;
static int compile_end;
/*-----------------------------------------------------------------------------
@ -173,6 +174,7 @@ static void do_compile ()
compile_y++;
if (compile_y == GRID_SIZE)
compiled = true;
compile_end = GetTickCount ();
}
compile_count++;
@ -199,7 +201,6 @@ float EntityProgress ()
return (float)compile_count / (GRID_SIZE * GRID_SIZE);
}
@ -222,8 +223,11 @@ void EntityUpdate ()
}
//We want to do several cells at once. Enough to get things done, but
//not so many that the program is unresponsive.
stop_time = GetTickCount () + 100;
while (!compiled && GetTickCount () < stop_time)
if (LOADING_SCREEN) { //If we're using a loading screen, we want to build as fast as possible
stop_time = GetTickCount () + 100;
while (!compiled && GetTickCount () < stop_time)
do_compile ();
} else //Take it slow
do_compile ();
}
@ -238,12 +242,21 @@ void EntityRender ()
int polymode[2];
bool wireframe;
int x, y;
int elapsed;
//Draw all textured objects
glGetIntegerv (GL_POLYGON_MODE, &polymode[0]);
wireframe = polymode[0] != GL_FILL;
if (RenderFlat ())
glDisable (GL_TEXTURE_2D);
//If we're not using a loading screen, make the wireframe fade out via fog
if (!LOADING_SCREEN && wireframe) {
elapsed = 6000 - WorldSceneElapsed ();
if (elapsed >= 0 && elapsed <= 6000)
RenderFogFX ((float)elapsed / 6000.0f);
else
return;
}
for (x = 0; x < GRID_SIZE; x++) {
for (y = 0; y < GRID_SIZE; y++) {
if (Visible (x,y))

View File

@ -24,6 +24,7 @@
#include "glTypes.h"
#include "camera.h"
#include "entity.h"
#include "light.h"
#include "macro.h"
#include "math.h"
@ -76,6 +77,8 @@ void LightRender ()
CLight* l;
if (!EntityReady ())
return;
if (!angles_done) {
for (int size = 0; size < MAX_SIZE; size++) {
for (int i = 0 ;i < 360; i++) {

View File

@ -217,7 +217,7 @@ static void do_effects (int type)
fade = WorldFade ();
bloom_radius = 15;
bloom_step = bloom_radius / 3;
if (!TextureReady () && fade == 0.0f)
if (!TextureReady ())
return;
//Now change projection modes so we can render full-screen effects
glDisable(GL_DEPTH_TEST);
@ -230,9 +230,9 @@ static void do_effects (int type)
glLoadIdentity();
glTranslatef(0, 0, -1.0f);
glDisable (GL_CULL_FACE);
glDisable (GL_FOG);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//Render full-screen effects
glBlendFunc (GL_ONE, GL_ONE);
glEnable (GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_BLOOM));
@ -326,26 +326,31 @@ static void do_effects (int type)
break;
}
//Do the fade to / from darkness used to hide scene transitions
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_BLEND);
glDisable (GL_TEXTURE_2D);
glColor4f (0, 0, 0, fade);
glBegin (GL_QUADS);
glVertex2i (0, 0);
glVertex2i (0, render_height);
glVertex2i (render_width, render_height);
glVertex2i (render_width, 0);
glEnd ();
if (TextureReady () && !EntityReady () && fade != 0.0f) {
radius = render_width / 16;
do_progress ((float)render_width / 2, (float)render_height / 2, (float)radius, fade, EntityProgress ());
RenderPrint (render_width / 2 - LOGO_PIXELS, render_height / 2 + LOGO_PIXELS, 0, glRgba (0.5f), "%1.2f%%", EntityProgress () * 100.0f);
RenderPrint (1, "%s v%d.%d.%03d", APP_TITLE, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
if (LOADING_SCREEN) {
if (fade > 0.0f) {
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_BLEND);
glDisable (GL_TEXTURE_2D);
glColor4f (0, 0, 0, fade);
glBegin (GL_QUADS);
glVertex2i (0, 0);
glVertex2i (0, render_height);
glVertex2i (render_width, render_height);
glVertex2i (render_width, 0);
glEnd ();
}
if (TextureReady () && !EntityReady () && fade != 0.0f) {
radius = render_width / 16;
do_progress ((float)render_width / 2, (float)render_height / 2, (float)radius, fade, EntityProgress ());
RenderPrint (render_width / 2 - LOGO_PIXELS, render_height / 2 + LOGO_PIXELS, 0, glRgba (0.5f), "%1.2f%%", EntityProgress () * 100.0f);
RenderPrint (1, "%s v%d.%d.%03d", APP_TITLE, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
}
}
glPopMatrix ();
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glMatrixMode (GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
}
@ -711,6 +716,27 @@ float RenderFogDistance ()
}
/*-----------------------------------------------------------------------------
This is used to set a gradient fog that goes from camera to some portion of
the normal fog distance. This is used for making wireframe outlines and
flat surfaces fade out after rebuild. Looks cool.
-----------------------------------------------------------------------------*/
void RenderFogFX (float scalar)
{
if (scalar >= 1.0f) {
glDisable (GL_FOG);
return;
}
glFogf (GL_FOG_START, 0.0f);
glFogf (GL_FOG_END, fog_distance * 2.0f * scalar);
glEnable (GL_FOG);
}
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
@ -721,32 +747,26 @@ void RenderUpdate (void)
GLvector pos;
GLvector angle;
GLrgba color;
int elapsed;
frames++;
do_fps ();
glViewport (0, 0, WinWidth (), WinHeight ());
glDepthMask (true);
glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (letterbox)
glViewport (0, letterbox_offset, render_width, render_height);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (TextureReady () && !EntityReady ()) {
do_effects (-1);
if (LOADING_SCREEN && TextureReady () && !EntityReady ()) {
do_effects (EFFECT_NONE);
SwapBuffers (hDC);
return;
}
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glShadeModel(GL_SMOOTH);
glFogi (GL_FOG_MODE, GL_LINEAR);
if (show_fog) {
glEnable (GL_FOG);
glFogf (GL_FOG_START, fog_distance - 100);
glFogf (GL_FOG_END, fog_distance);
color = glRgba (0.0f);
glFogfv (GL_FOG_COLOR, &color.red);
} else
glDisable (GL_FOG);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glEnable (GL_CULL_FACE);
glCullFace (GL_BACK);
glEnable (GL_BLEND);
@ -766,7 +786,15 @@ void RenderUpdate (void)
glEnable (GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//Render all the stuff in the whole entire world.
glDisable (GL_FOG);
SkyRender ();
if (show_fog) {
glEnable (GL_FOG);
glFogf (GL_FOG_START, fog_distance - 100);
glFogf (GL_FOG_END, fog_distance);
color = glRgba (0.0f);
glFogfv (GL_FOG_COLOR, &color.red);
}
WorldRender ();
if (effect == EFFECT_GLASS_CITY) {
glDisable (GL_CULL_FACE);
@ -782,7 +810,19 @@ void RenderUpdate (void)
glDisable (GL_BLEND);
}
EntityRender ();
LightRender ();
if (!LOADING_SCREEN) {
elapsed = 3000 - WorldSceneElapsed ();
if (elapsed >= 0 && elapsed <= 3000) {
RenderFogFX ((float)elapsed / 3000.0f);
glDisable (GL_TEXTURE_2D);
glEnable (GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE);
EntityRender ();
}
}
if (EntityReady ())
LightRender ();
CarRender ();
if (show_wireframe) {
glDisable (GL_TEXTURE_2D);
@ -791,13 +831,11 @@ void RenderUpdate (void)
}
do_effects (effect);
//Framerate tracker
if (show_fps) {
if (show_fps)
RenderPrint (1, "FPS=%d : Entities=%d : polys=%d", current_fps, EntityCount () + LightCount () + CarCount (), EntityPolyCount () + LightCount () + CarCount ());
}
//Show the help overlay
if (show_help)
do_help ();
glDepthMask (true);
SwapBuffers (hDC);
}

View File

@ -5,6 +5,7 @@ void RenderFlatToggle ();
float RenderFogDistance ();
bool RenderFog ();
void RenderFogToggle ();
void RenderFogFX (float scalar);
void RenderFPSToggle ();
void RenderInit ();
void RenderLetterboxToggle ();

View File

@ -149,8 +149,6 @@ public:
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];
@ -294,8 +292,6 @@ static void window (int x, int y, int size, int id, GLrgba color)
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);
@ -343,7 +339,6 @@ static void window (int x, int y, int size, int id, GLrgba color)
static void do_bloom (CTexture* t)
{
LIMIT_INTERVAL (10);
glBindTexture(GL_TEXTURE_2D, 0);
glViewport(0, 0, t->_size , t->_size);
glCullFace (GL_BACK);
@ -459,6 +454,7 @@ void CTexture::Rebuild ()
int name_num, prefix_num, suffix_num;
int max_size;
float radius;
float grey;
GLvector2 pos;
GLrgba color;
bool use_framebuffer;
@ -467,20 +463,21 @@ void CTexture::Rebuild ()
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;
glBindTexture(GL_TEXTURE_2D, _glid);
//Set up the texture
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);
}
//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.
@ -492,6 +489,7 @@ void CTexture::Rebuild ()
glPushMatrix ();
glLoadIdentity();
glDisable (GL_CULL_FACE);
glDisable (GL_FOG);
glBindTexture(GL_TEXTURE_2D, 0);
glTranslatef(0, 0, -10.0f);
glClearColor (0, 0, 0, _masked ? 0.0f : 1.0f);
@ -581,7 +579,6 @@ void CTexture::Rebuild ()
glEnd ();
break;
case TEXTURE_LIGHT:
//
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
radius = ((float)_half) - 3;
@ -686,7 +683,7 @@ void CTexture::Rebuild ()
inv_scale = 1.0f - (scale);
if (scale < 0.4f)
color = cloud_color;
color = WorldBloomColor () * 0.1f;
else
color = glRgba (0.0f);
color.alpha = 1.0f;
@ -721,12 +718,16 @@ void CTexture::Rebuild ()
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:
color = WorldBloomColor ();
grey = (color.red + color.green + color.blue) / 3.0f;
//desaturate, slightly dim
color = (color + glRgba (grey) * 2.0f) / 15.0f;
glDisable (GL_BLEND);
glBegin (GL_QUAD_STRIP);
glColor3f (0,0,0);
glVertex2i (0, _half);
glVertex2i (_size, _half);
glColor3fv (&horizon_color.red);
glColor3fv (&color.red);
glVertex2i (0, _size - 2);
glVertex2i (_size, _size - 2);
glEnd ();
@ -796,16 +797,10 @@ unsigned TextureRandomBuilding (int 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));

40
Win.cpp
View File

@ -193,50 +193,15 @@ void AppUpdate ()
{
CameraUpdate ();
EntityUpdate ();
WorldUpdate ();
TextureUpdate ();
VisibleUpdate ();
CarUpdate ();
EntityUpdate ();
RenderUpdate ();
}
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
void CALLBACK Appx (HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
static int ii;
//for (int i = 0; i < 1000;i++)
AppUpdate ();
ii++;
if (ii > 1)
ii++;
//PostQuitMessage (1);
//exit (1);
}
static void do_timer ()
{
TIMECAPS tc;
int resolution;
if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
resolution = 0;
}
resolution = min(max(tc.wPeriodMin, 1), tc.wPeriodMax);
if (!timeSetEvent (1, resolution,(LPTIMECALLBACK)Appx, 123, TIME_PERIODIC | TIME_CALLBACK_FUNCTION ))
resolution = 0;
}
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
@ -445,7 +410,8 @@ LONG WINAPI ScreenSaverProc(HWND hwnd_in,UINT message,WPARAM wparam,LPARAM lpara
break;
case WM_CREATE:
hwnd = hwnd_in;
AppInit ();
if (SCREENSAVER)
AppInit ();
SetTimer (hwnd, 1, 7, NULL);
return 0;
case WM_TIMER:

8
Win.h
View File

@ -3,15 +3,17 @@
#define APP "pixelcity"
#define VERSION_MAJOR 1
#define VERSION_MINOR 0
#define VERSION_REVISION 5
#define VERSION_REVISION 10
//Best to disable screensaver mode when working on the program.
#define SCREENSAVER 0
//Do we hide scene building behing a loading screen or show it?
#define LOADING_SCREEN 1
//Controls the density of cars.
#define CARS 0
#define CARS 500
//The "dead zone" along the edge of the world, with super-low detail.
#define WORLD_EDGE 200
//How often to rebuild the city
#define RESET_INTERVAL (SCREENSAVER ? 120 : 999)//seconds
#define RESET_INTERVAL (SCREENSAVER ? 120000 : 999999)//milliseconds
//How long the screen fade takes when transitioning to a new city
#define FADE_TIME (SCREENSAVER ? 1500 : 1) //milliseconds
//Debug ground texture that shows traffic lanes

View File

@ -112,6 +112,7 @@ static int skyscrapers;
static GLbbox hot_zone;
static int logo_index;
static unsigned start_time;
static int scene_begin;
/*-----------------------------------------------------------------------------
@ -272,7 +273,7 @@ void do_building (plot p)
return;
//If the area is too big for one building, sub-divide it.
if (area > 1400) {
if (area > 800) {
if (COIN_FLIP) {
p.width /= 2;
if (COIN_FLIP)
@ -295,7 +296,7 @@ void do_building (plot p)
square = abs (p.width - p.depth) < 10;
//mark the land as used so other buildings don't appear here, even if we don't use it all.
claim (p.x, p.z, p.width, p.depth, CLAIM_BUILDING);
/*
//The roundy mod buildings look best on square plots.
if (square && p.width > 20) {
height = 45 + RandomVal (10);
@ -304,6 +305,7 @@ void do_building (plot p)
new CBuilding (BUILDING_MODERN, p.x, p.z, height, p.width, p.depth, seed, color);
return;
}
/*
//Rectangular plots are a good place for Blocky style buildsing to sprawl blockily.
if (p.width > p.depth * 2 || p.depth > p.width * 2 && area > 800) {
height = 20 + RandomVal (10);
@ -313,7 +315,7 @@ void do_building (plot p)
return;
}
*/
tower_count = -1;
//tower_count = -1;
//This spot isn't ideal for any particular building, but try to keep a good mix
if (tower_count < modern_count && tower_count < blocky_count) {
type = BUILDING_TOWER;
@ -410,6 +412,7 @@ static void do_reset (void)
broadway_done = false;
skyscrapers = 0;
logo_index = 0;
scene_begin = 0;
tower_count = blocky_count = modern_count = 0;
hot_zone = glBboxClear ();
EntityClear ();
@ -681,6 +684,36 @@ float WorldFade (void)
}
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
int WorldSceneBegin ()
{
return scene_begin;
}
/*-----------------------------------------------------------------------------
How long since this current iteration of the city went on display,
-----------------------------------------------------------------------------*/
int WorldSceneElapsed ()
{
int elapsed;
if (!EntityReady () || !WorldSceneBegin ())
elapsed = 1;
else
elapsed = GetTickCount () - (WorldSceneBegin ());
elapsed = MAX (elapsed, 1);
return elapsed;
}
/*-----------------------------------------------------------------------------
@ -690,7 +723,7 @@ void WorldUpdate (void)
{
unsigned fade_delta;
unsigned now, elapsed;
int now;
now = GetTickCount ();
if (reset_needed) {
@ -713,6 +746,7 @@ void WorldUpdate (void)
fade_state = FADE_IDLE;
fade_current = 0.0f;
start_time = time (NULL);
scene_begin = GetTickCount ();
}
} else {
fade_current = (float)fade_delta / FADE_TIME;
@ -728,8 +762,7 @@ void WorldUpdate (void)
fade_state = FADE_IN;
fade_start = now;
}
elapsed = time (NULL) - start_time;
if (fade_state == FADE_IDLE && elapsed > RESET_INTERVAL)
if (fade_state == FADE_IDLE && WorldSceneElapsed () > RESET_INTERVAL)
WorldReset ();
}

View File

@ -8,6 +8,8 @@ void WorldInit (void);
float WorldFade (void);
void WorldRender ();
void WorldReset (void);
int WorldSceneBegin ();
int WorldSceneElapsed ();
void WorldTerm (void);
void WorldUpdate (void);