diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp')
13 files changed, 554 insertions, 291 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java index fcccf592e..998129551 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java @@ -33,6 +33,7 @@ import javax.media.opengl.GL2ES2; import javax.media.opengl.GLException; import javax.media.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderState; import com.jogamp.opengl.util.PMVMatrix; @@ -263,21 +264,31 @@ public abstract class Renderer { return true; } - protected String getVertexShaderName(GL2ES2 gl) { - return "curverenderer01" + getShaderGLVersionSuffix(gl); + protected String getVertexShaderName() { + return "curverenderer" + getImplVersion(); } - protected String getFragmentShaderName(GL2ES2 gl) { - final String type = "01" ; // Region.isNonUniformWeight(renderModes) ? "02" : "01" ; - final String pass = Region.isVBAA(renderModes) ? "b" : "a" ; - return "curverenderer" + type + pass + getShaderGLVersionSuffix(gl); + protected String getFragmentShaderName() { + final String version = getImplVersion(); + final String pass = Region.isVBAA(renderModes) ? "-2pass" : "-1pass" ; + final String weight = Region.isNonUniformWeight(renderModes) ? "-weight" : "" ; + return "curverenderer" + version + pass + weight; } - - protected String getShaderGLVersionSuffix(GL2ES2 gl) { - if(gl.isGLES2()) { - return "-es2"; + + // FIXME: Really required to have sampler2D def. precision ? If not, we can drop getFragmentShaderPrecision(..) and use default ShaderCode .. + public static final String es2_precision_fp = "\nprecision mediump float;\nprecision mediump int;\nprecision mediump sampler2D;\n"; + + protected String getFragmentShaderPrecision(GL2ES2 gl) { + if( gl.isGLES2() ) { + return es2_precision_fp; } - return "-gl2"; - } + if( ShaderCode.requiresGL3DefaultPrecision(gl) ) { + return ShaderCode.gl3_default_precision_fp; + } + return null; + } + protected String getImplVersion() { + return "01"; + } }
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java index 33d487355..bbdfc0e9f 100644 --- a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java +++ b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java @@ -33,13 +33,23 @@ import java.net.URLConnection; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.ReflectionUtil; -import com.jogamp.common.util.SecurityUtil; import jogamp.graph.font.FontConstructor; import jogamp.graph.font.JavaFontLoader; import jogamp.graph.font.UbuntuFontLoader; +/** + * The optional property <i>jogamp.graph.font.ctor</i> + * allows user to specify the {@link FontConstructor} implementation. + * <p> + * Default {@link FontConstructor} is {@link jogamp.graph.font.typecast.TypecastFontConstructor}, + * i.e. using our internal <i>typecast</i> branch. + * </p> + */ public class FontFactory { + private static final String FontConstructorPropKey = "jogamp.graph.font.ctor"; + private static final String DefaultFontConstructor = "jogamp.graph.font.typecast.TypecastFontConstructor"; + /** Ubuntu is the default font family */ public static final int UBUNTU = 0; @@ -54,9 +64,9 @@ public class FontFactory { * "jogamp.graph.font.typecast.TypecastFontFactory" (default) * "jogamp.graph.font.ttf.TTFFontImpl" */ - String fontImplName = PropertyAccess.getProperty("FontImpl", true, SecurityUtil.getCommonAccessControlContext(FontFactory.class)); + String fontImplName = PropertyAccess.getProperty(FontConstructorPropKey, true); if(null == fontImplName) { - fontImplName = "jogamp.graph.font.typecast.TypecastFontConstructor"; + fontImplName = DefaultFontConstructor; } fontConstr = (FontConstructor) ReflectionUtil.createInstance(fontImplName, FontFactory.class.getClassLoader()); } diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java index 6f2ac3e35..7060bb7d1 100644 --- a/src/jogl/classes/com/jogamp/opengl/FBObject.java +++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java @@ -60,7 +60,6 @@ import com.jogamp.opengl.FBObject.Attachment.Type; */ public class FBObject { protected static final boolean DEBUG = Debug.debug("FBObject"); - private static final boolean forceMinimumFBOSupport = Debug.isPropertyDefined("jogl.fbo.force.min", true); private static final boolean FBOResizeQuirk = false; private static enum DetachAction { NONE, DISPOSE, RECREATE }; @@ -813,6 +812,7 @@ public class FBObject { maxColorAttachments = 1; if( fullFBOSupport || NV_fbo_color_attachments ) { try { + val[0] = 0; gl.glGetIntegerv(GL2ES2.GL_MAX_COLOR_ATTACHMENTS, val, 0); realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1 } catch (GLException gle) { gle.printStackTrace(); } @@ -823,15 +823,10 @@ public class FBObject { colorAttachmentCount = 0; maxSamples = gl.getMaxRenderbufferSamples(); - if(!forceMinimumFBOSupport) { - gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0); - maxTextureSize = val[0]; - gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0); - maxRenderbufferSize = val[0]; - } else { - maxTextureSize = 2048; - maxRenderbufferSize = 2048; - } + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0); + maxTextureSize = val[0]; + gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0); + maxRenderbufferSize = val[0]; checkPreGLError(gl); diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java index 78bd62e42..36893f5ec 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java +++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java @@ -27,6 +27,8 @@ */ package com.jogamp.opengl; +import java.util.List; + /** * GLRendererQuirks contains information of known bugs of various GL renderer. * This information allows us to workaround them. @@ -151,14 +153,36 @@ public class GLRendererQuirks { */ public static final int NeedCurrCtx4ARBCreateContext = 10; + /** + * No full FBO support, i.e. not compliant w/ + * <ul> + * <li>GL_ARB_framebuffer_object</li> + * <li>EXT_framebuffer_object</li> + * <li>EXT_framebuffer_multisample</li> + * <li>EXT_framebuffer_blit</li> + * <li>EXT_packed_depth_stencil</li> + * </ul>. + * Drivers known exposing such bug: + * <ul> + * <li>Mesa <i>7.12-devel</i> on Windows with VMware <i>SVGA3D</i> renderer: + * <ul> + * <li>GL_VERSION: <i>2.1 Mesa 7.12-devel (git-d6c318e)</i> </li> + * <li>GL_RENDERER: <i>Gallium 0.4 on SVGA3D; build: RELEASE;</i> </li> + * </ul></li> + * </ul> + * Quirk can also be enabled via property: <code>jogl.fbo.force.min</code>. + */ + public static final int NoFullFBOSupport = 11; + /** Number of quirks known. */ - public static final int COUNT = 11; + public static final int COUNT = 12; private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval", "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard", "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11Display", - "NeedCurrCtx4ARBPixFmtQueries", "NeedCurrCtx4ARBCreateContext" + "NeedCurrCtx4ARBPixFmtQueries", "NeedCurrCtx4ARBCreateContext", + "NoFullFBOSupport" }; private final int _bitmask; @@ -183,6 +207,20 @@ public class GLRendererQuirks { } /** + * @param quirks a list of valid quirks + * @throws IllegalArgumentException if one of the quirks is out of range + */ + public GLRendererQuirks(List<Integer> quirks) throws IllegalArgumentException { + int bitmask = 0; + for(int i=0; i<quirks.size(); i++) { + final int quirk = quirks.get(i); + validateQuirk(quirk); + bitmask |= 1 << quirk; + } + _bitmask = bitmask; + } + + /** * @param quirk the quirk to be tested * @return true if quirk exist, otherwise false * @throws IllegalArgumentException if quirk is out of range diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java index 9a51c32b3..f3f44f15a 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java @@ -113,6 +113,22 @@ public class FloatUtil { } /** + * @param a 4x4 matrix in column-major order (also result) + * @param b 4x4 matrix in column-major order + */ + public static final void multMatrixf(final float[] a, int a_off, final float[] b, int b_off) { + for (int i = 0; i < 4; i++) { + // one row in column-major order + final int a_off_i = a_off+i; + final float ai0=a[a_off_i+0*4], ai1=a[a_off_i+1*4], ai2=a[a_off_i+2*4], ai3=a[a_off_i+3*4]; // row-i of a + a[a_off_i+0*4] = ai0 * b[b_off+0+0*4] + ai1 * b[b_off+1+0*4] + ai2 * b[b_off+2+0*4] + ai3 * b[b_off+3+0*4] ; + a[a_off_i+1*4] = ai0 * b[b_off+0+1*4] + ai1 * b[b_off+1+1*4] + ai2 * b[b_off+2+1*4] + ai3 * b[b_off+3+1*4] ; + a[a_off_i+2*4] = ai0 * b[b_off+0+2*4] + ai1 * b[b_off+1+2*4] + ai2 * b[b_off+2+2*4] + ai3 * b[b_off+3+2*4] ; + a[a_off_i+3*4] = ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] ; + } + } + + /** * @param a 4x4 matrix in column-major order * @param b 4x4 matrix in column-major order * @param d result a*b in column-major order @@ -146,6 +162,23 @@ public class FloatUtil { d.put(dP+i+3*4 , ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] ); } } + + /** + * @param a 4x4 matrix in column-major order (also result) + * @param b 4x4 matrix in column-major order + */ + public static final void multMatrixf(final FloatBuffer a, final float[] b, int b_off) { + final int aP = a.position(); + for (int i = 0; i < 4; i++) { + // one row in column-major order + final int aP_i = aP+i; + final float ai0=a.get(aP_i+0*4), ai1=a.get(aP_i+1*4), ai2=a.get(aP_i+2*4), ai3=a.get(aP_i+3*4); // row-i of a + a.put(aP_i+0*4 , ai0 * b[b_off+0+0*4] + ai1 * b[b_off+1+0*4] + ai2 * b[b_off+2+0*4] + ai3 * b[b_off+3+0*4] ); + a.put(aP_i+1*4 , ai0 * b[b_off+0+1*4] + ai1 * b[b_off+1+1*4] + ai2 * b[b_off+2+1*4] + ai3 * b[b_off+3+1*4] ); + a.put(aP_i+2*4 , ai0 * b[b_off+0+2*4] + ai1 * b[b_off+1+2*4] + ai2 * b[b_off+2+2*4] + ai3 * b[b_off+3+2*4] ); + a.put(aP_i+3*4 , ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] ); + } + } /** * @param a 4x4 matrix in column-major order @@ -167,6 +200,24 @@ public class FloatUtil { } /** + * @param a 4x4 matrix in column-major order (also result) + * @param b 4x4 matrix in column-major order + */ + public static final void multMatrixf(final FloatBuffer a, final FloatBuffer b) { + final int aP = a.position(); + final int bP = b.position(); + for (int i = 0; i < 4; i++) { + // one row in column-major order + final int aP_i = aP+i; + final float ai0=a.get(aP_i+0*4), ai1=a.get(aP_i+1*4), ai2=a.get(aP_i+2*4), ai3=a.get(aP_i+3*4); // row-i of a + a.put(aP_i+0*4 , ai0 * b.get(bP+0+0*4) + ai1 * b.get(bP+1+0*4) + ai2 * b.get(bP+2+0*4) + ai3 * b.get(bP+3+0*4) ); + a.put(aP_i+1*4 , ai0 * b.get(bP+0+1*4) + ai1 * b.get(bP+1+1*4) + ai2 * b.get(bP+2+1*4) + ai3 * b.get(bP+3+1*4) ); + a.put(aP_i+2*4 , ai0 * b.get(bP+0+2*4) + ai1 * b.get(bP+1+2*4) + ai2 * b.get(bP+2+2*4) + ai3 * b.get(bP+3+2*4) ); + a.put(aP_i+3*4 , ai0 * b.get(bP+0+3*4) + ai1 * b.get(bP+1+3*4) + ai2 * b.get(bP+2+3*4) + ai3 * b.get(bP+3+3*4) ); + } + } + + /** * @param a 4x4 matrix in column-major order * @param b 4x4 matrix in column-major order * @param d result a*b in column-major order diff --git a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java index 0cc5f5ae7..d5ffe2da4 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java +++ b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java @@ -27,191 +27,204 @@ */ package com.jogamp.opengl.math; - - public class Quaternion { - protected float x,y,z,w; - - public Quaternion(){ + protected float x, y, z, w; + public Quaternion() { + setIdentity(); } + public Quaternion(Quaternion q) { + x = q.x; + y = q.y; + z = q.z; + w = q.w; + } + public Quaternion(float x, float y, float z, float w) { this.x = x; this.y = y; this.z = z; this.w = w; } - - /** Constructor to create a rotation based quaternion from two vectors + + /** + * Constructor to create a rotation based quaternion from two vectors + * * @param vector1 * @param vector2 */ - public Quaternion(float[] vector1, float[] vector2) - { - float theta = (float)FloatUtil.acos(dot(vector1, vector2)); - float[] cross = cross(vector1,vector2); - cross = normalizeVec(cross); - - this.x = (float)FloatUtil.sin(theta/2)*cross[0]; - this.y = (float)FloatUtil.sin(theta/2)*cross[1]; - this.z = (float)FloatUtil.sin(theta/2)*cross[2]; - this.w = (float)FloatUtil.cos(theta/2); - this.normalize(); + public Quaternion(float[] vector1, float[] vector2) { + final float theta = FloatUtil.acos(VectorUtil.dot(vector1, vector2)); + final float[] cross = VectorUtil.cross(vector1, vector2); + fromAxis(cross, theta); } - /** Transform the rotational quaternion to axis based rotation angles - * @return new float[4] with ,theta,Rx,Ry,Rz + /*** + * Constructor to create a rotation based quaternion from axis vector and angle + * @param vector axis vector + * @param angle rotation angle (rads) + * @see #fromAxis(float[], float) */ - public float[] toAxis() - { - float[] vec = new float[4]; - float scale = (float)FloatUtil.sqrt(x * x + y * y + z * z); - vec[0] =(float) FloatUtil.acos(w) * 2.0f; - vec[1] = x / scale; - vec[2] = y / scale; - vec[3] = z / scale; - return vec; + public Quaternion(float[] vector, float angle) { + fromAxis(vector, angle); } - /** Normalize a vector - * @param vector input vector - * @return normalized vector + /*** + * Initialize this quaternion with given axis vector and rotation angle + * + * @param vector axis vector + * @param angle rotation angle (rads) */ - private float[] normalizeVec(float[] vector) - { - float[] newVector = new float[3]; - - float d = FloatUtil.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]); - if(d> 0.0f) - { - newVector[0] = vector[0]/d; - newVector[1] = vector[1]/d; - newVector[2] = vector[2]/d; - } - return newVector; + public void fromAxis(float[] vector, float angle) { + final float halfangle = angle * 0.5f; + final float sin = FloatUtil.sin(halfangle); + final float[] nv = VectorUtil.normalize(vector); + x = (nv[0] * sin); + y = (nv[1] * sin); + z = (nv[2] * sin); + w = FloatUtil.cos(halfangle); } - /** compute the dot product of two points - * @param vec1 vector 1 - * @param vec2 vector 2 - * @return the dot product as float + + /** + * Transform the rotational quaternion to axis based rotation angles + * + * @return new float[4] with ,theta,Rx,Ry,Rz */ - private float dot(float[] vec1, float[] vec2) - { - return (vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]); + public float[] toAxis() { + final float[] vec = new float[4]; + final float scale = FloatUtil.sqrt(x * x + y * y + z * z); + vec[0] = FloatUtil.acos(w) * 2.0f; + vec[1] = x / scale; + vec[2] = y / scale; + vec[3] = z / scale; + return vec; } - /** cross product vec1 x vec2 - * @param vec1 vector 1 - * @param vec2 vecttor 2 - * @return the resulting vector - */ - private float[] cross(float[] vec1, float[] vec2) - { - float[] out = new float[3]; - - out[0] = vec2[2]*vec1[1] - vec2[1]*vec1[2]; - out[1] = vec2[0]*vec1[2] - vec2[2]*vec1[0]; - out[2] = vec2[1]*vec1[0] - vec2[0]*vec1[1]; - return out; - } public float getW() { return w; } + public void setW(float w) { this.w = w; } + public float getX() { return x; } + public void setX(float x) { this.x = x; } + public float getY() { return y; } + public void setY(float y) { this.y = y; } + public float getZ() { return z; } + public void setZ(float z) { this.z = z; } - /** Add a quaternion + /** + * Add a quaternion + * * @param q quaternion */ - public void add(Quaternion q) - { - x+=q.x; - y+=q.y; - z+=q.z; + public void add(Quaternion q) { + x += q.x; + y += q.y; + z += q.z; } - - /** Subtract a quaternion + + /** + * Subtract a quaternion + * * @param q quaternion */ - public void subtract(Quaternion q) - { - x-=q.x; - y-=q.y; - z-=q.z; + public void subtract(Quaternion q) { + x -= q.x; + y -= q.y; + z -= q.z; } - - /** Divide a quaternion by a constant + + /** + * Divide a quaternion by a constant + * * @param n a float to divide by */ - public void divide(float n) - { - x/=n; - y/=n; - z/=n; + public void divide(float n) { + x /= n; + y /= n; + z /= n; } - - /** Multiply this quaternion by - * the param quaternion + + /** + * Multiply this quaternion by the param quaternion + * * @param q a quaternion to multiply with */ - public void mult(Quaternion q) - { - float w1 = w*q.w - x*q.x - y*q.y - z*q.z; + public void mult(Quaternion q) { + final float w1 = w * q.w - x * q.x - y * q.y - z * q.z; - float x1 = w*q.x + x*q.w + y*q.z - z*q.y; - float y1 = w*q.y - x*q.z + y*q.w + z*q.x; - float z1 = w*q.z + x*q.y - y*q.x + z*q.w; + final float x1 = w * q.x + x * q.w + y * q.z - z * q.y; + final float y1 = w * q.y - x * q.z + y * q.w + z * q.x; + final float z1 = w * q.z + x * q.y - y * q.x + z * q.w; w = w1; x = x1; y = y1; - z = z1; + z = z1; } - - /** Multiply a quaternion by a constant + + /** + * Multiply a quaternion by a constant + * * @param n a float constant */ - public void mult(float n) - { - x*=n; - y*=n; - z*=n; + public void mult(float n) { + x *= n; + y *= n; + z *= n; } - /** Normalize a quaternion required if - * to be used as a rotational quaternion + /*** + * Rotate given vector by this quaternion + * + * @param vector input vector + * @return rotated vector */ - public void normalize() - { - float norme = (float)FloatUtil.sqrt(w*w + x*x + y*y + z*z); - if (norme == 0.0f) - { - w = 1.0f; - x = y = z = 0.0f; - } - else - { - float recip = 1.0f/norme; + public float[] mult(float[] vector) { + // TODO : optimize + final float[] res = new float[3]; + final Quaternion a = new Quaternion(vector[0], vector[1], vector[2], 0.0f); + final Quaternion b = new Quaternion(this); + final Quaternion c = new Quaternion(this); + b.inverse(); + a.mult(b); + c.mult(a); + res[0] = c.x; + res[1] = c.y; + res[2] = c.z; + return res; + } + + /** + * Normalize a quaternion required if to be used as a rotational quaternion + */ + public void normalize() { + final float norme = (float) FloatUtil.sqrt(w * w + x * x + y * y + z * z); + if (norme == 0.0f) { + setIdentity(); + } else { + final float recip = 1.0f / norme; w *= recip; x *= recip; @@ -219,42 +232,42 @@ public class Quaternion { z *= recip; } } - - /** Invert the quaternion If rotational, - * will produce a the inverse rotation + + /** + * Invert the quaternion If rotational, will produce a the inverse rotation */ - public void inverse() - { - float norm = w*w + x*x + y*y + z*z; + public void inverse() { + final float norm = w * w + x * x + y * y + z * z; - float recip = 1.0f/norm; + final float recip = 1.0f / norm; w *= recip; - x = -1*x*recip; - y = -1*y*recip; - z = -1*z*recip; + x = -1 * x * recip; + y = -1 * y * recip; + z = -1 * z * recip; } - - /** Transform this quaternion to a - * 4x4 column matrix representing the rotation - * @return new float[16] column matrix 4x4 + + /** + * Transform this quaternion to a 4x4 column matrix representing the + * rotation + * + * @return new float[16] column matrix 4x4 */ - public float[] toMatrix() - { - float[] matrix = new float[16]; - matrix[0] = 1.0f - 2*y*y - 2*z*z; - matrix[1] = 2*x*y + 2*w*z; - matrix[2] = 2*x*z - 2*w*y; + public float[] toMatrix() { + final float[] matrix = new float[16]; + matrix[0] = 1.0f - 2 * y * y - 2 * z * z; + matrix[1] = 2 * x * y + 2 * w * z; + matrix[2] = 2 * x * z - 2 * w * y; matrix[3] = 0; - matrix[4] = 2*x*y - 2*w*z; - matrix[5] = 1.0f - 2*x*x - 2*z*z; - matrix[6] = 2*y*z + 2*w*x; + matrix[4] = 2 * x * y - 2 * w * z; + matrix[5] = 1.0f - 2 * x * x - 2 * z * z; + matrix[6] = 2 * y * z + 2 * w * x; matrix[7] = 0; - matrix[8] = 2*x*z + 2*w*y; - matrix[9] = 2*y*z - 2*w*x; - matrix[10] = 1.0f - 2*x*x - 2*y*y; + matrix[8] = 2 * x * z + 2 * w * y; + matrix[9] = 2 * y * z - 2 * w * x; + matrix[10] = 1.0f - 2 * x * x - 2 * y * y; matrix[11] = 0; matrix[12] = 0; @@ -263,15 +276,18 @@ public class Quaternion { matrix[15] = 1; return matrix; } - - /** Set this quaternion from a Sphereical interpolation - * of two param quaternion, used mostly for rotational animation. - * <p> - * Note: Method does not normalize this quaternion! - * </p> - * <p> - * See http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - * </p> + + /** + * Set this quaternion from a Sphereical interpolation of two param + * quaternion, used mostly for rotational animation. + * <p> + * Note: Method does not normalize this quaternion! + * </p> + * <p> + * See http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/ + * quaternions/slerp/ + * </p> + * * @param a initial quaternion * @param b target quaternion * @param t float between 0 and 1 representing interp. @@ -279,7 +295,7 @@ public class Quaternion { public void slerp(Quaternion a, Quaternion b, float t) { final float cosom = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; final float t1 = 1.0f - t; - + // if the two quaternions are close, just use linear interpolation if (cosom >= 0.95f) { x = a.x * t1 + b.x * t; @@ -288,8 +304,9 @@ public class Quaternion { w = a.w * t1 + b.w * t; return; } - - // the quaternions are nearly opposite, we can pick any axis normal to a,b + + // the quaternions are nearly opposite, we can pick any axis normal to + // a,b // to do the rotation if (cosom <= -0.99f) { x = 0.5f * (a.x + b.x); @@ -298,94 +315,112 @@ public class Quaternion { w = 0.5f * (a.w + b.w); return; } - + // cosom is now withion range of acos, do a SLERP final float sinom = FloatUtil.sqrt(1.0f - cosom * cosom); final float omega = FloatUtil.acos(cosom); - + final float scla = FloatUtil.sin(t1 * omega) / sinom; - final float sclb = FloatUtil.sin( t * omega) / sinom; - + final float sclb = FloatUtil.sin(t * omega) / sinom; + x = a.x * scla + b.x * sclb; y = a.y * scla + b.y * sclb; z = a.z * scla + b.z * sclb; w = a.w * scla + b.w * sclb; } - - /** Check if this quaternion is empty, ie (0,0,0,1) + + /** + * Check if this quaternion is empty, ie (0,0,0,1) + * * @return true if empty, false otherwise + * @deprecated use {@link #isIdentity()} instead */ - public boolean isEmpty() - { - if (w==1 && x==0 && y==0 && z==0) + @Deprecated + public boolean isEmpty() { + if (w == 1 && x == 0 && y == 0 && z == 0) return true; return false; } - - /** Check if this quaternion represents an identity - * matrix, for rotation. + + /** + * Check if this quaternion represents an identity matrix, for rotation. + * * @return true if it is an identity rep., false otherwise */ - public boolean isIdentity() - { - if (w==0 && x==0 && y==0 && z==0) - return true; - return false; + public boolean isIdentity() { + return w == 1 && x == 0 && y == 0 && z == 0; } - /** compute the quaternion from a 3x3 column matrix - * @param m 3x3 column matrix + /*** + * Set this quaternion to identity (x=0,y=0,z=0,w=1) + */ + public void setIdentity() { + x = y = z = 0; + w = 1; + } + + /** + * compute the quaternion from a 3x3 column matrix + * + * @param m 3x3 column matrix */ public void setFromMatrix(float[] m) { - float T= m[0] + m[4] + m[8] + 1; - if (T>0){ - float S = 0.5f / (float)FloatUtil.sqrt(T); + final float T = m[0] + m[4] + m[8] + 1; + if (T > 0) { + final float S = 0.5f / (float) FloatUtil.sqrt(T); w = 0.25f / S; - x = ( m[5] - m[7]) * S; - y = ( m[6] - m[2]) * S; - z = ( m[1] - m[3] ) * S; - } - else{ - if ((m[0] > m[4])&(m[0] > m[8])) { - float S = FloatUtil.sqrt( 1.0f + m[0] - m[4] - m[8] ) * 2f; // S=4*qx + x = (m[5] - m[7]) * S; + y = (m[6] - m[2]) * S; + z = (m[1] - m[3]) * S; + } else { + if ((m[0] > m[4]) & (m[0] > m[8])) { + final float S = FloatUtil.sqrt(1.0f + m[0] - m[4] - m[8]) * 2f; // S=4*qx w = (m[7] - m[5]) / S; x = 0.25f * S; - y = (m[3] + m[1]) / S; - z = (m[6] + m[2]) / S; - } - else if (m[4] > m[8]) { - float S = FloatUtil.sqrt( 1.0f + m[4] - m[0] - m[8] ) * 2f; // S=4*qy + y = (m[3] + m[1]) / S; + z = (m[6] + m[2]) / S; + } else if (m[4] > m[8]) { + final float S = FloatUtil.sqrt(1.0f + m[4] - m[0] - m[8]) * 2f; // S=4*qy w = (m[6] - m[2]) / S; - x = (m[3] + m[1]) / S; + x = (m[3] + m[1]) / S; y = 0.25f * S; - z = (m[7] + m[5]) / S; - } - else { - float S = FloatUtil.sqrt( 1.0f + m[8] - m[0] - m[4] ) * 2f; // S=4*qz + z = (m[7] + m[5]) / S; + } else { + final float S = FloatUtil.sqrt(1.0f + m[8] - m[0] - m[4]) * 2f; // S=4*qz w = (m[3] - m[1]) / S; - x = (m[6] + m[2]) / S; - y = (m[7] + m[5]) / S; + x = (m[6] + m[2]) / S; + y = (m[7] + m[5]) / S; z = 0.25f * S; - } + } } } - - /** Check if the the 3x3 matrix (param) is in fact - * an affine rotational matrix + + /** + * Check if the the 3x3 matrix (param) is in fact an affine rotational + * matrix + * * @param m 3x3 column matrix * @return true if representing a rotational matrix, false otherwise */ public boolean isRotationMatrix(float[] m) { - double epsilon = 0.01; // margin to allow for rounding errors - if (FloatUtil.abs(m[0]*m[3] + m[3]*m[4] + m[6]*m[7]) > epsilon) return false; - if (FloatUtil.abs(m[0]*m[2] + m[3]*m[5] + m[6]*m[8]) > epsilon) return false; - if (FloatUtil.abs(m[1]*m[2] + m[4]*m[5] + m[7]*m[8]) > epsilon) return false; - if (FloatUtil.abs(m[0]*m[0] + m[3]*m[3] + m[6]*m[6] - 1) > epsilon) return false; - if (FloatUtil.abs(m[1]*m[1] + m[4]*m[4] + m[7]*m[7] - 1) > epsilon) return false; - if (FloatUtil.abs(m[2]*m[2] + m[5]*m[5] + m[8]*m[8] - 1) > epsilon) return false; - return (FloatUtil.abs(determinant(m)-1) < epsilon); + final double epsilon = 0.01; // margin to allow for rounding errors + if (FloatUtil.abs(m[0] * m[3] + m[3] * m[4] + m[6] * m[7]) > epsilon) + return false; + if (FloatUtil.abs(m[0] * m[2] + m[3] * m[5] + m[6] * m[8]) > epsilon) + return false; + if (FloatUtil.abs(m[1] * m[2] + m[4] * m[5] + m[7] * m[8]) > epsilon) + return false; + if (FloatUtil.abs(m[0] * m[0] + m[3] * m[3] + m[6] * m[6] - 1) > epsilon) + return false; + if (FloatUtil.abs(m[1] * m[1] + m[4] * m[4] + m[7] * m[7] - 1) > epsilon) + return false; + if (FloatUtil.abs(m[2] * m[2] + m[5] * m[5] + m[8] * m[8] - 1) > epsilon) + return false; + return (FloatUtil.abs(determinant(m) - 1) < epsilon); } + private float determinant(float[] m) { - return m[0]*m[4]*m[8] + m[3]*m[7]*m[2] + m[6]*m[1]*m[5] - m[0]*m[7]*m[5] - m[3]*m[1]*m[8] - m[6]*m[4]*m[2]; + return m[0] * m[4] * m[8] + m[3] * m[7] * m[2] + m[6] * m[1] * m[5] + - m[0] * m[7] * m[5] - m[3] * m[1] * m[8] - m[6] * m[4] * m[2]; } } diff --git a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java index 5a75d016a..0033afeaa 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java @@ -292,21 +292,21 @@ public class VectorUtil { */ public static boolean vertexInTriangle(float[] a, float[] b, float[] c, float[] p){ // Compute vectors - float[] ac = computeVector(a, c); //v0 - float[] ab = computeVector(a, b); //v1 - float[] ap = computeVector(a, p); //v2 + final float[] ac = computeVector(a, c); //v0 + final float[] ab = computeVector(a, b); //v1 + final float[] ap = computeVector(a, p); //v2 // Compute dot products - float dot00 = dot(ac, ac); - float dot01 = dot(ac, ab); - float dot02 = dot(ac, ap); - float dot11 = dot(ab, ab); - float dot12 = dot(ab, ap); + final float dot00 = dot(ac, ac); + final float dot01 = dot(ac, ab); + final float dot02 = dot(ac, ap); + final float dot11 = dot(ab, ab); + final float dot12 = dot(ab, ap); // Compute barycentric coordinates - float invDenom = 1 / (dot00 * dot11 - dot01 * dot01); - float u = (dot11 * dot02 - dot01 * dot12) * invDenom; - float v = (dot00 * dot12 - dot01 * dot02) * invDenom; + final float invDenom = 1 / (dot00 * dot11 - dot01 * dot01); + final float u = (dot11 * dot02 - dot01 * dot12) * invDenom; + final float v = (dot00 * dot12 - dot01 * dot02) * invDenom; // Check if point is in triangle return (u >= 0) && (v >= 0) && (u + v < 1); @@ -337,12 +337,12 @@ public class VectorUtil { * @return positive area if ccw else negative area value */ public static float area(ArrayList<? extends Vert2fImmutable> vertices) { - int n = vertices.size(); + final int n = vertices.size(); float area = 0.0f; for (int p = n - 1, q = 0; q < n; p = q++) { - float[] pCoord = vertices.get(p).getCoord(); - float[] qCoord = vertices.get(q).getCoord(); + final float[] pCoord = vertices.get(p).getCoord(); + final float[] qCoord = vertices.get(q).getCoord(); area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1]; } return area; @@ -366,18 +366,18 @@ public class VectorUtil { * returns null */ public static float[] seg2SegIntersection(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d) { - float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX()); + final float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX()); if (determinant == 0) return null; - float alpha = (a.getX()*b.getY()-a.getY()*b.getX()); - float beta = (c.getX()*d.getY()-c.getY()*d.getY()); - float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant; - float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant; + final float alpha = (a.getX()*b.getY()-a.getY()*b.getX()); + final float beta = (c.getX()*d.getY()-c.getY()*d.getY()); + final float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant; + final float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant; - float gamma = (xi - a.getX())/(b.getX() - a.getX()); - float gamma1 = (xi - c.getX())/(d.getX() - c.getX()); + final float gamma = (xi - a.getX())/(b.getX() - a.getX()); + final float gamma1 = (xi - c.getX())/(d.getX() - c.getX()); if(gamma <= 0 || gamma >= 1) return null; if(gamma1 <= 0 || gamma1 >= 1) return null; @@ -393,15 +393,15 @@ public class VectorUtil { * returns null */ public static float[] line2lineIntersection(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d) { - float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX()); + final float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX()); if (determinant == 0) return null; - float alpha = (a.getX()*b.getY()-a.getY()*b.getX()); - float beta = (c.getX()*d.getY()-c.getY()*d.getY()); - float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant; - float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant; + final float alpha = (a.getX()*b.getY()-a.getY()*b.getX()); + final float beta = (c.getX()*d.getY()-c.getY()*d.getY()); + final float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant; + final float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant; return new float[]{xi,yi,0}; } diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java index f3fa5012f..f8b17501e 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java @@ -246,7 +246,9 @@ public class GLArrayDataWrapper implements GLArrayData { case GL.GL_SHORT: case GL.GL_UNSIGNED_SHORT: return ShortBuffer.class; + case GL.GL_UNSIGNED_INT: case GL2ES1.GL_FIXED: + case GL2ES2.GL_INT: return IntBuffer.class; case GL.GL_FLOAT: return FloatBuffer.class; diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java index 6b9d3bf2c..b0fc7f332 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java @@ -212,7 +212,7 @@ public class GLPixelBuffer { this.bufferElemSize = Buffers.sizeOfBufferElem(buffer); } - /** Is not {@link #dispose()} and has {@link #byteSize} > 0. */ + /** Is not {@link #dispose() disposed} and has {@link #byteSize} > 0. */ public boolean isValid() { return !disposed && 0 < byteSize; } @@ -240,8 +240,8 @@ public class GLPixelBuffer { } /** - * Returns true, if implementation requires a new buffer based on the new size - * due to pixel alignment or byte size or if {@link #isValid() invalid}, otherwise false. + * Returns true, if {@link #isValid() invalid} or implementation requires a new buffer based on the new size + * due to pixel alignment or byte size, otherwise false. * <p> * It is assumed that <code>pixelAttributes</code>, <code>depth</code> and <code>pack</code> stays the same! * </p> @@ -257,11 +257,12 @@ public class GLPixelBuffer { * @see GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) */ public boolean requiresNewBuffer(GL gl, int newWidth, int newHeight, int minByteSize) { - return !isValid() || this.byteSize < minByteSize; + return !isValid() || byteSize < minByteSize; } - /** Dispose resources. */ + /** Dispose resources. See {@link #isValid()}. */ public void dispose() { + disposed = true; buffer.clear(); } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java index bfc03d019..58151856f 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java +++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java @@ -488,7 +488,7 @@ public class PMVMatrix implements GLMatrixFunc { if(matrixGetName==GL_MATRIX_MODE) { params.put((float)matrixMode); } else { - FloatBuffer matrix = glGetMatrixf(matrixGetName); + final FloatBuffer matrix = glGetMatrixf(matrixGetName); params.put(matrix); // matrix -> params matrix.reset(); } @@ -500,7 +500,7 @@ public class PMVMatrix implements GLMatrixFunc { if(matrixGetName==GL_MATRIX_MODE) { params[params_offset]=(float)matrixMode; } else { - FloatBuffer matrix = glGetMatrixf(matrixGetName); + final FloatBuffer matrix = glGetMatrixf(matrixGetName); matrix.get(params, params_offset, 16); // matrix -> params matrix.reset(); } @@ -619,15 +619,15 @@ public class PMVMatrix implements GLMatrixFunc { @Override public final void glMultMatrixf(final FloatBuffer m) { if(matrixMode==GL_MODELVIEW) { - FloatUtil.multMatrixf(matrixMv, m, matrixMv); + FloatUtil.multMatrixf(matrixMv, m); dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - FloatUtil.multMatrixf(matrixP, m, matrixP); + FloatUtil.multMatrixf(matrixP, m); dirtyBits |= DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - FloatUtil.multMatrixf(matrixTex, m, matrixTex); + FloatUtil.multMatrixf(matrixTex, m); modifiedBits |= MODIFIED_TEXTURE; } } @@ -635,15 +635,15 @@ public class PMVMatrix implements GLMatrixFunc { @Override public final void glMultMatrixf(float[] m, int m_offset) { if(matrixMode==GL_MODELVIEW) { - FloatUtil.multMatrixf(matrixMv, m, m_offset, matrixMv); + FloatUtil.multMatrixf(matrixMv, m, m_offset); dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - FloatUtil.multMatrixf(matrixP, m, m_offset, matrixP); + FloatUtil.multMatrixf(matrixP, m, m_offset); dirtyBits |= DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - FloatUtil.multMatrixf(matrixTex, m, m_offset, matrixTex); + FloatUtil.multMatrixf(matrixTex, m, m_offset); modifiedBits |= MODIFIED_TEXTURE; } } @@ -813,8 +813,8 @@ public class PMVMatrix implements GLMatrixFunc { float[] win_pos, int win_pos_offset ) { if(usesBackingArray) { return projectFloat.gluProject(objx, objy, objz, - matrixMv.array(), 0, - matrixP.array(), 0, + matrixMv.array(), matrixMv.position(), + matrixP.array(), matrixP.position(), viewport, viewport_offset, win_pos, win_pos_offset); } else { @@ -843,8 +843,8 @@ public class PMVMatrix implements GLMatrixFunc { float[] obj_pos, int obj_pos_offset) { if(usesBackingArray) { return projectFloat.gluUnProject(winx, winy, winz, - matrixMv.array(), 0, - matrixP.array(), 0, + matrixMv.array(), matrixMv.position(), + matrixP.array(), matrixP.position(), viewport, viewport_offset, obj_pos, obj_pos_offset); } else { diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java index 1e552c17f..edc3d2677 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java @@ -54,6 +54,7 @@ import jogamp.opengl.Debug; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.VersionNumber; /** * Convenient shader code class to use and instantiate vertex or fragment programs. @@ -683,7 +684,7 @@ public class ShaderCode { * * @param shaderIdx the shader index to be used. * @param position in shader source segments of shader <code>shaderIdx</code> - * @param data the text to be inserted. Shall end with an EOL '\n' character. + * @param data the text to be inserted. Shall end with an EOL '\n' character * @return index after the inserted <code>data</code> * * @throws IllegalStateException if the shader source's CharSequence is immutable, i.e. not of type <code>StringBuilder</code> @@ -716,6 +717,7 @@ public class ShaderCode { return -1; } + @SuppressWarnings("resource") private static int readShaderSource(Class<?> context, URLConnection conn, StringBuilder result, int lineno) throws IOException { if(DEBUG_CODE) { if(0 == lineno) { @@ -823,11 +825,94 @@ public class ShaderCode { } // Shall we use: #ifdef GL_FRAGMENT_PRECISION_HIGH .. #endif for using highp in fragment shader if avail ? - /** {@value #es2_default_precision_vp} */ + /** Default precision of {@link GL#isGLES2() ES2} for {@link GL2ES2#GL_VERTEX_SHADER vertex-shader}: {@value #es2_default_precision_vp} */ public static final String es2_default_precision_vp = "\nprecision highp float;\nprecision highp int;\n"; - /** {@value #es2_default_precision_fp} */ + /** Default precision of {@link GL#isGLES2() ES2} for {@link GL2ES2#GL_FRAGMENT_SHADER fragment-shader}: {@value #es2_default_precision_fp} */ public static final String es2_default_precision_fp = "\nprecision mediump float;\nprecision mediump int;\n/*precision lowp sampler2D;*/\n"; + /** Default precision of GLSL ≥ 1.30 as required until < 1.50 for {@link GL2ES2#GL_VERTEX_SHADER vertex-shader} or {@link GL3#GL_GEOMETRY_SHADER geometry-shader}: {@value #gl3_default_precision_vp_gp}. See GLSL Spec 1.30-1.50 Section 4.5.3. */ + public static final String gl3_default_precision_vp_gp = "\nprecision highp float;\nprecision highp int;\n"; + /** Default precision of GLSL ≥ 1.30 as required until < 1.50 for {@link GL2ES2#GL_FRAGMENT_SHADER fragment-shader}: {@value #gl3_default_precision_fp}. See GLSL Spec 1.30-1.50 Section 4.5.3. */ + public static final String gl3_default_precision_fp = "\nprecision highp float;\nprecision mediump int;\n/*precision mediump sampler2D;*/\n"; + + /** Prefer <code>enable</code> over <code>require</code>, since it won't force a failure. */ + public static final String extOESDerivativesEnable = "#extension GL_OES_standard_derivatives : enable\n"; + + /** + * Add GLSL version at the head of this shader source code. + * <p> + * Note: The shader source to be edit must be created using a mutable StringBuilder. + * </p> + * @param gl a GL context, which must have been made current once + * @return the index after the inserted data, maybe 0 if nothing has be inserted. + */ + public final int addGLSLVersion(GL2ES2 gl) { + return insertShaderSource(0, 0, gl.getContext().getGLSLVersionString()); + } + + /** + * Adds default precision to source code at given position if required, i.e. + * {@link #es2_default_precision_vp}, {@link #es2_default_precision_fp}, + * {@link #gl3_default_precision_vp_gp}, {@link #gl3_default_precision_fp} or none, + * depending on the {@link GLContext#getGLSLVersionNumber() GLSL version} being used. + * <p> + * Note: The shader source to be edit must be created using a mutable StringBuilder. + * </p> + * @param gl a GL context, which must have been made current once + * @param pos position within this mutable shader source. + * @return the index after the inserted data, maybe 0 if nothing has be inserted. + */ + public final int addDefaultShaderPrecision(GL2ES2 gl, int pos) { + final String defaultPrecision; + if( gl.isGLES2() ) { + switch ( shaderType ) { + case GL2ES2.GL_VERTEX_SHADER: + defaultPrecision = es2_default_precision_vp; break; + case GL2ES2.GL_FRAGMENT_SHADER: + defaultPrecision = es2_default_precision_vp; break; + default: + defaultPrecision = null; + break; + } + } else if( requiresGL3DefaultPrecision(gl) ) { + // GLSL [ 1.30 .. 1.50 [ needs at least fragement float default precision! + switch ( shaderType ) { + case GL2ES2.GL_VERTEX_SHADER: + case GL3.GL_GEOMETRY_SHADER: + defaultPrecision = gl3_default_precision_vp_gp; break; + case GL2ES2.GL_FRAGMENT_SHADER: + defaultPrecision = gl3_default_precision_fp; break; + default: + defaultPrecision = null; + break; + } + } else { + defaultPrecision = null; + } + if( null != defaultPrecision ) { + pos = insertShaderSource(0, pos, defaultPrecision); + } + return pos; + } + + /** Returns true, if GLSL version requires default precision, i.e. ES2 or GLSL [1.30 .. 1.50[. */ + public static final boolean requiresDefaultPrecision(GL2ES2 gl) { + if( gl.isGLES2() ) { + return true; + } + return requiresGL3DefaultPrecision(gl); + } + + /** Returns true, if GL3 GLSL version requires default precision, i.e. GLSL [1.30 .. 1.50[. */ + public static final boolean requiresGL3DefaultPrecision(GL2ES2 gl) { + if( gl.isGL3() ) { + final VersionNumber glslVersion = gl.getContext().getGLSLVersionNumber(); + return glslVersion.compareTo(GLContext.Version130) >= 0 && glslVersion.compareTo(GLContext.Version150) < 0 ; + } else { + return false; + } + } + /** * Default customization of this shader source code. * <p> @@ -835,18 +920,51 @@ public class ShaderCode { * </p> * @param gl a GL context, which must have been made current once * @param preludeVersion if true {@link GLContext#getGLSLVersionString()} is preluded, otherwise not. - * @param es2DefaultPrecision optional default precision source code line(s) preluded if not null and if {@link GL#isGLES()}. + * @param addDefaultPrecision if <code>true</code> default precision source code line(s) are added, i.e. + * {@link #es2_default_precision_vp}, {@link #es2_default_precision_fp}, + * {@link #gl3_default_precision_vp_gp}, {@link #gl3_default_precision_fp} or none, + * depending on the {@link GLContext#getGLSLVersionNumber() GLSL version} being used. + * @return the index after the inserted data, maybe 0 if nothing has be inserted. + * @see #addGLSLVersion(GL2ES2) + * @see #addDefaultShaderPrecision(GL2ES2, int) + */ + public final int defaultShaderCustomization(GL2ES2 gl, boolean preludeVersion, boolean addDefaultPrecision) { + int pos; + if( preludeVersion ) { + pos = addGLSLVersion(gl); + } else { + pos = 0; + } + if( addDefaultPrecision ) { + pos = addDefaultShaderPrecision(gl, pos); + } + return pos; + } + + /** + * Default customization of this shader source code. + * <p> + * Note: The shader source to be edit must be created using a mutable StringBuilder. + * </p> + * @param gl a GL context, which must have been made current once + * @param preludeVersion if true {@link GLContext#getGLSLVersionString()} is preluded, otherwise not. + * @param esDefaultPrecision optional default precision source code line(s) preluded if not null and if {@link GL#isGLES()}. * You may use {@link #es2_default_precision_fp} for fragment shader and {@link #es2_default_precision_vp} for vertex shader. * @return the index after the inserted data, maybe 0 if nothing has be inserted. + * @see #addGLSLVersion(GL2ES2) + * @see #addDefaultShaderPrecision(GL2ES2, int) */ - public final int defaultShaderCustomization(GL2ES2 gl, boolean preludeVersion, String es2DefaultPrecision) { - int pos = 0; - if(preludeVersion) { - final String glslVersion_prelude = gl.getContext().getGLSLVersionString(); - pos = insertShaderSource(0, pos, glslVersion_prelude); - } - if( gl.isGLES() && null != es2DefaultPrecision ) { - pos = insertShaderSource(0, pos, es2DefaultPrecision); + public final int defaultShaderCustomization(GL2ES2 gl, boolean preludeVersion, String esDefaultPrecision) { + int pos; + if( preludeVersion ) { + pos = addGLSLVersion(gl); + } else { + pos = 0; + } + if( gl.isGLES2() && null != esDefaultPrecision ) { + pos = insertShaderSource(0, pos, esDefaultPrecision); + } else { + pos = addDefaultShaderPrecision(gl, pos); } return pos; } diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java index 9cade1e90..1337a7e2b 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java @@ -85,7 +85,9 @@ public class ShaderProgram { * If <code>destroyShaderCode</code> is true it destroys the shader codes as well. */ public synchronized void release(GL2ES2 gl, boolean destroyShaderCode) { - useProgram(gl, false); + if( programLinked ) { + useProgram(gl, false); + } for(Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) { ShaderCode shaderCode = iter.next(); if(attachedShaderCode.remove(shaderCode)) { diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java index a221cd51e..968391976 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java @@ -231,7 +231,7 @@ public class ShaderState { * @see ShaderProgram#release(GL2ES2, boolean) */ public synchronized void release(GL2ES2 gl, boolean destroyBoundAttributes, boolean destroyShaderProgram, boolean destroyShaderCode) { - if(null!=shaderProgram) { + if(null!=shaderProgram && shaderProgram.linked() ) { shaderProgram.useProgram(gl, false); } if(destroyBoundAttributes) { |