diff --git a/CMakeLists.txt b/CMakeLists.txt index 723d10b347..b3439d1a53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,6 +202,7 @@ link_directories(${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR}) add_subdirectory( extern/caelum ) add_subdirectory( extern/mygui_3.0.1 ) +add_subdirectory( files/) # Make sure that certain libraries are used as static libraries # This is in effect turns off __declspec (dllexport) for windows diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e17a2cb25f..f1d940253d 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -16,7 +16,7 @@ set(GAME_HEADER source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender - renderingmanager debugging sky player npcs creatures objects renderinginterface + renderingmanager debugging sky player npcs creatures objects renderinginterface water ) add_openmw_dir (mwinput diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp new file mode 100644 index 0000000000..acfda488bc --- /dev/null +++ b/apps/openmw/mwrender/water.cpp @@ -0,0 +1,104 @@ +#include "water.hpp" + +namespace MWRender { + Water::Water (Ogre::Camera *camera) : mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()) { + + try { + Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "Water", -1); + Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false); + } catch(...) { + } + mIsUnderwater = false; + + mCamera->addListener(this); + + + for (unsigned int i = 0; i < 2; i++) { + Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().createManual(i == 0 ? "refraction" : "reflection", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 512, 512, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); + + Ogre::RenderTarget* rtt = tex->getBuffer()->getRenderTarget(); + rtt->addViewport(mCamera)->setOverlaysEnabled(false); + rtt->addListener(this); + + if (i == 0) mRefractionTarget = rtt; + else mReflectionTarget = rtt; + } + + + mWaterPlane = Ogre::Plane(Ogre::Vector3::UNIT_Y, 0); + Ogre::MeshManager::getSingleton().createPlane("water", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mWaterPlane, 7000, 7000, 10, 10, true, 1, 3, 5, Ogre::Vector3::UNIT_Z); + + + mWater = mSceneManager->createEntity("Water", "water"); + mWater->setMaterialName("Water/ReflectionRefraction"); + mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode(); + mWaterNode->attachObject(mWater); + + } + + + Water::~Water() { + Ogre::MeshManager::getSingleton().remove("water"); + Ogre::TextureManager::getSingleton().remove("refraction"); + Ogre::TextureManager::getSingleton().remove("reflection"); + Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport); + } + + + void Water::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) { + mWater->setVisible(false); + + if (evt.source == mReflectionTarget) { + mCamera->enableReflection(mWaterPlane); + } else { + } + } + + void Water::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) { + mWater->setVisible(true); + + if (evt.source == mReflectionTarget) { + mCamera->disableReflection(); + } else { + } + } + + void Water::checkUnderwater() { + Ogre::Vector3 pos = mCamera->getPosition(); + if (mIsUnderwater && pos.y > 0) { + try { + Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false); + } catch(...) { + } + std::cout << "Removing water compositor" << "\n"; + mIsUnderwater = false; + } + + if (!mIsUnderwater && pos.y < 0) { + try { + Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", true); + } catch(...) { + } + mIsUnderwater = true; + std::cout << "Adding water compositor" << "\n"; + } + } + + + void Water::cameraPreRenderScene(Ogre::Camera *cam) { + Ogre::Vector3 pos = cam->getPosition(); + + if (pos != mOldCameraPos) { + mWaterNode->setPosition(pos.x, 0, pos.z); + + mOldCameraPos = pos; + } + } + + void Water::cameraPostRenderScene(Ogre::Camera *cam) { + } + + void Water::cameraDestroyed(Ogre::Camera *cam) { + } + +} diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp new file mode 100644 index 0000000000..8e04ca3c81 --- /dev/null +++ b/apps/openmw/mwrender/water.hpp @@ -0,0 +1,45 @@ +#ifndef GAME_MWRENDER_WATER_H +#define GAME_MWRENDER_WATER_H + +#include + + +namespace MWRender { + + /// Water rendering + class Water : Ogre::RenderTargetListener, Ogre::Camera::Listener { + Ogre::Camera *mCamera; + Ogre::SceneManager *mSceneManager; + Ogre::Viewport *mViewport; + + Ogre::RenderTarget *mRefractionTarget; + Ogre::RenderTarget *mReflectionTarget; + + Ogre::Plane mWaterPlane; + Ogre::SceneNode *mWaterNode; + Ogre::Entity *mWater; + + Ogre::Vector3 mOldCameraPos; + bool mIsUnderwater; + + + + void preRenderTargetUpdate(const Ogre::RenderTargetEvent&); + void postRenderTargetUpdate(const Ogre::RenderTargetEvent&); + + void cameraPreRenderScene(Ogre::Camera *cam); + void cameraPostRenderScene(Ogre::Camera *cam); + void cameraDestroyed(Ogre::Camera *cam); + + public: + + Water (Ogre::Camera *camera); + ~Water(); + + void checkUnderwater(); + + + }; +} + +#endif diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index c9d477833b..152e001302 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -15,30 +15,6 @@ namespace { - - -template -void insertCellRefList (T& cellRefList, ESMS::CellStore &cell) -{ - if (!cellRefList.list.empty()) - { - //const MWWorld::Class& class_ = MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell)); - - for (typename T::List::iterator it = cellRefList.list.begin(); - it != cellRefList.list.end(); it++) - { - if (it->mData.getCount() || it->mData.isEnabled()) - { - MWWorld::Ptr ptr (&*it, &cell); - /* TODO: call - * RenderingManager.insertObject - * class_.insertObjectPhysic - * class_.insertObjectMechanics - */ - } - } - } -} template void insertCellRefList(MWRender::RenderingManager& rendering, MWWorld::Environment& environment, T& cellRefList, ESMS::CellStore &cell, MWWorld::PhysicsSystem& physics) @@ -76,20 +52,22 @@ void insertCellRefList(MWRender::RenderingManager& rendering, MWWorld::Environme namespace MWWorld { - + void Scene::unloadCell (CellStoreCollection::iterator iter) { - + std::cout << "Unloading cell\n"; ListHandles functor; - + MWWorld::Ptr::CellStore* active = *iter; - mRendering.removeCell(active); + + + active->forEach(functor); - { + { + - // silence annoying g++ warning for (std::vector::const_iterator iter (functor.mHandles.begin()); iter!=functor.mHandles.end(); ++iter){ @@ -97,10 +75,13 @@ namespace MWWorld mPhysics->removeObject (node->getName()); } } + mRendering.removeCell(active); + //mPhysics->removeObject("Unnamed_43"); mWorld->getLocalScripts().clearCell (active); mEnvironment.mMechanicsManager->dropActors (active); mEnvironment.mSoundManager->stopSound (active); - mActiveCells.erase (iter); + mActiveCells.erase(active); + } void Scene::loadCell (Ptr::CellStore *cell) @@ -108,18 +89,18 @@ namespace MWWorld // register local scripts mWorld->getLocalScripts().addCell (cell); - + std::pair result = mActiveCells.insert(cell); if(result.second){ insertCell(*cell, mEnvironment); - mRendering.getObjects().buildStaticGeometry(*cell); + //mRendering.cellAdded (cell); mRendering.configureAmbient(*cell); - + } - - + + } void Scene::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, @@ -140,15 +121,13 @@ namespace MWWorld mEnvironment.mMechanicsManager->removeActor (mWorld->getPlayer().getPlayer()); CellStoreCollection::iterator active = mActiveCells.begin(); - Ptr::CellStore* cellstore = *active; - + while (active!=mActiveCells.end()) { - cellstore = *active; - if (!(cellstore->cell->data.flags & ESM::Cell::Interior)) + if (!((*active)->cell->data.flags & ESM::Cell::Interior)) { - if (std::abs (X-cellstore->cell->data.gridX)<=1 && - std::abs (Y-cellstore->cell->data.gridY)<=1) + if (std::abs (X-(*active)->cell->data.gridX)<=1 && + std::abs (Y-(*active)->cell->data.gridY)<=1) { // keep cells within the new 3x3 grid ++active; @@ -164,15 +143,13 @@ namespace MWWorld for (int y=Y-1; y<=Y+1; ++y) { CellStoreCollection::iterator iter = mActiveCells.begin(); - while (iter!=mActiveCells.end()) { - cellstore = *iter; - assert (!(cellstore->cell->data.flags & ESM::Cell::Interior)); + assert (!((*iter)->cell->data.flags & ESM::Cell::Interior)); - if (x==cellstore->cell->data.gridX && - y==cellstore->cell->data.gridY) + if (x==(*iter)->cell->data.gridX && + y==(*iter)->cell->data.gridY) break; ++iter; @@ -188,15 +165,13 @@ namespace MWWorld // find current cell CellStoreCollection::iterator iter = mActiveCells.begin(); - while (iter!=mActiveCells.end()) { - cellstore = *iter; - assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); + assert (!((*iter)->cell->data.flags & ESM::Cell::Interior)); - if (X==cellstore->cell->data.gridX && - Y==cellstore->cell->data.gridY) + if (X==(*iter)->cell->data.gridX && + Y==(*iter)->cell->data.gridY) break; ++iter; @@ -204,7 +179,7 @@ namespace MWWorld assert (iter!=mActiveCells.end()); - mCurrentCell = cellstore; + mCurrentCell = *iter; // adjust player playerCellChange (mWorld->getExterior(X, Y), position, adjustPlayerPos); @@ -215,10 +190,10 @@ namespace MWWorld mCellChanged = true; } - //We need the ogre renderer and a scene node. + //We need the ogre renderer and a scene node. Scene::Scene (Environment& environment, World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics) - : mRendering(rendering), mCurrentCell (0), - mCellChanged (false), mEnvironment (environment), mWorld(world), mPhysics(physics) + : mCurrentCell (0), mCellChanged (false), mEnvironment (environment), mWorld(world), + mPhysics(physics), mRendering(rendering) { } @@ -241,7 +216,7 @@ namespace MWWorld std::cout << "Changing to interior\n"; // remove active CellStoreCollection::iterator active = mActiveCells.begin(); - std::cout << "Size: " << mActiveCells.size() << "\n"; + while (active!=mActiveCells.end()) { unloadCell (active++); @@ -261,7 +236,6 @@ namespace MWWorld mWorld->adjustSky(); mCellChanged = true; - //currentRegion->name = ""; } void Scene::changeToExteriorCell (const ESM::Position& position) @@ -284,38 +258,6 @@ namespace MWWorld mCellChanged = false; } -/*#include -#include -#include - -#include "../mwworld/class.hpp" -#include "../mwworld/ptr.hpp"*/ - -void Scene::insertCell(ESMS::CellStore &cell) -{ - // Loop through all references in the cell - insertCellRefList (cell.activators, cell); - insertCellRefList (cell.potions, cell); - insertCellRefList (cell.appas, cell); - insertCellRefList (cell.armors, cell); - insertCellRefList (cell.books, cell); - insertCellRefList (cell.clothes, cell); - insertCellRefList (cell.containers, cell); - insertCellRefList (cell.creatures, cell); - insertCellRefList (cell.doors, cell); - insertCellRefList (cell.ingreds, cell); - insertCellRefList (cell.creatureLists, cell); - insertCellRefList (cell.itemLists, cell); - insertCellRefList (cell.lights, cell); - insertCellRefList (cell.lockpicks, cell); - insertCellRefList (cell.miscItems, cell); - insertCellRefList (cell.npcs, cell); - insertCellRefList (cell.probes, cell); - insertCellRefList (cell.repairs, cell); - insertCellRefList (cell.statics, cell); - insertCellRefList(cell.weapons, cell); -} - void Scene::insertCell(ESMS::CellStore &cell, MWWorld::Environment& environment) { diff --git a/files/CMakeLists.txt b/files/CMakeLists.txt new file mode 100644 index 0000000000..720044df8d --- /dev/null +++ b/files/CMakeLists.txt @@ -0,0 +1,12 @@ +project(resources) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/caustic_0.png "${OpenMW_BINARY_DIR}/resources/water/caustic_0.png" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/Example_Fresnel.cg "${OpenMW_BINARY_DIR}/resources/water/Example_Fresnel.cg" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/Example_FresnelPS.asm "${OpenMW_BINARY_DIR}/resources/water/Example_FresnelPS.asm" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/GlassFP.cg "${OpenMW_BINARY_DIR}/resources/water/GlassFP.cg" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/GlassVP.cg "${OpenMW_BINARY_DIR}/resources/water/GlassVP.cg" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/perlinvolume.dds "${OpenMW_BINARY_DIR}/resources/water/perlinvolume.dds" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/Water02.jpg "${OpenMW_BINARY_DIR}/resources/water/Water02.jpg" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.compositor "${OpenMW_BINARY_DIR}/resources/water/water.compositor" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.material "${OpenMW_BINARY_DIR}/resources/water/water.material" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/waves2.dds "${OpenMW_BINARY_DIR}/resources/water/waves2.dds" COPYONLY) diff --git a/files/plugins.cfg.linux b/files/plugins.cfg.linux index b6e104351d..2921153b4f 100644 --- a/files/plugins.cfg.linux +++ b/files/plugins.cfg.linux @@ -7,6 +7,6 @@ PluginFolder=${OGRE_PLUGIN_DIR} Plugin=RenderSystem_GL Plugin=Plugin_ParticleFX Plugin=Plugin_OctreeSceneManager -# Plugin=Plugin_CgProgramManager +Plugin=Plugin_CgProgramManager diff --git a/files/water/Example_Fresnel.cg b/files/water/Example_Fresnel.cg new file mode 100644 index 0000000000..e091fc5878 --- /dev/null +++ b/files/water/Example_Fresnel.cg @@ -0,0 +1,116 @@ +// Vertex program for fresnel reflections / refractions +void main_vp( + float4 pos : POSITION, + float4 normal : NORMAL, + float2 tex : TEXCOORD0, + + out float4 oPos : POSITION, + out float3 noiseCoord : TEXCOORD0, + out float4 projectionCoord : TEXCOORD1, + out float3 oEyeDir : TEXCOORD2, + out float3 oNormal : TEXCOORD3, + + uniform float4x4 worldViewProjMatrix, + uniform float3 eyePosition, // object space + uniform float timeVal, + uniform float scale, // the amount to scale the noise texture by + uniform float scroll, // the amount by which to scroll the noise + uniform float noise // the noise perturb as a factor of the time + ) +{ + oPos = mul(worldViewProjMatrix, pos); + // Projective texture coordinates, adjust for mapping + 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); + projectionCoord = mul(scalemat, oPos); + // Noise map coords + noiseCoord.xy = (tex + (timeVal * scroll)) * scale; + noiseCoord.z = noise * timeVal; + + oEyeDir = normalize(pos.xyz - eyePosition); + oNormal = normal.rgb; + +} + +// Fragment program for distorting a texture using a 3D noise texture +void main_fp( + float3 noiseCoord : TEXCOORD0, + float4 projectionCoord : TEXCOORD1, + float3 eyeDir : TEXCOORD2, + float3 normal : TEXCOORD3, + + out float4 col : COLOR, + + uniform float4 tintColour, + uniform float noiseScale, + uniform float fresnelBias, + uniform float fresnelScale, + uniform float fresnelPower, + uniform sampler2D waterTex : register(s0), + uniform sampler2D noiseMap : register(s1), + uniform sampler2D reflectMap : register(s2), + uniform sampler2D refractMap : register(s3) + ) +{ + // Do the tex projection manually so we can distort _after_ + float2 final = projectionCoord.xy / projectionCoord.w; + + // Noise + float3 noiseNormal = (tex2D(noiseMap, (noiseCoord.xy / 5)).rgb - 0.5).rbg * noiseScale; + final += noiseNormal.xz; + + // Fresnel + //normal = normalize(normal + noiseNormal.xz); + float fresnel = fresnelBias + fresnelScale * pow(1 + dot(eyeDir, normal), fresnelPower); + + // Reflection / refraction + float4 reflectionColour = tex2D(reflectMap, final); + float4 refractionColour = tex2D(refractMap, final) + tintColour; + + // Final colour + col = lerp(refractionColour, reflectionColour, fresnel) * tex2D(waterTex, noiseNormal) / 3 ; + + +} + + +// Old version to match ATI PS 1.3 implementation +void main_vp_old( + float4 pos : POSITION, + float4 normal : NORMAL, + float2 tex : TEXCOORD0, + + out float4 oPos : POSITION, + out float fresnel : COLOR, + out float3 noiseCoord : TEXCOORD0, + out float4 projectionCoord : TEXCOORD1, + + uniform float4x4 worldViewProjMatrix, + uniform float3 eyePosition, // object space + uniform float fresnelBias, + uniform float fresnelScale, + uniform float fresnelPower, + uniform float timeVal, + uniform float scale, // the amount to scale the noise texture by + uniform float scroll, // the amount by which to scroll the noise + uniform float noise // the noise perturb as a factor of the time + ) +{ + oPos = mul(worldViewProjMatrix, pos); + // Projective texture coordinates, adjust for mapping + 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); + projectionCoord = mul(scalemat, oPos); + // Noise map coords + noiseCoord.xy = (tex + (timeVal * scroll)) * scale; + noiseCoord.z = noise * timeVal; + + // calc fresnel factor (reflection coefficient) + float3 eyeDir = normalize(pos.xyz - eyePosition); + fresnel = fresnelBias + fresnelScale * pow(1 + dot(eyeDir, normal), fresnelPower); + +} diff --git a/files/water/Example_FresnelPS.asm b/files/water/Example_FresnelPS.asm new file mode 100644 index 0000000000..2de078ef5a --- /dev/null +++ b/files/water/Example_FresnelPS.asm @@ -0,0 +1,72 @@ +ps.1.4 + // conversion from Cg generated ARB_fragment_program to ps.1.4 by NFZ + // command line args: -profile arbfp1 -entry main_fp + // program main_fp + // c0 : distortionRange + // c1 : tintColour + // testure 0 : noiseMap + // texture 1 : reflectMap + // texture 2 : refractMap + // v0.x : fresnel + // t0.xyz : noiseCoord + // t1.xyw : projectionCoord + +def c2, 2, 1, 0, 0 + + // Cg: distort.x = tex3D(noiseMap, noiseCoord).x; + // arbfp1: TEX R0.x, fragment.texcoord[0], texture[0], 3D; + // sample noise map using noiseCoord in TEX unit 0 + +texld r0, t0.xyz + + // get projected texture coordinates from TEX coord 1 + // will be used in phase 2 + +texcrd r1.xy, t1_dw.xyw +mov r1.z, c2.y + + // Cg: distort.y = tex3D(noiseMap, noiseCoord + yoffset).x; + // arbfp1: ADD R1.xyz, fragment.texcoord[0], c1; + // arbfp1: TEX R1.x, R1, texture[0], 3D; + // arbfp1: MOV R0.y, R1.x; + + // Cg: distort = (distort * 2 - 1) * distortionRange; + // arbfp1: MAD R0.xy, R0, c0.x, -c0.y; + // arbfp1: MUL R0.xy, R0, u0.x; + // (distort * 2 - 1) same as 2*(distort -.5) so use _bx2 + + + // Cg: final = projectionCoord.xy / projectionCoord.w; + // Cg: final += distort; + // arbfp1: RCP R0.w, fragment.texcoord[1].w; + // arbfp1: MAD R0.xy, fragment.texcoord[1], R0.w, R0; + // final = (distort * projectionCoord.w) + projectionCoord.xy + // for ps.1.4 have to re-arrange things a bit to perturb projected texture coordinates + +mad r0.xyz, r0_bx2, c0.x, r1 + +phase + + // do dependant texture reads + // Cg: reflectionColour = tex2D(reflectMap, final); + // arbfp1: TEX R0, R0, texture[1], 2D; + // sampe reflectMap using dependant read : texunit 1 + +texld r1, r0.xyz + + // Cg: refractionColour = tex2D(refractMap, final) + tintColour; + // arbfp1: TEX R1, R0, texture[2], 2D; + // sample refractMap : texunit 2 + +texld r2, r0.xyz + + // adding tintColour that is in global c1 + // arbfp1: ADD R1, R1, u1; + +add r2, r2, c1 + + // Cg: col = lerp(refractionColour, reflectionColour, fresnel); + // arbfp1: ADD R0, R0, -R1; + // arbfp1: MAD result.color, fragment.color.primary.x, R0, R1; + +lrp r0, v0.x, r1, r2 diff --git a/files/water/GlassFP.cg b/files/water/GlassFP.cg new file mode 100644 index 0000000000..eb18885d25 --- /dev/null +++ b/files/water/GlassFP.cg @@ -0,0 +1,15 @@ +sampler RT : register(s0); +sampler NormalMap : register(s1); +sampler CausticMap : register(s2); + +float4 main_ps(float2 iTexCoord : TEXCOORD0, + float3 noiseCoord : TEXCOORD1, + uniform float4 tintColour) : COLOR +{ + float4 normal = tex2D(NormalMap, noiseCoord); + + + return tex2D(RT, iTexCoord + normal.xy * 0.05) + + (tex2D(CausticMap, noiseCoord) / 5) + + tintColour ; +} diff --git a/files/water/GlassVP.cg b/files/water/GlassVP.cg new file mode 100644 index 0000000000..71153769c2 --- /dev/null +++ b/files/water/GlassVP.cg @@ -0,0 +1,24 @@ +void glass_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; +} + diff --git a/files/water/Water02.jpg b/files/water/Water02.jpg new file mode 100644 index 0000000000..3efda7b6a8 Binary files /dev/null and b/files/water/Water02.jpg differ diff --git a/files/water/caustic_0.png b/files/water/caustic_0.png new file mode 100644 index 0000000000..fee464860e Binary files /dev/null and b/files/water/caustic_0.png differ diff --git a/files/water/perlinvolume.dds b/files/water/perlinvolume.dds new file mode 100644 index 0000000000..bd8147d49f Binary files /dev/null and b/files/water/perlinvolume.dds differ diff --git a/files/water/water.compositor b/files/water/water.compositor new file mode 100644 index 0000000000..67bf908960 --- /dev/null +++ b/files/water/water.compositor @@ -0,0 +1,21 @@ +compositor Water +{ + 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/Compositor + input 0 rt0 + } + } + } +} diff --git a/files/water/water.material b/files/water/water.material new file mode 100644 index 0000000000..9929feabc3 --- /dev/null +++ b/files/water/water.material @@ -0,0 +1,217 @@ +// Derived from ogre samples + + +vertex_program Water/GlassVP cg +{ + source GlassVP.cg + entry_point glass_vp + profiles vs_1_1 arbvp1 + + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + } +} + + +fragment_program Water/GlassFP cg +{ + source GlassFP.cg + entry_point main_ps + profiles ps_2_0 arbfp1 +} + +material Water/Compositor +{ + technique + { + pass + { + depth_check off + + vertex_program_ref Water/GlassVP + { + param_named_auto timeVal time 0.25 + param_named scale float 0.1 + } + + fragment_program_ref Water/GlassFP + { + param_named tintColour float4 0 0.35 0.35 1 + } + + texture_unit RT + { + tex_coord_set 0 + tex_address_mode clamp + filtering linear linear linear + } + + texture_unit + { + texture WaterNormal1.tga 2d + tex_coord_set 1 + //tex_address_mode clamp + filtering linear linear linear + } + texture_unit + { + texture caustic_0.png 2d + tex_coord_set 2 + //tex_address_mode clamp + filtering linear linear linear + } + } + } +} + + + + + + + +vertex_program Water/RefractReflectVP cg +{ + source Example_Fresnel.cg + entry_point main_vp + profiles vs_1_1 arbvp1 +} +vertex_program Water/RefractReflectVPold cg +{ + source Example_Fresnel.cg + entry_point main_vp_old + profiles vs_1_1 arbvp1 +} + +fragment_program Water/RefractReflectFP cg +{ + source Example_Fresnel.cg + entry_point main_fp + // sorry, ps_1_1 and fp20 can't do this + profiles ps_2_0 arbfp1 +} + +fragment_program Water/RefractReflectPS asm +{ + source Example_FresnelPS.asm + // sorry, only for ps_1_4 :) + syntax ps_1_4 + +} + + +material Water/ReflectionRefraction +{ + // ps_2_0 / arbfp1 + technique + { + pass + { + + vertex_program_ref Water/RefractReflectVP + { + param_named_auto worldViewProjMatrix worldviewproj_matrix + param_named_auto eyePosition camera_position_object_space + param_named_auto timeVal time 0.15 + param_named scroll float 1 + param_named scale float 1 + param_named noise float 1 + // scroll and noisePos will need updating per frame + } + fragment_program_ref Water/RefractReflectFP + { + param_named fresnelBias float -0.1 + param_named fresnelScale float 0.8 + param_named fresnelPower float 20 + param_named tintColour float4 0 0.15 0.15 1 + param_named noiseScale float 0.05 + } + // Water + texture_unit + { + // Water texture + texture Water02.jpg + // min / mag filtering, no mip + filtering linear linear none + } + // Noise + texture_unit + { + // Perlin noise volume + texture waves2.dds + // min / mag filtering, no mip + filtering linear linear none + } + // Reflection + texture_unit + { + // Will be filled in at runtime + texture reflection + tex_address_mode clamp + } + // Refraction + texture_unit + { + // Will be filled in at runtime + texture refraction + tex_address_mode clamp + } + } + + + } + + // ATI 8500 + + technique + { + pass + { + vertex_program_ref Water/RefractReflectVPold + { + param_named_auto worldViewProjMatrix worldviewproj_matrix + param_named_auto eyePosition camera_position_object_space + param_named fresnelBias float -0.3 + param_named fresnelScale float 1.4 + param_named fresnelPower float 8 + param_named_auto timeVal time_0_1 20 + param_named scroll float 1 + param_named scale float 4 + param_named noise float 1 + // scroll and noisePos will need updating per frame + } + + // for ATI RADEON 8500 - 9200 + fragment_program_ref Water/RefractReflectPS + { + // distortionRange + param_indexed 0 float 0.025 + // tintColour + param_indexed 1 float4 0.05 0.12 0.15 1 + } + + // Noise + texture_unit + { + // Perlin noise volume + texture perlinvolume.dds 3d + // min / mag filtering, no mip + filtering linear linear none + } + // Reflection + texture_unit + { + // Will be filled in at runtime + texture Reflection + tex_address_mode clamp + } + // Refraction + texture_unit + { + // Will be filled in at runtime + texture Refraction + tex_address_mode clamp + } + } + } +} diff --git a/files/water/waves2.dds b/files/water/waves2.dds new file mode 100644 index 0000000000..c379886fae Binary files /dev/null and b/files/water/waves2.dds differ