Jump to content

  • Log In with Google      Sign In   
  • Create Account

Budinga

Member Since 20 Jan 2008
Offline Last Active Jul 26 2014 02:06 AM

Topics I've Started

Problems Porting Eric Bruneton's Water to XNA

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

          //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

Snycing Clipmap Cube Face Cenetrs

12 June 2011 - 03:01 AM

Well i am having a problem trying to snc the clipmap cube face centers from my procedural planet renderer, im very stuck at the moment. I want to get the same cube center no matter were the camera is i think i need some sort of projection. heres a pic of the clipmaps synced, but they do that as i move away and when i move close the move away from me. Anybody got any ideas.



Posted Image

Maybe i could have some sort of virtual box and project, from the camera and get an x,z coord on that box, just a bit stumped on how to go about it.

Any ideas will be great.

SOLVED [XNA] Is there a right way to generate a sphere for an atmosphere

25 January 2011 - 02:45 PM

<P>Well i have spent loadz of time working on procedural planet based on oneal's sandbox all written in vb.net and xna.i have the basic shaders working down to a T, but i have 1 problem, as i have to render the atmosphere mesh after the planet and cull the front faces as i understand when i do this i get gaps in the triangles and it overlays the planet, am i generating it wrong or am i doing something else wrong. the way i got round it is to render the atmosphere after the planet with not depth buffer but this does not work properly as when you go round the planet the atmosphere lookes strange. here is the code i am using to generate and render the sphere. i also got a slight prob using the bitshifting to calculate the quadtrees but im getting there, i think i should fix this first as the rest works ok for now.<BR><BR>
<BR>        Public Sub New(ByVal Dev As GraphicsDevice, ByVal Cam As Camera, ByVal PlMap As PlanetaryMap, ByVal FromSpaceShader As Effect, ByVal Stacks As Integer, ByVal Slices As Integer, ByVal Radius As Single)<BR>            Device = Dev<BR>            Camera = Camera<BR>            Planet = PlMap<BR>            Dim elm() As VertexElement = {New VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0)}<BR>            Declaration = New VertexDeclaration(Device, elm)</P>
<P>            ' Calculates the resulting number of vertices and indices<BR>            Dim numberVertices = (Stacks + 1) * (Slices + 1)<BR>            Dim numberIndices = (3 * Stacks * (Slices + 1)) * 2<BR>            Dim indices As Integer() = New Integer(numberIndices - 1) {}<BR>            Dim vertices As Vector3() = New Vector3(numberVertices - 1) {}</P>
<P>            Dim StackAngle As Single = MathHelper.Pi / CSng(Stacks)<BR>            Dim SliceAngle As Single = CSng(Math.PI * 2.0) / CSng(Slices)</P>
<P>            ' Generate the group of Stacks for the sphere  <BR>            Dim wVertexIndex As Integer = 0<BR>            Dim vertexCount As Integer = 0<BR>            Dim indexCount As Integer = 0</P>
<P>            For stack As Integer = 0 To (Stacks + 1) - 1</P>
<P>                Dim r As Single = CSng(Math.Sin(CSng(stack) * StackAngle))<BR>                Dim y As Single = CSng(Math.Cos(CSng(stack) * StackAngle))</P>
<P>                ' Generate the group of segments for the current Stack  <BR>                For slice As Integer = 0 To (Slices + 1) - 1<BR>                    Dim x As Single = r * CSng(Math.Sin(CSng(slice) * SliceAngle))<BR>                    Dim z As Single = r * CSng(Math.Cos(CSng(slice) * SliceAngle))<BR>                    vertices(vertexCount) = New Vector3(x * Radius, y * Radius, z * Radius)</P>
<P>                    'vertices(vertexCount).Normal = Vector3.Normalize(New Vector3(x, y, z))</P>
<P>                    'vertices(vertexCount).TextureCoordinate = New Vector2(CSng(slice) / CSng(Slices), CSng(stack) / CSng(Stacks))<BR>                    vertexCount += 1<BR>                    If Not (stack = (Stacks - 1)) Then<BR>                        ' First Face<BR>                        indices(indexCount) = wVertexIndex + (Slices + 1)<BR>                        indexCount += 1</P>
<P>                        indices(indexCount) = wVertexIndex<BR>                        indexCount += 1</P>
<P>                        indices(indexCount) = wVertexIndex + 1<BR>                        indexCount += 1</P>
<P>                        ' Second Face<BR>                        indices(indexCount) = wVertexIndex + (Slices)<BR>                        indexCount += 1</P>
<P>                        indices(indexCount) = wVertexIndex<BR>                        indexCount += 1</P>
<P>                        indices(indexCount) = wVertexIndex + (Slices + 1)<BR>                        indexCount += 1</P>
<P>                        wVertexIndex += 1<BR>                    End If<BR>                Next<BR>            Next</P>
<P>            Me.IndexCount = indexCount<BR>            Me.VertexCount = wVertexIndex</P>
<P>            Vertexbuffer = New VertexBuffer(Device, GetType(Vector3), numberVertices, BufferUsage.None)<BR>            Vertexbuffer.SetData(vertices, 0, vertices.Length)<BR>            IndexBuffer = New IndexBuffer(Device, GetType(Integer), numberIndices, BufferUsage.None)<BR>            IndexBuffer.SetData(indices, 0, indices.Length)<BR>            AtmosphereEffect = FromSpaceShader<BR>        End Sub<BR>
<BR><BR><BR>and the render code<BR><BR>
<BR> Public Sub Draw(ByVal gametime As GameTime)</P>
<P>            Device.VertexDeclaration = Declaration</P>
<P> </P>
<P>            Device.Vertices(0).SetSource(Vertexbuffer, 0, 12)<BR>            Device.Indices = IndexBuffer</P>
<P>            SetAtmosphereFromSPaceShaderVariables(gametime)<BR><BR>            If IsInAtmosphere Then<BR>                AtmosphereEffect.CurrentTechnique = AtmosphereEffect.Techniques("SkyFromAtmosphere")<BR>            Else<BR>                AtmosphereEffect.CurrentTechnique = AtmosphereEffect.Techniques("SkyFromSpace")<BR>            End If</P>
<P><BR>            AtmosphereEffect.Begin()</P>
<P>            For Each pass As EffectPass In AtmosphereEffect.CurrentTechnique.Passes<BR>                pass.Begin()</P>
<P>                Device.DrawIndexedPrimitives(PrimitiveType.TriangleStrip, 0, 0, VertexCount, 0, IndexCount)</P>
<P>                pass.End()<BR>            Next</P>
<P>            AtmosphereEffect.End()</P>
<P>            Device.RenderState.DepthBufferEnable = True<BR></P>
<P>        End Sub<BR>
<BR><BR>you can see the progress screenshots at budinga.blogspot.com. Help is always much apreciated. </P>



