Hi all, I'm trying to port the Ogre3D ocean demo to OpenSceneGraph but I've problem achieving the ocean demo effect. Has anybody did this before?
VP:
Code:
uniform float BumpScale;
uniform vec2 textureScale;
uniform vec2 bumpSpeed;
uniform float time;
uniform float waveFreq;
uniform float waveAmp;
uniform mat4 osg_ViewMatrix;
varying vec3 eyePosition;
varying mat3 rotMatrix; // transform from tangent to obj space
varying vec2 bumpCoord0;
varying vec2 bumpCoord1;
varying vec2 bumpCoord2;
varying vec3 eyeVector;
// wave functions
struct Wave {
float freq; // 2*PI / wavelength
float amp; // amplitude
float phase; // speed * 2*PI / wavelength
vec2 dir;
};
void main(void)
{
#define NWAVES 2
Wave wave[NWAVES];
wave[0] = Wave( waveFreq, waveAmp, 0.5, vec2(-1, 0) );
wave[1] = Wave( 3.0 * waveFreq, 0.33 * waveAmp, 1.7, vec2(-0.7, 0.7) );
vec4 P = gl_Vertex;
// sum waves
float ddx = 0.0, ddy = 0.0;
float deriv;
float angle;
// wave synthesis using two sine waves at different frequencies and
phase shift
for(int i = 0; i<NWAVES; ++i)
{
angle = dot(wave[i].dir, P.xy) * wave[i].freq + time *
wave[i].phase;
P.z += wave[i].amp * sin( angle );
// calculate derivate of wave function
deriv = wave[i].freq * wave[i].amp * cos(angle);
ddx += deriv * wave[i].dir.x;
ddy += deriv * wave[i].dir.y;
}
// compute the 3x3 tranform from tangent space to object space
// compute tangent basis
vec3 T = normalize(vec3(0.0, 1.0, ddy)) * BumpScale;
vec3 B = normalize(vec3(1.0, 0.0, ddx)) * BumpScale;
vec3 N = normalize(vec3(-ddx, -ddy, 1.0));
rotMatrix = mat3(T, B, N);
gl_Position = gl_ModelViewProjectionMatrix * P;
// calculate texture coordinates for normal map lookup
bumpCoord0.xy = gl_MultiTexCoord0.xy * textureScale + time * bumpSpeed;
bumpCoord1.xy = gl_MultiTexCoord0.xy * textureScale * 2.0 + time *
bumpSpeed * 4.0;
bumpCoord2.xy = gl_MultiTexCoord0.xy * textureScale * 4.0 + time *
bumpSpeed * 8.0;
eyePosition = -osg_ViewMatrix[3].xyz / osg_ViewMatrix[3].w;
//vec3(gl_ModelViewMatrix * P);
eyeVector = P.xyz - eyePosition; // eye position in vertex space
}
FP:
Code:
uniform sampler2D NormalMap;
uniform samplerCube EnvironmentMap;
uniform vec4 deepColor;
uniform vec4 shallowColor;
uniform vec4 reflectionColor;
uniform float reflectionAmount;
uniform float reflectionBlur;
uniform float waterAmount;
uniform float fresnelPower;
uniform float fresnelBias;
uniform float hdrMultiplier;
varying mat3 rotMatrix; // first row of the 3x3 transform from tangent to cube
space
varying vec2 bumpCoord0;
varying vec2 bumpCoord1;
varying vec2 bumpCoord2;
varying vec3 eyeVector;
void main(void)
{
// sum normal maps
// sample from 3 different points so no texture repetition is noticeable
vec4 t0 = texture2D(NormalMap, bumpCoord0) * 2.0 - 1.0;
vec4 t1 = texture2D(NormalMap, bumpCoord1) * 2.0 - 1.0;
vec4 t2 = texture2D(NormalMap, bumpCoord2) * 2.0 - 1.0;
vec3 N = t0.xyz + t1.xyz + t2.xyz;
N = normalize(rotMatrix * N);
// reflection
vec3 E = normalize(eyeVector);
vec3 R = reflect(E, N);
// Ogre conversion for cube map lookup
R.y = -R.y;
vec4 reflection = textureCube(EnvironmentMap, R, reflectionBlur);
// cheap hdr effect
reflection.rgb *= (reflection.r + reflection.g + reflection.b) *
hdrMultiplier;
// fresnel
float facing = 1.0 - dot(-E, N);
float fresnel = clamp(fresnelBias + pow(facing, fresnelPower), 0.0, 1.0);
vec4 waterColor = mix(shallowColor, deepColor, facing) * waterAmount;
reflection = mix(waterColor, reflection * reflectionColor, fresnel) *
reflectionAmount;
gl_FragColor = waterColor + reflection;
}
Main code:
Code:
osg::TextureCubeMap* readCubeMap()
{
osg::TextureCubeMap* cubemap = new osg::TextureCubeMap;
osg::Image* imagePosX = osgDB::readImageFile(
"./Images/cubemapsJS/morning_RT.jpg" );
osg::Image* imageNegX = osgDB::readImageFile(
"./Images/cubemapsJS/morning_LF.jpg" );
osg::Image* imagePosY = osgDB::readImageFile(
"./Images/cubemapsJS/morning_FR.jpg" );
osg::Image* imageNegY = osgDB::readImageFile(
"./Images/cubemapsJS/morning_BK.jpg" );
osg::Image* imagePosZ = osgDB::readImageFile(
"./Images/cubemapsJS/morning_DN.jpg" );
osg::Image* imageNegZ = osgDB::readImageFile(
"./Images/cubemapsJS/morning_UP.jpg" );
if (imagePosX && imageNegX && imagePosY /*&& imageNegY && imagePosZ &&
imageNegZ*/)
{
cubemap->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX);
cubemap->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX);
cubemap->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY);
cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY);
cubemap->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ);
cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ);
cubemap->setWrap(osg::Texture::WRAP_S,
osg::Texture::CLAMP_TO_EDGE);
cubemap->setWrap(osg::Texture::WRAP_T,
osg::Texture::CLAMP_TO_EDGE);
cubemap->setWrap(osg::Texture::WRAP_R,
osg::Texture::CLAMP_TO_EDGE);
cubemap->setFilter(osg::Texture::MIN_FILTER,
osg::Texture::LINEAR_MIPMAP_NEAREST);
cubemap->setFilter(osg::Texture::MAG_FILTER,
osg::Texture::LINEAR);
}
return cubemap;
}
class updateShader : public osg::Uniform::Callback
{
public:
updateShader() : time(0.0), dir(true) {}
virtual void operator() ( osg::Uniform* uniform, osg::NodeVisitor* nv )
{
time = nv->getFrameStamp()->getSimulationTime();
uniform->set( fmod(time, 100.0f) );
}
bool dir;
float time;
};
void setupOceanShader(osg::StateSet* stateset)
{
osg::Shader* vertexShader = new osg::Shader( osg::Shader::VERTEX );
osg::Shader* fragmentShader = new osg::Shader( osg::Shader::FRAGMENT );
vertexShader->loadShaderSourceFromFile( "./shaders/ocean2GLSL.vert" );
fragmentShader->loadShaderSourceFromFile( "./shaders/ocean2GLSL.frag" );
osg::Program* program = new osg::Program;
program->addShader( vertexShader );
program->addShader( fragmentShader );
stateset->setAttributeAndModes( program, osg::StateAttribute::ON );
osg::Uniform* param1 = new osg::Uniform( "BumpScale", 0.2f );
stateset->addUniform( param1 );
osg::Uniform* param2 = new osg::Uniform( "textureScale",
osg::Vec2(25.0, 26.0) );
stateset->addUniform( param2 );
osg::Uniform* param3 = new osg::Uniform( "bumpSpeed", osg::Vec2(0.015,
0.005) );
stateset->addUniform( param3 );
osg::Uniform* param4 = new osg::Uniform( "time", 100.0f );
param4->setUpdateCallback( new updateShader );
stateset->addUniform( param4 );
osg::Uniform* param5 = new osg::Uniform( "waveFreq", 0.028f );
stateset->addUniform( param5 );
osg::Uniform* param6 = new osg::Uniform( "waveAmp", 1.8f );
stateset->addUniform( param6 );
osg::Uniform* param7 = new osg::Uniform( "deepColor", osg::Vec4(0, 0.3,
0.5, 1.0) );
stateset->addUniform( param7 );
osg::Uniform* param8 = new osg::Uniform( "shallowColor", osg::Vec4(0,
1, 1, 1.0) );
stateset->addUniform( param8 );
osg::Uniform* param9 = new osg::Uniform( "reflectionColor",
osg::Vec4(0.95, 1, 1, 1.0) );
stateset->addUniform( param9 );
osg::Uniform* param10 = new osg::Uniform( "reflectionAmount", 1.0f);
stateset->addUniform( param10 );
osg::Uniform* param11 = new osg::Uniform( "reflectionBlur", 0.0f);
stateset->addUniform( param11 );
osg::Uniform* param12 = new osg::Uniform( "waterAmount", 0.3f);
stateset->addUniform( param12 );
osg::Uniform* param13 = new osg::Uniform( "fresnelPower", 5.0f);
stateset->addUniform( param13 );
osg::Uniform* param14 = new osg::Uniform( "fresnelBias", 0.328f);
stateset->addUniform( param14 );
osg::Uniform* param15 = new osg::Uniform( "hdrMultiplier", 0.471f);
stateset->addUniform( param15 );
osg::Uniform* param16 = new osg::Uniform( "NormalMap", 0 );
stateset->addUniform( param16 );
osg::Uniform* param17 = new osg::Uniform( "EnvironmentMap", 1 );
stateset->addUniform( param17 );
osg::Image* image = osgDB::readImageFile( "./Images/waves2.dds" );
osg::Texture2D* tex = new osg::Texture2D( image );
tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
//tex->setWrap(osg::Texture::WRAP_R, osg::Texture::REPEAT);
tex->setFilter(osg::Texture::MIN_FILTER,
osg::Texture::LINEAR_MIPMAP_NEAREST);
tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
stateset->setTextureAttributeAndModes( 0, tex, osg::StateAttribute::ON
);
stateset->setTextureAttributeAndModes( 1, readCubeMap(),
osg::StateAttribute::ON );
}
int main(int argc, char** argv)
{
osg::Group* root = new osg::Group;
osg::Geode* model = new osg::Geode;
model->addDrawable( GenTriGrid(1000, 1000, 50, 50).get() );
root->addChild( model );
osg::StateSet* stateset = model->getOrCreateStateSet();
osg::BlendFunc* trans = new osg::BlendFunc;
trans->setFunction(osg::BlendFunc::SRC_ALPHA,
osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
stateset->setAttributeAndModes(trans, osg::StateAttribute::ON);
setupOceanShader(stateset);
osgViewer::Viewer viewer;
viewer.addEventHandler( new
osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
viewer.addEventHandler(new osgViewer::StatsHandler);
viewer.setSceneData( root );
viewer.realize();
return viewer.run();
}
Thank you.
Regards,
Tim
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=10595#10595
<<attachment: ocean.jpg>>
_______________________________________________ osg-users mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

