Announcement

Collapse
No announcement yet.

Sun shader

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Sun shader

    Hi all,

    I've implemented a (very alpha) sun shader layer using GLSL shaders. It shows a reflection of the sun off the ocean using basic specular lighting calculations. It also shows the NASA night lights layer on the side of the earth with no sun.

    It uses a slightly modified RectangularTesselator class that calculates normals according to the globe surface (assumes it's a ellipsoid, doesn't calculate terrain normals).

    To use this layer you must have a video card that supports shaders. You must also set the tesselator class name using the code as follows (before the WorldWindow is set up):
    Code:
    Configuration.setValue(AVKey.TESSELLATOR_CLASS_NAME,
        NormalTessellator.class.getName());
    I've created a special tile set to support this layer. The layer won't work without it. It is quite simple: the oceans are blue, the landmass is green, and the nightlights are red (nightlights on landmass = green+red = yellow). The shader then takes these colours and makes it look lovely.

    This tile set was created from the freely available NASA blue marble and nightlight images. Obviously it is too big to upload as an attachment, but I've uploaded the first level (level 0) so people can test the layer. Simply extract it to your cache directory, or add the extracted directory to the data file cache using WorldWind.getDataFileCache().addCacheLoc ation().

    I hope people extend this!

    Kind regards,
    -Michael
    Attached Files

  • #2
    Hi Michael, this is really impressive and thank you for sharing your efforts, but i don't understand why the sun spot on the earth is moving when i move the view.
    This seems to me unrealistic but maybe i am wrong.
    -Nicolas CASTEL- Thales Alenia Space, Toulouse, France-

    Comment


    • #3
      Nice work Michael! I wish i had more time to play with the fun stuff.

      I'm a big fan of shading and i'm glad to see you are interested too. You are just inches from terrain shading.

      There is some commented out normal computation code in the tessellator that is a 'work in progress'. It is only intended to compute one tile normals, but there is another step needed to deal with the edges - where normals should account for the neighboring tiles too. The strategy is to use the skirts vertices to compute one extra row and column of terrain surface around the tile, compute the normals, and then 'fold down' the skirts around the sides. Care to try it?

      Nice stuff with the shaders too. I would suggest you factor out the shader code from the layer and create a Shader base class that would handle reading source code, compiling and applying. That would make it easier to use shaders in other parts of the rendering pass.

      And thanks for the sun calculator too
      My World Wind Java Blog & WW.net Plugins page

      Comment


      • #4
        Originally posted by vash View Post
        Hi Michael, this is really impressive and thank you for sharing your efforts, but i don't understand why the sun spot on the earth is moving when i move the view.
        This seems to me unrealistic but maybe i am wrong.
        It does seem weird at first, but remember that the whole of space is moving when you move the view. This includes the sun. The sun position is calculated according to the current time of day, and the lighted part of the globe is constant even when you move the globe around. The sun spot is using specular lighting calculations: a vector is calculated that is halfway between the sunPosition and the cameraVector for each vertex, and the dot product between that vector and the normal for the vertex is used to find out how much specular lighting is required at that vertex. This means that as the camera moves, so does the apparent 'reflection' of the sun on the globe.

        Originally posted by patmurris View Post
        There is some commented out normal computation code in the tessellator that is a 'work in progress'. It is only intended to compute one tile normals, but there is another step needed to deal with the edges - where normals should account for the neighboring tiles too. The strategy is to use the skirts vertices to compute one extra row and column of terrain surface around the tile, compute the normals, and then 'fold down' the skirts around the sides. Care to try it?
        I was almost there! Thanks for your suggestion, it worked well. I've rewritten the buildVerts() function to add an extra row and column around the tile, calculated the normals, and then fold the skirts down. I've also written my own getNormals() function which should be more optimal than the one commented out at the bottom of RectangularTesselator. See the attachment.

        Can you tell me the reason for the refCenter Vec4 in the original buildVerts()? I modified it to a zero vector and it worked fine; it just seems to complicate things?
        Attached Files

        Comment


        • #5
          Excellent! Can't wait to see some screenshots (i have little time to play with it unfortunately).

          The reference center we use in many parts of the SDK is actually an important step to ensure maximum accuracy on the globe surface. The reason is that actual GPUs are not using doubles but floats which precision decrease sharply as you go away from zero. As all units in WW are in meter, any point on the globe will have cartesian coordinates in the range of the Earth radius. Without a local reference center for each geometry tile, vertices will end up being drawn slightly off their expected position, which can introduce significant errors when you try to place objects a few meters apart. This also produces what is often described as 'view jitter' where the eye seems to move in steps rather then smoothly.

          Looking at your getNormals() code, i see you compute two normals for each vertice, based on the four surrounding vertices. I don't think this is good enough since some vertices are involved in up to six adjacent triangles with their own orientation and normals. That is why the commented out code works in two pass.
          My World Wind Java Blog & WW.net Plugins page

          Comment


          • #6
            Originally posted by patmurris View Post
            Looking at your getNormals() code, i see you compute two normals for each vertice, based on the four surrounding vertices. I don't think this is good enough since some vertices are involved in up to six adjacent triangles with their own orientation and normals. That is why the commented out code works in two pass.
            Ahh, now I realise why the code was like that. The reason I wrote my own was because the commented out code didn't calculate correct normals: it wasn't taking into account the difference between clockwise and anti-clockwise triangles, which caused vertical strips of alternating dark/light vertices. I've refactored it so it works. The normals are now calculated taking into account each face the vertex is involved in. See attached if interested
            Attached Files

            Comment


            • #7
              Thanks for fixing and cleaning up that piece of code.

              The next step would be to add a light vector to the tessellator, or more likely to the surface tile renderer. If null, lighting would be disabled (default) otherwise it would be used to setup light before rendering a tile.

              Good work Michael, i'll try to integrate this tessellator as an alternate option in 0.6 and see if it fits in - there has been some refactoring since 0.5.

              How does it look like? - any screenshot?
              My World Wind Java Blog & WW.net Plugins page

              Comment


              • #8
                I managed to 'merge' your updated tessellator with the current 0.6 one and it works well, although i've seen some artefacts in some places (there may be something wrong with normals at the edge of tiles or i may have introduced a bug while converting your code...). Here is the new RectangularNormalTessellator and a SunShading example app that sets the light direction relative to the current eye position.

                In the tessellator code, you will be interested in the beginLighting() and endLighting() methods.

                Attached Files
                Last edited by patmurris; 02-20-2009, 03:37 PM.
                My World Wind Java Blog & WW.net Plugins page

                Comment


                • #9
                  Nice work Pat and Omega, you just couldn't resist having some fun could you
                  Bull_[UK]

                  Comment


                  • #10
                    Well done Pat, thanks for merging it with 0.6, and thanks for the screenshot! It looks great.

                    Originally posted by patmurris View Post
                    ...although i've seen some artefacts in some places (there may be something wrong with normals at the edge of tiles or i may have introduced a bug while converting your code...).
                    I noticed this as well; could the artifacts be caused from drawing tiles at different levels? When two tiles of different levels are drawn next to each other, the normals will be slightly different at the edges, therefore the edges are visible. It's especially noticable when the GLSL shader lighting is used.

                    Comment


                    • #11
                      Tiles from different levels will not match well but there is nothing we can do about it IMO and it is not so bad - it also happens with textures. I was referring to a sharper artifact - like an obvious black strip in one place, but haven't seen it elsewhere so it may be a 'local' problem with elevation data... not sure really.

                      I've already spent too much time on this so will forget about it now. How about atmospheric scattering? There is working code in WW.net begging to be ported to Java...
                      My World Wind Java Blog & WW.net Plugins page

                      Comment


                      • #12
                        If you port that to WW Java please consider improving the gpu rendering, cpu looks great but gpu rendering was never polished.
                        Bull_[UK]

                        Comment


                        • #13
                          In World.cs there is an AtmosphericScatteringSphere class that contains an Updater() method which seems to set up a number of parameters for CPU vs GPU rendering. You will notice a few difference between the two, in particular, the number of samples is 4 for CPU and 2 for GPU.

                          Did you try to bump the GPU samples from 2 to 4?
                          My World Wind Java Blog & WW.net Plugins page

                          Comment


                          • #14
                            Hmm thanks Pat I'll give that a try, Chris may have set the GPU stuff lower for those horrid Intel GPU's
                            Bull_[UK]

                            Comment


                            • #15
                              I tryed changing some values in World.cs without much success, but I did find this thread on gamedev which may be interesting for you guys http://www.gamedev.net/community/for...25&WhichPage=1
                              Bull_[UK]

                              Comment

                              Working...
                              X