My shaders will not work :( - Porting C++ Code to LWJGL

Started by storm8ring3r, September 10, 2015, 15:40:18

Previous topic - Next topic

storm8ring3r

Hi everyone!
I'm new here and to LWJGL3/OpenGL and am working on a project porting C++ code to LWJGL. 
I am at my wits end.
The Model (Stanford Bunny) renders, but whenever I try to use the shaders from the old project, I get a blank (black) window. I am attaching the C++ source code, the shaders and my java project. There is a simple mistake somewhere, and I can't find it. Probably because I am so new to graphics programming.

package main;

import org.joml.Matrix4f;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWvidmode;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;

import util.ObjectModel;
import util.Shader;
import util.OBJLoader;
import static util.OBJLoader.*;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import static org.lwjgl.glfw.Callbacks.errorCallbackPrint;
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.NULL;

public class ModelDemo {
	// FloatBuffer um Matrizen an OpenGL übergeben zu können
	static FloatBuffer fb = BufferUtils.createFloatBuffer(16);
	// Callbacks brauchen eine starke Referenz, damit sie nicht Garbage-collected werden.
	private static GLFWErrorCallback errorCallback;
	private static GLFWKeyCallback keyCallback;

	// Das Handle für das Fenster
	private static long window;

	private static int vaoHandle;
	private static int vboHandle;
	public static int iboHandle;

	// Dateipfade der Ressourcen
	private static final String FRAGSHADER_PATH = "resources/simple.frag";
	private static final String VERTSHADER_PATH = "resources/simple.vert";
	private static final String MODEL_LOCATION = "resources/bunny.obj";

	private static Shader shader;

	private static Matrix4f projectionMatrix = new Matrix4f(2.414214f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
			2.414214f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, -1.002002f, -1.000000f, 0.000000f, 0.000000f,
			0.020020f, 0.000000f);

	private static Matrix4f modelViewMatrix = new Matrix4f((float) 0.707107, (float) -0.408248, (float) 0.577350,
			(float) 0.000000, (float) 0.000000, (float) 0.816497, (float) 0.577350, (float) 0.000000, (float) -0.707107,
			(float) -0.408248, (float) 0.577350, (float) 0.000000, (float) 0.025249, (float) -0.085015,
			(float) -0.391099, (float) 1.000000);

	private static ObjectModel model;

	public static void main(String[] args) {

		try {
			init();
			updateGL();
			cleanUp();
		} finally {
			// Terminate GLFW and release the GLFWerrorfun
			glfwTerminate();
			errorCallback.release();
		}
		System.exit(0);
	}

	private static void init() {
		// Error Callback setzen. Die standard-Implementierung schreibt
		// Fehlermeldungen
		// in System.err
		glfwSetErrorCallback(errorCallback = errorCallbackPrint(System.err));

		// GLFW Initialisieren. Die meisten GLFW-Funktionen funktionieren vorher
		// nicht.
		if (glfwInit() != GL11.GL_TRUE)
			throw new IllegalStateException("Unable to initialize GLFW");

		// Konfigurieren des Fensters
		glfwDefaultWindowHints(); // optional, die aktuellen Window-Hints sind
									// bereits Standardwerte
		glfwWindowHint(GLFW_VISIBLE, GL_FALSE); // Das Fenster bleibt nach dem
												// Erzeugen versteckt.
		glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Die Fenstergröße lässt sich
													// verändern.

		int WIDTH = 512;
		int HEIGHT = 512;

		// Das Fenster erzeugen.
		window = glfwCreateWindow(WIDTH, HEIGHT, "Exercise 02 - Play with the bunny", NULL, NULL);
		if (window == NULL)
			throw new RuntimeException("Failed to create the GLFW window");

		// Key-Callback aufsetzen. Wird jedes mal gerufen, wenn eine Taste
		// gedrückt oder losgelassen wird.
		glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() {
			@Override
			public void invoke(long window, int key, int scancode, int action, int mods) {
				if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
					glfwSetWindowShouldClose(window, GL_TRUE); // Auf dieser
																// Wert wird im
																// Rendering-Loop
																// überprüft.
			}
		});

		// Auflösung des primären Displays holen.
		ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
		// Fenster zentrieren
		glfwSetWindowPos(window, (GLFWvidmode.width(vidmode) - WIDTH) / 2, (GLFWvidmode.height(vidmode) - HEIGHT) / 2);

		// Den OpenGL Kontext aktuell machen.
		glfwMakeContextCurrent(window);
		// V-Sync aktivieren.
		glfwSwapInterval(1);

		// GL Kontext unter Berücksichtigung des Betriebssystems erzeugen.
		// GLContext.createFromCurrent();
		GL.createCapabilities();
		System.out.println("Your OpenGL version is " + GL11.glGetString(GL11.GL_VERSION));
		// Das Fenster sichtbar machen.
		glfwShowWindow(window);
	}

	private static void initShader() {
		shader = new Shader(VERTSHADER_PATH, FRAGSHADER_PATH);
	}

	private static void updateGL() {
		// Die Hintergrundfarbe (Clear Color) setzen.
		// Enable depth testing
		glEnable(GL_DEPTH_TEST);
		glEnable(GL_CULL_FACE);
		glCullFace(GL_BACK);

		initShader();
		initScene();

		while (glfwWindowShouldClose(window) == GL_FALSE) {
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			projectionMatrix.get(fb);
			glUniformMatrix4fv(glGetUniformLocation(shader.getID(), "projection"), false, fb);

			modelViewMatrix.get(fb);
			glUniformMatrix4fv(glGetUniformLocation(shader.getID(), "modelview"), false, fb);
			renderScene();
			glfwSwapBuffers(window);
			glfwPollEvents();
		}
	}

	static void initScene() {
		try {
			model = OBJLoader.loadObjectModel(new File(MODEL_LOCATION));
		} catch (IOException e) {
			e.printStackTrace();
			cleanUp();
			System.exit(1);
		}
		vaoHandle = glGenVertexArrays();
		glBindVertexArray(vaoHandle);

		vboHandle = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, vboHandle);
		
		FloatBuffer vertices = OBJLoader.reserveData(model.getFaces().size() * 18);
		for (ObjectModel.Face face : model.getFaces()) {
			vertices.put(asFloats(ObjectModel.getVertices().get(face.getVertexIndices()[0] - 1)));
			vertices.put(asFloats(ObjectModel.getVertices().get(face.getVertexIndices()[1] - 1)));
			vertices.put(asFloats(ObjectModel.getVertices().get(face.getVertexIndices()[2] - 1)));
		}
		for (ObjectModel.Face face : model.getFaces()) {
			vertices.put(asFloats(ObjectModel.getNormals().get(face.getNormalIndices()[0] - 1)));
			vertices.put(asFloats(ObjectModel.getNormals().get(face.getNormalIndices()[1] - 1)));
			vertices.put(asFloats(ObjectModel.getNormals().get(face.getNormalIndices()[2] - 1)));
		}
		vertices.flip();

		glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
		glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0L);
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0L + (3 * model.getFaces().size() * 4));
		glEnableVertexAttribArray(1);
		
		iboHandle = glGenBuffers();
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboHandle);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
		glBindVertexArray(0);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
	}

	private static void renderScene() {
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		 shader.start();
		glBindVertexArray(vaoHandle);
		glDrawArrays(GL_TRIANGLES, 0, ObjectModel.getVertices().size() * 3);

		glBindVertexArray(0);
		 shader.stop();
	}

	private static void cleanUp() {
		glfwDestroyWindow(window);
		keyCallback.release();
	}
}


