Applying multitexture to single poly in object

Started by rolz, December 26, 2005, 05:01:16 PM

Previous topic - Next topic

rolz

Helge,


We've got object3d.setTexture(TextureInfo) method that works just fine, but is it by any way possible to apply multitexture to a single poly ? like
PolygonManager.setPolygonTexture(polyId, textureInfo) ?
Regards,
Andrei

EgonOlsen


rolz

Ok, thanks.  

Helge, another quick thing - is there a way to disable tiling for specific layer in TextureInfo ?
Regards,
Andrei

EgonOlsen

Quote from: "rolz"Helge, another quick thing - is there a way to disable tiling for specific layer in TextureInfo ?
No. Do you really need that?

rolz

Well, let's say i have a small texture i want to place over a polygon - a blood stain, a shadow - it is expected that texture image is smaller than the polygon to which i plan to apply it.  
After applying the texture, it is tiled all over the polygon - repeated several times. I thought it would be great to have a way to somehow handle tiling, as per this case.

p.s. another example - the "shadow" texture could occupy more than 1 polygon -  let's say it occupies 1 entire polygon and partially several adjacent polygons. With tiling, "shadow" is placed fine on one polygod and is tiled across these "partially occupied" polygons.
Regards,
Andrei

EgonOlsen

I see...I'll have a look at it next year... :wink:

EgonOlsen

Here you go: *edit: download removed!*
It includes both changes, i.e. an extended setPolygonTexture(...) in the PolygonManager and the possibility to set a texture to clamping mode. In OpenGL, this is bound to the texture, so i had to add the method to Texture too, albeit i'm not really happy with that. Anyway...i hope i haven't broken anything else as i haven't tested this version very much. Here's some example code, that moves a decal over a plane using multi texturing only:

import com.threed.jpct.*;
import org.lwjgl.opengl.*;
import java.awt.event.*;
import com.threed.jpct.util.*;

public class MTMove {

 public static void main(String[] args) throws Exception {
   MTMove mt = new MTMove();
   mt.doIt();
 }

 private void doIt() throws Exception {
   FrameBuffer fb=new FrameBuffer(640, 480, FrameBuffer.SAMPLINGMODE_HARDWARE_ONLY);
   fb.disableRenderer(IRenderer.RENDERER_SOFTWARE);
   fb.enableRenderer(IRenderer.RENDERER_OPENGL);

   World w=new World();
   w.setAmbientLight(255,255,255);

   TextureManager tm=TextureManager.getInstance();
   Texture base=new Texture("base.jpg");
   Texture decal=new Texture("decal.jpg");

   tm.addTexture("base", base);
   tm.addTexture("decal", decal);

   decal.enableGLClamping();

   int bid=tm.getTextureID("base");
   int did=tm.getTextureID("decal");

   Object3D plane=new Object3D(9);
   plane.setCulling(Object3D.CULLING_DISABLED);

   TextureInfo tInf1 = new TextureInfo(bid, -1, -1, 2, -1, -1, 2);
   tInf1.add(did, -1, -1, 2, -1, -1, 2, TextureInfo.MODE_ADD);
   TextureInfo tInf2 = new TextureInfo(bid, 2, -1, 2, 2, -1, 2);
   tInf2.add(did, 2, -1, 2, 2, -1, 2, TextureInfo.MODE_ADD);
   plane.addTriangle(new SimpleVector( -10, -10, 30), new SimpleVector( -10, 10, 30), new SimpleVector(10, -10, 30), tInf1);
   plane.addTriangle(new SimpleVector( -10, 10, 30), new SimpleVector(10, 10, 30), new SimpleVector(10, -10, 30), tInf2);

   w.addObject(plane);
   w.buildAllObjects();

   KeyMapper km=new KeyMapper();
   PolygonManager pm = plane.getPolygonManager();

   float u=-1;
   float v=-1;

   int bs=0;

   while (!Display.isCloseRequested()) {
     fb.clear();
     w.renderScene(fb);
     w.draw(fb);
     fb.displayGLOnly();

     KeyState key=null;

     while(key!=KeyState.NONE) {
       key = km.poll();
       int keyc=key.getKeyCode();
       if (keyc == KeyEvent.VK_W) {
         bs ^= 4;
       }
       if (keyc == KeyEvent.VK_S) {
         bs ^= 8;
       }
       if (keyc == KeyEvent.VK_A) {
         bs ^= 2;
       }
       if (keyc == KeyEvent.VK_D) {
         bs ^= 1;
       }
     }

     if ((bs & 4) == 4) {
       u += 0.01f;
     }
     if ((bs & 8) == 8) {
       u -= 0.01f;
     }
     if ((bs & 2) == 2) {
       v += 0.01f;
     }
     if ((bs & 1) == 1) {
       v -= 0.01f;
     }

     if (bs!=0) {
       tInf1 = new TextureInfo(bid, -1, -1, 2, -1, -1, 2);
       tInf1.add(did, u, v, u + 3, v, u, v + 3, TextureInfo.MODE_ADD);
       tInf2 = new TextureInfo(bid, 2, -1, 2, 2, -1, 2);
       tInf2.add(did, u + 3, v, u + 3, v + 3, u, v + 3, TextureInfo.MODE_ADD);
       pm.setPolygonTexture(0, tInf1);
       pm.setPolygonTexture(1, tInf2);
     }

     Thread.sleep(10);
   }

   km.destroy();
   fb.disableRenderer(IRenderer.RENDERER_OPENGL);
   System.exit(0);
 }
}

rolz

#7
Thanks for the great update, it was really just what i needed !

I've got multitexturing working properly, here is the quick shot:
*Removed*

A couple of questions/ requests:

