blank screen by shader render

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

blank screen by shader render

slava_jazz
Hi All, sorry for dummy question, but you are my last hope...
I am using:
jogl: windows-amd64 build 2.0-b45-20111219 on Windows7.
Native GL: 4.2.0  ( gl2.glGetString(GL.GL_VERSION) )
Graphic card: Nvidia Quadro 600

Currently I am trying to complete very simply program, which shows a single white triangle using shader based rendering. Unfortunately, because result screen is always blank,it  looks like that I did some mistakes, which I can not see... Would anybody help me to find where and what is wrong?

Sorry for lot of code

Triangle.java::=
import com.jogamp.opengl.util.Animator;

import javax.media.opengl.*;
import javax.media.opengl.awt.GLCanvas;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.Scanner;

public class Triangle implements GLEventListener
{
    private static final int INITIAL_SURFACE_WIDTH = 300;
    private static final int INITIAL_SURFACE_HEIGHT = 300;
    
    private static final float SHAPE[] = 
            {
                    -.5f, .0f, .0f, 
                     .0f, 1.f, .0f, 
                     .5f, .0f, .0f 
            };

    private static final short INDICES[] = {0,3,6};

    private static final float MATRIX[] =
            {
                    1.f, 0f, 0f, 0f,
                    0.f, 1f, 0f, 0f,
                    0.f, 0f, 1f, 0f,
                    0.f, 0f, 0f, 1f
            };

    private static final FloatBuffer MATRIX_BUFFER = FloatBuffer.wrap(MATRIX);
    
    
    private int[] data;
    private int[] shader;
    private int prog;
    private int u_mvpMatrix;
    private int a_vertex;
    private boolean readyToDraw;


    public static void main(String[] _a)
    {
        GLProfile glp = GLProfile.getDefault();
        GLCapabilities caps = new GLCapabilities(glp);
        GLCanvas canvas = new GLCanvas(caps);

        Frame frame = new Frame("Triangle");
        frame.setSize(INITIAL_SURFACE_WIDTH, INITIAL_SURFACE_HEIGHT);
        frame.add(canvas);
        frame.setVisible(true);

        frame.addWindowListener(new WindowAdapter()
        {
            public void windowClosing(WindowEvent e)
            {
                System.exit(0);
            }
        });

        canvas.addGLEventListener(new Triangle());

        Animator animator = new Animator(canvas);
        animator.add(canvas);
        animator.start();
    }

    @Override
    public void init(final GLAutoDrawable _gl_drawable)
    {
        readyToDraw = false;
        try
        {
            GL2 gl2 = _gl_drawable.getGL().getGL2();
            data = Triangle.uploadData(gl2,Triangle.SHAPE,Triangle.INDICES);
            if(data != null)
            {
                shader = new int[]
                        {
                                Triangle.loadShaderFromFile(gl2, GL2.GL_VERTEX_SHADER, "triangle-vertex.glsl"),
                                Triangle.loadShaderFromFile(gl2, GL2.GL_FRAGMENT_SHADER, "triangle-fragment.glsl")
                        };
                if(
                        shader[0] != -1 &&
                        shader[1] != -1 &&
                        (prog = Triangle.linkProgram(gl2,shader)) != -1 &&
                        (u_mvpMatrix = gl2.glGetUniformLocation(prog, "u_mvpMatrix")) >= 0 &&
                        (a_vertex = gl2.glGetAttribLocation(prog, "a_vertex")) >= 0
                    )
                {
                    readyToDraw = true;
                }
            }
        }
        catch (Throwable e)
        {
            e.printStackTrace();
        }
        finally
        {
            if(!readyToDraw)
            {
                System.exit(-1);
            }
            else
            {
                System.out.println("ok.");
            }
        }

    }

    @Override
    public void dispose(final GLAutoDrawable _gl_drawable)
    {

    }

