Texture a Quad

Hi,

I want to texture a quad like it:


http://img4.hostingpics.net/thumbs/mini_581712texture.png

In black, the quad that i want to fill with the texture.
In Gray, the texture clamp & size with a repeat factor.

I must set the texture coord for 4 vertices, how can i give in this way the texture scaling and the texture clamp point and the repeat mode ?

Bets regards,
Sébastien.

Hi Sébastien

I have a question for you. Have you noticed an important boost when using the repeat factor instead of using more vertices?

In your case, I would use something close to [0.5,0.5] [4.5,0.5][4.5,2.5][0.5,2.5] (not tested).

Ok, if i understand it correctly, the 0.5 to 4.5 on the x axis means to draw 4 times the texture on this region starting it at the middle of the texture (0.5f)
This way it give the clamp point (0.5) and the scale (number of repetitions in the region).

I will try it this evening, i understand better how texCoord works (all examples found are always the same with texCoord from 0 to 1)

Thanks for all.

The final texture coordinate with wrapping just becomes (s % 1, y % 1) for each pixel, so 0.5 to 1.5 goes from 0.5 --> 1.0 == 0.0 --> 0.5. It just cuts off everything before the decimal point.

I have the same problem, I want to use this feature but all examples I found are simplistic in comparison to what I plan to achieve. I fear that a part of the texture won’t appear anyway with my suggestion because the repetitions are identical, you can only repeat the same “part” of the texture or use mirroring whereas in your case you don’t want to do that, the very first and the very fast parts don’t use the same part of the texture than the ones in the middle.

Maybe I’m just misunderstanding but what are you trying to say? Are you asking for help (“have the same problem” —> STILL have the same problem?) or are you just saying that the examples available on the internet are not very good? =S

I understand better how things works.

But now, i would texture a quad with a repeat factor but only with a region of a texture

So for the example, Considering that i want to use only the rectangle (0.25,0.25) x (0.75,0.75) of a texture.
But i want to repeat i 4 times on a quad that have dimension (100,100) and starting at (50,50)

i would do a things like it

   // bind texture
   // enable "repeat" mode 
   // set QUAD operation
   // begin

   // first vertex
   glTexCoord(0.25,0.25);
   glVertex2f( 50 , 50 );

    // second vertex 
    glTexCoord(3.75,0.25);
    glVertex2f( 150 , 50);

    // third vertex
    glTexCoord( 3.75 , 3.75 );
    glVertex2f( 150 , 150); 

    // last vertex
    glTexCoord( 0.25 , 3.75 );
    glVertex2f( 50 , 150); 

(the vertices order may be wrong, i do it without my dev pc)
So if i understand, it will draw like it

Horizontall i will have

 [0.25 ~ 1] + [0 ~ 1 ] + [0 ~ 1 ] + [0 ~ 1 ] + [0 ~ 0.75 ]

Instead of what i want:

 [0.25 ~ 0.75] + [0.25 ~ 0.75] + [0.25 ~ 0.75] + [0.25 ~ 0.75]

How can i achieve my goal ?
Thanks in advance.

You can’t, with regular texture coords. You either have to draw it as separate quads, copy the sub-section to a new texture, or write a shader that lets you tile sub regions.

Separate quads is probably most sensible.

Unless you are pushing hundreds of thousands of vertices per frame, just use multiple quads to define each “repeat” of your tile. The performance difference will be negligible and it will allow you to use texture atlases. Use a single glBegin/glEnd to push all of your quads at once. Ideally you should be using vertex arrays instead of immediate mode.

A pixel shader with a one-line main method does the trick, but just drawing many quads work. Textures only wrap around their edges, so you can’t do this with wrapping. You could just cut out the needed part into it’s own texture…

The quad is just a case of filling form that should work.
I want to “generalize” it for triangles, shapes (with tesselation), circles (a shape) etc…

i don’t know at all what is a pixel shader and how it works…
I will go deeper this evening on this stuff.

I just read some stuf about Pixel shaders, and it seems to take a big bazzoka for kill an insect…
I must do few tests…

It’s not much more than writing a vertex and fragment shader and binding it. You don’t even need a vertex shader if you use older versions of GLSL.

Problem is creating the classes to load Shaders in opengl. thats the most hard part for me.

all of this is new , i need to understand theses new stuff. it will take some times.

ShaderProgram + Shader = 120 lines of code for me, with like 30-40% blank lines, and 50% of the Shader class is loading a text file from disc. All in all it’s only like 10 encapsulated OpenGL functions. Well, shaders aren’t the easiest part of OpenGL at least, I’ll give you that. =S

Wow… thank you for that point :smiley:

You only need to do it once, then you have a library. Here’s a minimal example, feel free to adapt from this: https://bitbucket.org/chuck/lwjgl-sandbox/src/tip/src/main/java/sandbox/util/ShaderProgram.java

Sadly it’s incomplete, stuff like binding attributes isn’t in there, you’ll have to take that on yourself or find a better library.

At the first, i decide to wrote the coord mapping in java before to try to do it in a pixel shader.

It give this try :

public static class TextureCoordInterpolator {
		
