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