    @Override
    public void display(final GLAutoDrawable _gl_drawable)
    {
        GL2 gl2 = _gl_drawable.getGL().getGL2();

        // Clears the color and depth render buffer.
        gl2.glClearColor(.5f, .5f, .5f, 1.f);
        gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        
        
        gl2.glUseProgram(prog);

        // Sets the uniform to MVP Matrix.
        Triangle.MATRIX_BUFFER.rewind();
        gl2.glUniformMatrix4fv(u_mvpMatrix, 1, false, Triangle.MATRIX_BUFFER);

        // Bind the Buffer Objects which we'll use now.
        gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, data[0]);
        gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, data[1]);
        gl2.glVertexAttribPointer(a_vertex,3 , GL2.GL_FLOAT, false, 0, 0L);


        // Draws the triangles, starting by the index 0 in the IBO.
        int count = Triangle.INDICES.length;     // also tried with Triangle.INDICES.length/3 
        gl2.glDrawElements(GL2.GL_TRIANGLES, count, GL2.GL_UNSIGNED_SHORT, 0);

        // Unbid all the Buffer Objects currently in use.
        gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
        gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, 0);

        gl2.glFlush();
    }

    @Override
    public void reshape(final GLAutoDrawable _gl_drawable, final int i, final int i1, final int i2, final int i3)
    {

    }
    
    
    private static int linkProgram(final GL2 _gl2, final int[] _shader)
    {
        int prog = _gl2.glCreateProgram();
        _gl2.glAttachShader(prog, _shader[0]);    
        _gl2.glAttachShader(prog, _shader[1]);    
        _gl2.glLinkProgram(prog);

        _gl2.glValidateProgram(prog);
        IntBuffer int_buffer = IntBuffer.allocate(1);
        _gl2.glGetProgramiv(prog, GL2.GL_LINK_STATUS, int_buffer);
        if (int_buffer.get(0) != 1)
        {
            prog = -1;
            int_buffer.rewind();
            _gl2.glGetProgramiv(prog, GL2.GL_INFO_LOG_LENGTH, int_buffer);
            int size = int_buffer.get(0);
            ByteBuffer byte_buffer = ByteBuffer.allocate(size);
            _gl2.glGetProgramInfoLog(prog, size, int_buffer, byte_buffer);
            System.err.println("program link error:\n" + new String(byte_buffer.array(), 0, int_buffer.get(0)));
        }
        return prog;
    }
    
    private static int[] uploadData(final GL2 _gl2, final float[] _vertexes, final short[] _indices)
    {
        int h[] = new int[] {-1,-1};
        _gl2.glGenBuffers(2, h, 0);
        if(h[0] != -1 && h[1] != -1)
        {
            _gl2.glBindBuffer(GL.GL_ARRAY_BUFFER, h[0]);
            _gl2.glBufferData(GL.GL_ARRAY_BUFFER, _vertexes.length, FloatBuffer.wrap(_vertexes), GL.GL_STATIC_DRAW);

            _gl2.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, h[1]);
            _gl2.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, _indices.length, ShortBuffer.wrap(_indices), GL.GL_STATIC_DRAW);
        }
        else
        {
            h = null;
        }
        return h;
    }

    private static int loadShaderFromFile(final GL2 _gl2, int _shader_type, final String _file_name)
    {
        int shader_index = -1;
        String shader_source = getFileContent(_file_name);
        if (shader_source != null)
        {
            shader_index = _gl2.glCreateShader(_shader_type);
            IntBuffer int_buffer = IntBuffer.wrap(new int[]{shader_source.length()});
            _gl2.glShaderSource(shader_index, 1, new String[]{shader_source}, int_buffer);
            _gl2.glCompileShader(shader_index);
            int_buffer.array()[0] = 0;
            int_buffer.rewind();
            _gl2.glGetShaderiv(shader_index, GL2.GL_INFO_LOG_LENGTH, int_buffer);
            if (int_buffer.array()[0] != 1)
            {
                ByteBuffer byte_buffer = ByteBuffer.allocate(int_buffer.get(0));
                _gl2.glGetShaderInfoLog(shader_index, int_buffer.get(0), int_buffer, byte_buffer);
                System.err.println("shader compilation error:\n" + new String(byte_buffer.array(), 0, int_buffer.get(0)));
            }
        }
        return shader_index;
    }


    private static String getFileContent(String _file_name)
    {
        String content = null;
        try
        {
            InputStream in = new FileInputStream(_file_name);
            StringBuilder buffer = new StringBuilder();
            Scanner scanner = new Scanner(in);
            try
            {
                while (scanner.hasNextLine())
                {
                    buffer.append(scanner.nextLine() + "\n");
                }
                content = buffer.toString();
            }
            finally
            {
                scanner.close();
            }
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }

        return content;
    }
}


