PDA

View Full Version : Java Port of www.arcsynthesis.org Hello, Triangle!



gmseed
11-16-2011, 08:11 AM
Hi

I was trying to build a Java port of the Hello, Triangle! tut1.cpp example at:

www.arcsynthesis.org (http://www.arcsynthesis.org)

It fails at the linking stage in createProgram() with "status" equal to 0.

Does anyone know why?

Thanks

Graham

===

package modern_gl_prog;

// java
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Canvas;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
// gl
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.common.nio.Buffers;

public class tut1 extends JFrame
{
private JPanel contentPane;
private Canvas canvas;

/**
* Launch the application.
*/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
tut1 frame = new tut1();
frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}

/**
* Create the frame.
*/
public tut1() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 545, 536);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);

canvas = new tut1Canvas();
canvas.setBounds(0, 0, 517, 390);
contentPane.add(canvas);

}
} // class tut1

class tut1Canvas extends GLCanvas
implements GLEventListener
{
protected int mTheProgram; // handle to program object
protected int mPositionBufferObject; // handle to buffer object
protected int mvao; // vertex array object

protected int mVertexCount = 3;
protected FloatBuffer mVertexPositions = null;

public tut1Canvas()
{
super();
this.addGLEventListener(this);
}

/*
private void checkLogInfo(GL gl, int programObject) {
IntBuffer intValue = BufferUtils.newIntBuffer(1);
gl.glGetObjectParameterivARB(programObject, GL.GL_OBJECT_INFO_LOG_LENGTH_ARB, intValue);

int lengthWithNull = intValue.get();

if (lengthWithNull <= 1) {
return;
}

ByteBuffer infoLog = BufferUtils.newByteBuffer(lengthWithNull);

intValue.flip();
gl.glGetInfoLogARB(programObject, lengthWithNull, intValue, infoLog);

int actualLength = intValue.get();

byte[] infoBytes = new byte[actualLength];
infoLog.get(infoBytes);
System.out.println("GLSL Validation >> " + new String(infoBytes));
}*/

private int createShader(GL2 gl, int eShaderType, String strShaderFile)
{
int shader = gl.glCreateShader(eShaderType);
String[] strings = new String[1]; strings[0] = strShaderFile;
gl.glShaderSource(shader, 1, strings,(int[])null,0); // public void glShaderSource(int shader, int count, java.lang.String[] string, int[] length, int length_offset);

gl.glCompileShader(shader);

int[] statusArray = new int[1];
int status;
gl.glGetShaderiv(shader, GL2.GL_COMPILE_STATUS, statusArray,0);
status = statusArray[0];
if (status == GL.GL_FALSE)
{
int[] infoLogLengthArray = new int[1];
int infoLogLength;
gl.glGetShaderiv(shader, GL2.GL_INFO_LOG_LENGTH,infoLogLengthArray,0);
infoLogLength = infoLogLengthArray[0];
IntBuffer intValue = IntBuffer.allocate(1);
ByteBuffer strInfoLog = Buffers.newDirectByteBuffer(infoLogLength + 1);
gl.glGetShaderInfoLog(shader, infoLogLength, intValue, strInfoLog);

String strShaderType = null;
switch(eShaderType)
{
case GL2.GL_VERTEX_SHADER: strShaderType = "vertex"; break;
case GL3.GL_GEOMETRY_SHADER: strShaderType = "geometry"; break;
case GL2.GL_FRAGMENT_SHADER: strShaderType = "fragment"; break;
}

System.out.println("Compile failure in " + strShaderType + " shader: " + strInfoLog);
}

return shader;
}

private int createProgram(GL2 gl, int[] shaderList)
{
int program = gl.glCreateProgram();

for(int iLoop = 0; iLoop < shaderList.length; iLoop++)
{
gl.glAttachShader(program, shaderList[iLoop]);
}

gl.glLinkProgram(program);

//gl.glValidateProgram(program);

int[] statusArray = new int[1];
int status;
gl.glGetProgramiv(program,GL2.GL_LINK_STATUS,statu sArray,0);
status = statusArray[0];
if (status == GL.GL_FALSE)
{
int[] infoLogLengthArray = new int[1];
int infoLogLength;
gl.glGetShaderiv(program, GL2.GL_INFO_LOG_LENGTH,infoLogLengthArray,0);
infoLogLength = infoLogLengthArray[0];

IntBuffer intValue = IntBuffer.allocate(1);
ByteBuffer strInfoLog = ByteBuffer.allocate(infoLogLength + 1);
gl.glGetProgramInfoLog(program, infoLogLength, intValue, strInfoLog);
System.out.println("Linker failure: " + strInfoLog);
}

for(int iLoop = 0; iLoop < shaderList.length; iLoop++)
{
gl.glDetachShader(program, shaderList[iLoop]);
}

return program;
}

public String strVertexShader()
{
String s = new String();
s += "#version 330\n";
s += "layout(location = 0) in vec4 position;\n";
s += "void main()\n";
s += "{\n";
s += " gl_Position = position;\n";
s += "}\n";
return s;
}

public String strFragmentShader()
{
String s = new String();
s += "#version 330\n";
s += "out vec4 outputColor;\n";
s += "void main()\n";
s += "{\n";
s += " outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n";
s += "}\n";
return s;
};

void initializeProgram(GL2 gl)
{
String vertexShaderString = strVertexShader();
String fragmentShaderString = strFragmentShader();
int vertexShader = createShader(gl,GL2.GL_VERTEX_SHADER,vertexShaderS tring);
int fragmentShader = createShader(gl,GL2.GL_VERTEX_SHADER,fragmentShade rString);
int[] shaderList = new int[2];
shaderList[0] = vertexShader;
shaderList[1] = fragmentShader;

mTheProgram = createProgram(gl,shaderList);
}

void initializeVertexBuffer(GL2 gl)
{
int[] array = new int[1];
gl.glGenBuffers(1, array, 0);
mPositionBufferObject = array[0];

// allocate vertex buffer [3 for (x,y,z,w) for each vertex]
mVertexPositions = FloatBuffer.allocate(4*mVertexCount);
mVertexPositions.put(0.75f); mVertexPositions.put(0.75f); mVertexPositions.put(0.75f); mVertexPositions.put(1.0f);
mVertexPositions.put(0.75f); mVertexPositions.put(-0.75f); mVertexPositions.put(0.0f); mVertexPositions.put(1.0f);
mVertexPositions.put(-0.75f); mVertexPositions.put(-0.75f); mVertexPositions.put(0.0f); mVertexPositions.put(1.0f);

gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,mPositionBuffe rObject);
gl.glBufferData(GL2.GL_ARRAY_BUFFER,3*mVertexCount ,mVertexPositions, GL2.GL_STATIC_DRAW);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
}

