Jump to content

  • Log In with Google      Sign In   
  • Create Account


#ActualBudinga

Posted 01 January 2013 - 04:13 AM

Hi Guyz. Well I have decided to use the great Eric Bruneton's water shaders in my procedural planet renderer, now I have managed to port the shaders, and also with a slightly modified ocean rendering class I get something on the screen, but due to the fact that he use's, a different coord system, well I think that's it I cant seem to get my brain round it. So I was wondering if anybody could spot my problem.

Original Render Function

bool DrawOceanTask::Impl::run()

{

    if (Logger::DEBUG_LOGGER != NULL) {

        Logger::DEBUG_LOGGER->log("OCEAN", "DrawOcean");

    }

    ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer();

    ptr<Program> prog = SceneManager::getCurrentProgram();


    if (o->nbWavesU == NULL) {

        o->nbWavesU = prog->getUniform1f("nbWaves");

        o->wavesU = prog->getUniformSampler("wavesSampler");

        o->cameraToOceanU = prog->getUniformMatrix4f("cameraToOcean");

        o->screenToCameraU = prog->getUniformMatrix4f("screenToCamera");

        o->cameraToScreenU = prog->getUniformMatrix4f("cameraToScreen");

        o->oceanToCameraU = prog->getUniformMatrix3f("oceanToCamera");

        o->oceanToWorldU = prog->getUniformMatrix4f("oceanToWorld");

        o->oceanCameraPosU = prog->getUniform3f("oceanCameraPos");

        o->oceanSunDirU = prog->getUniform3f("oceanSunDir");

        o->horizon1U = prog->getUniform3f("horizon1");

        o->horizon2U = prog->getUniform3f("horizon2");

        o->timeU = prog->getUniform1f("time");

        o->radiusU = prog->getUniform1f("radius");

        o->heightOffsetU = prog->getUniform1f("heightOffset");

        o->lodsU = prog->getUniform4f("lods");


        assert(o->nbWavesU != NULL);

        o->generateWaves();

    }


    vector< ptr<TileSampler> > uniforms;

    SceneNode::FieldIterator ui = n->getFields();

    while (ui.hasNext()) {

        ptr<TileSampler> u = ui.next().cast<TileSampler>();

        if (u != NULL && u->getTerrain(0) != NULL) {

            u->setTileMap();

        }

    }


    // compute ltoo = localToOcean transform, where ocean frame = tangent space at

    // camera projection on sphere o->radius in local space

    mat4d ctol = n->getLocalToCamera().inverse();

    vec3d cl = ctol * vec3d::ZERO; // camera in local space


    if ((o->radius == 0.0 && cl.z > o->zmin) ||

        (o->radius > 0.0 && cl.length() > o->radius + o->zmin) ||

        (o->radius < 0.0 && vec2d(cl.y, cl.z).length() < -o->radius - o->zmin))

    {

        o->oldLtoo = mat4d::IDENTITY;

        o->offset = vec3d::ZERO;

        return true;

    }


    vec3d ux, uy, uz, oo;


    if (o->radius == 0.0) {

        // flat ocean

        ux = vec3d::UNIT_X;

        uy = vec3d::UNIT_Y;

        uz = vec3d::UNIT_Z;

        oo = vec3d(cl.x, cl.y, 0.0);

    } else if (o->radius > 0.0) {

        // spherical ocean

        uz = cl.normalize(); // unit z vector of ocean frame, in local space

        if (o->oldLtoo != mat4d::IDENTITY) {

            ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();

        } else {

            ux = vec3d::UNIT_Z.crossProduct(uz).normalize();

        }

        uy = uz.crossProduct(ux); // unit y vector

        oo = uz * o->radius; // origin of ocean frame, in local space

    } else {

        // cylindrical ocean

        uz = vec3d(0.0, -cl.y, -cl.z).normalize();

        ux = vec3d::UNIT_X;

        uy = uz.crossProduct(ux);

        oo = vec3d(cl.x, 0.0, 0.0) + uz * o->radius;

    }


    mat4d ltoo = mat4d(

        ux.x, ux.y, ux.z, -ux.dotproduct(oo),

        uy.x, uy.y, uy.z, -uy.dotproduct(oo),

        uz.x, uz.y, uz.z, -uz.dotproduct(oo),

        0.0,  0.0,  0.0,  1.0);

    // compute ctoo = cameraToOcean transform

    mat4d ctoo = ltoo * ctol;


    if (o->oldLtoo != mat4d::IDENTITY) {

        vec3d delta = ltoo * (o->oldLtoo.inverse() * vec3d::ZERO);

        o->offset += delta;

    }

    o->oldLtoo = ltoo;


    mat4d ctos = n->getOwner()->getCameraToScreen();

    mat4d stoc = ctos.inverse();

    vec3d oc = ctoo * vec3d::ZERO;


    if (o->oceanSunDirU != NULL) {

        // TODO how to get sun dir in a better way?

        SceneManager::NodeIterator i = n->getOwner()->getNodes("light");

        if (i.hasNext()) {

            ptr<SceneNode> l = i.next();

            vec3d worldSunDir = l->getLocalToParent() * vec3d::ZERO;

            vec3d oceanSunDir = ltoo.mat3x3() * (n->getWorldToLocal().mat3x3() * worldSunDir);

            o->oceanSunDirU->set(oceanSunDir.cast<float>());

        }

    }


    vec4<GLint> screen = fb->getViewport();


    vec4d frustum[6];

    SceneManager::getFrustumPlanes(ctos, frustum);

    vec3d left = frustum[0].xyz().normalize();

    vec3d right = frustum[1].xyz().normalize();

    float fov = (float) safe_acos(-left.dotproduct(right));

    float pixelSize = atan(tan(fov / 2.0f) / (screen.w / 2.0f)); // angle under which a screen pixel is viewed from the camera


    o->cameraToOceanU->setMatrix(ctoo.cast<float>());

    o->screenToCameraU->setMatrix(stoc.cast<float>());

    o->cameraToScreenU->setMatrix(ctos.cast<float>());

    o->oceanToCameraU->setMatrix(ctoo.inverse().mat3x3().cast<float>());

    o->oceanCameraPosU->set(vec3f(float(-o->offset.x), float(-o->offset.y), float(oc.z)));

    if (o->oceanToWorldU != NULL) {

        o->oceanToWorldU->setMatrix((n->getLocalToWorld() * ltoo.inverse()).cast<float>());

    }


    if (o->horizon1U != NULL) {

        float h = oc.z;

        vec3d A0 = (ctoo * vec4d((stoc * vec4d(0.0, 0.0, 0.0, 1.0)).xyz(), 0.0)).xyz();

        vec3d dA = (ctoo * vec4d((stoc * vec4d(1.0, 0.0, 0.0, 0.0)).xyz(), 0.0)).xyz();

        vec3d B = (ctoo * vec4d((stoc * vec4d(0.0, 1.0, 0.0, 0.0)).xyz(), 0.0)).xyz();

        if (o->radius == 0.0) {

            o->horizon1U->set(vec3f(-(h * 1e-6 + A0.z) / B.z, -dA.z / B.z, 0.0));

            o->horizon2U->set(vec3f::ZERO);

        } else {

            double h1 = h * (h + 2.0 * o->radius);

            double h2 = (h + o->radius) * (h + o->radius);

            double alpha = B.dotproduct(B) * h1 - B.z * B.z * h2;

            double beta0 = (A0.dotproduct(B) * h1 - B.z * A0.z * h2) / alpha;

            double beta1 = (dA.dotproduct(B) * h1 - B.z * dA.z * h2) / alpha;

            double gamma0 = (A0.dotproduct(A0) * h1 - A0.z * A0.z * h2) / alpha;

            double gamma1 = (A0.dotproduct(dA) * h1 - A0.z * dA.z * h2) / alpha;

            double gamma2 = (dA.dotproduct(dA) * h1 - dA.z * dA.z * h2) / alpha;

            o->horizon1U->set(vec3f(-beta0, -beta1, 0.0));

            o->horizon2U->set(vec3f(beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2));

        }

    }


    o->timeU->set(n->getOwner()->getTime() * 1e-6);

    if (o->radiusU != NULL) {

        o->radiusU->set(o->radius < 0.0 ? -o->radius : o->radius);

    }

    o->heightOffsetU->set(-o->meanHeight);

    o->lodsU->set(vec4f(o->resolution,

            pixelSize * o->resolution,

            log(o->lambdaMin) / log(2.0f),

            (o->nbWavesU->get() - 1.0f) / (log(o->lambdaMax) / log(2.0f) -  log(o->lambdaMin) / log(2.0f))));


    if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {

        o->screenWidth = screen.z;

        o->screenHeight = screen.w;

        o->screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);

        o->screenGrid->addAttributeType(0, 2, A32F, false);


        float f = 1.25f;

        int NX = int(f * screen.z / o->resolution);

        int NY = int(f * screen.w / o->resolution);

        for (int i = 0; i < NY; ++i) {

            for (int j = 0; j < NX; ++j) {

                o->screenGrid->addVertex(vec2f(2.0*f*j/(NX-1.0f)-f, 2.0*f*i/(NY-1.0f)-f));

            }

        }

        for (int i = 0; i < NY-1; ++i) {

            for (int j = 0; j < NX-1; ++j) {

                o->screenGrid->addIndice(i*NX+j);

                o->screenGrid->addIndice(i*NX+j+1);

                o->screenGrid->addIndice((i+1)*NX+j);

                o->screenGrid->addIndice((i+1)*NX+j);

                o->screenGrid->addIndice(i*NX+j+1);

                o->screenGrid->addIndice((i+1)*NX+j+1);

            }

        }

    }


    fb->draw(prog, *(o->screenGrid));


    return true;

}



Now my update function (basically tries to do the same thing.


public void Update(GameTime gametime)

      {




          // compute ltoo = localToOcean transform, where ocean frame = tangent space at

          // camera projection on sphere o->radius in local space

          //Matrix.CreateRotationY (MathHelper.ToRadians(90)) * Matrix.CreateRotationZ (MathHelper.ToRadians(90))*

          Matrix ctol =   Matrix.Identity * Matrix.Invert(Parent.cam.View);

          Vector3 cl = Vector3.Transform(Vector3.Zero, ctol);//camera in local space


          if ((radius == 0.0 && cl.Z > zmin) ||

              (radius > 0.0 && cl.Length() > radius + zmin) ||

              (radius < 0.0 && new Vector2(cl.Y, cl.Z).Length() < -radius - zmin))

          {

              oldLtoo = Matrix.Identity;

              offset = Vector3.Zero;

              return;

          }


          Vector3 ux, uy, uz, oo;


          if (radius == 0.0)

          {

              // flat ocean

              ux = Vector3.UnitX;

              uy = Vector3.UnitY;

              uz = Vector3.UnitZ;

              oo = new Vector3(cl.X, cl.Y, 0.0f);

          }

          else if (radius > 0.0)

          {

              // spherical ocean

              uz = Vector3.Normalize(cl);// unit z vector of ocean frame, in local space


              if (oldLtoo != Matrix.Identity)

              {

                  //Matrix m = Matrix.Transpose(oldLtoo);

                  //ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();

                  ux = Vector3.Normalize(Vector3.Cross(new Vector3(oldLtoo.M21, oldLtoo.M22, oldLtoo.M23), uz));

              }

              else

              {

                  ux = Vector3.Normalize(Vector3.Cross(Vector3.UnitZ, uz));

              }



              uy = Vector3.Cross(uz, ux);// unit y vector // negate this ??

              //oo = uz * radius; // origin of ocean frame, in local space

              oo = ux * radius;


          }

          else

          {

              // cylindrical ocean

              uz = Vector3.Normalize(new Vector3(0, -cl.Y, -cl.Z));

              ux = Vector3.UnitX;

              uy = Vector3.Cross(uz, ux);

              oo = new Vector3(cl.X, 0, 0) + uz * radius;

          }



          Matrix ltoo = new Matrix(

              ux.X, uy.X, uz.X, 0.0f,

              ux.Y, uy.Y, uz.Y, 0.0f,

              ux.Z, uy.Z, uz.Z, 0.0f,

              -Vector3.Dot(ux, oo), -Vector3.Dot(uy, oo), -Vector3.Dot(uz, oo), 1.0f);




          ltoo = Matrix.Transpose(ltoo);






          // compute ctoo = cameraToOcean transform

          Matrix ctoo =   ltoo * Matrix.Transpose (ctol);






        if (oldLtoo != Matrix.Identity) 

        {

            Vector3 delta = Vector3.Transform(Vector3.Zero, Matrix.Transpose ( ltoo * Matrix.Invert(oldLtoo)));

            offset += delta; 

        }


              oldLtoo = ltoo;



            Matrix ctos = Matrix.Transpose (Parent.cam.Projection); //world*view*projection //n->getOwner()->getCameraToScreen();

            Matrix stoc = Matrix.Invert (ctos);

            Vector3 oc = Vector3.Transform(Vector3.Zero, ctoo);




            Vector3 worldsunDir = Parent.vLightDirection;

            Vector3 oceanSunDir = Vector3.Transform(worldsunDir, ltoo *  Parent.cam.View);


            BoundingFrustum frustum = new BoundingFrustum(ctos);

            Vector3 left = frustum.Left.Normal;

            Vector3 right = frustum.Right.Normal;

            float fov = (float)System.Math.Acos(Vector3.Dot(-left, right));


            float pixelSize = (float)System.Math.Atan(System.Math.Tan(fov / 2.0f) / (device.Viewport.Height / 2.0f));// angle under which a screen pixel is viewed from the camera



            float h = oc.Z;


            Vector4 tmp1,tmp2;


            tmp1 = Vector4.Transform ( new Vector4 (0,0,0,1),stoc);

            tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);

            Vector3 A0 = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);


            tmp1 = Vector4.Transform ( new Vector4 (1,0,0,0),stoc);

            tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);

            Vector3 dA = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);


            tmp1 = Vector4.Transform ( new Vector4 (0,1,0,0),stoc);

            tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);

            Vector3 B = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);


        if (radius == 0.0) 

        {

            horizon1U = new Vector3(-(h * 1e-6f + A0.Z) / B.Z, -dA.Z / B.Z, 0);

            horizon2U = Vector3.Zero;

        } 

        else 

        {

            double h1 = h * (h + 2.0 * radius);

            double h2 = (h + radius) * (h + radius);

            double alpha = Vector3.Dot (B,B) * h1 - B.Z * B.Z * h2;

            double beta0 = (Vector3.Dot (A0,B)  * h1 - B.Z * A0.Z * h2) / alpha;

            double beta1 = (Vector3.Dot (dA,B) * h1 - B.Z * dA.Z * h2) / alpha;

            double gamma0 = (Vector3.Dot (A0,A0) * h1 - A0.Z * A0.Z * h2) / alpha;

            double gamma1 = (Vector3.Dot(A0,dA) * h1 - A0.Z * dA.Z * h2) / alpha;

            double gamma2 = (Vector3.Dot(dA,dA) * h1 - dA.Z * dA.Z * h2) / alpha;

            horizon1U = new Vector3((float)-beta0, (float)-beta1, 0);

            horizon2U = new Vector3((float)beta0 * (float)beta0 - (float)gamma0, 2.0f * ((float)beta0 * (float)beta1 - (float)gamma1), (float)beta1 * (float)beta1 - (float)gamma2);


        }




          timeU = (float)gametime.TotalGameTime.TotalMilliseconds *0.0001f; 


          heightOffsetU = -meanHeight;


          lodsU = new Vector4(resolution,

                  pixelSize * resolution,

                  (float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f),

                  (nbWaves - 1.0f) / ((float)System.Math.Log(lambdaMax) / (float)System.Math.Log(2.0f) - (float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f)));




          cameraToOceanU =  Matrix.Transpose (ctoo);

          screenToCameraU = stoc;

          cameraToScreenU = ctos; 



          oceanCameraPosU = new Vector3(-offset.X, -offset.Y, -offset.Z);


          oceanToWorldU = Matrix.Transpose ( Parent.cam.Projection * Parent.cam.View) * Matrix.Invert (ltoo); 



          oceanToCameraU = Matrix.Transpose(Matrix.Invert(ctoo));  


          //Global Variables

          watereffect.Parameters["cameraToOcean"].SetValue(cameraToOceanU);

          watereffect.Parameters["screenToCamera"].SetValue(screenToCameraU); // World Projection Matrix Inverse

          watereffect.Parameters["cameraToScreen"].SetValue (cameraToScreenU); // World Projection Matrix

          watereffect.Parameters["oceanToCamera"].SetValue(oceanToCameraU);

          watereffect.Parameters["oceanToWorld"].SetValue(oceanToWorldU);          

          watereffect.Parameters["oceanCameraPos"].SetValue(oceanCameraPosU);

          watereffect.Parameters["oceanSunDir"].SetValue(oceanSunDir);

          watereffect.Parameters["horizon1"].SetValue(horizon1U);

          watereffect.Parameters["horizon2"].SetValue(horizon2U);

          watereffect.Parameters["worldCameraPos"].SetValue(Parent.cam.Position);

          watereffect.Parameters["worldSunDir"].SetValue(worldsunDir);

          watereffect.Parameters["seaColor"].SetValue(seaColor);

          watereffect.Parameters["seaRoughness"].SetValue(sigmaXsq);

          watereffect.Parameters["radius"].SetValue(radius);

          watereffect.Parameters["nbWaves"].SetValue(nbWaves); // number of waves

          watereffect.Parameters["heightOffset"].SetValue(heightOffsetU); ; // so that surface height is centered around z = 0

          watereffect.Parameters["time"].SetValue (timeU); // current time

          // grid cell size in pixels, angle under which a grid cell is seen,

          // and parameters of the geometric series used for wavelengths

          watereffect.Parameters["lods"].SetValue(lodsU);




            if (screengrid == null || screenWidth != device.Viewport.Width || screenHeight != device.Viewport.Height )

            {

                screenWidth = device.Viewport.Width;

                screenHeight = device.Viewport.Height;


                screengrid = new ScreenGrid ();



                float f = 1.25f;

                int NX = (int)(f * screenWidth / resolution);

                int NY = (int)(f * screenHeight / resolution);


                for (int i = 0; i < NY; ++i) 

                {

                    for (int j = 0; j < NX; ++j) 

                    {

                        screengrid.AddVertex (new Vector2(2.0f*f*j/(NX-1.0f)-f, 2.0f*f*i/(NY-1.0f)-f));

                                           }

                }



                for (int i = 0; i < NY-1; ++i) {

                    for (int j = 0; j < NX-1; ++j) {

                        screengrid.AddIndices(i * NX + j);

                        screengrid.AddIndices(i * NX + j + 1);

                        screengrid.AddIndices((i + 1) * NX + j);

                        screengrid.AddIndices((i + 1) * NX + j);

                        screengrid.AddIndices(i * NX + j + 1);

                        screengrid.AddIndices((i + 1) * NX + j + 1);

                    }

                }



                screengrid.UpdateBuffers(device);

    }




      }



and now for the shader code

original code


/*

* Proland: a procedural landscape rendering library.

* Copyright © 2008-2011 INRIA

*

* This program is free software: you can redistribute it and/or modify

* it under the terms of the GNU General Public License as published by

* the Free Software Foundation, either version 3 of the License, or

* (at your option) any later version.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program. If not, see <http://www.gnu.org/licenses/

*/

/*

* Proland is distributed under a dual-license scheme.

* You can obtain a specific license from Inria: proland-licensing@inria.fr.

*/

/*

* Authors: Eric Bruneton, Antoine Begault, Guillaume Piolat.

*/

#include "globalsShader.glhl"

#include "textureTile.glsl"

const float Z0 = 1.0;

uniform float radius;

uniform mat4 cameraToOcean;

uniform mat4 screenToCamera;

uniform mat4 cameraToScreen;

uniform mat3 oceanToCamera;

uniform mat4 oceanToWorld;

uniform vec3 oceanCameraPos;

uniform vec3 oceanSunDir;

uniform vec3 horizon1;

uniform vec3 horizon2;

uniform float nbWaves; // number of waves

uniform sampler1D wavesSampler; // waves parameters (h, omega, kx, ky) in wind space

uniform float heightOffset; // so that surface height is centered around z = 0

uniform float time; // current time

// grid cell size in pixels, angle under which a grid cell is seen,

// and parameters of the geometric series used for wavelengths

uniform vec4 lods;

#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated

#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all

const float g = 9.81;

const float PI = 3.141592657;

#ifdef _VERTEX_

layout(location=0) in vec3 vertex;

out float oceanLod;

out vec2 oceanUv; // coordinates in wind space used to compute P(u)

out vec3 oceanP; // wave point P(u) in ocean space

out vec3 oceanDPdu; // dPdu in wind space, used to compute N

out vec3 oceanDPdv; // dPdv in wind space, used to compute N

out float oceanRoughness; // variance of unresolved waves in wind space

vec2 oceanPos(vec3 vertex, out float t, out vec3 cameraDir, out vec3 oceanDir) {

float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);

cameraDir = normalize((screenToCamera * vec4(vertex.x, min(vertex.y, horizon), 0.0, 1.0)).xyz);

oceanDir = (cameraToOcean * vec4(cameraDir, 0.0)).xyz;

float cz = oceanCameraPos.z;

float dz = oceanDir.z;

if (radius == 0.0) {

t = (heightOffset + Z0 - cz) / dz;

} else {

float b = dz * (cz + radius);

float c = cz * (cz + 2.0 * radius);

float tSphere = - b - sqrt(max(b * b - c, 0.0));

float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));

t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;

}

return oceanCameraPos.xy + t * oceanDir.xy;

}

vec2 oceanPos(vec3 vertex) {

float t;

vec3 cameraDir;

vec3 oceanDir;

return oceanPos(vertex, t, cameraDir, oceanDir);

}

void main() {

float t;

vec3 cameraDir;

vec3 oceanDir;

vec2 uv = oceanPos(vertex, t, cameraDir, oceanDir);

float lod = - t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

vec2 duv = oceanPos(vertex + vec3(0.0, 0.01, 0.0)) - uv;

vec3 dP = vec3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0));

vec3 dPdu = vec3(1.0, 0.0, 0.0);

vec3 dPdv = vec3(0.0, 1.0, 0.0);

float roughness = getSeaRoughness();

if (duv.x != 0.0 || duv.y != 0.0) {

float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);

for (float i = iMin; i < nbWaves; ++i) {

vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

vec3 factor = wm * wt.x * vec3(wt.zw * overk, 1.0);

dP += factor * vec3(s, s, c);

vec3 dPd = factor * vec3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = wt.x / overk;

roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));

}

}

vec3 p = t * oceanDir + dP + vec3(0.0, 0.0, oceanCameraPos.z);

if (radius > 0.0) {

dPdu += vec3(0.0, 0.0, -p.x / (radius + p.z));

dPdv += vec3(0.0, 0.0, -p.y / (radius + p.z));

}

gl_Position = cameraToScreen * vec4(t * cameraDir + oceanToCamera * dP, 1.0);

oceanLod = lod;

oceanUv = uv;

oceanP = p;

oceanDPdu = dPdu;

oceanDPdv = dPdv;

oceanRoughness = roughness;

}

#endif

#ifdef _FRAGMENT_

#include "atmosphereShader.glhl"

#include "oceanBrdf.glhl"

#include "clouds.glhl"

in float oceanLod;

in vec2 oceanUv;

in vec3 oceanP;

in vec3 oceanDPdu;

in vec3 oceanDPdv;

in float oceanRoughness;

layout(location=0) out vec4 data;

void main() {

vec3 WSD = getWorldSunDir();

vec3 WCP = getWorldCameraPos();

float lod = oceanLod;

vec2 uv = oceanUv;

vec3 dPdu = oceanDPdu;

vec3 dPdv = oceanDPdv;

float roughness = oceanRoughness;

float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);

float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);

float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));

for (float i = iMin; i <= iMAX; i += 1.0) {

vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);

vec3 factor = (1.0 - wm) * wn * wt.x * vec3(wt.zw * overk, 1.0);

vec3 dPd = factor * vec3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = i < iMax ? wt.x / overk : 0.0;

float wkh = (1.0 - wn) * kh;

roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));

}

roughness = max(roughness, 1e-5);

vec3 earthCamera = vec3(0.0, 0.0, oceanCameraPos.z + radius);

vec3 earthP = radius > 0.0 ? normalize(oceanP + vec3(0.0, 0.0, radius)) * (radius + 10.0) : oceanP;

vec3 oceanCamera = vec3(0.0, 0.0, oceanCameraPos.z);

vec3 V = normalize(oceanCamera - oceanP);

vec3 N = normalize(cross(dPdu, dPdv));

if (dot(V, N) < 0.0) {

N = reflect(N, V); // reflects backfacing normals

}

vec3 sunL;

vec3 skyE;

vec3 extinction;

sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);

vec3 worldP = (oceanToWorld * vec4(oceanP, 1.0)).xyz;

sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);

vec3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);

// aerial perspective

vec3 inscatter = inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);

vec3 finalColor = surfaceColor * extinction + inscatter;

data.rgb = hdr(finalColor);

data.a = 1.0;

}

#endif



and now for my code


//Global Variables

float4x4 cameraToOcean;

float4x4 screenToCamera; // World Projection Matrix Inverse

float4x4 cameraToScreen; // World Projection Matrix

float3x3 oceanToCamera;

float4x4 oceanToWorld;

float3 oceanCameraPos;

float3 oceanSunDir;

float3 horizon1;

float3 horizon2;

