Problems with Cylabs's GLSL Demo - running/Compile...

Hi there,
I’ve tried the sample code to test & experiment glsl functionality.
Unfortunately, the code doesn’t run or compile…What do i miss?


SCHWERWIEGEND: null
java.io.IOException: URL was null
at com.sun.opengl.util.texture.TextureIO.newTextureDataImpl(TextureIO.java:818)
	at com.sun.opengl.util.texture.TextureIO.newTextureData(TextureIO.java:236)
	at com.sun.opengl.util.texture.TextureIO.newTexture(TextureIO.java:521)
	at glsl1.glsl1.init(glsl1.java:73)

I assume, he cannot find the picture file i want to use for the texture.
But its deffo there. Does anyone else have this problem? any hints od tips?
I’m using Eclipse with OpenGL Plugin as well netbeans 6.5 with opengl pack, just to check, unfortunately both doesn’t work.

Thanks,
el Normeo

Please post your code esp. around the line mentioned in the stacktrace (glsl1.glsl1.init(glsl1.java:73)) and describe where the picture is, you are loading.

I suspect the reference to your pic is not correct or the pic is not on the classpath or something.

yeah sure…
try
{
// Load some texture
Texture texture = TextureIO.newTexture(glsl1.class.getResource(“moon.png”), false, “png”);

		// Store the OpenGL texture object ID for later use
		textureID = texture.getTextureObject();
	}

that moon.png can be read by anyone and is locateted in my root of my project folder with its subfolders: src, lib, librc and bin…
I also put the pic in the different sub folders too, just to check…then i got the error: URL was null.
Quite funny and irritating;-)
I’ll get an white rectangle on black ground. Absolutly correct when there is no texture to load, but the file exists;-)
Here your code:

package glsl1;

import com.sun.opengl.util.Animator;
import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureIO;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
import static javax.media.opengl.GL.*;

/**
 * SimpleShaderTemplate.java
 * @author Mathias 'cylab' Henze
 */
public class glsl1 implements GLEventListener
{
	private GLU glu = new GLU();

	// Hold the shader program for later use
	private int program;
	// Holds the texture object for later use
	private int textureID;

	public static void main(String[] args)
	{
		Frame frame = new Frame("Simple JOGL GLSL Application");
		GLCanvas canvas = new GLCanvas();

		canvas.addGLEventListener(new glsl1());
		frame.add(canvas);
		frame.setSize(640, 480);
		final Animator animator = new Animator(canvas);
		frame.addWindowListener(new WindowAdapter()
		{
			@Override
			public void windowClosing(WindowEvent e)
			{
				// Run this on another thread than the AWT event queue
				// so that Animator.stop() completes before exiting
				new Thread(new Runnable()
				{
					public void run()
					{
						animator.stop();
						System.exit(0);
					}
				}).start();
			}
		});
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
		animator.start();
	}

	public void init(GLAutoDrawable drawable)
	{
		// drawable.setGL(new DebugGL(drawable.getGL()));
		GL gl = drawable.getGL();

		// You won't get far without error checking ;)
		String errors = null;

		try
		{
			// Load some texture
			Texture texture = TextureIO.newTexture(glsl1.class.getResource("moon.png"), false, "png");

			// Store the OpenGL texture object ID for later use
			textureID = texture.getTextureObject();
		}
		catch (Exception ex)
		{
			Logger.getLogger(glsl1.class.getName()).log(Level.SEVERE, null, ex);
		}

		// This is the shader source. For simplicity just use a single concatenated string
		String[] shader =
		{
			// This variable specifies the texture unit to use, called "sampler" in GLSL
			"uniform sampler2D texUnit;\n" +
			// main() is called for every pixel on screen (called "fragment" in GLSL) while rasterizing
			"void main(void)\n" +
			"{\n" +
			    // The gl_TexCoord array is a build in GLSL variable that holds the glTexCoordXX() values
			"   vec2 texCoord = gl_TexCoord[0].xy;\n" +
			    // texture2D() gets a texel from the texture unit at the given location
			"   vec4 texel = texture2D(texUnit, texCoord);\n" +
			    // Now assign the texel to be the current pixels output color.
			    // Mask out green, to see that the shader is indeed used (vec4 is r,g,b,a)
			"   gl_FragColor = texel * vec4(1.0, 0.0, 1.0, 1.0);\n" +
			"}\n"
		};

		// Since java Strings aren't 0-terminated, store the length for submission to glShaderSource
		// (maybe this unnecessary and JOGL implicitly 0-terminates the Strings, but you never know)
		int[] lengths = { shader[0].length() };

		// Create and store a shader program
		program = gl.glCreateProgramObjectARB();

		// Create the fragment shader object
		int frag = gl.glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

		// Tell the shader program to use the fragment shader
		gl.glAttachObjectARB(program, frag);

		// Copy the shader source to GL implementation.
		// You need the amount of Strings, the String[] and an array of the Strings lenghts
		gl.glShaderSourceARB(frag, shader.length, shader, lengths, 0);

		// Compile the shader
		gl.glCompileShaderARB(frag);

		// Check for compile errors
		if ((errors = getGLErrorLog(gl, frag)) != null)
			throw new RuntimeException("Compile error\n" + errors);

		// Link the program
		gl.glLinkProgramARB(program);

		// Check for link errors
		if ((errors = getGLErrorLog(gl, program)) != null)
			throw new RuntimeException("Link error\n" + errors);

		// Use the program, to be able to assign values to the uniforms
		gl.glUseProgramObjectARB(program);

		// Get the location of the texUnit uniform, so we can assign a value to it
		int texUnit = gl.glGetUniformLocationARB(program, "texUnit");

		// Assign the GL_TEXTURE0 unit to the uniform variable
		// CAUTION: you need to set the plain texture _unit_ _number_,
		// not the GL constant nor the textur object here!!!
		gl.glUniform1iARB(texUnit, 0);

		// Enable VSync
		gl.setSwapInterval(1);

		// Setup the clear color
		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	}

