Hi all!

I have found some docs about animating a textured object using texture3D.
So I have tried to do it myself but it doesn't seem to work, it freezes on a 
single noise 2D texture.

I use Perlin Noise to build dynamically the texture. Then I pass it to the 
fragment shader. I managed to write meaningful texture coordinates but i'm not 
sure they are right. Then I just take the first two coordinates and i use a 
time varying third coordinate to move along the third dimension of the texture, 
making the effect of animation. (By the way, I feel that the textures generated 
by the perlin algorithm are not as "beautiful" as expected -> and I can't 
manage to get the results published by some website with the same parameters - 
but it's far from being the main problem)

I have tried to look in osg examples but it seems that it's designed for 
another purpous that doesn't match at all with mine so it doesn't bring me much 
except that I don't understand the texture coordinates.

Thank you very much for your time :)

Find all the code below:

Perlin.h:

Code:

#ifndef PERLIN_H
#define PERLIN_H
//alpha: coefficient d'attenuation
//beta: espacement : <10
//n: nombre d'harmoniques
        double PerlinNoise1D(double x,double alpha,double beta,int n);
        double PerlinNoise2D(double x,double y,double alpha,double beta,int n);
        double PerlinNoise3D(double x,double y,double z,double alpha,double 
beta,int n);
        double PerlinNoise3DABS(double x,double y,double z,double alpha,double 
beta,int n);
#endif




Perlin.cpp:

Code:

//Bruit de Perlin, Bruit cohérent
//Pour plus d'information :
//http://www.mrl.nyu.edu/~perlin/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define B 0x100
#define BM 0xff
#define N 0x1000
#define NP 12   /* 2^N */
#define NM 0xfff

#define s_curve(t) ( t * t * (3. - 2. * t) )
#define lerp(t, a, b) ( a + t * (b - a) )

  

#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )


static int p[B + B + 2];
static double g3[B + B + 2][3];
static double g2[B + B + 2][2];
static double g1[B + B + 2];
static int start = 1;

#ifndef ABS
#define ABS(x) ((x)<0 ? (-x) : (x))
#endif

void normalize2(double v[2])
{
   double s;

   s = sqrt(v[0] * v[0] + v[1] * v[1]);
   v[0] = v[0] / s;
   v[1] = v[1] / s;
}

void normalize3(double v[3])
{
   double s;

   s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
   v[0] = v[0] / s;
   v[1] = v[1] / s;
   v[2] = v[2] / s;
}

void init(void)
{
   int i, j, k;
  
   for (i = 0 ; i < B ; i++) {
      p[i] = i;
      g1[i] = (double)((rand() % (B + B)) - B) / B;

      for (j = 0 ; j < 2 ; j++)
         g2[i][j] = (double)((rand() % (B + B)) - B) / B;
      normalize2(g2[i]);

      for (j = 0 ; j < 3 ; j++)
         g3[i][j] = (double)((rand() % (B + B)) - B) / B;
      normalize3(g3[i]);
   }

   while (--i) {
      k = p[i];
      p[i] = p[j = rand() % B];
      p[j] = k;
   }

   for (i = 0 ; i < B + 2 ; i++) {
      p[B + i] = p[i];
      g1[B + i] = g1[i];
      for (j = 0 ; j < 2 ; j++)
         g2[B + i][j] = g2[i][j];
      for (j = 0 ; j < 3 ; j++)
         g3[B + i][j] = g3[i][j];
   }
}
double noise1(double arg)
{
   int bx0, bx1;
   double rx0, rx1, sx, t, u, v, vec[1];

   vec[0] = arg;
   if (start) {
      start = 0;
      init();
   }

   
        t = vec[0] + N;
    bx0 = ((int)t) & BM;
    bx1 = (bx0+1) & BM;
    rx0 = t - (int)t;
    rx1 = rx0 - 1.;


   sx = s_curve(rx0);
   u = rx0 * g1[ p[ bx0 ] ];
   v = rx1 * g1[ p[ bx1 ] ];

   return(lerp(sx, u, v));
}