float3 worldCameraPos;

float3 worldSunDir;

float3 seaColor;

float hdrExposure = 0.3f;

float seaRoughness;

float radius;

float nbWaves; // number of waves

float heightOffset; // so that surface height is centered around z = 0

float time; // current time

// grid cell size in pixels, angle under which a grid cell is seen,

// and parameters of the geometric series used for wavelengths

float4 lods;

 

//Constants

#define PI 3.141592657

const float Z0 = 1.0;

const float g = 9.81;

#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated

#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all

//Textures

texture wavesTexture; // waves parameters (h, omega, kx, ky) in wind space texture2d

sampler wavesSampler = sampler_state

{

texture = <wavesTexture>;

magfilter = POINT;

minfilter = POINT;

mipfilter = POINT;

AddressU = CLAMP;

AddressV = CLAMP;

};

 

struct VertexShaderInput

{

float4 Position : POSITION0;

};

struct VertexShaderOutput

{

float4 Position : POSITION0;

float oceanLod : TEXCOORD0;

float2 oceanUv : TEXCOORD1; // coordinates in wind space used to compute P(u)

float3 oceanP: TEXCOORD2; // wave point P(u) in ocean space

float3 oceanDPdu: TEXCOORD3; // dPdu in wind space, used to compute N

float3 oceanDPdv: TEXCOORD4; // dPdv in wind space, used to compute N

float oceanRoughness: TEXCOORD5; // variance of unresolved waves in wind space

};

//--------------------------------------------------------------

//Utilitie Function Section

//--------------------------------------------------------------

float3 hdr(float3 L) {

#ifndef NOHDR

L = L * hdrExposure;

L.r = L.r < 1.413 ? pow(L.r * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.r);

L.g = L.g < 1.413 ? pow(L.g * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.g);

L.b = L.b < 1.413 ? pow(L.b * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.b);

#endif

return L;

}

//---------------------------------------------

// Fresnel Functions

//---------------------------------------------

float meanFresnel(float cosThetaV, float sigmaV) {

return pow(1.0 - cosThetaV, 5.0 * exp(-2.69 * sigmaV)) / (1.0 + 22.7 * pow(sigmaV, 1.5));

}

float meanFresnel(float3 V, float3 N, float sigmaSq) {

return meanFresnel(dot(V, N), sqrt(sigmaSq));

}

//-----------------------------------------------

//Radiance Functions

//-----------------------------------------------

float reflectedSunRadiance(float3 V, float3 N, float3 L, float sigmaSq) {

float3 H = normalize(L + V);

float hn = dot(H, N);

float p = exp(-2.0 * ((1.0 - hn * hn) / sigmaSq) / (1.0 + hn)) / (4.0 * PI * sigmaSq);

float c = 1.0 - dot(V, H);

float c2 = c * c;

float fresnel = 0.02 + 0.98 * c2 * c2 * c;

float zL = dot(L, N);

float zV = dot(V, N);

zL = max(zL, 0.01);

zV = max(zV, 0.01);

// brdf times cos(thetaL)

return zL <= 0.0 ? 0.0 : max(fresnel * p * sqrt(abs(zL / zV)), 0.0);

}

float3 oceanRadiance(float3 V, float3 N, float3 L, float seaRoughness, float3 sunL, float3 skyE) {

float F = meanFresnel(V, N, seaRoughness);

float3 Lsun = reflectedSunRadiance(V, N, L, seaRoughness) * sunL;

float3 Lsky = skyE * F / PI;

float3 Lsea = (1.0 - F) * seaColor * skyE / PI;

return Lsun + Lsky + Lsea;

}

//--------------------------------------------------------------

//Ocean Position Functions

//--------------------------------------------------------------

float2 oceanPos(float3 vertex, out float t, out float3 cameraDir, out float3 oceanDir)

{

float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);

cameraDir = normalize((mul(screenToCamera , float4(vertex.x, min(vertex.y, horizon), 0.0, 1.0))).xyz);

oceanDir = (mul(cameraToOcean , float4(cameraDir, 0.0))).xyz;

float cz = oceanCameraPos.z;

float dz = oceanDir.z;

if (radius == 0.0) {

t = (heightOffset + Z0 - cz) / dz;

} else {

float b = dz * (cz + radius);

float c = cz * (cz + 2.0 * radius);

float tSphere = - b - sqrt(max(b * b - c, 0.0));

float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));

t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;

}

return oceanCameraPos.xy + t * oceanDir.xy;

}

 

float2 oceanPos(float3 vertex) {

float t;

float3 cameraDir;

float3 oceanDir;

return oceanPos(vertex, t, cameraDir, oceanDir);

}

 

 

//--------------------------------------------------------------

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)

{

VertexShaderOutput output = (VertexShaderOutput)0;

float t;

float3 cameraDir;

float3 oceanDir;

float2 uv = oceanPos(input.Position.xyz, t, cameraDir, oceanDir);

float lod = -t / oceanDir.y * lods.y; //-t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

float2 duv = oceanPos(input.Position.xyz + float3(0.0, 0.01, 0.0)) - uv; // maybe y not z


//float4 tempPos = float4(worldPos.x, 0, worldPos.y, 1.0f);

//worldPos /= 2000.0f;

//worldPos += 0.5f / 512.0f;

float3 dP = float3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0)); // maybe y not z

float3 dPdu = float3(1.0, 0.0, 0.0); // maybe y not z

float3 dPdv = float3(0.0, 1.0, 0.0); // maybe y not z

 

float roughness = seaRoughness;

if (duv.x != 0.0 || duv.y != 0.0) {

float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);

for (float i = iMin; i < nbWaves; ++i)

{

float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float3 factor = wm * wt.x * float3(wt.zw * overk, 1.0);

dP += factor * float3(s, s, c);

float3 dPd = factor * float3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = wt.x / overk;

roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));

}

}

 

 

 

float3 p = t * oceanDir + dP + float3(0.0, 0.0, oceanCameraPos.z); // maybe y not z

if (radius > 0.0) {

dPdu += float3(0.0, 0.0, -p.x / (radius + p.z));

dPdv += float3(0.0, 0.0, -p.y / (radius + p.z));

}


output.Position = mul(cameraToScreen, float4(t * cameraDir + mul(dP,oceanToCamera), 1.0));

//output.Position = mul(cameraToScreen,float4(input.Position.xyz,1));

//logrithmic zbuffer.

const float Cc = 1.0;

const float Far = 1000000000000.0;

output.Position.z = log(Cc*output.Position.z + 1) / log(Cc*Far + 1) * output.Position.w;

output.oceanLod = lod;

output.oceanUv = uv;

output.oceanP = p;

output.oceanDPdu = dPdu;

output.oceanDPdv = dPdv;

output.oceanRoughness = roughness;

return output;

}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0

{

float3 WSD = worldSunDir;

float3 WCP = worldCameraPos;

float lod = input.oceanLod;

float2 uv = input.oceanUv;

float3 dPdu = input.oceanDPdu;

float3 dPdv = input.oceanDPdv;

float roughness = input.oceanRoughness;

float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);

float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);

float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));

for (float i = iMin; i <= iMAX; i += 1.0) {

float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);

float3 factor = (1.0 - wm) * wn * wt.x * float3(wt.zw * overk, 1.0);

float3 dPd = factor * float3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = i < iMax ? wt.x / overk : 0.0;

float wkh = (1.0 - wn) * kh;

roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));

}

roughness = max(roughness, 1e-5);

float3 earthCamera = float3(0.0, 0.0, oceanCameraPos.z + radius);

float3 earthP = radius > 0.0 ? normalize(input.oceanP + float3(0.0, 0.0, radius)) * (radius + 10.0) : input.oceanP;

float3 oceanCamera = float3(0.0, 0.0, oceanCameraPos.z);

float3 V = normalize(oceanCamera - input.oceanP);

float3 N = normalize(cross(dPdu, dPdv));

if (dot(V, N) < 0.0) {

N = reflect(N, V); // reflects backfacing normals

}

float3 sunL = (float3)1;

float3 skyE = (float3)1;

float3 extinction = (float3)1;

//sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);

float3 worldP = (mul(oceanToWorld , float4(input.oceanP, 1.0))).xyz;

//sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);

float3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);

// aerial perspective

float3 inscatter = (float3)1; //= inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);

float3 finalColor = surfaceColor * extinction + inscatter;

float4 data;

data.rgb = hdr(finalColor);

data.a = 1.0;

return data;

//return float4(1, 0, 0, 1);

}

technique Technique1

{

pass Pass1

{

// TODO: set renderstates here.

VertexShader = compile vs_3_0 VertexShaderFunction();

PixelShader = compile ps_3_0 PixelShaderFunction();

}

}



and now a picture of the result im getting.


Bare in mind this is suppose to be a sphere, it looks like its half working must be something to do with the y/z axis. I know its not a good thing to just post code and ask for help but im going nuts trying to figure this out any help will be much appreciated.

Budinga

screenshot1120139215.jpg

and this is the flat version it seems to be working but the projection and the surface its projecting is been rendered very strange.

screenshot1120131046.jpg

#5Budinga

Posted 01 January 2013 - 04:09 AM

Hi Guyz. Well I have decided to use the great Eric Bruneton's water shaders in my procedural planet renderer, now I have managed to port the shaders, and also with a slightly modified ocean rendering class I get something on the screen, but due to the fact that he use's, a different coord system, well I think that's it I cant seem to get my brain round it. So I was wondering if anybody could spot my problem.

Original Render Function

bool DrawOceanTask::Impl::run()

{

    if (Logger::DEBUG_LOGGER != NULL) {

        Logger::DEBUG_LOGGER->log("OCEAN", "DrawOcean");

    }

    ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer();

    ptr<Program> prog = SceneManager::getCurrentProgram();


    if (o->nbWavesU == NULL) {

        o->nbWavesU = prog->getUniform1f("nbWaves");

        o->wavesU = prog->getUniformSampler("wavesSampler");

        o->cameraToOceanU = prog->getUniformMatrix4f("cameraToOcean");

        o->screenToCameraU = prog->getUniformMatrix4f("screenToCamera");

        o->cameraToScreenU = prog->getUniformMatrix4f("cameraToScreen");

        o->oceanToCameraU = prog->getUniformMatrix3f("oceanToCamera");

        o->oceanToWorldU = prog->getUniformMatrix4f("oceanToWorld");

        o->oceanCameraPosU = prog->getUniform3f("oceanCameraPos");

        o->oceanSunDirU = prog->getUniform3f("oceanSunDir");

        o->horizon1U = prog->getUniform3f("horizon1");

        o->horizon2U = prog->getUniform3f("horizon2");

        o->timeU = prog->getUniform1f("time");

        o->radiusU = prog->getUniform1f("radius");

        o->heightOffsetU = prog->getUniform1f("heightOffset");

        o->lodsU = prog->getUniform4f("lods");


        assert(o->nbWavesU != NULL);

        o->generateWaves();

    }


    vector< ptr<TileSampler> > uniforms;

    SceneNode::FieldIterator ui = n->getFields();

    while (ui.hasNext()) {

        ptr<TileSampler> u = ui.next().cast<TileSampler>();

        if (u != NULL && u->getTerrain(0) != NULL) {

            u->setTileMap();

        }

    }


    // compute ltoo = localToOcean transform, where ocean frame = tangent space at

    // camera projection on sphere o->radius in local space

    mat4d ctol = n->getLocalToCamera().inverse();

    vec3d cl = ctol * vec3d::ZERO; // camera in local space


    if ((o->radius == 0.0 && cl.z > o->zmin) ||

        (o->radius > 0.0 && cl.length() > o->radius + o->zmin) ||

        (o->radius < 0.0 && vec2d(cl.y, cl.z).length() < -o->radius - o->zmin))

    {

        o->oldLtoo = mat4d::IDENTITY;

        o->offset = vec3d::ZERO;

        return true;

    }


    vec3d ux, uy, uz, oo;


    if (o->radius == 0.0) {

        // flat ocean

        ux = vec3d::UNIT_X;

        uy = vec3d::UNIT_Y;

        uz = vec3d::UNIT_Z;

        oo = vec3d(cl.x, cl.y, 0.0);

    } else if (o->radius > 0.0) {

        // spherical ocean

        uz = cl.normalize(); // unit z vector of ocean frame, in local space

        if (o->oldLtoo != mat4d::IDENTITY) {

            ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();

        } else {

            ux = vec3d::UNIT_Z.crossProduct(uz).normalize();

        }

        uy = uz.crossProduct(ux); // unit y vector

        oo = uz * o->radius; // origin of ocean frame, in local space

    } else {

        // cylindrical ocean

        uz = vec3d(0.0, -cl.y, -cl.z).normalize();

        ux = vec3d::UNIT_X;

        uy = uz.crossProduct(ux);

        oo = vec3d(cl.x, 0.0, 0.0) + uz * o->radius;

    }


    mat4d ltoo = mat4d(

        ux.x, ux.y, ux.z, -ux.dotproduct(oo),

        uy.x, uy.y, uy.z, -uy.dotproduct(oo),

        uz.x, uz.y, uz.z, -uz.dotproduct(oo),

        0.0,  0.0,  0.0,  1.0);

    // compute ctoo = cameraToOcean transform

    mat4d ctoo = ltoo * ctol;


    if (o->oldLtoo != mat4d::IDENTITY) {

        vec3d delta = ltoo * (o->oldLtoo.inverse() * vec3d::ZERO);

        o->offset += delta;

    }

    o->oldLtoo = ltoo;


    mat4d ctos = n->getOwner()->getCameraToScreen();

    mat4d stoc = ctos.inverse();

    vec3d oc = ctoo * vec3d::ZERO;


    if (o->oceanSunDirU != NULL) {

        // TODO how to get sun dir in a better way?

        SceneManager::NodeIterator i = n->getOwner()->getNodes("light");

        if (i.hasNext()) {

            ptr<SceneNode> l = i.next();

            vec3d worldSunDir = l->getLocalToParent() * vec3d::ZERO;

            vec3d oceanSunDir = ltoo.mat3x3() * (n->getWorldToLocal().mat3x3() * worldSunDir);

            o->oceanSunDirU->set(oceanSunDir.cast<float>());

        }

    }


    vec4<GLint> screen = fb->getViewport();


    vec4d frustum[6];

    SceneManager::getFrustumPlanes(ctos, frustum);

    vec3d left = frustum[0].xyz().normalize();

    vec3d right = frustum[1].xyz().normalize();

    float fov = (float) safe_acos(-left.dotproduct(right));

    float pixelSize = atan(tan(fov / 2.0f) / (screen.w / 2.0f)); // angle under which a screen pixel is viewed from the camera


    o->cameraToOceanU->setMatrix(ctoo.cast<float>());

    o->screenToCameraU->setMatrix(stoc.cast<float>());

    o->cameraToScreenU->setMatrix(ctos.cast<float>());

    o->oceanToCameraU->setMatrix(ctoo.inverse().mat3x3().cast<float>());

    o->oceanCameraPosU->set(vec3f(float(-o->offset.x), float(-o->offset.y), float(oc.z)));

    if (o->oceanToWorldU != NULL) {

        o->oceanToWorldU->setMatrix((n->getLocalToWorld() * ltoo.inverse()).cast<float>());

    }


    if (o->horizon1U != NULL) {

        float h = oc.z;

        vec3d A0 = (ctoo * vec4d((stoc * vec4d(0.0, 0.0, 0.0, 1.0)).xyz(), 0.0)).xyz();

        vec3d dA = (ctoo * vec4d((stoc * vec4d(1.0, 0.0, 0.0, 0.0)).xyz(), 0.0)).xyz();

        vec3d B = (ctoo * vec4d((stoc * vec4d(0.0, 1.0, 0.0, 0.0)).xyz(), 0.0)).xyz();

        if (o->radius == 0.0) {

            o->horizon1U->set(vec3f(-(h * 1e-6 + A0.z) / B.z, -dA.z / B.z, 0.0));

            o->horizon2U->set(vec3f::ZERO);

        } else {

            double h1 = h * (h + 2.0 * o->radius);

            double h2 = (h + o->radius) * (h + o->radius);

            double alpha = B.dotproduct(B) * h1 - B.z * B.z * h2;

            double beta0 = (A0.dotproduct(B) * h1 - B.z * A0.z * h2) / alpha;

            double beta1 = (dA.dotproduct(B) * h1 - B.z * dA.z * h2) / alpha;

            double gamma0 = (A0.dotproduct(A0) * h1 - A0.z * A0.z * h2) / alpha;

            double gamma1 = (A0.dotproduct(dA) * h1 - A0.z * dA.z * h2) / alpha;

            double gamma2 = (dA.dotproduct(dA) * h1 - dA.z * dA.z * h2) / alpha;

            o->horizon1U->set(vec3f(-beta0, -beta1, 0.0));

            o->horizon2U->set(vec3f(beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2));

        }

    }


    o->timeU->set(n->getOwner()->getTime() * 1e-6);

    if (o->radiusU != NULL) {

        o->radiusU->set(o->radius < 0.0 ? -o->radius : o->radius);

    }

    o->heightOffsetU->set(-o->meanHeight);

    o->lodsU->set(vec4f(o->resolution,

            pixelSize * o->resolution,

            log(o->lambdaMin) / log(2.0f),

            (o->nbWavesU->get() - 1.0f) / (log(o->lambdaMax) / log(2.0f) -  log(o->lambdaMin) / log(2.0f))));


    if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {

        o->screenWidth = screen.z;

        o->screenHeight = screen.w;

        o->screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);

        o->screenGrid->addAttributeType(0, 2, A32F, false);


        float f = 1.25f;

        int NX = int(f * screen.z / o->resolution);

        int NY = int(f * screen.w / o->resolution);

        for (int i = 0; i < NY; ++i) {

            for (int j = 0; j < NX; ++j) {

                o->screenGrid->addVertex(vec2f(2.0*f*j/(NX-1.0f)-f, 2.0*f*i/(NY-1.0f)-f));

            }

        }

        for (int i = 0; i < NY-1; ++i) {

            for (int j = 0; j < NX-1; ++j) {

                o->screenGrid->addIndice(i*NX+j);

                o->screenGrid->addIndice(i*NX+j+1);

                o->screenGrid->addIndice((i+1)*NX+j);

                o->screenGrid->addIndice((i+1)*NX+j);

                o->screenGrid->addIndice(i*NX+j+1);

                o->screenGrid->addIndice((i+1)*NX+j+1);

            }

        }

    }


    fb->draw(prog, *(o->screenGrid));


    return true;

}



Now my update function (basically tries to do the same thing.

public void Update(GameTime gametime){  // compute ltoo = localToOcean transform, where ocean frame = tangent space at// camera projection on sphere o->radius in local spaceVector3 cl = Vector3.Transform(Vector3.Zero, ctol);//camera in local spaceIf ((radius == 0.0 && cl.Z > zmin) ||(radius > 0.0 && cl.Length() > radius + zmin) ||(radius < 0.0 && new Vector2(cl.Y, cl.Z).Length() < -radius - zmin)){oldLtoo = Matrix.Identity;offset = Vector3.Zero;return;}Vector3 ux, uy, uz, oo;if (radius == 0.0){// flat oceanux = Vector3.UnitX;uy = Vector3.UnitY;uz = Vector3.UnitZ;oo = new Vector3(cl.X, cl.Y, 0.0f);}else if (radius > 0.0){// spherical oceanuz = Vector3.Normalize(cl);// unit z vector of ocean frame, in local spaceif (oldLtoo != Matrix.Identity){//Matrix m = Matrix.Transpose(oldLtoo);//ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();ux = Vector3.Normalize(Vector3.Cross(new Vector3(oldLtoo.M21, oldLtoo.M22, oldLtoo.M23), uz));}else{ux = Vector3.Normalize(Vector3.Cross(Vector3.UnitZ, uz));}uy = Vector3.Cross(uz, ux);// unit y vector // negate this ??//uz * radius; // origin of ocean frame, in local spaceoo = ux * radius; }else{// cylindrical oceanuz = Vector3.Normalize(new Vector3(0, -cl.Y, -cl.Z));ux = Vector3.UnitX;uy = Vector3.Cross(uz, ux);oo = new Vector3(cl.X, 0, 0) + uz * radius;}  Matrix ltoo = new Matrix(ux.X, uy.X, uz.X, 0.0f,ux.Y, uy.Y, uz.Y, 0.0f,ux.Z, uy.Z, uz.Z, 0.0f,-Vector3.Dot(ux, oo), -Vector3.Dot(uy, oo), -Vector3.Dot(uz, oo), 1.0f);   ltoo = Matrix.Transpose(ltoo); // compute ctoo = cameraToOcean transformMatrix ctoo = ltoo * Matrix.Transpose (ctol);    if (oldLtoo != Matrix.Identity){Vector3 delta = Vector3.Transform(Vector3.Zero, Matrix.Transpose ( ltoo * Matrix.Invert(oldLtoo)));offset += delta;}oldLtoo = ltoo; //added transposeMatrix ctos = Matrix.Transpose (Parent.cam.Projection); //world*view*projection //n->getOwner()->getCameraToScreen();Matrix stoc = Matrix.Invert (ctos);Vector3 oc = Vector3.Transform(Vector3.Zero, ctoo);//o->oceanSunDirU->set(oceanSunDir.cast<float>());Vector3 worldsunDir = Parent.vLightDirection;Vector3 oceanSunDir = Vector3.Transform(worldsunDir, ltoo * Parent.cam.View); BoundingFrustum frustum = new BoundingFrustum(ctos);Vector3 left = frustum.Left.Normal;Vector3 right = frustum.Right.Normal;float fov = (float)System.Math.Acos(Vector3.Dot(-left, right)); float pixelSize = (float)System.Math.Atan(System.Math.Tan(fov / 2.0f) / (device.Viewport.Height / 2.0f));// angle under which a screen pixel is viewed from the camera float h = oc.Z; Vector4 tmp1,tmp2;tmp1 = Vector4.Transform ( new Vector4 (0,0,0,1),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 A0 = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z); tmp1 = Vector4.Transform ( new Vector4 (1,0,0,0),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 dA = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);tmp1 = Vector4.Transform ( new Vector4 (0,1,0,0),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 B = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);if (radius == 0.0){horizon1U = new Vector3(-(h * 1e-6f + A0.Z) / B.Z, -dA.Z / B.Z, 0);horizon2U = Vector3.Zero;}else{double h1 = h * (h + 2.0 * radius);double h2 = (h + radius) * (h + radius);double alpha = Vector3.Dot (B,B) * h1 - B.Z * B.Z * h2;double beta0 = (Vector3.Dot (A0,B) * h1 - B.Z * A0.Z * h2) / alpha;double beta1 = (Vector3.Dot (dA,B) * h1 - B.Z * dA.Z * h2) / alpha;double gamma0 = (Vector3.Dot (A0,A0) * h1 - A0.Z * A0.Z * h2) / alpha;double gamma1 = (Vector3.Dot(A0,dA) * h1 - A0.Z * dA.Z * h2) / alpha;double gamma2 = (Vector3.Dot(dA,dA) * h1 - dA.Z * dA.Z * h2) / alpha;horizon1U = new Vector3((float)-beta0, (float)-beta1, 0);horizon2U = new Vector3((float)beta0 * (float)beta0 - (float)gamma0, 2.0f * ((float)beta0 * (float)beta1 - (float)gamma1), (float)beta1 * (float)beta1 - (float)gamma2);}  timeU = (float)gametime.TotalGameTime.TotalMilliseconds *0.0001f; //gametime.ElapsedGameTime.Milliseconds * 1e-6f;heightOffsetU = -meanHeight;lodsU = new Vector4(resolution,pixelSize * resolution,(float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f),(nbWaves - 1.0f) / ((float)System.Math.Log(lambdaMax) / (float)System.Math.Log(2.0f) - (float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f)));  cameraToOceanU = Matrix.Transpose (ctoo);screenToCameraU = stoc;//Matrix.Transpose ( Matrix.Invert ( Parent.cam.view));//stoc;cameraToScreenU = ctos; // already transposed  oceanCameraPosU = new Vector3(-offset.X, -offset.Y, -offset.Z);oceanToWorldU = Matrix.Transpose ( Parent.cam.Projection * Parent.cam.View) * Matrix.Invert (ltoo); //Parent.cam.View * Matrix.Invert(ltoo);oceanToCameraU = Matrix.Transpose(Matrix.Invert(ctoo));//Global Variableswatereffect.Parameters["cameraToOcean"].SetValue(cameraToOceanU);watereffect.Parameters["screenToCamera"].SetValue(screenToCameraU); // World Projection Matrix Inversewatereffect.Parameters["cameraToScreen"].SetValue (cameraToScreenU); // World Projection Matrixwatereffect.Parameters["oceanToCamera"].SetValue(oceanToCameraU);watereffect.Parameters["oceanToWorld"].SetValue(oceanToWorldU);//float height = Vector3.Distance (Parent.cam.Position ,Vector3.Zero) - meanHeight;watereffect.Parameters["oceanCameraPos"].SetValue(oceanCameraPosU);watereffect.Parameters["oceanSunDir"].SetValue(oceanSunDir);watereffect.Parameters["horizon1"].SetValue(horizon1U);watereffect.Parameters["horizon2"].SetValue(horizon2U);watereffect.Parameters["worldCameraPos"].SetValue(Parent.cam.Position);watereffect.Parameters["worldSunDir"].SetValue(worldsunDir);watereffect.Parameters["seaColor"].SetValue(seaColor);watereffect.Parameters["seaRoughness"].SetValue(sigmaXsq);watereffect.Parameters["radius"].SetValue(radius);watereffect.Parameters["nbWaves"].SetValue(nbWaves); // number of waveswatereffect.Parameters["heightOffset"].SetValue(heightOffsetU); ; // so that surface height is centered around z = 0watereffect.Parameters["time"].SetValue (timeU); // current time// grid cell size in pixels, angle under which a grid cell is seen,// and parameters of the geometric series used for wavelengthswatereffect.Parameters["lods"].SetValue(lodsU); //if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {if (screengrid == null || screenWidth != device.Viewport.Width || screenHeight != device.Viewport.Height ){screenWidth = device.Viewport.Width;screenHeight = device.Viewport.Height;//screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);//screenGrid->addAttributeType(0, 2, A32F, false);screengrid = new ScreenGrid (); float f = 1.25f;int NX = (int)(f * screenWidth / resolution);int NY = (int)(f * screenHeight / resolution);for (int i = 0; i < NY; ++i){for (int j = 0; j < NX; ++j){screengrid.AddVertex (new Vector2(2.0f*f*j/(NX-1.0f)-f, 2.0f*f*i/(NY-1.0f)-f));}} for (int i = 0; i < NY-1; ++i) {for (int j = 0; j < NX-1; ++j) {screengrid.AddIndices(i * NX + j);screengrid.AddIndices(i * NX + j + 1);screengrid.AddIndices((i + 1) * NX + j);screengrid.AddIndices((i + 1) * NX + j);screengrid.AddIndices(i * NX + j + 1);screengrid.AddIndices((i + 1) * NX + j + 1);}} screengrid.UpdateBuffers(device);} }

and now for the shader code

original code


/*

* Proland: a procedural landscape rendering library.

* Copyright © 2008-2011 INRIA

*

* This program is free software: you can redistribute it and/or modify

* it under the terms of the GNU General Public License as published by

* the Free Software Foundation, either version 3 of the License, or

* (at your option) any later version.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program. If not, see <http://www.gnu.org/licenses/

*/

/*

* Proland is distributed under a dual-license scheme.

* You can obtain a specific license from Inria: proland-licensing@inria.fr.

*/

/*

* Authors: Eric Bruneton, Antoine Begault, Guillaume Piolat.

*/

#include "globalsShader.glhl"

#include "textureTile.glsl"

const float Z0 = 1.0;

uniform float radius;

uniform mat4 cameraToOcean;

uniform mat4 screenToCamera;

uniform mat4 cameraToScreen;

uniform mat3 oceanToCamera;

uniform mat4 oceanToWorld;

uniform vec3 oceanCameraPos;

uniform vec3 oceanSunDir;

uniform vec3 horizon1;

uniform vec3 horizon2;

uniform float nbWaves; // number of waves

uniform sampler1D wavesSampler; // waves parameters (h, omega, kx, ky) in wind space

uniform float heightOffset; // so that surface height is centered around z = 0

uniform float time; // current time

// grid cell size in pixels, angle under which a grid cell is seen,

// and parameters of the geometric series used for wavelengths

uniform vec4 lods;

#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated

#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all

const float g = 9.81;

const float PI = 3.141592657;

#ifdef _VERTEX_

layout(location=0) in vec3 vertex;

out float oceanLod;

out vec2 oceanUv; // coordinates in wind space used to compute P(u)

out vec3 oceanP; // wave point P(u) in ocean space

out vec3 oceanDPdu; // dPdu in wind space, used to compute N

out vec3 oceanDPdv; // dPdv in wind space, used to compute N

out float oceanRoughness; // variance of unresolved waves in wind space

vec2 oceanPos(vec3 vertex, out float t, out vec3 cameraDir, out vec3 oceanDir) {

float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);

cameraDir = normalize((screenToCamera * vec4(vertex.x, min(vertex.y, horizon), 0.0, 1.0)).xyz);

oceanDir = (cameraToOcean * vec4(cameraDir, 0.0)).xyz;

float cz = oceanCameraPos.z;

float dz = oceanDir.z;

if (radius == 0.0) {

t = (heightOffset + Z0 - cz) / dz;

} else {

float b = dz * (cz + radius);

float c = cz * (cz + 2.0 * radius);

float tSphere = - b - sqrt(max(b * b - c, 0.0));

float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));

t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;

}

return oceanCameraPos.xy + t * oceanDir.xy;

}

vec2 oceanPos(vec3 vertex) {

float t;

vec3 cameraDir;

vec3 oceanDir;

return oceanPos(vertex, t, cameraDir, oceanDir);

}

void main() {

float t;

vec3 cameraDir;

vec3 oceanDir;

vec2 uv = oceanPos(vertex, t, cameraDir, oceanDir);

float lod = - t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

vec2 duv = oceanPos(vertex + vec3(0.0, 0.01, 0.0)) - uv;

vec3 dP = vec3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0));

vec3 dPdu = vec3(1.0, 0.0, 0.0);

vec3 dPdv = vec3(0.0, 1.0, 0.0);

float roughness = getSeaRoughness();

if (duv.x != 0.0 || duv.y != 0.0) {

float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);

for (float i = iMin; i < nbWaves; ++i) {

vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

vec3 factor = wm * wt.x * vec3(wt.zw * overk, 1.0);

dP += factor * vec3(s, s, c);

vec3 dPd = factor * vec3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = wt.x / overk;

roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));

}

}

vec3 p = t * oceanDir + dP + vec3(0.0, 0.0, oceanCameraPos.z);

if (radius > 0.0) {

dPdu += vec3(0.0, 0.0, -p.x / (radius + p.z));

dPdv += vec3(0.0, 0.0, -p.y / (radius + p.z));

}

gl_Position = cameraToScreen * vec4(t * cameraDir + oceanToCamera * dP, 1.0);

oceanLod = lod;

oceanUv = uv;

oceanP = p;

oceanDPdu = dPdu;

oceanDPdv = dPdv;

oceanRoughness = roughness;

}

#endif

#ifdef _FRAGMENT_

#include "atmosphereShader.glhl"

#include "oceanBrdf.glhl"

#include "clouds.glhl"

in float oceanLod;

in vec2 oceanUv;

in vec3 oceanP;

in vec3 oceanDPdu;

in vec3 oceanDPdv;

in float oceanRoughness;

layout(location=0) out vec4 data;

void main() {

vec3 WSD = getWorldSunDir();

vec3 WCP = getWorldCameraPos();

float lod = oceanLod;

vec2 uv = oceanUv;

vec3 dPdu = oceanDPdu;

vec3 dPdv = oceanDPdv;

float roughness = oceanRoughness;

float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);

float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);

float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));

for (float i = iMin; i <= iMAX; i += 1.0) {

vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);

vec3 factor = (1.0 - wm) * wn * wt.x * vec3(wt.zw * overk, 1.0);

vec3 dPd = factor * vec3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = i < iMax ? wt.x / overk : 0.0;

float wkh = (1.0 - wn) * kh;

roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));

}

roughness = max(roughness, 1e-5);

vec3 earthCamera = vec3(0.0, 0.0, oceanCameraPos.z + radius);

vec3 earthP = radius > 0.0 ? normalize(oceanP + vec3(0.0, 0.0, radius)) * (radius + 10.0) : oceanP;

vec3 oceanCamera = vec3(0.0, 0.0, oceanCameraPos.z);

vec3 V = normalize(oceanCamera - oceanP);

vec3 N = normalize(cross(dPdu, dPdv));

if (dot(V, N) < 0.0) {

N = reflect(N, V); // reflects backfacing normals

}

vec3 sunL;

vec3 skyE;

vec3 extinction;

sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);

vec3 worldP = (oceanToWorld * vec4(oceanP, 1.0)).xyz;

sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);

vec3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);

// aerial perspective

vec3 inscatter = inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);

vec3 finalColor = surfaceColor * extinction + inscatter;

data.rgb = hdr(finalColor);

data.a = 1.0;

}

#endif



and now for my code


//Global Variables

float4x4 cameraToOcean;

float4x4 screenToCamera; // World Projection Matrix Inverse

float4x4 cameraToScreen; // World Projection Matrix

float3x3 oceanToCamera;

float4x4 oceanToWorld;

float3 oceanCameraPos;

float3 oceanSunDir;

float3 horizon1;

float3 horizon2;

float3 worldCameraPos;

float3 worldSunDir;

float3 seaColor;

float hdrExposure = 0.3f;

float seaRoughness;

float radius;

float nbWaves; // number of waves

float heightOffset; // so that surface height is centered around z = 0

float time; // current time

// grid cell size in pixels, angle under which a grid cell is seen,

// and parameters of the geometric series used for wavelengths

float4 lods;

 

//Constants

#define PI 3.141592657

const float Z0 = 1.0;

const float g = 9.81;

#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated

#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all

//Textures

texture wavesTexture; // waves parameters (h, omega, kx, ky) in wind space texture2d

sampler wavesSampler = sampler_state

{

texture = <wavesTexture>;

magfilter = POINT;

minfilter = POINT;

mipfilter = POINT;

AddressU = CLAMP;

AddressV = CLAMP;

};

 

struct VertexShaderInput

{

float4 Position : POSITION0;

};

struct VertexShaderOutput

{

float4 Position : POSITION0;

float oceanLod : TEXCOORD0;

float2 oceanUv : TEXCOORD1; // coordinates in wind space used to compute P(u)

float3 oceanP: TEXCOORD2; // wave point P(u) in ocean space

float3 oceanDPdu: TEXCOORD3; // dPdu in wind space, used to compute N

float3 oceanDPdv: TEXCOORD4; // dPdv in wind space, used to compute N

float oceanRoughness: TEXCOORD5; // variance of unresolved waves in wind space

};

//--------------------------------------------------------------

//Utilitie Function Section

//--------------------------------------------------------------

float3 hdr(float3 L) {

#ifndef NOHDR

L = L * hdrExposure;

L.r = L.r < 1.413 ? pow(L.r * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.r);

L.g = L.g < 1.413 ? pow(L.g * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.g);

L.b = L.b < 1.413 ? pow(L.b * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.b);

#endif

return L;

}

//---------------------------------------------

// Fresnel Functions

//---------------------------------------------

float meanFresnel(float cosThetaV, float sigmaV) {

return pow(1.0 - cosThetaV, 5.0 * exp(-2.69 * sigmaV)) / (1.0 + 22.7 * pow(sigmaV, 1.5));

}

float meanFresnel(float3 V, float3 N, float sigmaSq) {

return meanFresnel(dot(V, N), sqrt(sigmaSq));

}

//-----------------------------------------------

//Radiance Functions

//-----------------------------------------------

float reflectedSunRadiance(float3 V, float3 N, float3 L, float sigmaSq) {

float3 H = normalize(L + V);

float hn = dot(H, N);

float p = exp(-2.0 * ((1.0 - hn * hn) / sigmaSq) / (1.0 + hn)) / (4.0 * PI * sigmaSq);

float c = 1.0 - dot(V, H);

float c2 = c * c;

float fresnel = 0.02 + 0.98 * c2 * c2 * c;

float zL = dot(L, N);

float zV = dot(V, N);

zL = max(zL, 0.01);

zV = max(zV, 0.01);

// brdf times cos(thetaL)

return zL <= 0.0 ? 0.0 : max(fresnel * p * sqrt(abs(zL / zV)), 0.0);

}

float3 oceanRadiance(float3 V, float3 N, float3 L, float seaRoughness, float3 sunL, float3 skyE) {

float F = meanFresnel(V, N, seaRoughness);

float3 Lsun = reflectedSunRadiance(V, N, L, seaRoughness) * sunL;

float3 Lsky = skyE * F / PI;

float3 Lsea = (1.0 - F) * seaColor * skyE / PI;

return Lsun + Lsky + Lsea;

}

//--------------------------------------------------------------

//Ocean Position Functions

//--------------------------------------------------------------

float2 oceanPos(float3 vertex, out float t, out float3 cameraDir, out float3 oceanDir)

{

float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);

cameraDir = normalize((mul(screenToCamera , float4(vertex.x, min(vertex.y, horizon), 0.0, 1.0))).xyz);

oceanDir = (mul(cameraToOcean , float4(cameraDir, 0.0))).xyz;

float cz = oceanCameraPos.z;

float dz = oceanDir.z;

if (radius == 0.0) {

t = (heightOffset + Z0 - cz) / dz;

} else {

float b = dz * (cz + radius);

float c = cz * (cz + 2.0 * radius);

float tSphere = - b - sqrt(max(b * b - c, 0.0));

float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));

t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;

}

return oceanCameraPos.xy + t * oceanDir.xy;

}

 

float2 oceanPos(float3 vertex) {

float t;

float3 cameraDir;

float3 oceanDir;

return oceanPos(vertex, t, cameraDir, oceanDir);

}

 

 

//--------------------------------------------------------------

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)

{

VertexShaderOutput output = (VertexShaderOutput)0;

float t;

float3 cameraDir;

float3 oceanDir;

float2 uv = oceanPos(input.Position.xyz, t, cameraDir, oceanDir);

float lod = -t / oceanDir.y * lods.y; //-t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

float2 duv = oceanPos(input.Position.xyz + float3(0.0, 0.01, 0.0)) - uv; // maybe y not z


//float4 tempPos = float4(worldPos.x, 0, worldPos.y, 1.0f);

//worldPos /= 2000.0f;

//worldPos += 0.5f / 512.0f;

float3 dP = float3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0)); // maybe y not z

float3 dPdu = float3(1.0, 0.0, 0.0); // maybe y not z

float3 dPdv = float3(0.0, 1.0, 0.0); // maybe y not z

 

float roughness = seaRoughness;

if (duv.x != 0.0 || duv.y != 0.0) {

float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);

for (float i = iMin; i < nbWaves; ++i)

{

float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float3 factor = wm * wt.x * float3(wt.zw * overk, 1.0);

dP += factor * float3(s, s, c);

float3 dPd = factor * float3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = wt.x / overk;

roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));

}

}

 

 

 

float3 p = t * oceanDir + dP + float3(0.0, 0.0, oceanCameraPos.z); // maybe y not z

if (radius > 0.0) {

dPdu += float3(0.0, 0.0, -p.x / (radius + p.z));

dPdv += float3(0.0, 0.0, -p.y / (radius + p.z));

}


output.Position = mul(cameraToScreen, float4(t * cameraDir + mul(dP,oceanToCamera), 1.0));

//output.Position = mul(cameraToScreen,float4(input.Position.xyz,1));

//logrithmic zbuffer.

const float Cc = 1.0;

const float Far = 1000000000000.0;

output.Position.z = log(Cc*output.Position.z + 1) / log(Cc*Far + 1) * output.Position.w;

output.oceanLod = lod;

output.oceanUv = uv;

output.oceanP = p;

output.oceanDPdu = dPdu;

output.oceanDPdv = dPdv;

output.oceanRoughness = roughness;

return output;

}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0

{

float3 WSD = worldSunDir;

float3 WCP = worldCameraPos;

float lod = input.oceanLod;

float2 uv = input.oceanUv;

float3 dPdu = input.oceanDPdu;

float3 dPdv = input.oceanDPdv;

float roughness = input.oceanRoughness;

float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);

float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);

float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));

for (float i = iMin; i <= iMAX; i += 1.0) {

float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);

float3 factor = (1.0 - wm) * wn * wt.x * float3(wt.zw * overk, 1.0);

float3 dPd = factor * float3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = i < iMax ? wt.x / overk : 0.0;

float wkh = (1.0 - wn) * kh;

roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));

}

roughness = max(roughness, 1e-5);

float3 earthCamera = float3(0.0, 0.0, oceanCameraPos.z + radius);

float3 earthP = radius > 0.0 ? normalize(input.oceanP + float3(0.0, 0.0, radius)) * (radius + 10.0) : input.oceanP;

float3 oceanCamera = float3(0.0, 0.0, oceanCameraPos.z);

float3 V = normalize(oceanCamera - input.oceanP);

float3 N = normalize(cross(dPdu, dPdv));

if (dot(V, N) < 0.0) {

N = reflect(N, V); // reflects backfacing normals

}

float3 sunL = (float3)1;

float3 skyE = (float3)1;

float3 extinction = (float3)1;

//sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);

float3 worldP = (mul(oceanToWorld , float4(input.oceanP, 1.0))).xyz;

//sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);

float3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);

// aerial perspective

float3 inscatter = (float3)1; //= inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);

float3 finalColor = surfaceColor * extinction + inscatter;

float4 data;

data.rgb = hdr(finalColor);

data.a = 1.0;

return data;

//return float4(1, 0, 0, 1);

}

technique Technique1

{

pass Pass1

{

// TODO: set renderstates here.

VertexShader = compile vs_3_0 VertexShaderFunction();

PixelShader = compile ps_3_0 PixelShaderFunction();

}

}



and now a picture of the result im getting.


Bare in mind this is suppose to be a sphere, it looks like its half working must be something to do with the y/z axis. I know its not a good thing to just post code and ask for help but im going nuts trying to figure this out any help will be much appreciated.

Budinga

screenshot1120139215.jpg

and this is the flat version it seems to be working but the projection and the surface its projecting is been rendered very strange.

screenshot1120131046.jpg

#4Budinga

Posted 01 January 2013 - 04:08 AM

Hi Guyz. Well I have decided to use the great Eric Bruneton's water shaders in my procedural planet renderer, now I have managed to port the shaders, and also with a slightly modified ocean rendering class I get something on the screen, but due to the fact that he use's, a different coord system, well I think that's it I cant seem to get my brain round it. So I was wondering if anybody could spot my problem.

Original Render Function

