Merge branch 'master' of github.com:OpenMW/openmw

deque
MiroslavR 10 years ago
commit 29f5cb46ac

@ -26,7 +26,7 @@ opencs_units (model/world
opencs_units_noqt (model/world
universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope landtexture land
)
opencs_hdrs_noqt (model/world
@ -76,7 +76,7 @@ opencs_units (view/widget
opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget
previewwidget terrainstorage
)
opencs_units_noqt (view/render

@ -539,6 +539,16 @@ CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles()
return mDebugProfiles;
}
const CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand() const
{
return mLand;
}
const CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures() const
{
return mLandTextures;
}
const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const
{
return mResourcesManager.get (id.getType());
@ -573,8 +583,11 @@ void CSMWorld::Data::merge()
int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base, bool project)
{
delete mReader;
// Don't delete the Reader yet. Some record types store a reference to the Reader to handle on-demand loading
boost::shared_ptr<ESM::ESMReader> ptr(mReader);
mReaders.push_back(ptr);
mReader = 0;
mDialogue = 0;
mRefLoadCache.clear();
@ -598,8 +611,11 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
if (!mReader->hasMoreRecs())
{
delete mReader;
// Don't delete the Reader yet. Some record types store a reference to the Reader to handle on-demand loading
boost::shared_ptr<ESM::ESMReader> ptr(mReader);
mReaders.push_back(ptr);
mReader = 0;
mDialogue = 0;
mRefLoadCache.clear();
return true;
@ -626,6 +642,9 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
case ESM::REC_ENCH: mEnchantments.load (*mReader, mBase); break;
case ESM::REC_BODY: mBodyParts.load (*mReader, mBase); break;
case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break;
case ESM::REC_LAND: mLand.load(*mReader, mBase); break;
case ESM::REC_CELL:
{
mCells.load (*mReader, mBase);
@ -775,7 +794,9 @@ bool CSMWorld::Data::hasId (const std::string& id) const
getCells().searchId (id)!=-1 ||
getEnchantments().searchId (id)!=-1 ||
getBodyParts().searchId (id)!=-1 ||
getReferenceables().searchId (id)!=-1;
getReferenceables().searchId (id)!=-1 ||
getLand().searchId (id) != -1 ||
getLandTextures().searchId (id) != -1;
}
int CSMWorld::Data::count (RecordBase::State state) const
@ -795,7 +816,9 @@ int CSMWorld::Data::count (RecordBase::State state) const
count (state, mCells) +
count (state, mEnchantments) +
count (state, mBodyParts) +
count (state, mReferenceables);
count (state, mReferenceables) +
count (state, mLand) +
count (state, mLandTextures);
}
void CSMWorld::Data::setDescription (const std::string& description)
@ -838,6 +861,8 @@ std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
appendIds (ids, mEnchantments, listDeleted);
appendIds (ids, mBodyParts, listDeleted);
appendIds (ids, mReferenceables, listDeleted);
appendIds (ids, mLand, listDeleted);
appendIds (ids, mLandTextures, listDeleted);
std::sort (ids.begin(), ids.end());

@ -33,6 +33,8 @@
#include "idcollection.hpp"
#include "universalid.hpp"
#include "cell.hpp"
#include "land.hpp"
#include "landtexture.hpp"
#include "refidcollection.hpp"
#include "refcollection.hpp"
#include "infocollection.hpp"
@ -74,6 +76,8 @@ namespace CSMWorld
InfoCollection mTopicInfos;
InfoCollection mJournalInfos;
IdCollection<Cell> mCells;
IdCollection<LandTexture> mLandTextures;
IdCollection<Land> mLand;
RefIdCollection mReferenceables;
RefCollection mRefs;
IdCollection<ESM::Filter> mFilters;
@ -88,6 +92,8 @@ namespace CSMWorld
bool mProject;
std::map<std::string, std::map<ESM::RefNum, std::string> > mRefLoadCache;
std::vector<boost::shared_ptr<ESM::ESMReader> > mReaders;
// not implemented
Data (const Data&);
Data& operator= (const Data&);
@ -195,6 +201,10 @@ namespace CSMWorld
IdCollection<ESM::DebugProfile>& getDebugProfiles();
const IdCollection<CSMWorld::Land>& getLand() const;
const IdCollection<CSMWorld::LandTexture>& getLandTextures() const;
/// Throws an exception, if \a id does not match a resources list.
const Resources& getResources (const UniversalId& id) const;
@ -247,4 +257,4 @@ namespace CSMWorld
};
}
#endif
#endif

@ -29,7 +29,7 @@ int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const
QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const
{
if (role!=Qt::DisplayRole && role!=Qt::EditRole)
if ((role!=Qt::DisplayRole && role!=Qt::EditRole) || index.row() < 0 || index.column() < 0)
return QVariant();
if (role==Qt::EditRole && !mIdCollection->getColumn (index.column()).isEditable())
@ -229,4 +229,4 @@ bool CSMWorld::IdTable::isDeleted (const std::string& id) const
int CSMWorld::IdTable::getColumnId(int column) const
{
return mIdCollection->getColumn(column).getId();
}
}

@ -0,0 +1,28 @@
#include "land.hpp"
#include <sstream>
namespace CSMWorld
{
Land::Land()
{
mLand.reset(new ESM::Land());
}
void Land::load(ESM::ESMReader &esm)
{
mLand->load(esm);
std::ostringstream stream;
stream << "#" << mLand->mX << " " << mLand->mY;
mId = stream.str();
}
void Land::blank()
{
/// \todo
}
}

@ -0,0 +1,29 @@
#ifndef CSM_WORLD_LAND_H
#define CSM_WORLD_LAND_H
#include <string>
#include <boost/shared_ptr.hpp>
#include <components/esm/loadland.hpp>
namespace CSMWorld
{
/// \brief Wrapper for Land record. Encodes X and Y cell index in the ID.
///
/// \todo Add worldspace support to the Land record.
/// \todo Add a proper copy constructor (currently worked around using shared_ptr)
struct Land
{
Land();
boost::shared_ptr<ESM::Land> mLand;
std::string mId;
/// Loads the metadata and ID
void load (ESM::ESMReader &esm);
void blank();
};
}
#endif

@ -0,0 +1,21 @@
#include "landtexture.hpp"
#include <components/esm/esmreader.hpp>
namespace CSMWorld
{
void LandTexture::load(ESM::ESMReader &esm)
{
ESM::LandTexture::load(esm);
int plugin = esm.getIndex();
std::ostringstream stream;
stream << mIndex << "_" << plugin;
mId = stream.str();
}
}

@ -0,0 +1,22 @@
#ifndef CSM_WORLD_LANDTEXTURE_H
#define CSM_WORLD_LANDTEXTURE_H
#include <string>
#include <components/esm/loadltex.hpp>
namespace CSMWorld
{
/// \brief Wrapper for LandTexture record. Encodes mIndex and the plugin index (obtained from ESMReader)
/// in the ID.
///
/// \attention The mId field of the ESM::LandTexture struct is not used.
struct LandTexture : public ESM::LandTexture
{
std::string mId;
void load (ESM::ESMReader &esm);
};
}
#endif

@ -10,6 +10,9 @@
#include "../../model/world/columns.hpp"
#include "../../model/world/data.hpp"
#include "elements.hpp"
#include "terrainstorage.hpp"
bool CSVRender::Cell::removeObject (const std::string& id)
{
std::map<std::string, Object *>::iterator iter =
@ -67,6 +70,18 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager,
int rows = references.rowCount();
addObjects (0, rows-1);
const CSMWorld::IdCollection<CSMWorld::Land>& land = mData.getLand();
int landIndex = land.searchId(mId);
if (landIndex != -1)
{
mTerrain.reset(new Terrain::TerrainGrid(sceneManager, new TerrainStorage(mData), Element_Terrain, true,
Terrain::Align_XY));
const ESM::Land* esmLand = land.getRecord(mId).get().mLand.get();
mTerrain->loadCell(esmLand->mX,
esmLand->mY);
}
}
CSVRender::Cell::~Cell()
@ -198,4 +213,4 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int
return false;
return addObjects (start, end);
}
}

