Noob question on opengl texturestate

When a texture state is created, and an image is loaded into the texture state via TextureManager.loadTexture.



Suppose that one huge image is loaded, the application wanted to make a normal texture state for it, and one with a scaled version or to use a different clamp, is there a way to refernce the one texture or will the gpu have to be sent it twice ??

If "scaled version" means you have different pixel information you have to send it twice. If you just want to scale the texture via transforms while rendering it can be done with a single texture.



The jME texture loader handles the second thing for you (it uses the same gl texture id if you specify to load the same texture file twice).

ooooo.



Currently use the code to create a texture

TextureState ts = TextureManager.loadTexture …



then have one thing that wants

ts.getTexture().setScale(new Vector3f(10f,10f,10f));



another thing wants

ts.getTexture().setScale(new Vector3f(20f,10f,20f));



Is this the way to do it to avoid duplication ???




Yes, I think using TextureManager.loadTexture twice should do the trick. I haven't looked at the code to double check it though…

Rats



The standard code creates the texture



TextureState ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
ts.setEnabled(true);
ts.setTexture(TextureManager.loadTexture(getImage(),Texture.MM_LINEAR,Texture.FM_LINEAR,false));




This for instance is a texture tile for a brick wall.

if i set the texture state for say a quad that is 4x2 it looks great, but i then need to re-use the texture for a wall that is 6x8 and to do so i need to change the scale, setting the scale also effects the 4x2 quad.

Using texture manager loadTexture loads up the same image twice and sends it to the GPU :(


Did you check the actual loadTexture code?



It doesn't… If you load a texture with the same file name, it makes a shallow copy of the texture, including the texture id. And it's the texture id that decides which textures get send to the GPU. However that means you need a textureid. Make sure you add your first texture to a TextureState and call TextureState.apply(), before loading the second texture with loadTexture.

kidneybean said:

Using texture manager loadTexture loads up the same image twice and sends it to the GPU :(

Why do you think it does this?

As Llama stated it should be sent only once. It even does that apply() for you, already. (So no need to do what Llama suggested :P)

All those pretty italics and bolds for nothing…  :’(

im using loadTexture(java.awt.Image image,

                                                    int minFilter, int magFilter, float anisoLevel, boolean flipped) {



If i use the url overloaded method it will, as i need to do some on the fly rendering into the image before hand i need to use the image method

the key for the caching is a TextureKey which relies on the URL of the filename. Is it important for it to use the URL???, was the overloaded method taking in the image added later …



Can it use the hashcode of the image instead. Only issue i can see is what happens if the image is modified post creation of the texture creation

Well you could do what I said after all, about the TextureState.apply(), and then use createSimpleClone() in Texture.

ill give that a go

Ok – using the url method in textureManager.loadtexture



If i have one hundred objects to be rendered with a briick wall image, this will mean i need 100 texture states and 100 Textures, the only thing they have in common is the image within the texture.



Is there a more efficient way to do this, bearing in mind that some of the trimeshes that represent the wall are of different sizes, therefore need to be scaled.

Well, scaling the trimeshes doesn't prevent you from reusing the same textures or texture states. Only when you scale the texture itself is that a problem.

Ive built in a sizing system into game using shared meshes - in essence, shared meshes re-use boxes - 100 walls == 100 shared meshes == 1 trimesh.



Although the boxes are not much of an issue - but complex building shapes like domes and cones, i really wouldnt want to have to scale to fit the image.



Have you seen super mario sunshine, im trying to create a town, many buildings.



Do you think there is a case here for something to be put on a wish list

Well with SharedMeshes you can re-use the texture and the texture state… so what's the issue?



edit; or do you mean that you've scaled the trimish, and then want to scale the texture in the opposite to compensate for that?

Okay - i have 4 buildings



two are banana shops -  equiv of 2.4 metres wide so i have a box with maxextent set to (2.4,2.4,2.4) and they use the sharedmesh of the box



other is a monkey shop and a sweet shop - they need to be bigger so are 3.2,3.2,3.2 - they both use the sharedmesh of the box



they are all built from brick, therefore i need to render the walls with a single tesselated brick image.



i need to use Texture.WM_WRAP_S_WRAP_T as the buildings are much bigger than the texture








Yes, so what you want to do is set the scale of the texture to something smaller for the sweetshop, so the bricks have the same size.



Well, this is not supported by jME, but maybe there are some ways you can do this. For example you could override the the draw(Renderer r) method of your SharedMesh (so you'll have a KidneySharedMesh) that sets the scale for the brick texture to match the size of the house. I'll give you some pseudo/java code to help you out:



In KidneySharedMesh:



public static TextureState some_empty_texture_state...;

public void draw (Renderer r) {
 

Hmmm, nice one llama,



Gonna have a ponder over this, i seem to have built up an eleagant inheritance architecture with an internal  catalog system and product factories. I may be able to acheive it by overriding sharedmesh and the system i have of obtaining the sharedmesh from the original spatial is aware of the need to scale specifically.



As for the adding to a render queue - this will be an educational trip :slight_smile:



ill keep you posted, and thank you

That's easy kidneybean, use spatial.setRenderQueueMode(Renderer.QUEUE_OPAQUE) for opaque objects (it should also give you a nice speed up), and Renderer.QUEUE_TRANSPARANT for those with transparancy (in fact, this is required for a correct scene).