	public void display(GLAutoDrawable drawable)
	{
		GL gl = drawable.getGL();

		// Clear the drawing area
		gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		// Reset the current matrix to the "identity"
		gl.glLoadIdentity();

		// Move the "drawing cursor" around
		gl.glTranslatef(0.0f, 0.0f, -3.0f);

		// Choose the current texture unit
		gl.glActiveTexture(GL_TEXTURE0);

		// Bind a texture to the current texture unit
		gl.glBindTexture(GL_TEXTURE_2D, textureID);

		// Enable the shader program
		gl.glUseProgramObjectARB(program);

		// Draw a quad to be textured
		gl.glBegin(GL_QUADS);
		{
			gl.glTexCoord2f(0, 0);
			gl.glVertex3f(-1, -1, 0);
			gl.glTexCoord2f(1, 0);
			gl.glVertex3f(1, -1, 0);
			gl.glTexCoord2f(1, 1);
			gl.glVertex3f(1, 1, 0);
			gl.glTexCoord2f(0, 1);
			gl.glVertex3f(-1, 1, 0);
		}
		gl.glEnd();

		// Disable all shaders
		gl.glUseProgramObjectARB(0);

		// Flush all drawing operations to the graphics card
		gl.glFlush();
	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height)
	{
		GL gl = drawable.getGL();

		if (height <= 0)
		{ // avoid a divide by zero error!

			height = 1;
		}
		final float h = (float) width / (float) height;
		gl.glViewport(0, 0, width, height);
		gl.glMatrixMode(GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(45.0f, h, 1.0, 20.0);
		gl.glMatrixMode(GL_MODELVIEW);
		gl.glLoadIdentity();
	}

	public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged)
	{
	}

	// Checks for arbitrary GL errors. Could also be accomplished by enabling the DebugGL pipeline
	private String getGLError(GL gl)
	{
		boolean hasError = false;
		String message = "";
		for (int glErr = gl.glGetError(); glErr != GL.GL_NO_ERROR; glErr = gl.glGetError())
		{
			message += (hasError ? "\n" : "") + glu.gluErrorString(glErr);
			hasError = true;
		}
		return hasError ? message : null;
	}

	// Checks the info log for compile/link errors
	private String getGLErrorLog(GL gl, int obj)
	{
		boolean hasError = false;
		int[] infologLength = {0};
		int[] charsWritten = {0};
		byte[] infoLog;

		String message = "";
		String error = getGLError(gl);
		if (error != null)
		{
			message += error;
			hasError = true;
		}

		gl.glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, infologLength, 0);
		error = getGLError(gl);
		if (error != null)
		{
			message += (hasError ? "\n" : "") + error;
			hasError = true;
		}

		if (infologLength[0] > 1)
		{
			infoLog = new byte[infologLength[0]];
			gl.glGetInfoLogARB(obj, infologLength[0], charsWritten, 0, infoLog, 0);
			message += (hasError ? "\n" : "") + "InfoLog:\n" + new String(infoLog);
			hasError = true;
		}
		error = getGLError(gl);
		if (error != null)
		{
			message += (hasError ? "\n" : "") + error;
			hasError = true;
		}
		return hasError ? message : null;
	}
}

replace

glsl1.class.getResource("moon.png")

with

glsl1.getClass().getResource("moon.png")

there is a tiny difference how the classloader searches for resources between both above (i forgot the details). The second method would start in the package of the class glsl1 with the search.
Put your pic in the same package as glsl1, clean build, and it should work.

btw classnames start per convention with capital letters

glsl1.class.getResource("moon.png")

retrieves the the “moon.png” relative to your glsl1 class. So you have to put it in the same package as the class (this would be “src/glsl1/” in your case). If you put the image directly under “src” you can also load the resource via an absolute reference:

glsl1.class.getResource("/moon.png")

(note the slash)

Another common way would be to make a resource-folder in your projects root and add it as source path in the project properties dialog. The files put into this can also be retrieved via:

glsl1.class.getResource("/moon.png")

I think this wouldn’t work, getClass() is not available on a class name.