diff options
Diffstat (limited to 'src')
26 files changed, 3781 insertions, 1215 deletions
diff --git a/src/classes/com/sun/opengl/impl/ProjectFloat.java b/src/classes/com/sun/opengl/impl/ProjectFloat.java index 637377237..309a6bdaf 100755 --- a/src/classes/com/sun/opengl/impl/ProjectFloat.java +++ b/src/classes/com/sun/opengl/impl/ProjectFloat.java @@ -153,8 +153,8 @@ public class ProjectFloat { // Array-based implementation private final float[] matrix = new float[16]; + private final float[][] tempInvertMatrix = new float[4][4]; - private final float[][] tempMatrix = new float[4][4]; private final float[] in = new float[4]; private final float[] out = new float[4]; @@ -164,8 +164,8 @@ public class ProjectFloat { // Buffer-based implementation private final FloatBuffer matrixBuf; + private final FloatBuffer tempInvertMatrixBuf; - private final FloatBuffer tempMatrixBuf; private final FloatBuffer inBuf; private final FloatBuffer outBuf; @@ -179,12 +179,12 @@ public class ProjectFloat { // Slice up one big buffer because some NIO implementations // allocate a huge amount of memory to back even the smallest of // buffers. - FloatBuffer buf = BufferUtil.newFloatBuffer(128); + FloatBuffer buf = BufferUtil.newFloatBuffer(2*16+2*4+3*3); int pos = 0; int sz = 16; matrixBuf = slice(buf, pos, sz); pos += sz; - tempMatrixBuf = slice(buf, pos, sz); + tempInvertMatrixBuf = slice(buf, pos, sz); pos += sz; sz = 4; inBuf = slice(buf, pos, sz); @@ -226,7 +226,7 @@ public class ProjectFloat { /** * Make matrix an identity matrix */ - private void gluMakeIdentityf(float[] m) { + public static void gluMakeIdentityf(float[] m) { for (int i = 0; i < 16; i++) { m[i] = IDENTITY_MATRIX[i]; } @@ -275,10 +275,10 @@ public class ProjectFloat { * * @return */ - private boolean __gluInvertMatrixf(float[] src, float[] inverse) { + public boolean gluInvertMatrixf(float[] src, float[] inverse) { int i, j, k, swap; float t; - float[][] temp = tempMatrix; + float[][] temp = tempInvertMatrix; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { @@ -345,14 +345,14 @@ public class ProjectFloat { * * @return */ - private boolean __gluInvertMatrixf(FloatBuffer src, FloatBuffer inverse) { + public boolean gluInvertMatrixf(FloatBuffer src, FloatBuffer inverse) { int i, j, k, swap; float t; int srcPos = src.position(); int invPos = inverse.position(); - FloatBuffer temp = tempMatrixBuf; + FloatBuffer temp = tempInvertMatrixBuf; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { @@ -772,7 +772,7 @@ public class ProjectFloat { gluMultMatricesf(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix); - if (!__gluInvertMatrixf(matrix, matrix)) + if (!gluInvertMatrixf(matrix, matrix)) return false; in[0] = winx; @@ -829,7 +829,7 @@ public class ProjectFloat { gluMultMatricesf(modelMatrix, projMatrix, matrixBuf); - if (!__gluInvertMatrixf(matrixBuf, matrixBuf)) + if (!gluInvertMatrixf(matrixBuf, matrixBuf)) return false; in.put(0, winx); @@ -898,7 +898,7 @@ public class ProjectFloat { gluMultMatricesf(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix); - if (!__gluInvertMatrixf(matrix, matrix)) + if (!gluInvertMatrixf(matrix, matrix)) return false; in[0] = winx; @@ -959,7 +959,7 @@ public class ProjectFloat { gluMultMatricesf(modelMatrix, projMatrix, matrixBuf); - if (!__gluInvertMatrixf(matrixBuf, matrixBuf)) + if (!gluInvertMatrixf(matrixBuf, matrixBuf)) return false; in.put(0, winx); diff --git a/src/classes/com/sun/opengl/impl/es2/FixedFuncShader.java b/src/classes/com/sun/opengl/impl/es2/FixedFuncShader.java deleted file mode 100644 index f6bf964a7..000000000 --- a/src/classes/com/sun/opengl/impl/es2/FixedFuncShader.java +++ /dev/null @@ -1,253 +0,0 @@ - -package com.sun.opengl.impl.es2; - -import javax.media.opengl.util.*; -import javax.media.opengl.*; -import java.nio.*; - -public class FixedFuncShader { - public FixedFuncShader(GL2ES2 gl, PMVMatrix pmvMatrix, ShaderData shaderData) { - init(gl, pmvMatrix, shaderData); - } - - public boolean isShaderDataValid() { - return shaderData.isValid(); - } - public boolean isValid() { - return shaderData.isValid() && shaderOk; - } - - public void glUseProgram(GL2ES2 gl, boolean on) { - if(shaderInUse==on) return; - if(!shaderOk) return; - gl.glUseProgram(on?shaderProgram:0); - shaderInUse = on; - } - - public void release(GL2ES2 gl) { - glUseProgram(gl, false); - gl.glDetachShader(shaderProgram, shaderData.vertexShader()); - gl.glDetachShader(shaderProgram, shaderData.fragmentShader()); - gl.glDeleteProgram(shaderProgram); - } - - public void syncUniforms(GL2ES2 gl) { - if(!shaderOk) return; - if(pmvMatrix.isDirty()) { - glUseProgram(gl, true); - gl.glUniformMatrix4fv(shaderPMVMatrix, 2, false, pmvMatrix.glGetPMVMatrixf()); - pmvMatrix.clear(); - } - } - - public int glArrayName2AttribName(int glName) { - switch(glName) { - case GL.GL_VERTEX_ARRAY: - return VERTEX_ARRAY; - case GL.GL_COLOR_ARRAY: - return COLOR_ARRAY; - case GL.GL_NORMAL_ARRAY: - return NORMAL_ARRAY; - case GL.GL_TEXTURE_COORD_ARRAY: - return TEXCOORD_ARRAY; - } - return -1; - } - - public void glEnableClientState(GL2ES2 gl, int glArrayName) { - if(!shaderOk) return; - int attribName = glArrayName2AttribName(glArrayName); - if(attribName>=0) { - glUseProgram(gl, true); - arrayInUse |= (1<<attribName); - gl.glEnableVertexAttribArray(attribName); - } - } - - public void glDisableClientState(GL2ES2 gl, int glArrayName) { - if(!shaderOk) return; - int attribName = glArrayName2AttribName(glArrayName); - if(attribName>=0) { - glUseProgram(gl, true); - gl.glDisableVertexAttribArray(attribName); - arrayInUse &= ~(1<<attribName); - if(0==arrayInUse) { - glUseProgram(gl, false); - } - } - } - - public void glVertexPointer(GL2ES2 gl, int size, int type, int stride, Buffer data ) { - if(!shaderOk) return; - glUseProgram(gl, true); - gl.glVertexAttribPointer(VERTEX_ARRAY, size, type, false, stride, data); - } - - public void glVertexPointer(GL2ES2 gl, int size, int type, int stride, long offset ) { - if(!shaderOk) return; - glUseProgram(gl, true); - gl.glVertexAttribPointer(VERTEX_ARRAY, size, type, false, stride, offset); - } - - public void glColorPointer(GL2ES2 gl, int size, int type, int stride, Buffer data ) { - if(!shaderOk) return; - glUseProgram(gl, true); - gl.glVertexAttribPointer(COLOR_ARRAY, size, type, false, stride, data); - } - - public void glColorPointer(GL2ES2 gl, int size, int type, int stride, long offset ) { - if(!shaderOk) return; - glUseProgram(gl, true); - gl.glVertexAttribPointer(COLOR_ARRAY, size, type, false, stride, offset); - } - - public void glColor4fv(GL2ES2 gl, FloatBuffer data ) { - glColorPointer(gl, 4, gl.GL_FLOAT, 0, data); - } - - public void glNormalPointer(GL2ES2 gl, int type, int stride, Buffer data ) { - if(!shaderOk) return; - glUseProgram(gl, true); - gl.glVertexAttribPointer(NORMAL_ARRAY, 3, type, false, stride, data); - } - - public void glNormalPointer(GL2ES2 gl, int type, int stride, long offset ) { - if(!shaderOk) return; - glUseProgram(gl, true); - gl.glVertexAttribPointer(NORMAL_ARRAY, 3, type, false, stride, offset); - } - - public void glTexCoordPointer(GL2ES2 gl, int size, int type, int stride, Buffer data ) { - if(!shaderOk) return; - glUseProgram(gl, true); - gl.glVertexAttribPointer(TEXCOORD_ARRAY, size, type, false, stride, data); - } - - public void glTexCoordPointer(GL2ES2 gl, int size, int type, int stride, long offset ) { - if(!shaderOk) return; - glUseProgram(gl, true); - gl.glVertexAttribPointer(TEXCOORD_ARRAY, size, type, false, stride, offset); - } - - public void setVertexAttribPointer(GL2ES2 gl, int glArrayName, int size, int type, int stride, Buffer data ) { - int attribName = glArrayName2AttribName(glArrayName); - if(!shaderOk || attribName<0) return; - glUseProgram(gl, true); - gl.glEnableVertexAttribArray(attribName); - gl.glVertexAttribPointer(attribName, size, type, false, stride, data); - } - - public void setVertexAttribPointer(GL2ES2 gl, int glArrayName, int size, int type, int stride, long offset ) { - int attribName = glArrayName2AttribName(glArrayName); - if(!shaderOk || attribName<0) return; - glUseProgram(gl, true); - gl.glEnableVertexAttribArray(attribName); - gl.glVertexAttribPointer(attribName, size, type, false, stride, offset); - } - - public void glLightfv(GL2ES2 gl, int light, int pname, java.nio.FloatBuffer params) { - if(!shaderOk) return; - light -=GL.GL_LIGHT0; - if(0 <= light && light <= 7) { - if(gl.GL_POSITION==pname && 0<=shaderLightsSource[light]) { - glUseProgram(gl, true); - gl.glUniform4fv(shaderLightsSource[light], 1, params); - } else if(gl.GL_AMBIENT==pname && 0<=shaderLigthsAmbient[light]) { - gl.glUniform4fv(shaderLigthsAmbient[light], 1, params); - } - } - } - - public void glShadeModel(GL2ES2 gl, int mode) { - if(!shaderOk || 0>shaderShadeModel) return; - glUseProgram(gl, true); - gl.glUniform1i(shaderShadeModel, mode); - } - - public void glActiveTexture(GL2ES2 gl, int texture) { - if(!shaderOk || 0>shaderShadeModel) return; - glUseProgram(gl, true); - texture-=gl.GL_TEXTURE0; - gl.glUniform1i(shaderActiveTexture, 0); - } - - protected void init(GL2ES2 gl, PMVMatrix pmvMatrix, ShaderData shaderData) { - if(shaderOk) return; - - if(null==pmvMatrix) { - throw new GLException("PMVMatrix is null"); - } - this.pmvMatrix=pmvMatrix; - this.shaderData=shaderData; - - if(!shaderData.createAndCompile(gl)) { - return; - } - - // Create the shader program - shaderProgram = gl.glCreateProgram(); - - // Attach the fragment and vertex shaders to it - gl.glAttachShader(shaderProgram, shaderData.vertexShader()); - gl.glAttachShader(shaderProgram, shaderData.fragmentShader()); - - gl.glBindAttribLocation(shaderProgram, VERTEX_ARRAY, "mgl_Vertex"); - gl.glBindAttribLocation(shaderProgram, COLOR_ARRAY, "mgl_Color"); - gl.glBindAttribLocation(shaderProgram, TEXCOORD_ARRAY, "mgl_MultiTexCoord0"); - - // Link the program - gl.glLinkProgram(shaderProgram); - - if ( ! gl.glIsProgramValid(shaderProgram, System.err) ) { - return; - } - - gl.glUseProgram(shaderProgram); - - shaderPMVMatrix = gl.glGetUniformLocation(shaderProgram, "mgl_PMVMatrix"); - if(0<=shaderPMVMatrix) { - gl.glUniformMatrix4fv(shaderPMVMatrix, 2, false, pmvMatrix.glGetPMVMatrixf()); - pmvMatrix.clear(); - shaderOk = true; - } else { - System.err.println("could not get uniform mgl_PMVMatrix: "+shaderPMVMatrix); - } - - // optional parameter .. - for(int i=0; i<7; i++) { - shaderLightsSource[i] = gl.glGetUniformLocation(shaderProgram, "mgl_LightSource"+i); - shaderLigthsAmbient[i] = gl.glGetUniformLocation(shaderProgram, "mgl_LightAmbient"+i); - } - shaderShadeModel = gl.glGetUniformLocation(shaderProgram, "mgl_ShadeModel"); - - shaderActiveTexture = gl.glGetUniformLocation(shaderProgram, "mgl_ActiveTexture"); - if(0<=shaderActiveTexture) { - gl.glUniform1i(shaderActiveTexture, 0); - } - - gl.glUseProgram(0); - shaderInUse = false; - } - - protected PMVMatrix pmvMatrix; - protected ShaderData shaderData; - - protected boolean shaderOk = false; - protected boolean shaderInUse = false; - protected int arrayInUse = 0; - protected int shaderProgram=-1; - - // attributes - protected static final int VERTEX_ARRAY = 0; // mgl_Vertex - protected static final int COLOR_ARRAY = 1; // mgl_Color - protected static final int NORMAL_ARRAY = 2; // ? - protected static final int TEXCOORD_ARRAY = 3; // mgl_MultiTexCoord0 - - // uniforms .. - protected int shaderPMVMatrix=-1; // mgl_PMVMatrix mat4 - protected int[] shaderLightsSource = new int[] { -1, -1, -1, -1, -1, -1, -1 }; // vec4f mgl_LightSourcei - protected int[] shaderLigthsAmbient = new int[] { -1, -1, -1, -1, -1, -1, -1 }; // vec4f mgl_LightAmbienti - protected int shaderShadeModel = -1; // mgl_ShadeModel int - protected int shaderActiveTexture = -1; // mgl_ActiveTexture int -} - diff --git a/src/classes/com/sun/opengl/impl/es2/FixedFuncShaderVertexColor.java b/src/classes/com/sun/opengl/impl/es2/FixedFuncShaderVertexColor.java deleted file mode 100644 index e3900d0b4..000000000 --- a/src/classes/com/sun/opengl/impl/es2/FixedFuncShaderVertexColor.java +++ /dev/null @@ -1,57 +0,0 @@ - -package com.sun.opengl.impl.es2; - -import javax.media.opengl.util.*; -import javax.media.opengl.*; -import java.nio.*; - -public class FixedFuncShaderVertexColor extends ShaderData { - - public static final String[][] vertShaderSource = new String[][] { { - "#ifdef GL_ES\n"+ - " #define MEDIUMP mediump\n"+ - " #define HIGHP highp\n"+ - "#else\n"+ - " #define MEDIUMP\n"+ - " #define HIGHP\n"+ - "#endif\n"+ - "\n"+ - "uniform MEDIUMP mat4 mgl_PMVMatrix[2];\n"+ - "attribute HIGHP vec4 mgl_Vertex;\n"+ - "attribute HIGHP vec4 mgl_Color;\n"+ - "varying HIGHP vec4 frontColor;\n"+ - "void main(void)\n"+ - "{\n"+ - " frontColor=mgl_Color;\n"+ - " gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;\n"+ - "}\n" } } ; - - public static final String[][] fragShaderSource = new String[][] { { - "#ifdef GL_ES\n"+ - " #define MEDIUMP mediump\n"+ - " #define HIGHP highp\n"+ - "#else\n"+ - " #define MEDIUMP\n"+ - " #define HIGHP\n"+ - "#endif\n"+ - "\n"+ - "varying HIGHP vec4 frontColor;\n"+ - "void main (void)\n"+ - "{\n"+ - " gl_FragColor = frontColor;\n"+ - "}\n" } } ; - - - public FixedFuncShaderVertexColor() { - super(1, 1); - } - - public int vertexShaderBinaryFormat() { return 0; } - public Buffer vertexShaderBinary() { return null; } - public String[][] vertexShaderSource() { return vertShaderSource; } - - public int fragmentShaderBinaryFormat() { return 0; } - public Buffer fragmentShaderBinary() { return null; } - public String[][] fragmentShaderSource() { return fragShaderSource; } -} - diff --git a/src/classes/com/sun/opengl/impl/es2/FixedFuncShaderVertexColorTexture.java b/src/classes/com/sun/opengl/impl/es2/FixedFuncShaderVertexColorTexture.java deleted file mode 100644 index 2c33c9c07..000000000 --- a/src/classes/com/sun/opengl/impl/es2/FixedFuncShaderVertexColorTexture.java +++ /dev/null @@ -1,67 +0,0 @@ - -package com.sun.opengl.impl.es2; - -import javax.media.opengl.util.*; -import javax.media.opengl.*; -import java.nio.*; - -public class FixedFuncShaderVertexColorTexture extends ShaderData { - - public static final String[][] vertShaderSource = new String[][] { { - "#ifdef GL_ES\n"+ - " #define MEDIUMP mediump\n"+ - " #define HIGHP highp\n"+ - "#else\n"+ - " #define MEDIUMP\n"+ - " #define HIGHP\n"+ - "#endif\n"+ - "\n"+ - "uniform MEDIUMP mat4 mgl_PMVMatrix[2];\n"+ - "attribute HIGHP vec4 mgl_Vertex;\n"+ - "attribute HIGHP vec4 mgl_Color;\n"+ - "attribute HIGHP vec4 mgl_MultiTexCoord0;\n"+ - "varying HIGHP vec4 gl_TexCoord[7];\n"+ - "varying HIGHP vec4 frontColor;\n"+ - "void main(void)\n"+ - "{\n"+ - " frontColor=mgl_Color;\n"+ - " gl_TexCoord[0] = mgl_MultiTexCoord0;\n"+ - " gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;\n"+ - "}\n" } } ; - - public static final String[][] fragShaderSource = new String[][] { { - "#ifdef GL_ES\n"+ - " #define MEDIUMP mediump\n"+ - " #define HIGHP highp\n"+ - "#else\n"+ - " #define MEDIUMP\n"+ - " #define HIGHP\n"+ - "#endif\n"+ - "\n"+ - "uniform HIGHP sampler2D mgl_ActiveTexture;\n"+ - "varying HIGHP vec4 frontColor;\n"+ - "const HIGHP vec4 one = vec4(1.0, 1.0, 1.0, 1.0);\n"+ - "const HIGHP vec4 zero = vec4(0.0, 0.0, 0.0, 0.0);\n"+ - "void main (void)\n"+ - "{\n"+ - " vec4 texColor = texture2D(mgl_ActiveTexture,gl_TexCoord[0].st);\n"+ - " if(greaterThan(texColor, zero)) {\n"+ - " gl_FragColor = vec4(frontColor.rgb*texColor.rgb, frontColor.a*texColor.a);\n"+ - " } else {\n"+ - " gl_FragColor = frontColor;\n"+ - " }\n"+ - "}\n" } } ; - - public FixedFuncShaderVertexColorTexture() { - super(1, 1); - } - - public int vertexShaderBinaryFormat() { return 0; } - public Buffer vertexShaderBinary() { return null; } - public String[][] vertexShaderSource() { return vertShaderSource; } - - public int fragmentShaderBinaryFormat() { return 0; } - public Buffer fragmentShaderBinary() { return null; } - public String[][] fragmentShaderSource() { return fragShaderSource; } -} - diff --git a/src/classes/com/sun/opengl/impl/es2/ShaderData.java b/src/classes/com/sun/opengl/impl/es2/ShaderData.java deleted file mode 100644 index 3a3c17811..000000000 --- a/src/classes/com/sun/opengl/impl/es2/ShaderData.java +++ /dev/null @@ -1,60 +0,0 @@ - -package com.sun.opengl.impl.es2; - -import javax.media.opengl.util.*; -import javax.media.opengl.*; -import java.nio.*; - -public abstract class ShaderData { - public abstract int vertexShaderBinaryFormat(); - public abstract Buffer vertexShaderBinary(); - public abstract String[][] vertexShaderSource(); - - public abstract int fragmentShaderBinaryFormat(); - public abstract Buffer fragmentShaderBinary(); - public abstract String[][] fragmentShaderSource(); - - public boolean isValid() { return valid; } - public void setValid(boolean val) { valid=val; } - - public ShaderData(int numVertexShader, int numFragmentShader) { - vertShader = BufferUtil.newIntBuffer(numVertexShader); - fragShader = BufferUtil.newIntBuffer(numFragmentShader); - } - - public IntBuffer vertexShader() { return vertShader; } - public IntBuffer fragmentShader() { return fragShader; } - - public boolean createAndCompile(GL2ES2 gl) { - if(isValid()) return true; - boolean res; - - // Create & Compile the vertex/fragment shader objects - res=gl.glCreateCompileShader(vertexShader(), gl.GL_VERTEX_SHADER, - vertexShaderBinaryFormat(), vertexShaderBinary(), - vertexShaderSource(), System.err); - if(!res) return false; - - res=gl.glCreateCompileShader(fragmentShader(), gl.GL_FRAGMENT_SHADER, - fragmentShaderBinaryFormat(), fragmentShaderBinary(), - fragmentShaderSource(), System.err); - if(!res) return false; - - setValid(true); - return true; - } - - public void release(GL2ES2 gl) { - if(isValid()) { - gl.glDeleteShader(fragmentShader()); - gl.glDeleteShader(vertexShader()); - setValid(false); - } - } - - protected IntBuffer vertShader = null; - protected IntBuffer fragShader = null; - - protected boolean valid=false; -} - diff --git a/src/classes/com/sun/opengl/impl/es2/VBOBufferDrawGLES2.java b/src/classes/com/sun/opengl/impl/es2/VBOBufferDrawGLES2.java deleted file mode 100644 index 30cf7e327..000000000 --- a/src/classes/com/sun/opengl/impl/es2/VBOBufferDrawGLES2.java +++ /dev/null @@ -1,70 +0,0 @@ - -package com.sun.opengl.impl.es2; - -import javax.media.opengl.util.VBOBufferDraw; -import javax.media.opengl.*; -import java.nio.*; - -public class VBOBufferDrawGLES2 extends VBOBufferDraw { - - public VBOBufferDrawGLES2(int glArrayType, int glDataType, int glBufferUsage, int comps, int initialSize) { - init(glArrayType, glDataType, glBufferUsage, comps, initialSize); - setVBOUsage(false); - //System.err.println("new VBOBufferDrawGLES2: "+this); - } - - protected void enableBufferGLImpl(GL gl, boolean newData) { - if(!bufferEnabled && null!=buffer) { - gl.glEnableClientState(glArrayType); - if(vboUsage) { - gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); - if(newData) { - gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit() * getBufferCompSize(), buffer, glBufferUsage); - } - switch(glArrayType) { - case GL.GL_VERTEX_ARRAY: - gl.glVertexPointer(components, glDataType, 0, 0); - break; - case GL.GL_NORMAL_ARRAY: - gl.glNormalPointer(glDataType, 0, 0); - break; - case GL.GL_COLOR_ARRAY: - gl.glColorPointer(components, glDataType, 0, 0); - break; - case GL.GL_TEXTURE_COORD_ARRAY: - gl.glTexCoordPointer(components, glDataType, 0, 0); - break; - default: - throw new GLException("invalid glArrayType: "+glArrayType+":\n\t"+this); - } - } else { - switch(glArrayType) { - case GL.GL_VERTEX_ARRAY: - gl.glVertexPointer(components, glDataType, 0, buffer); - break; - case GL.GL_NORMAL_ARRAY: - gl.glNormalPointer(glDataType, 0, buffer); - break; - case GL.GL_COLOR_ARRAY: - gl.glColorPointer(components, glDataType, 0, buffer); - break; - case GL.GL_TEXTURE_COORD_ARRAY: - gl.glTexCoordPointer(components, glDataType, 0, buffer); - break; - default: - throw new GLException("invalid glArrayType: "+glArrayType+":\n\t"+this); - } - } - bufferEnabled = true; - } - } - - protected void disableBufferGLImpl(GL gl) { - if(bufferEnabled && null!=buffer) { - gl.glDisableClientState(glArrayType); - bufferEnabled = false; - } - } - -} - diff --git a/src/classes/com/sun/opengl/impl/gl2es1/VBOBufferDrawGL2ES1.java b/src/classes/com/sun/opengl/impl/gl2es1/VBOBufferDrawGL2ES1.java deleted file mode 100644 index 5897b9a79..000000000 --- a/src/classes/com/sun/opengl/impl/gl2es1/VBOBufferDrawGL2ES1.java +++ /dev/null @@ -1,70 +0,0 @@ - -package com.sun.opengl.impl.gl2es1; - -import javax.media.opengl.util.VBOBufferDraw; -import javax.media.opengl.*; -import java.nio.*; - -public class VBOBufferDrawGL2ES1 extends VBOBufferDraw { - - public VBOBufferDrawGL2ES1(int glArrayType, int glDataType, int glBufferUsage, int comps, int initialSize) { - init(glArrayType, glDataType, glBufferUsage, comps, initialSize); - setVBOUsage(false); - //System.err.println("new VBOBufferDrawGL2ES1: "+this); - } - - protected void enableBufferGLImpl(GL gl, boolean newData) { - if(!bufferEnabled && null!=buffer) { - gl.glEnableClientState(glArrayType); - if(vboUsage) { - gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); - if(newData) { - gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit() * getBufferCompSize(), buffer, glBufferUsage); - } - switch(glArrayType) { - case GL.GL_VERTEX_ARRAY: - gl.glVertexPointer(components, glDataType, 0, 0); - break; - case GL.GL_NORMAL_ARRAY: - gl.glNormalPointer(glDataType, 0, 0); - break; - case GL.GL_COLOR_ARRAY: - gl.glColorPointer(components, glDataType, 0, 0); - break; - case GL.GL_TEXTURE_COORD_ARRAY: - gl.glTexCoordPointer(components, glDataType, 0, 0); - break; - default: - throw new GLException("invalid glArrayType: "+glArrayType+":\n\t"+this); - } - } else { - switch(glArrayType) { - case GL.GL_VERTEX_ARRAY: - gl.glVertexPointer(components, glDataType, 0, buffer); - break; - case GL.GL_NORMAL_ARRAY: - gl.glNormalPointer(glDataType, 0, buffer); - break; - case GL.GL_COLOR_ARRAY: - gl.glColorPointer(components, glDataType, 0, buffer); - break; - case GL.GL_TEXTURE_COORD_ARRAY: - gl.glTexCoordPointer(components, glDataType, 0, buffer); - break; - default: - throw new GLException("invalid glArrayType: "+glArrayType+":\n\t"+this); - } - } - bufferEnabled = true; - } - } - - protected void disableBufferGLImpl(GL gl) { - if(bufferEnabled && null!=buffer) { - gl.glDisableClientState(glArrayType); - bufferEnabled = false; - } - } - -} - diff --git a/src/classes/com/sun/opengl/impl/glsl/FixedFuncPipeline.java b/src/classes/com/sun/opengl/impl/glsl/FixedFuncPipeline.java new file mode 100644 index 000000000..e8cf58b42 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glsl/FixedFuncPipeline.java @@ -0,0 +1,468 @@ + +package com.sun.opengl.impl.es2; + +import javax.media.opengl.*; +import javax.media.opengl.util.*; +import javax.media.opengl.util.glsl.*; +import java.nio.*; + +public class FixedFuncPipeline { + public static final int MAX_TEXTURE_UNITS = 8; + public static final int MAX_LIGHTS = 8; + + public FixedFuncPipeline(GL2ES2 gl, PMVMatrix pmvMatrix) { + init(gl, pmvMatrix); + } + + public boolean verbose() { return verbose; } + + public void setVerbose(boolean v) { verbose=v; } + + public boolean isValid() { + return shaderState.linked(); + } + + public ShaderState getShaderState() { + return shaderState; + } + + public void enableLighting(boolean enable) { + lightingEnabled=enable; + } + + public boolean lightingEnabled() { + return lightingEnabled; + } + + public int getActiveTextureUnit() { + return activeTextureUnit; + } + + public String getArrayIndexName(int glArrayIndex) { + String name = GLContext.getPredefinedArrayIndexName(glArrayIndex); + switch(glArrayIndex) { + case GL.GL_VERTEX_ARRAY: + case GL.GL_NORMAL_ARRAY: + case GL.GL_COLOR_ARRAY: + break; + case GL.GL_TEXTURE_COORD_ARRAY: + name = name + activeTextureUnit; + } + return name; + } + + public void release(GL2ES2 gl) { + shaderState.release(gl); + shaderProgramColor.release(gl, true); + shaderProgramColorLight.release(gl, true); + shaderProgramColorTexture.release(gl, true); + shaderProgramColorTextureLight.release(gl, true); + } + + public void glEnableClientState(GL2ES2 gl, int glArrayIndex) { + shaderState.glUseProgram(gl, true); + + shaderState.glEnableVertexAttribArray(gl, getArrayIndexName(glArrayIndex)); + textureCoordsEnabled |= (1 << activeTextureUnit); + } + + public void glDisableClientState(GL2ES2 gl, int glArrayIndex) { + shaderState.glUseProgram(gl, true); + + shaderState.glDisableVertexAttribArray(gl, getArrayIndexName(glArrayIndex)); + textureCoordsEnabled &= ~(1 << activeTextureUnit); + } + + public void glVertexPointer(GL2ES2 gl, GLArrayData data) { + shaderState.glUseProgram(gl, true); + shaderState.glVertexAttribPointer(gl, data); + } + + public void glColorPointer(GL2ES2 gl, GLArrayData data) { + shaderState.glUseProgram(gl, true); + shaderState.glVertexAttribPointer(gl, data); + } + + public void glColor4fv(GL2ES2 gl, FloatBuffer data ) { + shaderState.glUseProgram(gl, true); + GLUniformData ud = shaderState.getUniform(mgl_ColorStatic); + if(null!=ud) { + ud.setData(data); + shaderState.glUniform(gl, ud); + } + } + + public void glNormalPointer(GL2ES2 gl, GLArrayData data) { + shaderState.glUseProgram(gl, true); + shaderState.glVertexAttribPointer(gl, data); + } + + public void glTexCoordPointer(GL2ES2 gl, GLArrayData data) { + shaderState.glUseProgram(gl, true); + data.setName( getArrayIndexName(data.getIndex()) ); + shaderState.glVertexAttribPointer(gl, data); + } + + public void glLightfv(GL2ES2 gl, int light, int pname, java.nio.FloatBuffer params) { + shaderState.glUseProgram(gl, true); + light -=GL.GL_LIGHT0; + if(0 <= light && light < MAX_LIGHTS) { + GLUniformData ud = null; + switch(pname) { + case GL.GL_AMBIENT: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].ambient"); + break; + case GL.GL_DIFFUSE: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].diffuse"); + break; + case GL.GL_SPECULAR: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].specular"); + break; + case GL.GL_POSITION: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].position"); + break; + case GL.GL_SPOT_DIRECTION: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].spotDirection"); + break; + case GL.GL_SPOT_EXPONENT: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].spotExponent"); + break; + case GL.GL_SPOT_CUTOFF: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].spotCutoff"); + break; + case GL.GL_CONSTANT_ATTENUATION: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].constantAttenuation"); + break; + case GL.GL_LINEAR_ATTENUATION: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].linearAttenuation"); + break; + case GL.GL_QUADRATIC_ATTENUATION: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].quadraticAttenuation"); + break; + default: + if(verbose) { + System.err.println("glLightfv pname not within [GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_POSITION GL_SPOT_DIRECTION]: "+pname); + } + return; + } + if(null!=ud) { + ud.setData(params); + shaderState.glUniform(gl, ud); + } + } else if(verbose) { + System.err.println("glLightfv light not within [0.."+MAX_LIGHTS+"]: "+light); + } + } + + public void glMaterialfv(GL2ES2 gl, int face, int pname, java.nio.FloatBuffer params) { + shaderState.glUseProgram(gl, true); + + switch (face) { + case GL.GL_FRONT: + case GL.GL_FRONT_AND_BACK: + break; + case GL.GL_BACK: + if(verbose) { + System.err.println("glMaterialfv face GL_BACK currently not supported"); + } + break; + default: + } + + GLUniformData ud = null; + switch(pname) { + case GL.GL_AMBIENT: + ud = shaderState.getUniform(mgl_FrontMaterial+".ambient"); + break; + case GL.GL_AMBIENT_AND_DIFFUSE: + glMaterialfv(gl, face, GL.GL_AMBIENT, params); + // fall through intended .. + case GL.GL_DIFFUSE: + ud = shaderState.getUniform(mgl_FrontMaterial+".diffuse"); + break; + case GL.GL_SPECULAR: + ud = shaderState.getUniform(mgl_FrontMaterial+".specular"); + break; + case GL.GL_EMISSION: + ud = shaderState.getUniform(mgl_FrontMaterial+".emission"); + break; + case GL.GL_SHININESS: + ud = shaderState.getUniform(mgl_FrontMaterial+".shininess"); + break; + default: + if(verbose) { + System.err.println("glMaterialfv pname not within [GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_EMISSION GL_SHININESS]: "+pname); + } + return; + } + if(null!=ud) { + ud.setData(params); + shaderState.glUniform(gl, ud); + } + } + + public void glShadeModel(GL2ES2 gl, int mode) { + shaderState.glUseProgram(gl, true); + GLUniformData ud = shaderState.getUniform(mgl_ShadeModel); + if(null!=ud) { + ud.setData(mode); + shaderState.glUniform(gl, ud); + } + } + + public void glActiveTexture(GL2ES2 gl, int textureUnit) { + textureUnit -= GL.GL_TEXTURE0; + if(0 <= textureUnit && textureUnit<MAX_TEXTURE_UNITS) { + shaderState.glUseProgram(gl, true); + GLUniformData ud; + ud = shaderState.getUniform(mgl_ActiveTexture); + if(null!=ud) { + ud.setData(textureUnit); + shaderState.glUniform(gl, ud); + } + ud = shaderState.getUniform(mgl_ActiveTextureIdx); + if(null!=ud) { + ud.setData(textureUnit); + shaderState.glUniform(gl, ud); + } + activeTextureUnit = textureUnit; + } else { + throw new GLException("glActivateTexture textureUnit not within GL_TEXTURE0 + [0.."+MAX_TEXTURE_UNITS+"]: "+textureUnit); + } + } + + public void glEnable(GL2ES2 gl, int cap, boolean enable) { + shaderState.glUseProgram(gl, true); + + switch(cap) { + case GL.GL_TEXTURE_2D: + textureEnabled=enable; + return; + case GL.GL_LIGHTING: + lightingEnabled=enable; + return; + } + + int light = cap - GL.GL_LIGHT0; + if(0 <= light && light < MAX_LIGHTS) { + if(enable) { + lightsEnabled |= (1 << light); + } else { + lightsEnabled &= ~(1 << light); + } + return; + } + + } + + public void validate(GL2ES2 gl) { + shaderState.glUseProgram(gl, true); + GLUniformData ud; + if(pmvMatrix.update()) { + ud = shaderState.getUniform(mgl_PMVMatrix); + if(null!=ud) { + // same data object .. + shaderState.glUniform(gl, ud); + } else { + throw new GLException("Failed to update: mgl_PMVMatrix"); + } + ud = shaderState.getUniform(mgl_NormalMatrix); + if(null!=ud) { + // same data object .. + shaderState.glUniform(gl, ud); + } + } + ud = shaderState.getUniform(mgl_ColorEnabled); + if(null!=ud) { + int ca = (shaderState.isVertexAttribArrayEnabled(GLContext.mgl_Color)==true)?1:0; + if(ca!=ud.intValue()) { + ud.setData(ca); + shaderState.glUniform(gl, ud); + } + } + + ud = shaderState.getUniform(mgl_TexCoordEnabled); + if(null!=ud) { + if(textureCoordsEnabled!=ud.intValue()) { + ud.setData(textureCoordsEnabled); + shaderState.glUniform(gl, ud); + } + } + + ud = shaderState.getUniform(mgl_LightsEnabled); + if(null!=ud) { + if(lightsEnabled!=ud.intValue()) { + ud.setData(lightsEnabled); + shaderState.glUniform(gl, ud); + } + } + + if(textureEnabled) { + if(lightingEnabled) { + shaderState.attachShaderProgram(gl, shaderProgramColorTextureLight); + } else { + shaderState.attachShaderProgram(gl, shaderProgramColorTexture); + } + } else { + if(lightingEnabled) { + shaderState.attachShaderProgram(gl, shaderProgramColorLight); + } else { + shaderState.attachShaderProgram(gl, shaderProgramColor); + } + } + if(DEBUG) { + System.out.println("validate: "+this); + } + } + + public String toString() { + return "FixedFuncPipeline[pmv: "+pmvMatrix+ + ", textureEnabled: "+textureEnabled+ + ", textureCoordsEnabled: "+textureCoordsEnabled+ + ", lightingEnabled: "+lightingEnabled+ + ", lightsEnabled: "+lightsEnabled+ + ", ShaderState: "+shaderState+ + "]"; + } + + protected void init(GL2ES2 gl, PMVMatrix pmvMatrix) { + if(null==pmvMatrix) { + throw new GLException("PMVMatrix is null"); + } + this.pmvMatrix=pmvMatrix; + this.shaderState=new ShaderState(); + this.shaderState.setVerbose(verbose); + + ShaderCode vertexColor = new ShaderCode( gl.GL_VERTEX_SHADER, 1, -1, null, + FixedFuncShaderVertexColor.vertShaderSource); + + ShaderCode vertexColorLight = new ShaderCode( gl.GL_VERTEX_SHADER, 1, -1, null, + FixedFuncShaderVertexColorLight.vertShaderSource); + + ShaderCode fragmentColor = new ShaderCode( gl.GL_FRAGMENT_SHADER, 1, -1, null, + FixedFuncShaderFragmentColor.fragShaderSource); + + ShaderCode fragmentColorTexture = new ShaderCode( gl.GL_FRAGMENT_SHADER, 1, -1, null, + FixedFuncShaderFragmentColorTexture.fragShaderSource); + + shaderProgramColor = new ShaderProgram(); + shaderProgramColor.add(vertexColor); + shaderProgramColor.add(fragmentColor); + if(!shaderProgramColor.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColor program"); + } + + shaderProgramColorTexture = new ShaderProgram(); + shaderProgramColorTexture.add(vertexColor); + shaderProgramColorTexture.add(fragmentColorTexture); + if(!shaderProgramColorTexture.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorTexture program"); + } + + shaderProgramColorLight = new ShaderProgram(); + shaderProgramColorLight.add(vertexColorLight); + shaderProgramColorLight.add(fragmentColor); + if(!shaderProgramColorLight.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorLight program"); + } + + shaderProgramColorTextureLight = new ShaderProgram(); + shaderProgramColorTextureLight.add(vertexColorLight); + shaderProgramColorTextureLight.add(fragmentColorTexture); + if(!shaderProgramColorTextureLight.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorLight program"); + } + + shaderState.attachShaderProgram(gl, shaderProgramColor); + shaderState.glUseProgram(gl, true); + + // mandatory .. + if(!shaderState.glUniform(gl, new GLUniformData(mgl_PMVMatrix, 4, 4, pmvMatrix.glGetPMvMviMatrixf()))) { + throw new GLException("Error setting PMVMatrix in shader: "+this); + } + + // optional parameter .. + shaderState.glUniform(gl, new GLUniformData(mgl_NormalMatrix, 3, 3, pmvMatrix.glGetNormalMatrixf())); + + shaderState.glUniform(gl, new GLUniformData(mgl_ColorEnabled, 0)); + shaderState.glUniform(gl, new GLUniformData(mgl_ColorStatic, 4, zero4f)); + shaderState.glUniform(gl, new GLUniformData(mgl_TexCoordEnabled, textureCoordsEnabled)); + shaderState.glUniform(gl, new GLUniformData(mgl_ActiveTexture, activeTextureUnit)); + shaderState.glUniform(gl, new GLUniformData(mgl_ActiveTextureIdx, activeTextureUnit)); + shaderState.glUniform(gl, new GLUniformData(mgl_ShadeModel, 0)); + for(int i=0; i<MAX_LIGHTS; i++) { + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].ambient", 4, defAmbient)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].diffuse", 4, defDiffuse)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].specular", 4, defSpecular)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].position", 4, defPosition)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].spotDirection", 3, defSpotDir)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].spotExponent", defSpotExponent)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].spotCutoff", defSpotCutoff)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].constantAttenuation", defConstantAtten)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].linearAttenuation", defLinearAtten)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].quadraticAttenuation", defQuadraticAtten)); + } + shaderState.glUniform(gl, new GLUniformData(mgl_LightsEnabled, lightsEnabled)); + shaderState.glUniform(gl, new GLUniformData(mgl_FrontMaterial+".ambient", 4, defMatAmbient)); + shaderState.glUniform(gl, new GLUniformData(mgl_FrontMaterial+".diffuse", 4, defMatDiffuse)); + shaderState.glUniform(gl, new GLUniformData(mgl_FrontMaterial+".specular", 4, defMatSpecular)); + shaderState.glUniform(gl, new GLUniformData(mgl_FrontMaterial+".emission", 4, defMatEmission)); + shaderState.glUniform(gl, new GLUniformData(mgl_FrontMaterial+".shininess", defMatShininess)); + + shaderState.glUseProgram(gl, false); + } + + protected static final boolean DEBUG=false; + + protected boolean verbose=false; + + protected boolean textureEnabled=false; + protected int textureCoordsEnabled=0; + protected int activeTextureUnit=0; + + protected boolean lightingEnabled=false; + protected int lightsEnabled=0; + + protected PMVMatrix pmvMatrix; + protected ShaderState shaderState; + protected ShaderProgram shaderProgramColor; + protected ShaderProgram shaderProgramColorTexture; + protected ShaderProgram shaderProgramColorLight; + protected ShaderProgram shaderProgramColorTextureLight; + + // uniforms .. + protected static final String mgl_PMVMatrix = "mgl_PMVMatrix"; // m4fv[3] + protected static final String mgl_NormalMatrix = "mgl_NormalMatrix"; // m4fv + protected static final String mgl_ColorEnabled = "mgl_ColorEnabled"; // 1i + protected static final String mgl_ColorStatic = "mgl_ColorStatic"; // 4fv + + protected static final String mgl_LightSource = "mgl_LightSource"; // struct mgl_LightSourceParameters[MAX_LIGHTS] + protected static final String mgl_FrontMaterial = "mgl_FrontMaterial"; // struct mgl_MaterialParameters + protected static final String mgl_LightsEnabled = "mgl_LightsEnabled"; // 1i bitfield + + protected static final String mgl_ShadeModel = "mgl_ShadeModel"; // 1i + + protected static final String mgl_TexCoordEnabled = "mgl_TexCoordEnabled"; // 1i bitfield + protected static final String mgl_ActiveTexture = "mgl_ActiveTexture"; // 1i + protected static final String mgl_ActiveTextureIdx = "mgl_ActiveTextureIdx";// 1i + + protected static final FloatBuffer zero4f = BufferUtil.newFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f, 0.0f }); + + public static final FloatBuffer defAmbient = BufferUtil.newFloatBuffer(new float[] { 0f, 0f, 0f, 1f }); + public static final FloatBuffer defDiffuse = zero4f; + public static final FloatBuffer defSpecular= zero4f; + public static final FloatBuffer defPosition= BufferUtil.newFloatBuffer(new float[] { 0f, 0f, 1f, 0f }); + public static final FloatBuffer defSpotDir = BufferUtil.newFloatBuffer(new float[] { 0f, 0f, -1f }); + public static final float defSpotExponent = 0f; + public static final float defSpotCutoff = 180f; + public static final float defConstantAtten = 1f; + public static final float defLinearAtten = 0f; + public static final float defQuadraticAtten= 0f; + + public static final FloatBuffer defMatAmbient = BufferUtil.newFloatBuffer(new float[] { 0.2f, 0.2f, 0.2f, 1.0f }); + public static final FloatBuffer defMatDiffuse = BufferUtil.newFloatBuffer(new float[] { 0.8f, 0.8f, 0.8f, 1.0f }); + public static final FloatBuffer defMatSpecular= BufferUtil.newFloatBuffer(new float[] { 0f, 0f, 0f, 1f}); + public static final FloatBuffer defMatEmission= BufferUtil.newFloatBuffer(new float[] { 0f, 0f, 0f, 1f}); + public static final float defMatShininess = 0f; +} + diff --git a/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderFragmentColor.java b/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderFragmentColor.java new file mode 100644 index 000000000..170a6c1da --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderFragmentColor.java @@ -0,0 +1,27 @@ + +package com.sun.opengl.impl.es2; + +import javax.media.opengl.util.*; +import javax.media.opengl.*; +import java.nio.*; + +public class FixedFuncShaderFragmentColor { + + public static final String[][] fragShaderSource = new String[][] { { + "#ifdef GL_ES\n"+ + " #define MEDIUMP mediump\n"+ + " #define HIGHP highp\n"+ + "#else\n"+ + " #define MEDIUMP\n"+ + " #define HIGHP\n"+ + "#endif\n"+ + "\n"+ + "varying HIGHP vec4 frontColor;\n"+ + "\n"+ + "void main (void)\n"+ + "{\n"+ + " gl_FragColor = frontColor;\n"+ + "}\n" } } ; + +} + diff --git a/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderFragmentColorTexture.java b/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderFragmentColorTexture.java new file mode 100644 index 000000000..7367a7cb9 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderFragmentColorTexture.java @@ -0,0 +1,39 @@ + +package com.sun.opengl.impl.es2; + +import javax.media.opengl.util.*; +import javax.media.opengl.*; +import java.nio.*; + +public class FixedFuncShaderFragmentColorTexture { + + public static final String[][] fragShaderSource = new String[][] { { + "#ifdef GL_ES\n"+ + " #define MEDIUMP mediump\n"+ + " #define HIGHP highp\n"+ + "#else\n"+ + " #define MEDIUMP\n"+ + " #define HIGHP\n"+ + "#endif\n"+ + "\n"+ + "const MEDIUMP int MAX_TEXTURE_UNITS = 8; // <=gl_MaxTextureImageUnits \n"+ + "const MEDIUMP int MAX_LIGHTS = 8; \n"+ + "const HIGHP vec4 zero = vec4(0.0, 0.0, 0.0, 0.0);\n"+ + "\n"+ + "uniform HIGHP sampler2D mgl_ActiveTexture;\n"+ + "uniform MEDIUMP int mgl_ActiveTextureIdx;\n"+ + "\n"+ + "varying HIGHP vec4 frontColor;\n"+ + "varying HIGHP vec4 mgl_TexCoord[MAX_TEXTURE_UNITS];\n"+ + "\n"+ + "void main (void)\n"+ + "{\n"+ + " vec4 texColor = texture2D(mgl_ActiveTexture,mgl_TexCoord[mgl_ActiveTextureIdx].st);\n"+ + " if(greaterThan(texColor, zero)) {\n"+ + " gl_FragColor = vec4(frontColor.rgb*texColor.rgb, frontColor.a * texColor.a) ; \n"+ + " } else {\n"+ + " gl_FragColor = frontColor;\n"+ + " }\n"+ + "}\n" } } ; +} + diff --git a/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderVertexColor.java b/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderVertexColor.java new file mode 100644 index 000000000..2fa8d5c46 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderVertexColor.java @@ -0,0 +1,65 @@ + +package com.sun.opengl.impl.es2; + +import javax.media.opengl.util.*; +import javax.media.opengl.*; +import java.nio.*; + +public class FixedFuncShaderVertexColor { + + public static final String[][] vertShaderSource = new String[][] { { + "#ifdef GL_ES\n"+ + " #define MEDIUMP mediump\n"+ + " #define HIGHP highp\n"+ + "#else\n"+ + " #define MEDIUMP\n"+ + " #define HIGHP\n"+ + "#endif\n"+ + "\n"+ + "const MEDIUMP int MAX_TEXTURE_UNITS = 8; // <=gl_MaxTextureImageUnits \n"+ + "const MEDIUMP int MAX_LIGHTS = 8; \n"+ + "\n"+ + "uniform HIGHP mat4 mgl_PMVMatrix[3]; // P, Mv, and Mvi\n"+ + "uniform MEDIUMP int mgl_ColorEnabled;\n"+ + "uniform HIGHP vec4 mgl_ColorStatic;\n"+ + "uniform MEDIUMP int mgl_TexCoordEnabled;\n"+ + "\n"+ + "attribute HIGHP vec4 mgl_Vertex;\n"+ + "attribute HIGHP vec4 mgl_Color;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord0;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord1;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord2;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord3;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord4;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord5;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord6;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord7;\n"+ + "\n"+ + "varying HIGHP vec4 frontColor;\n"+ + "varying HIGHP vec4 mgl_TexCoord[MAX_TEXTURE_UNITS];\n"+ + "\n"+ + "void setTexCoord(in HIGHP vec4 defpos) {\n"+ + " mgl_TexCoord[0] = ( 0 != (mgl_TexCoordEnabled & 1) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[1] = ( 0 != (mgl_TexCoordEnabled & 2) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[2] = ( 0 != (mgl_TexCoordEnabled & 4) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[3] = ( 0 != (mgl_TexCoordEnabled & 8) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[4] = ( 0 != (mgl_TexCoordEnabled & 16) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[5] = ( 0 != (mgl_TexCoordEnabled & 32) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[6] = ( 0 != (mgl_TexCoordEnabled & 64) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[7] = ( 0 != (mgl_TexCoordEnabled & 128) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + "}\n"+ + "\n"+ + "void main(void)\n"+ + "{\n"+ + " if(mgl_ColorEnabled>0) {\n"+ + " frontColor=mgl_Color;\n"+ + " } else {\n"+ + " frontColor=mgl_ColorStatic;\n"+ + " }\n"+ + "\n"+ + " gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;\n"+ + "\n"+ + " setTexCoord(gl_Position);\n"+ + "}\n" } } ; +} + diff --git a/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderVertexColorLight.java b/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderVertexColorLight.java new file mode 100644 index 000000000..f1e97a536 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glsl/FixedFuncShaderVertexColorLight.java @@ -0,0 +1,136 @@ + +package com.sun.opengl.impl.es2; + +import javax.media.opengl.util.*; +import javax.media.opengl.*; +import java.nio.*; + +public class FixedFuncShaderVertexColorLight { + + public static final String[][] vertShaderSource = new String[][] { { + "#ifdef GL_ES\n"+ + " #define MEDIUMP mediump\n"+ + " #define HIGHP highp\n"+ + "#else\n"+ + " #define MEDIUMP\n"+ + " #define HIGHP\n"+ + "#endif\n"+ + "\n"+ + "struct mgl_LightSourceParameters {\n"+ + " vec4 ambient; \n"+ + " vec4 diffuse; \n"+ + " vec4 specular; \n"+ + " vec4 position; \n"+ + " // vec4 halfVector; // is computed here\n"+ + " vec3 spotDirection; \n"+ + " float spotExponent; \n"+ + " float spotCutoff; // (range: [0.0,90.0], 180.0)\n"+ + " //float spotCosCutoff; // (range: [1.0,0.0],-1.0)\n"+ + " float constantAttenuation; \n"+ + " float linearAttenuation; \n"+ + " float quadraticAttenuation; \n"+ + "};\n"+ + "struct mgl_MaterialParameters {\n"+ + " vec4 ambient; \n"+ + " vec4 diffuse; \n"+ + " vec4 specular; \n"+ + " vec4 emission; \n"+ + " float shininess; \n"+ + "};\n"+ + "\n"+ + "\n"+ + "const MEDIUMP int MAX_TEXTURE_UNITS = 8; // <=gl_MaxTextureImageUnits \n"+ + "const MEDIUMP int MAX_LIGHTS = 8; \n"+ + "\n"+ + "uniform HIGHP mat4 mgl_PMVMatrix[3]; // P, Mv, and Mvi\n"+ + "uniform HIGHP mat3 mgl_NormalMatrix; // transpose(inverse(ModelView)).3x3\n"+ + "uniform MEDIUMP int mgl_ColorEnabled;\n"+ + "uniform HIGHP vec4 mgl_ColorStatic;\n"+ + "uniform MEDIUMP int mgl_TexCoordEnabled;\n"+ + "uniform MEDIUMP int mgl_LightsEnabled;\n"+ + "uniform mgl_LightSourceParameters mgl_LightSource[MAX_LIGHTS];\n"+ + "uniform mgl_MaterialParameters mgl_FrontMaterial;\n"+ + "\n"+ + "attribute HIGHP vec4 mgl_Vertex;\n"+ + "attribute HIGHP vec3 mgl_Normal;\n"+ + "attribute HIGHP vec4 mgl_Color;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord0;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord1;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord2;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord3;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord4;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord5;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord6;\n"+ + "attribute HIGHP vec4 mgl_MultiTexCoord7;\n"+ + "\n"+ + "varying HIGHP vec4 frontColor;\n"+ + "varying HIGHP vec4 mgl_TexCoord[MAX_TEXTURE_UNITS];\n"+ + "\n"+ + "void setTexCoord(in HIGHP vec4 defpos) {\n"+ + " mgl_TexCoord[0] = ( 0 != (mgl_TexCoordEnabled & 1) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[1] = ( 0 != (mgl_TexCoordEnabled & 2) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[2] = ( 0 != (mgl_TexCoordEnabled & 4) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[3] = ( 0 != (mgl_TexCoordEnabled & 8) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[4] = ( 0 != (mgl_TexCoordEnabled & 16) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[5] = ( 0 != (mgl_TexCoordEnabled & 32) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[6] = ( 0 != (mgl_TexCoordEnabled & 64) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + " mgl_TexCoord[7] = ( 0 != (mgl_TexCoordEnabled & 128) ) ? mgl_MultiTexCoord0 : defpos;\n"+ + "}\n"+ + "\n"+ + "void main(void)\n"+ + "{\n"+ + " vec4 position;\n"+ + " vec3 normal, lightDir, cameraDir, halfDir;\n"+ + " vec4 ambient, diffuse, specular;\n"+ + " float NdotL, NdotHV, dist, attenuation;\n"+ + " int i;\n"+ + "\n"+ + " position = mgl_PMVMatrix[1] * mgl_Vertex; // vertex eye position \n"+ + "\n"+ + " normal = normalize(mgl_NormalMatrix * mgl_Normal); \n"+ + " // cameraPosition: (mgl_PMVMatrix[2] * vec4(0,0,0,1.0)).xyz \n"+ + " cameraDir = normalize( (mgl_PMVMatrix[2] * vec4(0,0,0,1.0)).xyz - mgl_Vertex.xyz ); \n"+ + "\n"+ + " ambient = vec4(0,0,0,0);\n"+ + " diffuse = vec4(0,0,0,0);\n"+ + " specular = vec4(0,0,0,0);\n"+ + "\n"+ + " for(i=0; i<MAX_LIGHTS; i++) {\n"+ + " if( 0!= (mgl_LightsEnabled & (1<<i)) ) {\n"+ + " ambient += mgl_LightSource[i].ambient;\n"+ + " lightDir = mgl_LightSource[i].position.xyz - position.xyz;\n"+ + " dist = length(lightDir);\n"+ + " lightDir = normalize(lightDir);\n"+ + " attenuation = 1.0 / ( \n"+ + " mgl_LightSource[i].constantAttenuation+ \n"+ + " mgl_LightSource[i].linearAttenuation * dist + \n"+ + " mgl_LightSource[i].quadraticAttenuation * dist * dist );\n"+ + " NdotL = max(0.0, dot(normal, lightDir));\n"+ + " diffuse += mgl_LightSource[i].diffuse * NdotL * attenuation;\n"+ + " if (NdotL != 0.0) {\n"+ + " halfDir = normalize (lightDir + cameraDir); \n"+ + " NdotHV = max(0.0, dot(normal, halfDir));\n"+ + " specular += mgl_LightSource[i].specular * \n"+ + " pow(NdotHV,gl_FrontMaterial.shininess) * attenuation;\n"+ + " }\n"+ + " }\n"+ + " }\n"+ + " ambient += mgl_FrontMaterial.ambient;\n"+ + " diffuse *= mgl_FrontMaterial.diffuse;\n"+ + " specular *= mgl_FrontMaterial.specular;\n"+ + "\n"+ + " if(mgl_ColorEnabled>0) {\n"+ + " frontColor=mgl_Color;\n"+ + " } else {\n"+ + " frontColor=mgl_ColorStatic;\n"+ + " }\n"+ + " if( 0!= mgl_LightsEnabled ) {\n"+ + " frontColor *= ambient + diffuse + specular;\n"+ + " }\n"+ + "\n"+ + " gl_Position = mgl_PMVMatrix[0] * position;\n"+ + "\n"+ + " setTexCoord(gl_Position);\n"+ + "}\n" } } ; +} + diff --git a/src/classes/com/sun/opengl/impl/glsl/GLSLArrayDataServer.java b/src/classes/com/sun/opengl/impl/glsl/GLSLArrayDataServer.java new file mode 100644 index 000000000..551eb525f --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glsl/GLSLArrayDataServer.java @@ -0,0 +1,58 @@ + +package com.sun.opengl.impl.glsl; + +import javax.media.opengl.*; +import javax.media.opengl.util.glsl.ShaderState; +import java.nio.*; + +public class GLSLArrayDataServer extends GLArrayDataServer { + + public GLSLArrayDataServer(String name, int comps, int dataType, boolean normalized, + int stride, Buffer buffer, int glBufferUsage) { + init(name, -1, comps, dataType, normalized, stride, buffer, 0, buffer.limit(), glBufferUsage, true); + } + + public GLSLArrayDataServer(String name, int comps, int dataType, boolean normalized, + int stride, long bufferOffset) { + init(name, -1, comps, dataType, normalized, stride, null, bufferOffset, 0, -1, true); + } + + public GLSLArrayDataServer(String name, int comps, int dataType, boolean normalized, + int initialSize, int glBufferUsage) { + init(name, -1, comps, dataType, normalized, 0, null, 0, initialSize, glBufferUsage, true); + } + + + protected void enableBufferGLImpl(GL gl, boolean enable) { + GL2ES2 glsl = gl.getGL2ES2(); + ShaderState st = ShaderState.getCurrent(); + if(null==st) { + throw new GLException("No ShaderState current"); + } + + if(enable) { + if(!st.glEnableVertexAttribArray(glsl, name)) { + throw new RuntimeException("Internal Error"); + } + bufferEnabled = true; + + if(vboUsage) { + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); + if(!bufferWritten) { + gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit() * getBufferCompSize(), buffer, glBufferUsage); + } + } + if ( ! st.glVertexAttribPointer(glsl, this) ) { + throw new RuntimeException("Internal Error"); + } + bufferWritten=true; + } else { + if(!st.glDisableVertexAttribArray(glsl, name)) { + throw new RuntimeException("Internal Error"); + } + bufferEnabled = false; + } + } + +} + diff --git a/src/classes/com/sun/opengl/impl/glu/GLUquadricImpl.java b/src/classes/com/sun/opengl/impl/glu/GLUquadricImpl.java index 8c2a4eef2..031d23c50 100644 --- a/src/classes/com/sun/opengl/impl/glu/GLUquadricImpl.java +++ b/src/classes/com/sun/opengl/impl/glu/GLUquadricImpl.java @@ -130,6 +130,7 @@ import java.nio.*; */ public class GLUquadricImpl implements GLUquadric { + private boolean useGLSL; private int drawStyle; private int orientation; private boolean textureFlag; @@ -137,19 +138,29 @@ public class GLUquadricImpl implements GLUquadric { private boolean immModeSinkEnabled; private boolean immModeSinkImmediate; - public static final boolean USE_NORM_TXT = true; + public static final boolean USE_NORM = true; + public static final boolean USE_TEXT = false; private ImmModeSink immModeSink; - public GLUquadricImpl() { + public GLUquadricImpl(boolean useGLSL) { + this.useGLSL = useGLSL; drawStyle = GLU.GLU_FILL; orientation = GLU.GLU_OUTSIDE; textureFlag = false; normals = GLU.GLU_SMOOTH; - if(USE_NORM_TXT) { - immModeSink = new ImmModeSink(GL.GL_FLOAT, GL.GL_STATIC_DRAW, 3, 3, 0, 3, 32); + if(useGLSL) { + immModeSink = ImmModeSink.createGLSL (GL.GL_STATIC_DRAW, 32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, GL.GL_SHORT, // normal + USE_TEXT?2:0, GL.GL_FLOAT); // texture } else { - immModeSink = new ImmModeSink(GL.GL_FLOAT, GL.GL_STATIC_DRAW, 3, 0, 0, 0, 32); + immModeSink = ImmModeSink.createFixed(GL.GL_STATIC_DRAW, 32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, GL.GL_SHORT, // normal + USE_TEXT?2:0, GL.GL_FLOAT); // texture } immModeSinkImmediate=true; immModeSinkEnabled=!GLProfile.isGL2(); @@ -183,10 +194,18 @@ public class GLUquadricImpl implements GLUquadric { if(!immModeSinkEnabled) return null; ImmModeSink res = immModeSink; - if(USE_NORM_TXT) { - immModeSink = new ImmModeSink(GL.GL_FLOAT, GL.GL_STATIC_DRAW, 3, 3, 0, 3, 32); + if(useGLSL) { + immModeSink = ImmModeSink.createGLSL (GL.GL_STATIC_DRAW, 32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, GL.GL_SHORT, // normal + USE_TEXT?2:0, GL.GL_FLOAT); // texture } else { - immModeSink = new ImmModeSink(GL.GL_FLOAT, GL.GL_STATIC_DRAW, 3, 0, 0, 0, 32); + immModeSink = ImmModeSink.createFixed(GL.GL_STATIC_DRAW, 32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, GL.GL_SHORT, // normal + USE_TEXT?2:0, GL.GL_FLOAT); // texture } return res; } @@ -349,9 +368,7 @@ public class GLUquadricImpl implements GLUquadric { for (i = 0; i < slices; i++) { x = cos((i * da)); y = sin((i * da)); - if(USE_NORM_TXT) { - normal3f(gl, x * nsign, y * nsign, nz * nsign); - } + normal3f(gl, x * nsign, y * nsign, nz * nsign); z = 0.0f; r = baseRadius; @@ -372,9 +389,7 @@ public class GLUquadricImpl implements GLUquadric { for (i = 0; i < slices; i++) { x = cos((i * da)); y = sin((i * da)); - if(USE_NORM_TXT) { - normal3f(gl, x * nsign, y * nsign, nz * nsign); - } + normal3f(gl, x * nsign, y * nsign, nz * nsign); glVertex3f(gl, (x * r), (y * r), z); } glEnd(gl); @@ -388,9 +403,7 @@ public class GLUquadricImpl implements GLUquadric { for (i = 0; i < slices; i++) { x = cos((i * da)); y = sin((i * da)); - if(USE_NORM_TXT) { - normal3f(gl, x * nsign, y * nsign, nz * nsign); - } + normal3f(gl, x * nsign, y * nsign, nz * nsign); glVertex3f(gl, (x * baseRadius), (y * baseRadius), 0.0f); } glEnd(gl); @@ -398,9 +411,7 @@ public class GLUquadricImpl implements GLUquadric { for (i = 0; i < slices; i++) { x = cos((i * da)); y = sin((i * da)); - if(USE_NORM_TXT) { - normal3f(gl, x * nsign, y * nsign, nz * nsign); - } + normal3f(gl, x * nsign, y * nsign, nz * nsign); glVertex3f(gl, (x * topRadius), (y * topRadius), height); } glEnd(gl); @@ -411,9 +422,7 @@ public class GLUquadricImpl implements GLUquadric { for (i = 0; i < slices; i++) { x = cos((i * da)); y = sin((i * da)); - if(USE_NORM_TXT) { - normal3f(gl, x * nsign, y * nsign, nz * nsign); - } + normal3f(gl, x * nsign, y * nsign, nz * nsign); glVertex3f(gl, (x * baseRadius), (y * baseRadius), 0.0f); glVertex3f(gl, (x * topRadius), (y * topRadius), (height)); } @@ -436,26 +445,18 @@ public class GLUquadricImpl implements GLUquadric { y = cos((i * da)); } if (nsign == 1.0f) { - if(USE_NORM_TXT) { - normal3f(gl, (x * nsign), (y * nsign), (nz * nsign)); - TXTR_COORD(gl, s, t); - } + normal3f(gl, (x * nsign), (y * nsign), (nz * nsign)); + TXTR_COORD(gl, s, t); glVertex3f(gl, (x * r), (y * r), z); - if(USE_NORM_TXT) { - normal3f(gl, (x * nsign), (y * nsign), (nz * nsign)); - TXTR_COORD(gl, s, t + dt); - } + normal3f(gl, (x * nsign), (y * nsign), (nz * nsign)); + TXTR_COORD(gl, s, t + dt); glVertex3f(gl, (x * (r + dr)), (y * (r + dr)), (z + dz)); } else { - if(USE_NORM_TXT) { - normal3f(gl, x * nsign, y * nsign, nz * nsign); - TXTR_COORD(gl, s, t); - } + normal3f(gl, x * nsign, y * nsign, nz * nsign); + TXTR_COORD(gl, s, t); glVertex3f(gl, (x * r), (y * r), z); - if(USE_NORM_TXT) { - normal3f(gl, x * nsign, y * nsign, nz * nsign); - TXTR_COORD(gl, s, t + dt); - } + normal3f(gl, x * nsign, y * nsign, nz * nsign); + TXTR_COORD(gl, s, t + dt); glVertex3f(gl, (x * (r + dr)), (y * (r + dr)), (z + dz)); } s += ds; @@ -959,19 +960,15 @@ public class GLUquadricImpl implements GLUquadric { if (!textureFlag) { // draw +Z end as a triangle fan glBegin(gl, GL.GL_TRIANGLE_FAN); - if(USE_NORM_TXT) { - glNormal3f(gl, 0.0f, 0.0f, 1.0f); - } + glNormal3f(gl, 0.0f, 0.0f, 1.0f); glVertex3f(gl, 0.0f, 0.0f, nsign * radius); for (j = 0; j <= slices; j++) { theta = (j == slices) ? 0.0f : j * dtheta; x = -sin(theta) * sin(drho); y = cos(theta) * sin(drho); z = nsign * cos(drho); - if(USE_NORM_TXT) { - if (normals) { - glNormal3f(gl, x * nsign, y * nsign, z * nsign); - } + if (normals) { + glNormal3f(gl, x * nsign, y * nsign, z * nsign); } glVertex3f(gl, x * radius, y * radius, z * radius); } @@ -999,22 +996,18 @@ public class GLUquadricImpl implements GLUquadric { x = -sin(theta) * sin(rho); y = cos(theta) * sin(rho); z = nsign * cos(rho); - if(USE_NORM_TXT) { - if (normals) { - glNormal3f(gl, x * nsign, y * nsign, z * nsign); - } - TXTR_COORD(gl, s, t); + if (normals) { + glNormal3f(gl, x * nsign, y * nsign, z * nsign); } + TXTR_COORD(gl, s, t); glVertex3f(gl, x * radius, y * radius, z * radius); x = -sin(theta) * sin(rho + drho); y = cos(theta) * sin(rho + drho); z = nsign * cos(rho + drho); - if(USE_NORM_TXT) { - if (normals) { - glNormal3f(gl, x * nsign, y * nsign, z * nsign); - } - TXTR_COORD(gl, s, t - dt); + if (normals) { + glNormal3f(gl, x * nsign, y * nsign, z * nsign); } + TXTR_COORD(gl, s, t - dt); s += ds; glVertex3f(gl, x * radius, y * radius, z * radius); } @@ -1025,9 +1018,7 @@ public class GLUquadricImpl implements GLUquadric { if (!textureFlag) { // draw -Z end as a triangle fan glBegin(gl, GL.GL_TRIANGLE_FAN); - if(USE_NORM_TXT) { - glNormal3f(gl, 0.0f, 0.0f, -1.0f); - } + glNormal3f(gl, 0.0f, 0.0f, -1.0f); glVertex3f(gl, 0.0f, 0.0f, -radius * nsign); rho = PI - drho; s = 1.0f; @@ -1036,10 +1027,8 @@ public class GLUquadricImpl implements GLUquadric { x = -sin(theta) * sin(rho); y = cos(theta) * sin(rho); z = nsign * cos(rho); - if(USE_NORM_TXT) { - if (normals) - glNormal3f(gl, x * nsign, y * nsign, z * nsign); - } + if (normals) + glNormal3f(gl, x * nsign, y * nsign, z * nsign); s -= ds; glVertex3f(gl, x * radius, y * radius, z * radius); } @@ -1148,10 +1137,13 @@ public class GLUquadricImpl implements GLUquadric { } private final void glNormal3f(GL gl, float x, float y, float z) { + short a=(short)(x*0xFFFF); + short b=(short)(y*0xFFFF); + short c=(short)(z*0xFFFF); if(immModeSinkEnabled) { - immModeSink.glNormal3f(x, y, z); + immModeSink.glNormal3s(a, b, c); } else { - ((GL2)gl).glNormal3f(x, y, z); + ((GL2)gl).glNormal3s(a, b, c); } } @@ -1179,11 +1171,7 @@ public class GLUquadricImpl implements GLUquadric { y /= mag; z /= mag; } - if(immModeSinkEnabled) { - immModeSink.glNormal3f(x, y, z); - } else { - ((GL2)gl).glNormal3f(x, y, z); - } + glNormal3f(gl, x, y, z); } private final void TXTR_COORD(GL gl, float x, float y) { diff --git a/src/classes/javax/media/opengl/GLArrayData.java b/src/classes/javax/media/opengl/GLArrayData.java new file mode 100644 index 000000000..db017b00a --- /dev/null +++ b/src/classes/javax/media/opengl/GLArrayData.java @@ -0,0 +1,153 @@ + +package javax.media.opengl; + +import java.nio.*; + +public interface GLArrayData { + + /** + * Returns true if this data set is intended for a GLSL vertex shader attribute, + * otherwise false, ie intended for fixed function vertex pointer + */ + public boolean isVertexAttribute(); + + /** + * The index of the predefined array index, see list below, + * or -1 in case of a shader attribute array. + * + * @see javax.media.opengl.GL#GL_VERTEX_ARRAY + * @see javax.media.opengl.GL#GL_NORMAL_ARRAY + * @see javax.media.opengl.GL#GL_COLOR_ARRAY + * @see javax.media.opengl.GL#GL_TEXTURE_COORD_ARRAY + */ + public int getIndex(); + + /** + * The name of the reflecting shader array attribute. + */ + public String getName(); + + /** + * Set a new name for this array. + */ + public void setName(String newName); + + + /** + * Returns the shader attribute location for this name, + * -1 if not yet determined + */ + public int getLocation(); + + /** + * Sets the determined location of the shader attribute + * This is usually done within ShaderState. + * + * @see javax.media.opengl.util.glsl.ShaderState#glVertexAttribPointer(GL2ES2, GLArrayData) + */ + public void setLocation(int v); + + + public boolean sealed(); + + /** + * The offset, if it's an VBO, otherwise -1 + */ + public long getOffset(); + + /** + * The Buffer holding the data, may be null in case of VBO + */ + public Buffer getBuffer(); + + /** + * Determines wheather the data is server side (VBO), + * or a client side array (false). + */ + public boolean isVBO(); + + /** + * The number of components per element + */ + public int getComponents(); + + /** + * The GL data type of the components, ie. GL_FLOAT + */ + public int getDataType(); + + /** + * True, if GL shall normalize fixed point data while converting + * them into float + */ + public boolean getNormalized(); + + /** + * The distance to the next payload, + * allowing interleaved arrays. + */ + public int getStride(); + + public int getVerticeNumber(); + + public int getBufferCompSize(); + + public String toString(); + + // + // Data and GL state modification .. + // + + public void destroy(GL gl); + + public void reset(GL gl); + + /** + * If seal is true, it + * disable write operations to the buffer. + * Calls flip, ie limit:=position and position:=0. + * Also enables the buffer for OpenGL, and passes the data. + * + * If seal is false, it + * enable write operations continuing + * at the buffer position, where you left off at seal(true), + * ie position:=limit and limit:=capacity. + * Also disables the buffer for OpenGL. + * + * @see #seal(boolean) + */ + public void seal(GL gl, boolean seal); + + public void enableBuffer(GL gl, boolean enable); + + // + // Data modification .. + // + + public void reset(); + + /** + * If seal is true, it + * disable write operations to the buffer. + * Calls flip, ie limit:=position and position:=0. + * + * If seal is false, it + * enable write operations continuing + * at the buffer position, where you left off at seal(true), + * ie position:=limit and limit:=capacity. + * + */ + public void seal(boolean seal); + + public void rewind(); + public void padding(int done); + public void put(Buffer v); + public void putb(byte v); + public void puts(short v); + public void puti(int v); + public void putx(int v); + public void putf(float v); + public void putd(double v); + +} + diff --git a/src/classes/javax/media/opengl/GLArrayDataClient.java b/src/classes/javax/media/opengl/GLArrayDataClient.java new file mode 100644 index 000000000..5048e15c3 --- /dev/null +++ b/src/classes/javax/media/opengl/GLArrayDataClient.java @@ -0,0 +1,498 @@ + +package javax.media.opengl; + +import javax.media.opengl.util.*; +import com.sun.opengl.impl.GLReflection; + +import java.nio.*; + +public class GLArrayDataClient implements GLArrayData { + + /** + * @arg index The GL array index + * @arg name The optional custom name for the GL array index, maybe null. + * If null, the default name mapping will be used, see 'getPredefinedArrayIndexName(int)'. + * This name might be used as the shader attribute name. + * @arg comps The array component number + * @arg dataType The array index GL data type + * @arg normalized Wheather the data shall be normalized + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataClient createFixed(int index, String name, int comps, int dataType, boolean normalized, + int initialSize) + throws GLException + { + GLProfile.isValidateArrayDataType(index, comps, dataType, false, true); + GLArrayDataClient adc = new GLArrayDataClient(); + adc.init(name, index, comps, dataType, normalized, 0, null, initialSize, false); + return adc; + } + + public static GLArrayDataClient createFixed(int index, String name, int comps, int dataType, boolean normalized, + int stride, Buffer buffer) + throws GLException + { + GLProfile.isValidateArrayDataType(index, comps, dataType, false, true); + GLArrayDataClient adc = new GLArrayDataClient(); + adc.init(name, index, comps, dataType, normalized, stride, buffer, comps*comps, false); + return adc; + } + + public static GLArrayDataClient createGLSL(int index, String name, int comps, int dataType, boolean normalized, + int initialSize) + throws GLException + { + GLProfile.isValidateArrayDataType(index, comps, dataType, true, true); + GLArrayDataClient adc = new GLArrayDataClient(); + adc.init(name, index, comps, dataType, normalized, 0, null, initialSize, true); + return adc; + } + + public static GLArrayDataClient createGLSL(int index, String name, int comps, int dataType, boolean normalized, + int stride, Buffer buffer) + throws GLException + { + GLProfile.isValidateArrayDataType(index, comps, dataType, true, true); + GLArrayDataClient adc = new GLArrayDataClient(); + adc.init(name, index, comps, dataType, normalized, stride, buffer, comps*comps, true); + return adc; + } + + // + // Data read access + // + + public boolean isVertexAttribute() { return isVertexAttribute; } + + public int getIndex() { return index; } + + public int getLocation() { return location; } + + public void setLocation(int v) { location = v; } + + public String getName() { return name; } + + public long getOffset() { return -1; } + + public Buffer getBuffer() { return buffer; } + + public boolean isVBO() { return false; } + + public int getComponents() { return components; } + + public int getDataType() { return dataType; } + + public boolean getNormalized() { return normalized; } + + public int getStride() { return stride; } + + public boolean sealed() { return sealed; } + + public Class getBufferClass() { + return clazz; + } + + public int getVerticeNumber() { + return ( buffer!=null ) ? ( buffer.limit() / components ) : 0 ; + } + + // + // Data and GL state modification .. + // + + public void setName(String newName) { + location = -1; + name = newName; + } + + public void destroy(GL gl) { + reset(gl); + } + + public void reset(GL gl) { + enableBuffer(gl, false); + reset(); + } + + public void seal(GL gl, boolean seal) + { + seal(seal); + if(sealedGL==seal) return; + sealedGL = seal; + if(seal) { + init_vbo(gl); + + enableBuffer(gl, true); + } else { + enableBuffer(gl, false); + } + } + + public void enableBuffer(GL gl, boolean enable) + { + if(enable) { + checkSeal(true); + if(!bufferEnabled && null!=buffer) { + buffer.rewind(); + enableBufferGLImpl(gl, true); + } + } else if(bufferEnabled) { + enableBufferGLImpl(gl, false); + } + } + + // + // Data modification .. + // + + public void reset() { + if(buffer!=null) { + buffer.clear(); + } + this.sealed=false; + this.bufferEnabled=false; + this.bufferWritten=false; + } + + public void seal(boolean seal) + { + if(sealed==seal) return; + sealed = seal; + if(seal) { + bufferWritten=false; + if (null!=buffer) { + buffer.flip(); + } + } else { + if (null!=buffer) { + buffer.position(buffer.limit()); + buffer.limit(buffer.capacity()); + } + } + } + + + public void rewind() { + if(buffer!=null) { + buffer.rewind(); + } + } + + public void padding(int done) { + if ( buffer==null || sealed ) return; + while(done<strideL) { + if(clazz==ByteBuffer.class) { + ((ByteBuffer)buffer).put((byte)0); + } else if(clazz==ShortBuffer.class) { + ((ShortBuffer)buffer).put((short)0); + } else if(clazz==IntBuffer.class) { + ((IntBuffer)buffer).put(0); + } else if(clazz==FloatBuffer.class) { + ((FloatBuffer)buffer).put(0f); + } else { + throw new GLException("Given Buffer Class not supported: "+clazz+" :\n\t"+this); + } + done++; + } + } + + /** + * Generic buffer relative put method. + * + * This class buffer Class must match the arguments buffer class. + * The arguments remaining elements must be a multiple of this arrays element stride. + */ + public void put(Buffer v) { + if ( buffer==null || sealed ) return; + if(0!=(v.remaining() % strideL)) { + throw new GLException("Buffer length ("+v.remaining()+") is not a multiple of component-stride:\n\t"+this); + } + Class vClazz = v.getClass(); + if(!GLReflection.instanceOf(vClazz, clazz.getName())) { + throw new GLException("This array's buffer class "+clazz+" doesn't match the argument's Class: "+vClazz+" :\n\t"+this); + } + growBufferIfNecessary(v.remaining()); + if(clazz==ByteBuffer.class) { + ((ByteBuffer)buffer).put((ByteBuffer)v); + } else if(clazz==ShortBuffer.class) { + ((ShortBuffer)buffer).put((ShortBuffer)v); + } else if(clazz==IntBuffer.class) { + ((IntBuffer)buffer).put((IntBuffer)v); + } else if(clazz==FloatBuffer.class) { + ((FloatBuffer)buffer).put((FloatBuffer)v); + } + } + + public void putb(byte v) { + if ( buffer==null || sealed ) return; + growBufferIfNecessary(1); + if(clazz==ByteBuffer.class) { + ((ByteBuffer)buffer).put(v); + } else if(clazz==ShortBuffer.class) { + ((ShortBuffer)buffer).put((short)v); + } else if(clazz==IntBuffer.class) { + ((IntBuffer)buffer).put((int)v); + } else { + throw new GLException("Byte doesn't match Buffer Class: "+clazz+" :\n\t"+this); + } + } + + public void puts(short v) { + if ( buffer==null || sealed ) return; + growBufferIfNecessary(1); + if(clazz==ShortBuffer.class) { + ((ShortBuffer)buffer).put(v); + } else if(clazz==IntBuffer.class) { + ((IntBuffer)buffer).put((int)v); + } else { + throw new GLException("Short doesn't match Buffer Class: "+clazz+" :\n\t"+this); + } + } + + public void puti(int v) { + if ( buffer==null || sealed ) return; + growBufferIfNecessary(1); + if(clazz==IntBuffer.class) { + ((IntBuffer)buffer).put(v); + } else { + throw new GLException("Integer doesn't match Buffer Class: "+clazz+" :\n\t"+this); + } + } + + public void putx(int v) { + puti(v); + } + + public void putf(float v) { + if ( buffer==null || sealed ) return; + growBufferIfNecessary(1); + if(clazz==FloatBuffer.class) { + ((FloatBuffer)buffer).put(v); + } else if(clazz==IntBuffer.class) { + ((IntBuffer)buffer).put(FixedPoint.toFixed(v)); + } else { + throw new GLException("Float doesn't match Buffer Class: "+clazz+" :\n\t"+this); + } + } + + public void putd(double v) { + if ( buffer==null || sealed ) return; + growBufferIfNecessary(1); + if(clazz==FloatBuffer.class) { + ((FloatBuffer)buffer).put((float)v); + } else { + throw new GLException("Double doesn't match Buffer Class: "+clazz+" :\n\t"+this); + } + } + + public String toString() { + return "GLArrayDataClient["+name+ + ", index "+index+ + ", location "+location+ + ", isVertexAttribute "+isVertexAttribute+ + ", dataType "+dataType+ + ", bufferClazz "+clazz+ + ", vertices "+getVerticeNumber()+ + ", components "+components+ + ", stride "+stride+"u "+strideB+"b "+strideL+"c"+ + ", initialSize "+initialSize+ + ", sealed "+sealed+ + ", bufferEnabled "+bufferEnabled+ + ", bufferWritten "+bufferWritten+ + ", buffer "+buffer+ + "]"; + } + + public static final Class getBufferClass(int dataType) { + switch(dataType) { + case GL.GL_BYTE: + case GL.GL_UNSIGNED_BYTE: + return ByteBuffer.class; + case GL.GL_SHORT: + case GL.GL_UNSIGNED_SHORT: + return ShortBuffer.class; + case GL2ES1.GL_FIXED: + return IntBuffer.class; + case GL.GL_FLOAT: + return FloatBuffer.class; + default: + throw new GLException("Given OpenGL data type not supported: "+dataType); + } + } + + public final int getBufferCompSize() { + if(clazz==ByteBuffer.class) { + return BufferUtil.SIZEOF_BYTE; + } + if(clazz==ShortBuffer.class) { + return BufferUtil.SIZEOF_SHORT; + } + if(clazz==IntBuffer.class) { + return BufferUtil.SIZEOF_INT; + } + if(clazz==FloatBuffer.class) { + return BufferUtil.SIZEOF_FLOAT; + } + throw new GLException("Given Buffer Class not supported: "+clazz+":\n\t"+this); + } + + // non public matters + + protected final boolean growBufferIfNecessary(int spare) { + if(buffer==null || buffer.remaining()<spare) { + growBuffer(initialSize); + return true; + } + return false; + } + + protected final void growBuffer(int additional) { + if(sealed || 0==additional || 0==components) return; + + // add the stride delta + additional += (additional/components)*(strideL-components); + + if(components>0) { + int osize = (buffer!=null)?buffer.capacity():0; + if(clazz==ByteBuffer.class) { + ByteBuffer newBBuffer = BufferUtil.newByteBuffer( (osize+additional) * components ); + if(buffer!=null) { + buffer.flip(); + newBBuffer.put((ByteBuffer)buffer); + } + buffer = newBBuffer; + } else if(clazz==ShortBuffer.class) { + ShortBuffer newSBuffer = BufferUtil.newShortBuffer( (osize+additional) * components ); + if(buffer!=null) { + buffer.flip(); + newSBuffer.put((ShortBuffer)buffer); + } + buffer = newSBuffer; + } else if(clazz==IntBuffer.class) { + IntBuffer newIBuffer = BufferUtil.newIntBuffer( (osize+additional) * components ); + if(buffer!=null) { + buffer.flip(); + newIBuffer.put((IntBuffer)buffer); + } + buffer = newIBuffer; + } else if(clazz==FloatBuffer.class) { + FloatBuffer newFBuffer = BufferUtil.newFloatBuffer( (osize+additional) * components ); + if(buffer!=null) { + buffer.flip(); + newFBuffer.put((FloatBuffer)buffer); + } + buffer = newFBuffer; + } else { + throw new GLException("Given Buffer Class not supported: "+clazz+":\n\t"+this); + } + } + } + + protected final void checkSeal(boolean test) throws GLException { + if(sealed!=test) { + if(test) { + throw new GLException("Not Sealed yet, seal first:\n\t"+this); + } else { + throw new GLException("Already Sealed, can't modify VBO:\n\t"+this); + } + } + } + + protected void init(String name, int index, int comps, int dataType, boolean normalized, int stride, Buffer data, + int initialSize, boolean isVertexAttribute) + throws GLException + { + this.isVertexAttribute = isVertexAttribute; + this.index = index; + this.location = -1; + this.name = (null==name)?GLContext.getPredefinedArrayIndexName(index):name; + if(null==this.name) { + throw new GLException("Not a valid GL array index: "+index); + } + this.dataType = dataType; + this.clazz = getBufferClass(dataType); + switch(dataType) { + case GL.GL_BYTE: + case GL.GL_UNSIGNED_BYTE: + case GL.GL_SHORT: + case GL.GL_UNSIGNED_SHORT: + case GL2ES1.GL_FIXED: + this.normalized = normalized; + break; + default: + this.normalized = false; + } + + int bpc = getBufferCompSize(); + if(0<stride && stride<comps*bpc) { + throw new GLException("stride ("+stride+") lower than component bytes, "+comps+" * "+bpc); + } + if(0<stride && stride%bpc!=0) { + throw new GLException("stride ("+stride+") not a multiple of bpc "+bpc); + } + this.buffer = data; + this.components = comps; + this.stride=stride; + this.strideB=(0==stride)?comps*bpc:stride; + this.strideL=(0==stride)?comps:strideB/bpc; + this.initialSize = initialSize; + this.sealed=false; + this.sealedGL=false; + this.bufferEnabled=false; + this.bufferWritten=false; + if(null==buffer) { + growBuffer(initialSize); + } + } + + protected void enableBufferGLImpl(GL gl, boolean enable) { + if(enable) { + gl.glEnableClientState(index); + bufferEnabled = true; + + switch(index) { + case GL.GL_VERTEX_ARRAY: + gl.glVertexPointer(this); + break; + case GL.GL_NORMAL_ARRAY: + gl.glNormalPointer(this); + break; + case GL.GL_COLOR_ARRAY: + gl.glColorPointer(this); + break; + case GL.GL_TEXTURE_COORD_ARRAY: + gl.glTexCoordPointer(this); + break; + default: + throw new GLException("invalid glArrayIndex: "+index+":\n\t"+this); + } + bufferWritten=true; + } else { + gl.glDisableClientState(index); + bufferEnabled = false; + } + } + + protected void init_vbo(GL gl) {} + + protected GLArrayDataClient() { } + + protected int index; + protected int location; + protected String name; + protected int components; + protected int dataType; + protected boolean normalized; + protected int stride; // user given stride + protected int strideB; // stride in bytes + protected int strideL; // stride in logical components + protected Class clazz; + protected Buffer buffer; + protected int initialSize; + protected boolean isVertexAttribute; + protected boolean sealed, sealedGL; + protected boolean bufferEnabled; + protected boolean bufferWritten; +} + diff --git a/src/classes/javax/media/opengl/GLArrayDataServer.java b/src/classes/javax/media/opengl/GLArrayDataServer.java new file mode 100644 index 000000000..d4f2604fd --- /dev/null +++ b/src/classes/javax/media/opengl/GLArrayDataServer.java @@ -0,0 +1,265 @@ + +package javax.media.opengl; + +import javax.media.opengl.*; +import java.nio.*; +import com.sun.opengl.impl.*; + +public class GLArrayDataServer extends GLArrayDataClient implements GLArrayData { + + // + // lifetime matters + // + + /** + * Create a VBOBuffer object, using a predefined fixed function array index + * and starting with a given Buffer object incl it's stride + * + * On profiles GL2 and ES1 the fixed function pipeline behavior is as expected. + * On profile ES2 the fixed function emulation will transform these calls to + * EnableVertexAttribArray and VertexAttribPointer calls, + * and a predefined vertex attribute variable name will be choosen. + * + * @arg index The GL array index + * @arg name The optional custom name for the GL array index, maybe null. + * If null, the default name mapping will be used, see 'getPredefinedArrayIndexName(int)'. + * This name might be used as the shader attribute name. + * @arg comps The array component number + * @arg dataType The array index GL data type + * @arg normalized Wheather the data shall be normalized + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataServer createFixed(int index, String name, int comps, int dataType, boolean normalized, + int stride, Buffer buffer, int glBufferUsage) + throws GLException + { + GLProfile.isValidateArrayDataType(index, comps, dataType, false, true); + + GLArrayDataServer ads = new GLArrayDataServer(); + ads.init(name, index, comps, dataType, normalized, stride, buffer, 0, buffer.limit(), glBufferUsage, false); + return ads; + } + + /** + * Create a VBOBuffer object, using a predefined fixed function array index + * and starting with a new created Buffer object with initialSize size + * + * On profiles GL2 and ES1 the fixed function pipeline behavior is as expected. + * On profile ES2 the fixed function emulation will transform these calls to + * EnableVertexAttribArray and VertexAttribPointer calls, + * and a predefined vertex attribute variable name will be choosen. + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataServer createFixed(int index, String name, int comps, int dataType, boolean normalized, + int initialSize, int glBufferUsage) + throws GLException + { + GLProfile.isValidateArrayDataType(index, comps, dataType, false, true); + + GLArrayDataServer ads = new GLArrayDataServer(); + ads.init(name, index, comps, dataType, normalized, 0, null, 0, initialSize, glBufferUsage, false); + return ads; + } + + /** + * Create a VBOBuffer object, using a predefined fixed function array index + * and starting with a given Buffer offset incl it's stride + * + * This object can neither be enabled, nor rendered, since no knowledge of the buffer + * itself is available. This object is only a VBO variant of GLArrayData + * and cannot being drawn. + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataServer createFixed(int index, String name, int comps, int dataType, boolean normalized, + int stride, long bufferOffset) + throws GLException + { + GLProfile.isValidateArrayDataType(index, comps, dataType, false, true); + + GLArrayDataServer ads = new GLArrayDataServer(); + ads.init(name, index, comps, dataType, normalized, stride, null, bufferOffset, 0, -1, false); + return ads; + } + + /** + * Create a VBOBuffer object, using a custom GLSL array attribute name + * and starting with a new created Buffer object with initialSize size + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataServer createGLSL(String name, int comps, int dataType, boolean normalized, + int initialSize, int glBufferUsage) + throws GLException + { + GLProfile.isValidateArrayDataType(-1, comps, dataType, true, true); + Class[] types = new Class[]{ String.class, int.class, int.class, boolean.class, int.class, int.class }; + Object[] args = new Object[]{ name, new Integer(comps), new Integer(dataType), + new Boolean(normalized), new Integer(initialSize), new Integer(glBufferUsage) } ; + + if(GLProfile.isGL2ES2()) { + return (GLArrayDataServer) GLReflection.createInstance("com.sun.opengl.impl.glsl.GLSLArrayDataServer", types, args); + } + throw new GLException("GLArrayDataServer not supported for profile: "+GLProfile.getProfile()); + } + + /** + * Create a VBOBuffer object, using a custom GLSL array attribute name + * and starting with a given Buffer object incl it's stride + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataServer createGLSL(String name, int comps, int dataType, boolean normalized, + int stride, Buffer buffer, int glBufferUsage) + throws GLException + { + GLProfile.isValidateArrayDataType(-1, comps, dataType, true, true); + Class[] types = new Class[]{ String.class, int.class, int.class, boolean.class, int.class, Buffer.class, int.class }; + Object[] args = new Object[]{ name, new Integer(comps), new Integer(dataType), + new Boolean(normalized), new Integer(stride), buffer, new Integer(glBufferUsage) } ; + + if(GLProfile.isGL2ES2()) { + return (GLArrayDataServer) GLReflection.createInstance("com.sun.opengl.impl.glsl.GLSLArrayDataServer", types, args); + } + throw new GLException("GLArrayDataServer not supported for profile: "+GLProfile.getProfile()); + } + + // + // Data matters GLArrayData + // + + public long getOffset() { return vboUsage?bufferOffset:-1; } + + public boolean isVBO() { return vboUsage; } + + // + // Data and GL state modification .. + // + + public void destroy(GL gl) { + super.destroy(gl); + if(vboName!=0) { + int[] tmp = new int[1]; + tmp[0] = vboName; + gl.glDeleteBuffers(1, tmp, 0); + vboName = 0; + } + } + + // + // data matters + // + + /** + * Convenient way do disable the VBO behavior and + * switch to client side data one + * Only possible if buffer is defined. + */ + public void setVBOUsage(boolean vboUsage) { + checkSeal(false); + this.vboUsage=(null!=buffer)?vboUsage:true; + } + + public int getBufferUsage() { + return glBufferUsage; + } + + public String toString() { + return "GLArrayDataServer["+name+ + ", index "+index+ + ", location "+location+ + ", isVertexAttribute "+isVertexAttribute+ + ", dataType "+dataType+ + ", bufferClazz "+clazz+ + ", vertices "+getVerticeNumber()+ + ", components "+components+ + ", stride "+stride+"u "+strideB+"b "+strideL+"c"+ + ", initialSize "+initialSize+ + ", glBufferUsage "+glBufferUsage+ + ", vboUsage "+vboUsage+ + ", vboName "+vboName+ + ", sealed "+sealed+ + ", bufferEnabled "+bufferEnabled+ + ", bufferWritten "+bufferWritten+ + ", buffer "+buffer+ + ", offset "+bufferOffset+ + "]"; + } + + // + // non public matters .. + // + + protected void init(String name, int index, int comps, int dataType, boolean normalized, + int stride, Buffer data, long offset, int initialSize, int glBufferUsage, boolean isVertexAttribute) + throws GLException + { + super.init(name, index, comps, dataType, normalized, stride, data, initialSize, isVertexAttribute); + + vboUsage=true; + + if( ! (GLProfile.isGL2ES2() && glBufferUsage==GL2ES2.GL_STREAM_DRAW) ) { + switch(glBufferUsage) { + case -1: // nop + case GL2ES1.GL_STATIC_DRAW: + case GL2ES1.GL_DYNAMIC_DRAW: + break; + default: + throw new GLException("invalid glBufferUsage: "+glBufferUsage+":\n\t"+this); + } + } + this.bufferOffset=offset; + this.glBufferUsage = glBufferUsage; + this.vboName = 0; + } + + protected void enableBufferGLImpl(GL gl, boolean enable) { + if(enable) { + gl.glEnableClientState(index); + bufferEnabled = true; + + if(vboUsage) { + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); + if(!bufferWritten) { + gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit() * getBufferCompSize(), buffer, glBufferUsage); + } + } + switch(index) { + case GL.GL_VERTEX_ARRAY: + gl.glVertexPointer(this); + break; + case GL.GL_NORMAL_ARRAY: + gl.glNormalPointer(this); + break; + case GL.GL_COLOR_ARRAY: + gl.glColorPointer(this); + break; + case GL.GL_TEXTURE_COORD_ARRAY: + gl.glTexCoordPointer(this); + break; + default: + throw new GLException("invalid glArrayIndex: "+index+":\n\t"+this); + } + bufferWritten=true; + } else { + gl.glDisableClientState(index); + bufferEnabled = false; + } + } + protected void init_vbo(GL gl) { + if(vboUsage && vboName==0) { + int[] tmp = new int[1]; + gl.glGenBuffers(1, tmp, 0); + vboName = tmp[0]; + } + } + + protected long bufferOffset; + protected int glBufferUsage; + protected int vboName; + protected boolean vboUsage; + +} + diff --git a/src/classes/javax/media/opengl/GLContext.java b/src/classes/javax/media/opengl/GLContext.java index 02345ef04..998ede419 100644 --- a/src/classes/javax/media/opengl/GLContext.java +++ b/src/classes/javax/media/opengl/GLContext.java @@ -193,4 +193,63 @@ public abstract class GLContext { "(GL: "+getGL().getClass().getName()+","+ " Factory: "+ getGLDrawable().getFactory().getClass().getName()+")"; } + + /** + * Mapping fixed function (client) array indices to + * GLSL array attribute names. + * + * Useful for uniq mapping of canonical array index names as listed. + * + * @see #mgl_Vertex + * @see javax.media.opengl.GL#GL_VERTEX_ARRAY + * @see #mgl_Normal + * @see javax.media.opengl.GL#GL_NORMAL_ARRAY + * @see #mgl_Color + * @see javax.media.opengl.GL#GL_COLOR_ARRAY + * @see #mgl_MultiTexCoord + * @see javax.media.opengl.GL#GL_TEXTURE_COORD_ARRAY + * @see javax.media.opengl.GL#glEnableClientState + * @see javax.media.opengl.GL#glVertexPointer + * @see javax.media.opengl.GL#glColorPointer + * @see javax.media.opengl.GL#glNormalPointer + * @see javax.media.opengl.GL#glTexCoordPointer + */ + public static String getPredefinedArrayIndexName(int glArrayIndex) { + switch(glArrayIndex) { + case GL.GL_VERTEX_ARRAY: + return mgl_Vertex; + case GL.GL_NORMAL_ARRAY: + return mgl_Normal; + case GL.GL_COLOR_ARRAY: + return mgl_Color; + case GL.GL_TEXTURE_COORD_ARRAY: + return mgl_MultiTexCoord; + } + return null; + } + + /** + * String name for + * @see javax.media.opengl.GL#GL_VERTEX_ARRAY + */ + public static final String mgl_Vertex = "mgl_Vertex"; + + /** + * String name for + * @see javax.media.opengl.GL#GL_NORMAL_ARRAY + */ + public static final String mgl_Normal = "mgl_Normal"; + + /** + * String name for + * @see javax.media.opengl.GL#GL_COLOR_ARRAY + */ + public static final String mgl_Color = "mgl_Color"; + + /** + * String name for + * @see javax.media.opengl.GL#GL_TEXTURE_COORD_ARRAY + */ + public static final String mgl_MultiTexCoord = "mgl_MultiTexCoord" ; + } diff --git a/src/classes/javax/media/opengl/GLProfile.java b/src/classes/javax/media/opengl/GLProfile.java index ff68a6d38..67e427f5a 100644 --- a/src/classes/javax/media/opengl/GLProfile.java +++ b/src/classes/javax/media/opengl/GLProfile.java @@ -212,4 +212,306 @@ public class GLProfile { throw new GLUnsupportedException("unsupported profile \"" + profile + "\""); } } + + /** + * General validation if type is a valid GL data type + * for the current profile + */ + public static boolean isValidDataType(int type, boolean throwException) { + switch(type) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_BYTE: + case GL.GL_UNSIGNED_SHORT: + case GL.GL_SHORT: + case GL.GL_FLOAT: + case GL.GL_FIXED: + return true; + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: + if( isGL2ES2() ) { + return true; + } + case javax.media.opengl.GL2.GL_DOUBLE: + case javax.media.opengl.GL2.GL_2_BYTES: + case javax.media.opengl.GL2.GL_3_BYTES: + case javax.media.opengl.GL2.GL_4_BYTES: + if( isGL2ES12() || isGL2() ) { + return true; + } + } + if(throwException) { + throw new GLException("Illegal data type on profile "+GLProfile.getProfile()+": "+type); + } + return false; + } + + public static boolean isValidateArrayDataType(int index, int comps, int type, + boolean isVertexAttribPointer, boolean throwException) { + String indexName = GLContext.getPredefinedArrayIndexName(index); + if(GLProfile.isGLES1()) { + if(isVertexAttribPointer) { + if(throwException) { + throw new GLException("Illegal array type for "+indexName+" on profile GLES1: VertexAttribPointer"); + } + return false; + } + switch(index) { + case GL.GL_VERTEX_ARRAY: + case GL.GL_TEXTURE_COORD_ARRAY: + switch(type) { + case GL.GL_BYTE: + case GL.GL_SHORT: + case GL.GL_FIXED: + case GL.GL_FLOAT: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+indexName+" on profile GLES1: "+type); + } + return false; + } + switch(comps) { + case 0: + case 2: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+indexName+" on profile GLES1: "+comps); + } + return false; + } + break; + case GL.GL_NORMAL_ARRAY: + switch(type) { + case GL.GL_BYTE: + case GL.GL_SHORT: + case GL.GL_FIXED: + case GL.GL_FLOAT: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+indexName+" on profile GLES1: "+type); + } + return false; + } + switch(comps) { + case 0: + case 3: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+indexName+" on profile GLES1: "+comps); + } + return false; + } + break; + case GL.GL_COLOR_ARRAY: + switch(type) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_FIXED: + case GL.GL_FLOAT: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+indexName+" on profile GLES1: "+type); + } + return false; + } + switch(comps) { + case 0: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+indexName+" on profile GLES1: "+comps); + } + return false; + } + break; + } + } else if(GLProfile.isGLES2()) { + // simply ignore !isVertexAttribPointer case, since it is simulated anyway .. + + switch(type) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_BYTE: + case GL.GL_UNSIGNED_SHORT: + case GL.GL_SHORT: + case GL.GL_FLOAT: + case GL.GL_FIXED: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+indexName+" on profile GLES2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 1: + case 2: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+indexName+" on profile GLES1: "+comps); + } + return false; + } + } else if(GLProfile.isGL2ES12() || GLProfile.isGL2()) { + if(isVertexAttribPointer) { + switch(index) { + case GL.GL_VERTEX_ARRAY: + case GL.GL_TEXTURE_COORD_ARRAY: + case GL.GL_NORMAL_ARRAY: + case GL.GL_COLOR_ARRAY: + switch(type) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_BYTE: + case GL.GL_UNSIGNED_SHORT: + case GL.GL_SHORT: + case GL.GL_FLOAT: + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: + case javax.media.opengl.GL2.GL_DOUBLE: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+indexName+" on profile GL2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 1: + case 2: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+indexName+" on profile GL2: "+comps); + } + return false; + } + break; + } + } else { + switch(index) { + case GL.GL_VERTEX_ARRAY: + switch(type) { + case GL.GL_SHORT: + case GL.GL_FLOAT: + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2.GL_DOUBLE: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+indexName+" on profile GL2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 2: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+indexName+" on profile GL2: "+comps); + } + return false; + } + break; + case GL.GL_NORMAL_ARRAY: + switch(type) { + case GL.GL_BYTE: + case GL.GL_SHORT: + case GL.GL_FLOAT: + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2.GL_DOUBLE: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+indexName+" on profile GL2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 3: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+indexName+" on profile GLES1: "+comps); + } + return false; + } + break; + case GL.GL_COLOR_ARRAY: + switch(type) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_BYTE: + case GL.GL_UNSIGNED_SHORT: + case GL.GL_SHORT: + case GL.GL_FLOAT: + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: + case javax.media.opengl.GL2.GL_DOUBLE: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+indexName+" on profile GL2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+indexName+" on profile GL2: "+comps); + } + return false; + } + break; + case GL.GL_TEXTURE_COORD_ARRAY: + switch(type) { + case GL.GL_SHORT: + case GL.GL_FLOAT: + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2.GL_DOUBLE: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+indexName+" on profile GL2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 1: + case 2: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+indexName+" on profile GL2: "+comps); + } + return false; + } + break; + } + } + } + return true; + } + } diff --git a/src/classes/javax/media/opengl/GLUniformData.java b/src/classes/javax/media/opengl/GLUniformData.java new file mode 100644 index 000000000..929a59a2a --- /dev/null +++ b/src/classes/javax/media/opengl/GLUniformData.java @@ -0,0 +1,159 @@ + +package javax.media.opengl; + +import java.nio.*; + +public class GLUniformData { + + /** + * int atom + * + * Number of objects is 1 + * + * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + */ + public GLUniformData(String name, int val) { + init(name, 1, new Integer(val)); + } + + /** + * float atom + * + * Number of objects is 1 + * + * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + */ + public GLUniformData(String name, float val) { + init(name, 1, new Float(val)); + } + + /** + * Multiple IntBuffer Vector + * + * Number of objects is calculated by data.limit()/components + * + * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + */ + public GLUniformData(String name, int components, IntBuffer data) { + init(name, components, data); + } + + /** + * Multiple FloatBuffer Vector + * + * Number of objects is calculated by data.limit()/components + * + * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + */ + public GLUniformData(String name, int components, FloatBuffer data) { + init(name, components, data); + } + + /** + * Multiple FloatBuffer Matrix + * + * Number of objects is calculated by data.limit()/(rows*columns) + * + * @arg rows the matrix rows + * @arg column the matrix column + */ + public GLUniformData(String name, int rows, int columns, FloatBuffer data) { + init(name, rows, columns, data); + } + + public void setData(int data) { init(new Integer(data)); } + public void setData(float data) { init(new Float(data)); } + public void setData(IntBuffer data) { init(data); } + public void setData(FloatBuffer data) { init(data); } + + public int intValue() { return ((Integer)data).intValue(); }; + public float floatValue() { return ((Float)data).floatValue(); }; + public IntBuffer intBufferValue() { return (IntBuffer)data; }; + public FloatBuffer floatBufferValue() { return (FloatBuffer)data; }; + + public String toString() { + return "GLUniformData[name "+name+ + ", location "+location+ + ", size "+rows+"*"+columns+ + ", count "+count+ + ", matrix "+isMatrix+ + ", data "+data+ + "]"; + } + + private void init(String name, int rows, int columns, Object data) { + if( 2>rows || rows>4 || 2>columns || columns>4 ) { + throw new GLException("rowsXcolumns must be within [2..4]X[2..4], is: "+rows+"X"+columns); + } + this.name=name; + this.rows=rows; + this.columns=columns; + this.isMatrix=true; + this.location=-1; + init(data); + } + + private void init(String name, int components, Object data) { + if( 1>components || components>4 ) { + throw new GLException("components must be within [1..4], is: "+components); + } + this.name=name; + this.columns=components; + this.rows=1; + this.isMatrix=false; + this.location=-1; + init(data); + } + + private void init(Object data) { + if(data instanceof Buffer) { + int sz = rows*columns; + Buffer buffer = (Buffer)data; + if(buffer.limit()<sz || 0!=buffer.limit()%sz) { + throw new GLException("data buffer size invalid: new buffer limit: "+buffer.limit()+"\n\t"+this); + } + this.count=buffer.limit()/(rows*columns); + } else { + if(isMatrix) { + throw new GLException("Atom type not allowed for matrix : "+this); + } + this.count=1; + } + this.data=data; + } + + public String getName() { return name; } + + public int getLocation() { return location; } + + /** + * Sets the determined location of the shader uniform + * This is usually done within ShaderState. + * + * @see javax.media.opengl.util.glsl.ShaderState#glUniform(GL2ES2, GLUniformData) + */ + public void setLocation(int location) { this.location=location; } + + public Object getObject() { + return data; + } + public Buffer getBuffer() { + return (data instanceof Buffer)?(Buffer)data:null; + } + public boolean isBuffer() { + return (data instanceof Buffer); + } + public boolean isMatrix() { return isMatrix; } + + public int count() { return count; } + public int components() { return rows*columns; } + public int rows() { return rows; } + public int columns() { return columns; } + + private String name; + private int location; + private int rows, columns; + private int count; + private Object data; + private boolean isMatrix; +} diff --git a/src/classes/javax/media/opengl/util/ImmModeSink.java b/src/classes/javax/media/opengl/util/ImmModeSink.java index 459372d94..5de9df99a 100644 --- a/src/classes/javax/media/opengl/util/ImmModeSink.java +++ b/src/classes/javax/media/opengl/util/ImmModeSink.java @@ -2,6 +2,7 @@ package javax.media.opengl.util; import javax.media.opengl.*; +import com.sun.opengl.impl.GLReflection; import java.nio.*; import java.util.Iterator; import java.util.ArrayList; @@ -10,24 +11,39 @@ public class ImmModeSink { public static final boolean DEBUG_BEGIN_END = false; public static final boolean DEBUG_DRAW = false; - public static final boolean FLOAT2FIXED = false; - public static final int GL_QUADS = 0x0007; + // public static final int GL_QUADS = 0x0007; // Needs data manipulation public static final int GL_QUAD_STRIP = 0x0008; public static final int GL_POLYGON = 0x0009; - public ImmModeSink(int glDataType, int glDrawUsage, - int vComps, int nComps, int cComps, int tComps, int initialSize) { - - vboSet = new VBOSet(glDataType, glDrawUsage, vComps, nComps, cComps, tComps, initialSize); - this.vboSetList = new ArrayList(); + /** + * Uses a GL2ES1, or ES2 fixed function emulation immediate mode sink + */ + public static ImmModeSink createFixed(int glBufferUsage, int initialSize, + int vComps, int vDataType, + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType) { + return new ImmModeSink(glBufferUsage, initialSize, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, false); } - private void destroyList(GL gl) { - for(Iterator i=vboSetList.iterator(); i.hasNext() ; ) { - ((VBOSet)i.next()).destroy(gl); - } - vboSetList.clear(); + /** + * Uses a GL2ES2 GLSL shader immediate mode sink. + * To issue the draw() command, + * a ShaderState must be current, using ShaderState.glUseProgram(). + * + * @see #draw(GL, boolean) + * @see javax.media.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) + * @see javax.media.opengl.util.glsl.ShaderState#getCurrent() + */ + public static ImmModeSink createGLSL(int glBufferUsage, int initialSize, + int vComps, int vDataType, + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType) { + return new ImmModeSink(glBufferUsage, initialSize, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, true); } public void destroy(GL gl) { @@ -46,9 +62,20 @@ public class ImmModeSink { } public String toString() { - return "ImmModeSink[listsz: "+vboSetList.size()+ - ",\n"+vboSet+ - "]"; + StringBuffer sb = new StringBuffer("ImmModeSink["); + sb.append(",\n\tVBO list: "+vboSetList.size()+" ["); + for(Iterator i=vboSetList.iterator(); i.hasNext() ; ) { + sb.append("\n\t"); + sb.append( (VBOSet)i.next() ); + } + if(vboSetList.size()>0) { + sb.append("\n\t],\nVBO current: NOP]"); + } else { + sb.append("\n\t],\nVBO current: \n"); + sb.append(vboSet); + sb.append("\n]"); + } + return sb.toString(); } public void draw(GL gl, boolean disableBufferAfterDraw) { @@ -58,7 +85,18 @@ public class ImmModeSink { } int n=0; for(Iterator i=vboSetList.iterator(); i.hasNext() ; n++) { - ((VBOSet)i.next()).draw(gl, disableBufferAfterDraw, n); + ((VBOSet)i.next()).draw(gl, null, disableBufferAfterDraw, n); + } + } + + public void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw) { + if(DEBUG_DRAW) { + Exception e = new Exception("ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); + e.printStackTrace(); + } + int n=0; + for(Iterator i=vboSetList.iterator(); i.hasNext() ; n++) { + ((VBOSet)i.next()).draw(gl, indices, disableBufferAfterDraw, n); } } @@ -69,9 +107,10 @@ public class ImmModeSink { } vboSet.modeOrig = mode; switch(mode) { - case GL_QUADS: - mode=GL.GL_TRIANGLE_STRIP; - break; + // Needs data manipulation .. + //case GL_QUADS: + // mode=GL.GL_LINES; + // break; case GL_QUAD_STRIP: mode=GL.GL_TRIANGLE_STRIP; break; @@ -84,17 +123,25 @@ public class ImmModeSink { } public final void glEnd(GL gl) { - glEnd(gl, true); + glEnd(gl, null, true); } public void glEnd(GL gl, boolean immediateDraw) { + glEnd(gl, null, immediateDraw); + } + + public final void glEnd(GL gl, Buffer indices) { + glEnd(gl, indices, true); + } + + private void glEnd(GL gl, Buffer indices, boolean immediateDraw) { if(DEBUG_BEGIN_END) { Exception e = new Exception("ImmModeSink START glEnd(immediate: "+immediateDraw+"):\n\t"+this); e.printStackTrace(); } if(immediateDraw) { vboSet.seal(gl, false); - vboSet.draw(gl, true, -1); + vboSet.draw(gl, indices, true, -1); reset(gl); } else { vboSet.seal(gl, true); @@ -103,6 +150,9 @@ public class ImmModeSink { } } + public void glVertexv(Buffer v) { + vboSet.glVertexv(v); + } public final void glVertex2f(float x, float y) { vboSet.glVertex2f(x,y); } @@ -111,14 +161,27 @@ public class ImmModeSink { vboSet.glVertex3f(x,y,z); } + public void glNormalv(Buffer v) { + vboSet.glNormalv(v); + } public final void glNormal3f(float x, float y, float z) { vboSet.glNormal3f(x,y,z); } + public void glColorv(Buffer v) { + vboSet.glColorv(v); + } public final void glColor3f(float x, float y, float z) { vboSet.glColor3f(x,y,z); } + public final void glColor4f(float x, float y, float z, float a) { + vboSet.glColor4f(x,y,z, a); + } + + public void glTexCoordv(Buffer v) { + vboSet.glTexCoordv(v); + } public final void glTexCoord2f(float x, float y) { vboSet.glTexCoord2f(x,y); } @@ -127,29 +190,114 @@ public class ImmModeSink { vboSet.glTexCoord3f(x,y,z); } + public final void glVertex2s(short x, short y) { + vboSet.glVertex2s(x,y); + } + + public final void glVertex3s(short x, short y, short z) { + vboSet.glVertex3s(x,y,z); + } + + public final void glNormal3s(short x, short y, short z) { + vboSet.glNormal3s(x,y,z); + } + + public final void glColor3s(short x, short y, short z) { + vboSet.glColor3s(x,y,z); + } + + public final void glColor4s(short x, short y, short z, short a) { + vboSet.glColor4s(x,y,z,a); + } + + public final void glTexCoord2s(short x, short y) { + vboSet.glTexCoord2s(x,y); + } + + public final void glTexCoord3s(short x, short y, short z) { + vboSet.glTexCoord3s(x,y,z); + } + + public final void glVertex2b(byte x, byte y) { + vboSet.glVertex2b(x,y); + } + + public final void glVertex3b(byte x, byte y, byte z) { + vboSet.glVertex3b(x,y,z); + } + + public final void glNormal3b(byte x, byte y, byte z) { + vboSet.glNormal3b(x,y,z); + } + + public final void glColor3b(byte x, byte y, byte z) { + vboSet.glColor3b(x,y,z); + } + + public final void glColor4b(byte x, byte y, byte z, byte a) { + vboSet.glColor4b(x,y,z,a); + } + + public final void glTexCoord2b(byte x, byte y) { + vboSet.glTexCoord2b(x,y); + } + + public final void glTexCoord3b(byte x, byte y, byte z) { + vboSet.glTexCoord3b(x,y,z); + } + + protected ImmModeSink(int glBufferUsage, int initialSize, + int vComps, int vDataType, + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType, boolean useGLSL) { + if(useGLSL && !GLProfile.isGL2ES2()) { + throw new GLException("ImmModeSink GLSL usage not supported for profile: "+GLProfile.getProfile()); + } + vboSet = new VBOSet(glBufferUsage, initialSize, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL); + this.vboSetList = new ArrayList(); + } + + private void destroyList(GL gl) { + for(Iterator i=vboSetList.iterator(); i.hasNext() ; ) { + ((VBOSet)i.next()).destroy(gl); + } + vboSetList.clear(); + } + private VBOSet vboSet; private ArrayList vboSetList; protected static class VBOSet { - protected VBOSet(int glDataType, int glDrawUsage, - int vComps, int nComps, int cComps, int tComps, int initialSize) { - nComps = 0; - tComps = 0; - if(FLOAT2FIXED && glDataType==GL.GL_FLOAT) { - glDataType=GL2ES1.GL_FIXED; - } - this.glDataType=glDataType; - this.glDrawUsage=glDrawUsage; + protected VBOSet (int glBufferUsage, int initialSize, + int vComps, int vDataType, + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType, boolean useGLSL) { + this.glBufferUsage=glBufferUsage; + this.initialSize=initialSize; + this.vDataType=vDataType; this.vComps=vComps; - this.nComps=nComps; + this.cDataType=cDataType; this.cComps=cComps; + this.nDataType=nDataType; + this.nComps=nComps; + this.tDataType=tDataType; this.tComps=tComps; - this.initialSize=initialSize; - - this.vertexVBO = VBOBufferDraw.create(GL2ES1.GL_VERTEX_ARRAY, glDataType, glDrawUsage, vComps, initialSize); - this.normalVBO = VBOBufferDraw.create(GL2ES1.GL_NORMAL_ARRAY, glDataType, glDrawUsage, nComps, initialSize); - this.colorVBO = VBOBufferDraw.create(GL2ES1.GL_COLOR_ARRAY, glDataType, glDrawUsage, cComps, initialSize); - this.texcoordVBO = VBOBufferDraw.create(GL2ES1.GL_TEXTURE_COORD_ARRAY, glDataType, glDrawUsage, tComps, initialSize); + this.useGLSL=useGLSL; + + if(!useGLSL) { + this.vertexVBO = GLArrayDataServer.createFixed(GL.GL_VERTEX_ARRAY, null, vComps, vDataType, false, initialSize, glBufferUsage); + this.colorVBO = GLArrayDataServer.createFixed(GL.GL_COLOR_ARRAY, null, cComps, cDataType, false, initialSize, glBufferUsage); + this.normalVBO = GLArrayDataServer.createFixed(GL.GL_NORMAL_ARRAY, null, nComps, nDataType, false, initialSize, glBufferUsage); + this.texcoordVBO = GLArrayDataServer.createFixed(GL.GL_TEXTURE_COORD_ARRAY, null, tComps, tDataType, false, initialSize, glBufferUsage); + } else { + this.vertexVBO = GLArrayDataServer.createGLSL(GLContext.mgl_Vertex, vComps, vDataType, false, initialSize, glBufferUsage); + this.colorVBO = GLArrayDataServer.createGLSL(GLContext.mgl_Color, cComps, cDataType, false, initialSize, glBufferUsage); + this.normalVBO = GLArrayDataServer.createGLSL(GLContext.mgl_Normal, nComps, nDataType, false, initialSize, glBufferUsage); + this.texcoordVBO = GLArrayDataServer.createGLSL(GLContext.mgl_MultiTexCoord, tComps, tDataType, false, initialSize, glBufferUsage); + } this.sealed=false; this.mode = -1; @@ -157,7 +305,8 @@ public class ImmModeSink { } protected final VBOSet regenerate() { - return new VBOSet(glDataType, glDrawUsage, vComps, nComps, cComps, tComps, initialSize); + return new VBOSet(glBufferUsage, initialSize, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL); } protected void destroy(GL gl) { @@ -186,10 +335,10 @@ public class ImmModeSink { return "VBOSet[mode "+mode+ ", modeOrig "+modeOrig+ ", sealed "+sealed+ - ",\n\t vertexVBO "+vertexVBO+ - ",\n\t normalVBO "+normalVBO+ - ",\n\t colorVBO "+colorVBO+ - ",\n\t texcoordVBO "+texcoordVBO+ + ",\n\t"+vertexVBO+ + ",\n\t"+normalVBO+ + ",\n\t"+colorVBO+ + ",\n\t"+texcoordVBO+ "]"; } @@ -220,35 +369,60 @@ public class ImmModeSink { checkSeal(false); sealed = true; - vertexVBO.seal(gl, disableBufferAfterSeal); - normalVBO.seal(gl, disableBufferAfterSeal); - colorVBO.seal(gl, disableBufferAfterSeal); - texcoordVBO.seal(gl, disableBufferAfterSeal); + vertexVBO.seal(gl, true); + normalVBO.seal(gl, true); + colorVBO.seal(gl, true); + texcoordVBO.seal(gl, true); + + if(disableBufferAfterSeal) { + vertexVBO.enableBuffer(gl, false); + normalVBO.enableBuffer(gl, false); + colorVBO.enableBuffer(gl, false); + texcoordVBO.enableBuffer(gl, false); + } } - protected void draw(GL gl, boolean disableBufferAfterDraw, int i) + protected void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw, int i) { if(DEBUG_DRAW) { Exception e = new Exception("ImmModeSink.draw["+i+"](disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); e.printStackTrace(); } - vertexVBO.enableBuffer(gl); - normalVBO.enableBuffer(gl); - colorVBO.enableBuffer(gl); - texcoordVBO.enableBuffer(gl); + vertexVBO.enableBuffer(gl, true); + normalVBO.enableBuffer(gl, true); + colorVBO.enableBuffer(gl, true); + texcoordVBO.enableBuffer(gl, true); if (vertexVBO.getBuffer()!=null) { - gl.glDrawArrays(mode, 0, vertexVBO.getVerticeNumber()); + if(null==indices) { + gl.glDrawArrays(mode, 0, vertexVBO.getVerticeNumber()); + } else { + Class clazz = indices.getClass(); + int type=-1; + if(GLReflection.instanceOf(clazz, ByteBuffer.class.getName())) { + type = GL.GL_UNSIGNED_BYTE; + } else if(GLReflection.instanceOf(clazz, ShortBuffer.class.getName())) { + type = GL.GL_UNSIGNED_SHORT; + } + if(0>type) { + throw new GLException("Given Buffer Class not supported: "+clazz+", should be ubyte or ushort:\n\t"+this); + } + gl.glDrawElements(mode, indices.remaining(), type, indices); + } } if(disableBufferAfterDraw) { - vertexVBO.disableBuffer(gl); - normalVBO.disableBuffer(gl); - colorVBO.disableBuffer(gl); - texcoordVBO.disableBuffer(gl); + vertexVBO.enableBuffer(gl, false); + normalVBO.enableBuffer(gl, false); + colorVBO.enableBuffer(gl, false); + texcoordVBO.enableBuffer(gl, false); } } + protected void glVertexv(Buffer v) { + checkSeal(false); + vertexVBO.put(v); + } protected void glVertex2f(float x, float y) { checkSeal(false); vertexVBO.putf(x); @@ -256,7 +430,6 @@ public class ImmModeSink { vertexVBO.putf(y); vertexVBO.padding(2); } - protected void glVertex3f(float x, float y, float z) { checkSeal(false); vertexVBO.putf(x); @@ -267,6 +440,10 @@ public class ImmModeSink { vertexVBO.padding(3); } + protected void glNormalv(Buffer v) { + checkSeal(false); + normalVBO.put(v); + } protected void glNormal3f(float x, float y, float z) { checkSeal(false); normalVBO.putf(x); @@ -277,6 +454,10 @@ public class ImmModeSink { normalVBO.padding(3); } + protected void glColorv(Buffer v) { + checkSeal(false); + colorVBO.put(v); + } protected void glColor3f(float x, float y, float z) { checkSeal(false); colorVBO.putf(x); @@ -286,7 +467,22 @@ public class ImmModeSink { colorVBO.putf(z); colorVBO.padding(3); } + protected void glColor4f(float x, float y, float z, float a) { + checkSeal(false); + colorVBO.putf(x); + if(colorVBO.getComponents()>1) + colorVBO.putf(y); + if(colorVBO.getComponents()>2) + colorVBO.putf(z); + if(colorVBO.getComponents()>3) + colorVBO.putf(a); + colorVBO.padding(4); + } + protected void glTexCoordv(Buffer v) { + checkSeal(false); + texcoordVBO.put(v); + } protected void glTexCoord2f(float x, float y) { checkSeal(false); texcoordVBO.putf(x); @@ -294,7 +490,6 @@ public class ImmModeSink { texcoordVBO.putf(y); texcoordVBO.padding(2); } - protected void glTexCoord3f(float x, float y, float z) { checkSeal(false); texcoordVBO.putf(x); @@ -305,13 +500,145 @@ public class ImmModeSink { texcoordVBO.padding(3); } - VBOBufferDraw vertexVBO; - VBOBufferDraw normalVBO; - VBOBufferDraw colorVBO; - VBOBufferDraw texcoordVBO; + protected void glVertex2s(short x, short y) { + checkSeal(false); + vertexVBO.puts(x); + if(vertexVBO.getComponents()>1) + vertexVBO.puts(y); + vertexVBO.padding(2); + } + protected void glVertex3s(short x, short y, short z) { + checkSeal(false); + vertexVBO.puts(x); + if(vertexVBO.getComponents()>1) + vertexVBO.puts(y); + if(vertexVBO.getComponents()>2) + vertexVBO.puts(z); + vertexVBO.padding(3); + } + + protected void glNormal3s(short x, short y, short z) { + checkSeal(false); + normalVBO.puts(x); + if(normalVBO.getComponents()>1) + normalVBO.puts(y); + if(normalVBO.getComponents()>2) + normalVBO.puts(z); + normalVBO.padding(3); + } + + protected void glColor3s(short x, short y, short z) { + checkSeal(false); + colorVBO.puts(x); + if(colorVBO.getComponents()>1) + colorVBO.puts(y); + if(colorVBO.getComponents()>2) + colorVBO.puts(z); + colorVBO.padding(3); + } + protected void glColor4s(short x, short y, short z, short a) { + checkSeal(false); + colorVBO.puts(x); + if(colorVBO.getComponents()>1) + colorVBO.puts(y); + if(colorVBO.getComponents()>2) + colorVBO.puts(z); + if(colorVBO.getComponents()>3) + colorVBO.puts(a); + colorVBO.padding(4); + } + + protected void glTexCoord2s(short x, short y) { + checkSeal(false); + texcoordVBO.puts(x); + if(texcoordVBO.getComponents()>1) + texcoordVBO.puts(y); + texcoordVBO.padding(2); + } + protected void glTexCoord3s(short x, short y, short z) { + checkSeal(false); + texcoordVBO.puts(x); + if(texcoordVBO.getComponents()>1) + texcoordVBO.puts(y); + if(texcoordVBO.getComponents()>2) + texcoordVBO.puts(z); + texcoordVBO.padding(3); + } + + protected void glVertex2b(byte x, byte y) { + checkSeal(false); + vertexVBO.putb(x); + if(vertexVBO.getComponents()>1) + vertexVBO.putb(y); + vertexVBO.padding(2); + } + protected void glVertex3b(byte x, byte y, byte z) { + checkSeal(false); + vertexVBO.putb(x); + if(vertexVBO.getComponents()>1) + vertexVBO.putb(y); + if(vertexVBO.getComponents()>2) + vertexVBO.putb(z); + vertexVBO.padding(3); + } + + protected void glNormal3b(byte x, byte y, byte z) { + checkSeal(false); + normalVBO.putb(x); + if(normalVBO.getComponents()>1) + normalVBO.putb(y); + if(normalVBO.getComponents()>2) + normalVBO.putb(z); + normalVBO.padding(3); + } + + protected void glColor3b(byte x, byte y, byte z) { + checkSeal(false); + colorVBO.putb(x); + if(colorVBO.getComponents()>1) + colorVBO.putb(y); + if(colorVBO.getComponents()>2) + colorVBO.putb(z); + colorVBO.padding(3); + } + protected void glColor4b(byte x, byte y, byte z, byte a) { + checkSeal(false); + colorVBO.putb(x); + if(colorVBO.getComponents()>1) + colorVBO.putb(y); + if(colorVBO.getComponents()>2) + colorVBO.putb(z); + if(colorVBO.getComponents()>3) + colorVBO.putb(a); + colorVBO.padding(4); + } + protected void glTexCoord2b(byte x, byte y) { + checkSeal(false); + texcoordVBO.putb(x); + if(texcoordVBO.getComponents()>1) + texcoordVBO.putb(y); + texcoordVBO.padding(2); + } + + protected void glTexCoord3b(byte x, byte y, byte z) { + checkSeal(false); + texcoordVBO.putb(x); + if(texcoordVBO.getComponents()>1) + texcoordVBO.putb(y); + if(texcoordVBO.getComponents()>2) + texcoordVBO.putb(z); + texcoordVBO.padding(3); + } + + GLArrayDataServer vertexVBO; + GLArrayDataServer normalVBO; + GLArrayDataServer colorVBO; + GLArrayDataServer texcoordVBO; int mode, modeOrig; - int glDataType, glDrawUsage, vComps, nComps, cComps, tComps, initialSize; - boolean sealed; + int glBufferUsage, initialSize; + int vComps, cComps, nComps, tComps; + int vDataType, cDataType, nDataType, tDataType; + boolean sealed, useGLSL; } } diff --git a/src/classes/javax/media/opengl/util/PMVMatrix.java b/src/classes/javax/media/opengl/util/PMVMatrix.java index 4e8693be0..37472dfe6 100755 --- a/src/classes/javax/media/opengl/util/PMVMatrix.java +++ b/src/classes/javax/media/opengl/util/PMVMatrix.java @@ -9,55 +9,54 @@ import java.util.List; public class PMVMatrix { - protected ProjectFloat pvmProjectf = null; - protected FloatBuffer matrixPMV, matrixP, matrixMV; - protected FloatBuffer matrixTemp, matrixTrans, matrixRot, matrixScale, matrixOrtho, matrixPersp, matrixFrustum; - protected float[] vec3f; - protected List/*FloatBuffer*/ matrixPStack, matrixMVStack; - protected int matrixMode = GL.GL_MODELVIEW; - protected boolean modifiedPMV = false; - public PMVMatrix() { - pvmProjectf = new ProjectFloat(); + projectFloat = new ProjectFloat(); + + matrixIdent = BufferUtil.newFloatBuffer(1*16); + projectFloat.gluMakeIdentityf(matrixIdent); + matrixIdent.rewind(); + + matrixPMvMviT = BufferUtil.newFloatBuffer(4*16); // grouping P + Mv + Mvi + MviT + matrixPMvMvi = slice(matrixPMvMviT, 0*16, 3*16); // grouping P + Mv + Mvi + matrixPMv = slice(matrixPMvMviT, 0*16, 2*16); // grouping P + Mv + matrixP = slice(matrixPMvMviT, 0*16, 1*16); + matrixMv = slice(matrixPMvMviT, 1*16, 1*16); + matrixMvi = slice(matrixPMvMviT, 2*16, 1*16); + matrixMvit = slice(matrixPMvMviT, 3*16, 1*16); + matrixPMvMviT.rewind(); - matrixPMV = BufferUtil.newFloatBuffer(2*16); - matrixP = slice(matrixPMV, 0*16, 16); - matrixMV = slice(matrixPMV, 1*16, 16); - matrixPMV.rewind(); + matrixMvit3 = BufferUtil.newFloatBuffer(3*3); - FloatBuffer buf = BufferUtil.newFloatBuffer(7*16); + FloatBuffer buf = BufferUtil.newFloatBuffer(6*16); - matrixTemp=slice(buf, 0*16, 16); + matrixMult=slice(buf, 0*16, 16); matrixTrans=slice(buf, 1*16, 16); - pvmProjectf.gluMakeIdentityf(matrixTrans); + projectFloat.gluMakeIdentityf(matrixTrans); matrixRot=slice(buf, 2*16, 16); - pvmProjectf.gluMakeIdentityf(matrixRot); + projectFloat.gluMakeIdentityf(matrixRot); matrixScale=slice(buf, 3*16, 16); - pvmProjectf.gluMakeIdentityf(matrixScale); + projectFloat.gluMakeIdentityf(matrixScale); matrixOrtho=slice(buf, 4*16, 16); - pvmProjectf.gluMakeIdentityf(matrixOrtho); + projectFloat.gluMakeIdentityf(matrixOrtho); matrixFrustum=slice(buf, 5*16, 16); - pvmProjectf.gluMakeZero(matrixFrustum); - - matrixPersp=slice(buf, 6*16, 16); - pvmProjectf.gluMakeIdentityf(matrixPersp); + projectFloat.gluMakeZero(matrixFrustum); vec3f=new float[3]; matrixPStack = new ArrayList(); - matrixMVStack= new ArrayList(); + matrixMvStack= new ArrayList(); // default values and mode glMatrixMode(GL.GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL.GL_MODELVIEW); glLoadIdentity(); - modifiedPMV = true; + modified = true; } private static FloatBuffer slice(FloatBuffer buf, int pos, int len) { @@ -67,11 +66,16 @@ public class PMVMatrix { } public boolean isDirty() { - return modifiedPMV; + return modified; } - public void clear() { - modifiedPMV=false; + public boolean update() { + boolean res = modified; + if(res) { + setMviMvit(); + modified=false; + } + return res; } public final int glGetMatrixMode() { @@ -89,8 +93,24 @@ public class PMVMatrix { matrixMode = matrixName; } - public final FloatBuffer glGetPMVMatrixf() { - return matrixPMV; + public final FloatBuffer glGetPMvMviTMatrixf() { + return matrixPMvMviT; + } + + public final FloatBuffer glGetPMvMviMatrixf() { + return matrixPMvMvi; + } + + public final FloatBuffer glGetPMvMatrixf() { + return matrixPMv; + } + + public final FloatBuffer glGetMviMatrixf() { + return matrixMvi; + } + + public final FloatBuffer glGetNormalMatrixf() { + return matrixMvit3; } public final FloatBuffer glGetMatrixf() { @@ -99,82 +119,116 @@ public class PMVMatrix { public final FloatBuffer glGetMatrixf(int matrixName) { if(matrixName==GL.GL_MODELVIEW) { - return matrixMV; + return matrixMv; } else if(matrixName==GL.GL_PROJECTION) { return matrixP; } return null; } + public void glLoadMatrixf(float[] values, int offset) { + int len = values.length-offset; + if(matrixMode==GL.GL_MODELVIEW) { + matrixMv.clear(); + matrixMv.put(values, offset, len); + matrixMv.rewind(); + } else if(matrixMode==GL.GL_PROJECTION) { + matrixP.clear(); + matrixP.put(values, offset, len); + matrixP.rewind(); + } + modified = true; + } + public void glLoadMatrixf(java.nio.FloatBuffer m) { + int spos = m.position(); if(matrixMode==GL.GL_MODELVIEW) { - matrixMV.clear(); - matrixMV.put(m); - matrixMV.rewind(); + matrixMv.clear(); + matrixMv.put(m); + matrixMv.rewind(); } else if(matrixMode==GL.GL_PROJECTION) { matrixP.clear(); matrixP.put(m); matrixP.rewind(); } - modifiedPMV = true; + m.position(spos); + modified = true; } public void glPopMatrix() { + float[] stackEntry=null; if(matrixMode==GL.GL_MODELVIEW) { - matrixMV=(FloatBuffer)matrixMVStack.remove(0); + stackEntry = (float[])matrixMvStack.remove(0); } else if(matrixMode==GL.GL_PROJECTION) { - matrixP=(FloatBuffer)matrixPStack.remove(0); + stackEntry = (float[])matrixPStack.remove(0); } - modifiedPMV = true; + glLoadMatrixf(stackEntry, 0); } public void glPushMatrix() { + float[] stackEntry = new float[1*16]; if(matrixMode==GL.GL_MODELVIEW) { - matrixMVStack.add(0, matrixMV); + matrixMv.get(stackEntry); + matrixMv.rewind(); + matrixMvStack.add(0, stackEntry); } else if(matrixMode==GL.GL_PROJECTION) { - matrixPStack.add(0, matrixP); - } + matrixP.get(stackEntry); + matrixP.rewind(); + matrixPStack.add(0, stackEntry); + } } public void glLoadIdentity() { if(matrixMode==GL.GL_MODELVIEW) { - matrixMV.clear(); - pvmProjectf.gluMakeIdentityf(matrixMV); - matrixMV.rewind(); + matrixMv.clear(); + matrixMv.put(matrixIdent); + matrixMv.rewind(); + matrixIdent.rewind(); } else if(matrixMode==GL.GL_PROJECTION) { matrixP.clear(); - pvmProjectf.gluMakeIdentityf(matrixP); + matrixP.put(matrixIdent); matrixP.rewind(); + matrixIdent.rewind(); } - modifiedPMV = true; + modified = true; + } + + public void glMultMatrixf(FloatBuffer a, FloatBuffer b, FloatBuffer p) { + for (int i = 0; i < 4; i++) { + final float ai0=a.get(i+0*4), ai1=a.get(i+1*4), ai2=a.get(i+2*4), ai3=a.get(i+3*4); + p.put(i+0*4 , ai0 * b.get(0+0*4) + ai1 * b.get(1+0*4) + ai2 * b.get(2+0*4) + ai3 * b.get(3+0*4) ); + p.put(i+1*4 , ai0 * b.get(0+1*4) + ai1 * b.get(1+1*4) + ai2 * b.get(2+1*4) + ai3 * b.get(3+1*4) ); + p.put(i+2*4 , ai0 * b.get(0+2*4) + ai1 * b.get(1+2*4) + ai2 * b.get(2+2*4) + ai3 * b.get(3+2*4) ); + p.put(i+3*4 , ai0 * b.get(0+3*4) + ai1 * b.get(1+3*4) + ai2 * b.get(2+3*4) + ai3 * b.get(3+3*4) ); + } + // or .. projectFloat.gluMultMatricesf(b, a, p); } public void glMultMatrixf(FloatBuffer m) { if(matrixMode==GL.GL_MODELVIEW) { - pvmProjectf.gluMultMatricesf(m, matrixMV, matrixTemp); - matrixMV.clear(); - matrixMV.put(matrixTemp); - matrixMV.rewind(); + glMultMatrixf(matrixMv, m, matrixMult); + matrixMv.clear(); + matrixMv.put(matrixMult); + matrixMv.rewind(); } else if(matrixMode==GL.GL_PROJECTION) { - pvmProjectf.gluMultMatricesf(m, matrixP, matrixTemp); + glMultMatrixf(matrixP, m, matrixMult); matrixP.clear(); - matrixP.put(matrixTemp); + matrixP.put(matrixMult); matrixP.rewind(); } - matrixTemp.rewind(); - modifiedPMV = true; + matrixMult.rewind(); + modified = true; } public void glTranslatef(float x, float y, float z) { // Translation matrix: - // 1 0 0 0 - // 0 1 0 0 - // 0 0 1 0 - // x y z 1 - matrixTrans.put(3*4+0, x); - matrixTrans.put(3*4+1, y); - matrixTrans.put(3*4+2, z); - + // 1 0 0 x + // 0 1 0 y + // 0 0 1 z + // 0 0 0 1 + matrixTrans.put(0+4*3, x); + matrixTrans.put(1+4*3, y); + matrixTrans.put(2+4*3, z); glMultMatrixf(matrixTrans); } @@ -185,7 +239,7 @@ public class PMVMatrix { float s = (float)Math.sin(angrad); vec3f[0]=x; vec3f[1]=y; vec3f[2]=z; - pvmProjectf.normalize(vec3f); + projectFloat.normalize(vec3f); x = vec3f[0]; y = vec3f[1]; z = vec3f[2]; // Rotation matrix: @@ -199,6 +253,19 @@ public class PMVMatrix { float ys = y*s; float yz = y*z; float zs = z*s; + if(false) { + matrixRot.put(0+4*0, x*x*ic+c); + matrixRot.put(0+4*1, xy*ic+zs); + matrixRot.put(0+4*2, xz*ic-ys); + + matrixRot.put(1+4*0, xy*ic+zs); + matrixRot.put(1+4*1, y*y*ic+c); + matrixRot.put(1+4*2, yz*ic-xs); + + matrixRot.put(2+4*0, xz*ic-ys); + matrixRot.put(2+4*1, yz*ic+xs); + matrixRot.put(2+4*2, z*z*ic+c); + } else { matrixRot.put(0*4+0, x*x*ic+c); matrixRot.put(0*4+1, xy*ic+zs); matrixRot.put(0*4+2, xz*ic-ys); @@ -210,6 +277,7 @@ public class PMVMatrix { matrixRot.put(2*4+0, xz*ic+ys); matrixRot.put(2*4+1, yz*ic-xs); matrixRot.put(2*4+2, z*z*ic+c); + } glMultMatrixf(matrixRot); } @@ -220,19 +288,19 @@ public class PMVMatrix { // 0 y 0 0 // 0 0 z 0 // 0 0 0 1 - matrixScale.put(0*4+0, x); - matrixScale.put(1*4+1, y); - matrixScale.put(2*4+2, z); + matrixScale.put(0+4*0, x); + matrixScale.put(1+4*1, y); + matrixScale.put(2+4*2, z); glMultMatrixf(matrixScale); } public void glOrthof(float left, float right, float bottom, float top, float zNear, float zFar) { // Ortho matrix: - // 2/dx 0 0 0 - // 0 2/dy 0 0 - // 0 0 2/dz 0 - // tx tx tx 1 + // 2/dx 0 0 tx + // 0 2/dy 0 ty + // 0 0 2/dz tz + // 0 0 0 1 float dx=right-left; float dy=top-bottom; float dz=zFar-zNear; @@ -240,12 +308,12 @@ public class PMVMatrix { float ty=-1.0f*(top+bottom)/dy; float tz=-1.0f*(zFar+zNear)/dz; - matrixOrtho.put(0*4+0, 2.0f/dx); - matrixOrtho.put(1*4+1, 2.0f/dy); - matrixOrtho.put(2*4+2, -2.0f/dz); - matrixOrtho.put(3*4+0, tx); - matrixOrtho.put(3*4+1, ty); - matrixOrtho.put(3*4+2, tz); + matrixOrtho.put(0+4*0, 2.0f/dx); + matrixOrtho.put(1+4*1, 2.0f/dy); + matrixOrtho.put(2+4*2, -2.0f/dz); + matrixOrtho.put(0+4*3, tx); + matrixOrtho.put(1+4*3, ty); + matrixOrtho.put(2+4*3, tz); glMultMatrixf(matrixOrtho); } @@ -271,40 +339,57 @@ public class PMVMatrix { float C=-1.0f*(zFar+zNear)/dz; float D=-2.0f*(zFar*zNear)/dz; - matrixFrustum.put(0*4+0, zNear2/dx); - matrixFrustum.put(1*4+1, zNear2/dy); - matrixFrustum.put(2*4+2, C); - matrixFrustum.put(0*4+2, A); - matrixFrustum.put(1*4+2, B); - matrixFrustum.put(2*4+3, D); - matrixFrustum.put(3*4+2, -1.0f); + matrixFrustum.put(0+4*0, zNear2/dx); + matrixFrustum.put(1+4*1, zNear2/dy); + matrixFrustum.put(2+4*2, C); + + matrixFrustum.put(0+4*2, A); + matrixFrustum.put(1+4*2, B); + + matrixFrustum.put(2+4*3, D); + matrixFrustum.put(3+4*2, -1.0f); glMultMatrixf(matrixFrustum); } public void gluPerspective(float fovy, float aspect, float zNear, float zFar) { - float radians = fovy/2 * (float) Math.PI / 180; - - float sine, cotangent, deltaZ; + float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear; + float bottom=-1.0f*top; + float left=aspect*bottom; + float right=aspect*top; + glFrustumf(left, right, bottom, top, zNear, zFar); + } - deltaZ = zFar - zNear; - sine = (float) Math.sin(radians); + private void setMviMvit() { + if(!projectFloat.gluInvertMatrixf(matrixMv, matrixMvi)) { + throw new GLException("Invalid source Mv matrix, can't compute inverse"); + } - if ((deltaZ == 0.0f) || (sine == 0.0f) || (aspect == 0.0f)) { - return; + // transpose matrix + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + matrixMvit.put(j+i*4, matrixMvi.get(i+j*4)); + } } - cotangent = (float) Math.cos(radians) / sine; + // fetch 3x3 + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + matrixMvit3.put(i+j*3, matrixMvit.get(i+j*4)); + } + } + } - matrixPersp.put(0 * 4 + 0, cotangent / aspect); - matrixPersp.put(1 * 4 + 1, cotangent); - matrixPersp.put(2 * 4 + 2, - (zFar + zNear) / deltaZ); - matrixPersp.put(2 * 4 + 3, -1); - matrixPersp.put(3 * 4 + 2, -2 * zNear * zFar / deltaZ); - matrixPersp.put(3 * 4 + 3, 0); + protected FloatBuffer matrixIdent; + protected FloatBuffer matrixPMvMviT, matrixPMvMvi, matrixPMv, matrixP, matrixMv, matrixMvi, matrixMvit; + protected FloatBuffer matrixMvit3; + protected FloatBuffer matrixMult, matrixTrans, matrixRot, matrixScale, matrixOrtho, matrixFrustum; + protected float[] vec3f; + protected List/*FloatBuffer*/ matrixPStack, matrixMvStack; + protected int matrixMode = GL.GL_MODELVIEW; + protected boolean modified = false; + protected ProjectFloat projectFloat; - glMultMatrixf(matrixPersp); - } } diff --git a/src/classes/javax/media/opengl/util/VBOBufferDraw.java b/src/classes/javax/media/opengl/util/VBOBufferDraw.java deleted file mode 100644 index 8ce1b3232..000000000 --- a/src/classes/javax/media/opengl/util/VBOBufferDraw.java +++ /dev/null @@ -1,392 +0,0 @@ - -package javax.media.opengl.util; - -import javax.media.opengl.*; -import java.nio.*; -import com.sun.opengl.impl.*; - -public abstract class VBOBufferDraw { - - public static VBOBufferDraw create(int glArrayType, int glDataType, int glBufferUsage, int comps, int initialSize) - throws GLException - { - Class[] types = new Class[]{ int.class, int.class, int.class, int.class, int.class }; - Object[] args = new Integer[]{ new Integer(glArrayType), new Integer(glDataType), new Integer(glBufferUsage), - new Integer(comps), new Integer(initialSize) } ; - - if(GLProfile.isGL2ES1()) { - return (VBOBufferDraw) GLReflection.createInstance("com.sun.opengl.impl.gl2es1.VBOBufferDrawGL2ES1", types, args); - } else if(GLProfile.isGLES2()) { - return (VBOBufferDraw) GLReflection.createInstance("com.sun.opengl.impl.es2.VBOBufferDrawGLES2", types, args); - } - throw new GLException("VBOBufferDraw not supported for profile: "+GLProfile.getProfile()); - } - - protected void init(int glArrayType, int glDataType, int glBufferUsage, int comps, int initialSize) - throws GLException - { - vboUsage=true; - - switch(glArrayType) { - case GL2ES1.GL_VERTEX_ARRAY: - case GL2ES1.GL_NORMAL_ARRAY: - if(3!=comps && 0!=comps) { - throw new GLException("component size for NORMAL_ARRAY must be 3 or 0: "+comps+" \n\t"+this); - } - case GL2ES1.GL_COLOR_ARRAY: - case GL2ES1.GL_TEXTURE_COORD_ARRAY: - break; - default: - throw new GLException("invalid glArrayType: "+glArrayType+":\n\t"+this); - } - this.glArrayType = glArrayType; - this.glDataType = glDataType; - this.clazz = getBufferClass(glDataType); - this.buffer = null; - this.components = comps; - this.initialSize = initialSize; - if( ! (GLProfile.isGL2ES2() && glBufferUsage==GL2ES2.GL_STREAM_DRAW) ) { - switch(glBufferUsage) { - case GL2ES1.GL_STATIC_DRAW: - case GL2ES1.GL_DYNAMIC_DRAW: - break; - default: - throw new GLException("invalid glBufferUsage: "+glBufferUsage+":\n\t"+this); - } - } - this.glBufferUsage = glBufferUsage; - this.vboName = 0; - this.sealed=false; - this.bufferEnabled=false; - growVBO(initialSize); - } - - public boolean usesVBO() { return vboUsage; } - - public void setVBOUsage(boolean vboUsage) { - checkSeal(false); - this.vboUsage=vboUsage; - } - - public int getGLArrayType() { - return glArrayType; - } - - public int getGlDataType() { - return glDataType; - } - - public int getComponents() { - return components; - } - - public Class getBufferClass() { - return clazz; - } - - public Buffer getBuffer() { - return buffer; - } - - public int getBufferUsage() { - return glBufferUsage; - } - - public void destroy(GL gl) { - reset(gl); - if(vboName!=0) { - int[] tmp = new int[1]; - tmp[0] = vboName; - gl.glDeleteBuffers(1, tmp, 0); - vboName = 0; - } - } - - public void reset() { - reset(null); - } - - public void reset(GL gl) { - if(gl!=null) { - disableBuffer(gl); - } - this.sealed=false; - if(buffer!=null) { - buffer.clear(); - } - } - - private final void init_vbo(GL gl) { - if(vboUsage && vboName==0) { - int[] tmp = new int[1]; - gl.glGenBuffers(1, tmp, 0); - vboName = tmp[0]; - } - } - - private final void checkSeal(boolean test) throws GLException { - if(sealed!=test) { - if(test) { - throw new GLException("Not Sealed yet, seal first:\n\t"+this); - } else { - throw new GLException("Already Sealed, can't modify VBO:\n\t"+this); - } - } - } - - public final boolean growVBOIfNecessary(int spare) { - if(buffer==null) { - throw new GLException("buffer no configured:\n\t"+this); - } - if(buffer!=null && buffer.remaining()<spare) { - growVBO(); - return true; - } - return false; - } - - public final void growVBO() { - growVBO(initialSize); - } - - public static final Class getBufferClass(int glDataType) { - switch(glDataType) { - case GL2ES1.GL_BYTE: - case GL2ES1.GL_UNSIGNED_BYTE: - return ByteBuffer.class; - case GL2ES1.GL_SHORT: - case GL2ES1.GL_UNSIGNED_SHORT: - return ShortBuffer.class; - case GL2ES1.GL_FIXED: - return IntBuffer.class; - case GL2ES1.GL_FLOAT: - return FloatBuffer.class; - default: - throw new GLException("Given OpenGL data type not supported: "+glDataType); - } - } - - public final int getBufferCompSize() { - if(clazz==ByteBuffer.class) { - return BufferUtil.SIZEOF_BYTE; - } - if(clazz==ShortBuffer.class) { - return BufferUtil.SIZEOF_SHORT; - } - if(clazz==IntBuffer.class) { - return BufferUtil.SIZEOF_INT; - } - if(clazz==FloatBuffer.class) { - return BufferUtil.SIZEOF_FLOAT; - } - throw new GLException("Given Buffer Class not supported: "+clazz+":\n\t"+this); - } - - public final void growVBO(int additional) { - int osize; - - checkSeal(false); - - if(components>0) { - osize = (buffer!=null)?buffer.capacity():0; - if(clazz==ByteBuffer.class) { - ByteBuffer newBBuffer = BufferUtil.newByteBuffer( (osize+additional) * components ); - if(buffer!=null) { - buffer.flip(); - newBBuffer.put((ByteBuffer)buffer); - } - buffer = newBBuffer; - } else if(clazz==ShortBuffer.class) { - ShortBuffer newSBuffer = BufferUtil.newShortBuffer( (osize+additional) * components ); - if(buffer!=null) { - buffer.flip(); - newSBuffer.put((ShortBuffer)buffer); - } - buffer = newSBuffer; - } else if(clazz==IntBuffer.class) { - IntBuffer newIBuffer = BufferUtil.newIntBuffer( (osize+additional) * components ); - if(buffer!=null) { - buffer.flip(); - newIBuffer.put((IntBuffer)buffer); - } - buffer = newIBuffer; - } else if(clazz==FloatBuffer.class) { - FloatBuffer newFBuffer = BufferUtil.newFloatBuffer( (osize+additional) * components ); - if(buffer!=null) { - buffer.flip(); - newFBuffer.put((FloatBuffer)buffer); - } - buffer = newFBuffer; - } else { - throw new GLException("Given Buffer Class not supported: "+clazz+":\n\t"+this); - } - } - } - - public void rewind() { - checkSeal(true); - - if(buffer!=null) { - buffer.rewind(); - } - } - - public int getVerticeNumber() { - return ( buffer!=null ) ? ( buffer.limit() / components ) : 0 ; - } - - public void seal(GL gl, boolean disableAfterSeal) - { - checkSeal(false); - sealed = true; - init_vbo(gl); - - if (null!=buffer) { - buffer.flip(); - enableBuffer(gl, true); - } - if(null==buffer || disableAfterSeal) { - disableBuffer(gl); - } - - } - - public void enableBuffer(GL gl) - { - enableBuffer(gl, false); - } - - private void enableBuffer(GL gl, boolean newData) - { - checkSeal(true); - enableBufferGLImpl(gl, newData); - } - - protected abstract void enableBufferGLImpl(GL gl, boolean newData); - - public void disableBuffer(GL gl) { - disableBufferGLImpl(gl); - } - - protected abstract void disableBufferGLImpl(GL gl) ; - - public void padding(int done) { - if(buffer==null) return; // JAU - if(buffer==null) { - throw new GLException("buffer no configured:\n\t"+this); - } - while(done<components) { - if(clazz==ByteBuffer.class) { - ((ByteBuffer)buffer).put((byte)0); - } else if(clazz==ShortBuffer.class) { - ((ShortBuffer)buffer).put((short)0); - } else if(clazz==IntBuffer.class) { - ((IntBuffer)buffer).put(0); - } else if(clazz==FloatBuffer.class) { - ((FloatBuffer)buffer).put(0f); - } else { - throw new GLException("Given Buffer Class not supported: "+clazz+" :\n\t"+this); - } - done++; - } - } - - public void putb(byte v) { - if(buffer==null) return; // JAU - growVBOIfNecessary(1); - if(clazz==ByteBuffer.class) { - ((ByteBuffer)buffer).put(v); - } else if(clazz==ShortBuffer.class) { - ((ShortBuffer)buffer).put((short)v); - } else if(clazz==IntBuffer.class) { - ((IntBuffer)buffer).put((int)v); - } else { - throw new GLException("Byte doesn't match Buffer Class: "+clazz+" :\n\t"+this); - } - } - - public void puts(short v) { - if(buffer==null) return; // JAU - growVBOIfNecessary(1); - if(clazz==ShortBuffer.class) { - ((ShortBuffer)buffer).put(v); - } else if(clazz==IntBuffer.class) { - ((IntBuffer)buffer).put((int)v); - } else { - throw new GLException("Short doesn't match Buffer Class: "+clazz+" :\n\t"+this); - } - } - - public void puti(int v) { - if(buffer==null) return; // JAU - growVBOIfNecessary(1); - if(clazz==IntBuffer.class) { - ((IntBuffer)buffer).put(v); - } else { - throw new GLException("Integer doesn't match Buffer Class: "+clazz+" :\n\t"+this); - } - } - - public void putx(int v) { - if(buffer==null) return; // JAU - growVBOIfNecessary(1); - if(clazz==IntBuffer.class) { - ((IntBuffer)buffer).put(v); - } else { - throw new GLException("Fixed doesn't match Buffer Class: "+clazz+" :\n\t"+this); - } - } - - public void putf(float v) { - if(buffer==null) return; // JAU - growVBOIfNecessary(1); - if(clazz==FloatBuffer.class) { - ((FloatBuffer)buffer).put(v); - } else if(clazz==IntBuffer.class) { - ((IntBuffer)buffer).put(FixedPoint.toFixed(v)); - } else { - throw new GLException("Float doesn't match Buffer Class: "+clazz+" :\n\t"+this); - } - } - - public void putd(double v) { - if(buffer==null) return; // JAU - growVBOIfNecessary(1); - if(clazz==FloatBuffer.class) { - // FIXME: ok ? - ((FloatBuffer)buffer).put((float)v); - } else { - throw new GLException("Double doesn't match Buffer Class: "+clazz+" :\n\t"+this); - } - } - - public String toString() { - return "VBOBufferDraw[vertices "+getVerticeNumber()+ - ", glArrayType "+glArrayType+ - ", glDataType "+glDataType+ - ", bufferClazz "+clazz+ - ", components "+components+ - ", initialSize "+initialSize+ - ", glBufferUsage "+glBufferUsage+ - ", vboUsage "+vboUsage+ - ", vboName "+vboName+ - ", sealed "+sealed+ - ", bufferEnabled "+bufferEnabled+ - ",\n\tbuffer "+buffer+ - "]"; - } - - protected int glArrayType; - protected int glDataType; - protected Class clazz; - protected Buffer buffer; - protected int components; - protected int initialSize; - protected int glBufferUsage; - protected int vboName; - protected boolean sealed; - protected boolean bufferEnabled; - protected boolean vboUsage; - -} - diff --git a/src/classes/javax/media/opengl/util/glsl/ShaderCode.java b/src/classes/javax/media/opengl/util/glsl/ShaderCode.java new file mode 100644 index 000000000..46ead1b30 --- /dev/null +++ b/src/classes/javax/media/opengl/util/glsl/ShaderCode.java @@ -0,0 +1,122 @@ + +package javax.media.opengl.util.glsl; + +import javax.media.opengl.util.*; +import javax.media.opengl.*; + +import java.nio.*; +import java.io.PrintStream; + +public class ShaderCode { + public ShaderCode(int type, int number, + int binFormat, Buffer binary, String[][] source) { + switch (type) { + case GL2ES2.GL_VERTEX_SHADER: + case GL2ES2.GL_FRAGMENT_SHADER: + break; + default: + throw new GLException("Unknown shader type: "+type); + } + shaderSource = source; + shaderBinaryFormat = binFormat; + shaderBinary = binary; + shaderType = type; + shader = BufferUtil.newIntBuffer(number); + id = getNextID(); + } + + /** + * returns the uniq shader id as an integer + * @see #key() + */ + public int id() { return id.intValue(); } + + /** + * returns the uniq shader id as an Integer + * + * @see #id() + */ + public Integer key() { return id; } + + public int shaderType() { return shaderType; } + public String shaderTypeStr() { return shaderTypeStr(shaderType); } + + public static String shaderTypeStr(int type) { + switch (type) { + case GL2ES2.GL_VERTEX_SHADER: + return "VERTEX_SHADER"; + case GL2ES2.GL_FRAGMENT_SHADER: + return "FRAGMENT_SHADER"; + } + return "UNKNOWN_SHADER"; + } + + public int shaderBinaryFormat() { return shaderBinaryFormat; } + public Buffer shaderBinary() { return shaderBinary; } + public String[][] shaderSource() { return shaderSource; } + + public boolean isValid() { return valid; } + + public IntBuffer shader() { return shader; } + + public boolean compile(GL2ES2 gl) { + return compile(gl, null); + } + public boolean compile(GL2ES2 gl, PrintStream verboseOut) { + if(isValid()) return true; + + // Create & Compile the vertex/fragment shader objects + valid=gl.glCreateCompileShader(shader, shaderType, + shaderBinaryFormat, shaderBinary, + shaderSource, verboseOut); + shader.clear(); + return valid; + } + + public void release(GL2ES2 gl) { + if(isValid()) { + gl.glDeleteShader(shader()); + valid=false; + } + } + + public boolean equals(Object obj) { + if(this==obj) return true; + if(obj instanceof ShaderCode) { + return id()==((ShaderCode)obj).id(); + } + return false; + } + public int hashCode() { + return id.intValue(); + } + public String toString() { + StringBuffer buf = new StringBuffer("ShaderCode [id="+id+", type="+shaderTypeStr()+", valid="+valid); + /* + if(shaderSource!=null) { + for(int i=0; i<shaderSource.length; i++) { + for(int j=0; j<shaderSource[i].length; j++) { + buf.append("\n\t, ShaderSource["+i+"]["+j+"]:\n"); + buf.append(shaderSource[i][j]); + } + } + } */ + buf.append("]"); + return buf.toString(); + } + + protected String[][] shaderSource = null; + protected Buffer shaderBinary = null; + protected int shaderBinaryFormat = -1; + protected IntBuffer shader = null; + protected int shaderType = -1; + protected Integer id = null; + + protected boolean valid=false; + + private static synchronized Integer getNextID() { + return new Integer(nextID++); + } + protected static int nextID = 1; +} + diff --git a/src/classes/javax/media/opengl/util/glsl/ShaderProgram.java b/src/classes/javax/media/opengl/util/glsl/ShaderProgram.java new file mode 100644 index 000000000..5628f3332 --- /dev/null +++ b/src/classes/javax/media/opengl/util/glsl/ShaderProgram.java @@ -0,0 +1,201 @@ + +package javax.media.opengl.util.glsl; + +import javax.media.opengl.util.*; +import javax.media.opengl.*; + +import java.util.HashMap; +import java.util.Iterator; +import java.nio.*; +import java.io.PrintStream; + +public class ShaderProgram { + public ShaderProgram() { + id = getNextID(); + } + + public boolean linked() { + return programLinked; + } + + public boolean inUse() { + return programInUse; + } + + public int program() { return shaderProgram; } + + /** + * returns the uniq shader id as an integer + * @see #key() + */ + public int id() { return id.intValue(); } + + /** + * returns the uniq shader id as an Integer + * + * @see #id() + */ + public Integer key() { return id; } + + /** + * @see #glReleaseAllVertexAttributes + */ + public synchronized void release(GL2ES2 gl) { + release(gl, false); + } + + /** + * @see #glReleaseAllVertexAttributes + */ + public synchronized void release(GL2ES2 gl, boolean releaseShaderToo) { + glUseProgram(gl, false); + for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) { + ShaderCode shaderCode = (ShaderCode) iter.next(); + gl.glDetachShader(shaderProgram, shaderCode.shader()); + if(releaseShaderToo) { + shaderCode.release(gl); + } + } + shaderMap.clear(); + gl.glDeleteProgram(shaderProgram); + shaderProgram=-1; + } + + // + // ShaderCode handling + // + + /** + * Adds a new shader to a this non running program. + * + * @return false if the program is in use, or the shader already exist, + * otherwise true. + */ + public synchronized boolean add(ShaderCode shaderCode) { + if(shaderMap.containsKey(shaderCode.key())) return false; + shaderMap.put(shaderCode.key(), shaderCode); + return true; + } + + public synchronized ShaderCode getShader(int id) { + return (ShaderCode) shaderMap.get(new Integer(id)); + } + + // + // Program handling + // + + /** + * Replace a shader in a 'running' program. + * Refetches all previously bin/get attribute names + * and resets all attribute data as well + * + * @see getAttribLocation + * @param gl + * @param oldShaderID the to be replace Shader + * @param newShader the new ShaderCode + * @param verboseOut the optional verbose outputstream + * @throws GLException is the program is not linked + * + * @see #glRefetchAttribLocations + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public synchronized boolean glReplaceShader(GL2ES2 gl, int oldShaderID, ShaderCode newShader, PrintStream verboseOut) { + if(!programLinked) throw new GLException("Program is not linked"); + boolean shaderWasInUse = programInUse; + glUseProgram(gl, false); + if(!newShader.compile(gl, verboseOut)) { + return false; + } + if(oldShaderID>=0) { + ShaderCode oldShader = (ShaderCode) shaderMap.remove(new Integer(oldShaderID)); + if(null!=oldShader) { + gl.glDetachShader(shaderProgram, oldShader.shader()); + } + } + add(newShader); + + gl.glAttachShader(shaderProgram, newShader.shader()); + gl.glLinkProgram(shaderProgram); + if ( ! gl.glIsProgramValid(shaderProgram, System.err) ) { + return false; + } + + if(shaderWasInUse) { + glUseProgram(gl, true); + } + return true; + } + + public synchronized boolean link(GL2ES2 gl, PrintStream verboseOut) { + if(programLinked) throw new GLException("Program is already linked"); + + if(0>shaderProgram) { + shaderProgram = gl.glCreateProgram(); + } + + for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) { + ShaderCode shaderCode = (ShaderCode) iter.next(); + if(!shaderCode.compile(gl, verboseOut)) { + return false; + } + gl.glAttachShader(shaderProgram, shaderCode.shader()); + } + + // Link the program + gl.glLinkProgram(shaderProgram); + + if ( ! gl.glIsProgramValid(shaderProgram, System.err) ) { + return false; + } + programLinked=true; + + return true; + } + + public boolean equals(Object obj) { + if(this==obj) return true; + if(obj instanceof ShaderCode) { + return id()==((ShaderCode)obj).id(); + } + return false; + } + public int hashCode() { + return id.intValue(); + } + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("ShaderProgram[id="+id); + buf.append(", linked="+programLinked+", inUse="+programInUse+", program: "+shaderProgram+", ["); + for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) { + buf.append((ShaderCode) iter.next()); + buf.append(" "); + } + buf.append("]"); + return buf.toString(); + } + + protected synchronized void glUseProgram(GL2ES2 gl, boolean on) { + if(!programLinked) throw new GLException("Program is not linked"); + if(programInUse==on) return; + gl.glUseProgram(on?shaderProgram:0); + programInUse = on; + + //Throwable tX = new Throwable("Info: ShaderProgram.glUseProgram: "+on); + //tX.printStackTrace(); + + } + + protected boolean programLinked = false; + protected boolean programInUse = false; + protected int shaderProgram=-1; + protected HashMap shaderMap = new HashMap(); + protected Integer id = null; + + private static synchronized Integer getNextID() { + return new Integer(nextID++); + } + protected static int nextID = 1; +} + diff --git a/src/classes/javax/media/opengl/util/glsl/ShaderState.java b/src/classes/javax/media/opengl/util/glsl/ShaderState.java new file mode 100644 index 000000000..7f917cc07 --- /dev/null +++ b/src/classes/javax/media/opengl/util/glsl/ShaderState.java @@ -0,0 +1,583 @@ + +package javax.media.opengl.util.glsl; + +import javax.media.opengl.util.*; +import javax.media.opengl.*; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.nio.*; +import java.io.PrintStream; + +public class ShaderState { + + public ShaderState() { + } + + public boolean verbose() { return verbose; } + + public void setVerbose(boolean v) { verbose=v; } + + /** + * Fetches the current shader state + * + * @see javax.media.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) + * @see javax.media.opengl.util.glsl.ShaderState#getCurrent() + */ + public static synchronized ShaderState getCurrent() { return currentShaderState; } + + /** + * Turns the shader program on + * and set this ShaderState to current if on equals true + * + * @see javax.media.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) + * @see javax.media.opengl.util.glsl.ShaderState#getCurrent() + */ + public synchronized void glUseProgram(GL2ES2 gl, boolean on) { + if(on) { + if(null!=shaderProgram) { + shaderProgram.glUseProgram(gl, true); + } else { + throw new GLException("No program is attached"); + } + if(currentShaderState!=this) { + currentShaderState = this; + } + } else if(null!=shaderProgram) { + shaderProgram.glUseProgram(gl, false); + } + } + + public boolean linked() { + return (null!=shaderProgram)?shaderProgram.linked():false; + } + + public boolean inUse() { + return (null!=shaderProgram)?shaderProgram.inUse():false; + } + + /** + * Attach or switch a shader program + * + * Attaching a shader program the first time, + * as well as switching to another program on the fly, + * while managing all attribute and uniform data. + */ + public synchronized void attachShaderProgram(GL2ES2 gl, ShaderProgram prog) { + boolean prgInUse = false; // earmarked state + + if(null!=shaderProgram) { + if(shaderProgram.equals(prog)) { + // nothing to do .. + if(DEBUG) { + System.err.println("Info: attachShaderProgram: NOP: equal id: "+shaderProgram.id()); + } + return; + } + prgInUse = shaderProgram.inUse(); + } + if(DEBUG) { + Throwable tX = new Throwable("Info: attachShaderProgram: BEGIN "+shaderProgram+" -> "+prog); + tX.printStackTrace(); + } + + // register new one + shaderProgram = prog; + + if(null!=shaderProgram) { + // reinstall all data .. + shaderProgram.glUseProgram(gl, true); + glResetAllVertexAttributes(gl); + glResetAllUniforms(gl); + if(!prgInUse) { + shaderProgram.glUseProgram(gl, false); + } + } + if(DEBUG) { + System.err.println("Info: attachShaderProgram: END"); + } + } + + public ShaderProgram shaderProgram() { return shaderProgram; } + + /** + * @see #glReleaseAllVertexAttributes + * @see #glReleaseAllUniforms + */ + public synchronized void release(GL2ES2 gl) { + release(gl, false, false); + } + + public synchronized void release(GL2ES2 gl, boolean releaseProgramToo, boolean releaseShaderToo) { + boolean prgInUse = false; + if(null!=shaderProgram) { + prgInUse = shaderProgram.inUse(); + if(!prgInUse) { + shaderProgram.glUseProgram(gl, true); + } + } + glReleaseAllVertexAttributes(gl); + glReleaseAllUniforms(gl); + if(null!=shaderProgram) { + if(releaseProgramToo) { + shaderProgram.release(gl, releaseShaderToo); + } else if(!prgInUse) { + shaderProgram.glUseProgram(gl, false); + } + } + } + + // + // Shader attribute handling + // + + /** + * Binds an attribute to the shader. + * This must be done before the program is linked ! + * n name - 1 idx, where name is a uniq key + * + * @throws GLException is the program is already linked + * + * @see #glBindAttribLocation + * @see javax.media.opengl.GL2ES2#glBindAttribLocation + * @see #glGetAttribLocation + * @see javax.media.opengl.GL2ES2#glGetAttribLocation + * @see #getAttribLocation + * @see #glReplaceShader + */ + public void glBindAttribLocation(GL2ES2 gl, int index, String name) { + if(null==shaderProgram) throw new GLException("No program is attached"); + if(shaderProgram.linked()) throw new GLException("Program is already linked"); + Integer idx = new Integer(index); + if(!attribMap2Idx.containsKey(name)) { + attribMap2Idx.put(name, idx); + gl.glBindAttribLocation(shaderProgram.program(), index, name); + } + } + + /** + * Gets the index of a shader attribute. + * This must be done after the program is linked ! + * + * @return -1 if there is no such attribute available, + * otherwise >= 0 + * @throws GLException is the program is not linked + * + * @see #glBindAttribLocation + * @see javax.media.opengl.GL2ES2#glBindAttribLocation + * @see #glGetAttribLocation + * @see javax.media.opengl.GL2ES2#glGetAttribLocation + * @see #getAttribLocation + * @see #glReplaceShader + */ + public int glGetAttribLocation(GL2ES2 gl, String name) { + if(!shaderProgram.linked()) throw new GLException("Program is not linked"); + int index = getAttribLocation(name); + if(0>index) { + index = gl.glGetAttribLocation(shaderProgram.program(), name); + if(0<=index) { + Integer idx = new Integer(index); + attribMap2Idx.put(name, idx); + } else if(verbose) { + Throwable tX = new Throwable("Info: glGetAttribLocation failed, no location for: "+name+", index: "+index); + tX.printStackTrace(); + } + } + return index; + } + + protected int getAttribLocation(String name) { + Integer idx = (Integer) attribMap2Idx.get(name); + return (null!=idx)?idx.intValue():-1; + } + + + // + // Enabled Vertex Arrays and its data + // + + /** + * Enable a vertex attribute array + * + * Even if the attribute is not found in the current shader, + * it is stored in this state. + * + * @returns false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public boolean glEnableVertexAttribArray(GL2ES2 gl, String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + enabledVertexAttribArraySet.add(name); + int index = glGetAttribLocation(gl, name); + if(0>index) { + if(verbose) { + Throwable tX = new Throwable("Info: glEnableVertexAttribArray failed, no index for: "+name); + tX.printStackTrace(); + } + return false; + } + if(DEBUG) { + System.err.println("Info: glEnableVertexAttribArray: "+name); + } + gl.glEnableVertexAttribArray(index); + return true; + } + + public boolean isVertexAttribArrayEnabled(String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + return enabledVertexAttribArraySet.contains(name); + } + + /** + * Disables a vertex attribute array + * + * Even if the attribute is not found in the current shader, + * it is removed from this state. + * + * @returns false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public boolean glDisableVertexAttribArray(GL2ES2 gl, String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + enabledVertexAttribArraySet.remove(name); + int index = glGetAttribLocation(gl, name); + if(0>index) { + if(verbose) { + Throwable tX = new Throwable("Info: glDisableVertexAttribArray failed, no index for: "+name); + tX.printStackTrace(); + } + return false; + } + if(DEBUG) { + System.err.println("Info: glDisableVertexAttribArray: "+name); + } + gl.glDisableVertexAttribArray(index); + return true; + } + + /** + * Set the vertex attribute data. + * Enable the attribute, if it is not enabled yet. + * + * Even if the attribute is not found in the current shader, + * it is stored in this state. + * + * @arg data the GLArrayData's name must match the attributes one, + * it's index will be set with the attribute's location, + * if found. + * + * @returns false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public boolean glVertexAttribPointer(GL2ES2 gl, GLArrayData data) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + if(!enabledVertexAttribArraySet.contains(data.getName())) { + if(!glEnableVertexAttribArray(gl, data.getName())) { + if(verbose) { + Throwable tX = new Throwable("Info: glVertexAttribPointer: couldn't enable: "+data); + tX.printStackTrace(); + } + } + } + int index = getAttribLocation(data.getName()); + if(0>index) { + if(verbose) { + Throwable tX = new Throwable("Info: glVertexAttribPointer failed, no index for: "+data); + tX.printStackTrace(); + } + } + data.setLocation(index); + vertexAttribMap2Data.put(data.getName(), data); + if(0<=index) { + // only pass the data, if the attribute exists in the current shader + if(DEBUG) { + System.err.println("Info: glVertexAttribPointer: "+data); + } + gl.glVertexAttribPointer(data); + return true; + } + return false; + } + + /** + * Get the vertex attribute data, previously set. + * + * @returns the GLArrayData object, null if not previously set. + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public GLArrayData getVertexAttribPointer(String name) { + return (GLArrayData) vertexAttribMap2Data.get(name); + } + + /** + * Releases all mapped vertex attribute data, + * disables all enabled attributes and loses all indices + * + * @throws GLException is the program is not in use but the shaderProgram is set + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public void glReleaseAllVertexAttributes(GL2ES2 gl) { + if(null!=shaderProgram) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + for(Iterator iter = vertexAttribMap2Data.keySet().iterator(); iter.hasNext(); ) { + if(!glDisableVertexAttribArray(gl, (String) iter.next())) { + throw new GLException("Internal Error: mapped vertex attribute couldn't be disabled"); + } + } + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + if(!glDisableVertexAttribArray(gl, (String) iter.next())) { + throw new GLException("Internal Error: prev enabled vertex attribute couldn't be disabled"); + } + } + } + vertexAttribMap2Data.clear(); + enabledVertexAttribArraySet.clear(); + attribMap2Idx.clear(); + } + + /** + * Disables all vertex attribute arrays. + * + * Their enabled stated will be removed from this state only + * if 'removeFromState' is true. + * + * This method purpose is more for debugging. + * + * @throws GLException is the program is not in use but the shaderProgram is set + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public void glDisableAllVertexAttributeArrays(GL2ES2 gl, boolean removeFromState) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + String name = (String) iter.next(); + if(removeFromState) { + enabledVertexAttribArraySet.remove(name); + } + int index = glGetAttribLocation(gl, name); + if(0<=index) { + gl.glDisableVertexAttribArray(index); + } + } + } + + /** + * Reset all previously mapped vertex attribute data, + * incl enabling them + * + * @throws GLException is the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttributePointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glReplaceShader + */ + public void glResetAllVertexAttributes(GL2ES2 gl) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + attribMap2Idx.clear(); + + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + glEnableVertexAttribArray(gl, (String) iter.next()); + } + + for(Iterator iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { + glVertexAttribPointer(gl, (GLArrayData) iter.next()); + } + } + + // + // Shader Uniform handling + // + + /** + * Gets the index of a shader uniform. + * This must be done when the program is in use ! + * + * @return -1 if there is no such attribute available, + * otherwise >= 0 + + * @throws GLException is the program is not linked + * + * @see #glGetUniformLocation + * @see javax.media.opengl.GL2ES2#glGetUniformLocation + * @see #getUniformLocation + * @see #glReplaceShader + */ + protected int glGetUniformLocation(GL2ES2 gl, String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + int index = getUniformLocation(name); + if(0>index) { + index = gl.glGetUniformLocation(shaderProgram.program(), name); + if(0<=index) { + Integer idx = new Integer(index); + uniformMap2Idx.put(name, idx); + } else if(verbose) { + Throwable tX = new Throwable("Info: glUniform failed, no location for: "+name+", index: "+index); + tX.printStackTrace(); + } + } + return index; + } + + protected int getUniformLocation(String name) { + Integer idx = (Integer) uniformMap2Idx.get(name); + return (null!=idx)?idx.intValue():-1; + } + + /** + * Set the uniform data. + * + * Even if the uniform is not found in the current shader, + * it is stored in this state. + * + * @arg data the GLUniforms's name must match the uniform one, + * it's index will be set with the uniforms's location, + * if found. + * + * + * @returns false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glGetUniformLocation + * @see javax.media.opengl.GL2ES2#glGetUniformLocation + * @see #getUniformLocation + * @see #glReplaceShader + */ + public boolean glUniform(GL2ES2 gl, GLUniformData data) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + int location = glGetUniformLocation(gl, data.getName()); + data.setLocation(location); + uniformMap2Data.put(data.getName(), data); + if(0<=location) { + // only pass the data, if the uniform exists in the current shader + if(DEBUG) { + System.err.println("Info: glUniform: "+data); + } + gl.glUniform(data); + } + return true; + } + + /** + * Get the uniform data, previously set. + * + * @returns the GLUniformData object, null if not previously set. + */ + public GLUniformData getUniform(String name) { + return (GLUniformData) uniformMap2Data.get(name); + } + + /** + * Releases all mapped uniform data + * and loses all indices + * + * @throws GLException is the program is not in use + */ + public void glReleaseAllUniforms(GL2ES2 gl) { + uniformMap2Data.clear(); + uniformMap2Idx.clear(); + } + + /** + * Reset all previously mapped uniform data + * + * @throws GLException is the program is not in use + */ + public void glResetAllUniforms(GL2ES2 gl) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + uniformMap2Idx.clear(); + for(Iterator iter = uniformMap2Data.values().iterator(); iter.hasNext(); ) { + glUniform(gl, (GLUniformData) iter.next()); + } + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("ShaderState["); + buf.append(shaderProgram.toString()); + buf.append(",EnabledStates: ["); + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + buf.append("\n "); + buf.append((String)iter.next()); + } + buf.append("], ["); + for(Iterator iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { + buf.append("\n "); + buf.append((GLArrayData) iter.next()); + } + buf.append("], ["); + for(Iterator iter=uniformMap2Data.values().iterator(); iter.hasNext(); ) { + buf.append("\n "); + buf.append((GLUniformData) iter.next()); + } + buf.append("]"); + return buf.toString(); + } + + protected static final boolean DEBUG = false; + protected boolean verbose = false; + protected ShaderProgram shaderProgram=null; + protected HashMap attribMap2Idx = new HashMap(); + protected HashSet enabledVertexAttribArraySet = new HashSet(); + protected HashMap vertexAttribMap2Data = new HashMap(); + protected HashMap uniformMap2Idx = new HashMap(); + protected HashMap uniformMap2Data = new HashMap(); + protected static ShaderState currentShaderState = null; + +} + |