Question about Fragment Programs

Started by MortusNegati, April 02, 2011, 09:43:39

Previous topic - Next topic

MortusNegati

I was just wondering if it was possible to use shaders using only the ARBFragmentProgram class and not ARBShaderObjects. I read the wonderful tutorial at http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL, but unfortunately I do not have support for Shader Objects. Although they are different systems, I managed to get shaders working on this computer using DirectX so I was hoping I could also get them to work in OpenGL.

I found that I do have the extensions for ARBVertexProgram and ARBFragmentProgram and was able to create compiled instances of both of these, (IE I created both using LWJGL commands without errors and they both return true with ARBVertexProgram.glIsProgramARB) but I can not figure out how to apply them to an object. I saw that GL20 has a useProgram method but I don't have support for that either.

I tried using ARBProgram.glBindProgramARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, glShaderID); to apply them to an object but it didn't do squat. I checked some other tutorials and found, to my embarrassment, that I did not have ARBVertexProgram or ARBFragmentProgram enabled. So I enabled them and ran into a different problem, nothing rendered at all. I am using the shaders from the tutorial linked above, which, I assume, should work.

With a little experimentation I found that enabling ARBVertexProgram does not affect the program, everything still draws. However, enabling ARBFragmentProgram and then immediately disabling the line after causes everything to disappear and stay that way. I am confused because these should be perfectly inverse functions right?

Am I just unable to use shaders and I should except that or is there something I'm missing with ARBFragmentPrograms? Is there another way? I have OpenGL 1.2 on my graphics card, is that version too old to support shading of any kind? Please help me out.

Here is the code I'm using to create shaders and hopefully apply them but I'm not sure that part works:

package easyOpenGL;

import java.io.BufferedReader;
import java.io.FileReader;

import org.lwjgl.opengl.ARBFragmentProgram;
import org.lwjgl.opengl.ARBProgram;
import org.lwjgl.opengl.ARBVertexProgram;
import org.lwjgl.opengl.GL11;

public class Shader {
	
	private static boolean shadersSupported;
	static {
		shadersSupported = OpenGL.extensionExists("GL_ARB_vertex_program") || OpenGL.extensionExists("GL_ARB_fragment_program");
	}

	public static enum ShaderType {
		Vertex, Fragment;
	}
	
	final boolean compiled;
	final ShaderType shaderType;
	final int glShaderID;
	
	public Shader(ShaderType type, String filename) {
		this.shaderType = type;
		
		if(type == ShaderType.Vertex && OpenGL.extensionExists("GL_ARB_vertex_program")) {
			GL11.glEnable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
			
			//Make Shader
			glShaderID = ARBVertexProgram.glGenProgramsARB();
			
			if(glShaderID == 0) {
				compiled = false; 
				return;
			}
			
			//Load shader code
			String code = "";
			String line = "";
			try {
				BufferedReader reader = new BufferedReader(new FileReader(filename));
				while((line = reader.readLine()) != null) {
					code += line + "\n";
				}
			} catch(Exception e) {
				System.err.println("Failed to read shader code from "+filename+".");
				compiled = false;
				return;
			}
			
			//Attempt to compile
			ARBVertexProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, glShaderID);
			ARBVertexProgram.glProgramStringARB(glShaderID, ARBProgram.GL_PROGRAM_FORMAT_ASCII_ARB, code);
			if(!ARBVertexProgram.glIsProgramARB(glShaderID)) {
				compiled = false;
				return;
			}
			
			System.out.println("Vertex Program Created: " + glShaderID);
			System.out.println("Errors in creation: "+GL11.glGetString(ARBVertexProgram.GL_PROGRAM_ERROR_STRING_ARB));
			compiled = true;

			GL11.glDisable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
			
		} else if(type == ShaderType.Fragment && OpenGL.extensionExists("GL_ARB_fragment_program")) {
			GL11.glEnable(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB);
			
			//Make Shader
			glShaderID = ARBFragmentProgram.glGenProgramsARB();
			
			if(glShaderID == 0) {
				compiled = false; 
				return;
			}
			
			//Load shader code
			String code = "";
			String line = "";
			try {
				BufferedReader reader = new BufferedReader(new FileReader(filename));
				while((line = reader.readLine()) != null) {
					code += line + "\n";
				}
			} catch(Exception e) {
				System.err.println("Failed to read shader code from "+filename+".");
				compiled = false;
				return;
			}
			
			//Attempt to compile
			ARBFragmentProgram.glBindProgramARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, glShaderID);
			ARBFragmentProgram.glProgramStringARB(glShaderID, ARBProgram.GL_PROGRAM_FORMAT_ASCII_ARB, code);
			if(!ARBFragmentProgram.glIsProgramARB(glShaderID)) {
				compiled = false;
				return;
			}