@ -6,6 +6,8 @@
#include <OgreVector3.h>
#include <components/terrain/terraingrid.hpp>
#include "object.hpp"
class QModelIndex;
@ -29,6 +31,7 @@ namespace CSVRender
std::string mId;
Ogre::SceneNode *mCellNode;
std::map<std::string, Object *> mObjects;
std::auto_ptr<Terrain::TerrainGrid> mTerrain;
/// Ignored if cell does not have an object with the given ID.
///

@ -50,7 +50,7 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells()
{
int index = cells.searchId (iter->getId (mWorldspace));
if (index!=0 && cells.getRecord (index).mState!=CSMWorld::RecordBase::State_Deleted &&
if (index > 0 && cells.getRecord (index).mState!=CSMWorld::RecordBase::State_Deleted &&
mCells.find (*iter)==mCells.end())
{
if (setCamera)
@ -315,4 +315,4 @@ void CSVRender::PagedWorldspaceWidget::cellAdded (const QModelIndex& index, int
/// \todo check if no selected cell is affected and do not update, if that is the case
if (adjustCells())
flagAsModified();
}
}

@ -0,0 +1,43 @@
#include "terrainstorage.hpp"
namespace CSVRender
{
TerrainStorage::TerrainStorage(const CSMWorld::Data &data)
: mData(data)
{
}
ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
{
std::ostringstream stream;
stream << "#" << cellX << " " << cellY;
// The cell isn't guaranteed to have Land. This is because the terrain implementation
// has to wrap the vertices of the last row and column to the next cell, which may be a nonexisting cell
int index = mData.getLand().searchId(stream.str());
if (index == -1)
return NULL;
ESM::Land* land = mData.getLand().getRecord(index).get().mLand.get();
int mask = ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX;
if (!land->isDataLoaded(mask))
land->loadData(mask);
return land;
}
const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin)
{
std::ostringstream stream;
stream << index << "_" << plugin;
return &mData.getLandTextures().getRecord(stream.str()).get();
}
void TerrainStorage::getBounds(float &minX, float &maxX, float &minY, float &maxY)
{
// not needed at the moment - this returns the bounds of the whole world, but we only edit individual cells
throw std::runtime_error("getBounds not implemented");
}
}

@ -0,0 +1,29 @@
#ifndef OPENCS_RENDER_TERRAINSTORAGE_H
#define OPENCS_RENDER_TERRAINSTORAGE_H
#include <components/esmterrain/storage.hpp>
#include "../../model/world/data.hpp"
namespace CSVRender
{
/**
* @brief A bridge between the terrain component and OpenCS's terrain data storage.
*/
class TerrainStorage : public ESMTerrain::Storage
{
public:
TerrainStorage(const CSMWorld::Data& data);
private:
const CSMWorld::Data& mData;
virtual ESM::Land* getLand (int cellX, int cellY);
virtual const ESM::LandTexture* getLandTexture(int index, short plugin);
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY);
};
}
#endif

@ -478,7 +478,7 @@ void OMW::Engine::go()
}
// Start the main rendering loop
while (!mEnvironment.get().getStateManager()->hasQuitRequest())
while (!MWBase::Environment::get().getStateManager()->hasQuitRequest())
Ogre::Root::getSingleton().renderOneFrame();
// Save user settings

@ -63,7 +63,7 @@ namespace MWClass
virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const;
///< Return item max health or throw an exception, if class does not have item health
/// (default implementation: throw an exceoption)
/// (default implementation: throw an exception)
virtual float getWeight (const MWWorld::Ptr& ptr) const;

@ -246,10 +246,7 @@ namespace MWMechanics
const ESM::Spell* spell, const MagicEffects* effects)
{
float resistance = getEffectResistance(effectId, actor, caster, spell, effects);
if (resistance >= 0)
return 1 - resistance / 100.f;
else
return -(resistance-100) / 100.f;
return 1 - resistance / 100.f;
}
/// Check if the given affect can be applied to the target. If \a castByPlayer, emits a message box on failure.

@ -51,6 +51,10 @@ namespace MWMechanics
float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
const ESM::Spell* spell = NULL, const MagicEffects* effects = NULL);
/// Get an effect multiplier for applying an effect cast by the given actor in the given spell (optional).
/// @return effect multiplier from 0 to 2. (100% net resistance to 100% net weakness)
/// @param effects Override the actor's current magicEffects. Useful if there are effects currently
/// being applied (but not applied yet) that should also be considered.
float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
const ESM::Spell* spell = NULL, const MagicEffects* effects = NULL);

@ -120,11 +120,14 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
// Set default texture filtering options
TextureFilterOptions tfo;
std::string filter = Settings::Manager::getString("texture filtering", "General");
#ifndef ANDROID
if (filter == "anisotropic") tfo = TFO_ANISOTROPIC;
else if (filter == "trilinear") tfo = TFO_TRILINEAR;
else if (filter == "bilinear") tfo = TFO_BILINEAR;
else /*if (filter == "none")*/ tfo = TFO_NONE;
#else
tfo = TFO_NONE;
#endif
MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 );

@ -96,7 +96,7 @@ namespace MWWorld
virtual MWMechanics::CreatureStats& getCreatureStats (const Ptr& ptr) const;
///< Return creature stats or throw an exception, if class does not have creature stats
/// (default implementation: throw an exceoption)
/// (default implementation: throw an exception)
virtual bool hasToolTip (const Ptr& ptr) const;
///< @return true if this object has a tooltip when focused (default implementation: false)
@ -106,7 +106,7 @@ namespace MWWorld
virtual MWMechanics::NpcStats& getNpcStats (const Ptr& ptr) const;
///< Return NPC stats or throw an exception, if class does not have NPC stats
/// (default implementation: throw an exceoption)
/// (default implementation: throw an exception)
virtual bool hasItemHealth (const Ptr& ptr) const;
///< \return Item health data available? (default implementation: false)
@ -123,7 +123,7 @@ namespace MWWorld
/// of the given attacker, and whoever is hit.
/// \param type - type of attack, one of the MWMechanics::CreatureStats::AttackType
/// enums. ignored for creature attacks.
/// (default implementation: throw an exceoption)
/// (default implementation: throw an exception)
virtual void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const;
///< Alerts \a ptr that it's being hit for \a damage points to health if \a ishealth is
@ -139,7 +139,7 @@ namespace MWWorld
///< Sets a new current health value for the actor, optionally specifying the object causing
/// the change. Use this instead of using CreatureStats directly as this will make sure the
/// correct dialog and actor states are properly handled when being hurt or healed.
/// (default implementation: throw an exceoption)
/// (default implementation: throw an exception)
virtual boost::shared_ptr<Action> activate (const Ptr& ptr, const Ptr& actor) const;
///< Generate action for activation (default implementation: return a null action).
@ -151,11 +151,11 @@ namespace MWWorld
virtual ContainerStore& getContainerStore (const Ptr& ptr) const;
///< Return container store or throw an exception, if class does not have a
/// container store (default implementation: throw an exceoption)
/// container store (default implementation: throw an exception)
virtual InventoryStore& getInventoryStore (const Ptr& ptr) const;
///< Return inventory store or throw an exception, if class does not have a
/// inventory store (default implementation: throw an exceoption)
/// inventory store (default implementation: throw an exception)
virtual bool hasInventoryStore (const Ptr& ptr) const;
///< Does this object have an inventory store, i.e. equipment slots? (default implementation: false)

@ -98,6 +98,8 @@ struct Land
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank() {}
/**
* Actually loads data
*/

@ -19,4 +19,10 @@ void LandTexture::save(ESMWriter &esm) const
esm.writeHNCString("DATA", mTexture);
}
void LandTexture::blank()
{
mTexture.clear();
mIndex = -1;
}
}

@ -32,6 +32,9 @@ struct LandTexture
std::string mId, mTexture;
int mIndex;
void blank();
///< Set record to default state (does not touch the ID).
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
};

@ -53,22 +53,22 @@ AndroidPath::AndroidPath(const std::string& application_name)
boost::filesystem::path AndroidPath::getUserConfigPath() const
{
return getEnv("XDG_CONFIG_HOME", "/sdcard/morrowind/config") / mName;
return getEnv("XDG_CONFIG_HOME", "/sdcard/libopenmw/config") / mName;
}
boost::filesystem::path AndroidPath::getUserDataPath() const
{
return getEnv("XDG_DATA_HOME", "/sdcard/morrowind/share") / mName;
return getEnv("XDG_DATA_HOME", "/sdcard/libopenmw/share") / mName;
}
boost::filesystem::path AndroidPath::getCachePath() const
{
return getEnv("XDG_CACHE_HOME", "/sdcard/morrowind/cache") / mName;
return getEnv("XDG_CACHE_HOME", "/sdcard/libopenmw/cache") / mName;
}
boost::filesystem::path AndroidPath::getGlobalConfigPath() const
{
boost::filesystem::path globalPath("/sdcard/morrowind/");
boost::filesystem::path globalPath("/sdcard/libopenmw/");
return globalPath / mName;
}
@ -79,7 +79,7 @@ boost::filesystem::path AndroidPath::getLocalPath() const
boost::filesystem::path AndroidPath::getGlobalDataPath() const
{
boost::filesystem::path globalDataPath("/sdcard/morrowind/data");
boost::filesystem::path globalDataPath("/sdcard/libopenmw/data");
return globalDataPath / mName;
}

@ -47,7 +47,7 @@
// Scroll in y direction
float2 scrolledUV = UV + float2(0,1) * cloudAnimationTimer * 0.003;
float4 albedo = shSample(diffuseMap1, scrolledUV) * (1-cloudBlendFactor) + shSample(diffuseMap2, scrolledUV) * cloudBlendFactor;
float4 albedo = shSample(diffuseMap1, scrolledUV) * (1.0-cloudBlendFactor) + shSample(diffuseMap2, scrolledUV) * cloudBlendFactor;
shOutputColour(0) = float4(cloudColour, 1) * albedo * float4(1,1,1, cloudOpacity * alphaFade);
}

@ -45,8 +45,8 @@ shUniform(float4x4, projection) @shAutoConstant(projection, projection_matrix)
shOutputColour(0).a = shSample(alphaMap, UV).a * materialDiffuse.a;
shOutputColour(0).rgb += (1-tex.a) * shOutputColour(0).a * atmosphereColour.rgb; //fill dark side of moon with atmosphereColour
shOutputColour(0).rgb += (1-materialDiffuse.a) * atmosphereColour.rgb; //fade bump
shOutputColour(0).rgb += (1.0-tex.a) * shOutputColour(0).a * atmosphereColour.rgb; //fill dark side of moon with atmosphereColour
shOutputColour(0).rgb += (1.0-materialDiffuse.a) * atmosphereColour.rgb; //fade bump
}