I was generating the sphere wrong, needed to get rid of the -1 in the loop and also use trianglelist instead of strip.

[Solved] Another Atmosphere from Space post

04 September 2010 - 02:50 AM

Well i have progressed slightly in my quest to create a planet renderer in MDX 1.1 and vb.net. I now have a planet no LOD yet well a cube morphed in to a sphere, and i can somewat heightmap it, i am now trying to get an atmosphere shader working,based on sponeil.net code in HL shader, it is based on an implementation i found on the forums. I start with a DXMesh sphere and pass the shader over it all i get is a white band, and the rest of it is black. Here is an image of what i get.


http://yfrog.com/evscreenshot492010143010j



http://yfrog.com/msscreenshot492010143016j


I am completely confused i have tryed everything all i get is that no matter what i do. My code i use is

'Atmosphere mesh generation code
    Private Sub GenerateAtmosphere()
     AtmosphereInnerRad = CType((Me.Radius / 100 * 25) + Me.Radius, Single)
     Atmospehere = Mesh.Sphere(dev, AtmosphereInnerRad, 256, 128)
             Dim elements As VertexElement() = New VertexElement() {New VertexElement(0, 0, DeclarationType.Short4, DeclarationMethod.Default, DeclarationUsage.Position, 0), VertexElement.VertexDeclarationEnd}
        AtmosphereDeclaration = New VertexDeclaration(dev, elements)
        Atmospehere = Atmospehere.Clone(MeshFlags.Managed, elements, dev)
    End Sub

