Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (538)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (601)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Help on Geometry Shaders using jogl  (Read 3634 times)
0 Members and 1 Guest are viewing this topic.
Offline harishd

Senior Newbie





« Posted 2009-02-26 08:56:36 »

Hi, I am a new to shaders in general, especially geometry shaders. I have a 8800GTX card.
When I tried to run a simple geometry shader program (obtained from a tutorial online), it doesnt seem to be working when I use jogl, while the same thing works when written in C.

in the GLEventListener's init() method, i initialize the geometry shader as follows

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
g = gl.glCreateShader(GL.GL_GEOMETRY_SHADER_EXT);
String [] gs = new String [1];
gs[0] = readShaderFile("glsl/toon.geom");

int [] gb = new int [] {gs[0].length()};
gl.glShaderSource(g,1,gs,gb,0);
gl.glCompileShader(g);

p = gl.glCreateProgram();
gl.glAttachShader(p,g);
     
gl.glProgramParameteriEXT(g,GL.GL_GEOMETRY_INPUT_TYPE_EXT,GL.GL_LINES);
gl.glProgramParameteriEXT(g,GL.GL_GEOMETRY_OUTPUT_TYPE_EXT,GL.GL_LINE_STRIP);

int [] temp = new int[2];
gl.glGetIntegerv(GL.GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT,temp,0);
gl.glProgramParameteriEXT(g,GL.GL_GEOMETRY_VERTICES_OUT_EXT,temp[0]);

gl.glLinkProgram(p);
gl.glUseProgram(p);


and my geometry shader code is as follows. (I only draw one line in the display() method , and i want two lines in the output)

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
#version 120 
#extension GL_EXT_geometry_shader4 : enable

void main(void)
{
   //increment variable
   int i;

   //Pass-thru!
   for(i=0; i< gl_VerticesIn; i++){
      gl_Position = gl_PositionIn[i];
      EmitVertex();
   }
   EndPrimitive();

   //New piece of geometry!  We just swizzle the x and y terms
   for(i=0; i< gl_VerticesIn; i++){
      gl_Position = gl_PositionIn[i];
      gl_Position.xy = gl_Position.yx;
      EmitVertex();
   }
   EndPrimitive();
}


Any idea where I might be making a mistake. any help would be appreciated.
Offline irreversible_kev

Junior Devvie





« Reply #1 - Posted 2009-02-26 09:44:09 »

I have two things to say:

1. You should check for errors in both your shaders and your programs using code similar to

In my Shader.java :
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
    private void checkCompileError(GL gl) {
        IntBuffer status = BufferUtil.newIntBuffer(1);
        gl.glGetShaderiv(id, GL.GL_COMPILE_STATUS, status);

        if (status.get() == GL.GL_FALSE) {
            getInfoLog(gl);
        } else {
            System.out.println("Successfully compiled shader " + id);
        }
    }

    private void getInfoLog(GL gl) {
        IntBuffer infoLogLength = BufferUtil.newIntBuffer(1);
        gl.glGetShaderiv(id, GL.GL_INFO_LOG_LENGTH, infoLogLength);

        ByteBuffer infoLog = BufferUtil.newByteBuffer(infoLogLength.get(0));
        gl.glGetShaderInfoLog(id, infoLogLength.get(0), null, infoLog);

        String infoLogString =
                Charset.forName("US-ASCII").decode(infoLog).toString();
        throw new Error("Shader compile error\n" + infoLogString);
    }