Please ignore the horrible coding style, I will refactor everything into proper object-oriented Java style once I can see the bunny. Especially loading the Object and populating the Buffers.

These are the shaders:

#version 330
in vec3 vertexColor;
out vec4 color;

void main() {
  color = vec4(0.5 * normalize(vertexColor) + vec3(0.5, 0.5, 0.5), 1);  
}


#version 330
layout(location = 0) in vec3 vertex;
layout(location = 1) in vec3 normal;
out vec3 vertexColor;

uniform  mat4 modelview;
uniform  mat4 projection;

void main() {
  vertexColor = (modelview * vec4(normal, 0)).xyz;
  gl_Position = projection * modelview * vec4(vertex, 1.0);
}


And finally, the old code I am using as a reference:

#include "Ex02.h"

// OpenGL and GLSL stuff //
void initGL();
void initShader();
bool enableShader();
void disableShader();
void deleteShader();
char* loadShaderSource(const char* fileName);
GLuint loadShaderFile(const char* fileName, GLenum shaderType);
GLuint shaderProgram = 0;
GLint uniform_projectionMatrix;
GLint uniform_modelViewMatrix;

// window controls //
void updateGL();
void idle();
void keyboardEvent(unsigned char key, int x, int y);

// geometry //
GLuint bunnyVAO = 0;
GLuint bunnyVBO = 0;
GLuint bunnyIBO = 0;

