Java tutorial
/* * Copyright LWJGL. All rights reserved. * License terms: http://lwjgl.org/license.php */ package org.lwjgl.demo.opengl; import org.lwjgl.BufferUtils; import org.lwjgl.PointerBuffer; import org.lwjgl.glfw.*; import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GLUtil; import org.lwjgl.system.Callback; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import static org.lwjgl.demo.opengl.util.DemoUtils.*; import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL15.*; import static org.lwjgl.opengl.GL20.*; import static org.lwjgl.opengl.GL30.*; import static org.lwjgl.system.MemoryUtil.*; /** * Simple demo to showcase the use of * {@link GL20#glUniform3fv(int, FloatBuffer)}. * * @author Kai Burjack * */ public class UniformArrayDemo { private long window; private int width = 1024; private int height = 768; private int vao; private int program; private int vec3ArrayUniform; private int chosenUniform; private int chosen = 0; private FloatBuffer colors = BufferUtils.createFloatBuffer(3 * 4); { colors.put(1).put(0).put(0); // red colors.put(0).put(1).put(0); // green colors.put(0).put(0).put(1); // blue colors.put(1).put(1).put(0); // yellow colors.flip(); } GLFWErrorCallback errCallback; GLFWKeyCallback keyCallback; GLFWFramebufferSizeCallback fbCallback; Callback debugProc; private void init() throws IOException { glfwSetErrorCallback(errCallback = new GLFWErrorCallback() { private GLFWErrorCallback delegate = GLFWErrorCallback.createPrint(System.err); @Override public void invoke(int error, long description) { if (error == GLFW_VERSION_UNAVAILABLE) System.err.println("This demo requires OpenGL 3.0 or higher."); delegate.invoke(error, description); } @Override public void free() { delegate.free(); } }); if (!glfwInit()) throw new IllegalStateException("Unable to initialize GLFW"); glfwDefaultWindowHints(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); window = glfwCreateWindow(width, height, "Uniform array test", NULL, NULL); if (window == NULL) { throw new AssertionError("Failed to create the GLFW window"); } System.out.println("Press 'up' or 'down' to cycle through some colors."); glfwSetFramebufferSizeCallback(window, fbCallback = new GLFWFramebufferSizeCallback() { @Override public void invoke(long window, int width, int height) { if (width > 0 && height > 0 && (UniformArrayDemo.this.width != width || UniformArrayDemo.this.height != height)) { UniformArrayDemo.this.width = width; UniformArrayDemo.this.height = height; } } }); glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() { @Override public void invoke(long window, int key, int scancode, int action, int mods) { if (action != GLFW_RELEASE) return; if (key == GLFW_KEY_ESCAPE) { glfwSetWindowShouldClose(window, true); } else if (key == GLFW_KEY_UP) { chosen = (chosen + 1) % 4; } else if (key == GLFW_KEY_DOWN) { chosen = (chosen + 3) % 4; } } }); GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); glfwSetWindowPos(window, (vidmode.width() - width) / 2, (vidmode.height() - height) / 2); glfwMakeContextCurrent(window); glfwSwapInterval(0); glfwShowWindow(window); IntBuffer framebufferSize = BufferUtils.createIntBuffer(2); nglfwGetFramebufferSize(window, memAddress(framebufferSize), memAddress(framebufferSize) + 4); width = framebufferSize.get(0); height = framebufferSize.get(1); GL.createCapabilities(); debugProc = GLUtil.setupDebugMessageCallback(); /* Create all needed GL resources */ createVao(); createRasterProgram(); initProgram(); } /** * Simple fullscreen quad. */ private void createVao() { this.vao = glGenVertexArrays(); int vbo = glGenBuffers(); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); ByteBuffer bb = BufferUtils.createByteBuffer(4 * 2 * 6); FloatBuffer fv = bb.asFloatBuffer(); fv.put(-1.0f).put(-1.0f); fv.put(1.0f).put(-1.0f); fv.put(1.0f).put(1.0f); fv.put(1.0f).put(1.0f); fv.put(-1.0f).put(1.0f); fv.put(-1.0f).put(-1.0f); glBufferData(GL_ARRAY_BUFFER, bb, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0L); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } /** * Create a shader object from the given classpath resource. * * @param resource * the class path * @param type * the shader type * * @return the shader object id * * @throws IOException */ private static int createShader(String resource, int type) throws IOException { int shader = glCreateShader(type); ByteBuffer source = ioResourceToByteBuffer(resource, 8192); PointerBuffer strings = BufferUtils.createPointerBuffer(1); IntBuffer lengths = BufferUtils.createIntBuffer(1); strings.put(0, source); lengths.put(0, source.remaining()); glShaderSource(shader, strings, lengths); glCompileShader(shader); int compiled = glGetShaderi(shader, GL_COMPILE_STATUS); String shaderLog = glGetShaderInfoLog(shader); if (shaderLog.trim().length() > 0) { System.err.println(shaderLog); } if (compiled == 0) { throw new AssertionError("Could not compile shader"); } return shader; } /** * Create the raster shader. * * @throws IOException */ private void createRasterProgram() throws IOException { int program = glCreateProgram(); int vshader = createShader("org/lwjgl/demo/opengl/uniformarray-vs.glsl", GL_VERTEX_SHADER); int fshader = createShader("org/lwjgl/demo/opengl/uniformarray-fs.glsl", GL_FRAGMENT_SHADER); glAttachShader(program, vshader); glAttachShader(program, fshader); glBindAttribLocation(program, 0, "position"); glBindFragDataLocation(program, 0, "color"); glLinkProgram(program); int linked = glGetProgrami(program, GL_LINK_STATUS); String programLog = glGetProgramInfoLog(program); if (programLog.trim().length() > 0) { System.err.println(programLog); } if (linked == 0) { throw new AssertionError("Could not link program"); } this.program = program; } /** * Initialize the shader program. */ private void initProgram() { glUseProgram(this.program); vec3ArrayUniform = glGetUniformLocation(this.program, "cols"); chosenUniform = glGetUniformLocation(this.program, "chosen"); glUseProgram(0); } private void render() { glUseProgram(this.program); /* Set uniform array. */ glUniform3fv(vec3ArrayUniform, colors); /* Set chosen color (index into array) */ glUniform1i(chosenUniform, chosen); glBindVertexArray(vao); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); glUseProgram(0); } private void loop() { while (!glfwWindowShouldClose(window)) { glfwPollEvents(); glViewport(0, 0, width, height); render(); glfwSwapBuffers(window); } } private void run() { try { init(); loop(); errCallback.free(); keyCallback.free(); fbCallback.free(); if (debugProc != null) debugProc.free(); glfwDestroyWindow(window); } catch (Throwable t) { t.printStackTrace(); } finally { glfwTerminate(); } } public static void main(String[] args) { new UniformArrayDemo().run(); } }