Water is in ECS; water material is created in code
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
#include <Ogre.h>
|
||||
#include <OgreColourValue.h>
|
||||
#include <OgreShaderSubRenderState.h>
|
||||
#include <OgreShaderGenerator.h>
|
||||
#include <OgreRTShaderSystem.h>
|
||||
#include "GameData.h"
|
||||
#include "Components.h"
|
||||
#include "WaterModule.h"
|
||||
@@ -10,7 +14,7 @@ WaterModule::WaterModule(flecs::world &ecs)
|
||||
ecs.module<WaterModule>();
|
||||
ecs.component<WaterSurface>().add(flecs::Singleton);
|
||||
ecs.component<WaterBody>().add(flecs::Singleton);
|
||||
ecs.set<WaterSurface>({ nullptr, nullptr });
|
||||
ecs.set<WaterSurface>({ nullptr, nullptr, nullptr });
|
||||
ecs.set<WaterBody>({ nullptr });
|
||||
ecs.system<const EngineData, const Camera, WaterSurface>("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<const EngineData, const WaterSurface, WaterBody>(
|
||||
"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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,28 @@
|
||||
#ifndef WATER_MODULE_H
|
||||
#define WATER_MODULE_H
|
||||
#include <vector>
|
||||
#include <flecs.h>
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user