diff options
Diffstat (limited to 'src')
19 files changed, 587 insertions, 183 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid00.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid00.java new file mode 100644 index 000000000..fbe62c675 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid00.java @@ -0,0 +1,319 @@ +/** + * Copyright 2010-2023 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.demos.graph.ui; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.jogamp.common.net.Uri; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.font.FontScale; +import com.jogamp.graph.ui.Group; +import com.jogamp.graph.ui.Scene; +import com.jogamp.graph.ui.Shape; +import com.jogamp.graph.ui.layout.Alignment; +import com.jogamp.graph.ui.layout.Gap; +import com.jogamp.graph.ui.layout.GridLayout; +import com.jogamp.graph.ui.shapes.MediaButton; +import com.jogamp.math.Vec2i; +import com.jogamp.math.Vec4f; +import com.jogamp.math.geom.AABBox; +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +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.GLCapabilities; +import com.jogamp.opengl.GLCapabilitiesImmutable; +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; +import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayer.EventMask; +import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; +import com.jogamp.opengl.util.av.GLMediaPlayerFactory; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; + +/** + * MediaButtons in a grid, filled by media files from a directory in different aspect ratios + */ +public class UIMediaGrid00 { + static CommandlineOptions options = new CommandlineOptions(1920, 1080, Region.VBAA_RENDERING_BIT); + + public static int aid = GLMediaPlayer.STREAM_ID_AUTO; + + public static void main(final String[] args) throws IOException { + final List<Uri> mediaFiles = new ArrayList<Uri>(); + 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("-file")) { + idx[0]++; + final Uri u = Uri.tryUriOrFile( args[idx[0]] ); + if( null != u ) { + mediaFiles.add(u); + } + } else if(args[idx[0]].equals("-aid")) { + idx[0]++; + aid = MiscUtils.atoi(args[idx[0]], aid); + } else if(args[idx[0]].equals("-mute")) { + aid = GLMediaPlayer.STREAM_ID_NONE; + } + } + } + System.err.println(options); + System.err.println("aid "+aid); + + if( 0 == mediaFiles.size() ) { + System.err.println("No media files, exit."); + return; + } + for(final Uri uri : mediaFiles) { + System.err.println("- "+uri); + } + final Vec2i gridDim = new Vec2i(4, mediaFiles.size()); + + // final Font fontStatus = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeMono.ttf", FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true); + final Font fontInfo = FontFactory.get(FontFactory.UBUNTU).getDefault(); + + final GLProfile reqGLP = GLProfile.get(options.glProfileName); + System.err.println("GLProfile: "+reqGLP); + + final GLCapabilities caps = new GLCapabilities(reqGLP); + caps.setAlphaBits(4); + if( options.sceneMSAASamples > 0 ) { + caps.setSampleBuffers(true); + caps.setNumSamples(options.sceneMSAASamples); + } + System.out.println("Requested: " + caps); + + final Animator animator = new Animator(0 /* w/o AWT */); + animator.setUpdateFPSFrames(1*60, null); // System.err); + final GLWindow window = GLWindow.create(caps); + window.setSize(options.surface_width, options.surface_height); + window.setTitle(UIMediaGrid00.class.getSimpleName()); + window.setVisible(true); + window.addWindowListener(new WindowAdapter() { + @Override + public void windowResized(final WindowEvent e) { + window.setTitle(FontView01.class.getSimpleName()+": "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight()); + } + @Override + public void windowDestroyNotify(final WindowEvent e) { + animator.stop(); + } + }); + animator.add(window); + + final Scene scene = new Scene(options.graphAASamples); + scene.setClearParams(new float[] { 1f, 1f, 1f, 1f}, GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + scene.setFrustumCullingEnabled(true); + + scene.attachInputListenerTo(window); + window.addGLEventListener(scene); + + + final float[] ppmm = window.getPixelsPerMM(new float[2]); + { + final float[] dpi = FontScale.ppmmToPPI( new float[] { ppmm[0], ppmm[1] } ); + System.err.println("DPI "+dpi[0]+" x "+dpi[1]+", "+ppmm[0]+" x "+ppmm[1]+" pixel/mm"); + + final float[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new float[2]); + System.err.println("HiDPI PixelScale: "+hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); + } + final Group mediaGrid; + { + final float cellWidth = 1f; + final float cellHeight = 1f; + mediaGrid = new Group(new GridLayout(gridDim.x(), cellWidth*0.9f, cellHeight*0.9f, Alignment.FillCenter, new Gap(cellHeight*0.1f, cellWidth*0.1f))); + mediaGrid.setRelayoutOnDirtyShapes(false); + } + addMedia(reqGLP, fontInfo, mediaGrid, gridDim, mediaFiles, null); + mediaGrid.validate(reqGLP); + System.err.println("MediaGrid "+mediaGrid); + System.err.println("MediaGrid "+mediaGrid.getLayout()); + + final Group mainGrid = new Group(new GridLayout(1, 0f, 0f, Alignment.None)); + mainGrid.addShape(mediaGrid); + scene.addShape(mainGrid); + + window.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(final KeyEvent e) { + final short keySym = e.getKeySymbol(); + if( keySym == KeyEvent.VK_S ) { + printScreenOnGLThread(scene, window.getChosenGLCapabilities()); + } else if( keySym == KeyEvent.VK_DOWN ) { + } else if( keySym == KeyEvent.VK_PAGE_DOWN ) { + } else if( keySym == KeyEvent.VK_UP ) { + } else if( keySym == KeyEvent.VK_PAGE_UP ) { + } else if( keySym == KeyEvent.VK_F4 || keySym == KeyEvent.VK_ESCAPE || keySym == KeyEvent.VK_Q ) { + MiscUtils.destroyWindow(window); + } else if( keySym == KeyEvent.VK_SPACE ) { + final Shape a = scene.getActiveShape(); + if( a instanceof MediaButton ) { + final MediaButton b = (MediaButton)a; + final GLMediaPlayer mPlayer = b.getGLMediaPlayer(); + if( GLMediaPlayer.State.Paused == mPlayer.getState() ) { + mPlayer.resume(); + } else if(GLMediaPlayer.State.Uninitialized == mPlayer.getState()) { + mPlayer.playStream(mPlayer.getUri(), GLMediaPlayer.STREAM_ID_AUTO, aid, MediaTexCount); + } else if( e.isShiftDown() ) { + mPlayer.stop(); + } else { + mPlayer.pause(false); + } + } + } + } + }); + + animator.start(); + scene.waitUntilDisplayed(); + { + final AABBox sceneBox = scene.getBounds(); + final AABBox mainGridBox = mainGrid.getBounds(); + final float sx = sceneBox.getWidth() / mainGridBox.getWidth(); + final float sy = sceneBox.getHeight() / mainGridBox.getHeight(); + final float sxy = Math.min(sx, sy); + System.err.println("SceneBox "+sceneBox); + System.err.println("MainGridBox "+mainGridBox); + System.err.println("scale sx "+sx+", sy "+sy+", sxy "+sxy); + // scale, moveTo origin bottom-left, then move up to top-left corner. + mainGrid.scale(sxy, sxy, 1f).moveTo(sceneBox.getLow()).move(0, sceneBox.getHeight()-mainGridBox.getHeight()*sxy, 0); + } + printScreenOnGLThread(scene, window.getChosenGLCapabilities()); + // stay open .. + } + static void printScreenOnGLThread(final Scene scene, final GLCapabilitiesImmutable caps) { + scene.screenshot(true, scene.nextScreenshotFile(null, UIMediaGrid00.class.getSimpleName(), options.renderModes, caps, "media")); + } + + public static final int MediaTexUnitMediaPlayer = 1; + public static final int MediaTexCount = 3; // GLMediaPlayer.TEXTURE_COUNT_DEFAULT + + public static MediaButton createMediaButton(final Uri medium, final float aratio, final boolean letterBox, final Shape.MouseGestureListener mouseListener) { + final float borderSz = 0.02f; + final Vec4f borderToggleOff = new Vec4f(0, 0, 0, 0.7f); + final Vec4f borderToggleOn = new Vec4f(0, 0, 1, 0.7f); + final Vec4f borderActive = new Vec4f(1, 1, 0, 0.7f); + + final GLMediaPlayer mPlayer = GLMediaPlayerFactory.createDefault(); + mPlayer.setTextureUnit(MediaTexUnitMediaPlayer); + // mPlayer.setAudioChannelLimit(1); // enforce mono to enjoy spatial 3D position effects + final MediaButton button = new MediaButton(options.renderModes, aratio, 1, mPlayer); + button.setVerbose(false).addDefaultEventListener().setTextureLetterbox(letterBox).setFixedARatioResize(true); + if( aid == GLMediaPlayer.STREAM_ID_NONE ) { + button.setToggle( true ); // toggle == false -> mute audio + } else { + button.setToggleable(true); + button.setToggle(false); // toggle == false -> mute audio + } + mPlayer.setAudioVolume( 0f ); + if( null != mouseListener ) { + button.addMouseListener(mouseListener); + } + button.onToggle( (final Shape s) -> { + mPlayer.setAudioVolume( s.isToggleOn() ? 1f : 0f ); + if( s.isActive() ) { + s.setBorderColor(borderActive); + } else { + if( s.isToggleOn() ) { + s.setBorderColor(borderToggleOn); + } else { + s.setBorderColor(borderToggleOff); + } + } + }); + button.onActivation( (final Shape s) -> { + System.err.println("XXX "+s); + if( s.isActive() ) { + s.setBorderColor(borderActive); + } else { + if( s.isToggleOn() ) { + s.setBorderColor(borderToggleOn); + } else { + s.setBorderColor(borderToggleOff); + } + } + }); + mPlayer.addEventListener( new GLMediaEventListener() { + @Override + public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) { } + + @Override + public void attributesChanged(final GLMediaPlayer mp, final EventMask eventMask, final long when) { + // System.err.println("MediaButton AttributesChanges: "+eventMask+", when "+when); + // System.err.println("MediaButton State: "+mp); + if( eventMask.isSet(GLMediaPlayer.EventMask.Bit.Init) ) { + System.err.println(mp.toString()); + } + if( eventMask.isSet(GLMediaPlayer.EventMask.Bit.EOS) ) { + final StreamException err = mp.getStreamException(); + if( null != err ) { + System.err.println("MovieSimple State: Exception: "+err.getMessage()); + } else { + new InterruptSource.Thread() { + @Override + public void run() { + mp.setPlaySpeed(1f); + mp.seek(0); + mp.resume(); + } + }.start(); + } + } + } + }); + button.setToggleOffColorMod(1f, 1f, 1f, 1f); + button.setPressedColorMod(1f, 1f, 1f, 0.85f); + button.setPerp().setBorderColor(borderToggleOff).setBorder(borderSz); + mPlayer.playStream(medium, GLMediaPlayer.STREAM_ID_AUTO, aid, MediaTexCount); + return button; + } + + static void addMedia(final GLProfile glp, final Font font, final Group grid, + final Vec2i gridDim, final List<Uri> mediaFiles, + final Shape.MouseGestureListener mouseListener) { + for(final Uri medium : mediaFiles) { + grid.addShape( createMediaButton(medium, 16f/9f, false, mouseListener) ); + grid.addShape( createMediaButton(medium, 4f/3f, false, mouseListener) ); + grid.addShape( createMediaButton(medium, 16f/9f, true, mouseListener) ); + grid.addShape( createMediaButton(medium, 4f/3f, true, mouseListener) ); + } + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java index df85e8ccf..95c8d3a38 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java @@ -35,7 +35,6 @@ import java.util.Arrays; import java.util.List; import com.jogamp.common.net.Uri; -import com.jogamp.common.util.InterruptSource; import com.jogamp.graph.curve.Region; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; @@ -47,13 +46,10 @@ import com.jogamp.graph.ui.layout.Alignment; import com.jogamp.graph.ui.layout.Gap; import com.jogamp.graph.ui.layout.GridLayout; import com.jogamp.graph.ui.shapes.MediaButton; -import com.jogamp.math.FloatUtil; import com.jogamp.math.Vec2i; -import com.jogamp.math.Vec3f; import com.jogamp.math.geom.AABBox; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; -import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; @@ -65,11 +61,6 @@ import com.jogamp.opengl.demos.util.CommandlineOptions; import com.jogamp.opengl.demos.util.MiscUtils; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.av.GLMediaPlayer; -import com.jogamp.opengl.util.av.GLMediaPlayer.EventMask; -import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; -import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; -import com.jogamp.opengl.util.av.GLMediaPlayerFactory; -import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; /** * MediaButtons in a grid, filled by media files from a directory. @@ -77,11 +68,13 @@ import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; public class UIMediaGrid01 { static CommandlineOptions options = new CommandlineOptions(1920, 1080, Region.VBAA_RENDERING_BIT); - public static final List<String> MEDIA_SUFFIXES = Arrays.asList("mp4", "mkv"); + public static final List<String> MEDIA_SUFFIXES = Arrays.asList("mp4", "mkv", "m2v", "avi"); public static int aid = GLMediaPlayer.STREAM_ID_AUTO; + public static float boxRatio = 16f/9f; + public static boolean letterBox = true; public static void main(final String[] args) throws IOException { - int maxMediaFiles = Integer.MAX_VALUE; + int maxMediaFiles = 12; // Integer.MAX_VALUE; String mediaDir = null; if( 0 != args.length ) { final int[] idx = { 0 }; @@ -99,11 +92,21 @@ public class UIMediaGrid01 { aid = MiscUtils.atoi(args[idx[0]], aid); } else if(args[idx[0]].equals("-mute")) { aid = GLMediaPlayer.STREAM_ID_NONE; + } else if(args[idx[0]].equals("-ratio")) { + idx[0]++; + boxRatio = MiscUtils.atof(args[idx[0]], boxRatio); + } else if(args[idx[0]].equals("-zoom")) { + letterBox = false; } } } System.err.println(options); System.err.println("mediaDir "+mediaDir); + System.err.println("maxMediaFiles "+maxMediaFiles); + System.err.println("aid "+aid); + System.err.println("boxRatio "+boxRatio); + System.err.println("letterBox "+letterBox); + final List<Uri> mediaFiles = new ArrayList<Uri>(); if( null != mediaDir && mediaDir.length() > 0 ) { final File dir = new File(mediaDir); @@ -201,11 +204,12 @@ public class UIMediaGrid01 { } final Group mediaGrid; { - final float cellWidth = 16.0f/9.0f; + final float cellWidth = boxRatio; final float cellHeight = 1f; mediaGrid = new Group(new GridLayout(gridDim.x(), cellWidth*0.9f, cellHeight*0.9f, Alignment.FillCenter, new Gap(cellHeight*0.1f, cellWidth*0.1f))); + mediaGrid.setRelayoutOnDirtyShapes(false); } - addMedia(reqGLP, fontInfo, mediaGrid, gridDim, mediaFiles, 16.0f/9.0f, null); + addMedia(reqGLP, fontInfo, mediaGrid, gridDim, mediaFiles, boxRatio, null); mediaGrid.validate(reqGLP); System.err.println("MediaGrid "+mediaGrid); System.err.println("MediaGrid "+mediaGrid.getLayout()); @@ -234,7 +238,7 @@ public class UIMediaGrid01 { if( GLMediaPlayer.State.Paused == mPlayer.getState() ) { mPlayer.resume(); } else if(GLMediaPlayer.State.Uninitialized == mPlayer.getState()) { - mPlayer.playStream(mPlayer.getUri(), GLMediaPlayer.STREAM_ID_AUTO, aid, MediaTexCount); + mPlayer.playStream(mPlayer.getUri(), GLMediaPlayer.STREAM_ID_AUTO, aid, UIMediaGrid00.MediaTexCount); } else if( e.isShiftDown() ) { mPlayer.stop(); } else { @@ -266,95 +270,11 @@ public class UIMediaGrid01 { scene.screenshot(true, scene.nextScreenshotFile(null, UIMediaGrid01.class.getSimpleName(), options.renderModes, caps, "media")); } - private static final int MediaTexUnitMediaPlayer = 1; - private static final int MediaTexCount = 3; // GLMediaPlayer.TEXTURE_COUNT_DEFAULT - static void addMedia(final GLProfile glp, final Font font, final Group grid, final Vec2i gridDim, final List<Uri> mediaFiles, final float defRatio, final Shape.MouseGestureListener mouseListener) { for(final Uri medium : mediaFiles) { - final GLMediaPlayer mPlayer = GLMediaPlayerFactory.createDefault(); - mPlayer.setTextureUnit(MediaTexUnitMediaPlayer); - // mPlayer.setAudioChannelLimit(1); // enforce mono to enjoy spatial 3D position effects - final MediaButton button = new MediaButton(options.renderModes, defRatio, 1, mPlayer); - button.setVerbose(false).addDefaultEventListener().setFixedARatioResize(true); - if( aid == GLMediaPlayer.STREAM_ID_NONE ) { - button.setToggle( true ); // toggle == false -> mute audio - } else { - button.setToggleable(true); - button.setToggle(false); // toggle == false -> mute audio - button.setToggleOffColorMod(0.80f, 0.80f, 0.95f, 1.0f); - } - mPlayer.setAudioVolume( 0f ); - if( null != mouseListener ) { - button.addMouseListener(mouseListener); - } - button.onToggle( (final Shape s) -> { - mPlayer.setAudioVolume( s.isToggleOn() ? 1f : 0f ); - }); - mPlayer.addEventListener( new GLMediaEventListener() { - @Override - public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) { } - - @Override - public void attributesChanged(final GLMediaPlayer mp, final EventMask eventMask, final long when) { - // System.err.println("MediaButton AttributesChanges: "+eventMask+", when "+when); - // System.err.println("MediaButton State: "+mp); - if( eventMask.isSet(GLMediaPlayer.EventMask.Bit.Init) ) { - System.err.println(mp.toString()); - } - if( eventMask.isSet(GLMediaPlayer.EventMask.Bit.EOS) ) { - final StreamException err = mp.getStreamException(); - if( null != err ) { - System.err.println("MovieSimple State: Exception: "+err.getMessage()); - } else { - new InterruptSource.Thread() { - @Override - public void run() { - mp.setPlaySpeed(1f); - mp.seek(0); - mp.resume(); - } - }.start(); - } - } - } - }); - button.setPerp().setBorderColor(0, 0, 0, 1).setBorder(0.01f); - grid.addShape(button); - mPlayer.playStream(medium, GLMediaPlayer.STREAM_ID_AUTO, aid, MediaTexCount); + grid.addShape( UIMediaGrid00.createMediaButton(medium, defRatio, letterBox, mouseListener) ); } } - - /** - * We can share this instance w/ all UI elements, - * since only mouse action / gesture is complete for a single one (press, drag, released and click). - */ - private final Shape.MouseGestureAdapter dragZoomRotateListener = new Shape.MouseGestureAdapter() { - MediaButton zoomed = null; - - @Override - public void mousePressed(final MouseEvent e) { - zoomed = null; - } - @Override - public void mouseReleased(final MouseEvent e) { - zoomed = null; - } - - @Override - public void mouseDragged(final MouseEvent e) { - final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); - } - - @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 ) ); - } - }; - } diff --git a/src/graphui/classes/com/jogamp/graph/ui/shapes/GLButton.java b/src/graphui/classes/com/jogamp/graph/ui/shapes/GLButton.java index a8d7c4295..d5a192456 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/shapes/GLButton.java +++ b/src/graphui/classes/com/jogamp/graph/ui/shapes/GLButton.java @@ -76,7 +76,7 @@ public class GLButton extends TexSeqButton { this.glel = glel; this.useAlpha = useAlpha; - setColor(1.0f, 1.0f, 1.0f, 1.0f); + setColor(1.0f, 1.0f, 1.0f, 0.0f); setPressedColorMod(0.9f, 0.9f, 0.9f, 0.7f); setToggleOffColorMod(0.8f, 0.8f, 0.8f, 1.0f); setToggleOnColorMod(1.0f, 1.0f, 1.0f, 1.0f); diff --git a/src/graphui/classes/com/jogamp/graph/ui/shapes/ImageButton.java b/src/graphui/classes/com/jogamp/graph/ui/shapes/ImageButton.java index cd919546d..d8c79d8e7 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/shapes/ImageButton.java +++ b/src/graphui/classes/com/jogamp/graph/ui/shapes/ImageButton.java @@ -55,7 +55,7 @@ public class ImageButton extends TexSeqButton { final float height, final ImageSequence texSeq) { super(renderModes, width, height, texSeq); - setColor(1f, 1f, 1f, 1.0f); + setColor(1f, 1f, 1f, 0.0f); setPressedColorMod(0.9f, 0.9f, 0.9f, 0.9f); setToggleOffColorMod(1f, 1f, 1f, 1f); setToggleOnColorMod(0.8f, 0.8f, 0.8f, 1f); diff --git a/src/graphui/classes/com/jogamp/graph/ui/shapes/MediaButton.java b/src/graphui/classes/com/jogamp/graph/ui/shapes/MediaButton.java index b73f224d1..ed44324de 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/shapes/MediaButton.java +++ b/src/graphui/classes/com/jogamp/graph/ui/shapes/MediaButton.java @@ -68,7 +68,7 @@ public class MediaButton extends TexSeqButton { final float height, final GLMediaPlayer mPlayer) { super(renderModes, width, height, mPlayer); - setColor(1.0f, 1.0f, 1.0f, 1.0f); + setColor(1.0f, 1.0f, 1.0f, 0.0f); setPressedColorMod(0.9f, 0.9f, 0.9f, 0.7f); setToggleOffColorMod(0.8f, 0.8f, 0.8f, 1.0f); setToggleOnColorMod(1.0f, 1.0f, 1.0f, 1.0f); diff --git a/src/graphui/classes/com/jogamp/graph/ui/shapes/TexSeqButton.java b/src/graphui/classes/com/jogamp/graph/ui/shapes/TexSeqButton.java index 0dbd11adf..de5c43be1 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/shapes/TexSeqButton.java +++ b/src/graphui/classes/com/jogamp/graph/ui/shapes/TexSeqButton.java @@ -55,6 +55,19 @@ public abstract class TexSeqButton extends BaseButton { public final TextureSequence getTextureSequence() { return this.texSeq; } + /** + * Sets a renderMode {@link Region#COLORTEXTURE_LETTERBOX_RENDERING_BIT} on or off. + * @return this instance for chaining + */ + public TexSeqButton setTextureLetterbox(final boolean v) { + if( getTextureLetterbox() != v ) { + renderModes = Region.setRenderMode(renderModes, Region.COLORTEXTURE_LETTERBOX_RENDERING_BIT, v); + markShapeDirty(); + } + return this; + } + public boolean getTextureLetterbox() { return Region.isColorTextureLetterbox(renderModes); } + @Override protected void addShapeToRegion(final GLProfile glp, final GL2ES2 gl) { final OutlineShape shape = createBaseShape(0f); diff --git a/src/jogl/classes/com/jogamp/graph/curve/Region.java b/src/jogl/classes/com/jogamp/graph/curve/Region.java index 93b05aefa..5f78283ed 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/Region.java +++ b/src/jogl/classes/com/jogamp/graph/curve/Region.java @@ -127,9 +127,21 @@ public abstract class Region { * <p> * If set, a color texture is used to determine the color. * </p> + * @see #COLORTEXTURE_LETTERBOX_RENDERING_BIT */ public static final int COLORTEXTURE_RENDERING_BIT = 1 << 10; + /** + * Rendering-Mode bit for {@link #getRenderModes() Region} + * <p> + * If set, a used {@link #COLORTEXTURE_RENDERING_BIT} color texture is added letter-box space to match aspect-ratio, otherwise it will be zoomed in. + * </p> + * <p> + * Note that {@link #COLORTEXTURE_RENDERING_BIT} must also be set to even enable color texture. + * </p> + */ + public static final int COLORTEXTURE_LETTERBOX_RENDERING_BIT = 1 << 11; + /** Default maximum {@link #getQuality() quality}, {@value}. */ public static final int MAX_QUALITY = 1; @@ -147,6 +159,9 @@ public abstract class Region { protected final AABBox box = new AABBox(); protected Frustum frustum = null; + public static final boolean isRenderModeSet(final int renderModes, final int mask) { return mask == ( renderModes & mask ); } + public static final int setRenderMode(int renderModes, final int mask, final boolean v) { if( v ) { renderModes |= mask; } else { renderModes &= ~mask; }; return renderModes; } + /** Returns true if given {@code renderModes} has {@link Region#VBAA_RENDERING_BIT} set. */ public static boolean isVBAA(final int renderModes) { return 0 != (renderModes & Region.VBAA_RENDERING_BIT); @@ -194,6 +209,11 @@ public abstract class Region { return 0 != (renderModes & Region.COLORTEXTURE_RENDERING_BIT); } + /** Returns true if given {@code renderModes} has {@link Region#COLORTEXTURE_LETTERBOX_RENDERING_BIT} set. */ + public static boolean isColorTextureLetterbox(final int renderModes) { + return 0 != ( renderModes & Region.COLORTEXTURE_LETTERBOX_RENDERING_BIT ); + } + /** * Returns a unique technical description string for renderModes as follows: * <pre> @@ -204,7 +224,16 @@ public abstract class Region { public static String getRenderModeString(final int renderModes) { final String curveS = hasVariableWeight(renderModes) ? "-curve" : ""; final String cChanS = hasColorChannel(renderModes) ? "-cols" : ""; - final String cTexS = hasColorTexture(renderModes) ? "-ctex" : ""; + final String cTexS; + if( hasColorTexture(renderModes) ) { + if( Region.isColorTextureLetterbox(renderModes) ) { + cTexS = "-ctex_lbox"; + } else { + cTexS = "-ctex_zoom"; + } + } else { + cTexS = ""; + } if( Region.isVBAA(renderModes) ) { return "vbaa"+curveS+cChanS+cTexS; } else if( Region.isMSAA(renderModes) ) { @@ -299,6 +328,8 @@ public abstract class Region { box.reset(); } + public final boolean isRenderModeSet(final int mask) { return mask == ( renderModes & mask ); } + /** * Returns true if capable of two pass rendering - VBAA, otherwise false. * @see #getRenderModes() @@ -340,11 +371,16 @@ public abstract class Region { * i.e. the bit {@link #COLORTEXTURE_RENDERING_BIT} is set, * otherwise false. * @see #getRenderModes() + * @see #isColorTextureLetterbox() */ public final boolean hasColorTexture() { return Region.hasColorTexture(renderModes); } + /** Returns true if given {@code renderModes} has {@link Region#COLORTEXTURE_LETTERBOX_RENDERING_BIT} set. */ + public final boolean isColorTextureLetterbox() { + return Region.isColorTextureLetterbox(renderModes); + } /** See {@link #setFrustum(Frustum)} */ public final Frustum getFrustum() { return frustum; } 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 7e3a7ff30..0927c41cb 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -631,6 +631,7 @@ public final class RegionRenderer { } try { + 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"); } catch (final IOException ioe) { diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java index 17fcc7016..b4fd0cc1e 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java @@ -78,20 +78,16 @@ public class TextureCoords { return d; } - /** Returns the leftmost (x) texture coordinate of this - rectangle. */ + /** Returns the leftmost (x) texture coordinate of this rectangle. */ public float left() { return left; } - /** Returns the rightmost (x) texture coordinate of this - rectangle. */ + /** Returns the rightmost (x) texture coordinate of this rectangle. */ public float right() { return right; } - /** Returns the bottommost (y) texture coordinate of this - rectangle. */ + /** Returns the bottommost (y) texture coordinate of this rectangle. */ public float bottom() { return bottom; } - /** Returns the topmost (y) texture coordinate of this - rectangle. */ + /** Returns the topmost (y) texture coordinate of this rectangle. */ public float top() { return top; } @Override diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java index 1e308b215..7c924864a 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java @@ -33,6 +33,7 @@ import com.jogamp.opengl.GLRunnable; import com.jogamp.opengl.GLEventListener; import com.jogamp.common.av.TimeFrameI; +import com.jogamp.math.geom.AABBox; /** * Protocol for texture sequences, like animations, movies, etc. @@ -303,4 +304,114 @@ public interface TextureSequence { * @see #getTextureLookupFragmentShaderImpl() */ public int getTextureFragmentShaderHashCode(); + + /** + * Calculates the texture coordinates bounding box while correcting for aspect-ratio. + * @param tex the {@link Texture} + * @param box the {@Link AABBpx} of the destination + * @param letterBox true to produce letter-box space to match aspect-ratio, otherwise will zoom in + * @param colorTexBBox destination float[6] array for the following three texture-coordinate tuples: minX/minY, maxX/maxY, texW/texH + */ + @SuppressWarnings("unused") + public static void setTexCoordBBox(final Texture tex, final AABBox box, final boolean letterBox, final float[] colorTexBBox) { + final TextureCoords tc = tex.getImageTexCoords(); + final float boxRatio = box.getWidth() / box.getHeight(); + final float imgRatio = tex.getAspectRatio(); + final float box2ImgRatio = boxRatio / imgRatio; + final float tcW = tc.right() - tc.left(); + final float tcH; + float boxWidthCut=0, boxHeightCut=0, boxWidthExt=0, boxHeightExt=0; + if( box2ImgRatio >= 1.0f ) { + if( letterBox ) { + boxWidthCut = box.getWidth() * ( 1f - 1f / box2ImgRatio ); + final float tcWH = tcW * 0.5f; + final float boxWidthCutL = boxWidthCut * tcWH; + final float boxWidthCutR = boxWidthCut * ( 1f - tcWH ); + colorTexBBox[0] = ( box.getMinX() + boxWidthCutL ) / tcW; + colorTexBBox[2] = ( box.getMaxX() - boxWidthCutR ) / tcW; + if( tex.getMustFlipVertically() ) { + tcH = tc.bottom() - tc.top(); + colorTexBBox[1] = box.getMaxY() / tcH; + colorTexBBox[3] = box.getMinY() / tcH; + } else { + tcH = tc.top() - tc.bottom(); + colorTexBBox[1] = box.getMinY() / tcH; + colorTexBBox[3] = box.getMaxY() / tcH; + } + } else { + colorTexBBox[0] = box.getMinX() / tcW; + colorTexBBox[2] = box.getMaxX() / tcW; + boxHeightExt = box.getHeight() * ( box2ImgRatio - 1f ); + if( tex.getMustFlipVertically() ) { + tcH = tc.bottom() - tc.top(); + final float tcHH = tcH * 0.5f; + final float boxHeightExtB = boxHeightExt * tcHH; + final float boxHeightExtT = boxHeightExt * ( 1f - tcHH ); + colorTexBBox[1] = ( box.getMaxY() + boxHeightExtT ) / tcH; + colorTexBBox[3] = ( box.getMinY() - boxHeightExtB ) / tcH; + } else { + tcH = tc.top() - tc.bottom(); + final float tcHH = tcH * 0.5f; + final float boxHeightExtB = boxHeightExt * tcHH; + final float boxHeightExtT = boxHeightExt * ( 1f - tcHH ); + colorTexBBox[1] = ( box.getMinY() - boxHeightExtB ) / tcH; + colorTexBBox[3] = ( box.getMaxY() + boxHeightExtT ) / tcH; + } + } + } else { + if( letterBox ) { + colorTexBBox[0] = box.getMinX() / tcW; + colorTexBBox[2] = box.getMaxX() / tcW; + boxHeightCut = box.getHeight() * ( 1f - box2ImgRatio ); + if( tex.getMustFlipVertically() ) { + tcH = tc.bottom() - tc.top(); + final float tcHH = tcH * 0.5f; + final float boxHeightCutB = boxHeightCut * tcHH; + final float boxHeightCutT = boxHeightCut * ( 1f - tcHH ); + colorTexBBox[1] = ( box.getMaxY() - boxHeightCutT ) / tcH; + colorTexBBox[3] = ( box.getMinY() + boxHeightCutB ) / tcH; + } else { + tcH = tc.top() - tc.bottom(); + final float tcHH = tcH * 0.5f; + final float boxHeightCutB = boxHeightCut * tcHH; + final float boxHeightCutT = boxHeightCut * ( 1f - tcHH ); + colorTexBBox[1] = ( box.getMinY() + boxHeightCutB ) / tcH; + colorTexBBox[3] = ( box.getMaxY() - boxHeightCutT ) / tcH; + } + } else { + boxWidthExt = box.getWidth() * ( 1f / box2ImgRatio - 1f ); + final float tcWH = tcW * 0.5f; + final float boxWidthExtL = boxWidthExt * tcWH; + final float boxWidthExtR = boxWidthExt * ( 1f - tcWH ); + colorTexBBox[0] = ( box.getMinX() - boxWidthExtL ) / tcW; + colorTexBBox[2] = ( box.getMaxX() + boxWidthExtR ) / tcW; + if( tex.getMustFlipVertically() ) { + tcH = tc.bottom() - tc.top(); + colorTexBBox[1] = box.getMaxY() / tcH; + colorTexBBox[3] = box.getMinY() / tcH; + } else { + tcH = tc.top() - tc.bottom(); + colorTexBBox[1] = box.getMinY() / tcH; + colorTexBBox[3] = box.getMaxY() / tcH; + } + } + } + colorTexBBox[4] = tcW; + colorTexBBox[5] = tcH; + if( false ) { + final float texWidthRatio = (float)tex.getImageWidth() / (float)tex.getWidth(); + final float texHeightRatio = (float)tex.getImageHeight() / (float)tex.getHeight(); + final float texRatio = ( tc.right() - tc.left() ) / ( tc.bottom() - tc.top() ); + final float box2TexRatio = boxRatio / texRatio; + final float colorTexBBoxW = colorTexBBox[2] - colorTexBBox[0]; + final float colorTexBBoxH = colorTexBBox[3] - colorTexBBox[1]; + System.err.println("XXX"); + System.err.println("XXX ColorTex imgRatio "+imgRatio+", texRatio "+texRatio+", texPixelRatio[w "+texWidthRatio+", h "+texHeightRatio+"], "+tex); + System.err.println("XXX ColorTexBBox lbox "+letterBox+", cut "+boxWidthCut+"/"+boxHeightCut+", ext "+boxWidthExt+"/"+boxHeightExt); + System.err.println("XXX ColorTexBBox min "+colorTexBBox[0]+"/"+colorTexBBox[1]+", max "+colorTexBBox[2]+" x "+colorTexBBox[3]+ + ", dim "+colorTexBBoxW+" x "+colorTexBBoxH+ + ", tc-dim "+tcW+" x "+tcH+", tc "+tc+", box2ImgRatio "+box2ImgRatio+", box2TexRatio "+box2TexRatio); + System.err.println("XXX Box ratio "+boxRatio+", "+box); + } + } } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java index 73af4603d..c5b1e8309 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java @@ -50,7 +50,6 @@ import com.jogamp.opengl.FBObject.Attachment; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.texture.Texture; -import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureSequence; public final class VBORegion2PMSAAES2 extends GLRegion { @@ -61,8 +60,8 @@ public final class VBORegion2PMSAAES2 extends GLRegion { // Pass-1: private final GLUniformData gcu_ColorTexUnit; - private final float[] colorTexBBox; // x0, y0, x1, y1 - private final GLUniformData gcu_ColorTexBBox; + 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 ShaderProgram spPass1 = null; // Pass-2: @@ -97,8 +96,8 @@ public final class VBORegion2PMSAAES2 extends GLRegion { if( hasColorTexture() ) { gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit()); - colorTexBBox = new float[4]; - gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 4, FloatBuffer.wrap(colorTexBBox)); + colorTexBBox = new float[6]; + gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 2, FloatBuffer.wrap(colorTexBBox)); } else { gcu_ColorTexUnit = null; colorTexBBox = null; @@ -148,21 +147,7 @@ public final class VBORegion2PMSAAES2 extends GLRegion { vpc_ileave.enableBuffer(gl, false); if( hasColorTexture && null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) { - final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture(); - final Texture tex = frame.getTexture(); - final TextureCoords tc = tex.getImageTexCoords(); - final float tcSx = 1f / ( tc.right() - tc.left() ); - colorTexBBox[0] = box.getMinX() * tcSx; - colorTexBBox[2] = box.getMaxX() * tcSx; - if( tex.getMustFlipVertically() ) { - final float tcSy = 1f / ( tc.bottom() - tc.top() ); - colorTexBBox[1] = box.getMaxY() * tcSy; - colorTexBBox[3] = box.getMinY() * tcSy; - } else { - final float tcSy = 1f / ( tc.top() - tc.bottom() ); - colorTexBBox[1] = box.getMinY() * tcSy; - colorTexBBox[3] = box.getMaxY() * tcSy; - } + TextureSequence.setTexCoordBBox(colorTexSeq.getLastTexture().getTexture(), box, isColorTextureLetterbox(), colorTexBBox); } gca_FboVerticesAttr.seal(gl, false); { diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java index 9fad72881..b05a04802 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java @@ -53,7 +53,6 @@ import com.jogamp.opengl.FBObject.TextureAttachment; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.texture.Texture; -import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureSequence; public final class VBORegion2PVBAAES2 extends GLRegion { @@ -94,8 +93,9 @@ public final class VBORegion2PVBAAES2 extends GLRegion { // Pass-1: private final GLUniformData gcu_ColorTexUnit; - private final float[] colorTexBBox; // x0, y0, x1, y1 - private final GLUniformData gcu_ColorTexBBox; + 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 ShaderProgram spPass1 = null; // Pass-2: @@ -193,8 +193,8 @@ public final class VBORegion2PVBAAES2 extends GLRegion { if( hasColorTexture() ) { gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit()); - colorTexBBox = new float[4]; - gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 4, FloatBuffer.wrap(colorTexBBox)); + colorTexBBox = new float[6]; + gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 2, FloatBuffer.wrap(colorTexBBox)); } else { gcu_ColorTexUnit = null; colorTexBBox = null; @@ -235,6 +235,7 @@ public final class VBORegion2PVBAAES2 extends GLRegion { @Override protected void updateImpl(final GL2ES2 gl, final int curRenderModes) { + @SuppressWarnings("unused") final boolean hasColorChannel = Region.hasColorChannel( curRenderModes ); final boolean hasColorTexture = Region.hasColorTexture( curRenderModes ); @@ -244,21 +245,7 @@ public final class VBORegion2PVBAAES2 extends GLRegion { vpc_ileave.seal(gl, true); vpc_ileave.enableBuffer(gl, false); if( hasColorTexture && null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) { - final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture(); - final Texture tex = frame.getTexture(); - final TextureCoords tc = tex.getImageTexCoords(); - final float tcSx = 1f / ( tc.right() - tc.left() ); - colorTexBBox[0] = box.getMinX() * tcSx; - colorTexBBox[2] = box.getMaxX() * tcSx; - if( tex.getMustFlipVertically() ) { - final float tcSy = 1f / ( tc.bottom() - tc.top() ); - colorTexBBox[1] = box.getMaxY() * tcSy; - colorTexBBox[3] = box.getMinY() * tcSy; - } else { - final float tcSy = 1f / ( tc.top() - tc.bottom() ); - colorTexBBox[1] = box.getMinY() * tcSy; - colorTexBBox[3] = box.getMaxY() * tcSy; - } + TextureSequence.setTexCoordBBox(colorTexSeq.getLastTexture().getTexture(), box, isColorTextureLetterbox(), colorTexBBox); } gca_FboVerticesAttr.seal(gl, false); { diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java index a819f9267..634b53fe2 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java @@ -42,7 +42,6 @@ import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.texture.Texture; -import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureSequence; public final class VBORegionSPES2 extends GLRegion { @@ -50,8 +49,8 @@ public final class VBORegionSPES2 extends GLRegion { // Pass-1: private final GLUniformData gcu_ColorTexUnit; - private final float[] colorTexBBox; // x0, y0, x1, y1 - private final GLUniformData gcu_ColorTexBBox; + 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 ShaderProgram spPass1 = null; public VBORegionSPES2(final GLProfile glp, final int renderModes, final TextureSequence colorTexSeq, @@ -65,8 +64,8 @@ public final class VBORegionSPES2 extends GLRegion { if( hasColorTexture() ) { gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit()); - colorTexBBox = new float[4]; - gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 4, FloatBuffer.wrap(colorTexBBox)); + colorTexBBox = new float[6]; + gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 2, FloatBuffer.wrap(colorTexBBox)); } else { gcu_ColorTexUnit = null; colorTexBBox = null; @@ -91,22 +90,7 @@ public final class VBORegionSPES2 extends GLRegion { vpc_ileave.seal(gl, true); vpc_ileave.enableBuffer(gl, false); if( hasColorTexture && null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) { - final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture(); - final Texture tex = frame.getTexture(); - final TextureCoords tc = tex.getImageTexCoords(); - final float tcSx = 1f / ( tc.right() - tc.left() ); - colorTexBBox[0] = box.getMinX() * tcSx; - colorTexBBox[2] = box.getMaxX() * tcSx; - final float tcSy; - if( tex.getMustFlipVertically() ) { - tcSy = 1f / ( tc.bottom() - tc.top() ); - colorTexBBox[1] = box.getMaxY() * tcSy; - colorTexBBox[3] = box.getMinY() * tcSy; - } else { - tcSy = 1f / ( tc.top() - tc.bottom() ); - colorTexBBox[1] = box.getMinY() * tcSy; - colorTexBBox[3] = box.getMaxY() * tcSy; - } + TextureSequence.setTexCoordBBox(colorTexSeq.getLastTexture().getTexture(), box, isColorTextureLetterbox(), colorTexBBox); } indicesBuffer.seal(gl, true); indicesBuffer.enableBuffer(gl, false); 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 447242438..6ff35df85 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,10 +1,15 @@ + // Copyright 2010-2023 JogAmp Community. All rights reserved. if( gcv_CurveParam.x == 0.0 && gcv_CurveParam.y == 0.0 ) { // pass-1: Lines #if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL) - mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcv_Color * gcu_ColorStatic; + vec4 t = clip_coord(gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st), vec4(1), gcv_ColorTexCoord, vec2(0), gcv_ColorTexExt); + + mgl_FragColor = vec4( mix( t.rgb * gcu_ColorStatic.rgb, gcv_Color.rgb, gcv_Color.a ), + mix( t.a * gcu_ColorStatic.a, 1, gcv_Color.a) ); #elif defined(USE_COLOR_TEXTURE) - mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcu_ColorStatic; + mgl_FragColor = clip_coord(gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st), vec4(1), gcv_ColorTexCoord, vec2(0), gcv_ColorTexExt) + * gcu_ColorStatic; #elif defined(USE_COLOR_CHANNEL) mgl_FragColor = gcv_Color * gcu_ColorStatic; #else @@ -22,10 +27,13 @@ float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_CurveParam.y), 0.0, 1.0); #if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL) - vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st); - mgl_FragColor = vec4(t.rgb * gcv_Color.rgb * gcu_ColorStatic.rgb, t.a * gcv_Color.a * gcu_ColorStatic.a * a); + vec4 t = clip_coord(gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st), vec4(1), gcv_ColorTexCoord, vec2(0), gcv_ColorTexExt); + + mgl_FragColor = vec4( mix( t.rgb * gcu_ColorStatic.rgb, gcv_Color.rgb, gcv_Color.a ), + a * mix( t.a * gcu_ColorStatic.a, 1, gcv_Color.a) ); #elif defined(USE_COLOR_TEXTURE) - vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st); + vec4 t = clip_coord(gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st), vec4(1), gcv_ColorTexCoord, vec2(0), gcv_ColorTexExt); + mgl_FragColor = vec4(t.rgb * gcu_ColorStatic.rgb, t.a * gcu_ColorStatic.a * a); #elif defined(USE_COLOR_CHANNEL) mgl_FragColor = vec4(gcv_Color.rgb * gcu_ColorStatic.rgb, gcv_Color.a * gcu_ColorStatic.a * a); diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp index c6ed4ca58..de41d9198 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp @@ -1,4 +1,4 @@ -//Copyright 2010 JogAmp Community. All rights reserved. +// Copyright 2010-2023 JogAmp Community. All rights reserved. #if __VERSION__ >= 130 #define attribute in @@ -24,8 +24,9 @@ void main(void) } #endif #ifdef USE_COLOR_TEXTURE - vec2 dim = vec2(gcu_ColorTexBBox.z - gcu_ColorTexBBox.x, gcu_ColorTexBBox.w - gcu_ColorTexBBox.y); - gcv_ColorTexCoord = vec2(gca_Vertices.x - gcu_ColorTexBBox.x, gca_Vertices.y - gcu_ColorTexBBox.y) / dim; + vec2 dim = vec2(gcu_ColorTexBBox[1].x - gcu_ColorTexBBox[0].x, gcu_ColorTexBBox[1].y - gcu_ColorTexBBox[0].y); + gcv_ColorTexCoord = vec2(gca_Vertices.x - gcu_ColorTexBBox[0].x, gca_Vertices.y - gcu_ColorTexBBox[0].y) / dim; + gcv_ColorTexExt = gcu_ColorTexBBox[2]; // texture-size #endif #ifdef USE_COLOR_CHANNEL gcv_Color = gca_Colors; diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp index 05407a4e6..c88619154 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp @@ -1,4 +1,4 @@ -//Copyright 2010 JogAmp Community. All rights reserved. +// Copyright 2010-2023 JogAmp Community. All rights reserved. // // 2-pass shader w/o weight @@ -13,4 +13,3 @@ #endif #define GetSample(texUnit, texCoord, psize, cx, cy, offX, offY) texture2D(texUnit, texCoord + psize * vec2(cx+offX, cy+offY)) - diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/functions.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/functions.glsl new file mode 100644 index 000000000..eeab54ebf --- /dev/null +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/functions.glsl @@ -0,0 +1,42 @@ +// Copyright 2023 JogAmp Community. All rights reserved. + +#ifndef functions_glsl +#define functions_glsl + +/** Returns product of components. */ +float v_mul( vec2 v ) { + return v.x * v.y; +} +/** Returns component wise logical 'or' as float '0' or '1' using the components product and clamp. */ +float v_or( vec2 v ) { + return clamp(v.x * v.y, 0, 1); +} + +/** Returns sum of components. */ +float v_sum( vec2 v ) { + return v.x + v.y; +} +/** Returns component wise logical 'and' as float '0' or '1' using the components sum and clamp. */ +float v_and( vec2 v ) { + return clamp(v.x + v.y, 0, 1); +} + +/** + * Branch-less clipping function. + * <p> + * Returns either 'col_in' if the 'coord' is within ['low'..'high'] range, + * otherwise 'col_ex'. + * </p> + * <p> + * This is achieved via the build-in 'step' and 'mix' function + * as well as our own 'v_mul' and v_and' function, + * which flattens a 'vec2' to one float suitable to be used as the 'mix' criteria. + * </p> + */ +vec4 clip_coord(vec4 col_in, vec4 col_ex, vec2 coord, vec2 low, vec2 high) { + vec4 c = mix( col_ex, col_in, v_mul( step(low, coord) )); + return mix( c, col_ex, v_and( step(high, coord) )); +} + +#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 cd014b732..956c31d4b 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl @@ -7,7 +7,7 @@ uniform vec4 gcu_ColorStatic; uniform float gcu_Weight; #ifdef USE_COLOR_TEXTURE - uniform vec4 gcu_ColorTexBBox; + uniform vec2 gcu_ColorTexBBox[3]; // box-min[2], box-max[2] and tex-size[2] #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 265ab6915..a64b8ad4d 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl @@ -8,11 +8,13 @@ varying vec2 gcv_FboTexCoord; #ifdef USE_COLOR_TEXTURE varying vec2 gcv_ColorTexCoord; + varying vec2 gcv_ColorTexExt; #endif #ifdef USE_COLOR_CHANNEL varying vec4 gcv_Color; #endif + #endif // varyings_glsl |