triangle-vertex.glsl::=
uniform mat4 u_mvpMatrix;
attribute vec4 a_vertex;
void main()
{
    gl_Position = u_mvpMatrix * a_vertex;
}

triangle-fragment.glsl::=
void main()
{
    gl_FragColor = vec4 (1.0, 1.0, 1.0, 1.0);
}
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

gouessej
Administrator
Hi

Maybe Demoscene Passivist could help you.

Why do you do this???

int_buffer.array()[0] = 0;
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

slava_jazz
to erase old value before glGetShaderiv. just paranoid a little...
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

gouessej
Administrator
Maybe use ShaderCode, ShaderProgram, ShaderState and ShaderUtil if you fail in using low-level methods to manipulate shaders.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

slava_jazz
In reply to this post by slava_jazz
I did some more tries with "draw" workflow:

original::=
        gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, data[0]);
        gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, data[1]);
        gl2.glVertexAttribPointer(a_vertex, 3, GL2.GL_FLOAT, false, 0, 0L);
        int count = Triangle.INDICES.length;
        gl2.glDrawElements(GL2.GL_TRIANGLES, count, GL2.GL_UNSIGNED_SHORT, 0);

alt1::=
        gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
        gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, data[1]);
        gl2.glVertexAttribPointer(a_vertex, 3, GL2.GL_FLOAT, false,0,FloatBuffer.wrap(SHAPE));
        int count = Triangle.INDICES.length;
        gl2.glEnableVertexAttribArray(a_vertex);
        gl2.glDrawArrays(GL2.GL_TRIANGLES, 0, count);

alt2::=
        gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, data[0]);
        gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, data[1]);
        gl2.glVertexAttribPointer(a_vertex, 3, GL2.GL_FLOAT, false, 0, 0l);
        int count = Triangle.INDICES.length;
        gl2.glDrawArrays(GL2.GL_TRIANGLES, 0, count);

alt3::=
        gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
        gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, data[1]);
        gl2.glVertexAttribPointer(a_vertex, 3, GL2.GL_FLOAT, false,0,FloatBuffer.wrap(SHAPE));
        int count = Triangle.INDICES.length;
        gl2.glEnableVertexAttribArray(a_vertex);
        gl2.glDrawElements(GL2.GL_TRIANGLES, count, GL2.GL_UNSIGNED_SHORT, 0);

hmm, woks only alt1 - if I point on vertexes data on client side and if I use glDrawArrays....
Other variants does not work.  What is happens there? I do not like to transfer a lot of data from heap to gpu each time as "draw" called (see alt1 variant).  And why glDrawElements does not work in alt3 ?

 
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

Wade Walker
Administrator
In reply to this post by slava_jazz
I noticed that in glBufferData, you're passing the number of floats as the size, but it should be the size in bytes instead (so number of floats * 4). There's the same problem with your index buffer (should be number of shorts * 2).

You might also want to check the GL error status after every GL call that might set it. This can find errors that might leave you puzzled for a very long time  I usually define a function like this:

    /**
     * Checks if there have been any GL errors. Throws an exception with the
     * error codes in the message if there have been.
     * @param gl Used to make GL calls.
     * @param sFuncName Name of GL function we're checking for errors after.
     */
    public static void checkGLError( GL2ES2 gl, String sFuncName ) {

        int iError;
        StringBuilder sb = null;
        do {
            iError = gl.glGetError();
            if( iError != GL.GL_NO_ERROR ) {
                if( sb == null )
                    sb = new StringBuilder();
                sb.append( sFuncName + " failed, GL error: 0x" + Integer.toHexString( iError ) + "\n" );
            }
        }
        while( iError != GL.GL_NO_ERROR );

        if( sb != null )
            Assert.assertTrue( sb.toString(), false  );
    }

