The skyFactory now supports Equirectangular environment maps, as it's a pretty popular format.

It has been refactored to handle the 3 env map types : CubeMap, SphereMap, EquirectMap
experimental
Nehon 10 years ago
parent 9f459af4e3
commit 05baf56130
  1. 194
      jme3-core/src/main/java/com/jme3/util/SkyFactory.java
  2. 2
      jme3-core/src/main/resources/Common/MatDefs/Misc/Sky.j3md
  3. 17
      jme3-core/src/main/resources/Common/ShaderLib/Optics.glsllib

@ -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
* <a href="http://en.wikipedia.org/wiki/Sphere_mapping">sphere
* mapping</a>.
*/
SphereMap,
/**
* The env map is an Equirectangular map. A 2D textures with pixels
* arranged for <a href="http://en.wikipedia.org/wiki/Equirectangular_projection">equirectangular
* projection mapping.</a>.
*
*/
EquirectMap
}
/**
* Create a sky with radius=10 using the given cubemap or spheremap texture.
*
@ -77,12 +103,33 @@ public class SkyFactory {
* </ul>
* @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);
@ -137,6 +212,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:<br>
* <ul>
* <li>true: The texture is a Texture2D with the pixels arranged for
* <a href="http://en.wikipedia.org/wiki/Sphere_mapping">sphere
* mapping</a>.</li>
* <li>false: The texture is either a TextureCubeMap or Texture2D. If it is
* a Texture2D then the image is taken from it and is inserted into a
* TextureCubeMap</li>
* </ul>
* @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:<br>
* <ul>
* <li>true: The texture is a Texture2D with the pixels arranged for
* <a href="http://en.wikipedia.org/wiki/Sphere_mapping">sphere
* mapping</a>.</li>
* <li>false: The texture is either a TextureCubeMap or Texture2D. If it is
* a Texture2D then the image is taken from it and is inserted into a
* TextureCubeMap</li>
* </ul>
* @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)
// throw new IllegalArgumentException("3D/Array images not allowed");
@ -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);
}
}

@ -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 {

@ -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
}
Loading…
Cancel
Save