double noise2(double vec[2])
{
   int bx0, bx1, by0, by1, b00, b10, b01, b11;
   double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
   int i, j;

   if (start) {
      start = 0;
      init();
   }

  

   t = vec[0] + N;
    bx0 = ((int)t) & BM;
    bx1 = (bx0+1) & BM;
    rx0 = t - (int)t;
    rx1 = rx0 - 1.;

        t = vec[1] + N;
    by0 = ((int)t) & BM;
    by1 = (by0+1) & BM;
    ry0 = t - (int)t;
    ry1 = ry0 - 1.;

   i = p[ bx0 ];
   j = p[ bx1 ];

   b00 = p[ i + by0 ];
   b10 = p[ j + by0 ];
   b01 = p[ i + by1 ];
   b11 = p[ j + by1 ];

   sx = s_curve(rx0);
   sy = s_curve(ry0);

   q = g2[ b00 ] ; u = at2(rx0,ry0);
   q = g2[ b10 ] ; v = at2(rx1,ry0);
   a = lerp(sx, u, v);

   q = g2[ b01 ] ; u = at2(rx0,ry1);
   q = g2[ b11 ] ; v = at2(rx1,ry1);
   b = lerp(sx, u, v);

   return lerp(sy, a, b);
}

double noise3(double vec[3])
{
   int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
   double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
   int i, j;

   if (start) {
      start = 0;
      init();
   }

   t = vec[0] + N;
    bx0 = ((int)t) & BM;
    bx1 = (bx0+1) & BM;
    rx0 = t - (int)t;
    rx1 = rx0 - 1.;

        t = vec[1] + N;
    by0 = ((int)t) & BM;
    by1 = (by0+1) & BM;
    ry0 = t - (int)t;
    ry1 = ry0 - 1.;

        t = vec[2] + N;
    bz0 = ((int)t) & BM;
    bz1 = (bz0+1) & BM;
    rz0 = t - (int)t;
    rz1 = rz0 - 1.;


   i = p[ bx0 ];
   j = p[ bx1 ];

   b00 = p[ i + by0 ];
   b10 = p[ j + by0 ];
   b01 = p[ i + by1 ];
   b11 = p[ j + by1 ];

   t  = s_curve(rx0);
   sy = s_curve(ry0);
   sz = s_curve(rz0);

   q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
   q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
   a = lerp(t, u, v);

   q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
   q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
   b = lerp(t, u, v);

   c = lerp(sy, a, b);

   q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
   q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
   a = lerp(t, u, v);

   q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
   q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
   b = lerp(t, u, v);

   d = lerp(sy, a, b);

   return lerp(sz, c, d);
}

//Le somme des armoniques:
//Alpha : coefficient d'atténuation pour la prochaine fréquence, plus on 
diminue ce coef, et plus
//la fonction est bruité
//Beta  : espacement.
//n le nombre d'harmonique.
double PerlinNoise1D(double x,double alpha,double beta,int n)
{
   int i;
   double val,sum = 0;
   double p,scale = 1;

   p = x;
   for (i=0;i<n;i++) {
      val = noise1(p);
      sum += val / scale;
      scale *= alpha;
      p *= beta;
   }
   return(sum);
}

double PerlinNoise2D(double x,double y,double alpha,double beta,int n)
{
   int i;
   double val,sum = 0;
   double p[2],scale = 1;

   p[0] = x;
   p[1] = y;
   for (i=0;i<n;i++) {
      val = noise2(p);
      sum += val / scale;
      scale *= alpha;
      p[0] *= beta;
      p[1] *= beta;
   }
   return(sum);
}

double PerlinNoise3D(double x,double y,double z,double alpha,double beta,int n)
{
   int i;
   double val,sum = 0;
   double p[3],scale = 1;

   p[0] = x;
   p[1] = y;
   p[2] = z;
   for (i=0;i<n;i++) {
      val = noise3(p);
      sum += val / scale;
      scale *= alpha;
      p[0] *= beta;
      p[1] *= beta;
      p[2] *= beta;
   }
   return(sum/(n*alpha));
}



double PerlinNoise3DABS(double x,double y,double z,double alpha,double beta,int 
n)
{
   int i;
   double val,sum = 0;
   double p[3],scale = 1;

   p[0] = x;
   p[1] = y;
   p[2] = z;
   for (i=0;i<n;i++) {
      val = noise3(p);
                        val = ABS(val);
      sum += val / scale;
      scale *= alpha;
      p[0] *= beta;
      p[1] *= beta;
      p[2] *= beta;
   }
   return(sum);
}






main.cpp:

Code:

#include <osg/Referenced>

#include <osg/Geometry>
#include <osg/PositionAttitudeTransform>
#include <osg/Geode>
#include <osg/Drawable>
#include <osg/Group>
#include <osg/StateSet>

