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.