Working TextureArray (17 posts)

  • Profile picture of phate666 phate66670p said 10 months, 3 weeks ago:

    Hi,
    I added support for Texture2DArray, should work on all GPUs with OpenGL>=3

    A testcase is included in the diff:

    Index: src/test/jme3test/texture/TestTextureArray.java
    ===================================================================
    --- src/test/jme3test/texture/TestTextureArray.java	(revision 0)
    +++ src/test/jme3test/texture/TestTextureArray.java	(revision 0)
    @@ -0,0 +1,78 @@
    +package jme3test.texture;
    +
    +import java.util.ArrayList;
    +import java.util.List;
    +
    +import com.jme3.app.SimpleApplication;
    +import com.jme3.material.Material;
    +import com.jme3.math.ColorRGBA;
    +import com.jme3.math.Vector3f;
    +import com.jme3.scene.Geometry;
    +import com.jme3.scene.Mesh;
    +import com.jme3.scene.VertexBuffer.Type;
    +import com.jme3.texture.Image;
    +import com.jme3.texture.Texture;
    +import com.jme3.texture.TextureArray;
    +import com.jme3.util.BufferUtils;
    +
    +public class TestTextureArray extends SimpleApplication
    +{
    +
    +	@Override
    +	public void simpleInitApp()
    +	{
    +		Material mat = new Material(assetManager, "Common/MatDefs/Misc/UnshadedArray.j3md");
    +
    +		Texture tex1 = assetManager.loadTexture( "Textures/Terrain/Pond/Pond.png");
    +		Texture tex2 = assetManager.loadTexture("Textures/Terrain/Rock2/rock.jpg");
    +		List<Image> images = new ArrayList<Image>();
    +		images.add(tex1.getImage());
    +		images.add(tex2.getImage());
    +		TextureArray tex3 = new TextureArray(images);
    +		mat.setTexture("ColorMap", tex3);
    +
    +		Mesh m = new Mesh();
    +		Vector3f[] vertices = new Vector3f[8];
    +		vertices[0] = new Vector3f(0, 0, 0);
    +		vertices[1] = new Vector3f(3, 0, 0);
    +		vertices[2] = new Vector3f(0, 3, 0);
    +		vertices[3] = new Vector3f(3, 3, 0);
    +
    +		vertices[4] = new Vector3f(3, 0, 0);
    +		vertices[5] = new Vector3f(6, 0, 0);
    +		vertices[6] = new Vector3f(3, 3, 0);
    +		vertices[7] = new Vector3f(6, 3, 0);
    +
    +		Vector3f[] texCoord = new Vector3f[8];
    +		texCoord[0] = new Vector3f(0, 0, 0);
    +		texCoord[1] = new Vector3f(1, 0, 0);
    +		texCoord[2] = new Vector3f(0, 1, 0);
    +		texCoord[3] = new Vector3f(1, 1, 0);
    +
    +		texCoord[4] = new Vector3f(0, 0, 1);
    +		texCoord[5] = new Vector3f(1, 0, 1);
    +		texCoord[6] = new Vector3f(0, 1, 1);
    +		texCoord[7] = new Vector3f(1, 1, 1);
    +
    +		int[] indexes = { 2, 0, 1, 1, 3, 2 , 6, 4, 5, 5, 7, 6};
    +
    +		m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
    +		m.setBuffer(Type.TexCoord, 3, BufferUtils.createFloatBuffer(texCoord));
    +		m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));
    +		m.updateBound();
    +
    +		Geometry geom = new Geometry("Mesh", m);
    +		geom.setMaterial(mat);
    +		rootNode.attachChild(geom);
    +	}
    +
    +	/**
    +	 * @param args
    +	 */
    +	public static void main(String[] args)
    +	{
    +		TestTextureArray app = new TestTextureArray();
    +		app.start();
    +	}
    +
    +}
    Index: src/core/com/jme3/texture/TextureArray.java
    ===================================================================
    --- src/core/com/jme3/texture/TextureArray.java	(revision 0)
    +++ src/core/com/jme3/texture/TextureArray.java	(revision 0)
    @@ -0,0 +1,111 @@
    +package com.jme3.texture;
    +
    +import java.util.List;
    +import java.util.logging.Level;
    +import java.util.logging.Logger;
    +
    +import com.jme3.scene.Node;
    +
    +public class TextureArray extends Texture
    +{
    +	private WrapMode wrapS = WrapMode.EdgeClamp;
    +	private WrapMode wrapT = WrapMode.EdgeClamp;
    +
    +	public TextureArray()
    +	{
    +		super();
    +	}
    +
    +	public TextureArray(List<Image> images)
    +	{
    +		super();
    +		int width = images.get(0).getWidth();
    +		int height = images.get(0).getHeight();
    +		Image arrayImage = new Image(images.get(0).getFormat(), width, height,
    +				null);
    +
    +		for (Image img : images)
    +		{
    +			if (img.getHeight() != height || img.getWidth() != width)
    +			{
    +				Logger.getLogger(TextureArray.class.getName()).log(
    +						Level.WARNING,
    +						"all images must have the same width/height");
    +				continue;
    +			}
    +			arrayImage.addData(img.getData(0));
    +		}
    +		setImage(arrayImage);
    +	}
    +
    +	@Override
    +	public Texture createSimpleClone()
    +	{
    +		TextureArray clone = new TextureArray();
    +		createSimpleClone(clone);
    +		return clone;
    +	}
    +
    +	@Override
    +	public Texture createSimpleClone(Texture rVal)
    +	{
    +		rVal.setWrap(WrapAxis.S, wrapS);
    +		rVal.setWrap(WrapAxis.T, wrapT);
    +		return super.createSimpleClone(rVal);
    +	}
    +
    +	@Override
    +	public Type getType()
    +	{
    +		return Type.TwoDimensionalArray;
    +	}
    +
    +	@Override
    +	public WrapMode getWrap(WrapAxis axis)
    +	{
    +		switch (axis)
    +		{
    +		case S:
    +			return wrapS;
    +		case T:
    +			return wrapT;
    +		default:
    +			throw new IllegalArgumentException("invalid WrapAxis: " + axis);
    +		}
    +	}
    +
    +	@Override
    +	public void setWrap(WrapAxis axis, WrapMode mode)
    +	{
    +		if (mode == null)
    +		{
    +			throw new IllegalArgumentException("mode can not be null.");
    +		} else if (axis == null)
    +		{
    +			throw new IllegalArgumentException("axis can not be null.");
    +		}
    +		switch (axis)
    +		{
    +		case S:
    +			this.wrapS = mode;
    +			break;
    +		case T:
    +			this.wrapT = mode;
    +			break;
    +		default:
    +			throw new IllegalArgumentException("Not applicable for 2D textures");
    +		}
    +	}
    +
    +	@Override
    +	public void setWrap(WrapMode mode)
    +	{
    +		if (mode == null)
    +		{
    +			throw new IllegalArgumentException("mode can not be null.");
    +		}
    +		this.wrapS = mode;
    +		this.wrapT = mode;
    +	}
    +
    +}
    Index: src/lwjgl-ogl/com/jme3/renderer/lwjgl/TextureUtil.java
    ===================================================================
    --- src/lwjgl-ogl/com/jme3/renderer/lwjgl/TextureUtil.java	(revision 7731)
    +++ src/lwjgl-ogl/com/jme3/renderer/lwjgl/TextureUtil.java	(working copy)
    @@ -474,7 +474,7 @@
                                          border,
                                          format,
                                          dataType,
    -                                     0);
    +                                     data);
                         }else{
                             glTexSubImage3D(target,
                                             i, // level
    Index: src/core-data/Common/MatDefs/Misc/UnshadedArray.j3md
    ===================================================================
    --- src/core-data/Common/MatDefs/Misc/UnshadedArray.j3md	(revision 0)
    +++ src/core-data/Common/MatDefs/Misc/UnshadedArray.j3md	(revision 0)
    @@ -0,0 +1,70 @@
    +MaterialDef Unshaded {
    +
    +    MaterialParameters {
    +        TextureArray ColorMap
    +        Texture2D LightMap
    +        Color Color : Color
    +        Boolean VertexColor
    +        Boolean SeparateTexCoord
    +
    +        // Texture of the glowing parts of the material
    +        Texture2D GlowMap
    +        // The glow color of the object
    +        Color GlowColor
    +    }
    +
    +    Technique {
    +        VertexShader GLSL100:   Common/MatDefs/Misc/UnshadedArray.vert
    +        FragmentShader GLSL100: Common/MatDefs/Misc/UnshadedArray.frag
    +
    +        WorldParameters {
    +            WorldViewProjectionMatrix
    +        }
    +
    +        Defines {
    +            SEPARATE_TEXCOORD : SeparateTexCoord
    +            HAS_COLORMAP : ColorMap
    +            HAS_LIGHTMAP : LightMap
    +            HAS_VERTEXCOLOR : VertexColor
    +            HAS_COLOR : Color
    +        }
    +    }
    +
    +      Technique PreNormalPass {
    +
    +            VertexShader GLSL100 :   Common/MatDefs/SSAO/normal.vert
    +            FragmentShader GLSL100 : Common/MatDefs/SSAO/normal.frag
    +
    +            WorldParameters {
    +                WorldViewProjectionMatrix
    +                WorldViewMatrix
    +                NormalMatrix
    +            }
    +
    +            RenderState {
    +
    +            }
    +
    +        }
    +
    +
    +    Technique Glow {
    +
    +        VertexShader GLSL100:   Common/MatDefs/Misc/UnshadedArray.vert
    +        FragmentShader GLSL100: Common/MatDefs/Light/Glow.frag
    +
    +        WorldParameters {
    +            WorldViewProjectionMatrix
    +        }
    +
    +        Defines {
    +            HAS_GLOWMAP : GlowMap
    +            HAS_GLOWCOLOR : GlowColor
    +            HAS_COLORMAP // Must be passed so that Unshaded.vert exports texCoord.
    +        }
    +    }
    +
    +    Technique FixedFunc {
    +    }
    +
    +}
    Index: src/core-data/Common/MatDefs/Misc/UnshadedArray.frag
    ===================================================================
    --- src/core-data/Common/MatDefs/Misc/UnshadedArray.frag	(revision 0)
    +++ src/core-data/Common/MatDefs/Misc/UnshadedArray.frag	(revision 0)
    @@ -0,0 +1,50 @@
    +uniform vec4 m_Color;
    +
    +#if defined(HAS_GLOWMAP) || defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD))
    +    #define NEED_TEXCOORD1
    +#endif
    +
    +#ifdef HAS_COLORMAP
    +    uniform sampler2DArray m_ColorMap;
    +#endif
    +
    +#ifdef NEED_TEXCOORD1
    +    varying vec3 texCoord1;
    +#endif
    +
    +#ifdef HAS_LIGHTMAP
    +    uniform sampler2D m_LightMap;
    +    #ifdef SEPERATE_TEXCOORD
    +        varying vec3 texCoord2;
    +    #endif
    +#endif
    +
    +#ifdef HAS_VERTEXCOLOR
    +    varying vec4 vertColor;
    +#endif
    +
    +void main(){
    +    vec4 color = vec4(1.0);
    +
    +    #ifdef HAS_COLORMAP
    +        color *= texture2DArray(m_ColorMap, texCoord1);
    +    #endif
    +
    +    #ifdef HAS_VERTEXCOLOR
    +        color *= vertColor;
    +    #endif
    +
    +    #ifdef HAS_COLOR
    +        color *= m_Color;
    +    #endif
    +
    +    #ifdef HAS_LIGHTMAP
    +        #ifdef SEPARATE_TEXCOORD
    +            color.rgb *= texture2D(m_LightMap, texCoord2).rgb;
    +        #else
    +            color.rgb *= texture2D(m_LightMap, texCoord1).rgb;
    +        #endif
    +    #endif
    +
    +    gl_FragColor = color;
    +}
    Index: src/core-data/Common/MatDefs/Misc/UnshadedArray.vert
    ===================================================================
    --- src/core-data/Common/MatDefs/Misc/UnshadedArray.vert	(revision 0)
    +++ src/core-data/Common/MatDefs/Misc/UnshadedArray.vert	(revision 0)
    @@ -0,0 +1,37 @@
    +uniform mat4 g_WorldViewProjectionMatrix;
    +attribute vec3 inPosition;
    +
    +#if defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD))
    +    #define NEED_TEXCOORD1
    +#endif
    +
    +#ifdef NEED_TEXCOORD1
    +    attribute vec3 inTexCoord;
    +    varying vec3 texCoord1;
    +#endif
    +
    +#ifdef SEPARATE_TEXCOORD
    +    attribute vec3 inTexCoord2;
    +    varying vec3 texCoord2;
    +#endif
    +
    +#ifdef HAS_VERTEXCOLOR
    +    attribute vec4 inColor;
    +    varying vec4 vertColor;
    +#endif
    +
    +void main(){
    +    #ifdef NEED_TEXCOORD1
    +        texCoord1 = inTexCoord;
    +    #endif
    +
    +    #ifdef SEPARATE_TEXCOORD
    +        texCoord2 = inTexCoord2;
    +    #endif
    +
    +    #ifdef HAS_VERTEXCOLOR
    +        vertColor = inColor;
    +    #endif
    +
    +    gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
    +}
    
  • Profile picture of Empire Phoenix Empire Phoenix156p said 6 months, 4 weeks ago:

    daily bump till answer if will be integrated, and if not reasons why. Works after a very small change to the material, since definitions changed a little. (also int the testcase one texture changed from png to jpg)

  • Profile picture of nehon nehon590p said 6 months, 2 weeks ago:

    It’s added in last SVN, thanks for the contribution @phate666

    I added a check for the TextureArray capability in the test case that throw an UnsupportedOperationException, since it’s a ogl3.0 feature.

    Also I put the UnshadedArray material files in the test repo only.

    BTW do you know if there is a limitation on how many textures you can send to the GPU like this?

  • Profile picture of alrik alrik said 3 months, 2 weeks ago:

    is there any chance for a ShadedArray.j3md?

  • Profile picture of Empire Phoenix Empire Phoenix156p said 3 months, 2 weeks ago:

    Well yes, it just depends on if anyone writes it.

  • Profile picture of obi48 obi48 said 2 months, 3 weeks ago:

    Hi,

    How can I add textures with alpha channel? It seems that doesn’t work with the following code:

    ...
    mat = new Material(assetManager, "Textures/UnshadedArray.j3md");
            Texture tex0 = assetManager.loadTexture("Materials/Glass.png");
    
     List<Image> images = new ArrayList<Image>();
            images.add(tex0.getImage()); 
    
    TextureArray tex = new TextureArray(images);
            mat.setTexture("ColorMap", tex);
            mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
    ...
    
  • Profile picture of Empire Phoenix Empire Phoenix156p said 2 months, 3 weeks ago:

    I guess the shader(fragment) is just ignoring alpha values

  • Profile picture of obi48 obi48 said 2 months, 3 weeks ago:

    ok but how can I add alphachannel-support to the fragmentshader?

  • Profile picture of Momoko_Fan Momoko_Fan366p said 2 months, 3 weeks ago:

    The fragment shader is in fact writing the alpha value from the texture into the pixel. Something else must be wrong …

  • Profile picture of obi48 obi48 said 2 months, 3 weeks ago:

    Ok i built a custom mesh here is my code:

    
    //First I set all buffers
            FloatBuffer bufferpos = BufferUtils.createFloatBuffer(max_cubes_per_chunk * 24 * 3);
            m.setBuffer(Type.Position, 3, bufferpos);
    
            FloatBuffer buffertex = BufferUtils.createFloatBuffer(max_cubes_per_chunk * 24 * 3);
            m.setBuffer(Type.TexCoord, 3, buffertex);
    
            IntBuffer bufferind = BufferUtils.createIntBuffer(36 * max_cubes_per_chunk);
            m.setBuffer(Type.Index, 1, bufferind);
    
            FloatBuffer buffernorm = BufferUtils.createFloatBuffer(max_cubes_per_chunk * 24 * 3);
            m.setBuffer(Type.Normal, 3, buffernorm);
    
            VertexBuffer pvb, tvb, ivb, nvb;
            FloatBuffer bufferVert, bufferTex, bufferNorm;
            IntBuffer bufferInd;
    
            //Get Meshbuffers
            pvb = m.getBuffer(VertexBuffer.Type.Position);
            tvb = m.getBuffer(VertexBuffer.Type.TexCoord);
            ivb = m.getBuffer(VertexBuffer.Type.Index);
            nvb = m.getBuffer(VertexBuffer.Type.Normal);
    
            //Get DataBuffers from Meshbuffers
            bufferVert = (FloatBuffer) pvb.getData();
            bufferTex = (FloatBuffer) tvb.getData();
            bufferInd = (IntBuffer) ivb.getData();
            bufferNorm = (FloatBuffer) nvb.getData();
    
            //Bufferreset
            bufferVert.rewind();
            bufferTex.rewind();
            bufferNorm.rewind();
            bufferInd.rewind();
    
    //Then i write all datas (texcoords, vert, normals, indexes) to the buffers
    //+ updating at the end
            pvb.setUpdateNeeded();
            tvb.setUpdateNeeded();
            ivb.setUpdateNeeded();
            nvb.setUpdateNeeded();
    
            m.updateBound();
            m.createCollisionData();
    

    It runs great but the textures with alphachannel are black boxes for example:

    how can I solve that?

  • Profile picture of Empire Phoenix Empire Phoenix156p said 2 months, 3 weeks ago:

    Are thy in the Alpha queue bucket? (You need to have transparent objects in another queue than non transparent ones.
    Also transparent boxes are not a perfect case for batching in a box world, since depending on case there is no right renderorder so taht all transparencies are correct)

  • Profile picture of obi48 obi48 said 2 months, 3 weeks ago:

    yes i have set the transparency bucketmode

    m.setQueueBucket(Bucket.Transparent);

    should i build a new custom mesh only for transparent boxes?

    so there is no way to handle transparent and solid blocks in one mesh?

  • Profile picture of pspeed pspeed805p said 2 months, 3 weeks ago:

    Forgive me if this has been covered already, but what makes the background of your screen shot blue? Do you have a sky or have you set the viewport’s background color?

  • Profile picture of obi48 obi48 said 2 months, 3 weeks ago:

    I have set the vieport’s backgroundcolor:

    viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
  • Profile picture of nehon nehon590p said 2 months, 3 weeks ago:

    Also the blend mode of your material must be Alpha
    material.getAdditionalRenderState().setBlendMode(Blend.alpha);