problem with shader

hi,
i want to write a small program which processes input data with a shader. unfortunately i don’t get the results i would like to have. the fragment shader should calculate new values depending on the old values(texture information). therefor i have a simple test shader:


uniform sampler2D BaseImage;

void main(void) {
	vec4 tmp = texture2D(BaseImage,gl_TexCoord[0].st);
   	tmp += 0.5;
   	gl_FragColor = tmp;
}

and here is my code for the java part:


public abstract class GPUCalculator implements GLEventListener {

	private GLPbuffer		pbuffer;
	private GL				gl;

	private int				texture_target	= GL.GL_TEXTURE_RECTANGLE_ARB;
	private int				texture_format	= GL.GL_RGB;
	private int				data_type		= GL.GL_FLOAT;

	private int[]			texID			= new int[1];

	private int				width;
	private int				height;
	private float[]			data;

	public GPUCalculator ( int width, int height, float[] data ) {
		this.width = width;
		this.height = height;
		this.data = data;

		GLDrawableFactory factory = GLDrawableFactory.getFactory ();
		if ( factory.canCreateGLPbuffer () ) {
			try {
				this.pbuffer = factory.createGLPbuffer ( new GLCapabilities (), null, this.width, this.height, null );
				this.pbuffer.addGLEventListener ( this );
				this.pbuffer.display ();
				// this.pbuffer.getContext ().destroy ();
			} catch ( Exception e ) {
				System.out.println ( "PBuffer error" );
				e.printStackTrace ();
			}
		}
	}

	public void display ( GLAutoDrawable drawable ) {
		this.gl.glDrawBuffer (GL.GL_COLOR_ATTACHMENT0_EXT);
		renderQuad ( this.gl );
		readDataFromGPU ();
	}

	public void displayChanged ( GLAutoDrawable drawable, boolean arg1, boolean arg2 ) {

	}

	public void reshape ( GLAutoDrawable drawable, int arg1, int arg2, int arg3, int arg4 ) {
	}

	public void init ( GLAutoDrawable drawable ) {
		System.out.println ( "initializing" );

		this.gl = drawable.getGL ();

		if ( this.gl.glCheckFramebufferStatusEXT ( GL.GL_FRAMEBUFFER_EXT ) == 0 ) {
			return;
		}

		defineViewport ();

		defineTextures ();

		updateTexture ( this.data, this.width, this.height );

		defineFBO ();

		bindTexture ();

		defineShader ();
	}

	private void defineViewport () {
		GLU glu = new GLU ();
		this.gl.glMatrixMode ( GL.GL_PROJECTION );
		this.gl.glLoadIdentity ();
		glu.gluOrtho2D ( 0, this.width, 0, this.height );
		this.gl.glMatrixMode ( GL.GL_MODELVIEW );
		this.gl.glLoadIdentity ();
		this.gl.glViewport ( 0, 0, this.width, this.height );
	}

	private void defineFBO () {
		int[] fb = new int[1];
		this.gl.glGenFramebuffersEXT ( 1, fb, 0 );
		this.gl.glBindFramebufferEXT ( GL.GL_FRAMEBUFFER_EXT, fb[0] );
	}

	private void defineShader () {
		int program = gl.glCreateProgramObjectARB ();
		int frag = gl.glCreateShaderObjectARB ( GL.GL_FRAGMENT_SHADER_ARB );

		this.gl.glAttachObjectARB ( program, frag );
		this.gl.glShaderSourceARB ( frag, 1, getShaderSource ( "shader/simpleShader.glsl" ), null );
		this.gl.glCompileShaderARB ( frag );
		this.gl.glLinkProgramARB ( program );

		int texImage = gl.glGetUniformLocationARB ( program, "BaseImage" );

		this.gl.glUseProgramObjectARB ( program );
		//this.gl.glActiveTexture ( GL.GL_TEXTURE0 );
		this.gl.glUniform1iARB ( texImage, 0 );
	}

