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
3.0
kim..ng 14 years ago
parent 4fa5522c8e
commit e5478faae0
  1. 105
      engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
  2. 30
      engine/src/android/com/jme3/renderer/android/TextureUtil.java
  3. 148
      engine/src/android/com/jme3/util/android/AndroidSkyFactory.java

@ -1708,7 +1708,12 @@ 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
@ -1725,21 +1730,24 @@ public class OGLESShaderRenderer implements Renderer {
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:
@ -1747,6 +1755,7 @@ public class OGLESShaderRenderer implements Renderer {
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:
@ -1773,11 +1782,18 @@ 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)");
@ -1791,9 +1807,10 @@ public class OGLESShaderRenderer implements Renderer {
// bind texture
int target = convertTextureType(type);
if (context.boundTextures[0] != img){
if (context.boundTextureUnit != 0){
if (context.boundTextures[0] != img)
{
if (context.boundTextureUnit != 0)
{
if (verboseLogging)
logger.info("GLES20.glActiveTexture(GLES20.GL_TEXTURE0)");
@ -1808,55 +1825,38 @@ public class OGLESShaderRenderer implements Renderer {
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){
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 (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.uploadTexture(img, GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc, true, powerOf2);
for (int i = 0; i < 6; i++)
{
TextureUtil.uploadTextureBitmap(GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, bmps.get(i), false, 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);
else
{
TextureUtil.uploadTexture(img, target, 0, 0, tdc, false, 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 (!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);
}
}
// if (GLContext.getCapabilities().GL_EXT_framebuffer_multisample){
// glGenerateMipmapEXT(target);
// }
img.clearUpdateNeeded();
}
@ -1866,7 +1866,10 @@ public class OGLESShaderRenderer implements Renderer {
Image image = tex.getImage();
if (image.isUpdateNeeded())
{
/*
Bitmap bmp = (Bitmap)image.getEfficentData();
if (bmp != null)
{
// Check if the bitmap got recycled, can happen after wakeup/restart
if ( bmp.isRecycled() )
{
@ -1874,6 +1877,8 @@ public class OGLESShaderRenderer implements Renderer {
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;
}

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