bool DrawOceanTask::Impl::run(){if (Logger::DEBUG_LOGGER != NULL) {Logger::DEBUG_LOGGER->log("OCEAN", "DrawOcean");}ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer();ptr<Program> prog = SceneManager::getCurrentProgram();if (o->nbWavesU == NULL) {o->nbWavesU = prog->getUniform1f("nbWaves");o->wavesU = prog->getUniformSampler("wavesSampler");o->cameraToOceanU = prog->getUniformMatrix4f("cameraToOcean");o->screenToCameraU = prog->getUniformMatrix4f("screenToCamera");o->cameraToScreenU = prog->getUniformMatrix4f("cameraToScreen");o->oceanToCameraU = prog->getUniformMatrix3f("oceanToCamera");o->oceanToWorldU = prog->getUniformMatrix4f("oceanToWorld");o->oceanCameraPosU = prog->getUniform3f("oceanCameraPos");o->oceanSunDirU = prog->getUniform3f("oceanSunDir");o->horizon1U = prog->getUniform3f("horizon1");o->horizon2U = prog->getUniform3f("horizon2");o->timeU = prog->getUniform1f("time");o->radiusU = prog->getUniform1f("radius");o->heightOffsetU = prog->getUniform1f("heightOffset");o->lodsU = prog->getUniform4f("lods");assert(o->nbWavesU != NULL);o->generateWaves();}vector< ptr<TileSampler> > uniforms;SceneNode::FieldIterator ui = n->getFields();while (ui.hasNext()) {ptr<TileSampler> u = ui.next().cast<TileSampler>();if (u != NULL && u->getTerrain(0) != NULL) {u->setTileMap();}}// compute ltoo = localToOcean transform, where ocean frame = tangent space at// camera projection on sphere o->radius in local spacemat4d ctol = n->getLocalToCamera().inverse();vec3d cl = ctol * vec3d::ZERO; // camera in local spaceif ((o->radius == 0.0 && cl.z > o->zmin) ||(o->radius > 0.0 && cl.length() > o->radius + o->zmin) ||(o->radius < 0.0 && vec2d(cl.y, cl.z).length() < -o->radius - o->zmin)){o->oldLtoo = mat4d::IDENTITY;o->offset = vec3d::ZERO;return true;}vec3d ux, uy, uz, oo;if (o->radius == 0.0) {// flat oceanux = vec3d::UNIT_X;uy = vec3d::UNIT_Y;uz = vec3d::UNIT_Z;oo = vec3d(cl.x, cl.y, 0.0);} else if (o->radius > 0.0) {// spherical oceanuz = cl.normalize(); // unit z vector of ocean frame, in local spaceif (o->oldLtoo != mat4d::IDENTITY) {ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();} else {ux = vec3d::UNIT_Z.crossProduct(uz).normalize();}uy = uz.crossProduct(ux); // unit y vectoroo = uz * o->radius; // origin of ocean frame, in local space} else {// cylindrical oceanuz = vec3d(0.0, -cl.y, -cl.z).normalize();ux = vec3d::UNIT_X;uy = uz.crossProduct(ux);oo = vec3d(cl.x, 0.0, 0.0) + uz * o->radius;}mat4d ltoo = mat4d(ux.x, ux.y, ux.z, -ux.dotproduct(oo),uy.x, uy.y, uy.z, -uy.dotproduct(oo),uz.x, uz.y, uz.z, -uz.dotproduct(oo),0.0, 0.0, 0.0, 1.0);// compute ctoo = cameraToOcean transformmat4d ctoo = ltoo * ctol;if (o->oldLtoo != mat4d::IDENTITY) {vec3d delta = ltoo * (o->oldLtoo.inverse() * vec3d::ZERO);o->offset += delta;}o->oldLtoo = ltoo;mat4d ctos = n->getOwner()->getCameraToScreen();mat4d stoc = ctos.inverse();vec3d oc = ctoo * vec3d::ZERO;if (o->oceanSunDirU != NULL) {// TODO how to get sun dir in a better way?SceneManager::NodeIterator i = n->getOwner()->getNodes("light");if (i.hasNext()) {ptr<SceneNode> l = i.next();vec3d worldSunDir = l->getLocalToParent() * vec3d::ZERO;vec3d oceanSunDir = ltoo.mat3x3() * (n->getWorldToLocal().mat3x3() * worldSunDir);o->oceanSunDirU->set(oceanSunDir.cast<float>());}}vec4<GLint> screen = fb->getViewport();vec4d frustum[6];SceneManager::getFrustumPlanes(ctos, frustum);vec3d left = frustum[0].xyz().normalize();vec3d right = frustum[1].xyz().normalize();float fov = (float) safe_acos(-left.dotproduct(right));float pixelSize = atan(tan(fov / 2.0f) / (screen.w / 2.0f)); // angle under which a screen pixel is viewed from the camerao->cameraToOceanU->setMatrix(ctoo.cast<float>());o->screenToCameraU->setMatrix(stoc.cast<float>());o->cameraToScreenU->setMatrix(ctos.cast<float>());o->oceanToCameraU->setMatrix(ctoo.inverse().mat3x3().cast<float>());o->oceanCameraPosU->set(vec3f(float(-o->offset.x), float(-o->offset.y), float(oc.z)));if (o->oceanToWorldU != NULL) {o->oceanToWorldU->setMatrix((n->getLocalToWorld() * ltoo.inverse()).cast<float>());}if (o->horizon1U != NULL) {float h = oc.z;vec3d A0 = (ctoo * vec4d((stoc * vec4d(0.0, 0.0, 0.0, 1.0)).xyz(), 0.0)).xyz();vec3d dA = (ctoo * vec4d((stoc * vec4d(1.0, 0.0, 0.0, 0.0)).xyz(), 0.0)).xyz();vec3d B = (ctoo * vec4d((stoc * vec4d(0.0, 1.0, 0.0, 0.0)).xyz(), 0.0)).xyz();if (o->radius == 0.0) {o->horizon1U->set(vec3f(-(h * 1e-6 + A0.z) / B.z, -dA.z / B.z, 0.0));o->horizon2U->set(vec3f::ZERO);} else {double h1 = h * (h + 2.0 * o->radius);double h2 = (h + o->radius) * (h + o->radius);double alpha = B.dotproduct(B) * h1 - B.z * B.z * h2;double beta0 = (A0.dotproduct(B) * h1 - B.z * A0.z * h2) / alpha;double beta1 = (dA.dotproduct(B) * h1 - B.z * dA.z * h2) / alpha;double gamma0 = (A0.dotproduct(A0) * h1 - A0.z * A0.z * h2) / alpha;double gamma1 = (A0.dotproduct(dA) * h1 - A0.z * dA.z * h2) / alpha;double gamma2 = (dA.dotproduct(dA) * h1 - dA.z * dA.z * h2) / alpha;o->horizon1U->set(vec3f(-beta0, -beta1, 0.0));o->horizon2U->set(vec3f(beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2));}}o->timeU->set(n->getOwner()->getTime() * 1e-6);if (o->radiusU != NULL) {o->radiusU->set(o->radius < 0.0 ? -o->radius : o->radius);}o->heightOffsetU->set(-o->meanHeight);o->lodsU->set(vec4f(o->resolution,pixelSize * o->resolution,log(o->lambdaMin) / log(2.0f),(o->nbWavesU->get() - 1.0f) / (log(o->lambdaMax) / log(2.0f) - log(o->lambdaMin) / log(2.0f))));if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {o->screenWidth = screen.z;o->screenHeight = screen.w;o->screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);o->screenGrid->addAttributeType(0, 2, A32F, false);float f = 1.25f;int NX = int(f * screen.z / o->resolution);int NY = int(f * screen.w / o->resolution);for (int i = 0; i < NY; ++i) {for (int j = 0; j < NX; ++j) {o->screenGrid->addVertex(vec2f(2.0*f*j/(NX-1.0f)-f, 2.0*f*i/(NY-1.0f)-f));}}for (int i = 0; i < NY-1; ++i) {for (int j = 0; j < NX-1; ++j) {o->screenGrid->addIndice(i*NX+j);o->screenGrid->addIndice(i*NX+j+1);o->screenGrid->addIndice((i+1)*NX+j);o->screenGrid->addIndice((i+1)*NX+j);o->screenGrid->addIndice(i*NX+j+1);o->screenGrid->addIndice((i+1)*NX+j+1);}}}fb->draw(prog, *(o->screenGrid));return true;}


Now my update function (basically tries to do the same thing.

public void Update(GameTime gametime){  // compute ltoo = localToOcean transform, where ocean frame = tangent space at// camera projection on sphere o->radius in local spaceVector3 cl = Vector3.Transform(Vector3.Zero, ctol);//camera in local spaceIf ((radius == 0.0 && cl.Z > zmin) ||(radius > 0.0 && cl.Length() > radius + zmin) ||(radius < 0.0 && new Vector2(cl.Y, cl.Z).Length() < -radius - zmin)){oldLtoo = Matrix.Identity;offset = Vector3.Zero;return;}Vector3 ux, uy, uz, oo;if (radius == 0.0){// flat oceanux = Vector3.UnitX;uy = Vector3.UnitY;uz = Vector3.UnitZ;oo = new Vector3(cl.X, cl.Y, 0.0f);}else if (radius > 0.0){// spherical oceanuz = Vector3.Normalize(cl);// unit z vector of ocean frame, in local spaceif (oldLtoo != Matrix.Identity){//Matrix m = Matrix.Transpose(oldLtoo);//ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();ux = Vector3.Normalize(Vector3.Cross(new Vector3(oldLtoo.M21, oldLtoo.M22, oldLtoo.M23), uz));}else{ux = Vector3.Normalize(Vector3.Cross(Vector3.UnitZ, uz));}uy = Vector3.Cross(uz, ux);// unit y vector // negate this ??//uz * radius; // origin of ocean frame, in local spaceoo = ux * radius; }else{// cylindrical oceanuz = Vector3.Normalize(new Vector3(0, -cl.Y, -cl.Z));ux = Vector3.UnitX;uy = Vector3.Cross(uz, ux);oo = new Vector3(cl.X, 0, 0) + uz * radius;}  Matrix ltoo = new Matrix(ux.X, uy.X, uz.X, 0.0f,ux.Y, uy.Y, uz.Y, 0.0f,ux.Z, uy.Z, uz.Z, 0.0f,-Vector3.Dot(ux, oo), -Vector3.Dot(uy, oo), -Vector3.Dot(uz, oo), 1.0f);   ltoo = Matrix.Transpose(ltoo); // compute ctoo = cameraToOcean transformMatrix ctoo = ltoo * Matrix.Transpose (ctol);    if (oldLtoo != Matrix.Identity){Vector3 delta = Vector3.Transform(Vector3.Zero, Matrix.Transpose ( ltoo * Matrix.Invert(oldLtoo)));offset += delta;}oldLtoo = ltoo; //added transposeMatrix ctos = Matrix.Transpose (Parent.cam.Projection); //world*view*projection //n->getOwner()->getCameraToScreen();Matrix stoc = Matrix.Invert (ctos);Vector3 oc = Vector3.Transform(Vector3.Zero, ctoo);//o->oceanSunDirU->set(oceanSunDir.cast<float>());Vector3 worldsunDir = Parent.vLightDirection;Vector3 oceanSunDir = Vector3.Transform(worldsunDir, ltoo * Parent.cam.View); BoundingFrustum frustum = new BoundingFrustum(ctos);Vector3 left = frustum.Left.Normal;Vector3 right = frustum.Right.Normal;float fov = (float)System.Math.Acos(Vector3.Dot(-left, right)); float pixelSize = (float)System.Math.Atan(System.Math.Tan(fov / 2.0f) / (device.Viewport.Height / 2.0f));// angle under which a screen pixel is viewed from the camera float h = oc.Z; Vector4 tmp1,tmp2;tmp1 = Vector4.Transform ( new Vector4 (0,0,0,1),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 A0 = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z); tmp1 = Vector4.Transform ( new Vector4 (1,0,0,0),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 dA = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);tmp1 = Vector4.Transform ( new Vector4 (0,1,0,0),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 B = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);if (radius == 0.0){horizon1U = new Vector3(-(h * 1e-6f + A0.Z) / B.Z, -dA.Z / B.Z, 0);horizon2U = Vector3.Zero;}else{double h1 = h * (h + 2.0 * radius);double h2 = (h + radius) * (h + radius);double alpha = Vector3.Dot (B,B) * h1 - B.Z * B.Z * h2;double beta0 = (Vector3.Dot (A0,B) * h1 - B.Z * A0.Z * h2) / alpha;double beta1 = (Vector3.Dot (dA,B) * h1 - B.Z * dA.Z * h2) / alpha;double gamma0 = (Vector3.Dot (A0,A0) * h1 - A0.Z * A0.Z * h2) / alpha;double gamma1 = (Vector3.Dot(A0,dA) * h1 - A0.Z * dA.Z * h2) / alpha;double gamma2 = (Vector3.Dot(dA,dA) * h1 - dA.Z * dA.Z * h2) / alpha;horizon1U = new Vector3((float)-beta0, (float)-beta1, 0);horizon2U = new Vector3((float)beta0 * (float)beta0 - (float)gamma0, 2.0f * ((float)beta0 * (float)beta1 - (float)gamma1), (float)beta1 * (float)beta1 - (float)gamma2);}  timeU = (float)gametime.TotalGameTime.TotalMilliseconds *0.0001f; //gametime.ElapsedGameTime.Milliseconds * 1e-6f;heightOffsetU = -meanHeight;lodsU = new Vector4(resolution,pixelSize * resolution,(float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f),(nbWaves - 1.0f) / ((float)System.Math.Log(lambdaMax) / (float)System.Math.Log(2.0f) - (float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f)));  cameraToOceanU = Matrix.Transpose (ctoo);screenToCameraU = stoc;//Matrix.Transpose ( Matrix.Invert ( Parent.cam.view));//stoc;cameraToScreenU = ctos; // already transposed  oceanCameraPosU = new Vector3(-offset.X, -offset.Y, -offset.Z);oceanToWorldU = Matrix.Transpose ( Parent.cam.Projection * Parent.cam.View) * Matrix.Invert (ltoo); //Parent.cam.View * Matrix.Invert(ltoo);oceanToCameraU = Matrix.Transpose(Matrix.Invert(ctoo));//Global Variableswatereffect.Parameters["cameraToOcean"].SetValue(cameraToOceanU);watereffect.Parameters["screenToCamera"].SetValue(screenToCameraU); // World Projection Matrix Inversewatereffect.Parameters["cameraToScreen"].SetValue (cameraToScreenU); // World Projection Matrixwatereffect.Parameters["oceanToCamera"].SetValue(oceanToCameraU);watereffect.Parameters["oceanToWorld"].SetValue(oceanToWorldU);//float height = Vector3.Distance (Parent.cam.Position ,Vector3.Zero) - meanHeight;watereffect.Parameters["oceanCameraPos"].SetValue(oceanCameraPosU);watereffect.Parameters["oceanSunDir"].SetValue(oceanSunDir);watereffect.Parameters["horizon1"].SetValue(horizon1U);watereffect.Parameters["horizon2"].SetValue(horizon2U);watereffect.Parameters["worldCameraPos"].SetValue(Parent.cam.Position);watereffect.Parameters["worldSunDir"].SetValue(worldsunDir);watereffect.Parameters["seaColor"].SetValue(seaColor);watereffect.Parameters["seaRoughness"].SetValue(sigmaXsq);watereffect.Parameters["radius"].SetValue(radius);watereffect.Parameters["nbWaves"].SetValue(nbWaves); // number of waveswatereffect.Parameters["heightOffset"].SetValue(heightOffsetU); ; // so that surface height is centered around z = 0watereffect.Parameters["time"].SetValue (timeU); // current time// grid cell size in pixels, angle under which a grid cell is seen,// and parameters of the geometric series used for wavelengthswatereffect.Parameters["lods"].SetValue(lodsU); //if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {if (screengrid == null || screenWidth != device.Viewport.Width || screenHeight != device.Viewport.Height ){screenWidth = device.Viewport.Width;screenHeight = device.Viewport.Height;//screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);//screenGrid->addAttributeType(0, 2, A32F, false);screengrid = new ScreenGrid (); float f = 1.25f;int NX = (int)(f * screenWidth / resolution);int NY = (int)(f * screenHeight / resolution);for (int i = 0; i < NY; ++i){for (int j = 0; j < NX; ++j){screengrid.AddVertex (new Vector2(2.0f*f*j/(NX-1.0f)-f, 2.0f*f*i/(NY-1.0f)-f));}} for (int i = 0; i < NY-1; ++i) {for (int j = 0; j < NX-1; ++j) {screengrid.AddIndices(i * NX + j);screengrid.AddIndices(i * NX + j + 1);screengrid.AddIndices((i + 1) * NX + j);screengrid.AddIndices((i + 1) * NX + j);screengrid.AddIndices(i * NX + j + 1);screengrid.AddIndices((i + 1) * NX + j + 1);}} screengrid.UpdateBuffers(device);} }

and now for the shader code

original code


/*

* Proland: a procedural landscape rendering library.

* Copyright © 2008-2011 INRIA

*

* This program is free software: you can redistribute it and/or modify

* it under the terms of the GNU General Public License as published by

* the Free Software Foundation, either version 3 of the License, or

* (at your option) any later version.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program. If not, see <http://www.gnu.org/licenses/

*/

/*

* Proland is distributed under a dual-license scheme.

* You can obtain a specific license from Inria: proland-licensing@inria.fr.

*/

/*

* Authors: Eric Bruneton, Antoine Begault, Guillaume Piolat.

*/

#include "globalsShader.glhl"

#include "textureTile.glsl"

const float Z0 = 1.0;

uniform float radius;

uniform mat4 cameraToOcean;

uniform mat4 screenToCamera;

uniform mat4 cameraToScreen;

uniform mat3 oceanToCamera;

uniform mat4 oceanToWorld;

uniform vec3 oceanCameraPos;

uniform vec3 oceanSunDir;

uniform vec3 horizon1;

uniform vec3 horizon2;

uniform float nbWaves; // number of waves

uniform sampler1D wavesSampler; // waves parameters (h, omega, kx, ky) in wind space

uniform float heightOffset; // so that surface height is centered around z = 0

uniform float time; // current time

// grid cell size in pixels, angle under which a grid cell is seen,

// and parameters of the geometric series used for wavelengths

uniform vec4 lods;

#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated

#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all

const float g = 9.81;

const float PI = 3.141592657;

#ifdef _VERTEX_

layout(location=0) in vec3 vertex;

out float oceanLod;

out vec2 oceanUv; // coordinates in wind space used to compute P(u)

out vec3 oceanP; // wave point P(u) in ocean space

out vec3 oceanDPdu; // dPdu in wind space, used to compute N

out vec3 oceanDPdv; // dPdv in wind space, used to compute N

out float oceanRoughness; // variance of unresolved waves in wind space

vec2 oceanPos(vec3 vertex, out float t, out vec3 cameraDir, out vec3 oceanDir) {

float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);

cameraDir = normalize((screenToCamera * vec4(vertex.x, min(vertex.y, horizon), 0.0, 1.0)).xyz);

oceanDir = (cameraToOcean * vec4(cameraDir, 0.0)).xyz;

float cz = oceanCameraPos.z;

float dz = oceanDir.z;

if (radius == 0.0) {

t = (heightOffset + Z0 - cz) / dz;

} else {

float b = dz * (cz + radius);

float c = cz * (cz + 2.0 * radius);

float tSphere = - b - sqrt(max(b * b - c, 0.0));

float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));

t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;

}

return oceanCameraPos.xy + t * oceanDir.xy;

}

vec2 oceanPos(vec3 vertex) {

float t;

vec3 cameraDir;

vec3 oceanDir;

return oceanPos(vertex, t, cameraDir, oceanDir);

}

void main() {

float t;

vec3 cameraDir;

vec3 oceanDir;

vec2 uv = oceanPos(vertex, t, cameraDir, oceanDir);

float lod = - t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

vec2 duv = oceanPos(vertex + vec3(0.0, 0.01, 0.0)) - uv;

vec3 dP = vec3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0));

vec3 dPdu = vec3(1.0, 0.0, 0.0);

vec3 dPdv = vec3(0.0, 1.0, 0.0);

float roughness = getSeaRoughness();

if (duv.x != 0.0 || duv.y != 0.0) {

float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);

for (float i = iMin; i < nbWaves; ++i) {

vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

vec3 factor = wm * wt.x * vec3(wt.zw * overk, 1.0);

dP += factor * vec3(s, s, c);

vec3 dPd = factor * vec3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = wt.x / overk;

roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));

}

}

vec3 p = t * oceanDir + dP + vec3(0.0, 0.0, oceanCameraPos.z);

if (radius > 0.0) {

dPdu += vec3(0.0, 0.0, -p.x / (radius + p.z));

dPdv += vec3(0.0, 0.0, -p.y / (radius + p.z));

}

gl_Position = cameraToScreen * vec4(t * cameraDir + oceanToCamera * dP, 1.0);

oceanLod = lod;

oceanUv = uv;

oceanP = p;

oceanDPdu = dPdu;

oceanDPdv = dPdv;

oceanRoughness = roughness;

}

#endif

#ifdef _FRAGMENT_

#include "atmosphereShader.glhl"

#include "oceanBrdf.glhl"

#include "clouds.glhl"

in float oceanLod;

in vec2 oceanUv;

in vec3 oceanP;

in vec3 oceanDPdu;

in vec3 oceanDPdv;

in float oceanRoughness;

layout(location=0) out vec4 data;

void main() {

vec3 WSD = getWorldSunDir();

vec3 WCP = getWorldCameraPos();

float lod = oceanLod;

vec2 uv = oceanUv;

vec3 dPdu = oceanDPdu;

vec3 dPdv = oceanDPdv;

float roughness = oceanRoughness;

float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);

float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);

float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));

for (float i = iMin; i <= iMAX; i += 1.0) {

vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);

vec3 factor = (1.0 - wm) * wn * wt.x * vec3(wt.zw * overk, 1.0);

vec3 dPd = factor * vec3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = i < iMax ? wt.x / overk : 0.0;

float wkh = (1.0 - wn) * kh;

roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));

}

roughness = max(roughness, 1e-5);

vec3 earthCamera = vec3(0.0, 0.0, oceanCameraPos.z + radius);

vec3 earthP = radius > 0.0 ? normalize(oceanP + vec3(0.0, 0.0, radius)) * (radius + 10.0) : oceanP;

vec3 oceanCamera = vec3(0.0, 0.0, oceanCameraPos.z);

vec3 V = normalize(oceanCamera - oceanP);

vec3 N = normalize(cross(dPdu, dPdv));

if (dot(V, N) < 0.0) {

N = reflect(N, V); // reflects backfacing normals

}

vec3 sunL;

vec3 skyE;

vec3 extinction;

sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);

vec3 worldP = (oceanToWorld * vec4(oceanP, 1.0)).xyz;

sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);

vec3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);

// aerial perspective

vec3 inscatter = inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);

vec3 finalColor = surfaceColor * extinction + inscatter;

data.rgb = hdr(finalColor);

data.a = 1.0;

}

#endif



and now for my code


//Global Variables

float4x4 cameraToOcean;

float4x4 screenToCamera; // World Projection Matrix Inverse

float4x4 cameraToScreen; // World Projection Matrix

float3x3 oceanToCamera;

float4x4 oceanToWorld;

float3 oceanCameraPos;

float3 oceanSunDir;

float3 horizon1;

float3 horizon2;

float3 worldCameraPos;

float3 worldSunDir;

float3 seaColor;

float hdrExposure = 0.3f;

float seaRoughness;

float radius;

float nbWaves; // number of waves

float heightOffset; // so that surface height is centered around z = 0

float time; // current time

// grid cell size in pixels, angle under which a grid cell is seen,

// and parameters of the geometric series used for wavelengths

float4 lods;

 

//Constants

#define PI 3.141592657

const float Z0 = 1.0;

const float g = 9.81;

#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated

#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all

//Textures

texture wavesTexture; // waves parameters (h, omega, kx, ky) in wind space texture2d

sampler wavesSampler = sampler_state

{

texture = <wavesTexture>;

magfilter = POINT;

minfilter = POINT;

mipfilter = POINT;

AddressU = CLAMP;

AddressV = CLAMP;

};

 

struct VertexShaderInput

{

float4 Position : POSITION0;

};

struct VertexShaderOutput

{

float4 Position : POSITION0;

float oceanLod : TEXCOORD0;

float2 oceanUv : TEXCOORD1; // coordinates in wind space used to compute P(u)

float3 oceanP: TEXCOORD2; // wave point P(u) in ocean space

float3 oceanDPdu: TEXCOORD3; // dPdu in wind space, used to compute N

float3 oceanDPdv: TEXCOORD4; // dPdv in wind space, used to compute N

float oceanRoughness: TEXCOORD5; // variance of unresolved waves in wind space

};

//--------------------------------------------------------------

//Utilitie Function Section

//--------------------------------------------------------------

float3 hdr(float3 L) {

#ifndef NOHDR

L = L * hdrExposure;

L.r = L.r < 1.413 ? pow(L.r * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.r);

L.g = L.g < 1.413 ? pow(L.g * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.g);

L.b = L.b < 1.413 ? pow(L.b * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.b);

#endif

return L;

}

//---------------------------------------------

// Fresnel Functions

//---------------------------------------------

float meanFresnel(float cosThetaV, float sigmaV) {

return pow(1.0 - cosThetaV, 5.0 * exp(-2.69 * sigmaV)) / (1.0 + 22.7 * pow(sigmaV, 1.5));

}

float meanFresnel(float3 V, float3 N, float sigmaSq) {

return meanFresnel(dot(V, N), sqrt(sigmaSq));

}

//-----------------------------------------------

//Radiance Functions

//-----------------------------------------------

float reflectedSunRadiance(float3 V, float3 N, float3 L, float sigmaSq) {

float3 H = normalize(L + V);

float hn = dot(H, N);

float p = exp(-2.0 * ((1.0 - hn * hn) / sigmaSq) / (1.0 + hn)) / (4.0 * PI * sigmaSq);

float c = 1.0 - dot(V, H);

float c2 = c * c;

float fresnel = 0.02 + 0.98 * c2 * c2 * c;

float zL = dot(L, N);

float zV = dot(V, N);

zL = max(zL, 0.01);

zV = max(zV, 0.01);

// brdf times cos(thetaL)

return zL <= 0.0 ? 0.0 : max(fresnel * p * sqrt(abs(zL / zV)), 0.0);

}

float3 oceanRadiance(float3 V, float3 N, float3 L, float seaRoughness, float3 sunL, float3 skyE) {

float F = meanFresnel(V, N, seaRoughness);

float3 Lsun = reflectedSunRadiance(V, N, L, seaRoughness) * sunL;

float3 Lsky = skyE * F / PI;

float3 Lsea = (1.0 - F) * seaColor * skyE / PI;

return Lsun + Lsky + Lsea;

}

//--------------------------------------------------------------

//Ocean Position Functions

//--------------------------------------------------------------

float2 oceanPos(float3 vertex, out float t, out float3 cameraDir, out float3 oceanDir)

{

float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);

cameraDir = normalize((mul(screenToCamera , float4(vertex.x, min(vertex.y, horizon), 0.0, 1.0))).xyz);

oceanDir = (mul(cameraToOcean , float4(cameraDir, 0.0))).xyz;

float cz = oceanCameraPos.z;

float dz = oceanDir.z;

if (radius == 0.0) {

t = (heightOffset + Z0 - cz) / dz;

} else {

float b = dz * (cz + radius);

float c = cz * (cz + 2.0 * radius);

float tSphere = - b - sqrt(max(b * b - c, 0.0));

float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));

t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;

}

return oceanCameraPos.xy + t * oceanDir.xy;

}

 

float2 oceanPos(float3 vertex) {

float t;

float3 cameraDir;

float3 oceanDir;

return oceanPos(vertex, t, cameraDir, oceanDir);

}

 

 

//--------------------------------------------------------------

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)

{

VertexShaderOutput output = (VertexShaderOutput)0;

float t;

float3 cameraDir;

float3 oceanDir;

float2 uv = oceanPos(input.Position.xyz, t, cameraDir, oceanDir);

float lod = -t / oceanDir.y * lods.y; //-t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

float2 duv = oceanPos(input.Position.xyz + float3(0.0, 0.01, 0.0)) - uv; // maybe y not z


//float4 tempPos = float4(worldPos.x, 0, worldPos.y, 1.0f);

//worldPos /= 2000.0f;

//worldPos += 0.5f / 512.0f;

float3 dP = float3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0)); // maybe y not z

float3 dPdu = float3(1.0, 0.0, 0.0); // maybe y not z

float3 dPdv = float3(0.0, 1.0, 0.0); // maybe y not z

 

float roughness = seaRoughness;

if (duv.x != 0.0 || duv.y != 0.0) {

float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);

for (float i = iMin; i < nbWaves; ++i)

{

float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float3 factor = wm * wt.x * float3(wt.zw * overk, 1.0);

dP += factor * float3(s, s, c);

float3 dPd = factor * float3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = wt.x / overk;

roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));

}

}

 

 

 

float3 p = t * oceanDir + dP + float3(0.0, 0.0, oceanCameraPos.z); // maybe y not z

if (radius > 0.0) {

dPdu += float3(0.0, 0.0, -p.x / (radius + p.z));

dPdv += float3(0.0, 0.0, -p.y / (radius + p.z));

}


output.Position = mul(cameraToScreen, float4(t * cameraDir + mul(dP,oceanToCamera), 1.0));

//output.Position = mul(cameraToScreen,float4(input.Position.xyz,1));

//logrithmic zbuffer.

const float Cc = 1.0;

const float Far = 1000000000000.0;

output.Position.z = log(Cc*output.Position.z + 1) / log(Cc*Far + 1) * output.Position.w;

output.oceanLod = lod;

output.oceanUv = uv;

output.oceanP = p;

output.oceanDPdu = dPdu;

output.oceanDPdv = dPdv;

output.oceanRoughness = roughness;

return output;

}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0

{

float3 WSD = worldSunDir;

float3 WCP = worldCameraPos;

float lod = input.oceanLod;

float2 uv = input.oceanUv;

float3 dPdu = input.oceanDPdu;

float3 dPdv = input.oceanDPdv;

float roughness = input.oceanRoughness;

float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);

float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);

float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));

for (float i = iMin; i <= iMAX; i += 1.0) {

float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);

float3 factor = (1.0 - wm) * wn * wt.x * float3(wt.zw * overk, 1.0);

float3 dPd = factor * float3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = i < iMax ? wt.x / overk : 0.0;

float wkh = (1.0 - wn) * kh;

roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));

}

roughness = max(roughness, 1e-5);

float3 earthCamera = float3(0.0, 0.0, oceanCameraPos.z + radius);

float3 earthP = radius > 0.0 ? normalize(input.oceanP + float3(0.0, 0.0, radius)) * (radius + 10.0) : input.oceanP;

float3 oceanCamera = float3(0.0, 0.0, oceanCameraPos.z);

float3 V = normalize(oceanCamera - input.oceanP);

float3 N = normalize(cross(dPdu, dPdv));

if (dot(V, N) < 0.0) {

N = reflect(N, V); // reflects backfacing normals

}

float3 sunL = (float3)1;

float3 skyE = (float3)1;

float3 extinction = (float3)1;

//sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);

float3 worldP = (mul(oceanToWorld , float4(input.oceanP, 1.0))).xyz;

//sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);

float3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);

// aerial perspective

float3 inscatter = (float3)1; //= inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);

float3 finalColor = surfaceColor * extinction + inscatter;

float4 data;

data.rgb = hdr(finalColor);

data.a = 1.0;

return data;

//return float4(1, 0, 0, 1);

}

technique Technique1

{

pass Pass1

{

// TODO: set renderstates here.

VertexShader = compile vs_3_0 VertexShaderFunction();

PixelShader = compile ps_3_0 PixelShaderFunction();

}

}



and now a picture of the result im getting.


Bare in mind this is suppose to be a sphere, it looks like its half working must be something to do with the y/z axis. I know its not a good thing to just post code and ask for help but im going nuts trying to figure this out any help will be much appreciated.

Budinga

screenshot1120139215.jpg

and this is the flat version it seems to be working but the projection and the surface its projecting is been rendered very strange.

screenshot1120131046.jpg

#3Budinga

Posted 01 January 2013 - 04:06 AM

Hi Guyz. Well I have decided to use the great Eric Bruneton's water shaders in my procedural planet renderer, now I have managed to port the shaders, and also with a slightly modified ocean rendering class I get something on the screen, but due to the fact that he use's, a different coord system, well I think that's it I cant seem to get my brain round it. So I was wondering if anybody could spot my problem.

