I've got the folowing code:
package test.opengl;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.utils.BufferUtils;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;
import static com.badlogic.gdx.graphics.GL20.*;
public class GLClass extends ApplicationAdapter
{
private int shaderProgram;
private GL30 gl;
FloatBuffer vertices;
IntBuffer vao = BufferUtils.newIntBuffer(1);
IntBuffer vbo = BufferUtils.newIntBuffer(1);
#Override
public void create()
{
gl = Gdx.gl30;
compileShaders();
vertices = BufferUtils.newFloatBuffer(9);
vertices.put(new float[]
{
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
});
gl.glEnable(GL_DEPTH_TEST);
gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
gl.glGenVertexArrays(1, vao);
gl.glGenBuffers(1, vbo);
gl.glBindVertexArray(vao.get(0));
gl.glBindBuffer(GL_ARRAY_BUFFER, vbo.get(0));
gl.glBufferData(GL_ARRAY_BUFFER, 9, vertices, GL_STATIC_DRAW);
gl.glVertexAttribPointer(0, 3, GL_FLOAT, false, 3, 0);
gl.glEnableVertexAttribArray(0);
gl.glBindVertexArray(0);
}
#Override
public void render()
{
gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl.glUseProgram(shaderProgram);
gl.glBindVertexArray(vao.get(0));
gl.glDrawArrays(GL_TRIANGLES, 0, 3);
gl.glBindVertexArray(0);
int err = gl.glGetError();
if (err != 0)
System.err.println("ERROR: " + err);
}
#Override
public void resize(int width, int height)
{
gl.glViewport(0, 0, width, height);
}
private void compileShaders()
{
String vsSource;
String fsSource;
try
{
vsSource = new String(Files.readAllBytes(Paths.get("shaders/shader.vert")));
fsSource = new String(Files.readAllBytes(Paths.get("shaders/shader.frag")));
} catch (IOException e)
{
throw new RuntimeException(e);
}
shaderProgram = gl.glCreateProgram();
int vertexShader = gl.glCreateShader(GL_VERTEX_SHADER);
gl.glShaderSource(vertexShader, vsSource);
gl.glCompileShader(vertexShader);
System.err.println(gl.glGetShaderInfoLog(vertexShader));
gl.glAttachShader(shaderProgram, vertexShader);
int fragmentShader = gl.glCreateShader(GL_FRAGMENT_SHADER);
gl.glShaderSource(fragmentShader, fsSource);
gl.glCompileShader(fragmentShader);
System.err.println(gl.glGetShaderInfoLog(fragmentShader));
gl.glAttachShader(shaderProgram, fragmentShader);
gl.glLinkProgram(shaderProgram);
gl.glDeleteShader(vertexShader);
gl.glDeleteShader(fragmentShader);
}
}
The code for shader.vert:
#version 330 core
layout (location = 0) in vec3 position;
void main()
{
gl_Position = vec4(position.x, position.y, position.z, 1.0);
}
The code for shader.frag:
#version 330
out vec4 out_Color;
void main()
{
out_Color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
It is running on desktop and the program crashes as soon as the first call of render() is completed, without a stacktrace and a segfault log. config.useGL30 is set to true.
Why is it crashing? Am I doing anything wrong?
Related
I can create the window, but I cannot render anything. Here's my code:
LWJGLTutorial.java:
package core;
import logger.Logger;
import model.ModelLoader;
import model.RawModel;
import org.lwjgl.Version;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.MemoryStack;
import java.nio.IntBuffer;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;
// Main class
public class LWJGLTutorial {
// The window
private long window;
// The game
private void run() {
// Create logger
Logger logger = new Logger("MAIN");
// Validate LWJGL installation
logger.log("LWJGL Version: " + Version.getVersion());
// Set a error callback
GLFWErrorCallback.createPrint(System.err).set();
// Initialize and configure GLFW
if(!glfwInit())
throw new IllegalStateException("Unable to initialize GLFW");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
logger.log("Initialized GLFW");
// Create window
window = glfwCreateWindow(800, 600, "LWJGL Tutorial", NULL, NULL);
if(window == NULL)
throw new RuntimeException("Failed to create window");
logger.log("Created window");
// Set a key callback
glfwSetKeyCallback(window, new GLFWKeyCallback() {
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
});
// Set a framebuffer size callback
glfwSetFramebufferSizeCallback(window, new GLFWFramebufferSizeCallback() {
#Override
public void invoke(long window, int width, int height) {
glViewport(0, 0, width, height);
}
});
logger.log("Callbacks set");
// Get the thread stack and push a new frame
try(MemoryStack stack = stackPush()) {
IntBuffer pWidth = stack.mallocInt(1);
IntBuffer pHeight = stack.mallocInt(1);
glfwGetWindowSize(window, pWidth, pHeight);
GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (vidMode.width() - pWidth.get(0)) / 2, (vidMode.height() - pHeight.get(0)) / 2);
}
// Make OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);
// Show window
glfwShowWindow(window);
// This line is critical for LWJGL's interoperation with GLFW's OpenGL context
GL.createCapabilities();
float[] vertices = {
// Left bottom triangle
-0.5f, 0.5f, 0f,
-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
// Right top triangle
0.5f, -0.5f, 0f,
0.5f, 0.5f, 0f,
-0.5f, 0.5f, 0f
};
RawModel model = ModelLoader.load(vertices);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Render loop
while(!glfwWindowShouldClose(window)) {
// Set clear color
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
// Clear framebuffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Render models
Renderer.render(model);
// Swap color buffer
glfwSwapBuffers(window);
// Poll IO events
glfwPollEvents();
}
// Clean up
logger.log("Clean up...");
ModelLoader.cleanUp();
// Free the window callbacks and destroy the window
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
// Terminate GLFW and free error callback
glfwTerminate();
glfwSetErrorCallback(null).free();
logger.log("Normal exit");
}
public static void main(String[] args) {
new LWJGLTutorial().run();
}
}
ModelLoader.java:
package model;
import org.lwjgl.BufferUtils;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
import static org.lwjgl.opengl.GL30.*;
// Loads data into a RawModel
public class ModelLoader {
// A list of VAOs
private static List<Integer> VAOs = new ArrayList<>();
// A list of VBOs
private static List<Integer> VBOs = new ArrayList<>();
// Load data into a RawModel
public static RawModel load(float[] data) {
int vao = createVAO();
int vbo = createVBO();
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
FloatBuffer buffer = storeDataInFloatBuffer(data);
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
return new RawModel(vao, data.length / 3);
}
// Deletes all created VAO and VBO
public static void cleanUp() {
for(int VAO : VAOs)
glDeleteVertexArrays(VAO);
for(int VBO : VBOs)
glDeleteBuffers(VBO);
}
// Generates a new VAO and stores it into the VAO list
private static int createVAO() {
int vao = glGenVertexArrays();
VAOs.add(vao);
return vao;
}
// Generates a new VBO and stores it into the VBO list
private static int createVBO() {
int vbo = glGenBuffers();
VBOs.add(vbo);
return vbo;
}
// Convert data into FloatBuffer
private static FloatBuffer storeDataInFloatBuffer(float[] data) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
Renderer.java:
package core;
import model.RawModel;
import static org.lwjgl.opengl.GL30.*;
// Renderer that render stuff onto the screen
public class Renderer {
// Render a RawModel
public static void render(RawModel model) {
glBindVertexArray(model.getVAO());
glDrawArrays(GL_TRIANGLES, 0, model.getVertexCount());
}
}
RawModel.java:
package model;
import lombok.Getter;
// Represents a model that can be rendered
public class RawModel {
// VAO
#Getter
private int VAO;
// Number of vertices
#Getter
private int vertexCount;
public RawModel(int VAO, int vertexCount) {
this.VAO = VAO;
this.vertexCount = vertexCount;
}
}
I should be able to render a rectangle, but nothing is showing. I knew that it is not the problem with lombok, and I suspect that something went wrong in ModelLoader.java or Renderer.java. What is wrong with my code?
I don't see a shader created or being used in your code. A shader is what essentially renders the program. Do you have one?
The problem is that i am trying to create a 3D Cube via using the shaders, but the problem is that, it doesn't read the file correctly.
Here are the shaders that I have created, the problem is that it reads not correctly the sharders and give the error
I also get just a black screen as a result
My Shaders
Vertex shader
// vertex.glsl
#version 430
layout (location = 0) in vec3 position;
uniform mat4 proj_matrix;
uniform mat4 mv_matrix;
void main(void) {
gl_Position = proj_matrix * mv_matrix * vec4(position, 1.0);
}
Fragemtn shader
// fragment.glsl
#version 430
out vec4 color;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
void main(void) {
color = vec4(1.0, 0.0, 0.0, 1.0);
}
main code
// my main code
import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.Date;
import java.util.Random;
import java.util.Scanner;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.math.Matrix4;
import com.jogamp.opengl.math.Quaternion;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.common.nio.Buffers;
import com.jogamp.gluegen.*;
public class GOVNO extends JFrame implements GLEventListener {
private GLCanvas myCanvas;
private int rendering_program;
private int vbo[] = new int[2];
private int mTrans;
public GOVNO() {
setTitle("Chapter2 - program1");
setSize(600, 400);
setLocation(200, 200);
GLProfile profile = GLProfile.getDefault();
GLCapabilities capabilities = new GLCapabilities(profile);
myCanvas = new GLCanvas(capabilities);
myCanvas.addGLEventListener(this);
this.add(myCanvas);
setVisible(true);
}
public void display(GLAutoDrawable drawable) {
GL2 gl = (GL2) GLContext.getCurrentGL();
gl.glUseProgram(rendering_program);
float a = 0;
//Matrix4 mTransMatrix = new Matrix4();
float mTransMatrix[] = {
(float) Math.cos(a), (float) -Math.sin(a), 0, 0,
(float) Math.sin(a), (float) Math.cos(a), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
gl.glUniformMatrix4fv(mTrans, 1, false, mTransMatrix, 0);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo[0]);
gl.glVertexAttribPointer(0, 2, GL3.GL_FLOAT, false, 0, 0);
gl.glEnableVertexAttribArray(0);
gl.glDrawArrays(GL3.GL_TRIANGLES, 0, 6);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo[1]);
gl.glVertexAttribPointer(0, 2, GL3.GL_FLOAT, false, 0, 0);
gl.glEnableVertexAttribArray(0);
gl.glDrawArrays(GL3.GL_QUADS, 0, 8);
}
public void init(GLAutoDrawable drawable) {
GL2 gl = (GL2) GLContext.getCurrentGL();
rendering_program = createShaderProgram();
// generating location for transformation matrix
mTrans = gl.glGetUniformLocation(rendering_program, "trans");
float[] vertex_positions = { -0.5f, -1.0f, 0.0f, -0.5f, 0.5f, -1.0f, };
gl.glGenBuffers(vbo.length, vbo, 0);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo[0]);
FloatBuffer vertBuf Buffers.newDirectFloatBuffer(vertex_positions);
gl.glBufferData(GL3.GL_ARRAY_BUFFER, vertBuf.limit() * 4, vertBuf, GL3.GL_STATIC_DRAW);
float[] vertex_positions2 = { -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f };
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo[1]);
FloatBuffer vertBuf2 = Buffers.newDirectFloatBuffer(vertex_positions2);
gl.glBufferData(GL3.GL_ARRAY_BUFFER, vertBuf2.limit() * 4, vertBuf2, GL3.GL_STATIC_DRAW);
}
private int createShaderProgram() {
GL2 gl = (GL2) GLContext.getCurrentGL();
String vshaderSource[] = readShaderSource("src/vertex.glsl");
String fshaderSource[] = readShaderSource("src/fragment.glsl");
int vShader = gl.glCreateShader(GL3.GL_VERTEX_SHADER);
gl.glShaderSource(vShader, vshaderSource.length, vshaderSource, null, 0);
gl.glCompileShader(vShader);
printShaderLog(vShader);
int fShader = gl.glCreateShader(GL3.GL_FRAGMENT_SHADER);
gl.glShaderSource(fShader, fshaderSource.length, fshaderSource, null, 0);
gl.glCompileShader(fShader);
printShaderLog(fShader);
int vfprogram = gl.glCreateProgram();
gl.glAttachShader(vfprogram, vShader);
gl.glAttachShader(vfprogram, fShader);
gl.glLinkProgram(vfprogram);
gl.glDeleteShader(vShader);
gl.glDeleteShader(fShader);
printProgramLog(vfprogram);
return vfprogram;
}
private String[] readShaderSource(String filename) {
Vector<String> lines = new Vector<String>();
Scanner sc;
try {
sc = new Scanner(new File(filename));
} catch (IOException e) {
System.err.println("IOException reading file: " + e);
return null;
}
while (sc.hasNext()) {
lines.addElement(sc.nextLine());
}
String[] program = new String[lines.size()];
for (int i = 0; i < lines.size(); i++) {
program[i] = (String) lines.elementAt(i) + "\n";
System.out.print(program[i]);
}
return program;
}
private void printShaderLog(int shader) {
GL2 gl = (GL2) GLContext.getCurrentGL();
int[] len = new int[1];
int[] chWrittn = new int[1];
byte[] log = null;
// determine the length of the shader compilation log
gl.glGetShaderiv(shader, GL3.GL_INFO_LOG_LENGTH, len, 0);
if (len[0] > 0) {
log = new byte[len[0]];
gl.glGetShaderInfoLog(shader, len[0], chWrittn, 0, log, 0);
System.out.println("Shader Info Log: ");
for (int i = 0; i < log.length; i++) {
System.out.print((char) log[i]);
}
}
}
void printProgramLog(int prog) {
GL2 gl = (GL2) GLContext.getCurrentGL();
int[] len = new int[1];
int[] chWrittn = new int[1];
byte[] log = null;
// determine the length of the program linking log
gl.glGetProgramiv(prog, GL3.GL_INFO_LOG_LENGTH, len, 0);
if (len[0] > 0) {
log = new byte[len[0]];
gl.glGetProgramInfoLog(prog, len[0], chWrittn, 0, log, 0);
System.out.println("Program Info Log: ");
for (int i = 0; i < log.length; i++) {
System.out.print((char) log[i]);
}
}
}
public static void main(String[] args) {
System.out.println("Working Directory = " + System.getProperty("user.dir"));
new GOVNO();
}
}
I've been trying to resolve this problem for the past three days, but in vain. Therefore, I'd be very grateful for any help. I am currently learning how to draw triangles with VBOs and VAOs, so all of the code is included in one single "test" class.
package quad;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import static org.lwjgl.system.MemoryUtil.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL11.GL_TRUE;
import static org.lwjgl.opengl.GL.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
public class Quad {
private long window;
private final String WINDOW_TITLE = "The Quad: glDrawArrays";
private final int WIDTH = 1920;
private final int HEIGHT = 1080;
// Quad variables
private int vaoId = 0;
private int vboId = 0;
private int vertexCount = 0;
private boolean running = false;
public static void main(String[] args) {
new Quad().start();
}
public void start() {
running = true;
setupOpenGL();
setupQuad();
while (running) {
loopCycle();
update();
if(glfwWindowShouldClose(window)) {
running = false;
}
}
destroyOpenGL();
}
public void setupOpenGL() {
if(!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW!");
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
window = glfwCreateWindow(WIDTH, HEIGHT, WINDOW_TITLE, NULL, NULL);
if (window == NULL) {
throw new RuntimeException("Cannot create window!");
}
glfwMakeContextCurrent(window);
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (vidmode.width() - WIDTH) / 2, (vidmode.height() - HEIGHT) / 2);
glfwShowWindow(window);
GL.createCapabilities();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
public void setupQuad() {
float[] vertices = {
// Left bottom triangle
-0.5f, 0.5f, 0f,
-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
// Right top triangle
0.5f, -0.5f, 0f,
0.5f, 0.5f, 0f,
-0.5f, 0.5f, 0f
};
FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
verticesBuffer.put(vertices);
verticesBuffer.flip();
vertexCount = 6;
// 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 = glGenVertexArrays();
glBindVertexArray(vaoId);
// 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 = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);
// Put the VBO in the attributes list at index 0
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
// Deselect (bind to 0) the VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Deselect (bind to 0) the VAO
glBindVertexArray(0);
}
public void loopCycle() {
glClear(GL_COLOR_BUFFER_BIT);
// Bind to the VAO that has all the information about the quad vertices
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
// Draw the vertices
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
// Put everything back to default (deselect)
glDisableVertexAttribArray(0);
glBindVertexArray(0);
}
public void destroyOpenGL() {
// Disable the VBO index from the VAO attributes list
glDisableVertexAttribArray(0);
// Delete the VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(vboId);
// Delete the VAO
glBindVertexArray(0);
glDeleteVertexArrays(vaoId);
glfwDestroyWindow(window);
glfwTerminate();
}
public void update() {
glfwSwapBuffers(window);
glfwPollEvents();
}
}
Note: I've modernised this tutorial code example so LWJGL3 is used (none of the old Displays etc).
Everything functions correctly at the first glance, but when the code is run, only a window with black colour (which is set by glClearColor(0.0f, 0.0f, 0.0f, 0.0f) inside the setupOpengl() method.
Why are the quads not showing up?
Had this working on OpenGL ES 1.0 & 2.0.
Goal: Make a box, then display it
Won't work with LWJGL on Win 7. Loads a green box (as it should), and then starts to display a bunch of really thick white lines that won't stay as a box. There is a lot of flickering. Here is a picture.
Here is the code for windows.
Main.java
package play.box;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
public class Main {
public static final boolean VSYNC = true;
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
public static final boolean FULLSCREEN = false;
protected boolean running = false;
public static void main(String[] args) {
try {
start();
} catch (LWJGLException e) {
e.printStackTrace();
}
}
public static void start() throws LWJGLException {
Display.setTitle("Display example");
Display.setResizable(false);
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.setVSyncEnabled(VSYNC);
Display.setFullscreen(FULLSCREEN);
Display.create();
// Setup OpenGL
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(-3, 3, -2, 2, -1, 1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
new Renderer().run();
}
}
Renderer.java
package play.box;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
public class Renderer implements Runnable {
public Renderer() {
}
#Override
public void run() {
while(!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
GL11.glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
// Rendering //
/*GL11.glBegin(GL11.GL_TRIANGLES);
GL11.glColor3f(1.0f, 0.0f, 0.0f);
GL11.glVertex2f(0.0f, 1.0f);
GL11.glColor3f(1.0f, 0.0f, 0.0f);
GL11.glVertex2f(1.0f, 1.0f);
GL11.glColor3f(1.0f, 0.0f, 0.0f);
GL11.glVertex2f(1.0f, -1.0f);
GL11.glEnd();*/
Box box = new Box();
box.draw();
// End of Rendering //
Display.update();
try {
Thread.sleep(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
Box.java
package play.box;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import org.lwjgl.opengl.GL11;
public class Box {
private float verticies[] = {
-1.0f, 1.0f, // Left Top (0)
-1.0f, -1.0f, // Left Bottom (1)
1.0f, -1.0f, // Right Bottom (2)
1.0f, 1.0f // Right Top (4)
};
private short indicies[] = {
0, 1, 2,
2, 3, 0
};
private FloatBuffer vertBuff;
private ShortBuffer indexBuff;
public Box() {
this.setupBuffers();
}
private void setupBuffers() {
ByteBuffer bBuff = ByteBuffer.allocateDirect(this.verticies.length * 4);
bBuff.order(ByteOrder.nativeOrder());
this.vertBuff = bBuff.asFloatBuffer();
this.vertBuff.put(this.verticies);
this.vertBuff.position(0);
ByteBuffer pbBuff = ByteBuffer.allocateDirect(this.indicies.length * 2);
pbBuff.order(ByteOrder.nativeOrder());
this.indexBuff = pbBuff.asShortBuffer();
this.indexBuff.put(this.indicies);
this.indexBuff.position(0);
}
public void draw() {
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glVertexPointer(2, GL11.GL_FLOAT, this.vertBuff);
GL11.glDrawElements(GL11.GL_TRIANGLES, this.indexBuff);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
}
}
Updated Code:
package play.box;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
public class Box {
private float verticies[] = {
-1.0f, 1.0f, // Left Top (0)
-1.0f, -1.0f, // Left Bottom (1)
1.0f, -1.0f, // Right Bottom (2)
1.0f, 1.0f // Right Top (4)
};
private short indicies[] = {
0, 1, 2,
2, 3, 0
};
private FloatBuffer vertBuff;
private ShortBuffer indexBuff;
private int vbo_handle;
private int ibo_handle;
private int vao_handle;
private String vShaderStr =
"attribute vec4 vPosition; \n"
+ "void main() { \n"
+ " gl_Position = vPosition;\n"
+ "} \n";
private String fShaderStr =
"precision mediump float; \n"
+ "void main() { \n"
+ " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n"
+ "} \n";
private int vertexShader;
private int fragmentShader;
private int programObject;
public Box() {
}
public void create() {
ByteBuffer bBuff = ByteBuffer.allocateDirect(this.verticies.length * 4);
bBuff.order(ByteOrder.nativeOrder());
this.vertBuff = bBuff.asFloatBuffer();
this.vertBuff.put(this.verticies);
//this.vertBuff.flip();
this.vertBuff.position(0);
ByteBuffer pbBuff = ByteBuffer.allocateDirect(this.indicies.length * 2);
pbBuff.order(ByteOrder.nativeOrder());
this.indexBuff = pbBuff.asShortBuffer();
this.indexBuff.put(this.indicies);
//this.indexBuff.flip();
this.indexBuff.position(0);
// Create VBO
this.vbo_handle = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vbo_handle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, this.vertBuff, GL15.GL_DYNAMIC_DRAW);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
// Create IBO
this.ibo_handle = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, this.ibo_handle);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, this.indexBuff, GL15.GL_DYNAMIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
// Create VAO
this.vao_handle = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vao_handle);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_handle);
GL20.glEnableVertexAttribArray(0);
GL20.glVertexAttribPointer(0, 2, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ibo_handle);
GL30.glBindVertexArray(0);
// Setup Shaders
this.vertexShader = this.loadShader(GL20.GL_VERTEX_SHADER, this.vShaderStr);
this.fragmentShader = this.loadShader(GL20.GL_FRAGMENT_SHADER, this.fShaderStr);
// Setup Program
int program = GL20.glCreateProgram();
if(program == 0) {
return;
}
GL20.glAttachShader(program, this.vertexShader);
GL20.glAttachShader(program, this.fragmentShader);
GL20.glBindAttribLocation(program, 0, "vPosition");
GL20.glLinkProgram(program);
if(GL20.glGetProgrami(program, GL20.GL_LINK_STATUS) == 0) {
System.out.println("Error Creating Program: " + GL20.glGetProgramInfoLog(program, Integer.MAX_VALUE));
GL20.glDeleteProgram(program);
return;
}
this.programObject = program;
}
public void draw() {
this.create();
GL20.glUseProgram(this.programObject);
GL30.glBindVertexArray(vao_handle);
GL11.glDrawElements(GL11.GL_TRIANGLES, 2, GL11.GL_FLOAT, 0);
GL30.glBindVertexArray(0);
this.dispose();
}
public void draw(boolean useVAO) {
if(useVAO) {
this.draw();
} else {
this.create();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vbo_handle);
GL11.glVertexPointer(2, GL11.GL_FLOAT, 0, 0L);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, this.ibo_handle);
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDrawElements(GL11.GL_TRIANGLES, this.indicies.length, GL11.GL_UNSIGNED_SHORT, 0L);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
this.dispose();
}
}
public void dispose() {
GL30.glDeleteVertexArrays(vao_handle);
GL30.glDeleteVertexArrays(vbo_handle);
GL30.glDeleteVertexArrays(ibo_handle);
this.vao_handle = -1;
this.vbo_handle = -1;
this.ibo_handle = -1;
}
private int loadShader(int type, String shaderSrc) {
int shader;
shader = GL20.glCreateShader(type);
if(shader == 0) {
return 0;
}
GL20.glShaderSource(shader, shaderSrc);
GL20.glCompileShader(shader);
if(GL20.glGetShaderi(shader, GL20.GL_COMPILE_STATUS) == 0) {
System.out.println("Error Loading Shader: " + GL20.glGetShaderInfoLog(shader, Integer.MAX_VALUE));
GL20.glDeleteShader(shader);
return 0;
}
return shader;
}
}
Instead of just showing you what you asked for in the comments, I will demonstrate how you create, render and dispose a VAO using a VBO and IBO.
VAO <=> Vertex Array Object
VBO <=> Vertex Buffer Object
IBO <=> Index Buffer Object
Creating VAO, VBO & IBO
The vao_handle, vbo_handle and ibo_handle is 3 integers containing the id/handle, these 3 variables are used in the whole following code.
vbo_data <=> FloatBuffer containing the vertices
ibo_data <=> IntBuffer containing the indices
The two above variables are used in the following code.
// Creating the VBO
vbo_handle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo_handle);
glBufferData(GL_ARRAY_BUFFER, vbo_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Creating the IBO
ibo_handle = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_handle );
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ibo_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Creating the VAO
vao_handle = glGenVertexArrays();
glBindVertexArray(vao_handle);
glBindBuffer(GL_ARRAY_BUFFER, vbo_handle);
glEnableVertexAttribArray(INDEX); // Place your own INDEX value in the parenthesis
glVertexAttribPointer(INDEX, SIZE, TYPE, NORMALIZED, STRIDE, OFFSET); // Replace all the VARIABLES with the values which fit to your VAO, VBO and IBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_handle);
glBindVertexArray(0);
/*
* Remember that the INDEX given in the
* glEnableVertexAttribArray() and in
* glVertexAttribPointer() is the same
* INDEX used in Shaders (GLSL)
*
* If the INDEX is 0 then in GLSL it
* should look like this
* GLSL: layout(location = 0) in vec3 position;
*
* ^ we can ignore this if you aren't
* using Shaders, though keep it in mind
* since we might need it in the future
*/
Rendering VAO
glBindVertexArray(vao_handle);
glDrawElements(MODE, SIZE, TYPE, OFFSET); // Again replace the variables, so it fits to your VAO, VBO and IBO
glBindVertexArray(0);
Dispose VAO, VBO & IBO
This is how you delete the different buffers, which is a good thing to do, when you close the program or if at some point you don't need them anymore.
glDeleteVertexArrays(vao_handle); // Deletes the VAO
glDeleteBuffers(vbo_handle); // Deletes the VBO
glDeleteBuffers(ibo_handle); // Deletes the IBO
vao_handle = -1;
vbo_handle = -1;
ibo_handle = -1;
So I've tried to follow some tutorials on OpenGL and GLSL. I'm writing them in Java, using JOGL2, Original is in C++ though. All code compiles without any problems, shader preview in Shader designer even shows right effect, but when I run my app, it only draws blank white triangle. I can't find where am I making a mistake at all-.- btw my graphics card is Geforce GT330M, supports OpenGL 3.3, GLSL 3.30. newest drivers installed, so that shouldnt be a problem I guess.
My code for loading and creating a shader:
package OpenGL33.Utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import javax.media.opengl.GL3;
public class ShaderUtils {
public int createProgram(GL3 gl, String vertexSource, String fragmentSource) throws IOException{
int v = gl.glCreateShader(GL3.GL_VERTEX_SHADER);
int f = gl.glCreateShader(GL3.GL_FRAGMENT_SHADER);
String[] strings;
/*
* vertex shader
*/
strings = loadResource(vertexSource);
gl.glShaderSource(v, strings.length, strings, (int[]) null, 0);
gl.glCompileShader(v);
/*
* fragment shader
*/
strings = loadResource(fragmentSource);
gl.glShaderSource(f, strings.length, strings, (int[]) null, 0);
gl.glCompileShader(f);
/*
* Create shader program and attach shaders
*/
int program = gl.glCreateProgram();
gl.glAttachShader(program, v);
gl.glAttachShader(program, f);
gl.glLinkProgram(program);
gl.glValidateProgram(program);
return program;
}
private String[] loadResource(String resource) throws IOException{
BufferedReader reader;
ArrayList<String> input = new ArrayList<String>();
String line;
reader = new BufferedReader(new InputStreamReader(getClass().getResource(resource).openStream()));
while ((line = reader.readLine()) != null) {
input.add(line);
}
String[] strings = new String[input.size()];
input.toArray(strings);
return strings;
}
}
Vertex shader:
#version 330
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
}
Fragment shader:
#version 330
out vec4 outputColor;
void main()
{
float lerpValue = gl_FragCoord.y / 500.0f;
outputColor = mix(vec4(1.0f, 1.0f, 1.0f, 1.0f),
vec4(0.0f, 0.0f, 0.0f, 1.0f), lerpValue);
}
and OpenGlListener class:
package OpenGL33;
import OpenGL33.Utils.ShaderUtils;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.gl2.GLUT;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.media.opengl.GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
class OpenGlListener implements GLEventListener{
private GLU glu = new GLU();
private GLUT glut = new GLUT();
// vertex buffer
private FloatBuffer vertices;
private int[] verticesBuffer = new int[1];
private int shaderProgram;
private ShaderUtils sUtils;
// triangle coords
public static final float[] vertexPositions = {
0.0f, 0.5f, 0.0f, 1.0f,
0.5f, -0.366f, 0.0f, 1.0f,
-0.5f, -0.366f, 0.0f, 1.0f};
public OpenGlListener(){
sUtils = new ShaderUtils();
}
public void initializeVertexBuffer(GLAutoDrawable drawable){
GL3 gl = drawable.getGL().getGL3bc();
vertices = Buffers.newDirectFloatBuffer(vertexPositions.length);
vertices.put(vertexPositions);
vertices.position(0);
gl.glGenBuffers(1, verticesBuffer, 0);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, verticesBuffer[0]);
gl.glBufferData(GL3.GL_ARRAY_BUFFER, vertexPositions.length * 4 * Buffers.SIZEOF_FLOAT, vertices, GL3.GL_STATIC_DRAW);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0);
}
#Override
public void init(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
// check VBO support
if(!gl.isExtensionAvailable("GL_ARB_vertex_buffer_object")){
System.err.println("Error - missing VBO support");
}
// load shaders
try{
//tutorial 1
shaderProgram = sUtils.createProgram(gl, "/resources/shaders/FragPosition.vert", "/resources/shaders/FragPosition.frag");
//tutorial 2
//shaderProgram = sUtils.createProgram(gl, "/resources/shaders/MultiInput.vert", "/resources/shaders/MultiInput.frag");
}
catch (IOException ex) {
Logger.getLogger(OpenGlListener.class.getName()).log(Level.SEVERE, null, ex);
}
initializeVertexBuffer(drawable);
}
#Override
public void dispose(GLAutoDrawable drawable) {
//To change body of generated methods, choose Tools | Templates.
}
#Override
public void display(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
gl.glClear(GL3.GL_COLOR_BUFFER_BIT);
gl.glUseProgram(shaderProgram);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, verticesBuffer[0]);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0, 4, GL3.GL_FLOAT, false, 0, 0);
gl.glDrawArrays(GL3.GL_TRIANGLES, 0, 3);
gl.glDisableVertexAttribArray(0);
gl.glUseProgram(0);
drawable.swapBuffers();
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
GL3 gl = drawable.getGL().getGL3bc();
gl.glViewport(0, 0, width, height);
}
}
App runs in swing window, drawing in GLJPanel.