In my Program.java:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
    private void checkLinkAndValidationErrors(GL gl) {
        IntBuffer status = BufferUtil.newIntBuffer(1);
        gl.glGetProgramiv(id, GL.GL_LINK_STATUS, status);

        if (status.get() == GL.GL_FALSE) {
            getInfoLog(gl);
        } else {
            status.rewind();
            gl.glValidateProgram(id);
            gl.glGetProgramiv(id, GL.GL_VALIDATE_STATUS, status);
            if (status.get() == GL.GL_FALSE) {
                getInfoLog(gl);
            } else {
                System.out.println("Successfully linked program " + id);
            }
        }
    }

    private void getInfoLog(GL gl) {
        IntBuffer infoLogLength = BufferUtil.newIntBuffer(1);
        gl.glGetProgramiv(id, GL.GL_INFO_LOG_LENGTH, infoLogLength);

        ByteBuffer infoLog = BufferUtil.newByteBuffer(infoLogLength.get(0));
        gl.glGetProgramInfoLog(id, infoLogLength.get(0), null, infoLog);

        String infoLogString =
                Charset.forName("US-ASCII").decode(infoLog).toString();
        throw new Error("Program compile error\n" + infoLogString);
    }


2. It looks as if you are trying to send the geometry shader's source code as one String. Although it doesn't matter whether or not you start a new line for the code, it does matter for pre-processor statements and comments.

IE it will understand
1  
   for(i=0; i< gl_VerticesIn; i++){gl_Position = gl_PositionIn[i];EmitVertex();}

but it won't understand
1  
#version 120 #extension GL_EXT_geometry_shader4 : enablevoid main(void){   //increment variableint i;


Your readShaderFile should return an array of Strings each containing one line of the source code.

EDIT : Acctually you may only need one String if each line is separated with \n. You should experiment with this.
Offline harishd

Senior Newbie





« Reply #2 - Posted 2009-02-27 06:21:09 »

thanks for the suggestions, but the geometry shader still doesn't work Sad

As for your questions,
1. the shader code compiled and linked succesfully.
2. The shader program is in a single string with a "\n" after each line.

I didn't mention it in my previously, but its only the geometry shader that is not working. The vertex and fragment shaders work fine.
(Actually when using the geometry shader, there is no output on the screen, not even the original line that i draw).

EDIT: When I attach only the geometry shader ( and not the vertex and fragment shader) there is a link error, but when all three shaders are attached then, the shader program successfully links. Also, the infostring is emty, so I can't figure out what the error is.

I am attaching my entire code, may be something is wrong with it.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
208  
209  
210  
211  
212  
213  
214  
215  
216  
217  
218  
219  
220  
221  
222  
223  
224  
225  
226  
227  
228  
229  
230  
231  
232  
233  
234  
235  
236  
237  
238  
239  
240  
241  
242  
243  
244  
245  
246  
247  
248  
249  
250  
251  
252  
253  
254  
255  
256  
257  
258  
259  
260  
261  
262  
263  
264  
265  
266  
267  
268  
269  
270  
271  
272  
273  
274  
275  
276  
277  
278  
279  
280  
281  
282  
283  
284  
package hope.it.works;

import java.awt.BorderLayout;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.NumberFormat;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.swing.JFrame;

import com.sun.opengl.util.Animator;
import com.sun.opengl.util.BufferUtil;

public class Shader extends JFrame implements GLEventListener, WindowListener {

   private static final long serialVersionUID = 1L;
   boolean first = true;
   int list;
   int no;
   double[] x, y, z, a;

   public Shader() {
      super("Test Shader");

      setLayout(new BorderLayout());
      addWindowListener(this);

      setSize(850, 850);
      setVisible(true);

      setupJOGL();
      String s = "0.00";
      noFormat = new DecimalFormat(s);
   }

   private void setupJOGL() {
      GLCapabilities caps = new GLCapabilities();
      caps.setDoubleBuffered(true);
      caps.setHardwareAccelerated(true);
      GLCanvas canvas = new GLCanvas(caps);
      canvas.addGLEventListener(this);

      add(canvas, BorderLayout.CENTER);

      Animator anim = new Animator(canvas);
      anim.start();
   }

   /**
    * @param args
    */

   public static void main(String[] args) {
      new Shader().setVisible(true);
   }

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

      gl.glLoadIdentity();
      gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

