diff options
Diffstat (limited to 'src/demos/proceduralTexturePhysics')
-rw-r--r-- | src/demos/proceduralTexturePhysics/ProceduralTexturePhysics.java | 9 | ||||
-rw-r--r-- | src/demos/proceduralTexturePhysics/Water.java | 1212 |
2 files changed, 526 insertions, 695 deletions
diff --git a/src/demos/proceduralTexturePhysics/ProceduralTexturePhysics.java b/src/demos/proceduralTexturePhysics/ProceduralTexturePhysics.java index 03ef552..9fa329d 100644 --- a/src/demos/proceduralTexturePhysics/ProceduralTexturePhysics.java +++ b/src/demos/proceduralTexturePhysics/ProceduralTexturePhysics.java @@ -48,11 +48,11 @@ import gleem.linalg.*; * * <P> * - * Demonstrates pbuffers, vertex programs, register combiners + * Demonstrates pbuffers, vertex programs, fragment programs * * <P> * - * Ported to Java by Kenneth Russell + * Ported to Java and ARB_fragment_program by Kenneth Russell * */ @@ -131,9 +131,8 @@ public class ProceduralTexturePhysics { try { checkExtension(gl, "GL_ARB_multitexture"); - checkExtension(gl, "GL_NV_vertex_program"); - checkExtension(gl, "GL_NV_texture_shader"); - checkExtension(gl, "GL_NV_register_combiners"); + checkExtension(gl, "GL_ARB_vertex_program"); + checkExtension(gl, "GL_ARB_fragment_program"); checkExtension(gl, "GL_ARB_pbuffer"); checkExtension(gl, "GL_ARB_pixel_format"); } catch (GLException e) { diff --git a/src/demos/proceduralTexturePhysics/Water.java b/src/demos/proceduralTexturePhysics/Water.java index ed6fe04..7230a20 100644 --- a/src/demos/proceduralTexturePhysics/Water.java +++ b/src/demos/proceduralTexturePhysics/Water.java @@ -49,7 +49,7 @@ import demos.util.*; * * <P> * - * Ported to Java by Kenneth Russell + * Ported to Java and ARB_fragment_program by Kenneth Russell */ public class Water { @@ -96,15 +96,15 @@ public class Water { private static final int CA_NUM_DYNAMIC_TEXTURES = 7; // List names - private static final int CA_REGCOMBINER_EQ_WEIGHT_COMBINE = 0; - private static final int CA_REGCOMBINER_NEIGHBOR_FORCE_CALC_1 = 1; - private static final int CA_REGCOMBINER_NEIGHBOR_FORCE_CALC_2 = 2; - private static final int CA_REGCOMBINER_APPLY_FORCE = 3; - private static final int CA_REGCOMBINER_APPLY_VELOCITY = 4; - private static final int CA_REGCOMBINER_CREATE_NORMAL_MAP = 5; - private static final int CA_TEXTURE_SHADER_REFLECT = 6; - private static final int CA_DRAW_SCREEN_QUAD = 7; - private static final int CA_NUM_LISTS = 8; + 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; private int[] staticTextureIDs = new int[CA_NUM_STATIC_TEXTURES]; private int[] dynamicTextureIDs = new int[CA_NUM_DYNAMIC_TEXTURES]; @@ -118,7 +118,7 @@ public class Water { private int[] displayListIDs = new int[CA_NUM_LISTS]; - private int vertexProgramID; // one vertex shader is used to choose the texcoord offset + private int vertexProgramID; // one vertex program is used to choose the texcoord offset private int flipState; // used to flip target texture configurations. @@ -154,38 +154,33 @@ public class Water { private int renderMode; // Constant memory locations - private static final int CV_WORLDVIEWPROJ_0 = 0; - private static final int CV_WORLDVIEWPROJ_1 = 1; - private static final int CV_WORLDVIEWPROJ_2 = 2; - private static final int CV_WORLDVIEWPROJ_3 = 3; - - private static final int CV_UV_OFFSET_TO_USE = 4; - - private static final int CV_UV_T0_NO_OFFSET = 8; - private static final int CV_UV_T0_TYPE1 = 9; - private static final int CV_UV_T0_TYPE2 = 10; - private static final int CV_UV_T0_TYPE3 = 11; - private static final int CV_UV_T0_TYPE4 = 12; - - private static final int CV_UV_T1_NO_OFFSET = 13; - private static final int CV_UV_T1_TYPE1 = 14; - private static final int CV_UV_T1_TYPE2 = 15; - private static final int CV_UV_T1_TYPE3 = 16; - private static final int CV_UV_T1_TYPE4 = 17; - - private static final int CV_UV_T2_NO_OFFSET = 18; - private static final int CV_UV_T2_TYPE1 = 19; - private static final int CV_UV_T2_TYPE2 = 20; - private static final int CV_UV_T2_TYPE3 = 21; - private static final int CV_UV_T2_TYPE4 = 22; - - private static final int CV_UV_T3_NO_OFFSET = 23; - private static final int CV_UV_T3_TYPE1 = 24; - private static final int CV_UV_T3_TYPE2 = 25; - private static final int CV_UV_T3_TYPE3 = 26; - private static final int CV_UV_T3_TYPE4 = 27; - - private static final int CV_CONSTS_1 = 28; + 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, @@ -244,7 +239,7 @@ public class Water { rot.setRotation(cameraOrientation); Mat4f matRot = rot.mul(bscale); - gl.glCallList(displayListIDs[CA_TEXTURE_SHADER_REFLECT]); + gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_REFLECT]); // Draw quad over full display gl.glActiveTextureARB(GL.GL_TEXTURE0_ARB); @@ -283,8 +278,7 @@ public class Water { gl.glEnd(); - gl.glDisable(GL.GL_TEXTURE_SHADER_NV); - gl.glDisable(GL.GL_REGISTER_COMBINERS_NV); + gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); break; } @@ -498,165 +492,140 @@ public class Water { createAndWriteUVOffsets(gl, initialMapDimensions[0], initialMapDimensions[1]); - checkExtension(gl, "GL_NV_register_combiners"); - checkExtension(gl, "GL_NV_register_combiners2"); - checkExtension(gl, "GL_NV_texture_shader"); + checkExtension(gl, "GL_ARB_vertex_program"); + checkExtension(gl, "GL_ARB_fragment_program"); checkExtension(gl, "GL_ARB_multitexture"); /////////////////////////////////////////////////////////////////////////// // UV Offset Vertex Program /////////////////////////////////////////////////////////////////////////// - // track the MVP matrix for the vertex program - gl.glTrackMatrixNV(GL.GL_VERTEX_PROGRAM_NV, 0, GL.GL_MODELVIEW_PROJECTION_NV, GL.GL_IDENTITY_NV); - float[] rCVConsts = new float[] { 0, 0.5f, 1.0f, 2.0f }; - gl.glProgramParameter4fvNV(GL.GL_VERTEX_PROGRAM_NV, CV_CONSTS_1, rCVConsts); int[] tmpInt = new int[1]; - gl.glGenProgramsNV(1, tmpInt); + gl.glGenProgramsARB(1, tmpInt); vertexProgramID = tmpInt[0]; - gl.glBindProgramNV(GL.GL_VERTEX_PROGRAM_NV, vertexProgramID); - - String programBuffer = - "!!VP1.0\n" + - "# CV_WORLDVIEWPROJ_0 = 0,\n" + - "# CV_WORLDVIEWPROJ_1 = 1,\n" + - "# CV_WORLDVIEWPROJ_2 = 2,\n" + - "# CV_WORLDVIEWPROJ_3 = 3,\n" + - "#\n" + - "# CV_UV_OFFSET_TO_USE = 4,\n" + - "#\n" + - "#\n" + - "# CV_UV_T0_NO_OFFSET = 8,\n" + - "# CV_UV_T0_TYPE1 = 9,\n" + - "# CV_UV_T0_TYPE2 = 10,\n" + - "# CV_UV_T0_TYPE3 = 11,\n" + - "# CV_UV_T0_TYPE4 = 12,\n" + - "#\n" + - "# CV_UV_T1_NO_OFFSET = 13,\n" + - "# CV_UV_T1_TYPE1 = 14,\n" + - "# CV_UV_T1_TYPE2 = 15,\n" + - "# CV_UV_T1_TYPE3 = 16,\n" + - "# CV_UV_T1_TYPE4 = 17,\n" + - "#\n" + - "# CV_UV_T2_NO_OFFSET = 18,\n" + - "# CV_UV_T2_TYPE1 = 19,\n" + - "# CV_UV_T2_TYPE2 = 20,\n" + - "# CV_UV_T2_TYPE3 = 21,\n" + - "# CV_UV_T2_TYPE4 = 22,\n" + - "#\n" + - "# CV_UV_T3_NO_OFFSET = 23,\n" + - "# CV_UV_T3_TYPE1 = 24,\n" + - "# CV_UV_T3_TYPE2 = 25,\n" + - "# CV_UV_T3_TYPE3 = 26,\n" + - "# CV_UV_T3_TYPE4 = 27,\n" + - "#\n" + - "# CV_CONSTS_1 = 28\n" + - "\n" + - "# Transform vertex-position to clip-space\n" + - "DP4 o[HPOS].x, v[OPOS], c[0];\n" + - "DP4 o[HPOS].y, v[OPOS], c[1];\n" + - "DP4 o[HPOS].z, v[OPOS], c[2];\n" + - "DP4 o[HPOS].w, v[OPOS], c[3];\n" + - "\n" + - "# Read which set of offsets to use\n" + - "ARL A0.x, c[4].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" + - "\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" + - "\n" + - "ADD o[TEX0], c[A0.x + 8], v[TEX0];\n" + - "ADD o[TEX1], c[A0.x + 13], v[TEX0];\n" + - "ADD o[TEX2], c[A0.x + 18], v[TEX0];\n" + - "ADD o[TEX3], c[A0.x + 23], v[TEX0];\n" + - "\n" + - "#MAD o[TEX0], R0, c[A0.x + 8], v[TEX0];\n" + - "#MAD o[TEX1], R0, c[A0.x + 13], v[TEX0]; \n" + - "#MAD o[TEX2], R0, c[A0.x + 18], v[TEX0]; \n" + - "#MAD o[TEX3], R0, c[A0.x + 23], v[TEX0];\n" + - "\n" + - "END \n"; - - gl.glLoadProgramNV(GL.GL_VERTEX_PROGRAM_NV, vertexProgramID, programBuffer.length(), programBuffer); - if (gl.glGetError() != GL.GL_NO_ERROR) { - throw new GLException("Error loading vertex program \"Texcoord_4_Offset.vp\""); - } + 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); + + loadProgram(gl, GL.GL_VERTEX_PROGRAM_ARB, programBuffer); /////////////////////////////////////////////////////////////////////////// - // register combiner setup for equal weight combination of texels + // fragment program setup for equal weight combination of texels /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_REGCOMBINER_EQ_WEIGHT_COMBINE] = gl.glGenLists(1); - gl.glNewList(displayListIDs[CA_REGCOMBINER_EQ_WEIGHT_COMBINE], GL.GL_COMPILE); - initEqWeightCombine_PostMult(gl); - gl.glEnable(GL.GL_REGISTER_COMBINERS_NV); - gl.glEndList(); + displayListIDs[CA_FRAGMENT_PROGRAM_EQ_WEIGHT_COMBINE] = gl.glGenLists(1); + initEqWeightCombine_PostMult(gl, displayListIDs[CA_FRAGMENT_PROGRAM_EQ_WEIGHT_COMBINE]); /////////////////////////////////////////////////////////////////////////// - // register combiners setup for computing force from neighbors (step 1) + // fragment program setup for computing force from neighbors (step 1) /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_REGCOMBINER_NEIGHBOR_FORCE_CALC_1] = gl.glGenLists(1); - gl.glNewList(displayListIDs[CA_REGCOMBINER_NEIGHBOR_FORCE_CALC_1], GL.GL_COMPILE); - initNeighborForceCalcStep1(gl); - gl.glEnable(GL.GL_REGISTER_COMBINERS_NV); - gl.glEndList(); + displayListIDs[CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_1] = gl.glGenLists(1); + initNeighborForceCalcStep1(gl, displayListIDs[CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_1]); /////////////////////////////////////////////////////////////////////////// - // register combiners setup for computing force from neighbors (step 2) + // fragment program setup for computing force from neighbors (step 2) /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_REGCOMBINER_NEIGHBOR_FORCE_CALC_2] = gl.glGenLists(1); - gl.glNewList(displayListIDs[CA_REGCOMBINER_NEIGHBOR_FORCE_CALC_2], GL.GL_COMPILE); - initNeighborForceCalcStep2(gl); - gl.glEnable(GL.GL_REGISTER_COMBINERS_NV); - gl.glEndList(); + displayListIDs[CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_2] = gl.glGenLists(1); + initNeighborForceCalcStep2(gl, displayListIDs[CA_FRAGMENT_PROGRAM_NEIGHBOR_FORCE_CALC_2]); /////////////////////////////////////////////////////////////////////////// - // register combiners setup to apply force + // fragment program setup to apply force /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_REGCOMBINER_APPLY_FORCE] = gl.glGenLists(1); - gl.glNewList(displayListIDs[CA_REGCOMBINER_APPLY_FORCE], GL.GL_COMPILE); - initApplyForce(gl); - gl.glEnable(GL.GL_REGISTER_COMBINERS_NV); - gl.glEndList(); + displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_FORCE] = gl.glGenLists(1); + initApplyForce(gl, displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_FORCE]); /////////////////////////////////////////////////////////////////////////// - // register combiners setup to apply velocity + // fragment program setup to apply velocity /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_REGCOMBINER_APPLY_VELOCITY] = gl.glGenLists(1); - gl.glNewList(displayListIDs[CA_REGCOMBINER_APPLY_VELOCITY], GL.GL_COMPILE); - initApplyVelocity(gl); - gl.glEnable(GL.GL_REGISTER_COMBINERS_NV); - gl.glEndList(); + displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_VELOCITY] = gl.glGenLists(1); + initApplyVelocity(gl, displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_VELOCITY]); /////////////////////////////////////////////////////////////////////////// - // register combiners setup to create a normal map + // fragment program setup to create a normal map /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_REGCOMBINER_CREATE_NORMAL_MAP] = gl.glGenLists(1); - gl.glNewList(displayListIDs[CA_REGCOMBINER_CREATE_NORMAL_MAP], GL.GL_COMPILE); - initCreateNormalMap(gl); - gl.glEnable(GL.GL_REGISTER_COMBINERS_NV); - gl.glEndList(); + displayListIDs[CA_FRAGMENT_PROGRAM_CREATE_NORMAL_MAP] = gl.glGenLists(1); + initCreateNormalMap(gl, displayListIDs[CA_FRAGMENT_PROGRAM_CREATE_NORMAL_MAP]); /////////////////////////////////////////////////////////////////////////// - // texture shader setup for dot product reflection + // fragment program setup for dot product reflection /////////////////////////////////////////////////////////////////////////// - displayListIDs[CA_TEXTURE_SHADER_REFLECT] = gl.glGenLists(1); - gl.glNewList(displayListIDs[CA_TEXTURE_SHADER_REFLECT], GL.GL_COMPILE); - initDotProductReflect(gl); - gl.glDisable(GL.GL_BLEND); - gl.glEnable(GL.GL_TEXTURE_SHADER_NV); - gl.glEnable(GL.GL_REGISTER_COMBINERS_NV); - gl.glEndList(); + displayListIDs[CA_FRAGMENT_PROGRAM_REFLECT] = gl.glGenLists(1); + initDotProductReflect(gl, displayListIDs[CA_FRAGMENT_PROGRAM_REFLECT]); /////////////////////////////////////////////////////////////////////////// // display list to render a single screen space quad. @@ -739,7 +708,7 @@ public class Water { // is same for all stages as we're turning height difference // of nearest neightbor texels into a force value. - gl.glCallList(displayListIDs[CA_REGCOMBINER_NEIGHBOR_FORCE_CALC_1]); + 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++) @@ -757,15 +726,17 @@ public class Water { gl.glDisable(GL.GL_BLEND); // render using offset 1 (type 1 -- center + 3 of 4 nearest neighbors). - gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_OFFSET_TO_USE, 1, 0, 0, 0); + 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.glBindProgramNV(GL.GL_VERTEX_PROGRAM_NV, vertexProgramID); - gl.glEnable(GL.GL_VERTEX_PROGRAM_NV); + 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.glActiveTextureARB(GL.GL_TEXTURE2_ARB); gl.glBindTexture(GL.GL_TEXTURE_2D, dynamicTextureIDs[CA_TEXTURE_FORCE_INTERMEDIATE]); @@ -778,7 +749,7 @@ public class Water { // that we didn't have enough texture lookups to do in the // first pass - gl.glCallList(displayListIDs[CA_REGCOMBINER_NEIGHBOR_FORCE_CALC_2]); + 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. @@ -801,11 +772,13 @@ public class Water { // vertex program already bound. // render using offset 2 (type 2 -- final nearest neighbor plus center of previous result). - gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_OFFSET_TO_USE, 2, 0, 0, 0); + 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.glActiveTextureARB(GL.GL_TEXTURE1_ARB); gl.glBindTexture(GL.GL_TEXTURE_2D, dynamicTextureIDs[CA_TEXTURE_FORCE_TARGET]); @@ -817,10 +790,10 @@ public class Water { // 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_REGCOMBINER_APPLY_FORCE]); + gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_FORCE]); // use offsets of zero - gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_OFFSET_TO_USE, 0, 0, 0, 0); + 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. @@ -836,6 +809,8 @@ public class Water { // 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. @@ -865,8 +840,8 @@ public class Water { ////////////////////////////////////////////////////////////////////// // Apply velocity to position - gl.glCallList(displayListIDs[CA_REGCOMBINER_APPLY_VELOCITY]); - gl.glEnable(GL.GL_VERTEX_PROGRAM_NV); + gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_APPLY_VELOCITY]); + gl.glEnable(GL.GL_VERTEX_PROGRAM_ARB); gl.glActiveTextureARB(GL.GL_TEXTURE0_ARB); gl.glBindTexture(GL.GL_TEXTURE_2D, texHeightInput); @@ -874,11 +849,13 @@ public class Water { gl.glEnable(GL.GL_TEXTURE_2D); // use offsets of zero - gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_OFFSET_TO_USE, 0, 0, 0, 0); + 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.glActiveTextureARB(GL.GL_TEXTURE0_ARB); gl.glBindTexture(GL.GL_TEXTURE_2D, texHeightInput); @@ -898,15 +875,16 @@ public class Water { } // use offsets of 3 - gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_OFFSET_TO_USE, 3, 0, 0, 0); + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_OFFSET_TO_USE, 3, 0, 0, 0); - gl.glCallList(displayListIDs[CA_REGCOMBINER_EQ_WEIGHT_COMBINE]); + 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_NV); + gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB); drawInteriorBoundaryObjects(gl); } @@ -951,21 +929,23 @@ public class Water { // Red mask first float[] pixMasks = new float[] { normalSTScale, 0.0f, 0.0f, 0.0f }; - gl.glCombinerStageParameterfvNV(GL.GL_COMBINER2_NV, GL.GL_CONSTANT_COLOR0_NV, pixMasks); + gl.glProgramEnvParameter4fvARB(GL.GL_FRAGMENT_PROGRAM_ARB, 0, pixMasks); // Now green mask & scale: pixMasks[0] = 0.0f; pixMasks[1] = normalSTScale; - gl.glCombinerStageParameterfvNV(GL.GL_COMBINER2_NV, GL.GL_CONSTANT_COLOR1_NV, pixMasks); + gl.glProgramEnvParameter4fvARB(GL.GL_FRAGMENT_PROGRAM_ARB, 1, pixMasks); - gl.glCallList(displayListIDs[CA_REGCOMBINER_CREATE_NORMAL_MAP]); + gl.glCallList(displayListIDs[CA_FRAGMENT_PROGRAM_CREATE_NORMAL_MAP]); // set vp offsets to nearest neighbors - gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_OFFSET_TO_USE, 4, 0, 0, 0); - gl.glEnable(GL.GL_VERTEX_PROGRAM_NV); + 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.glActiveTextureARB(GL.GL_TEXTURE0_ARB); gl.glBindTexture(GL.GL_TEXTURE_2D, dynamicTextureIDs[CA_TEXTURE_NORMAL_MAP]); @@ -1167,10 +1147,10 @@ public class Water { float type2Offset[] = { type2OffsetX[i], type2OffsetY[i], 0.0f, 0.0f }; float type4Offset[] = { type4OffsetX[i], type4OffsetY[i], 0.0f, 0.0f }; - gl.glProgramParameter4fvNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_T0_NO_OFFSET + 5 * i, noOffset); - gl.glProgramParameter4fvNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_T0_TYPE1 + 5 * i, type1Offset); - gl.glProgramParameter4fvNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_T0_TYPE2 + 5 * i, type2Offset); - gl.glProgramParameter4fvNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_T0_TYPE4 + 5 * i, type4Offset); + gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_T0_NO_OFFSET + 5 * i, noOffset); + gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_T0_TYPE1 + 5 * i, type1Offset); + gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_T0_TYPE2 + 5 * i, type2Offset); + gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_T0_TYPE4 + 5 * i, type4Offset); } } @@ -1190,13 +1170,13 @@ public class Water { for (int i = 0; i < 4; ++i) { offsets[0] = blurDist * ( type3OffsetX[i]); offsets[1] = blurDist * ( type3OffsetY[i]); - gl.glProgramParameter4fvNV(GL.GL_VERTEX_PROGRAM_NV, CV_UV_T0_TYPE3 + 5 * i, offsets); + gl.glProgramEnvParameter4fvARB(GL.GL_VERTEX_PROGRAM_ARB, CV_UV_T0_TYPE3 + 5 * i, offsets); } } private synchronized void drawDroplets(GL gl) { - gl.glDisable(GL.GL_REGISTER_COMBINERS_NV); - gl.glDisable(GL.GL_VERTEX_PROGRAM_NV); + gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); + gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB); gl.glActiveTextureARB(GL.GL_TEXTURE0_ARB); gl.glBindTexture(GL.GL_TEXTURE_2D, staticTextureIDs[CA_TEXTURE_DROPLET]); @@ -1233,15 +1213,12 @@ public class Water { // 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) { - float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - float[] const1 = new float[] { 1.0f, 1.0f, 1.0f, 1.0f }; - - gl.glCombinerParameterfvNV(GL.GL_CONSTANT_COLOR0_NV, const0); - gl.glCombinerParameterfvNV(GL.GL_CONSTANT_COLOR1_NV, const1); - gl.glCombinerParameteriNV(GL.GL_NUM_GENERAL_COMBINERS_NV, 4); - - int stage = 0; + 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 // { @@ -1250,18 +1227,6 @@ public class Water { // spare0 = sum(); // scale_by_one_half(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE0_ARB, GL.GL_HALF_BIAS_NORMAL_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE1_ARB, GL.GL_HALF_BIAS_NORMAL_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_SCALE_BY_ONE_HALF_NV, GL.GL_NONE, false, false, false); - - // Stage 0 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 1 // rgb // { @@ -1270,18 +1235,6 @@ public class Water { // spare1 = sum(); // scale_by_one_half(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE2_ARB, GL.GL_HALF_BIAS_NORMAL_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE3_ARB, GL.GL_HALF_BIAS_NORMAL_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE1_NV, GL.GL_SCALE_BY_ONE_HALF_NV, GL.GL_NONE, false, false, false); - - // Stage 1 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 2 // rgb // { @@ -1290,18 +1243,6 @@ public class Water { // spare0 = sum(); // scale_by_one_half(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_SPARE1_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_SCALE_BY_ONE_HALF_NV, GL.GL_NONE, false, false, false); - - // Stage 2 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 3 // rgb // { @@ -1309,23 +1250,44 @@ public class Water { // discard = spare0; // spare0 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - // Stage 3 - // alpha - discardAlpha(gl, stage); - - gl.glDisable(GL.GL_PER_STAGE_CONSTANTS_NV); - gl.glCombinerParameteriNV(GL.GL_COLOR_SUM_CLAMP_NV, GL.GL_FALSE); + float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - doFinal(gl, GL.GL_SPARE0_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV); + int[] tmpInt = new int[1]; + gl.glGenProgramsARB(1, tmpInt); + 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); + gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); + gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); + gl.glEndList(); } - private void initNeighborForceCalcStep1(GL gl) { + 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. // @@ -1342,12 +1304,8 @@ public class Water { // so force for that axis == t1 - t0 + t2 - t0 // tex3 = 3rd neighbor on other axis - float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - - gl.glCombinerParameterfvNV(GL.GL_CONSTANT_COLOR0_NV, const0); - gl.glCombinerParameteriNV(GL.GL_NUM_GENERAL_COMBINERS_NV, 8); - - int stage = 0; + // Original register combiner program: + // // Stage 0 // rgb // { @@ -1356,18 +1314,6 @@ public class Water { // discard = tex1; // spare0 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE0_ARB, GL.GL_SIGNED_NEGATE_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE1_ARB, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 0 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 1 // rgb // { @@ -1376,18 +1322,6 @@ public class Water { // discard = tex2; // spare1 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE0_ARB, GL.GL_SIGNED_NEGATE_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE2_ARB, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE1_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 1 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 2 // // 'force' for 1st axis // rgb @@ -1397,18 +1331,6 @@ public class Water { // discard = spare1; // spare0 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_SPARE1_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 2 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 3 // // one more point for 2nd axis // rgb @@ -1418,18 +1340,6 @@ public class Water { // discard = tex3; // spare1 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE0_ARB, GL.GL_SIGNED_NEGATE_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE3_ARB, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE1_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 3 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 4 // rgb // { @@ -1438,18 +1348,6 @@ public class Water { // discard = spare1; // spare0 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_SPARE1_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 4 - // alpha - discardAlpha(gl, stage); - - ++stage; - // 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 @@ -1463,18 +1361,6 @@ public class Water { // discard = const0; // spare1 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE0_ARB, GL.GL_SIGNED_NEGATE_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE1_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 5 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 6 // { // rgb @@ -1484,18 +1370,6 @@ public class Water { // spare0 = sum(); // } // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE1_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 6 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 7 // rgb // { @@ -1503,22 +1377,61 @@ public class Water { // discard = const0; // spare0 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - // Stage 7 - // alpha - discardAlpha(gl, stage); + float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - gl.glDisable(GL.GL_PER_STAGE_CONSTANTS_NV); - gl.glCombinerParameteriNV(GL.GL_COLOR_SUM_CLAMP_NV, GL.GL_FALSE); - doFinal(gl, GL.GL_SPARE0_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV); + int[] tmpInt = new int[1]; + gl.glGenProgramsARB(1, tmpInt); + 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); + gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); + gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); + gl.glEndList(); } - private void initNeighborForceCalcStep2(GL gl) { + private void initNeighborForceCalcStep2(GL gl, int displayListID) { // 2nd step of force calc for render-to-texture // water simulation. // @@ -1535,12 +1448,8 @@ public class Water { // Result from t1 - t0 is added to this t2 // partial result & output - float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - - gl.glCombinerParameterfvNV(GL.GL_CONSTANT_COLOR0_NV, const0); - gl.glCombinerParameteriNV(GL.GL_NUM_GENERAL_COMBINERS_NV, 2); - - int stage = 0; + // Original register combiner program: + // // Stage 0 // last element of neighbor force // rgb @@ -1549,18 +1458,6 @@ public class Water { // discard = tex1; // spare0 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE0_ARB, GL.GL_SIGNED_NEGATE_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE1_ARB, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 0 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 1 // add with previous partial force amount // rgb @@ -1569,22 +1466,35 @@ public class Water { // discard = tex2; // spare0 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE2_ARB, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 1 - // alpha - discardAlpha(gl, stage); - gl.glDisable(GL.GL_PER_STAGE_CONSTANTS_NV); - gl.glCombinerParameteriNV(GL.GL_COLOR_SUM_CLAMP_NV, GL.GL_FALSE); - doFinal(gl, GL.GL_SPARE0_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV); + int[] tmpInt = new int[1]; + gl.glGenProgramsARB(1, tmpInt); + 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) { + 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. // @@ -1608,14 +1518,8 @@ public class Water { // // New velocity = force * scale + previous velocity - float[] const0 = new float[] { 0.25f, 0.25f, 0.25f, 1.0f }; - float[] const1 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - - gl.glCombinerParameterfvNV(GL.GL_CONSTANT_COLOR0_NV, const0); - gl.glCombinerParameterfvNV(GL.GL_CONSTANT_COLOR1_NV, const1); - gl.glCombinerParameteriNV(GL.GL_NUM_GENERAL_COMBINERS_NV, 4); - - int stage = 0; + // Original register combiner program: + // // Stage 0 // rgb // { @@ -1624,18 +1528,6 @@ public class Water { // spare0 = sum(); // scale_by_one_half(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE1_ARB, GL.GL_EXPAND_NORMAL_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE0_ARB, GL.GL_EXPAND_NORMAL_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_SCALE_BY_ONE_HALF_NV, GL.GL_NONE, false, false, false); - - // Stage 0 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 1 // rgb // { @@ -1643,22 +1535,45 @@ public class Water { // discard = const1; // spare0 = sum(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_CONSTANT_COLOR1_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - // Stage 1 - // alpha - discardAlpha(gl, stage); + float[] const0 = new float[] { 0.25f, 0.25f, 0.25f, 1.0f }; + float[] const1 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - gl.glDisable(GL.GL_PER_STAGE_CONSTANTS_NV); - gl.glCombinerParameteriNV(GL.GL_COLOR_SUM_CLAMP_NV, GL.GL_FALSE); - doFinal(gl, GL.GL_SPARE0_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_UNSIGNED_IDENTITY_NV); + int[] tmpInt = new int[1]; + gl.glGenProgramsARB(1, tmpInt); + 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); + gl.glProgramEnvParameter4fvARB(GL.GL_FRAGMENT_PROGRAM_ARB, 1, const1); + gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); + gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); + gl.glEndList(); } - private void initApplyVelocity(GL gl) { + 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. // @@ -1682,12 +1597,8 @@ public class Water { // // New height = velocity * scale factor + old height - float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - - gl.glCombinerParameterfvNV(GL.GL_CONSTANT_COLOR0_NV, const0); - gl.glCombinerParameteriNV(GL.GL_NUM_GENERAL_COMBINERS_NV, 2); - - int stage = 0; + // Original register combiner program: + // // Stage 0 // rgb // { @@ -1696,18 +1607,6 @@ public class Water { // spare0 = sum(); // scale_by_one_half(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE1_ARB, GL.GL_EXPAND_NORMAL_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE0_ARB, GL.GL_EXPAND_NORMAL_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_SCALE_BY_ONE_HALF_NV, GL.GL_NONE, false, false, false); - - // Stage 0 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 1 // rgb // { @@ -1716,22 +1615,42 @@ public class Water { // spare0 = sum(); // } // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - // Stage 1 - // alpha - discardAlpha(gl, stage); + float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - gl.glDisable(GL.GL_PER_STAGE_CONSTANTS_NV); - gl.glCombinerParameteriNV(GL.GL_COLOR_SUM_CLAMP_NV, GL.GL_FALSE); - doFinal(gl, GL.GL_SPARE0_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_UNSIGNED_IDENTITY_NV); + int[] tmpInt = new int[1]; + gl.glGenProgramsARB(1, tmpInt); + 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); + gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); + gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); + gl.glEndList(); } - private void initCreateNormalMap(GL gl) { + 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 @@ -1747,9 +1666,8 @@ public class Water { // tex2 = 0, +t // tex3 = 0, -t - gl.glCombinerParameteriNV(GL.GL_NUM_GENERAL_COMBINERS_NV, 7); - - int stage = 0; + // Original register combiner program: + // // Stage 0 // rgb // { @@ -1759,18 +1677,6 @@ public class Water { // spare0 = sum(); // scale_by_four(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE1_ARB, GL.GL_SIGNED_NEGATE_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE0_ARB, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_SCALE_BY_FOUR_NV, GL.GL_NONE, false, false, false); - - // Stage 0 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 1 // rgb // { @@ -1780,25 +1686,14 @@ public class Water { // spare1 = sum(); // scale_by_four(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE2_ARB, GL.GL_SIGNED_NEGATE_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE3_ARB, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE1_NV, GL.GL_SCALE_BY_FOUR_NV, GL.GL_NONE, false, false, false); - - // Stage 1 - // alpha - discardAlpha(gl, stage); - - ++stage; - // 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! @@ -1807,64 +1702,20 @@ public class Water { // discard = spare1 * const1; // spare0 = sum(); // } - // - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_SPARE1_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_CONSTANT_COLOR1_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 2 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 3 // rgb // { // tex1 = spare0 * spare0; // scale_by_two(); // } - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_TEXTURE1_ARB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SCALE_BY_TWO_NV, GL.GL_NONE, false, false, false); - - // Stage 3 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 4 - // // const0 = (1, 1, 0, 0); // rgb // { // spare1 = unsigned_invert(tex1) . const0; // scale_by_one_half(); // } - // - float[] const0 = new float[] { 1.0f, 1.0f, 0.0f, 0.0f }; - - gl.glCombinerStageParameterfvNV(GL.GL_COMBINER0_NV + stage, GL.GL_CONSTANT_COLOR0_NV, const0); - - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE1_ARB, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_SPARE1_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SCALE_BY_ONE_HALF_NV, GL.GL_NONE, true, false, false); - - // Stage 4 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 5 - // // const0 = (0.5, 0.5, 0, 0); // rgb // { @@ -1872,26 +1723,7 @@ public class Water { // discard = const0; // spare0 = sum(); // } - // - const0 = new float[] { 0.5f, 0.5f, 0.0f, 0.0f }; - - gl.glCombinerStageParameterfvNV(GL.GL_COMBINER0_NV + stage, GL.GL_CONSTANT_COLOR0_NV, const0); - - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 5 - // alpha - discardAlpha(gl, stage); - - ++stage; - // Stage 6 - // - // // const0 = (0, 0, 1, 1); // rgb // { @@ -1899,157 +1731,157 @@ public class Water { // discard = spare0; // spare0 = sum(); // } - // - const0 = new float[] { 0.0f, 0.0f, 1.0f, 1.0f }; - - gl.glCombinerStageParameterfvNV(GL.GL_COMBINER0_NV + stage, GL.GL_CONSTANT_COLOR0_NV, const0); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_SPARE1_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_CONSTANT_COLOR0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_SPARE0_NV, GL.GL_SIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - // Stage 6 - // alpha - discardAlpha(gl, stage); - - ++stage; - - gl.glEnable(GL.GL_PER_STAGE_CONSTANTS_NV); - gl.glCombinerParameteriNV(GL.GL_COLOR_SUM_CLAMP_NV, GL.GL_FALSE); - doFinal(gl, GL.GL_SPARE0_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV); - } - - private void initDotProductReflect(GL gl) { - gl.glActiveTextureARB(GL.GL_TEXTURE0_ARB); - gl.glTexEnvi(GL.GL_TEXTURE_SHADER_NV, GL.GL_SHADER_OPERATION_NV, GL.GL_TEXTURE_2D); - - // 1 of 3 - gl.glActiveTextureARB(GL.GL_TEXTURE1_ARB); - gl.glTexEnvi(GL.GL_TEXTURE_SHADER_NV, GL.GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV, GL.GL_EXPAND_NORMAL_NV); - gl.glTexEnvi(GL.GL_TEXTURE_SHADER_NV, GL.GL_SHADER_OPERATION_NV, GL.GL_DOT_PRODUCT_NV); - gl.glTexEnvi(GL.GL_TEXTURE_SHADER_NV, GL.GL_PREVIOUS_TEXTURE_INPUT_NV, GL.GL_TEXTURE0_ARB); - - // 2 of 3 - gl.glActiveTextureARB(GL.GL_TEXTURE2_ARB); - gl.glTexEnvi(GL.GL_TEXTURE_SHADER_NV, GL.GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV, GL.GL_EXPAND_NORMAL_NV); - gl.glTexEnvi(GL.GL_TEXTURE_SHADER_NV, GL.GL_SHADER_OPERATION_NV, GL.GL_DOT_PRODUCT_NV); - gl.glTexEnvi(GL.GL_TEXTURE_SHADER_NV, GL.GL_PREVIOUS_TEXTURE_INPUT_NV, GL.GL_TEXTURE0_ARB); - - // 3 of 3 - gl.glActiveTextureARB(GL.GL_TEXTURE3_ARB); - gl.glTexEnvi(GL.GL_TEXTURE_SHADER_NV, GL.GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV, GL.GL_EXPAND_NORMAL_NV); - gl.glTexEnvi(GL.GL_TEXTURE_SHADER_NV, GL.GL_SHADER_OPERATION_NV, GL.GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV); - gl.glTexEnvi(GL.GL_TEXTURE_SHADER_NV, GL.GL_PREVIOUS_TEXTURE_INPUT_NV, GL.GL_TEXTURE0_ARB); + float[] const0 = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; - gl.glActiveTextureARB(GL.GL_TEXTURE0_ARB); - gl.glCombinerParameteriNV(GL.GL_NUM_GENERAL_COMBINERS_NV, 1); - - int stage = 0; - // Stage 0 - // rgb - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - doIn(gl, stage, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - doOut(gl, stage, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - - // Stage 0 - // alpha - discardAlpha(gl, stage); - - ++stage; - - gl.glDisable(GL.GL_PER_STAGE_CONSTANTS_NV); - gl.glCombinerParameteriNV(GL.GL_COLOR_SUM_CLAMP_NV, GL.GL_FALSE); - doFinal(gl, GL.GL_TEXTURE3_ARB, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV); - } - - private void discardAlpha(GL gl, int stage) { - doIn(gl, stage, GL.GL_ALPHA, GL.GL_VARIABLE_A_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_BLUE); - doIn(gl, stage, GL.GL_ALPHA, GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_BLUE); - doIn(gl, stage, GL.GL_ALPHA, GL.GL_VARIABLE_C_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_BLUE); - doIn(gl, stage, GL.GL_ALPHA, GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_BLUE); - doOut(gl, stage, GL.GL_ALPHA, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); + int[] tmpInt = new int[1]; + gl.glGenProgramsARB(1, tmpInt); + 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 doIn(GL gl, - int stage, - int colorSpace, - int variable, - int reg, - int operation, - int colorSelector) { - gl.glCombinerInputNV(GL.GL_COMBINER0_NV + stage, - colorSpace, - variable, - reg, - operation, - colorSelector); - } + 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. - private void doOut(GL gl, - int stage, - int colorSpace, - int in0, - int in1, - int out0, - int scale, - int bias, - boolean unknown0, - boolean unknown1, - boolean unknown2) { - gl.glCombinerOutputNV(GL.GL_COMBINER0_NV + stage, - colorSpace, - in0, - in1, - out0, - scale, - bias, - unknown0, - unknown1, - unknown2); + int[] tmpInt = new int[1]; + gl.glGenProgramsARB(1, tmpInt); + 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 doFinal(GL gl, - int variableDInput, - int variableDOperation, - int variableGInput, - int variableGOperation) { - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_A_NV, - GL.GL_ZERO, - GL.GL_UNSIGNED_IDENTITY_NV, - GL.GL_RGB); - - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_B_NV, - GL.GL_ZERO, - GL.GL_UNSIGNED_IDENTITY_NV, - GL.GL_RGB); - - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_C_NV, - GL.GL_ZERO, - GL.GL_UNSIGNED_IDENTITY_NV, - GL.GL_RGB); - - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_D_NV, - variableDInput, - variableDOperation, - GL.GL_RGB); - - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_E_NV, - GL.GL_ZERO, - GL.GL_UNSIGNED_IDENTITY_NV, - GL.GL_RGB); - - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_F_NV, - GL.GL_ZERO, - GL.GL_UNSIGNED_IDENTITY_NV, - GL.GL_RGB); - - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_G_NV, - variableGInput, - variableGOperation, - GL.GL_ALPHA); + 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); + 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); + // if (isNative[1] != 1) { + if (isNative[0] != 1) { + System.out.println("WARNING: fragment program is over native resource limits"); + Thread.dumpStack(); + } + } + } } } |