shader setup code

    Private Sub SetSkyFromSpaceEffectParameters()

        Dim m_vLight As Vector3 = New Vector3(1000, 1000, 1000)
        Dim ld As Single = Vector3MathHelper.MagnitudeSingle(m_vLight)
        Dim m_vLightDirection As Vector3 = New Vector3(m_vLight.X / ld, m_vLight.Y / ld, m_vLight.Z / ld)

        Dim m_nSamples As Single = 2 ' Number of sample rays to use in integral equation
        Dim m_Kr As Single = 0.0025F       ' Rayleigh scattering constant
        Dim m_Kr4PI As Single = m_Kr * 4.0F * PI
        Dim m_Km As Single = 0.0015F       ' Mie scattering constant
        Dim m_Km4PI As Single = m_Km * 4.0F * PI
        Dim m_ESun As Single = 5.0F ' Sun brightness constant
        Dim m_g As Single = -0.95F         ' The Mie phase asymmetry factor

        'Dim SkyRad As Single = Me.Radius + Me.Radius / 4
        Dim m_fInnerRadius As Single = AtmosphereInnerRad
        Dim m_fOuterRadius As Single = AtmosphereInnerRad * 1.025F  '* 4 'AtmosphereInnerRad * 1.025F 
        Dim m_fScale As Single = 1 / (m_fOuterRadius - m_fInnerRadius)

        Dim m_fwavelength(2) As Single
        m_fwavelength(0) = 0.65F      ' 650 nm for red
        m_fwavelength(1) = 0.57F      ' 570 nm for green
        m_fwavelength(2) = 0.475F     ' 475 nm for blue

        Dim m_fWavelength4(2) As Single
        m_fWavelength4(0) = Pow(m_fwavelength(0), 4.0F) ''powf??
        m_fWavelength4(1) = Pow(m_fwavelength(1), 4.0F)
        m_fWavelength4(2) = Pow(m_fwavelength(2), 4.0F)


        Dim m_fRayleighScaleDepth As Single = 0.25F '0.25F
        Dim m_fMieScaleDepth As Single = 0.1F

        Dim m_fExposure As Single = 2.0F

        Dim CamPos() As Single = New Single() {Camera.CameraPosition.X, Camera.CameraPosition.Y, Camera.CameraPosition.Z}
        Dim LightPos() As Single = New Single() {m_vLightDirection.X, m_vLightDirection.Y, m_vLightDirection.Z}
        Dim Wavl() As Single = New Single() {1 / m_fWavelength4(0), 1 / m_fWavelength4(1), 1 / m_fWavelength4(2)}
        Dim CameraMag As Single = Vector3MathHelper.MagnitudeSingle(Camera.CameraPosition)
        Dim CameraMagSqr As Single = Vector3MathHelper.MagnitudeSquaredSingle(Camera.CameraPosition)

        AtmosphereEffect.SetValue("v3CameraPos", CamPos)
        AtmosphereEffect.SetValue("v3LightPos", LightPos) ' shader v1
        AtmosphereEffect.SetValue("v3InvWavelength", Wavl)
        AtmosphereEffect.SetValue("fCameraHeight", CameraMag)
        AtmosphereEffect.SetValue("fCameraHeight2", CameraMagSqr)
        AtmosphereEffect.SetValue("fInnerRadius", m_fInnerRadius)
        AtmosphereEffect.SetValue("fInnerRadius2", m_fInnerRadius * m_fInnerRadius)

        AtmosphereEffect.SetValue("fOuterRadius", m_fOuterRadius)
        AtmosphereEffect.SetValue("fOuterRadius2", m_fOuterRadius * m_fOuterRadius)
        AtmosphereEffect.SetValue("fKrESun", m_Kr * m_ESun) ' shader v1
        AtmosphereEffect.SetValue("fKmESun", m_Km * m_ESun) ' shader v1

        AtmosphereEffect.SetValue("fKr4PI", m_Kr4PI) 'shader v1
        AtmosphereEffect.SetValue("fKm4PI", m_Km4PI) 'shader v1
        AtmosphereEffect.SetValue("fScale", m_fScale) '1.0F / (m_fOuterRadius - m_fInnerRadius))'shader v1
        AtmosphereEffect.SetValue("fScaleDepth", m_fRayleighScaleDepth) 'shader v1

        AtmosphereEffect.SetValue("fScaleOverScaleDepth", (1.0F / (m_fOuterRadius - m_fInnerRadius)) / m_fRayleighScaleDepth)
        AtmosphereEffect.SetValue("g", m_g)
        AtmosphereEffect.SetValue("g2", m_g * m_g)
        AtmosphereEffect.SetValue("nSamples", m_nSamples) 'shader v1
        AtmosphereEffect.SetValue("fSamples", m_nSamples) 'shader v1
        'AtmosphereEffect.SetValue("numSamples", m_nSamples)
        'AtmosphereEffect.SetValue("samples", m_nSamples)

        AtmosphereEffect.SetValue("fExposure", m_fExposure)

        Dim World As Matrix = Matrix.Translation(New Vector3(0, 0, 0)) * Matrix.Scaling(1, 1, 1) 'Matrix.Scaling(AtmosphereInnerRad, AtmosphereInnerRad, AtmosphereInnerRad) '* Matrix.RotationX(Pitch)
        Dim WVP As Matrix = World * Camera.ViewProjectionMatrix 'dev.Transform.View * dev.Transform.Projection
        AtmosphereEffect.SetValue("WorldViewProjectionMatrix", WVP) ' shader v1

    End Sub

