我试图在正交模式下进行2D图形处理。该代码加载了一张猫和2个简单着色器的图片,这些着色器只是通过它们的输入,未经修改。我希望程序能够在屏幕中间显示猫的图片(或者至少是它的一部分),没有任何旋转或歪斜。
程序执行成功,但我无法弄清楚结果如下所示:
OpenGL大师可能会很快发现问题,但我无法找到它。我觉得问题可能出在"创建缓冲区的顶点和纹理坐标"部分,但一切都很好。
猫图片:
顶点着色器:
#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);
}
}
}
答案 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);