From 663647bee80d5c80263039107911d11659d03523 Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Wed, 1 Oct 2014 22:55:21 -0500 Subject: [PATCH 01/11] Simplify getEffectMultiplier. Both return cases were same, except for some overflow conditions. --- apps/openmw/mwmechanics/spellcasting.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 373ca7af9..03c30ab15 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -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. From 2f5721bf615cf68d6e13df219e5d08e349066f03 Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Sun, 5 Oct 2014 17:59:53 -0500 Subject: [PATCH 02/11] Fix typo in comments. --- apps/openmw/mwclass/repair.hpp | 2 +- apps/openmw/mwworld/class.hpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 17730d6ec..f89258234 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -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; diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 8ac39eaa9..9e146a142 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -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 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) From aac2de270e55781318dae36f1c4f360ca9b53cbe Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Sun, 5 Oct 2014 18:06:50 -0500 Subject: [PATCH 03/11] Cleanup: Don't call .get(). mEnvironment.get() is redundant. Switch the call to resemble the surrounding environment get() calls, instead. --- apps/openmw/engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 00ad90a02..2eebb8c28 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -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 From 012928c082960d1f12da5ef8a59275ddca6b48ef Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 6 Oct 2014 14:36:29 +0200 Subject: [PATCH 04/11] Fix HasSoulgem function to return number of soulgems --- apps/openmw/mwscript/containerextensions.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 93711d036..96e30e396 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -290,18 +290,15 @@ namespace MWScript const std::string &name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); + int count = 0; MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr); for (MWWorld::ContainerStoreIterator it = invStore.begin(MWWorld::ContainerStore::Type_Miscellaneous); it != invStore.end(); ++it) { - if (::Misc::StringUtils::ciEqual(it->getCellRef().getSoul(), name)) - { - runtime.push(1); - return; - } + ++count; } - runtime.push(0); + runtime.push(count); } }; From 56db525a9399febc171668d13e6c01e2bd806e66 Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Mon, 6 Oct 2014 21:56:41 -0500 Subject: [PATCH 05/11] Document the return value of getEffectMultiplier. --- apps/openmw/mwmechanics/spellcasting.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index 66e91d055..c01fede37 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -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); From f75721a217c164787a5f57b823dd78622db1dd77 Mon Sep 17 00:00:00 2001 From: sylar Date: Tue, 7 Oct 2014 23:30:31 +0400 Subject: [PATCH 06/11] Add none texture filtering .It is fixes a bug with black objects in shaders glsles --- apps/openmw/mwgui/settingswindow.cpp | 4 +++- apps/openmw/mwrender/renderingmanager.cpp | 2 +- files/mygui/openmw_settings_window.layout | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 74def66e3..b87154df8 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -35,8 +35,10 @@ namespace return "Anisotropic"; else if (val == "bilinear") return "Bilinear"; - else + else if (val == "trilinear") return "Trilinear"; + else if (val == "none") + return "None"; } void parseResolution (int &x, int &y, const std::string& str) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 4fbc55089..d449ba0b6 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -122,7 +122,7 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b 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 if (filter == "none") tfo = TFO_NONE; MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 ); diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index fa6485688..d2aac01d2 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -324,6 +324,7 @@ + From 4c46da79de2e77128ea8b7c7557c4d807b329a89 Mon Sep 17 00:00:00 2001 From: sylar Date: Tue, 7 Oct 2014 23:31:22 +0400 Subject: [PATCH 07/11] changed android configs paths --- components/files/androidpath.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/files/androidpath.cpp b/components/files/androidpath.cpp index 52ae73803..e2f9e948a 100644 --- a/components/files/androidpath.cpp +++ b/components/files/androidpath.cpp @@ -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; } From 3a625c567d0ca192877f0ede3b8d2ebbf52b9a77 Mon Sep 17 00:00:00 2001 From: sylar Date: Tue, 7 Oct 2014 23:32:19 +0400 Subject: [PATCH 08/11] fixes for shaders glsles --- files/materials/clouds.shader | 2 +- files/materials/moon.shader | 4 +- files/materials/shadowcaster.shader | 110 ++--- files/materials/stars.shader | 96 ++-- files/materials/water.shader | 740 ++++++++++++++-------------- 5 files changed, 476 insertions(+), 476 deletions(-) diff --git a/files/materials/clouds.shader b/files/materials/clouds.shader index 90c4d0f84..93d0780e0 100644 --- a/files/materials/clouds.shader +++ b/files/materials/clouds.shader @@ -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); } diff --git a/files/materials/moon.shader b/files/materials/moon.shader index d369a1c68..eb7243d3f 100644 --- a/files/materials/moon.shader +++ b/files/materials/moon.shader @@ -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 } diff --git a/files/materials/shadowcaster.shader b/files/materials/shadowcaster.shader index b992366a7..8f7911553 100644 --- a/files/materials/shadowcaster.shader +++ b/files/materials/shadowcaster.shader @@ -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 diff --git a/files/materials/stars.shader b/files/materials/stars.shader index b84d37135..f2eb616a2 100644 --- a/files/materials/stars.shader +++ b/files/materials/stars.shader @@ -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 diff --git a/files/materials/water.shader b/files/materials/water.shader index 418b13715..a6f49e0a1 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -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 From 70fd531722b6e12b27390e9045e683437e0aae87 Mon Sep 17 00:00:00 2001 From: sylar Date: Wed, 8 Oct 2014 00:15:22 +0400 Subject: [PATCH 09/11] None texturing filtering enable for android by default --- apps/openmw/mwgui/settingswindow.cpp | 4 +--- apps/openmw/mwrender/renderingmanager.cpp | 7 +++++-- files/mygui/openmw_settings_window.layout | 1 - 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index b87154df8..74def66e3 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -35,10 +35,8 @@ namespace return "Anisotropic"; else if (val == "bilinear") return "Bilinear"; - else if (val == "trilinear") + else return "Trilinear"; - else if (val == "none") - return "None"; } void parseResolution (int &x, int &y, const std::string& str) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index d449ba0b6..b1e2240ba 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -119,11 +119,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 /*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 ); diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index d2aac01d2..fa6485688 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -324,7 +324,6 @@ - From 8786fb639ff5ce1d1e608ede1f11a746df9319cc Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 8 Oct 2014 17:17:31 +0200 Subject: [PATCH 10/11] Implement terrain rendering in OpenCS (Fixes #1597) --- apps/opencs/CMakeLists.txt | 4 +- apps/opencs/model/world/data.cpp | 33 +++++++++++++++-- apps/opencs/model/world/data.hpp | 12 +++++- apps/opencs/model/world/land.cpp | 28 ++++++++++++++ apps/opencs/model/world/land.hpp | 29 +++++++++++++++ apps/opencs/model/world/landtexture.cpp | 21 +++++++++++ apps/opencs/model/world/landtexture.hpp | 22 +++++++++++ apps/opencs/view/render/cell.cpp | 17 ++++++++- apps/opencs/view/render/cell.hpp | 3 ++ apps/opencs/view/render/terrainstorage.cpp | 43 ++++++++++++++++++++++ apps/opencs/view/render/terrainstorage.hpp | 29 +++++++++++++++ components/esm/loadland.hpp | 2 + components/esm/loadltex.cpp | 6 +++ components/esm/loadltex.hpp | 3 ++ 14 files changed, 244 insertions(+), 8 deletions(-) create mode 100644 apps/opencs/model/world/land.cpp create mode 100644 apps/opencs/model/world/land.hpp create mode 100644 apps/opencs/model/world/landtexture.cpp create mode 100644 apps/opencs/model/world/landtexture.hpp create mode 100644 apps/opencs/view/render/terrainstorage.cpp create mode 100644 apps/opencs/view/render/terrainstorage.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 7094f8799..76d1e9a64 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -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 diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index bb4fa0b43..78349a8db 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -539,6 +539,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getDebugProfiles() return mDebugProfiles; } +const CSMWorld::IdCollection& CSMWorld::Data::getLand() const +{ + return mLand; +} + +const CSMWorld::IdCollection& 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 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 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 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()); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index d0a07c677..aa4e640c2 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -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 mCells; + IdCollection mLandTextures; + IdCollection mLand; RefIdCollection mReferenceables; RefCollection mRefs; IdCollection mFilters; @@ -88,6 +92,8 @@ namespace CSMWorld bool mProject; std::map > mRefLoadCache; + std::vector > mReaders; + // not implemented Data (const Data&); Data& operator= (const Data&); @@ -195,6 +201,10 @@ namespace CSMWorld IdCollection& getDebugProfiles(); + const IdCollection& getLand() const; + + const IdCollection& 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 \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/land.cpp b/apps/opencs/model/world/land.cpp new file mode 100644 index 000000000..119e18761 --- /dev/null +++ b/apps/opencs/model/world/land.cpp @@ -0,0 +1,28 @@ +#include "land.hpp" + +#include + +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 + } + +} diff --git a/apps/opencs/model/world/land.hpp b/apps/opencs/model/world/land.hpp new file mode 100644 index 000000000..e97a2d7dd --- /dev/null +++ b/apps/opencs/model/world/land.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_WORLD_LAND_H +#define CSM_WORLD_LAND_H + +#include +#include +#include + +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 mLand; + + std::string mId; + + /// Loads the metadata and ID + void load (ESM::ESMReader &esm); + + void blank(); + }; +} + +#endif diff --git a/apps/opencs/model/world/landtexture.cpp b/apps/opencs/model/world/landtexture.cpp new file mode 100644 index 000000000..4725866a5 --- /dev/null +++ b/apps/opencs/model/world/landtexture.cpp @@ -0,0 +1,21 @@ +#include "landtexture.hpp" + +#include + +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(); + } + +} diff --git a/apps/opencs/model/world/landtexture.hpp b/apps/opencs/model/world/landtexture.hpp new file mode 100644 index 000000000..b13903186 --- /dev/null +++ b/apps/opencs/model/world/landtexture.hpp @@ -0,0 +1,22 @@ +#ifndef CSM_WORLD_LANDTEXTURE_H +#define CSM_WORLD_LANDTEXTURE_H + +#include + +#include + +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 diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 1e25f42e2..4fd66b14a 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -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::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& 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); -} \ No newline at end of file +} diff --git a/apps/opencs/view/render/cell.hpp b/apps/opencs/view/render/cell.hpp index 70adebe45..e63e09520 100644 --- a/apps/opencs/view/render/cell.hpp +++ b/apps/opencs/view/render/cell.hpp @@ -6,6 +6,8 @@ #include +#include + #include "object.hpp" class QModelIndex; @@ -29,6 +31,7 @@ namespace CSVRender std::string mId; Ogre::SceneNode *mCellNode; std::map mObjects; + std::auto_ptr mTerrain; /// Ignored if cell does not have an object with the given ID. /// diff --git a/apps/opencs/view/render/terrainstorage.cpp b/apps/opencs/view/render/terrainstorage.cpp new file mode 100644 index 000000000..a14eea5dd --- /dev/null +++ b/apps/opencs/view/render/terrainstorage.cpp @@ -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"); + } + +} diff --git a/apps/opencs/view/render/terrainstorage.hpp b/apps/opencs/view/render/terrainstorage.hpp new file mode 100644 index 000000000..97782ad17 --- /dev/null +++ b/apps/opencs/view/render/terrainstorage.hpp @@ -0,0 +1,29 @@ +#ifndef OPENCS_RENDER_TERRAINSTORAGE_H +#define OPENCS_RENDER_TERRAINSTORAGE_H + +#include + +#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 diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 028341ced..019bf4161 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -98,6 +98,8 @@ struct Land void load(ESMReader &esm); void save(ESMWriter &esm) const; + void blank() {} + /** * Actually loads data */ diff --git a/components/esm/loadltex.cpp b/components/esm/loadltex.cpp index bd28c8488..c3e2d50ff 100644 --- a/components/esm/loadltex.cpp +++ b/components/esm/loadltex.cpp @@ -19,4 +19,10 @@ void LandTexture::save(ESMWriter &esm) const esm.writeHNCString("DATA", mTexture); } +void LandTexture::blank() +{ + mTexture.clear(); + mIndex = -1; +} + } diff --git a/components/esm/loadltex.hpp b/components/esm/loadltex.hpp index 5e84428b2..8b45f8211 100644 --- a/components/esm/loadltex.hpp +++ b/components/esm/loadltex.hpp @@ -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; }; From 13f028e27ba8c993b96698792d3b2708d7822469 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 9 Oct 2014 07:01:18 +1100 Subject: [PATCH 11/11] Avoid out of range exceptions. --- apps/opencs/model/world/idtable.cpp | 4 ++-- apps/opencs/view/render/pagedworldspacewidget.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 3a48317ef..c68b71789 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -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(); -} \ No newline at end of file +} diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index ab594826d..a66a1bb7e 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -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(); -} \ No newline at end of file +}