用lwjgl在现代OpenGL中绘制纹理

时间:2014-03-23 17:48:46

标签: java opengl textures lwjgl

我试图在这个tutorial中使用java中的opengl绘制纹理,一切都运行良好,直到我试图绘制纹理。它只绘制了一个彩色的盒子,但没有纹理。

这是我的代码:

package main;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.Scanner;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;

//OpenGL version: 4.4.0

public class OpenGLTester {

    final static int SIZE_OF_FLOAT = 4;

    final int screenWidth = 1000;
    final int screenHeight = 800;

    int program;

    final float[] vertices = { 
        //  Position      Color             Texcoords
            -0.5f,  0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-left
             0.5f,  0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-right
             0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-right
            -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f  // Bottom-left
    };

    final byte[] elements = {
            0, 1, 2,
            2, 3, 0
    };

    private int vao;

    private int vbo;

    private int vertexShader;

    private int fragmentShader;

    private int ebo;

    private FloatBuffer verticiesBuffer;

    private ByteBuffer indicesBuffer;

    private Texture texture;

    public OpenGLTester() {
        createDisplay();    
        initOpenGL();

        while(!Display.isCloseRequested()) {            
            // Clear the screen to black
            glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);

            texture.bind();

            glDrawElements(GL_TRIANGLES, indicesBuffer);

            Display.update();
            Display.sync(60);
        }

        glDeleteProgram(program);
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);

        glDeleteBuffers(vbo);
        glDeleteBuffers(ebo);

        glDeleteVertexArrays(vao);

        texture.release();
    }

    private void createDisplay() {
        //make display (this also automatically sets up the open glcontext
        try {
            Display.setDisplayMode(new DisplayMode(screenWidth, screenHeight));
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
        }
    }

    private void initOpenGL() {
        //do vao shit that is shit
        vao = glGenVertexArrays();
        glBindVertexArray(vao);

        //give it the vertices, indices, and texture
        vbo = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        verticiesBuffer = BufferUtils.createFloatBuffer(vertices.length);
        verticiesBuffer.put(vertices);
        verticiesBuffer.flip();
        glBufferData(GL_ARRAY_BUFFER, verticiesBuffer, GL_STATIC_DRAW);

        indicesBuffer = BufferUtils.createByteBuffer(elements.length);
        indicesBuffer.put(elements);
        indicesBuffer.flip();   

        int tex = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, tex);
        try {
            texture = TextureLoader.getTexture("PNG", new FileInputStream("texture.png"));
            ByteBuffer textureByteBuffer = BufferUtils.createByteBuffer(texture.getTextureData().length);
            textureByteBuffer.put(texture.getTextureData());
            textureByteBuffer.flip();

            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (int)texture.getWidth(), (int)texture.getHeight(), 0, GL_RGB, GL_BYTE, textureByteBuffer);
        } catch (IOException e) {
            System.out.println("texture didnt load correctly.");
        }

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);       

        //read in and compile the vertex shader
        vertexShader = glCreateShader(GL_VERTEX_SHADER);
        String vertexShaderSource = readInFile("VertexShader.txt");
        glShaderSource(vertexShader, vertexShaderSource);
        glCompileShader(vertexShader);

        System.out.println(glGetShaderInfoLog(vertexShader, 512));  //print errors from vertex shader

        //read in and compile the fragment shader
        fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        String fragmentShaderSource = readInFile("FragmentShader.txt");
        glShaderSource(fragmentShader, fragmentShaderSource);
        glCompileShader(fragmentShader);

        System.out.println(glGetShaderInfoLog(fragmentShader, 512)); //print errors from fragment shader

        //combine the vertex and fragment shader into a program
        program = glCreateProgram();
        glAttachShader(program, vertexShader);
        glAttachShader(program, fragmentShader);
        glBindFragDataLocation(program, 0, "outColor");
        glLinkProgram(program);
        glUseProgram(program);


        //tell opengl how to read in the vertex data
        int positionAttribute = glGetAttribLocation(program, "position");
        glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, false, 7 * SIZE_OF_FLOAT, 0);
        glEnableVertexAttribArray(positionAttribute);

        int colorAttribute = glGetAttribLocation(program, "color");
        glVertexAttribPointer(colorAttribute, 3, GL_FLOAT, false, 7 * SIZE_OF_FLOAT, 2 * SIZE_OF_FLOAT);
        glEnableVertexAttribArray(colorAttribute);

        int texAttrib = glGetAttribLocation(program, "texcoord");
        glVertexAttribPointer(texAttrib, 2, GL_FLOAT, false, 7 * SIZE_OF_FLOAT, 5 * SIZE_OF_FLOAT);
        glEnableVertexAttribArray(texAttrib);

        ebo = glGenBuffers();
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, ebo, GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }

    private String readInFile(String name) {
        File f = new File(name);

        String out = "";

        try {
            Scanner s = new Scanner(f);

            while(s.hasNextLine()) {
                out += s.nextLine() + "\n";
            }
            s.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return out;
    }

    public static void main(String[] args) {
        new OpenGLTester();
    }

}

这是我的顶点着色器:

#version 150

in vec2 position;
in vec3 color;
in vec2 texcoord;

out vec3 Color;
out vec2 Texcoord;

void main() {
    Color = color;
    gl_Position = vec4(position, 0.0, 1.0);
    Texcoord = texcoord;
}

和我的片段着色器

#version 150

in vec3 Color;
in vec2 Texcoord;

out vec4 outColor;

uniform sampler2D tex;

void main()
{
    outColor = texture(tex, Texcoord) * vec4(Color, 1.0);
}

1 个答案:

答案 0 :(得分:1)

uniform不是魔法。您必须抓住他们的位置(glGetUniformLocation())并实际上传一些内容(glUniform()),以便包含有用信息。

与纹理单元索引类似,例如:

...

int texAttrib = glGetAttribLocation(program, "texcoord");
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, false, 7 * SIZE_OF_FLOAT, 5 * SIZE_OF_FLOAT);
glEnableVertexAttribArray(texAttrib);

int texUnit = 0;
int texUniform = glGetUniformLocation( program, "tex" );
glUniform1i( texUniform, texUnit );
glActiveTexture( GL_TEXTURE0 + texUnit );
glBindTexture( GL_TEXTURE_2D, tex );

...