lwjgl - 仅在四边形上渲染的左上角像素

时间:2016-05-13 09:14:42

标签: java opengl lwjgl

过去几天我一直在尝试将纹理缩放到Quad(OpenGL 3)......

但由于某种原因,我只得到渲染到四边形的图像的左上角像素,我使用Slick-Utils来加载和绑定纹理....

以下是代码:

MainGame.java

package test.game;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.PixelFormat;
import org.newdawn.slick.opengl.Texture;

import test.engine.Loader;
import test.engine.rendersystem.Model;
import test.engine.rendersystem.ShaderProgram;

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

import java.io.IOException;
import java.util.HashMap;

public class MainGame {

// Constants
public static final String WINDOW_TITLE = "Neon Indev";
public static final int WIDTH = 800;
public static final int HEIGHT = 480;
public static final ContextAttribs OPENGL_CONTEXTS_ATTRIBS = new ContextAttribs(3, 2).withForwardCompatible(true).withProfileCore(true);
public static final int SYNC_FPS = 60;

static float[] vertexData = 
    {
            -0.5f, 0.5f,
            0.5f, 0.5f,
            0.5f, -0.5f,
            -0.5f, -0.5f
    };
static float[] colorData = { 0f, 1f, 1f, 1f,
                            0f, 1f, 1f, 1f,
                            0f, 1f, 1f, 1f,
                            0f, 1f, 1f, 1f,
                            0f, 1f, 1f, 1f,
                            0f, 1f, 1f, 1f};
static int[] indexData = {
        0, 1, 3,
        3, 1, 2
};

static float[] texData = {
        0,0,
        1,0,
        1,1,
        0,1
};

static Model model;
static ShaderProgram shader;
static Texture testTexture;

public static void main(String[] args) {
    init();
    render();
}

private static void init() {
    // Display Initialization
    try {
        Display.setTitle(WINDOW_TITLE);
        Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
        Display.create(new PixelFormat(), OPENGL_CONTEXTS_ATTRIBS);
    } catch (LWJGLException e) {
        e.printStackTrace();
        System.exit(1);
    }

    // OpenGL Initialization
    glViewport(0, 0, WIDTH, HEIGHT);
    glClearColor(0f, 0f, 0f, 1f);

    model = new Model(vertexData, colorData, indexData);
    try {
        testTexture = Loader.loadTexture("res/images/png/image02 (1).png", "PNG");
    } catch (IOException e) {
        e.printStackTrace();
        System.exit(1);
    }
    model.setTexture(testTexture, texData);


    // Shader Initialization
    HashMap<String, Integer> vboDataToBind = new HashMap<String, Integer>();
    vboDataToBind.put("in_Position", Model.ATTRIB_VERTEX);
    vboDataToBind.put("in_Color", Model.ATTRIB_COLOR);
    vboDataToBind.put("in_TextureCoord", Model.ATTRIB_TEXTURE);

    shader = new ShaderProgram("res/shaders/frag/color.frag", "res/shaders/vert/color.vert", true, true, vboDataToBind);
}

private static void render() {
    // Resize Check
    if (Display.wasResized()) {
        resize();
    }

    // Render loop
    while (!Display.isCloseRequested()) {

        glClear(GL_COLOR_BUFFER_BIT);

        shader.bind();
        model.render();
        shader.unbind();

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

    // Dispose if out of the loop
    dispose();
}

private static void resize() {
    // Resize code goes here
}

private static void dispose() {
    model.dispose();
    shader.dispose();
    Display.destroy();
}

}

ShaderProgram.java

package test.game.engine.rendersystem;

import java.io.IOException;
import java.util.HashMap;
import java.util.Set;

import test.engine.Loader;

import static org.lwjgl.opengl.GL20.*;

public class ShaderProgram {

String fragmentShader;
String vertexShader;

int programID, vertexShaderID, fragmentShaderID;
boolean initialized;

public ShaderProgram(String fragmentShader, String vertexShader, boolean url, boolean init, HashMap<String, Integer> vboDataToBind) {
    if (url) {
        try {
            this.fragmentShader = Loader.getStringFromTextFile(fragmentShader);
            this.vertexShader = Loader.getStringFromTextFile(vertexShader);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    } else {
        this.fragmentShader = fragmentShader;
        this.vertexShader = vertexShader;
    }

    if (init) {
        init(vboDataToBind);
        this.initialized = true;
    } else {
        this.initialized = false;
    }
}

public void init(HashMap<String, Integer> vboDataToBind) {
    if (!initialized) {
        // Initialize the shaders
        vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
        fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

        // Setting up the shader values
        glShaderSource(vertexShaderID, vertexShader);
        glShaderSource(fragmentShaderID, fragmentShader);

        // Compile the shaders
        glCompileShader(vertexShaderID);
        glCompileShader(fragmentShaderID);

        // Create the shader program and attach them
        programID = glCreateProgram();
        glAttachShader(programID, vertexShaderID);
        glAttachShader(programID, fragmentShaderID);

        // Bind any needed data
        if (!vboDataToBind.isEmpty()) {
            Set<String> keys = vboDataToBind.keySet();
            for (String key : keys) {
                bindVBOAttrib(vboDataToBind.get(key), key);
            }
        }

        // Link and validate the program
        glLinkProgram(programID);
        glValidateProgram(programID);
    }
}

public void bind() {
    glUseProgram(programID);
}

public void unbind() {
    glUseProgram(0);
}

public void dispose() {
    glDeleteProgram(programID);
    glDeleteShader(vertexShaderID);
    glDeleteShader(fragmentShaderID);
}

public void bindVBOAttrib(int attribNumber, String variableName) {
    glBindAttribLocation(programID, attribNumber, variableName);
}

public String getFragmentShader() {
    return fragmentShader;
}
public String getVertexShader() {
    return vertexShader;
}

public int getProgramID() {
    return programID;
}

public int getVertexShaderID() {
    return vertexShaderID;
}

public int getFragmentShaderID() {
    return fragmentShaderID;
}
}

顶点着色器:

#version 150 core

in vec4 in_Position;
in vec4 in_Color;
in vec2 in_TextureCoord;

out vec4 pass_Color;
out vec2 pass_TextureCoord;

void main(void) {
gl_Position = in_Position;

pass_Color = in_Color;
pass_TextureCoord = in_TextureCoord;
}

Fragment Shader:

#version 150 core

uniform sampler2D texture_diffuse;

in vec4 pass_Color;
in vec2 pass_TextureCoord;

out vec4 out_Color;

void main(void) {
out_Color = pass_Color;
// Override out_Color with our texture pixel
out_Color = texture(texture_diffuse, pass_TextureCoord);
}

Loader.java

package test.game.engine;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;

public class Loader {

public static String getStringFromTextFile(String url) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(new File(url)));
    String line;
    StringBuilder response = new StringBuilder();
    while ((line = reader.readLine()) != null) {
        response.append(line).append("\n");
    }
    reader.close();
    return response.toString();
}

public static Texture loadTexture(String url, String format) throws IOException {
    return TextureLoader.getTexture(format, ResourceLoader.getResourceAsStream(url));
}

}

Model.java

package test.game.engine.rendersystem;

import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL11.*;

import org.newdawn.slick.opengl.Texture;

public class Model {

// Attribute Numbers
public static final int ATTRIB_VERTEX = 0;
public static final int ATTRIB_INDEX = 1;
public static final int ATTRIB_COLOR = 2;
public static final int ATTRIB_TEXTURE = 3;

// Dimensions
public static final int DIMEN_VERTEX = 2;
public static final int DIMEN_INDEX = 1;
public static final int DIMEN_COLOR = 4;
public static final int DIMEN_TEXTURE = 2;

int vaoID;
int vertexCount;
VBO vertexData;
VBO colorData;
VBO textureData;
IntVBO indexData;

boolean textured;
Texture texture;

public Model(float[] vertexData, float[] colorData, int[] indexData) {
    this.vertexCount = vertexData.length;
    this.vaoID = glGenVertexArrays();
    this.textured = false;

    bindVertexArray();
    this.vertexData = new VBO(ATTRIB_VERTEX, vaoID, vertexData, DIMEN_VERTEX, true);
    this.colorData = new VBO(ATTRIB_COLOR, vaoID, colorData, DIMEN_COLOR, true);
    this.indexData = new IntVBO(ATTRIB_INDEX, vaoID, indexData, DIMEN_INDEX, true);
    unbindVertexArray();
}

public boolean isTextured() {
    return textured;
}

public void setTexture(Texture texture, float[] texCoords) {
    this.textured = true;
    this.textureData = new VBO(ATTRIB_TEXTURE, vaoID, texCoords, DIMEN_TEXTURE, true);
    this.texture = texture;
}

public void unbindVertexArray() {
    glBindVertexArray(0);
}

public void bindVertexArray() {
    glBindVertexArray(vaoID);
}

public void dispose() {
    vertexData.dispose();
    colorData.dispose();
    indexData.dispose();
    glDeleteVertexArrays(vaoID);
}

public void render() {
    bindVertexArray();
    colorData.bind();
    vertexData.bind();
    if (textured) textureData.bind();
    indexData.bind();

    vertexData.enable();
    if (textured) textureData.enable();
    colorData.enable();
    indexData.enable();

    // Loading in the texture data
    if (textured) {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture.getTextureID());
    }

    glDrawElements(GL_TRIANGLES, this.vertexCount, GL_UNSIGNED_INT, 0);

    colorData.disable();
    vertexData.disable();
    indexData.disable();
    if (textured) textureData.disable();

    vertexData.unbind();
    colorData.unbind();
    indexData.unbind();
    if (textured) textureData.disable();

    unbindVertexArray();
}
}

VBO.java

package test.game.engine.rendersystem;

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

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;

import static org.lwjgl.opengl.GL15.*;

public class VBO {

public int vboID;
public int attributeNumber;
public int vaoID;
public int dataDimensions;
public float[] data;

public VBO(int attributeNumber, int vaoID, float[] data, int dimensions, boolean loadToVBO) {
    this.attributeNumber = attributeNumber;
    this.vaoID = vaoID;
    this.data = data;
    this.dataDimensions = dimensions;

    if (loadToVBO) {
        loadToVBO();
    }
}

public void loadToVBO() {
    this.vboID = glGenBuffers();
    bind();
    glBufferData(GL_ARRAY_BUFFER, storeDataInFloatBuffer(), GL_STATIC_DRAW);
    glVertexAttribPointer(attributeNumber, dataDimensions, GL_FLOAT, false, 0, 0);
    unbind();
}

public void bind() {
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
}

public void unbind() {
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

public void enable() {
    glEnableVertexAttribArray(attributeNumber);
}

public void disable() {
    glDisableVertexAttribArray(attributeNumber);
}

public void dispose() {
    glDeleteBuffers(vboID);
}

private FloatBuffer storeDataInFloatBuffer() {
    FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
    buffer.put(data);
    buffer.flip();
    return buffer;
}

}

这是我想要渲染的图像(它是一个测试图像)(它是在PNG中) 一头牛:

enter image description here

这是我得到的输出。四边形上的一头牛:

enter image description here

P.S我是OpenGL和低级图形API的新手....如果我做了任何新手/ noob错误,请原谅我。

1 个答案:

答案 0 :(得分:0)

我相信你的问题在于:

public void setTexture(Texture texture, float[] texCoords) { 
this.textured = true; 
this.textureData = new VBO(ATTRIB_TEXTURE, vaoID, texCoords, DIMEN_TEXTURE, true);
this.texture = texture; 
}

当您创建初始vbos时,您绑定了VAO然后解除绑定它允许绘图发生,但是当您添加纹理坐标时,没有绑定VAO导致您的vbo绑定到任何内容。然后调用渲染并找到没有任何内容的纹理坐标,因此使用默认的0; 0坐标,也就是单角像素。