package org.osm2world.core.target.jogl;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.imageio.ImageIO;
import javax.media.opengl.GL;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GL3;
/**
* Utility class to manage low level shader creation.
*/
public class ShaderManager {
/**
* Loads the vertex shader from a resource file, compiles it and does error checking.
* @param filename path to the resource containing the shader code
* @return handle of the created vertex shader
*/
public static int createVertexShader(GL3 gl, String filename) {
// get the unique id
int vertShader = gl.glCreateShader(GL3.GL_VERTEX_SHADER);
if (vertShader == 0)
throw new RuntimeException("Unable to create vertex shader.");
// create a single String array index to hold the shader code
String[] vertCode = new String[1];
vertCode[0] = "";
String line;
// open the file and read the contents into the String array.
InputStream stream = System.class.getResourceAsStream(filename);
if (stream == null) {
throw new RuntimeException("Vertex shader not found in classpath: \""+ filename +"\"");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
try {
while ((line = reader.readLine()) != null) {
vertCode[0] += line + "\n";
}
} catch (IOException e) {
throw new RuntimeException("Failed reading vertex shader \"" + filename + "\".",e);
}
// Associate the code string with the unique id
gl.glShaderSource(vertShader, 1, vertCode, null);
// compile the vertex shader
gl.glCompileShader(vertShader);
// acquire compilation status
IntBuffer shaderStatus = IntBuffer.allocate(1);
gl.glGetShaderiv(vertShader, GL3.GL_COMPILE_STATUS, shaderStatus);
// check whether compilation was successful
if (shaderStatus.get() == GL.GL_FALSE) {
printShaderInfoLog(gl, vertShader);
throw new IllegalStateException("compilation error for shader ["
+ filename + "].");
}
printShaderInfoLog(gl, vertShader);
// the int returned is now associated with the compiled shader
return vertShader;
}
/**
* Loads the fragment shader from a resource file, compiles it and does error checking.
* @param filename path to the resource containing the shader code
* @return handle of the created fragment shader
*/
public static int createFragmentShader(GL3 gl, String filename) {
int fragShader = gl.glCreateShader(GL3.GL_FRAGMENT_SHADER);
if (fragShader == 0)
return 0;
String[] fragCode = new String[1];
fragCode[0] = "";
String line;
InputStream stream = System.class.getResourceAsStream(filename);
if (stream == null) {
throw new RuntimeException("Fragment shader not found in classpath: \""+ filename +"\"");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
try {
while ((line = reader.readLine()) != null) {
fragCode[0] += line + "\n";
}
} catch (IOException e) {
throw new RuntimeException("Failed reading fragment shader \"" + filename + "\".",e);
}
gl.glShaderSource(fragShader, 1, fragCode, null);
gl.glCompileShader(fragShader);
// acquire compilation status
IntBuffer shaderStatus = IntBuffer.allocate(1);
gl.glGetShaderiv(fragShader, GL3.GL_COMPILE_STATUS, shaderStatus);
// check whether compilation was successful
if (shaderStatus.get() == GL.GL_FALSE) {
printShaderInfoLog(gl, fragShader);
throw new IllegalStateException("compilation error for shader ["
+ filename + "].");
}
printShaderInfoLog(gl, fragShader);
return fragShader;
}
/**
* Prints the shader log to System.out
*/
public static boolean printShaderInfoLog(GL3 gl, int shader) {
IntBuffer ival = IntBuffer.allocate(1);
gl.glGetShaderiv(shader, GL3.GL_INFO_LOG_LENGTH,
ival);
int size = ival.get();
if (size > 1) {
ByteBuffer log = ByteBuffer.allocate(size);
ival.flip();
gl.glGetShaderInfoLog(shader, size, ival, log);
byte[] infoBytes = new byte[size];
log.get(infoBytes);
System.out.println("Info log: " + new String(infoBytes));
return true;
}
return false;
}
/**
* Reads the program log into a String.
* @param prog handle to the shader program
* @return the program log as String
*/
public static String getProgramInfoLog(GL3 gl, int prog) {
IntBuffer ival = IntBuffer.allocate(1);
gl.glGetProgramiv(prog, GL3.GL_INFO_LOG_LENGTH,
ival);
int size = ival.get();
if (size > 1) {
ByteBuffer log = ByteBuffer.allocate(size);
ival.flip();
gl.glGetProgramInfoLog(prog, size, ival, log);
byte[] infoBytes = new byte[size];
log.get(infoBytes);
return new String(infoBytes);
}
return "";
}
/**
* Prints the program log to System.out
*/
public static boolean printProgramInfoLog(GL3 gl, int prog) {
IntBuffer ival = IntBuffer.allocate(1);
gl.glGetProgramiv(prog, GL3.GL_INFO_LOG_LENGTH,
ival);
int size = ival.get();
if (size > 1) {
ByteBuffer log = ByteBuffer.allocate(size);
ival.flip();
gl.glGetProgramInfoLog(prog, size, ival, log);
byte[] infoBytes = new byte[size];
log.get(infoBytes);
System.out.println("Info log: " + new String(infoBytes));
return true;
}
return false;
}
/**
* Save a depth buffer texture to a file as png.
*/
public static void saveDepthBuffer(File file, int depthBufferHandle, int width, int height, GL2GL3 gl) {
// create buffer to store image
FloatBuffer buffer=FloatBuffer.allocate(width*height);//ByteBuffer.allocate(shadowMapWidth*shadowMapHeight*4).asFloatBuffer();
// load image in buffer
gl.glBindTexture(GL.GL_TEXTURE_2D, depthBufferHandle);
gl.glGetTexImage(GL.GL_TEXTURE_2D, 0, GL3.GL_DEPTH_COMPONENT, GL.GL_FLOAT, buffer);
buffer.rewind();
// create buffered image
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
// copy data to buffered image
WritableRaster wr = img.getRaster();
for (int col=0; col<img.getWidth(); col++) {
for (int row=0; row<img.getHeight(); row++) {
float f = buffer.get(row*width+col);
int v = (int)(f*255);
wr.setPixel(col, height-1-row, new int[] {v});
}
}
// save to file
try {
ImageIO.write(img, "png", file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}