@ -1,55 +1,55 @@
#include "core.h"
#define ALPHA @shPropertyBool(shadow_transparency)
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
#if ALPHA
shVertexInput(float2, uv0)
shOutput(float2, UV)
#endif
shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix)
shOutput(float2, depth)
SH_START_PROGRAM
{
// this is the view space position
shOutputPosition = shMatrixMult(wvp, shInputPosition);
// depth info for the fragment.
depth.x = shOutputPosition.z;
depth.y = shOutputPosition.w;
// clamp z to zero. seem to do the trick. :-/
shOutputPosition.z = max(shOutputPosition.z, 0);
#if ALPHA
UV = uv0;
#endif
}
#else
SH_BEGIN_PROGRAM
#if ALPHA
shInput(float2, UV)
shSampler2D(texture1)
#endif
shInput(float2, depth)
SH_START_PROGRAM
{
float finalDepth = depth.x / depth.y;
#if ALPHA
// use alpha channel of the first texture
float alpha = shSample(texture1, UV).a;
if (alpha < 0.5)
discard;
#endif
shOutputColour(0) = float4(finalDepth, finalDepth, finalDepth, 1);
}
#endif
#include "core.h"
#define ALPHA @shPropertyBool(shadow_transparency)
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
#if ALPHA
shVertexInput(float2, uv0)
shOutput(float2, UV)
#endif
shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix)
shOutput(float2, depth)
SH_START_PROGRAM
{
// this is the view space position
shOutputPosition = shMatrixMult(wvp, shInputPosition);
// depth info for the fragment.
depth.x = shOutputPosition.z;
depth.y = shOutputPosition.w;
// clamp z to zero. seem to do the trick. :-/
shOutputPosition.z = max(shOutputPosition.z, 0.0);
#if ALPHA
UV = uv0;
#endif
}
#else
SH_BEGIN_PROGRAM
#if ALPHA
shInput(float2, UV)
shSampler2D(texture1)
#endif
shInput(float2, depth)
SH_START_PROGRAM
{
float finalDepth = depth.x / depth.y;
#if ALPHA
// use alpha channel of the first texture
float alpha = shSample(texture1, UV).a;
if (alpha < 0.5)
discard;
#endif
shOutputColour(0) = float4(finalDepth, finalDepth, finalDepth, 1.0);
}
#endif

@ -1,48 +1,48 @@
#include "core.h"
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
shUniform(float4x4, worldview) @shAutoConstant(worldview, worldview_matrix)
shUniform(float4x4, proj) @shAutoConstant(proj, projection_matrix)
shVertexInput(float2, uv0)
shOutput(float2, UV)
shOutput(float, fade)
SH_START_PROGRAM
{
float4x4 worldviewFixed = worldview;
#if !SH_GLSL
worldviewFixed[0][3] = 0;
worldviewFixed[1][3] = 0;
worldviewFixed[2][3] = 0;
#else
worldviewFixed[3][0] = 0;
worldviewFixed[3][1] = 0;
worldviewFixed[3][2] = 0;
#endif
shOutputPosition = shMatrixMult(proj, shMatrixMult(worldviewFixed, shInputPosition));
UV = uv0;
fade = (shInputPosition.z > 50) ? 1 : 0;
}
#else
SH_BEGIN_PROGRAM
shInput(float2, UV)
shInput(float, fade)
shSampler2D(diffuseMap)
shUniform(float, nightFade) @shSharedParameter(nightFade)
SH_START_PROGRAM
{
shOutputColour(0) = shSample(diffuseMap, UV) * float4(1,1,1, nightFade * fade);
}
#endif
#include "core.h"
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
shUniform(float4x4, worldview) @shAutoConstant(worldview, worldview_matrix)
shUniform(float4x4, proj) @shAutoConstant(proj, projection_matrix)
shVertexInput(float2, uv0)
shOutput(float2, UV)
shOutput(float, fade)
SH_START_PROGRAM
{
float4x4 worldviewFixed = worldview;
#if !SH_GLSL
worldviewFixed[0][3] = 0.0;
worldviewFixed[1][3] = 0.0;
worldviewFixed[2][3] = 0.0;
#else
worldviewFixed[3][0] = 0.0;
worldviewFixed[3][1] = 0.0;
worldviewFixed[3][2] = 0.0;
#endif
shOutputPosition = shMatrixMult(proj, shMatrixMult(worldviewFixed, shInputPosition));
UV = uv0;
fade = (shInputPosition.z > 50.0) ? 1.0 : 0.0;
}
#else
SH_BEGIN_PROGRAM
shInput(float2, UV)
shInput(float, fade)
shSampler2D(diffuseMap)
shUniform(float, nightFade) @shSharedParameter(nightFade)
SH_START_PROGRAM
{
shOutputColour(0) = shSample(diffuseMap, UV) * float4(1,1,1, nightFade * fade);
}
#endif