void initScene();
void deleteScene();
void renderScene();

// view matrices //
glm::mat4 projectionMatrix = glm::mat4(2.414214, 0.000000, 0.000000, 0.000000, 0.000000, 2.414214, 0.000000, 0.000000, 0.000000, 0.000000, -1.002002, -1.000000, 0.000000, 0.000000, -0.020020, 0.000000);
glm::mat4 modelViewMatrix = glm::mat4(0.707107, -0.408248, 0.577350, 0.000000, 0.000000, 0.816497, 0.577350, 0.000000, -0.707107, -0.408248, 0.577350, 0.000000, 0.025249, -0.085015, -0.391099, 1.000000);

bool glError(char *msg) {
	// check OpenGL error
    GLenum err;
	bool err_occured = false;
    while ((err = glGetError()) != GL_NO_ERROR) {
		err_occured = true;
		if (msg == "") {
			std::cerr << "OpenGL error : " << err << std::endl;
		}
		else std::cerr << "OpenGL error ( " << msg << " ) : " << err << std::endl;
    }
	return err_occured;
}

int main (int argc, char **argv) {
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitContextVersion(3,3);
  glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
  glutInitContextProfile(GLUT_CORE_PROFILE);

  glutInitWindowSize (512, 512);
  glutInitWindowPosition (100, 100);
  glutCreateWindow("Exercise 02 - Play with the bunny");
  
  glutDisplayFunc(updateGL);
  glutIdleFunc(idle);
  glutKeyboardFunc(keyboardEvent);
  
  glError("before creating rendering context");

  glewExperimental = GL_TRUE;
  GLenum err = glewInit();
  if (GLEW_OK != err) {
    std::cout << "(glewInit) - Error: " << glewGetErrorString(err) << std::endl;
  }
  std::cout << "(glewInit) - Using GLEW " << glewGetString(GLEW_VERSION) << std::endl;

  glError("rendering context created");
  
  // init stuff //
  initGL();
  initShader();
  initScene();
  
  // start render loop //
  if (enableShader()) {
    glutMainLoop();
    disableShader();
    
    // clean up allocated data //
    deleteScene();
    deleteShader();
  }
  
  return 0;
}

void initGL() {
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glEnable(GL_DEPTH_TEST);
}

void initShader() {
  // TODO:
  //  load the vertex and fragment shader from source files attach them to a shader program
  //  - load the file "shader/simple.vert" as GL_VERTEX_SHADER
  //  - load the file "shader/simple.frag" as GL_FRAGMENT_SHADER
  //  - create a shader program "shaderProgram" (global member)
  //  - attach both shaders to this shader program
  //  - link the shader program
  
  // TODO: create new shader program "shaderProgram" //
  shaderProgram = glCreateProgram();
  // check if operation failed //
  if (shaderProgram == 0) {
    std::cout << "(initShader) - Failed creating shader program." << std::endl;
    return;
  }
  
  // TODO: load vertex shader source //
  GLuint vertexShader = loadShaderFile("../shader/simple.vert", GL_VERTEX_SHADER);
  //GLuint vertexShader = loadShaderFile("simple.vert", GL_VERTEX_SHADER);
  if (vertexShader == 0) {
    std::cout << "(initShader) - Could not create vertex shader." << std::endl;
    deleteShader();
    return;
  }
  // TODO: load fragment shader source //
  GLuint fragmentShader = loadShaderFile("../shader/simple.frag", GL_FRAGMENT_SHADER);
  //GLuint fragmentShader = loadShaderFile("simple.frag", GL_FRAGMENT_SHADER);
  if (fragmentShader == 0) {
    std::cout << "(initShader) - Could not create vertex shader." << std::endl;
    deleteShader();
    return;
  }
  
  // successfully loaded and compiled shaders -> attach them to program //
  // attach shaders to "shaderProgram" //
  glAttachShader(shaderProgram, vertexShader);
  glAttachShader(shaderProgram, fragmentShader);
  
  // mark shaders for deletion after clean up (they will be deleted, when detached from all shader programs) //
  glDeleteShader(vertexShader);
  glDeleteShader(fragmentShader);
  
  // link shader program //
  glLinkProgram(shaderProgram);
  
  // get log //
  int logMaxLength = 0;
  glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &logMaxLength);
  char *log = new char[logMaxLength]();
  int logLength = 0;
  glGetShaderInfoLog(shaderProgram, logMaxLength, &logLength, log);
  if (logLength > 0) {
    std::cout << "(initShader) - Linker log:\n------------------\n" << log << "\n------------------" << std::endl;
  }
  delete[] log;
  
  // set address of fragment color output //
  glBindFragDataLocation(shaderProgram, 0, "color");
}

