So, I'm trying to learn how to use shaders, but the tutorial on the wiki (
http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL) is not working for me.
First off, the code, when copy-pasted, was wrong.

Pretty badly so. Aside from a typo that actually meant the code had compile errors, the main class didn't even access the class that ran the shaders. Did whoever wrote this tutorial even test-run the code? It really should get fixed.
Secondly, when I fixed those problems (had the main class create an instance of the Box class and use it, fixed the typo), the shaders I created with copy and paste didn't work. Both the vertex and the fragment shaders didn't process past printLogInfo(); the returned value for the log length was 0 in both cases. I also checked that the files were being read appropriately; they were.
Since I really don't have a very good idea of how to work with shaders, the fact that this tutorial is broken is very detrimental to my ability to figure out what's going on.
Here's the code I'm using (it has been very slightly modified from the code on the wiki):
Main.java:import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.util.glu.GLU;
/*
* Sets up the Display, the GL context, and runs the main game
loop.
*
* @author Stephen Jones
*/
public class Main {
private boolean done = false; // game runs until done is set to true
private Box box;
public Main() {
init();
while (!done) {
if (Display.isCloseRequested())
done = true;
render();
Display.update();
}
Display.destroy();
}
private void render() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glLoadIdentity();
box.draw();
}
private void init() {
int w = 1024;
int h = 768;
try {
Display.setDisplayMode(new DisplayMode(w, h));
Display.setVSyncEnabled(true);
Display.setTitle("Shader Setup");
Display.create();
} catch (Exception e) {
System.out.println("Error setting up display");
System.exit(0);
}
GL11.glViewport(0, 0, w, h);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluPerspective(45.0f, ((float) w / (float) h), 0.1f, 100.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL11.glClearDepth(1.0f);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LEQUAL);
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
box = new Box();
}
public static void main(String[] args) {
EngineDirectory.init();
LWJGLNatives.load();
new Main();
}
}
Box.javaimport org.lwjgl.opengl.GL11;
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.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.ARBFragmentShader;
/**
* The vertex and fragment shaders are setup when the box object is constructed.
* They are applied to the GL state prior to the box being drawn, and released
* from that state after drawing.
*
* @author Stephen Jones
*/
public class Box {
/*
* if the shaders are setup ok we can use shaders, otherwise we just use
* default settings
*/
private boolean useShader = true;
/*
* program shader, to which is attached a vertex and fragment shaders. They
* are set to 0 as a check because GL will assign unique int values to each
*/
private int shader = 0;
private int vertShader = 0;
private int fragShader = 0;
public Box() {
/*
* create the shader program. If OK, create vertex and fragment shaders
*/
shader = ARBShaderObjects.glCreateProgramObjectARB();
if (shader != 0) {
vertShader = createVertShader("shaders/screen.vert");
fragShader = createFragShader("shaders/screen.frag");
} else
useShader = false;
/*
* if the vertex and fragment shaders setup sucessfully, attach them to
* the shader program, link the sahder program (into the GL context I
* suppose), and validate
*/
if (vertShader != 0 && fragShader != 0) {
ARBShaderObjects.glAttachObjectARB(shader, vertShader);
ARBShaderObjects.glAttachObjectARB(shader, fragShader);
ARBShaderObjects.glLinkProgramARB(shader);
ARBShaderObjects.glValidateProgramARB(shader);
useShader = printLogInfo(shader);
} else
useShader = false;
}
/*
* If the shader was setup succesfully, we use the shader. Otherwise we run
* normal drawing code.
*/
public void draw() {
if (useShader) {
ARBShaderObjects.glUseProgramObjectARB(shader);
}
GL11.glLoadIdentity();
GL11.glTranslatef(0.0f, 0.0f, -10.0f);
GL11.glColor3f(1.0f, 1.0f, 1.0f);// white
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex3f(-1.0f, 1.0f, 0.0f);
GL11.glVertex3f(1.0f, 1.0f, 0.0f);
GL11.glVertex3f(1.0f, -1.0f, 0.0f);
GL11.glVertex3f(-1.0f, -1.0f, 0.0f);
GL11.glEnd();
// release the shader
ARBShaderObjects.glUseProgramObjectARB(0);
}
/*
* With the exception of syntax, setting up vertex and fragment shaders is
* the same.
*
* @param the name and path to the vertex shader
*/
private int createVertShader(String filename) {
// vertShader will be non zero if successfully created
vertShader = ARBShaderObjects
.glCreateShaderObjectARB(ARBVertexShader.GL_VERTEX_SHADER_ARB);
// if created, convert the vertex shader code to a String
if (vertShader == 0) {
return 0;
}
String vertexCode = "";
String line;
try {
BufferedReader reader = new BufferedReader(new FileReader(new File(
Box.class.getClassLoader().getResource(filename).toURI())));
while ((line = reader.readLine()) != null) {
vertexCode += line + "\n";
}
} catch (Exception e) {
System.out.println("Fail reading vertex shading code");
return 0;
}
/*
* associate the vertex code String with the created vertex shader and
* compile
*/
ARBShaderObjects.glShaderSourceARB(vertShader, vertexCode);
ARBShaderObjects.glCompileShaderARB(vertShader);
// if there was a problem compiling, reset vertShader to zero
if (!printLogInfo(vertShader)) {
vertShader = 0;
}
// if zero we won't be using the shader
return vertShader;
}
// same as per the vertex shader except for method syntax
private int createFragShader(String filename) {
fragShader = ARBShaderObjects
.glCreateShaderObjectARB(ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);
if (fragShader == 0) {
return 0;
}
String fragCode = "";
String line;
try {
BufferedReader reader = new BufferedReader(new FileReader(new File(
Box.class.getClassLoader().getResource(filename).toURI())));
while ((line = reader.readLine()) != null) {
fragCode += line + "\n";
}
} catch (Exception e) {
System.out.println("Fail reading fragment shading code");
return 0;
}
ARBShaderObjects.glShaderSourceARB(fragShader, fragCode);
ARBShaderObjects.glCompileShaderARB(fragShader);
if (!printLogInfo(fragShader)) {
fragShader = 0;
}
return fragShader;
}
/*
* oddly enough, checking the success when setting up the shaders is verbose
* upon success. If the reference iVal becomes greater than 1, the setup
* being examined (obj) has been successful, the information gets printed to
* System.out, and true is returned.
*/
private static boolean printLogInfo(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("Info log:\n" + out);
return true;
}
System.err.println("Error accessing shader log!");
return false;
}
}
screen.vertvarying vec4 vertColor;
void main(){
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
vertColor = vec4(0.6, 0.3, 0.4, 1.0);
}
screen.fragvarying vec4 vertColor;
void main(){
gl_FragColor = vertColor;
}
So, why aren't the shaders working? The syntax seems correct when I look at other examples, and I seem to be sending it to the graphics card appropriately.
And yes, my graphics card definitely supports shaders.
PS: Sorry if my tone is a little irritated; I've been banging my head against the wall on this one for a while.