Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (580)
games submitted by our members
Games in WIP (500)
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  
  releasing shaders after glEnd doesn't apply the shader?  (Read 1347 times)
0 Members and 1 Guest are viewing this topic.
Offline Tommassino

Senior Newbie





« Posted 2012-04-04 13:55:41 »

Hey,
I found out some strange behaviour, shaders in my code work kind of wierd when you release them with ARBShaderObjects.glUseProgramObjectARB(0). In the example below after 2k ticks it starts releasing the shader in the render cycle, and as that happens, it wont apply the shaders at all even retroactively on the quad that already has been glEnded(in this case, no image is drawn on the quad). This is kind of wierd considering releasing after glEnd is suggested in most shader guides (e.g. http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL).

What is even more interesting but isnt demonstrated in my code here is, when i draw multiple objects with shaders and dont ever release them with ARBShaderObjects.glUseProgramObjectARB(0), just bind them, it works all good.

So, what exactly does ARBShaderObjects.glUseProgramObjectARB(0) do? Do I use it correctly? What causes this strange behaviour?

The first class is the main class that runs everything. Then I have a few utility classes that i wont post here (ShaderLoader,ImageLoader, I think you know what they do). The second class is the Shader class which is capable of loading and compiling the Shader, and some utility methods for setting up the shader and binding 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  
package cz.witzany.gamev2.twlgui;

import static org.lwjgl.opengl.GL11.*;

import java.awt.Rectangle;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

import cz.witzany.gamev2.graphics.shaders.Shader;
import cz.witzany.gamev2.graphics.shaders.ShaderLoader;
import cz.witzany.gamev2.graphics.shaders.SimpleImage;
import cz.witzany.gamev2.graphics.utils.ImageLoader;

public class TestCase implements Runnable {
   int texture;
   Shader shader;
   int timeout = 0;

   public static void main(String[] args) {
      new TestCase().run();
   }

   @Override
   public void run() {
      initGL();
      initObjects();

      while (!Display.isCloseRequested()) {
         glClear(GL11.GL_COLOR_BUFFER_BIT);

         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
         glOrtho(-400, 400, -300, 300, 10, -10);
         glMatrixMode(GL_MODELVIEW);
         glLoadIdentity();
         
         shader.bind();
         shader.setTexture("colorMap", 0, texture);
         shader.setUniformF("tx", 1/90.0f);
         shader.setUniformF("ty", 1/90.0f);
         shader.setUniformF("meshScale", 1.0f);

         glScaled(90, -90, 1);
         glBegin(GL11.GL_QUADS);
         glTexCoord2f(0, 0);
         glVertex2d(0, 0);
         glTexCoord2f(1, 0);
         glVertex2d(1, 0);
         glTexCoord2f(1, 1);
         glVertex2d(1, 1);
         glTexCoord2f(0, 1);
         glVertex2d(0, 1);
         glEnd();
         
         if(timeout > 2000)
            shader.unbind();
         timeout++;
         
         Display.update();
      }
   }

   private void initObjects() {
      shader = ShaderLoader.loadShader("Data/Shaders/Sprite");
      texture = ImageLoader.loadImage("Data/Textures/Sprites/Creeper/Creeper.png", new Rectangle());
   }

   private void initGL() {
      try {
         Display.setDisplayMode(new DisplayMode(800, 600));
         Display.create();
      } catch (LWJGLException e) {
         e.printStackTrace();
         System.exit(0);
      }

      glShadeModel(GL_SMOOTH);
      glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT
            | GL_STENCIL_BUFFER_BIT);
      glDepthRange(1.0f, 0.0f);
      glAlphaFunc(GL_GREATER, 0x00);
      glDepthFunc(GL_GREATER);
      glStencilFunc(GL_NEVER, 0x0, 0xFFFFFFFF);
      glBlendFunc(GL_ZERO, GL_SRC_COLOR);

      GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());
   }
}




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  
package cz.witzany.gamev2.graphics.shaders;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.ARBFragmentShader;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;

public class Shader {
   private static int activeShader = -1;
   public int shader;
   public int vertShader;
   public int fragShader;
   private boolean useShader;

   public Shader(String shaderDir) {
      File sDir = new File(shaderDir);
      useShader = true;
      if (!sDir.exists() || !sDir.isDirectory()) {
         useShader = false;
         return;
      }
      File vShader = new File(sDir, sDir.getName() + ".vert");
      File fShader = new File(sDir, sDir.getName() + ".frag");
      if (!vShader.exists() || !fShader.exists()) {
         useShader = false;
         return;
      }
      shader = ARBShaderObjects.glCreateProgramObjectARB();
      if (shader == 0) {
         useShader = false;
         return;
      }
      vertShader = createShader(vShader.getAbsolutePath(),
            ARBVertexShader.GL_VERTEX_SHADER_ARB);
      fragShader = createShader(fShader.getAbsolutePath(),
            ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);
      if (vertShader == 0 || fragShader == 0) {
         useShader = false;
         return;
      }
      ARBShaderObjects.glAttachObjectARB(shader, vertShader);
      ARBShaderObjects.glAttachObjectARB(shader, fragShader);
      ARBShaderObjects.glLinkProgramARB(shader);

      if (GL20.glGetShader(shader, GL20.GL_LINK_STATUS) == GL11.GL_FALSE) {
         printLogInfo(shaderDir, shader);
         useShader = false;
         return;
      }

      ARBShaderObjects.glValidateProgramARB(shader);

      if (GL20.glGetShader(shader, GL20.GL_VALIDATE_STATUS) == GL11.GL_FALSE) {
         printLogInfo(shaderDir, shader);
         useShader = false;
         return;
      }
      useShader = true;
      System.out.println("Loaded shader " + shaderDir);
   }