	private void defineTextures () {
		this.gl.glGenTextures ( 1, texID, 0 );
		this.gl.glBindTexture ( this.texture_target, texID[0] );
		this.gl.glTexParameteri ( this.texture_target, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST );
		this.gl.glTexParameteri ( this.texture_target, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST );
		this.gl.glTexParameteri ( this.texture_target, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP );
		this.gl.glTexParameteri ( this.texture_target, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP );
	}

	public void updateTexture ( float[] newData, int newWidth, int newHeight ) {
		this.data = newData;
		this.gl.glTexImage2D ( this.texture_target, 0, GL.GL_RGB32F_ARB, newWidth, newHeight, 0, this.texture_format,
				this.data_type, FloatBuffer.wrap ( this.data ) );
	}

	private void bindTexture () {
		this.gl.glFramebufferTexture2DEXT ( GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, this.texture_target,
				texID[0], 0 );
		this.gl.glBindTexture ( this.texture_target, this.texID[0] );

	}

	private void renderQuad ( GL gl ) {
		this.gl.glPolygonMode ( GL.GL_FRONT, GL.GL_FILL );
		this.gl.glBegin ( GL.GL_QUADS );
		this.gl.glTexCoord2f ( 0.0f, 0.0f );
		this.gl.glVertex2f ( 0.0f, 0.0f );
		this.gl.glTexCoord2f ( this.width, 0.0f );
		this.gl.glVertex2f ( this.width, 0.0f );
		this.gl.glTexCoord2f ( this.width, this.height );
		this.gl.glVertex2f ( this.width, this.height );
		this.gl.glTexCoord2f ( 0.0f, this.height );
		this.gl.glVertex2f ( 0.0f, this.height );
		this.gl.glEnd ();
	}

	public void transferDataToGPU () {
		this.gl.glTexSubImage2D ( this.texture_target, 0, 0, 0, this.width, this.height, this.texture_format,
				this.data_type, FloatBuffer.wrap ( this.data ) );
	}

	public float[] readDataFromGPU () {
		float[] outData = new float[this.data.length];
		this.gl.glReadBuffer ( GL.GL_COLOR_ATTACHMENT0_EXT );
		this.gl.glReadPixels ( 0, 0, this.width, this.height, this.texture_format, this.data_type, FloatBuffer
				.wrap ( outData ) );

		for ( int i = 0; i < data.length; i++ ) {
			System.out.println ( "temp: " + outData[i] );
		}
		return outData;
	}

	private String[] getShaderSource ( String fileName ) {
[...]
	}
}

the shader seems to replace all values by 0.5. so i guess that the input to the shader are not the desired value.

example:
input: 0.1, 0.2, 0.3
output: 0.5, 0.5, 0.5

i hope soomeone can help me…

A couple of things to try, even though I’m pretty sure you set the sampler variable correctly, try giving it the texture target instead of the texture unit. Also try verify that your texture was loaded correctly and that it is complete. Make sure that floating point textures are supported on your graphics card. I noticed that you just wrap the float[] data array into a FloatBuffer to pass in. Most other Buffer options require that the buffer be in native byte order and direct (and I’m pretty sure that a wrapped buffer isn’t direct). Try using BufferUtil to get a FloatBuffer and then filling it with the float[] data.

Hopefully something in there works.

hi,
thank you for your quick answer.
how can i give the sampler variable the texture target?
(i’m sorry if i ask any trivial questions…i’m just working with jogl and shaders for a couple of days)
i replaced the float[] by FloatBuffers, but unfortunately the result is the same.
if i remove the call to the method renderquad() in the display method, the results in the output are the same as they are from the input:
in: 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8
out: 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8
…so i assume that the input values of the texture are correct.

another example:
if i render the quad without the shader, all output values are 1.0:
in: 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8
out: 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0

perhaps this helps to get the problem…

i guess that floating point textures are supported by my graphics card (nvidia 7800 gt). how can i check this?

greetings,
wano

ohh…i got it!

my shader code was wrong.
i have to use rects:


uniform samplerRect BaseImage;

void main(void) {
	vec4 tmp = textureRect(BaseImage,gl_TexCoord[0].st);
   	tmp += 0.5;
   	gl_FragColor = tmp;
}

now it’s working :wink: