Added shader tests

This commit is contained in:
Ioannis Tsakpinis 2004-03-30 23:25:17 +00:00
parent 8fe46e0223
commit 79e83e4533
12 changed files with 1151 additions and 0 deletions

View File

@ -0,0 +1,188 @@
/*
* Copyright (c) 2002 Lightweight Java Game Library Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'Light Weight Java Game Library' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Created by LWJGL.
* User: spasi
* Date: 2004-03-30
* Time: 8:41:42 pm
*/
package org.lwjgl.test.opengl.shaders;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.ARBProgram;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.Util;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
abstract class Shader {
protected static IntBuffer programBuffer = BufferUtils.createIntBuffer(1);
protected static ByteBuffer fileBuffer = BufferUtils.createByteBuffer(1024 * 10);
protected Shader() {
}
abstract void render();
abstract void cleanup();
protected static ByteBuffer getShaderText(String file) {
ByteBuffer shader = null;
try {
ClassLoader loader = ShadersTest.class.getClassLoader();
InputStream inputStream = loader.getResourceAsStream("org/lwjgl/test/opengl/shaders/" + file);
if ( inputStream == null )
ShadersTest.kill("A shader source file could not be found: " + file);
BufferedInputStream stream = new BufferedInputStream(inputStream);
byte character;
while ( (character = (byte)stream.read()) != -1 )
fileBuffer.put(character);
stream.close();
fileBuffer.flip();
shader = BufferUtils.createByteBuffer(fileBuffer.limit());
shader.put(fileBuffer);
shader.clear();
fileBuffer.clear();
} catch (IOException e) {
ShadersTest.kill("Failed to read the shader source file: " + file, e);
}
return shader;
}
protected static void checkProgramError(String programFile, ByteBuffer programSource) {
if ( GL11.glGetError() == GL11.GL_INVALID_OPERATION ) {
programSource.clear();
final byte[] bytes = new byte[programSource.capacity()];
programSource.get(bytes);
final int errorPos = Util.glGetInteger(ARBProgram.GL_PROGRAM_ERROR_POSITION_ARB);
int lineStart = 0;
int lineEnd = -1;
for ( int i = 0; i < bytes.length; i++ ) {
if ( bytes[i] == '\n' ) {
if ( i <= errorPos ) {
lineStart = i + 1;
} else {
lineEnd = i;
break;
}
}
}
if ( lineEnd == -1 )
lineEnd = bytes.length;
ShadersTest.kill("Low-level program error in file: " + programFile
+ "\n\tError line: " + new String(bytes, lineStart, lineEnd - lineStart)
+ "\n\tError message: " + GL11.glGetString(ARBProgram.GL_PROGRAM_ERROR_STRING_ARB));
}
}
protected static int getUniformLocation(int ID, String name) {
fileBuffer.clear();
int length = name.length();
char[] charArray = new char[length];
name.getChars(0, length, charArray, 0);
for ( int i = 0; i < length; i++ )
fileBuffer.put((byte)charArray[i]);
fileBuffer.put((byte)0); // Must be null-terminated.
fileBuffer.flip();
final int location = ARBShaderObjects.glGetUniformLocationARB(ID, fileBuffer);
if ( location == -1 )
throw new IllegalArgumentException("The uniform \"" + name + "\" does not exist in the Shader Program.");
return location;
}
protected static void printShaderObjectInfoLog(String file, int ID) {
ARBShaderObjects.glGetObjectParameterARB(ID, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB, programBuffer);
final int logLength = programBuffer.get(0);
if ( logLength <= 1 )
return;
final ByteBuffer log = BufferUtils.createByteBuffer(logLength);
ARBShaderObjects.glGetInfoLogARB(ID, null, log);
final char[] charArray = new char[logLength];
for ( int i = 0; i < logLength; i++ )
charArray[i] = (char)log.get();
System.out.println("\nInfo Log of Shader Object: " + file);
System.out.println("--------------------------");
System.out.println(new String(charArray, 0, logLength));
}
protected static void printShaderProgramInfoLog(int ID) {
ARBShaderObjects.glGetObjectParameterARB(ID, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB, programBuffer);
final int logLength = programBuffer.get(0);
if ( logLength <= 1 )
return;
final ByteBuffer log = BufferUtils.createByteBuffer(logLength);
ARBShaderObjects.glGetInfoLogARB(ID, null, log);
final char[] charArray = new char[logLength];
for ( int i = 0; i < logLength; i++ )
charArray[i] = (char)log.get();
System.out.println("\nShader Program Info Log: ");
System.out.println("--------------------------");
System.out.println(new String(charArray, 0, logLength));
}
}

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2002 Lightweight Java Game Library Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'Light Weight Java Game Library' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Created by LWJGL.
* User: spasi
* Date: 2004-03-30
* Time: 9:55:38 pm
*/
package org.lwjgl.test.opengl.shaders;
import org.lwjgl.opengl.ARBFragmentProgram;
import org.lwjgl.opengl.ARBProgram;
import org.lwjgl.opengl.ARBVertexProgram;
import org.lwjgl.opengl.GL11;
import java.nio.ByteBuffer;
final class ShaderFP extends Shader {
final String vpFile;
final ByteBuffer vpSource;
final int vpID;
final String fpFile;
final ByteBuffer fpSource;
final int fpID;
ShaderFP(final String vpShaderFile, final String fpShaderFile) {
// Initialize the vertex program.
vpFile = vpShaderFile;
vpSource = getShaderText(vpShaderFile);
ARBProgram.glGenProgramsARB(programBuffer);
vpID = programBuffer.get(0);
ARBProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, vpID);
ARBProgram.glProgramStringARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, ARBProgram.GL_PROGRAM_FORMAT_ASCII_ARB, vpSource);
checkProgramError(vpFile, vpSource);
// Initialize the fragment program.
fpFile = fpShaderFile;
fpSource = getShaderText(fpShaderFile);
ARBProgram.glGenProgramsARB(programBuffer);
fpID = programBuffer.get(0);
ARBProgram.glBindProgramARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, fpID);
ARBProgram.glProgramStringARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, ARBProgram.GL_PROGRAM_FORMAT_ASCII_ARB, fpSource);
checkProgramError(fpFile, fpSource);
}
void render() {
GL11.glEnable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
ARBProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, vpID);
GL11.glEnable(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB);
ARBProgram.glBindProgramARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, fpID);
ARBProgram.glProgramLocalParameter4fARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, 0,
ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f, 0.0f, 0.0f);
ARBProgram.glProgramLocalParameter4fARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, 0,
ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f,
-ShadersTest.getDisplayWidth() * 0.5f, -ShadersTest.getDisplayHeight() * 0.5f);
ShadersTest.renderObject();
GL11.glDisable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
GL11.glDisable(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB);
}
void cleanup() {
programBuffer.put(0, vpID);
ARBProgram.glDeleteProgramsARB(programBuffer);
programBuffer.put(0, fpID);
ARBProgram.glDeleteProgramsARB(programBuffer);
}
}

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2002 Lightweight Java Game Library Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'Light Weight Java Game Library' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Created by LWJGL.
* User: spasi
* Date: 2004-03-30
* Time: 9:55:38 pm
*/
package org.lwjgl.test.opengl.shaders;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.ARBFragmentShader;
import java.nio.ByteBuffer;
final class ShaderFSH extends Shader {
final String vshFile;
final ByteBuffer vshSource;
final int vshID;
final String fshFile;
final ByteBuffer fshSource;
final int fshID;
final int programID;
final int uniformLocation;
ShaderFSH(final String vshFile, final String fshFile) {
// Initialize the vertex shader.
this.vshFile = vshFile;
vshSource = getShaderText(vshFile);
vshID = ARBShaderObjects.glCreateShaderObjectARB(ARBVertexShader.GL_VERTEX_SHADER_ARB);
ARBShaderObjects.glShaderSourceARB(vshID, vshSource);
ARBShaderObjects.glCompileShaderARB(vshID);
printShaderObjectInfoLog(this.vshFile, vshID);
ARBShaderObjects.glGetObjectParameterARB(vshID, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB, programBuffer);
if ( programBuffer.get(0) == GL11.GL_FALSE )
ShadersTest.kill("A compilation error occured in a vertex shader.");
// Initialize the fragment shader.
this.fshFile = fshFile;
fshSource = getShaderText(fshFile);
fshID = ARBShaderObjects.glCreateShaderObjectARB(ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);
ARBShaderObjects.glShaderSourceARB(fshID, fshSource);
ARBShaderObjects.glCompileShaderARB(fshID);
printShaderObjectInfoLog(this.fshFile, fshID);
ARBShaderObjects.glGetObjectParameterARB(fshID, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB, programBuffer);
if ( programBuffer.get(0) == GL11.GL_FALSE )
ShadersTest.kill("A compilation error occured in a fragment shader.");
// Initialize the shader program.
programID = ARBShaderObjects.glCreateProgramObjectARB();
ARBShaderObjects.glAttachObjectARB(programID, vshID);
ARBShaderObjects.glAttachObjectARB(programID, fshID);
ARBShaderObjects.glLinkProgramARB(programID);
printShaderProgramInfoLog(programID);
ARBShaderObjects.glGetObjectParameterARB(programID, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB, programBuffer);
if ( programBuffer.get(0) == GL11.GL_FALSE )
ShadersTest.kill("A linking error occured in a shader program.");
uniformLocation = getUniformLocation(programID, "UNIFORMS");
}
void render() {
ARBShaderObjects.glUseProgramObjectARB(programID);
ARBShaderObjects.glUniform4fARB(uniformLocation,
ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f,
-ShadersTest.getDisplayWidth() * 0.5f, -ShadersTest.getDisplayHeight() * 0.5f);
ShadersTest.renderObject();
ARBShaderObjects.glUseProgramObjectARB(0);
}
void cleanup() {
ARBShaderObjects.glDetachObjectARB(programID, vshID);
ARBShaderObjects.glDetachObjectARB(programID, fshID);
ARBShaderObjects.glDeleteObjectARB(vshID);
ARBShaderObjects.glDeleteObjectARB(fshID);
ARBShaderObjects.glDeleteObjectARB(programID);
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2002 Lightweight Java Game Library Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'Light Weight Java Game Library' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Created by LWJGL.
* User: spasi
* Date: 2004-03-30
* Time: 9:55:38 pm
*/
package org.lwjgl.test.opengl.shaders;
import org.lwjgl.opengl.ARBProgram;
import org.lwjgl.opengl.ARBVertexProgram;
import org.lwjgl.opengl.GL11;
import java.nio.ByteBuffer;
final class ShaderVP extends Shader {
final String file;
final ByteBuffer source;
final int ID;
ShaderVP(final String shaderFile) {
file = shaderFile;
source = getShaderText(shaderFile);
ARBProgram.glGenProgramsARB(programBuffer);
ID = programBuffer.get(0);
ARBProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, ID);
ARBProgram.glProgramStringARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, ARBProgram.GL_PROGRAM_FORMAT_ASCII_ARB, source);
checkProgramError(file, source);
}
void render() {
GL11.glEnable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
ARBProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, ID);
ARBProgram.glProgramLocalParameter4fARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, 0,
ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f, 0.0f, 0.0f);
ShadersTest.renderObject();
GL11.glDisable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
}
void cleanup() {
programBuffer.put(0, ID);
ARBProgram.glDeleteProgramsARB(programBuffer);
}
}

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2002 Lightweight Java Game Library Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'Light Weight Java Game Library' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Created by LWJGL.
* User: spasi
* Date: 2004-03-30
* Time: 9:55:38 pm
*/
package org.lwjgl.test.opengl.shaders;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.GL11;
import java.nio.ByteBuffer;
final class ShaderVSH extends Shader {
final String file;
final ByteBuffer source;
final int shaderID;
final int programID;
final int uniformLocation;
ShaderVSH(final String shaderFile) {
file = shaderFile;
source = getShaderText(shaderFile);
shaderID = ARBShaderObjects.glCreateShaderObjectARB(ARBVertexShader.GL_VERTEX_SHADER_ARB);
ARBShaderObjects.glShaderSourceARB(shaderID, source);
ARBShaderObjects.glCompileShaderARB(shaderID);
printShaderObjectInfoLog(file, shaderID);
ARBShaderObjects.glGetObjectParameterARB(shaderID, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB, programBuffer);
if ( programBuffer.get(0) == GL11.GL_FALSE )
ShadersTest.kill("A compilation error occured in a vertex shader.");
programID = ARBShaderObjects.glCreateProgramObjectARB();
ARBShaderObjects.glAttachObjectARB(programID, shaderID);
ARBShaderObjects.glLinkProgramARB(programID);
printShaderProgramInfoLog(programID);
ARBShaderObjects.glGetObjectParameterARB(programID, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB, programBuffer);
if ( programBuffer.get(0) == GL11.GL_FALSE )
ShadersTest.kill("A linking error occured in a shader program.");
uniformLocation = getUniformLocation(programID, "UNIFORMS");
}
void render() {
ARBShaderObjects.glUseProgramObjectARB(programID);
ARBShaderObjects.glUniform2fARB(uniformLocation, ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f);
ShadersTest.renderObject();
ARBShaderObjects.glUseProgramObjectARB(0);
}
void cleanup() {
ARBShaderObjects.glDetachObjectARB(programID, shaderID);
ARBShaderObjects.glDeleteObjectARB(shaderID);
ARBShaderObjects.glDeleteObjectARB(programID);
}
}

