JOGL shader simple code, not working

Hi,

I want to make a simpliest shader + VBO (no glBegin etc) code running with JOGL. I tried to port this C tutorial (https://sites.google.com/site/justinscsstuff/jogl-tutorial-3) , in simplified form (no textures), and it does not work… The desired output is a white window: there are two triangles covering the viewport, and a shader that makes them white. The actual output is a black window (nothing rendered). I debugged the code and it seems to be OK, but apparently is not. Any idea?

Here I paste the java code (quite lengthy, sorry), and below that the shader code. At the bottom I paste the output from my debug functions, maybe will help. Thanks in advance

Java:


// https://sites.google.com/site/justinscsstuff/jogl-tutorial-3

import java.awt.Frame;
import java.awt.event.*;
import java.io.*;
import java.nio.*;
import java.util.*;
 
import javax.media.opengl.*;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.GLProfile;

import com.jogamp.opengl.util.*;

public class SimpleScene implements GLEventListener {
	
	static { GLProfile.initSingleton( true ); }
	
    public static void main(String[] args) {
    	
        GLProfile glp = GLProfile.getDefault();
        GLCapabilities caps = new GLCapabilities(glp);
        GLCanvas canvas = new GLCanvas(caps);
        
        canvas.addGLEventListener( new SimpleScene() );
        
        FPSAnimator animator = new FPSAnimator( canvas, 75 );
        animator.add( canvas );
        animator.start();
        
        Frame frame = new Frame("AWT Window Test");
        frame.setSize(300, 300);
        frame.add(canvas);
        frame.setVisible(true);
        
        // by default, an AWT Frame doesn't do anything when you click
        // the close button; this bit of code will terminate the program when
        // the window is asked to close
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            } } );
    }
    
	@Override
	public void init(GLAutoDrawable drawable)
	{
		GL2 gl = drawable.getGL().getGL2();
		int vertex_shader = 0, fragment_shader = 0;
		
		FloatBuffer vertex_buffer = FloatBuffer.allocate( 8 );
		vertex_buffer.put( new float[]{
				    -1.0f, -1.0f,
				     1.0f, -1.0f,
				    -1.0f,  1.0f,
				     1.0f,  1.0f
		} );
		
		ShortBuffer element_buffer = ShortBuffer.allocate( 4 );
		element_buffer.put( new short[] { 0, 1, 2, 3 } );
		
		int vertex_buffer_size = vertex_buffer.capacity() * sizeof_float;
		int element_buffer_size = element_buffer.capacity() * sizeof_short;
		
		diagnoseArrayBufferBinding(gl);
		diagnoseElementArrayBufferBinding(gl);
		
		try {
			m_vertex_buffer = make_buffer( gl, GL2.GL_ARRAY_BUFFER, vertex_buffer_size, vertex_buffer );
			m_element_buffer = make_buffer( gl, GL2.GL_ELEMENT_ARRAY_BUFFER, element_buffer_size, element_buffer );
		} catch (BufferException e1) {
			System.out.print("BUFFER!");
			System.exit(1);
		}
		
		diagnoseArrayBufferBinding(gl);
		diagnoseElementArrayBufferBinding(gl);
		
		checkGLError(gl, "make buffers");
		
		try {
			vertex_shader = make_shader(gl, GL2.GL_VERTEX_SHADER, m_fname_vertex_shader );
			fragment_shader = make_shader(gl, GL2.GL_FRAGMENT_SHADER, m_fname_fragment_shader );
		} 
		catch (Exception e ) {
			System.out.print("SHADER!");
			System.exit(1);
		}
		
		checkGLError(gl, "make shaders");
	
		m_program = make_program(gl, vertex_shader, fragment_shader);
		if ( m_program == 0 ) throw new Error("PROGRAM");
		
		checkGLError(gl, "make program");
		
		m_attribute_position = gl.glGetAttribLocation( m_program, "position");
		
		checkGLError(gl, "make locations");
	}

	private void render( GLAutoDrawable drawable )
	{
		
		GL2 gl = drawable.getGL().getGL2();
		gl.glClear(GL.GL_COLOR_BUFFER_BIT);
		
		gl.glUseProgram(m_program);
		
	    gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, m_vertex_buffer );

	    gl.glVertexAttribPointer(
	    		m_attribute_position,
	    		2,
	    		GL2.GL_FLOAT,
	    		false,
	    		sizeof_float * 2,
	    		0
	    		);
	    gl.glEnableVertexAttribArray( m_attribute_position );
	    
	    gl.glBindBuffer( GL2.GL_ELEMENT_ARRAY_BUFFER, m_element_buffer );
	    gl.glDrawElements(
	    		GL2.GL_TRIANGLE_STRIP,
	    		4,
	    		GL2.GL_UNSIGNED_SHORT,
	    		0);
		gl.glDisableVertexAttribArray( m_attribute_position );
		
		gl.glFlush();
		
//		drawable.swapBuffers();
		
		checkGLError(gl);
	}
	
	void diagnoseArrayBufferBinding( GL2 gl ) {
		diagnoseCustom( gl, GL2.GL_ARRAY_BUFFER_BINDING, 
				"GL_ARRAY_BUFFER_BINDING");
	}
	
	void diagnoseElementArrayBufferBinding( GL2 gl ) {
		diagnoseCustom(gl, GL2.GL_ELEMENT_ARRAY_BUFFER_BINDING,
				"GL_ELEMENT_ARRAY_BUFFER_BINDING");
	}

	void diagnoseCustom( GL2 gl, int target, String msg ) {
		int[] t = new int [1];
		gl.glGetIntegerv( target, t, 0 );
		System.out.printf("%s %d\n", msg, t[0]);
	}

	private int make_buffer(GL2 gl, int gl_target, int data_size_bytes, Buffer data_buffer) throws BufferException
	{
		int[] t_buffer = new int[1];
		gl.glGenBuffers(1, t_buffer, 0);
		
		int buffer = t_buffer[0];		
		gl.glBindBuffer(gl_target, buffer);
		gl.glBufferData(gl_target, data_size_bytes, data_buffer, GL2.GL_STATIC_DRAW );
		diagnoseBuffer( gl, gl_target);
		
		if ( buffer == 0) throw new BufferException();
		return buffer;
	}
	
	private void diagnoseBuffer( GL2 gl, int target ) {
		int[] t_int = new int[1];
		
		gl.glGetBufferParameteriv( target, GL2.GL_BUFFER_ACCESS, t_int, 0);
		System.out.printf("buffer %d: GL_BUFFER_ACCESS %d\n", target, t_int[0] );
		gl.glGetBufferParameteriv( target, GL2.GL_BUFFER_MAPPED, t_int, 0);
		System.out.printf("buffer %d: GL_BUFFER_MAPPED %d\n", target, t_int[0] );
		gl.glGetBufferParameteriv( target, GL2.GL_BUFFER_SIZE, t_int, 0);
		System.out.printf("buffer %d: GL_BUFFER_SIZE %d\n", target, t_int[0] );
		gl.glGetBufferParameteriv( target, GL2.GL_BUFFER_USAGE, t_int, 0);
		System.out.printf("buffer %d: GL_BUFFER_USAGE %d\n", target, t_int[0] );
	}
	
	private int make_shader(GL2 gl, int type, String filename) throws FileNotFoundException, ShaderException
	{
		String code = getFileContent(filename);
		
		int shader = gl.glCreateShader( type );
		gl.glShaderSource(shader, 1, new String[] { code }, (int[]) null, 0);
		gl.glCompileShader(shader);
		
		IntBuffer shader_ok = IntBuffer.allocate(1);
		gl.glGetShaderiv(shader, GL2.GL_COMPILE_STATUS, shader_ok);
		if ( shader_ok.get(0) == 0 ) {
			throw new ShaderException();
		}
		
		if (shader == 0) throw new ShaderException();
		
		return shader;
	}
	
	private static String getFileContent( String filename ) throws FileNotFoundException
	{
		InputStream ins = new FileInputStream( filename );
        StringBuffer buffer = new StringBuffer();
        Scanner scanner = new Scanner(ins);
        try {
            while (scanner.hasNextLine()) {
                buffer.append(scanner.nextLine() + "\n");
            }
        } finally {
            scanner.close();
        }

        return buffer.toString();
	}
	
	private int make_program( GL2 gl, int vertex_shader, int fragment_shader )
	{
		int program = gl.glCreateProgram();
		gl.glAttachShader( program, vertex_shader );
		gl.glAttachShader( program, fragment_shader );
		gl.glLinkProgram( program );
		gl.glValidateProgram( program );
		
		String log = getProgramLog( gl, program );
		System.out.printf("program log:\n%s\n", log );
		return program;
	}
	
	private String getProgramLog( GL2 gl, int program ) {
		int buffer_size = 10000;
		IntBuffer buf_i = IntBuffer.allocate(1);
		ByteBuffer buf_b = ByteBuffer.allocate(buffer_size);
		gl.glGetProgramInfoLog(program, buffer_size, buf_i, buf_b);
		return new String( buf_b.array() );		
	}
	
	void checkGLError( GL2 gl ) 
	{
		checkGLError(gl, "", false);
	}
	
	void checkGLError( GL2 gl, String msg ) 
	{
		checkGLError(gl, msg, true);
	}
	
	void checkGLError( GL2 gl, String msg, boolean verbose  )
	{
		final GLU glu = new GLU();
	
		int e = gl.glGetError();
		
		if ( e != GL2.GL_NO_ERROR ) {
			System.out.printf("error %s: %s\n", msg, glu.gluErrorString( e ));
		}
		else if ( verbose ) {
			System.out.printf("error %s: %s\n", msg, glu.gluErrorString( e ));
		}
	}

	@Override
	public void display(GLAutoDrawable drawable) {
		render( drawable );
	}
	
	@Override
	public void dispose(GLAutoDrawable arg0) {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3,
			int arg4) {
		// TODO Auto-generated method stub
	}
	
	private int m_program;
	
	private int m_attribute_position;
	private int m_vertex_buffer;
	private int m_element_buffer;
	
	private static String m_fname_vertex_shader = "vertex_shader.glsl";
	private static String m_fname_fragment_shader = "fragment_shader.glsl";
	
	private static int sizeof_float = 4;
	private static int sizeof_short = 2;
	
}

