texturing vertex arrays

Started by kramer, October 15, 2003, 23:39:24

Previous topic - Next topic

kramer

Hi guys,

I've been trying to texture a vertex buffer object square but had problems so thought I'll take a step back and texture a vertex array (since the syntax/concept of VA and VBO are closely related) but have had no luck.  I even tried just added some colours but that doesn't seem to have any effect either.

If anyone has a snippet of code showing how to do this, I would greatly appreciate it.

Cheers,
K

thinker

I would be happy to help, as i just got textures and materials working with vertex arrays myself.

First i would suggest getting materials working, as they are a little easier to debug then textures imo.

Do you have vertex arrays working enough to render an object?
Does it just render in full white with no material/texture?
What draw method are you using? glDrawElements or glDrawArrays, or other?

Can you paste the important lines of your code where you call the gl*Pointer() methods and the glDraw*() method(s)? Do you have lighting on?

Also make sure your buffers are flip() 'ed before passing them on to LWJGL after filling them up so the position and limit are set correctly.
...
thinker

kramer

Thanks thinker.

Yes, I can render the basic object, and yes it comes out default white.  I am using glDrawArrays() and am not using lighting.


- I call this during my init:
       GL.glEnableClientState(GL.GL_VERTEX_ARRAY);
       GL.glEnableClientState(GL.GL_COLOR_ARRAY);
       createVertexArrays();

- here is my draw call:
GL.glDrawArrays(GL.GL_QUADS, 0, 4);

