diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index ab828a3ad..532e5cedc 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -24,6 +24,8 @@ #include #include +#include + #include #include @@ -40,58 +42,6 @@ #include "renderbin.hpp" #include "util.hpp" -namespace -{ - - osg::ref_ptr createWaterGeometry(float size, int segments, float textureRepeats) - { - osg::ref_ptr verts (new osg::Vec3Array); - osg::ref_ptr texcoords (new osg::Vec2Array); - - // some drivers don't like huge triangles, so we do some subdivisons - // a paged solution would be even better - const float step = size/segments; - const float texCoordStep = textureRepeats / segments; - for (int x=0; xpush_back(osg::Vec3f(x1, y2, 0.f)); - verts->push_back(osg::Vec3f(x1, y1, 0.f)); - verts->push_back(osg::Vec3f(x2, y1, 0.f)); - verts->push_back(osg::Vec3f(x2, y2, 0.f)); - - float u1 = x*texCoordStep; - float v1 = y*texCoordStep; - float u2 = u1 + texCoordStep; - float v2 = v1 + texCoordStep; - - texcoords->push_back(osg::Vec2f(u1, v2)); - texcoords->push_back(osg::Vec2f(u1, v1)); - texcoords->push_back(osg::Vec2f(u2, v1)); - texcoords->push_back(osg::Vec2f(u2, v2)); - } - } - - osg::ref_ptr waterGeom (new osg::Geometry); - waterGeom->setVertexArray(verts); - waterGeom->setTexCoordArray(0, texcoords); - - osg::ref_ptr normal (new osg::Vec3Array); - normal->push_back(osg::Vec3f(0,0,1)); - waterGeom->setNormalArray(normal, osg::Array::BIND_OVERALL); - - waterGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,verts->size())); - return waterGeom; - } - -} - namespace MWRender { @@ -465,7 +415,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem { mSimulation.reset(new RippleSimulation(parent, resourceSystem, fallback)); - mWaterGeom = createWaterGeometry(CELL_SIZE*150, 40, 900); + mWaterGeom = SceneUtil::createWaterGeometry(CELL_SIZE*150, 40, 900); mWaterGeom->setDrawCallback(new DepthClampCallback); mWaterGeom->setNodeMask(Mask_Water); @@ -527,26 +477,11 @@ void Water::updateWaterMaterial() void Water::createSimpleWaterStateSet(osg::Node* node, float alpha) { - osg::ref_ptr stateset (new osg::StateSet); - - osg::ref_ptr material (new osg::Material); - material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 1.f)); - material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, alpha)); - material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, 1.f)); - material->setColorMode(osg::Material::OFF); - stateset->setAttributeAndModes(material, osg::StateAttribute::ON); - - stateset->setMode(GL_BLEND, osg::StateAttribute::ON); - stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); - - osg::ref_ptr depth (new osg::Depth); - depth->setWriteMask(false); - stateset->setAttributeAndModes(depth, osg::StateAttribute::ON); - - stateset->setRenderBinDetails(MWRender::RenderBin_Water, "RenderBin"); + osg::ref_ptr stateset = SceneUtil::createSimpleWaterStateSet(alpha, MWRender::RenderBin_Water); node->setStateSet(stateset); + // Add animated textures std::vector > textures; int frameCount = mFallback->getFallbackInt("Water_SurfaceFrameCount"); std::string texture = mFallback->getFallbackString("Water_SurfaceTexture"); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index f50f30fa6..663616873 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -50,7 +50,7 @@ add_component_dir (shader add_component_dir (sceneutil clone attach visitor util statesetupdater controller skeleton riggeometry lightcontroller - lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil + lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil waterutil ) add_component_dir (nif diff --git a/components/sceneutil/waterutil.cpp b/components/sceneutil/waterutil.cpp new file mode 100644 index 000000000..562b0ee73 --- /dev/null +++ b/components/sceneutil/waterutil.cpp @@ -0,0 +1,79 @@ +#include "waterutil.hpp" + +#include +#include +#include +#include + +namespace SceneUtil +{ + osg::ref_ptr createWaterGeometry(float size, int segments, float textureRepeats) + { + osg::ref_ptr verts (new osg::Vec3Array); + osg::ref_ptr texcoords (new osg::Vec2Array); + + // some drivers don't like huge triangles, so we do some subdivisons + // a paged solution would be even better + const float step = size/segments; + const float texCoordStep = textureRepeats / segments; + for (int x=0; xpush_back(osg::Vec3f(x1, y2, 0.f)); + verts->push_back(osg::Vec3f(x1, y1, 0.f)); + verts->push_back(osg::Vec3f(x2, y1, 0.f)); + verts->push_back(osg::Vec3f(x2, y2, 0.f)); + + float u1 = x*texCoordStep; + float v1 = y*texCoordStep; + float u2 = u1 + texCoordStep; + float v2 = v1 + texCoordStep; + + texcoords->push_back(osg::Vec2f(u1, v2)); + texcoords->push_back(osg::Vec2f(u1, v1)); + texcoords->push_back(osg::Vec2f(u2, v1)); + texcoords->push_back(osg::Vec2f(u2, v2)); + } + } + + osg::ref_ptr waterGeom (new osg::Geometry); + waterGeom->setVertexArray(verts); + waterGeom->setTexCoordArray(0, texcoords); + + osg::ref_ptr normal (new osg::Vec3Array); + normal->push_back(osg::Vec3f(0,0,1)); + waterGeom->setNormalArray(normal, osg::Array::BIND_OVERALL); + + waterGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,verts->size())); + return waterGeom; + } + + osg::ref_ptr createSimpleWaterStateSet(float alpha, int renderBin) + { + osg::ref_ptr stateset (new osg::StateSet); + + osg::ref_ptr material (new osg::Material); + material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 1.f)); + material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, alpha)); + material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, 1.f)); + material->setColorMode(osg::Material::OFF); + stateset->setAttributeAndModes(material, osg::StateAttribute::ON); + + stateset->setMode(GL_BLEND, osg::StateAttribute::ON); + stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); + + osg::ref_ptr depth (new osg::Depth); + depth->setWriteMask(false); + stateset->setAttributeAndModes(depth, osg::StateAttribute::ON); + + stateset->setRenderBinDetails(renderBin, "RenderBin"); + + return stateset; + } +} diff --git a/components/sceneutil/waterutil.hpp b/components/sceneutil/waterutil.hpp new file mode 100644 index 000000000..7b8c38010 --- /dev/null +++ b/components/sceneutil/waterutil.hpp @@ -0,0 +1,19 @@ +#ifndef OPENMW_COMPONENTS_WATERUTIL_H +#define OPENMW_COMPONENTS_WATERUTIL_H + +#include + +namespace osg +{ + class Geometry; + class StateSet; +} + +namespace SceneUtil +{ + osg::ref_ptr createWaterGeometry(float size, int segments, float textureRepeats); + + osg::ref_ptr createSimpleWaterStateSet(float alpha, int renderBin); +} + +#endif