CyanPrime
CyanPrime

Reputation: 5193

GLSL LWJGL woes/Shaders do nothing?

Okay, so I'm trying to get the tutorial here to work: http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL

My question is why aren't my shaders doing anything in this example? I'm very new to GLSL.

here is the code for the main class

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 GLSLTest{

    Box box;
    private boolean done=false; //game runs until done is set to true

    public GLSLTest(){
        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){
        new GLSLTest();
    }
}

Here is the code for the Box class:

import org.lwjgl.opengl.GL11;
import java.io.BufferedReader;
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;
import org.lwjgl.opengl.Util;

/**
* 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("screen.vert");
            fragShader=createFragShader("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 succefully 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(filename));
            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(filename));
            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;
    }

    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);
        }
        else return true;
        return false;
    }

}

Here is the code for the fragment shader

varying vec4 vertColor;

void main(){
    gl_FragColor = vertColor;
}

and vertex shader:

varying vec4 vertColor;

void main(){
    gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
    vertColor = vec4(0.6, 0.3, 0.4, 1.0);
}

Here is the output I get when I run the code:

Info log:
Vertex shader was successfully compiled to run on hardware.
Info log:
Fragment shader was successfully compiled to run on hardware.

And here is a screenshot: http://dl.dropbox.com/u/28109593/glslss.png

Upvotes: 0

Views: 3395

Answers (2)

dardo
dardo

Reputation: 4970

The shaders are doing what they're supposed to do.

Don't think of shaders in the sense of what you hear in video games, shaders are simply a way of having direct access to the GPU.

The reason you're not seeing a difference in color is due to the fact that color is not being output, try changing what is being set in the fragment shader for gl_fragColor.

If you're looking for more information on shader driven opengl I'd suggest taking a look at the online book

Learning Modern 3D Graphics Programming

If you google that title, it should be the first result.

Hope this helps!

Upvotes: 0

Chuck Adams
Chuck Adams

Reputation: 777

The problem is due to the fact that you're seeing anything in the Info log at all, i.e. it's yielding a message on success, the way some OpenGL drivers are inclined to do. printLogInfo is also doubling as a validation function, and returning false if there was any log info, which is telling createVertShader and createFragShader to zero out your perfectly good shader id and return a failure. It's really not at all a good design, for reasons exactly like this (and I know it came from someone else, so I know I'm not slagging you off personally :)

A quick workaround for this program ONLY would be to simply make printLogInfo always return true. What you ultimately need to do is check the return status, using glGetShader(id, param), like so:

glCompileShader(obj)
if (glGetShader(obj, GL_COMPILE_STATUS) == GL_FALSE
    ... handle error here ...

Then for linking and validating:

glLinkProgram(obj)
if (glGetProgram(obj, GL_LINK_STATUS) == GL_FALSE
    ... handle error here ...

glValidateProgram(obj)
if (glGetProgram(obj, GL_VALIDATE_STATUS) == GL_FALSE
    ... handle error here ...

I don't know the ARB_* equivalents of these, sorry, but you probably should be using OpenGL 2.0 API instead of ARB extensions for something this basic. Anything that still only supports shaders as an extension is probably not worth doing shaders on anyway.

Upvotes: 3

Related Questions