[SOLVED] Passing Array to Shader

Hello, I’m working on a shader and I’m trying to pass an array of textures to the shader. I was able to pass an array of Vectors, using the "VarType.Vector3Array" as the type when settings a material param from java code, but when I try passing an array of textures using the "VarType.TextureArray" I get the following error from this line of code:

private Texture[] textureEffectsArray = new Texture[30];

textureEffectsArray[i] = textureEffect.getTexture();
afflictedMat.setParam("TextureEffects", VarType.TextureArray, textureEffectsArray); //<-- error thrown on this line

error:

java.lang.ClassCastException: [Lcom.jme3.texture.Texture; cannot be cast to com.jme3.texture.Texture
	at com.jme3.material.Material.setParam(Material.java:479)
	at SpecialEffects.TextureEffects.TextureEffectManagerState.alterAffectedObjects(TextureEffectManagerState.java:98)
	at SpecialEffects.TextureEffects.TextureEffectManagerState.update(TextureEffectManagerState.java:52)
	at CoreAppClasses.AppController.update(AppController.java:180)
	at MainSA.Main.simpleUpdate(Main.java:130)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:239)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:197)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:232)
	at java.lang.Thread.run(Thread.java:748)

and here’s how I have the array of Textures defined in the .j3md file :

Vector3Array TextureEffectLocations
TextureArray TextureEffects

My initial thought was that I am confusing an Array of Textures with a “TextureArray” (which could work in my case, but an array of unique textures that could be dynamically altered would be optimal) . But I honestly have no clue - all I’m finding is general information on ArrayTextures when I do a google search, so I figured I’d ask for some advice here :slightly_smiling_face: Thanks for any help.

http://javadoc.jmonkeyengine.org/com/jme3/texture/TextureArray.html

Edit: I see that you mentioned this class… but a TextureArray type is a TextureArray.

1 Like

Thanks for the clarification, I was beginning to think that is probably the case, but a small part of me was hoping otherwise so that I wouldn’t have to change my plans and could just pass a big array of textures :laughing:

So I guess my options are to use an actual TextureArray… Or declare a bunch of Uniform Texture2D paramaters, similar to the way the TerrainLighting shader declares its texture channels. Are there any major drawbacks to declaring too many “Texture2D” paramaters in a single shader?

You only have so many available.

TextureArray is better for an array of textures… it has its own limitations, though. One of which is the min openGL version… another is that they all must be the same size, etc…

1 Like

I think I’ll go with a TextureArray. If there’s any case where a user has an older version, I think I should be able to get away with displaying a solid color instead of referencing the TextureArray.

Speaking of colors, I’m also trying to pass a Vector4Array to my shader to represent the color and opacity of each active effect, but I’m getting this error when I set a VarType.Vector4Array paramater

public Vector4f[] effectColors = new Vector4f[30];
afflictedMat.setParam("TextureEffectColors", VarType.Vector4Array, effectColors);

.

     java.lang.NullPointerException
    	at com.jme3.util.BufferUtils.setInBuffer(BufferUtils.java:337)
     	at com.jme3.shader.Uniform.setValue(Uniform.java:299)
     	at com.jme3.material.Material.updateShaderMaterialParameters(Material.java:810)
     	at com.jme3.material.Material.render(Material.java:968)
     	at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:614)
     	at com.jme3.renderer.queue.RenderQueue.renderGeometryList(RenderQueue.java:266)
     	at com.jme3.renderer.queue.RenderQueue.renderQueue(RenderQueue.java:305)
     	at com.jme3.renderer.RenderManager.renderViewPortQueues(RenderManager.java:877)
     	at com.jme3.renderer.RenderManager.flushQueue(RenderManager.java:779)
     	at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1108)
     	at com.jme3.water.SimpleWaterProcessor.postQueue(SimpleWaterProcessor.java:203)
     	at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1103)
     	at com.jme3.renderer.RenderManager.render(RenderManager.java:1158)
     	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:253)
     	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
     	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:197)
     	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:232)
     	at java.lang.Thread.run(Thread.java:748)

If I omit the Alpha value for my color and store just the RGB values in a Vector3Array, then I don’t get this error (but then I have to pass the opacity over as a FloatArray to set the alpha value)

mhh this looks like a bug
let me check

1 Like

mhh nope I can’t reproduce. Are you 100% sure there is no null Vector4f in your arrray?
Make sure to initialize them all

1 Like

That seemed to fix the issue, thanks! I filled the Vector4f array with a default value and everything works correctly now.

 Arrays.fill(effectColors, new Vector4f(1,1,1,1));

 afflictedMat.setParam("TextureEffectLocations", VarType.Vector3Array, effectLocations);
 afflictedMat.setParam("TextureEffectColors", VarType.Vector4Array, effectColors);

Although it’s strange that I only encountered the error passing a Vector4f array. It doesn’t seem to mind that my other array of Vector3s has some null entries, but nonetheless its working now :slightly_smiling_face:

yeah for some reason the setInBuffer method in BufferUtils accomodates for null values in its Vector3f version and not in it’s other types version… This could be enhanced.

1 Like