LWJGLShaderObjectsState oddity

Hi,



last week I did some extensive shader testing, and had serious problems setting more than one vertex atribute pointer.



In LWJGLShaderObjectsState.java, line 111, is the comment "//index 0-13 is occupied by standard glsl attributes(gl_Vertex, gl_Normal etc)". While that might be true, there should be a check against GL_MAX_VERTEX_ATTRIBS (see http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocation.xml). Is it true, and always and everywhere true, anyways?



When I set a single vertex attribute pointer (to a tangents array), everything works fine. It breaks as soon as I set another pointer, again via setAttributePointer().



From my understanding (which is in this case rather small), vertex attribute indices used by standard glsl attributes should not be used for custom attributes. But when I randomly hardcoded e.g. 4 and 6 as indices for the two pointers, everything worked fine. The indices 14 and 15 didn't, but they are what I get with the unmodified version of LWJGLShaderObjectsState.



Any idea what could be wrong/odd here?

I stumbled across a comment in the sourcecode, and one in these forums, that the shader code will be revised soon or later. Is that correct?



I'm having serious trouble with LWJGLShaderObjectState as it is. If I construct two shader states with one attribute pointer for each state, my VM crashes… I played around in the sourcecode and managed to get it working by making the index in LWJGLShaderObjectState's relinkProgram() static, and thus sharing and increasing the index for all states. But thats of course just a work around…



Any comment is highly appreciated!  :slight_smile:

On a side note: the ShaderObjectsStateRecord.java class looks suspicious, too…  }:-@

Shameless bump 

Yesterday, LWJGL 1.1.1 was released. See http://lwjgl.org/forum/index.php/topic,2392.0.html



In the release notes (http://sourceforge.net/project/shownotes.php?release_id=530119&group_id=58488), my friends the attribute pointers are mentioned:


2007-05-22 22:30  elias_naur

   * src/java/org/lwjgl/opengl/BaseReferences.java,
     src/java/org/lwjgl/opengl/ReferencesStack.java,
     src/java/org/lwjgl/util/generator/CachedReference.java,
     src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java,
     src/java/org/lwjgl/util/generator/ReferencesGeneratorProcessorFactory.java,
     src/templates/org/lwjgl/opengl/ARB_vertex_program.java,
     src/templates/org/lwjgl/opengl/ARB_vertex_shader.java,
     src/templates/org/lwjgl/opengl/GL11.java,
     src/templates/org/lwjgl/opengl/GL13.java,
     src/templates/org/lwjgl/opengl/GL20.java,
     src/templates/org/lwjgl/opengl/NV_vertex_program.java:
     Implemented proper buffer reference retaining for complicated
     functions like glVertexAttribPointer and glTexCoordPointer. Patch
     by MatthiasM.



I switched to LWJGL 1.1.1 immediately, but the above errors still occur. Perhaps LWJGLShaderObjectState.java has to altered in some way to make use of the LWJGL changes?

Am I the only one using attribute pointers? Or is no one else having problems with them (with more than one shaded geometry)?

I'll bump mrcoder and see if he has suggestions…

The main reason this has not popped up before is that noone ever used it.  :smiley:

Before I rewrote the shaderstate implementation, attributes just didnt work at all(as well as other bugs, huge memory leaks and bad architecture/performance).

I didn't find much info on the attribute indexes, but found out through testing that setting indexes like 1 to something else would overwrite the automatic gl_Vertex etc, so I just indexed past them…Might be some other way to handle that completely. Would love to get help and info to fix that up…I'll do some testing with several attribute pointers myself and see what I come up with.



Thanks for the bumping  :wink:

MrCoder said:

The main reason this has not popped up before is that noone ever used it.  :D
Before I rewrote the shaderstate implementation, attributes just didnt work at all(as well as other bugs, huge memory leaks and bad architecture/performance).
I didn't find much info on the attribute indexes, but found out through testing that setting indexes like 1 to something else would overwrite the automatic gl_Vertex etc, so I just indexed past them...Might be some other way to handle that completely. Would love to get help and info to fix that up...I'll do some testing with several attribute pointers myself and see what I come up with.

Thanks for the bumping  ;)


Light at the end of the tunnel  :D Thanks for looking into this, it's driving me nuts! And I absolutely _have_ to use shaders with attribute pointers, so I'm quite stalled currently. If I can help you with anything, please raise your voice!

a few questions…


  1. what is the format of the attributes you are setting? float, vec3, mat4 etc etc
  2. does the TestGLGLShaderAttributes test work for you?
MrCoder said:

a few questions...

1) what is the format of the attributes you are setting? float, vec3, mat4 etc etc
2) does the TestGLGLShaderAttributes test work for you?


