diff --git a/jme3-core/src/main/java/com/jme3/util/SkyFactory.java b/jme3-core/src/main/java/com/jme3/util/SkyFactory.java index 7fb70e76f..6104141aa 100644 --- a/jme3-core/src/main/java/com/jme3/util/SkyFactory.java +++ b/jme3-core/src/main/java/com/jme3/util/SkyFactory.java @@ -55,6 +55,32 @@ import java.util.ArrayList; */ public class SkyFactory { + + /** + * The type of map fed to the shader + */ + public enum EnvMapType{ + /** + * The env map is a cube map see {@link TextureCubeMap} or 6 separate images that form a cube map + * The texture is either a {@link TextureCubeMap} or 6 {@link Texture2D}. + * In the latter case, a TextureCubeMap is build from the 6 2d maps. + */ + CubeMap, + /** + * The env map is a Sphere map. The texture is a Texture2D with the pixels arranged for + * sphere + * mapping. + */ + SphereMap, + /** + * The env map is an Equirectangular map. A 2D textures with pixels + * arranged for equirectangular + * projection mapping.. + * + */ + EquirectMap + } + /** * Create a sky with radius=10 using the given cubemap or spheremap texture. * @@ -77,12 +103,33 @@ public class SkyFactory { * * @return a new spatial representing the sky, ready to be attached to the * scene graph + * @deprecated use {@link SkyFactory#createSky(com.jme3.asset.AssetManager, com.jme3.texture.Texture, com.jme3.math.Vector3f, com.jme3.util.SkyFactory.EnvMapType)} */ + @Deprecated public static Spatial createSky(AssetManager assetManager, Texture texture, Vector3f normalScale, boolean sphereMap) { return createSky(assetManager, texture, normalScale, sphereMap, 10); } + /** + * Create a sky with radius=10 using the given cubemap or spheremap texture. + * + * For the sky to be visible, its radius must fall between the near and far + * planes of the camera's frustrum. + * + * @param assetManager from which to load materials + * @param texture to use + * @param normalScale The normal scale is multiplied by the 3D normal to get + * a texture coordinate. Use Vector3f.UNIT_XYZ to not apply and + * transformation to the normal. + * @param envMapType see {@link EnvMapType} + * @return a new spatial representing the sky, ready to be attached to the + * scene graph + */ + public static Spatial createSky(AssetManager assetManager, Texture texture, + Vector3f normalScale, EnvMapType envMapType) { + return createSky(assetManager, texture, normalScale, envMapType, 10); + } /** * Create a sky using the given cubemap or spheremap texture. * @@ -105,9 +152,31 @@ public class SkyFactory { * frustrum * @return a new spatial representing the sky, ready to be attached to the * scene graph + * @deprecated use {@link SkyFactory#createSky(com.jme3.asset.AssetManager, com.jme3.texture.Texture, com.jme3.math.Vector3f, com.jme3.util.SkyFactory.EnvMapType, int)} */ + @Deprecated public static Spatial createSky(AssetManager assetManager, Texture texture, Vector3f normalScale, boolean sphereMap, int sphereRadius) { + return createSky(assetManager, texture, normalScale, sphereMap?EnvMapType.SphereMap:EnvMapType.CubeMap, sphereRadius); + } + + /** + * Create a sky using the given cubemap or spheremap texture. + * + * @param assetManager from which to load materials + * @param texture to use + * @param normalScale The normal scale is multiplied by the 3D normal to get + * a texture coordinate. Use Vector3f.UNIT_XYZ to not apply and + * transformation to the normal. + * @param envMapType see {@link EnvMapType} + * @param sphereRadius the sky sphere's radius: for the sky to be visible, + * its radius must fall between the near and far planes of the camera's + * frustrum + * @return a new spatial representing the sky, ready to be attached to the + * scene graph + */ + public static Spatial createSky(AssetManager assetManager, Texture texture, + Vector3f normalScale, EnvMapType envMapType, int sphereRadius) { if (texture == null) { throw new IllegalArgumentException("texture cannot be null"); } @@ -121,13 +190,19 @@ public class SkyFactory { Material skyMat = new Material(assetManager, "Common/MatDefs/Misc/Sky.j3md"); skyMat.setVector3("NormalScale", normalScale); - if (sphereMap) { - skyMat.setBoolean("SphereMap", sphereMap); - } else if (!(texture instanceof TextureCubeMap)) { - // make sure its a cubemap - Image img = texture.getImage(); - texture = new TextureCubeMap(); - texture.setImage(img); + switch (envMapType){ + case CubeMap : + // make sure its a cubemap + Image img = texture.getImage(); + texture = new TextureCubeMap(); + texture.setImage(img); + break; + case SphereMap : + skyMat.setBoolean("SphereMap", true); + break; + case EquirectMap : + skyMat.setBoolean("EquirectMap", true); + break; } texture.setMagFilter(Texture.MagFilter.Bilinear); texture.setMinFilter(Texture.MinFilter.BilinearNoMipMaps); @@ -136,6 +211,84 @@ public class SkyFactory { return sky; } + + /** + * Create a sky using the given cubemap or spheremap texture. + * + * @param assetManager from which to load materials + * @param texture to use * + * @param sphereMap determines how the texture is used:
+ * + * @return a new spatial representing the sky, ready to be attached to the + * scene graph + * @deprecated use {@link SkyFactory#createSky(com.jme3.asset.AssetManager, com.jme3.texture.Texture, com.jme3.math.Vector3f, com.jme3.util.SkyFactory.EnvMapType)} + */ + @Deprecated + public static Spatial createSky(AssetManager assetManager, Texture texture, boolean sphereMap) { + return createSky(assetManager, texture, Vector3f.UNIT_XYZ, sphereMap?EnvMapType.SphereMap:EnvMapType.CubeMap); + } + + /** + * Create a sky using the given cubemap or spheremap texture. + * + * @param assetManager from which to load materials + * @param textureName the path to the texture asset to use + * @param sphereMap determines how the texture is used:
+ * + * @return a new spatial representing the sky, ready to be attached to the + * scene graph + * @deprecated use {@link SkyFactory#createSky(com.jme3.asset.AssetManager, java.lang.String, com.jme3.math.Vector3f, com.jme3.util.SkyFactory.EnvMapType)} + */ + @Deprecated + public static Spatial createSky(AssetManager assetManager, String textureName, boolean sphereMap) { + return createSky(assetManager, textureName, sphereMap?EnvMapType.SphereMap:EnvMapType.CubeMap); + } + + /** + * Create a sky using the given cubemap or spheremap texture. + * + * @param assetManager from which to load materials + * @param texture to use + * @param envMapType see {@link EnvMapType} + * @return a new spatial representing the sky, ready to be attached to the + * scene graph + */ + public static Spatial createSky(AssetManager assetManager, Texture texture, EnvMapType envMapType) { + return createSky(assetManager, texture, Vector3f.UNIT_XYZ, envMapType); + } + + /** + * Create a sky using the given cubemap or spheremap texture. + * + * @param assetManager from which to load materials + * @param textureName the path to the texture asset to use + * @param envMapType see {@link EnvMapType} + * @return a new spatial representing the sky, ready to be attached to the + * scene graph + */ + public static Spatial createSky(AssetManager assetManager, String textureName, EnvMapType envMapType) { + TextureKey key = new TextureKey(textureName, true); + key.setGenerateMips(false); + if (envMapType == EnvMapType.CubeMap) { + key.setTextureTypeHint(Texture.Type.CubeMap); + } + Texture tex = assetManager.loadTexture(key); + return createSky(assetManager, tex, envMapType); + } private static void checkImage(Image image) { // if (image.getDepth() != 1) @@ -282,21 +435,20 @@ public class SkyFactory { return sky; } + /** + * Create a cube-mapped sky using six textures. + * + * @param assetManager from which to load materials + * @param west texture for the western face of the cube + * @param east texture for the eastern face of the cube + * @param north texture for the northern face of the cube + * @param south texture for the southern face of the cube + * @param up texture for the top face of the cube + * @param down texture for the bottom face of the cube * + * @return a new spatial representing the sky, ready to be attached to the + * scene graph + */ public static Spatial createSky(AssetManager assetManager, Texture west, Texture east, Texture north, Texture south, Texture up, Texture down) { return createSky(assetManager, west, east, north, south, up, down, Vector3f.UNIT_XYZ); } - - public static Spatial createSky(AssetManager assetManager, Texture texture, boolean sphereMap) { - return createSky(assetManager, texture, Vector3f.UNIT_XYZ, sphereMap); - } - - public static Spatial createSky(AssetManager assetManager, String textureName, boolean sphereMap) { - TextureKey key = new TextureKey(textureName, true); - key.setGenerateMips(false); - if (!sphereMap) { - key.setTextureTypeHint(Texture.Type.CubeMap); - } - Texture tex = assetManager.loadTexture(key); - return createSky(assetManager, tex, sphereMap); - } } diff --git a/jme3-core/src/main/resources/Common/MatDefs/Misc/Sky.j3md b/jme3-core/src/main/resources/Common/MatDefs/Misc/Sky.j3md index 515777428..2e2aa4f8f 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Misc/Sky.j3md +++ b/jme3-core/src/main/resources/Common/MatDefs/Misc/Sky.j3md @@ -2,6 +2,7 @@ MaterialDef Sky Plane { MaterialParameters { TextureCubeMap Texture Boolean SphereMap + Boolean EquirectMap Vector3 NormalScale } Technique { @@ -20,6 +21,7 @@ MaterialDef Sky Plane { Defines { SPHERE_MAP : SphereMap + EQUIRECT_MAP : EquirectMap } } Technique { diff --git a/jme3-core/src/main/resources/Common/ShaderLib/Optics.glsllib b/jme3-core/src/main/resources/Common/ShaderLib/Optics.glsllib index 5f762434f..546d7a1af 100644 --- a/jme3-core/src/main/resources/Common/ShaderLib/Optics.glsllib +++ b/jme3-core/src/main/resources/Common/ShaderLib/Optics.glsllib @@ -1,4 +1,4 @@ -#ifdef SPHERE_MAP +#if defined(SPHERE_MAP) || defined(EQUIRECT_MAP) #define ENVMAP sampler2D #define TEXENV texture2D #else @@ -23,10 +23,23 @@ vec2 Optics_SphereCoord(in vec3 dir){ return (dir.xy * vec2(inv_two_p)) + vec2(0.5); } +#define PI 3.141592653589793 +//const vec2 rads = vec2(1.0 / (PI * 2.0), 1.0 / PI); +const vec2 rads = vec2(0.159154943091895, 0.318309886183790); +vec2 Optics_LonLatCoords(in ENVMAP envMap, in vec3 dir){ + float lon = atan(dir.z, dir.x)+ PI; + float lat = acos(dir.y); + return vec2(lon, lat) * rads; +} + vec4 Optics_GetEnvColor(in ENVMAP envMap, in vec3 dir){ #ifdef SPHERE_MAP return texture2D(envMap, Optics_SphereCoord(dir)); #else - return textureCube(envMap, dir); + #ifdef EQUIRECT_MAP + return texture2D(envMap, Optics_LonLatCoords(envMap,dir)); + #else + return textureCube(envMap, dir); + #endif #endif -} \ No newline at end of file +}