"Hello World" Pixel Shader?

Started by dime, April 12, 2011, 06:00:16

Previous topic - Next topic

dime

I'm a newbie at this and was wondering if anyone had a "Hello World" type of tutorial for pixel shading.  Maybe setting every pixel from black to white or such.

I think I want to use GLSlang?

I found this, but it's incomplete: http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL
The Main doesn't even call Box, so doesn't do anything other than create a window.

dime

Here is an update to that wiki page.  It "runs" now and tad more verbose, but keeps failing.  That is, this glGetObjectParameterARB in the printLogInfo function always returns 0.  Thoughts?

IntBuffer iVal = BufferUtils.createIntBuffer(1);

		ARBShaderObjects.glGetObjectParameterARB(obj,
				ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB, iVal);



Main.java
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
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) {
		new Main();
	}
}


Box.java
import java.io.BufferedReader;
import java.io.FileReader;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.ARBFragmentShader;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.GL11;

/**
 * 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) {
			System.err
					.println("vertShader-> Failed creating shader in ARBShaderObjects.glCreateShaderObjectARB\n");
			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: " + filename);
			System.exit(0);
			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) {
			System.err
					.println("fragShader -> Failed creating shader in ARBShaderObjects.glCreateShaderObjectARB\n");
			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;
	}

	/*
	 * 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);
		} else {
			System.err.println("Error log: shader failed to load: " + obj);
			return false;
		}
		return true;
	}

}

dime


So, there is something wrong with the logic in this.
I comment out the "if (useShader)" parts and it works, even though the original author thinks it is "failing" to load.

ste3e

Hi Dime. I wrote the tutorial. The working version can be found at http://www.sjonesart.com/gl.php.