INVALID_OPERATION code 1282

Started by ted_gress, August 20, 2016, 00:29:15

Previous topic - Next topic

ted_gress

Hi, I'm just learning how to use the lwgl and I'm getting the following error:

Exception in thread "main" org.lwjgl.opengl.OpenGLException: Cannot use offsets when Array Buffer Object is disabled
   at org.lwjgl.opengl.GLChecks.ensureArrayVBOenabled(GLChecks.java:93)
   at org.lwjgl.opengl.GL20.glVertexAttribPointer(GL20.java:951)
   at RenderEngine.Loader.storeDataInAttributeList(Loader.java:93)
   at RenderEngine.Loader.loadToVAO(Loader.java:31)
   at EngineTester.MainGameLoop.main(MainGameLoop.java:48)

Below is my code:


package RenderEngine;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

public abstract class ShaderProgram {

   private int programID;
   
   private int vertexShaderID;
   
   private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);
   
   private int fragmentShaderID;
   
   public ShaderProgram(String vertexFile, String fragmentFile)
   {
      vertexShaderID = loadShader(vertexFile, GL20.GL_VERTEX_SHADER);
      fragmentShaderID = loadShader(fragmentFile, GL20.GL_FRAGMENT_SHADER);
      programID = GL20.glCreateProgram();
      GL20.glAttachShader(programID, vertexShaderID);
      GL20.glAttachShader(programID, fragmentShaderID);
      bindAttributes();
      GL20.glLinkProgram(programID);
      GL20.glValidateProgram(programID);;
   
   
   }

   protected abstract void getALlUniformLocations();
   
   protected int getUnifromLocation(String uniformName)
   {
      return GL20.glGetUniformLocation(programID, uniformName);
   }
   
   public void start() {
      GL20.glUseProgram(programID);
   }
   
   public void stop() {
      GL20.glUseProgram(0);
   }
   
   public void cleanUp()
   {
      stop();
      GL20.glDetachShader(programID, vertexShaderID);
      GL20.glDetachShader(programID, fragmentShaderID);
      GL20.glDeleteShader(vertexShaderID);
      GL20.glDeleteShader(fragmentShaderID);
      GL20.glDeleteProgram(programID);
   }
   
   protected void bindAttribute(int attribute, String variableName)
   {
      GL20.glBindAttribLocation(programID, attribute, variableName);
   }
   
   protected abstract void bindAttributes();
   
   
   protected void loadFloat(int location, float value)
   {
      GL20.glUniform1f(location, value);
   }
   
   protected void loadVector(int location, Vector3f vector)
   {
      GL20.glUniform3f(location, vector.x, vector.y, vector.z);
   }
   
   protected void loadBoolean(int location, boolean value)
   {
      float toLoad = 0;
      if (value)
         toLoad = 1;
      GL20.glUniform1f(location, toLoad);
   }
   
   protected void loadMatrix(int location, Matrix4f matrix)
   {
      matrix.store(matrixBuffer);
      matrixBuffer.flip();
      
      
      GL20.glUniformMatrix4(location, false, matrixBuffer);
   }
   
   @SuppressWarnings("deprecation")
   private static int loadShader(String file, int type)
   {
      StringBuilder shaderSource = new StringBuilder();
      try
      {
         BufferedReader reader = new BufferedReader(new FileReader(file));
         String line;
         
         while ((line = reader.readLine()) != null) {
            shaderSource.append(line).append("\n");
         }
         reader.close();
         
      }
      catch (IOException e) {
         System.err.println("Could not read file!");
         e.printStackTrace();
         System.exit(-1);
      }
      
      int shaderID = GL20.glCreateShader(type);
      GL20.glShaderSource(shaderID, shaderSource);
      GL20.glCompileShader(shaderID);
      
      if (GL20.glGetShader(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE)
      {
         System.out.println(GL20.glGetShaderInfoLog(shaderID,  500));
         System.err.println("Could not compile shader");
         System.exit(-1);

      }
      return shaderID;
   }
   
}

quew8

OK firstly, the exception is being thrown in your "Loader" class so you've shown us the wrong code.

Secondly when you post code please use code tags - makes it so much easier to read, especially when referencing line numbers. (The insert code button is the one with the "#" symbol. Or you can type the code bbc markup tags around the code. "[code]" before and "[/code] after".

Now. The exception is thrown because you are trying to specify vertex pointers as an offset and stride into a vertex buffer when you have no vertex buffer (VBO) bound (0 is bound to the GL_ARRAY_BUFFER target), so that offset and stride are meaningless. Now I can't really tell what you're trying to do without the code but make sure you create and bind your VBO before setting up the vertex pointers.

ted_gress

Hi. I think my VBOs are being bound before my VAOs??

Here is my code (sorry about not doing a code block before this is the first time I posted on this forum)

package RenderEngine;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

import models.RawModel;

public class Loader {
	
	private List<Integer> vaos = new ArrayList<Integer>();
	private List<Integer> vbos = new ArrayList<Integer>();
	private List<Integer> textures = new ArrayList<Integer>();
	
	public RawModel loadToVAO(float [] positions, float [] textureCoords,  int [] indices)
	{
		int vaoID = createVAO();
		bindIndicesVBO(indices);
		storeDataInAttributeList(0, 3, positions);
		storeDataInAttributeList(1, 2, textureCoords);

		unbindVAO();
		return new RawModel(vaoID, indices.length);
	
	}
	
	public int loadTexture(String fileName)
	{
		Texture texture = null;
		try {
			texture = TextureLoader.getTexture("PNG", new FileInputStream("res"+fileName+".png"));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		int textureID = texture.getTextureID();
		textures.add(textureID);
		return textureID;
	}
	
	
	public void cleanUp()
	{
		for (int vao:vaos)
		{
			GL30.glDeleteVertexArrays(vao);
		}
		
		for (int vbo:vbos)
		{
			GL15.glDeleteBuffers(vbo);
		}
		
		for (int texture:textures)
		{
			GL11.glDeleteTextures(texture);
		}
	}
	
	private int createVAO() {
	
		
		int vaoID = GL30.glGenVertexArrays();
		
		
		vaos.add(vaoID);
		GL30.glBindVertexArray(vaoID);
		return vaoID;
	}
	
	private void storeDataInAttributeList(int attributeNumber, int coordinateSize, float [] data) {
		int vboID = GL15.glGenBuffers();
		vbos.add(vboID);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboID);
		FloatBuffer buffer = storeDataInFloatBuffer(data);
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
		GL20.glVertexAttribPointer(attributeNumber, coordinateSize, GL11.GL_FLOAT, false, 0, 0);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER,  0);
	}
	
	private void unbindVAO() {
		GL30.glBindVertexArray(0);
	}
	
	private void bindIndicesVBO(int [] indices) { 
		int vboID = GL15.glGenBuffers();
		vbos.add(vboID);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboID);
	
		IntBuffer buffer = storeDataInIntBuffer(indices);
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_COPY);
	
	}
	
	private IntBuffer storeDataInIntBuffer(int [] data)
	{
		IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
		buffer.put(data);
		buffer.flip();
		return buffer;
	}
	
	
	private FloatBuffer storeDataInFloatBuffer(float[] data)
	{
		FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
		buffer.put(data);
		buffer.flip();
		return buffer;
	}
}

quew8

Not a problem. We're all here to learn.

This function is your problem.
private void storeDataInAttributeList(int attributeNumber, int coordinateSize, float [] data) {
    int vboID = GL15.glGenBuffers();
    vbos.add(vboID);
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboID);
    FloatBuffer buffer = storeDataInFloatBuffer(data);
    GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
    GL20.glVertexAttribPointer(attributeNumber, coordinateSize, GL11.GL_FLOAT, false, 0, 0);
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER,  0);
}

You're binding your VBOs to the wrong target. Index data gets put in an GL_ELEMENT_ARRAY_BUFFER (aka IBO) and you reference this when you call a function like glDrawElements(). Vertex data goes in an GL_ARRAY_BUFFER (aka VBO) and is referenced when calling functions like glVertexAttribPointer()  (which sets up an attribute pointer and it is THIS that is then dereferenced when drawing primitives). You might have already knew all this and have just made a typo but getting it clear in your head is always helpful (so for example you can understand why array buffer binding is not part of VAO state. Now I'm just fact dropping here in case it turns out to be useful).

Anyway TLDR;
You need to change every instance of "GL_ELEMENT_ARRAY_BUFFER" in the above to "GL_ARRAY_BUFFER".

ted_gress

Ok. Update. The code now uses ARRAY_BUFFER instead of ARRAY_ELEMENT_BUFFER as such:

package RenderEngine;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

import models.RawModel;

public class Loader {
	
	private List<Integer> vaos = new ArrayList<Integer>();
	private List<Integer> vbos = new ArrayList<Integer>();
	private List<Integer> textures = new ArrayList<Integer>();
	
	public RawModel loadToVAO(float [] positions, float [] textureCoords,  int [] indices)
	{
		int vaoID = createVAO();
		bindIndicesVBO(indices);
		storeDataInAttributeList(0, 3, positions);
		storeDataInAttributeList(1, 2, textureCoords);

		unbindVAO();
		return new RawModel(vaoID, indices.length);
	
	}
	
	public int loadTexture(String fileName)
	{
		Texture texture = null;
		try {
			texture = TextureLoader.getTexture("PNG", new FileInputStream("res"+fileName+".png"));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		int textureID = texture.getTextureID();
		textures.add(textureID);
		return textureID;
	}
	
	
	public void cleanUp()
	{
		for (int vao:vaos)
		{
			GL30.glDeleteVertexArrays(vao);
		}
		
		for (int vbo:vbos)
		{
			GL15.glDeleteBuffers(vbo);
		}
		
		for (int texture:textures)
		{
			GL11.glDeleteTextures(texture);
		}
	}
	
	private int createVAO() {
	
		
		int vaoID = GL30.glGenVertexArrays();
		
		
		vaos.add(vaoID);
		GL30.glBindVertexArray(vaoID);
		return vaoID;
	}
	
	private void storeDataInAttributeList(int attributeNumber, int coordinateSize, float [] data) {
		int vboID = GL15.glGenBuffers();
		vbos.add(vboID);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
		FloatBuffer buffer = storeDataInFloatBuffer(data);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
		GL20.glVertexAttribPointer(attributeNumber, coordinateSize, GL11.GL_FLOAT, false, 0, 0);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,  0);
	}
	
	private void unbindVAO() {
		GL30.glBindVertexArray(0);
	}
	
	private void bindIndicesVBO(int [] indices) { 
		int vboID = GL15.glGenBuffers();
		vbos.add(vboID);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
	
		IntBuffer buffer = storeDataInIntBuffer(indices);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_COPY);
	
	}
	
	private IntBuffer storeDataInIntBuffer(int [] data)
	{
		IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
		buffer.put(data);
		buffer.flip();
		return buffer;
	}
	
	
	private FloatBuffer storeDataInFloatBuffer(float[] data)
	{
		FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
		buffer.put(data);
		buffer.flip();
		return buffer;
	}
}


Here is the exception:

Sat Aug 20 19:27:16 EDT 2016 INFO:Use Java PNG Loader = true
Exception in thread "main" org.lwjgl.opengl.OpenGLException: Invalid operation (1282)
	at org.lwjgl.opengl.Util.checkGLError(Util.java:59)
	at org.lwjgl.opengl.GL20.glUniformMatrix4(GL20.java:511)
	at RenderEngine.ShaderProgram.loadMatrix(ShaderProgram.java:96)
	at RenderEngine.StaticShader.loadViewMatrix(StaticShader.java:47)
	at EngineTester.MainGameLoop.main(MainGameLoop.java:65)


And finally the shaders:

(vertex)

#version 330 core

in vec3 position;
in vec2 textureCoords;


out vec3 colour;
out vec2 pass_textureCoords;

uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;


void main(void) {

	gl_Position = viewMatrix * projectionMatrix * transformationMatrix * vec4(position, 1.0);
	pass_textureCoords = textureCoords;
	colour = vec3(position.x+0.5, 0.0, position.y+0.5);
}


(fragment)

#version 330 core

in vec2 pass_textureCoords;

out vec4 out_Color;

uniform sampler2D textureSampler;

void main(void) 
{

	out_Color = texture(textureSampler, pass_textureCoords);
}


Anything stand out explicitly to you guys? I can't figure out what exactly the problem is...


quew8

Well you haven't posted the source for StaticShader.loadViewMatrix() so can't tell what arguments ShaderProgram.loadMatrix() is called with. But as ever the place to go when you want to know what's going wrong is the docs: http://docs.gl/gl2/glUniform.

Causes for invalid operation
QuoteGL_INVALID_OPERATION is generated if there is no current program object.
Potentially

QuoteGL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.
Nope. Using matrix4 for a mat4. That's fine.

QuoteGL_INVALID_OPERATION is generated if one of the integer variants of this function is used to load a uniform variable of type float, vec2, vec3, vec4, or an array of these, or if one of the floating-point variants of this function is used to load a uniform variable of type int, ivec2, ivec3, or ivec4, or an array of these.
Again not a problem.

QuoteGL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1.
Potentially. (The -1 thing btw is because glGetUniformLocation() returns -1 if there is no such uniform variable and if this is the case glUniform*() is supposed to silently fail)

QuoteGL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.
Not a sampler.

QuoteGL_INVALID_OPERATION is generated if glUniform is executed between the execution of glBegin and the corresponding execution of glEnd.
Potentially but very unlikely.

So there are three potentials there and only two of them are really likely.

ted_gress

Thanks! The problem was the shader programs not compiling. Although I am getting this error now:

Program Shader Compile Failed
Sat Aug 20 23:59:46 EDT 2016 INFO:Use Java PNG Loader = true
Exception in thread "main" org.lwjgl.opengl.OpenGLException: Invalid operation (1282)
	at org.lwjgl.opengl.Util.checkGLError(Util.java:59)
	at org.lwjgl.opengl.GL20.glUniformMatrix4(GL20.java:511)
	at RenderEngine.ShaderProgram.loadMatrix(ShaderProgram.java:104)
	at RenderEngine.StaticShader.loadViewMatrix(StaticShader.java:47)
	at EngineTester.MainGameLoop.main(MainGameLoop.java:65)



I tried changing around the path and it didn't seem to fix it. Not sure what else could be wrong.

ted_gress

So I'm getting this error. I searched google but didn't get an answer I quite understood:

Program Shader Compile Failed
Exception in thread "main" org.lwjgl.opengl.OpenGLException: Cannot use offsets when Array Buffer Object is disabled
	at org.lwjgl.opengl.GLChecks.ensureArrayVBOenabled(GLChecks.java:93)
	at org.lwjgl.opengl.GL20.glVertexAttribPointer(GL20.java:951)
	at RenderEngine.Loader.storeDataInAttributeList(Loader.java:93)
	at RenderEngine.Loader.loadToVAO(Loader.java:31)
	at EngineTester.MainGameLoop.main(MainGameLoop.java:48)

quew8

That's the problem you were having initially. Did you do my fix?