@Override
public void init(GLAutoDrawable gLDrawable)
{
GL2 gl = gLDrawable.getGL().getGL2();

initializeProgram(gl);
initializeVertexBuffer(gl);

// generate vertex array and bind
int[] array = new int[1];
gl.glGenVertexArrays(1,array,0);
mvao = array[0];
gl.glBindVertexArray(mvao);
}

@Override
public void display(GLAutoDrawable gLDrawable)
{
final GL2 gl = gLDrawable.getGL().getGL2();
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

gl.glUseProgram(mTheProgram);

gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,mPositionBuffe rObject);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0, 4, GL.GL_FLOAT,false, 0, 0);

gl.glDrawArrays(GL.GL_TRIANGLES, 0, 3);

gl.glDisableVertexAttribArray(0);
gl.glUseProgram(0);

gLDrawable.swapBuffers();
}

@Override
public void reshape(GLAutoDrawable gLDrawable, int x, int y, int width, int height)
{
GL2 gl = gLDrawable.getGL().getGL2();
if (height <= 0)
{
height = 1;
}
gl.glViewport(0,0,width,height);
}

@Override
public void dispose(GLAutoDrawable arg0)
{
// do nothing
}
} // class tut1Canvas

Dan Bartlett
11-16-2011, 08:36 AM
int fragmentShader = createShader(gl,GL2.GL_VERTEX_SHADER,fragmentShade rString);
should probably be:

