-
-
Save nbilyk/189cd36f22cbb8582cff5853edcec6b1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.lwjgl.*; | |
import org.lwjgl.glfw.*; | |
import org.lwjgl.opengl.*; | |
import java.io.File; | |
import java.nio.ByteBuffer; | |
import java.nio.FloatBuffer; | |
import static org.lwjgl.glfw.GLFW.*; | |
import static org.lwjgl.opengl.GL11.*; | |
import static org.lwjgl.system.MemoryUtil.*; | |
public class Main { | |
// We need to strongly reference callback instances. | |
private GLFWErrorCallback errorCallback; | |
// The window handle | |
private long window; | |
// Quad variables | |
private int vaoId = 0; | |
private int vboId = 0; | |
private int vboiId = 0; | |
private FloatBuffer verticesBuffer; | |
private ByteBuffer indicesBuffer; | |
public void run() { | |
try { | |
initGl(); | |
initShader(); | |
setupQuad(); | |
// System.out.println("Hello LWJGL " + Version.getVersion() + "!"); | |
loop(); | |
dispose(); | |
// Destroy window and window callbacks | |
glfwDestroyWindow(window); | |
} finally { | |
// Terminate GLFW and free the GLFWErrorCallback | |
glfwTerminate(); | |
errorCallback.free(); | |
} | |
} | |
private int _program = -1; | |
private void initShader() { | |
String vertexShaderSrc = "#version 100\n" + | |
"attribute vec4 a_position;\n" + | |
"\n" + | |
"void main() {\n" + | |
"\tgl_Position = a_position;\n" + | |
"}"; | |
_program = GL20.glCreateProgram(); | |
compileShader(vertexShaderSrc, GL20.GL_VERTEX_SHADER); | |
String fragmentShaderSrc = "void main() {\n" + | |
"\tgl_FragColor = vec4(0.0, 1.0, 0.0, 0.2);\n" + | |
"}"; | |
compileShader(fragmentShaderSrc, GL20.GL_FRAGMENT_SHADER); | |
GL20.glLinkProgram(_program); | |
GL20.glUseProgram(_program); | |
} | |
private int compileShader(String shaderSrc, int shaderType) { | |
int shader = GL20.glCreateShader(shaderType); | |
GL20.glShaderSource(shader, shaderSrc); | |
GL20.glCompileShader(shader); | |
GL20.glAttachShader(_program, shader); | |
System.out.println("Shader info: " + GL20.glGetShaderInfoLog(shader)); | |
return shader; | |
} | |
private void initGl() { | |
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); | |
// Setup an error callback. The default implementation | |
// will print the error message in System.err. | |
glfwSetErrorCallback(errorCallback = GLFWErrorCallback.createPrint(System.err)); | |
// Initialize GLFW. Most GLFW functions will not work before doing this. | |
if (glfwInit() != GLFW_TRUE) | |
throw new IllegalStateException("Unable to initialize GLFW"); | |
// Configure our window | |
glfwDefaultWindowHints(); // optional, the current window hints are already the default | |
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation | |
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable | |
int WIDTH = 300; | |
int HEIGHT = 300; | |
// Create the window | |
window = glfwCreateWindow(WIDTH, HEIGHT, "Hello World!", NULL, NULL); | |
if (window == NULL) | |
throw new RuntimeException("Failed to create the GLFW window"); | |
// Get the resolution of the primary monitor | |
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); | |
// Center our window | |
glfwSetWindowPos( | |
window, | |
(vidmode.width() - WIDTH) / 2, | |
(vidmode.height() - HEIGHT) / 2 | |
); | |
// Make the OpenGL context current | |
glfwMakeContextCurrent(window); | |
// Enable v-sync | |
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. | |
GL.createCapabilities(); | |
// And do this after glfwMakeContextCurrent(window) | |
GLUtil.setupDebugMessageCallback(System.err); | |
// Set the clear color | |
glClearColor(1.0f, 0.0f, 0.0f, 0.0f); | |
} | |
public void setupQuad() { | |
// Sending data to OpenGL requires the usage of (flipped) byte buffers | |
verticesBuffer = BufferUtils.createFloatBuffer(1024); | |
indicesBuffer = BufferUtils.createByteBuffer(1024); | |
GL20.glEnableVertexAttribArray(0); | |
// Create a new Vertex Buffer Object in memory and select it (bind) | |
// A VBO is a collection of Vectors which in this case resemble the location of each vertex. | |
vboId = GL15.glGenBuffers(); | |
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId); | |
// Create a new VBO for the indices and select it (bind) | |
vboiId = GL15.glGenBuffers(); | |
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId); | |
GL20.glEnableVertexAttribArray(0); | |
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0); | |
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, 4 * 3 << 2, GL15.GL_STATIC_DRAW); | |
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, 4 << 1, GL15.GL_STATIC_DRAW); | |
} | |
private void loop() { | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer | |
draw1(); | |
draw2(); | |
glfwSwapBuffers(window); // swap the color buffers | |
// Run the rendering loop until the user has attempted to close | |
// the window or has pressed the ESCAPE key. | |
while (glfwWindowShouldClose(window) == GLFW_FALSE) { | |
// Poll for window events. The key callback above will only be | |
// invoked during this call. | |
glfwPollEvents(); | |
} | |
} | |
private void draw1() { | |
float offset = 0.2f * 2f - 1f; | |
float[] vertices = { | |
-0.5f + offset, 0.5f + offset, 0f, // Left top ID: 0 | |
-0.5f + offset, -0.5f + offset, 0f, // Left bottom ID: 1 | |
0.5f + offset, -0.5f + offset, 0f, // Right bottom ID: 2 | |
0.5f + offset, 0.5f + offset, 0f // Right top ID: 3 | |
}; | |
byte[] indices = { 0, 1, 2, 2, 3, 0 }; | |
draw(vertices, indices); | |
} | |
private void draw2() { | |
float offset = 0.8f * 2f - 1f; | |
float[] vertices = { | |
-0.5f + offset, -0.5f + offset, 0f, // Left bottom ID: 0 | |
-0.5f + offset, 0.5f + offset, 0f, // Left top ID: 1 | |
0.5f + offset, -0.5f + offset, 0f, // Right bottom ID: 2 | |
0.5f + offset, 0.5f + offset, 0f // Right top ID: 3 | |
}; | |
byte[] indices = { 1, 0, 3, 3, 0, 2 }; | |
draw(vertices, indices); | |
} | |
private void draw(float[] vertices, byte[] indices) { | |
verticesBuffer.put(vertices); | |
verticesBuffer.flip(); | |
GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, verticesBuffer); | |
indicesBuffer.put(indices); | |
indicesBuffer.flip(); | |
GL15.glBufferSubData(GL15.GL_ELEMENT_ARRAY_BUFFER, 0, indicesBuffer); | |
// Draw the vertices | |
GL11.glDrawElements(GL11.GL_TRIANGLES, indices.length, GL11.GL_UNSIGNED_BYTE, 0); | |
} | |
private void dispose() { | |
// Disable the VBO index from the VAO attributes list | |
GL20.glDisableVertexAttribArray(0); | |
// Delete the vertex VBO | |
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); | |
GL15.glDeleteBuffers(vboId); | |
// Delete the index VBO | |
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); | |
GL15.glDeleteBuffers(vboiId); | |
// Delete the VAO | |
// GL30.glBindVertexArray(0); | |
// GL30.glDeleteVertexArrays(vaoId); | |
} | |
public static void main(String[] args) { | |
File file = new File("native"); | |
if (!file.exists()) throw new RuntimeException("native folder does not exist"); | |
System.setProperty("org.lwjgl.librarypath", file.getAbsolutePath()); | |
new Main().run(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment