Does anyone knows how to use GL_REPEAT in JOGL 2. I would like to have a rectangle with one texture repeated 4 times by using GL_REPEAT. I know how to do this with other implementations of opengl but since JOGL uses the Texture Class, I don't get it to work.
Also I don't want a GL_REPEAT example with spaces in between tiles, which is what I get when using the JOGL 2 Texture Class. Moreover, there are no examples of this on the web. Any examples anyone? Thanks in advance. |
Administrator
|
It's quite simple to endlessly repeat a texture using the JOGL Texture class.
E.g. take one of my routines wich render a fullscreen billboard: GL3_AnalogDistortions.java Change the init method to this, explicitly setting the texture border mode: public void init_FBORenderer(GL2 inGL,GLU inGLU,GLUT inGLUT) { mTexture_Diffuse = TextureUtils.loadImageAsTexture_UNMODIFIED(inGL,"/binaries/textures/Wallpaper_JOGAMP_MyJapanHoliday_03_1920pel.png"); mTexture_Diffuse.setTexParameterf(inGL,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); mTexture_Diffuse.setTexParameterf(inGL,GL_TEXTURE_MAG_FILTER,GL_LINEAR); mTexture_Diffuse.setTexParameterf(inGL,GL_TEXTURE_WRAP_S,GL_REPEAT); mTexture_Diffuse.setTexParameterf(inGL,GL_TEXTURE_WRAP_T,GL_REPEAT); } (its done already implicitly in my utility method, but to make things clear I set it here "once more") Also change the texture coordinates of the billboard to a "double span" vom range 0.0-2.0 instead of the "normal" 0.0-1.0: inGL.glBegin(GL_QUADS); inGL.glTexCoord2f(0.0f, 0.0f); inGL.glVertex2f(0.0f, 0.0f); inGL.glTexCoord2f(2.0f, 0.0f); inGL.glVertex2f(mBaseFrameBufferObjectRendererExecutor.getWidth(), 0.0f); inGL.glTexCoord2f(2.0f, 2.0f); inGL.glVertex2f(mBaseFrameBufferObjectRendererExecutor.getWidth(), mBaseFrameBufferObjectRendererExecutor.getHeight()); inGL.glTexCoord2f(0.0f, 2.0f); inGL.glVertex2f(0.0f, mBaseFrameBufferObjectRendererExecutor.getHeight()); inGL.glEnd(); ... this gives u a 2x2 (4 times) repeated texture |
Would someone try this code and tell me how to get it to repeat (GL_REPEAT).
Please try it. package pixelapp.samplecode; import java.awt.Cursor; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import javax.swing.JFrame; import com.jogamp.opengl.util.FPSAnimator; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureIO; public class SampleCode implements GLEventListener { // Load Textures private static ClassLoader cl; private String file[] = {"wlap1.png" }; private String folder = "pixelapp/samplecode/images/"; private JFrame myFrame; // Create JFrame object. private final int ZERO = 0; private int count = ZERO; private int acc = ZERO; // Accumulator private int NUMTEXTURES = 1; // Number of textures private Texture[] tex = new Texture[NUMTEXTURES]; private String[] fileName = new String[NUMTEXTURES]; private TextureCoords[] tc = new TextureCoords[NUMTEXTURES]; private int cubeAcc = 0; // To calculate textures private final int SQUARE_VERT = 4; private float one = 1; // Display private int NUM_CUBES_DISPLAY = 1; private final int MAX_NUM_CUBES_DISPLAY = 1; private FloatBuffer[] mVertexBufferDisplay = new FloatBuffer[MAX_NUM_CUBES_DISPLAY]; private FloatBuffer[] mColorBufferDisplay = new FloatBuffer[MAX_NUM_CUBES_DISPLAY]; private ByteBuffer[] mIndexBufferDisplay = new ByteBuffer[MAX_NUM_CUBES_DISPLAY]; private FloatBuffer[] mTexBufferDisplay = new FloatBuffer[MAX_NUM_CUBES_DISPLAY]; private ByteBuffer[] vbbDisplay = new ByteBuffer[MAX_NUM_CUBES_DISPLAY]; private ByteBuffer[] cbbDisplay = new ByteBuffer[MAX_NUM_CUBES_DISPLAY]; private ByteBuffer[] tbbDisplay = new ByteBuffer[MAX_NUM_CUBES_DISPLAY]; private float[] cubeFillerVDisplay = { 1f, 1f, 0f, 1f, -1, 0f, -1f, -1f, 0f, -1f, 1f, 0f, }; private float[] cubeFillerCDisplay = { one, one, one, one, one, one, one, one, one, one, one, one, one , one, one, one, }; private byte[] cubeFillerIDisplay = { 1 - 1, 4 - 1, 3 - 1, 1 - 1, 3 - 1, 2 - 1, }; private GLCanvas miCanvas; private FPSAnimator animator; public SampleCode() { // Create JFrame object. myFrame = new JFrame("Wavelogy"); // Close program on Finish. myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); GLProfile glp = GLProfile.getDefault(); GLCapabilities caps = new GLCapabilities(glp); miCanvas = new GLCanvas(caps); // Indicate Canvas to detect the events of OpenGL in this Class. miCanvas.addGLEventListener(this); miCanvas.setFocusable(true); // To receive key event miCanvas.requestFocus(); // Insert Canvas in the Frame. myFrame.add(miCanvas); // Hide Cursor // Transparent 16 x 16 pixel cursor image. BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); // Create a new blank cursor. Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor( cursorImg, new Point(0, 0), "blank cursor"); // Set the blank cursor to the JFrame. myFrame.getContentPane().setCursor(blankCursor); // Size of the window myFrame.setSize(1280, 600); // Eliminates the windows frames look. myFrame.setUndecorated(true); /** * Full Screen Mode */ GraphicsEnvironment env = GraphicsEnvironment. getLocalGraphicsEnvironment(); GraphicsDevice device = env.getDefaultScreenDevice(); device.setFullScreenWindow(myFrame); // Renders continuously JOGL2. animator = new FPSAnimator(miCanvas, 30); animator.add(miCanvas); animator.start(); // Get current classloader cl = this.getClass().getClassLoader(); // Display // Buffers to be passed to gl*Pointer() functions // must be direct, i.e., they must be placed on the // native heap where the garbage collector cannot // move them. // // Buffers with multi-byte datatypes (e.g., short, int, float) // must have their byte order set to native order for (cubeAcc = ZERO; cubeAcc < NUM_CUBES_DISPLAY; cubeAcc++) { vbbDisplay[cubeAcc] = ByteBuffer .allocateDirect(cubeFillerVDisplay.length * 4); vbbDisplay[cubeAcc].order(ByteOrder.nativeOrder()); mVertexBufferDisplay[cubeAcc] = vbbDisplay[cubeAcc].asFloatBuffer(); mVertexBufferDisplay[cubeAcc].put(cubeFillerVDisplay); mVertexBufferDisplay[cubeAcc].position(0); } for (cubeAcc = ZERO; cubeAcc < NUM_CUBES_DISPLAY; cubeAcc++) { cbbDisplay[cubeAcc] = ByteBuffer .allocateDirect(cubeFillerCDisplay.length * 4); cbbDisplay[cubeAcc].order(ByteOrder.nativeOrder()); mColorBufferDisplay[cubeAcc] = cbbDisplay[cubeAcc].asFloatBuffer(); mColorBufferDisplay[cubeAcc].put(cubeFillerCDisplay); mColorBufferDisplay[cubeAcc].position(0); } for (cubeAcc = ZERO; cubeAcc < NUM_CUBES_DISPLAY; cubeAcc++) { mIndexBufferDisplay[cubeAcc] = ByteBuffer .allocateDirect(cubeFillerIDisplay.length); mIndexBufferDisplay[cubeAcc].put(cubeFillerIDisplay); mIndexBufferDisplay[cubeAcc].position(0); } for (cubeAcc = ZERO; cubeAcc < NUM_CUBES_DISPLAY; cubeAcc++) { tbbDisplay[cubeAcc] = ByteBuffer.allocateDirect(SQUARE_VERT * 2 * 4); tbbDisplay[cubeAcc].order(ByteOrder.nativeOrder()); mTexBufferDisplay[cubeAcc] = tbbDisplay[cubeAcc].asFloatBuffer(); } } /** * @param args */ public static void main(String[] args) { new SampleCode(); } @Override public void init(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); // Initialize the variable GL // >> gl.glClearDepth(1.0f); // Set depth's clear-value to farthest gl.glEnable(GL2.GL_DEPTH_TEST); // Enables depth-buffer for hidden // surface removal gl.glDepthFunc(GL2.GL_LEQUAL); // The type of depth testing to do gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST); // nice perspective view, avoid texture distortion. gl.glShadeModel(GL2.GL_SMOOTH); // Enable smooth shading of color gl.glDisable(GL2.GL_DITHER); // Disable dithering for better performance // sky color background gl.glClearColor(0.17f, 0.65f, 0.92f, 0.0f); loadTexture(file, gl); // for the billboard // Align textures to edges for (count = ZERO; count < NUMTEXTURES; count++) { tc[count] = tex[count].getImageTexCoords(); } } private void loadTexture(String[] fnm, GL2 gl) { for (count = ZERO; count < NUMTEXTURES; count++) { fileName[count] = folder + fnm[count]; try { tex[count] = TextureIO.newTexture( cl.getResource(fileName[count]), false, null); tex[count].setTexParameterf(gl, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST); tex[count].setTexParameterf(gl, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST); tex[count].setTexParameterf(gl, GL2.GL_TEXTURE_WRAP_S, GL2.GL_REPEAT); tex[count].setTexParameterf(gl, GL2.GL_TEXTURE_WRAP_T, GL2.GL_REPEAT); } catch (Exception e) { System.out.println("Error loading texture " + fileName[count]); } } } @Override public void dispose(GLAutoDrawable drawable) { // TODO Auto-generated method stub } @Override public void display(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); // Initialize the variable GL /* * By default, OpenGL enables features that improve quality but reduce * performance. One might want to tweak that especially on software * renderer. */ gl.glDisable(GL2.GL_DITHER); // >> gl.glTexEnvf(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE); /* * Usually, the first thing one might want to do is to clear the screen. * The most efficient way of doing this is to use glClear(). */ gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); /* * Now we're ready to draw some 3D objects */ gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0, 0, -5.2f); gl.glEnableClientState(GL2.GL_VERTEX_ARRAY); gl.glEnableClientState(GL2.GL_COLOR_ARRAY); gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY); // Display mTexBufferDisplay[0].put(tc[0].left()); // x or s mTexBufferDisplay[0].put(2); // y or t mTexBufferDisplay[0].put(2); // x or s mTexBufferDisplay[0].put(2); // y or t mTexBufferDisplay[0].put(2); // x or s mTexBufferDisplay[0].put(tc[0].top()); // y or t mTexBufferDisplay[0].put(tc[0].left()); // x or s mTexBufferDisplay[0].put(tc[0].top()); // y or t mTexBufferDisplay[0].position(0); gl.glActiveTexture(GL2.GL_TEXTURE0); gl.glEnable(GL2.GL_TEXTURE_2D); // do not draw the transparent parts of the texture gl.glEnable(GL2.GL_BLEND); gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA); // don't show source alpha parts in the destination // determine which areas of the polygon are to be rendered gl.glEnable(GL2.GL_ALPHA_TEST); gl.glAlphaFunc(GL2.GL_GREATER, 0); // only render if alpha > 0 // Display for (acc = ZERO; acc < NUM_CUBES_DISPLAY; acc++) { tex[0].bind(gl); gl.glPushMatrix(); gl.glFrontFace(GL2.GL_CCW); gl.glVertexPointer(3, GL2.GL_FLOAT, 0, mVertexBufferDisplay[acc]); gl.glEnable(GL2.GL_TEXTURE_2D); gl.glColorPointer(4, GL2.GL_FLOAT, 0, mColorBufferDisplay[acc]); gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, mTexBufferDisplay[0]); gl.glDrawElements(GL2.GL_TRIANGLES, cubeFillerIDisplay.length, GL2.GL_UNSIGNED_BYTE, mIndexBufferDisplay[acc]); gl.glPopMatrix(); } } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL2 gl = drawable.getGL().getGL2(); // Initialize the variable GL if (height == 0) { height = 1; // to avoid division by 0 in aspect ratio below } float ratio = (float) width / height; gl.glViewport(0, 0, width, height); /* * Set our projection matrix. This doesn't have to be done each time we * draw, but usually a new projection needs to be set when the viewport * is resized. */ gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustum(-ratio, ratio, -1, 1, 1, 300); } } Thanks in advance. |
In reply to this post by Pixelapp
Ok, the solution is to load Textures in Pure Open GL without much use of the Texture Class.
|
Administrator
|
Glad you got it working Care to post your solution here? It might help others who could be out there Googling for something similar.
|
Administrator
|
In reply to this post by Pixelapp
On Sunday, November 06, 2011 06:06:44 PM pixdesk [via jogamp] wrote:
> > Ok, the solution is to load Textures in Pure Open GL without much use of the > Texture Class. > Maybe you can offer a patch to the Texture class reflecting this parameter ? ~Sven |
I searched the solution from tutorials, but I decided not to use it because there are pros and cons. So I chose to stay with the Texture class. Therefore, I don't have any code with the Pure Open GL solution.
Let me know if you want something with more depth. |
In reply to this post by Pixelapp
Ok. The idea to solve the problem is to convert an image (.png) into a Buffer object (java.nio.Buffer;).
then bind a gl object. I.e. gl.glBind(GL_TEXTURE_2D, blah), set parameters: linear, linear, glrepeat, glrepeat. Respectively. and the final step to load the texture is gl.glTexImage2D(). Which is here where you put the Buffer image as an argument of the glTexImage2D() method from javax.media.opengl.GL2 package. Note: this is some serious but very short (8 to 10 lines) coding. It should be almost identical to this: //Create Texture gl.glGenTextures(1, texture); gl.glBindTexture(GL_TEXTURE_2D, texture[0]); gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // GL_REPEAT HERE // GL_REPEAT HERE gl.glTexImage2D(GL_TEXTURE_2D, 0, 3, texLoader.getImageWidth(), texLoader.getImageHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, /** Buffer object goes here*/); NOTICE; pay close attention, I never used the Texture Class (com.jogamp.opengl.util.texture) to create textures in this. |
In reply to this post by Pixelapp
I'll give it a try. Let's all give it a try .
|
Administrator
|
To be honest I can't understand the whole point here. Theres nothing wrong with the JOGL Texture class regarding GL_REPEAT texure wrapping. The code I postet before as a simple example works fine, and I've used the Texture class setTexParameterf() dozends of times in conjunction with GL_REPEAT. It exactly does what it's supposed to do.
Sure maybe the code u posted doesn't work (haven't tested it), but I think u are looking at the wrong place here regarding ur texture wrapping bug, even though changing stg with the texture loading fixed ur problem. Please don't misunderstand my comment here, it is in no way meant to be discouraging ur efforts, but I think ur chasing ghosts by picking up on the Texture class. ps. Maybe if u need some example code on how to use the Texture class or e.g. load a texture directly via bytebuffers u may have a look at my TextureUtils.java. |
Demoscene Passivist, just try the above code (Texture class) and you will see it doesn't work.
So, everyone let's get back into coding and solving this problem. |
In reply to this post by Pixelapp
Listen, Listen, Listen. I found a complete code of the freaking problem. Finally.
http://www.java-tips.org/other-api-tips/jogl/texture-mapping-nehe-tutorial-jogl-port.html Please notice they don't use the Texture Class. We need to add this functionality to JOGAMP Texture class! Problem solved! So; Wade Walker, there you go! |
In reply to this post by Pixelapp
I hope this does the GL_REPEAT properly though.
|
Administrator
|
In reply to this post by Pixelapp
What do we need to add? Can you be more precise?
Julien Gouesse | Personal blog | Website
|
Just look at the code in the java-tips.org link above. Get GL_REPEAT to work correctly, and show it to me.
|
Ok. So here it is.
All the above code is correct, in this post. The problem with GL_REPEAT was that my texture was not power-of-two. Now, my mytexture.png is power of two and everything is fine. I didn't pick up on this simple solution because my code on Android gives me no errors, however it does in JOGL. In short, make sure your texture are power-of-two. Finally!!!!!!!!!!!!! |
Free forum by Nabble | Edit this page |