bool enableShader() {
  if (shaderProgram > 0) {
    glUseProgram(shaderProgram);
  } else {
    std::cout << "(enableShader) - Shader program not initialized." << std::endl;
  }
  return shaderProgram > 0;
}

void disableShader() {
  glUseProgram(0);
}

void deleteShader() {
  // use standard pipeline //
  glUseProgram(0);
  // delete shader program //
  glDeleteProgram(shaderProgram);
  shaderProgram = 0;
}

// load and compile shader code //
char* loadShaderSource(const char* fileName) {
  char *shaderSource = NULL;
  
  // TODO:
  //  import source code from a given file
  //  - open file
  //  - read in file into char array
  //  - close file and return array
  
  
  std::ifstream file(fileName, std::ios::in);
  if (file.is_open()) {
    unsigned long srcLength = 0;
    file.tellg();
    file.seekg(0, std::ios::end);
    srcLength = file.tellg();
    file.seekg(0, std::ios::beg);
    shaderSource = new char[srcLength];
    file.read(shaderSource, srcLength);
    file.close();
  } else {
    std::cout << "(loadShaderSource) - Could not open file \"" << fileName << "\"." << std::endl;
  }
  
  //std::cout << shaderSource << std::endl;
  
  return shaderSource;
}

// loads a source file and directly compiles it to a shader of 'shaderType' //
GLuint loadShaderFile(const char* fileName, GLenum shaderType) {
  // TODO:
  //  create a shader program using code from a given file
  //  - create new shader of appropriate shader type (defined by 'shaderType')
  //  - load shader source from file
  //  - load shader source into shader and compile
  //  - (check for compilation errors (shader info log) )
  //  - return compiled shader
  
  
  // TODO: create new shader of type "shaderType" //
  GLuint shader = glCreateShader(shaderType);
  // check if operation failed //
  if (shader == 0) {
    std::cout << "(loadShaderFile) - Could not create shader." << std::endl;
    return 0;
  }
  
  // TODO: load source code from file //
  const char* shaderSrc = loadShaderSource(fileName);
  if (shaderSrc == NULL) return 0;
  // TODO: pass source code to new shader object //
  glShaderSource(shader, 1, (const char**)&shaderSrc, NULL);

  delete[] shaderSrc;
  // TODO: compile shader //
  glCompileShader(shader);
  
  // log compile messages, if any //
  int logMaxLength;
  glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logMaxLength);
  char *log = new char[logMaxLength]();
  int logLength = 0;
  glGetShaderInfoLog(shader, logMaxLength, &logLength, log);
  if (logLength > 0) {
    std::cout << "(loadShaderFile) - Compiler log:\n------------------\n" << log << "------------------" << std::endl;
  }
  delete[] log;
  
  // return compiled shader (may have compiled WITH errors) //
  return shader;
}

void initScene() {  

  // TODO: import data from bunny.h and concatenate vertex and normal data //
  GLfloat vertexList[6 * NUM_POINTS];
  std::copy(bunny, bunny + 3 * NUM_POINTS, &vertexList[0]);
  std::copy(normals, normals + 3 * NUM_POINTS, &vertexList[3 * NUM_POINTS]);
    
  // TODO: init VAO //
  if (bunnyVAO == 0) {
    glGenVertexArrays(1, &bunnyVAO);
  }
  glBindVertexArray(bunnyVAO);
  
  // TODO: init and bind a VBO (vertex buffer object) //
  if (bunnyVBO == 0) {
    glGenBuffers(1, &bunnyVBO);
  }
  glBindBuffer(GL_ARRAY_BUFFER, bunnyVBO);

  // TODO: copy data into the VBO //
  glBufferData(GL_ARRAY_BUFFER, 6 * NUM_POINTS * sizeof(GLfloat), &vertexList[0], GL_STATIC_DRAW);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
  glEnableVertexAttribArray(0);

  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)(3 * NUM_POINTS * sizeof(GLfloat)));
  glEnableVertexAttribArray(1);
  
  // TODO: init and bind a IBO (index buffer object) //
  if (bunnyIBO == 0) {
    glGenBuffers(1, &bunnyIBO);
  }
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bunnyIBO);
  
  // TODO: copy data into the IBO //
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * NUM_TRIANGLES * sizeof(GLint), &triangles[0], GL_STATIC_DRAW);
  
  
  // unbind buffers //
  glBindVertexArray(0);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void deleteScene() {
  glDeleteBuffers(1, &bunnyIBO);
  glDeleteBuffers(1, &bunnyVBO);
  glDeleteVertexArrays(1, &bunnyVAO);
}