and finally my shader code

float4x4 WorldViewProjectionMatrix;

float3 v3CameraPos;    // The camera's current position
float3 v3LightPos;    // The direction vector to the light source
float3 v3InvWavelength;  // 1 / pow(wavelength, 4) for the red, green, and blue channels

float fCameraHeight;  // The camera's current height
float fCameraHeight2;  // fCameraHeight^2
float fOuterRadius;    // The outer (atmosphere) radius
float fOuterRadius2;  // fOuterRadius^2
float fInnerRadius;    // The inner (planetary) radius
float fInnerRadius2;  // fInnerRadius^2

float fKrESun;      // Kr * ESun
float fKmESun;      // Km * ESun
float fKr4PI;      // Kr * 4 * PI
float fKm4PI;      // Km * 4 * PI

float fScale;      // 1 / (fOuterRadius - fInnerRadius)
float fScaleDepth;    // The scale depth (i.e. the altitude at which the atmosphere's average density is found)
float fScaleOverScaleDepth;  // fScale / fScaleDepth

int nSamples;
float fSamples;

float g;
float g2;
float fExposure =2;

struct VertexShaderInput
{    
float4 Position : POSITION0;
};

struct VertexShaderOutput
{    
float4 Position : POSITION0;    
float4 RayleighColor : TEXCOORD0;    
float4 MieColor : TEXCOORD1;    
float3 Direction : TEXCOORD2;
};

