diff options
author | Sven Göthel <[email protected]> | 2024-01-20 05:01:38 +0100 |
---|---|---|
committer | Sven Göthel <[email protected]> | 2024-01-20 05:01:38 +0100 |
commit | c1531c3d99b19032040018b9414263b0d3000147 (patch) | |
tree | 93ad05df0398d430884350166a88371f82143947 | |
parent | 5cca51e32999a882e2a5f00cb45ecafc824ffd86 (diff) |
Graph Clipping: Use Frustum Clipping using AABBox -> Mv transformed Cube -> Frustum mapping + GraphUI Support
AABBox clipping naturally couldn't be transformed into 3D Model-View (Mv) Space,
as it is axis aligned and only provided 2 points (min/max).
Therefor we map the Group's AABBox to a 8-point Cube,
perform the Mv-transformation and then produce the 6-plane Frustum.
As before, we cull fully outside shapes within the Group's draw method
and perform fragment clipping with same Frustum planes in the shader.
With clipping enabled, the 3D z-axis getBounds() depth
will be slightly increased for functional Frustum operation.
This is also done for setFixedSize(Vec2f).
The Frustum planes are copied to the Graph shader
via float[4*6] -> uniform vec4 gcu_ClipFrustum[6]; // L, R, B, T, N, F each {n.x, n.y, n.z, d}
+++
Concludes related work of below commits
- 1040bed4ecc6f4598ea459f1073a9240583fc3c3
- 5cca51e32999a882e2a5f00cb45ecafc824ffd86
22 files changed, 364 insertions, 219 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeClippingDemo00.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeClippingDemo00.java index b23f33d36..c97292b4b 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeClippingDemo00.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeClippingDemo00.java @@ -38,6 +38,8 @@ import com.jogamp.graph.ui.shapes.Rectangle; import com.jogamp.math.FloatUtil; import com.jogamp.math.Vec3f; import com.jogamp.math.geom.AABBox; +import com.jogamp.math.geom.Cube; +import com.jogamp.math.geom.Frustum; import com.jogamp.math.geom.plane.AffineTransform; import com.jogamp.math.util.PMVMatrix4f; import com.jogamp.newt.Window; @@ -291,22 +293,19 @@ public class UIShapeClippingDemo00 implements GLEventListener { drawShape(gl, renderer, clipRect); { final AABBox sbox = shape.getBounds(gl.getGLProfile()); - final AABBox clipBBox; // Mv pre-multiplied AABBox + final Frustum clipFrustumMv; { final PMVMatrix4f pmv = renderer.getMatrix(); pmv.pushMv(); clipRect.setTransformMv(pmv); - final AABBox cb = new AABBox(clipRect.getBounds()); - cb.getLow().setZ(sbox.getLow().z()); - cb.getHigh().setZ(sbox.getHigh().z()); - clipBBox = cb.transform(pmv.getMv(), new AABBox()); + clipFrustumMv = new Cube( clipRect.getBounds() ).transform( pmv.getMv() ).updateFrustumPlanes(new Frustum()); pmv.popMv(); } - renderer.setClipBBox( clipBBox ); + renderer.setClipFrustum( clipFrustumMv ); // System.err.println("Clipping "+renderer.getClipBBox()); drawShape(gl, renderer, shape); // System.err.println("draw.0: "+shape); - renderer.setClipBBox(null); + renderer.setClipFrustum(null); } } renderer.enable(gl, false); diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeClippingDemo01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeClippingDemo01.java index f80b1a87f..887284f99 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeClippingDemo01.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeClippingDemo01.java @@ -31,6 +31,7 @@ import java.io.IOException; import com.jogamp.common.util.InterruptSource; import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.font.FontSet; @@ -38,12 +39,13 @@ import com.jogamp.graph.ui.GraphShape; import com.jogamp.graph.ui.Group; import com.jogamp.graph.ui.Scene; import com.jogamp.graph.ui.Shape; -import com.jogamp.graph.ui.shapes.Button; +import com.jogamp.graph.ui.shapes.Rectangle; import com.jogamp.math.FloatUtil; -import com.jogamp.math.Recti; import com.jogamp.math.Vec2f; import com.jogamp.math.Vec3f; import com.jogamp.math.geom.AABBox; +import com.jogamp.math.geom.Cube; +import com.jogamp.math.geom.Frustum; import com.jogamp.math.util.PMVMatrix4f; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; @@ -52,20 +54,35 @@ import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.GL; +import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.demos.util.CommandlineOptions; +import com.jogamp.opengl.demos.util.MiscUtils; import com.jogamp.opengl.util.Animator; /** - * Basic UIShape Clipping demo using a Scene and and Shape within a clipping Group + * Basic UIShape Clipping demo using a Scene and Shape within a clipping Group */ public class UIShapeClippingDemo01 { static CommandlineOptions options = new CommandlineOptions(1280, 720, Region.VBAA_RENDERING_BIT); public static void main(final String[] args) throws IOException { - options.parse(args); + boolean _useFixedSize = true; + if( 0 != args.length ) { + final int[] idx = { 0 }; + for (idx[0] = 0; idx[0] < args.length; ++idx[0]) { + if( options.parse(args, idx) ) { + continue; + } else if(args[idx[0]].equals("-NoFixedSize")) { + _useFixedSize = false; + } + } + } + final boolean useFixedSize = _useFixedSize; System.err.println(options); + System.err.println("useFixedSize "+useFixedSize); final GLProfile reqGLP = GLProfile.get(options.glProfileName); System.err.println("GLProfile: "+reqGLP); @@ -74,33 +91,10 @@ public class UIShapeClippingDemo01 { final Font font = FontFactory.get(FontFactory.UBUNTU).get(FontSet.FAMILY_LIGHT, FontSet.STYLE_SERIF); System.err.println("Font: "+font.getFullFamilyName()); - final GraphShape shape = new Button(options.renderModes, font, "Hello JogAmp", 0.20f, 0.20f/2.5f); // normalized: 1 is 100% surface size (width and/or height) - - final Group contentBox = new Group(); - contentBox.setBorder(0.005f); - contentBox.setInteractive(true); - contentBox.setClipOnBounds(true); - contentBox.setFixedSize(new Vec2f(0.6f, 0.4f)); - contentBox.move(-0.6f/2f, -0.4f/2f, 0); - contentBox.addShape(shape); - - contentBox.addMouseListener( new Shape.MouseGestureAdapter() { - @Override - public void mouseWheelMoved(final MouseEvent e) { - final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); - final Vec3f rot = new Vec3f(e.getRotation()).scale( FloatUtil.PI / 180.0f ); - // swap axis for onscreen rotation matching natural feel - final float tmp = rot.x(); rot.setX( rot.y() ); rot.setY( tmp ); - shapeEvent.shape.getRotation().rotateByEuler( rot.scale( 2f ) ); - } - }); - final Scene scene = new Scene(options.graphAASamples); - scene.setPMVMatrixSetup(new MyPMVMatrixSetup()); + scene.setPMVMatrixSetup(new Scene.DefaultPMVMatrixSetup(-1f)); // better distance for perspective action scene.setClearParams(new float[] { 1f, 1f, 1f, 1f}, GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - scene.addShape(contentBox); scene.setAAQuality(options.graphAAQuality); - final Animator animator = new Animator(0 /* w/o AWT */); final GLCapabilities caps = new GLCapabilities(reqGLP); @@ -112,6 +106,87 @@ public class UIShapeClippingDemo01 { window.setTitle(UIShapeClippingDemo01.class.getSimpleName()+": "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight()); window.setVisible(true); window.addGLEventListener(scene); + window.addGLEventListener(new GLEventListener() { + GraphShape shape = null; + Group contentBox = null; + + @Override + public void init(final GLAutoDrawable drawable) { + final AABBox sbox = scene.getBounds(); + System.err.println("Init Scene "+sbox); + // shape = new Button(options.renderModes, font, "Hello JogAmp", sbox.getWidth()/8f, sbox.getWidth()/16f); + shape = new Rectangle(options.renderModes, sbox.getWidth()/8f, sbox.getWidth()/16f, 0); + + contentBox = new Group(); + contentBox.setBorder(0.005f); + contentBox.setInteractive(true); + contentBox.setClipOnBounds(true); + contentBox.addShape(shape); + { + final float w = sbox.getWidth()*0.6f; + final float h = sbox.getHeight()*0.6f; + if( useFixedSize ) { + contentBox.setFixedSize(new Vec2f(w, h)); + } + contentBox.move(-w/2f, -h/2f, 0); + System.err.println("XXX contentBox "+contentBox.getBounds(drawable.getGLProfile())); + System.err.println("XXX shape "+shape.getBounds()); + } + + contentBox.addMouseListener( new Shape.MouseGestureAdapter() { + @Override + public void mouseWheelMoved(final MouseEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + final Vec3f rot = new Vec3f(e.getRotation()).scale( FloatUtil.PI / 180.0f ); + // swap axis for onscreen rotation matching natural feel + final float tmp = rot.x(); rot.setX( rot.y() ); rot.setY( tmp ); + shapeEvent.shape.getRotation().rotateByEuler( rot.scale( 2f ) ); + } + }); + scene.addShape(contentBox); + } + + @Override + public void dispose(final GLAutoDrawable drawable) { } + @Override + public void display(final GLAutoDrawable drawable) { + final RegionRenderer renderer = scene.getRenderer(); + final PMVMatrix4f pmv = renderer.getMatrix(); + + pmv.pushMv(); + contentBox.setTransformMv(pmv); + { + final AABBox box = contentBox.getBounds(); + final Cube cube = tempC00.set(box); + final Frustum frustumCbMv = tempC01.set(cube).transform(pmv.getMv()).updateFrustumPlanes(new Frustum()); + + pmv.pushMv(); + shape.setTransformMv(pmv); + { + final AABBox shapeBox = shape.getBounds(); + final Cube shapedMv = tempC10.set(shapeBox).transform(pmv.getMv()); + + final boolean isOutMv = frustumCbMv.isOutside( shapedMv ); + + final Frustum frustumPMv = pmv.getPMv().updateFrustumPlanes(new Frustum()); + final boolean isOutPMv = frustumPMv.isOutside( shapeBox ); + + System.err.println("ClipBox "+box); + System.err.println("ShapeBox "+shapeBox); + System.err.println("FrusPMv "+isOutPMv+", "+frustumPMv); + System.err.println("FsCbMv 1 "+isOutMv+", "+frustumCbMv); + } + pmv.popMv(); + } + pmv.popMv(); + } + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } + private final Cube tempC00 = new Cube(); // OK, synchronized + private final Cube tempC01 = new Cube(); // OK, synchronized + private final Cube tempC10 = new Cube(); // OK, synchronized + }); + window.addWindowListener(new WindowAdapter() { @Override public void windowResized(final WindowEvent e) { @@ -143,20 +218,4 @@ public class UIShapeClippingDemo01 { animator.add(window); animator.start(); } - - static class MyPMVMatrixSetup extends Scene.DefaultPMVMatrixSetup { - @Override - public void set(final PMVMatrix4f pmv, final Recti viewport) { - super.set(pmv, viewport); - - // Scale (back) to have normalized plane dimensions, 1 for the greater of width and height. - final AABBox planeBox0 = new AABBox(); - setPlaneBox(planeBox0, pmv, viewport); - final float sx = planeBox0.getWidth(); - final float sy = planeBox0.getHeight(); - final float sxy = sx > sy ? sx : sy; - pmv.scaleP(sxy, sxy, 1f); - } - }; - } diff --git a/src/graphui/classes/com/jogamp/graph/ui/Group.java b/src/graphui/classes/com/jogamp/graph/ui/Group.java index 1202752b1..d1156120a 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Group.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Group.java @@ -42,6 +42,8 @@ import com.jogamp.math.Vec2f; import com.jogamp.math.Vec3f; import com.jogamp.math.Vec4f; import com.jogamp.math.geom.AABBox; +import com.jogamp.math.geom.Cube; +import com.jogamp.math.geom.Frustum; import com.jogamp.math.util.PMVMatrix4f; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLProfile; @@ -77,14 +79,15 @@ public class Group extends Shape implements Container { } private final List<Shape> shapes = new CopyOnWriteArrayList<Shape>(); - private final Vec2f fixedSize = new Vec2f(); + /** Enforced fixed size. In case z-axis is NaN, its 3D z-axis will be adjusted. */ + private final Vec3f fixedSize = new Vec3f(); private Layout layouter; private Rectangle border = null; private boolean relayoutOnDirtyShapes = true; private boolean widgetMode = false; private boolean clipOnBounds = false; - private AABBox clipBBox = null; + private Frustum clipFrustum = null; /** * Create a group of {@link Shape}s w/o {@link Group.Layout}. @@ -118,43 +121,65 @@ public class Group extends Shape implements Container { /** Set {@link Group.Layout}. */ public Group setLayout(final Layout l) { layouter = l; return this; } - /** Enforce size of this group to given dimension. */ - public Group setFixedSize(final Vec2f v) { fixedSize.set(v); return this; } - public Vec2f getFixedSize() { return fixedSize; } + /** Enforce size of this group for all given 3 dimensions {@link #getBounds()} without adjusting 3D z-axis like {@link #setFixedSize(Vec2f)}. */ + public Group setFixedSize(final Vec3f v) { fixedSize.set(v); return this; } + /** + * Enforce size of this group to given 2 dimensions, + * adjusting the 3D z-axis {@link #getBounds()} giving room for potential clipping via {@link #setClipOnBounds(boolean)} or {@link #setClipFrustum(Frustum)}. + * @see #setFixedSize(Vec3f) + */ + public Group setFixedSize(final Vec2f v) { fixedSize.set(v.x(), v.y(), Float.NaN); return this; } + /** Returns borrowed fixed size instance, see {@link #setFixedSize(Vec3f)} and {@link #setFixedSize(Vec2f)}. */ + public Vec3f getFixedSize() { return fixedSize; } + /** Returns given {@link Vec2f} instance set with 2 dimensions, see {@link #setFixedSize(Vec2f)}. */ + public Vec2f getFixedSize(final Vec2f out) { out.set(fixedSize.x(), fixedSize.y()); return out; } /** - * Enable {@link AABBox} clipping on {@link #getBounds()} for this group and its shapes as follows + * Enable {@link Frustum} clipping on {@link #getBounds()} for this group and its shapes as follows * <ul> * <li>Discard {@link Shape} {@link #draw(GL2ES2, RegionRenderer) rendering} if not intersecting {@code clip-box}.</li> * <li>Otherwise perform pixel-accurate clipping inside the shader to {@code clip-box}.</li> * </ul> * <p> - * {@link #setClipBBox(AABBox)} takes precedence over {@link #setClipOnBounds(boolean)}. + * {@link #setClipFrustum(Frustum)} takes precedence over {@link #setClipOnBounds(boolean)}. + * </p> + * <p> + * With clipping enabled, the 3D z-axis {@link #getBounds()} depth + * will be slightly increased for functional {@link Frustum} operation. * </p> * @param v boolean to toggle clipping * @return this instance for chaining - * @see #setClipBBox(AABBox) + * @see #setClipFrustum(Frustum) + * @see #setFixedSize(Vec2f) + * @see #setFixedSize(Vec3f) */ public Group setClipOnBounds(final boolean v) { clipOnBounds = v; return this; } /** Returns {@link #setClipOnBounds(boolean)} value */ public boolean getClipOnBounds() { return clipOnBounds; } /** - * Enable {@link AABBox} clipping on explicit given pre-multiplied Mv-matrix {@code clip-box} as follows + * Enable {@link Frustum} clipping on explicit given pre-multiplied w/ Mv-matrix {@code clip-box} + * for this group and its shapes as follows * <ul> * <li>Discard {@link Shape} {@link #draw(GL2ES2, RegionRenderer) rendering} if not intersecting {@code clip-box}.</li> * <li>Otherwise perform pixel-accurate clipping inside the shader to {@code clip-box}.</li> * </ul> * <p> - * {@link #setClipBBox(AABBox)} takes precedence over {@link #setClipOnBounds(boolean)}. + * {@link #setClipFrustum(Frustum)} takes precedence over {@link #setClipOnBounds(boolean)}. + * </p> + * <p> + * With clipping enabled, the 3D z-axis {@link #getBounds()} depth + * will be slightly increased for functional {@link Frustum} operation. * </p> - * @param v {@link AABBox} pre-multiplied Mv-matrix + * @param v {@link Frustum} pre-multiplied w/ Mv-matrix * @return this instance for chaining * @see #setClipOnBounds(boolean) + * @see #setFixedSize(Vec2f) + * @see #setFixedSize(Vec3f) */ - public Group setClipBBox(final AABBox v) { clipBBox = v; return this; } - /** Returns {@link #setClipBBox(AABBox)} value */ - public AABBox getClipBBox() { return clipBBox; } + public Group setClipFrustum(final Frustum v) { clipFrustum = v; return this; } + /** Returns {@link #setClipFrustum(Frustum)} value */ + public Frustum getClipFrustum() { return clipFrustum; } @Override public int getShapeCount() { return shapes.size(); } @@ -281,12 +306,12 @@ public class Group extends Shape implements Container { final Object[] shapesS = shapes.toArray(); Arrays.sort(shapesS, (Comparator)Shape.ZAscendingComparator); - final boolean useClipBBox = null != clipBBox; - if( useClipBBox || clipOnBounds ) { - final AABBox origClipBox = renderer.getClipBBox(); + final boolean useClipFrustum = null != clipFrustum; + if( useClipFrustum || clipOnBounds ) { + final Frustum origClipFrustum = renderer.getClipFrustum(); - final AABBox clipBox = useClipBBox ? clipBBox : box.transform(pmv.getMv(), tempBB0); - renderer.setClipBBox( tempBB1.set(clipBox) ); // Mv pre-multiplied AABBox + final Frustum frustumMv = useClipFrustum ? clipFrustum : tempC00.set( box ).transform( pmv.getMv() ).updateFrustumPlanes(tempF00); + renderer.setClipFrustum( frustumMv ); final int shapeCount = shapesS.length; for(int i=0; i<shapeCount; i++) { @@ -295,16 +320,18 @@ public class Group extends Shape implements Container { pmv.pushMv(); shape.setTransformMv(pmv); - final AABBox childBox = shape.getBounds(); - if( clipBox.intersects( childBox.transform(pmv.getMv(), tempBB0) ) && - ( !doFrustumCulling || !pmv.getFrustum().isAABBoxOutside( childBox ) ) ) + final AABBox shapeBox = shape.getBounds(); + final Cube shapeMv = tempC01.set( shapeBox ).transform( pmv.getMv() ); + + if( ( !frustumMv.isOutside( shapeMv ) ) && + ( !doFrustumCulling || !pmv.getFrustum().isOutside( shapeBox ) ) ) { shape.draw(gl, renderer); } pmv.popMv(); } } - renderer.setClipBBox(origClipBox); + renderer.setClipFrustum(origClipFrustum); } else { final int shapeCount = shapesS.length; for(int i=0; i<shapeCount; i++) { @@ -323,8 +350,9 @@ public class Group extends Shape implements Container { border.draw(gl, renderer); } } - private final AABBox tempBB0 = new AABBox(); // OK, synchronized - private final AABBox tempBB1 = new AABBox(); // OK, synchronized + private final Frustum tempF00 = new Frustum(); // OK, synchronized + private final Cube tempC00 = new Cube(); // OK, synchronized + private final Cube tempC01 = new Cube(); // OK, synchronized @SuppressWarnings({ "unchecked", "rawtypes" }) @Override @@ -489,12 +517,35 @@ public class Group extends Shape implements Container { box.resize(h.x() + p.right, h.y() + p.top, l.z()); setRotationPivot( box.getCenter() ); } - if( !FloatUtil.isZero(fixedSize.x()) && !FloatUtil.isZero(fixedSize.y()) ) { - final Vec3f low = box.getLow(); - final Vec3f high = new Vec3f(low); - high.add(fixedSize.x(), fixedSize.y(), 0); - box.setSize(low, high); + final boolean useFixedSize = !FloatUtil.isZero(fixedSize.x()) && !FloatUtil.isZero(fixedSize.y()); + final boolean useClipping = null != clipFrustum || clipOnBounds; + if( useFixedSize || useClipping ) { + // final AABBox old = new AABBox(box); + final boolean adjustZ = useClipping || ( useFixedSize && Float.isNaN(fixedSize.z()) ); + final Vec3f lo = box.getLow(); + if( adjustZ ) { + final float oldDepth = box.getDepth(); + final Vec3f hi; + final float zAdjustment = 10f*Scene.DEFAULT_ACTIVE_ZOFFSET_SCALE*Scene.DEFAULT_Z16_EPSILON; + lo.add( 0, 0, -(1f*zAdjustment)); + if( useFixedSize ) { + hi = new Vec3f(lo); + hi.add(fixedSize.x(), fixedSize.y(), oldDepth+(2f*zAdjustment)); + } else { + hi = box.getHigh(); + hi.add( 0, 0, oldDepth+(1f*zAdjustment)); + } + box.setSize(lo, hi); + } else if( useFixedSize ) { + final Vec3f hi = useFixedSize ? new Vec3f(lo) : box.getHigh(); + + hi.add(fixedSize.x(), fixedSize.y(), fixedSize.z()); + box.setSize(lo, hi); + } + // System.err.println("- was "+old); + // System.err.println("- has "+box); } + if( hasBorder() ) { if( null == border ) { final int firstRMs = null != firstGS ? firstGS.getRenderModes() : 0; diff --git a/src/graphui/classes/com/jogamp/graph/ui/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/Scene.java index 189c75c9d..03cc29097 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Scene.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Scene.java @@ -111,6 +111,8 @@ public final class Scene implements Container, GLEventListener { public static final float DEFAULT_ZFAR = 7000.0f; /** Default Z precision on 16-bit depth buffer using {@link #DEFAULT_SCENE_DIST} z-position and {@link #DEFAULT_ZNEAR}. Value is {@code 6.1033297E-6}. */ public static final float DEFAULT_Z16_EPSILON = FloatUtil.getZBufferEpsilon(16 /* zBits */, DEFAULT_SCENE_DIST, DEFAULT_ZNEAR); + /** Default Z precision scale, i.e. multiple of {@link #DEFAULT_Z16_EPSILON} for {@link #setActiveShapeZOffsetScale(float)}. Value is {@value}. */ + public static final float DEFAULT_ACTIVE_ZOFFSET_SCALE = 10f; /** Default Z precision on 16-bit depth buffer using {@code -1} z-position and {@link #DEFAULT_ZNEAR}. Value is {@code 1.5256461E-4}. */ // public static final float DIST1_Z16_EPSILON = FloatUtil.getZBufferEpsilon(16 /* zBits */, -1, DEFAULT_ZNEAR); @@ -1033,7 +1035,7 @@ public final class Scene implements Container, GLEventListener { activeShape = shape; } } - private float activeZOffsetScale = 10f; + private float activeZOffsetScale = DEFAULT_ACTIVE_ZOFFSET_SCALE; /** Returns the active {@link Shape} Z-Offset scale, defaults to {@code 10.0}. */ public float getActiveShapeZOffsetScale() { return activeZOffsetScale; } diff --git a/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java b/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java index f84c3cf5a..838a39254 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java +++ b/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java @@ -39,6 +39,9 @@ import com.jogamp.math.Vec2f; import com.jogamp.math.Vec3f; import com.jogamp.math.Vec4f; import com.jogamp.math.geom.AABBox; +import com.jogamp.math.geom.Cube; +import com.jogamp.math.geom.Frustum; +import com.jogamp.math.util.PMVMatrix4f; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.texture.TextureSequence; @@ -134,7 +137,7 @@ public class RangedGroup extends Widget { } public Group getContent() { return content; } - public Vec2f getContentSize() { return clippedContent.getFixedSize(); } + public Vec2f getContentSize(final Vec2f out) { return clippedContent.getFixedSize(out); } public Group getClippedContent() { return clippedContent; } public RangeSlider getHorizSlider() { return horizSlider; } public RangeSlider getVertSlider() { return vertSlider; } @@ -145,7 +148,7 @@ public class RangedGroup extends Widget { super.validateImpl(gl, glp); final AABBox b = content.getBounds(); - final Vec2f contentSize = getContentSize(); + final Vec3f contentSize = clippedContent.getFixedSize(); contentPosZero.set(0, 0); if( null != horizSlider ) { horizSlider.setMinMax(new Vec2f(0, content.getBounds().getWidth()), 0); @@ -164,12 +167,15 @@ public class RangedGroup extends Widget { @Override protected void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final Vec4f rgba) { if( content.isVisible() ) { - // Mv pre-multiplied AABBox, clippedContent is on same PMV - final AABBox clipBBox = clippedContent.getBounds().transform(renderer.getMatrix().getMv(), tempBB); - content.setClipBBox(clipBBox); + final PMVMatrix4f pmv = renderer.getMatrix(); + + // Mv pre-multiplied Frustum, clippedContent is on same PMV + final Frustum clipFrustum = tempC00.set( clippedContent.getBounds() ).transform( pmv.getMv() ).updateFrustumPlanes(tempF00); + content.setClipFrustum(clipFrustum); super.drawImpl0(gl, renderer, rgba); - content.setClipBBox(null); + content.setClipFrustum(null); } } - private final AABBox tempBB = new AABBox(); // OK, synchronized + private final Frustum tempF00 = new Frustum(); // OK, synchronized + private final Cube tempC00 = new Cube(); // OK, synchronized } diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java index 50fae4907..e9c185753 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -48,7 +48,7 @@ import com.jogamp.common.os.Platform; import com.jogamp.graph.curve.Region; import com.jogamp.math.Recti; import com.jogamp.math.Vec4f; -import com.jogamp.math.geom.AABBox; +import com.jogamp.math.geom.Frustum; import com.jogamp.math.util.PMVMatrix4f; /** @@ -314,10 +314,10 @@ public final class RegionRenderer { /** Returns pass2 AA sample count for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link #VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */ public final int getSampleCount() { return rs.getSampleCount(); } - /** Set the optional clipping {@link AABBox}, which shall be pre-multiplied with the Mv-matrix or null to disable. */ - public final void setClipBBox(final AABBox clipBBox) { rs.setClipBBox(clipBBox); } - /** Returns the optional Mv-premultiplied clipping {@link AABBox} or null if unused. */ - public final AABBox getClipBBox() { return rs.getClipBBox(); } + /** Set the optional clipping {@link Frustum}, which shall be pre-multiplied with the Mv-matrix or null to disable. */ + public final void setClipFrustum(final Frustum clipFrustum) { rs.setClipFrustum(clipFrustum); } + /** Returns the optional Mv-premultiplied clipping {@link Frustum} or null if unused. */ + public final Frustum getClipFrustum() { return rs.getClipFrustum(); } public final boolean isHintMaskSet(final int mask) { return rs.isHintMaskSet(mask); } @@ -419,7 +419,7 @@ public final class RegionRenderer { private static final String GLSL_PARAM_COMMENT_END = "// JogAmp Graph Parameter End\n\n"; private static final String GLSL_USE_COLOR_CHANNEL = "#define USE_COLOR_CHANNEL 1\n"; private static final String GLSL_USE_COLOR_TEXTURE = "#define USE_COLOR_TEXTURE 1\n"; - private static final String GLSL_USE_AABBOX_CLIPPING = "#define USE_AABBOX_CLIPPING 1\n"; + private static final String GLSL_USE_FRUSTUM_CLIPPING = "#define USE_FRUSTUM_CLIPPING 1\n"; private static final String GLSL_DEF_SAMPLE_COUNT = "#define SAMPLE_COUNT "; private static final String GLSL_CONST_SAMPLE_COUNT = "const float sample_count = "; private static final String GLSL_MAIN_BEGIN = "void main (void)\n{\n"; @@ -525,7 +525,7 @@ public final class RegionRenderer { final boolean isTwoPass; final boolean pass1; final ShaderModeSelector1 sms; - final boolean hasAABBoxClipping; // pass1 or pass2 + final boolean hasFrustumClipping; // pass1 or pass2 final boolean hasColorChannel; // pass1 only final boolean hasColorTexture; // pass1 only final String colorTexSeqID; @@ -534,12 +534,12 @@ public final class RegionRenderer { final String texLookupFuncName; final int hashValue; - ShaderKey(final int renderModes, final boolean pass1_, final int pass2Quality, final int sampleCount, final TextureSequence colorTexSeq, final boolean hasClipBBox) { + ShaderKey(final int renderModes, final boolean pass1_, final int pass2Quality, final int sampleCount, final TextureSequence colorTexSeq, final boolean hasClipFrustum) { isTwoPass = Region.isTwoPass( renderModes ); pass1 = pass1_; sms = pass1 ? ShaderModeSelector1.selectPass1(renderModes) : ShaderModeSelector1.selectPass2(renderModes, pass2Quality, sampleCount); - hasAABBoxClipping = hasClipBBox && ( ( !isTwoPass && pass1 ) || ( isTwoPass && !pass1 ) ); + hasFrustumClipping = hasClipFrustum && ( ( !isTwoPass && pass1 ) || ( isTwoPass && !pass1 ) ); hasColorChannel = pass1 && Region.hasColorChannel( renderModes ); hasColorTexture = pass1 && Region.hasColorTexture( renderModes ) && null != colorTexSeq; if( hasColorTexture ) { @@ -558,7 +558,7 @@ public final class RegionRenderer { // hash = ((hash << 5) - hash) + pass2Quality; // included in sms // hash = ((hash << 5) - hash) + sampleCount; // included in sms hash = ((hash << 5) - hash) + sms.ordinal(); - hash = ((hash << 5) - hash) + ( hasAABBoxClipping ? 1 : 0 ); + hash = ((hash << 5) - hash) + ( hasFrustumClipping ? 1 : 0 ); hash = ((hash << 5) - hash) + ( hasColorChannel ? 1 : 0 ); hash = ((hash << 5) - hash) + ( hasColorTexture ? 1 : 0 ); hash = ((hash << 5) - hash) + colorTexSeqHash; @@ -579,7 +579,7 @@ public final class RegionRenderer { // pass2Quality == o.pass2Quality && // included in sms // sampleCount == o.sampleCount && // included in sms sms.ordinal() == o.sms.ordinal() && - hasAABBoxClipping == o.hasAABBoxClipping && + hasFrustumClipping == o.hasFrustumClipping && hasColorChannel == o.hasColorChannel && hasColorTexture == o.hasColorTexture && colorTexSeqID.equals(o.colorTexSeqID); @@ -587,7 +587,7 @@ public final class RegionRenderer { @Override public String toString() { return "ShaderKey[hash 0x"+Integer.toHexString(hashValue)+", is2Pass "+isTwoPass+", pass1 "+pass1+ - ", has[clip "+hasAABBoxClipping+", colChan "+hasColorChannel+", colTex "+hasColorTexture+"], "+sms+"]"; + ", has[clip "+hasFrustumClipping+", colChan "+hasColorChannel+", colTex "+hasColorTexture+"], "+sms+"]"; } } private final HashMap<ShaderKey, ShaderProgram> shaderPrograms = new HashMap<ShaderKey, ShaderProgram>(); @@ -609,7 +609,7 @@ public final class RegionRenderer { * @see RenderState#getShaderProgram() */ public final boolean useShaderProgram(final GL2ES2 gl, final int renderModes, final boolean pass1, final TextureSequence colorTexSeq) { - final ShaderKey shaderKey = new ShaderKey(renderModes, pass1, getAAQuality(), getSampleCount(), colorTexSeq, null != getClipBBox()); + final ShaderKey shaderKey = new ShaderKey(renderModes, pass1, getAAQuality(), getSampleCount(), colorTexSeq, null != getClipFrustum()); /** if(DEBUG) { @@ -686,9 +686,9 @@ public final class RegionRenderer { posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_DISCARD); } - if( shaderKey.hasAABBoxClipping ) { - posVp = rsVp.insertShaderSource(0, posVp, GLSL_USE_AABBOX_CLIPPING); - posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_AABBOX_CLIPPING); + if( shaderKey.hasFrustumClipping ) { + posVp = rsVp.insertShaderSource(0, posVp, GLSL_USE_FRUSTUM_CLIPPING); + posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_FRUSTUM_CLIPPING); } if( shaderKey.hasColorChannel ) { @@ -708,11 +708,11 @@ public final class RegionRenderer { posFp = rsFp.insertShaderSource(0, posFp, GLSL_PARAM_COMMENT_END); try { - if( shaderKey.hasColorTexture || shaderKey.hasAABBoxClipping ) { - posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "functions.glsl"); - } posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "uniforms.glsl"); posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "varyings.glsl"); + if( shaderKey.hasColorTexture || shaderKey.hasFrustumClipping ) { + posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "functions.glsl"); + } } catch (final IOException ioe) { throw new RuntimeException("Failed to read: includes", ioe); } diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java index ed5bcb110..d6be9e07b 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java @@ -39,7 +39,7 @@ import jogamp.graph.curve.opengl.shader.UniformNames; import com.jogamp.graph.curve.Region; import com.jogamp.math.Vec4f; -import com.jogamp.math.geom.AABBox; +import com.jogamp.math.geom.Frustum; import com.jogamp.math.util.PMVMatrix4f; import com.jogamp.opengl.util.GLArrayDataWrapper; import com.jogamp.opengl.util.glsl.ShaderProgram; @@ -102,8 +102,9 @@ public class RenderState { private int aaQuality; /** Default pass2 AA sample count {@value} for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */ private int sampleCount; - /** Optional clipping {@link AABBox}, which shall be pre-multiplied with the Mv-matrix. Null if unused. */ - private AABBox clipBBox; + /** Optional clipping {@link Frustum}, which shall be pre-multiplied with the Mv-matrix. Null if unused. */ + private final Frustum clipFrustum; + private boolean useClipFrustum; private int hintBitfield; private ShaderProgram sp; @@ -205,7 +206,9 @@ public class RenderState { this.colorStaticBuffer = FloatBuffer.wrap(colorStatic); this.aaQuality = Region.DEFAULT_AA_QUALITY; this.sampleCount = Region.DEFAULT_AA_SAMPLE_COUNT; - this.clipBBox = null; + this.clipFrustum = new Frustum(); + this.useClipFrustum = false; + this.hintBitfield = 0; this.sp = null; } @@ -281,10 +284,17 @@ public class RenderState { /** Returns pass2 AA sample count for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link #VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */ public final int getSampleCount() { return this.sampleCount; } - /** Set the optional clipping {@link AABBox}, which shall be pre-multiplied with the Mv-matrix or null to disable. */ - public final void setClipBBox(final AABBox clipBBox) { this.clipBBox = clipBBox; } - /** Returns the optional Mv-premultiplied clipping {@link AABBox} or null if unused. */ - public final AABBox getClipBBox() { return this.clipBBox; } + /** Set the optional clipping {@link Frustum}, which shall be pre-multiplied with the Mv-matrix or null to disable. */ + public final void setClipFrustum(final Frustum clipFrustum) { + if( null != clipFrustum ) { + this.clipFrustum.set(clipFrustum); + this.useClipFrustum=true; + } else { + this.useClipFrustum=false; + } + } + /** Returns the optional Mv-premultiplied clipping {@link Frustum} or null if unused. */ + public final Frustum getClipFrustum() { return useClipFrustum ? this.clipFrustum : null; } /** * diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java index ae4a734be..a6ba0e810 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java @@ -45,6 +45,7 @@ import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.math.Matrix4f; import com.jogamp.math.Recti; import com.jogamp.math.geom.AABBox; +import com.jogamp.math.geom.Frustum; import com.jogamp.math.util.SyncMatrices4f16; import com.jogamp.opengl.FBObject; import com.jogamp.opengl.FBObject.Attachment; @@ -66,8 +67,8 @@ public final class VBORegion2PMSAAES2 extends GLRegion { private final GLUniformData gcu_ColorTexUnit; private final float[] colorTexBBox; // minX/minY, maxX/maxY, texW/texH private final GLUniformData gcu_ColorTexBBox; // vec2 gcu_ColorTexBBox[3] -> boxMin[2], boxMax[2] and texSize[2] - private final float[] clipBBox; // minX/minY/minZ, maxX/maxY/maxZ - private final GLUniformData gcu_ClipBBox; // uniform vec3 gcu_ClipBBox[2]; // box-min[3], box-max[3] + private final float[/* 4*6 */] clipFrustum; // 6 frustum planes, each [n.x, n.y. n.z, d] + private final GLUniformData gcu_ClipFrustum; // uniform vec4 gcu_ClipFrustum[6]; // L, R, B, T, N, F private ShaderProgram spPass1 = null; // Pass-2: @@ -111,8 +112,8 @@ public final class VBORegion2PMSAAES2 extends GLRegion { colorTexBBox = null; gcu_ColorTexBBox = null; } - clipBBox = new float[6]; - gcu_ClipBBox = new GLUniformData(UniformNames.gcu_ClipBBox, 3, FloatBuffer.wrap(clipBBox)); + clipFrustum = new float[4*6]; + gcu_ClipFrustum = new GLUniformData(UniformNames.gcu_ClipFrustum, 4, FloatBuffer.wrap(clipFrustum)); gcu_PMVMatrix02 = new GLUniformData(UniformNames.gcu_PMVMatrix02, 4, 4, new SyncMatrices4f16( new Matrix4f[] { matP, matMv } )); // Pass 2: @@ -185,7 +186,7 @@ public final class VBORegion2PMSAAES2 extends GLRegion { final boolean hasColorTexture = Region.hasColorTexture( curRenderModes ) && null != colorTexSeq; final RenderState rs = renderer.getRenderState(); - final boolean hasAABBoxClipping = null != rs.getClipBBox() && ( ( !isTwoPass && pass1 ) || ( isTwoPass && !pass1 ) ); + final boolean hasFrustumClipping = null != rs.getClipFrustum() && ( ( !isTwoPass && pass1 ) || ( isTwoPass && !pass1 ) ); final boolean updateLocGlobal = renderer.useShaderProgram(gl, curRenderModes, pass1, colorTexSeq); final ShaderProgram sp = renderer.getRenderState().getShaderProgram(); @@ -230,8 +231,8 @@ public final class VBORegion2PMSAAES2 extends GLRegion { rsLocal.update(gl, rs, updateLocLocal, curRenderModes, true, false, true); rs.updateUniformDataLoc(gl, updateLocLocal, false /* updateData */, gcu_FboTexUnit, true); // FIXME always update if changing tex-unit } - if( hasAABBoxClipping && updateLocLocal ) { - rs.updateUniformLoc(gl, true, gcu_ClipBBox, true); + if( hasFrustumClipping && updateLocLocal ) { + rs.updateUniformLoc(gl, true, gcu_ClipFrustum, true); } } @@ -381,11 +382,10 @@ public final class VBORegion2PMSAAES2 extends GLRegion { } { - final AABBox cb = rs.getClipBBox(); - if( null != cb ) { - clipBBox[0] = cb.getMinX(); clipBBox[1] = cb.getMinY(); clipBBox[2] = cb.getMinZ(); - clipBBox[3] = cb.getMaxX(); clipBBox[4] = cb.getMaxY(); clipBBox[5] = cb.getMaxZ(); - gl.glUniform(gcu_ClipBBox); // Always update, since program maybe used by multiple regions + final Frustum f = rs.getClipFrustum(); + if( null != f ) { + f.getPlanes(clipFrustum, 0); + gl.glUniform(gcu_ClipFrustum); // Always update, since program maybe used by multiple regions } } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java index bf23f33e9..4585c4cab 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java @@ -46,6 +46,7 @@ import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.math.Matrix4f; import com.jogamp.math.Recti; import com.jogamp.math.geom.AABBox; +import com.jogamp.math.geom.Frustum; import com.jogamp.math.util.SyncMatrices4f16; import com.jogamp.opengl.FBObject; import com.jogamp.opengl.FBObject.Attachment; @@ -71,8 +72,8 @@ public final class VBORegion2PVBAAES2 extends GLRegion { private final GLUniformData gcu_ColorTexUnit; private final float[] colorTexBBox; // minX/minY, maxX/maxY, texW/texH private final GLUniformData gcu_ColorTexBBox; // vec2 gcu_ColorTexBBox[3] -> boxMin[2], boxMax[2] and texSize[2] - private final float[] clipBBox; // minX/minY/minZ, maxX/maxY/maxZ - private final GLUniformData gcu_ClipBBox; // uniform vec3 gcu_ClipBBox[2]; // box-min[3], box-max[3] + private final float[/* 4*6 */] clipFrustum; // 6 frustum planes, each [n.x, n.y. n.z, d] + private final GLUniformData gcu_ClipFrustum; // uniform vec4 gcu_ClipFrustum[6]; // L, R, B, T, N, F private ShaderProgram spPass1 = null; // Pass-2: @@ -96,6 +97,50 @@ public final class VBORegion2PVBAAES2 extends GLRegion { final int[] maxTexSize = new int[] { -1 } ; + public VBORegion2PVBAAES2(final GLProfile glp, final int renderModes, final TextureSequence colorTexSeq, final int pass2TexUnit, + final int initialVerticesCount, final int initialIndicesCount) + { + super(glp, renderModes, colorTexSeq); + + rsLocal = new RenderState.ProgramLocal(); + + // Pass 1: + initBuffer(initialVerticesCount, initialIndicesCount); + + if( hasColorTexture() ) { + gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit()); + colorTexBBox = new float[6]; + gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 2, FloatBuffer.wrap(colorTexBBox)); + } else { + gcu_ColorTexUnit = null; + colorTexBBox = null; + gcu_ColorTexBBox = null; + } + clipFrustum = new float[4*6]; + gcu_ClipFrustum = new GLUniformData(UniformNames.gcu_ClipFrustum, 4, FloatBuffer.wrap(clipFrustum)); + gcu_PMVMatrix02 = new GLUniformData(UniformNames.gcu_PMVMatrix02, 4, 4, new SyncMatrices4f16( new Matrix4f[] { matP, matMv } )); + + // Pass 2: + gcu_FboTexUnit = new GLUniformData(UniformNames.gcu_FboTexUnit, pass2TexUnit); + gcu_FboTexSize = new GLUniformData(UniformNames.gcu_FboTexSize, 2, FloatBuffer.wrap(new float[2])); + + indicesFbo = GLArrayDataServer.createData(3, GL.GL_UNSIGNED_SHORT, 2, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); + indicesFbo.puts((short) 0); indicesFbo.puts((short) 1); indicesFbo.puts((short) 3); + indicesFbo.puts((short) 1); indicesFbo.puts((short) 2); indicesFbo.puts((short) 3); + indicesFbo.seal(true); + + gca_FboTexCoordsAttr = GLArrayDataServer.createGLSL(AttributeNames.FBO_TEXCOORDS_ATTR_NAME, 2, GL.GL_FLOAT, + false, 4, GL.GL_STATIC_DRAW); + gca_FboTexCoordsAttr.putf(0); gca_FboTexCoordsAttr.putf(0); + gca_FboTexCoordsAttr.putf(0); gca_FboTexCoordsAttr.putf(1); + gca_FboTexCoordsAttr.putf(1); gca_FboTexCoordsAttr.putf(1); + gca_FboTexCoordsAttr.putf(1); gca_FboTexCoordsAttr.putf(0); + gca_FboTexCoordsAttr.seal(true); + + gca_FboVerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.FBO_VERTEX_ATTR_NAME, 3, GL.GL_FLOAT, + false, 4, GL.GL_STATIC_DRAW); + } + /** * <p> * Since multiple {@link Region}s may share one @@ -113,7 +158,7 @@ public final class VBORegion2PVBAAES2 extends GLRegion { final boolean hasColorTexture = Region.hasColorTexture( curRenderModes ) && null != colorTexSeq; final RenderState rs = renderer.getRenderState(); - final boolean hasAABBoxClipping = null != rs.getClipBBox() && ( ( !isTwoPass && pass1 ) || ( isTwoPass && !pass1 ) ); + final boolean hasFrustumClipping = null != rs.getClipFrustum() && ( ( !isTwoPass && pass1 ) || ( isTwoPass && !pass1 ) ); final boolean updateLocGlobal = renderer.useShaderProgram(gl, curRenderModes, pass1, colorTexSeq); final ShaderProgram sp = renderer.getRenderState().getShaderProgram(); @@ -159,55 +204,11 @@ public final class VBORegion2PVBAAES2 extends GLRegion { rs.updateUniformDataLoc(gl, updateLocLocal, false /* updateData */, gcu_FboTexUnit, true); // FIXME always update if changing tex-unit rs.updateUniformLoc(gl, updateLocLocal, gcu_FboTexSize, rs.getSampleCount() > 1); // maybe optimized away for sampleCount <= 1 } - if( hasAABBoxClipping && updateLocLocal ) { - rs.updateUniformLoc(gl, true, gcu_ClipBBox, true); + if( hasFrustumClipping && updateLocLocal ) { + rs.updateUniformLoc(gl, true, gcu_ClipFrustum, true); } } - public VBORegion2PVBAAES2(final GLProfile glp, final int renderModes, final TextureSequence colorTexSeq, final int pass2TexUnit, - final int initialVerticesCount, final int initialIndicesCount) - { - super(glp, renderModes, colorTexSeq); - - rsLocal = new RenderState.ProgramLocal(); - - // Pass 1: - initBuffer(initialVerticesCount, initialIndicesCount); - - if( hasColorTexture() ) { - gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit()); - colorTexBBox = new float[6]; - gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 2, FloatBuffer.wrap(colorTexBBox)); - } else { - gcu_ColorTexUnit = null; - colorTexBBox = null; - gcu_ColorTexBBox = null; - } - clipBBox = new float[6]; - gcu_ClipBBox = new GLUniformData(UniformNames.gcu_ClipBBox, 3, FloatBuffer.wrap(clipBBox)); - gcu_PMVMatrix02 = new GLUniformData(UniformNames.gcu_PMVMatrix02, 4, 4, new SyncMatrices4f16( new Matrix4f[] { matP, matMv } )); - - // Pass 2: - gcu_FboTexUnit = new GLUniformData(UniformNames.gcu_FboTexUnit, pass2TexUnit); - gcu_FboTexSize = new GLUniformData(UniformNames.gcu_FboTexSize, 2, FloatBuffer.wrap(new float[2])); - - indicesFbo = GLArrayDataServer.createData(3, GL.GL_UNSIGNED_SHORT, 2, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); - indicesFbo.puts((short) 0); indicesFbo.puts((short) 1); indicesFbo.puts((short) 3); - indicesFbo.puts((short) 1); indicesFbo.puts((short) 2); indicesFbo.puts((short) 3); - indicesFbo.seal(true); - - gca_FboTexCoordsAttr = GLArrayDataServer.createGLSL(AttributeNames.FBO_TEXCOORDS_ATTR_NAME, 2, GL.GL_FLOAT, - false, 4, GL.GL_STATIC_DRAW); - gca_FboTexCoordsAttr.putf(0); gca_FboTexCoordsAttr.putf(0); - gca_FboTexCoordsAttr.putf(0); gca_FboTexCoordsAttr.putf(1); - gca_FboTexCoordsAttr.putf(1); gca_FboTexCoordsAttr.putf(1); - gca_FboTexCoordsAttr.putf(1); gca_FboTexCoordsAttr.putf(0); - gca_FboTexCoordsAttr.seal(true); - - gca_FboVerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.FBO_VERTEX_ATTR_NAME, 3, GL.GL_FLOAT, - false, 4, GL.GL_STATIC_DRAW); - } - @Override public void setTextureUnit(final int pass2TexUnit) { gcu_FboTexUnit.setData(pass2TexUnit); @@ -420,11 +421,10 @@ public final class VBORegion2PVBAAES2 extends GLRegion { gl.glUniform(gcu_FboTexSize); { - final AABBox cb = rs.getClipBBox(); - if( null != cb ) { - clipBBox[0] = cb.getMinX(); clipBBox[1] = cb.getMinY(); clipBBox[2] = cb.getMinZ(); - clipBBox[3] = cb.getMaxX(); clipBBox[4] = cb.getMaxY(); clipBBox[5] = cb.getMaxZ(); - gl.glUniform(gcu_ClipBBox); // Always update, since program maybe used by multiple regions + final Frustum f = rs.getClipFrustum(); + if( null != f ) { + f.getPlanes(clipFrustum, 0); + gl.glUniform(gcu_ClipFrustum); // Always update, since program maybe used by multiple regions } } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java index 3a568758c..c4e842791 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java @@ -40,7 +40,7 @@ import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.curve.opengl.RenderState; -import com.jogamp.math.geom.AABBox; +import com.jogamp.math.geom.Frustum; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureSequence; @@ -52,8 +52,8 @@ public final class VBORegionSPES2 extends GLRegion { private final GLUniformData gcu_ColorTexUnit; private final float[] colorTexBBox; // minX/minY, maxX/maxY, texW/texH private final GLUniformData gcu_ColorTexBBox; // vec2 gcu_ColorTexBBox[3] -> boxMin[2], boxMax[2] and texSize[2] - private final float[] clipBBox; // minX/minY/minZ, maxX/maxY/maxZ - private final GLUniformData gcu_ClipBBox; // uniform vec3 gcu_ClipBBox[2]; // box-min[3], box-max[3] + private final float[/* 4*6 */] clipFrustum; // 6 frustum planes, each [n.x, n.y. n.z, d] + private final GLUniformData gcu_ClipFrustum; // uniform vec4 gcu_ClipFrustum[6]; // L, R, B, T, N, F private ShaderProgram spPass1 = null; public VBORegionSPES2(final GLProfile glp, final int renderModes, final TextureSequence colorTexSeq, @@ -74,8 +74,8 @@ public final class VBORegionSPES2 extends GLRegion { colorTexBBox = null; gcu_ColorTexBBox = null; } - clipBBox = new float[6]; - gcu_ClipBBox = new GLUniformData(UniformNames.gcu_ClipBBox, 3, FloatBuffer.wrap(clipBBox)); + clipFrustum = new float[4*6]; + gcu_ClipFrustum = new GLUniformData(UniformNames.gcu_ClipFrustum, 4, FloatBuffer.wrap(clipFrustum)); } @Override @@ -122,7 +122,7 @@ public final class VBORegionSPES2 extends GLRegion { final boolean hasColorTexture = Region.hasColorTexture( curRenderModes ) && null != colorTexSeq; final RenderState rs = renderer.getRenderState(); - final boolean hasAABBoxClipping = null != rs.getClipBBox(); + final boolean hasFrustumClipping = null != rs.getClipFrustum(); final boolean updateLocGlobal = renderer.useShaderProgram(gl, curRenderModes, true, colorTexSeq); final ShaderProgram sp = renderer.getRenderState().getShaderProgram(); @@ -139,8 +139,8 @@ public final class VBORegionSPES2 extends GLRegion { if( hasColorChannel && null != gca_ColorsAttr ) { rs.updateAttributeLoc(gl, true, gca_ColorsAttr, throwOnError); } - if( hasAABBoxClipping ) { - rs.updateUniformLoc(gl, true, gcu_ClipBBox, throwOnError); + if( hasFrustumClipping ) { + rs.updateUniformLoc(gl, true, gcu_ClipFrustum, throwOnError); } } rsLocal.update(gl, rs, updateLocLocal, curRenderModes, true, true, throwOnError); @@ -158,11 +158,10 @@ public final class VBORegionSPES2 extends GLRegion { useShaderProgram(gl, renderer, curRenderModes); { - final AABBox cb = renderer.getClipBBox(); - if( null != cb ) { - clipBBox[0] = cb.getMinX(); clipBBox[1] = cb.getMinY(); clipBBox[2] = cb.getMinZ(); - clipBBox[3] = cb.getMaxX(); clipBBox[4] = cb.getMaxY(); clipBBox[5] = cb.getMaxZ(); - gl.glUniform(gcu_ClipBBox); // Always update, since program maybe used by multiple regions + final Frustum f = renderer.getClipFrustum(); + if( null != f ) { + f.getPlanes(clipFrustum, 0); + gl.glUniform(gcu_ClipFrustum); // Always update, since program maybe used by multiple regions } } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/UniformNames.java b/src/jogl/classes/jogamp/graph/curve/opengl/shader/UniformNames.java index 4a66295f2..7a20fc2da 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/UniformNames.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/UniformNames.java @@ -6,7 +6,7 @@ public class UniformNames { public static final String gcu_Weight = "gcu_Weight"; public static final String gcu_ColorTexUnit = "gcu_ColorTexUnit"; public static final String gcu_ColorTexBBox = "gcu_ColorTexBBox"; - public static final String gcu_ClipBBox = "gcu_ClipBBox"; + public static final String gcu_ClipFrustum = "gcu_ClipFrustum"; public static final String gcu_PMVMatrix02 = "gcu_PMVMatrix02"; // gcu_PMVMatrix[3]; // P, Mv, and Mvi public static final String gcu_FboTexUnit = "gcu_FboTexUnit"; diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl index c5850f5fa..edb3b553b 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl @@ -1,7 +1,7 @@ // Copyright 2010-2024 JogAmp Community. All rights reserved. -#ifdef USE_AABBOX_CLIPPING - if( is_inside(gcv_ClipBBoxCoord, gcu_ClipBBox[0], gcu_ClipBBox[1]) < 0.5 ) { +#ifdef USE_FRUSTUM_CLIPPING + if( isOutsideMvFrustum(gcv_ClipCoord) ) { #if USE_DISCARD discard; // discard freezes NV tegra2 compiler #else diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_weight.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_weight.glsl index e7172d834..9c8b6a4a5 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_weight.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_weight.glsl @@ -1,7 +1,7 @@ // Copyright 2010-2024 JogAmp Community. All rights reserved. -#ifdef USE_AABBOX_CLIPPING - if( is_inside(gcv_ClipBBoxCoord, gcu_ClipBBox[0], gcu_ClipBBox[1]) < 0.5 ) { +#ifdef USE_FRUSTUM_CLIPPING + if( isOutsideMvFrustum(gcv_ClipCoord) ) { #if USE_DISCARD discard; // discard freezes NV tegra2 compiler #else diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl index 3d4cdc887..3b7291446 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl @@ -1,6 +1,7 @@ // Pass-2: Dump Texture -#ifdef USE_AABBOX_CLIPPING - if( is_inside(gcv_ClipBBoxCoord, gcu_ClipBBox[0], gcu_ClipBBox[1]) < 0.5 ) { + +#ifdef USE_FRUSTUM_CLIPPING + if( isOutsideMvFrustum(gcv_ClipCoord) ) { #if USE_DISCARD discard; // discard freezes NV tegra2 compiler #else diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl index 5e14a1a23..c71267be4 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl @@ -1,10 +1,10 @@ // Pass-2: AA on Texture // Note: gcv_FboTexCoord is in center of sample pixels. -#ifdef USE_AABBOX_CLIPPING - if( is_inside(gcv_ClipBBoxCoord, gcu_ClipBBox[0], gcu_ClipBBox[1]) < 0.5 ) { +#ifdef USE_FRUSTUM_CLIPPING + if( isOutsideMvFrustum(gcv_ClipCoord) ) { #if USE_DISCARD - discard; // discard freezes NV tegra2 compiler + discard; // discard freezes NV tegra2 compiler #else mgl_FragColor = vec4(0); #endif diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl index b7d2e0e4e..4fa3c601e 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl @@ -1,8 +1,8 @@ // Pass-2: AA on Texture // Note: gcv_FboTexCoord is in center of sample pixels. -#ifdef USE_AABBOX_CLIPPING - if( is_inside(gcv_ClipBBoxCoord, gcu_ClipBBox[0], gcu_ClipBBox[1]) < 0.5 ) { +#ifdef USE_FRUSTUM_CLIPPING + if( isOutsideMvFrustum(gcv_ClipCoord) ) { #if USE_DISCARD discard; // discard freezes NV tegra2 compiler #else diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl index da0306425..76b064420 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl @@ -4,8 +4,8 @@ // // Same as flipquad - but w/ rgss coordinates -#ifdef USE_AABBOX_CLIPPING - if( is_inside(gcv_ClipBBoxCoord, gcu_ClipBBox[0], gcu_ClipBBox[1]) < 0.5 ) { +#ifdef USE_FRUSTUM_CLIPPING + if( isOutsideMvFrustum(gcv_ClipCoord) ) { #if USE_DISCARD discard; // discard freezes NV tegra2 compiler #else diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp index dce78b9c8..5ee5fcb46 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp @@ -14,8 +14,8 @@ void main(void) // gl_Position = gcu_PMVMatrix01[0] * gcu_PMVMatrix01[1] * vec4(gca_FboVertices, 1); gl_Position = gcu_PMVMatrix01[0] * gcu_PMVMatrix01[1] * gca_FboVertices; -#ifdef USE_AABBOX_CLIPPING - gcv_ClipBBoxCoord = (gcu_PMVMatrix01[1] * gca_FboVertices).xyz; // Mv +#ifdef USE_FRUSTUM_CLIPPING + gcv_ClipCoord = (gcu_PMVMatrix01[1] * gca_FboVertices).xyz; // Mv #endif gcv_FboTexCoord = gca_FboTexCoords; diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp index 2f07ad7d0..bda10c432 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp @@ -24,8 +24,8 @@ void main(void) } #endif -#ifdef USE_AABBOX_CLIPPING - gcv_ClipBBoxCoord = (gcu_PMVMatrix01[1] * gca_Vertices).xyz; // Mv +#ifdef USE_FRUSTUM_CLIPPING + gcv_ClipCoord = (gcu_PMVMatrix01[1] * gca_Vertices).xyz; // Mv #endif #ifdef USE_COLOR_TEXTURE diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/functions.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/functions.glsl index 41e65178e..3b36b021a 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/functions.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/functions.glsl @@ -75,12 +75,30 @@ vec4 clip_coord(vec4 col_in, vec4 col_ex, vec3 coord, vec3 low, vec3 high) { * </p> */ float is_inside(vec2 coord, vec2 low, vec2 high) { - return v_mul( step(low, coord) ) * ( 1 - v_or( step(high+EPSILON, coord) ) ); + return v_mul( step(low-EPSILON, coord) ) * ( 1 - v_or( step(high+EPSILON, coord) ) ); } /** Branch-less clipping test using vec3 coordinates and low/high clipping. */ float is_inside(vec3 coord, vec3 low, vec3 high) { - return v_mul( step(low, coord) ) * ( 1 - v_or( step(high+EPSILON, coord) ) ); + return v_mul( step(low-EPSILON, coord) ) * ( 1 - v_or( step(high+EPSILON, coord) ) ); } +/** Return distance of plane {n, d} to given point p. */ +float planeDistance(vec3 n, float d, vec3 p) { + return dot(n, p) + d; +} + +#ifdef USE_FRUSTUM_CLIPPING + +bool isOutsideMvFrustum(vec3 p) { + return planeDistance(gcu_ClipFrustum[0].xyz, gcu_ClipFrustum[0].w, p) < 0 || + planeDistance(gcu_ClipFrustum[1].xyz, gcu_ClipFrustum[1].w, p) < 0 || + planeDistance(gcu_ClipFrustum[2].xyz, gcu_ClipFrustum[2].w, p) < 0 || + planeDistance(gcu_ClipFrustum[3].xyz, gcu_ClipFrustum[3].w, p) < 0 || + planeDistance(gcu_ClipFrustum[4].xyz, gcu_ClipFrustum[4].w, p) < 0 || + planeDistance(gcu_ClipFrustum[5].xyz, gcu_ClipFrustum[5].w, p) < 0; +} + +#endif // USE_FRUSTUM_CLIPPING + #endif // functions_glsl diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl index a9554528c..18c563fbb 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl @@ -10,8 +10,8 @@ uniform float gcu_Weight; #ifdef USE_COLOR_TEXTURE uniform vec2 gcu_ColorTexBBox[3]; // box-min[2], box-max[2] and tex-size[2] #endif -#ifdef USE_AABBOX_CLIPPING - uniform vec3 gcu_ClipBBox[2]; // box-min[3], box-max[3] +#ifdef USE_FRUSTUM_CLIPPING + uniform vec4 gcu_ClipFrustum[6]; // L, R, B, T, N, F each {n.x, n.y, n.z, d} #endif uniform mat4 gcu_PMVMatrix02[3]; // P, Mv, and Mvi diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl index 0e8d5b843..6139c9d8f 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl @@ -10,8 +10,8 @@ varying vec2 gcv_FboTexCoord; #ifdef USE_COLOR_TEXTURE varying vec2 gcv_ColorTexCoord; #endif -#ifdef USE_AABBOX_CLIPPING - varying vec3 gcv_ClipBBoxCoord; +#ifdef USE_FRUSTUM_CLIPPING + varying vec3 gcv_ClipCoord; #endif #ifdef USE_COLOR_CHANNEL |