GLSL Shader Objects State

Since the code review thread for these is already locked, I’ll post it here.



My GF4TI4200 does support vertex, but not fragment shaders. The new state object needs both. It checks if vertex OR fragment shader is null and then tries to load both, so I cannot set the frag parameter to null (will cause a NullPointerException).



Any way to get around this (other than buying a different graphics board)?

Well, when coding this state, I was thinking about adding a “vertex or fragment shader only” option, but since it’s never used (very very limited), I thought it was better to leave it…

Would you like me to add these options ?



(I would be curious to see your single vertex shader :), because a single vertex shader can’t do things that the original opengl pipeline do… Might be better to use pure OpenGL for lower-end cards… Or maybe you’re just playing with GLSL ?)



Chman

Hmm, the old cell demo used only vertex shader… Isn’t that enough to manipulate the uv coordinates of vertices eg?

Ok, so what method name would you like ?

Something like :


loadVertexOnly(String path);
loadFragmentOnly(String path);


or something more like :

load(String path, int type);
// Where type equals to SO_VERTEX_SHADER or SO_FRAGMENT_SHADER)



Or something else ? Just tell me :)

Chman

Currently it has a load method with vert and frag, IIRC (I’m not at home currently, so I cannot look it up).



Easiest would be to set the one to null which you do not want to provide, I think.

Ok, I’ll make the load() method able to handle a null parameter. I’m not at home at the moment (new year’s day…), but I will implement it asap !



Chman

Ok here it is. Just change the load(url,url) method from LWJGLShaderObjectsState with this one :



    /**
     * Loads the shader object.
     *
     * @see com.jme.scene.state.ShaderObjectsState#load(java.net.URL,
     *      java.net.URL)
     */
    public void load(URL vert, URL frag) {
        ByteBuffer vertexByteBuffer = null;
        ByteBuffer fragmentByteBuffer = null;
        int vertexShaderID = -1;
        int fragmentShaderID = -1;
        IntBuffer compiled = BufferUtils.createIntBuffer(1);
       
        if (vert != null) {
            // Load the shader code
            vertexByteBuffer = load(vert);
           
            // Create the shader objects
            vertexShaderID = ARBShaderObjects
                    .glCreateShaderObjectARB(ARBVertexShader.GL_VERTEX_SHADER_ARB);
           
            // Create the sources
            ARBShaderObjects.glShaderSourceARB(vertexShaderID,
                    vertexByteBuffer);
           
            // Compile the vertex shader
            ARBShaderObjects.glCompileShaderARB(vertexShaderID);
            ARBShaderObjects.glGetObjectParameterARB(vertexShaderID,
                    ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB, compiled);
            checkProgramError(compiled, vertexShaderID);
        }
        if (frag != null) {
            // Load the shader code
            fragmentByteBuffer = load(frag);
           
            // Create the shader objects
            fragmentShaderID = ARBShaderObjects
                    .glCreateShaderObjectARB(ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);
           
            // Create the sources
            ARBShaderObjects.glShaderSourceARB(fragmentShaderID,
                    fragmentByteBuffer);
           
            // Compile the fragment shader
            compiled.clear();
            ARBShaderObjects.glCompileShaderARB(fragmentShaderID);
            ARBShaderObjects.glGetObjectParameterARB(fragmentShaderID,
                    ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB, compiled);
            checkProgramError(compiled, fragmentShaderID);
        }
       
        // Create the program
        if (vert != null || frag != null) {
            programID = ARBShaderObjects.glCreateProgramObjectARB();
            if (vert != null) ARBShaderObjects.glAttachObjectARB(programID, vertexShaderID);
            if (frag != null) ARBShaderObjects.glAttachObjectARB(programID, fragmentShaderID);
            ARBShaderObjects.glLinkProgramARB(programID);
        }
    }



I don't post it into the code review part because it's untested, but this should work. Tell me if it doesn't (Haven't time to test it tonight).

Chman