Original Render Function
bool DrawOceanTask::Impl::run(){if (Logger::DEBUG_LOGGER != NULL) {Logger::DEBUG_LOGGER->log("OCEAN", "DrawOcean");}ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer();ptr<Program> prog = SceneManager::getCurrentProgram();if (o->nbWavesU == NULL) {o->nbWavesU = prog->getUniform1f("nbWaves");o->wavesU = prog->getUniformSampler("wavesSampler");o->cameraToOceanU = prog->getUniformMatrix4f("cameraToOcean");o->screenToCameraU = prog->getUniformMatrix4f("screenToCamera");o->cameraToScreenU = prog->getUniformMatrix4f("cameraToScreen");o->oceanToCameraU = prog->getUniformMatrix3f("oceanToCamera");o->oceanToWorldU = prog->getUniformMatrix4f("oceanToWorld");o->oceanCameraPosU = prog->getUniform3f("oceanCameraPos");o->oceanSunDirU = prog->getUniform3f("oceanSunDir");o->horizon1U = prog->getUniform3f("horizon1");o->horizon2U = prog->getUniform3f("horizon2");o->timeU = prog->getUniform1f("time");o->radiusU = prog->getUniform1f("radius");o->heightOffsetU = prog->getUniform1f("heightOffset");o->lodsU = prog->getUniform4f("lods");assert(o->nbWavesU != NULL);o->generateWaves();}vector< ptr<TileSampler> > uniforms;SceneNode::FieldIterator ui = n->getFields();while (ui.hasNext()) {ptr<TileSampler> u = ui.next().cast<TileSampler>();if (u != NULL && u->getTerrain(0) != NULL) {u->setTileMap();}}// compute ltoo = localToOcean transform, where ocean frame = tangent space at// camera projection on sphere o->radius in local spacemat4d ctol = n->getLocalToCamera().inverse();vec3d cl = ctol * vec3d::ZERO; // camera in local spaceif ((o->radius == 0.0 && cl.z > o->zmin) ||(o->radius > 0.0 && cl.length() > o->radius + o->zmin) ||(o->radius < 0.0 && vec2d(cl.y, cl.z).length() < -o->radius - o->zmin)){o->oldLtoo = mat4d::IDENTITY;o->offset = vec3d::ZERO;return true;}vec3d ux, uy, uz, oo;if (o->radius == 0.0) {// flat oceanux = vec3d::UNIT_X;uy = vec3d::UNIT_Y;uz = vec3d::UNIT_Z;oo = vec3d(cl.x, cl.y, 0.0);} else if (o->radius > 0.0) {// spherical oceanuz = cl.normalize(); // unit z vector of ocean frame, in local spaceif (o->oldLtoo != mat4d::IDENTITY) {ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();} else {ux = vec3d::UNIT_Z.crossProduct(uz).normalize();}uy = uz.crossProduct(ux); // unit y vectoroo = uz * o->radius; // origin of ocean frame, in local space} else {// cylindrical oceanuz = vec3d(0.0, -cl.y, -cl.z).normalize();ux = vec3d::UNIT_X;uy = uz.crossProduct(ux);oo = vec3d(cl.x, 0.0, 0.0) + uz * o->radius;}mat4d ltoo = mat4d(ux.x, ux.y, ux.z, -ux.dotproduct(oo),uy.x, uy.y, uy.z, -uy.dotproduct(oo),uz.x, uz.y, uz.z, -uz.dotproduct(oo),0.0, 0.0, 0.0, 1.0);// compute ctoo = cameraToOcean transformmat4d ctoo = ltoo * ctol;if (o->oldLtoo != mat4d::IDENTITY) {vec3d delta = ltoo * (o->oldLtoo.inverse() * vec3d::ZERO);o->offset += delta;}o->oldLtoo = ltoo;mat4d ctos = n->getOwner()->getCameraToScreen();mat4d stoc = ctos.inverse();vec3d oc = ctoo * vec3d::ZERO;if (o->oceanSunDirU != NULL) {// TODO how to get sun dir in a better way?SceneManager::NodeIterator i = n->getOwner()->getNodes("light");if (i.hasNext()) {ptr<SceneNode> l = i.next();vec3d worldSunDir = l->getLocalToParent() * vec3d::ZERO;vec3d oceanSunDir = ltoo.mat3x3() * (n->getWorldToLocal().mat3x3() * worldSunDir);o->oceanSunDirU->set(oceanSunDir.cast<float>());}}vec4<GLint> screen = fb->getViewport();vec4d frustum[6];SceneManager::getFrustumPlanes(ctos, frustum);vec3d left = frustum[0].xyz().normalize();vec3d right = frustum[1].xyz().normalize();float fov = (float) safe_acos(-left.dotproduct(right));float pixelSize = atan(tan(fov / 2.0f) / (screen.w / 2.0f)); // angle under which a screen pixel is viewed from the camerao->cameraToOceanU->setMatrix(ctoo.cast<float>());o->screenToCameraU->setMatrix(stoc.cast<float>());o->cameraToScreenU->setMatrix(ctos.cast<float>());o->oceanToCameraU->setMatrix(ctoo.inverse().mat3x3().cast<float>());o->oceanCameraPosU->set(vec3f(float(-o->offset.x), float(-o->offset.y), float(oc.z)));if (o->oceanToWorldU != NULL) {o->oceanToWorldU->setMatrix((n->getLocalToWorld() * ltoo.inverse()).cast<float>());}if (o->horizon1U != NULL) {float h = oc.z;vec3d A0 = (ctoo * vec4d((stoc * vec4d(0.0, 0.0, 0.0, 1.0)).xyz(), 0.0)).xyz();vec3d dA = (ctoo * vec4d((stoc * vec4d(1.0, 0.0, 0.0, 0.0)).xyz(), 0.0)).xyz();vec3d B = (ctoo * vec4d((stoc * vec4d(0.0, 1.0, 0.0, 0.0)).xyz(), 0.0)).xyz();if (o->radius == 0.0) {o->horizon1U->set(vec3f(-(h * 1e-6 + A0.z) / B.z, -dA.z / B.z, 0.0));o->horizon2U->set(vec3f::ZERO);} else {double h1 = h * (h + 2.0 * o->radius);double h2 = (h + o->radius) * (h + o->radius);double alpha = B.dotproduct(B) * h1 - B.z * B.z * h2;double beta0 = (A0.dotproduct(B) * h1 - B.z * A0.z * h2) / alpha;double beta1 = (dA.dotproduct(B) * h1 - B.z * dA.z * h2) / alpha;double gamma0 = (A0.dotproduct(A0) * h1 - A0.z * A0.z * h2) / alpha;double gamma1 = (A0.dotproduct(dA) * h1 - A0.z * dA.z * h2) / alpha;double gamma2 = (dA.dotproduct(dA) * h1 - dA.z * dA.z * h2) / alpha;o->horizon1U->set(vec3f(-beta0, -beta1, 0.0));o->horizon2U->set(vec3f(beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2));}}o->timeU->set(n->getOwner()->getTime() * 1e-6);if (o->radiusU != NULL) {o->radiusU->set(o->radius < 0.0 ? -o->radius : o->radius);}o->heightOffsetU->set(-o->meanHeight);o->lodsU->set(vec4f(o->resolution,pixelSize * o->resolution,log(o->lambdaMin) / log(2.0f),(o->nbWavesU->get() - 1.0f) / (log(o->lambdaMax) / log(2.0f) - log(o->lambdaMin) / log(2.0f))));if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {o->screenWidth = screen.z;o->screenHeight = screen.w;o->screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);o->screenGrid->addAttributeType(0, 2, A32F, false);float f = 1.25f;int NX = int(f * screen.z / o->resolution);int NY = int(f * screen.w / o->resolution);for (int i = 0; i < NY; ++i) {for (int j = 0; j < NX; ++j) {o->screenGrid->addVertex(vec2f(2.0*f*j/(NX-1.0f)-f, 2.0*f*i/(NY-1.0f)-f));}}for (int i = 0; i < NY-1; ++i) {for (int j = 0; j < NX-1; ++j) {o->screenGrid->addIndice(i*NX+j);o->screenGrid->addIndice(i*NX+j+1);o->screenGrid->addIndice((i+1)*NX+j);o->screenGrid->addIndice((i+1)*NX+j);o->screenGrid->addIndice(i*NX+j+1);o->screenGrid->addIndice((i+1)*NX+j+1);}}}fb->draw(prog, *(o->screenGrid));return true;}

Now my update function (basically tries to do the same thing.

public void Update(GameTime gametime){  // compute ltoo = localToOcean transform, where ocean frame = tangent space at// camera projection on sphere o->radius in local spaceVector3 cl = Vector3.Transform(Vector3.Zero, ctol);//camera in local spaceIf ((radius == 0.0 && cl.Z > zmin) ||(radius > 0.0 && cl.Length() > radius + zmin) ||(radius < 0.0 && new Vector2(cl.Y, cl.Z).Length() < -radius - zmin)){oldLtoo = Matrix.Identity;offset = Vector3.Zero;return;}Vector3 ux, uy, uz, oo;if (radius == 0.0){// flat oceanux = Vector3.UnitX;uy = Vector3.UnitY;uz = Vector3.UnitZ;oo = new Vector3(cl.X, cl.Y, 0.0f);}else if (radius > 0.0){// spherical oceanuz = Vector3.Normalize(cl);// unit z vector of ocean frame, in local spaceif (oldLtoo != Matrix.Identity){//Matrix m = Matrix.Transpose(oldLtoo);//ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();ux = Vector3.Normalize(Vector3.Cross(new Vector3(oldLtoo.M21, oldLtoo.M22, oldLtoo.M23), uz));}else{ux = Vector3.Normalize(Vector3.Cross(Vector3.UnitZ, uz));}uy = Vector3.Cross(uz, ux);// unit y vector // negate this ??//uz * radius; // origin of ocean frame, in local spaceoo = ux * radius; }else{// cylindrical oceanuz = Vector3.Normalize(new Vector3(0, -cl.Y, -cl.Z));ux = Vector3.UnitX;uy = Vector3.Cross(uz, ux);oo = new Vector3(cl.X, 0, 0) + uz * radius;}  Matrix ltoo = new Matrix(ux.X, uy.X, uz.X, 0.0f,ux.Y, uy.Y, uz.Y, 0.0f,ux.Z, uy.Z, uz.Z, 0.0f,-Vector3.Dot(ux, oo), -Vector3.Dot(uy, oo), -Vector3.Dot(uz, oo), 1.0f);   ltoo = Matrix.Transpose(ltoo); // compute ctoo = cameraToOcean transformMatrix ctoo = ltoo * Matrix.Transpose (ctol);    if (oldLtoo != Matrix.Identity){Vector3 delta = Vector3.Transform(Vector3.Zero, Matrix.Transpose ( ltoo * Matrix.Invert(oldLtoo)));offset += delta;}oldLtoo = ltoo; //added transposeMatrix ctos = Matrix.Transpose (Parent.cam.Projection); //world*view*projection //n->getOwner()->getCameraToScreen();Matrix stoc = Matrix.Invert (ctos);Vector3 oc = Vector3.Transform(Vector3.Zero, ctoo);//o->oceanSunDirU->set(oceanSunDir.cast<float>());Vector3 worldsunDir = Parent.vLightDirection;Vector3 oceanSunDir = Vector3.Transform(worldsunDir, ltoo * Parent.cam.View); BoundingFrustum frustum = new BoundingFrustum(ctos);Vector3 left = frustum.Left.Normal;Vector3 right = frustum.Right.Normal;float fov = (float)System.Math.Acos(Vector3.Dot(-left, right)); float pixelSize = (float)System.Math.Atan(System.Math.Tan(fov / 2.0f) / (device.Viewport.Height / 2.0f));// angle under which a screen pixel is viewed from the camera float h = oc.Z; Vector4 tmp1,tmp2;tmp1 = Vector4.Transform ( new Vector4 (0,0,0,1),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 A0 = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z); tmp1 = Vector4.Transform ( new Vector4 (1,0,0,0),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 dA = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);tmp1 = Vector4.Transform ( new Vector4 (0,1,0,0),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 B = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);if (radius == 0.0){horizon1U = new Vector3(-(h * 1e-6f + A0.Z) / B.Z, -dA.Z / B.Z, 0);horizon2U = Vector3.Zero;}else{double h1 = h * (h + 2.0 * radius);double h2 = (h + radius) * (h + radius);double alpha = Vector3.Dot (B,B) * h1 - B.Z * B.Z * h2;double beta0 = (Vector3.Dot (A0,B) * h1 - B.Z * A0.Z * h2) / alpha;double beta1 = (Vector3.Dot (dA,B) * h1 - B.Z * dA.Z * h2) / alpha;double gamma0 = (Vector3.Dot (A0,A0) * h1 - A0.Z * A0.Z * h2) / alpha;double gamma1 = (Vector3.Dot(A0,dA) * h1 - A0.Z * dA.Z * h2) / alpha;double gamma2 = (Vector3.Dot(dA,dA) * h1 - dA.Z * dA.Z * h2) / alpha;horizon1U = new Vector3((float)-beta0, (float)-beta1, 0);horizon2U = new Vector3((float)beta0 * (float)beta0 - (float)gamma0, 2.0f * ((float)beta0 * (float)beta1 - (float)gamma1), (float)beta1 * (float)beta1 - (float)gamma2);}  timeU = (float)gametime.TotalGameTime.TotalMilliseconds *0.0001f; //gametime.ElapsedGameTime.Milliseconds * 1e-6f;heightOffsetU = -meanHeight;lodsU = new Vector4(resolution,pixelSize * resolution,(float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f),(nbWaves - 1.0f) / ((float)System.Math.Log(lambdaMax) / (float)System.Math.Log(2.0f) - (float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f)));  cameraToOceanU = Matrix.Transpose (ctoo);screenToCameraU = stoc;//Matrix.Transpose ( Matrix.Invert ( Parent.cam.view));//stoc;cameraToScreenU = ctos; // already transposed  oceanCameraPosU = new Vector3(-offset.X, -offset.Y, -offset.Z);oceanToWorldU = Matrix.Transpose ( Parent.cam.Projection * Parent.cam.View) * Matrix.Invert (ltoo); //Parent.cam.View * Matrix.Invert(ltoo);oceanToCameraU = Matrix.Transpose(Matrix.Invert(ctoo));//Global Variableswatereffect.Parameters["cameraToOcean"].SetValue(cameraToOceanU);watereffect.Parameters["screenToCamera"].SetValue(screenToCameraU); // World Projection Matrix Inversewatereffect.Parameters["cameraToScreen"].SetValue (cameraToScreenU); // World Projection Matrixwatereffect.Parameters["oceanToCamera"].SetValue(oceanToCameraU);watereffect.Parameters["oceanToWorld"].SetValue(oceanToWorldU);//float height = Vector3.Distance (Parent.cam.Position ,Vector3.Zero) - meanHeight;watereffect.Parameters["oceanCameraPos"].SetValue(oceanCameraPosU);watereffect.Parameters["oceanSunDir"].SetValue(oceanSunDir);watereffect.Parameters["horizon1"].SetValue(horizon1U);watereffect.Parameters["horizon2"].SetValue(horizon2U);watereffect.Parameters["worldCameraPos"].SetValue(Parent.cam.Position);watereffect.Parameters["worldSunDir"].SetValue(worldsunDir);watereffect.Parameters["seaColor"].SetValue(seaColor);watereffect.Parameters["seaRoughness"].SetValue(sigmaXsq);watereffect.Parameters["radius"].SetValue(radius);watereffect.Parameters["nbWaves"].SetValue(nbWaves); // number of waveswatereffect.Parameters["heightOffset"].SetValue(heightOffsetU); ; // so that surface height is centered around z = 0watereffect.Parameters["time"].SetValue (timeU); // current time// grid cell size in pixels, angle under which a grid cell is seen,// and parameters of the geometric series used for wavelengthswatereffect.Parameters["lods"].SetValue(lodsU); //if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {if (screengrid == null || screenWidth != device.Viewport.Width || screenHeight != device.Viewport.Height ){screenWidth = device.Viewport.Width;screenHeight = device.Viewport.Height;//screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);//screenGrid->addAttributeType(0, 2, A32F, false);screengrid = new ScreenGrid (); float f = 1.25f;int NX = (int)(f * screenWidth / resolution);int NY = (int)(f * screenHeight / resolution);for (int i = 0; i < NY; ++i){for (int j = 0; j < NX; ++j){screengrid.AddVertex (new Vector2(2.0f*f*j/(NX-1.0f)-f, 2.0f*f*i/(NY-1.0f)-f));}} for (int i = 0; i < NY-1; ++i) {for (int j = 0; j < NX-1; ++j) {screengrid.AddIndices(i * NX + j);screengrid.AddIndices(i * NX + j + 1);screengrid.AddIndices((i + 1) * NX + j);screengrid.AddIndices((i + 1) * NX + j);screengrid.AddIndices(i * NX + j + 1);screengrid.AddIndices((i + 1) * NX + j + 1);}} screengrid.UpdateBuffers(device);} }
and now for the shader code

original code


/*

* Proland: a procedural landscape rendering library.

* Copyright © 2008-2011 INRIA

*

* This program is free software: you can redistribute it and/or modify

* it under the terms of the GNU General Public License as published by

* the Free Software Foundation, either version 3 of the License, or

* (at your option) any later version.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program. If not, see <http://www.gnu.org/licenses/

*/

/*

* Proland is distributed under a dual-license scheme.

* You can obtain a specific license from Inria: proland-licensing@inria.fr.

*/

/*

* Authors: Eric Bruneton, Antoine Begault, Guillaume Piolat.

*/

#include "globalsShader.glhl"

#include "textureTile.glsl"

const float Z0 = 1.0;

uniform float radius;

uniform mat4 cameraToOcean;

uniform mat4 screenToCamera;

uniform mat4 cameraToScreen;

uniform mat3 oceanToCamera;

uniform mat4 oceanToWorld;

uniform vec3 oceanCameraPos;

uniform vec3 oceanSunDir;

uniform vec3 horizon1;

uniform vec3 horizon2;

uniform float nbWaves; // number of waves

uniform sampler1D wavesSampler; // waves parameters (h, omega, kx, ky) in wind space

uniform float heightOffset; // so that surface height is centered around z = 0

uniform float time; // current time

// grid cell size in pixels, angle under which a grid cell is seen,

// and parameters of the geometric series used for wavelengths

uniform vec4 lods;

#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated

#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all

const float g = 9.81;

const float PI = 3.141592657;

#ifdef _VERTEX_

layout(location=0) in vec3 vertex;

out float oceanLod;

out vec2 oceanUv; // coordinates in wind space used to compute P(u)

out vec3 oceanP; // wave point P(u) in ocean space

out vec3 oceanDPdu; // dPdu in wind space, used to compute N

out vec3 oceanDPdv; // dPdv in wind space, used to compute N

out float oceanRoughness; // variance of unresolved waves in wind space

vec2 oceanPos(vec3 vertex, out float t, out vec3 cameraDir, out vec3 oceanDir) {

float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);

cameraDir = normalize((screenToCamera * vec4(vertex.x, min(vertex.y, horizon), 0.0, 1.0)).xyz);

oceanDir = (cameraToOcean * vec4(cameraDir, 0.0)).xyz;

float cz = oceanCameraPos.z;

float dz = oceanDir.z;

if (radius == 0.0) {

t = (heightOffset + Z0 - cz) / dz;

} else {

float b = dz * (cz + radius);

float c = cz * (cz + 2.0 * radius);

float tSphere = - b - sqrt(max(b * b - c, 0.0));

float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));

t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;

}

return oceanCameraPos.xy + t * oceanDir.xy;

}

vec2 oceanPos(vec3 vertex) {

float t;

vec3 cameraDir;

vec3 oceanDir;

return oceanPos(vertex, t, cameraDir, oceanDir);

}

void main() {

float t;

vec3 cameraDir;

vec3 oceanDir;

vec2 uv = oceanPos(vertex, t, cameraDir, oceanDir);

float lod = - t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

vec2 duv = oceanPos(vertex + vec3(0.0, 0.01, 0.0)) - uv;

vec3 dP = vec3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0));

vec3 dPdu = vec3(1.0, 0.0, 0.0);

vec3 dPdv = vec3(0.0, 1.0, 0.0);

float roughness = getSeaRoughness();

if (duv.x != 0.0 || duv.y != 0.0) {

float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);

for (float i = iMin; i < nbWaves; ++i) {

vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

vec3 factor = wm * wt.x * vec3(wt.zw * overk, 1.0);

dP += factor * vec3(s, s, c);

vec3 dPd = factor * vec3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = wt.x / overk;

roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));

}

}

vec3 p = t * oceanDir + dP + vec3(0.0, 0.0, oceanCameraPos.z);

if (radius > 0.0) {

dPdu += vec3(0.0, 0.0, -p.x / (radius + p.z));

dPdv += vec3(0.0, 0.0, -p.y / (radius + p.z));

}

gl_Position = cameraToScreen * vec4(t * cameraDir + oceanToCamera * dP, 1.0);

oceanLod = lod;

oceanUv = uv;

oceanP = p;

oceanDPdu = dPdu;

oceanDPdv = dPdv;

oceanRoughness = roughness;

}

#endif

#ifdef _FRAGMENT_

#include "atmosphereShader.glhl"

#include "oceanBrdf.glhl"

#include "clouds.glhl"

in float oceanLod;

in vec2 oceanUv;

in vec3 oceanP;

in vec3 oceanDPdu;

in vec3 oceanDPdv;

in float oceanRoughness;

layout(location=0) out vec4 data;

void main() {

vec3 WSD = getWorldSunDir();

vec3 WCP = getWorldCameraPos();

float lod = oceanLod;

vec2 uv = oceanUv;

vec3 dPdu = oceanDPdu;

vec3 dPdv = oceanDPdv;

float roughness = oceanRoughness;

float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);

float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);

float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));

for (float i = iMin; i <= iMAX; i += 1.0) {

vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);

vec3 factor = (1.0 - wm) * wn * wt.x * vec3(wt.zw * overk, 1.0);

vec3 dPd = factor * vec3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = i < iMax ? wt.x / overk : 0.0;

float wkh = (1.0 - wn) * kh;

roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));

}

roughness = max(roughness, 1e-5);

vec3 earthCamera = vec3(0.0, 0.0, oceanCameraPos.z + radius);

vec3 earthP = radius > 0.0 ? normalize(oceanP + vec3(0.0, 0.0, radius)) * (radius + 10.0) : oceanP;

vec3 oceanCamera = vec3(0.0, 0.0, oceanCameraPos.z);

vec3 V = normalize(oceanCamera - oceanP);

vec3 N = normalize(cross(dPdu, dPdv));

if (dot(V, N) < 0.0) {

N = reflect(N, V); // reflects backfacing normals

}

vec3 sunL;

vec3 skyE;

vec3 extinction;

sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);

vec3 worldP = (oceanToWorld * vec4(oceanP, 1.0)).xyz;

sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);

vec3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);

// aerial perspective

vec3 inscatter = inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);

vec3 finalColor = surfaceColor * extinction + inscatter;

data.rgb = hdr(finalColor);

data.a = 1.0;

}

#endif



and now for my code


//Global Variables

float4x4 cameraToOcean;

float4x4 screenToCamera; // World Projection Matrix Inverse

float4x4 cameraToScreen; // World Projection Matrix

float3x3 oceanToCamera;

float4x4 oceanToWorld;

float3 oceanCameraPos;

float3 oceanSunDir;

float3 horizon1;

float3 horizon2;

float3 worldCameraPos;

float3 worldSunDir;

float3 seaColor;

float hdrExposure = 0.3f;

float seaRoughness;

float radius;

float nbWaves; // number of waves

float heightOffset; // so that surface height is centered around z = 0

float time; // current time

// grid cell size in pixels, angle under which a grid cell is seen,

// and parameters of the geometric series used for wavelengths

float4 lods;

 

//Constants

#define PI 3.141592657

const float Z0 = 1.0;

const float g = 9.81;

#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated

#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all

//Textures

texture wavesTexture; // waves parameters (h, omega, kx, ky) in wind space texture2d

sampler wavesSampler = sampler_state

{

texture = <wavesTexture>;

magfilter = POINT;

minfilter = POINT;

mipfilter = POINT;

AddressU = CLAMP;

AddressV = CLAMP;

};

 

struct VertexShaderInput

{

float4 Position : POSITION0;

};

struct VertexShaderOutput

{

float4 Position : POSITION0;

float oceanLod : TEXCOORD0;

float2 oceanUv : TEXCOORD1; // coordinates in wind space used to compute P(u)

float3 oceanP: TEXCOORD2; // wave point P(u) in ocean space

float3 oceanDPdu: TEXCOORD3; // dPdu in wind space, used to compute N

float3 oceanDPdv: TEXCOORD4; // dPdv in wind space, used to compute N

float oceanRoughness: TEXCOORD5; // variance of unresolved waves in wind space

};

//--------------------------------------------------------------

//Utilitie Function Section

//--------------------------------------------------------------

float3 hdr(float3 L) {

#ifndef NOHDR

L = L * hdrExposure;

L.r = L.r < 1.413 ? pow(L.r * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.r);

L.g = L.g < 1.413 ? pow(L.g * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.g);

L.b = L.b < 1.413 ? pow(L.b * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.b);

#endif

return L;

}

//---------------------------------------------

// Fresnel Functions

//---------------------------------------------

float meanFresnel(float cosThetaV, float sigmaV) {

return pow(1.0 - cosThetaV, 5.0 * exp(-2.69 * sigmaV)) / (1.0 + 22.7 * pow(sigmaV, 1.5));

}

float meanFresnel(float3 V, float3 N, float sigmaSq) {

return meanFresnel(dot(V, N), sqrt(sigmaSq));

}

//-----------------------------------------------

//Radiance Functions

//-----------------------------------------------