      gl.glColor3f(1, 0, 0);
      gl.glBegin(GL.GL_LINES);
      gl.glVertex2d(0, -d);
      gl.glVertex2d(0, d);
      gl.glEnd();
      updateFPS();
   }

   public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2) {
      // TODO Auto-generated method stub

   }

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

      gl.glClearColor(0, 0, 0, 0);
      gl.glMatrixMode(GL.GL_PROJECTION);
      gl.glLoadIdentity();
      gl.glOrtho(0, 1, 0, 1, -1, 1);

      gl.glMatrixMode(GL.GL_MODELVIEW);
      gl.glLoadIdentity();

      setupShaders(gl);
   }

   int p;
   int v;
   int f;
   int g;

   private void setupShaders(GL gl) {

      v = gl.glCreateShader(GL.GL_VERTEX_SHADER);
      f = gl.glCreateShader(GL.GL_FRAGMENT_SHADER);
      g = gl.glCreateShader(GL.GL_GEOMETRY_SHADER_EXT);

      String[] vs = new String[1];
      vs[0] = readShaderFile("glsl/toon.vert");
      String[] gs = new String[1];
      gs[0] = readShaderFile("glsl/toon.geom");
      String[] fs = new String[1];
      fs[0] = readShaderFile("glsl/toon.frag");

      int[] vb = new int[] { vs[0].length() };
      gl.glShaderSource(v, 1, vs, vb, 0);

      int[] fb = new int[] { fs[0].length() };
      gl.glShaderSource(f, 1, fs, fb, 0);

      int[] gb = new int[] { gs[0].length() };
      gl.glShaderSource(g, 1, gs, gb, 0);

      gl.glCompileShader(v);
      checkCompileError(gl, v);

      gl.glCompileShader(f);
      checkCompileError(gl, f);

      gl.glCompileShader(g);
      checkCompileError(gl, g);

      p = gl.glCreateProgram();

      gl.glAttachShader(p, f);
      gl.glAttachShader(p, v);
      gl.glAttachShader(p, g);

      gl
            .glProgramParameteriEXT(g, GL.GL_GEOMETRY_INPUT_TYPE_EXT,
                  GL.GL_LINES);
      gl.glProgramParameteriEXT(g, GL.GL_GEOMETRY_OUTPUT_TYPE_EXT,
            GL.GL_LINE_STRIP);

      int[] temp = new int[2];
      gl.glGetIntegerv(GL.GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, temp, 0);
      gl.glProgramParameteriEXT(g, GL.GL_GEOMETRY_VERTICES_OUT_EXT, temp[0]);

      gl.glLinkProgram(p);
      checkLinkAndValidationErrors(gl, p);
      gl.glUseProgram(p);
   }

   private void checkCompileError(GL gl, int id) {
      IntBuffer status = BufferUtil.newIntBuffer(1);
      gl.glGetShaderiv(id, GL.GL_COMPILE_STATUS, status);

      if (status.get() == GL.GL_FALSE) {
         getInfoLog(gl, id);
      } else {
         System.out.println("Successfully compiled shader " + id);
      }
   }

   private void getInfoLog(GL gl, int id) {
      IntBuffer infoLogLength = BufferUtil.newIntBuffer(1);
      gl.glGetShaderiv(id, GL.GL_INFO_LOG_LENGTH, infoLogLength);

      ByteBuffer infoLog = BufferUtil.newByteBuffer(infoLogLength.get(0));
      gl.glGetShaderInfoLog(id, infoLogLength.get(0), null, infoLog);

      String infoLogString = Charset.forName("US-ASCII").decode(infoLog)
            .toString();
      throw new Error("Shader compile error\n" + infoLogString);
   }

   private void checkLinkAndValidationErrors(GL gl, int id) {
      IntBuffer status = BufferUtil.newIntBuffer(1);
      gl.glGetProgramiv(id, GL.GL_LINK_STATUS, status);

      if (status.get() == GL.GL_FALSE) {
         getInfoLog(gl, id);
      } else {
         status.rewind();
         gl.glValidateProgram(id);
         gl.glGetProgramiv(id, GL.GL_VALIDATE_STATUS, status);
         if (status.get() == GL.GL_FALSE) {
            getInfoLog(gl, id);
         } else {
            System.out.println("Successfully linked program " + id);
         }
      }
   }

   private String readShaderFile(String file) {
      String s = "";
      try {
         BufferedReader r = new BufferedReader(new FileReader(file));
         String t = r.readLine();
         while (t != null) {
            s += t;
            s += "\n";
            t = r.readLine();
         }
      } catch (Exception e) {
         e.printStackTrace();
      }
      return s;
   }

   int w;
   int h;
   int d;

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

      gl.glViewport(0, 0, width, height);
      gl.glMatrixMode(GL.GL_PROJECTION);
      gl.glLoadIdentity();

      w = width / 2;
      h = height / 2;
      gl.glOrtho(-1 * w, w, -1 * h, h, -600, 600);
      gl.glMatrixMode(GL.GL_MODELVIEW);
      gl.glLoadIdentity();
      d = Math.min(w, h);
   }

   public void windowActivated(WindowEvent e) {
      // TODO Auto-generated method stub

   }

   public void windowClosed(WindowEvent e) {
      // TODO Auto-generated method stub

   }

   public void windowClosing(WindowEvent e) {
      System.exit(0);
   }

   public void windowDeactivated(WindowEvent e) {
      // TODO Auto-generated method stub

   }

   public void windowDeiconified(WindowEvent e) {
      // TODO Auto-generated method stub

   }

   public void windowIconified(WindowEvent e) {
      // TODO Auto-generated method stub

   }

   public void windowOpened(WindowEvent e) {
      // TODO Auto-generated method stub

   }

   private double stTime;
   private double enTime;
   private double frameCt;
   private NumberFormat noFormat;

   private void updateFPS() {
      enTime = System.currentTimeMillis();
      double diff = enTime - stTime;
      frameCt++;
      if (diff > 1000) {
         double fps = frameCt * 1000 / diff;
         stTime = enTime;
         String s = noFormat.format(fps);
         this.setTitle("Name [FPS: " + s + "]");
         frameCt = 0;
      }
   }
}


