简体   繁体   中英

LWJGL textures don't render when using drawArrays

I've been trying to make a simple rendering engine in lwjgl but I've been having an issue. I moved away from Immediate mode and decided to use drawArrays. However, as soon as I try to render any textures, I see no results. No image appears. Here's my renderer class:

package com.nightfall.morningside;

import java.nio.*;

import com.nightfall.morningside.geometry.*;
import com.nightfall.morningside.windowingtoolkit.*;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.*;

public class Renderer {
    float LineWidth = 1.0f;

    public void setLineWidth(float width){
        LineWidth = width;
    }

    /*
     * you can pass a com.morningside.geometry.Rectangle to this function if you don't want to use the one with floats.
     */
    public void drawRectangle(Rectangle r, Colour fill){
        drawRectangle(r.getX1(), r.getY1(), r.getWidth(), r.getHeight(), fill);
    }

    public void drawRectangle(float x1, float y1, float w, float h, Colour fill){
        drawTriangle(x1, y1, x1 + w, y1 + h, x1, y1 + h, fill);
        drawTriangle(x1 + w, y1, x1, y1, x1 + w, y1 + h, fill);
    }

    public void drawColouredRectangle(ColouredRectangle r){
        drawColouredRectangle(r.getX1(), r.getY1(), r.getWidth(), r.getHeight(), r.getColour1(), r.getColour2(), r.getColour3(), r.getColour4());
    }

    public void drawColouredRectangle(float x1, float y1, float w, float h, Colour c1, Colour c2, Colour c3, Colour c4){
        drawColouredTriangle(x1, y1, x1 + w, y1 + h, x1, y1 + h, c1, c3, c4);
        drawColouredTriangle(x1 + w, y1, x1, y1, x1 + w, y1 + h, c2, c1, c3);
    }

    public void drawLine(Point p1, Point p2, Colour c){
        drawLine(p1.getX(), p1.getY(), p2.getX(), p2.getY(), c);
    }

    public void drawLine(float x1, float y1, float x2, float y2, Colour c){
        /*GL11.glBegin(GL11.GL_LINE_STRIP);
        GL11.glLineWidth(LineWidth);
        GL11.glColor4f(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
        GL11.glVertex2f(x1, y1);
        GL11.glVertex2f(x2, y2);
        GL11.glEnd(); */

        FloatBuffer vb = BufferUtils.createFloatBuffer(6);
        vb.put(x1).put(y1).put(0f);
        vb.put(x2).put(y2).put(0f);
        vb.flip();

        FloatBuffer cb = BufferUtils.createFloatBuffer(8);
        cb.put(c.getRed()).put(c.getBlue()).put(c.getGreen()).put(c.getAlpha());
        cb.put(c.getRed()).put(c.getBlue()).put(c.getGreen()).put(c.getAlpha());
        cb.flip();

        GL11.glEnable(GL11.GL_VERTEX_ARRAY);
        GL11.glEnable(GL11.GL_COLOR_ARRAY);

        GL11.glColorPointer(4, 4 << 2, cb);
        GL11.glVertexPointer(2, 0, vb);
        GL11.glDrawArrays(GL11.GL_LINE_STRIP, 0, 2);

        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
    }

    public void drawTriangle(Triangle t, Colour c){
        drawTriangle(t.getX1(), t.getY1(), t.getX2(), t.getY2(), t.getX3(), t.getY3(), c);
    }

    public void drawTriangle(float x1, float y1, float x2, float y2, float x3, float y3, Colour c){
        //this is the way it should be done
        FloatBuffer vb = BufferUtils.createFloatBuffer(9);
        vb.put(x1).put(y1).put(0f);
        vb.put(x2).put(y2).put(0f);
        vb.put(x3).put(y3).put(0f);
        vb.flip();

        FloatBuffer cb = BufferUtils.createFloatBuffer(12);
        cb.put(c.getRed()).put(c.getBlue()).put(c.getGreen()).put(c.getAlpha());
        cb.put(c.getRed()).put(c.getBlue()).put(c.getGreen()).put(c.getAlpha());
        cb.put(c.getRed()).put(c.getBlue()).put(c.getGreen()).put(c.getAlpha());
        cb.flip();

        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);

