summaryrefslogtreecommitdiffstats
path: root/src/demos/proceduralTexturePhysics/Water.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/demos/proceduralTexturePhysics/Water.java')
-rw-r--r--src/demos/proceduralTexturePhysics/Water.java1844
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();
- }
- }
- }
- }
-}