class ShaderException extends Exception {
	private static final long serialVersionUID = -745084418598495557L;
}

class BufferException extends Exception {
	private static final long serialVersionUID = 8513749851376590348L;
}



And shaders:

fragment_shader.glsl


#version 110

varying vec2 texcoord;

void main()
{
    gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );
}

vertex_shader.glsl


#version 110

attribute vec2 position;

varying vec2 texcoord;

void main()
{
    gl_Position = vec4(position, 0.0, 1.0);
    texcoord = position * vec2(0.5) + vec2(0.5);
}

Debug output:


GL_ARRAY_BUFFER_BINDING 0
GL_ELEMENT_ARRAY_BUFFER_BINDING 0
buffer 34962: GL_BUFFER_ACCESS 35002
buffer 34962: GL_BUFFER_MAPPED 0
buffer 34962: GL_BUFFER_SIZE 32
buffer 34962: GL_BUFFER_USAGE 35044
buffer 34963: GL_BUFFER_ACCESS 35002
buffer 34963: GL_BUFFER_MAPPED 0
buffer 34963: GL_BUFFER_SIZE 8
buffer 34963: GL_BUFFER_USAGE 35044
GL_ARRAY_BUFFER_BINDING 1
GL_ELEMENT_ARRAY_BUFFER_BINDING 2
error make buffers: no error
error make shaders: no error
program log:
Validation successful.

Hi

I don’t see what is wrong. You should directly contact Justin and/or post your question on the official forum of JogAmp.