- here is where I build the buffers:
   private static final void createVertexArrays()
   {
       float[] vertexes = {0f, 1f, 0f,
                           10f, 1f, 0f,
                           10f, 1f, 10f,
                           0f, 1f, 10f};
       float[] colors = {1f, 1f, 0f,
                           1f, 0f, 0f,
                           0f, 1f, 0f,
                           0f, 0f, 1f};
       buf = ByteBuffer.allocateDirect(12*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexes);
       buf.flip();
       buf2 = ByteBuffer.allocateDirect(12*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(colors);
       buf2.flip();
       GL.glVertexPointer(3, 0, buf);
       GL.glColorPointer(3, 0, buf2);
   }


If you could give me the important snippets of how you got it working, that would be great.

thinker

First try to enable lighting:

//enable lighting
GL.glEnable( GL.GL_LIGHTING );

// global ambient light
float[] ambient_light = { 1.0f, 1.0f, 1.0f, 1.0f };
ByteBuffer temp = ByteBuffer.allocateDirect( 16 );
temp.order( ByteOrder.nativeOrder() );
GL.glLightModel( GL.GL_LIGHT_MODEL_AMBIENT, temp.asFloatBuffer().put( ambient_light ) );


In my application, if i comment out the line where i enable lighting, my objects that do not have a texture will just render all white.
...
thinker

kramer

Ok, I messed around with some stuff and managed to get colors working in the example i gave above, I then tried  putting a texture on but no luck.

So I added the lighting code you gave to my init(), but no luck.  I tried it with just color pointer to see what would happen and the result is a black square.  I know the square is rendering because my background is grey.

Now I haven't messed around with OpenGl lighting before, so I may be missing some trivial thing...

thinker

Can you get textures working if you don't use a vertex arrays? Just to validate that you have the texture loaded correctly and that lighting and such is correct. Once you have that with out arrays then at least you know to focus aspects that are different.
...
thinker

kramer

Yep, I can texture in immediate mode, no problem.

I'll show you the entire program, note that there's some stuff to do with terrain in here which is not really relevent...


import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.FloatBuffer;
import org.lwjgl.*;
import org.lwjgl.opengl.*;
import org.lwjgl.input.*;

/** Main class
 */

public class VATest
{
    private final static float PI_OVER_180 = 0.0174532925f;            // ...convert between degrees and radians
    private final static int DETAIL_SCALE = 16;
    private final static String TERRAIN_TEX = "d:/tmp/tex.png";
    private final static String DETAIL_TEX = "d:/tmp/detail.png";
    
    private final static int TERRAIN_ID = 0;
    private final static int DETAIL_ID = 1;

    /** Global variable declaration */
    private static boolean finished;
    private static float xpos;
    private static float ypos = 1;
    private static float zpos;
    private static float xrot;
    private static float yrot = 180;
    private static float zrot;
private static float t=0;
    private static Object height_map;
    

static int tex;        

//private static float g_Shine = 10.0f;
//private static FloatBuffer g_ShineBuffer = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asFloatBuffer();

    private static FloatBuffer buf;
    private static FloatBuffer buf2;
    
    
    // GL context creation...
    static
    {
        try
        {
            Window.create("Basic Window", 50, 50, 800, 600, 16, 0, 8, 0); // Create The Opengl Context
        } catch (Exception e)
        {
            System.exit(1);
        }
    }



    /**
     * Main method
     */
    public static void main(String args[])
    {
        try
        {
            init(); // Init Opengl

            while (!finished)
            {
                Keyboard.poll();
                processKeyboard(); // Get Keyboard Events
                Mouse.poll();
                processMouse();
                processWindow(); // Get Window Events
                render(); // Render To Screen
                Window.update();
                Window.paint(); // Swap Opengl Buffers
            }
        } 
        catch (Throwable t)
        {
            t.printStackTrace();
        } 
        finally
        {
            cleanup();
        }
    }

    /**
     * Init opengl
     */
    private static void init() throws Exception
    {
        // load height map...
        try
        {
            FileInputStream in = new FileInputStream("d:/tmp/cds.raw");
            ObjectInputStream s = new ObjectInputStream(in);
            height_map = s.readObject();
        }
        catch (Exception e)
        { 
            e.printStackTrace();
        } 

        Keyboard.create();
        Mouse.create();

//        GL.glEnable(GL.GL_BLEND);       // alpha blending
        GL.glShadeModel(GL.GL_SMOOTH); // Enable Smooth Shading
        GL.glClearColor(0.5f, 0.5f, 0.5f, 0.0f); // Black Background
        GL.glClearDepth(1.0); // Depth Buffer Setup
        GL.glEnable(GL.GL_DEPTH_TEST); // Enables Depth Testing
        GL.glDepthFunc(GL.GL_LEQUAL); // The Type Of Depth Testing To Do

        
//enable lighting
GL.glEnable( GL.GL_LIGHTING );
// global ambient light
float[] ambient_light = { 1.0f, 1.0f, 1.0f, 1.0f };
ByteBuffer temp = ByteBuffer.allocateDirect( 16 );
temp.order( ByteOrder.nativeOrder() );
GL.glLightModel( GL.GL_LIGHT_MODEL_AMBIENT, temp.asFloatBuffer().put( ambient_light ) );
        
        
        // enable & build vertex arrays...
        GL.glEnableClientState(GL.GL_VERTEX_ARRAY);
//        GL.glEnableClientState(GL.GL_COLOR_ARRAY);
        GL.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
        createVertexArrays();
        
        GL.glMatrixMode(GL.GL_PROJECTION); // Select The Projection Matrix
        GL.glLoadIdentity(); // Reset The Projection Matrix

        // Calculate The Aspect Ratio Of The Window
        GLU.gluPerspective(45.0f, (float)Display.getWidth() / (float)Display.getHeight(), 0.1f, 100.0f);
        GL.glMatrixMode(GL.GL_MODELVIEW); // Select The Modelview Matrix

        // Really Nice Perspective Calculations
        GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);


        //sync to monitor
        GLCaps.determineAvailableExtensions();
        if(GLCaps.WGL_EXT_swap_control)
        {
            GL.wglSwapIntervalEXT(1);
        }
    }


    /**
     * main render loop
     */
    private final static void render()
    {
        GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);  // Clear Screen And Depth Buffer
        GL.glLoadIdentity();                                          // Reset The Current Modelview Matrix
                     
        GL.glRotatef(360 - yrot, 0.0f, 1.0f, 0.0f);
        GL.glTranslatef(-xpos, -ypos, -zpos);
        GL.glDrawArrays(GL.GL_QUADS, 0, 4);
    }

    private static final void createVertexArrays()
    {
        float[] vertexes = {0f, 1f, 0f,
                            10f, 1f, 0f, 
                            10f, 1f, 10f,
                            0f, 1f, 10f};
/*        float[] colors = {1f, 1f, 0f,
                            1f, 0f, 0f, 
                            0f, 1f, 0f,
                            0f, 0f, 1f};*/
        buf = ByteBuffer.allocateDirect(12*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexes);
        buf.flip();
//        buf2 = ByteBuffer.allocateDirect(12*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(colors);
//        buf2.flip();
float texCoords[]= {1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f};
FloatBuffer tex_buf = ByteBuffer.allocateDirect(2*16).order(ByteOrder.nativeOrder()).asFloatBuffer().put(texCoords);
tex_buf.flip();
tex = loadTexture("d:/tmp/detail.png");        
        GL.glVertexPointer(3, 0, buf);
//        GL.glColorPointer(3, 0, buf2);
GL.glTexCoordPointer(2, 0, tex_buf);
    }
    
    /**
     * Process keyboard events
     */
    private final static void processKeyboard()
    {
        if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
            finished = true;
        if (Keyboard.isKeyDown(Keyboard.KEY_EQUALS))
        {
            t -= .5f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_MINUS))
        {
            t += .5f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_UP))
        {
            xpos -= (float)Math.sin(yrot * PI_OVER_180) * 0.05f;
            zpos -= (float)Math.cos(yrot * PI_OVER_180) * 0.05f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_DOWN))
        {
            xpos += (float)Math.sin(yrot * PI_OVER_180) * 0.05f;
            zpos += (float)Math.cos(yrot * PI_OVER_180) * 0.05f;
        }

        Object row = Array.get(height_map, (int)xpos);
        ypos = (10 * Array.getFloat(row, (int)zpos)) + .1f;
    }

    /**
     * Process mouse events
     */
    private final static void processMouse()
    {
        yrot += Mouse.dx/10;
    }

    /**
     * Process window events
     */
    private final static void processWindow()
    {
        if (Window.isCloseRequested())
        {
            finished = true;
        }
    }

    /**
     * Cleanup
     */
    private final static void cleanup()
    {
        Keyboard.destroy(); // Destroy The Keyboard
        Window.destroy(); // Destroy The Opengl Context
    }

    /**
     * Load a texture in OpenGL memory
     */
    private final static int loadTexture(String path)
    {
        Image image = (new javax.swing.ImageIcon(path)).getImage();

        // Exctract The Image
        BufferedImage tex = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_3BYTE_BGR);
        Graphics2D g = (Graphics2D) tex.getGraphics();
        g.drawImage(image, null, null);
        g.dispose();

        // Flip Image
        AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
        tx.translate(0, -image.getHeight(null));
        AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
        tex = op.filter(tex, null);

        // Put Image In Memory
        ByteBuffer scratch = ByteBuffer.allocateDirect(4 * tex.getWidth() * tex.getHeight());

        byte data[] = (byte[]) tex.getRaster().getDataElements(0, 0, tex.getWidth(), tex.getHeight(), null);
        scratch.clear();
        scratch.put(data);
        scratch.rewind();

        // Create A IntBuffer For Image Address In Memory
        IntBuffer buf = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
        GL.glGenTextures(buf); // Create Texture In OpenGL

        GL.glBindTexture(GL.GL_TEXTURE_2D, buf.get(0));
        // Typical Texture Generation Using Data From The Image

        // Linear Filtering
        GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
        // Linear Filtering
        GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);

        // Generate The Texture
        GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, tex.getWidth(), tex.getHeight(),
                        0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, scratch);

        return buf.get(0); // Return Image Address In Memory
    }

}

kramer

Lol, I found out what I was doing wrong...

When I was cutting this example from the main app I'm working from to try and figure out vertex arrays, I inadvertantly cut out this line:

       GL.glEnable(GL.GL_TEXTURE_2D);

No wonder I couldn't get any texturing... heh

thinker

ahh, great. glad it works for you now :)
...
thinker