diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 86584cc22..993ec6623 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -261,7 +261,7 @@ int main(int argc, char**argv) boost::filesystem::current_path(bundlePath); #endif - //try + try { Files::ConfigurationManager cfgMgr; OMW::Engine engine(cfgMgr); @@ -271,11 +271,11 @@ int main(int argc, char**argv) engine.go(); } } - /*catch (std::exception &e) + catch (std::exception &e) { std::cout << "\nERROR: " << e.what() << std::endl; return 1; - }*/ + } return 0; } diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 3ef89d422..96cdef4cc 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -209,7 +209,7 @@ namespace MWGui mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}"); - mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect objects", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect statics", "Water") ? "#{sOn}" : "#{sOff}"); mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}"); mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}"); diff --git a/apps/openmw/mwrender/renderconst.hpp b/apps/openmw/mwrender/renderconst.hpp index 457b6e601..9f57833bb 100644 --- a/apps/openmw/mwrender/renderconst.hpp +++ b/apps/openmw/mwrender/renderconst.hpp @@ -18,7 +18,7 @@ enum RenderQueueGroups RQG_OcclusionQuery = Ogre::RENDER_QUEUE_6, - RQG_UnderWater = Ogre::RENDER_QUEUE_7, + RQG_UnderWater = Ogre::RENDER_QUEUE_4, RQG_Water = Ogre::RENDER_QUEUE_7+1, @@ -49,8 +49,8 @@ enum VisibilityFlags RV_Sky = 64, - // Sun glare (not visible in reflection) - RV_Glare = 128, + // not visible in reflection + RV_NoReflection = 128, RV_OcclusionQuery = 256, diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 916ccb0c0..e1ff91a24 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -725,14 +725,9 @@ void RenderingManager::applyCompositors() { mCompositors->addCompositor("gbuffer", 0); mCompositors->setCompositorEnabled("gbuffer", true); - mCompositors->addCompositor("Underwater", 1); mCompositors->addCompositor("gbufferFinalizer", 2); mCompositors->setCompositorEnabled("gbufferFinalizer", true); } - else - { - mCompositors->addCompositor("UnderwaterNoMRT", 0); - } if (mWater) mWater->assignTextures(); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index f84c12b4e..25928cf3f 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -307,7 +307,7 @@ void SkyManager::create() mSun->setRenderQueue(RQG_SkiesEarly+4); mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4, 0.4, 0.4), mRootNode, "openmw_sun"); mSunGlare->setRenderQueue(RQG_SkiesLate); - mSunGlare->setVisibilityFlags(RV_Glare); + mSunGlare->setVisibilityFlags(RV_NoReflection); // Stars MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif"); @@ -389,7 +389,6 @@ void SkyManager::update(float duration) sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer", sh::makeProperty(new sh::FloatValue(mCloudAnimationTimer))); - /// \todo improve this mMasser->setPhase( static_cast( (int) ((mDay % 32)/4.f)) ); mSecunda->setPhase ( static_cast( (int) ((mDay % 32)/4.f)) ); @@ -559,6 +558,10 @@ void SkyManager::setSunDirection(const Vector3& direction) if (!mCreated) return; mSun->setPosition(direction); mSunGlare->setPosition(direction); + + float height = direction.z; + float fade = ( height > 0.5) ? 1.0 : height * 2; + sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(fade, height))); } void SkyManager::setMasserDirection(const Vector3& direction) @@ -607,6 +610,7 @@ void SkyManager::setLightningStrength(const float factor) void SkyManager::setLightningDirection(const Ogre::Vector3& dir) { + if (!mCreated) return; mLightning->setDirection (dir); } @@ -653,3 +657,10 @@ void SkyManager::scaleSky(float scale) { mRootNode->setScale(scale, scale, scale); } + +void SkyManager::setGlareEnabled (bool enabled) +{ + if (!mCreated) + return; + mSunGlare->setVisible (mSunEnabled && enabled); +} diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 4a0a7b36b..d785c6eb6 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -164,6 +164,7 @@ namespace MWRender void setLightningDirection(const Ogre::Vector3& dir); void setGlare(const float glare); + void setGlareEnabled(bool enabled); Ogre::Vector3 getRealSunPos(); void setSkyPosition(const Ogre::Vector3& position); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 90967c886..bdf61e96d 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -28,7 +28,7 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mIsUnderwater(false), mVisibilityFlags(0), mReflectionTarget(0), mActive(1), mToggled(1), mReflectionRenderActive(false), mRendering(rend), - mOldFarClip(0), + mOldFarClip(0), mOldFarClip2(0), mWaterTimer(0.f) { mSky = rend->getSkyManager(); @@ -73,8 +73,9 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel underwaterDome->setRenderQueueGroup (RQG_UnderWater); mUnderwaterDome = mSceneManager->getRootSceneNode ()->createChildSceneNode (); mUnderwaterDome->attachObject (underwaterDome); - mUnderwaterDome->setScale(100,100,100); + mUnderwaterDome->setScale(10000,10000,10000); mUnderwaterDome->setVisible(false); + underwaterDome->setMaterialName("Underwater_Dome"); mSceneManager->addRenderQueueListener(this); @@ -162,7 +163,12 @@ void Water::changeCell(const ESM::Cell* cell) void Water::setHeight(const float height) { mTop = height; + mWaterPlane = Plane(Vector3::UNIT_Y, height); + + // small error due to reflection texture size & reflection distortion + mErrorPlane = Plane(Vector3::UNIT_Y, height - 5); + mWaterNode->setPosition(0, height, 0); sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty(new sh::FloatValue(height))); } @@ -177,39 +183,16 @@ void Water::checkUnderwater(float y) { if (!mActive) { - mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false); return; } if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID) { - //mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false); - - // tell the shader we are not underwater - -/* - Ogre::Pass* pass = mMaterial->getTechnique(0)->getPass(0); - if (pass->hasFragmentProgram() && pass->getFragmentProgramParameters()->_findNamedConstantDefinition("isUnderwater", false)) - pass->getFragmentProgramParameters()->setNamedConstant("isUnderwater", Real(0)); -*/ - mWater->setRenderQueueGroup(RQG_Water); - mIsUnderwater = false; } if (!mIsUnderwater && y < mTop && mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID) { - //if (mUnderwaterEffect) - //mRendering->getCompositors()->setCompositorEnabled(mCompositorName, true); - - // tell the shader we are underwater -/* - Ogre::Pass* pass = mMaterial->getTechnique(0)->getPass(0); - if (pass->hasFragmentProgram() && pass->getFragmentProgramParameters()->_findNamedConstantDefinition("isUnderwater", false)) - pass->getFragmentProgramParameters()->setNamedConstant("isUnderwater", Real(1)); -*/ - //mWater->setRenderQueueGroup(RQG_UnderWater); - mIsUnderwater = true; } @@ -308,24 +291,36 @@ void Water::updateVisible() void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) { // We don't want the sky to get clipped by custom near clip plane (the water plane) - if (queueGroupId < 20 && mReflectionRenderActive) + if (((queueGroupId < 20) || queueGroupId == RQG_UnderWater) && mReflectionRenderActive) { mOldFarClip = mReflectionCamera->getFarClipDistance (); mReflectionCamera->disableCustomNearClipPlane(); mReflectionCamera->setFarClipDistance (1000000000); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); } + else if (queueGroupId == RQG_UnderWater) + {/* + mOldFarClip2 = mCamera->getFarClipDistance (); + mCamera->setFarClipDistance (1000000000); + Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); + */} } void Water::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation) { - if (queueGroupId < 20 && mReflectionRenderActive) + if (((queueGroupId < 20) || queueGroupId == RQG_UnderWater) && mReflectionRenderActive) { mReflectionCamera->setFarClipDistance (mOldFarClip); if (!mIsUnderwater) - mReflectionCamera->enableCustomNearClipPlane(mWaterPlane); + mReflectionCamera->enableCustomNearClipPlane(mErrorPlane); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); } + if (queueGroupId == RQG_UnderWater) + { + /* + mCamera->setFarClipDistance (mOldFarClip2); + Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); + */} } void Water::update(float dt) @@ -336,6 +331,8 @@ void Water::update(float dt) mWaterTimer += dt; sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty(new sh::FloatValue(mWaterTimer))); + + mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater); } void Water::applyRTT() @@ -366,8 +363,6 @@ void Water::applyRTT() mReflectionTarget = rtt; } - - mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT"; } void Water::applyVisibilityMask() diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index ac837ca0d..6d0001119 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -36,6 +36,8 @@ namespace MWRender { Ogre::SceneManager *mSceneManager; Ogre::Plane mWaterPlane; + Ogre::Plane mErrorPlane; + Ogre::SceneNode *mWaterNode; Ogre::Entity *mWater; @@ -47,6 +49,7 @@ namespace MWRender { int mTop; int mOldFarClip; + int mOldFarClip2; float mWaterTimer; diff --git a/files/gbuffer/gbuffer.cg b/files/gbuffer/gbuffer.cg deleted file mode 100644 index c7f2fe678..000000000 --- a/files/gbuffer/gbuffer.cg +++ /dev/null @@ -1,18 +0,0 @@ -void RenderScene_vs(in float4 position : POSITION - ,in float2 uv :TEXCOORD0 - ,uniform float4x4 wvp - ,out float4 oPosition : POSITION - ,out float2 oUV :TEXCOORD0) -{ - oPosition = mul(wvp, position); - oUV = uv; -} - -void RenderScene_ps(in float4 position : POSITION - ,in float2 uv :TEXCOORD0 - ,uniform sampler2D tex1 : TEXUNIT0 - ,out float4 oColor : COLOR) -{ - float4 scene =tex2D(tex1, uv); - oColor= scene; -} diff --git a/files/gbuffer/gbuffer.compositor b/files/gbuffer/gbuffer.compositor index 19b890fec..b3d80e9d5 100644 --- a/files/gbuffer/gbuffer.compositor +++ b/files/gbuffer/gbuffer.compositor @@ -29,7 +29,7 @@ compositor gbuffer pass render_quad { - material RenderScene + material quad input 0 mrt_output 0 } } @@ -61,7 +61,7 @@ compositor gbufferFinalizer } pass render_quad { - material RenderSceneNoDepth + material quad_noDepthWrite input 0 previousscene } pass render_scene @@ -78,7 +78,7 @@ compositor gbufferFinalizer } pass render_quad { - material RenderSceneNoDepth + material quad_noDepthWrite input 0 no_mrt_output } } diff --git a/files/gbuffer/gbuffer.material b/files/gbuffer/gbuffer.material deleted file mode 100644 index faa8dd498..000000000 --- a/files/gbuffer/gbuffer.material +++ /dev/null @@ -1,63 +0,0 @@ -vertex_program RenderGBuffer_vs cg -{ - source gbuffer.cg - profiles vs_4_0 vs_1_1 arbvp1 - entry_point RenderScene_vs - default_params - { - param_named_auto wvp worldviewproj_matrix - } -} -fragment_program RenderGBuffer_ps cg -{ - source gbuffer.cg - entry_point RenderScene_ps - profiles ps_4_0 ps_2_x arbfp1 - default_params - { - } -} -material RenderScene -{ - technique - { - pass - { - vertex_program_ref RenderGBuffer_vs - { - } - - fragment_program_ref RenderGBuffer_ps - { - } - - texture_unit tex1 - { - //scenebuffer - } - } - } -} - -material RenderSceneNoDepth -{ - technique - { - pass - { - depth_write off - vertex_program_ref RenderGBuffer_vs - { - } - - fragment_program_ref RenderGBuffer_ps - { - } - - texture_unit tex1 - { - //scenebuffer - } - } - } -} diff --git a/files/materials/caustics.h b/files/materials/caustics.h deleted file mode 100644 index d6be680f0..000000000 --- a/files/materials/caustics.h +++ /dev/null @@ -1,117 +0,0 @@ -#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 0.01 // overall wave scale - -#define ABBERATION 0.001 // chromatic abberation amount - -float3 intercept(float3 lineP, - float3 lineN, - float3 planeN, - float planeD) -{ - - float distance = (planeD - dot(planeN, lineP)) / dot(lineN, planeN); - return lineP + lineN * distance; -} - -float3 perturb1(shTexture2D tex, float2 coords, float bend, float2 windDir, float windSpeed, float timer) -{ - float2 nCoord = float2(0.0); - bend *= WAVE_CHOPPYNESS; - nCoord = coords * (WAVE_SCALE * 0.05) + windDir * timer * (windSpeed*0.04); - float3 normal0 = 2.0 * shSample(tex, nCoord + float2(-timer*0.015,-timer*0.05)).rgb - 1.0; - nCoord = coords * (WAVE_SCALE * 0.1) + windDir * timer * (windSpeed*0.08)-normal0.xy*bend; - float3 normal1 = 2.0 * shSample(tex, nCoord + float2(+timer*0.020,+timer*0.015)).rgb - 1.0; - - nCoord = coords * (WAVE_SCALE * 0.25) + windDir * timer * (windSpeed*0.07)-normal1.xy*bend; - float3 normal2 = 2.0 * shSample(tex, nCoord + float2(-timer*0.04,-timer*0.03)).rgb - 1.0; - nCoord = coords * (WAVE_SCALE * 0.5) + windDir * timer * (windSpeed*0.09)-normal2.xy*bend; - float3 normal3 = 2.0 * shSample(tex, nCoord + float2(+timer*0.03,+timer*0.04)).rgb - 1.0; - - nCoord = coords * (WAVE_SCALE* 1.0) + windDir * timer * (windSpeed*0.4)-normal3.xy*bend; - float3 normal4 = 2.0 * shSample(tex, nCoord + float2(-timer*0.2,+timer*0.1)).rgb - 1.0; - nCoord = coords * (WAVE_SCALE * 2.0) + windDir * timer * (windSpeed*0.7)-normal4.xy*bend; - float3 normal5 = 2.0 * shSample(tex, nCoord + float2(+timer*0.1,-timer*0.06)).rgb - 1.0; - - - float3 normal = normalize(normal0 * BIG_WAVES_X + normal1 * BIG_WAVES_Y + - normal2 * MID_WAVES_X + normal3 * MID_WAVES_Y + - normal4 * SMALL_WAVES_X + normal5 * SMALL_WAVES_Y); - return normal; -} - -float3 perturb(shTexture2D tex, float2 coords, float bend, float2 windDir, float windSpeed, float timer) -{ - bend *= WAVE_CHOPPYNESS; - float3 col = float3(0.0); - float2 nCoord = float2(0.0); //normal coords - - nCoord = coords * (WAVE_SCALE * 0.025) + windDir * timer * (windSpeed*0.03); - col += shSample(tex,nCoord + float2(-timer*0.005,-timer*0.01)).rgb*0.20; - nCoord = coords * (WAVE_SCALE * 0.1) + windDir * timer * (windSpeed*0.05)-(col.xy/col.zz)*bend; - col += shSample(tex,nCoord + float2(+timer*0.01,+timer*0.005)).rgb*0.20; - - nCoord = coords * (WAVE_SCALE * 0.2) + windDir * timer * (windSpeed*0.1)-(col.xy/col.zz)*bend; - col += shSample(tex,nCoord + float2(-timer*0.02,-timer*0.03)).rgb*0.20; - nCoord = coords * (WAVE_SCALE * 0.5) + windDir * timer * (windSpeed*0.2)-(col.xy/col.zz)*bend; - col += shSample(tex,nCoord + float2(+timer*0.03,+timer*0.02)).rgb*0.15; - - nCoord = coords * (WAVE_SCALE* 0.8) + windDir * timer * (windSpeed*1.0)-(col.xy/col.zz)*bend; - col += shSample(tex, nCoord + float2(-timer*0.06,+timer*0.08)).rgb*0.15; - nCoord = coords * (WAVE_SCALE * 1.0) + windDir * timer * (windSpeed*1.3)-(col.xy/col.zz)*bend; - col += shSample(tex,nCoord + float2(+timer*0.08,-timer*0.06)).rgb*0.10; - - return col; -} - - -float3 getCaustics (shTexture2D causticMap, float3 worldPos, float3 eyePosWS, float3 worldNormal, float3 lightDirectionWS0, float waterLevel, float waterTimer, float3 windDir_windSpeed) -{ - float3 waterEyePos = intercept(worldPos.xyz, eyePosWS - worldPos, float3(0,1,0), waterLevel); - float waterDepth = shSaturate((waterEyePos.y - worldPos.y) / 50.0); - - float3 causticPos = intercept(worldPos.xyz, lightDirectionWS0.xyz, float3(0,1,0), waterLevel); - - ///\ todo clean this up - float causticdepth = length(causticPos-worldPos.xyz); - causticdepth = 1.0-shSaturate(causticdepth / VISIBILITY); - causticdepth = shSaturate(causticdepth); - - // NOTE: the original shader calculated a tangent space basis here, - // but using only the world normal is cheaper and i couldn't see a visual difference - // also, if this effect gets moved to screen-space some day, it's unlikely to have tangent information - float3 causticNorm = worldNormal.xyz * perturb(causticMap, causticPos.xz, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).xzy * 2 - 1; - - //float fresnel = pow(clamp(dot(LV,causticnorm),0.0,1.0),2.0); - - float NdotL = max(dot(worldNormal.xyz, lightDirectionWS0.xyz),0.0); - - float causticR = 1.0-perturb(causticMap, causticPos.xz, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z; - - /// \todo sunFade - - // float3 caustics = clamp(pow(float3(causticR)*5.5,float3(5.5*causticdepth)),0.0,1.0)*NdotL*sunFade*causticdepth; - float3 caustics = clamp(pow(float3(causticR)*5.5,float3(5.5*causticdepth)),0.0,1.0)*NdotL*causticdepth; - float causticG = 1.0-perturb(causticMap,causticPos.xz+(1.0-causticdepth)*ABBERATION, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z; - float causticB = 1.0-perturb(causticMap,causticPos.xz+(1.0-causticdepth)*ABBERATION*2.0, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z; - //caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth)))*NdotL*sunFade*causticdepth; - caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth)))*NdotL*causticdepth; - - caustics *= 3; - - // shore transition - caustics = shLerp (float3(1,1,1), caustics, waterDepth); - - return caustics; -} - diff --git a/files/materials/objects.mat b/files/materials/objects.mat index 9b0357f01..f1198b4a2 100644 --- a/files/materials/objects.mat +++ b/files/materials/objects.mat @@ -11,9 +11,6 @@ material openmw_objects_base scene_blend default depth_write default alpha_rejection default - shadow_transparency true // use diffuse alpha as mask for shadow - - shadow_caster_material openmw_shadowcaster pass { diff --git a/files/materials/objects.shader b/files/materials/objects.shader index fdf2b3676..f40094fa7 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -94,7 +94,7 @@ // ----------------------------------- FRAGMENT ------------------------------------------ #if UNDERWATER - #include "caustics.h" + #include "underwater.h" #endif SH_BEGIN_PROGRAM @@ -163,7 +163,8 @@ shSampler2D(causticMap) shUniform(float, waterTimer) @shSharedParameter(waterTimer) - + shUniform(float2, waterSunFade_sunHeight) @shSharedParameter(waterSunFade_sunHeight) + shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed) #endif @@ -262,22 +263,30 @@ shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0,0,0)); #if UNDERWATER - float fogAmount = (worldPos.y > waterLevel) + float fogAmount = (cameraPos.y > waterLevel) ? shSaturate(length(waterEyePos-worldPos) / VISIBILITY) : shSaturate(length(cameraPos.xyz-worldPos)/ VISIBILITY); float3 eyeVec = normalize(cameraPos.xyz-worldPos); + float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); - waterSunGradient = clamp(pow(waterSunGradient*0.7+0.3,2.0),0.0,1.0); + waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); + float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; - float waterGradient = dot(eyeVec, vec3(0.0,-1.0,0.0)); + float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - - float3 waterSunColour = vec3(0.0,1.0,0.85)*waterSunGradient; - waterSunColour = (cameraPos.z < waterLevel) ? waterSunColour*0.5:waterSunColour*0.25;//below or above water? - - float3 waterColour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; - shOutputColour(0).xyz = waterColour; + float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; + float3 waterext = float3(0.6, 0.9, 1.0);//water extinction + watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); + watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3; + + + float darkness = VISIBILITY*2.0; + darkness = clamp((waterEyePos.y - waterLevel + darkness)/darkness,0.2,1.0); + watercolour *= darkness; + + float isUnderwater = (worldPos.y < waterLevel) ? 1.0 : 0.0; + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater); #endif #if MRT diff --git a/files/materials/quad.mat b/files/materials/quad.mat new file mode 100644 index 000000000..1ada37bc4 --- /dev/null +++ b/files/materials/quad.mat @@ -0,0 +1,22 @@ +material quad +{ + depth_write on + + pass + { + vertex_program quad_vertex + fragment_program quad_fragment + + depth_write $depth_write + + texture_unit SceneBuffer + { + } + } +} + +material quad_noDepthWrite +{ + parent quad + depth_write off +} diff --git a/files/materials/quad.shader b/files/materials/quad.shader new file mode 100644 index 000000000..4fa38cac9 --- /dev/null +++ b/files/materials/quad.shader @@ -0,0 +1,25 @@ +#include "core.h" + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM + shInput(float2, uv0) + shOutput(float2, UV) + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + SH_START_PROGRAM + { + shOutputPosition = shMatrixMult(wvp, shInputPosition); + UV = uv0; + } + +#else + + SH_BEGIN_PROGRAM + shInput(float2, UV) + shSampler2D(SceneBuffer) + SH_START_PROGRAM + { + shOutputColour(0) = shSample(SceneBuffer, UV); + } + +#endif diff --git a/files/materials/quad.shaderset b/files/materials/quad.shaderset new file mode 100644 index 000000000..a1252b15c --- /dev/null +++ b/files/materials/quad.shaderset @@ -0,0 +1,15 @@ +shader_set quad_vertex +{ + source quad.shader + type vertex + profiles_cg vs_2_0 vp40 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set quad_fragment +{ + source quad.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps fp40 arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 77ba01494..919857401 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -125,7 +125,7 @@ // ----------------------------------- FRAGMENT ------------------------------------------ #if UNDERWATER - #include "caustics.h" + #include "underwater.h" #endif SH_BEGIN_PROGRAM @@ -195,7 +195,8 @@ shSampler2D(causticMap) shUniform(float, waterTimer) @shSharedParameter(waterTimer) - + shUniform(float2, waterSunFade_sunHeight) @shSharedParameter(waterSunFade_sunHeight) + shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed) #endif @@ -226,7 +227,7 @@ if (worldPos.y < waterLevel) { float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); - waterEyePos = intercept(worldPos, eyePosWS - worldPos, float3(0,1,0), waterLevel); + waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,1,0), waterLevel); caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); } @@ -331,9 +332,44 @@ #if FOG float fogValue = shSaturate((depth - fogParams.y) * fogParams.w); + + #if UNDERWATER + // regular fog only if fragment is above water + if (worldPos.y > waterLevel) + #endif shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); #endif + // prevent negative colour output (for example with negative lights) + shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0,0,0)); + +#if UNDERWATER + float fogAmount = (cameraPos.y > waterLevel) + ? shSaturate(length(waterEyePos-worldPos) / VISIBILITY) + : shSaturate(length(cameraPos.xyz-worldPos)/ VISIBILITY); + + float3 eyeVec = normalize(cameraPos.xyz-worldPos); + + float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); + waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); + float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; + + float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); + waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); + float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; + float3 waterext = float3(0.6, 0.9, 1.0);//water extinction + watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); + watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3; + + + float darkness = VISIBILITY*2.0; + darkness = clamp((waterEyePos.y - waterLevel + darkness)/darkness,0.2,1.0); + watercolour *= darkness; + + float isUnderwater = (worldPos.y < waterLevel) ? 1.0 : 0.0; + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater); +#endif + #if MRT shOutputColour(1) = float4(depth / far,1,1,1); diff --git a/files/materials/underwater.h b/files/materials/underwater.h index fa744ac39..fe19ff93b 100644 --- a/files/materials/underwater.h +++ b/files/materials/underwater.h @@ -14,6 +14,8 @@ #define ABBERATION 0.001 // chromatic abberation amount +#define SUN_EXT float3(0.45, 0.55, 0.68) //sunlight extinction + float3 intercept(float3 lineP, float3 lineN, float3 planeN, diff --git a/files/materials/water.mat b/files/materials/water.mat index d74305c73..2ae561d77 100644 --- a/files/materials/water.mat +++ b/files/materials/water.mat @@ -31,3 +31,11 @@ material Water } } } + + +material Underwater_Dome +{ + parent openmw_objects_base + + depth_write off +} diff --git a/files/materials/water.shader b/files/materials/water.shader index 4945770a5..4bfc32421 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -43,6 +43,8 @@ // 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 @@ -57,15 +59,15 @@ #define ABBERATION 0.001 // chromatic abberation amount #define BUMP 1.5 // overall water surface bumpiness - #define REFL_BUMP 0.11 // reflection distortion amount - #define REFR_BUMP 0.08 // refraction distortion amount + #define REFL_BUMP 0.08 // reflection distortion amount + #define REFR_BUMP 0.06 // refraction distortion amount #define SCATTER_AMOUNT 3.0 // 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 + #define SPEC_HARDNESS 256 // specular highlights hardness // --------------------------------------------------------------- @@ -201,16 +203,6 @@ // brighten up the refraction underwater refraction = (cameraPos.y < 0) ? shSaturate(refraction * 1.5) : refraction; - - float waterSunGradient = dot(-vVec, -lVec); - waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; - - float waterGradient = dot(-vVec, float3(0.0,-1.0,0.0)); - waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; - float3 waterext = float3(0.6, 0.9, 1.0);//water extinction - watercolour = mix(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); // specular float specular = pow(max(dot(R, lVec), 0.0),SPEC_HARDNESS); @@ -221,8 +213,31 @@ shOutputColour(0).xyz = shLerp(shOutputColour(0).xyz, refraction, (1-shoreFade) * (1-isUnderwater)); // fog - float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); + if (isUnderwater == 1) + { + float waterSunGradient = dot(-vVec, -lVec); + waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); + float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; + + float waterGradient = dot(-vVec, float3(0.0,-1.0,0.0)); + waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); + float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; + float3 waterext = float3(0.6, 0.9, 1.0);//water extinction + watercolour = mix(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); + + float darkness = VISIBILITY*2.0; + darkness = clamp((cameraPos.y+darkness)/darkness,0.2,1.0); + + + float fog = shSaturate(length(cameraPos.xyz-position.xyz) / VISIBILITY); + shOutputColour(0).xyz = shLerp(shOutputColour(0).xyz, watercolour * darkness, shSaturate(fog / waterext)); + } + else + { + float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); + } + } #endif diff --git a/files/water/WaterNormal2.tga b/files/water/WaterNormal2.tga deleted file mode 100644 index 771d15041..000000000 Binary files a/files/water/WaterNormal2.tga and /dev/null differ diff --git a/files/water/caustic_0.png b/files/water/caustic_0.png deleted file mode 100644 index fee464860..000000000 Binary files a/files/water/caustic_0.png and /dev/null differ diff --git a/files/water/perlinvolume.dds b/files/water/perlinvolume.dds deleted file mode 100644 index bd8147d49..000000000 Binary files a/files/water/perlinvolume.dds and /dev/null differ diff --git a/files/water/underwater.cg b/files/water/underwater.cg deleted file mode 100644 index 829d34347..000000000 --- a/files/water/underwater.cg +++ /dev/null @@ -1,61 +0,0 @@ -void main_vp -( - in float4 inPos : POSITION, - - out float4 pos : POSITION, - out float2 uv0 : TEXCOORD0, - out float4 noiseCoord : TEXCOORD1, - - uniform float4x4 worldViewProj, - uniform float timeVal, - uniform float scale -) -{ - // Use standardise transform, so work accord with render system specific (RS depth, requires texture flipping, etc) - pos = mul(worldViewProj, inPos); - - // The input positions adjusted by texel offsets, so clean up inaccuracies - inPos.xy = sign(inPos.xy); - - // Convert to image-space - uv0 = (float2(inPos.x, -inPos.y) + 1.0f) * 0.5f; - noiseCoord = (pos + timeVal) * scale; -} - - - -float4 main_fp_nomrt (float2 iTexCoord : TEXCOORD0, - float3 noiseCoord : TEXCOORD1, - uniform sampler2D RT : register(s0), - uniform sampler2D NormalMap : register(s1), - uniform sampler2D CausticMap : register(s2)) : COLOR -{ - float4 normal = tex2D(NormalMap, noiseCoord) * 2 - 1; - - float4 col = tex2D(RT, iTexCoord + normal.xy * 0.015) + - (tex2D(CausticMap, noiseCoord) / 5); - col.xyz = lerp(col.xyz, float3(0.15, 0.40, 0.40), 0.4); - return col; - -} - - -float4 main_fp (float2 iTexCoord : TEXCOORD0, - float3 noiseCoord : TEXCOORD1, - uniform float far, - uniform sampler2D RT : register(s0), - uniform sampler2D NormalMap : register(s1), - uniform sampler2D CausticMap : register(s2), - uniform sampler2D DepthMap : register(s3)) : COLOR -{ - float4 normal = tex2D(NormalMap, noiseCoord) * 2 - 1; - - float depth = tex2D(DepthMap, iTexCoord + normal.xy * 0.015).r * far; - depth = saturate(depth / 2000.f); - - float4 color = tex2D(RT, iTexCoord + normal.xy * 0.015) + - (tex2D(CausticMap, noiseCoord) / 5); - color.xyz = lerp(color.xyz, float3(0.15, 0.40, 0.40), 0.4); - - return lerp(color, float4(0.15, 0.40, 0.40, 1), depth); -} diff --git a/files/water/water.cg b/files/water/water.cg deleted file mode 100644 index ad0ff57f7..000000000 --- a/files/water/water.cg +++ /dev/null @@ -1,121 +0,0 @@ -void main_vp -( - in float4 iPos : POSITION - , in float2 iUv : TEXCOORD0 - - , out float4 oPos : POSITION - , out float3 oScreenCoords : TEXCOORD0 - , out float2 oUv : TEXCOORD1 - , out float oDepth : TEXCOORD2 - , out float4 oEyeVector : TEXCOORD3 - - , uniform float4x4 wvpMat - , uniform float4 camPosObjSpace -) -{ - oPos = mul(wvpMat, iPos); - - oUv = iUv * 10; // uv scale - oDepth = oPos.z; - - 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 ); - float4 texcoordProj = mul(scalemat, oPos); - oScreenCoords = float3(texcoordProj.x, texcoordProj.y, texcoordProj.w); - - oEyeVector = camPosObjSpace - iPos; -} - -void main_fp -( - out float4 oColor : COLOR - - , in float3 iScreenCoords : TEXCOORD0 - , in float2 iUv : TEXCOORD1 - , in float iDepth : TEXCOORD2 - , in float4 iEyeVector : TEXCOORD3 - , uniform float renderTargetFlipping - , uniform float4 lightPosObjSpace0 - , uniform float4 lightSpecularColour0 - - , uniform sampler2D reflectionMap : register(s0) - , uniform sampler2D refractionMap : register(s1) - , uniform sampler2D depthMap : register(s2) - , uniform sampler2D normalMap : register(s3) - , uniform float time - , uniform float far - , uniform float4 fogParams - , uniform float4 fogColour - , uniform float isUnderwater -) -{ - - float2 screenCoords = iScreenCoords.xy / iScreenCoords.z; - screenCoords.y = (1-saturate(renderTargetFlipping))+renderTargetFlipping*screenCoords.y; - - // No need for transparency since we are using a refraction map - oColor.a = 1; - - // Sample screen-space depth map and subtract pixel depth to get the real water depth - float depthTex = tex2D(depthMap, screenCoords).r; - float depth1 = depthTex * far - iDepth; - depth1 = saturate(depth1 / 500.f); - - // Simple wave effect. to be replaced by something better - float2 uv1 = iUv + time * float2(0.5, 0); - float2 uv2 = iUv + time * float2(0, 0.5); - float2 uv3 = iUv + time * float2(-0.5, 0); - float2 uv4 = iUv + time * float2(0, -0.5); - float4 normal = tex2D(normalMap, uv1) + tex2D(normalMap, uv2) + tex2D(normalMap, uv3) + tex2D(normalMap, uv4); - normal = normal / 4.f; - normal = 2*normal - 1; - - float2 screenCoords_reflect = screenCoords + normal.yx * 0.05; - float2 screenCoords_refract = screenCoords + normal.yx * 0.05 * depth1; - - // Sample depth again with the refracted coordinates - depthTex = tex2D(depthMap, screenCoords_refract).r; - float depth2 = (depthTex * far - iDepth) / 500.f; - depth2 = (depthTex == 0 ? 1 : depth2); - // if depth2 is less than 0, this means we would refract something which is above water, - // which we don't want to - so in that case, don't refract - if (depth2 < 0.25) // delta due to inaccuracies - { - screenCoords_refract = screenCoords; - depth2 = depth1; - } - depth2 = saturate(depth2); - - float4 reflection = tex2D(reflectionMap, screenCoords_reflect); - float4 refraction = tex2D(refractionMap, screenCoords_refract); - - // tangent to object space - normal.xyz = normal.xzy; - - iEyeVector.xyz = normalize(iEyeVector.xyz); - - // fresnel - float facing = 1.0 - max(abs(dot(iEyeVector.xyz, normal.xyz)), 0); - float reflectionFactor = saturate(0.35 + 0.65 * pow(facing, 2)); - - // specular - float3 lightDir = normalize(lightPosObjSpace0.xyz); // assumes that light 0 is a directional light - float3 halfVector = normalize(iEyeVector + lightDir); - float specular = pow(max(dot(normal.xyz, halfVector.xyz), 0), 64); - - float opacity = depth2 * saturate(reflectionFactor + specular); - opacity *= (1-isUnderwater); - - reflection.xyz += lightSpecularColour0.xyz * specular; - - oColor.xyz = lerp(refraction.xyz, reflection.xyz, opacity); - - oColor.xyz = lerp(oColor.xyz, float3(0.15, 0.40, 0.40), isUnderwater*0.6); // underwater tint color - oColor.xyz = lerp(oColor.xyz, float3(0.15, 0.40, 0.40), saturate(isUnderwater * (iDepth / 2000.f))); // underwater fog - - // add fog - //float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); - //oColor.xyz = lerp(oColor.xyz, fogColour, fogValue); -} diff --git a/files/water/water.compositor b/files/water/water.compositor deleted file mode 100644 index 94b778773..000000000 --- a/files/water/water.compositor +++ /dev/null @@ -1,45 +0,0 @@ -compositor UnderwaterNoMRT -{ - technique - { - texture rt0 target_width target_height PF_R8G8B8 - - target rt0 { input previous } - - target_output - { - // Start with clear output - input none - - pass render_quad - { - material Water/CompositorNoMRT - input 0 rt0 - } - } - } -} - - -compositor Underwater -{ - technique - { - texture_ref scene gbuffer mrt_output - texture rt0 target_width target_height PF_R8G8B8 - - target rt0 { input previous } - - target_output - { - // Start with clear output - input none - - pass render_quad - { - material Water/Compositor - input 0 rt0 - } - } - } -}