float reflectedSunRadiance(float3 V, float3 N, float3 L, float sigmaSq) {

float3 H = normalize(L + V);

float hn = dot(H, N);

float p = exp(-2.0 * ((1.0 - hn * hn) / sigmaSq) / (1.0 + hn)) / (4.0 * PI * sigmaSq);

float c = 1.0 - dot(V, H);

float c2 = c * c;

float fresnel = 0.02 + 0.98 * c2 * c2 * c;

float zL = dot(L, N);

float zV = dot(V, N);

zL = max(zL, 0.01);

zV = max(zV, 0.01);

// brdf times cos(thetaL)

return zL <= 0.0 ? 0.0 : max(fresnel * p * sqrt(abs(zL / zV)), 0.0);

}

float3 oceanRadiance(float3 V, float3 N, float3 L, float seaRoughness, float3 sunL, float3 skyE) {

float F = meanFresnel(V, N, seaRoughness);

float3 Lsun = reflectedSunRadiance(V, N, L, seaRoughness) * sunL;

float3 Lsky = skyE * F / PI;

float3 Lsea = (1.0 - F) * seaColor * skyE / PI;

return Lsun + Lsky + Lsea;

}

//--------------------------------------------------------------

//Ocean Position Functions

//--------------------------------------------------------------

float2 oceanPos(float3 vertex, out float t, out float3 cameraDir, out float3 oceanDir)

{

float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);

cameraDir = normalize((mul(screenToCamera , float4(vertex.x, min(vertex.y, horizon), 0.0, 1.0))).xyz);

oceanDir = (mul(cameraToOcean , float4(cameraDir, 0.0))).xyz;

float cz = oceanCameraPos.z;

float dz = oceanDir.z;

if (radius == 0.0) {

t = (heightOffset + Z0 - cz) / dz;

} else {

float b = dz * (cz + radius);

float c = cz * (cz + 2.0 * radius);

float tSphere = - b - sqrt(max(b * b - c, 0.0));

float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));

t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;

}

return oceanCameraPos.xy + t * oceanDir.xy;

}

 

float2 oceanPos(float3 vertex) {

float t;

float3 cameraDir;

float3 oceanDir;

return oceanPos(vertex, t, cameraDir, oceanDir);

}

 

 

//--------------------------------------------------------------

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)

{

VertexShaderOutput output = (VertexShaderOutput)0;

float t;

float3 cameraDir;

float3 oceanDir;

float2 uv = oceanPos(input.Position.xyz, t, cameraDir, oceanDir);

float lod = -t / oceanDir.y * lods.y; //-t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

float2 duv = oceanPos(input.Position.xyz + float3(0.0, 0.01, 0.0)) - uv; // maybe y not z


//float4 tempPos = float4(worldPos.x, 0, worldPos.y, 1.0f);

//worldPos /= 2000.0f;

//worldPos += 0.5f / 512.0f;

float3 dP = float3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0)); // maybe y not z

float3 dPdu = float3(1.0, 0.0, 0.0); // maybe y not z

float3 dPdv = float3(0.0, 1.0, 0.0); // maybe y not z

 

float roughness = seaRoughness;

if (duv.x != 0.0 || duv.y != 0.0) {

float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);

for (float i = iMin; i < nbWaves; ++i)

{

float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float3 factor = wm * wt.x * float3(wt.zw * overk, 1.0);

dP += factor * float3(s, s, c);

float3 dPd = factor * float3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = wt.x / overk;

roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));

}

}

 

 

 

float3 p = t * oceanDir + dP + float3(0.0, 0.0, oceanCameraPos.z); // maybe y not z

if (radius > 0.0) {

dPdu += float3(0.0, 0.0, -p.x / (radius + p.z));

dPdv += float3(0.0, 0.0, -p.y / (radius + p.z));

}


output.Position = mul(cameraToScreen, float4(t * cameraDir + mul(dP,oceanToCamera), 1.0));

//output.Position = mul(cameraToScreen,float4(input.Position.xyz,1));

//logrithmic zbuffer.

const float Cc = 1.0;

const float Far = 1000000000000.0;

output.Position.z = log(Cc*output.Position.z + 1) / log(Cc*Far + 1) * output.Position.w;

output.oceanLod = lod;

output.oceanUv = uv;

output.oceanP = p;

output.oceanDPdu = dPdu;

output.oceanDPdv = dPdv;

output.oceanRoughness = roughness;

return output;

}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0

{

float3 WSD = worldSunDir;

float3 WCP = worldCameraPos;

float lod = input.oceanLod;

float2 uv = input.oceanUv;

float3 dPdu = input.oceanDPdu;

float3 dPdv = input.oceanDPdv;

float roughness = input.oceanRoughness;

float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);

float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);

float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));

for (float i = iMin; i <= iMAX; i += 1.0) {

float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);

float3 factor = (1.0 - wm) * wn * wt.x * float3(wt.zw * overk, 1.0);

float3 dPd = factor * float3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = i < iMax ? wt.x / overk : 0.0;

float wkh = (1.0 - wn) * kh;

roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));

}

roughness = max(roughness, 1e-5);

float3 earthCamera = float3(0.0, 0.0, oceanCameraPos.z + radius);

float3 earthP = radius > 0.0 ? normalize(input.oceanP + float3(0.0, 0.0, radius)) * (radius + 10.0) : input.oceanP;

float3 oceanCamera = float3(0.0, 0.0, oceanCameraPos.z);

float3 V = normalize(oceanCamera - input.oceanP);

float3 N = normalize(cross(dPdu, dPdv));

if (dot(V, N) < 0.0) {

N = reflect(N, V); // reflects backfacing normals

}

float3 sunL = (float3)1;

float3 skyE = (float3)1;

float3 extinction = (float3)1;

//sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);

float3 worldP = (mul(oceanToWorld , float4(input.oceanP, 1.0))).xyz;

//sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);

float3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);

// aerial perspective

float3 inscatter = (float3)1; //= inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);

float3 finalColor = surfaceColor * extinction + inscatter;

float4 data;

data.rgb = hdr(finalColor);

data.a = 1.0;

return data;

//return float4(1, 0, 0, 1);

}

technique Technique1

{

pass Pass1

{

// TODO: set renderstates here.

VertexShader = compile vs_3_0 VertexShaderFunction();

PixelShader = compile ps_3_0 PixelShaderFunction();

}

}



and now a picture of the result im getting.


Bare in mind this is suppose to be a sphere, it looks like its half working must be something to do with the y/z axis. I know its not a good thing to just post code and ask for help but im going nuts trying to figure this out any help will be much appreciated.

Budinga

screenshot1120139215.jpg

and this is the flat version it seems to be working but the projection and the surface its projecting is been rendered very strange.

screenshot1120131046.jpg

#2Budinga

Posted 01 January 2013 - 04:06 AM

Hi Guyz. Well I have decided to use the great Eric Bruneton's water shaders in my procedural planet renderer, now I have managed to port the shaders, and also with a slightly modified ocean rendering class I get something on the screen, but due to the fact that he use's, a different coord system, well I think that's it I cant seem to get my brain round it. So I was wondering if anybody could spot my problem.

Original Render Function
bool DrawOceanTask::Impl::run(){if (Logger::DEBUG_LOGGER != NULL) {Logger::DEBUG_LOGGER->log("OCEAN", "DrawOcean");}ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer();ptr<Program> prog = SceneManager::getCurrentProgram();if (o->nbWavesU == NULL) {o->nbWavesU = prog->getUniform1f("nbWaves");o->wavesU = prog->getUniformSampler("wavesSampler");o->cameraToOceanU = prog->getUniformMatrix4f("cameraToOcean");o->screenToCameraU = prog->getUniformMatrix4f("screenToCamera");o->cameraToScreenU = prog->getUniformMatrix4f("cameraToScreen");o->oceanToCameraU = prog->getUniformMatrix3f("oceanToCamera");o->oceanToWorldU = prog->getUniformMatrix4f("oceanToWorld");o->oceanCameraPosU = prog->getUniform3f("oceanCameraPos");o->oceanSunDirU = prog->getUniform3f("oceanSunDir");o->horizon1U = prog->getUniform3f("horizon1");o->horizon2U = prog->getUniform3f("horizon2");o->timeU = prog->getUniform1f("time");o->radiusU = prog->getUniform1f("radius");o->heightOffsetU = prog->getUniform1f("heightOffset");o->lodsU = prog->getUniform4f("lods");assert(o->nbWavesU != NULL);o->generateWaves();}vector< ptr<TileSampler> > uniforms;SceneNode::FieldIterator ui = n->getFields();while (ui.hasNext()) {ptr<TileSampler> u = ui.next().cast<TileSampler>();if (u != NULL && u->getTerrain(0) != NULL) {u->setTileMap();}}// compute ltoo = localToOcean transform, where ocean frame = tangent space at// camera projection on sphere o->radius in local spacemat4d ctol = n->getLocalToCamera().inverse();vec3d cl = ctol * vec3d::ZERO; // camera in local spaceif ((o->radius == 0.0 && cl.z > o->zmin) ||(o->radius > 0.0 && cl.length() > o->radius + o->zmin) ||(o->radius < 0.0 && vec2d(cl.y, cl.z).length() < -o->radius - o->zmin)){o->oldLtoo = mat4d::IDENTITY;o->offset = vec3d::ZERO;return true;}vec3d ux, uy, uz, oo;if (o->radius == 0.0) {// flat oceanux = vec3d::UNIT_X;uy = vec3d::UNIT_Y;uz = vec3d::UNIT_Z;oo = vec3d(cl.x, cl.y, 0.0);} else if (o->radius > 0.0) {// spherical oceanuz = cl.normalize(); // unit z vector of ocean frame, in local spaceif (o->oldLtoo != mat4d::IDENTITY) {ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();} else {ux = vec3d::UNIT_Z.crossProduct(uz).normalize();}uy = uz.crossProduct(ux); // unit y vectoroo = uz * o->radius; // origin of ocean frame, in local space} else {// cylindrical oceanuz = vec3d(0.0, -cl.y, -cl.z).normalize();ux = vec3d::UNIT_X;uy = uz.crossProduct(ux);oo = vec3d(cl.x, 0.0, 0.0) + uz * o->radius;}mat4d ltoo = mat4d(ux.x, ux.y, ux.z, -ux.dotproduct(oo),uy.x, uy.y, uy.z, -uy.dotproduct(oo),uz.x, uz.y, uz.z, -uz.dotproduct(oo),0.0, 0.0, 0.0, 1.0);// compute ctoo = cameraToOcean transformmat4d ctoo = ltoo * ctol;if (o->oldLtoo != mat4d::IDENTITY) {vec3d delta = ltoo * (o->oldLtoo.inverse() * vec3d::ZERO);o->offset += delta;}o->oldLtoo = ltoo;mat4d ctos = n->getOwner()->getCameraToScreen();mat4d stoc = ctos.inverse();vec3d oc = ctoo * vec3d::ZERO;if (o->oceanSunDirU != NULL) {// TODO how to get sun dir in a better way?SceneManager::NodeIterator i = n->getOwner()->getNodes("light");if (i.hasNext()) {ptr<SceneNode> l = i.next();vec3d worldSunDir = l->getLocalToParent() * vec3d::ZERO;vec3d oceanSunDir = ltoo.mat3x3() * (n->getWorldToLocal().mat3x3() * worldSunDir);o->oceanSunDirU->set(oceanSunDir.cast<float>());}}vec4<GLint> screen = fb->getViewport();vec4d frustum[6];SceneManager::getFrustumPlanes(ctos, frustum);vec3d left = frustum[0].xyz().normalize();vec3d right = frustum[1].xyz().normalize();float fov = (float) safe_acos(-left.dotproduct(right));float pixelSize = atan(tan(fov / 2.0f) / (screen.w / 2.0f)); // angle under which a screen pixel is viewed from the camerao->cameraToOceanU->setMatrix(ctoo.cast<float>());o->screenToCameraU->setMatrix(stoc.cast<float>());o->cameraToScreenU->setMatrix(ctos.cast<float>());o->oceanToCameraU->setMatrix(ctoo.inverse().mat3x3().cast<float>());o->oceanCameraPosU->set(vec3f(float(-o->offset.x), float(-o->offset.y), float(oc.z)));if (o->oceanToWorldU != NULL) {o->oceanToWorldU->setMatrix((n->getLocalToWorld() * ltoo.inverse()).cast<float>());}if (o->horizon1U != NULL) {float h = oc.z;vec3d A0 = (ctoo * vec4d((stoc * vec4d(0.0, 0.0, 0.0, 1.0)).xyz(), 0.0)).xyz();vec3d dA = (ctoo * vec4d((stoc * vec4d(1.0, 0.0, 0.0, 0.0)).xyz(), 0.0)).xyz();vec3d B = (ctoo * vec4d((stoc * vec4d(0.0, 1.0, 0.0, 0.0)).xyz(), 0.0)).xyz();if (o->radius == 0.0) {o->horizon1U->set(vec3f(-(h * 1e-6 + A0.z) / B.z, -dA.z / B.z, 0.0));o->horizon2U->set(vec3f::ZERO);} else {double h1 = h * (h + 2.0 * o->radius);double h2 = (h + o->radius) * (h + o->radius);double alpha = B.dotproduct(B) * h1 - B.z * B.z * h2;double beta0 = (A0.dotproduct(B) * h1 - B.z * A0.z * h2) / alpha;double beta1 = (dA.dotproduct(B) * h1 - B.z * dA.z * h2) / alpha;double gamma0 = (A0.dotproduct(A0) * h1 - A0.z * A0.z * h2) / alpha;double gamma1 = (A0.dotproduct(dA) * h1 - A0.z * dA.z * h2) / alpha;double gamma2 = (dA.dotproduct(dA) * h1 - dA.z * dA.z * h2) / alpha;o->horizon1U->set(vec3f(-beta0, -beta1, 0.0));o->horizon2U->set(vec3f(beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2));}}o->timeU->set(n->getOwner()->getTime() * 1e-6);if (o->radiusU != NULL) {o->radiusU->set(o->radius < 0.0 ? -o->radius : o->radius);}o->heightOffsetU->set(-o->meanHeight);o->lodsU->set(vec4f(o->resolution,pixelSize * o->resolution,log(o->lambdaMin) / log(2.0f),(o->nbWavesU->get() - 1.0f) / (log(o->lambdaMax) / log(2.0f) - log(o->lambdaMin) / log(2.0f))));if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {o->screenWidth = screen.z;o->screenHeight = screen.w;o->screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);o->screenGrid->addAttributeType(0, 2, A32F, false);float f = 1.25f;int NX = int(f * screen.z / o->resolution);int NY = int(f * screen.w / o->resolution);for (int i = 0; i < NY; ++i) {for (int j = 0; j < NX; ++j) {o->screenGrid->addVertex(vec2f(2.0*f*j/(NX-1.0f)-f, 2.0*f*i/(NY-1.0f)-f));}}for (int i = 0; i < NY-1; ++i) {for (int j = 0; j < NX-1; ++j) {o->screenGrid->addIndice(i*NX+j);o->screenGrid->addIndice(i*NX+j+1);o->screenGrid->addIndice((i+1)*NX+j);o->screenGrid->addIndice((i+1)*NX+j);o->screenGrid->addIndice(i*NX+j+1);o->screenGrid->addIndice((i+1)*NX+j+1);}}}fb->draw(prog, *(o->screenGrid));return true;}

Now my update function (basically tries to do the same thing.

public void Update(GameTime gametime){  // compute ltoo = localToOcean transform, where ocean frame = tangent space at// camera projection on sphere o->radius in local spaceVector3 cl = Vector3.Transform(Vector3.Zero, ctol);//camera in local spaceIf ((radius == 0.0 && cl.Z > zmin) ||(radius > 0.0 && cl.Length() > radius + zmin) ||(radius < 0.0 && new Vector2(cl.Y, cl.Z).Length() < -radius - zmin)){oldLtoo = Matrix.Identity;offset = Vector3.Zero;return;}Vector3 ux, uy, uz, oo;if (radius == 0.0){// flat oceanux = Vector3.UnitX;uy = Vector3.UnitY;uz = Vector3.UnitZ;oo = new Vector3(cl.X, cl.Y, 0.0f);}else if (radius > 0.0){// spherical oceanuz = Vector3.Normalize(cl);// unit z vector of ocean frame, in local spaceif (oldLtoo != Matrix.Identity){//Matrix m = Matrix.Transpose(oldLtoo);//ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();ux = Vector3.Normalize(Vector3.Cross(new Vector3(oldLtoo.M21, oldLtoo.M22, oldLtoo.M23), uz));}else{ux = Vector3.Normalize(Vector3.Cross(Vector3.UnitZ, uz));}uy = Vector3.Cross(uz, ux);// unit y vector // negate this ??//uz * radius; // origin of ocean frame, in local spaceoo = ux * radius; }else{// cylindrical oceanuz = Vector3.Normalize(new Vector3(0, -cl.Y, -cl.Z));ux = Vector3.UnitX;uy = Vector3.Cross(uz, ux);oo = new Vector3(cl.X, 0, 0) + uz * radius;}  Matrix ltoo = new Matrix(ux.X, uy.X, uz.X, 0.0f,ux.Y, uy.Y, uz.Y, 0.0f,ux.Z, uy.Z, uz.Z, 0.0f,-Vector3.Dot(ux, oo), -Vector3.Dot(uy, oo), -Vector3.Dot(uz, oo), 1.0f);   ltoo = Matrix.Transpose(ltoo); // compute ctoo = cameraToOcean transformMatrix ctoo = ltoo * Matrix.Transpose (ctol);    if (oldLtoo != Matrix.Identity){Vector3 delta = Vector3.Transform(Vector3.Zero, Matrix.Transpose ( ltoo * Matrix.Invert(oldLtoo)));offset += delta;}oldLtoo = ltoo; //added transposeMatrix ctos = Matrix.Transpose (Parent.cam.Projection); //world*view*projection //n->getOwner()->getCameraToScreen();Matrix stoc = Matrix.Invert (ctos);Vector3 oc = Vector3.Transform(Vector3.Zero, ctoo);//o->oceanSunDirU->set(oceanSunDir.cast<float>());Vector3 worldsunDir = Parent.vLightDirection;Vector3 oceanSunDir = Vector3.Transform(worldsunDir, ltoo * Parent.cam.View); BoundingFrustum frustum = new BoundingFrustum(ctos);Vector3 left = frustum.Left.Normal;Vector3 right = frustum.Right.Normal;float fov = (float)System.Math.Acos(Vector3.Dot(-left, right)); float pixelSize = (float)System.Math.Atan(System.Math.Tan(fov / 2.0f) / (device.Viewport.Height / 2.0f));// angle under which a screen pixel is viewed from the camera float h = oc.Z; Vector4 tmp1,tmp2;tmp1 = Vector4.Transform ( new Vector4 (0,0,0,1),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 A0 = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z); tmp1 = Vector4.Transform ( new Vector4 (1,0,0,0),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 dA = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);tmp1 = Vector4.Transform ( new Vector4 (0,1,0,0),stoc);tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);Vector3 B = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);if (radius == 0.0){horizon1U = new Vector3(-(h * 1e-6f + A0.Z) / B.Z, -dA.Z / B.Z, 0);horizon2U = Vector3.Zero;}else{double h1 = h * (h + 2.0 * radius);double h2 = (h + radius) * (h + radius);double alpha = Vector3.Dot (B,B) * h1 - B.Z * B.Z * h2;double beta0 = (Vector3.Dot (A0,B) * h1 - B.Z * A0.Z * h2) / alpha;double beta1 = (Vector3.Dot (dA,B) * h1 - B.Z * dA.Z * h2) / alpha;double gamma0 = (Vector3.Dot (A0,A0) * h1 - A0.Z * A0.Z * h2) / alpha;double gamma1 = (Vector3.Dot(A0,dA) * h1 - A0.Z * dA.Z * h2) / alpha;double gamma2 = (Vector3.Dot(dA,dA) * h1 - dA.Z * dA.Z * h2) / alpha;horizon1U = new Vector3((float)-beta0, (float)-beta1, 0);horizon2U = new Vector3((float)beta0 * (float)beta0 - (float)gamma0, 2.0f * ((float)beta0 * (float)beta1 - (float)gamma1), (float)beta1 * (float)beta1 - (float)gamma2);}  timeU = (float)gametime.TotalGameTime.TotalMilliseconds *0.0001f; //gametime.ElapsedGameTime.Milliseconds * 1e-6f;heightOffsetU = -meanHeight;lodsU = new Vector4(resolution,pixelSize * resolution,(float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f),(nbWaves - 1.0f) / ((float)System.Math.Log(lambdaMax) / (float)System.Math.Log(2.0f) - (float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f)));  cameraToOceanU = Matrix.Transpose (ctoo);screenToCameraU = stoc;//Matrix.Transpose ( Matrix.Invert ( Parent.cam.view));//stoc;cameraToScreenU = ctos; // already transposed  oceanCameraPosU = new Vector3(-offset.X, -offset.Y, -offset.Z);oceanToWorldU = Matrix.Transpose ( Parent.cam.Projection * Parent.cam.View) * Matrix.Invert (ltoo); //Parent.cam.View * Matrix.Invert(ltoo);oceanToCameraU = Matrix.Transpose(Matrix.Invert(ctoo));//Global Variableswatereffect.Parameters["cameraToOcean"].SetValue(cameraToOceanU);watereffect.Parameters["screenToCamera"].SetValue(screenToCameraU); // World Projection Matrix Inversewatereffect.Parameters["cameraToScreen"].SetValue (cameraToScreenU); // World Projection Matrixwatereffect.Parameters["oceanToCamera"].SetValue(oceanToCameraU);watereffect.Parameters["oceanToWorld"].SetValue(oceanToWorldU);//float height = Vector3.Distance (Parent.cam.Position ,Vector3.Zero) - meanHeight;watereffect.Parameters["oceanCameraPos"].SetValue(oceanCameraPosU);watereffect.Parameters["oceanSunDir"].SetValue(oceanSunDir);watereffect.Parameters["horizon1"].SetValue(horizon1U);watereffect.Parameters["horizon2"].SetValue(horizon2U);watereffect.Parameters["worldCameraPos"].SetValue(Parent.cam.Position);watereffect.Parameters["worldSunDir"].SetValue(worldsunDir);watereffect.Parameters["seaColor"].SetValue(seaColor);watereffect.Parameters["seaRoughness"].SetValue(sigmaXsq);watereffect.Parameters["radius"].SetValue(radius);watereffect.Parameters["nbWaves"].SetValue(nbWaves); // number of waveswatereffect.Parameters["heightOffset"].SetValue(heightOffsetU); ; // so that surface height is centered around z = 0watereffect.Parameters["time"].SetValue (timeU); // current time// grid cell size in pixels, angle under which a grid cell is seen,// and parameters of the geometric series used for wavelengthswatereffect.Parameters["lods"].SetValue(lodsU); //if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {if (screengrid == null || screenWidth != device.Viewport.Width || screenHeight != device.Viewport.Height ){screenWidth = device.Viewport.Width;screenHeight = device.Viewport.Height;//screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);//screenGrid->addAttributeType(0, 2, A32F, false);screengrid = new ScreenGrid (); float f = 1.25f;int NX = (int)(f * screenWidth / resolution);int NY = (int)(f * screenHeight / resolution);for (int i = 0; i < NY; ++i){for (int j = 0; j < NX; ++j){screengrid.AddVertex (new Vector2(2.0f*f*j/(NX-1.0f)-f, 2.0f*f*i/(NY-1.0f)-f));}} for (int i = 0; i < NY-1; ++i) {for (int j = 0; j < NX-1; ++j) {screengrid.AddIndices(i * NX + j);screengrid.AddIndices(i * NX + j + 1);screengrid.AddIndices((i + 1) * NX + j);screengrid.AddIndices((i + 1) * NX + j);screengrid.AddIndices(i * NX + j + 1);screengrid.AddIndices((i + 1) * NX + j + 1);}} screengrid.UpdateBuffers(device);} }
and now for the shader code

original code


/*

* Proland: a procedural landscape rendering library.

* Copyright © 2008-2011 INRIA

*

* This program is free software: you can redistribute it and/or modify

* it under the terms of the GNU General Public License as published by

* the Free Software Foundation, either version 3 of the License, or

* (at your option) any later version.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program. If not, see <http://www.gnu.org/licenses/

*/

/*

* Proland is distributed under a dual-license scheme.

* You can obtain a specific license from Inria: proland-licensing@inria.fr.

*/

/*

* Authors: Eric Bruneton, Antoine Begault, Guillaume Piolat.

*/

#include "globalsShader.glhl"

#include "textureTile.glsl"

const float Z0 = 1.0;

uniform float radius;

uniform mat4 cameraToOcean;

uniform mat4 screenToCamera;

uniform mat4 cameraToScreen;

uniform mat3 oceanToCamera;

uniform mat4 oceanToWorld;

uniform vec3 oceanCameraPos;

uniform vec3 oceanSunDir;

uniform vec3 horizon1;

uniform vec3 horizon2;

uniform float nbWaves; // number of waves

uniform sampler1D wavesSampler; // waves parameters (h, omega, kx, ky) in wind space

uniform float heightOffset; // so that surface height is centered around z = 0

uniform float time; // current time

// grid cell size in pixels, angle under which a grid cell is seen,

// and parameters of the geometric series used for wavelengths

uniform vec4 lods;

#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated

#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all

const float g = 9.81;

const float PI = 3.141592657;

#ifdef _VERTEX_

layout(location=0) in vec3 vertex;

out float oceanLod;

out vec2 oceanUv; // coordinates in wind space used to compute P(u)

out vec3 oceanP; // wave point P(u) in ocean space

out vec3 oceanDPdu; // dPdu in wind space, used to compute N

out vec3 oceanDPdv; // dPdv in wind space, used to compute N

out float oceanRoughness; // variance of unresolved waves in wind space

vec2 oceanPos(vec3 vertex, out float t, out vec3 cameraDir, out vec3 oceanDir) {

float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);

cameraDir = normalize((screenToCamera * vec4(vertex.x, min(vertex.y, horizon), 0.0, 1.0)).xyz);

oceanDir = (cameraToOcean * vec4(cameraDir, 0.0)).xyz;

float cz = oceanCameraPos.z;

float dz = oceanDir.z;

if (radius == 0.0) {

t = (heightOffset + Z0 - cz) / dz;

} else {

float b = dz * (cz + radius);

float c = cz * (cz + 2.0 * radius);

float tSphere = - b - sqrt(max(b * b - c, 0.0));

float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));

t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;

}

return oceanCameraPos.xy + t * oceanDir.xy;

}