1. removing unused textures
I am going to generate shadows for ground objects from their silhouette. It makes sense to remove unused texture from TextureManager when the object is no longer visible (e.g. object has been removed).
Currently i will have to implement a pool of "shadow" textures and replace unused textures with newly generated, but i dont feel like this is better than just removing unused textures from videocard's memory. What would you suggest ?

2. TextureInfo.MODE_ADD transparency ?
I am using TextureInfo.MODE_ADD when placing additional texture over the base texture. I have noticed that the second texture is ~50% transparent. Is it possible to adjust transparency value when placing one texture over another ? (e.g. put a bloodstain on the ground and make it almost opaque, like with object3d.setTransparency(255)

3. alpha channel for textures
is there a way to use PNG as texture ? basicly, what i want is a semi-transparent texture which fades away from the center to borders ( smooth shadow)
Regards,
Andrei

EgonOlsen

Great that it worked so far. Now to your questions... :wink:

1. Removing textures from the TextureManager is difficult, because the TextureManager doesn't know if the texture is still in use by an object. It can't even query the objects, because it doesn't know them. It would be possible to remove it anyway, but that will cause a crash or at least a white object (when using the dummy texture instead..if possible...i'll have to check this out) in case it will be used again. An easier task would be to simply unload it from the graphics card's memory and let jPCT upload it again if needed. That would free at least the memory on the video card but not in the TextureManager itself. Or leave it like it is and go for the pooling...not sure, which way to go...


2. No, but you could try to use MODE_MODULATE instead. But: The current implementation uses GL_CLAMP at the borders. According to the specs (some cards/drivers (Nvidia) seem to ignore them but anyway...), this will cause black (or whatever colored) borders for bilinear filtering. This will look strange if the texture is actually clamped. If you have tried this, you'll have already noticed it. I could use GL_CLAMP_TO_EDGE to get rid of this, but that's GL 1.2...but that shouldn't be a problem and i may still use GL_CLAMP as a fallback solution. To understand this better, i've made a picture:


3. Currently not. If clamping is set to GL_CLAMP_TO_EDGE in the future, it should be possible to get what you want with MODE_MODULATE. It's not possible to create shadows by using MODE_ADD anyway.

Like so:


To play around with MODE_MODULATE, here is a jar with  GL_CLAMP_TO_EDGE hacked into the renderer (i.e. no fallback to GL_CLAMP for GL 1.1): http://www.jpct.net/download/beta/jpct.jar

rolz

Thanks for prompt response,

Quote from: "EgonOlsen"
1. Removing textures from the TextureManager is difficult, because the TextureManager doesn't know if the texture is still in use by an object. It can't even query the objects, because it doesn't know them. It would be possible to remove it anyway, but that will cause a crash or at least a white object (when using the dummy texture instead..if possible...i'll have to check this out) in case it will be used again. An easier task would be to simply unload it from the graphics card's memory and let jPCT upload it again if needed. That would free at least the memory on the video card but not in the TextureManager itself. Or leave it like it is and go for the pooling...not sure, which way to go...
I think it is ok to leave as is then, let's see if i get into troubles with textures generated on the fly.

Quote
2. No, but you could try to use MODE_MODULATE instead. But: The current implementation uses GL_CLAMP at the borders. According to the specs (some cards/drivers (Nvidia) seem to ignore them but anyway...), this will cause black (or whatever colored) borders for bilinear filtering. This will look strange if the texture is actually clamped. If you have tried this, you'll have already noticed it. I could use GL_CLAMP_TO_EDGE to get rid of this, but that's GL 1.2...but that shouldn't be a problem and i may still use GL_CLAMP as a fallback solution. To understand this better, i've made a picture:


3. Currently not. If clamping is set to GL_CLAMP_TO_EDGE in the future, it should be possible to get what you want with MODE_MODULATE. It's not possible to create shadows by using MODE_ADD anyway.

Like so:


To play around with MODE_MODULATE, here is a jar with  GL_CLAMP_TO_EDGE hacked into the renderer (i.e. no fallback to GL_CLAMP for GL 1.1): http://www.jpct.net/download/beta/jpct.jar

Just tried and it worked just as planned. Thank you again for prompt response. Hope to post more screenshots when I have something to show. ;)
Regards,
Andrei

rolz

Textures won't display at all if there are 3+ textures on polygon already. Is it hardware limit, or it can be somehow overriden ?
Regards,
Andrei

EgonOlsen

Quote from: "rolz"Textures won't display at all if there are 3+ textures on polygon already. Is it hardware limit, or it can be somehow overriden ?
If 3 is max, it's a hardware limit. jPCT itself is limited to 4 textures/polygon but that's just for optimization purposes and because i don't know of any current hardware that supports more. When initializing the renderer, it tells you the max. number of texture stages supported (the number in brackets behind the init-message) by your hardware.
2 should be possible on almost every hardware (starting with Riva TNT, GF2(MX), GF4MX etc.). More current cards (GF3+, ATI Radeon 9x00 etc) supports 3 or 4, but if you want to support older ones, i suggest to limit yourself to 2. If you add more than the hardware supports, jPCT will ignore them.

rolz

#12
well, yes, it's look like that it's 4.
*Removed*

I've talked to a guy who helped me to understand multitexturing, he mentioned that it should be possible to lay more textures per polygon than video card allows to do in single pass. He mentioned "multipass multitexturing" - do you have an idea what is that, and if it will fit JPCT ?  :(
Regards,
Andrei

rolz

I am in despair ...  :cry:  :cry:  :cry:
spent a couple of nights trying to make multitexturing work and now stuck at those restrictions ............ !@#$#!@#@#.
Regards,
Andrei

EgonOlsen

Yes, i've already thought about adding a multipass rendering thingy to the engine to overcome these limitations. I think that it would require quite a change to the current pipeline...i'll look into it, when i find the time.