void renderScene() {
  if (bunnyVAO != 0) {
    // TODO: bind VAO //
    glBindVertexArray(bunnyVAO);
    
    // TODO: render VAO as triangles //
    glDrawElements(GL_TRIANGLES, 3 * NUM_TRIANGLES, GL_UNSIGNED_INT, (void*)0);
    
    // TODO: unbind active buffer //
    glBindVertexArray(0);
  }
}

GLfloat rotAngle = 0;
void updateGL() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  
  glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, false, glm::value_ptr(projectionMatrix));
  glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "modelview"), 1, false, glm::value_ptr(modelViewMatrix));

  // now the scene will be rendered //
  renderScene();
  
  // swap renderbuffers for smooth rendering //
  glutSwapBuffers();
}

void idle() {
  glutPostRedisplay();
}

void keyboardEvent(unsigned char key, int x, int y) {
  if (key == 'x' || key == 27) {
    exit(0);
  }
  glutPostRedisplay();
}


That code compiles without errors, and shows the model correctly.
Someone experienced may be able to help me with this  :(
Please tell me if you need to see my utility classes as well and thanks to anyone who takes a look at this :)

spasi

Hard to test the above code without the util.* classes.

Advice: set an OpenGL debug callback and inspect the shader/program info logs. The debug callback can be set easily with:

glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); // before creating the window
GLUtil.setupDebugMessageCallback(); // after GL.createCapabilities()

abcdef

change the clear color to white to see if you can see any sign of the object in the background. If you see the outline of a shape then you know its a color issue, else it must be a vertex data issue.

storm8ring3r

[LWJGL] OpenGL debug message
	ID: 0x501
	Source: API
	Type: ERROR
	Severity: HIGH
	Message: GL_INVALID_VALUE error generated. One or more handles do not refer to an object generated by OpenGL.
[LWJGL] OpenGL debug message
	ID: 0x20071
	Source: API
	Type: OTHER
	Severity: NOTIFICATION
	Message: Buffer detailed info: Buffer object 3 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.
[LWJGL] OpenGL debug message
	ID: 0x20071
	Source: API
	Type: OTHER
	Severity: NOTIFICATION
	Message: Buffer detailed info: Buffer object 4 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.
[LWJGL] OpenGL debug message
	ID: 0x502
	Source: API
	Type: ERROR
	Severity: HIGH
	Message: GL_INVALID_OPERATION error generated. No active program.


These are the errors it's throwing when I try to use the shaders. I'm making a mistake with some of the handles I guess?

FortressBuilder

Before any calls to glUniform* you have to activate the shader program with glUseProgram (or shader.start() in your example).

BTW: You should cache the values returned by glGetUniformLocation because querying values from OpenGL can be quite slow.

storm8ring3r

while (glfwWindowShouldClose(window) == GL_FALSE) {	
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			shader.start();
			projectionMatrix.get(fb);
			glUniformMatrix4fv(glGetUniformLocation(shader.getID(), "projection"), false, fb);
			modelViewMatrix.get(fb);
			glUniformMatrix4fv(glGetUniformLocation(shader.getID(), "modelview"), false, fb);
			render();
			shader.stop();
			glfwSwapBuffers(window);
			glfwPollEvents();
		}
	}


After this adjustment nothing renders and it is still throwing the following error three times
[LWJGL] OpenGL debug message
	ID: 0x501
	Source: API
	Type: ERROR
	Severity: HIGH
	Message: GL_INVALID_VALUE error generated. One or more handles do not refer to an object generated by OpenGL.

Compiling the shaders and validating the program doesn't throw any errors though. I'll have some more time to look at this later, any pointers on what else I should check? Thank you very much for the hint about the shaderprogram needing to be active before calling glunifrom, makes sense now that I think about it.

storm8ring3r

Okay, so this is a screenshot of what it's rendering when the shaders are commented out. It looks to me like maybe the vertices indexes are messed up?

storm8ring3r