View File

@ -0,0 +1,338 @@
/*
* Copyright (c) 2002 Lightweight Java Game Library Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'Light Weight Java Game Library' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Created by LWJGL.
* User: spasi
* Date: 2004-03-30
* Time: 8:41:42 pm
*/
package org.lwjgl.test.opengl.shaders;
import org.lwjgl.*;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.opengl.Window;
import org.lwjgl.opengl.glu.GLU;
import org.lwjgl.opengl.glu.Sphere;
import java.nio.FloatBuffer;
public final class ShadersTest {
private static DisplayMode displayMode;
private static boolean run = true;
private static final FloatBuffer vectorBuffer = BufferUtils.createFloatBuffer(4);
private static Sphere sphere;
private static Shader shader;
private static float frameTime;
private static float angle;
private static float sin;
private static int specularity = 4;
private ShadersTest() {
}
public static void main(String[] args) {
initialize(args);
long frameStart;
long lastFrameTime = 0;
while ( run ) {
if ( Window.isMinimized() )
Thread.yield();
else {
// This is the current frame time.
frameStart = Sys.getTime();
// How many seconds passed since last frame.
frameTime = (float)((frameStart - lastFrameTime) / (double)Sys.getTimerResolution());
lastFrameTime = frameStart;
angle += frameTime * 90.0f;
sin = (float)Math.sin(Math.toRadians(angle));
handleIO();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
if ( shader != null )
shader.render();
else
renderObject();
// Restore camera position.
GL11.glPopMatrix();
GL11.glPushMatrix();
}
Window.update();
if ( Window.isCloseRequested() )
break;
}
cleanup();
}
private static void initialize(String[] args) {
if ( args.length != 1 )
argsError();
DisplayMode[] modes = Display.getAvailableDisplayModes();
DisplayMode displayMode;
displayMode = chooseMode(modes, 1024, 768, 32);
if ( displayMode == null )
displayMode = chooseMode(modes, 800, 600, 32);
if ( displayMode == null )
displayMode = chooseMode(modes, 1024, 768, 16);
if ( displayMode == null )
displayMode = chooseMode(modes, 800, 600, 16);
if ( displayMode == null )
kill("Failed to set an appropriate display mode.");
try {
System.out.println("Setting display mode to: " + displayMode);
Display.setDisplayMode(displayMode);
Window.create("OpenGL Shaders Test", displayMode.bpp, 8, 24, 0);
} catch (LWJGLException e) {
kill(e.getMessage());
}
ShadersTest.displayMode = displayMode;
if ( "NONE".equalsIgnoreCase(args[0]) ) {
shader = null;
} else if ( "VP".equalsIgnoreCase(args[0]) ) {
if ( !GLContext.GL_ARB_vertex_program )
kill("The ARB_vertex_program extension is not supported.");
shader = new ShaderVP("shaderVP.vp");
} else if ( "FP".equalsIgnoreCase(args[0]) ) {
if ( !GLContext.GL_ARB_vertex_program )
kill("The ARB_vertex_program extension is not supported.");
if ( !GLContext.GL_ARB_fragment_program )
kill("The ARB_fragment_program extension is not supported.");
shader = new ShaderFP("shaderFP.vp", "shaderFP.fp");
} else if ( "VSH".equalsIgnoreCase(args[0]) ) {
if ( !GLContext.GL_ARB_vertex_shader )
kill("The ARB_vertex_shader extension is not supported.");
shader = new ShaderVSH("shaderVSH.vsh");
} else if ( "FSH".equalsIgnoreCase(args[0]) ) {
if ( !GLContext.GL_ARB_vertex_shader )
kill("The ARB_vertex_shader extension is not supported.");
if ( !GLContext.GL_ARB_fragment_shader )
kill("The ARB_fragment_shader extension is not supported.");
shader = new ShaderFSH("shaderFSH.vsh", "shaderFSH.fsh");
} else {
argsError();
}
GL11.glViewport(0, 0, displayMode.width, displayMode.height);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluPerspective(45, displayMode.width / (float)displayMode.height, 1.0f, 10.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
// Setup camera position.
GL11.glTranslatef(0.0f, 0.0f, -4.0f);
GL11.glRotatef(15.0f, 1.0f, 0.0f, 0.0f);
GL11.glPushMatrix();
GL11.glClearDepth(1.0f);
GL11.glDepthFunc(GL11.GL_LEQUAL);
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
GL11.glFrontFace(GL11.GL_CCW);
GL11.glPolygonMode(GL11.GL_FRONT, GL11.GL_FILL);
GL11.glCullFace(GL11.GL_BACK);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glAlphaFunc(GL11.GL_NOTEQUAL, 0.0f);
GL11.glEnable(GL11.GL_ALPHA_TEST);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glEnable(GL11.GL_BLEND);
// Setup lighting for when we have fixed function fragment rendering.
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_LIGHT0);
vectorBuffer.clear();
vectorBuffer.put(1.0f).put(1.0f).put(1.0f).put(1.0f);
vectorBuffer.clear();
GL11.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, vectorBuffer);
vectorBuffer.put(1.0f).put(1.0f).put(1.0f).put(1.0f);
vectorBuffer.clear();
GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, vectorBuffer);
vectorBuffer.put(1.0f).put(1.0f).put(0.5f).put(1.0f);
vectorBuffer.clear();
GL11.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, vectorBuffer);
vectorBuffer.put(-1.0f / 3.0f).put(1.0f / 3.0f).put(1.0f / 3.0f).put(0.0f); // Infinite
vectorBuffer.clear();
GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, vectorBuffer);
vectorBuffer.put(0.2f).put(0.2f).put(0.2f).put(1.0f);
vectorBuffer.clear();
GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, vectorBuffer);
sphere = new Sphere();
}
private static void handleIO() {
if ( Keyboard.getNumKeyboardEvents() != 0 ) {
while ( Keyboard.next() ) {
if ( Keyboard.getEventKeyState() )
continue;
switch ( Keyboard.getEventKey() ) {
case Keyboard.KEY_EQUALS:
if ( specularity < 8 )
specularity++;
break;
case Keyboard.KEY_MINUS:
if ( specularity > 1 )
specularity--;
break;
case Keyboard.KEY_ESCAPE:
run = false;
break;
}
}
}
while ( Mouse.next() ) ;
}
static int getDisplayWidth() {
return displayMode.width;
}
static int getDisplayHeight() {
return displayMode.height;
}
static float getSin() {
return sin;
}
static int getSpecularity() {
return specularity;
}
static void renderObject() {
GL11.glColor3b((byte)255, (byte)255, (byte)255);
sphere.draw(1.0f, 32, 32);
}
private static DisplayMode chooseMode(DisplayMode[] modes, int width, int height, int bpp) {
DisplayMode bestMode = null;
for ( int i = 0; i < modes.length; i++ ) {
DisplayMode mode = modes[i];
if ( mode.width == width && mode.height == height && mode.bpp == bpp && mode.freq <= 85 ) {
if ( bestMode == null || bestMode.freq < mode.freq )
bestMode = mode;
}
}
return bestMode;
}
private static void cleanup() {
// This is not necessary, just showing how to properly delete a program/shader.
if ( shader != null )
shader.cleanup();
if ( Window.isCreated() )
Window.destroy();
Display.resetDisplayMode();
}
private static void argsError() {
System.out.println("\nInvalid program arguments.");
System.out.println("\nUsage: ShadersTest <shaderType>, where <shaderType> argument can be one of the following:\n");
System.out.println("none\t- Use fixed function rendering.");
System.out.println("vp\t- Use ARB_vertex_program (low-level) only.");
System.out.println("vsh\t- Use ARB_vertex_shader (GLSL) only.");
System.out.println("fp\t- Use ARB_vertex_program + ARB_fragment_program (low-level).");
System.out.println("fsh\t- Use ARB_vertex_shader + ARB_fragment_shader (GLSL).");
cleanup();
System.exit(-1);
}
static void kill(String reason) {
System.out.println("The ShaderTest program was terminated because an error occured.\n");
System.out.println("Reason: " + (reason == null ? "Unknown" : reason));
cleanup();
System.exit(-1);
}
static void kill(String reason, Throwable t) {
System.out.println("The ShaderTest program was terminated because an exception occured.\n");
System.out.println("Reason: " + reason == null ? "Unknown" : reason);
System.out.println("Exception message: " + t.getMessage());
cleanup();
System.exit(-1);
}
}

