diff --git a/Game.cpp b/Game.cpp index 1000a77..d861a02 100644 --- a/Game.cpp +++ b/Game.cpp @@ -445,6 +445,8 @@ public: } void locateResources() override { + Ogre::ResourceGroupManager::getSingleton().createResourceGroup( + "Water", true); OgreBites::ApplicationContext::locateResources(); } void loadResources() override diff --git a/resources.cfg b/resources.cfg index 3999a48..d83fbfb 100644 --- a/resources.cfg +++ b/resources.cfg @@ -22,7 +22,6 @@ FileSystem=skybox FileSystem=resources/buildings FileSystem=resources/vehicles FileSystem=resources/debug -FileSystem=water # PBR media must come before the scripts that reference it #FileSystem=./Media/PBR #FileSystem=./Media/PBR/filament @@ -77,3 +76,5 @@ FileSystem=./characters/female [Audio] FileSystem=./audio/gui +[Water] +FileSystem=water diff --git a/src/gamedata/WaterModule.cpp b/src/gamedata/WaterModule.cpp index 39b0c9e..729f5f6 100644 --- a/src/gamedata/WaterModule.cpp +++ b/src/gamedata/WaterModule.cpp @@ -1,4 +1,8 @@ #include +#include +#include +#include +#include #include "GameData.h" #include "Components.h" #include "WaterModule.h" @@ -10,7 +14,7 @@ WaterModule::WaterModule(flecs::world &ecs) ecs.module(); ecs.component().add(flecs::Singleton); ecs.component().add(flecs::Singleton); - ecs.set({ nullptr, nullptr }); + ecs.set({ nullptr, nullptr, nullptr }); ecs.set({ nullptr }); ecs.system("UpdateWater") .kind(flecs::OnUpdate) @@ -18,15 +22,171 @@ WaterModule::WaterModule(flecs::world &ecs) WaterSurface &water) { float delta = eng.delta; if (!water.mWaterEnt || !water.mWaterNode) { + water.mAbove = false; + water.mInRefTexUpdate = false; + water.mRenderTargetListener.mSurface = &water; + const Ogre::String renderTargetName = + "ReflectionRefractionTexture"; + water.mWaterPlane = + Ogre::Plane(Ogre::Vector3::UNIT_Y, 0); + water.mReflectionPlane = Ogre::Plane( + Ogre::Vector3(0.0, 1.0, 0.0), + 0.0f /* water height */); + water.mReflectionClipPlaneAbove = Ogre::Plane( + Ogre::Vector3(0.0, 1.0, 0.0), + 0.0f /* water height */ - 2.0f); + water.mReflectionClipPlaneBelow = Ogre::Plane( + Ogre::Vector3(0.0, -1.0, 0.0), + -(0.0f /* water height */ + 2.0)); + water.mRefractionClipPlaneAbove = Ogre::Plane( + Ogre::Vector3(0.0, -1.0, 0.0), + -(0.0f /* water height */ + 2.0)); + water.mRefractionClipPlaneBelow = Ogre::Plane( + Ogre::Vector3(0.0, 1.0, 0.0), + 0.0f /* water height */ - 2.0); +#if 0 + if (Ogre::TextureManager::getSingleton() + .resourceExists(renderTargetName)) + Ogre::TextureManager::getSingleton() + .remove(renderTargetName); +#endif + Ogre::TexturePtr reflectionTexture = + Ogre::TextureManager::getSingleton().createManual( + renderTargetName, + Ogre::ResourceGroupManager:: + DEFAULT_RESOURCE_GROUP_NAME, + Ogre::TEX_TYPE_2D, 512, 512, 0, + Ogre::PF_R8G8B8A8, + Ogre::TU_RENDERTARGET); + + water.mReflectionTexture = + reflectionTexture->getBuffer() + ->getRenderTarget(); + water.mReflectionTexture->setAutoUpdated(false); water.mWaterNode = eng.mScnMgr->getRootSceneNode() ->createChildSceneNode("Water"); + Ogre::MaterialPtr mat = + Ogre::MaterialManager::getSingleton() + .getByName("Water/Above", + "Water"); + if (!mat) { + mat = Ogre::MaterialManager::getSingleton() + .create("Water/Above", + "Water"); + Ogre::Technique *tech = + mat->getTechnique(0); + Ogre::Pass *pass = tech->getPass(0); + pass->setLightingEnabled(true); + pass->setAmbient( + Ogre::ColourValue(1, 1, 1, 1)); + pass->setDiffuse(Ogre::ColourValue( + 0.0f, 0.2f, 0.5f, 1.0f)); + pass->setCullingMode(Ogre::CULL_NONE); + pass->setManualCullingMode( + Ogre::MANUAL_CULL_NONE); + pass->setVertexProgram( + "Water/water_vp"); + pass->setFragmentProgram( + "Water/water_fp"); +#if 0 + Ogre::GpuProgramPtr water_vp = + Ogre::GpuProgramManager::getSingleton() + .getByName( + "Water/water_vp", + Ogre::RGN_AUTODETECT); + OgreAssert(water_vp != nullptr, + "VP failed"); + pass->setGpuProgram( + Ogre::GPT_VERTEX_PROGRAM, + water_vp); + OgreAssert(water_vp->isSupported(), + "VP not supported"); + Ogre::GpuProgramPtr water_fp = + Ogre::GpuProgramManager::getSingleton() + .getByName( + "Water/water_fp", + Ogre::RGN_AUTODETECT); + OgreAssert(water_vp != nullptr, + "FP failed"); + pass->setGpuProgram( + Ogre::GPT_FRAGMENT_PROGRAM, + water_fp); + OgreAssert(water_fp->isSupported(), + "FP not supported"); + Ogre::GpuProgramParametersSharedPtr paramsVP = + water_vp->getDefaultParameters(); + paramsVP->setNamedAutoConstant( + "world", + Ogre::GpuProgramParameters:: + ACT_WORLD_MATRIX); + paramsVP->setNamedAutoConstant( + "worldViewProj", + Ogre::GpuProgramParameters:: + ACT_WORLDVIEWPROJ_MATRIX); + paramsVP->setNamedAutoConstant( + "textureProjMatrix", + Ogre::GpuProgramParameters:: + ACT_TEXTURE_WORLDVIEWPROJ_MATRIX); + paramsVP->setNamedAutoConstant( + "eyePosition", + Ogre::GpuProgramParameters:: + ACT_CAMERA_POSITION_OBJECT_SPACE); + paramsVP->setNamedAutoConstant( + "normalMatrix", + Ogre::GpuProgramParameters:: + ACT_NORMAL_MATRIX); + paramsVP->setNamedAutoConstant( + "worldView", + Ogre::GpuProgramParameters:: + ACT_WORLDVIEW_MATRIX); + paramsVP->setNamedAutoConstant( + "viewProj", + Ogre::GpuProgramParameters:: + ACT_VIEWPROJ_MATRIX); + Ogre::GpuProgramParametersSharedPtr paramsFP = + water_fp->getDefaultParameters(); +#endif + Ogre::TextureUnitState *texture_unit = + pass->createTextureUnitState(); + texture_unit->setTextureName( + "ReflectionRefractionTexture"); + Ogre::Sampler::UVWAddressingMode uvw; + uvw.u = Ogre::TextureUnitState::TAM_MIRROR; + uvw.v = Ogre::TextureUnitState::TAM_MIRROR; + uvw.w = Ogre::TextureUnitState::TAM_MIRROR; + texture_unit->setTextureAddressingMode( + uvw); + texture_unit->setTextureFiltering( + Ogre::FT_MIN, Ogre::FO_LINEAR); + texture_unit->setTextureFiltering( + Ogre::FT_MAG, Ogre::FO_LINEAR); + texture_unit->setTextureFiltering( + Ogre::FT_MIP, Ogre::FO_LINEAR); +#if 0 + Ogre::RTShader::RenderState *renderState = + Ogre::RTShader::ShaderGenerator:: + getSingletonPtr() + ->createOrRetrieveRenderState( + Ogre::MSN_SHADERGEN) + .first; + Ogre::RTShader::SubRenderState *perPixelLightModel = + Ogre::RTShader::ShaderGenerator::getSingletonPtr() + ->createSubRenderState( + Ogre::RTShader:: + SRS_PER_PIXEL_LIGHTING); + renderState->addTemplateSubRenderState( + perPixelLightModel); +#endif + } - /* - auto mat = Ogre::MaterialManager::getSingleton() +#if 0 + mat = Ogre::MaterialManager::getSingleton() .getByName("Water/Above"); mat->load(); +#endif mat->setReceiveShadows(false); + /* auto mat2 = Ogre::MaterialManager::getSingleton() .getByName("Water/Below"); @@ -39,11 +199,68 @@ WaterModule::WaterModule(flecs::world &ecs) "Ocean", "sea.glb"); water.mWaterEnt->setVisibilityFlags(WATER_MASK); water.mWaterEnt->setCastShadows(true); - // water.mWaterEnt->setMaterialName("Water/Above"); - // water.mWaterEnt->setMaterial(mat); + // water.mWaterEnt->setMaterialName("Water/Above"); + water.mWaterEnt->setMaterial(mat); water.mWaterNode->attachObject(water.mWaterEnt); // mDynWorld->attachCollisionObject( // mWaterBody, water_ent, 1, 0x7FFFFFFF); + water.mReflectionTexture->addListener( + &water.mRenderTargetListener); + water.mReflectionCamera = + eng.mScnMgr->createCamera( + "ReflectionCamera"); + camera.mCamera->getParentSceneNode() + ->attachObject(water.mReflectionCamera); + water.mReflectionCamera->setAspectRatio( + camera.mCamera->getAspectRatio()); + water.mReflectionCamera->setNearClipDistance( + camera.mCamera->getNearClipDistance()); + water.mReflectionCamera->setFarClipDistance( + camera.mCamera->getFarClipDistance()); + water.mReflectionCamera + ->enableCustomNearClipPlane( + water.mReflectionClipPlaneAbove); + water.mReflectionCamera->enableReflection( + water.mReflectionPlane); + + Ogre::Viewport *reflectionViewport = + water.mReflectionTexture->addViewport( + water.mReflectionCamera, 0, 0, + 0, 0.5f, 1.0f); + reflectionViewport->setClearEveryFrame(true); + reflectionViewport->setBackgroundColour( + Ogre::ColourValue(0.0, 0.0, 1.0, 1.0)); + reflectionViewport->setOverlaysEnabled(false); + reflectionViewport->setSkiesEnabled(true); + reflectionViewport->setAutoUpdated(false); + water.mViewports[0] = reflectionViewport; + + water.mRefractionCamera = + eng.mScnMgr->createCamera( + "RefractionCamera"); + camera.mCamera->getParentSceneNode() + ->attachObject(water.mRefractionCamera); + water.mRefractionCamera->setAspectRatio( + camera.mCamera->getAspectRatio()); + water.mRefractionCamera->setNearClipDistance( + camera.mCamera->getNearClipDistance()); + water.mRefractionCamera->setFarClipDistance( + camera.mCamera->getFarClipDistance()); + water.mRefractionCamera + ->enableCustomNearClipPlane( + water.mRefractionClipPlaneAbove); + + Ogre::Viewport *refractionViewport = + water.mReflectionTexture->addViewport( + water.mRefractionCamera, 1, 0.5, + 0, 0.5f, 1.0f); + refractionViewport->setClearEveryFrame(true); + refractionViewport->setBackgroundColour( + Ogre::ColourValue(0.0, 0.5, 1.0, 1.0)); + refractionViewport->setOverlaysEnabled(false); + refractionViewport->setSkiesEnabled(false); + refractionViewport->setAutoUpdated(false); + water.mViewports[1] = refractionViewport; } Ogre::Vector3 mCameraPos = camera.mCameraNode->_getDerivedPosition(); @@ -58,6 +275,10 @@ WaterModule::WaterModule(flecs::world &ecs) water.mWaterNode->translate(d * 3.0f * delta); else water.mWaterNode->translate(d); + water.mWaterEnt->setVisible(false); + water.mViewports[0]->update(); + water.mViewports[1]->update(); + water.mWaterEnt->setVisible(true); }); ecs.system( "UpdateWaterBody") @@ -84,4 +305,24 @@ WaterModule::WaterModule(flecs::world &ecs) } }); } +void WaterSurface::RenderTextureListener::preRenderTargetUpdate( + const Ogre::RenderTargetEvent &evt) +{ + int i; + if (evt.source == mSurface->mReflectionTexture) { + mSurface->mWaterEnt->setVisible(false); + if (evt.source == mSurface->mReflectionTexture) + mSurface->mInRefTexUpdate = true; + } else { + mSurface->mWaterEnt->setVisible(true); + mSurface->mInRefTexUpdate = false; + } +} +void WaterSurface::RenderTextureListener::postRenderTargetUpdate( + const Ogre::RenderTargetEvent &evt) +{ + int i; + mSurface->mWaterEnt->setVisible(true); + mSurface->mInRefTexUpdate = false; +} } \ No newline at end of file diff --git a/src/gamedata/WaterModule.h b/src/gamedata/WaterModule.h index 2c2b631..b483401 100644 --- a/src/gamedata/WaterModule.h +++ b/src/gamedata/WaterModule.h @@ -1,11 +1,28 @@ #ifndef WATER_MODULE_H #define WATER_MODULE_H +#include #include namespace ECS { struct WaterSurface { Ogre::SceneNode *mWaterNode; Ogre::Entity *mWaterEnt; + Ogre::RenderTexture *mReflectionTexture; + Ogre::Camera *mReflectionCamera, *mRefractionCamera; + bool mInRefTexUpdate; + bool mAbove; + struct RenderTextureListener : public Ogre::RenderTargetListener { + WaterSurface *mSurface; + void preRenderTargetUpdate( + const Ogre::RenderTargetEvent &evt) override; + void postRenderTargetUpdate( + const Ogre::RenderTargetEvent &evt) override; + }; + RenderTextureListener mRenderTargetListener; + Ogre::Plane mWaterPlane, mReflectionPlane, mReflectionClipPlaneAbove, + mReflectionClipPlaneBelow, mRefractionClipPlaneAbove, + mRefractionClipPlaneBelow; + Ogre::Viewport *mViewports[2]; }; struct WaterBody { btGhostObject *mWaterBody; diff --git a/water/depth.frag b/water/depth.frag new file mode 100644 index 0000000..08ecad4 --- /dev/null +++ b/water/depth.frag @@ -0,0 +1,14 @@ +OGRE_NATIVE_GLSL_VERSION_DIRECTIVE +#include + +OGRE_UNIFORMS( +uniform vec3 cameraPosition; +) +MAIN_PARAMETERS +IN(vec4 position, POSITION) +IN(vec3 positionWS, TEXCOORD0) +MAIN_DECLARATION +{ + vec4 depth = vec4(length(positionWS - cameraPosition), 0.0, 0.0, 1.0); + gl_FragColor = depth; +} diff --git a/water/depth.vert b/water/depth.vert new file mode 100644 index 0000000..0b3f255 --- /dev/null +++ b/water/depth.vert @@ -0,0 +1,20 @@ +OGRE_NATIVE_GLSL_VERSION_DIRECTIVE +#include + +OGRE_UNIFORMS( + uniform mat4 world; + uniform mat4 worldViewProj; +) + +MAIN_PARAMETERS +IN(vec4 vertex, POSITION); +OUT(vec4 vposition, POSITION); +OUT(vec3 positionWS, TEXCOORD0); + +MAIN_DECLARATION +{ + vposition = mul(worldViewProj, vertex); + positionWS = mul(world, vertex).xyz; + gl_Position = vposition; +} + diff --git a/water/water.material b/water/water.material index 14a3b86..2783272 100644 --- a/water/water.material +++ b/water/water.material @@ -1,25 +1,4 @@ /* -//---------------------------- -// Distortion effects -//---------------------------- -vertex_program Examples/FresnelRefractReflectVP glsl glsles glslang hlsl -{ - source Example_FresnelVp.glsl -} -fragment_program Examples/FresnelRefractReflectFP glsl glsles glslang hlsl -{ - source Example_FresnelFp.glsl - default_params - { - // assign samplers as required by GLSL - param_named noiseMap int 0 - param_named reflectMap int 1 - param_named refractMap int 2 - } -} - -*/ - material Water/Above { technique @@ -31,82 +10,18 @@ material Water/Above diffuse 0.0 0.2 0.5 1.0 cull_hardware none cull_software none -/* - vertex_program_ref Examples/FresnelRefractReflectVP - { - param_named_auto worldViewProjMatrix worldviewproj_matrix - param_named_auto textureProjMatrix texture_worldviewproj_matrix 0 - param_named_auto eyePosition camera_position_object_space - param_named_auto timeVal time 0.05 - 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 Examples/FresnelRefractReflectFP - { - param_named fresnelBias float -0.1 - param_named fresnelScale float 1.8 - param_named fresnelPower float 8 - param_named tintColour float4 0 0.05 0.05 1 - param_named noiseScale float 0.05 - } -*/ vertex_program_ref Water/water_vp { } fragment_program_ref Water/water_fp { } -/* - // Noise - texture_unit - { - // Perlin noise volume - texture waves2.png - // min / mag filtering, no mip - filtering linear linear none - tex_address_mode mirror - } - // Reflection - texture_unit - { - content_type compositor Fresnel reflection - tex_address_mode mirror - } - // Refraction - texture_unit - { - content_type compositor Fresnel refraction - tex_address_mode mirror - } - // Normal - texture_unit - { - texture waves2.png - sampler_ref RTSS/NormalMapSampler - // RT Shader system section. - rtshader_system - { - normal_map tangent_space - } - tex_address_mode mirror - } -*/ texture_unit { texture ReflectionRefractionTexture tex_address_mode mirror filtering linear linear linear } -/* - texture_unit - { - texture RefractionTexture - tex_address_mode mirror - filtering linear linear linear - } -*/ } } rtshader_system @@ -134,43 +49,12 @@ material Water/Below fragment_program_ref Water/water_fp { } -/* - // Noise - texture_unit - { - // Perlin noise volume - texture waves2.png - // min / mag filtering, no mip - filtering linear linear none - tex_address_mode mirror - } - // Reflection - texture_unit - { - content_type compositor Fresnel reflection - tex_address_mode mirror - } - // Refraction - texture_unit - { - content_type compositor Fresnel refraction - tex_address_mode mirror - } -*/ texture_unit { texture ReflectionRefractionTexture tex_address_mode mirror filtering linear linear linear } -/* - texture_unit - { - texture RefractionTexture - tex_address_mode mirror - filtering linear linear linear - } -*/ } } rtshader_system @@ -179,28 +63,5 @@ material Water/Below lighting_stage per_pixel } } - -/* - -material Water/Depth -{ - technique - { - pass - { - cull_hardware none - alpha_rejection greater_equal 0.5 - vertex_program_ref Water/depth_vp - { - param_named_auto world world_matrix - param_named_auto worldViewProj worldviewproj_matrix - } - fragment_program_ref Water/depth_fp - { - param_named_auto cameraPosition camera_position - } - } - } -} */ diff --git a/water/water.program b/water/water.program index b0256b9..d76e59d 100644 --- a/water/water.program +++ b/water/water.program @@ -24,32 +24,32 @@ fragment_program Water/water_fp glsl glsles glslang hlsl { param_named_auto renderTargetFlipping render_target_flipping param_named_auto cameraPosition camera_position - param_named_auto ambient surface_ambient_colour - param_named_auto diffuse surface_diffuse_colour +// param_named_auto ambient surface_ambient_colour +// param_named_auto diffuse surface_diffuse_colour param_named_auto viewportSize viewport_size - param_named_auto time time -// param_named NormalMap int 0 -// param_named EnvironmentMap int 1 - param_named deepColor float4 0 0.2 0.5 1.0 - param_named shallowColor float4 0 0.8 1 1.0 - param_named reflectionColor float4 0.95 1 1 1.0 - param_named reflectionAmount float 0.5 - param_named reflectionBlur float 0.0 - param_named waterAmount float 0.5 -// param_named fresnelPower float 5.0 -// param_named fresnelPower float 8.0 - param_named fresnelPower float 2.0 +//// param_named_auto time time +//// param_named NormalMap int 0 +//// param_named EnvironmentMap int 1 +// param_named deepColor float4 0 0.2 0.5 1.0 +// param_named shallowColor float4 0 0.8 1 1.0 +// param_named reflectionColor float4 0.95 1 1 1.0 +// param_named reflectionAmount float 0.5 +// param_named reflectionBlur float 0.0 +// param_named waterAmount float 0.5 +//// param_named fresnelPower float 5.0 +//// param_named fresnelPower float 8.0 +// param_named fresnelPower float 2.0 +//// param_named fresnelBias float 0.328 // param_named fresnelBias float 0.328 - param_named fresnelBias float 0.328 -// param_named fresnelScale float 1.8 -// param_named fresnelScale float 1.8 - param_named fresnelScale float 1.0 - param_named hdrMultiplier float 0.471 - param_named tintColour float4 0 0.05 0.05 1 - param_named noiseScale float 0.03 -// param_named noiseMap int 0 +//// param_named fresnelScale float 1.8 +//// param_named fresnelScale float 1.8 +// param_named fresnelScale float 1.0 +// param_named hdrMultiplier float 0.471 +// param_named tintColour float4 0 0.05 0.05 1 +// param_named noiseScale float 0.03 +//// param_named noiseMap int 0 param_named reflectMap int 0 -// param_named refractMap int 1 +//// param_named refractMap int 1 } }