在LWJGL中渲染3D立方体,需要以下几个步骤:
下面是一个简单的示例代码:
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.system.MemoryUtil.*;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWCursorPosCallback;
import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWMouseButtonCallback;
import org.lwjgl.glfw.GLFWScrollCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLCapabilities;
import org.lwjgl.system.MemoryUtil;
public class LWJGLDemo {
private static final int WIDTH = 1280;
private static final int HEIGHT = 720;
private static final float[] VERTICES = {
// Front face
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
// Back face
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
// Top face
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
// Bottom face
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Right face
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
// Left face
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
};
private static final float[] TEXTURE_COORDS = {
// Front face
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
// Back face
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
// Top face
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
// Bottom face
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
// Right face
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
// Left face
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
};
private static final int[] INDICES = {
// Front face
0, 1, 2,
2, 3, 0,
// Top face
4, 5, 6,
6, 7, 4,
// Back face
8, 9, 10,
10, 11, 8,
// Bottom face
12, 13, 14,
14, 15, 12,
// Right face
16, 17, 18,
18, 19, 16,
// Left face
20, 21, 22,
22, 23, 20,
};
private long window;
private int texture;
private int vao;
private int vbo;
private int ebo;
private int shaderProgram;
public static void main(String[] args) {
new LWJGLDemo().run();
}
private void run() {
// Initialize GLFW
if (!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW");
}
// Configure GLFW
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
// Create the window
window = glfwCreateWindow(WIDTH, HEIGHT, "LWJGL Demo", NULL, NULL);
if (window == NULL) {
throw new RuntimeException("Failed to create the GLFW window");
}
// Setup callbacks
GLFWFramebufferSizeCallback fbCallback = new GLFWFramebufferSizeCallback() {
public void invoke(long window, int width, int height) {
glViewport(0, 0, width, height);
}
};
glfwSetFramebufferSizeCallback(window, fbCallback);
// Make the OpenGL context current
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
// Make the window visible
glfwShowWindow(window);
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the GLCapabilities instance and makes the OpenGL
// bindings available for use.
GLCapabilities caps = GL.createCapabilities();
// Set the clear color
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// Initialize the shader program
shaderProgram = createShaderProgram();
// Initialize the vertex data
vao = glGenVertexArrays();
glBindVertexArray(vao);
vbo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, toFloatBuffer(VERTICES), GL_STATIC_DRAW);
ebo = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, toIntBuffer(INDICES), GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * 4, 0);
glEnableVertexAttribArray(0);
// Texture coordinate attribute
glVertexAttribPointer(1, 2, GL_FLOAT, false, 2 * 4, 3 * 4 * VERTICES.length);
glEnableVertexAttribArray(1);
// Initialize the texture
texture = glGenTextures();
glBindTexture(GL_TEXTURE_2D, texture);
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);
// Load the texture
int[] width = new int[1];
int[] height = new int[1];
int[] channels = new int[1];
ByteBuffer data = stbi_load("texture.jpg", width, height, channels, 0);
if (data != null) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width[0], height[0], 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
throw new RuntimeException("Failed to load texture");
}
stbi_image_free(data);
// Game loop
while (!glfwWindowShouldClose(window)) {
// Poll events
glfwPollEvents();
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Bind the shader program
glUseProgram(shaderProgram);
// Bind the texture
glBindTexture(GL_TEXTURE_2D, texture);
// Draw the cube
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, INDICES.length, GL_UNSIGNED_INT, 0);
// Swap the buffers
glfwSwapBuffers(window);
}
// Cleanup
glDeleteVertexArrays(vao);
glDeleteBuffers(vbo);
glDeleteBuffers(ebo);
glDeleteTextures(texture);
glDeleteProgram(shaderProgram);
// Terminate GLFW
glfwTerminate();
}
private int createShaderProgram() {
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, "#version 330 core\n" +
"layout(location = 0) in vec3 aPos;\n" +
"layout(location = 1) in vec2 aTexCoord;\n" +
"out vec2 TexCoord;\n" +
"uniform mat4 projection;\n" +
"uniform mat4 view;\n" +
"uniform mat4 model;\n" +
"void main()\n" +
"{\n" +
" gl_Position = projection * view * model * vec4(aPos, 1.0);\n" +
" TexCoord = aTexCoord;\n" +
"}\n");
glCompileShader(vertexShader);
if (glGetShaderi(vertexShader, GL_COMPILE_STATUS) == GL_FALSE) {
throw new RuntimeException("Failed to compile vertex shader: " + glGetShaderInfoLog(vertexShader));
}
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, "#version 330 core\n" +
"out vec4 FragColor;\n" +
"in vec2 TexCoord;\n" +
"uniform sampler2D texture1;\n" +
"void main()\n" +
"{\n" +
" FragColor = texture(texture1, TexCoord);\n" +
"}\n");
glCompileShader(fragmentShader);
if (glGetShaderi(fragmentShader, GL_COMPILE_STATUS) == GL_FALSE) {
throw new RuntimeException("Failed to compile fragment shader: " + glGetShaderInfoLog(fragmentShader));
}
int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
if (glGetProgrami(shaderProgram, GL_LINK_STATUS) == GL_FALSE) {
throw new RuntimeException("Failed to link shader program: " + glGetProgramInfoLog(shaderProgram));
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return shaderProgram;
}
private FloatBuffer toFloatBuffer(float[] data) {
FloatBuffer buffer = MemoryUtil.memAllocFloat(data.length);
buffer.put(data).flip();
return buffer;
}
private IntBuffer toIntBuffer(int[] data) {
IntBuffer buffer = MemoryUtil.memAllocInt(data.length);
buffer.put(data).flip();
return buffer;
}
}
领取专属 10元无门槛券
手把手带您无忧上云