Posted by
xghost on
Jul 23, 2014; 11:24am
URL: https://forum.jogamp.org/Need-Help-Solving-OpenGL-GLSL-4-4-Issues-tp4032557p4032640.html
jmaasing wrote
Vacation today so I had some time to test your code :-)
Thanks. I appreciate it :)
jmaasing wrote
I haven't fixed it yet but there are two problems I saw right away, if you add
public void init(GLAutoDrawable drawable) {
drawable.setGL(new DebugGL4((GL4) drawable.getGL()));
GL4 gl = (GL4) drawable.getGL();
You will see that OpenGL complains about invalid operation (at least on my platform):
Exception in thread "main-AWTAnimator" java.lang.RuntimeException: javax.media.opengl.GLException: Thread[AWT-EventQueue-0,6,main] glGetError() returned the following error codes after a call to glGenVertexArrays(<int> 0x1, <[I>, <int> 0x0): GL_INVALID_OPERATION ( 1282 0x502),
I refactored my pixel-drawing demo. Some of the changes (will post in full at bottom) in init(...)
GL4 gl = (GL4) drawable.getGL();
drawable.setGL(new DebugGL4(gl));
I also used built-in ShaderCode and ShaderProgram classes and added a trailing 'f' for the floating-point values in the shader code as recommended.
Interestingly, I had initially checked for compilation/linking issues with GL_COMPILE_STATUS in glGetShaderiv and GL_LINK_STATUS in glGetProgramiv in a previous version of the code, and it was returning GL_TRUE with the original shader code, so it seemed to have ruled out shader code as the problem.
Now I'm using the built-in classes; the shaders compile successfully on their own and the program still links just fine as before. In fact, it is working normally now without a real explanation as to why this is the case --both color and position modifications show up as expected.
This is the case even if the original shaders where the literals do
not use the trailing 'f' are used, e.g.:
gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
The shaders were building before and they are building now. The only real difference is the Java code..
jmaasing wrote
Also, your shaders are not correct (on strict drivers they would not even compile I guess) since you use doubles when they should be floats, this is how it ought to be written:
gl_Position = vec4(0.0f, 0.0f, 0.5f, 1.0f);
I took a quick look at the GLSL 4 spec (
https://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf), but I didn't immediately notice anything that would suggest shaders being invalidated by simply omitting the trailing 'f' in them. (I could've missed it since I didn't read the entire document, only read through some portions that seemed relevant.) Therefore, it seems the shader code itself was not the real source of the problem AFAIK (at least not for GLSL 4.4 core under GNU/Linux).
Do you have a reference where it's mentioned that GLSL literals must be written as such and that something different would be invalid?
I'm not exactly sure about the 'strict drivers'. I'm speculating a bit here, but when drivers implement the OpenGL/GLSL specs, the spec is responsible for stating what the result should be, unless we're talking about undefined behaviour. If the shader code is invalid, then it would not compile as shown below after intentionally messing up the vertex shader:
Shader status invalid: 0(4) : error C0000: syntax error, unexpected '{', expecting "::" at token "{"
jmaasing wrote
If you look at the sample code I posted I use JOGL classes (ShaderProgram et c) to compile the shaders, they can help in presenting the compilation/linking errors.
I went through it again. It was very helpful, so thanks again.
jmaasing wrote
If you want to use glCompileShader straight up you really should check for GL errors after each step to verify that the shader compiled/linked.
I had done this, but I had not received errors for whatever reason. In fact, I'm still doing this in one of my other (broken) demos and this is how the error-checking code looks:
int vertexShader = gl.glCreateShader(GL4.GL_VERTEX_SHADER);
gl.glShaderSource(vertexShader, 1, vertexShaderSource, null);
gl.glCompileShader(vertexShader);
checkCompilationErrors(drawable);
gl.glGetShaderiv(vertexShader, GL4.GL_COMPILE_STATUS, compiledVertShaders, 0);
if(compiledVertShaders[0] == GL.GL_TRUE) {
System.out.println("ok");
} else {
System.out.println("failed");
printShaderLog(drawable, vertexShader);
}
with the shader source code in this one being:
---- vertex shader ----
#version 440 core
void main(void)
{
gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
}
---- fragment ----
#version 440 core
out vec4 color;
void main(void)
{
color = vec4(0.0, 0.8, 1.0, 1.0);
}
and the 'checkCompilationErrors method being:
private boolean checkCompilationErrors(GLAutoDrawable drawable) {
GL4 gl = (GL4) drawable.getGL();
boolean foundError = false;
int glErr = gl.glGetError();
while (glErr != GL.GL_NO_ERROR) {
System.err.println("glError: " + glu.gluErrorString(glErr));
foundError = true;
glErr = gl.glGetError();
}
return foundError;
}
The console output below says that things are "ok"...
[info] Compiling vertex shader...ok
[info] Compiling fragment shader...ok
[info] GLSL source compilation status...ok
[info] Creating GLSL program...ok
But this demo (which I'll refactor later) still behaves incorrectly by displaying the black pixel, even though it shouldn't be black.
A quick look at some of the JOGL code for compiling/linking the shader code seemed quite similar to what I was doing (aside from the object's internal state management and debug stuff). So it does not really explain the difference in behaviour to me.
I'm still not sure what I was (or was not) doing that was causing a problem. This is especially true given the working samples I've looked at which suggest that what I tried to do
should've worked :(
jmaasing wrote
Note that there is a large difference in how "forgiving" drivers are with these kinds of errors, maybe your driver understands and compiles even though it strictly isn't correct. (another disclaimer; I'm stuck on Mac OpenGL 4.1 so maybe these things have changed in later versions).
That's an interesting note, though I tried 2 different drivers under 2 different OSes (GNU/Linux and (reluctantly) Windows 7). If it's true that a driver might be more 'forgiving' (which could be the case but would seem odd, given that they must adhere to the spec for compliance), then perhaps it's more of a vendor-specific (e.g. AMD vs NVIDIA) rather than a driver-specific detail(?)
I'm also not sure if the differences are due to GL 4.1 vs 4.4 updates or not. The last time I had used OpenGL was version 2.0 several years ago in C++ with the fixed pipeline, so I wouldn't know :)
jmaasing wrote
gouessej wrote
Yes, he should call glGetShaderInfoLog after compiling and glGetProgramInfoLog after linking, am I wrong?
Yeah, and also
"Each shader object has a boolean status, COMPILE_STATUS, that is modified as a result of compilation. This status can be queried with GetShaderiv"
Or simply use the very convenient JOGL classes

Yup, been there, done that :)
Not feeling closer to a root cause analysis (RCA) here :(
[EDIT1: Meme seemed fitting]
[EDIT2: Reduced meme image size]

I will start refactoring some of the other demos and report my findings as I make progress. Perhaps the reason for the issues will become apparent later (I hope). If you have any additional comments/suggestions, I'd appreciate them.
-------- Refactored/Working Demo3 Code for Simple Centered Pixel --------
/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ray.cg.demos.demo3;
import java.nio.FloatBuffer;
import javax.media.opengl.DebugGL4;
import javax.media.opengl.GL4;
import javax.media.opengl.GLAutoDrawable;
import ray.cg.lib.DemoFrame;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
public class Demo3 extends DemoFrame {
private static final long serialVersionUID = 1L;
private final Animator animator;
private int program;
private final int[] vertexArray;
public Demo3() {
super("Demo3: Ch2 Pg18");
super.initOpenGL();
setVisible(true);
vertexArray = new int[1];
animator = new Animator(canvas);
animator.start();
}
@Override
public void init(GLAutoDrawable drawable) {
GL4 gl = (GL4) drawable.getGL();
drawable.setGL(new DebugGL4(gl));
program = createProgram(gl);
gl.glGenVertexArrays(vertexArray.length, vertexArray, 0);
gl.glBindVertexArray(vertexArray[0]);
}
@Override
public void display(GLAutoDrawable drawable) {
GL4 gl = (GL4) drawable.getGL();
FloatBuffer color = FloatBuffer.allocate(4);
color.put(0, (float) (Math.sin(System.currentTimeMillis()/100.0)*0.5 + 0.5));
color.put(1, (float) (Math.cos(System.currentTimeMillis()/100.0)*0.5 + 0.5));
color.put(2, 0.0f);
color.put(3, 1.0f);
gl.glClearBufferfv(GL4.GL_COLOR, 0, color);
gl.glUseProgram(program);
gl.glPointSize(60.0f);
gl.glDrawArrays(GL4.GL_POINTS, 0, 1);
}
private int createProgram(GL4 gl) {
String vertexShaderSource =
"#version 440 core \n" +
" \n" +
"void main(void) \n" +
"{ \n" +
" gl_Position = vec4(0.0f, 0.0f, 0.5f, 1.0f);\n" +
"} \n";
String fragmentShaderSource =
"#version 440 core \n" +
" \n" +
"out vec4 color; \n" +
" \n" +
"void main(void) \n" +
"{ \n" +
" color = vec4(1.0f, 1.0f, 1.0f, 1.0f); \n" +
"} \n";
String[][] sources = new String[1][1];
sources[0] = new String[]{ vertexShaderSource };
ShaderCode vertexShaderCode = new ShaderCode(GL4.GL_VERTEX_SHADER, sources.length, sources);
boolean compiled = vertexShaderCode.compile(gl, System.err);
if (!compiled)
System.err.println("[error] Unable to compile vertex shader: " + sources);
sources[0] = new String[]{ fragmentShaderSource };
ShaderCode fragmentShaderCode = new ShaderCode(GL4.GL_FRAGMENT_SHADER, sources.length, sources);
compiled = fragmentShaderCode.compile(gl, System.err);
if (!compiled)
System.err.println("[error] Unable to compile fragment shader: " + sources);
ShaderProgram program = new ShaderProgram();
program.init(gl);
program.add(vertexShaderCode);
program.add(fragmentShaderCode);
program.link(gl, System.out);
if(!program.validateProgram(gl, System.out))
System.err.println("[error] Unable to link program");
return program.program();
}
@Override
public void dispose(GLAutoDrawable drawable) {
GL4 gl = (GL4) drawable.getGL();
animator.stop();
gl.glDeleteVertexArrays(vertexArray.length, vertexArray, 0);
gl.glDeleteProgram(program);
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width,
int height) {
GL4 gl = (GL4) drawable.getGL();
gl.glViewport(x, y, width, height);
}
public static void main(String[] args) {
new Demo3();
}
}