#include <osgViewer/Viewer>

#include <osgManipulator/Command>

#include <osgViewer/ViewerEventHandlers>
#include <osgGA/StateSetManipulator>
#include <osgGA/TrackBallManipulator>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <sstream>
#include <math.h>



#include <osgGA/GUIEventHandler>

#include <osg/Timer>

#include <osg/TextureRectangle>
#include <osg/Texture>
#include <osg/Texture2D>
#include <osg/Texture3D>

#include <osg/Image>

#include <osg/Program>
#include <osg/Uniform>

#include "Perlin.h"

using namespace std;

osg::Texture3D* createNoiseTexture()
{
        osg::Image* noiseImage = new osg::Image();
        noiseImage->allocateImage(256, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE);
        //float min = 0.0;
        //float max= 0.0;
        for(int i=0; i<256; i++)
        {
                for(int j=0; j<256; j++)
                {
                        for(int k=0; k<256; k++)
                        {
                                float val = 
256.0*(1.0+PerlinNoise3D(i,j,k,0.15,9.9,3)/78.0)/2.0;
                                noiseImage->data(k, j, i)[0] = val;
                                noiseImage->data(k, j, i)[1] = val;
                                noiseImage->data(k, j, i)[2] = val;
                                noiseImage->data(k, j, i)[3] = 255.0;

                                //if(val<min)
                                //      min=val;
                                //if(val>max)
                                //      max=val;
                        }
                }
        }
        //cout << min << " et " << max << endl;
        
        //osgDB::writeImageFile(*noiseImage,"noise.rgba");
        osg::Texture3D* noiseTexture = new osg::Texture3D(noiseImage);
        return noiseTexture;
}

osg::PositionAttitudeTransform* createSquare(int numFace, 
osg::TextureRectangle* texture, osg::TextureRectangle* texture2, 
osg::Texture3D* noiseTexture)
{
        osg::Geode* face = new osg::Geode();
        
//-----------------------------------------------------------------------------------------------------------------------------------------------------
        osg::Geometry* squareGeometry = new osg::Geometry();
        osg::Vec3Array* squareVertices = new osg::Vec3Array();

        //Colors
        osg::Vec4Array  *colors = new osg::Vec4Array(1);

        (*colors)[0] = osg::Vec4(1,1,1,1);
        squareGeometry->setColorArray(colors);
        //squareGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);

        squareVertices->push_back( osg::Vec3(  5 ,5, 5 ) );//Point2
        squareVertices->push_back( osg::Vec3( -5 ,5, 5 ) );//Point5
        squareVertices->push_back( osg::Vec3( -5 ,5, -5) );//Point7
        squareVertices->push_back( osg::Vec3(  5 ,5, -5) );//Point4

        squareGeometry->setVertexArray(squareVertices);

        osg::DrawElementsUInt* squareFace = new 
osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
        squareFace->push_back(0);
        squareFace->push_back(1);
        squareFace->push_back(2);
        squareFace->push_back(3);
        squareGeometry->addPrimitiveSet(squareFace);

        face->addDrawable(squareGeometry);
        
//-----------------------------------------------------------------------------------------------------------------------------------------------------

        osg::PositionAttitudeTransform* faceOrientable = new 
osg::PositionAttitudeTransform();

                switch(numFace)
                {
                case 0:
                                
faceOrientable->setAttitude(osg::Quat(osg::DegreesToRadians(180.0f), 
osg::Vec3(0,0,1)));
                                break;
                case 1:
                                
faceOrientable->setAttitude(osg::Quat(osg::DegreesToRadians(90.0f), 
osg::Vec3(0,0,1)));
                                break;
                case 2:
                                break;
                case 3:
                                
faceOrientable->setAttitude(osg::Quat(osg::DegreesToRadians(270.0f), 
osg::Vec3(0,0,1)));
                                break;
                }

        faceOrientable->addChild(face);

        //BUG fix
        osg::Vec2 textureStart(0.01,0.01);
        osg::Vec2 textureEnd(0.99,0.99);

        osg::Vec2 imageSize(texture->getImage(0)->s(), 
texture->getImage(0)->t());

        osg::Vec2Array* tcoords = new osg::Vec2Array(4);
        (*tcoords)[0].set(imageSize[0] * textureStart[0], imageSize[1] * 
textureEnd[1]);
        (*tcoords)[1].set(imageSize[0] * textureEnd[0], imageSize[1] * 
textureEnd[1]);
        (*tcoords)[2].set(imageSize[0] * textureEnd[0], imageSize[1] * 
textureStart[1]);
        (*tcoords)[3].set(imageSize[0] * textureStart[0], imageSize[1] * 
textureStart[1]);

        osg::Vec2 imageSize2(noiseTexture->getImage(0)->s(), 
noiseTexture->getImage(0)->t());

        osg::Vec2Array* tcoords2 = new osg::Vec2Array(4);
        (*tcoords2)[0].set(imageSize2[0] * textureStart[0], imageSize2[1] * 
textureEnd[1]);
        (*tcoords2)[1].set(imageSize2[0] * textureEnd[0], imageSize2[1] * 
textureEnd[1]);
        (*tcoords2)[2].set(imageSize2[0] * textureEnd[0], imageSize2[1] * 
textureStart[1]);
        (*tcoords2)[3].set(imageSize2[0] * textureStart[0], imageSize2[1] * 
textureStart[1]);

        osg::Vec3Array* tcoords3 = new osg::Vec3Array(8);
        (*tcoords3)[0].set(0.0, 0.0, 0.0);
        (*tcoords3)[1].set(1.0, 0.0, 0.0);
        (*tcoords3)[2].set(1.0, 1.0, 0.0);
        (*tcoords3)[3].set(0.0, 1.0, 0.0);
        (*tcoords3)[4].set(0.0, 1.0, 1.0);
        (*tcoords3)[5].set(0.0, 0.0, 1.0);
        (*tcoords3)[6].set(1.0, 0.0, 1.0);
        (*tcoords3)[7].set(1.0, 1.0, 1.0);


        squareGeometry->setTexCoordArray(2*numFace,tcoords);
        squareGeometry->setTexCoordArray(2*numFace+1,tcoords2);
        squareGeometry->setTexCoordArray(2*numFace+2,tcoords3);
        
squareGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(2*numFace,texture,osg::StateAttribute::ON);
        
squareGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(2*numFace+1,texture2,osg::StateAttribute::ON);
        
squareGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(2*numFace+2,noiseTexture,osg::StateAttribute::ON);
        
//-------------------------------------------------------------------------------------------------------

        return faceOrientable;
}