float scale(float fCos)
{  
float x = 1.0 - fCos;  
return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{  
VertexShaderOutput output;   

 // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)  
float3 v3Pos = input.Position.xyz;  
float3 v3Ray = v3Pos - v3CameraPos;  
float fFar = length(v3Ray);  
v3Ray /= fFar;  

// Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)  
float B = 2.0 * dot(v3CameraPos, v3Ray);  
float C = fCameraHeight2 - fOuterRadius2;  
float fDet = max(0.0, B*B - 4.0 * C);  
float fNear = 0.5 * (-B - sqrt(fDet));  

// Calculate the ray's starting position, then calculate its scattering offset  
float3 v3Start = v3CameraPos + v3Ray * fNear;  fFar -= fNear;  
float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius;  
float fStartDepth = exp(-1.0 / fScaleDepth);  
float fStartOffset = fStartDepth*scale(fStartAngle);  

// Initialize the scattering loop variables  
float fSampleLength = fFar / fSamples; 
float fScaledLength = fSampleLength * fScale;  
float3 v3SampleRay = v3Ray * fSampleLength;  
float3 v3SamplePoint = v3Start + v3SampleRay * 0.5; 

// Now loop through the sample rays  
float3 v3FrontColor = float3(0.0, 0.0, 0.0);  
  
  for(int i=0; i<nSamples; i++)  
  {    
  float fHeight = length(v3SamplePoint);    
  float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));    
  float fLightAngle = dot(v3LightPos, v3SamplePoint) / fHeight;    
  float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;   
  float fScatter = (fStartOffset + fDepth*(scale(fLightAngle) - scale(fCameraAngle)));    
  float3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));   
  v3FrontColor += v3Attenuate * (fDepth * fScaledLength);    
  v3SamplePoint += v3SampleRay;  
  }  
  
  // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader  
  output.MieColor = float4(v3FrontColor * fKmESun, 1.0);  
  output.RayleighColor = float4(v3FrontColor * (v3InvWavelength * fKrESun), 1.0);  
  output.Position = mul(input.Position, WorldViewProjectionMatrix);  
  output.Direction = v3CameraPos - v3Pos;  
  return output;
  }
  
  float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
  {    
  float fCos = dot(v3LightPos, input.Direction) / length(input.Direction);    
  float fRayleighPhase = 0.75 * (1.0 + fCos*fCos);    
  float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);    
  float4 col=(fRayleighPhase * input.RayleighColor) + (fMiePhase * input.MieColor);   
  col.a=max(col.b,col.r);

  //return fRayleighPhase * input.RayleighColor + fMiePhase * input.MieColor;
  return 1 - exp(-fExposure * col);
  }
  
  technique SkyFromSpace
  {    
  pass Pass1    
  {        
  VertexShader = compile vs_2_0 VertexShaderFunction();        
  PixelShader = compile ps_2_0 PixelShaderFunction();    
  }
  } 

I know this can be really tricky to get working, but it is slowing down work on other things, all help is much apreciated.

[Edited by - Budinga on September 15, 2010 1:29:28 PM]

Mapping a Cube To A Sphere

04 July 2010 - 02:42 AM

Could somebody please explain a bit more on how this works, i have been looking at various proof especially this maths proof.

http://mathproofs.blogspot.com/2005/07/mapping-cube-to-sphere.html

What i dont really get it do i make a cube and then project it on to a sphere or am i drawing a sphere and map the heightmap using log and lat to the sphere.

Also them equations are a bit dificult to understand, im can program terrains etc, but i cant for the life of me get round them equations, well the best way to aproach this.

Also i have no idea how to aproach this with code all examples are in opengl, anything directx lurking around, or maybe im just to dumb to undertsand it.

Thanx in advance.


So far i have 6 Vertex buffers and 6 Index buffers all hold 1 face of a cube, which is a grid i can define the width and depth of the cube, in the class. Now i want to morph it so to speak in to a sphere, after i will atempt to add some sort of LOD, but for now gotta get this working.


so far i got this. different colors representing diferent faces, esentially there all just a simple brute force terrain, without the heightmap applyed.

Posted Image[/IMG]


[Edited by - Budinga on July 4, 2010 9:43:28 AM]

PARTNERS