The shaders im using are as follows

The vertex shader

1  
2  
3  
4  
5  
void main()
{  
   //Transform the vertex (ModelViewProj matrix)
   gl_Position = ftransform();
}


The fragment shader

1  
2  
3  
4  
5  
void main()
{  
   //Shade to blue!
   gl_FragColor = vec4(0.0,0.0,1.0,1.0);  
}


I had already posted the geometry shader code in my initial post.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline irreversible_kev

Junior Devvie





« Reply #3 - Posted 2009-02-27 09:37:13 »

OK Fixed.

1. You should use the DebugGL object as follows:
1  
2  
3  
4  
5  
6  
    public void init(GLAutoDrawable drawable) {
        drawable.setGL(new DebugGL(drawable.getGL()));
        GL gl = drawable.getGL();

        gl.glClearColor(0, 0, 0, 0);
        ....


We checked for program errors and shader errors but forgot to check for basic OpenGL errors!
The DebugGL object will call glGetError after every gl command.

2. This will show you that the problem is
1  
2  
3  
4  
        gl.glProgramParameteriEXT(g, GL.GL_GEOMETRY_INPUT_TYPE_EXT, GL.GL_LINES);
        gl.glProgramParameteriEXT(g, GL.GL_GEOMETRY_OUTPUT_TYPE_EXT, GL.GL_LINE_STRIP);
        ...
        gl.glProgramParameteriEXT(g, GL.GL_GEOMETRY_VERTICES_OUT_EXT, temp[0]);


You are setting program parameters and these apply to the program not the geometry shader.
IE you should have
1  
2  
        gl.glProgramParameteriEXT(p, GL.GL_GEOMETRY_INPUT_TYPE_EXT, GL.GL_LINES);
        ...
Offline harishd

Senior Newbie





« Reply #4 - Posted 2009-02-27 12:13:37 »

It now works. Thanks a lot.

EDIT: I have another basic question. When I tried using only the vertex shader and geometry shader, I found that there was no output, but using these two along with the fragment shader, it worked. Till now i was under the assumption that if no fragment shader is specified, then the opengl default will be used. But I guess i was wrong, and the shader program uses whatever shaders that were attached to it. If this is case, what do I need to do to get the default functionality vertex shader and fragment shader to work with my customized geometry shader?
Offline lhkbob

JGO Knight


Medals: 32



« Reply #5 - Posted 2009-02-27 16:51:36 »

According to the spec, a vertex or a fragment shader should work on its own.  There are a few things that make it complicated, and not recommended, however.  If you're just writing a vertex shader, there are a lot of variables you have to give values to provide all of the information that the fixed function pipeline would already have. 

In your example shaders, you don't pass color information from the vertex shader.  This means that the fragment stage for the ffp doesn't have any color.  What's probably doing is just rendering everything as black, or the last set color.

Offline harishd

Senior Newbie





« Reply #6 - Posted 2009-03-03 08:29:32 »

Thanks, I set the front and back color in the vertex shader and it works now.

Now I have yet another problem  Huh If I generate primitives within a loop (where the iterations of the loop is variable), then the performance of the program drastically decreases. Where as if I loop a constant no. of times (Ex. for (int i = 0;i < 10; i++) ), then there is no performance degradation. Also the constant seems to be a small number. Any one knows if there is an optimal way for generating as many output primitives as possible? The maximum no. of output vertices as specified in the glProgramParameteriEXT() method is 1024, so I have no idea why this should happen.
Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 840
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #7 - Posted 2009-03-03 21:12:47 »

This is a result of the design of the hardware.

Your GPU will have dozens of shader units, probably a multiple of 16 or 32.

Now the problem is that each shader unit isn't isolated, it is located in a block of shaders (probably 16 or 32 shaders per block). There is only 1 instructor dispatcher per block, so all shaders in that block are working in lockstep on the same instruction. When there are IF statements (or loops, that cannot be unrolled - loops with a constant can be unrolled..), and 50% of the shaders evaluate the condition to true and 50% to false, you'll have 50% of your shaders in that block idling, waiting for the other shaders to finish those instructions that are part of the IF branch, you get the reverse effect when the ELSE branch is executed (if any).

When 10% of of the fragments enter an IF branch, 90% will be blocking. That's what causing your dynamic-for-loops to drastically reduce performance.

Besides that, branch-prediction and conditional jump themselves are not so performant on GPUs.



I thought ATi AMD GPUs have a more efficient design that 'lock step' , but you might have to Google that.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social
Offline harishd

Senior Newbie





« Reply #8 - Posted 2009-03-04 03:23:30 »

Even if AMD does have an efficient design, it doesnt help much since they do not provide GLSL support for geometric shaders in their OpenGL driver.
Offline lhkbob

JGO Knight


Medals: 32



« Reply #9 - Posted 2009-03-04 06:25:54 »

Even if AMD does have an efficient design, it doesnt help much since they do not provide GLSL support for geometric shaders in their OpenGL driver.
Those goddamn sons of bitches!

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline harishd

Senior Newbie





« Reply #10 - Posted 2009-03-06 08:08:53 »

Does any one know how i can debug a shader program? I heard gDebugger supports shader debugging, but dont know how to run a java application for it. I was wondering if there is any Eclipse plugin for debugging shaders  Grin
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

rwatson462 (29 views)
2014-12-15 09:26:44

Mr.CodeIt (20 views)
2014-12-14 19:50:38

BurntPizza (42 views)
2014-12-09 22:41:13

BurntPizza (76 views)
2014-12-08 04:46:31

JscottyBieshaar (37 views)
2014-12-05 12:39:02

SHC (50 views)
2014-12-03 16:27:13

CopyableCougar4 (47 views)
2014-11-29 21:32:03

toopeicgaming1999 (114 views)
2014-11-26 15:22:04

toopeicgaming1999 (102 views)
2014-11-26 15:20:36

toopeicgaming1999 (30 views)
2014-11-26 15:20:08
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!