okay, sorry for pushing my own topic, but I've made some progress (I was creating both shaders as a FRAGMENT_SHADER :-\ ). Nothing is being rendered still, with or without the shaders now, but I managed to get rid of all the errors concerning handles. I think I am still missing something with how the VAO, VBO and IBO are being set up, but this is what I have:
public static void initScene(ObjectModel model) {
    	model.VAO = glGenVertexArrays();
        glBindVertexArray(model.VAO);
        System.out.println("model.VAO = "+ model.VAO);
        
        model.VBO = glGenBuffers();

        System.out.println("model.VBO = "+ model.VBO);
        FloatBuffer vertices = reserveData(model.getFaces().size() * 9);
        FloatBuffer normals = reserveData(model.getFaces().size() * 9);
        for (ObjectModel.Face face : model.getFaces()) {
            vertices.put(asFloats(model.getVertices().get(face.getVertexIndices()[0] - 1)));
            vertices.put(asFloats(model.getVertices().get(face.getVertexIndices()[1] - 1)));
            vertices.put(asFloats(model.getVertices().get(face.getVertexIndices()[2] - 1)));
            normals.put(asFloats(model.getNormals().get(face.getNormalIndices()[0] - 1)));
            normals.put(asFloats(model.getNormals().get(face.getNormalIndices()[1] - 1)));
            normals.put(asFloats(model.getNormals().get(face.getNormalIndices()[2] - 1)));
        }
        vertices.flip();
        normals.flip();
        glBindBuffer(GL_ARRAY_BUFFER, model.VBO);
        
        glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0L);
        glEnableVertexAttribArray(0);
        
        glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, (model.getFaces().size() * 3 * 4));
        glEnableVertexAttribArray(1);
        
        model.IBO = glGenBuffers();
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model.IBO);

        System.out.println("model.IBO = "+ model.IBO);
        
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,(model.getFaces().size() * 3 * 4), GL_STATIC_DRAW);
        glBindVertexArray(0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

This is the console log for running:

Your OpenGL version is 4.5.0 NVIDIA 352.21
shaderID: 35633
shaderID: 35632
Shader programID: 3


model.VAO = 1
model.VBO = 3
[LWJGL] OpenGL debug message
	ID: 0x20071
	Source: API
	Type: OTHER
	Severity: NOTIFICATION
	Message: Buffer detailed info: Buffer object 3 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.
model.IBO = 4
Uniform mat4 projection location: 1
Uniform mat4 modelview location: 0
[LWJGL] OpenGL debug message
	ID: 0x20071
	Source: API
	Type: OTHER
	Severity: NOTIFICATION
	Message: Buffer detailed info: Buffer object 4 (bound to GL_ELEMENT_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.


Are the NOTIFICATIONs a problem? Am I setting up the buffer objects correctly? This is the main loop() and updateGL()
private static void loop() {
		while (glfwWindowShouldClose(window) == GL_FALSE) {
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			shader.start();
			System.out.println("Uniform mat4 projection location: " + shader.getUniform("projection"));
			System.out.println("Uniform mat4 modelview location: " + shader.getUniform("modelview"));
			projectionMatrix.get(fb);
			glUniformMatrix4fv(shader.getUniform("projection"), false, fb);
			modelViewMatrix.get(fb);
			glUniformMatrix4fv(shader.getUniform("modelview"), false, fb);

			updateGL();
			shader.stop();
			glfwSwapBuffers(window);
			glfwPollEvents();
}

	private static void updateGL() {
		glBindVertexArray(model.VAO);

		glDrawElements(GL_TRIANGLES, 3 * model.getFaces().size(), GL_UNSIGNED_INT, 0L);

		glBindVertexArray(0);
	}

spasi

Quote from: storm8ring3r on September 13, 2015, 16:23:07Are the NOTIFICATIONs a problem?

No. You can disable such notifications with GL43.glDebugMessageControl:

glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_OTHER, GL_DEBUG_SEVERITY_NOTIFICATION, null, false);


Please note that LWJGL currently has a bug here and won't allow the null parameter. It will be fixed in the next nightly build. Workaround:

nglDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_OTHER, GL_DEBUG_SEVERITY_NOTIFICATION, 0, NULL, false);

storm8ring3r

Thank your for the advice concerning the notifications. I think one thing that I am missing is how the .obj is being parsed, the vertices and normals aren't in the same order. Or does OpenGL need a sort of index buffer?

quew8

You can do index buffers in OpenGL but they have to be the same indices for all the different attributes (ie position and normal). So you cannot use wavefront (.obj) data directly and instead you must create a new buffer in the appropriate format.