and call it after every GL function that can set an error code.
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

slava_jazz
Thanks, Wade Walker,  
after size fixing the  "glDrawArray" works correct for both cases (data pre-loaded into gpu and on-fly loaded from heap). Additional I was found that  "gl2.glEnableVertexAttribArray(a_vertex);" have to be called for both cases as well.

Big step forward, but "glDrawElements" still does not work, your nice diagnostic function checkGLError(gl2,"glDrawElements"); keep silence...
would you please look what there can be wrong:
        int count = Triangle.INDICES.length;
        gl2.glEnable(GL2.GL_VERTEX_ARRAY);
        checkGLError(gl2,"glEnable");
        gl2.glDrawElements(GL2.GL_TRIANGLES, count, GL2.GL_UNSIGNED_SHORT, 0);
        checkGLError(gl2,"glDrawElements");
 
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

gouessej
Administrator
Why do you use GL2.GL_UNSIGNED_SHORT?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

slava_jazz
just automatically, because it  it is a size.  sizeof(short) is the same as sizeof (unsigned short).
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

gouessej
Administrator
Your indices aren't short, are they?

Edit.: sorry they are short.

Edit.: What do you pass to glVertexAttribPointer before calling glDrawElements?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

slava_jazz
sorry for delay, I just back from business trip.
actually my load code is:
    private static int[] uploadData(final GL2 _gl2, final float[] _vertexes, final short[] _indices)
    {
        int h[] = new int[]{-1, -1};
        _gl2.glGenBuffers(2, h, 0);
        if (h[0] != -1 && h[1] != -1)
        {
            _gl2.glBindBuffer(GL.GL_ARRAY_BUFFER, h[0]);
            _gl2.glBufferData(GL.GL_ARRAY_BUFFER, _vertexes.length * 4, FloatBuffer.wrap(_vertexes), GL.GL_STATIC_DRAW);
            checkGLError(_gl2, "glBufferData");
            _gl2.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, h[1]);
            _gl2.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, _indices.length * 2, ShortBuffer.wrap(_indices), GL.GL_STATIC_DRAW);
            checkGLError(_gl2, "glBufferData");
        }
        else
        {
            h = null;
        }
        return h;
    }
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

Wade Walker
Administrator
Sorry to not give you more specific advice, but I'd say to just go through every GL function call carefully, checking all arguments for type, value, length, et cetera. Usually I check my code against examples online to make sure I'm using each function correctly.

If it makes you feel any better, I think every GL program I've ever written comes up with a blank screen initially  But if you persevere, eventually it will work.
Reply | Threaded
Open this post in threaded view
|

Re: blank screen by shader render

Sven Gothel
Administrator
On 03/30/2012 02:32 AM, Wade Walker [via jogamp] wrote:
>
>
> Sorry to not give you more specific advice, but I'd say to just go through
> every GL function call carefully, checking all arguments for type, value,
> length, et cetera. Usually I check my code against examples online to make
> sure I'm using each function correctly.
>

You can try setting -Djogl.debug.TraceGL and  -Djogl.debug.DebugGL
system properties. The latter option will end your program in case of an GL error.

If you use our ShaderUtil class to handle the shader code (load, compile,
link, ..) you can also set: -Djogl.debug.GLSLCode
which verifies the shader a bit more thoroughly and dumps it on the console.
Read our ShaderCode and ShaderUtil[s] class about how to verify the code.

Maybe the GL trace discloses the missing piece, like enabling an attribute,
passing a proper PMV matrix uniform, etc ..
Usually it's just one of the 2 above.

> If it makes you feel any better, I think every GL program I've ever written
> comes up with a blank screen initially  But if you persevere, eventually it
> will work.

indeed :)

~Sven


signature.asc (910 bytes) Download Attachment