        GL11.glColorPointer(4, 4 << 2, cb);
        GL11.glVertexPointer(3, 3 << 2, vb);
        GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);

        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
    }

    public void drawColouredTriangle(ColouredTriangle t){
        drawColouredTriangle(t.getX1(), t.getY1(), t.getX2(), t.getY2(), t.getX3(), t.getY3(), t.getColour1(), t.getColour2(), t.getColour3());
    }

    public void drawColouredTriangle(float x1, float y1, float x2, float y2, float x3, float y3, Colour c1, Colour c2, Colour c3){
        //this is the way it should be done
        FloatBuffer vb = BufferUtils.createFloatBuffer(9);
        vb.put(x1).put(y1).put(0f);
        vb.put(x2).put(y2).put(0f);
        vb.put(x3).put(y3).put(0f);
        vb.flip();

        FloatBuffer cb = BufferUtils.createFloatBuffer(12);
        cb.put(c1.getRed()).put(c1.getGreen()).put(c1.getBlue()).put(c1.getAlpha());
        cb.put(c2.getRed()).put(c2.getGreen()).put(c2.getBlue()).put(c2.getAlpha());
        cb.put(c3.getRed()).put(c3.getGreen()).put(c3.getBlue()).put(c3.getAlpha());
        cb.flip();

        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);

        GL11.glColorPointer(4, 4 << 2, cb);
        GL11.glVertexPointer(3, 3 << 2, vb);
        GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);

        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
    }

    public void drawCircle(){
        //GL11.glBegin(GL11.gl_);
    }

    public void drawTexturedRectangle(TexturedRectangle t){
        //GL11.glColor4f(fill.getRed(), fill.getGreen(), fill.getBlue(), fill.getAlpha()); 
        drawTexturedRectangle(t.getX1(), t.getY1(), t.getWidth(), t.getHeight(), t.getTexture());
    }

    public void drawTexturedRectangle(float x1, float y1, float w, float h, Texture t){
        /*for some reason, we need to only have GL_TEXTURE_2D enabled when we're actually rendering a
          texture because otherwise weird things happen */
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        drawRectangle(x1, y1, w, h, Colour.ORANGE);

        FloatBuffer vb = BufferUtils.createFloatBuffer(2*4);
        FloatBuffer tex = BufferUtils.createFloatBuffer(2*4);

        t.bind();
        //GL11.glBindTexture(GL11.GL_TEXTURE_2D, t.id);

        vb.put(new float[] {
            // X    Y
               x1,   y1,    // <- First vertex
               x1 + w, y1,    // <- Second vertex
               x1 + w, y1 + h,  // <- Third vertex
               x1,   y1 + h   // <- Fourth vertex
        });

        tex.put(new float[] {
            // X    Y
               0,   0,    // <- First texture coord
               1,   0,    // <- Second texture coord
               1,   1,    // <- Third texture coord
               0,   1     // <- Fourth texture coord
        });

        tex.rewind();
        vb.rewind();

        GL11.glBindTexture(GL11.GL_TEXTURE_2D, t.id);

        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

        GL11.glTexCoordPointer(4, 0, tex);
        GL11.glVertexPointer(4, 0, vb);
        GL11.glDrawArrays(GL11.GL_QUADS, 0, 4);

        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
    }

    public void drawTexture(float x1, float y1, float w, float h, Texture t){
        drawTexturedRectangle(x1, y1, w, h, t);
    }


    public void drawString(String s, float x1, float y1, float width, float height, Colour c, Font f){
        GL11.glColor4f(1f, 1f, 1f, 1f);
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glPushMatrix();
        f.bind();
        GL11.glTranslatef(x1, y1, 0);
        for (int i = 0; i < s.length(); i++){
            float x = f.charAt(s.charAt(i)).getX();
            GL11.glBegin(GL11.GL_QUADS);
            {
                  GL11.glTexCoord2f(x, 0);
                  GL11.glVertex2f(i * width, 0);
                  GL11.glTexCoord2f(x, 1);
                  GL11.glVertex2f(i * width, height);
                  GL11.glTexCoord2f(x + 0.01f, 1);
                  GL11.glVertex2f(width + (i * width), height);
                  GL11.glTexCoord2f(x + 0.01f, 0);
                  GL11.glVertex2f(width + (i * width), 0);
            }
            GL11.glEnd();
        }

        GL11.glPopMatrix();

        GL11.glDisable(GL11.GL_TEXTURE_2D);
    }
}

Some of the code is still using deprecated methods, this is only because I haven't rolled everything over yet. Here is the code for the Texture class:

/*
 * Sourced code from:
 * https://github.com/mattdesl/lwjgl-basics/wiki/Textures
 * Will adapt this soon
 */

package com.nightfall.morningside;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.ByteBuffer;

import org.lwjgl.BufferUtils;

import de.matthiasmann.twl.utils.PNGDecoder;

public class Texture {

    public final int target = GL_TEXTURE_2D;
    public final int id;
    public final int width;
    public final int height;

    public static final int LINEAR = GL_LINEAR;
    public static final int NEAREST = GL_NEAREST;

    public static final int CLAMP = GL_CLAMP;
    public static final int CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE;
    public static final int REPEAT = GL_REPEAT;

    public Texture(URL pngRef) throws IOException {
        this(pngRef, GL_NEAREST);
    }

    public Texture(URL pngRef, int filter) throws IOException {
        this(pngRef, filter, GL_REPEAT);
    }