			System.out.println("Fragment Program Created: " + glShaderID);
			System.out.println("Errors in creation: "+GL11.glGetString(ARBFragmentProgram.GL_PROGRAM_ERROR_STRING_ARB));
			compiled = true;

			GL11.glDisable(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB);
		} else {
			glShaderID = 0;
			compiled = false;
		}
	}
	
	public void bind() {
		if(compiled) {
			if(shaderType == ShaderType.Fragment) {
				//GL11.glEnable(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB);
				ARBFragmentProgram.glBindProgramARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, glShaderID);
			}
			if(shaderType == ShaderType.Vertex) {
				//GL11.glEnable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
				ARBVertexProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, glShaderID);
			}
		}
	}
	
	public void unbind() {
		if(compiled) {
			if(shaderType == ShaderType.Fragment) {
				ARBFragmentProgram.glBindProgramARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, 0);
				//GL11.glDisable(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB);
			}
			if(shaderType == ShaderType.Vertex) {
				ARBVertexProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, 0);
				//GL11.glDisable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
			}
		}
	}
	
	public void destroy() {	
		if(shaderType == ShaderType.Fragment) {
			ARBFragmentProgram.glDeleteProgramsARB(glShaderID);
		}
		if(shaderType == ShaderType.Vertex) {
			ARBVertexProgram.glDeleteProgramsARB(glShaderID);
		}
	}
	
}


both of the objects that my main method constructs make it to the end of their initialization and print

Fragment Program Created: 1
Errors in creation: 
Fragment Program Created: 2
Errors in creation:


which I assume means they worked, however my method of binding them has no effect and enable frgment programs actually destroy what I do have working. I'm thoroughly confused.  ???

If I'm being dumb, please let me know, If I'm not, does anybody know if it is possible for me to get fragment programs to work? Thanks in advance for any advice/responses and thanks presently for taking the time to read this whole post, I know it's long  :P

MortusNegati

It's been a long time since I posted this and I just got an email saying someone responded... Since I don't see this response I figured I'd answer my own question in case people wanted to know how shaders work in LWJGL.

A shader program is made up of a vertex shader and a fragment shader

First make a vertex shader:
     int vertexShader = GL20.glCreateShader(GL20.GL_VERTEX_SHADER)      
     GL20.glShaderSource(this.shaderID, source); //Source is the source code for the shader
     GL20.glCompileShader(this.shaderID);
     String status = GL20.glGetShaderInfoLog(this.shaderID, 1000); //This returns any error or debugging info you need

Then make a fragement shader: (same method except with GL_FRAGMENT_SHADER)

Then combine the two in a shader program:
     int shaderProgram = GL20.glCreateProgram();
     GL20.glAttachShader(shaderProgram, vertexShader);
     GL20.glAttachShader(shaderProgram, fragmentShader);
     GL20.glLinkProgram(shaderProgram); //links the compiled shaders
     String status = GL20.glGetProgramInfoLog(shaderProgram, GL20.GL_LINK_STATUS); //Check the status to see if it worked
And then bind it whenever with:
     GL20.glUseProgram(shaderProgram);

That should do it, you need to have the proper GL Extensions for this to work:
GL_ARB_VERTEX_PROGRAM, GL_ARB_VERTEX_SHADER, GL_ARB_FRAGMENT_PROGRAM, and GL_ARB_FRAGMENT_SHADER

I think that's it, I hope this helps someone!   ;)