1
0
forked from mirrors/0ad

* clean up CLightEnv a bit

* add CLightEnv::m_TerrainShadowTransparency
* shadows will let a fraction of diffuse light through
* added JS LightEnv objects, so the lighting environment can be changed
  from the console
* new element TerrainShadowTransparency supported in the scenario .xml
format,
  changed cantabrian_generated with an example

This was SVN commit r3513.
This commit is contained in:
prefect
2006-02-15 00:45:16 +00:00
parent 1560a17dfb
commit 36fa5ec2bf
18 changed files with 649 additions and 191 deletions
@@ -1,6 +1,6 @@
<!ELEMENT Scenario (Environment,Entities,Nonentities)>
<!ELEMENT Environment (SunColour,SunElevation,SunRotation,TerrainAmbientColour,UnitsAmbientColour)>
<!ELEMENT Environment (SunColour,SunElevation,SunRotation,TerrainAmbientColour,UnitsAmbientColour,TerrainShadowTransparency)>
<!ELEMENT SunColour EMPTY>
<!ATTLIST SunColour
@@ -31,6 +31,7 @@
g CDATA #REQUIRED
b CDATA #REQUIRED
>
<!ELEMENT TerrainShadowTransparency (#PCDATA)>
<!ELEMENT Entities (Entity*)>
+60 -26
View File
@@ -85,7 +85,7 @@ CGameView::CGameView(CGame *pGame):
m_UnitView=NULL;
m_UnitAttach=NULL;
/* //TEST TRACK
/* //TEST TRACK
int Test_Nodes=15;
int Test_Variance=10.0f; //rand() % Test_Variance distortion of linear points
int Test_Space=30;
@@ -98,7 +98,7 @@ CGameView::CGameView(CGame *pGame):
CCinemaData Test_Data;
TNSpline Test_Spline;
CCinemaTrack Test_Track;
//linear generation with variance factor
for (int i=0; i<Test_Nodes; i++)
{
@@ -107,12 +107,12 @@ CGameView::CGameView(CGame *pGame):
linear.X += rand() % Test_Variance;
else
linear.X -= rand() % Test_Variance;
if ( rand() % 2 )
linear.Y += rand() % Test_Variance;
else
linear.Y -= rand() % Test_Variance;
if ( rand() % 2 )
linear.Z += rand() % Test_Variance;
else
@@ -120,7 +120,7 @@ CGameView::CGameView(CGame *pGame):
Test_Spline.AddNode( linear, Test_NodeTime );
}
Test_Data.m_TotalDuration = Test_Spline.MaxDistance;
Test_Data.m_TotalRotation = CVector3D( 0.0f, DEGTORAD(-150.0f), 0.0f );
Test_Data.m_Growth = Test_Data.m_GrowthCount = 1.9f;
@@ -130,14 +130,14 @@ CGameView::CGameView(CGame *pGame):
Test_Track.m_StartRotation = CVector3D( DEGTORAD(30), DEGTORAD(-45), 0.0f );
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Style = ES_GROWTH;
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Mode = EM_OUT;
Test_Data.m_Style = ES_EXPO;
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Mode = EM_INOUT;
Test_Data.m_Style = ES_GROWTH;
Test_Track.AddPath( Test_Data, Test_Spline );
@@ -149,9 +149,9 @@ CGameView::CGameView(CGame *pGame):
m_TrackManager.AddTrack(Test_Track, "test");
m_TrackManager.QueueTrack("test", true);
*/
//TEST TRACK
CVector3D Test_NodePos[] = { CVector3D( 109.31228f, 93.302315f, -28.760098f ),
//TEST TRACK
CVector3D Test_NodePos[] = { CVector3D( 109.31228f, 93.302315f, -28.760098f ),
CVector3D( 147.03696f, 87.134117f, 54.718628f ),
CVector3D( 174.245293f, 97.134117f, 116.449940f ),
CVector3D( 146.245293f, 107.134117f, 162.449940f ),
@@ -163,13 +163,13 @@ CGameView::CGameView(CGame *pGame):
CCinemaData Test_Data;
TNSpline Test_Spline;
CCinemaTrack Test_Track;
//linear generation with variance factor
for (int i=0; i<ARRAY_SIZE(Test_NodePos); i++)
{
Test_Spline.AddNode( Test_NodePos[i], Test_NodeTime );
}
Test_Data.m_TotalDuration = Test_Spline.MaxDistance;
Test_Data.m_TotalRotation = CVector3D( DEGTORAD(15.0f), DEGTORAD(-100.0f), 0.0f );
Test_Data.m_Growth = Test_Data.m_GrowthCount = 1.9f;
@@ -179,14 +179,14 @@ CGameView::CGameView(CGame *pGame):
Test_Track.m_StartRotation = CVector3D( DEGTORAD(30), DEGTORAD(-45), 0.0f );
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Style = ES_GROWTH;
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Mode = EM_OUT;
Test_Data.m_Style = ES_EXPO;
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Mode = EM_INOUT;
Test_Data.m_Style = ES_GROWTH;
Test_Track.AddPath( Test_Data, Test_Spline );
@@ -196,7 +196,7 @@ CGameView::CGameView(CGame *pGame):
Test_Track.AddPath( Test_Data, Test_Spline );
m_TrackManager.AddTrack(Test_Track, "test");
m_TestTrack.m_Paths.push_back(CCinemaPath());
ONCE( ScriptingInit(); );
}
@@ -262,6 +262,8 @@ void CGameView::Render()
m_CullCamera = m_ViewCamera;
g_Renderer.SetCamera(m_ViewCamera, m_CullCamera);
CheckLightEnv();
MICROLOG(L"render terrain");
PROFILE_START( "render terrain" );
RenderTerrain(m_pWorld->GetTerrain());
@@ -345,8 +347,8 @@ void CGameView::RenderModels(CUnitManager *pUnitMan, CProjectileManager *pProjec
//locks the camera in place
void CGameView::CameraLock(CVector3D Trans, bool smooth)
{
m_Terrain=g_Game->GetWorld()->GetTerrain();
float height=m_Terrain->getExactGroundLevel(
CTerrain* pTerrain = m_pWorld->GetTerrain();
float height=pTerrain->getExactGroundLevel(
m_ViewCamera.m_Orientation._14 + Trans.X, m_ViewCamera.m_Orientation._34 + Trans.Z) +
g_YMinOffset;
//is requested position within limits?
@@ -368,8 +370,8 @@ void CGameView::CameraLock(CVector3D Trans, bool smooth)
void CGameView::CameraLock(float x, float y, float z, bool smooth)
{
m_Terrain=g_Game->GetWorld()->GetTerrain();
float height=m_Terrain->getExactGroundLevel(
CTerrain* pTerrain = m_pWorld->GetTerrain();
float height = pTerrain->getExactGroundLevel(
m_ViewCamera.m_Orientation._14 + x, m_ViewCamera.m_Orientation._34 + z) +
g_YMinOffset;
//is requested position within limits?
@@ -409,6 +411,8 @@ void CGameView::RenderNoCull()
m_CullCamera = m_ViewCamera;
g_Renderer.SetCamera(m_ViewCamera, m_CullCamera);
CheckLightEnv();
uint i,j;
const std::vector<CUnit*>& units=pUnitMan->GetUnits();
for (i=0;i<units.size();++i) {
@@ -424,6 +428,36 @@ void CGameView::RenderNoCull()
}
}
static void MarkUpdateColorRecursive(CModel* model)
{
model->SetDirty(RENDERDATA_UPDATE_COLOR);
const std::vector<CModel::Prop>& props = model->GetProps();
for(uint i = 0; i < props.size(); ++i) {
MarkUpdateColorRecursive(props[i].m_Model);
}
}
void CGameView::CheckLightEnv()
{
if (m_cachedLightEnv == g_LightEnv)
return;
m_cachedLightEnv = g_LightEnv;
CTerrain* pTerrain = m_pWorld->GetTerrain();
if (!pTerrain)
return;
PROFILE("update light env");
pTerrain->MakeDirty(RENDERDATA_UPDATE_COLOR);
const std::vector<CUnit*>& units = m_pWorld->GetUnitManager()->GetUnits();
for(int i = 0; i < units.size(); ++i) {
MarkUpdateColorRecursive(units[i]->GetModel());
}
}
void CGameView::UnloadResources()
{
@@ -488,7 +522,7 @@ void CGameView::Update(float DeltaTime)
m_ViewCamera.UpdateFrustum();
return;
}
if (m_TrackManager.IsPlaying())
{
if(!m_TrackManager.Update(DeltaTime))
@@ -696,7 +730,7 @@ void CGameView::Update(float DeltaTime)
CameraLock(forwards_horizontal * (m_ViewScrollSpeed * DeltaTime));
}
//Temporary hack for cinematic interface
if ( hotkeys[HOTKEY_CAMERA_CINEMA_ADD] )
{
@@ -704,7 +738,7 @@ void CGameView::Update(float DeltaTime)
if (it->GetNodeCount() == 0)
m_TestTrack.m_StartRotation = m_ViewCamera.m_Orientation.GetRotation().m_V;
it->AddNode(m_ViewCamera.m_Orientation.GetTranslation(), 1.5f);
it->AddNode(m_ViewCamera.m_Orientation.GetTranslation(), 1.5f);
it->UpdateSpline();
}
if ( hotkeys[HOTKEY_CAMERA_CINEMA_DELETE] )
@@ -720,7 +754,7 @@ void CGameView::Update(float DeltaTime)
}
if ( hotkeys[HOTKEY_CAMERA_CINEMA_QUEUE] )
m_TrackManager.QueueTrack("test", false);
// Smoothed zooming (move a certain percentage towards the desired zoom distance every frame)
// Note that scroll wheel zooming is event-based and handled in game_view_handler
@@ -875,7 +909,7 @@ InReaction CGameView::HandleEvent(const SDL_Event* ev)
PopCameraTarget();
currentBookmark = -1;
break;
default:
return( IN_PASS );
}
+28 -19
View File
@@ -9,6 +9,7 @@ extern float g_YMinOffset;
#include "CinemaTrack.h"
#include "ModelDef.h"
#include "Vector3D.h"
#include "LightEnv.h"
#include "scripting/ScriptableObject.h"
#include "lib/input.h"
@@ -26,34 +27,39 @@ class CGameView: public CJSObject<CGameView>
{
CGame *m_pGame;
CWorld *m_pWorld;
CTerrain *m_Terrain;
/**
* m_ViewCamera: this camera controls the eye position when rendering
*/
CCamera m_ViewCamera;
/**
* m_CullCamera: this camera controls the frustum that is used for culling
* and shadow calculations
*
*
* Note that all code that works with camera movements should only change
* m_ViewCamera. The render functions automatically sync the cull camera to
* the view camera depending on the value of m_LockCullCamera.
*/
CCamera m_CullCamera;
/**
* m_LockCullCamera: When @c true, the cull camera is locked in place.
* When @c false, the cull camera follows the view camera.
*
*
* Exposed to JS as gameView.lockCullCamera
*/
bool m_LockCullCamera;
/**
* m_cachedLightEnv: Cache global lighting environment. This is used to check whether the
* environment has changed during the last frame, so that vertex data can be updated etc.
*/
CLightEnv m_cachedLightEnv;
CCinemaManager m_TrackManager;
CCinemaTrack m_TestTrack;
////////////////////////////////////////
// Settings
float m_ViewScrollSpeed;
@@ -81,7 +87,10 @@ class CGameView: public CJSObject<CGameView>
// Accumulate zooming changes across frames for smoothness
float m_ZoomDelta;
// Check whether lighting environment has changed and update vertex data if necessary
void CheckLightEnv();
// RenderTerrain: iterate through all terrain patches and submit all patches
// in viewing frustum to the renderer, for terrain, water and LOS painting
void RenderTerrain(CTerrain *pTerrain);
@@ -89,18 +98,18 @@ class CGameView: public CJSObject<CGameView>
// RenderModels: iterate through model list and submit all models in viewing
// frustum to the Renderer
void RenderModels(CUnitManager *pUnitMan, CProjectileManager *pProjectileManager);
// SubmitModelRecursive: recurse down given model, submitting it and all its
// descendents to the renderer
void SubmitModelRecursive(CModel *pModel);
// InitResources(): Load all graphics resources (textures, actor objects and
// alpha maps) required by the game
//void InitResources();
// UnloadResources(): Unload all graphics resources loaded by InitResources
void UnloadResources();
// JS Interface
bool JSI_StartCustomSelection(JSContext *cx, uintN argc, jsval *argv);
bool JSI_EndCustomSelection(JSContext *cx, uintN argc, jsval *argv);
@@ -110,15 +119,15 @@ class CGameView: public CJSObject<CGameView>
public:
CGameView(CGame *pGame);
~CGameView();
void RegisterInit(CGameAttributes *pAttribs);
int Initialize(CGameAttributes *pGameAttributes);
// Update: Update all the view information (i.e. rotate camera, scroll,
// Update: Update all the view information (i.e. rotate camera, scroll,
// whatever). This will *not* change any World information - only the
// *presentation*
void Update(float DeltaTime);
// Render: Render the World
void Render();
@@ -132,12 +141,12 @@ public:
// RenderNoCull: render absolutely everything to a blank frame to force
// renderer to load required assets
void RenderNoCull();
// Camera Control Functions (used by input handler)
void ResetCamera();
void ResetCameraOrientation();
void RotateAboutTarget();
void PushCameraTarget( const CVector3D& target );
void SetCameraTarget( const CVector3D& target );
void PopCameraTarget();
@@ -146,10 +155,10 @@ public:
void ToUnitView(CEntity* target, CModel* prop);
//Keep view the same but follow the unit
void AttachToUnit(CEntity* target) { m_UnitAttach = target; }
bool IsAttached () { if( m_UnitAttach ) { return true; } return false; }
bool IsUnitView () { if( m_UnitView ) { return true; } return false; }
inline CCamera *GetCamera()
{ return &m_ViewCamera; }
};
+53
View File
@@ -0,0 +1,53 @@
/**
* =========================================================================
* File : LightEnv.cpp
* Project : Pyrogenesis
* Description : CLightEnv implementation
*
* @author Nicolai Hähnle <nicolai@wildfiregames.com>
* =========================================================================
*/
#include "precompiled.h"
#include "maths/MathUtil.h"
#include "graphics/LightEnv.h"
CLightEnv::CLightEnv()
: m_Elevation(DEGTORAD(45)),
m_Rotation(DEGTORAD(270)),
m_TerrainShadowTransparency(0.0),
m_SunColor(1,1,1),
m_TerrainAmbientColor(0.4f,0.4f,0.4f),
m_UnitsAmbientColor(0.4f,0.4f,0.4f)
{
CalculateSunDirection();
}
void CLightEnv::SetElevation(float f)
{
m_Elevation = f;
CalculateSunDirection();
}
void CLightEnv::SetRotation(float f)
{
m_Rotation = f;
CalculateSunDirection();
}
void CLightEnv::SetTerrainShadowTransparency(float f)
{
m_TerrainShadowTransparency = f;
}
void CLightEnv::CalculateSunDirection()
{
m_SunDir.Y=-float(sin(m_Elevation));
float scale=1+m_SunDir.Y;
m_SunDir.X=scale*float(sin(m_Rotation));
m_SunDir.Z=scale*float(cos(m_Rotation));
m_SunDir.Normalize();
}
+65 -49
View File
@@ -1,16 +1,13 @@
///////////////////////////////////////////////////////////////////////////////
//
// Name: LightEnv.h
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
// Description: class describing current lighting environment -
// at the minute, this is only sunlight and ambient light
// parameters; will be extended to handle dynamic lights at some
// later date
//
///////////////////////////////////////////////////////////////////////////////
/**
* =========================================================================
* File : LightEnv.h
* Project : Pyrogenesis
* Description : CLightEnv, a class describing the current lights
*
* @author Rich Cross <rich@wildfiregames.com>
* @author Nicolai Hähnle <nicolai@wildfiregames.com>
* =========================================================================
*/
#ifndef __LIGHTENV_H
#define __LIGHTENV_H
@@ -20,52 +17,62 @@
class CMapWriter;
class CMapReader;
class CEditorData;
class CMainFrame;
class CLightSettingsDlg;
///////////////////////////////////////////////////////////////////////////////
// CLightEnv: description of a lighting environment - contains all the
// necessary parameters for representation of the lighting within a scenario
/**
* Class CLightEnv: description of a lighting environment - contains all the
* necessary parameters for representation of the lighting within a scenario
*/
class CLightEnv
{
friend class CMapWriter;
friend class CMapReader;
friend class CXMLReader;
/* Trying to compile ScEd? ;)
friend class CEditorData;
friend class CMainFrame;
friend class CLightSettingsDlg;
// weird accessor order to preserve memory layout of the class
public:
RGBColor m_SunColor;
*/
private:
/**
* m_Elevation: Height of sun above the horizon, in radians.
* For example, an elevation of PI/2 means the sun is straight up.
*/
float m_Elevation;
/**
* m_Rotation: Direction of sun on the compass, in radians.
* For example, a rotation of zero means the sun is in the direction (0,0,-1)
* and a rotation of PI/2 means the sun is in the direction (1,0,0) (not taking
* elevation into account).
*/
float m_Rotation;
public:
RGBColor m_TerrainAmbientColor;
RGBColor m_UnitsAmbientColor;
/**
* m_TerrainShadowTransparency: Fraction of diffuse light that reaches shadowed terrain.
* A value of 0.0 means shadowed polygons get only ambient light, while a value of 1.0
* means shadows don't have any effect at all.
*/
float m_TerrainShadowTransparency;
CVector3D m_SunDir;
// get sun direction from a rotation and elevation; defined such that:
// 0 rotation = (0,0,1)
// PI/2 rotation = (-1,0,0)
// 0 elevation = (0,0,0)
// PI/2 elevation = (0,-1,0)
public:
RGBColor m_SunColor;
RGBColor m_TerrainAmbientColor;
RGBColor m_UnitsAmbientColor;
float GetElevation() { return m_Elevation; }
float GetRotation() { return m_Rotation; }
public:
CLightEnv();
void SetElevation(float f)
{
m_Elevation = f;
CalculateSunDirection();
}
float GetElevation() const { return m_Elevation; }
float GetRotation() const { return m_Rotation; }
const CVector3D& GetSunDir() const { return m_SunDir; }
float GetTerrainShadowTransparency() const { return m_TerrainShadowTransparency; }
void SetRotation(float f)
{
m_Rotation = f;
CalculateSunDirection();
}
void SetElevation(float f);
void SetRotation(float f);
void SetTerrainShadowTransparency(float f);
/**
* EvaluateTerrain: Calculate brightness of a point of the terrain with the given normal
@@ -118,15 +125,24 @@ public:
color = CVector3D(0,0,0);
}
private:
void CalculateSunDirection()
// Comparison operators
bool operator==(const CLightEnv& o) const
{
m_SunDir.Y=-float(sin(m_Elevation));
float scale=1+m_SunDir.Y;
m_SunDir.X=scale*float(sin(m_Rotation));
m_SunDir.Z=scale*float(cos(m_Rotation));
m_SunDir.Normalize();
return m_Elevation == o.m_Elevation &&
m_Rotation == o.m_Rotation &&
m_TerrainShadowTransparency == o.m_TerrainShadowTransparency &&
m_SunColor == o.m_SunColor &&
m_TerrainAmbientColor == o.m_TerrainAmbientColor &&
m_UnitsAmbientColor == o.m_UnitsAmbientColor;
}
bool operator!=(const CLightEnv& o) const
{
return !(*this == o);
}
private:
void CalculateSunDirection();
};
#endif
+8 -3
View File
@@ -41,7 +41,7 @@ void CMapReader::LoadMap(const char* filename, CTerrain *pTerrain_, CUnitManager
// [25ms]
unpacker.Read(filename,"PSMP");
// check version
// check version
if (unpacker.GetVersion() < FILE_READ_VERSION) {
throw CFileUnpacker::CFileVersionError();
}
@@ -174,8 +174,8 @@ int CMapReader::UnpackTerrain()
// ApplyData: take all the input data, and rebuild the scene from it
int CMapReader::ApplyData()
{
// initialise the terrain
pTerrain->Initialize(m_MapSize, &m_Heightmap[0]);
// initialise the terrain
pTerrain->Initialize(m_MapSize, &m_Heightmap[0]);
// setup the textures on the minipatches
STileDesc* tileptr = &m_Tiles[0];
@@ -323,6 +323,7 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
EL(sunrotation);
EL(terrainambientcolour);
EL(unitsambientcolour);
EL(terrainshadowtransparency);
AT(r); AT(g); AT(b);
#undef AT
#undef EL
@@ -361,6 +362,10 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
CStr(attrs.getNamedItem(at_g)).ToFloat(),
CStr(attrs.getNamedItem(at_b)).ToFloat());
}
else if (element_name == el_terrainshadowtransparency)
{
m_MapReader.m_LightEnv.SetTerrainShadowTransparency(CStr(element.getText()).ToFloat());
}
else
debug_warn("Invalid XML data - DTD shouldn't allow this");
}
+7 -7
View File
@@ -18,14 +18,14 @@
// need updating
#define RENDERDATA_UPDATE_VERTICES (1<<1)
#define RENDERDATA_UPDATE_INDICES (1<<2)
#define RENDERDATA_UPDATE_TRANSFORM (1<<3)
#define RENDERDATA_UPDATE_COLOR (1<<4)
///////////////////////////////////////////////////////////////////////////////
// CRenderData: base class of all the renderer's renderdata classes - the
// derived class stores necessary information for rendering an object of a
// CRenderData: base class of all the renderer's renderdata classes - the
// derived class stores necessary information for rendering an object of a
// particular type
class CRenderData
class CRenderData
{
public:
CRenderData() : m_UpdateFlags(0) {}
@@ -36,7 +36,7 @@ public:
///////////////////////////////////////////////////////////////////////////////
// CRenderableObject: base class of all renderable objects - patches, models,
// sprites, etc; stores position and bound information, and a pointer to
// sprites, etc; stores position and bound information, and a pointer to
// some renderdata necessary for the renderer to actually render it
class CRenderableObject
{
@@ -85,9 +85,9 @@ public:
void InvalidateBounds() { m_BoundsValid = false; }
// Set the object renderdata and free previous renderdata, if any.
void SetRenderData(CRenderData* renderdata) {
void SetRenderData(CRenderData* renderdata) {
delete m_RenderData;
m_RenderData = renderdata;
m_RenderData = renderdata;
}
// return object renderdata - can be null if renderer hasn't yet
@@ -0,0 +1,246 @@
/**
* =========================================================================
* File : JSInterface_LightEnv.cpp
* Project : Pyrogenesis
* Description : Provide the LightEnv object type for JavaScript
*
* @author Nicolai Hähnle <nicolai@wildfiregames.com>
* =========================================================================
*/
#include "precompiled.h"
#include "maths/scripting/JSInterface_Vector3D.h"
#include "graphics/scripting/JSInterface_LightEnv.h"
#include "graphics/LightEnv.h"
#include "ps/World.h"
#include "scripting/JSConversions.h"
namespace JSI_LightEnv {
namespace {
extern JSClass JSI_class;
/**
* This enumeration is used to index properties with the JavaScript implementation.
*/
enum
{
lightenv_elevation,
lightenv_rotation,
lightenv_terrainShadowTransparency,
lightenv_sun,
lightenv_terrainAmbient,
lightenv_unitsAmbient
};
///////////////////////////////////////////////////////////////////////////////////////////////
// LightEnv_Info, the private structure that holds data for individual LightEnv objects
struct LightEnv_Info : public IPropertyOwner
{
CLightEnv* m_Data;
bool m_EngineOwned;
// Create a new LightEnv that will only be used by JavaScript
LightEnv_Info()
{
m_Data = new CLightEnv;
m_EngineOwned = false;
}
// Use the given CLightEnv from the engine. The caller must guarantee that
// the copy object will not be deleted.
LightEnv_Info(CLightEnv* copy)
{
m_Data = copy;
m_EngineOwned = true;
}
~LightEnv_Info()
{
if (!m_EngineOwned)
delete m_Data;
}
};
///////////////////////////////////////////////////////////////////////////////////////////////
// Construction and finalization of LightEnvs
/**
* construct: the LightEnv constructor has been called from JavaScript, so create a new
* LightEnv object
*/
JSBool construct(JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* UNUSED(argv), jsval* rval)
{
JSObject* lightenv = JS_NewObject(cx, &JSI_class, NULL, NULL);
if(argc == 0)
{
JS_SetPrivate(cx, lightenv, new LightEnv_Info);
}
else
{
JS_ReportError(cx, "[LightEnv] Too many arguments to constructor");
*rval = JSVAL_NULL;
return JS_TRUE;
}
*rval = OBJECT_TO_JSVAL(lightenv);
return JS_TRUE;
}
/**
* finalize: callback from the JS engine to indicate we should free our private data
*/
void finalize(JSContext* cx, JSObject* obj)
{
delete (LightEnv_Info*)JS_GetPrivate(cx, obj);
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Accessing properties of a LightEnv object
// Can't use ToJSVal here because we need live updates from the vectors
JSBool getVectorProperty(JSContext* cx, LightEnv_Info* lightenvInfo, CVector3D* vec, jsval* vp)
{
JSObject* vector3d = JS_NewObject(cx, &JSI_Vector3D::JSI_class, NULL, NULL);
JS_SetPrivate(cx, vector3d, new JSI_Vector3D::Vector3D_Info(vec, lightenvInfo));
*vp = OBJECT_TO_JSVAL(vector3d);
return JS_TRUE;
}
JSBool getProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp)
{
if (!JSVAL_IS_INT(id))
return JS_TRUE ;
LightEnv_Info* lightenvInfo = (LightEnv_Info*)JS_GetPrivate(cx, obj);
if (!lightenvInfo)
{
JS_ReportError(cx, "[LightEnv] Invalid Reference");
return JS_TRUE;
}
CLightEnv* lightenv = lightenvInfo->m_Data;
switch(ToPrimitive<int>(id)) {
case lightenv_elevation: *vp = ToJSVal(lightenv->GetElevation()); break;
case lightenv_rotation: *vp = ToJSVal(lightenv->GetRotation()); break;
case lightenv_terrainShadowTransparency: *vp = ToJSVal(lightenv->GetTerrainShadowTransparency()); break;
case lightenv_sun: return getVectorProperty(cx, lightenvInfo, &lightenv->m_SunColor, vp);
case lightenv_terrainAmbient: return getVectorProperty(cx, lightenvInfo, &lightenv->m_TerrainAmbientColor, vp);
case lightenv_unitsAmbient: return getVectorProperty(cx, lightenvInfo, &lightenv->m_UnitsAmbientColor, vp);
default: break;
}
return JS_TRUE;
}
JSBool setProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp)
{
if (!JSVAL_IS_INT(id))
return( JS_TRUE );
LightEnv_Info* lightenvInfo = (LightEnv_Info*)JS_GetPrivate(cx, obj);
if (!lightenvInfo)
{
JS_ReportError(cx, "[LightEnv] Invalid reference");
return JS_TRUE;
}
CLightEnv* lightenv = lightenvInfo->m_Data;
switch(ToPrimitive<int>(id)) {
case lightenv_elevation: lightenv->SetElevation(ToPrimitive<float>(*vp)); break;
case lightenv_rotation: lightenv->SetRotation(ToPrimitive<float>(*vp)); break;
case lightenv_terrainShadowTransparency: lightenv->SetTerrainShadowTransparency(ToPrimitive<float>(*vp)); break;
case lightenv_sun: lightenv->m_SunColor = ToPrimitive<CVector3D>(*vp); break;
case lightenv_terrainAmbient: lightenv->m_TerrainAmbientColor = ToPrimitive<CVector3D>(*vp); break;
case lightenv_unitsAmbient: lightenv->m_UnitsAmbientColor = ToPrimitive<CVector3D>(*vp); break;
default: break;
}
return JS_TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Registration of LightEnv class with JavaScript
JSClass JSI_class = {
"LightEnv", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub,
getProperty, setProperty,
JS_EnumerateStub, JS_ResolveStub,
JS_ConvertStub, finalize,
NULL, NULL, NULL, NULL
};
JSPropertySpec JSI_props[] =
{
{ "elevation", lightenv_elevation, JSPROP_ENUMERATE },
{ "rotation", lightenv_rotation, JSPROP_ENUMERATE },
{ "terrainShadowTransparency", lightenv_terrainShadowTransparency, JSPROP_ENUMERATE },
{ "sun", lightenv_sun, JSPROP_ENUMERATE },
{ "terrainAmbient", lightenv_terrainAmbient, JSPROP_ENUMERATE },
{ "unitsAmbient", lightenv_unitsAmbient, JSPROP_ENUMERATE },
{ 0 },
};
JSFunctionSpec JSI_methods[] =
{
{ 0 }
};
}; // anonymous namespace
/**
* init: called by GameSetup to register the LightEnv class with the JS engine.
*/
void init()
{
g_ScriptingHost.DefineCustomObjectType( &JSI_class, construct, 0, JSI_props, JSI_methods, NULL, NULL );
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Accessing the global lightenv
JSBool getLightEnv(JSContext* cx, JSObject* UNUSED(obj), jsval UNUSED(id), jsval* vp)
{
JSObject* lightenv = JS_NewObject(cx, &JSI_class, NULL, NULL);
JS_SetPrivate(cx, lightenv, new LightEnv_Info(&g_LightEnv));
*vp = OBJECT_TO_JSVAL(lightenv);
return JS_TRUE;
}
JSBool setLightEnv(JSContext* cx, JSObject* UNUSED(obj), jsval UNUSED(id), jsval* vp)
{
JSObject* lightenv = JSVAL_TO_OBJECT(*vp);
LightEnv_Info* lightenvInfo;
if (!JSVAL_IS_OBJECT(*vp) || NULL == (lightenvInfo = (LightEnv_Info*)JS_GetInstancePrivate(cx, lightenv, &JSI_class, NULL)))
{
JS_ReportError( cx, "[LightEnv] Invalid object" );
}
else
{
g_LightEnv = *lightenvInfo->m_Data;
}
return JS_TRUE;
}
}; // namespace JSI_LightEnv
@@ -0,0 +1,23 @@
/**
* =========================================================================
* File : JSInterface_LightEnv.h
* Project : Pyrogenesis
* Description : Provide the LightEnv object type for JavaScript
*
* @author Nicolai Hähnle <nicolai@wildfiregames.com>
* =========================================================================
*/
#ifndef JSI_LIGHTENV_INCLUDED
#define JSI_LIGHTENV_INCLUDED
#include "scripting/ScriptingHost.h"
namespace JSI_LightEnv
{
void init();
JSBool getLightEnv( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
JSBool setLightEnv( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
};
#endif
+3 -6
View File
@@ -62,6 +62,7 @@
#include "scripting/JSInterface_Camera.h"
#include "scripting/JSInterface_Selection.h"
#include "scripting/JSInterface_Console.h"
#include "graphics/scripting/JSInterface_LightEnv.h"
#include "scripting/JSCollection.h"
#include "scripting/DOMEvent.h"
#ifndef NO_GUI
@@ -522,6 +523,7 @@ static void InitScripting()
JSI_Camera::init();
JSI_Console::init();
JSI_LightEnv::init();
new CGameEvents;
}
@@ -660,14 +662,9 @@ static void InitRenderer()
MICROLOG(L"init renderer");
g_Renderer.Open(g_xres,g_yres,g_bpp);
// Setup default lighting environment. Since the Renderer accesses the
// Setup lighting environment. Since the Renderer accesses the
// lighting environment through a pointer, this has to be done before
// the first Frame.
g_LightEnv.m_SunColor=RGBColor(1,1,1);
g_LightEnv.SetRotation(DEGTORAD(270));
g_LightEnv.SetElevation(DEGTORAD(45));
g_LightEnv.m_TerrainAmbientColor=RGBColor(0.4f,0.4f,0.4f);
g_LightEnv.m_UnitsAmbientColor=RGBColor(0.4f,0.4f,0.4f);
g_Renderer.SetLightEnv(&g_LightEnv);
// I haven't seen the camera affecting GUI rendering and such, but the
+29 -29
View File
@@ -36,13 +36,13 @@ struct FFModelDef : public CModelDefRPrivate
{
/// Indices are the same for all models, so share them
u16* m_Indices;
/// Static per-CModelDef vertex array
VertexArray m_Array;
/// UV coordinates are stored in the static array
VertexArray::Attribute m_UV;
FFModelDef(CModelDefPtr mdef);
~FFModelDef() { delete[] m_Indices; }
};
@@ -52,21 +52,21 @@ FFModelDef::FFModelDef(CModelDefPtr mdef)
: m_Array(false)
{
size_t numVertices = mdef->GetNumVertices();
m_UV.type = GL_FLOAT;
m_UV.elems = 2;
m_Array.AddAttribute(&m_UV);
m_Array.SetNumVertices(numVertices);
m_Array.Layout();
VertexArrayIterator<float[2]> UVit = m_UV.GetIterator<float[2]>();
ModelRenderer::BuildUV(mdef, UVit);
m_Array.Upload();
m_Array.FreeBackingStore();
m_Indices = new u16[mdef->GetNumFaces()*3];
ModelRenderer::BuildIndices(mdef, m_Indices);
}
@@ -76,11 +76,11 @@ struct FFModel
{
/// Dynamic per-CModel vertex array
VertexArray m_Array;
/// Position and lighting are recalculated on CPU every frame
VertexArray::Attribute m_Position;
VertexArray::Attribute m_Color;
FFModel() : m_Array(true) { }
};
@@ -89,7 +89,7 @@ struct FixedFunctionModelRendererInternals
{
/// Transformed vertex normals - required for recalculating lighting on skinned models
std::vector<CVector3D> normals;
/// Previously prepared modeldef
FFModelDef* ffmodeldef;
};
@@ -130,7 +130,7 @@ void* FixedFunctionModelRenderer::CreateModelData(CModel* model)
ffmodel->m_Color.type = GL_UNSIGNED_BYTE;
ffmodel->m_Color.elems = 4;
ffmodel->m_Array.AddAttribute(&ffmodel->m_Color);
ffmodel->m_Array.SetNumVertices(mdef->GetNumVertices());
ffmodel->m_Array.Layout();
@@ -142,25 +142,25 @@ void* FixedFunctionModelRenderer::CreateModelData(CModel* model)
void FixedFunctionModelRenderer::UpdateModelData(CModel* model, void* data, u32 updateflags)
{
FFModel* ffmodel = (FFModel*)data;
if (updateflags & RENDERDATA_UPDATE_VERTICES)
if (updateflags & (RENDERDATA_UPDATE_VERTICES|RENDERDATA_UPDATE_COLOR))
{
CModelDefPtr mdef = model->GetModelDef();
size_t numVertices = mdef->GetNumVertices();
// build vertices
if (m->normals.size() < numVertices)
m->normals.resize(numVertices);
VertexArrayIterator<CVector3D> Position = ffmodel->m_Position.GetIterator<CVector3D>();
VertexArrayIterator<CVector3D> Normal = VertexArrayIterator<CVector3D>((char*)&m->normals[0], sizeof(CVector3D));
ModelRenderer::BuildPositionAndNormals(model, Position, Normal);
VertexArrayIterator<SColor4ub> Color = ffmodel->m_Color.GetIterator<SColor4ub>();
ModelRenderer::BuildColor4ub(model, Normal, Color);
// upload everything to vertex buffer
ffmodel->m_Array.Upload();
}
@@ -172,7 +172,7 @@ void FixedFunctionModelRenderer::UpdateModelData(CModel* model, void* data, u32
void FixedFunctionModelRenderer::DestroyModelData(CModel* UNUSED(model), void* data)
{
FFModel* ffmodel = (FFModel*)data;
delete ffmodel;
}
@@ -181,7 +181,7 @@ void FixedFunctionModelRenderer::DestroyModelData(CModel* UNUSED(model), void* d
void FixedFunctionModelRenderer::BeginPass(uint streamflags)
{
glEnableClientState(GL_VERTEX_ARRAY);
if (streamflags & STREAM_UV0) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (streamflags & STREAM_COLOR) glEnableClientState(GL_COLOR_ARRAY);
}
@@ -192,7 +192,7 @@ void FixedFunctionModelRenderer::EndPass(uint streamflags)
{
if (streamflags & STREAM_UV0) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (streamflags & STREAM_COLOR) glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
@@ -201,14 +201,14 @@ void FixedFunctionModelRenderer::EndPass(uint streamflags)
void FixedFunctionModelRenderer::PrepareModelDef(uint streamflags, CModelDefPtr def)
{
m->ffmodeldef = (FFModelDef*)def->GetRenderData(m);
debug_assert(m->ffmodeldef);
if (streamflags & STREAM_UV0)
{
u8* base = m->ffmodeldef->m_Array.Bind();
GLsizei stride = (GLsizei)m->ffmodeldef->m_Array.GetStride();
glTexCoordPointer(2, GL_FLOAT, stride, base + m->ffmodeldef->m_UV.offset);
}
}
@@ -219,13 +219,13 @@ void FixedFunctionModelRenderer::RenderModel(uint streamflags, CModel* model, vo
{
CModelDefPtr mdldef = model->GetModelDef();
FFModel* ffmodel = (FFModel*)data;
u8* base = ffmodel->m_Array.Bind();
GLsizei stride = (GLsizei)ffmodel->m_Array.GetStride();
glVertexPointer(3, GL_FLOAT, stride, base + ffmodel->m_Position.offset);
if (streamflags & STREAM_COLOR)
glColorPointer(3, ffmodel->m_Color.type, stride, base + ffmodel->m_Color.offset);
glColorPointer(3, ffmodel->m_Color.type, stride, base + ffmodel->m_Color.offset);
// render the lot
size_t numFaces = mdldef->GetNumFaces();
+1 -1
View File
@@ -184,7 +184,7 @@ void HWLightingModelRenderer::BeginPass(uint streamflags)
idx = g_Renderer.m_VertexShader->m_ModelLight_Ambient;
pglUniform3fvARB(idx, 1, &lightEnv.m_UnitsAmbientColor.X);
idx = g_Renderer.m_VertexShader->m_ModelLight_SunDir;
pglUniform3fvARB(idx, 1, &lightEnv.m_SunDir.X);
pglUniform3fvARB(idx, 1, &lightEnv.GetSunDir().X);
idx = g_Renderer.m_VertexShader->m_ModelLight_SunColor;
pglUniform3fvARB(idx, 1, &lightEnv.m_SunColor.X);
+1 -1
View File
@@ -164,7 +164,7 @@ void InstancingModelRenderer::BeginPass(uint streamflags)
idx = g_Renderer.m_VertexShader->m_InstancingLight_Ambient;
pglUniform3fvARB(idx, 1, &lightEnv.m_UnitsAmbientColor.X);
idx = g_Renderer.m_VertexShader->m_InstancingLight_SunDir;
pglUniform3fvARB(idx, 1, &lightEnv.m_SunDir.X);
pglUniform3fvARB(idx, 1, &lightEnv.GetSunDir().X);
idx = g_Renderer.m_VertexShader->m_InstancingLight_SunColor;
pglUniform3fvARB(idx, 1, &lightEnv.m_SunColor.X);
+10 -3
View File
@@ -366,8 +366,14 @@ void CRenderer::EnumCaps()
if (oglHaveExtension("GL_ARB_vertex_shader"))
m_Caps.m_VertexShader=true;
}
if (0 == oglHaveExtensions(0, "GL_ARB_shadow", "GL_ARB_depth_texture", 0)) {
m_Caps.m_DepthTextureShadows = true;
// According to Delphi3d.net, all relevant graphics chips that support depth textures
// (i.e. Geforce3+, Radeon9500+, even i915) also have >= 4 TMUs, so this restriction
// isn't actually a restriction, and it helps with integrating depth texture
// shadows into rendering paths.
if (ogl_max_tex_units >= 4)
m_Caps.m_DepthTextureShadows = true;
}
}
@@ -587,7 +593,7 @@ void CRenderer::BeginFrame()
m_Stats.Reset();
// init per frame stuff
m->shadow->SetupFrame(m_CullCamera, m_LightEnv->m_SunDir);
m->shadow->SetupFrame(m_CullCamera, m_LightEnv->GetSunDir());
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -606,7 +612,8 @@ void CRenderer::RenderShadowMap()
m->shadow->BeginRender();
glColor3ub(0, 0, 0);
float shadowTransp = m_LightEnv->GetTerrainShadowTransparency();
glColor3f(shadowTransp, shadowTransp, shadowTransp);
// Figure out transparent rendering strategy
RenderModifierPtr transparentShadows = m_Models.ModTransparentShadow;
+101 -37
View File
@@ -151,7 +151,7 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
float one[4] = { 1.f, 1.f, 1.f, 1.f };
static const float one[4] = { 1.f, 1.f, 1.f, 1.f };
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, one);
for(uint i = 0; i < m->visiblePatches.size(); ++i)
@@ -197,51 +197,114 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// Now apply lighting
// Light color is Ambient + ShadowTerm * Diffuse
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
glBlendFunc(GL_DST_COLOR, GL_ZERO);
pglActiveTextureARB(GL_TEXTURE0); // Diffuse * Shadow
if (shadow)
glBindTexture(GL_TEXTURE_2D, shadow->GetTexture());
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
pglActiveTextureARB(GL_TEXTURE1); // + Ambient
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &lightEnv.m_TerrainAmbientColor.X);
pglActiveTextureARB(GL_TEXTURE0);
if (shadow)
if (!shadow)
{
const CMatrix3D& texturematrix = shadow->GetTextureMatrix();
pglActiveTextureARB(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(&texturematrix._11);
glMatrixMode(GL_MODELVIEW);
// Shadow rendering disabled: Ambient + Diffuse
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &lightEnv.m_TerrainAmbientColor.X);
}
else
{
glBindTexture(GL_TEXTURE_2D, 0);
const CMatrix3D& texturematrix = shadow->GetTextureMatrix();
pglActiveTextureARB(GL_TEXTURE0);
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(&texturematrix._11);
glMatrixMode(GL_MODELVIEW);
glBindTexture(GL_TEXTURE_2D, shadow->GetTexture());
if (shadow->GetUseDepthTexture())
{
// Ambient + ShTranslucency * Diffuse * (1 - Shadow) + Diffuse * Shadow
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
float shadowTransp = g_Renderer.GetLightEnv().GetTerrainShadowTransparency();
float color[4] = { shadowTransp, shadowTransp, shadowTransp, 1.0 };
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
pglActiveTextureARB(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
pglActiveTextureARB(GL_TEXTURE2);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, shadow->GetTexture()); // Need a valid texture or the unit will be disabled
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &lightEnv.m_TerrainAmbientColor.X);
}
else
{
// Ambient + Diffuse * Shadow
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
pglActiveTextureARB(GL_TEXTURE1); // + Ambient
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &lightEnv.m_TerrainAmbientColor.X);
}
}
pglActiveTextureARB(GL_TEXTURE0);
pglClientActiveTextureARB(GL_TEXTURE0);
for (uint i = 0; i < m->visiblePatches.size(); ++i)
@@ -255,6 +318,7 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
glMatrixMode(GL_MODELVIEW);
// restore OpenGL state
g_Renderer.BindTexture(2,0);
g_Renderer.BindTexture(1,0);
pglClientActiveTextureARB(GL_TEXTURE0);
+1 -1
View File
@@ -219,7 +219,7 @@ void PolygonSortModelRenderer::UpdateModelData(CModel* model, void* data, u32 up
{
PSModel* psmdl = (PSModel*)data;
if (updateflags & RENDERDATA_UPDATE_VERTICES)
if (updateflags & (RENDERDATA_UPDATE_VERTICES|RENDERDATA_UPDATE_COLOR))
{
CModelDefPtr mdef = model->GetModelDef();
size_t numVertices = mdef->GetNumVertices();
+9 -6
View File
@@ -35,6 +35,7 @@
#include "scripting/JSInterface_Camera.h"
#include "scripting/JSInterface_Console.h"
#include "scripting/JSInterface_VFS.h"
#include "graphics/scripting/JSInterface_LightEnv.h"
#include "scripting/JSConversions.h"
#include "renderer/WaterManager.h"
#ifndef NO_GUI
@@ -204,7 +205,7 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv
entities.push_back( (ToNative<CEntity>(argv[0])) ->me);
else
entities = *EntityCollection::RetrieveSet(cx, JSVAL_TO_OBJECT(argv[0]));
//Destroy old listeners if we're explicitly being reassigned
for ( size_t i=0; i < entities.size(); i++)
{
@@ -925,7 +926,7 @@ JSBool setWaterAlphaOffset( JSContext* cx, JSObject* UNUSED(globalObject), uint
JSBool isPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval )
{
REQUIRE_NO_PARAMS( isPaused );
if( !g_Game )
{
JS_ReportError( cx, "Game is not started" );
@@ -940,17 +941,17 @@ JSBool isPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval
JSBool setPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* UNUSED(rval) )
{
REQUIRE_PARAMS( 1, setPaused );
if( !g_Game )
{
JS_ReportError( cx, "Game is not started" );
return JS_FALSE;
}
try
try
{
g_Game->m_Paused = ToPrimitive<bool>( argv[0] );
}
}
catch( PSERROR_Scripting_ConversionFailed )
{
JS_ReportError( cx, "Invalid parameter to setPaused" );
@@ -963,7 +964,7 @@ JSBool setPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsva
JSBool getGameTime( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval )
{
REQUIRE_NO_PARAMS( getGameTime );
if( !g_Game )
{
JS_ReportError( cx, "Game is not started" );
@@ -1177,6 +1178,7 @@ enum ScriptGlobalTinyIDs
GLOBAL_GROUPSARRAY,
GLOBAL_CAMERA,
GLOBAL_CONSOLE,
GLOBAL_LIGHTENV
};
// shorthand
@@ -1189,6 +1191,7 @@ JSPropertySpec ScriptGlobalTable[] =
{ "groups" , GLOBAL_GROUPSARRAY, PERM, JSI_Selection::getGroups, JSI_Selection::setGroups },
{ "camera" , GLOBAL_CAMERA, PERM, JSI_Camera::getCamera, JSI_Camera::setCamera },
{ "console" , GLOBAL_CONSOLE, PERM | CONST, JSI_Console::getConsole, 0 },
{ "lightenv" , GLOBAL_LIGHTENV, PERM, JSI_LightEnv::getLightEnv, JSI_LightEnv::setLightEnv },
{ "entities" , 0, PERM | CONST, GetEntitySet, 0 },
{ "players" , 0, PERM | CONST, GetPlayerSet, 0 },
{ "localPlayer", 0, PERM , GetLocalPlayer, SetLocalPlayer },