class CUpdateUniforms: public osg::NodeCallback
{
public:
        CUpdateUniforms(float 
duration):_firstTime(true),_time(0.0f),_duration(duration){}

        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
        {
                // Timer
                if(_firstTime)
                {
                        //Get the actual time
                        _lastTime = osg::Timer::instance()->tick();
                        _firstTime=false;
                }
                //Update uniforms
                {
                        // Update des paramètres
                        //Delta_s : secondes
                        float timePassed = 
osg::Timer::instance()->delta_s(_lastTime, osg::Timer::instance()->tick());
                        _lastTime = osg::Timer::instance()->tick();
                        _time+=timePassed;
                        osg::ref_ptr<osg::StateSet> stateSet = 
dynamic_cast<osg::StateSet*> 
(node->asGroup()->getChild(0)->asGeode()->getDrawable(0)->getOrCreateStateSet() 
);
                        stateSet->addUniform(new 
osg::Uniform("timeCoef",_time/_duration));
                }
                traverse(node,nv);

        }
private:
        float _firstTime;
        osg::Timer_t _lastTime;
        float _time;
        float _duration;
};

int     main(int ac, char **av)
{
//-----------------------------------------------------------------------------------------------------------------------------------------------------
        //OSG
        osg::setNotifyLevel(osg::NOTICE);

        // Viewer init
        osgViewer::Viewer* viewer= new osgViewer::Viewer;

        //viewer->setCameraManipulator(new CFixedCamera());
        viewer->setCameraManipulator(new osgGA::TrackballManipulator());
        viewer->addEventHandler(new 
osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
        viewer->addEventHandler(new osgViewer::StatsHandler());
        viewer->addEventHandler(new osgViewer::WindowSizeHandler);

        viewer->setUpViewInWindow(100, 100, 1024, 768);

        //Le root
        osg::PositionAttitudeTransform* rootNode = new 
osg::PositionAttitudeTransform();
        rootNode->setAttitude(osg::Quat(osg::DegreesToRadians(180.0f), 
osg::Vec3(1,0,0)));
//-----------------------------------------------------------------------------------------------------------------------------------------------------
        
        
        osg::Image* image = new osg::Image();
        
//-------------------------------------------------------------------------------------------------------
        ostringstream srcImg1;
        srcImg1 << "../Media/Images/GALET_NOIR1.jpg";
        string filename = srcImg1.str();
        cout << filename << endl;
        image = osgDB::readImageFile(filename);// On récupère l'image à partir 
du fichier
        if (!image)//Teste si l'image s'est bien chargée
        {
                std::cout << " couldn't find texture, quiting." << std::endl;
                return false;
        }
        
//-------------------------------------------------------------------------------------------------------
        
        osg::TextureRectangle* texture= new osg::TextureRectangle(image);// On 
crée une nouvelle texture
        texture->setDataVariance(osg::Object::DYNAMIC);// On la protège pour 
les optimisations

        osg::Image* image2 = new osg::Image();
        
//-------------------------------------------------------------------------------------------------------
        ostringstream srcImg2;
        srcImg2 << "../Media/Images/GALET_NOIR0.jpg";
        string filename2 = srcImg2.str();
        cout << filename2 << endl;
        image2 = osgDB::readImageFile(filename2);// On récupère l'image à 
partir du fichier
        if (!image)//Teste si l'image s'est bien chargée
        {
                std::cout << " couldn't find texture2, quiting." << std::endl;
                return false;
        }
        
//-------------------------------------------------------------------------------------------------------
        
        osg::TextureRectangle* texture2= new osg::TextureRectangle(image2);// 
On crée une nouvelle texture
        texture2->setDataVariance(osg::Object::DYNAMIC);// On la protège pour 
les optimisations

        osg::Texture3D* noiseTexture = createNoiseTexture();
        noiseTexture->setDataVariance(osg::Object::DYNAMIC);// On la protège 
pour les optimisations

        osg::PositionAttitudeTransform* quad = createSquare(0, texture, 
texture2, noiseTexture);
        
        osg::Program* _programColor = new osg::Program();
        {
                //Read the shader frag
                osg::Shader* colorFrag = 
osgDB::readShaderFile(osg::Shader::FRAGMENT, 
"shaders/fragmentShaderAnimated.frag");
                if (colorFrag == NULL)
                {
                   osg::notify(osg::NOTICE) << "Color Effect not 
supported(frag) !" << std::endl;
                   return false;
                }
                _programColor->addShader(colorFrag);

                //Read the shader vert
                osg::Shader* colorVert = 
osgDB::readShaderFile(osg::Shader::VERTEX, "shaders/vertexShader.vert");
                if (colorVert == NULL)
                {
                   osg::notify(osg::NOTICE) << "Color Effect not 
supported(vert) !" << std::endl;
                   return false;
                }
                _programColor->addShader(colorVert);
        }

        quad->addUpdateCallback(new CUpdateUniforms(10.0));

        //Stateset
        osg::StateSet *stateSet = quad->getOrCreateStateSet();

        //Texture Base
        osg::Uniform* textureBaseU = new osg::Uniform("textureBaseRect1", 0);
        stateSet->addUniform(textureBaseU);

        osg::Uniform* textureNoiseU = new osg::Uniform("textureNoise", 2);
        stateSet->addUniform(textureNoiseU);

        stateSet->setAttributeAndModes(_programColor, osg::StateAttribute::ON);

        rootNode->addChild( quad );
        rootNode->getOrCreateStateSet()->setMode(GL_LIGHTING, 
osg::StateAttribute::OFF);

        viewer->setSceneData( rootNode );
        viewer->realize();
        viewer->run();

        return (0);
}




vertex shader:

Code:

void main()
{
        gl_TexCoord[0] = gl_TextureMatrix[0]*gl_MultiTexCoord0;
        gl_TexCoord[2] = gl_TextureMatrix[2]*gl_MultiTexCoord2;
        gl_Position = ftransform();
}




fragment shader:

Code:

uniform sampler2DRect textureBaseRect1;
uniform sampler3D textureNoise;
uniform float timeCoef;

void main()
{       
        gl_FragColor = 
texture2DRect(textureBaseRect1,gl_TexCoord[0].st)+texture3D(textureNoise, 
vec3(gl_TexCoord[2].st,timeCoef*256.0));
}




The third texture is here for another part of the project and some code may be 
irrelevant to you but i don't touch anything to avoid bugs. I tried to clean 
the code a bit, but it's long and dangerous. Sorry if it's confusing.[/code]

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=18808#18808





_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to