   private int createShader(String filename, int type) {
      int nshader = ARBShaderObjects.glCreateShaderObjectARB(type);
      if (nshader == 0) {
         return 0;
      }
      String code = "";
      String line;
      try {
         BufferedReader reader = new BufferedReader(new FileReader(filename));
         while ((line = reader.readLine()) != null) {
            code += line + "\n";
         }
         reader.close();
      } catch (Exception e) {
         System.out.println("Fail reading vertex shading code");
         return 0;
      }
      ARBShaderObjects.glShaderSourceARB(nshader, code);
      ARBShaderObjects.glCompileShaderARB(nshader);
      printLogInfo(filename, nshader);

      if (GL20.glGetShader(nshader, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE)
         return 0;
      return nshader;
   }

   private boolean printLogInfo(String name, int obj) {
      IntBuffer iVal = BufferUtils.createIntBuffer(1);
      ARBShaderObjects.glGetObjectParameterARB(obj,
            ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB, iVal);

      int length = iVal.get();
      if (length > 1) {
         // We have some info we need to output.
        ByteBuffer infoLog = BufferUtils.createByteBuffer(length);
         iVal.flip();
         ARBShaderObjects.glGetInfoLogARB(obj, iVal, infoLog);
         byte[] infoBytes = new byte[length];
         infoLog.get(infoBytes);
         String out = new String(infoBytes);
         System.out.println(name + " log:\n" + out);
      }
      return true;
   }

   private int getUniformLocation(String name) {
      int location = ARBShaderObjects.glGetUniformLocationARB(shader, name);
      if (location == -1)
         throw new RuntimeException(name + " not available");
      return location;
   }

   public void setTexture(String name, int index, int pointer) {
      int location = getUniformLocation(name);
      GL13.glActiveTexture(GL13.GL_TEXTURE0 + index);
      GL11.glBindTexture(GL11.GL_TEXTURE_2D, pointer);
      ARBShaderObjects.glUniform1iARB(location, index);
   }

   public synchronized void bind() {
      if (activeShader == shader)
         return;
      if (useShader) {
         //unbind();
        ARBShaderObjects.glUseProgramObjectARB(shader);
         activeShader = shader;
      } else
         System.out.println("warning, shader not used");
   }

   public void unbind() {
      ARBShaderObjects.glUseProgramObjectARB(0);
   }
   
   public void setUniformF(String name, Float value){
      int location = getUniformLocation(name);
      ARBShaderObjects.glUniform1fARB(location, value);
   }
}
Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #1 - Posted 2012-04-04 14:28:33 »

This looks suspicious:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public synchronized void bind() {
      if (activeShader == shader)
         return;
      if (useShader) {
         //unbind();
        ARBShaderObjects.glUseProgramObjectARB(shader);
         activeShader = shader;
      } else
         System.out.println("warning, shader not used");
   }

   public void unbind() {
      ARBShaderObjects.glUseProgramObjectARB(0);
   }


Your 'bind' attempts to not re-bind if the shader is already set, but your 'unbind' doesn't update activeShader. You probably want to update activeShader to -1 in unbind (or use 0, since that indicates 'fixed function shader'). And define a constant for it while you're at it.

It may be worth taking out your early-exit from bind() while you're testing things, since it *should* work the same without it.

Also it might be a good idea to throw an exception here rather than just fail silently:
1  
2  
3  
4  
5  
 shader = ARBShaderObjects.glCreateProgramObjectARB();
      if (shader == 0) {
         useShader = false;
         return;
      }

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline Tommassino

Senior Newbie





« Reply #2 - Posted 2012-04-04 15:02:19 »

Haha, great, that was it. Now i feel stupid, thank you very much sir xD
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline davedes
« Reply #3 - Posted 2012-04-04 16:37:53 »

You should be consistent with entry points -- right now you're using GL20.glGetShader alongside ARBShaderObjects. And you should probably not rely on File objects if you plan to package your game in a JAR.

You might be able to get some inspiration from Slick's ShaderProgram. Especially in regards to file reading, error checking, etc.
ShaderProgram
ShaderTest

(you're free to use part of the class or even the whole thing within your project -- see license)

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.

xsi3rr4x (51 views)
2014-04-15 18:08:23

BurntPizza (48 views)
2014-04-15 03:46:01

UprightPath (63 views)
2014-04-14 17:39:50

UprightPath (45 views)
2014-04-14 17:35:47

Porlus (62 views)
2014-04-14 15:48:38

tom_mai78101 (86 views)
2014-04-10 04:04:31

BurntPizza (146 views)
2014-04-08 23:06:04

tom_mai78101 (243 views)
2014-04-05 13:34:39

trollwarrior1 (202 views)
2014-04-04 12:06:45

CJLetsGame (209 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
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!