View File

@ -0,0 +1,40 @@
!!ARBfp1.0
OPTION ARB_precision_hint_fastest;
ATTRIB winPos = fragment.position;
ATTRIB iDots = fragment.texcoord[0];
PARAM ambience = state.lightmodel.ambient;
PARAM specularColor = state.light[0].specular;
PARAM UNIFORMS = program.local[0];
TEMP temp;
OUTPUT oColor = result.color;
# Offset window-space fragment position.
ADD temp.xyz, winPos, UNIFORMS.zwxx;
# Normalize position.
DP3 temp.w, temp, temp;
RSQ temp.w, temp.w;
MUL temp.xy, temp, temp.w;
# Multiply with current sin.
MUL temp.xy, temp, UNIFORMS.x;
# {-1..1} => {0..1}
MAD temp.xy, temp, 0.5, 0.5;
# Intensify colors.
MUL temp.xy, temp, 2.0;
MOV temp.z, 1.0;
# Accumulate color contributions.
MAD temp.xyz, iDots.x, temp, ambience;
# Calculate <specular dot product>^<specular exponent>
POW temp.w, iDots.y, UNIFORMS.y;
MAD oColor.xyz, temp.w, specularColor, temp;
MOV oColor.w, 1.0;
END

View File

@ -0,0 +1,37 @@
!!ARBvp1.0
ATTRIB iPos = vertex.position;
ATTRIB iNormal = vertex.normal;
PARAM mvp[4] = { state.matrix.mvp };
PARAM mvIT[4] = { state.matrix.modelview.invtrans };
PARAM lightDir = state.light[0].position;
PARAM halfDir = state.light[0].half;
PARAM UNIFORMS = program.local[0];
TEMP normal, dots;
OUTPUT oPos = result.position;
OUTPUT oDots = result.texcoord[0];
# Transform the vertex to clip coordinates.
DP4 oPos.x, mvp[0], iPos;
DP4 oPos.y, mvp[1], iPos;
DP4 oPos.z, mvp[2], iPos;
DP4 oPos.w, mvp[3], iPos;
# Transform the normal to eye coordinates.
DP3 normal.x, mvIT[0], iNormal;
DP3 normal.y, mvIT[1], iNormal;
DP3 normal.z, mvIT[2], iNormal;
# Compute diffuse and specular dot products and clamp them.
DP3 dots.x, normal, lightDir;
MAX oDots.x, dots.x, 0.0;
DP3 dots.y, normal, halfDir;
MAX oDots.y, dots.y, 0.0;
END

