Hi,

Excuse me for my newbiness.  I'm still learning OSG.

I tried the following code by Jean-Sébastien, and it worked great.  Thank you!

I have two questions about it:

- The texture on the skybox gets magnified quite largely.  If I use
512x512 image as texture, my entire screen gets occupied by probably
200x150 portion of it.  As a result, the image gets stretched, and the
quality suffers.  It is like the camera is too close to the skybox.
Is there any way to change this (make the skybox far from the camera)?

- It seems that texture is shown upside-down.  At least I can tell
positive-y image is.  I believe I can fix this by rotating the jpeg
image, but is there a better (or more right) way of fixing this?

Any help shall be appreciated.

Thanks,

Nao

-- 

> I want to skybox for surround my terrain! How can I do ? Which way
> is the easiest? And is there any example?

I don't believe there is any example of this in OSG right now. This
has come up a few times recently on the list. Here is some code I
developed to create a skybox out of a vertical cross cubemap, like the
ones you can find on http://www.debevec.org/Probes/ . I hope it is
useful.

To use it:

   osg::Node* skybox = createSkyBoxCubeMap(filename);

Then put the returned node under your scene root. Optionally, you can
pass a stateset as second argument, which will be used on the cubemap,
and then you can change the cubemap image at run time. This was used
in my Masters project. But the default second argument of zero will
just create a stateset.

The filename must be a vertical cross cubemap. It can be in HDR format
or any other format that OSG supports. HDR images will be clamped (no
tone mapping is done).

One note: I have found that using the cubemaps on debevec.org, I had
to resize them down by 1 pixel (they are 1024x1365, resize it to
1023x1364) so that the dimensions are divisible by the number of
images in each direction (3 horizontally, 4 vertically). You can use
HDRShop (available at http://projects.ict.usc.edu/graphics/HDRShop/)
to resize HDR images. YMMV.

This could be modified to use 6 images, and would actually be much
simpler, as most of the code relates to extracting the 6 faces from
the vertical cross, and then rotating/mirroring them correctly so they
appear on the skybox in the correct orientation.

Hope this helps,

J-S
-- 
______________________________________________________
Jean-Sebastien Guay     jean-sebastien.guay at polymtl.ca
                         http://whitestar02.webhop.org/

----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.

-------------- next part --------------
//---------------------------------------------------------------------------
// (c) 2006-2008   Jean-Sébastien Guay
//
// This code will create a skybox in OpenSceneGraph. The core of it comes
// from Farshid Lashkari <flashk_at_gmail.com> - see
// http://openscenegraph.org/archiver/osg-users/2005-June/0581.html
//
// I added the functionality to be able to extract the six cube face
// textures from a vertical cross texture such as the ones on
// http://www.debevec.org/Probes/.
//
// This code is distributed in the hope it will be useful, but without
// any warranty whatsoever. You may use it in any project, as well as modify
// it without restriction, as long as this notice is retained in the
// relevant files.
//---------------------------------------------------------------------------

#ifndef __SKYBOX_H__
#define __SKYBOX_H__ 1

#include <string>
#include <osg/Node>

osg::Node* createSkyBoxCubeMap(const std::string& cubemap,
osg::StateSet* stateset = 0);

#endif
-------------- next part --------------
//---------------------------------------------------------------------------
// (c) 2006-2008   Jean-Sébastien Guay
// This code is distributed in the hope it will be useful, but without
// any warranty whatsoever. You may use it in any project, as well as modify
// it without restriction, as long as this notice is retained in the
// relevant files.
//---------------------------------------------------------------------------

#include "Skybox.h"

#include <iostream>
#include <cassert>

#include <osg/Geometry>
#include <osg/Depth>
#include <osg/TextureCubeMap>
#include <osg/TexEnv>
#include <osgDB/ReadFile>
#include <osgUtil/CullVisitor>

#include "osgUtil.h"

class SkyboxTransform : public osg::Transform
{
    public:
        // Get the transformation matrix which moves from local coords
to world coords.
        virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
            osg::NodeVisitor* nv) const
        {
            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
            if (cv)
            {
                osg::Vec3 eyePointLocal = cv->getEyeLocal();
                matrix.preMult(osg::Matrix::translate(eyePointLocal));
            }

            return true;
        }

        // Get the transformation matrix which moves from world coords
to local coords.
        virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
            osg::NodeVisitor* nv) const
        {
            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
            if (cv)
            {
                osg::Vec3 eyePointLocal = cv->getEyeLocal();
                matrix.postMult(osg::Matrix::translate(-eyePointLocal));
            }

            return true;
        }
};

osg::Node* createSkyBoxCubeMap(const std::string& cubemap,
osg::StateSet* stateset)
{
    float radius = 100.0f;

    if (!stateset)
        stateset = new osg::StateSet;

    // Set texture mode to REPLACE
    osg::TexEnv* te = new osg::TexEnv;
    te->setMode(osg::TexEnv::REPLACE);
    stateset->setTextureAttributeAndModes(0, te, osg::StateAttribute::ON);

    // Turn off lighting and cull face
    stateset->setMode(GL_LIGHTING,  osg::StateAttribute::OFF);
    stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);

    // Basic principle of skyboxes: render it last, and with a depth func
    // that only sets pixels at the far plane. That way, if the sky is not
    // visible at all for example, the sky won't be drawn (and possibly
    // fragment shaders will not be called) whereas rendering it first will
    // cause all pixels to be written, then overwritten by objects, and
    // possibly fragment shaders will have been called for nothing.

    // Clear the depth to the far plane.
    osg::Depth* depth = new osg::Depth(osg::Depth::LEQUAL, 1.0, 1.0);
    stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);

    // Make sure it is drawn last
    stateset->setRenderBinDetails(1000, "RenderBin");

    // Create a drawable for the skybox
    osg::Geometry* drawable = new osg::Geometry;


    // Create vertices for box
    osg::Vec3Array *verts = new osg::Vec3Array;
    verts->push_back(osg::Vec3(-radius, -radius,  radius));
    verts->push_back(osg::Vec3(-radius,  radius,  radius));
    verts->push_back(osg::Vec3( radius,  radius,  radius));
    verts->push_back(osg::Vec3( radius, -radius,  radius));
    verts->push_back(osg::Vec3(-radius, -radius, -radius));
    verts->push_back(osg::Vec3(-radius,  radius, -radius));
    verts->push_back(osg::Vec3( radius,  radius, -radius));
    verts->push_back(osg::Vec3( radius, -radius, -radius));
    drawable->setVertexArray(verts);

    // Create texture coordinates for cubemaps
    osg::Vec3Array *coords = new osg::Vec3Array;
    coords->push_back(osg::Vec3(-1,  1, -1));
    coords->push_back(osg::Vec3(-1, -1, -1));
    coords->push_back(osg::Vec3( 1, -1, -1));
    coords->push_back(osg::Vec3( 1,  1, -1));
    coords->push_back(osg::Vec3(-1,  1,  1));
    coords->push_back(osg::Vec3(-1, -1,  1));
    coords->push_back(osg::Vec3( 1, -1,  1));
    coords->push_back(osg::Vec3( 1,  1,  1));

    drawable->setTexCoordArray(0,coords);

    // Create an index array for the box
    osg::ref_ptr<osg::UIntArray> indices = new osg::UIntArray;

    // Front face
    indices->push_back(0);
    indices->push_back(1);
    indices->push_back(2);
    indices->push_back(3);

    // Back face
    indices->push_back(4);
    indices->push_back(5);
    indices->push_back(6);
    indices->push_back(7);

    // Right face
    indices->push_back(6);
    indices->push_back(7);
    indices->push_back(3);
    indices->push_back(2);

    // Left face
    indices->push_back(0);
    indices->push_back(1);
    indices->push_back(5);
    indices->push_back(4);

    // Top face
    indices->push_back(1);
    indices->push_back(2);
    indices->push_back(6);
    indices->push_back(5);

    // Bottom face
    indices->push_back(0);
    indices->push_back(3);
    indices->push_back(7);
    indices->push_back(4);

    drawable->addPrimitiveSet(
        new osg::DrawElementsUInt(GL_QUADS,
            indices->size(), &(indices->front())));


    // Create a geode for the skybox
    osg::Geode* geode = new osg::Geode;
    geode->setName("Skybox");

    // Disable culling
    geode->setCullingActive(false);

    // Set the stateset
    geode->setStateSet(stateset);

    // Add the skybox
    geode->addDrawable(drawable);


    // Load the texture
    osg::ref_ptr<osg::TextureCubeMap> texture =
loadVerticalCrossCubeMap(cubemap);
    if (texture.valid())
    {
        texture->setResizeNonPowerOfTwoHint(false);
        texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
        texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
        stateset->setTextureAttributeAndModes(0, texture.get(),
osg::StateAttribute::ON);
    }

    // Create a transform and set it to absolute so it does not influence
    // the viewer's bounds computation (for initial camera settings).
    osg::Transform* transform = new SkyboxTransform;
    transform->setCullingActive(false);
    transform->addChild(geode);
    transform->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    transform->setName("SkyboxTransform");

    return transform;
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to