347 lines
9.7 KiB
Java
347 lines
9.7 KiB
Java
/*
|
|
* Copyright (c) 2002-2008 LWJGL 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 'LWJGL' 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 java.nio.FloatBuffer;
|
|
|
|
import org.lwjgl.BufferUtils;
|
|
import org.lwjgl.LWJGLException;
|
|
import org.lwjgl.Sys;
|
|
import org.lwjgl.input.Keyboard;
|
|
import org.lwjgl.input.Mouse;
|
|
import org.lwjgl.opengl.*;
|
|
import org.lwjgl.util.glu.Sphere;
|
|
|
|
import static org.lwjgl.opengl.GL11.*;
|
|
import static org.lwjgl.util.glu.GLU.*;
|
|
|
|
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 (!Display.isVisible() )
|
|
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;
|
|
angle += 0.1f;
|
|
sin = (float)Math.sin(Math.toRadians(angle));
|
|
|
|
handleIO();
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
if ( shader != null )
|
|
shader.render();
|
|
else
|
|
renderObject();
|
|
|
|
// Restore camera position.
|
|
glPopMatrix();
|
|
glPushMatrix();
|
|
}
|
|
|
|
Display.update();
|
|
|
|
if ( Display.isCloseRequested() )
|
|
break;
|
|
}
|
|
|
|
cleanup();
|
|
System.exit(0);
|
|
}
|
|
|
|
private static void initialize(String[] args) {
|
|
if ( args.length != 1 )
|
|
argsError();
|
|
|
|
try {
|
|
DisplayMode[] modes = Display.getAvailableDisplayModes();
|
|
|
|
DisplayMode displayMode;
|
|
|
|
displayMode = chooseMode(modes, 1024, 768);
|
|
if ( displayMode == null )
|
|
displayMode = chooseMode(modes, 800, 600);
|
|
if ( displayMode == null )
|
|
displayMode = chooseMode(modes, 640, 480);
|
|
if ( displayMode == null )
|
|
kill("Failed to set an appropriate display mode.");
|
|
|
|
System.out.println("Setting display mode to: " + displayMode);
|
|
Display.setDisplayMode(displayMode);
|
|
Display.create(new PixelFormat(8, 24, 0));
|
|
ShadersTest.displayMode = displayMode;
|
|
} catch (LWJGLException e) {
|
|
kill(e.getMessage());
|
|
}
|
|
|
|
final ContextCapabilities caps = GLContext.getCapabilities();
|
|
|
|
if ( "NONE".equalsIgnoreCase(args[0]) ) {
|
|
shader = null;
|
|
} else if ( "VP".equalsIgnoreCase(args[0]) ) {
|
|
if ( !caps.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 ( !caps.GL_ARB_vertex_program )
|
|
kill("The ARB_vertex_program extension is not supported.");
|
|
if ( !caps.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 ( !caps.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 ( !caps.GL_ARB_vertex_shader )
|
|
kill("The ARB_vertex_shader extension is not supported.");
|
|
if ( !caps.GL_ARB_fragment_shader )
|
|
kill("The ARB_fragment_shader extension is not supported.");
|
|
|
|
shader = new ShaderFSH("shaderFSH.vsh", "shaderFSH.fsh");
|
|
} else if ("UNI".equalsIgnoreCase(args[0]) ) {
|
|
if ( !(caps.OpenGL31 || caps.GL_ARB_uniform_buffer_object) )
|
|
kill("Neither OpenGL version 3.1 nor ARB_uniform_buffer_object are supported.");
|
|
|
|
shader = new ShaderUNI("shaderUNI.vsh");
|
|
} else {
|
|
argsError();
|
|
}
|
|
|
|
glViewport(0, 0, displayMode.getWidth(), displayMode.getHeight());
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(45, displayMode.getWidth() / (float)displayMode.getHeight(), 1.0f, 10.0f);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
|
|
// Setup camera position.
|
|
glTranslatef(0.0f, 0.0f, -4.0f);
|
|
glRotatef(15.0f, 1.0f, 0.0f, 0.0f);
|
|
glPushMatrix();
|
|
|
|
glClearDepth(1.0f);
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
|
|
|
glFrontFace(GL_CCW);
|
|
glPolygonMode(GL_FRONT, GL_FILL);
|
|
|
|
glCullFace(GL_BACK);
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
glAlphaFunc(GL_NOTEQUAL, 0.0f);
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glEnable(GL_BLEND);
|
|
|
|
// Setup lighting for when we have fixed function fragment rendering.
|
|
glShadeModel(GL_SMOOTH);
|
|
|
|
if ( shader == null ) {
|
|
glEnable(GL_LIGHTING);
|
|
glEnable(GL_LIGHT0);
|
|
}
|
|
|
|
vectorBuffer.clear();
|
|
vectorBuffer.put(1.0f).put(1.0f).put(1.0f).put(1.0f);
|
|
vectorBuffer.clear();
|
|
glLight(GL_LIGHT0, GL_DIFFUSE, vectorBuffer);
|
|
|
|
vectorBuffer.put(1.0f).put(1.0f).put(1.0f).put(1.0f);
|
|
vectorBuffer.clear();
|
|
glLight(GL_LIGHT0, GL_AMBIENT, vectorBuffer);
|
|
|
|
vectorBuffer.put(1.0f).put(1.0f).put(0.5f).put(1.0f);
|
|
vectorBuffer.clear();
|
|
glLight(GL_LIGHT0, 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();
|
|
glLight(GL_LIGHT0, GL_POSITION, vectorBuffer);
|
|
|
|
vectorBuffer.put(0.2f).put(0.2f).put(0.2f).put(1.0f);
|
|
vectorBuffer.clear();
|
|
glLightModel(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.getWidth();
|
|
}
|
|
|
|
static int getDisplayHeight() {
|
|
return displayMode.getHeight();
|
|
}
|
|
|
|
static float getSin() {
|
|
return sin;
|
|
}
|
|
|
|
static int getSpecularity() {
|
|
return specularity;
|
|
}
|
|
|
|
static void renderObject() {
|
|
glColor3b((byte)255, (byte)255, (byte)255);
|
|
sphere.draw(1.0f, 32, 32);
|
|
}
|
|
|
|
private static DisplayMode chooseMode(DisplayMode[] modes, int width, int height) {
|
|
DisplayMode bestMode = null;
|
|
|
|
for ( DisplayMode mode : modes ) {
|
|
if ( mode.getWidth() == width && mode.getHeight() == height && mode.getFrequency() <= 85 ) {
|
|
if ( bestMode == null || (mode.getBitsPerPixel() >= bestMode.getBitsPerPixel() && mode.getFrequency() > bestMode.getFrequency()) )
|
|
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 ( Display.isCreated() )
|
|
Display.destroy();
|
|
}
|
|
|
|
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).");
|
|
System.out.println("uni\t- Use ARB_uniform_buffer_object to update shader uniforms (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);
|
|
}
|
|
|
|
}
|