com.jogamp.opengl.util.glsl.sdk.CompileShader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jogl-all Show documentation
Show all versions of jogl-all Show documentation
Java™ Binding for the OpenGL® API
package com.jogamp.opengl.util.glsl.sdk;
import com.jogamp.common.util.IOUtil;
import javax.media.opengl.*;
import com.jogamp.opengl.util.glsl.*;
import java.io.*;
import java.net.*;
/**
* Precompiles a shader into a vendor binary format. Input is the
* resource name of the shader, such as
* "com/jogamp/opengl/impl/glsl/fixed/shader/a.fp".
* Output is "com/jogamp/opengl/impl/glsl/fixed/shader/bin/nvidia/a.bfp".
*
* All path and suffixes are determined by the ShaderCode class,
* which ensures runtime compatibility.
*
* @see com.jogamp.opengl.util.glsl.ShaderCode
*/
public abstract class CompileShader {
public abstract int getBinaryFormat();
public abstract File getSDKCompilerDir();
public abstract String getVertexShaderCompiler();
public abstract String getFragmentShaderCompiler();
public void processOneShader(String resourceName)
throws IOException, UnsupportedEncodingException, InterruptedException
{
int type = -1;
String outName=null;
int suffixLen = -1;
if(resourceName.endsWith(ShaderCode.getFileSuffix(false, GL2ES2.GL_FRAGMENT_SHADER))) {
suffixLen = 2;
type = GL2ES2.GL_FRAGMENT_SHADER;
} else if(resourceName.endsWith(".frag")) {
suffixLen = 4;
type = GL2ES2.GL_FRAGMENT_SHADER;
} else if(resourceName.endsWith(ShaderCode.getFileSuffix(false, GL2ES2.GL_VERTEX_SHADER))) {
suffixLen = 2;
type = GL2ES2.GL_VERTEX_SHADER;
} else if(resourceName.endsWith(".vert")) {
suffixLen = 4;
type = GL2ES2.GL_VERTEX_SHADER;
}
String justName = basename(resourceName);
outName = justName.substring(0, justName.length() - suffixLen) +
ShaderCode.getFileSuffix(true, type);
URL resourceURL = IOUtil.getResource(null, resourceName).getURL();
String dirName = dirname(resourceURL.getPath());
outName = dirName + File.separator + "bin" + File.separator +
ShaderCode.getBinarySubPath(getBinaryFormat()) + File.separator +
outName;
processOneShader(resourceName, outName, type);
}
public void processOneShader(String resourceName, String outName, int type)
throws IOException, UnsupportedEncodingException, InterruptedException
{
URL resourceURL = IOUtil.getResource(null, resourceName).getURL();
String dirName = dirname(resourceURL.getPath());
CharSequence shader = ShaderCode.readShaderSource(null, resourceName, false);
if(null==shader) {
System.err.println("Can't find shader source " + resourceName + " - ignored");
return;
}
System.err.println("Preprocessing: "+ resourceName+", in dir: "+dirName);
String justName = basename(resourceName);
String processor;
switch (type) {
case GL2ES2.GL_VERTEX_SHADER:
processor = getVertexShaderCompiler();
break;
case GL2ES2.GL_FRAGMENT_SHADER:
processor = getFragmentShaderCompiler();
break;
default:
throw new GLException("Unknown shader type: "+type);
}
File outputFile = new File(outName);
// Write shader to a file in java.io.tmpdir
File tmpDir = new File(dirName+File.separator+"tmp");
tmpDir.mkdirs();
File tmpFile = new File(tmpDir, justName);
Writer writer = new BufferedWriter(new FileWriter(tmpFile));
writer.write(shader.toString(), 0, shader.length());
writer.flush();
writer.close();
System.err.println("Preprocessed: "+ tmpFile.getAbsolutePath());
File processorDir = getSDKCompilerDir();
System.err.println("SDK: "+ processorDir.getAbsolutePath() + ", compiler: "+processor);
System.err.println("Output: "+ outputFile.getAbsolutePath());
// Run the tool
Process process = Runtime.getRuntime().exec(new String[] {
processorDir.getAbsolutePath() + File.separator + processor,
tmpFile.getAbsolutePath(),
outputFile.getAbsolutePath()
}); // , null, processorDir);
new StreamMonitor(process.getInputStream());
new StreamMonitor(process.getErrorStream());
process.waitFor();
// Delete the temporary file
// tmpFile.delete();
}
protected static String basename(String path) {
int lastSlash = path.lastIndexOf("/");
if (lastSlash < 0) {
lastSlash = path.lastIndexOf("\\");
}
String basename;
if (lastSlash < 0) {
basename = path;
} else {
basename = path.substring(lastSlash + 1);
}
return basename;
}
protected static String dirname(String path) {
int lastSlash = path.lastIndexOf("/");
if (lastSlash < 0) {
lastSlash = path.lastIndexOf("\\");
}
String dirname;
if (lastSlash < 0) {
dirname = new String();
} else {
dirname = path.substring(0, lastSlash + 1);
}
return dirname;
}
public void run(String[] args) {
try {
for (int i = 0; i < args.length; i++) {
processOneShader(args[i]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static class StreamMonitor implements Runnable {
private InputStream istream;
public StreamMonitor(InputStream stream) {
istream = stream;
new Thread(this, "Output Reader Thread").start();
}
public void run()
{
byte[] buffer = new byte[4096];
try {
int numRead = 0;
do {
numRead = istream.read(buffer);
if (numRead > 0) {
System.out.write(buffer, 0, numRead);
System.out.flush();
}
} while (numRead >= 0);
}
catch (IOException e) {
try {
istream.close();
} catch (IOException e2) {
}
// Should allow clean exit when process shuts down
}
}
}
}