带着色器的LWJGL纹理产生了倾斜的图像

时间:2017-01-07 20:28:17

标签: opengl lwjgl

我试图在正交模式下进行2D图形处理。该代码加载了一张猫和2个简单着色器的图片,这些着色器只是通过它们的输入,未经修改。我希望程序能够在屏幕中间显示猫的图片(或者至少是它的一部分),没有任何旋转或歪斜。

程序执行成功,但我无法弄清楚结果如下所示:

Screenshot

OpenGL大师可能会很快发现问题,但我无法找到它。我觉得问题可能出在"创建缓冲区的顶点和纹理坐标"部分,但一切都很好。

猫图片:

cat

顶点着色器:

#version 150 core

in vec4 in_Position;
in vec2 in_TextureCoord;

out vec2 pass_TextureCoord;

void main(void) {
    gl_Position = in_Position;

    pass_TextureCoord = in_TextureCoord;
}

像素着色器:

#version 150 core

uniform sampler2D texture_diffuse;
in vec2 pass_TextureCoord;
out vec4 out_Color;

void main(void) {
    out_Color = texture(texture_diffuse, pass_TextureCoord);
}

Java(LWJGL)代码:

package lwjgl_test1;

import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.*;

import javax.imageio.ImageIO;

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

import static org.lwjgl.glfw.GLFW.*;
import java.util.concurrent.TimeUnit;
import static org.lwjgl.opengl.GL11.*;


public class Main {
    public static void main(String[] args) {
        try {
            if (!glfwInit()) {
                throw(new Exception("Can't init glfw."));
            }

            /*
             * Create Window
             */
            glfwWindowHint(GLFW_RESIZABLE, 0);
            long windowGlID = glfwCreateWindow(1024, 768, "Example OpenGL App", 0, 0);

            glfwSetWindowPos(windowGlID, 50, 50);
            glfwMakeContextCurrent(windowGlID);
            glfwShowWindow(windowGlID);

            /*
             * Initialize OpenGL
             */
            GL.createCapabilities();

            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glOrtho(0, 1024, 768, 0, 0, 1);
            glMatrixMode(GL_MODELVIEW);

            /*
             * Load texture
             */
            int cat = loadTexture("cat.png");

            /*
             * Load shaders
             */
            int vertexShader = loadShader("vertex_shader.txt", GL20.GL_VERTEX_SHADER);
            int pixelShader = loadShader("pixel_shader.txt", GL20.GL_FRAGMENT_SHADER);

            int pId = GL20.glCreateProgram();
            GL20.glAttachShader(pId, vertexShader);
            GL20.glAttachShader(pId, pixelShader);

            // Position information will be attribute 0
            GL20.glBindAttribLocation(pId, 0, "in_Position");
            // Textute information will be attribute 1
            GL20.glBindAttribLocation(pId, 1, "in_TextureCoord");

            GL20.glLinkProgram(pId);
            GL20.glValidateProgram(pId);

            exitOnGLError("Compiling shaders failed.");

            /*
             * Create buffer for vertex and texture coordinates
             */
            float size = 120.0f;

            FloatBuffer vertex_data = BufferUtils.createFloatBuffer(20);
            vertex_data.put(new float[] { -size, -size, 0f, 0f, 0f });  // (Vx, Vy, Vz, Tx, Ty)
            vertex_data.put(new float[] { size, -size, 0f, 0f, 1f });
            vertex_data.put(new float[] { size, size, 0f, 1f, 1f });
            vertex_data.put(new float[] { -size, size, 0f, 1f, 0f });
            vertex_data.flip();

            int vbo_vertex_handle = GL15.glGenBuffers();
            GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_vertex_handle);
            GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertex_data, GL15.GL_STATIC_DRAW);

            GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 2 * 4, 0);   // mark vertex coordinates
            GL20.glVertexAttribPointer(1, 2, GL11.GL_FLOAT, false, 3 * 4, 3 * 4);   // mark texture coordinates

            GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
            GL30.glBindVertexArray(0);

            exitOnGLError("Creating buffers failed.");

            /*
             * Main rendering loop
             */
            while(true) {
                /*
                 * Clear screen
                 */
                glClearColor(0.0f, 1.0f, 1.0f, 0.0f);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                /*
                 * Apply shader program
                 */
                GL20.glUseProgram(pId);

                // Bind the texture
                GL13.glActiveTexture(GL13.GL_TEXTURE0);
                GL11.glBindTexture(GL11.GL_TEXTURE_2D, cat);

                /*
                 * Draw (use buffers)
                 */
                GL20.glEnableVertexAttribArray(0);
                GL20.glEnableVertexAttribArray(1);

                GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_vertex_handle);
                GL11.glDrawArrays(GL11.GL_QUADS, 0, 4); // Draw an entity with 4 vertices
                GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

                exitOnGLError("Draw failed.");

                GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
                GL20.glUseProgram(0); // deselect

                /*
                 * Swap buffers
                 */
                glfwSwapBuffers(windowGlID);

                /*
                 * Events
                 */
                glfwPollEvents();
                if (glfwWindowShouldClose(windowGlID)) {
                    break;
                }

                TimeUnit.MILLISECONDS.sleep(10);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static int loadTexture(String path) throws Exception {
        int[] pixels = null;
        BufferedImage image = null;

        image = ImageIO.read(new FileInputStream(path));
        int width = image.getWidth();
        int height = image.getHeight();
        pixels = new int[width * height];
        image.getRGB(0, 0, width, height, pixels, 0, width);

        int[] data = new int[width * height];
        for (int i = 0; i < width * height; i++) {
            int a = (pixels[i] & 0xff000000) >> 24;
            int r = (pixels[i] & 0xff0000) >> 16;
            int g = (pixels[i] & 0xff00) >> 8;
            int b = (pixels[i] & 0xff);

            data[i] = a << 24 | b << 16 | g << 8 | r;
        }

        IntBuffer intBuffer1 = ByteBuffer.allocateDirect(data.length << 2).order(ByteOrder.nativeOrder()).asIntBuffer();
        intBuffer1.put(data).flip();

        int result = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, result);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, intBuffer1);
        glBindTexture(GL_TEXTURE_2D, 0);

        exitOnGLError("Loading texture '"+ path +"' failed.");

        return result;
    }

    private static int loadShader(String filename, int type) {
        StringBuilder shaderSource = new StringBuilder();
        int shaderID = 0;

        try {
            BufferedReader reader = new BufferedReader(new FileReader(filename));
            String line;
            while ((line = reader.readLine()) != null) {
                shaderSource.append(line).append("\n");
            }
            reader.close();
        } catch (IOException e) {
            System.err.println("Could not read file.");
            e.printStackTrace();
            System.exit(-1);
        }

        shaderID = GL20.glCreateShader(type);
        GL20.glShaderSource(shaderID, shaderSource);
        GL20.glCompileShader(shaderID);

        if (GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
            System.err.println("Could not compile shader.");
            System.exit(-1);
        }

        return shaderID;
    }

    private static void exitOnGLError(String errorMessage) throws Exception {
        int errorValue = GL11.glGetError();

        if (errorValue != GL11.GL_NO_ERROR) {
            throw new Exception(errorMessage);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

问题出在这一行的stride参数中:

GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 2 * 4, 0);
GL20.glVertexAttribPointer(1, 2, GL11.GL_FLOAT, false, 3 * 4, 3 * 4);

Stride告诉OpenGL两个连续条目的开头相互之间有多少字节。由于每个顶点使用5个浮点数,因此在两行中都必须为5 * 4

GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 5 * 4, 0);
GL20.glVertexAttribPointer(1, 2, GL11.GL_FLOAT, false, 5 * 4, 3 * 4);