View File

@ -0,0 +1,21 @@
uniform vec4 UNIFORMS;
varying vec2 dots;
void main(void) {
// Offset window-space fragment position.
vec3 color2D = vec3(gl_FragCoord + UNIFORMS.zwxx);
// Normalize position.
// Multiply with current sin.
color2D.xy = normalize(color2D) * UNIFORMS.x;
// {-1..1} => {0..1} & Intensify colors.
color2D.xy = (vec2(color2D) * 0.5 + 0.5) * 2.0;
color2D.z = 1.0;
// Accumulate color contributions.
// Hardcoded ambience and specular color, due to buggy drivers.
color2D = dots.x * color2D + vec3(0.2, 0.2, 0.2);
gl_FragColor.rgb = pow(dots.y, UNIFORMS.y) * vec3(1.0, 1.0, 0.5) + color2D;
gl_FragColor.a = 1.0;
}

View File

@ -0,0 +1,11 @@
varying vec2 dots;
void main(void) {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec3 normal = gl_NormalMatrix * gl_Normal;
// Pass the dot products to the fragment shader.
dots.x = max(dot(normal, gl_LightSource[0].position), 0.0);
dots.y = max(dot(normal, gl_LightSource[0].halfVector), 0.0);
}

View File

@ -0,0 +1,59 @@
!!ARBvp1.0
ATTRIB iPos = vertex.position;
ATTRIB iNormal = vertex.normal;
PARAM mvp[4] = { state.matrix.mvp };
PARAM mvIT[4] = { state.matrix.modelview.invtrans };
PARAM ambience = state.lightmodel.ambient;
PARAM lightDir = state.light[0].position;
PARAM halfDir = state.light[0].half;
PARAM diffuseColor = state.light[0].diffuse;
PARAM specularColor = state.light[0].specular;
PARAM UNIFORMS = program.local[0];
TEMP temp, temp2, normal, dots;
OUTPUT oPos = result.position;
OUTPUT oColor = result.color;
# Transform the vertex to clip coordinates.
DP4 oPos.x, mvp[0], iPos;
DP4 oPos.y, mvp[1], iPos;
DP4 oPos.z, mvp[2], iPos;
DP4 oPos.w, mvp[3], iPos;
# Transform the normal to eye coordinates.
DP3 normal.x, mvIT[0], iNormal;
DP3 normal.y, mvIT[1], iNormal;
DP3 normal.z, mvIT[2], iNormal;
# Compute diffuse and specular dot products and use LIT to compute
# lighting coefficients.
DP3 dots.x, normal, lightDir;
DP3 dots.y, normal, halfDir;
MOV dots.w, UNIFORMS.y;
LIT dots, dots;
# Normalize position, to get a {-1..1} value for each vertex.
DP3 temp.w, iPos, iPos;
RSQ temp.w, temp.w;
MUL temp.xyz, iPos, temp.w;
# Multiply with current sin.
MUL temp.xyz, temp, UNIFORMS.x;
# {-1..1} => {0..1}
MAD temp.xyz, temp, 0.5, 0.5;
# Intensify colors.
MUL temp.xyz, temp, 2.0;
# Accumulate color contributions.
MAD temp.xyz, dots.y, temp, ambience;
MAD oColor.xyz, dots.z, specularColor, temp;
MOV oColor.w, 1.0;
END

View File

@ -0,0 +1,22 @@
uniform vec2 UNIFORMS;
void main(void) {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec3 normal = gl_NormalMatrix * gl_Normal;
float diffuseDot = max(dot(normal, gl_LightSource[0].position), 0.0);
float specularDot = max(dot(normal, gl_LightSource[0].halfVector), 0.0);
specularDot = pow(specularDot, UNIFORMS.y);
// Normalize position, to get a {-1..1} value for each vertex.
// Multiply with current sin.
vec3 color3D = normalize(vec3(gl_Vertex)) * UNIFORMS.x;
// {-1..1} => {0..1} & Intensify colors.
color3D = (color3D * 0.5 + 0.5) * 2.0;
// Accumulate color contributions.
color3D = diffuseDot * color3D + gl_LightModel.ambient;
gl_FrontColor.rgb = specularDot * gl_LightSource[0].specular + color3D;
gl_FrontColor.a = 1.0;
}