-
-
Save nbilyk/4d0af9fd885bca5f87e5aa1379d3706e 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() { | |
// 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(); | |
// 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); | |
// Create a new Vertex Array Object in memory and select it (bind) | |
// A VAO can have up to 16 attributes (VBO's) assigned to it by default | |
vaoId = GL30.glGenVertexArrays(); | |
GL30.glBindVertexArray(vaoId); | |
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); | |
// Put the VBO in the attributes list at index 0 | |
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0); | |
// Create a new VBO for the indices and select it (bind) | |
vboiId = GL15.glGenBuffers(); | |
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId); | |
} | |
private void loop() { | |
// Run the rendering loop until the user has attempted to close | |
// the window or has pressed the ESCAPE key. | |
while (glfwWindowShouldClose(window) == GLFW_FALSE) { | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer | |
int n = 10; | |
for (int i = 0; i < n; i++) { | |
float p = i / (float) n; | |
float offset = p * 2f - 1f; | |
// Vertices, the order is not important. | |
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 left ID: 3 | |
}; | |
// OpenGL expects to draw vertices in counter clockwise order by default | |
byte[] indices = { | |
// Left bottom triangle | |
0, 1, 2, | |
// Right top triangle | |
2, 3, 0 | |
}; | |
draw(vertices, indices); | |
} | |
glfwSwapBuffers(window); // swap the color buffers | |
// Poll for window events. The key callback above will only be | |
// invoked during this call. | |
glfwPollEvents(); | |
} | |
} | |
private void draw(float[] vertices, byte[] indices) { | |
verticesBuffer.put(vertices); | |
verticesBuffer.flip(); | |
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesBuffer, GL15.GL_STATIC_DRAW); | |
indicesBuffer.put(indices); | |
indicesBuffer.flip(); | |
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL15.GL_STATIC_DRAW); | |
// 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