vec2 oceanPos(vec3 vertex) {

float t;

vec3 cameraDir;

vec3 oceanDir;

return oceanPos(vertex, t, cameraDir, oceanDir);

}

void main() {

float t;

vec3 cameraDir;

vec3 oceanDir;

vec2 uv = oceanPos(vertex, t, cameraDir, oceanDir);

float lod = - t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

vec2 duv = oceanPos(vertex + vec3(0.0, 0.01, 0.0)) - uv;

vec3 dP = vec3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0));

vec3 dPdu = vec3(1.0, 0.0, 0.0);

vec3 dPdv = vec3(0.0, 1.0, 0.0);

float roughness = getSeaRoughness();

if (duv.x != 0.0 || duv.y != 0.0) {

float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);

for (float i = iMin; i < nbWaves; ++i) {

vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

vec3 factor = wm * wt.x * vec3(wt.zw * overk, 1.0);

dP += factor * vec3(s, s, c);

vec3 dPd = factor * vec3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = wt.x / overk;

roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));

}

}

vec3 p = t * oceanDir + dP + vec3(0.0, 0.0, oceanCameraPos.z);

if (radius > 0.0) {

dPdu += vec3(0.0, 0.0, -p.x / (radius + p.z));

dPdv += vec3(0.0, 0.0, -p.y / (radius + p.z));

}

gl_Position = cameraToScreen * vec4(t * cameraDir + oceanToCamera * dP, 1.0);

oceanLod = lod;

oceanUv = uv;

oceanP = p;

oceanDPdu = dPdu;

oceanDPdv = dPdv;

oceanRoughness = roughness;

}

#endif

#ifdef _FRAGMENT_

#include "atmosphereShader.glhl"

#include "oceanBrdf.glhl"

#include "clouds.glhl"

in float oceanLod;

in vec2 oceanUv;

in vec3 oceanP;

in vec3 oceanDPdu;

in vec3 oceanDPdv;

in float oceanRoughness;

layout(location=0) out vec4 data;

void main() {

vec3 WSD = getWorldSunDir();

vec3 WCP = getWorldCameraPos();

float lod = oceanLod;

vec2 uv = oceanUv;

vec3 dPdu = oceanDPdu;

vec3 dPdv = oceanDPdv;

float roughness = oceanRoughness;

float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);

float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);

float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));

for (float i = iMin; i <= iMAX; i += 1.0) {

vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);

vec3 factor = (1.0 - wm) * wn * wt.x * vec3(wt.zw * overk, 1.0);

vec3 dPd = factor * vec3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = i < iMax ? wt.x / overk : 0.0;

float wkh = (1.0 - wn) * kh;

roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));

}

roughness = max(roughness, 1e-5);

vec3 earthCamera = vec3(0.0, 0.0, oceanCameraPos.z + radius);

vec3 earthP = radius > 0.0 ? normalize(oceanP + vec3(0.0, 0.0, radius)) * (radius + 10.0) : oceanP;

vec3 oceanCamera = vec3(0.0, 0.0, oceanCameraPos.z);

vec3 V = normalize(oceanCamera - oceanP);

vec3 N = normalize(cross(dPdu, dPdv));

if (dot(V, N) < 0.0) {

N = reflect(N, V); // reflects backfacing normals

}

vec3 sunL;

vec3 skyE;

vec3 extinction;

sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);

vec3 worldP = (oceanToWorld * vec4(oceanP, 1.0)).xyz;

sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);

vec3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);

// aerial perspective

vec3 inscatter = inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);

vec3 finalColor = surfaceColor * extinction + inscatter;

data.rgb = hdr(finalColor);

data.a = 1.0;

}

#endif



and now for my code


//Global Variables

float4x4 cameraToOcean;

float4x4 screenToCamera; // World Projection Matrix Inverse

float4x4 cameraToScreen; // World Projection Matrix

float3x3 oceanToCamera;

float4x4 oceanToWorld;

float3 oceanCameraPos;

float3 oceanSunDir;

float3 horizon1;

float3 horizon2;

float3 worldCameraPos;

float3 worldSunDir;

float3 seaColor;

float hdrExposure = 0.3f;

float seaRoughness;

float radius;

float nbWaves; // number of waves

float heightOffset; // so that surface height is centered around z = 0

float time; // current time

// grid cell size in pixels, angle under which a grid cell is seen,

// and parameters of the geometric series used for wavelengths

float4 lods;

 

//Constants

#define PI 3.141592657

const float Z0 = 1.0;

const float g = 9.81;

#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated

#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all

//Textures

texture wavesTexture; // waves parameters (h, omega, kx, ky) in wind space texture2d

sampler wavesSampler = sampler_state

{

texture = <wavesTexture>;

magfilter = POINT;

minfilter = POINT;

mipfilter = POINT;

AddressU = CLAMP;

AddressV = CLAMP;

};

 

struct VertexShaderInput

{

float4 Position : POSITION0;

};

struct VertexShaderOutput

{

float4 Position : POSITION0;

float oceanLod : TEXCOORD0;

float2 oceanUv : TEXCOORD1; // coordinates in wind space used to compute P(u)

float3 oceanP: TEXCOORD2; // wave point P(u) in ocean space

float3 oceanDPdu: TEXCOORD3; // dPdu in wind space, used to compute N

float3 oceanDPdv: TEXCOORD4; // dPdv in wind space, used to compute N

float oceanRoughness: TEXCOORD5; // variance of unresolved waves in wind space

};

//--------------------------------------------------------------

//Utilitie Function Section

//--------------------------------------------------------------

float3 hdr(float3 L) {

#ifndef NOHDR

L = L * hdrExposure;

L.r = L.r < 1.413 ? pow(L.r * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.r);

L.g = L.g < 1.413 ? pow(L.g * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.g);

L.b = L.b < 1.413 ? pow(L.b * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.b);

#endif

return L;

}

//---------------------------------------------

// Fresnel Functions

//---------------------------------------------

float meanFresnel(float cosThetaV, float sigmaV) {

return pow(1.0 - cosThetaV, 5.0 * exp(-2.69 * sigmaV)) / (1.0 + 22.7 * pow(sigmaV, 1.5));

}

float meanFresnel(float3 V, float3 N, float sigmaSq) {

return meanFresnel(dot(V, N), sqrt(sigmaSq));

}

//-----------------------------------------------

//Radiance Functions

//-----------------------------------------------

float reflectedSunRadiance(float3 V, float3 N, float3 L, float sigmaSq) {

float3 H = normalize(L + V);

float hn = dot(H, N);

float p = exp(-2.0 * ((1.0 - hn * hn) / sigmaSq) / (1.0 + hn)) / (4.0 * PI * sigmaSq);

float c = 1.0 - dot(V, H);

float c2 = c * c;

float fresnel = 0.02 + 0.98 * c2 * c2 * c;

float zL = dot(L, N);

float zV = dot(V, N);

zL = max(zL, 0.01);

zV = max(zV, 0.01);

// brdf times cos(thetaL)

return zL <= 0.0 ? 0.0 : max(fresnel * p * sqrt(abs(zL / zV)), 0.0);

}

float3 oceanRadiance(float3 V, float3 N, float3 L, float seaRoughness, float3 sunL, float3 skyE) {

float F = meanFresnel(V, N, seaRoughness);

float3 Lsun = reflectedSunRadiance(V, N, L, seaRoughness) * sunL;

float3 Lsky = skyE * F / PI;

float3 Lsea = (1.0 - F) * seaColor * skyE / PI;

return Lsun + Lsky + Lsea;

}

//--------------------------------------------------------------

//Ocean Position Functions

//--------------------------------------------------------------

float2 oceanPos(float3 vertex, out float t, out float3 cameraDir, out float3 oceanDir)

{

float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);

cameraDir = normalize((mul(screenToCamera , float4(vertex.x, min(vertex.y, horizon), 0.0, 1.0))).xyz);

oceanDir = (mul(cameraToOcean , float4(cameraDir, 0.0))).xyz;

float cz = oceanCameraPos.z;

float dz = oceanDir.z;

if (radius == 0.0) {

t = (heightOffset + Z0 - cz) / dz;

} else {

float b = dz * (cz + radius);

float c = cz * (cz + 2.0 * radius);

float tSphere = - b - sqrt(max(b * b - c, 0.0));

float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));

t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;

}

return oceanCameraPos.xy + t * oceanDir.xy;

}

 

float2 oceanPos(float3 vertex) {

float t;

float3 cameraDir;

float3 oceanDir;

return oceanPos(vertex, t, cameraDir, oceanDir);

}

 

 

//--------------------------------------------------------------

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)

{

VertexShaderOutput output = (VertexShaderOutput)0;

float t;

float3 cameraDir;

float3 oceanDir;

float2 uv = oceanPos(input.Position.xyz, t, cameraDir, oceanDir);

float lod = -t / oceanDir.y * lods.y; //-t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

float2 duv = oceanPos(input.Position.xyz + float3(0.0, 0.01, 0.0)) - uv; // maybe y not z


//float4 tempPos = float4(worldPos.x, 0, worldPos.y, 1.0f);

//worldPos /= 2000.0f;

//worldPos += 0.5f / 512.0f;

float3 dP = float3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0)); // maybe y not z

float3 dPdu = float3(1.0, 0.0, 0.0); // maybe y not z

float3 dPdv = float3(0.0, 1.0, 0.0); // maybe y not z

 

float roughness = seaRoughness;

if (duv.x != 0.0 || duv.y != 0.0) {

float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);

for (float i = iMin; i < nbWaves; ++i)

{

float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float3 factor = wm * wt.x * float3(wt.zw * overk, 1.0);

dP += factor * float3(s, s, c);

float3 dPd = factor * float3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = wt.x / overk;

roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));

}

}

 

 

 

float3 p = t * oceanDir + dP + float3(0.0, 0.0, oceanCameraPos.z); // maybe y not z

if (radius > 0.0) {

dPdu += float3(0.0, 0.0, -p.x / (radius + p.z));

dPdv += float3(0.0, 0.0, -p.y / (radius + p.z));

}


output.Position = mul(cameraToScreen, float4(t * cameraDir + mul(dP,oceanToCamera), 1.0));

//output.Position = mul(cameraToScreen,float4(input.Position.xyz,1));

//logrithmic zbuffer.

const float Cc = 1.0;

const float Far = 1000000000000.0;

output.Position.z = log(Cc*output.Position.z + 1) / log(Cc*Far + 1) * output.Position.w;

output.oceanLod = lod;

output.oceanUv = uv;

output.oceanP = p;

output.oceanDPdu = dPdu;

output.oceanDPdv = dPdv;

output.oceanRoughness = roughness;

return output;

}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0

{

float3 WSD = worldSunDir;

float3 WCP = worldCameraPos;

float lod = input.oceanLod;

float2 uv = input.oceanUv;

float3 dPdu = input.oceanDPdu;

float3 dPdv = input.oceanDPdv;

float roughness = input.oceanRoughness;

float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);

float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);

float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));

for (float i = iMin; i <= iMAX; i += 1.0) {

float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);

float phase = wt.y * time - dot(wt.zw, uv);

float s = sin(phase);

float c = cos(phase);

float overk = g / (wt.y * wt.y);

float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);

float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);

float3 factor = (1.0 - wm) * wn * wt.x * float3(wt.zw * overk, 1.0);

float3 dPd = factor * float3(c, c, -s);

dPdu -= dPd * wt.z;

dPdv -= dPd * wt.w;

wt.zw *= overk;

float kh = i < iMax ? wt.x / overk : 0.0;

float wkh = (1.0 - wn) * kh;

roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));

}

roughness = max(roughness, 1e-5);

float3 earthCamera = float3(0.0, 0.0, oceanCameraPos.z + radius);

float3 earthP = radius > 0.0 ? normalize(input.oceanP + float3(0.0, 0.0, radius)) * (radius + 10.0) : input.oceanP;

float3 oceanCamera = float3(0.0, 0.0, oceanCameraPos.z);

float3 V = normalize(oceanCamera - input.oceanP);

float3 N = normalize(cross(dPdu, dPdv));

if (dot(V, N) < 0.0) {

N = reflect(N, V); // reflects backfacing normals

}

float3 sunL = (float3)1;

float3 skyE = (float3)1;

float3 extinction = (float3)1;

//sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);

float3 worldP = (mul(oceanToWorld , float4(input.oceanP, 1.0))).xyz;

//sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);

float3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);

// aerial perspective

float3 inscatter = (float3)1; //= inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);

float3 finalColor = surfaceColor * extinction + inscatter;

float4 data;

data.rgb = hdr(finalColor);

data.a = 1.0;

return data;

//return float4(1, 0, 0, 1);

}

technique Technique1

{

pass Pass1

{

// TODO: set renderstates here.

VertexShader = compile vs_3_0 VertexShaderFunction();

PixelShader = compile ps_3_0 PixelShaderFunction();

}

}



and now a picture of the result im getting.


Bare in mind this is suppose to be a sphere, it looks like its half working must be something to do with the y/z axis. I know its not a good thing to just post code and ask for help but im going nuts trying to figure this out any help will be much appreciated.

Budinga

screenshot1120139215.jpg

and this is the flat version it seems to be working but the projection and the surface its projecting is been rendered very strange.

screenshot1120131046.jpg

#1Budinga

Posted 01 January 2013 - 03:43 AM

Hi Guyz. Well I have decided to use the great Eric Bruneton's water shaders in my procedural planet renderer, now I have managed to port the shaders, and also with a slightly modified ocean rendering class I get something on the screen, but due to the fact that he use's, a different coord system, well I think that's it I cant seem to get my brain round it. So I was wondering if anybody could spot my problem.

 

Original Render Function

 

bool DrawOceanTask::Impl::run()
{
if (Logger::DEBUG_LOGGER != NULL) {
Logger::DEBUG_LOGGER->log("OCEAN", "DrawOcean");
}
ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer();
ptr<Program> prog = SceneManager::getCurrentProgram();
if (o->nbWavesU == NULL) {
o->nbWavesU = prog->getUniform1f("nbWaves");
o->wavesU = prog->getUniformSampler("wavesSampler");
o->cameraToOceanU = prog->getUniformMatrix4f("cameraToOcean");
o->screenToCameraU = prog->getUniformMatrix4f("screenToCamera");
o->cameraToScreenU = prog->getUniformMatrix4f("cameraToScreen");
o->oceanToCameraU = prog->getUniformMatrix3f("oceanToCamera");
o->oceanToWorldU = prog->getUniformMatrix4f("oceanToWorld");
o->oceanCameraPosU = prog->getUniform3f("oceanCameraPos");
o->oceanSunDirU = prog->getUniform3f("oceanSunDir");
o->horizon1U = prog->getUniform3f("horizon1");
o->horizon2U = prog->getUniform3f("horizon2");
o->timeU = prog->getUniform1f("time");
o->radiusU = prog->getUniform1f("radius");
o->heightOffsetU = prog->getUniform1f("heightOffset");
o->lodsU = prog->getUniform4f("lods");
assert(o->nbWavesU != NULL);
o->generateWaves();
}
vector< ptr<TileSampler> > uniforms;
SceneNode::FieldIterator ui = n->getFields();
while (ui.hasNext()) {
ptr<TileSampler> u = ui.next().cast<TileSampler>();
if (u != NULL && u->getTerrain(0) != NULL) {
u->setTileMap();
}
}
// compute ltoo = localToOcean transform, where ocean frame = tangent space at
// camera projection on sphere o->radius in local space
mat4d ctol = n->getLocalToCamera().inverse();
vec3d cl = ctol * vec3d::ZERO; // camera in local space
if ((o->radius == 0.0 && cl.z > o->zmin) ||
(o->radius > 0.0 && cl.length() > o->radius + o->zmin) ||
(o->radius < 0.0 && vec2d(cl.y, cl.z).length() < -o->radius - o->zmin))
{
o->oldLtoo = mat4d::IDENTITY;
o->offset = vec3d::ZERO;
return true;
}
vec3d ux, uy, uz, oo;
if (o->radius == 0.0) {
// flat ocean
ux = vec3d::UNIT_X;
uy = vec3d::UNIT_Y;
uz = vec3d::UNIT_Z;
oo = vec3d(cl.x, cl.y, 0.0);
} else if (o->radius > 0.0) {
// spherical ocean
uz = cl.normalize(); // unit z vector of ocean frame, in local space
if (o->oldLtoo != mat4d::IDENTITY) {
ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();
} else {
ux = vec3d::UNIT_Z.crossProduct(uz).normalize();
}
uy = uz.crossProduct(ux); // unit y vector
oo = uz * o->radius; // origin of ocean frame, in local space
} else {
// cylindrical ocean
uz = vec3d(0.0, -cl.y, -cl.z).normalize();
ux = vec3d::UNIT_X;
uy = uz.crossProduct(ux);
oo = vec3d(cl.x, 0.0, 0.0) + uz * o->radius;
}
mat4d ltoo = mat4d(
ux.x, ux.y, ux.z, -ux.dotproduct(oo),
uy.x, uy.y, uy.z, -uy.dotproduct(oo),
uz.x, uz.y, uz.z, -uz.dotproduct(oo),
0.0, 0.0, 0.0, 1.0);
// compute ctoo = cameraToOcean transform
mat4d ctoo = ltoo * ctol;
if (o->oldLtoo != mat4d::IDENTITY) {
vec3d delta = ltoo * (o->oldLtoo.inverse() * vec3d::ZERO);
o->offset += delta;
}
o->oldLtoo = ltoo;
mat4d ctos = n->getOwner()->getCameraToScreen();
mat4d stoc = ctos.inverse();
vec3d oc = ctoo * vec3d::ZERO;
if (o->oceanSunDirU != NULL) {
// TODO how to get sun dir in a better way?
SceneManager::NodeIterator i = n->getOwner()->getNodes("light");
if (i.hasNext()) {
ptr<SceneNode> l = i.next();
vec3d worldSunDir = l->getLocalToParent() * vec3d::ZERO;
vec3d oceanSunDir = ltoo.mat3x3() * (n->getWorldToLocal().mat3x3() * worldSunDir);
o->oceanSunDirU->set(oceanSunDir.cast<float>());
}
}
vec4<GLint> screen = fb->getViewport();
vec4d frustum[6];
SceneManager::getFrustumPlanes(ctos, frustum);
vec3d left = frustum[0].xyz().normalize();
vec3d right = frustum[1].xyz().normalize();
float fov = (float) safe_acos(-left.dotproduct(right));
float pixelSize = atan(tan(fov / 2.0f) / (screen.w / 2.0f)); // angle under which a screen pixel is viewed from the camera
o->cameraToOceanU->setMatrix(ctoo.cast<float>());
o->screenToCameraU->setMatrix(stoc.cast<float>());
o->cameraToScreenU->setMatrix(ctos.cast<float>());
o->oceanToCameraU->setMatrix(ctoo.inverse().mat3x3().cast<float>());
o->oceanCameraPosU->set(vec3f(float(-o->offset.x), float(-o->offset.y), float(oc.z)));
if (o->oceanToWorldU != NULL) {
o->oceanToWorldU->setMatrix((n->getLocalToWorld() * ltoo.inverse()).cast<float>());
}
if (o->horizon1U != NULL) {
float h = oc.z;
vec3d A0 = (ctoo * vec4d((stoc * vec4d(0.0, 0.0, 0.0, 1.0)).xyz(), 0.0)).xyz();
vec3d dA = (ctoo * vec4d((stoc * vec4d(1.0, 0.0, 0.0, 0.0)).xyz(), 0.0)).xyz();
vec3d B = (ctoo * vec4d((stoc * vec4d(0.0, 1.0, 0.0, 0.0)).xyz(), 0.0)).xyz();
if (o->radius == 0.0) {
o->horizon1U->set(vec3f(-(h * 1e-6 + A0.z) / B.z, -dA.z / B.z, 0.0));
o->horizon2U->set(vec3f::ZERO);
} else {
double h1 = h * (h + 2.0 * o->radius);
double h2 = (h + o->radius) * (h + o->radius);
double alpha = B.dotproduct(B) * h1 - B.z * B.z * h2;
double beta0 = (A0.dotproduct(B) * h1 - B.z * A0.z * h2) / alpha;
double beta1 = (dA.dotproduct(B) * h1 - B.z * dA.z * h2) / alpha;
double gamma0 = (A0.dotproduct(A0) * h1 - A0.z * A0.z * h2) / alpha;
double gamma1 = (A0.dotproduct(dA) * h1 - A0.z * dA.z * h2) / alpha;
double gamma2 = (dA.dotproduct(dA) * h1 - dA.z * dA.z * h2) / alpha;
o->horizon1U->set(vec3f(-beta0, -beta1, 0.0));
o->horizon2U->set(vec3f(beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2));
}
}
o->timeU->set(n->getOwner()->getTime() * 1e-6);
if (o->radiusU != NULL) {
o->radiusU->set(o->radius < 0.0 ? -o->radius : o->radius);
}
o->heightOffsetU->set(-o->meanHeight);
o->lodsU->set(vec4f(o->resolution,
pixelSize * o->resolution,
log(o->lambdaMin) / log(2.0f),
(o->nbWavesU->get() - 1.0f) / (log(o->lambdaMax) / log(2.0f) - log(o->lambdaMin) / log(2.0f))));
if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {
o->screenWidth = screen.z;
o->screenHeight = screen.w;
o->screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);
o->screenGrid->addAttributeType(0, 2, A32F, false);
float f = 1.25f;
int NX = int(f * screen.z / o->resolution);
int NY = int(f * screen.w / o->resolution);
for (int i = 0; i < NY; ++i) {
for (int j = 0; j < NX; ++j) {
o->screenGrid->addVertex(vec2f(2.0*f*j/(NX-1.0f)-f, 2.0*f*i/(NY-1.0f)-f));
}
}
for (int i = 0; i < NY-1; ++i) {
for (int j = 0; j < NX-1; ++j) {
o->screenGrid->addIndice(i*NX+j);
o->screenGrid->addIndice(i*NX+j+1);
o->screenGrid->addIndice((i+1)*NX+j);
o->screenGrid->addIndice((i+1)*NX+j);
o->screenGrid->addIndice(i*NX+j+1);
o->screenGrid->addIndice((i+1)*NX+j+1);
}
}
}
fb->draw(prog, *(o->screenGrid));
return true;
}

 

 

Now my update function (basically tries to do the same thing.

 

 

public void Update(GameTime gametime)
{
 
 
// compute ltoo = localToOcean transform, where ocean frame = tangent space at
// camera projection on sphere o->radius in local space
Vector3 cl = Vector3.Transform(Vector3.Zero, ctol);//camera in local space
I
f ((radius == 0.0 && cl.Z > zmin) ||
(radius > 0.0 && cl.Length() > radius + zmin) ||
(radius < 0.0 && new Vector2(cl.Y, cl.Z).Length() < -radius - zmin))
{
oldLtoo = Matrix.Identity;
offset = Vector3.Zero;
return;
}
Vector3 ux, uy, uz, oo;
if (radius == 0.0)
{
// flat ocean
ux = Vector3.UnitX;
uy = Vector3.UnitY;
uz = Vector3.UnitZ;
oo = new Vector3(cl.X, cl.Y, 0.0f);
}
else if (radius > 0.0)
{
// spherical ocean
uz = Vector3.Normalize(cl);// unit z vector of ocean frame, in local space
if (oldLtoo != Matrix.Identity)
{
//Matrix m = Matrix.Transpose(oldLtoo);
//ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();
ux = Vector3.Normalize(Vector3.Cross(new Vector3(oldLtoo.M21, oldLtoo.M22, oldLtoo.M23), uz));
}
else
{
ux = Vector3.Normalize(Vector3.Cross(Vector3.UnitZ, uz));
}
uy = Vector3.Cross(uz, ux);// unit y vector // negate this ??
//uz * radius; // origin of ocean frame, in local space
oo = ux * radius;
 
}
else
{
// cylindrical ocean
uz = Vector3.Normalize(new Vector3(0, -cl.Y, -cl.Z));
ux = Vector3.UnitX;
uy = Vector3.Cross(uz, ux);
oo = new Vector3(cl.X, 0, 0) + uz * radius;
}
 
 
Matrix ltoo = new Matrix(
ux.X, uy.X, uz.X, 0.0f,
ux.Y, uy.Y, uz.Y, 0.0f,
ux.Z, uy.Z, uz.Z, 0.0f,
-Vector3.Dot(ux, oo), -Vector3.Dot(uy, oo), -Vector3.Dot(uz, oo), 1.0f);
 
 
 
ltoo = Matrix.Transpose(ltoo);
 
// compute ctoo = cameraToOcean transform
Matrix ctoo = ltoo * Matrix.Transpose (ctol);
 
 
 
 
if (oldLtoo != Matrix.Identity)
{
Vector3 delta = Vector3.Transform(Vector3.Zero, Matrix.Transpose ( ltoo * Matrix.Invert(oldLtoo)));
offset += delta;
}
oldLtoo = ltoo;
 
//added transpose
Matrix ctos = Matrix.Transpose (Parent.cam.Projection); //world*view*projection //n->getOwner()->getCameraToScreen();
Matrix stoc = Matrix.Invert (ctos);
Vector3 oc = Vector3.Transform(Vector3.Zero, ctoo);
//o->oceanSunDirU->set(oceanSunDir.cast<float>());
Vector3 worldsunDir = Parent.vLightDirection;
Vector3 oceanSunDir = Vector3.Transform(worldsunDir, ltoo * Parent.cam.View);
 
BoundingFrustum frustum = new BoundingFrustum(ctos);
Vector3 left = frustum.Left.Normal;
Vector3 right = frustum.Right.Normal;
float fov = (float)System.Math.Acos(Vector3.Dot(-left, right));
 
float pixelSize = (float)System.Math.Atan(System.Math.Tan(fov / 2.0f) / (device.Viewport.Height / 2.0f));// angle under which a screen pixel is viewed from the camera
 
float h = oc.Z;
 
Vector4 tmp1,tmp2;
tmp1 = Vector4.Transform ( new Vector4 (0,0,0,1),stoc);
tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);
Vector3 A0 = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);
 
