diff options
Diffstat (limited to 'src/demos/proceduralTexturePhysics/Water.java')
-rw-r--r-- | src/demos/proceduralTexturePhysics/Water.java | 1844 |
1 files changed, 0 insertions, 1844 deletions
diff --git a/src/demos/proceduralTexturePhysics/Water.java b/src/demos/proceduralTexturePhysics/Water.java deleted file mode 100644 index 50be158..0000000 --- a/src/demos/proceduralTexturePhysics/Water.java +++ /dev/null @@ -1,1844 +0,0 @@ -/* - * Portions Copyright (C) 2003 Sun Microsystems, Inc. - * All rights reserved. - */ - -/* - * - * COPYRIGHT NVIDIA CORPORATION 2003. ALL RIGHTS RESERVED. - * BY ACCESSING OR USING THIS SOFTWARE, YOU AGREE TO: - * - * 1) ACKNOWLEDGE NVIDIA'S EXCLUSIVE OWNERSHIP OF ALL RIGHTS - * IN AND TO THE SOFTWARE; - * - * 2) NOT MAKE OR DISTRIBUTE COPIES OF THE SOFTWARE WITHOUT - * INCLUDING THIS NOTICE AND AGREEMENT; - * - * 3) ACKNOWLEDGE THAT TO THE MAXIMUM EXTENT PERMITTED BY - * APPLICABLE LAW, THIS SOFTWARE IS PROVIDED *AS IS* AND - * THAT NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, - * EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED - * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS BE LIABLE FOR ANY - * SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES - * WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS - * OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS - * INFORMATION, OR ANY OTHER PECUNIARY LOSS), INCLUDING ATTORNEYS' - * FEES, RELATING TO THE USE OF OR INABILITY TO USE THIS SOFTWARE, - * EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package demos.proceduralTexturePhysics; - -import java.awt.Image; -import java.awt.image.*; -import java.io.*; -import java.nio.*; -import java.text.*; -import java.util.*; - -import gleem.linalg.*; -import javax.media.opengl.*; -import javax.media.opengl.glu.*; -import com.sun.opengl.util.*; -import com.sun.opengl.util.texture.*; -import demos.util.*; - -/** - * Auxiliary Water simulation class used by ProceduralTexturePhysics - * main loop. Demonstration by NVidia Corporation. - * - * <P> - * - * Ported to Java and ARB_fragment_program by Kenneth Russell - */ - -public class Water { - // Note: this class is organized differently than most of the demos - // due to the fact that it is used for two purposes: when the - // pbuffer's context is current it is used to update the cellular - // automata, and when the parent drawable's context is current it is - // used to render the water geometry (with the parent drawable's GL - // object). - - private GLU glu = new GLU(); - - // Rendering modes - public static final int CA_FULLSCREEN_REFLECT = 0; - public static final int CA_FULLSCREEN_FORCE = 1; - public static final int CA_FULLSCREEN_HEIGHT = 2; - public static final int CA_FULLSCREEN_NORMALMAP = 3; - public static final int CA_TILED_THREE_WINDOWS = 4; - public static final int CA_DO_NOT_RENDER = 5; - - private int[] initialMapDimensions = new int[2]; - private TextureData initialMapData; - - private String tmpSpinFilename; - private String tmpDropletFilename; - private String tmpCubeMapFilenamePrefix; - private String tmpCubeMapFilenameSuffix; - - private GLPbuffer pbuffer; - private Rotf cameraOrientation = new Rotf(); - - // Dynamic texture names - private static final int CA_TEXTURE_FORCE_INTERMEDIATE = 0; - private static final int CA_TEXTURE_FORCE_TARGET = 1; - private static final int CA_TEXTURE_VELOCITY_SOURCE = 2; - private static final int CA_TEXTURE_VELOCITY_TARGET = 3; - private static final int CA_TEXTURE_HEIGHT_SOURCE = 4; - private static final int CA_TEXTURE_HEIGHT_TARGET = 5; - private static final int CA_TEXTURE_NORMAL_MAP = 6; - private static final int CA_NUM_DYNAMIC_TEXTURES = 7; - - // List names - private static final int CA_FRAGMENT_PROGRAM_EQ_WEIGHT_COMBINE = 0; - private static final int CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_1 = 1; - private static final int CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_2 = 2; - private static final int CA_FRAGMENT_PROGRAM_APPLY_FORCE = 3; - private static final int CA_FRAGMENT_PROGRAM_APPLY_VELOCITY = 4; - private static final int CA_FRAGMENT_PROGRAM_CREATE_NORMAL_MAP = 5; - private static final int CA_FRAGMENT_PROGRAM_REFLECT = 6; - private static final int CA_DRAW_SCREEN_QUAD = 7; - private static final int CA_NUM_LISTS = 8; - - // Static textures - private Texture initialMapTex; - private Texture spinTex; - private Texture dropletTex; - private Texture cubemap; - - private Texture[] dynamicTextures = new Texture[CA_NUM_DYNAMIC_TEXTURES]; - - private int texHeightInput; // current input height texture ID. - private int texHeightOutput; // current output height texture ID. - private int texVelocityInput; // current input velocity texture ID. - private int texVelocityOutput; // current output velocity texture ID. - private int texForceStepOne; // intermediate force computation result texture ID. - private int texForceOutput; // current output force texture ID. - - private int[] displayListIDs = new int[CA_NUM_LISTS]; - - private int vertexProgramID; // one vertex program is used to choose the texcoord offset - - private int flipState; // used to flip target texture configurations. - - private boolean wrap; // CA can either wrap its borders, or clamp (clamp by default) - private boolean reset = true; // are we resetting this frame? (user hit reset). - private boolean singleStep; // animation step on keypress. - private boolean animate = true; // continuous animation. - private boolean slow = true; // run slow. - private boolean wireframe; // render in wireframe mode - private boolean applyInteriorBoundaries = true; // enable / disable "boundary" image drawing. - private boolean spinLogo = true; // draw spinning logo. - private boolean createNormalMap = true; // enable / disable normal map creation. - - private float perTexelWidth; // width of a texel (percentage of texture) - private float perTexelHeight; // height of a texel - - private float blurDist = 0.5f; // distance over which to blur. - private boolean mustUpdateBlurOffsets; // flag indicating blurDist was set last tick - - private float normalSTScale = 0.8f; // scale of normals in normal map. - private float bumpScale = 0.25f; // scale of bumps in water. - - private float dropletFrequency = 0.175f; // frequency at which droplets are drawn in water... - - private int slowDelay = 1; // amount (milliseconds) to delay when running slow. - private int skipInterval; // frames to skip simulation. - private int skipCount; // frame count for skipping rendering - - private int angle; // angle in degrees for spinning logo - - private List/*<Droplet>*/ droplets = new ArrayList/*<Droplet>*/(); // array of droplets - - private int renderMode; - - // Constant memory locations - private static final int CV_UV_OFFSET_TO_USE = 0; - - private static final int CV_UV_T0_NO_OFFSET = 1; - private static final int CV_UV_T0_TYPE1 = 2; - private static final int CV_UV_T0_TYPE2 = 3; - private static final int CV_UV_T0_TYPE3 = 4; - private static final int CV_UV_T0_TYPE4 = 5; - - private static final int CV_UV_T1_NO_OFFSET = 6; - private static final int CV_UV_T1_TYPE1 = 7; - private static final int CV_UV_T1_TYPE2 = 8; - private static final int CV_UV_T1_TYPE3 = 9; - private static final int CV_UV_T1_TYPE4 = 10; - - private static final int CV_UV_T2_NO_OFFSET = 11; - private static final int CV_UV_T2_TYPE1 = 12; - private static final int CV_UV_T2_TYPE2 = 13; - private static final int CV_UV_T2_TYPE3 = 14; - private static final int CV_UV_T2_TYPE4 = 15; - - private static final int CV_UV_T3_NO_OFFSET = 16; - private static final int CV_UV_T3_TYPE1 = 17; - private static final int CV_UV_T3_TYPE2 = 18; - private static final int CV_UV_T3_TYPE3 = 19; - private static final int CV_UV_T3_TYPE4 = 20; - - private static final int CV_CONSTS_1 = 21; - - public void initialize(String initialMapFilename, - String spinFilename, - String dropletFilename, - String cubeMapFilenamePrefix, - String cubeMapFilenameSuffix, - GLAutoDrawable parentWindow) { - loadInitialTexture(initialMapFilename); - tmpSpinFilename = spinFilename; - tmpDropletFilename = dropletFilename; - tmpCubeMapFilenamePrefix = cubeMapFilenamePrefix; - tmpCubeMapFilenameSuffix = cubeMapFilenameSuffix; - - // create the pbuffer. Will use this as an offscreen rendering buffer. - // it allows rendering a texture larger than our window. - GLCapabilities caps = new GLCapabilities(); - caps.setDoubleBuffered(false); - if (!GLDrawableFactory.getFactory().canCreateGLPbuffer()) { - throw new GLException("Pbuffers not supported with this graphics card"); - } - pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, - null, - initialMapDimensions[0], - initialMapDimensions[1], - parentWindow.getContext()); - pbuffer.addGLEventListener(new Listener()); - } - - public void destroy() { - if (pbuffer != null) { - pbuffer.destroy(); - pbuffer = null; - } - reset = true; - } - - public void tick() { - pbuffer.display(); - } - - public void draw(GL gl, Rotf cameraOrientation) { - this.cameraOrientation.set(cameraOrientation); - - if (skipCount >= skipInterval && renderMode != CA_DO_NOT_RENDER) { - skipCount = 0; - // Display the results of the rendering to texture - if (wireframe) { - gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE); - - // chances are the texture will be all dark, so lets not use a texture - gl.glDisable(GL.GL_TEXTURE_2D); - } else { - gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); - - gl.glActiveTexture(GL.GL_TEXTURE0); - gl.glEnable(GL.GL_TEXTURE_2D); - } - - switch (renderMode) { - case CA_FULLSCREEN_REFLECT: { - // include bump scale... - Mat4f bscale = new Mat4f(); - bscale.makeIdent(); - bscale.set(0, 0, bumpScale); - bscale.set(1, 1, bumpScale); - Mat4f rot = new Mat4f(); - rot.makeIdent(); - rot.setRotation(cameraOrientation); - Mat4f matRot = rot.mul(bscale); - - gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_REFLECT]); - - // Draw quad over full display - gl.glActiveTexture(GL.GL_TEXTURE0); - dynamicTextures[CA_TEXTURE_NORMAL_MAP].bind(); - dynamicTextures[CA_TEXTURE_NORMAL_MAP].disable(); - gl.glActiveTexture(GL.GL_TEXTURE3); - cubemap.bind(); - cubemap.enable(); - - gl.glColor4f(1, 1, 1, 1); - gl.glBegin(GL.GL_QUADS); - - gl.glMultiTexCoord2f(GL.GL_TEXTURE0, 0,0); - gl.glMultiTexCoord4f(GL.GL_TEXTURE1, matRot.get(0,0), matRot.get(0,1), matRot.get(0,2), 1); - gl.glMultiTexCoord4f(GL.GL_TEXTURE2, matRot.get(1,0), matRot.get(1,1), matRot.get(1,2), 1); - gl.glMultiTexCoord4f(GL.GL_TEXTURE3, matRot.get(2,0), matRot.get(2,1), matRot.get(2,2), 1); - gl.glVertex2f(-1,-1); - - gl.glMultiTexCoord2f(GL.GL_TEXTURE0, 1,0); - gl.glMultiTexCoord4f(GL.GL_TEXTURE1, matRot.get(0,0), matRot.get(0,1), matRot.get(0,2), -1); - gl.glMultiTexCoord4f(GL.GL_TEXTURE2, matRot.get(1,0), matRot.get(1,1), matRot.get(1,2), 1); - gl.glMultiTexCoord4f(GL.GL_TEXTURE3, matRot.get(2,0), matRot.get(2,1), matRot.get(2,2), 1); - gl.glVertex2f( 1,-1); - - gl.glMultiTexCoord2f(GL.GL_TEXTURE0, 1,1); - gl.glMultiTexCoord4f(GL.GL_TEXTURE1, matRot.get(0,0), matRot.get(0,1), matRot.get(0,2), -1); - gl.glMultiTexCoord4f(GL.GL_TEXTURE2, matRot.get(1,0), matRot.get(1,1), matRot.get(1,2), -1); - gl.glMultiTexCoord4f(GL.GL_TEXTURE3, matRot.get(2,0), matRot.get(2,1), matRot.get(2,2), 1); - gl.glVertex2f( 1, 1); - - gl.glMultiTexCoord2f(GL.GL_TEXTURE0, 0,1); - gl.glMultiTexCoord4f(GL.GL_TEXTURE1, matRot.get(0,0), matRot.get(0,1), matRot.get(0,2), 1); - gl.glMultiTexCoord4f(GL.GL_TEXTURE2, matRot.get(1,0), matRot.get(1,1), matRot.get(1,2), -1); - gl.glMultiTexCoord4f(GL.GL_TEXTURE3, matRot.get(2,0), matRot.get(2,1), matRot.get(2,2), 1); - gl.glVertex2f(-1, 1); - - gl.glEnd(); - - cubemap.disable(); - gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); - - break; - } - - case CA_FULLSCREEN_NORMALMAP: { - // Draw quad over full display - gl.glActiveTexture(GL.GL_TEXTURE0); - dynamicTextures[CA_TEXTURE_NORMAL_MAP].bind(); - - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - break; - } - - case CA_FULLSCREEN_HEIGHT: { - // Draw quad over full display - gl.glActiveTexture(GL.GL_TEXTURE0); - gl.glBindTexture(GL.GL_TEXTURE_2D, texHeightOutput); - - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - break; - } - - case CA_FULLSCREEN_FORCE: { - // Draw quad over full display - gl.glActiveTexture(GL.GL_TEXTURE0); - dynamicTextures[CA_TEXTURE_FORCE_TARGET].bind(); - - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - break; - } - - case CA_TILED_THREE_WINDOWS: { - // Draw quad over full display - // lower left - gl.glActiveTexture(GL.GL_TEXTURE0); - dynamicTextures[CA_TEXTURE_FORCE_TARGET].bind(); - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glPushMatrix(); - - gl.glTranslatef(-0.5f, -0.5f, 0); - gl.glScalef(0.5f, 0.5f, 1); - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - gl.glPopMatrix(); - - // lower right - gl.glBindTexture(GL.GL_TEXTURE_2D, texVelocityOutput); - gl.glPushMatrix(); - - gl.glTranslatef(0.5f, -0.5f, 0); - gl.glScalef(0.5f, 0.5f, 1); - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - gl.glPopMatrix(); - - // upper left - dynamicTextures[CA_TEXTURE_NORMAL_MAP].bind(); - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glPushMatrix(); - - gl.glTranslatef(-0.5f, 0.5f, 0); - gl.glScalef(0.5f, 0.5f, 1); - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - gl.glPopMatrix(); - - // upper right - gl.glBindTexture(GL.GL_TEXTURE_2D, texHeightOutput); - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glPushMatrix(); - - gl.glTranslatef(0.5f, 0.5f, 0); - gl.glScalef(0.5f, 0.5f, 1); - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - gl.glPopMatrix(); - - break; - } - } - } else { - // skip rendering this frame - skipCount++; - } - } - - public void singleStep() { singleStep = true; } - public void enableAnimation(boolean enable) { animate = enable; } - public void enableSlowAnimation(boolean enable) { slow = enable; } - public void reset() { reset = true; } - public void setRenderMode(int mode) { renderMode = mode; } - - public void enableWireframe(boolean enable) { wireframe = enable; } - public void enableBorderWrapping(boolean enable) { wrap = enable; } - - public void enableBoundaryApplication(boolean enable) { applyInteriorBoundaries = enable; } - public void enableSpinningLogo(boolean enable) { spinLogo = enable; } - - public void setBlurDistance(float distance) { blurDist = distance; - mustUpdateBlurOffsets = true; } - public float getBlurDistance() { return blurDist; } - - public void setBumpScale(float scale) { bumpScale = scale; } - public float getBumpScale() { return bumpScale; } - - public void setDropFrequency(float frequency) { dropletFrequency = frequency; } - public float getDropFrequency() { return dropletFrequency; } - - public static class Droplet { - private float rX; - private float rY; - private float rScale; - - Droplet(float rX, float rY, float rScale) { - this.rX = rX; - this.rY = rY; - this.rScale = rScale; - } - - float rX() { return rX; } - float rY() { return rY; } - float rScale() { return rScale; } - } - - public synchronized void addDroplet(Droplet drop) { - droplets.add(drop); - } - - //---------------------------------------------------------------------- - // Internals only below this point - // - - class Listener implements GLEventListener { - public void init(GLAutoDrawable drawable) { - GL gl = drawable.getGL(); - - initOpenGL(gl); - } - - public void display(GLAutoDrawable drawable) { - GL gl = drawable.getGL(); - if (mustUpdateBlurOffsets) { - updateBlurVertOffset(gl); - mustUpdateBlurOffsets = false; - } - - // Take a single step in the cellular automaton - - // Disable culling - gl.glDisable(GL.GL_CULL_FACE); - - if (reset) { - reset = false; - flipState = 0; - } - - if (animate) { - // Update the textures for one step of the simulation - doSingleTimeStep(gl); - } else if (singleStep) { - doSingleTimeStep(gl); - singleStep = false; - } - - // Force rendering to pbuffer to complete - gl.glFlush(); - - if (slow && (slowDelay > 0) ) { - try { - Thread.sleep(slowDelay); - } catch (InterruptedException e) { - } - } - } - - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} - - // Unused routines - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} - } - - // We need to load the initial texture file early to get the width - // and height for the pbuffer - private void loadInitialTexture(String initialMapFilename) { - try { - initialMapData = TextureIO.newTextureData(getClass().getClassLoader().getResourceAsStream(initialMapFilename), - false, - FileUtil.getFileSuffix(initialMapFilename)); - } catch (IOException e) { - throw new GLException(e); - } - initialMapDimensions[0] = initialMapData.getWidth(); - initialMapDimensions[1] = initialMapData.getHeight(); - } - - private void initOpenGL(GL gl) { - try { - loadTextures(gl, tmpSpinFilename, tmpDropletFilename, tmpCubeMapFilenamePrefix, tmpCubeMapFilenameSuffix); - } catch (IOException e) { - throw new GLException(e); - } - tmpSpinFilename = null; - tmpDropletFilename = null; - tmpCubeMapFilenamePrefix = null; - tmpCubeMapFilenameSuffix = null; - - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glLoadIdentity(); - gl.glMatrixMode(GL.GL_PROJECTION); - gl.glLoadIdentity(); - glu.gluOrtho2D(-1, 1, -1, 1); - - gl.glClearColor(0, 0, 0, 0); - gl.glDisable(GL.GL_LIGHTING); - gl.glDisable(GL.GL_DEPTH_TEST); - - createAndWriteUVOffsets(gl, initialMapDimensions[0], initialMapDimensions[1]); - - checkExtension(gl, "GL_ARB_vertex_program"); - checkExtension(gl, "GL_ARB_fragment_program"); - checkExtension(gl, "GL_ARB_multitexture"); - - /////////////////////////////////////////////////////////////////////////// - // UV Offset Vertex Program - /////////////////////////////////////////////////////////////////////////// - - int[] tmpInt = new int[1]; - gl.glGenProgramsARB(1, tmpInt, 0); - vertexProgramID = tmpInt[0]; - gl.glBindProgramARB(GL.GL_VERTEX_PROGRAM_ARB, vertexProgramID); - - String programBuffer = -"!!ARBvp1.0\n" + -"# Constant memory location declarations (must match those in Java sources)\n" + -"# CV_UV_OFFSET_TO_USE = 0\n" + -"\n" + -"# CV_UV_T0_NO_OFFSET = 1\n" + -"# CV_UV_T0_TYPE1 = 2\n" + -"# CV_UV_T0_TYPE2 = 3\n" + -"# CV_UV_T0_TYPE3 = 4\n" + -"# CV_UV_T0_TYPE4 = 5\n" + -"\n" + -"# CV_UV_T1_NO_OFFSET = 6\n" + -"# CV_UV_T1_TYPE1 = 7\n" + -"# CV_UV_T1_TYPE2 = 8\n" + -"# CV_UV_T1_TYPE3 = 9\n" + -"# CV_UV_T1_TYPE4 = 10\n" + -"\n" + -"# CV_UV_T2_NO_OFFSET = 11\n" + -"# CV_UV_T2_TYPE1 = 12\n" + -"# CV_UV_T2_TYPE2 = 13\n" + -"# CV_UV_T2_TYPE3 = 14\n" + -"# CV_UV_T2_TYPE4 = 15\n" + -"\n" + -"# CV_UV_T3_NO_OFFSET = 16\n" + -"# CV_UV_T3_TYPE1 = 17\n" + -"# CV_UV_T3_TYPE2 = 18\n" + -"# CV_UV_T3_TYPE3 = 19\n" + -"# CV_UV_T3_TYPE4 = 20\n" + -"\n" + -"# CV_CONSTS_1 = 21\n" + -"\n" + -"# Parameters\n" + -"PARAM mvp [4] = { state.matrix.mvp }; # modelview projection matrix\n" + -"PARAM uvOffsetToUse = program.env[0];\n" + -"PARAM uvOffsets[20] = { program.env[1..20] };\n" + -"\n" + -"# Addresses\n" + -"ADDRESS addr;\n" + -"\n" + -"# Per vertex inputs\n" + -"ATTRIB iPos = vertex.position; #position\n" + -"\n" + -"# Outputs\n" + -"OUTPUT oPos = result.position; #position\n" + -"\n" + -"# Transform vertex-position to clip-space\n" + -"DP4 oPos.x, iPos, mvp[0];\n" + -"DP4 oPos.y, iPos, mvp[1];\n" + -"DP4 oPos.z, iPos, mvp[2];\n" + -"DP4 oPos.w, iPos, mvp[3];\n" + -"\n" + -"# Read which set of offsets to use\n" + -"ARL addr.x, uvOffsetToUse.x;\n" + -"\n" + -"# c[CV_CONSTS_1] = c[28]\n" + -"# x = 0\n" + -"# y = 0.5\n" + -"# z = 1\n" + -"# w = 2.0f\n" + -"\n" + -"# Put a scale factor into r0 so the sample points\n" + -"# can be moved farther from the texel being written\n" + -"# MOV R0, c[28].z;\n" + -"\n" + -"# Add the offsets to the input texture\n" + -"# coordinate, creating 4 sets of independent\n" + -"# texture coordinates.\n" + -"ADD result.texcoord[0], uvOffsets[addr.x ], vertex.texcoord[0];\n" + -"ADD result.texcoord[1], uvOffsets[addr.x + 5 ], vertex.texcoord[0];\n" + -"ADD result.texcoord[2], uvOffsets[addr.x + 10], vertex.texcoord[0];\n" + -"ADD result.texcoord[3], uvOffsets[addr.x + 15], vertex.texcoord[0];\n" + -"\n" + -"END\n"; - - // set up constants (not currently used in the vertex program, though) - float[] rCVConsts = new float[] { 0, 0.5f, 1.0f, 2.0f }; - gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_CONSTS_1, rCVConsts, 0); - - loadProgram(gl, GL.GL_VERTEX_PROGRAM_ARB, programBuffer); - - /////////////////////////////////////////////////////////////////////////// - // fragment program setup for equal weight combination of texels - /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_FRAGMENT_PROGRAM_EQ_WEIGHT_COMBINE] = gl.glGenLists(1); - initEqWeightCombine_PostMult(gl, displayListIDs[CA_FRAGMENT_PROGRAM_EQ_WEIGHT_COMBINE]); - - /////////////////////////////////////////////////////////////////////////// - // fragment program setup for computing force from neighbors (step 1) - /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_1] = gl.glGenLists(1); - initNeighborForceCalcStep1(gl, displayListIDs[CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_1]); - - /////////////////////////////////////////////////////////////////////////// - // fragment program setup for computing force from neighbors (step 2) - /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_2] = gl.glGenLists(1); - initNeighborForceCalcStep2(gl, displayListIDs[CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_2]); - - /////////////////////////////////////////////////////////////////////////// - // fragment program setup to apply force - /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_FORCE] = gl.glGenLists(1); - initApplyForce(gl, displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_FORCE]); - - /////////////////////////////////////////////////////////////////////////// - // fragment program setup to apply velocity - /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_VELOCITY] = gl.glGenLists(1); - initApplyVelocity(gl, displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_VELOCITY]); - - /////////////////////////////////////////////////////////////////////////// - // fragment program setup to create a normal map - /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_FRAGMENT_PROGRAM_CREATE_NORMAL_MAP] = gl.glGenLists(1); - initCreateNormalMap(gl, displayListIDs[CA_FRAGMENT_PROGRAM_CREATE_NORMAL_MAP]); - - /////////////////////////////////////////////////////////////////////////// - // fragment program setup for dot product reflection - /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_FRAGMENT_PROGRAM_REFLECT] = gl.glGenLists(1); - initDotProductReflect(gl, displayListIDs[CA_FRAGMENT_PROGRAM_REFLECT]); - - /////////////////////////////////////////////////////////////////////////// - // display list to render a single screen space quad. - /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_DRAW_SCREEN_QUAD] = gl.glGenLists(1); - gl.glNewList(displayListIDs[CA_DRAW_SCREEN_QUAD], GL.GL_COMPILE); - gl.glColor4f(1, 1, 1, 1); - gl.glBegin(GL.GL_TRIANGLE_STRIP); - gl.glTexCoord2f(0, 1); gl.glVertex2f(-1, 1); - gl.glTexCoord2f(0, 0); gl.glVertex2f(-1, -1); - gl.glTexCoord2f(1, 1); gl.glVertex2f( 1, 1); - gl.glTexCoord2f(1, 0); gl.glVertex2f( 1, -1); - gl.glEnd(); - gl.glEndList(); - } - - private void checkExtension(GL gl, String extensionName) { - if (!gl.isExtensionAvailable(extensionName)) { - throw new GLException("Unable to initialize " + extensionName + " OpenGL extension"); - } - } - - private void doSingleTimeStep(GL gl) { - int temp; - - // Swap texture source & target indices & pointers - // 0 = start from initial loaded texture - // 1/2 = flip flop back and forth between targets & sources - - switch (flipState) { - case 0: - texHeightInput = dynamicTextures[CA_TEXTURE_HEIGHT_SOURCE].getTextureObject(); // initial height map. - texHeightOutput = dynamicTextures[CA_TEXTURE_HEIGHT_TARGET].getTextureObject(); // next height map. - - texVelocityInput = dynamicTextures[CA_TEXTURE_VELOCITY_SOURCE].getTextureObject(); // initial velocity. - texVelocityOutput = dynamicTextures[CA_TEXTURE_VELOCITY_TARGET].getTextureObject(); // next velocity. - - // Clear initial velocity texture to 0x80 == gray - gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); - gl.glClear(GL.GL_COLOR_BUFFER_BIT); - - // Now we need to copy the resulting pixels into the intermediate force field texture - gl.glActiveTexture(GL.GL_TEXTURE0); - gl.glBindTexture(GL.GL_TEXTURE_2D, texVelocityInput); - - // use CopyTexSubImage for speed (even though we copy all of it) since we pre-allocated the texture - gl.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, 0, 0, initialMapDimensions[0], initialMapDimensions[1]); - - break; - - case 1: - temp = texHeightInput; - texHeightInput = texHeightOutput; - texHeightOutput = temp; - - temp = texVelocityInput; - texVelocityInput = texVelocityOutput; - texVelocityOutput = temp; - - break; - - case 2: - temp = texHeightInput; - texHeightInput = texHeightOutput; - texHeightOutput = temp; - - temp = texVelocityInput; - texVelocityInput = texVelocityOutput; - texVelocityOutput = temp; - break; - } - - // even if wireframe mode, render to texture as solid - gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); - - ///////////////////////////////////////////////////////////// - // Render first 3 components of force from three neighbors - // Offsets selected are 1 center texel for center height - // and 3 of the 4 nearest neighbors. Texture selected - // is same for all stages as we're turning height difference - // of nearest neightbor texels into a force value. - - gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_1]); - - // set current source texture for stage 0 texture - for (int i = 0; i < 4; i++) - { - gl.glActiveTexture(GL.GL_TEXTURE0 + i); - gl.glBindTexture(GL.GL_TEXTURE_2D, texHeightInput); - gl.glEnable(GL.GL_TEXTURE_2D); - } - - int wrapMode = wrap ? GL.GL_REPEAT : GL.GL_CLAMP_TO_EDGE; - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapMode); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapMode); - - // disable blending - gl.glDisable(GL.GL_BLEND); - - // render using offset 1 (type 1 -- center + 3 of 4 nearest neighbors). - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_OFFSET_TO_USE, 1, 0, 0, 0); - - // bind the vertex program to be used for this step and the next one. - gl.glBindProgramARB(GL.GL_VERTEX_PROGRAM_ARB, vertexProgramID); - gl.glEnable(GL.GL_VERTEX_PROGRAM_ARB); - - // render a screen quad. with texture coords doing difference of nearby texels for force calc. - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - - gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); - - // Now we need to copy the resulting pixels into the intermediate force field texture - gl.glActiveTexture(GL.GL_TEXTURE2); - dynamicTextures[CA_TEXTURE_FORCE_INTERMEDIATE].bind(); - - // use CopyTexSubImage for speed (even though we copy all of it) since we pre-allocated the texture - gl.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, 0, 0, initialMapDimensions[0], initialMapDimensions[1]); - - //////////////////////////////////////////////////////////////// - // Now add in last component of force for the 4th neighbor - // that we didn't have enough texture lookups to do in the - // first pass - - gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_2]); - - // Cannot use additive blending as the force contribution might - // be negative and would have to subtract from the dest. - // We must instead use an additional texture as target and read - // the previous partial 3-neighbor result into the pixel shader - // for possible subtraction - - // Alphablend must be false - - //; t0 = center (same as last phase) - //; t1 = 2nd axis final point (same as last phase) - //; t2 = previous partial result texture sampled at center (result of last phase copied to texture) - //; t3 = not used (disable now) - - gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapMode); - gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapMode); - - gl.glActiveTexture(GL.GL_TEXTURE3); - gl.glDisable(GL.GL_TEXTURE_2D); - - // vertex program already bound. - // render using offset 2 (type 2 -- final nearest neighbor plus center of previous result). - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_OFFSET_TO_USE, 2, 0, 0, 0); - - // render a screen quad - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - - gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); - - // Now we need to copy the resulting pixels into the intermediate force field texture - gl.glActiveTexture(GL.GL_TEXTURE1); - dynamicTextures[CA_TEXTURE_FORCE_TARGET].bind(); - - // use CopyTexSubImage for speed (even though we copy all of it) since we pre-allocated the texture - gl.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, 0, 0, initialMapDimensions[0], initialMapDimensions[1]); - - ///////////////////////////////////////////////////////////////// - // Apply the force with a scale factor to reduce it's magnitude. - // Add this to the current texture representing the water height. - - gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_FORCE]); - - // use offsets of zero - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_OFFSET_TO_USE, 0, 0, 0, 0); - - // bind the vertex program to be used for this step and the next one. - - gl.glActiveTexture(GL.GL_TEXTURE0); - gl.glBindTexture(GL.GL_TEXTURE_2D, texVelocityInput); - gl.glActiveTexture(GL.GL_TEXTURE1); - dynamicTextures[CA_TEXTURE_FORCE_TARGET].bind(); - gl.glActiveTexture(GL.GL_TEXTURE2); - gl.glDisable(GL.GL_TEXTURE_2D); - gl.glActiveTexture(GL.GL_TEXTURE3); - gl.glDisable(GL.GL_TEXTURE_2D); - - // Draw the quad to add in force. - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - - gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); - - /////////////////////////////////////////////////////////////////// - // With velocity texture selected, render new excitation droplets - // at random freq. - - float randomFrequency = (float) Math.random(); - - if (dropletFrequency > randomFrequency) { - // a drop falls - decide where - Droplet drop = new Droplet(2 * ((float)Math.random() - 0.5f), - 2 * ((float)Math.random() - 0.5f), - 0.02f + 0.1f * ((float)Math.random())); - addDroplet(drop); - } - - // Now draw the droplets: - if (!droplets.isEmpty()) { - drawDroplets(gl); - droplets.clear(); - } - - // Now we need to copy the resulting pixels into the velocity texture - gl.glActiveTexture(GL.GL_TEXTURE1); - gl.glBindTexture(GL.GL_TEXTURE_2D, texVelocityOutput); - - // use CopyTexSubImage for speed (even though we copy all of it) since we pre-allocated the texture - gl.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, 0, 0, initialMapDimensions[0], initialMapDimensions[1]); - - ////////////////////////////////////////////////////////////////////// - // Apply velocity to position - gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_VELOCITY]); - gl.glEnable(GL.GL_VERTEX_PROGRAM_ARB); - - gl.glActiveTexture(GL.GL_TEXTURE0); - gl.glBindTexture(GL.GL_TEXTURE_2D, texHeightInput); - gl.glActiveTexture(GL.GL_TEXTURE1); // velocity output already bound - gl.glEnable(GL.GL_TEXTURE_2D); - - // use offsets of zero - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_OFFSET_TO_USE, 0, 0, 0, 0); - - // Draw the quad to add in force. - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - - gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); - - // Now we need to copy the resulting pixels into the input height texture - gl.glActiveTexture(GL.GL_TEXTURE0); - gl.glBindTexture(GL.GL_TEXTURE_2D, texHeightInput); - - // use CopyTexSubImage for speed (even though we copy all of it) since we pre-allocated the texture - gl.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, 0, 0, initialMapDimensions[0], initialMapDimensions[1]); - - /////////////////////////////////////////////////////////////////// - // blur positions to smooth noise & generaly dampen things - // degree of blur is controlled by magnitude of 4 neighbor texel - // offsets with bilinear on - - for (int i = 1; i < 4; i++) { - gl.glActiveTexture(GL.GL_TEXTURE0 + i); - gl.glBindTexture(GL.GL_TEXTURE_2D, texHeightInput); - gl.glEnable(GL.GL_TEXTURE_2D); - } - - // use offsets of 3 - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_OFFSET_TO_USE, 3, 0, 0, 0); - - gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_EQ_WEIGHT_COMBINE]); - - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); - - // Draw the logo in the water. - if (applyInteriorBoundaries) { - gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB); - drawInteriorBoundaryObjects(gl); - } - - // Now we need to copy the resulting pixels into the velocity texture - gl.glActiveTexture(GL.GL_TEXTURE0); - gl.glBindTexture(GL.GL_TEXTURE_2D, texHeightOutput); - - // use CopyTexSubImage for speed (even though we copy all of it) since we pre-allocated the texture - gl.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, 0, 0, initialMapDimensions[0], initialMapDimensions[1]); - - /////////////////////////////////////////////////////////////////// - // If selected, create a normal map from the height - - if (createNormalMap) { - createNormalMap(gl); - } - - /////////////////////////////////////////////////////////// - // Flip the state variable for the next round of rendering - switch (flipState) { - case 0: - flipState = 1; - break; - case 1: - flipState = 2; - break; - case 2: - flipState = 1; - break; - } - } - - private void createNormalMap(GL gl) { - // use the height output on all four texture stages - for (int i = 0; i < 4; i++) { - gl.glActiveTexture(GL.GL_TEXTURE0 + i); - gl.glBindTexture(GL.GL_TEXTURE_2D, texHeightOutput); - gl.glEnable(GL.GL_TEXTURE_2D); - } - - // Set constants for red & green scale factors (also essential color masks) - // Red mask first - float[] pixMasks = new float[] { normalSTScale, 0.0f, 0.0f, 0.0f }; - - gl.glProgramEnvParameter4fvARB(GL.GL_FRAGMENT_PROGRAM_ARB, 0, pixMasks, 0); - - // Now green mask & scale: - pixMasks[0] = 0.0f; - pixMasks[1] = normalSTScale; - gl.glProgramEnvParameter4fvARB(GL.GL_FRAGMENT_PROGRAM_ARB, 1, pixMasks, 0); - - gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_CREATE_NORMAL_MAP]); - - // set vp offsets to nearest neighbors - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_OFFSET_TO_USE, 4, 0, 0, 0); - gl.glEnable(GL.GL_VERTEX_PROGRAM_ARB); - - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - - gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); - - // Now we need to copy the resulting pixels into the normal map - gl.glActiveTexture(GL.GL_TEXTURE0); - dynamicTextures[CA_TEXTURE_NORMAL_MAP].bind(); - - // use CopyTexSubImage for speed (even though we copy all of it) since we pre-allocated the texture - gl.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, 0, 0, initialMapDimensions[0], initialMapDimensions[1]); - } - - private void drawInteriorBoundaryObjects(GL gl) { - gl.glDisable(GL.GL_REGISTER_COMBINERS_NV); - - gl.glActiveTexture(GL.GL_TEXTURE0); - initialMapTex.bind(); - initialMapTex.enable(); - - gl.glEnable(GL.GL_ALPHA_TEST); - - // disable other texture units. - for (int i = 1; i < 4; i++) { - gl.glActiveTexture(GL.GL_TEXTURE0 + i); - gl.glDisable(GL.GL_TEXTURE_2D); - } - - gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); - gl.glEnable(GL.GL_BLEND); - - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - - if (spinLogo) { - gl.glActiveTexture(GL.GL_TEXTURE0); - spinTex.bind(); - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glPushMatrix(); - gl.glRotatef(angle, 0, 0, 1); - angle += 1; - - gl.glCallList(displayListIDs[CA_DRAW_SCREEN_QUAD]); - - gl.glPopMatrix(); - } - - gl.glDisable(GL.GL_ALPHA_TEST); - gl.glDisable(GL.GL_BLEND); - } - - private void loadTextures(GL gl, - String spinFilename, - String dropletFilename, - String cubeMapFilenamePrefix, - String cubeMapFilenameSuffix) throws IOException { - if (initialMapData == null) { - throw new GLException("Must call loadInitialTexture ahead of time"); - } - - initialMapTex = TextureIO.newTexture(initialMapData); - spinTex = TextureIO.newTexture(getClass().getClassLoader().getResourceAsStream(spinFilename), false, - FileUtil.getFileSuffix(spinFilename)); - dropletTex = TextureIO.newTexture(getClass().getClassLoader().getResourceAsStream(dropletFilename), false, - FileUtil.getFileSuffix(dropletFilename)); - - // load the cubemap texture - cubemap = Cubemap.loadFromStreams(getClass().getClassLoader(), - cubeMapFilenamePrefix, - cubeMapFilenameSuffix, - true); - - // now create dummy intermediate textures from the initial map texture - for (int i = 0; i < CA_NUM_DYNAMIC_TEXTURES; i++) { - dynamicTextures[i] = TextureIO.newTexture(initialMapData); - } - - initialMapData = null; - - texHeightInput = initialMapTex.getTextureObject(); // initial height map. - texHeightOutput = dynamicTextures[CA_TEXTURE_HEIGHT_TARGET].getTextureObject(); // next height map. - - texVelocityInput = dynamicTextures[CA_TEXTURE_VELOCITY_SOURCE].getTextureObject(); // initial velocity. - texVelocityOutput = dynamicTextures[CA_TEXTURE_VELOCITY_TARGET].getTextureObject(); // next velocity. - } - - private void createAndWriteUVOffsets(GL gl, int width, int height) { - // This sets vertex shader constants used to displace the - // source texture over several additive samples. This is - // used to accumulate neighboring texel information that we - // need to run the game - the 8 surrounding texels, and the - // single source texel which will either spawn or die in the - // next generation. - // Label the texels as follows, for a source texel "e" that - // we want to compute for the next generation: - // - // abc - // def - // ghi: - - // first the easy one: no offsets for sampling center - // occupied or unoccupied - // Use index offset value 0.0 to access these in the - // vertex shader. - - perTexelWidth = 1.0f / width; - perTexelHeight = 1.0f / height; - - // Offset set 0 : center texel sampling - float[] noOffsetX = new float[] { 0, 0, 0, 0 }; - float[] noOffsetY = new float[] { 0, 0, 0, 0 }; - - // Offset set 1: For use with neighbor force pixel shader 1 - // samples center with 0, +u, -u, and +v, - // ie the 'e','d', 'f', and 'h' texels - float dist = 1.5f; - float[] type1OffsetX = new float[] { 0.0f, -dist * perTexelWidth, dist * perTexelWidth, dist * perTexelWidth }; - float[] type1OffsetY = new float[] { 0.0f, dist * perTexelHeight, dist * perTexelHeight, -dist * perTexelHeight }; - - // Offset set 2: for use with neighbor force pixel shader 2 - // samples center with 0, and -v texels - // ie the 'e' and 'b' texels - // This completes a pattern of sampling center texel and it's - // 4 nearest neighbors to run the height-based water simulation - // 3rd must be 0 0 to sample texel center from partial result - // texture. - - float[] type2OffsetX = new float[] { 0.0f, -dist * perTexelWidth, 0.0f, 0.0f }; - float[] type2OffsetY = new float[] { 0.0f, -dist * perTexelHeight, 0.0f, 0.0f }; - - // type 3 offsets - updateBlurVertOffset(gl); - - ///////////////////////////////////////////////////////////// - // Nearest neighbor offsets: - - float[] type4OffsetX = new float[] { -perTexelWidth, perTexelWidth, 0.0f, 0.0f }; - float[] type4OffsetY = new float[] { 0.0f, 0.0f, -perTexelHeight, perTexelHeight }; - - // write all these offsets to constant memory - for (int i = 0; i < 4; ++i) { - float noOffset[] = { noOffsetX[i], noOffsetY[i], 0.0f, 0.0f }; - float type1Offset[] = { type1OffsetX[i], type1OffsetY[i], 0.0f, 0.0f }; - float type2Offset[] = { type2OffsetX[i], type2OffsetY[i], 0.0f, 0.0f }; - float type4Offset[] = { type4OffsetX[i], type4OffsetY[i], 0.0f, 0.0f }; - - gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_T0_NO_OFFSET + 5 * i, noOffset, 0); - gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_T0_TYPE1 + 5 * i, type1Offset, 0); - gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_T0_TYPE2 + 5 * i, type2Offset, 0); - gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_T0_TYPE4 + 5 * i, type4Offset, 0); - } - } - - private void updateBlurVertOffset(GL gl) { - float[] type3OffsetX = new float[] { -perTexelWidth * 0.5f, - perTexelWidth, - perTexelWidth * 0.5f, - -perTexelWidth - }; - float[] type3OffsetY = new float[] { perTexelHeight, - perTexelHeight * 0.5f, - -perTexelHeight, - -perTexelHeight * 0.5f - }; - float[] offsets = new float[] { 0, 0, 0, 0 }; - - for (int i = 0; i < 4; ++i) { - offsets[0] = blurDist * ( type3OffsetX[i]); - offsets[1] = blurDist * ( type3OffsetY[i]); - gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_T0_TYPE3 + 5 * i, offsets, 0); - } - } - - private synchronized void drawDroplets(GL gl) { - gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); - gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB); - - gl.glActiveTexture(GL.GL_TEXTURE0); - dropletTex.bind(); - dropletTex.enable(); - - gl.glActiveTexture(GL.GL_TEXTURE1); - gl.glDisable(GL.GL_TEXTURE_2D); - - gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE); - gl.glEnable(GL.GL_BLEND); - - gl.glBegin(GL.GL_QUADS); - gl.glColor4f(1, 1, 1, 1); - for (Iterator iter = droplets.iterator(); iter.hasNext(); ) { - Droplet droplet = (Droplet) iter.next(); - // coords in [-1,1] range - - // Draw a single quad to the texture render target - // The quad is textured with the initial droplet texture, and - // covers some small portion of the render target - // Draw the droplet - - gl.glTexCoord2f(0, 0); gl.glVertex2f(droplet.rX() - droplet.rScale(), droplet.rY() - droplet.rScale()); - gl.glTexCoord2f(1, 0); gl.glVertex2f(droplet.rX() + droplet.rScale(), droplet.rY() - droplet.rScale()); - gl.glTexCoord2f(1, 1); gl.glVertex2f(droplet.rX() + droplet.rScale(), droplet.rY() + droplet.rScale()); - gl.glTexCoord2f(0, 1); gl.glVertex2f(droplet.rX() - droplet.rScale(), droplet.rY() + droplet.rScale()); - } - gl.glEnd(); - - gl.glDisable(GL.GL_BLEND); - } - - //---------------------------------------------------------------------- - // Inlined register combiner and texture shader programs - // (don't want to port nvparse as it's a dead-end; we'll focus on Cg instead) - - private void initEqWeightCombine_PostMult(GL gl, int displayListID) { - // Take samples of all four texture inputs and average them, - // adding on a bias - // - // Original register combiner program: - // - // Stage 0 - // rgb - // { - // discard = half_bias(tex0); - // discard = half_bias(tex1); - // spare0 = sum(); - // scale_by_one_half(); - // } - // Stage 1 - // rgb - // { - // discard = half_bias(tex2); - // discard = half_bias(tex3); - // spare1 = sum(); - // scale_by_one_half(); - // } - // Stage 2 - // rgb - // { - // discard = spare0; - // discard = spare1; - // spare0 = sum(); - // scale_by_one_half(); - // } - // Stage 3 - // rgb - // { - // discard = const0; - // discard = spare0; - // spare0 = sum(); - // } - - float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - - int[] tmpInt = new int[1]; - gl.glGenProgramsARB(1, tmpInt, 0); - int fragProg = tmpInt[0]; - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - - String program = -"!!ARBfp1.0\n" + -"PARAM const0 = program.env[0];\n" + -"PARAM oneQtr = { 0.25, 0.25, 0.25, 0.25 };\n" + -"PARAM two = { 2.0, 2.0, 2.0, 2.0 };\n" + -"TEMP texSamp0, texSamp1, texSamp2, texSamp3;\n" + -"TEMP spare0, spare1;\n" + -"\n" + -"TEX texSamp0, fragment.texcoord[0], texture[0], 2D;\n" + -"TEX texSamp1, fragment.texcoord[1], texture[1], 2D;\n" + -"TEX texSamp2, fragment.texcoord[2], texture[2], 2D;\n" + -"TEX texSamp3, fragment.texcoord[3], texture[3], 2D;\n" + -"ADD spare0, texSamp0, texSamp1;\n" + -"ADD spare1, texSamp2, texSamp3;\n" + -"ADD spare0, spare0, spare1;\n" + -"SUB spare0, spare0, two;\n" + -"MAD result.color, oneQtr, spare0, const0;\n" + -"\n" + -"END\n"; - - loadProgram(gl, GL.GL_FRAGMENT_PROGRAM_ARB, program); - - gl.glNewList(displayListID, GL.GL_COMPILE); - gl.glProgramEnvParameter4fvARB(GL.GL_FRAGMENT_PROGRAM_ARB, 0, const0, 0); - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); - gl.glEndList(); - } - - private void initNeighborForceCalcStep1(GL gl, int displayListID) { - // Step one in the nearest-neighbor force calculation for height-based water - // simulation. NeighborForceCalc2 is the second step. - // - // This step takes the center point and three neighboring points, and computes - // the texel difference as the "force" acting to pull the center texel. - // - // The amount to which the computed force is applied to the texel is controlled - // in a separate shader. - - // get colors from all 4 texture stages - // tex0 = center texel - // tex1 = 1st neighbor - // tex2 = 2nd neighbor - same axis as 1st neighbor point - // so force for that axis == t1 - t0 + t2 - t0 - // tex3 = 3rd neighbor on other axis - - // Original register combiner program: - // - // Stage 0 - // rgb - // { - // //s0 = t1 - t0; - // discard = -tex0; - // discard = tex1; - // spare0 = sum(); - // } - // Stage 1 - // rgb - // { - // //s1 = t2 - t0; - // discard = -tex0; - // discard = tex2; - // spare1 = sum(); - // } - // Stage 2 - // // 'force' for 1st axis - // rgb - // { - // //s0 = s0 + s1 = t1 - t0 + t2 - t0; - // discard = spare0; - // discard = spare1; - // spare0 = sum(); - // } - // Stage 3 - // // one more point for 2nd axis - // rgb - // { - // //s1 = t3 - t0; - // discard = -tex0; - // discard = tex3; - // spare1 = sum(); - // } - // Stage 4 - // rgb - // { - // //s0 = s0 + s1 = t3 - t0 + t2 - t0 + t1 - t0; - // discard = spare0; - // discard = spare1; - // spare0 = sum(); - // } - // Stage 5 - // // Now add in a force to gently pull the center texel's - // // value to 0.5. The strength of this is controlled by - // // the PCN_EQ_REST_FAC - restoration factor - // // Without this, the simulation will fade to zero or fly - // // away to saturate at 1.0 - // rgb - // { - // //s1 = 0.5 - t0; - // discard = -tex0; - // discard = const0; - // spare1 = sum(); - // } - // Stage 6 - // { - // rgb - // { - // discard = spare1 * const0; - // discard = spare0; - // spare0 = sum(); - // } - // } - // Stage 7 - // rgb - // { - // discard = spare0; - // discard = const0; - // spare0 = sum(); - // } - - float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - - int[] tmpInt = new int[1]; - gl.glGenProgramsARB(1, tmpInt, 0); - int fragProg = tmpInt[0]; - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - - String program = -"!!ARBfp1.0\n" + -"PARAM const0 = program.env[0];\n" + -"PARAM three = { 3, 3, 3, 1.0 };\n" + -"TEMP texSamp0, texSamp1, texSamp2, texSamp3;\n" + -"TEMP spare0, spare1;\n" + -"\n" + -"TEX texSamp0, fragment.texcoord[0], texture[0], 2D;\n" + -"TEX texSamp1, fragment.texcoord[1], texture[1], 2D;\n" + -"TEX texSamp2, fragment.texcoord[2], texture[2], 2D;\n" + -"TEX texSamp3, fragment.texcoord[3], texture[3], 2D;\n" + -"ADD spare0, texSamp1, texSamp2;\n" + -"MAD spare1, const0, const0, const0;\n" + -"ADD spare0, texSamp3, spare0;\n" + -"ADD spare0, spare1, spare0;\n" + -"ADD spare1, three, const0;\n" + -"MAD result.color, -spare1, texSamp0, spare0;\n" + - -// Faster version which hardcodes in value of const0: -//"ADD spare0, texSamp1, texSamp2;\n" + -//"ADD spare1, texSamp3, pointSevenFive;\n" + -//"ADD spare0, spare0, spare1;\n" + -//"MAD result.color, minusThreePointFive, texSamp0, spare0;\n" + - -// Straightforward port: -//"SUB spare0, texSamp1, texSamp0;\n" + -//"SUB spare1, texSamp2, texSamp0;\n" + -//"ADD spare0, spare0, spare1;\n" + -//"SUB spare1, texSamp3, texSamp0;\n" + -//"ADD spare0, spare0, spare1;\n" + -//"SUB spare1, const0, texSamp0;\n" + -//"MAD spare0, const0, spare1, spare0;\n" + -//"ADD result.color, spare0, const0;\n" + - -"\n" + -"END\n"; - - loadProgram(gl, GL.GL_FRAGMENT_PROGRAM_ARB, program); - - gl.glNewList(displayListID, GL.GL_COMPILE); - gl.glProgramEnvParameter4fvARB(GL.GL_FRAGMENT_PROGRAM_ARB, 0, const0, 0); - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); - gl.glEndList(); - } - - private void initNeighborForceCalcStep2(GL gl, int displayListID) { - // 2nd step of force calc for render-to-texture - // water simulation. - // - // Adds the 4th & final neighbor point to the - // force calc.. - // - // Bias and scale the values so 0 force is 0.5, - // full negative force is 0.0, and full pos is - // 1.0 - // - // tex0 Center texel - // tex1 2nd axis neighbor point - // tex2 previous partial force amount - // Result from t1 - t0 is added to this t2 - // partial result & output - - // Original register combiner program: - // - // Stage 0 - // last element of neighbor force - // rgb - // { - // discard = -tex0; - // discard = tex1; - // spare0 = sum(); - // } - // Stage 1 - // add with previous partial force amount - // rgb - // { - // discard = spare0; - // discard = tex2; - // spare0 = sum(); - // } - - int[] tmpInt = new int[1]; - gl.glGenProgramsARB(1, tmpInt, 0); - int fragProg = tmpInt[0]; - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - - String program = -"!!ARBfp1.0\n" + -"PARAM const0 = program.env[0];\n" + -"TEMP texSamp0, texSamp1, texSamp2;\n" + -"TEMP spare0;\n" + -"\n" + -"TEX texSamp0, fragment.texcoord[0], texture[0], 2D;\n" + -"TEX texSamp1, fragment.texcoord[1], texture[1], 2D;\n" + -"TEX texSamp2, fragment.texcoord[2], texture[2], 2D;\n" + -"SUB spare0, texSamp1, texSamp0;\n" + -"ADD result.color, spare0, texSamp2;\n" + -"\n" + -"END\n"; - - loadProgram(gl, GL.GL_FRAGMENT_PROGRAM_ARB, program); - - gl.glNewList(displayListID, GL.GL_COMPILE); - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); - gl.glEndList(); - } - - private void initApplyForce(GL gl, int displayListID) { - // This shader samples t1, biases its value to a signed number, and applies this - // value multiplied by a scale factor to the t0 sample. - // - // This is used to apply a "force" texture value to a "velocity" state texture - // for nearest-neighbor height-based water simulations. The output pixel is - // the new "velocity" value to replace the t0 sample in rendering to a new - // texture which will replace the texture selected into t0. - // - // A nearly identical shader using a different scaling constant is used to - // apply the "velocity" value to a "height" texture at each texel. - // - // t1 comes in the range [0,1] but needs to hold signed values, so a value of - // 0.5 in t1 represents zero force. This is biased to a signed value in - // computing the new velocity. - // - // tex0 = previous velocity - // tex1 = force - // - // Bias the force so that 0.5 input = no change in t0 value - // and 0.0 input means -0.5 * scale change in t0 value - // - // New velocity = force * scale + previous velocity - - // Original register combiner program: - // - // Stage 0 - // rgb - // { - // discard = expand(tex1) * const0; - // discard = expand(tex0); - // spare0 = sum(); - // scale_by_one_half(); - // } - // Stage 1 - // rgb - // { - // discard = spare0; - // discard = const1; - // spare0 = sum(); - // } - - float[] const0 = new float[] { 0.25f, 0.25f, 0.25f, 1.0f }; - float[] const1 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - - int[] tmpInt = new int[1]; - gl.glGenProgramsARB(1, tmpInt, 0); - int fragProg = tmpInt[0]; - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - - String program = -"!!ARBfp1.0\n" + -"PARAM const0 = program.env[0];\n" + -"PARAM const1 = program.env[1];\n" + -"PARAM one = { 1.0, 1.0, 1.0, 0.0 };\n" + -"PARAM oneHalf = { 0.5, 0.5, 0.5, 1.0 };\n" + -"PARAM two = { 2.0, 2.0, 2.0, 1.0 };\n" + -"TEMP texSamp0, texSamp1;\n" + -"TEMP spare0, spare1;\n" + -"\n" + -"TEX texSamp0, fragment.texcoord[0], texture[0], 2D;\n" + -"TEX texSamp1, fragment.texcoord[1], texture[1], 2D;\n" + -"MAD spare0, two, texSamp1, -one;\n" + -"MAD spare1, two, texSamp0, -one;\n" + -"MAD spare0, spare0, const0, spare1;\n" + -"MAD result.color, oneHalf, spare0, const1;\n" + -"\n" + -"END\n"; - - loadProgram(gl, GL.GL_FRAGMENT_PROGRAM_ARB, program); - - gl.glNewList(displayListID, GL.GL_COMPILE); - gl.glProgramEnvParameter4fvARB(GL.GL_FRAGMENT_PROGRAM_ARB, 0, const0, 0); - gl.glProgramEnvParameter4fvARB(GL.GL_FRAGMENT_PROGRAM_ARB, 1, const1, 0); - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); - gl.glEndList(); - } - - private void initApplyVelocity(GL gl, int displayListID) { - // This shader samples t1, biases its value to a signed number, and applies this - // value multiplied by a scale factor to the t0 sample. - // - // This is used to apply a "velocity" texture value to a "height" state texture - // for nearest-neighbor height-based water simulations. The output pixel is - // the new "height" value to replace the t0 sample in rendering to a new - // texture which will replace the texture selected into t0. - // - // A nearly identical shader using a different scaling constant is used to - // apply the "force" value to the "velocity" texture at each texel. - // - // t1 comes in the range [0,1] but needs to hold signed values, so a value of - // 0.5 in t1 represents zero velocity. This is biased to a signed value in - // computing the new position. - // - // tex0 = height field - // tex1 = velocity - // - // Bias the force/velocity to a signed value so we can subtract from - // the t0 position sample. - // - // New height = velocity * scale factor + old height - - // Original register combiner program: - // - // Stage 0 - // rgb - // { - // discard = expand(tex1) * const0; - // discard = expand(tex0); - // spare0 = sum(); - // scale_by_one_half(); - // } - // Stage 1 - // rgb - // { - // discard = spare0; - // discard = const0; - // spare0 = sum(); - // } - // } - - float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - - int[] tmpInt = new int[1]; - gl.glGenProgramsARB(1, tmpInt, 0); - int fragProg = tmpInt[0]; - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - - String program = -"!!ARBfp1.0\n" + -"PARAM const0 = program.env[0];\n" + -"PARAM one = { 1.0, 1.0, 1.0, 0.0 };\n" + -"PARAM oneHalf = { 0.5, 0.5, 0.5, 1.0 };\n" + -"PARAM two = { 2.0, 2.0, 2.0, 1.0 };\n" + -"TEMP texSamp0, texSamp1;\n" + -"TEMP spare0, spare1;\n" + -"\n" + -"TEX texSamp0, fragment.texcoord[0], texture[0], 2D;\n" + -"TEX texSamp1, fragment.texcoord[1], texture[1], 2D;\n" + -"MAD spare0, two, texSamp1, -one;\n" + -"MAD spare1, two, texSamp0, -one;\n" + -"MAD spare0, spare0, const0, spare1;\n" + -"MAD result.color, oneHalf, spare0, const0;\n" + -"\n" + -"END\n"; - - loadProgram(gl, GL.GL_FRAGMENT_PROGRAM_ARB, program); - - gl.glNewList(displayListID, GL.GL_COMPILE); - gl.glProgramEnvParameter4fvARB(GL.GL_FRAGMENT_PROGRAM_ARB, 0, const0, 0); - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); - gl.glEndList(); - } - - private void initCreateNormalMap(GL gl, int displayListID) { - // Neighbor-differencing for RGB normal map creation. Scale factors for s and t - // axis components are set in program code. - // This does a crude 1-s^2-t^2 calculation for the blue component in order to - // approximately normalize the RGB normal map vector. For s^2+t^2 close to 1.0, - // this is a close approximation to blue = sqrt(1 - s^2 - t^2) which would give a - // normalized vector. - // An additional pass with a dependent texture lookup (alpha-red or green-blue) - // could be used to produce an exactly normalized normal. - - // colors from all 4 texture stages - // tex0 = -s, 0 - // tex1 = +s, 0 - // tex2 = 0, +t - // tex3 = 0, -t - - // Original register combiner program: - // - // Stage 0 - // rgb - // { - // // (t0 - t1)*4 : 4 for higher scale - // discard = -tex1; - // discard = tex0; - // spare0 = sum(); - // scale_by_four(); - // } - // Stage 1 - // rgb - // { - // // (t3 - t2)*4 : 4 for higher scale - // discard = -tex2; - // discard = tex3; - // spare1 = sum(); - // scale_by_four(); - // } - // Stage 2 - // Define const0 in the third general combiner as RGBA = (scale, 0, 0, 0) - // Where scale [0,1] is applied to reduce the magnitude - // of the s axis component of the normal. - // Define const1 in the third combiner similarly to affect the t axis component - // define these by "ramboing" them in the C++ code that uses this combiner script. - // Note: these variables have been renamed to "redMask" and "greenMask" in - // the fragment program below. - // rgb - // { - // // see comment about consts above! - // // t0 = s result in red only - // discard = spare0 * const0; - // discard = spare1 * const1; - // spare0 = sum(); - // } - // Stage 3 - // rgb - // { - // tex1 = spare0 * spare0; - // scale_by_two(); - // } - // Stage 4 - // const0 = (1, 1, 0, 0); - // rgb - // { - // spare1 = unsigned_invert(tex1) . const0; - // scale_by_one_half(); - // } - // Stage 5 - // const0 = (0.5, 0.5, 0, 0); - // rgb - // { - // discard = spare0; - // discard = const0; - // spare0 = sum(); - // } - // Stage 6 - // const0 = (0, 0, 1, 1); - // rgb - // { - // discard = spare1 * const0; - // discard = spare0; - // spare0 = sum(); - // } - - - float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - - int[] tmpInt = new int[1]; - gl.glGenProgramsARB(1, tmpInt, 0); - int fragProg = tmpInt[0]; - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - - String program = -"!!ARBfp1.0\n" + -"PARAM redMask = program.env[0];\n" + -"PARAM greenMask = program.env[1];\n" + -"PARAM const0 = { 1.0, 1.0, 0.0, 0.0 };\n" + -"PARAM const1 = { 0.5, 0.5, 0.0, 0.0 };\n" + -"PARAM const2 = { 0.0, 0.0, 1.0, 1.0 };\n" + -"PARAM one = { 1.0, 1.0, 1.0, 0.0 };\n" + -"PARAM oneHalf = { 0.5, 0.5, 0.5, 1.0 };\n" + -"PARAM two = { 2.0, 2.0, 2.0, 1.0 };\n" + -"PARAM four = { 4.0, 4.0, 4.0, 1.0 };\n" + -"TEMP texSamp0, texSamp1, texSamp2, texSamp3;\n" + -"TEMP spare0, spare1, spare2;\n" + -"\n" + -"TEX texSamp0, fragment.texcoord[0], texture[0], 2D;\n" + -"TEX texSamp1, fragment.texcoord[1], texture[1], 2D;\n" + -"TEX texSamp2, fragment.texcoord[2], texture[2], 2D;\n" + -"TEX texSamp3, fragment.texcoord[3], texture[3], 2D;\n" + -"SUB spare0, texSamp0, texSamp1;\n" + -"MUL spare0, spare0, four;\n" + -"SUB spare1, texSamp3, texSamp2;\n" + -"MUL spare1, spare1, four;\n" + -"MUL spare0, spare0, redMask;\n" + -"MAD spare0, greenMask, spare1, spare0;\n" + -"MUL_SAT spare2, spare0, spare0;\n" + -"SUB spare2, one, spare2;\n" + -"DP3 spare1, spare2, const0;\n" + -"ADD spare0, spare0, const1;\n" + -"MAD result.color, const2, spare1, spare0;\n" + -"\n" + -"END\n"; - - loadProgram(gl, GL.GL_FRAGMENT_PROGRAM_ARB, program); - - gl.glNewList(displayListID, GL.GL_COMPILE); - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); - gl.glEndList(); - } - - private void initDotProductReflect(GL gl, int displayListID) { - // Pseudocode for this operation, derived from the NVidia - // texture_shader.txt documentation at - // http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_shader.txt - - // TEX texSamp0, fragment.texcoord[0], texture[0], 2D; - // MAD texSamp0, two, texSamp0, minusOne; - // TEMP dotPP = texSamp0 . texcoord[1]; - // TEMP dotP = texSamp0 . texcoord[2]; - // TEMP dotC = texSamp0 . texcoord[3]; - // TEMP R, N, E; - // N = [dotPP, dotP, dotC]; - // ooNLength = N dot N; - // RCP ooNLength, ooNLength; - // E = [texcoord[1].w, texcoord[2].w, texcoord[3].w]; - // nDotE = N dot E; - // MUL R, nDotE, N; - // MUL R, R, two; - // MUL R, R, ooNLength; - // SUB R, R, E; - // TEX result.color, R, texture[3], CUBE; - - // This fragment program is pretty length-sensitive; making it too - // big causes the frame rate to be cut in half on my machine - // (Quadro FX Go700) due to sync-to-vertical-refresh. The program - // below is more optimized in its use of temporaries. Some of the - // scaling operations on the first component of the normal vector - // (before subtracting off the E vector) don't appear to make much - // of a visual difference so they are skipped as well. - - int[] tmpInt = new int[1]; - gl.glGenProgramsARB(1, tmpInt, 0); - int fragProg = tmpInt[0]; - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - - String program = -"!!ARBfp1.0\n" + -"PARAM minusOne = { -1.0, -1.0, -1.0, 0.0 };\n" + -"PARAM two = { 2.0, 2.0, 2.0, 0.0 };\n" + -"TEMP texSamp0, R, N, E;\n" + -"\n" + -"TEX texSamp0, fragment.texcoord[0], texture[0], 2D;\n" + -"MAD texSamp0, two, texSamp0, minusOne;\n" + -"DP3 N.x, texSamp0, fragment.texcoord[1];\n" + -"DP3 N.y, texSamp0, fragment.texcoord[2];\n" + -"DP3 N.z, texSamp0, fragment.texcoord[3];\n" + -"MOV E.x, fragment.texcoord[1].w;\n" + -"MOV E.y, fragment.texcoord[2].w;\n" + -"MOV E.z, fragment.texcoord[3].w;\n" + -"MUL N, N, two;\n" + -"SUB R, N, E;\n" + -"TEX result.color, R, texture[3], CUBE;\n" + -"\n" + -"END"; - - loadProgram(gl, GL.GL_FRAGMENT_PROGRAM_ARB, program); - - gl.glNewList(displayListID, GL.GL_COMPILE); - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); - gl.glEndList(); - } - - private void loadProgram(GL gl, - int target, - String programBuffer) { - gl.glProgramStringARB(target, GL.GL_PROGRAM_FORMAT_ASCII_ARB, programBuffer.length(), programBuffer); - int[] errPos = new int[1]; - gl.glGetIntegerv(GL.GL_PROGRAM_ERROR_POSITION_ARB, errPos, 0); - if (errPos[0] >= 0) { - String kind = "Program"; - if (target == GL.GL_VERTEX_PROGRAM_ARB) { - kind = "Vertex program"; - } else if (target == GL.GL_FRAGMENT_PROGRAM_ARB) { - kind = "Fragment program"; - } - System.out.println(kind + " failed to load:"); - String errMsg = gl.glGetString(GL.GL_PROGRAM_ERROR_STRING_ARB); - if (errMsg == null) { - System.out.println("[No error message available]"); - } else { - System.out.println("Error message: \"" + errMsg + "\""); - } - System.out.println("Error occurred at position " + errPos[0] + " in program:"); - int endPos = errPos[0]; - while (endPos < programBuffer.length() && programBuffer.charAt(endPos) != '\n') { - ++endPos; - } - System.out.println(programBuffer.substring(errPos[0], endPos)); - throw new GLException("Error loading " + kind); - } else { - if (target == GL.GL_FRAGMENT_PROGRAM_ARB) { - int[] isNative = new int[1]; - gl.glGetProgramivARB(GL.GL_FRAGMENT_PROGRAM_ARB, - GL.GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, - isNative, 0); - if (isNative[0] != 1) { - System.out.println("WARNING: fragment program is over native resource limits"); - Thread.dumpStack(); - } - } - } - } -} |