Index: ps/trunk/source/ps/GameSetup/Config.cpp
===================================================================
--- ps/trunk/source/ps/GameSetup/Config.cpp (revision 9188)
+++ ps/trunk/source/ps/GameSetup/Config.cpp (revision 9189)
@@ -1,185 +1,183 @@
/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "precompiled.h"
#include "ps/ConfigDB.h"
#include "ps/CConsole.h"
#include "ps/GameSetup/CmdLineArgs.h"
#include "lib/timer.h"
#include "lib/res/sound/snd_mgr.h"
#include "Config.h"
// (these variables are documented in the header.)
CStrW g_CursorName = L"test";
bool g_NoGLS3TC = false;
bool g_NoGLAutoMipmap = false;
bool g_NoGLVBO = false;
-bool g_NoGLFramebufferObject = false;
bool g_Shadows = false;
bool g_FancyWater = false;
float g_LodBias = 0.0f;
float g_Gamma = 1.0f;
bool g_EntGraph = false;
CStr g_RenderPath = "default";
int g_xres, g_yres;
bool g_VSync = false;
bool g_Quickstart = false;
bool g_DisableAudio = false;
// flag to switch on drawing terrain overlays
bool g_ShowPathfindingOverlay = false;
// flag to switch on triangulation pathfinding
bool g_TriPathfind = false;
// If non-empty, specified map will be automatically loaded
CStr g_AutostartMap = "";
//----------------------------------------------------------------------------
// config
//----------------------------------------------------------------------------
// Fill in the globals from the config files.
static void LoadGlobals()
{
CFG_GET_USER_VAL("vsync", Bool, g_VSync);
CFG_GET_USER_VAL("nos3tc", Bool, g_NoGLS3TC);
CFG_GET_USER_VAL("noautomipmap", Bool, g_NoGLAutoMipmap);
CFG_GET_USER_VAL("novbo", Bool, g_NoGLVBO);
- CFG_GET_USER_VAL("noframebufferobject", Bool, g_NoGLFramebufferObject);
CFG_GET_USER_VAL("shadows", Bool, g_Shadows);
CFG_GET_USER_VAL("fancywater", Bool, g_FancyWater);
CFG_GET_USER_VAL("renderpath", String, g_RenderPath);
CFG_GET_USER_VAL("lodbias", Float, g_LodBias);
float gain = -1.0f;
CFG_GET_USER_VAL("sound.mastergain", Float, gain);
if(gain >= 0.0f)
WARN_ERR(snd_set_master_gain(gain));
}
static void ProcessCommandLineArgs(const CmdLineArgs& args)
{
// TODO: all these options (and the ones processed elsewhere) should
// be documented somewhere for users.
if (args.Has("buildarchive"))
{
// note: VFS init is sure to have been completed by now
// (since CONFIG_Init reads from file); therefore,
// it is safe to call this from here directly.
// vfs_opt_rebuild_main_archive("mods/official/official1.zip", "../logs/trace.txt");
}
// Handle "-conf=key:value" (potentially multiple times)
std::vector conf = args.GetMultiple("conf");
for (size_t i = 0; i < conf.size(); ++i)
{
CStr name_value = conf[i];
if (name_value.Find(':') != -1)
{
CStr name = name_value.BeforeFirst(":");
CStr value = name_value.AfterFirst(":");
g_ConfigDB.CreateValue(CFG_COMMAND, name)->m_String = value;
}
}
if (args.Has("entgraph"))
g_EntGraph = true;
if (args.Has("g"))
{
g_Gamma = args.Get("g").ToFloat();
if (g_Gamma == 0.0f)
g_Gamma = 1.0f;
}
// if (args.Has("listfiles"))
// trace_enable(true);
if (args.Has("profile"))
g_ConfigDB.CreateValue(CFG_COMMAND, "profile")->m_String = args.Get("profile");
if (args.Has("quickstart"))
{
g_Quickstart = true;
g_DisableAudio = true; // do this for backward-compatibility with user expectations
}
if (args.Has("nosound"))
g_DisableAudio = true;
if (args.Has("shadows"))
g_ConfigDB.CreateValue(CFG_COMMAND, "shadows")->m_String = "true";
if (args.Has("xres"))
g_ConfigDB.CreateValue(CFG_COMMAND, "xres")->m_String = args.Get("xres");
if (args.Has("yres"))
g_ConfigDB.CreateValue(CFG_COMMAND, "yres")->m_String = args.Get("yres");
if (args.Has("vsync"))
g_ConfigDB.CreateValue(CFG_COMMAND, "vsync")->m_String = "true";
}
void CONFIG_Init(const CmdLineArgs& args)
{
TIMER(L"CONFIG_Init");
new CConfigDB;
// Load the global, default config file
g_ConfigDB.SetConfigFile(CFG_DEFAULT, L"config/default.cfg");
g_ConfigDB.Reload(CFG_DEFAULT); // 216ms
// Try loading the local system config file (which doesn't exist by
// default) - this is designed as a way of letting developers edit the
// system config without accidentally committing their changes back to SVN.
g_ConfigDB.SetConfigFile(CFG_SYSTEM, L"config/local.cfg");
g_ConfigDB.Reload(CFG_SYSTEM);
g_ConfigDB.SetConfigFile(CFG_USER, L"config/user.cfg");
g_ConfigDB.Reload(CFG_USER);
g_ConfigDB.SetConfigFile(CFG_MOD, L"config/mod.cfg");
// No point in reloading mod.cfg here - we haven't mounted mods yet
ProcessCommandLineArgs(args);
// Initialise console history file
int max_history_lines = 200;
CFG_GET_USER_VAL("console.history.size", Int, max_history_lines);
g_Console->UseHistoryFile(L"config/console.txt", max_history_lines);
// Collect information from system.cfg, the profile file,
// and any command-line overrides to fill in the globals.
LoadGlobals(); // 64ms
}
Index: ps/trunk/source/ps/GameSetup/Config.h
===================================================================
--- ps/trunk/source/ps/GameSetup/Config.h (revision 9188)
+++ ps/trunk/source/ps/GameSetup/Config.h (revision 9189)
@@ -1,70 +1,67 @@
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#ifndef INCLUDED_PS_GAMESETUP_CONFIG
#define INCLUDED_PS_GAMESETUP_CONFIG
#include "ps/CStr.h"
//-----------------------------------------------------------------------------
// prevent various OpenGL features from being used. this allows working
// around issues like buggy drivers.
// when loading S3TC-compressed texture files, do not pass them directly to
// OpenGL; instead, decompress them via software to regular textures.
// (necessary on JW's S3 laptop graphics card -- oh, the irony)
extern bool g_NoGLS3TC;
// do not ask OpenGL to create mipmaps; instead, generate them in software
// and upload them all manually. (potentially helpful for PT's system, where
// Mesa falsely reports full S3TC support but isn't able to generate mipmaps
// for them)
extern bool g_NoGLAutoMipmap;
// don't use VBOs. (RC: that was necessary on laptop Radeon cards)
extern bool g_NoGLVBO;
-// disable FBO extension in case the driver is flaky
-extern bool g_NoGLFramebufferObject;
-
//-----------------------------------------------------------------------------
// flag to switch on shadows
extern bool g_Shadows;
// flag to switch on reflective/refractive water
extern bool g_FancyWater;
extern float g_LodBias;
extern float g_Gamma;
extern bool g_EntGraph;
// name of configured render path (depending on OpenGL extensions, this may not be
// the render path that is actually in use right now)
extern CStr g_RenderPath;
extern int g_xres, g_yres;
extern bool g_VSync;
extern bool g_Quickstart;
extern bool g_DisableAudio;
extern CStrW g_CursorName;
class CmdLineArgs;
extern void CONFIG_Init(const CmdLineArgs& args);
#endif // INCLUDED_PS_GAMESETUP_CONFIG
Index: ps/trunk/source/ps/GameSetup/GameSetup.cpp
===================================================================
--- ps/trunk/source/ps/GameSetup/GameSetup.cpp (revision 9188)
+++ ps/trunk/source/ps/GameSetup/GameSetup.cpp (revision 9189)
@@ -1,1100 +1,1099 @@
/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "precompiled.h"
#include "lib/app_hooks.h"
#include "lib/input.h"
#include "lib/lockfree.h"
#include "lib/ogl.h"
#include "lib/timer.h"
#include "lib/external_libraries/sdl.h"
#include "lib/file/common/file_stats.h"
#include "lib/res/h_mgr.h"
#include "lib/res/graphics/cursor.h"
#include "lib/res/sound/snd_mgr.h"
#include "lib/sysdep/cursor.h"
#include "lib/sysdep/cpu.h"
#include "lib/sysdep/gfx.h"
#include "lib/tex/tex.h"
#if OS_WIN
#include "lib/sysdep/os/win/wversion.h"
#endif
#include "ps/CConsole.h"
#include "ps/CLogger.h"
#include "ps/ConfigDB.h"
#include "ps/Filesystem.h"
#include "ps/Font.h"
#include "ps/Game.h"
#include "ps/Globals.h"
#include "ps/Hotkey.h"
#include "ps/Joystick.h"
#include "ps/Loader.h"
#include "ps/Overlay.h"
#include "ps/Profile.h"
#include "ps/ProfileViewer.h"
#include "ps/UserReport.h"
#include "ps/Util.h"
#include "ps/VideoMode.h"
#include "ps/World.h"
#include "graphics/CinemaTrack.h"
#include "graphics/GameView.h"
#include "graphics/LightEnv.h"
#include "graphics/MapReader.h"
#include "graphics/MaterialManager.h"
#include "graphics/TerrainTextureManager.h"
#include "renderer/Renderer.h"
#include "renderer/VertexBufferManager.h"
#include "maths/MathUtil.h"
#include "simulation2/Simulation2.h"
#include "scripting/ScriptingHost.h"
#include "scripting/ScriptGlue.h"
#include "scriptinterface/ScriptInterface.h"
#include "scriptinterface/ScriptStats.h"
#include "maths/scripting/JSInterface_Vector3D.h"
#include "ps/scripting/JSInterface_Console.h"
#include "gui/GUI.h"
#include "gui/GUIManager.h"
#include "gui/scripting/JSInterface_IGUIObject.h"
#include "gui/scripting/JSInterface_GUITypes.h"
#include "gui/scripting/ScriptFunctions.h"
#include "sound/JSI_Sound.h"
#include "network/NetServer.h"
#include "network/NetClient.h"
#include "ps/Pyrogenesis.h" // psSetLogDir
#include "ps/GameSetup/Atlas.h"
#include "ps/GameSetup/GameSetup.h"
#include "ps/GameSetup/Paths.h"
#include "ps/GameSetup/Config.h"
#include "ps/GameSetup/CmdLineArgs.h"
#include "ps/GameSetup/HWDetect.h"
#if !(OS_WIN || OS_MACOSX) // assume all other platforms use X11 for wxWidgets
#define MUST_INIT_X11 1
#include
#else
#define MUST_INIT_X11 0
#endif
#include
ERROR_GROUP(System);
ERROR_TYPE(System, SDLInitFailed);
ERROR_TYPE(System, VmodeFailed);
ERROR_TYPE(System, RequiredExtensionsMissing);
bool g_DoRenderGui = true;
bool g_DoRenderLogger = true;
bool g_DoRenderCursor = true;
static const int SANE_TEX_QUALITY_DEFAULT = 5; // keep in sync with code
static void SetTextureQuality(int quality)
{
int q_flags;
GLint filter;
retry:
// keep this in sync with SANE_TEX_QUALITY_DEFAULT
switch(quality)
{
// worst quality
case 0:
q_flags = OGL_TEX_HALF_RES|OGL_TEX_HALF_BPP;
filter = GL_NEAREST;
break;
// [perf] add bilinear filtering
case 1:
q_flags = OGL_TEX_HALF_RES|OGL_TEX_HALF_BPP;
filter = GL_LINEAR;
break;
// [vmem] no longer reduce resolution
case 2:
q_flags = OGL_TEX_HALF_BPP;
filter = GL_LINEAR;
break;
// [vmem] add mipmaps
case 3:
q_flags = OGL_TEX_HALF_BPP;
filter = GL_NEAREST_MIPMAP_LINEAR;
break;
// [perf] better filtering
case 4:
q_flags = OGL_TEX_HALF_BPP;
filter = GL_LINEAR_MIPMAP_LINEAR;
break;
// [vmem] no longer reduce bpp
case SANE_TEX_QUALITY_DEFAULT:
q_flags = OGL_TEX_FULL_QUALITY;
filter = GL_LINEAR_MIPMAP_LINEAR;
break;
// [perf] add anisotropy
case 6:
// TODO: add anisotropic filtering
q_flags = OGL_TEX_FULL_QUALITY;
filter = GL_LINEAR_MIPMAP_LINEAR;
break;
// invalid
default:
debug_warn(L"SetTextureQuality: invalid quality");
quality = SANE_TEX_QUALITY_DEFAULT;
// careful: recursion doesn't work and we don't want to duplicate
// the "sane" default values.
goto retry;
}
ogl_tex_set_defaults(q_flags, filter);
}
//----------------------------------------------------------------------------
// GUI integration
//----------------------------------------------------------------------------
// display progress / description in loading screen
void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task)
{
g_ScriptingHost.GetScriptInterface().SetGlobal("g_Progress", percent, true);
g_ScriptingHost.GetScriptInterface().SetGlobal("g_LoadDescription", pending_task, true);
g_GUI->SendEventToAll("progress");
}
void Render()
{
ogl_WarnIfError();
CStr skystring = "255 0 255";
CFG_GET_USER_VAL("skycolor", String, skystring);
CColor skycol;
GUI::ParseString(skystring.FromUTF8(), skycol);
g_Renderer.SetClearColor(skycol.AsSColor4ub());
// prepare before starting the renderer frame
if (g_Game && g_Game->IsGameStarted())
g_Game->GetView()->BeginFrame();
// start new frame
g_Renderer.BeginFrame();
ogl_WarnIfError();
if (g_Game && g_Game->IsGameStarted())
g_Game->GetView()->Render();
ogl_WarnIfError();
// set up overlay mode
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
glDisable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.f, (float)g_xres, 0.f, (float)g_yres, -1.f, 1000.f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
ogl_WarnIfError();
g_Renderer.RenderTextOverlays();
// Temp GUI message GeeTODO
PROFILE_START("render gui");
if(g_DoRenderGui) g_GUI->Draw();
PROFILE_END("render gui");
ogl_WarnIfError();
// Text:
// Use the GL_ALPHA texture as the alpha channel with a flat colouring
glDisable(GL_ALPHA_TEST);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// Added --
glEnable(GL_TEXTURE_2D);
// -- GL
glLoadIdentity();
PROFILE_START("render console");
g_Console->Render();
PROFILE_END("render console");
ogl_WarnIfError();
PROFILE_START("render logger");
if(g_DoRenderLogger) g_Logger->Render();
PROFILE_END("render logger");
ogl_WarnIfError();
// Profile information
PROFILE_START("render profiling");
g_ProfileViewer.RenderProfile();
PROFILE_END("render profiling");
ogl_WarnIfError();
// Draw the cursor (or set the Windows cursor, on Windows)
if (g_DoRenderCursor)
{
PROFILE("render cursor");
CStrW cursorName = g_CursorName;
if (cursorName.empty())
{
cursor_draw(g_VFS, NULL, g_mouse_x, g_yres-g_mouse_y);
}
else
{
if (cursor_draw(g_VFS, cursorName.c_str(), g_mouse_x, g_yres-g_mouse_y) < 0)
LOGWARNING(L"Failed to draw cursor '%ls'", cursorName.c_str());
}
}
// restore
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
g_Renderer.EndFrame();
ogl_WarnIfError();
}
static void RegisterJavascriptInterfaces()
{
// maths
JSI_Vector3D::init();
// graphics
CGameView::ScriptingInit();
// renderer
CRenderer::ScriptingInit();
// sound
JSI_Sound::ScriptingInit();
// ps
JSI_Console::init();
// GUI
CGUI::ScriptingInit();
GuiScriptingInit(g_ScriptingHost.GetScriptInterface());
}
static void InitScripting()
{
TIMER(L"InitScripting");
// Create the scripting host. This needs to be done before the GUI is created.
// [7ms]
new ScriptingHost;
RegisterJavascriptInterfaces();
}
#if 0
// disabled because the file cache doesn't work (http://trac.wildfiregames.com/ticket/611)
static size_t OperatingSystemFootprint()
{
#if OS_WIN
switch(wversion_Number())
{
case WVERSION_2K:
case WVERSION_XP:
return 150;
case WVERSION_XP64:
return 200;
default: // don't warn about newer Windows versions
case WVERSION_VISTA:
return 300;
case WVERSION_7:
return 250;
}
#else
return 200;
#endif
}
static size_t ChooseCacheSize()
{
// (all sizes in MiB)
const size_t total = os_cpu_MemorySize();
const size_t available = os_cpu_MemoryAvailable();
debug_assert(total >= available);
const size_t inUse = total-available;
size_t os = OperatingSystemFootprint();
debug_assert(total >= os/2);
size_t apps = (inUse > os)? (inUse - os) : 0;
size_t game = 300;
size_t cache = 200;
// plenty of memory
if(os + apps + game + cache < total)
{
cache = total - os - apps - game;
}
else // below min-spec
{
// assume kernel+other apps will be swapped out
os = 9*os/10;
apps = 2*apps/3;
game = 3*game/4;
if(os + apps + game + cache < total)
cache = total - os - apps - game;
else
{
cache = 50;
debug_printf(L"Warning: memory size (%d MiB, %d used) is rather low\n", total, available);
}
}
// total data is currently about 500 MiB, and not all of it
// is used at once, so don't use more than that.
// (this also ensures the byte count will fit in size_t and
// avoids using up too much address space)
cache = std::min(cache, (size_t)500);
debug_printf(L"Cache: %d (total: %d; available: %d)\n", cache, total, available);
return cache*MiB;
}
#else
static size_t ChooseCacheSize()
{
return 32*MiB;
}
#endif
ErrorReactionInternal psDisplayError(const wchar_t* UNUSED(text), size_t UNUSED(flags))
{
// If we're fullscreen, then sometimes (at least on some particular drivers on Linux)
// displaying the error dialog hangs the desktop since the dialog box is behind the
// fullscreen window. So we just force the game to windowed mode before displaying the dialog.
// (But only if we're in the main thread, and not if we're being reentrant.)
if (ThreadUtil::IsMainThread())
{
static bool reentering = false;
if (!reentering)
{
reentering = true;
g_VideoMode.SetFullscreen(false);
reentering = false;
}
}
// We don't actually implement the error display here, so return appropriately
return ERI_NOT_IMPLEMENTED;
}
static void InitVfs(const CmdLineArgs& args)
{
TIMER(L"InitVfs");
const Paths paths(args);
OsPath logs(paths.Logs());
CreateDirectories(logs, 0700);
psSetLogDir(logs);
// desired location for crashlog is now known. update AppHooks ASAP
// (particularly before the following error-prone operations):
AppHooks hooks = {0};
hooks.bundle_logs = psBundleLogs;
hooks.get_log_dir = psLogDir;
hooks.display_error = psDisplayError;
app_hooks_update(&hooks);
const size_t cacheSize = ChooseCacheSize();
g_VFS = CreateVfs(cacheSize);
g_VFS->Mount(L"screenshots/", paths.Data()/"screenshots/");
const OsPath readonlyConfig = paths.RData()/"config/";
g_VFS->Mount(L"config/", readonlyConfig);
if(readonlyConfig != paths.Config())
g_VFS->Mount(L"config/", paths.Config());
g_VFS->Mount(L"cache/", paths.Cache(), VFS_MOUNT_ARCHIVABLE); // (adding XMBs to archive speeds up subsequent reads)
std::vector mods = args.GetMultiple("mod");
mods.push_back("public");
if(!args.Has("onlyPublicFiles"))
mods.push_back("internal");
OsPath modArchivePath = paths.Cache()/"mods";
OsPath modLoosePath = paths.RData()/"mods";
for (size_t i = 0; i < mods.size(); ++i)
{
size_t priority = i;
size_t flags = VFS_MOUNT_WATCH|VFS_MOUNT_ARCHIVABLE|VFS_MOUNT_MUST_EXIST;
OsPath modName(mods[i]);
g_VFS->Mount(L"", modLoosePath / modName/"", flags, priority);
g_VFS->Mount(L"", modArchivePath / modName/"", flags, priority);
}
// note: don't bother with g_VFS->TextRepresentation - directories
// haven't yet been populated and are empty.
}
static void InitPs(bool setup_gui, const CStrW& gui_page, CScriptVal initData)
{
{
// console
TIMER(L"ps_console");
g_Console->UpdateScreenSize(g_xres, g_yres);
// Calculate and store the line spacing
CFont font(CONSOLE_FONT);
g_Console->m_iFontHeight = font.GetLineSpacing();
g_Console->m_iFontWidth = font.GetCharacterWidth(L'C');
g_Console->m_charsPerPage = (size_t)(g_xres / g_Console->m_iFontWidth);
// Offset by an arbitrary amount, to make it fit more nicely
g_Console->m_iFontOffset = 7;
}
// hotkeys
{
TIMER(L"ps_lang_hotkeys");
LoadHotkeys();
}
if (!setup_gui)
{
// We do actually need *some* kind of GUI loaded, so use the
// (currently empty) Atlas one
g_GUI->SwitchPage(L"page_atlas.xml", initData);
return;
}
// GUI uses VFS, so this must come after VFS init.
g_GUI->SwitchPage(gui_page, initData);
}
static void InitInput()
{
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
g_Joystick.Initialise();
// register input handlers
// This stack is constructed so the first added, will be the last
// one called. This is important, because each of the handlers
// has the potential to block events to go further down
// in the chain. I.e. the last one in the list added, is the
// only handler that can block all messages before they are
// processed.
in_add_handler(game_view_handler);
in_add_handler(CProfileViewer::InputThunk);
in_add_handler(conInputHandler);
in_add_handler(HotkeyInputHandler);
// gui_handler needs to be registered after (i.e. called before!) the
// hotkey handler so that input boxes can be typed in without
// setting off hotkeys.
in_add_handler(gui_handler);
// must be registered after (called before) the GUI which relies on these globals
in_add_handler(GlobalsInputHandler);
}
static void ShutdownPs()
{
SAFE_DELETE(g_GUI);
SAFE_DELETE(g_Console);
// disable the special Windows cursor, or free textures for OGL cursors
cursor_draw(g_VFS, 0, g_mouse_x, g_yres-g_mouse_y);
}
static void InitRenderer()
{
TIMER(L"InitRenderer");
if(g_NoGLS3TC)
ogl_tex_override(OGL_TEX_S3TC, OGL_TEX_DISABLE);
if(g_NoGLAutoMipmap)
ogl_tex_override(OGL_TEX_AUTO_MIPMAP_GEN, OGL_TEX_DISABLE);
// create renderer
new CRenderer;
// set renderer options from command line options - NOVBO must be set before opening the renderer
g_Renderer.SetOptionBool(CRenderer::OPT_NOVBO,g_NoGLVBO);
- g_Renderer.SetOptionBool(CRenderer::OPT_NOFRAMEBUFFEROBJECT,g_NoGLFramebufferObject);
g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWS,g_Shadows);
g_Renderer.SetOptionBool(CRenderer::OPT_FANCYWATER,g_FancyWater);
g_Renderer.SetRenderPath(CRenderer::GetRenderPathByName(g_RenderPath));
g_Renderer.SetOptionFloat(CRenderer::OPT_LODBIAS, g_LodBias);
// create terrain related stuff
new CTerrainTextureManager;
// create the material manager
new CMaterialManager;
g_Renderer.Open(g_xres,g_yres);
// Setup lighting environment. Since the Renderer accesses the
// lighting environment through a pointer, this has to be done before
// the first Frame.
g_Renderer.SetLightEnv(&g_LightEnv);
// I haven't seen the camera affecting GUI rendering and such, but the
// viewport has to be updated according to the video mode
SViewPort vp;
vp.m_X=0;
vp.m_Y=0;
vp.m_Width=g_xres;
vp.m_Height=g_yres;
g_Renderer.SetViewport(vp);
ColorActivateFastImpl();
}
static void InitSDL()
{
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE) < 0)
{
LOGERROR(L"SDL library initialization failed: %hs", SDL_GetError());
throw PSERROR_System_SDLInitFailed();
}
atexit(SDL_Quit);
SDL_EnableUNICODE(1);
}
static void ShutdownSDL()
{
SDL_Quit();
sys_cursor_reset();
}
void EndGame()
{
SAFE_DELETE(g_NetServer);
SAFE_DELETE(g_NetClient);
SAFE_DELETE(g_Game);
}
void Shutdown(int UNUSED(flags))
{
EndGame();
ShutdownPs(); // Must delete g_GUI before g_ScriptingHost
in_reset_handlers();
// destroy actor related stuff
TIMER_BEGIN(L"shutdown actor stuff");
delete &g_MaterialManager;
TIMER_END(L"shutdown actor stuff");
// destroy terrain related stuff
TIMER_BEGIN(L"shutdown TexMan");
delete &g_TexMan;
TIMER_END(L"shutdown TexMan");
// destroy renderer
TIMER_BEGIN(L"shutdown Renderer");
delete &g_Renderer;
g_VBMan.Shutdown();
TIMER_END(L"shutdown Renderer");
tex_codec_unregister_all();
TIMER_BEGIN(L"shutdown SDL");
ShutdownSDL();
TIMER_END(L"shutdown SDL");
g_VideoMode.Shutdown();
TIMER_BEGIN(L"shutdown UserReporter");
g_UserReporter.Deinitialize();
TIMER_END(L"shutdown UserReporter");
TIMER_BEGIN(L"shutdown ScriptingHost");
delete &g_ScriptingHost;
TIMER_END(L"shutdown ScriptingHost");
TIMER_BEGIN(L"shutdown ConfigDB");
delete &g_ConfigDB;
TIMER_END(L"shutdown ConfigDB");
// resource
// first shut down all resource owners, and then the handle manager.
TIMER_BEGIN(L"resource modules");
snd_shutdown();
g_VFS.reset();
// this forcibly frees all open handles (thus preventing real leaks),
// and makes further access to h_mgr impossible.
h_mgr_shutdown();
file_stats_dump();
TIMER_END(L"resource modules");
TIMER_BEGIN(L"shutdown misc");
timer_DisplayClientTotals();
CNetHost::Deinitialize();
SAFE_DELETE(g_ScriptStatsTable);
// should be last, since the above use them
SAFE_DELETE(g_Logger);
delete &g_Profiler;
delete &g_ProfileViewer;
TIMER_END(L"shutdown misc");
}
#if OS_UNIX
void SetDefaultIfLocaleInvalid()
{
// On misconfigured systems with incorrect locale settings, we'll die
// with a C++ exception when some code tries to use locales.
// To avoid death, we'll detect the problem here and warn the user and
// reset to the default C locale.
// For informing the user of the problem, use the list of env vars that
// glibc setlocale looks at. (LC_ALL is checked first, and LANG last.)
const char* const LocaleEnvVars[] = {
"LC_ALL",
"LC_COLLATE",
"LC_CTYPE",
"LC_MONETARY",
"LC_NUMERIC",
"LC_TIME",
"LC_MESSAGES",
"LANG"
};
try
{
// this constructor is similar to setlocale(LC_ALL, ""),
// but instead of returning NULL, it throws runtime_error
// when the first locale env variable found contains an invalid value
std::locale("");
}
catch (std::runtime_error&)
{
LOGWARNING(L"Invalid locale settings");
for (size_t i = 0; i < ARRAY_SIZE(LocaleEnvVars); i++)
{
if (char* envval = getenv(LocaleEnvVars[i]))
LOGWARNING(L" %hs=\"%hs\"", LocaleEnvVars[i], envval);
else
LOGWARNING(L" %hs=\"(unset)\"", LocaleEnvVars[i]);
}
// We should set LC_ALL since it overrides LANG
if (setenv("LC_ALL", std::locale::classic().name().c_str(), 1))
debug_warn(L"Invalid locale settings, and unable to set LC_ALL env variable.");
else
LOGWARNING(L"Setting LC_ALL env variable to: %hs", getenv("LC_ALL"));
}
}
#else
void SetDefaultIfLocaleInvalid()
{
// Do nothing on Windows
}
#endif
void EarlyInit()
{
// If you ever want to catch a particular allocation:
//_CrtSetBreakAlloc(232647);
ThreadUtil::SetMainThread();
debug_SetThreadName("main");
// add all debug_printf "tags" that we are interested in:
debug_filter_add(L"TIMER");
debug_filter_add(L"HRT");
cpu_ConfigureFloatingPoint();
timer_LatchStartTime();
SetDefaultIfLocaleInvalid();
// Because we do GL calls from a secondary thread, Xlib needs to
// be told to support multiple threads safely.
// This is needed for Atlas, but we have to call it before any other
// Xlib functions (e.g. the ones used when drawing the main menu
// before launching Atlas)
#if MUST_INIT_X11
int status = XInitThreads();
if (status == 0)
debug_printf(L"Error enabling thread-safety via XInitThreads\n");
#endif
// Initialise the low-quality rand function
srand(time(NULL)); // NOTE: this rand should *not* be used for simulation!
}
static bool Autostart(const CmdLineArgs& args);
void Init(const CmdLineArgs& args, int UNUSED(flags))
{
h_mgr_init();
// Do this as soon as possible, because it chdirs
// and will mess up the error reporting if anything
// crashes before the working directory is set.
InitVfs(args);
// This must come after VFS init, which sets the current directory
// (required for finding our output log files).
g_Logger = new CLogger;
// Special command-line mode to dump the entity schemas instead of running the game.
// (This must be done after loading VFS etc, but should be done before wasting time
// on anything else.)
if (args.Has("dumpSchema"))
{
CSimulation2 sim(NULL, NULL);
sim.LoadDefaultScripts();
std::ofstream f("entity.rng", std::ios_base::out | std::ios_base::trunc);
f << sim.GenerateSchema();
std::cout << "Generated entity.rng\n";
exit(0);
}
// override ah_translate with our i18n code.
AppHooks hooks = {0};
hooks.translate = psTranslate;
hooks.translate_free = psTranslateFree;
app_hooks_update(&hooks);
// Set up the console early, so that debugging
// messages can be logged to it. (The console's size
// and fonts are set later in InitPs())
g_Console = new CConsole();
CNetHost::Initialize();
new CProfileViewer;
new CProfileManager; // before any script code
g_ScriptStatsTable = new CScriptStatsTable;
g_ProfileViewer.AddRootTable(g_ScriptStatsTable);
InitScripting(); // before GUI
// g_ConfigDB, command line args, globals
CONFIG_Init(args);
if (!g_Quickstart)
g_UserReporter.Initialize(); // after config
}
void InitGraphics(const CmdLineArgs& args, int flags)
{
const bool setup_vmode = (flags & INIT_HAVE_VMODE) == 0;
if(setup_vmode)
{
InitSDL();
if (!g_VideoMode.InitSDL())
throw PSERROR_System_VmodeFailed(); // abort startup
SDL_WM_SetCaption("0 A.D.", "0 A.D.");
}
// needed by ogl_tex to detect broken gfx card/driver combos,
// but takes a while due to WMI startup, so make it optional.
if(!g_Quickstart)
gfx_detect();
RunHardwareDetection();
tex_codec_register_all();
const int quality = SANE_TEX_QUALITY_DEFAULT; // TODO: set value from config file
SetTextureQuality(quality);
ogl_WarnIfError();
if(!g_Quickstart)
{
WriteSystemInfo();
// note: no longer vfs_display here. it's dog-slow due to unbuffered
// file output and very rarely needed.
}
if(g_DisableAudio)
{
// speed up startup by disabling all sound
// (OpenAL init will be skipped).
// must be called before first snd_open.
snd_disable(true);
}
g_GUI = new CGUIManager(g_ScriptingHost.GetScriptInterface());
// (must come after SetVideoMode, since it calls ogl_Init)
const char* missing = ogl_HaveExtensions(0,
"GL_ARB_multitexture",
"GL_EXT_draw_range_elements",
"GL_ARB_texture_env_combine",
"GL_ARB_texture_env_dot3",
NULL);
if(missing)
{
wchar_t buf[500];
swprintf_s(buf, ARRAY_SIZE(buf),
L"The %hs extension doesn't appear to be available on your computer."
L" The game may still work, though - you are welcome to try at your own risk."
L" If not or it doesn't look right, upgrade your graphics card.",
missing
);
DEBUG_DISPLAY_ERROR(buf);
// TODO: i18n
}
if (!ogl_HaveExtension("GL_ARB_texture_env_crossbar"))
{
DEBUG_DISPLAY_ERROR(
L"The GL_ARB_texture_env_crossbar extension doesn't appear to be available on your computer."
L" Shadows are not available and overall graphics quality might suffer."
L" You are advised to try installing newer drivers and/or upgrade your graphics card.");
g_Shadows = false;
}
ogl_WarnIfError();
InitRenderer();
InitInput();
ogl_WarnIfError();
if (!Autostart(args))
{
const bool setup_gui = ((flags & INIT_NO_GUI) == 0);
InitPs(setup_gui, L"page_pregame.xml", JSVAL_VOID);
}
}
void RenderGui(bool RenderingState)
{
g_DoRenderGui = RenderingState;
}
void RenderLogger(bool RenderingState)
{
g_DoRenderLogger = RenderingState;
}
void RenderCursor(bool RenderingState)
{
g_DoRenderCursor = RenderingState;
}
static bool Autostart(const CmdLineArgs& args)
{
/*
* Handle various command-line options, for quick testing of various features:
* -autostart=mapname -- single-player
* -autostart=mapname -autostart-playername=Player -autostart-host -autostart-players=2 -- multiplayer host, wait for 2 players
* -autostart=mapname -autostart-playername=Player -autostart-client -autostart-ip=127.0.0.1 -- multiplayer client, connect to 127.0.0.1
* -autostart=scriptname -autostart-random=104 -- random map, seed 104 (default is 0, for random choose -1)
*/
CStr autoStartName = args.Get("autostart");
if (autoStartName.empty())
return false;
g_Game = new CGame();
ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface();
CScriptValRooted attrs;
scriptInterface.Eval("({})", attrs);
CScriptVal settings;
scriptInterface.Eval("({})", settings);
CScriptVal playerData;
scriptInterface.Eval("([])", playerData);
// Set different attributes for random or scenario game
if (args.Has("autostart-random"))
{
CStr seedArg = args.Get("autostart-random");
// Default seed is 0
uint32 seed = 0;
if (!seedArg.empty())
{
if (seedArg.compare("-1") == 0)
{ // Random seed value
seed = rand();
}
else
{
seed = seedArg.ToULong();
}
}
scriptInterface.SetProperty(attrs.get(), "script", std::string(autoStartName), false); // RMS name
scriptInterface.SetProperty(attrs.get(), "mapType", std::string("random"), false);
// For random map, there are special settings
// TODO: Get these from command line - using defaults for now
scriptInterface.SetProperty(settings.get(), "Size", 12); // Random map size (in patches)
scriptInterface.SetProperty(settings.get(), "Seed", seed); // Random seed
scriptInterface.SetProperty(settings.get(), "BaseTerrain", std::string("grass1_spring")); // Base terrain texture
scriptInterface.SetProperty(settings.get(), "BaseHeight", 0); // Base terrain height
// Define players
// TODO: Get these from command line? - using defaults for now
size_t numPlayers = 2;
for (size_t i = 0; i < numPlayers; ++i)
{
CScriptVal player;
scriptInterface.Eval("({})", player);
scriptInterface.SetProperty(player.get(), "Civ", std::string("hele"));
scriptInterface.SetPropertyInt(playerData.get(), i, player);
}
}
else
{
scriptInterface.SetProperty(attrs.get(), "map", std::string(autoStartName), false);
scriptInterface.SetProperty(attrs.get(), "mapType", std::string("scenario"), false);
}
// Set player data for AIs
// attrs.settings = { PlayerData: [ { AI: ... }, ... ] }:
/*
* Handle command-line options for AI:
* -autostart-ai=1:dummybot -autostart-ai=2:dummybot -- adds the dummybot AI to players 1 and 2
*/
if (args.Has("autostart-ai"))
{
std::vector aiArgs = args.GetMultiple("autostart-ai");
for (size_t i = 0; i < aiArgs.size(); ++i)
{
CScriptVal player;
scriptInterface.Eval("({})", player);
int playerID = aiArgs[i].BeforeFirst(":").ToInt();
CStr name = aiArgs[i].AfterFirst(":");
scriptInterface.SetProperty(player.get(), "AI", std::string(name));
scriptInterface.SetPropertyInt(playerData.get(), playerID-1, player);
}
}
// Add player data to map settings
scriptInterface.SetProperty(settings.get(), "PlayerData", playerData);
// Add map settings to game attributes
scriptInterface.SetProperty(attrs.get(), "settings", settings);
CScriptVal mpInitData;
g_GUI->GetScriptInterface().Eval("({isNetworked:true, playerAssignments:{}})", mpInitData);
g_GUI->GetScriptInterface().SetProperty(mpInitData.get(), "attribs",
CScriptVal(g_GUI->GetScriptInterface().CloneValueFromOtherContext(scriptInterface, attrs.get())), false);
if (args.Has("autostart-host"))
{
InitPs(true, L"page_loading.xml", mpInitData.get());
size_t maxPlayers = 2;
if (args.Has("autostart-players"))
maxPlayers = args.Get("autostart-players").ToUInt();
g_NetServer = new CNetServer(maxPlayers);
g_NetServer->UpdateGameAttributes(attrs.get(), scriptInterface);
bool ok = g_NetServer->SetupConnection();
debug_assert(ok);
g_NetClient = new CNetClient(g_Game);
// TODO: player name, etc
g_NetClient->SetupConnection("127.0.0.1");
}
else if (args.Has("autostart-client"))
{
InitPs(true, L"page_loading.xml", mpInitData.get());
g_NetClient = new CNetClient(g_Game);
// TODO: player name, etc
CStr ip = "127.0.0.1";
if (args.Has("autostart-ip"))
ip = args.Get("autostart-ip");
bool ok = g_NetClient->SetupConnection(ip);
debug_assert(ok);
}
else
{
g_Game->SetPlayerID(1);
g_Game->StartGame(attrs);
LDR_NonprogressiveLoad();
PSRETURN ret = g_Game->ReallyStartGame();
debug_assert(ret == PSRETURN_OK);
InitPs(true, L"page_session.xml", JSVAL_VOID);
}
return true;
}
Index: ps/trunk/source/renderer/Renderer.h
===================================================================
--- ps/trunk/source/renderer/Renderer.h (revision 9188)
+++ ps/trunk/source/renderer/Renderer.h (revision 9189)
@@ -1,493 +1,489 @@
/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
/*
* higher level interface on top of OpenGL to render basic objects:
* terrain, models, sprites, particles etc.
*/
#ifndef INCLUDED_RENDERER
#define INCLUDED_RENDERER
#include "graphics/Camera.h"
#include "graphics/SColor.h"
#include "graphics/ShaderProgram.h"
#include "lib/ogl.h"
#include "lib/res/handle.h"
#include "ps/Singleton.h"
#include "scripting/ScriptableObject.h"
#include "renderer/Scene.h"
// necessary declarations
class CPatch;
class CMaterial;
class CModel;
class CLightEnv;
class RenderPathVertexShader;
class WaterManager;
class SkyManager;
class CTextureManager;
class CShaderManager;
class CParticleManager;
// rendering modes
enum ERenderMode { WIREFRAME, SOLID, EDGED_FACES };
// stream flags
#define STREAM_POS (1 << 0)
#define STREAM_NORMAL (1 << 1)
#define STREAM_COLOR (1 << 2)
#define STREAM_UV0 (1 << 3)
#define STREAM_UV1 (1 << 4)
#define STREAM_UV2 (1 << 5)
#define STREAM_UV3 (1 << 6)
#define STREAM_POSTOUV0 (1 << 7)
#define STREAM_POSTOUV1 (1 << 8)
#define STREAM_POSTOUV2 (1 << 9)
#define STREAM_POSTOUV3 (1 << 10)
#define STREAM_TEXGENTOUV1 (1 << 11)
// access to sole renderer object
#define g_Renderer CRenderer::GetSingleton()
///////////////////////////////////////////////////////////////////////////////////////////
// CRenderer: base renderer class - primary interface to the rendering engine
struct CRendererInternals;
class CRenderer :
public Singleton,
public CJSObject,
private SceneCollector
{
public:
// various enumerations and renderer related constants
enum { NumAlphaMaps=14 };
enum Option {
OPT_NOVBO,
- OPT_NOFRAMEBUFFEROBJECT,
OPT_SHADOWS,
OPT_FANCYWATER,
OPT_LODBIAS
};
enum RenderPath {
// If no rendering path is configured explicitly, the renderer
// will choose the path when Open() is called.
RP_DEFAULT,
// Classic fixed function.
RP_FIXED,
// Use new ARB/GLSL system
RP_SHADER
};
// stats class - per frame counts of number of draw calls, poly counts etc
struct Stats {
// set all stats to zero
void Reset() { memset(this,0,sizeof(*this)); }
// add given stats to this stats
Stats& operator+=(const Stats& rhs) {
m_Counter++;
m_DrawCalls+=rhs.m_DrawCalls;
m_TerrainTris+=rhs.m_TerrainTris;
m_ModelTris+=rhs.m_ModelTris;
m_BlendSplats+=rhs.m_BlendSplats;
return *this;
}
// count of the number of stats added together
size_t m_Counter;
// number of draw calls per frame - total DrawElements + Begin/End immediate mode loops
size_t m_DrawCalls;
// number of terrain triangles drawn
size_t m_TerrainTris;
// number of (non-transparent) model triangles drawn
size_t m_ModelTris;
// number of splat passes for alphamapping
size_t m_BlendSplats;
};
// renderer options
struct Options {
bool m_NoVBO;
- bool m_NoFramebufferObject;
bool m_Shadows;
bool m_FancyWater;
float m_LodBias;
RenderPath m_RenderPath;
bool m_ShadowAlphaFix;
bool m_ARBProgramShadow;
} m_Options;
struct Caps {
bool m_VBO;
bool m_ARBProgram;
bool m_ARBProgramShadow;
bool m_VertexShader;
bool m_FragmentShader;
bool m_Shadows;
- bool m_DepthTextureShadows;
- bool m_FramebufferObject;
};
public:
// constructor, destructor
CRenderer();
~CRenderer();
// open up the renderer: performs any necessary initialisation
bool Open(int width,int height);
// resize renderer view
void Resize(int width,int height);
// set/get boolean renderer option
void SetOptionBool(enum Option opt,bool value);
bool GetOptionBool(enum Option opt) const;
void SetOptionFloat(enum Option opt, float val);
void SetRenderPath(RenderPath rp);
RenderPath GetRenderPath() const { return m_Options.m_RenderPath; }
static CStr GetRenderPathName(RenderPath rp);
static RenderPath GetRenderPathByName(const CStr& name);
// return view width
int GetWidth() const { return m_Width; }
// return view height
int GetHeight() const { return m_Height; }
// return view aspect ratio
float GetAspect() const { return float(m_Width)/float(m_Height); }
// signal frame start
void BeginFrame();
// signal frame end
void EndFrame();
// set color used to clear screen in BeginFrame()
void SetClearColor(SColor4ub color);
// trigger a reload of shaders (when parameters they depend on have changed)
void MakeShadersDirty();
/**
* Set up the camera used for rendering the next scene; this includes
* setting OpenGL state like viewport, projection and modelview matrices.
*
* @param viewCamera this camera determines the eye position for rendering
* @param cullCamera this camera determines the frustum for culling in the renderer and
* for shadow calculations
*/
void SetSceneCamera(const CCamera& viewCamera, const CCamera& cullCamera);
// set the viewport
void SetViewport(const SViewPort &);
/**
* Render the given scene immediately.
* @param scene a Scene object describing what should be rendered.
*/
void RenderScene(Scene& scene);
/**
* Return the scene that is currently being rendered.
* Only valid when the renderer is in a RenderScene call.
*/
Scene& GetScene();
/**
* Render text overlays on top of the scene.
* Assumes the caller has set up the GL environment for orthographic rendering
* with texturing and blending.
*/
void RenderTextOverlays();
// set the current lighting environment; (note: the passed pointer is just copied to a variable within the renderer,
// so the lightenv passed must be scoped such that it is not destructed until after the renderer is no longer rendering)
void SetLightEnv(CLightEnv* lightenv) {
m_LightEnv=lightenv;
}
// set the mode to render subsequent terrain patches
void SetTerrainRenderMode(ERenderMode mode) { m_TerrainRenderMode=mode; }
// get the mode to render subsequent terrain patches
ERenderMode GetTerrainRenderMode() const { return m_TerrainRenderMode; }
// set the mode to render subsequent models
void SetModelRenderMode(ERenderMode mode) { m_ModelRenderMode=mode; }
// get the mode to render subsequent models
ERenderMode GetModelRenderMode() const { return m_ModelRenderMode; }
// debugging
void SetDisplayTerrainPriorities(bool enabled) { m_DisplayTerrainPriorities = enabled; }
// bind a GL texture object to active unit
void BindTexture(int unit,GLuint tex);
// load the default set of alphamaps.
// return a negative error code if anything along the way fails.
// called via delay-load mechanism.
int LoadAlphaMaps();
void UnloadAlphaMaps();
// return stats accumulated for current frame
const Stats& GetStats() { return m_Stats; }
// return the current light environment
const CLightEnv &GetLightEnv() { return *m_LightEnv; }
// return the current view camera
const CCamera& GetViewCamera() const { return m_ViewCamera; }
// return the current cull camera
const CCamera& GetCullCamera() const { return m_CullCamera; }
// get the current OpenGL model-view-projection matrix into the given float[]
CMatrix3D GetModelViewProjectionMatrix();
/**
* GetWaterManager: Return the renderer's water manager.
*
* @return the WaterManager object used by the renderer
*/
WaterManager* GetWaterManager() { return m_WaterManager; }
/**
* GetSkyManager: Return the renderer's sky manager.
*
* @return the SkyManager object used by the renderer
*/
SkyManager* GetSkyManager() { return m_SkyManager; }
CTextureManager& GetTextureManager();
CShaderManager& GetShaderManager();
CParticleManager& GetParticleManager();
/**
* SetFastPlayerColor: Tell the renderer which path to take for
* player colored models. Both paths should provide the same visual
* quality, however the slow path runs on older hardware using multi-pass.
*
* @param fast true if the fast path should be used from now on. If fast
* is true but the OpenGL implementation does not support it, a warning
* is printed and the slow path is used instead.
*/
void SetFastPlayerColor(bool fast);
/**
* GetCapabilities: Return which OpenGL capabilities are available and enabled.
*
* @return capabilities structure
*/
const Caps& GetCapabilities() const { return m_Caps; }
bool GetDisableCopyShadow() const { return m_DisableCopyShadow; }
static void ScriptingInit();
protected:
friend struct CRendererInternals;
friend class CVertexBuffer;
friend class CPatchRData;
friend class CDecalRData;
friend class FixedFunctionModelRenderer;
friend class ModelRenderer;
friend class PolygonSortModelRenderer;
friend class SortModelRenderer;
friend class RenderPathVertexShader;
friend class HWLightingModelRenderer;
friend class ShaderModelRenderer;
friend class InstancingModelRenderer;
friend class ShaderInstancingModelRenderer;
friend class TerrainRenderer;
// scripting
// TODO: Perhaps we could have a version of AddLocalProperty for function-driven
// properties? Then we could hide these function in the private implementation class.
jsval JSI_GetFastPlayerColor(JSContext*);
void JSI_SetFastPlayerColor(JSContext* ctx, jsval newval);
jsval JSI_GetRenderPath(JSContext*);
void JSI_SetRenderPath(JSContext* ctx, jsval newval);
jsval JSI_GetDepthTextureBits(JSContext*);
void JSI_SetDepthTextureBits(JSContext* ctx, jsval newval);
jsval JSI_GetShadows(JSContext*);
void JSI_SetShadows(JSContext* ctx, jsval newval);
jsval JSI_GetShadowAlphaFix(JSContext*);
void JSI_SetShadowAlphaFix(JSContext* ctx, jsval newval);
jsval JSI_GetSky(JSContext*);
void JSI_SetSky(JSContext* ctx, jsval newval);
//BEGIN: Implementation of SceneCollector
void Submit(CPatch* patch);
void Submit(SOverlayLine* overlay);
void Submit(SOverlaySprite* overlay);
void Submit(CModelDecal* decal);
void Submit(CParticleEmitter* emitter);
void SubmitNonRecursive(CModel* model);
//END: Implementation of SceneCollector
// render any batched objects
void RenderSubmissions();
// patch rendering stuff
void RenderPatches();
// model rendering stuff
void RenderModels();
void RenderTransparentModels();
void RenderSilhouettes();
void RenderParticles();
// shadow rendering stuff
void RenderShadowMap();
// render water reflection and refraction textures
void RenderReflections();
void RenderRefractions();
// debugging
void DisplayFrustum();
// enable oblique frustum clipping with the given clip plane
void SetObliqueFrustumClipping(const CVector4D& clipPlane, int sign);
void ReloadShaders();
// hotloading
static LibError ReloadChangedFileCB(void* param, const VfsPath& path);
// RENDERER DATA:
/// Private data that is not needed by inline functions
CRendererInternals* m;
// view width
int m_Width;
// view height
int m_Height;
// current terrain rendering mode
ERenderMode m_TerrainRenderMode;
// current model rendering mode
ERenderMode m_ModelRenderMode;
/**
* m_ViewCamera: determines the eye position for rendering
*
* @see CGameView::m_ViewCamera
*/
CCamera m_ViewCamera;
/**
* m_CullCamera: determines the frustum for culling and shadowmap calculations
*
* @see CGameView::m_ViewCamera
*/
CCamera m_CullCamera;
// only valid inside a call to RenderScene
Scene* m_CurrentScene;
// color used to clear screen in BeginFrame
float m_ClearColor[4];
// current lighting setup
CLightEnv* m_LightEnv;
// ogl_tex handle of composite alpha map (all the alpha maps packed into one texture)
Handle m_hCompositeAlphaMap;
// coordinates of each (untransformed) alpha map within the packed texture
struct {
float u0,u1,v0,v1;
} m_AlphaMapCoords[NumAlphaMaps];
// card capabilities
Caps m_Caps;
// build card cap bits
void EnumCaps();
// per-frame renderer stats
Stats m_Stats;
/// If false, use a multipass fallback for player colors.
bool m_FastPlayerColor;
/**
* m_WaterManager: the WaterManager object used for water textures and settings
* (e.g. water color, water height)
*/
WaterManager* m_WaterManager;
/**
* m_SkyManager: the SkyManager object used for sky textures and settings
*/
SkyManager* m_SkyManager;
/**
* m_SortAllTransparent: If true, all transparent models are
* rendered using the TransparencyRenderer which performs sorting.
*
* Otherwise, transparent models are rendered using the faster
* batching renderer when possible.
*/
bool m_SortAllTransparent;
/**
* m_DisplayFrustum: Render the cull frustum and other data that may be interesting
* to evaluate culling and shadow map calculations
*
* Can be controlled from JS via renderer.displayFrustum
*/
bool m_DisplayFrustum;
/**
* m_DisableCopyShadow: For debugging purpose:
* Disable copying of shadow data into the shadow texture (when EXT_fbo is not available)
*/
bool m_DisableCopyShadow;
/**
* Enable rendering of terrain tile priority text overlay, for debugging.
*/
bool m_DisplayTerrainPriorities;
public:
/**
* m_ShadowZBias: Z bias used when rendering shadows into a depth texture.
* This can be used to control shadowing artifacts.
*
* Can be accessed via JS as renderer.shadowZBias
* ShadowMap uses this for matrix calculation.
*/
float m_ShadowZBias;
/**
* m_ShadowMapSize: Size of shadow map, or 0 for default. Typically slow but useful
* for high-quality rendering. Changes don't take effect until the shadow map
* is regenerated.
*
* Can be accessed via JS as renderer.shadowMapSize
*/
int m_ShadowMapSize;
/**
* m_SkipSubmit: Disable the actual submission of rendering commands to OpenGL.
* All state setup is still performed as usual.
*
* Can be accessed via JS as renderer.skipSubmit
*/
bool m_SkipSubmit;
};
#endif
Index: ps/trunk/source/renderer/Renderer.cpp
===================================================================
--- ps/trunk/source/renderer/Renderer.cpp (revision 9188)
+++ ps/trunk/source/renderer/Renderer.cpp (revision 9189)
@@ -1,2002 +1,1976 @@
/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
/*
* higher level interface on top of OpenGL to render basic objects:
* terrain, models, sprites, particles etc.
*/
#include "precompiled.h"
#include