1. The format is float with a size of 3 (for the x,y,z of the tangents)
2. Yes it runs (didn't know of this test yet)

I think I got it! MrCoder, please have a look at this. I modified your Test slightly to more than one geometry. Code follows:


public class TestGLSLShaderAttributes extends SimpleGame {

  class ColorQuad extends Quad {

    private ColorRGBA color;
    /** Shader attribute buffer for vertex colors */
    private FloatBuffer vertexColors;
    /** Shader attribute buffer for amount of offset to normal */
    private FloatBuffer vertexOffset;

    public ColorQuad(ColorRGBA color) {
      super("glslQuad", 1f, 1f);

      this.color = color;

      GLSLShaderObjectsState so = display.getRenderer()
          .createGLSLShaderObjectsState();

      // Check is GLSL is supported on current hardware.
      if (!so.isSupported()) {
        quit();
      }

      so.load(TestGLSLShaderAttributes.class.getClassLoader().getResource(
          "jmetest/data/images/attributeshader.vert"),
          TestGLSLShaderAttributes.class.getClassLoader().getResource(
              "jmetest/data/images/attributeshader.frag"));

      vertexColors = BufferUtils.createFloatBuffer(16);
      for (int i = 0; i < 4; i++) {
        vertexColors.put(color.r);
        vertexColors.put(color.g);
        vertexColors.put(color.b);
        vertexColors.put(color.a);
      }
      so.setAttributePointer("vertexColors", 4, true, 0, vertexColors);

      vertexOffset = BufferUtils.createFloatBuffer(4);
      so.setAttributePointer("vertexOffset", 1, true, 0, vertexOffset);

      so.setEnabled(true);

      setRenderState(so);
    }

    public void update() {
      vertexOffset.rewind();
      vertexOffset
          .put(FastMath.sin(timer.getTimeInSeconds() * 5.0f) * 0.5f + 0.5f)
          .put(
              FastMath.sin(timer.getTimeInSeconds() * 5.0f + 1.0f) * 0.5f + 0.5f)
          .put(
              FastMath.sin(timer.getTimeInSeconds() * 5.0f + 2.0f) * 0.5f + 0.5f)
          .put(
              FastMath.sin(timer.getTimeInSeconds() * 5.0f + 3.0f) * 0.5f + 0.5f);
    }

  }

  public static void main(String[] args) {
    TestGLSLShaderAttributes app = new TestGLSLShaderAttributes();
    app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
    app.start();
  }

  private ColorQuad quad0, quad1, quad2, quad3;

  protected void simpleInitGame() {
    display.setTitle("Test GLSL attributes");

    cam.setLocation(new Vector3f(0, 0, 2));
    cam.update();
    input = new NodeHandler(rootNode, 10, 2);

    quad0 = new ColorQuad(ColorRGBA.red);
    rootNode.attachChild(quad0);
    quad0.getLocalTranslation().x -= 0.5f;
    quad0.getLocalTranslation().y -= 0.5f;

    quad1 = new ColorQuad(ColorRGBA.green);
    rootNode.attachChild(quad1);
    quad1.getLocalTranslation().x += 0.5f;
    quad1.getLocalTranslation().y -= 0.5f;

    quad2 = new ColorQuad(ColorRGBA.blue);
    rootNode.attachChild(quad2);
    quad2.getLocalTranslation().x -= 0.5f;
    quad2.getLocalTranslation().y += 0.5f;

    quad3 = new ColorQuad(ColorRGBA.orange);
    rootNode.attachChild(quad3);
    quad3.getLocalTranslation().x += 0.5f;
    quad3.getLocalTranslation().y += 0.5f;

    rootNode.updateRenderState();
  }

  protected void simpleUpdate() {
    quad0.update();
    quad1.update();
    quad2.update();
    quad3.update();
  }

}



Basically we now have four different quads, and each one should have a different color. BUT THEY DON'T! Every quad is orange. It seems that the same attribute pointer buffer is used for all quads! Could there be a problem with a reference that is always overridden by the last setAttributePointer() call?

This would explain every oddity I have with my program. If that is the reason, my VM crashes surely derive from the fact that my tangent buffers are not the same size (opposed to the color buffers in this test).

very strange. the data seems to be correctly sent to ARBVertexProgram.glEnableVertexAttribArrayARB, and the programID's are different for the shaders, and bound before setting the attributes…wonder what i'm missing

Do you also get 4 orange quads? I have tested my program on different machines, but not this quad test.



It really seems as if the other shaders get the identical buffer reference, so that the last attribute pointer wins.

Bregosch said:

Do you also get 4 orange quads? I have tested my program on different machines, but not this quad test.


Four orange quads here, too.

Sor

With help from Bregosch I think we squashed some major issues with attributes…So, check out the latest from cvs and see if it works…

…it does work. Seeing all four colors now.



Sor

MrCoder said:

With help from Bregosch I think we squashed some major issues with attributes...So, check out the latest from cvs and see if it works...


That was a really cool bug hunt, thanks again for your help! Much appreciated!  8)