@ -1,370 +1,370 @@
#include "core.h"
#define SIMPLE_WATER @shGlobalSettingBool(simple_water)
#if SIMPLE_WATER
// --------------------------------------- SIMPLE WATER ---------------------------------------------------
#define FOG @shGlobalSettingBool(fog)
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix)
shVertexInput(float2, uv0)
shOutput(float2, UV)
#if FOG
shOutput(float, depth)
#endif
SH_START_PROGRAM
{
shOutputPosition = shMatrixMult(wvp, shInputPosition);
UV = uv0;
#if FOG
depth = shOutputPosition.z;
#endif
}
#else
SH_BEGIN_PROGRAM
shSampler2D(animatedTexture)
shInput(float2, UV)
shInput(float, depth)
shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour)
shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params)
SH_START_PROGRAM
{
shOutputColour(0).xyz = shSample(animatedTexture, UV * float2(15.0, 15.0)).xyz * float3(1.0, 1.0, 1.0);
shOutputColour(0).w = 0.7;
#if FOG
float fogValue = shSaturate((depth - fogParams.y) * fogParams.w);
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue);
#endif
}
#endif
#else
// Inspired by Blender GLSL Water by martinsh ( http://devlog-martinsh.blogspot.de/2012/07/waterundewater-shader-wip.html )
#define SHADOWS_PSSM @shGlobalSettingBool(shadows_pssm)
#define SHADOWS @shGlobalSettingBool(shadows)
#if SHADOWS || SHADOWS_PSSM
#include "shadows.h"
#endif
#define RIPPLES 1
#define REFRACTION @shGlobalSettingBool(refraction)
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix)
shVertexInput(float2, uv0)
shOutput(float2, UV)
shOutput(float3, screenCoordsPassthrough)
shOutput(float4, position)
shOutput(float, depthPassthrough)
#if SHADOWS
shOutput(float4, lightSpacePos0)
shUniform(float4x4, texViewProjMatrix0) @shAutoConstant(texViewProjMatrix0, texture_viewproj_matrix)
#endif
#if SHADOWS_PSSM
@shForeach(3)
shOutput(float4, lightSpacePos@shIterator)
shUniform(float4x4, texViewProjMatrix@shIterator) @shAutoConstant(texViewProjMatrix@shIterator, texture_viewproj_matrix, @shIterator)
@shEndForeach
#endif
#if SHADOWS || SHADOWS_PSSM
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
#endif
SH_START_PROGRAM
{
shOutputPosition = shMatrixMult(wvp, shInputPosition);
UV = uv0;
#if !SH_GLSL
float4x4 scalemat = float4x4( 0.5, 0, 0, 0.5,
0, -0.5, 0, 0.5,
0, 0, 0.5, 0.5,
0, 0, 0, 1 );
#else
mat4 scalemat = mat4(0.5, 0.0, 0.0, 0.0,
0.0, -0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0);
#endif
float4 texcoordProj = shMatrixMult(scalemat, shOutputPosition);
screenCoordsPassthrough = float3(texcoordProj.x, texcoordProj.y, texcoordProj.w);
position = shInputPosition;
depthPassthrough = shOutputPosition.z;
#if SHADOWS
lightSpacePos0 = shMatrixMult(texViewProjMatrix0, shMatrixMult(worldMatrix, shInputPosition));
#endif
#if SHADOWS_PSSM
float4 wPos = shMatrixMult(worldMatrix, shInputPosition);
@shForeach(3)
lightSpacePos@shIterator = shMatrixMult(texViewProjMatrix@shIterator, wPos);
@shEndForeach
#endif
}
#else
// tweakables ----------------------------------------------------
#define VISIBILITY 1500.0 // how far you can look through water
#define BIG_WAVES_X 0.3 // strength of big waves
#define BIG_WAVES_Y 0.3
#define MID_WAVES_X 0.3 // strength of middle sized waves
#define MID_WAVES_Y 0.15
#define SMALL_WAVES_X 0.15 // strength of small waves
#define SMALL_WAVES_Y 0.1
#define WAVE_CHOPPYNESS 0.15 // wave choppyness
#define WAVE_SCALE 75 // overall wave scale
#define BUMP 1.5 // overall water surface bumpiness
#define REFL_BUMP 0.08 // reflection distortion amount
#define REFR_BUMP 0.06 // refraction distortion amount
#define SCATTER_AMOUNT 0.3 // amount of sunlight scattering
#define SCATTER_COLOUR float3(0.0,1.0,0.95) // colour of sunlight scattering
#define SUN_EXT float3(0.45, 0.55, 0.68) //sunlight extinction
#define SPEC_HARDNESS 256 // specular highlights hardness
// ---------------------------------------------------------------
float fresnel_dielectric(float3 Incoming, float3 Normal, float eta)
{
/* compute fresnel reflectance without explicitly computing
the refracted direction */
float c = abs(dot(Incoming, Normal));
float g = eta * eta - 1.0 + c * c;
float result;
if(g > 0.0) {
g = sqrt(g);
float A =(g - c)/(g + c);
float B =(c *(g + c)- 1.0)/(c *(g - c)+ 1.0);
result = 0.5 * A * A *(1.0 + B * B);
}
else
result = 1.0; /* TIR (no refracted component) */
return result;
}
SH_BEGIN_PROGRAM
shInput(float2, UV)
shInput(float3, screenCoordsPassthrough)
shInput(float4, position)
shInput(float, depthPassthrough)
#if RIPPLES
shUniform(float3, rippleCenter) @shSharedParameter(rippleCenter, rippleCenter)
shUniform(float, rippleAreaLength) @shSharedParameter(rippleAreaLength, rippleAreaLength)
#endif
shUniform(float, far) @shAutoConstant(far, far_clip_distance)
shSampler2D(reflectionMap)
#if REFRACTION
shSampler2D(refractionMap)
#endif
shSampler2D(depthMap)
shSampler2D(normalMap)
#if RIPPLES
shSampler2D(rippleNormalMap)
shUniform(float4x4, wMat) @shAutoConstant(wMat, world_matrix)
#endif
shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed)
#define WIND_SPEED windDir_windSpeed.z
#define WIND_DIR windDir_windSpeed.xy
shUniform(float, waterTimer) @shSharedParameter(waterTimer)
shUniform(float2, waterSunFade_sunHeight) @shSharedParameter(waterSunFade_sunHeight)
shUniform(float4, sunPosition) @shAutoConstant(sunPosition, light_position, 0)
shUniform(float4, sunSpecular) @shAutoConstant(sunSpecular, light_specular_colour, 0)
shUniform(float, renderTargetFlipping) @shAutoConstant(renderTargetFlipping, render_target_flipping)
shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour)
shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params)
shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position_object_space)
#if SHADOWS
shInput(float4, lightSpacePos0)
shSampler2D(shadowMap0)
shUniform(float2, invShadowmapSize0) @shAutoConstant(invShadowmapSize0, inverse_texture_size, 1)
#endif
#if SHADOWS_PSSM
@shForeach(3)
shInput(float4, lightSpacePos@shIterator)
shSampler2D(shadowMap@shIterator)
shUniform(float2, invShadowmapSize@shIterator) @shAutoConstant(invShadowmapSize@shIterator, inverse_texture_size, @shIterator(1))
@shEndForeach
shUniform(float3, pssmSplitPoints) @shSharedParameter(pssmSplitPoints)
#endif
#if SHADOWS || SHADOWS_PSSM
shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart)
#endif
SH_START_PROGRAM
{
#if SHADOWS
float shadow = depthShadowPCF (shadowMap0, lightSpacePos0, invShadowmapSize0);
#endif
#if SHADOWS_PSSM
float shadow = pssmDepthShadow (lightSpacePos0, invShadowmapSize0, shadowMap0, lightSpacePos1, invShadowmapSize1, shadowMap1, lightSpacePos2, invShadowmapSize2, shadowMap2, depthPassthrough, pssmSplitPoints);
#endif
#if SHADOWS || SHADOWS_PSSM
float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y;
float fade = 1-((depthPassthrough - shadowFar_fadeStart.y) / fadeRange);
shadow = (depthPassthrough > shadowFar_fadeStart.x) ? 1.0 : ((depthPassthrough > shadowFar_fadeStart.y) ? 1.0-((1.0-shadow)*fade) : shadow);
#endif
#if !SHADOWS && !SHADOWS_PSSM
float shadow = 1.0;
#endif
float2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z;
screenCoords.y = (1-shSaturate(renderTargetFlipping))+renderTargetFlipping*screenCoords.y;
float2 nCoord = float2(0,0);
nCoord = UV * (WAVE_SCALE * 0.05) + WIND_DIR * waterTimer * (WIND_SPEED*0.04);
float3 normal0 = 2.0 * shSample(normalMap, nCoord + float2(-waterTimer*0.015,-waterTimer*0.005)).rgb - 1.0;
nCoord = UV * (WAVE_SCALE * 0.1) + WIND_DIR * waterTimer * (WIND_SPEED*0.08)-(normal0.xy/normal0.zz)*WAVE_CHOPPYNESS;
float3 normal1 = 2.0 * shSample(normalMap, nCoord + float2(+waterTimer*0.020,+waterTimer*0.015)).rgb - 1.0;
nCoord = UV * (WAVE_SCALE * 0.25) + WIND_DIR * waterTimer * (WIND_SPEED*0.07)-(normal1.xy/normal1.zz)*WAVE_CHOPPYNESS;
float3 normal2 = 2.0 * shSample(normalMap, nCoord + float2(-waterTimer*0.04,-waterTimer*0.03)).rgb - 1.0;
nCoord = UV * (WAVE_SCALE * 0.5) + WIND_DIR * waterTimer * (WIND_SPEED*0.09)-(normal2.xy/normal2.z)*WAVE_CHOPPYNESS;
float3 normal3 = 2.0 * shSample(normalMap, nCoord + float2(+waterTimer*0.03,+waterTimer*0.04)).rgb - 1.0;
nCoord = UV * (WAVE_SCALE* 1.0) + WIND_DIR * waterTimer * (WIND_SPEED*0.4)-(normal3.xy/normal3.zz)*WAVE_CHOPPYNESS;
float3 normal4 = 2.0 * shSample(normalMap, nCoord + float2(-waterTimer*0.02,+waterTimer*0.1)).rgb - 1.0;
nCoord = UV * (WAVE_SCALE * 2.0) + WIND_DIR * waterTimer * (WIND_SPEED*0.7)-(normal4.xy/normal4.zz)*WAVE_CHOPPYNESS;
float3 normal5 = 2.0 * shSample(normalMap, nCoord + float2(+waterTimer*0.1,-waterTimer*0.06)).rgb - 1.0;
float3 normal = (normal0 * BIG_WAVES_X + normal1 * BIG_WAVES_Y +
normal2 * MID_WAVES_X + normal3 * MID_WAVES_Y +
normal4 * SMALL_WAVES_X + normal5 * SMALL_WAVES_Y);
float4 worldPosition = shMatrixMult(wMat, float4(position.xyz, 1));
float2 relPos = (worldPosition.xy - rippleCenter.xy) / rippleAreaLength + 0.5;
float3 normal_ripple = normalize(shSample(rippleNormalMap, relPos.xy).xyz * 2 - 1);
//normal = normalize(normal + normal_ripple);
normal = normalize(float3(normal.x * BUMP + normal_ripple.x, normal.y * BUMP + normal_ripple.y, normal.z));
normal = float3(normal.x, normal.y, -normal.z);
// normal for sunlight scattering
float3 lNormal = (normal0 * BIG_WAVES_X*0.5 + normal1 * BIG_WAVES_Y*0.5 +
normal2 * MID_WAVES_X*0.2 + normal3 * MID_WAVES_Y*0.2 +
normal4 * SMALL_WAVES_X*0.1 + normal5 * SMALL_WAVES_Y*0.1).xyz;
lNormal = normalize(float3(lNormal.x * BUMP, lNormal.y * BUMP, lNormal.z));
lNormal = float3(lNormal.x, lNormal.y, -lNormal.z);
float3 lVec = normalize(sunPosition.xyz);
float3 vVec = normalize(position.xyz - cameraPos.xyz);
float isUnderwater = (cameraPos.z > 0) ? 0.0 : 1.0;
// sunlight scattering
float3 pNormal = float3(0,0,1);
float3 lR = reflect(lVec, lNormal);
float3 llR = reflect(lVec, pNormal);
float s = shSaturate(dot(lR, vVec)*2.0-1.2);
float lightScatter = shadow * shSaturate(dot(-lVec,lNormal)*0.7+0.3) * s * SCATTER_AMOUNT * waterSunFade_sunHeight.x * shSaturate(1.0-exp(-waterSunFade_sunHeight.y));
float3 scatterColour = shLerp(float3(SCATTER_COLOUR)*float3(1.0,0.4,0.0), SCATTER_COLOUR, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT)));
// fresnel
float ior = (cameraPos.z>0)?(1.333/1.0):(1.0/1.333); //air to water; water to air
float fresnel = fresnel_dielectric(-vVec, normal, ior);
fresnel = shSaturate(fresnel);
// reflection
float3 reflection = shSample(reflectionMap, screenCoords+(normal.xy*REFL_BUMP)).rgb;
// refraction
float3 R = reflect(vVec, normal);
#if REFRACTION
float3 refraction = shSample(refractionMap, (screenCoords-(normal.xy*REFR_BUMP))*1.0).rgb;
// brighten up the refraction underwater
refraction = (cameraPos.z < 0) ? shSaturate(refraction * 1.5) : refraction;
#endif
// specular
float specular = pow(max(dot(R, lVec), 0.0),SPEC_HARDNESS) * shadow;
#if REFRACTION
shOutputColour(0).xyz = shLerp( shLerp(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * sunSpecular.xyz;
#else
shOutputColour(0).xyz = shLerp(reflection, float3(0.090195, 0.115685, 0.12745), (1.0-fresnel)*0.5) + specular * sunSpecular.xyz;
#endif
// fog
float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w);
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue);
#if REFRACTION
shOutputColour(0).w = 1;
#else
shOutputColour(0).w = shSaturate(fresnel*2 + specular);
#endif
}
#endif
#endif
#include "core.h"
#define SIMPLE_WATER @shGlobalSettingBool(simple_water)
#if SIMPLE_WATER
// --------------------------------------- SIMPLE WATER ---------------------------------------------------
#define FOG @shGlobalSettingBool(fog)
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix)
shVertexInput(float2, uv0)
shOutput(float2, UV)
#if FOG
shOutput(float, depth)
#endif
SH_START_PROGRAM
{
shOutputPosition = shMatrixMult(wvp, shInputPosition);
UV = uv0;
#if FOG
depth = shOutputPosition.z;
#endif
}
#else
SH_BEGIN_PROGRAM
shSampler2D(animatedTexture)
shInput(float2, UV)
shInput(float, depth)
shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour)
shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params)
SH_START_PROGRAM
{
shOutputColour(0).xyz = shSample(animatedTexture, UV * float2(15.0, 15.0)).xyz * float3(1.0, 1.0, 1.0);
shOutputColour(0).w = 0.7;
#if FOG
float fogValue = shSaturate((depth - fogParams.y) * fogParams.w);
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue);
#endif
}
#endif
#else
// Inspired by Blender GLSL Water by martinsh ( http://devlog-martinsh.blogspot.de/2012/07/waterundewater-shader-wip.html )
#define SHADOWS_PSSM @shGlobalSettingBool(shadows_pssm)
#define SHADOWS @shGlobalSettingBool(shadows)
#if SHADOWS || SHADOWS_PSSM
#include "shadows.h"
#endif
#define RIPPLES 1
#define REFRACTION @shGlobalSettingBool(refraction)
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix)
shVertexInput(float2, uv0)
shOutput(float2, UV)
shOutput(float3, screenCoordsPassthrough)
shOutput(float4, position)
shOutput(float, depthPassthrough)
#if SHADOWS
shOutput(float4, lightSpacePos0)
shUniform(float4x4, texViewProjMatrix0) @shAutoConstant(texViewProjMatrix0, texture_viewproj_matrix)
#endif
#if SHADOWS_PSSM
@shForeach(3)
shOutput(float4, lightSpacePos@shIterator)
shUniform(float4x4, texViewProjMatrix@shIterator) @shAutoConstant(texViewProjMatrix@shIterator, texture_viewproj_matrix, @shIterator)
@shEndForeach
#endif
#if SHADOWS || SHADOWS_PSSM
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
#endif
SH_START_PROGRAM
{
shOutputPosition = shMatrixMult(wvp, shInputPosition);
UV = uv0;
#if !SH_GLSL
float4x4 scalemat = float4x4( 0.5, 0.0, 0.0, 0.5,
0.0, -0.5, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5,
0.0, 0.0, 0.0, 1.0 );
#else
mat4 scalemat = mat4(0.5, 0.0, 0.0, 0.0,
0.0, -0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0);
#endif
float4 texcoordProj = shMatrixMult(scalemat, shOutputPosition);
screenCoordsPassthrough = float3(texcoordProj.x, texcoordProj.y, texcoordProj.w);
position = shInputPosition;
depthPassthrough = shOutputPosition.z;
#if SHADOWS
lightSpacePos0 = shMatrixMult(texViewProjMatrix0, shMatrixMult(worldMatrix, shInputPosition));
#endif
#if SHADOWS_PSSM
float4 wPos = shMatrixMult(worldMatrix, shInputPosition);
@shForeach(3)
lightSpacePos@shIterator = shMatrixMult(texViewProjMatrix@shIterator, wPos);
@shEndForeach
#endif
}
#else
// tweakables ----------------------------------------------------
#define VISIBILITY 1500.0 // how far you can look through water
#define BIG_WAVES_X 0.3 // strength of big waves
#define BIG_WAVES_Y 0.3
#define MID_WAVES_X 0.3 // strength of middle sized waves
#define MID_WAVES_Y 0.15
#define SMALL_WAVES_X 0.15 // strength of small waves
#define SMALL_WAVES_Y 0.1
#define WAVE_CHOPPYNESS 0.15 // wave choppyness
#define WAVE_SCALE 75.0 // overall wave scale
#define BUMP 1.5 // overall water surface bumpiness
#define REFL_BUMP 0.08 // reflection distortion amount
#define REFR_BUMP 0.06 // refraction distortion amount
#define SCATTER_AMOUNT 0.3 // amount of sunlight scattering
#define SCATTER_COLOUR float3(0.0,1.0,0.95) // colour of sunlight scattering
#define SUN_EXT float3(0.45, 0.55, 0.68) //sunlight extinction
#define SPEC_HARDNESS 256.0 // specular highlights hardness
// ---------------------------------------------------------------
float fresnel_dielectric(float3 Incoming, float3 Normal, float eta)
{
/* compute fresnel reflectance without explicitly computing
the refracted direction */
float c = abs(dot(Incoming, Normal));
float g = eta * eta - 1.0 + c * c;
float result;
if(g > 0.0) {
g = sqrt(g);
float A =(g - c)/(g + c);
float B =(c *(g + c)- 1.0)/(c *(g - c)+ 1.0);
result = 0.5 * A * A *(1.0 + B * B);
}
else
result = 1.0; /* TIR (no refracted component) */
return result;
}
SH_BEGIN_PROGRAM
shInput(float2, UV)
shInput(float3, screenCoordsPassthrough)
shInput(float4, position)
shInput(float, depthPassthrough)
#if RIPPLES
shUniform(float3, rippleCenter) @shSharedParameter(rippleCenter, rippleCenter)
shUniform(float, rippleAreaLength) @shSharedParameter(rippleAreaLength, rippleAreaLength)
#endif
shUniform(float, far) @shAutoConstant(far, far_clip_distance)
shSampler2D(reflectionMap)
#if REFRACTION
shSampler2D(refractionMap)
#endif
shSampler2D(depthMap)
shSampler2D(normalMap)
#if RIPPLES
shSampler2D(rippleNormalMap)
shUniform(float4x4, wMat) @shAutoConstant(wMat, world_matrix)
#endif
shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed)
#define WIND_SPEED windDir_windSpeed.z
#define WIND_DIR windDir_windSpeed.xy
shUniform(float, waterTimer) @shSharedParameter(waterTimer)
shUniform(float2, waterSunFade_sunHeight) @shSharedParameter(waterSunFade_sunHeight)
shUniform(float4, sunPosition) @shAutoConstant(sunPosition, light_position, 0)
shUniform(float4, sunSpecular) @shAutoConstant(sunSpecular, light_specular_colour, 0)
shUniform(float, renderTargetFlipping) @shAutoConstant(renderTargetFlipping, render_target_flipping)
shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour)
shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params)
shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position_object_space)
#if SHADOWS
shInput(float4, lightSpacePos0)
shSampler2D(shadowMap0)
shUniform(float2, invShadowmapSize0) @shAutoConstant(invShadowmapSize0, inverse_texture_size, 1)
#endif
#if SHADOWS_PSSM
@shForeach(3)
shInput(float4, lightSpacePos@shIterator)
shSampler2D(shadowMap@shIterator)
shUniform(float2, invShadowmapSize@shIterator) @shAutoConstant(invShadowmapSize@shIterator, inverse_texture_size, @shIterator(1))
@shEndForeach
shUniform(float3, pssmSplitPoints) @shSharedParameter(pssmSplitPoints)
#endif
#if SHADOWS || SHADOWS_PSSM
shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart)
#endif
SH_START_PROGRAM
{
#if SHADOWS
float shadow = depthShadowPCF (shadowMap0, lightSpacePos0, invShadowmapSize0);
#endif
#if SHADOWS_PSSM
float shadow = pssmDepthShadow (lightSpacePos0, invShadowmapSize0, shadowMap0, lightSpacePos1, invShadowmapSize1, shadowMap1, lightSpacePos2, invShadowmapSize2, shadowMap2, depthPassthrough, pssmSplitPoints);
#endif
#if SHADOWS || SHADOWS_PSSM
float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y;
float fade = 1.0-((depthPassthrough - shadowFar_fadeStart.y) / fadeRange);
shadow = (depthPassthrough > shadowFar_fadeStart.x) ? 1.0 : ((depthPassthrough > shadowFar_fadeStart.y) ? 1.0-((1.0-shadow)*fade) : shadow);
#endif
#if !SHADOWS && !SHADOWS_PSSM
float shadow = 1.0;
#endif
float2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z;
screenCoords.y = (1.0-shSaturate(renderTargetFlipping))+renderTargetFlipping*screenCoords.y;
float2 nCoord = float2(0.0,0.0);
nCoord = UV * (WAVE_SCALE * 0.05) + WIND_DIR * waterTimer * (WIND_SPEED*0.04);
float3 normal0 = 2.0 * shSample(normalMap, nCoord + float2(-waterTimer*0.015,-waterTimer*0.005)).rgb - 1.0;
nCoord = UV * (WAVE_SCALE * 0.1) + WIND_DIR * waterTimer * (WIND_SPEED*0.08)-(normal0.xy/normal0.zz)*WAVE_CHOPPYNESS;
float3 normal1 = 2.0 * shSample(normalMap, nCoord + float2(+waterTimer*0.020,+waterTimer*0.015)).rgb - 1.0;
nCoord = UV * (WAVE_SCALE * 0.25) + WIND_DIR * waterTimer * (WIND_SPEED*0.07)-(normal1.xy/normal1.zz)*WAVE_CHOPPYNESS;
float3 normal2 = 2.0 * shSample(normalMap, nCoord + float2(-waterTimer*0.04,-waterTimer*0.03)).rgb - 1.0;
nCoord = UV * (WAVE_SCALE * 0.5) + WIND_DIR * waterTimer * (WIND_SPEED*0.09)-(normal2.xy/normal2.z)*WAVE_CHOPPYNESS;
float3 normal3 = 2.0 * shSample(normalMap, nCoord + float2(+waterTimer*0.03,+waterTimer*0.04)).rgb - 1.0;
nCoord = UV * (WAVE_SCALE* 1.0) + WIND_DIR * waterTimer * (WIND_SPEED*0.4)-(normal3.xy/normal3.zz)*WAVE_CHOPPYNESS;
float3 normal4 = 2.0 * shSample(normalMap, nCoord + float2(-waterTimer*0.02,+waterTimer*0.1)).rgb - 1.0;
nCoord = UV * (WAVE_SCALE * 2.0) + WIND_DIR * waterTimer * (WIND_SPEED*0.7)-(normal4.xy/normal4.zz)*WAVE_CHOPPYNESS;
float3 normal5 = 2.0 * shSample(normalMap, nCoord + float2(+waterTimer*0.1,-waterTimer*0.06)).rgb - 1.0;
float3 normal = (normal0 * BIG_WAVES_X + normal1 * BIG_WAVES_Y +
normal2 * MID_WAVES_X + normal3 * MID_WAVES_Y +
normal4 * SMALL_WAVES_X + normal5 * SMALL_WAVES_Y);
float4 worldPosition = shMatrixMult(wMat, float4(position.xyz, 1));
float2 relPos = (worldPosition.xy - rippleCenter.xy) / rippleAreaLength + 0.5;
float3 normal_ripple = normalize(shSample(rippleNormalMap, relPos.xy).xyz * 2.0 - 1.0);
//normal = normalize(normal + normal_ripple);
normal = normalize(float3(normal.x * BUMP + normal_ripple.x, normal.y * BUMP + normal_ripple.y, normal.z));
normal = float3(normal.x, normal.y, -normal.z);
// normal for sunlight scattering
float3 lNormal = (normal0 * BIG_WAVES_X*0.5 + normal1 * BIG_WAVES_Y*0.5 +
normal2 * MID_WAVES_X*0.2 + normal3 * MID_WAVES_Y*0.2 +
normal4 * SMALL_WAVES_X*0.1 + normal5 * SMALL_WAVES_Y*0.1).xyz;
lNormal = normalize(float3(lNormal.x * BUMP, lNormal.y * BUMP, lNormal.z));
lNormal = float3(lNormal.x, lNormal.y, -lNormal.z);
float3 lVec = normalize(sunPosition.xyz);
float3 vVec = normalize(position.xyz - cameraPos.xyz);
float isUnderwater = (cameraPos.z > 0.0) ? 0.0 : 1.0;
// sunlight scattering
float3 pNormal = float3(0,0,1);
float3 lR = reflect(lVec, lNormal);
float3 llR = reflect(lVec, pNormal);
float s = shSaturate(dot(lR, vVec)*2.0-1.2);
float lightScatter = shadow * shSaturate(dot(-lVec,lNormal)*0.7+0.3) * s * SCATTER_AMOUNT * waterSunFade_sunHeight.x * shSaturate(1.0-exp(-waterSunFade_sunHeight.y));
float3 scatterColour = shLerp(float3(SCATTER_COLOUR)*float3(1.0,0.4,0.0), SCATTER_COLOUR, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT)));
// fresnel
float ior = (cameraPos.z>0.0)?(1.333/1.0):(1.0/1.333); //air to water; water to air
float fresnel = fresnel_dielectric(-vVec, normal, ior);
fresnel = shSaturate(fresnel);
// reflection
float3 reflection = shSample(reflectionMap, screenCoords+(normal.xy*REFL_BUMP)).rgb;
// refraction
float3 R = reflect(vVec, normal);
#if REFRACTION
float3 refraction = shSample(refractionMap, (screenCoords-(normal.xy*REFR_BUMP))*1.0).rgb;
// brighten up the refraction underwater
refraction = (cameraPos.z < 0.0) ? shSaturate(refraction * 1.5) : refraction;
#endif
// specular
float specular = pow(max(dot(R, lVec), 0.0),SPEC_HARDNESS) * shadow;
#if REFRACTION
shOutputColour(0).xyz = shLerp( shLerp(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * sunSpecular.xyz;
#else
shOutputColour(0).xyz = shLerp(reflection, float3(0.090195, 0.115685, 0.12745), (1.0-fresnel)*0.5) + specular * sunSpecular.xyz;
#endif
// fog
float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w);
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue);
#if REFRACTION
shOutputColour(0).w = 1.0;
#else
shOutputColour(0).w = shSaturate(fresnel*2.0 + specular);
#endif
}
#endif
#endif

Loading…
Cancel
Save