    public Texture(URL pngRef, int filter, int wrap) throws IOException {
        InputStream input = null;
        try {
            //get an InputStream from our URL
            input = pngRef.openStream();

            //initialize the decoder
            PNGDecoder dec = new PNGDecoder(input);

            //set up image dimensions 
            width = dec.getWidth();
            height = dec.getHeight();

            //System.out.println(width + "/" + height);

            //we are using RGBA, i.e. 4 components or "bytes per pixel"
            final int bpp = 4;

            //create a new byte buffer which will hold our pixel data
            ByteBuffer buf = BufferUtils.createByteBuffer(bpp * width * height);

            //decode the image into the byte buffer, in RGBA format
            dec.decode(buf, width * bpp, PNGDecoder.Format.RGBA);

            //flip the buffer into "read mode" for OpenGL
            buf.flip();

            //enable textures and generate an ID
            glEnable(target);
            id = glGenTextures();

            //bind texture
            bind();

            //setup unpack mode
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

            //setup parameters
            glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
            glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
            glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
            glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);

            //pass RGBA data to OpenGL
            glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
        } finally {
            if (input != null) {
                try { input.close(); } catch (IOException e) { }
            }
        }
    }

    public void bind() {
        glBindTexture(target, id);
    }
}

Rectangle class:

package com.nightfall.morningside.geometry;

public class Rectangle {
    private float x1;
    private float y1;
    private float width;
    private float height;

    public Rectangle(float xone, float yone, float w, float h){
        x1 = xone;
        y1 = yone;
        width = w;
        height = h;
    }

    public float getX1(){
        return x1;
    }

    public float getY1(){
        return y1;
    }

    public float getHeight(){
        return height;
    }

    public float getWidth(){
        return width;
    }

    public Point getLocation(){
        return new Point(x1, y1);
    }
}

The Point class:

package com.nightfall.morningside.geometry;

public class Point {
    private float x1;
    private float y1;

    public Point(float x, float y){
        x1 = x;
        y1 = y;
    }

    public float getX(){
        return x1;
    }

    public float getY(){
        return y1;
    }
}

And the Colour class:

package com.nightfall.morningside.windowingtoolkit;

public class Colour {
    public static final Colour RED = new Colour(1.0f, 0.0f, 0.0f);
    public static final Colour GREEN = new Colour(0.0f, 1.0f, 0.0f);
    public static final Colour BLUE = new Colour(0.0f, 0.0f, 1.0f);
    public static final Colour ORANGE = new Colour(1.0f, 0.5f, 0.0f);
    public static final Colour YELLOW = new Colour(1.0f, 1.0f, 0.0f);
    public static final Colour PURPLE = new Colour(0.5f, 0.0f, 0.5f);
    public static final Colour PINK = new Colour(1.0f, (192 / 255), (203 / 255));
    public static final Colour BLACK = new Colour(0.0f, 0.0f, 0.0f);
    public static final Colour WHITE = new Colour(1.0f, 1.0f, 1.0f);
    public static final Colour MAROON = new Colour(0.36f, 0.0f, 0.0f);

    float r;
    float g;
    float b;
    float a;

    public Colour(float red, float green, float blue){
        this(red, green, blue, 1.0f);
    }

    public Colour(float red, float green, float blue, float alpha){
        r = red;
        g = green;
        b = blue;
        a = alpha;
    }

    public Colour(int red, int green, int blue){
        this(red, green, blue, 100);
    }

    public Colour(int red, int green, int blue, int alpha){
        r = red / 255;
        g = green / 255;
        b = blue / 255;
        a = alpha / 100;
    }

    public float getRed(){
        return r;
    }

    public float getGreen(){
        return g;
    }

    public float getBlue(){
        return b;
    }

    public float getAlpha(){
        return a;
    }

    public int getRedInt(){
        return (int) r * 255;
    }

    public int getGreenInt(){
        return (int) g * 255;
    }

    public int getBlueInt(){
        return (int) b * 255;
    }

    public int getAlphaInt(){
        return (int) a * 255;
    }

    public void darken(float s){
        s = 1-s;
        r *= s;
        g *= s;
        b *= s;
    }

    public void brighten(float s){
        s++;
        r *= s;
        g *= s;
        b *= s;
    }
}

I think these classes are the only ones related to my problem - everything else is irrelevant. So basically, textures don't render as they did when using Immediate Mode, and it's getting annoying. Help is appreciated, and if these methods are deprecated, let me know because I've seen a lot of tutorials on the Internet about drawArrays.

If there's anything you need let me know and I'll post it.

Also, the rectangle that shows up when drawTexturedRectangle is called is my doing - it was to see if I'd confused my coordinates.

I think I've fixed my problem. I was specifying the wrong amount of vertices in

GL11.glTexCoordPointer(2, 0, tex);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM