Android: added support for cube maps, Sky works now, use AndroidSkyFactory
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7531 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
4fa5522c8e
commit
e5478faae0
@ -1708,50 +1708,59 @@ public class OGLESShaderRenderer implements Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
private void setupTextureParams(Texture tex){
|
||||
/**
|
||||
* <code>setupTextureParams</code> sets the OpenGL context texture parameters
|
||||
* @param tex the Texture to set the texture parameters from
|
||||
*/
|
||||
private void setupTextureParams(Texture tex)
|
||||
{
|
||||
int target = convertTextureType(tex.getType());
|
||||
|
||||
// filter things
|
||||
int minFilter = convertMinFilter(tex.getMinFilter());
|
||||
int magFilter = convertMagFilter(tex.getMagFilter());
|
||||
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_MIN_FILTER, " + minFilter + ")");
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_MIN_FILTER, " + minFilter + ")");
|
||||
|
||||
GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_MIN_FILTER, minFilter);
|
||||
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_MAG_FILTER, " + magFilter + ")");
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_MAG_FILTER, " + magFilter + ")");
|
||||
|
||||
GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_MAG_FILTER, magFilter);
|
||||
|
||||
/*
|
||||
if (tex.getAnisotropicFilter() > 1){
|
||||
/*
|
||||
|
||||
if (GLContext.getCapabilities().GL_EXT_texture_filter_anisotropic){
|
||||
glTexParameterf(target,
|
||||
EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
tex.getAnisotropicFilter());
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
*/
|
||||
// repeat modes
|
||||
|
||||
switch (tex.getType()){
|
||||
case ThreeDimensional:
|
||||
case CubeMap: // cubemaps use 3D coords
|
||||
// GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
|
||||
// GL_TEXTURE_WRAP_R is not available in api 8
|
||||
//GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
|
||||
case TwoDimensional:
|
||||
case TwoDimensionalArray:
|
||||
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_WRAP_T, " + convertWrapMode(tex.getWrap(WrapAxis.T)));
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_WRAP_T, " + convertWrapMode(tex.getWrap(WrapAxis.T)));
|
||||
|
||||
GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T)));
|
||||
|
||||
// fall down here is intentional..
|
||||
// case OneDimensional:
|
||||
// case OneDimensional:
|
||||
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_WRAP_S, " + convertWrapMode(tex.getWrap(WrapAxis.S)));
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_WRAP_S, " + convertWrapMode(tex.getWrap(WrapAxis.S)));
|
||||
|
||||
GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S)));
|
||||
break;
|
||||
@ -1773,13 +1782,20 @@ public class OGLESShaderRenderer implements Renderer {
|
||||
*/
|
||||
}
|
||||
|
||||
public void updateTexImageData(Image img, Texture.Type type, boolean mips){
|
||||
/**
|
||||
* <code>updateTexImageData</code> activates and binds the texture
|
||||
* @param img
|
||||
* @param type
|
||||
* @param mips
|
||||
*/
|
||||
public void updateTexImageData(Image img, Texture.Type type, boolean mips)
|
||||
{
|
||||
int texId = img.getId();
|
||||
if (texId == -1){
|
||||
if (texId == -1)
|
||||
{
|
||||
// create texture
|
||||
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glGenTexture(1, buffer)");
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glGenTexture(1, buffer)");
|
||||
|
||||
GLES20.glGenTextures(1, intBuf1);
|
||||
texId = intBuf1.get(0);
|
||||
@ -1791,72 +1807,56 @@ public class OGLESShaderRenderer implements Renderer {
|
||||
|
||||
// bind texture
|
||||
int target = convertTextureType(type);
|
||||
if (context.boundTextures[0] != img){
|
||||
if (context.boundTextureUnit != 0){
|
||||
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glActiveTexture(GLES20.GL_TEXTURE0)");
|
||||
if (context.boundTextures[0] != img)
|
||||
{
|
||||
if (context.boundTextureUnit != 0)
|
||||
{
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glActiveTexture(GLES20.GL_TEXTURE0)");
|
||||
|
||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
||||
context.boundTextureUnit = 0;
|
||||
}
|
||||
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glBindTexture(" + target + ", " + texId + ")");
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glBindTexture(" + target + ", " + texId + ")");
|
||||
|
||||
GLES20.glBindTexture(target, texId);
|
||||
context.boundTextures[0] = img;
|
||||
}
|
||||
|
||||
if (!img.hasMipmaps() && mips){
|
||||
// No pregenerated mips available,
|
||||
// generate from base level if required
|
||||
// if (!GLContext.getCapabilities().GL_EXT_framebuffer_multisample){
|
||||
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + "GLES11.GL_GENERATE_MIMAP, GLES20.GL_TRUE)");
|
||||
|
||||
GLES20.glTexParameteri(target, GLES11.GL_GENERATE_MIPMAP, GLES20.GL_TRUE);
|
||||
// }
|
||||
}else{
|
||||
// glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0 );
|
||||
if (img.getMipMapSizes() != null){
|
||||
// GLES20.glTexParameteri(target, GLES11.GL_TEXTURE_MAX_LEVEL, img.getMipMapSizes().length );
|
||||
if (target == GLES20.GL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
// Upload a cube map / sky box
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Bitmap> bmps = (List<Bitmap>)img.getEfficentData();
|
||||
if (bmps.size() != 6)
|
||||
{
|
||||
throw new UnsupportedOperationException("Invalid texture: " + img +
|
||||
"Cubemap textures must contain 6 data units." );
|
||||
}
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
TextureUtil.uploadTextureBitmap(GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, bmps.get(i), false, powerOf2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureUtil.uploadTexture(img, target, 0, 0, tdc, false, powerOf2);
|
||||
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + "GLES11.GL_GENERATE_MIMAP, GLES20.GL_TRUE)");
|
||||
|
||||
if (target == GLES20.GL_TEXTURE_CUBE_MAP){
|
||||
List<ByteBuffer> data = img.getData();
|
||||
if (data.size() != 6){
|
||||
logger.log(Level.WARNING, "Invalid texture: {0}\n"
|
||||
+ "Cubemap textures must contain 6 data units.", img);
|
||||
return;
|
||||
if (!img.hasMipmaps() && mips)
|
||||
{
|
||||
// No pregenerated mips available,
|
||||
// generate from base level if required
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D)");
|
||||
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
|
||||
}
|
||||
for (int i = 0; i < 6; i++){
|
||||
TextureUtil.uploadTexture(img, GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc, true, powerOf2);
|
||||
}
|
||||
}/*else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT){
|
||||
List<ByteBuffer> data = img.getData();
|
||||
// -1 index specifies prepare data for 2D Array
|
||||
TextureUtil.uploadTexture(img, target, -1, 0, tdc);
|
||||
for (int i = 0; i < data.size(); i++){
|
||||
// upload each slice of 2D array in turn
|
||||
// this time with the appropriate index
|
||||
TextureUtil.uploadTexture(img, target, i, 0, tdc);
|
||||
}
|
||||
}*/else{
|
||||
TextureUtil.uploadTexture(img, target, 0, 0, tdc, true, powerOf2);
|
||||
|
||||
if (verboseLogging)
|
||||
logger.info("GLES20.glTexParameteri(" + target + "GLES11.GL_GENERATE_MIMAP, GLES20.GL_TRUE)");
|
||||
|
||||
GLES20.glTexParameteri(target, GLES11.GL_GENERATE_MIPMAP, GLES20.GL_TRUE);
|
||||
}
|
||||
|
||||
// if (GLContext.getCapabilities().GL_EXT_framebuffer_multisample){
|
||||
// glGenerateMipmapEXT(target);
|
||||
// }
|
||||
}
|
||||
|
||||
img.clearUpdateNeeded();
|
||||
}
|
||||
@ -1866,14 +1866,19 @@ public class OGLESShaderRenderer implements Renderer {
|
||||
Image image = tex.getImage();
|
||||
if (image.isUpdateNeeded())
|
||||
{
|
||||
/*
|
||||
Bitmap bmp = (Bitmap)image.getEfficentData();
|
||||
// Check if the bitmap got recycled, can happen after wakeup/restart
|
||||
if ( bmp.isRecycled() )
|
||||
if (bmp != null)
|
||||
{
|
||||
// We need to reload the bitmap
|
||||
Texture textureReloaded = JmeSystem.newAssetManager().loadTexture((TextureKey)tex.getKey());
|
||||
image.setEfficentData( textureReloaded.getImage().getEfficentData());
|
||||
// Check if the bitmap got recycled, can happen after wakeup/restart
|
||||
if ( bmp.isRecycled() )
|
||||
{
|
||||
// We need to reload the bitmap
|
||||
Texture textureReloaded = JmeSystem.newAssetManager().loadTexture((TextureKey)tex.getKey());
|
||||
image.setEfficentData( textureReloaded.getImage().getEfficentData());
|
||||
}
|
||||
}
|
||||
*/
|
||||
updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels());
|
||||
}
|
||||
|
||||
|
@ -62,11 +62,21 @@ public class TextureUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static void uploadTextureBitmap(Bitmap bitmap, boolean generateMips, boolean powerOf2){
|
||||
if (!powerOf2){
|
||||
/**
|
||||
* <code>uploadTextureBitmap</code> uploads a native android bitmap
|
||||
* @param target
|
||||
* @param bitmap
|
||||
* @param generateMips
|
||||
* @param powerOf2
|
||||
*/
|
||||
public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean generateMips, boolean powerOf2)
|
||||
{
|
||||
if (!powerOf2)
|
||||
{
|
||||
int width = bitmap.getWidth();
|
||||
int height = bitmap.getHeight();
|
||||
if (!FastMath.isPowerOfTwo(width) || !FastMath.isPowerOfTwo(height)){
|
||||
if (!FastMath.isPowerOfTwo(width) || !FastMath.isPowerOfTwo(height))
|
||||
{
|
||||
// scale to power of two
|
||||
width = FastMath.nearestPowerOfTwo(width);
|
||||
height = FastMath.nearestPowerOfTwo(height);
|
||||
@ -76,11 +86,14 @@ public class TextureUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (generateMips){
|
||||
if (generateMips)
|
||||
{
|
||||
buildMipmap(bitmap);
|
||||
}else{
|
||||
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
|
||||
bitmap.recycle();
|
||||
}
|
||||
else
|
||||
{
|
||||
GLUtils.texImage2D(target, 0, bitmap, 0);
|
||||
//bitmap.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,8 +108,7 @@ public class TextureUtil {
|
||||
|
||||
if (img.getEfficentData() instanceof Bitmap){
|
||||
Bitmap bitmap = (Bitmap) img.getEfficentData();
|
||||
uploadTextureBitmap(bitmap, generateMips, powerOf2);
|
||||
// img.setEfficentData(null);
|
||||
uploadTextureBitmap(target, bitmap, generateMips, powerOf2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
148
engine/src/android/com/jme3/util/android/AndroidSkyFactory.java
Normal file
148
engine/src/android/com/jme3/util/android/AndroidSkyFactory.java
Normal file
@ -0,0 +1,148 @@
|
||||
package com.jme3.util.android;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import com.jme3.asset.AssetManager;
|
||||
import com.jme3.asset.TextureKey;
|
||||
import com.jme3.material.Material;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.queue.RenderQueue.Bucket;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.shape.Sphere;
|
||||
import com.jme3.texture.Image;
|
||||
import com.jme3.texture.Image.Format;
|
||||
import com.jme3.texture.Texture;
|
||||
import com.jme3.texture.TextureCubeMap;
|
||||
|
||||
|
||||
/**
|
||||
* <code>AndroidSkyFactory</code> creates a sky box spatial
|
||||
* @author larynx, derived from SkyFactory and adapted for android
|
||||
*
|
||||
*/
|
||||
public class AndroidSkyFactory
|
||||
{
|
||||
private static final Sphere sphereMesh = new Sphere(10, 10, 101f, false, true);
|
||||
|
||||
public static Spatial createSky(AssetManager assetManager, Texture texture, Vector3f normalScale, boolean sphereMap)
|
||||
{
|
||||
Geometry sky = new Geometry("Sky", sphereMesh);
|
||||
sky.setQueueBucket(Bucket.Sky);
|
||||
sky.setCullHint(Spatial.CullHint.Never);
|
||||
|
||||
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);
|
||||
}
|
||||
skyMat.setTexture("Texture", texture);
|
||||
sky.setMaterial(skyMat);
|
||||
|
||||
return sky;
|
||||
}
|
||||
|
||||
private static void checkImage(Image image)
|
||||
{
|
||||
if (image.getWidth() != image.getHeight())
|
||||
throw new IllegalArgumentException("Image width and height must be the same");
|
||||
|
||||
if (image.getMultiSamples() != 1)
|
||||
throw new IllegalArgumentException("Multisample textures not allowed");
|
||||
}
|
||||
|
||||
private static void checkImagesForCubeMap(Image ... images)
|
||||
{
|
||||
if (images.length == 1) return;
|
||||
|
||||
Format fmt = images[0].getFormat();
|
||||
int width = images[0].getWidth();
|
||||
int height = images[0].getHeight();
|
||||
|
||||
checkImage(images[0]);
|
||||
|
||||
for (int i = 1; i < images.length; i++)
|
||||
{
|
||||
Image image = images[i];
|
||||
checkImage(images[i]);
|
||||
if (image.getFormat() != fmt) throw new IllegalArgumentException("Images must have same format");
|
||||
if (image.getWidth() != width) throw new IllegalArgumentException("Images must have same width");
|
||||
if (image.getHeight() != height) throw new IllegalArgumentException("Images must have same height");
|
||||
}
|
||||
}
|
||||
|
||||
public static Spatial createSky(AssetManager assetManager, Texture west, Texture east, Texture north, Texture south,
|
||||
Texture up, Texture down, Vector3f normalScale)
|
||||
{
|
||||
Geometry sky = new Geometry("Sky", sphereMesh);
|
||||
sky.setQueueBucket(Bucket.Sky);
|
||||
sky.setCullHint(Spatial.CullHint.Never);
|
||||
|
||||
Image westImg = west.getImage();
|
||||
Image eastImg = east.getImage();
|
||||
Image northImg = north.getImage();
|
||||
Image southImg = south.getImage();
|
||||
Image upImg = up.getImage();
|
||||
Image downImg = down.getImage();
|
||||
|
||||
checkImagesForCubeMap(westImg, eastImg, northImg, southImg, upImg, downImg);
|
||||
|
||||
Image cubeImage = new Image(westImg.getFormat(), westImg.getWidth(), westImg.getHeight(), null);
|
||||
|
||||
ArrayList<Bitmap> arrayList = new ArrayList<Bitmap>(6);
|
||||
|
||||
arrayList.add((Bitmap)westImg.getEfficentData());
|
||||
arrayList.add((Bitmap)eastImg.getEfficentData());
|
||||
|
||||
arrayList.add((Bitmap)downImg.getEfficentData());
|
||||
arrayList.add((Bitmap)upImg.getEfficentData());
|
||||
|
||||
arrayList.add((Bitmap)southImg.getEfficentData());
|
||||
arrayList.add((Bitmap)northImg.getEfficentData());
|
||||
|
||||
cubeImage.setEfficentData(arrayList);
|
||||
|
||||
TextureCubeMap cubeMap = new TextureCubeMap(cubeImage);
|
||||
cubeMap.setAnisotropicFilter(0);
|
||||
cubeMap.setMagFilter(Texture.MagFilter.Bilinear);
|
||||
cubeMap.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
|
||||
cubeMap.setWrap(Texture.WrapMode.EdgeClamp);
|
||||
|
||||
|
||||
Material skyMat = new Material(assetManager, "Common/MatDefs/Misc/Sky.j3md");
|
||||
skyMat.setTexture("Texture", cubeMap);
|
||||
skyMat.setVector3("NormalScale", normalScale);
|
||||
sky.setMaterial(skyMat);
|
||||
|
||||
return sky;
|
||||
}
|
||||
|
||||
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(true);
|
||||
key.setAsCube(!sphereMap);
|
||||
Texture tex = assetManager.loadTexture(key);
|
||||
return createSky(assetManager, tex, sphereMap);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user