		/** 
		 * Coordinate of the sub-texture inside the whole texture
		 */
		private int       x,y;
		
		/** Dimension of the sub-texture
		 */
		private int       width,height;
		
		/** Dimension of the whole-texture
		 */
		private int       textureWidth,textureHeight;
		
		/* The anchor region.
		 * This region define an area where drawing the Sub-Texture exactely and completely 1 time from (0,0) to (1,1) in sub-texture space-coordinate
		 */
		private Rectangle anchor;
		
		public void getTextureCoord( float pX , float pY ) {
			/** Sub-Texture coords
			 */
			float sx = ( pX - anchor.getX()  ) / ( anchor.getWidth() );
			float sy = ( pY - anchor.getY()  ) / ( anchor.getHeight() );
			System.out.println("getTextureCoord(" + pX + "," + pY + ") == subTextureCoord(" + sx + "," + sy + ")");
			
			/** Normalized Sub-Texture coord in [ 0 ~ 1 ]
			 */
			float rx = sx - (int)sx;   // just the rest ==> don't see difference between 0f and 1f
			float ry = sy - (int)sy;   // just the rest ==> don't see difference between 0f and 1f
			System.out.println("getTextureCoord(" + pX + "," + pY + ") == normalSubTextureCoord(" + rx + "," + ry + ")");
			
			/** Global Texture coord
			 */
			float gx = ( x + (rx * width) ) / textureWidth;
			float gy = ( y + (ry * height) ) / textureHeight;
			System.out.println("getTextureCoord(" + pX + "," + pY + ") == globalTextureCoord(" + gx + "," + gy + ")");
			
		}

It globbaly works, except that i don’t see any difference between the 0f and the 1f texCoord.
I’m not sure how can i handle it properly !! any idea ?

my main was:

	public static void main(String[] args) {
		TextureCoordInterpolator test = new TextureCoordInterpolator();
		test.x = 50;
		test.y = 50;
		test.width = 100;
		test.height = 100;
		test.textureWidth  = 200;
		test.textureHeight = 200;
		test.anchor = new Rectangle( 5 , 5 , 20 , 20 );
		test.getTextureCoord(5,5);
		test.getTextureCoord(24,24);
		test.getTextureCoord(25,24);
		test.getTextureCoord(26,24);
	}

With this version, i handle correctly the 0.0f and 1.0f texCoord

public static class TextureCoordInterpolator {
	      
	      /** 
	       * Coordinate of the sub-texture inside the whole texture
	       */
	      private int       x,y;
	      
	      /** Dimension of the sub-texture
	       */
	      private int       width,height;
	      
	      /** Dimension of the whole-texture
	       */
	      private int       textureWidth,textureHeight;
	      
	      /* The anchor region.
	       * This region define an area where drawing the Sub-Texture exactely and completely 1 time from (0,0) to (1,1) in sub-texture space-coordinate
	       */
	      private Rectangle anchor;
	      
	      public void getTextureCoord( float pX , float pY ) {
	         /** Sub-Texture coords
	          *  ==================
			  *  ( ( pX - anchorX ) % anchorWidth ) / ( anchorWidth - 1 )

			  *  With :
			  *  ====
			  *  x   [ 05      06      07      08    ] [ 09      10      11      12    ]
			  *  rx  [ 0.00f   0.33f   0.66f   1.00f ] [ 0.00f   0.33f   0.66f   1.00f ]
			  *  
			  *  anchorX     = 05
			  *  anchorWidth = 4
			  *  
			  *  case 05 >>>  ( ( 05 - 5 ) % 4 ) / 3 == 0.00f
			  *  case 06 >>>  ( ( 06 - 5 ) % 4 ) / 3 == 0.33f
			  *  case 07 >>>  ( ( 07 - 5 ) % 4 ) / 3 == 0.66f
			  *  case 08 >>>  ( ( 08 - 5 ) % 4 ) / 3 == 1.00f
			  *  
			  *  case 09 >>>  ( ( 09 - 5 ) % 4 ) / 3 == 0.00f
			  *  case 10 >>>  ( ( 10 - 5 ) % 4 ) / 3 == 0.33f
			  *  case 11 >>>  ( ( 11 - 5 ) % 4 ) / 3 == 0.66f
			  *  case 12 >>>  ( ( 12 - 5 ) % 4 ) / 3 == 1.00f
			  */
	         float rx = ( ( pX - anchor.getX()  ) % anchor.getWidth() ) / ( anchor.getWidth() - 1 );
	         float ry = ( ( pY - anchor.getY()  ) % anchor.getHeight() ) / ( anchor.getHeight() - 1 );
	         System.out.println("getTextureCoord(" + pX + "," + pY + ") == subTextureCoord(" + rx + "," + ry + ")");
	         
	         /** Global Texture coord
	          */
	         float gx = ( x + (rx * width) ) / textureWidth;
	         float gy = ( y + (ry * height) ) / textureHeight;
	         System.out.println("getTextureCoord(" + pX + "," + pY + ") == globalTextureCoord(" + gx + "," + gy + ")");
	      }
      }