3D textures

Hi,



Does anyone have any experience with using 3D textures in jme3???

I can see that TextureCubeMap exists but when I tried to use it the results were rather poor :frowning:



Could someone show me an example of using it ??

Cube map != 3dtexutre



Cube map is for reflection/sky only,

while a 3d texutre is a real texture with 3dimensions. However as far as I know there is currenlty no build in support for this(though it shouldn’t be that hard to implement one)

1 Like

OK, thanks for answer.



I’ll try to look into 3D textures matter.

Maybe it is really not difficult to implement it :wink:

Why not use a normal map? It gives a 3D “simulation” based on a normal map (image) of the texture you want with some relief.

Normal map will not fit for what I am going to implement.

I need to attach 3D texture to a 3D object and not creating a bump effect.



The 3D object must look like it was carved out of a 3D texture image.

Imagine a cube of marble and create a sphere out of it using appropriate tools :slight_smile:

The sphere will look like covered with the marble texture and that is what I intend to have.



If there is anyone who has been implementing the textures in jme I would appreciate help with this.

I’ve created very simple 3D texture class but when I apply it, it looks odd.

Some letters appear on my sphere not knowing why :smiley:

the letter texture is usualy a case of wrong / false state updates

OK, so I really think I will not be able to do it without help :frowning:



Here is my Texture3D code:

[java]

public class Texture3D extends Texture {

private WrapMode wrapS = WrapMode.EdgeClamp;

private WrapMode wrapT = WrapMode.EdgeClamp;

private WrapMode wrapR = WrapMode.EdgeClamp;



public Texture3D() {

}



public Texture3D(Image image) {

this.setImage(image);

}



public Texture3D(String name, Image image) {

this.setName(name);

this.setImage(image);

}



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

case R:

this.wrapR = mode;

break;

default:

throw new IllegalStateException("Unknown wrap axis: " + axis);

}

}



@Override

public void setWrap(WrapMode mode) {

if (mode == null) {

throw new IllegalArgumentException("Wrap mode can not be null.");

}

this.wrapS = mode;

this.wrapT = mode;

this.wrapR = mode;

}



@Override

public WrapMode getWrap(WrapAxis axis) {

switch (axis) {

case S:

return wrapS;

case T:

return wrapT;

case R:

return wrapR;

}

throw new IllegalArgumentException("Unknown wrap axis: " + axis);

}



@Override

public Type getType() {

return Type.ThreeDimensional;

}



@Override

public Texture createSimpleClone() {

return this.createSimpleClone(new TextureCubeMap());

}



@Override

public Texture createSimpleClone(Texture rVal) {

rVal.setWrap(WrapAxis.S, wrapS);

rVal.setWrap(WrapAxis.T, wrapT);

rVal.setWrap(WrapAxis.R, wrapR);

return super.createSimpleClone(rVal);

}

}

[/java]



And here is my simple game code:

[java]

public class Texture3DTest extends SimpleApplication {



public Texture3DTest() {

showSettings = false;

}



@Override

public void simpleInitApp() {

//mouseInput.setCursorVisible(true);

flyCam.setMoveSpeed(10);



//creating a sphere

Sphere sphere = new Sphere(32, 32, 1);



//getting the boundingbox

sphere.updateBound();

BoundingBox bb = (BoundingBox)sphere.getBound();

Vector3f min = bb.getMin(null);

float[] ext = new float[] {bb.getXExtent() * 2, bb.getYExtent() * 2, bb.getZExtent() * 2};



//we need to change the UV coordinates (the sphere is assumet to be inside the 3D image box)

sphere.clearBuffer(Type.TexCoord);

VertexBuffer vb = sphere.getBuffer(Type.Position);

FloatBuffer fb = (FloatBuffer) vb.getData();

float[] uvCoordinates = BufferUtils.getFloatArray(fb);



//now transform the coordinates so that they are in the range of <0; 1>

for(int i=0;i<uvCoordinates.length;i+:3) {

uvCoordinates = (uvCoordinates - min.x)/ext[0];

uvCoordinates = (uvCoordinates - min.y)/ext[1];

uvCoordinates = (uvCoordinates - min.z)/ext[2];

}



//apply new texture coordinates

VertexBuffer uvCoordsBuffer = new VertexBuffer(Type.TexCoord);

uvCoordsBuffer.setupData(Usage.Static, 3, com.jme3.scene.VertexBuffer.Format.Float,

BufferUtils.createFloatBuffer(uvCoordinates));

sphere.setBuffer(uvCoordsBuffer);



//create geometry, and apply material and our 3D texture

Geometry g = new Geometry("sphere", sphere);

Material material = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");

try {

Texture texture = this.getTexture();

material.setTexture("DiffuseMap", texture);

} catch (IOException e) {

e.printStackTrace();

}

g.setMaterial(material);

rootNode.attachChild(g);



//add some light so that it is visible

PointLight light = new PointLight();

light.setColor(ColorRGBA.White);

light.setPosition(new Vector3f(5, 5, 5));

light.setRadius(20);

rootNode.addLight(light);



light = new PointLight();

light.setColor(ColorRGBA.White);

light.setPosition(new Vector3f(-5, -5, -5));

light.setRadius(20);

rootNode.addLight(light);

}



/**

  • This method creates a RGB8 texture with the sizes of 10x10x10 pixels.

    /

    private Texture getTexture() throws IOException {

    ArrayList<ByteBuffer> data = new ArrayList<ByteBuffer>(1);

    ByteBuffer bb = BufferUtils.createByteBuffer(10
    10103);//all data must be inside one buffer

    for(int i=0;i<10;++i) {

    for(int j=0;j<10*10;++j) {

    bb.put((byte)255);

    bb.put((byte)255);

    bb.put((byte)255);

    }

    }

    bb.rewind();

    data.add(bb);

    return new Texture3D(new Image(Format.RGB8, 10, 10, 10, data));

    }

    }

    [/java]

@Kaelthas, it can’t work with the DiffuseMap parameter it’s a sampler2D. You need a sampler3D in the shader for it to work, and reading a 3D texture on the shader side is different.



What should your test case do?

ok I added texture3D to the core, look at the test case, it’s basically yours, but with a custom shader that supports 3D textures.

I changed a bit the texture generation to have some white to blue gradient.



see

http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/texture/TestTexture3D.java?spec=svn8002&r=8002

http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/texture/tex3D.j3md?spec=svn8002&r=8002

http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/texture/tex3D.vert?spec=svn8002&r=8002

http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/texture/tex3D.frag?spec=svn8002&r=8002

Actually yes, the implementation looks right, the problem is that Texture3d and ArrayTextures are only usable with Shaders. (Hey seems like my guess was right, its the Texturestate that is false)

OK thanks guys

I’ll look into it as soon as I can :slight_smile:

You can now load DDS 3D Textures see this example : http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/texture/TestTexture3DLoading.java?spec=svn8003&r=8003

Woow,



that really works awesome :smiley:

Thanks.

I’ll be able to finish texture mapping now.

I guess that within 2 weeks blender loader will load textures that not only have UV defined :wink:



Thanks a lot. :smiley:

You’re welcome :wink: