Help needed with opengl 4 and glUniform4dv

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Help needed with opengl 4 and glUniform4dv

siddharth.cmdz
Hi all,

Ive been trying out jogl 2.2 for opengl 4 and im particularly interested in using double precision GL_ARB_gpu_shader_fp64 extension for vertices. It seems like my double precision matrices are not being passed to the vertex shader. I get error when i turn on debuggin/trace in jogl :

Caused by: javax.media.opengl.GLException: Thread[AWT-EventQueue-0,6,main] glGetError() returned the following error codes after a call to glUniformMatrix4dv(<int> 0x0, <int> 0x1, <boolean> false, <java.nio.DoubleBuffer> java.nio.HeapDoubleBuffer[pos=0 lim=16 cap=16]): GL_INVALID_OPERATION ( 1282 0x502),
        at javax.media.opengl.DebugGL4bc.writeGLError(DebugGL4bc.java:29466)
        at javax.media.opengl.DebugGL4bc.glUniformMatrix4dv(DebugGL4bc.java:23881)
        at javax.media.opengl.TraceGL4bc.glUniformMatrix4dv(TraceGL4bc.java:17451)
        at javax.media.opengl.TraceGL4bc.glUniformMatrix4dv(TraceGL4bc.java:17451)
        at com.jogl.modern.workshop.core.ShaderProgram.setMatrixUniformd(ShaderProgram.java:93)

My system specs are :
Windows 8.1
Geforce GTX 780


Heres how i have my code layed out:
Implementation of GLEventListener (named as Geometry4View.java):

  public void init(GLAutoDrawable glad) {
    final GL4 gl4 = glad.getGL().getGL4();
    if( gl4.isExtensionAvailable("GL_ARB_gpu_shader_fp64") ) {
      Logger.getLogger(Geometry4View.class.getName()).info("GL_ARB_gpu_shader_fp64 extension is available");
    } else {
      Logger.getLogger(Geometry4View.class.getName()).info("GL_ARB_gpu_shader_fp64 extension is not available");
    }
    if(_glDebug) {
      GL gl = glad.getGL();
      try {
        gl = gl.getContext().setGL(GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null));  
      } catch(Exception ex) {
        ex.printStackTrace();
      }
    }
    if(_glTrace) {
      GL gl = glad.getGL();
      try {
        gl = gl.getContext().setGL(GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) );
      } catch(Exception ex) {
        ex.printStackTrace();
      }
    }
    ..
    //init geometry passing GL
    ..
    for(ShaderProgram shader : _shaderProgList) {
      boolean status = shader.init(gl4);
      if(!status) {
        throw new IllegalStateException("Improper Shaders");
      }
    }
  }

In the above method, I see that i do have the extension GL_ARB_gpu_shader_fp64 is available.

My shader program is initialized like this:
  public boolean init(GL4 gl4) {
    _shaderIds = new int[_shaderStrs.length];
    _programId = gl4.glCreateProgram();
    for(int i = 0; i < _shaderStrs.length; i++) {
      ShaderType shaderType = _shaderTypes[i];
     
     
      _shaderIds[i] = gl4.glCreateShader(shaderType.getGLConstant());
      gl4.glShaderSource(_shaderIds[i], 1, new String[]{_shaderStrs[i]}, null);
      gl4.glCompileShader(_shaderIds[i]);
     
      IntBuffer compileStatus = IntBuffer.allocate(1);
      gl4.glGetShaderiv(_shaderIds[i], GL4.GL_COMPILE_STATUS, compileStatus);
      compileStatus.rewind();
      int status = compileStatus.get();
      if(status == GL4.GL_FALSE) {
        int bufSize = 1024;
        IntBuffer returnedBufLength = IntBuffer.allocate(bufSize);
        ByteBuffer infolog = ByteBuffer.allocate(bufSize);
        gl4.glGetShaderInfoLog(_shaderIds[i], bufSize, returnedBufLength, infolog);
        infolog.rewind();
        StringBuilder builder = new StringBuilder();
        builder.append("Shader : "+_shaderTypes[i].toString()+" error : "+new String(infolog.array()));
        _error = builder.toString();
        return false;
      }
     
      //attach shader to program.
      gl4.glAttachShader(_programId, _shaderIds[i]);
    }
   
    gl4.glLinkProgram(_programId);
   
    StringBuilder builder = new StringBuilder();
    boolean shaderStatus = checkShaderLinkStatus(gl4, _programId, builder);
   
    gl4.glValidateProgram(_programId);
    IntBuffer validStatus = IntBuffer.allocate(1);
    gl4.glGetProgramiv(_programId, GL4.GL_VALIDATE_STATUS, validStatus);
    validStatus.rewind();
    int status = validStatus.get();
    shaderStatus = status == GL4.GL_TRUE ? true : false;
   
    return shaderStatus;
  }

In the above initialization of the shader program, i have only vertex and fragment shader and i see that my shaders are compiled and linked with no errors.

I set the matrix uniform like this:

  public void setMatrixUniformd(final GL4 gl4, String uniform, Matrix4d mat) {
    StringBuilder builder = new StringBuilder();
    if(!checkShaderLinkStatus(gl4, _programId, builder)) {
      throw new IllegalStateException("Shader Program is not linked");
    }
    int location = gl4.glGetUniformLocation(_programId, uniform);
    if(location < 0) {
      Logger.getLogger(ShaderProgram.class.getName()).warning("Uniform: "+uniform+" is not active uniform or could not be found in the shader");
    }
    DoubleBuffer value = DoubleBuffer.allocate(16);
    value.put(GLMatrix4d.getArray(mat));
    value.rewind();
    gl4.glUniformMatrix4dv(location, 1, false, value);
  }

In the above code, i make sure i get the uniform location from my passthrough vertex shader and fragment shader and use that location to pass the matrix elements.

My draw method in the GLEventListener looks like this:

  @Override
  public void display(GLAutoDrawable glad) {
    final GL4 gl4 = glad.getGL().getGL4();
   
    gl4.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
   
    Matrix4d trans = GLMatrix4d.translate(-_translate[0], -_translate[1], _translate[2]);
    Matrix4d rotMat = _arcballHandler.getMatrix4d();
    Matrix4d transBack = GLMatrix4d.translate(_delta[0], -_delta[1], -_zoom);

    double ar = (double)glad.getSurfaceWidth() / (double)glad.getSurfaceHeight();
    Matrix4d projMat = GLMatrix4d.perspectiveMat(Math.toDegrees(Math.PI/4), ar, 0.1, 100.0);
   
    Matrix4d mv = new Matrix4d();
    mv.setIdentity();
    mv.mul(rotMat, trans);
    mv.mul(transBack, mv);
   
    Matrix4d mvp = new Matrix4d();
    mvp.mul(mv, projMat);
   
    Matrix4d mvpMat = new Matrix4d();
    mvpMat.mul(projMat, mv);
   
    for(int i = 0; i < _geomList.size(); i++) {
      ShaderProgram shader = _shaderProgList.get(i);
      Geometry4 geom4 = _geomList.get(i);
      shader.apply(gl4);
      shader.setMatrixUniformd(gl4, "mvp", mvpMat);
      geom4.draw(gl4);
      shader.unapply(gl4);
    }
  }

In the above block of code, i call shader.apply() which simply calls glUseProgram(programId), the programId is valid and i called setMatrixUniformd(..) which i have shown above. shader.unapply(..) simply calls glUseProgram(0).

I also create GLCanvas with support for opengl4 like this:

    GLCapabilities cap = new GLCapabilities(GLProfile.get(GLProfile.GL4));
    GLCanvas  canvas = new GLCanvas(cap);
    canvas.addGLEventListener(gv);

In the above code, gv(Geometry4View) is an implementation of GLEventListener for which i have shown code above.

My vertex shader:
#version 330

layout(location = 0) in vec4 vPosition;
layout(location = 1) in vec4 vColor;

uniform mat4 mvp;

out vec4 color;

void main() {
        color = vColor;
        gl_Position = mvp * vPosition;
}

Fragment shader:
#version 330

out vec4 fColor;
in vec4 vColor;

void main() {
        fColor = vColor;
}


I have searched through this forum and i have seen some folks have issues as well with this method of passing the matrix, but both the threads dont seem to have resolved or havent posted back a solution. One thread said that he was able to resolve it with uniform blocks, but i dont intend to use uniform block because this is a simple test case with just one matrix i want to pass.

It may be something wrong with how I've setup my opengl, but i simply cant figure it out. Can someone help me in this regard? I've looked over the code, but cant seem to figure where i've erred.

Please let me know if this would make it simpler if you need the source code and i can upload the source along with eclipse project.

thanks

-Siddharth
Reply | Threaded
Open this post in threaded view
|

Re: Help needed with opengl 4 and glUniform4dv

siddharth.cmdz
well i suppose i have a little bit of progress...it seems like i had to define my matrix in the shader as dmat4 instead of mat4 and that type is only available with glsl 4.0+.
But modifying my vertex shader to use 440 core and using dmat4, i get this error when compiling the shader:

error C7011: implicit cast from "f64vec4" to "vec4"

Im also wondering its a required to use glVertexAttribLpointer...

Any ideas folks?

Vertex Shader
#version 440 core

layout(location = 0) in vec4 vPosition;
layout(location = 1) in vec4 vColor;

uniform dmat4 mvp;

out vec4 color;

void main() {
        color = vColor;
        gl_Position = mvp * vPosition;
}

Fragment Shader

#version 440 core

out vec4 fColor;
in vec4 vColor;

void main() {
        fColor = vColor;
}

Am i going in the right direction?

Please note, I do realize that 64bit precision is rarely needed and should not be used. This is a test for me to verify some of artifacts we get due to zbuffer precision that i would like to verify.

Any help/suggestion is appreciated.

thanks

-Siddharth
Reply | Threaded
Open this post in threaded view
|

Re: Help needed with opengl 4 and glUniform4dv

siddharth.cmdz
Fixed...was doing many stupid things.