tmp1 = Vector4.Transform ( new Vector4 (1,0,0,0),stoc);
tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);
Vector3 dA = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);
tmp1 = Vector4.Transform ( new Vector4 (0,1,0,0),stoc);
tmp2 = Vector4.Transform (new Vector4 (tmp1.X,tmp1.Y,tmp1.Z,0),ctoo);
Vector3 B = new Vector3 (tmp2.X,tmp2.Y,tmp2.Z);
if (radius == 0.0)
{
horizon1U = new Vector3(-(h * 1e-6f + A0.Z) / B.Z, -dA.Z / B.Z, 0);
horizon2U = Vector3.Zero;
}
else
{
double h1 = h * (h + 2.0 * radius);
double h2 = (h + radius) * (h + radius);
double alpha = Vector3.Dot (B,B) * h1 - B.Z * B.Z * h2;
double beta0 = (Vector3.Dot (A0,B) * h1 - B.Z * A0.Z * h2) / alpha;
double beta1 = (Vector3.Dot (dA,B) * h1 - B.Z * dA.Z * h2) / alpha;
double gamma0 = (Vector3.Dot (A0,A0) * h1 - A0.Z * A0.Z * h2) / alpha;
double gamma1 = (Vector3.Dot(A0,dA) * h1 - A0.Z * dA.Z * h2) / alpha;
double gamma2 = (Vector3.Dot(dA,dA) * h1 - dA.Z * dA.Z * h2) / alpha;
horizon1U = new Vector3((float)-beta0, (float)-beta1, 0);
horizon2U = new Vector3((float)beta0 * (float)beta0 - (float)gamma0, 2.0f * ((float)beta0 * (float)beta1 - (float)gamma1), (float)beta1 * (float)beta1 - (float)gamma2);
}
 
 
timeU = (float)gametime.TotalGameTime.TotalMilliseconds *0.0001f; //gametime.ElapsedGameTime.Milliseconds * 1e-6f;
heightOffsetU = -meanHeight;
lodsU = new Vector4(resolution,
pixelSize * resolution,
(float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f),
(nbWaves - 1.0f) / ((float)System.Math.Log(lambdaMax) / (float)System.Math.Log(2.0f) - (float)System.Math.Log(lambdaMin) / (float)System.Math.Log(2.0f)));
 
 
cameraToOceanU = Matrix.Transpose (ctoo);
screenToCameraU = stoc;//Matrix.Transpose ( Matrix.Invert ( Parent.cam.view));//stoc;
cameraToScreenU = ctos; // already transposed
 
 
oceanCameraPosU = new Vector3(-offset.X, -offset.Y, -offset.Z);
oceanToWorldU = Matrix.Transpose ( Parent.cam.Projection * Parent.cam.View) * Matrix.Invert (ltoo); //Parent.cam.View * Matrix.Invert(ltoo);
oceanToCameraU = Matrix.Transpose(Matrix.Invert(ctoo));
//Global Variables
watereffect.Parameters["cameraToOcean"].SetValue(cameraToOceanU);
watereffect.Parameters["screenToCamera"].SetValue(screenToCameraU); // World Projection Matrix Inverse
watereffect.Parameters["cameraToScreen"].SetValue (cameraToScreenU); // World Projection Matrix
watereffect.Parameters["oceanToCamera"].SetValue(oceanToCameraU);
watereffect.Parameters["oceanToWorld"].SetValue(oceanToWorldU);
//float height = Vector3.Distance (Parent.cam.Position ,Vector3.Zero) - meanHeight;
watereffect.Parameters["oceanCameraPos"].SetValue(oceanCameraPosU);
watereffect.Parameters["oceanSunDir"].SetValue(oceanSunDir);
watereffect.Parameters["horizon1"].SetValue(horizon1U);
watereffect.Parameters["horizon2"].SetValue(horizon2U);
watereffect.Parameters["worldCameraPos"].SetValue(Parent.cam.Position);
watereffect.Parameters["worldSunDir"].SetValue(worldsunDir);
watereffect.Parameters["seaColor"].SetValue(seaColor);
watereffect.Parameters["seaRoughness"].SetValue(sigmaXsq);
watereffect.Parameters["radius"].SetValue(radius);
watereffect.Parameters["nbWaves"].SetValue(nbWaves); // number of waves
watereffect.Parameters["heightOffset"].SetValue(heightOffsetU); ; // so that surface height is centered around z = 0
watereffect.Parameters["time"].SetValue (timeU); // current time
// grid cell size in pixels, angle under which a grid cell is seen,
// and parameters of the geometric series used for wavelengths
watereffect.Parameters["lods"].SetValue(lodsU);
 
//if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {
if (screengrid == null || screenWidth != device.Viewport.Width || screenHeight != device.Viewport.Height )
{
screenWidth = device.Viewport.Width;
screenHeight = device.Viewport.Height;
//screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);
//screenGrid->addAttributeType(0, 2, A32F, false);
screengrid = new ScreenGrid ();
 
float f = 1.25f;
int NX = (int)(f * screenWidth / resolution);
int NY = (int)(f * screenHeight / resolution);
for (int i = 0; i < NY; ++i)
{
for (int j = 0; j < NX; ++j)
{
screengrid.AddVertex (new Vector2(2.0f*f*j/(NX-1.0f)-f, 2.0f*f*i/(NY-1.0f)-f));
}
}
 
for (int i = 0; i < NY-1; ++i) {
for (int j = 0; j < NX-1; ++j) {
screengrid.AddIndices(i * NX + j);
screengrid.AddIndices(i * NX + j + 1);
screengrid.AddIndices((i + 1) * NX + j);
screengrid.AddIndices((i + 1) * NX + j);
screengrid.AddIndices(i * NX + j + 1);
screengrid.AddIndices((i + 1) * NX + j + 1);
}
}
 
screengrid.UpdateBuffers(device);
}
 
}

 

and now for the shader code

 

original code

 

/*
* Proland: a procedural landscape rendering library.
* Copyright © 2008-2011 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
/*
* Proland is distributed under a dual-license scheme.
* You can obtain a specific license from Inria: proland-licensing@inria.fr.
*/
/*
* Authors: Eric Bruneton, Antoine Begault, Guillaume Piolat.
*/
#include "globalsShader.glhl"
#include "textureTile.glsl"
const float Z0 = 1.0;
uniform float radius;
uniform mat4 cameraToOcean;
uniform mat4 screenToCamera;
uniform mat4 cameraToScreen;
uniform mat3 oceanToCamera;
uniform mat4 oceanToWorld;
uniform vec3 oceanCameraPos;
uniform vec3 oceanSunDir;
uniform vec3 horizon1;
uniform vec3 horizon2;
uniform float nbWaves; // number of waves
uniform sampler1D wavesSampler; // waves parameters (h, omega, kx, ky) in wind space
uniform float heightOffset; // so that surface height is centered around z = 0
uniform float time; // current time
// grid cell size in pixels, angle under which a grid cell is seen,
// and parameters of the geometric series used for wavelengths
uniform vec4 lods;
#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated
#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all
const float g = 9.81;
const float PI = 3.141592657;
#ifdef _VERTEX_
layout(location=0) in vec3 vertex;
out float oceanLod;
out vec2 oceanUv; // coordinates in wind space used to compute P(u)
out vec3 oceanP; // wave point P(u) in ocean space
out vec3 oceanDPdu; // dPdu in wind space, used to compute N
out vec3 oceanDPdv; // dPdv in wind space, used to compute N
out float oceanRoughness; // variance of unresolved waves in wind space
vec2 oceanPos(vec3 vertex, out float t, out vec3 cameraDir, out vec3 oceanDir) {
float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);
cameraDir = normalize((screenToCamera * vec4(vertex.x, min(vertex.y, horizon), 0.0, 1.0)).xyz);
oceanDir = (cameraToOcean * vec4(cameraDir, 0.0)).xyz;
float cz = oceanCameraPos.z;
float dz = oceanDir.z;
if (radius == 0.0) {
t = (heightOffset + Z0 - cz) / dz;
} else {
float b = dz * (cz + radius);
float c = cz * (cz + 2.0 * radius);
float tSphere = - b - sqrt(max(b * b - c, 0.0));
float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));
t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;
}
return oceanCameraPos.xy + t * oceanDir.xy;
}
vec2 oceanPos(vec3 vertex) {
float t;
vec3 cameraDir;
vec3 oceanDir;
return oceanPos(vertex, t, cameraDir, oceanDir);
}
void main() {
float t;
vec3 cameraDir;
vec3 oceanDir;
vec2 uv = oceanPos(vertex, t, cameraDir, oceanDir);
float lod = - t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface
vec2 duv = oceanPos(vertex + vec3(0.0, 0.01, 0.0)) - uv;
vec3 dP = vec3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0));
vec3 dPdu = vec3(1.0, 0.0, 0.0);
vec3 dPdv = vec3(0.0, 1.0, 0.0);
float roughness = getSeaRoughness();
if (duv.x != 0.0 || duv.y != 0.0) {
float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);
for (float i = iMin; i < nbWaves; ++i) {
vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);
float phase = wt.y * time - dot(wt.zw, uv);
float s = sin(phase);
float c = cos(phase);
float overk = g / (wt.y * wt.y);
float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);
vec3 factor = wm * wt.x * vec3(wt.zw * overk, 1.0);
dP += factor * vec3(s, s, c);
vec3 dPd = factor * vec3(c, c, -s);
dPdu -= dPd * wt.z;
dPdv -= dPd * wt.w;
wt.zw *= overk;
float kh = wt.x / overk;
roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));
}
}
vec3 p = t * oceanDir + dP + vec3(0.0, 0.0, oceanCameraPos.z);
if (radius > 0.0) {
dPdu += vec3(0.0, 0.0, -p.x / (radius + p.z));
dPdv += vec3(0.0, 0.0, -p.y / (radius + p.z));
}
gl_Position = cameraToScreen * vec4(t * cameraDir + oceanToCamera * dP, 1.0);
oceanLod = lod;
oceanUv = uv;
oceanP = p;
oceanDPdu = dPdu;
oceanDPdv = dPdv;
oceanRoughness = roughness;
}
#endif
#ifdef _FRAGMENT_
#include "atmosphereShader.glhl"
#include "oceanBrdf.glhl"
#include "clouds.glhl"
in float oceanLod;
in vec2 oceanUv;
in vec3 oceanP;
in vec3 oceanDPdu;
in vec3 oceanDPdv;
in float oceanRoughness;
layout(location=0) out vec4 data;
void main() {
vec3 WSD = getWorldSunDir();
vec3 WCP = getWorldCameraPos();
float lod = oceanLod;
vec2 uv = oceanUv;
vec3 dPdu = oceanDPdu;
vec3 dPdv = oceanDPdv;
float roughness = oceanRoughness;
float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);
float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);
float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));
for (float i = iMin; i <= iMAX; i += 1.0) {
vec4 wt = textureLod(wavesSampler, (i + 0.5) / nbWaves, 0.0);
float phase = wt.y * time - dot(wt.zw, uv);
float s = sin(phase);
float c = cos(phase);
float overk = g / (wt.y * wt.y);
float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);
float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);
vec3 factor = (1.0 - wm) * wn * wt.x * vec3(wt.zw * overk, 1.0);
vec3 dPd = factor * vec3(c, c, -s);
dPdu -= dPd * wt.z;
dPdv -= dPd * wt.w;
wt.zw *= overk;
float kh = i < iMax ? wt.x / overk : 0.0;
float wkh = (1.0 - wn) * kh;
roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));
}
roughness = max(roughness, 1e-5);
vec3 earthCamera = vec3(0.0, 0.0, oceanCameraPos.z + radius);
vec3 earthP = radius > 0.0 ? normalize(oceanP + vec3(0.0, 0.0, radius)) * (radius + 10.0) : oceanP;
vec3 oceanCamera = vec3(0.0, 0.0, oceanCameraPos.z);
vec3 V = normalize(oceanCamera - oceanP);
vec3 N = normalize(cross(dPdu, dPdv));
if (dot(V, N) < 0.0) {
N = reflect(N, V); // reflects backfacing normals
}
vec3 sunL;
vec3 skyE;
vec3 extinction;
sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);
vec3 worldP = (oceanToWorld * vec4(oceanP, 1.0)).xyz;
sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);
vec3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);
// aerial perspective
vec3 inscatter = inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);
vec3 finalColor = surfaceColor * extinction + inscatter;
data.rgb = hdr(finalColor);
data.a = 1.0;
}
#endif

 

and now for my code

 

//Global Variables
float4x4 cameraToOcean;
float4x4 screenToCamera; // World Projection Matrix Inverse
float4x4 cameraToScreen; // World Projection Matrix
float3x3 oceanToCamera;
float4x4 oceanToWorld;
float3 oceanCameraPos;
float3 oceanSunDir;
float3 horizon1;
float3 horizon2;
float3 worldCameraPos;
float3 worldSunDir;
float3 seaColor;
float hdrExposure = 0.3f;
float seaRoughness;
float radius;
float nbWaves; // number of waves
float heightOffset; // so that surface height is centered around z = 0
float time; // current time
// grid cell size in pixels, angle under which a grid cell is seen,
// and parameters of the geometric series used for wavelengths
float4 lods;
 
//Constants
#define PI 3.141592657
const float Z0 = 1.0;
const float g = 9.81;
#define NYQUIST_MIN 0.5 // wavelengths below NYQUIST_MIN * sampling period are fully attenuated
#define NYQUIST_MAX 1.25 // wavelengths above NYQUIST_MAX * sampling period are not attenuated at all
//Textures
texture wavesTexture; // waves parameters (h, omega, kx, ky) in wind space texture2d
sampler wavesSampler = sampler_state
{
texture = <wavesTexture>;
magfilter = POINT;
minfilter = POINT;
mipfilter = POINT;
AddressU = CLAMP;
AddressV = CLAMP;
};
 
struct VertexShaderInput
{
float4 Position : POSITION0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float oceanLod : TEXCOORD0;
float2 oceanUv : TEXCOORD1; // coordinates in wind space used to compute P(u)
float3 oceanP: TEXCOORD2; // wave point P(u) in ocean space
float3 oceanDPdu: TEXCOORD3; // dPdu in wind space, used to compute N
float3 oceanDPdv: TEXCOORD4; // dPdv in wind space, used to compute N
float oceanRoughness: TEXCOORD5; // variance of unresolved waves in wind space
};
//--------------------------------------------------------------
//Utilitie Function Section
//--------------------------------------------------------------
float3 hdr(float3 L) {
#ifndef NOHDR
L = L * hdrExposure;
L.r = L.r < 1.413 ? pow(L.r * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.r);
L.g = L.g < 1.413 ? pow(L.g * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.g);
L.b = L.b < 1.413 ? pow(L.b * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.b);
#endif
return L;
}
//---------------------------------------------
// Fresnel Functions
//---------------------------------------------
float meanFresnel(float cosThetaV, float sigmaV) {
return pow(1.0 - cosThetaV, 5.0 * exp(-2.69 * sigmaV)) / (1.0 + 22.7 * pow(sigmaV, 1.5));
}
float meanFresnel(float3 V, float3 N, float sigmaSq) {
return meanFresnel(dot(V, N), sqrt(sigmaSq));
}
//-----------------------------------------------
//Radiance Functions
//-----------------------------------------------
float reflectedSunRadiance(float3 V, float3 N, float3 L, float sigmaSq) {
float3 H = normalize(L + V);
float hn = dot(H, N);
float p = exp(-2.0 * ((1.0 - hn * hn) / sigmaSq) / (1.0 + hn)) / (4.0 * PI * sigmaSq);
float c = 1.0 - dot(V, H);
float c2 = c * c;
float fresnel = 0.02 + 0.98 * c2 * c2 * c;
float zL = dot(L, N);
float zV = dot(V, N);
zL = max(zL, 0.01);
zV = max(zV, 0.01);
// brdf times cos(thetaL)
return zL <= 0.0 ? 0.0 : max(fresnel * p * sqrt(abs(zL / zV)), 0.0);
}
float3 oceanRadiance(float3 V, float3 N, float3 L, float seaRoughness, float3 sunL, float3 skyE) {
float F = meanFresnel(V, N, seaRoughness);
float3 Lsun = reflectedSunRadiance(V, N, L, seaRoughness) * sunL;
float3 Lsky = skyE * F / PI;
float3 Lsea = (1.0 - F) * seaColor * skyE / PI;
return Lsun + Lsky + Lsea;
}
//--------------------------------------------------------------
//Ocean Position Functions
//--------------------------------------------------------------
float2 oceanPos(float3 vertex, out float t, out float3 cameraDir, out float3 oceanDir)
{
float horizon = horizon1.x + horizon1.y * vertex.x - sqrt(horizon2.x + (horizon2.y + horizon2.z * vertex.x) * vertex.x);
cameraDir = normalize((mul(screenToCamera , float4(vertex.x, min(vertex.y, horizon), 0.0, 1.0))).xyz);
oceanDir = (mul(cameraToOcean , float4(cameraDir, 0.0))).xyz;
float cz = oceanCameraPos.z;
float dz = oceanDir.z;
if (radius == 0.0) {
t = (heightOffset + Z0 - cz) / dz;
} else {
float b = dz * (cz + radius);
float c = cz * (cz + 2.0 * radius);
float tSphere = - b - sqrt(max(b * b - c, 0.0));
float tApprox = - cz / dz * (1.0 + cz / (2.0 * radius) * (1.0 - dz * dz));
t = abs((tApprox - tSphere) * dz) < 1.0 ? tApprox : tSphere;
}
return oceanCameraPos.xy + t * oceanDir.xy;
}
 
float2 oceanPos(float3 vertex) {
float t;
float3 cameraDir;
float3 oceanDir;
return oceanPos(vertex, t, cameraDir, oceanDir);
}
 
 
//--------------------------------------------------------------
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output = (VertexShaderOutput)0;
float t;
float3 cameraDir;
float3 oceanDir;
float2 uv = oceanPos(input.Position.xyz, t, cameraDir, oceanDir);
float lod = -t / oceanDir.y * lods.y; //-t / oceanDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface
float2 duv = oceanPos(input.Position.xyz + float3(0.0, 0.01, 0.0)) - uv; // maybe y not z
 
//float4 tempPos = float4(worldPos.x, 0, worldPos.y, 1.0f);
//worldPos /= 2000.0f;
//worldPos += 0.5f / 512.0f;
float3 dP = float3(0.0, 0.0, heightOffset + (radius > 0.0 ? 0.0 : Z0)); // maybe y not z
float3 dPdu = float3(1.0, 0.0, 0.0); // maybe y not z
float3 dPdv = float3(0.0, 1.0, 0.0); // maybe y not z
 
float roughness = seaRoughness;
if (duv.x != 0.0 || duv.y != 0.0) {
float iMin = max(floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w), 0.0);
for (float i = iMin; i < nbWaves; ++i)
{
float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);
float phase = wt.y * time - dot(wt.zw, uv);
float s = sin(phase);
float c = cos(phase);
float overk = g / (wt.y * wt.y);
float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);
float3 factor = wm * wt.x * float3(wt.zw * overk, 1.0);
dP += factor * float3(s, s, c);
float3 dPd = factor * float3(c, c, -s);
dPdu -= dPd * wt.z;
dPdv -= dPd * wt.w;
wt.zw *= overk;
float kh = wt.x / overk;
roughness -= wt.z * wt.z * (1.0 - sqrt(1.0 - kh * kh));
}
}
 
 
 
float3 p = t * oceanDir + dP + float3(0.0, 0.0, oceanCameraPos.z); // maybe y not z
if (radius > 0.0) {
dPdu += float3(0.0, 0.0, -p.x / (radius + p.z));
dPdv += float3(0.0, 0.0, -p.y / (radius + p.z));
}
 
output.Position = mul(cameraToScreen, float4(t * cameraDir + mul(dP,oceanToCamera), 1.0));
//output.Position = mul(cameraToScreen,float4(input.Position.xyz,1));
//logrithmic zbuffer.
const float Cc = 1.0;
const float Far = 1000000000000.0;
output.Position.z = log(Cc*output.Position.z + 1) / log(Cc*Far + 1) * output.Position.w;
output.oceanLod = lod;
output.oceanUv = uv;
output.oceanP = p;
output.oceanDPdu = dPdu;
output.oceanDPdv = dPdv;
output.oceanRoughness = roughness;
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float3 WSD = worldSunDir;
float3 WCP = worldCameraPos;
float lod = input.oceanLod;
float2 uv = input.oceanUv;
float3 dPdu = input.oceanDPdu;
float3 dPdv = input.oceanDPdv;
float roughness = input.oceanRoughness;
float iMAX = min(ceil((log2(NYQUIST_MAX * lod) - lods.z) * lods.w), nbWaves - 1.0);
float iMax = floor((log2(NYQUIST_MIN * lod) - lods.z) * lods.w);
float iMin = max(0.0, floor((log2(NYQUIST_MIN * lod / lods.x) - lods.z) * lods.w));
for (float i = iMin; i <= iMAX; i += 1.0) {
float4 wt = tex1Dlod(wavesSampler, (i + 0.5) / nbWaves);
float phase = wt.y * time - dot(wt.zw, uv);
float s = sin(phase);
float c = cos(phase);
float overk = g / (wt.y * wt.y);
float wm = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod);
float wn = smoothstep(NYQUIST_MIN, NYQUIST_MAX, (2.0 * PI) * overk / lod * lods.x);
float3 factor = (1.0 - wm) * wn * wt.x * float3(wt.zw * overk, 1.0);
float3 dPd = factor * float3(c, c, -s);
dPdu -= dPd * wt.z;
dPdv -= dPd * wt.w;
wt.zw *= overk;
float kh = i < iMax ? wt.x / overk : 0.0;
float wkh = (1.0 - wn) * kh;
roughness -= wt.z * wt.z * (sqrt(1.0 - wkh * wkh) - sqrt(1.0 - kh * kh));
}
roughness = max(roughness, 1e-5);
float3 earthCamera = float3(0.0, 0.0, oceanCameraPos.z + radius);
float3 earthP = radius > 0.0 ? normalize(input.oceanP + float3(0.0, 0.0, radius)) * (radius + 10.0) : input.oceanP;
float3 oceanCamera = float3(0.0, 0.0, oceanCameraPos.z);
float3 V = normalize(oceanCamera - input.oceanP);
float3 N = normalize(cross(dPdu, dPdv));
if (dot(V, N) < 0.0) {
N = reflect(N, V); // reflects backfacing normals
}
float3 sunL = (float3)1;
float3 skyE = (float3)1;
float3 extinction = (float3)1;
//sunRadianceAndSkyIrradiance(earthP, N, oceanSunDir, sunL, skyE);
float3 worldP = (mul(oceanToWorld , float4(input.oceanP, 1.0))).xyz;
//sunL *= cloudsShadow(worldP, WSD, 0.0, dot(normalize(worldP), WSD), radius);
float3 surfaceColor = oceanRadiance(V, N, oceanSunDir, roughness, sunL, skyE);
// aerial perspective
float3 inscatter = (float3)1; //= inScattering(earthCamera, earthP, oceanSunDir, extinction, 0.0);
float3 finalColor = surfaceColor * extinction + inscatter;
float4 data;
data.rgb = hdr(finalColor);
data.a = 1.0;
return data;
//return float4(1, 0, 0, 1);
}
technique Technique1
{
pass Pass1
{
// TODO: set renderstates here.
VertexShader = compile vs_3_0 VertexShaderFunction();
PixelShader = compile ps_3_0 PixelShaderFunction();
}
}

 

and now a picture of the result im getting.

 

 

Bare in mind this is suppose to be a sphere, it looks like its half working must be something to do with the y/z axis. I know its not a good thing to just post code and ask for help but im going nuts trying to figure this out any help will be much appreciated.

 

Budinga

 

screenshot1120139215.jpg


PARTNERS