int fragmentShader = createShader(gl,GL2.GL_FRAGMENT_SHADER,fragmentSha derString);

gmseed
11-16-2011, 09:05 AM
Hi

Thanks for your prompt reply.

I corrected the copy&amp;paste error and it now passes the linker stage fine.

I noticed that the size in bytes passed to glBufferData() in initializeVertexBuffer() was incorrect and should have read:
gl.glBufferData(GL2.GL_ARRAY_BUFFER,4*mVertexCount *Buffers.SIZEOF_FLOAT,mVertexPositions,GL2.GL_STAT IC_DRAW);

However, I still don't see a white triangle!

Cheers

Graham

gmseed
11-16-2011, 02:56 PM
Hi

When I run this tutorial on my PC I don't get any compile/lnk errors but when I run it on my laptop all fail:

Compile failure in vertex shader: java.nio.DirectByteBuffer[pos=0 lim=241 cap=241]
Compile failure in fragment shader: java.nio.DirectByteBuffer[pos=0 lim=183 cap=183]
Linker failure: java.nio.HeapByteBuffer[pos=0 lim=1 cap=1]

My PC has an Nvidia Quadro card and my laptop has an ATI Radeon.

Thanks

Graham

carsten neumann
11-16-2011, 04:51 PM
java.nio.HeapByteBuffer[pos=0 lim=1 cap=1]


that is not a glGetProgramInfoLog() message, should your log printing perhaps look something like this (I don't know the OpenGL java bindings, but you get the idea):



System.out.println("Linker failure: " + strInfoLog.asCharBuffer().toString());


? That should show the contents of the ByteBuffer strInfoLog, not information about its type and size.
With that info it should then be possible to figure out why compiling/linking fails.

gmseed
11-17-2011, 03:11 PM
Hi

Thanks - I added strInfoLog.asCharBuffer().toString());

but the output is a series of unknown characters. Stepping through with the debugger reveals the characters to be non-ascii.

Typical output:

Compile failure in vertex shader: ????????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????

Compile failure in fragment shader: ????????????????????????????????????????????????? ???????????????????????????????????????

Linker failure:

carsten neumann
11-17-2011, 03:52 PM
Hmm, ok, you'll have to find out how to get readable output from the ByteBuffer then, I'm not familiar enough with the java libraries to help, sorry.
Sounds almost like this would be a FAQ for the java bindings, but my quick search did not turn up anything.

gmseed
11-18-2011, 07:07 AM
Hi

Thanks - the ByteBuffer requires decoding, in the present case using the system encoding:

String encoding = System.getProperty("file.encoding");
CharBuffer charBuff = Charset.forName(encoding).decode(strInfoLog);
String buffString = charBuff.toString();
String msg = "Compile failure in " + strShaderType + " shader: " + buffString;

Thanks again for your help.

Graham

gmseed
11-18-2011, 11:12 AM
Hi

The compile output is as follows:

Compile failure in vertex shader: Vertex shader failed to compile with the following errors:
ERROR: 0:1: error(#106) Version number not supported by GL2
ERROR: 0:2: error(#279) Invalid layout qualifier 'location'
ERROR: error(#273) 2 compilation errors. No code generated

and is thus failing due to an unsupported version number, which is set to 330.

I added a constructor to explicitly specify a GLCaps:

// OPenGL 2.1 profile
GLProfile prof = GLProfile.get(GLProfile.GL2);
GLCapabilities caps = new GLCapabilities(prof);
canvas = new tut1Canvas(caps);

But I still get the error.

I am using jogl-2.0-b41-20110916-windows-amd64 downloaded from jogamp.org.

Thanks

Graham

Alfonse Reinheart
11-18-2011, 11:48 AM
My tutorials are for GL 3.3 and above. If your hardware/drivers do not support GL 3.3, then there's not much that can be done. Well, you could try to translate the code, but that would be difficult.