Hi Folks,
I am trying to make a very simple GLSL program. Attached is the current version. Note that the shader string fragments are at the very bottom. After tediously following the instructions in the Orange Book, I would expect to see a spinning red square. Instead, I get a spinning white square. The only function of importance should be GLEventListener.init(), starting on line 157.
Can you all run the program and do something for me:
- Tell me what color your square is.
- Give me any advice you have on what could be going wrong if you also get a white square.
As far as program logic goes, the fragment shader should just make the fragment red. As a sanity check, I tried putting all vertices at (0,0,0) but it looks like the fixed function pipeline still rules.
Thanks!
/*
* Created on Dec 7, 2004
*/
import javax.swing.JFrame;
import net.java.games.jogl.*;
import net.java.games.jogl.GLDrawable;
/**
* @author Mark Bastian (shaddam_IV on JOGL message boards)
*
*/
public class TheSimplestVertexShader extends JFrame
{
public TheSimplestVertexShader()
{
super("The Simplest Bare-Bones Shader Ever!");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
initialize();
}
private static int loadShader(GL gl, String[] shaders, int shaderType)
{
//Following the steps in the orange book...
//1. Create an empty shader object
int shader = gl.glCreateShaderObjectARB(shaderType);
//Sanity checks
assert shader != 0; assert 0 == gl.glGetError();
//Create an array consisting of shader lengths
int[] lengths = new int[shaders.length];
for(int i = 0; i < shaders.length; i++) lengths[i] = shaders[i].length();
//2. Provide shader source code
//Everything is simply copied over. There is not compiling and such done at
//this time. Resources may be freed or modified after the call is made since
//a copy is performed.
gl.glShaderSourceARB(shader, shaders.length, shaders, lengths);
assert 0 == gl.glGetError();
//3. Compile the shader
gl.glCompileShaderARB(shader);
assert 0 == gl.glGetError();
validateShader(gl, shader);
return shader;
}
private static void validateShader(GL gl, int shader)
{
//3a. Check the status of compilation
int[] compileStatus = new int[1];
gl.glGetObjectParameterivARB(shader, GL.GL_OBJECT_COMPILE_STATUS_ARB, compileStatus);
if(compileStatus[0] == GL.GL_TRUE)
{
System.out.println("Shader compiled!");
}
else
{
System.out.println("Shader compilation failed! Log dump:");
int[] infologlength = new int[1];
byte[] infolog = new byte[1024];
gl.glGetInfoLogARB(shader, 1024, infologlength, infolog);
String logstr = new String(infolog);
System.out.println(logstr);
}
}
private static void loadProgram(GL gl, String[] vertexShaders, String[] fragmentShaders)
{
int vertexShader = loadShader(gl, vertexShaders, GL.GL_VERTEX_SHADER_ARB);
int fragmentShader = loadShader(gl, fragmentShaders, GL.GL_FRAGMENT_SHADER_ARB);
//4. Create the program object
//The object is initially empty, so you will need to link a shader to it.
int programObject = gl.glCreateProgramObjectARB();
assert 0 != programObject; assert 0 == gl.glGetError();
//5. Attach the shader object to the program. You can link as many shaders
//as you want to a program object. Once the linking is done, you no longer
//need the shader object.
gl.glAttachObjectARB(programObject, vertexShader);
gl.glAttachObjectARB(programObject, fragmentShader);
assert 0 == gl.glGetError();
//6. Link the program object.
gl.glLinkProgramARB(programObject);
//6a. Check the status of compilation
int[] linkStatus = new int[1];
gl.glGetObjectParameterivARB(programObject, GL.GL_OBJECT_LINK_STATUS_ARB, linkStatus);
assert 0 == gl.glGetError();
if(linkStatus[0] == GL.GL_TRUE)
{
System.out.println("Program linked!");
}
else
{
System.out.println("Linking failed! Log dump:");
int[] infologlength = new int[1];
byte[] infolog = new byte[1024];
gl.glGetInfoLogARB(programObject, 1024, infologlength, infolog);
String logstr = new String(infolog);
System.out.println(logstr);
System.exit(-1);
}
assert 0 == gl.glGetError();
//7. Install the program into the current state machine
gl.glUseProgramObjectARB(programObject);
assert 0 == gl.glGetError();
}
private void initialize()
{
GLCapabilities glcaps = new GLCapabilities();
GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(glcaps);
final Animator animator = new Animator(canvas);
canvas.addGLEventListener(new GLEventListener()
{
private float theta = 0.0f;
public void display(GLDrawable drawable)
{
GL gl = drawable.getGL();
assert 0 == gl.glGetError();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -5.0f);
gl.glRotatef(theta += 1.0f, 1.0f, 1.0f, 0.0f);
gl.glBegin(GL.GL_QUADS);
gl.glVertex3f(-1.0f, -1.0f, 0.0f);
gl.glVertex3f(+1.0f, -1.0f, 0.0f);
gl.glVertex3f(+1.0f, +1.0f, 0.0f);
gl.glVertex3f(-1.0f, +1.0f, 0.0f);
gl.glEnd();
assert 0 != gl.glGetHandleARB(GL.GL_PROGRAM_OBJECT_ARB);
}
public void displayChanged(GLDrawable arg0, boolean arg1, boolean arg2) {}
public void init(GLDrawable drawable)
{
String[] vertexShaders = {vs};
String[] fragmentShaders = {fs};
GL gl = drawable.getGL();
loadProgram(gl, vertexShaders, fragmentShaders);
}
public void reshape(GLDrawable drawable, int x, int y, int w, int h)
{
GL gl = drawable.getGL();
GLU glu = drawable.getGLU();
double aspect = (h != 0.0) ? (double)w / (double)h : 1.0;
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(60.0, aspect, 0.01, 10.0);
gl.glMatrixMode(GL.GL_MODELVIEW);
}
});
getContentPane().add(canvas);
show();
animator.start();
}
public static void main(String[] args)
{
new TheSimplestVertexShader();
}
private static String vs =
"//\n"+
"//The simplest vertex shader ever\n"+
"void main()\n"+
"{\n"+
" gl_Position = ftransform();\n" +
" //Sanity check: Smash everything to a point-doesn't work when enabled\n"+
" //gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"+
"}\n";
private static String fs =
"//\n"+
"//The simplest fragment shader ever\n" +
"//Just color the fragment red\n"+
"void main()\n"+
"{\n"+
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"+
"}\n";
}