JOGL GL2.GL_REPEAT

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

JOGL GL2.GL_REPEAT

Pixelapp
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.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Demoscene Passivist
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
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Pixelapp
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.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Pixelapp
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.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Wade Walker
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.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Sven Gothel
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
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Pixelapp
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.

Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Pixelapp
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.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Pixelapp
In reply to this post by Pixelapp
I'll give it a try. Let's all give it a try .
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Demoscene Passivist
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.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Pixelapp
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.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Pixelapp
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!
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Pixelapp
In reply to this post by Pixelapp
I hope this does the GL_REPEAT properly though.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

gouessej
Administrator
In reply to this post by Pixelapp
What do we need to add? Can you be more precise?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Pixelapp
Just look at the code in the java-tips.org link above. Get GL_REPEAT to work correctly, and show it to me.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL GL2.GL_REPEAT

Pixelapp
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!!!!!!!!!!!!!