/* Copyright 2010-2011 Christian Matt
*
* This file is part of PonkOut.
*
* PonkOut is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PonkOut is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PonkOut. If not, see <http://www.gnu.org/licenses/>.
*/
package ponkOut.graphics.resources;
import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.ARBFragmentProgram;
import org.lwjgl.opengl.ARBProgram;
import org.lwjgl.opengl.ARBVertexProgram;
import org.lwjgl.opengl.GL11;
/**
* Contains a shader loaded from a file. Shaders are written in GLSL, but since
* some old GPUs do not support loading shader code, they are compiled using
* NVIDIA's Cg Toolkit to ARB programs.
*/
public class Shader {
private int id;
/** type of the shader; it can be a vertex shader or a fragment shader */
private int type;
/**
* @param filename
* name of the resource file containing the shader program
* @param type
* ARBVertexProgram.GL_VERTEX_PROGRAM_ARB or
* ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB
*/
protected Shader(String filename, int type) {
if (type != ARBVertexProgram.GL_VERTEX_PROGRAM_ARB && type != ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB)
throw new IllegalArgumentException("type must be either GL_VERTEX_PROGRAM_ARB or GL_FRAGMENT_PROGRAM_ARB");
this.type = type;
IntBuffer idBuffer = BufferUtils.createIntBuffer(1);
GL11.glEnable(type);
ARBProgram.glGenProgramsARB(idBuffer);
id = idBuffer.get(0);
ARBProgram.glBindProgramARB(type, id);
ARBProgram.glProgramStringARB(type, ARBProgram.GL_PROGRAM_FORMAT_ASCII_ARB, loadProgram(filename));
System.out.println(GL11.glGetString(ARBProgram.GL_PROGRAM_ERROR_STRING_ARB));
GL11.glDisable(type);
}
/**
* Enables the shader. Note that only one shader for each type can be
* enabled at the same time.
*/
public void enable() {
GL11.glEnable(type);
ARBProgram.glBindProgramARB(type, id);
}
/**
* Disables the shader reverting to fixed function pipeline.
*/
public void disable() {
GL11.glDisable(type);
}
public static void setTangent(float x, float y, float z) {
ARBVertexProgram.glVertexAttrib3fARB(1, x, y, z);
}
public static void setBinormal(float x, float y, float z) {
ARBVertexProgram.glVertexAttrib3fARB(3, x, y, z);
}
/**
* @param filename
* name of the resource file containing the program to load
* @return ByteBuffer containing the program
*/
protected static ByteBuffer loadProgram(String filename) {
DataInputStream dis = new DataInputStream(Thread.currentThread().getContextClassLoader()
.getResourceAsStream("shaders/" + filename));
byte[] program = null;
try {
program = new byte[dis.available()];
dis.readFully(program);
dis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ByteBuffer programBuffer = BufferUtils.createByteBuffer(program.length);
programBuffer.put(program).flip();
return programBuffer;
}
}