使用drawArrays时,LWJGL纹理不会渲染

时间:2013-10-19 05:31:04

标签: java opengl graphics lwjgl

我一直在尝试用lwjgl创建一个简单的渲染引擎,但我一直有问题。我离开了立即模式并决定使用drawArrays。但是,只要我尝试渲染任何纹理,我就看不到任何结果。没有图像出现。 这是我的渲染器类:

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);
    }
}

有些代码仍然使用不推荐使用的方法,这只是因为我尚未推出所有内容。这是Texture类的代码:

/*
 * 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);
    }
}

矩形类:

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);
    }
}

Point类:

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;
    }
}

Color类:

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;
    }
}

我认为这些课程是唯一与我的问题相关的课程 - 其他一切都无关紧要。所以基本上,纹理不会像使用立即模式时那样渲染,而且它变得很烦人。感谢帮助,如果不推荐使用这些方法,请告诉我,因为我在互联网上看过很多关于drawArrays的教程。

如果你需要什么,请告诉我,我会发布。

此外,调用drawTexturedRectangle时显示的矩形是我正在做的 - 这是为了看看我是否混淆了我的坐标。

1 个答案:

答案 0 :(得分:0)

我想我已经解决了我的问题。我在

中指定了错误的顶点数量
GL11.glTexCoordPointer(2, 0, tex);