【问题标题】:Drawing a texture in modern OpenGL with lwjgl使用 lwjgl 在现代 OpenGL 中绘制纹理
【发布时间】:2014-03-24 04:48:37
【问题描述】:

我正在尝试使用 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);
}

【问题讨论】:

  • 请同时发布您的着色器代码。
  • 你在哪里设置你的tex制服?我在您的 Java 代码中没有看到任何与统一相关的内容。
  • 教程中没有设置制服,但如果我要设置它,我会传入什么? sampler2D 吸收了什么?

标签: java opengl textures lwjgl


【解决方案1】:

uniforms 不是魔法。您必须获取他们的位置 (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 );

...

【讨论】:

  • 制服我应该上传什么?纹理字节数据?感谢您的帮助!
  • @MattCaswell:纹理绑定到的纹理单元的索引。见编辑。
  • 我在你给的代码里加了,现在什么都画不出来了,就连之前画的彩盒也没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多