aboutsummaryrefslogtreecommitdiffstats
path: root/src/test/com/jogamp
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/com/jogamp')
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java515
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp432
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp280
3 files changed, 1227 insertions, 0 deletions
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java
new file mode 100644
index 000000000..f484dbf72
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java
@@ -0,0 +1,515 @@
+/**
+ * Copyright 2011 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.test.junit.jogl.demos.es2;
+
+import java.nio.*;
+
+import javax.media.opengl.*;
+import javax.media.opengl.glu.*;
+
+import com.jogamp.common.nio.*;
+import com.jogamp.newt.opengl.*;
+import com.jogamp.opengl.util.*;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+import static javax.media.opengl.GL2ES2.*;
+
+/**
+ ** __ __|_ ___________________________________________________________________________ ___|__ __
+ ** // /\ _ /\ \\
+ ** //____/ \__ __ _____ _____ _____ _____ _____ | | __ _____ _____ __ __/ \____\\
+ ** \ \ / / __| | | __| _ | | _ | | | __| | | __| | /\ \ / /
+ ** \____\/_/ | | | | | | | | | | | __| | | | | | | | | | |__ " \_\/____/
+ ** /\ \ |_____|_____|_____|__|__|_|_|_|__| | | |_____|_____|_____|_____| _ / /\
+ ** / \____\ http://jogamp.org |_| /____/ \
+ ** \ / "' _________________________________________________________________________ `" \ /
+ ** \/____. .____\/
+ **
+ ** JOGL2 port of my PC 4k intro competition entry for Revision 2011. Sure it got a little bigger
+ ** while porting but the shader and control code remained more or less untouched. The intro renders
+ ** a fullscreen billboard using a single fragment shader. The shader encapsulates basically two
+ ** different routines: A sphere-tracing based raymarcher for a single fractal formula and a bitmap
+ ** orbit trap julia+mandelbrot fractal renderer. Additionally an inline-processing analog-distortion
+ ** filter is applied to all rendered fragments to make the overall look more interesting.
+ **
+ ** The different intro parts are all parameter variations of the two routines in the fragment shader
+ ** synched to the music: Parts 3+5 are obviously the mandelbrot and julia bitmap orbit traps, and parts
+ ** 1,2,4 and 6 are pure fractal sphere tracing.
+ **
+ ** During the development of the intro it turned out that perfectly raymarching every pixel of the orbit
+ ** trapped julia+mandelbrot fractal was way to slow even on highend hardware. So I inserted a lowres
+ ** intermediate FBO to be used by the bitmap based orbit trap routine wich was ofcourse way faster, but
+ ** had the obvious upscaling artefacts. Maybe I'll produce a perfect quality version for very patient
+ ** people with insane hardware :)
+ **
+ ** Papers and articles you should be familiar with before trying to understand the code:
+ **
+ ** Distance rendering for fractals: http://www.iquilezles.org/www/articles/distancefractals/distancefractals.htm
+ ** Geometric orbit traps: http://www.iquilezles.org/www/articles/ftrapsgeometric/ftrapsgeometric.htm
+ ** Bitmap orbit traps: http://www.iquilezles.org/www/articles/ftrapsbitmap/ftrapsbitmap.htm
+ ** Ambient occlusion techniques: http://www.iquilezles.org/www/articles/ao/ao.htm
+ ** Sphere tracing: A geometric method for the antialiased ray tracing of implicit surfaces: http://graphics.cs.uiuc.edu/~jch/papers/zeno.pdf
+ ** Rendering fractals with distance estimation function: http://www.iquilezles.org/www/articles/mandelbulb/mandelbulb.htm
+ **
+ ** For an impression how this routine looks like see here: http://www.youtube.com/watch?v=lvC8maVHh8Q
+ ** Original release from the Revision can be found here: http://www.pouet.net/prod.php?which=56860
+ **/
+public class ElektronenMultiplizierer implements GLEventListener {
+
+//BEGIN --- BaseGlobalEnvironment replacement ---
+
+ private final GLCapabilities mCaps;
+ private final GLU mGlu;
+
+ private String mCommandLineParameter_BaseRoutineClassName;
+ private boolean mCommandLineParameter_MultiSampling;
+ private int mCommandLineParameter_NumberOfSampleBuffers;
+ private boolean mCommandLineParameter_AnisotropicFiltering;
+ private float mCommandLineParameter_AnisotropyLevel;
+ private boolean mCommandLineParameter_FrameCapture;
+ private boolean mCommandLineParameter_FrameSkip;
+ private boolean mUsesFullScreenMode;
+ private int mFrameCounter;
+ private int mCommandLineParameter_FrameRate;
+ private long mFrameSkipAverageFramerateTimeStart;
+ private boolean mFrameSkipAverageFrameStartTimeInitialized;
+ private long mFrameSkipAverageFramerateTimeEnd;
+ private double mFrameCounterDifference;
+ private double mFrameCounterTargetValue;
+ private int mSkippedFramesCounter;
+// private BaseMusic mBaseMusic;
+ boolean mMusicSyncStartTimeInitialized = false;
+
+ private ShaderState st;
+ private PMVMatrix pmvMatrix;
+ private GLUniformData pmvMatrixUniform;
+ private GLUniformData mScreenDimensionUniform;
+ private GLArrayDataServer vertices0;
+ private GLArrayDataServer texCoords0;
+
+ public String getBaseRoutineClassName() { return mCommandLineParameter_BaseRoutineClassName; }
+ public boolean preferMultiSampling() { return mCommandLineParameter_MultiSampling; }
+ public int getNumberOfSamplingBuffers() { return mCommandLineParameter_NumberOfSampleBuffers; }
+ public boolean preferAnisotropicFiltering() { return mCommandLineParameter_AnisotropicFiltering; }
+ public float getAnisotropyLevel() { return mCommandLineParameter_AnisotropyLevel; }
+ public boolean wantsFrameCapture() { return mCommandLineParameter_FrameCapture; }
+ public int getDesiredFramerate() { return mCommandLineParameter_FrameRate; }
+ public boolean wantsFrameSkip() { return mCommandLineParameter_FrameSkip; }
+ public boolean usesFullScreenMode() { return mUsesFullScreenMode; }
+
+ public ElektronenMultiplizierer (
+ String inBaseRoutineClassName,
+ boolean inMultiSampling,
+ int inNumberOfSampleBuffers,
+ boolean inAnisotropicFiltering,
+ float inAnisotropyLevel,
+ boolean inFrameCapture,
+ boolean inFrameSkip, int desiredFrameRate
+ ) {
+ mGlu = new GLU();
+ mCommandLineParameter_BaseRoutineClassName = inBaseRoutineClassName;
+ mCommandLineParameter_MultiSampling = inMultiSampling;
+ mCommandLineParameter_NumberOfSampleBuffers = (inNumberOfSampleBuffers==-1) ? 2 : inNumberOfSampleBuffers;
+ mCommandLineParameter_AnisotropicFiltering = inAnisotropicFiltering;
+ mCommandLineParameter_AnisotropyLevel = (inAnisotropyLevel==-1.0f) ? 2.0f : inAnisotropyLevel;
+ mCommandLineParameter_FrameCapture = inFrameCapture;
+ mCommandLineParameter_FrameSkip = inFrameSkip;
+ mCommandLineParameter_FrameRate = desiredFrameRate;
+ mCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2));
+ if (preferMultiSampling()) {
+ // enable/configure multisampling support ...
+ mCaps.setSampleBuffers(true);
+ mCaps.setNumSamples(getNumberOfSamplingBuffers());
+ mCaps.setAccumAlphaBits(1);
+ mCaps.setAccumBlueBits(1);
+ mCaps.setAccumGreenBits(1);
+ mCaps.setAccumRedBits(1);
+ // turns out we need to have alpha, otherwise no AA will be visible
+ mCaps.setAlphaBits(1);
+ }
+ }
+
+ public GLCapabilitiesImmutable getGLCapabilities() {
+ return mCaps;
+ }
+
+ public void init(GLAutoDrawable drawable) {
+ GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.setSwapInterval(1);
+ mFrameCounter = 0;
+
+ st = new ShaderState();
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, this.getClass(),
+ "shader", "shader/bin", "default");
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, this.getClass(),
+ // "shader", "shader/bin", "elektronenmultiplizierer_development");
+ "shader", "shader/bin", "elektronenmultiplizierer_port");
+ final ShaderProgram sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ st.attachShaderProgram(gl, sp0);
+ st.useProgram(gl, true);
+
+ final float XRESf = (float) drawable.getWidth();
+ final float YRESf = (float) drawable.getHeight();
+
+ mScreenDimensionUniform = new GLUniformData("resolution", 2, Buffers.newDirectFloatBuffer(2));
+ final FloatBuffer mScreenDimensionV = (FloatBuffer) mScreenDimensionUniform.getBuffer();
+ mScreenDimensionV.put(0, XRESf);
+ mScreenDimensionV.put(1, YRESf);
+ st.ownUniform(mScreenDimensionUniform);
+ st.uniform(gl, mScreenDimensionUniform);
+
+ pmvMatrix = new PMVMatrix();
+ pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+
+ vertices0 = GLArrayDataServer.createGLSL(st, "gca_Vertices", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ vertices0.putf(0); vertices0.putf(YRESf);
+ vertices0.putf(XRESf); vertices0.putf(YRESf);
+ vertices0.putf(0); vertices0.putf(0);
+ vertices0.putf(XRESf); vertices0.putf(0);
+ vertices0.seal(gl, true);
+ st.ownAttribute(vertices0, true);
+ vertices0.enableBuffer(gl, false);
+
+ texCoords0 = GLArrayDataServer.createGLSL(st, "gca_TexCoords", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ texCoords0.putf(0f); texCoords0.putf(1f);
+ texCoords0.putf(1f); texCoords0.putf(1f);
+ texCoords0.putf(0f); texCoords0.putf(0f);
+ texCoords0.putf(1f); texCoords0.putf(0f);
+ texCoords0.seal(gl, true);
+ st.ownAttribute(texCoords0, true);
+ texCoords0.enableBuffer(gl, false);
+
+ //generate framebufferobject
+ int[] result = new int[1];
+ gl.glGenTextures(1, result, 0);
+ mFrameBufferTextureID = result[0];
+ gl.glBindTexture(GL_TEXTURE_2D, mFrameBufferTextureID);
+ gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 384, 384, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
+
+ //allocate the framebuffer object ...
+ gl.glGenFramebuffers(1, result, 0);
+ mFrameBufferObjectID = result[0];
+ gl.glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferObjectID);
+ gl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFrameBufferTextureID, 0);
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ st.uniform(gl, new GLUniformData("fb", 0));
+
+ // will be changed in display(..)
+ st.uniform(gl, new GLUniformData("en", 0));
+ st.uniform(gl, new GLUniformData("tm", 0.0f));
+ st.uniform(gl, new GLUniformData("br", 0.0f));
+ st.uniform(gl, new GLUniformData("et", 0.0f));
+
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+// mBaseMusic = new BaseMusic(BaseGlobalEnvironment.getInstance().getMusicFileName());
+// mBaseMusic.init();
+// mBaseMusic.play();
+ }
+
+ public void display(GLAutoDrawable drawable) {
+ GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ final int XRES = drawable.getWidth();
+ final int YRES = drawable.getHeight();
+
+ //if NO music is used sync to mainloop start ...
+ if (!mFrameSkipAverageFrameStartTimeInitialized) {
+ mFrameSkipAverageFrameStartTimeInitialized = true;
+ mFrameSkipAverageFramerateTimeStart = System.nanoTime();
+ }
+// if (!getBaseMusic().isOffline()) {
+// //if music IS used sync to first second of music ...
+// if (BaseRoutineRuntime.getInstance().getBaseMusic().getPositionInMilliseconds()>0 && !mMusicSyncStartTimeInitialized) {
+// BaseLogging.getInstance().info("Synching to BaseMusic ...");
+// mFrameSkipAverageFramerateTimeStart = (long)(System.nanoTime()-((double)BaseRoutineRuntime.getInstance().getBaseMusic().getPositionInMilliseconds()*1000000.0d));
+// mMusicSyncStartTimeInitialized = true;
+// }
+// }
+ //allow music DSP's to synchronize with framerate ...
+// mBaseMusic.synchonizeMusic();
+
+ //use this for offline rendering/capture ...
+ int MMTime_u_ms = (int)((((double)mFrameCounter)*44100.0f)/60.0f);
+ //use this for music synched rendering ...
+ //int MMTime_u_ms = (int)(BaseRoutineRuntime.getInstance().getBaseMusic().getPositionInMilliseconds()*(44100.0f/1000.0f));
+ //dedicated sync variable for each event ... kinda lame but who cares X-)
+ if (MMTime_u_ms>=522240 && !mSyncEvent_01) { mSyncEvent_01 = true; handleSyncEvent(MMTime_u_ms); }
+ if (MMTime_u_ms>=1305480 && !mSyncEvent_02) { mSyncEvent_02 = true; handleSyncEvent(MMTime_u_ms); }
+ if (MMTime_u_ms>=1827720 && !mSyncEvent_03) { mSyncEvent_03 = true; handleSyncEvent(MMTime_u_ms); }
+ if (MMTime_u_ms>=2349960 && !mSyncEvent_04) { mSyncEvent_04 = true; handleSyncEvent(MMTime_u_ms); }
+ if (MMTime_u_ms>=3394440 && !mSyncEvent_05) { mSyncEvent_05 = true; handleSyncEvent(MMTime_u_ms); }
+ if (MMTime_u_ms>=3916680 && !mSyncEvent_06) { mSyncEvent_06 = true; handleSyncEvent(MMTime_u_ms); }
+ if (MMTime_u_ms>=4438408 && !mSyncEvent_07) { mSyncEvent_07 = true; handleSyncEvent(MMTime_u_ms); }
+ if (MMTime_u_ms>=5482831 && !mSyncEvent_08) { mSyncEvent_08 = true; handleSyncEvent(MMTime_u_ms); }
+ //calculate current time based on 60fps reference framerate ...
+ MMTime_u_ms = (int)((((double)mFrameCounter)*44100.0)/60.0);
+ gl.glDisable(GL_CULL_FACE);
+ gl.glDisable(GL_DEPTH_TEST);
+
+ st.useProgram(gl, true);
+
+ vertices0.enableBuffer(gl, true);
+ texCoords0.enableBuffer(gl, true);
+
+ pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glOrthof(0f, XRES, YRES, 0f, -1f, 1f);
+ pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ st.uniform(gl, pmvMatrixUniform);
+
+ gl.glActiveTexture(GL_TEXTURE0);
+
+ //gogogo! O-)
+ float tBrightnessSync = 40.0f-((MMTime_u_ms-mSyncTime)/1000.0f);
+ if (tBrightnessSync<1) {
+ tBrightnessSync=1;
+ }
+ mEffectTime = (float)((MMTime_u_ms-mEffectSyncTime)/100000.0f);
+
+ if (mSyncEventNumber==0 && mEffectTime<4.0f) {
+ //fadein and fullscreen rotate
+ tBrightnessSync = mEffectTime/4.0f;
+ } else if (mSyncEventNumber==8 && mEffectTime>12.0f) {
+ //fullscrenn mushroom transform
+ tBrightnessSync = 1.0f-((mEffectTime-12.0f)/3.5f);
+ }
+
+ if (mSyncEventNumber==0 || mSyncEventNumber==1) {
+ //zoomin from fog
+ mEffectNumber = 3;
+ mEffectTime *= 1.75;
+ float tEffectTimeMax = 9.3f;
+ if (mEffectTime>=tEffectTimeMax) {
+ mEffectTime=tEffectTimeMax;
+ }
+ } else if(mSyncEventNumber==2 || mSyncEventNumber==3) {
+ //transform big after zoomin
+ mEffectNumber = 4;
+ mEffectTime *= 0.25f;
+ } else if(mSyncEventNumber==4) {
+ //mandelbrot orbit-trap zoomout
+ mEffectNumber = 1;
+ mEffectTime *= 0.0002f;
+ } else if(mSyncEventNumber==5 || mSyncEventNumber==6) {
+ //inside fractal
+ mEffectNumber = 5;
+ mEffectTime *= 0.02f;
+ } else if(mSyncEventNumber==7) {
+ //spiral orbit-trap
+ mEffectNumber = 0;
+ mEffectTime *= 0.02f;
+ } else if(mSyncEventNumber==8) {
+ //fadeout fractal
+ mEffectNumber = 6;
+ mEffectTime *= 0.364f;
+ }
+
+ gl.glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferObjectID);
+ // gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
+ GLUniformData en = st.getUniform("en");
+ if(mSyncEventNumber==7) {
+ en.setData(2);
+ }
+ if(mSyncEventNumber==4) {
+ en.setData(7);
+ } else {
+ en.setData(0);
+ }
+ st.uniform(gl, en);
+
+ GLUniformData et = st.getUniform("et");
+ st.uniform(gl, et.setData(9.1f));
+
+ st.uniform(gl, st.getUniform("tm").setData(MMTime_u_ms/40000.0f));
+ st.uniform(gl, st.getUniform("br").setData(tBrightnessSync));
+
+ if(mSyncEventNumber==4 || mSyncEventNumber==7) {
+ //render to fbo only when using julia/mandel orbittrap ...
+ // gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ }
+ gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ st.uniform(gl, en.setData(mEffectNumber));
+ st.uniform(gl, et.setData(mEffectTime));
+
+ gl.glEnable(GL_TEXTURE_2D);
+ gl.glBindTexture(GL_TEXTURE_2D, mFrameBufferTextureID);
+
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+
+ vertices0.enableBuffer(gl, false);
+ texCoords0.enableBuffer(gl, false);
+ st.useProgram(gl, false);
+
+ //---
+ mFrameCounter++;
+ if (wantsFrameSkip()) {
+ mFrameSkipAverageFramerateTimeEnd = System.nanoTime();
+ double tDesiredFrameRate = (float)getDesiredFramerate();
+ double tSingleFrameTime = 1000000000.0f/tDesiredFrameRate;
+ double tElapsedTime = mFrameSkipAverageFramerateTimeEnd - mFrameSkipAverageFramerateTimeStart;
+ mFrameCounterTargetValue = tElapsedTime/tSingleFrameTime;
+ mFrameCounterDifference = mFrameCounterTargetValue-mFrameCounter;
+ if (mFrameCounterDifference>2) {
+ mFrameCounter+=mFrameCounterDifference;
+ mSkippedFramesCounter+=mFrameCounterDifference;
+ } else if (mFrameCounterDifference<-2) {
+ //hold framecounter advance ...
+ mFrameCounter--;
+ }
+ }
+
+ }
+
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ st.useProgram(gl, true);
+ vertices0.seal(false);
+ vertices0.rewind();
+ vertices0.putf(0); vertices0.putf(height);
+ vertices0.putf(width); vertices0.putf(height);
+ vertices0.putf(0); vertices0.putf(0);
+ vertices0.putf(width); vertices0.putf(0);
+ vertices0.seal(gl, true);
+ st.ownAttribute(vertices0, true);
+ vertices0.enableBuffer(gl, false);
+
+ final FloatBuffer mScreenDimensionV = (FloatBuffer) mScreenDimensionUniform.getBuffer();
+ mScreenDimensionV.put(0, (float) width);
+ mScreenDimensionV.put(1, (float) height);
+ st.uniform(gl, mScreenDimensionUniform);
+
+ st.useProgram(gl, false);
+ gl.glViewport(0, 0, width, height);
+ }
+
+ public void dispose(GLAutoDrawable inDrawable) {
+ GL2ES2 gl = inDrawable.getGL().getGL2ES2();
+ gl.glDeleteFramebuffers(1, new int[] { mFrameBufferObjectID }, 0);
+ gl.glDeleteTextures(1, new int[] { mFrameBufferTextureID }, 0);
+ st.destroy(gl);
+ }
+
+// public BaseMusic getBaseMusic() {
+// return mBaseMusic;
+// }
+
+ public void resetFrameCounter() {
+ mFrameCounter = 0;
+ }
+
+//END --- BaseRoutineRuntime ---
+
+ protected int mFrameBufferTextureID;
+ protected int mFrameBufferObjectID;
+ protected int mSyncTime;
+ protected int mSyncEventNumber;
+ protected float mEffectTime;
+ protected int mEffectNumber;
+ protected int mEffectSyncTime;
+
+ protected boolean mSyncEvent_01;
+ protected boolean mSyncEvent_02;
+ protected boolean mSyncEvent_03;
+ protected boolean mSyncEvent_04;
+ protected boolean mSyncEvent_05;
+ protected boolean mSyncEvent_06;
+ protected boolean mSyncEvent_07;
+ protected boolean mSyncEvent_08;
+
+ public void handleSyncEvent(int inMMTime_u_ms) {
+ mSyncTime = inMMTime_u_ms;
+ mSyncEventNumber++;
+ System.out.println("NEW SYNC EVENT! tSyncEventNumber="+mSyncEventNumber+" tSyncTime="+mSyncTime);
+ if (mSyncEventNumber==0 || mSyncEventNumber==2 || mSyncEventNumber==5 || mSyncEventNumber==8) {
+ mEffectSyncTime = inMMTime_u_ms;
+ }
+ }
+
+
+//BEGIN --- main entry point ---
+
+ static {
+ //stg dirty I dont wanna think about any further X-) ...
+ GLProfile.initSingleton(true);
+ }
+
+ public static void main(String args[]) throws Exception {
+ String tRoutineClassName = null;
+ boolean tMultiSampling = false;
+ int tNumberOfSampleBuffers = -1;
+ boolean tAnisotropicFiltering = false;
+ float tAnisotropyLevel = -1.0f;
+ boolean tFrameCapture = false;
+ boolean tFrameSkip = true;
+ int desiredFrameRate = 30;
+
+ final ElektronenMultiplizierer demo = new ElektronenMultiplizierer(
+ tRoutineClassName,
+ tMultiSampling,tNumberOfSampleBuffers,
+ tAnisotropicFiltering,tAnisotropyLevel,
+ tFrameCapture,
+ tFrameSkip, desiredFrameRate
+ );
+ GLCapabilitiesImmutable caps = demo.getGLCapabilities();
+
+ GLWindow glWindow = GLWindow.create(caps);
+ glWindow.setSize(640, 480);
+ glWindow.setTitle("Jogamp.org - ElektronenMultiplizierer - GL2ES2/NEWT");
+ glWindow.addGLEventListener(demo);
+ final Animator animator = new Animator(glWindow);
+ animator.setUpdateFPSFrames(60, System.err);
+ glWindow.addWindowListener(new com.jogamp.newt.event.WindowAdapter() {
+ public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent e) {
+ animator.stop();
+ System.exit(0);
+ }
+ });
+ glWindow.setVisible(true);
+ animator.start();
+ }
+
+//END --- main entry point ---
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp
new file mode 100644
index 000000000..6b89e6670
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp
@@ -0,0 +1,432 @@
+/**
+ * Copyright 2011 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.
+ */
+
+/**
+ ** __ __|_ ___________________________________________________________________________ ___|__ __
+ ** // /\ _ /\ \\
+ ** //____/ \__ __ _____ _____ _____ _____ _____ | | __ _____ _____ __ __/ \____\\
+ ** \ \ / / __| | | __| _ | | _ | | | __| | | __| | /\ \ / /
+ ** \____\/_/ | | | | | | | | | | | __| | | | | | | | | | |__ " \_\/____/
+ ** /\ \ |_____|_____|_____|__|__|_|_|_|__| | | |_____|_____|_____|_____| _ / /\
+ ** / \____\ http://jogamp.org |_| /____/ \
+ ** \ / "' _________________________________________________________________________ `" \ /
+ ** \/____. .____\/
+ **
+ ** JOGL2 port of my PC 4k intro competition entry for Revision 2011. The shader encapsulates basically
+ ** two different routines: A sphere-tracing based raymarcher for a single fractal formula and a bitmap
+ ** orbit trap julia+mandelbrot fractal renderer. Additionally an inline-processing analog-distortion
+ ** filter is applied to all rendered fragments to make the overall look more interesting.
+ **
+ ** Papers and articles you should be familiar with before trying to understand the code:
+ **
+ ** Distance rendering for fractals: http://www.iquilezles.org/www/articles/distancefractals/distancefractals.htm
+ ** Geometric orbit traps: http://www.iquilezles.org/www/articles/ftrapsgeometric/ftrapsgeometric.htm
+ ** Bitmap orbit traps: http://www.iquilezles.org/www/articles/ftrapsbitmap/ftrapsbitmap.htm
+ ** Ambient occlusion techniques: http://www.iquilezles.org/www/articles/ao/ao.htm
+ ** Sphere tracing: A geometric method for the antialiased ray tracing of implicit surfaces: http://graphics.cs.uiuc.edu/~jch/papers/zeno.pdf
+ ** Rendering fractals with distance estimation function: http://www.iquilezles.org/www/articles/mandelbulb/mandelbulb.htm
+ **
+ ** For an impression how this routine looks like see here: http://www.youtube.com/watch?v=lvC8maVHh8Q
+ ** Original release from the Revision can be found here: http://www.pouet.net/prod.php?which=56860
+ **/
+
+//When I wrote this, only God and I understood what I was doing ...
+// ... now only God knows! X-)
+
+#ifdef GL_ES
+ #define MEDIUMP mediump
+ #define HIGHP highp
+ #define LOWP lowp
+#else
+ #define MEDIUMP
+ #define HIGHP
+ #define LOWP
+#endif
+
+uniform HIGHP int en; //effectnumber
+uniform HIGHP float et; //effecttime
+uniform HIGHP sampler2D fb; //fbotexture
+uniform HIGHP float br; //brightness
+uniform HIGHP float tm; //time
+uniform HIGHP vec2 resolution;//screen resolution/fbo resolution
+
+float camerafocallengthdode;
+vec3 camerapositiondode;
+vec2 sizedode;
+vec3 backgroundcolor = vec3(0,0.6,0.46);
+mat3 worldrotationxyz;
+mat3 fractalplanerotationx;
+mat3 fractalplanerotationy;
+mat3 camerarotationdode;
+vec2 oglFragCoord;
+
+//fractal formula used for sphreretracing/distance-estimation
+//dodecahedron serpinski (knighty)
+//http://www.fractalforums.com/index.php?topic=3158.msg16982#msg16982
+//normal vectors for the dodecahedra-siepinski folding planes are:
+//(phi^2, 1, -phi), (-phi, phi^2, 1), (1, -phi, phi^2), (-phi*(1+phi), phi^2-1, 1+phi), (1+phi, -phi*(1+phi), phi^2-1) and x=0, y=0, z=0 planes.
+
+//const pre-calc
+const float phi = 1.618;
+const float _IKVNORM_ = 1.0 / sqrt(pow(phi * (1.0 + phi), 2.0) + pow(phi * phi - 1.0, 2.0) + pow(1.0 + phi, 2.0));
+const float _C1_ = phi * (1.0 + phi) * _IKVNORM_;
+const float _C2_ = (phi * phi - 1.0) * _IKVNORM_;
+const float _1C_ = (1.0 + phi) * _IKVNORM_;
+const vec3 phi3 = vec3(0.5, 0.5 / phi, 0.5 * phi);
+const vec3 c3 = vec3(_C1_, _C2_, _1C_);
+
+vec3 distancefunction(vec3 w) {
+//!P center scale offset ...
+ vec3 offset;
+ if (en==6) {
+ offset = vec3(0.61,0.1*et,0.99);
+ } else {
+ offset = vec3(0.61,0.0,0.99);
+ }
+//!P center scale \0/ this is awesome for fadeins !!!
+ float scale = 2.;
+ w *= worldrotationxyz;
+ float d, t;
+ float md = 1000.0, cd = 0.0;
+//!P iterations (8) ... 2x see below
+ for (int i = 0; i < 8; i++) {
+ w *= fractalplanerotationx;
+ w = abs(w);
+ t = w.x * phi3.z + w.y * phi3.y - w.z * phi3.x;
+ if (t < 0.0) { w += vec3(-2.0, -2.0, 2.0) * t * phi3.zyx; }
+ t = -w.x * phi3.x + w.y * phi3.z + w.z * phi3.y;
+ if (t < 0.0) { w += vec3(2.0, -2.0, -2.0) * t * phi3.xzy; }
+ t = w.x * phi3.y - w.y * phi3.x + w.z * phi3.z;
+ if (t < 0.0) { w += vec3(-2.0, 2.0, -2.0) * t * phi3.yxz; }
+ t = -w.x * c3.x + w.y * c3.y + w.z * c3.z;
+ if (t < 0.0) { w += vec3(2.0, -2.0, -2.0) * t * c3.xyz; }
+ t = w.x * c3.z - w.y * c3.x + w.z * c3.y;
+ if (t < 0.0) { w += vec3(-2.0, 2.0, -2.0) * t * c3.zxy; }
+ w *= fractalplanerotationy;
+ w *= scale;
+ w -= offset * (scale - 1.0);
+ //accumulate minimum orbit for coloring ...
+ d = dot(w, w);
+//!P iterations for coloring (4)
+ if (i < 4) {
+ md = min(md, d);
+ cd = d;
+ }
+ }
+//!P max iterations (8)
+ return vec3((length(w) - 2.0) * pow(scale, -8.0), md, cd);
+}
+
+//calculate ray direction fragment coordinates
+vec3 raydirection(vec2 pixel) {
+ vec2 p = (0.5*sizedode-pixel)/vec2(sizedode.x,-sizedode.y);
+//!P aspect ratio of dode
+ p.x *= sizedode.x/sizedode.y;
+//!P vec3 w = vec3(0, 0, 1), vec3 v = vec3(0, 1, 0), vec3 u = vec3(1, 0, 0);
+ vec3 d = (p.x * vec3(1, 0, 0)+p.y * vec3(0, 1, 0)-camerafocallengthdode * vec3(0, 0, 1));
+ return normalize(camerarotationdode * d);
+}
+
+//iq's fake ambient occlusion
+//http://www.iquilezles.org/www/material/nvscene2008/rwwtt.pdf
+//http://www.iquilezles.org/www/articles/ao/ao.htm
+float ambientocclusion(vec3 p, vec3 n, float eps) {
+ float o = 1.0;
+//!P ao spread (10.6)
+// spreads the output color intensity
+ eps *= 10.6;
+//!P ao intensity (0.16)
+ float k = 0.16 / eps;
+ //add little start distance to the surface
+ float d = 2.0 * eps;
+//!P ao iterations (5) ...
+ for (int i = 0; i < 5; ++i) {
+ o -= (d - distancefunction(p + n * d).x) * k;
+ d += eps;
+ //fade ao when distance to the surface increases
+ k *= 0.5;
+ }
+ return clamp(o, 0.0, 1.0);
+}
+
+vec4 render(vec2 pixel) {
+ vec3 ray_direction = raydirection(pixel);
+//!P minimum ray length (6e-5)
+ float ray_length = 6e-5;
+ vec3 ray = camerapositiondode + ray_length * ray_direction;
+//!P minimum epsilon (6e-7) ...
+ float eps = 6e-7;
+ vec3 dist;
+ vec3 normal = vec3(0);
+ int steps = 0;
+ bool hit = false;
+ float minmarch = 0.0;
+//!P maxmarch = 10000.0;
+ float maxmarch = 25.0;
+//!P field of view scale = (1.0 / sqrt(1.0 + camerafocallengthdode * camerafocallengthdode))
+//!P detail of surface approximation = 1.22
+//!P pixelscale = (1.0 / min(sizedode.x, sizedode.y))
+ float epsfactor = 2.0 * (1.0 / sqrt(1.0 + camerafocallengthdode * camerafocallengthdode)) * (1.0 / min(sizedode.x, sizedode.y)) * 1.22;
+ ray_length = minmarch;
+ ray = camerapositiondode + ray_length * ray_direction;
+//!P max number of raymarching steps (90);
+ for (int i = 0; i < 90; i++) {
+ steps = i;
+ dist = distancefunction(ray);
+//!P X-) questionable surface smoothing (0.53)
+ dist.x *= 0.53;
+ //backtrack previous step and check if it was only a "fussel"
+ if (hit && dist.x < eps || ray_length > maxmarch || ray_length < minmarch) {
+ steps--;
+ break;
+ }
+ hit = false;
+ ray_length += dist.x;
+ ray = camerapositiondode + ray_length * ray_direction;
+ eps = ray_length * epsfactor;
+ if (dist.x < eps || ray_length < minmarch) {
+ hit = true;
+ }
+ }
+ //\0/ there is a hit!
+ vec4 color = vec4(backgroundcolor,0.5);
+ if (hit) {
+ float aof = 1.0;
+ if (steps < 1 || ray_length < minmarch) {
+ normal = normalize(ray);
+ } else {
+ //gradient in x,y and z direction for intersection point
+ //!P minimum normal (1.5e-7)
+ float e = max(eps * 0.5, 1.5e-7);
+ normal = normalize(vec3(
+ distancefunction(ray + vec3(e, 0, 0)).x - distancefunction(ray - vec3(e, 0, 0)).x,
+ distancefunction(ray + vec3(0, e, 0)).x - distancefunction(ray - vec3(0, e, 0)).x,
+ distancefunction(ray + vec3(0, 0, e)).x - distancefunction(ray - vec3(0, 0, e)).x
+ ));
+ aof = ambientocclusion(ray, normal, eps);
+ }
+//!P hardcoded light position vec3(-50,150,-25)
+ float diffuse = max(dot(normal, normalize(vec3(-50,150,-25) - ray)), 0.0);
+//blinn/phong specular stuff ...
+//!P specular exponent (4)
+//!P specularity (0.8)
+//!P diffuse color vec3(0.45) 2x in one line ...
+//!P ambient color vec2 ambientcolor = vec2(0.5,0.3)
+ color.rgb = (mix(vec3(0.5), backgroundcolor, 0.3) * vec3(0.45) + vec3(0.45) * diffuse + pow(diffuse, 4.) * 0.8)*aof;
+ color.a = 1.0;
+ }
+//!P fog factor = 0.01
+ color.rgb = mix(backgroundcolor, color.rgb, exp(-pow(ray_length, 2.0) * 0.01));
+ return color;
+}
+
+mat3 xmatrixrotation(float angle) {
+ return mat3(
+ vec3(1.0, 0.0, 0.0),
+ vec3(0.0, cos(angle), sin(angle)),
+ vec3(0.0, -sin(angle), cos(angle))
+ );
+}
+
+mat3 ymatrixrotation(float angle) {
+ return mat3(
+ vec3(cos(angle), 0.0, -sin(angle)),
+ vec3( 0.0, 1.0, 0.0),
+ vec3(sin(angle), 0.0, cos(angle))
+ );
+}
+
+vec4 raymarch_orbittrap_image(vec2 fragcoord) {
+ //do the matrix calculations by hand X-)
+ //as mat4 constructor and arithmetic assignments are
+ //currently broken (2010-09-21) on ATI cards i found
+ //a workaround using vec4 constructors wich works on
+ //both NVIDIA+ATI --- MAGIC. DO NOT TOUCH! -=#:-)
+ mat3 identitymatrix = mat3(1,0,0,0,1,0,0,0,1);
+ float sin_phi = sin(0.1*tm);
+ float cos_phi = cos(0.1*tm);
+ mat3 zrot = mat3(
+ vec3( cos_phi, sin_phi, 0.0),
+ vec3(-sin_phi, cos_phi, 0.0),
+ vec3( 0.0, 0.0, 1.0)
+ );
+ vec2 position;
+ float fractalplanex_var;
+ float fractalplaney_var;
+ position = oglFragCoord.xy;
+ camerafocallengthdode = 1.0;
+ if (en==2) {
+ sizedode = vec2(384,384);
+ camerapositiondode = vec3(0.0,0.0,-2.7);
+ } else if (en==3) {
+ camerapositiondode = vec3(0.0,0.0,-2.7*(10.-et));
+ } else if (en==4) {
+ camerapositiondode = vec3(0.0,0.0,-2.7*(10.-9.3));
+ fractalplanex_var = et;
+ fractalplaney_var = 0.0;
+ } else if (en==5) {
+ //inside effect
+ camerapositiondode = vec3(0.0,0.0,-0.05);
+ fractalplanex_var = 1.06;
+ fractalplaney_var = -1.0-et;
+ } else if (en==6) {
+ camerapositiondode = vec3(0.0,0.0,-2.7*(10.-9.5));
+ fractalplanex_var = et;
+ fractalplaney_var = sin(et*0.03)-1.0;
+ } else if (en==7) {
+ sizedode = vec2(384,384);
+ fractalplanex_var = et;
+ fractalplaney_var = sin(et*0.93)-1.0;
+ camerapositiondode = vec3(0.0,0.0,-2.7);
+ }
+ worldrotationxyz = xmatrixrotation(0.1*tm)*ymatrixrotation(0.1*tm)*zrot*identitymatrix;
+ fractalplanerotationx = xmatrixrotation(fractalplanex_var)*identitymatrix;
+ fractalplanerotationy = xmatrixrotation(fractalplaney_var)*identitymatrix;
+ camerarotationdode = ymatrixrotation(3.14)*identitymatrix;
+ vec4 color = render(position);
+ return color;
+}
+
+//----------------------------------------------------------------------------------------------------------
+
+vec4 orbitmapping(vec4 c, vec2 w) {
+//!P orbit trap scale and offset
+ vec2 orbittrapoffset = vec2(0.24,-0.24);
+ float orbittrapscale;
+ if (en==0) {
+ //julia set ...
+ orbittrapscale = 0.625;
+ } else {
+ //mandlebrot ...
+ orbittrapscale = 0.325;
+ }
+ vec2 sp = 0.5 + (w / orbittrapscale - orbittrapoffset);
+ vec4 s = texture2D(fb, sp);
+ if (s.a > 0.0) {
+ c = mix(c, s, s.a);
+ }
+ return c;
+}
+
+vec4 orbittrap(vec2 z) {
+ float powerjulia = 2.;
+ vec3 colorjulia = vec3(1.0);
+ vec4 color = vec4(colorjulia, 0.0);
+ float n = 0.0;
+ vec2 c;
+ if (en==0) {
+ //julia mode ...
+//!P use offset-julia from 2.25 to 2.5
+ c = vec2(sin(et+2.07)*0.05,cos(et+2.07));
+ } else {
+ //mandelbrot mode ...
+ c = z;
+ }
+//!P max iterations for julia (128) ... 2x parameter - see below!
+ for (int i = 0; i<128; i++) {
+ n += 1.0;
+ float r = pow(length(z), powerjulia);
+ float a = powerjulia * atan(z.y, z.x);
+ z = vec2(cos(a) * r, sin(a) * r) +c;
+//!P min iterations for julia (1.0) ...
+ if (n >= 1.0) {
+ color = orbitmapping(color, z);
+//!P orbit trap alpha precision (0.6) ...
+ if (color.a >= 0.6) {
+ break;
+ }
+ }
+ }
+//!P max iterations for julia (128.0) ...
+ float blend = clamp(1.0 - (n / 128.0) * 2.0, 0.0, 1.0);
+ color.rgb = mix(colorjulia, color.rgb, blend);
+ return color;
+}
+
+void main() {
+ vec2 sizejulia = resolution;
+ sizedode = sizejulia;
+ oglFragCoord = gl_FragCoord.xy;
+ vec4 color;
+ if (en==0 || en==1) {
+ //render 2d julia/mandelbrot
+//!P camera position for julia ...
+ vec3 camerapositionjulia;
+ if (en==0) {
+ //julia
+ camerapositionjulia = vec3(-0.2,-0.515,0.095347+(et*1.75));
+ } else {
+ //mandelbrot
+ camerapositionjulia = vec3(0.325895,0.049551,0.0005+et);
+ }
+//!P absolute output size of julia orbit trap ...
+ vec2 z = ((oglFragCoord.xy - (sizejulia * 0.5)) / sizejulia) *
+ vec2(sizejulia.x/sizejulia.y, 1.0) * //aspect ratio
+ camerapositionjulia.z +
+ camerapositionjulia.xy;
+ color = orbittrap(z);
+ } else {
+ color = raymarch_orbittrap_image(oglFragCoord.xy);
+ }
+ if (en==2 || en==7) {
+ gl_FragColor = color;
+ } else {
+ //do normal rendering ...
+ //analog-tv distortion ...
+ vec2 position = oglFragCoord.xy / sizejulia.xy;
+ position.y *=-1.0;
+ vec3 color_tv = color.rgb;
+ //contrast
+ color_tv = clamp(color_tv*0.5+0.5*color_tv*color_tv*1.2,0.0,1.0);
+ //circular vignette fade
+ color_tv *= 0.5 + 0.5*16.0*position.x*position.y*(1.0-position.x)*(-1.0-position.y);
+ //color shift
+ if (en==0 || en==3) {
+ color_tv *= vec3(0.8,1.0,0.7); //green
+ }
+ if (en==1 || en==4) {
+ color_tv *= vec3(0.95,0.85,1.0); //blue
+ }
+ if (en==5) {
+ color_tv *= vec3(1.0,0.7,1.0); //purple
+ }
+
+ if (en==6) {
+ color_tv *= vec3(0.7,1.0,1.0); //cyan
+ }
+ if (en==2) {
+ color_tv *= vec3(1.0,1.0,0.7); //yellow
+ }
+ //tvlines effect
+ color_tv *= 0.9+0.1*sin(1.5*tm+position.y*1000.0);
+ //tv flicker effect
+ color_tv *= 0.97+0.13*sin(2.5*tm);
+ color_tv *= br;
+ gl_FragColor = vec4(color_tv,1.0);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp
new file mode 100644
index 000000000..fdd159616
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp
@@ -0,0 +1,280 @@
+/**
+ * Copyright 2011 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.
+ */
+
+/**
+ ** __ __|_ ___________________________________________________________________________ ___|__ __
+ ** // /\ _ /\ \\
+ ** //____/ \__ __ _____ _____ _____ _____ _____ | | __ _____ _____ __ __/ \____\\
+ ** \ \ / / __| | | __| _ | | _ | | | __| | | __| | /\ \ / /
+ ** \____\/_/ | | | | | | | | | | | __| | | | | | | | | | |__ " \_\/____/
+ ** /\ \ |_____|_____|_____|__|__|_|_|_|__| | | |_____|_____|_____|_____| _ / /\
+ ** / \____\ http://jogamp.org |_| /____/ \
+ ** \ / "' _________________________________________________________________________ `" \ /
+ ** \/____. .____\/
+ **
+ ** JOGL2 port of my PC 4k intro competition entry for Revision 2011. The shader encapsulates basically
+ ** two different routines: A sphere-tracing based raymarcher for a single fractal formula and a bitmap
+ ** orbit trap julia+mandelbrot fractal renderer. Additionally an inline-processing analog-distortion
+ ** filter is applied to all rendered fragments to make the overall look more interesting.
+ **
+ ** Papers and articles you should be familiar with before trying to understand the code:
+ **
+ ** Distance rendering for fractals: http://www.iquilezles.org/www/articles/distancefractals/distancefractals.htm
+ ** Geometric orbit traps: http://www.iquilezles.org/www/articles/ftrapsgeometric/ftrapsgeometric.htm
+ ** Bitmap orbit traps: http://www.iquilezles.org/www/articles/ftrapsbitmap/ftrapsbitmap.htm
+ ** Ambient occlusion techniques: http://www.iquilezles.org/www/articles/ao/ao.htm
+ ** Sphere tracing: A geometric method for the antialiased ray tracing of implicit surfaces: http://graphics.cs.uiuc.edu/~jch/papers/zeno.pdf
+ ** Rendering fractals with distance estimation function: http://www.iquilezles.org/www/articles/mandelbulb/mandelbulb.htm
+ **
+ ** For an impression how this routine looks like see here: http://www.youtube.com/watch?v=lvC8maVHh8Q
+ ** Original release from the Revision can be found here: http://www.pouet.net/prod.php?which=56860
+ **/
+
+//When I wrote this, only God and I understood what I was doing ...
+// ... now only God knows! X-)
+
+uniform int en;
+uniform float et;
+uniform sampler2D fb;
+uniform float br,tm;
+uniform vec2 resolution;
+float v;
+vec3 n;
+vec2 e;
+vec3 f=vec3(0,.6,.46);
+mat3 i,m,r,y;
+vec2 c;
+const float x=1.618,t=1./sqrt(pow(x*(1.+x),2.)+pow(x*x-1.,2.)+pow(1.+x,2.)),z=x*(1.+x)*t,s=(x*x-1.)*t,w=(1.+x)*t;
+const vec3 a=vec3(.5,.5/x,.5*x),p=vec3(z,s,w);
+vec3 l(vec3 v) {
+ vec3 n;
+ if(en==6)
+ n=vec3(.61,.1*et,.99);
+ else
+ n=vec3(.61,0.,.99);
+ float e=2.;
+ v*=i;
+ float f,x,c=1000.,y=0.;
+ for(int z=0;z<8;z++) {
+ v*=m;
+ v=abs(v);
+ x=v.x*a.z+v.y*a.y-v.z*a.x;
+ if(x<0.)
+ v+=vec3(-2.,-2.,2.)*x*a.zyx;
+ x=-v.x*a.x+v.y*a.z+v.z*a.y;
+ if(x<0.)
+ v+=vec3(2.,-2.,-2.)*x*a.xzy;
+ x=v.x*a.y-v.y*a.x+v.z*a.z;
+ if(x<0.)
+ v+=vec3(-2.,2.,-2.)*x*a.yxz;
+ x=-v.x*p.x+v.y*p.y+v.z*p.z;
+ if(x<0.)
+ v+=vec3(2.,-2.,-2.)*x*p.xyz;
+ x=v.x*p.z-v.y*p.x+v.z*p.y;
+ if(x<0.)
+ v+=vec3(-2.,2.,-2.)*x*p.zxy;
+ v*=r;
+ v*=e;
+ v-=n*(e-1.);
+ f=dot(v,v);
+ if(z<4)
+ c=min(c,f),y=f;
+ }
+ return vec3((length(v)-2.)*pow(e,-8.),c,y);
+}
+vec3 b(vec2 x) {
+ vec2 n=(.5*e-x)/vec2(e.x,-e.y);
+ n.x*=e.x/e.y;
+ vec3 a=n.x*vec3(1,0,0)+n.y*vec3(0,1,0)-v*vec3(0,0,1);
+ return normalize(y*a);
+}
+float b(vec3 e,vec3 x,float v) {
+ float n=1.;
+ v*=10.6;
+ float t=.16/v,y=2.*v;
+ for(int i=0;i<5;++i)
+ n-=(y-l(e+x*y).x)*t,y+=v,t*=.5;
+ return clamp(n,0.,1.);
+}
+vec4 h(vec2 x) {
+ vec3 a=b(x);
+ float i=6e-05;
+ vec3 y=n+i*a;
+ float c=6e-07;
+ vec3 m,z=vec3(0);
+ int r=0;
+ bool t=false;
+ float s=0.,w=25.,p=2.*(1./sqrt(1.+v*v))*(1./min(e.x,e.y))*1.22;
+ i=s;
+ y=n+i*a;
+ for(int g=0;g<90;g++) {
+ r=g;
+ m=l(y);
+ m.x*=.53;
+ if(t&&m.x<c||i>w||i<s) {
+ r--;
+ break;
+ }
+ t=false;
+ i+=m.x;
+ y=n+i*a;
+ c=i*p;
+ if(m.x<c||i<s)
+ t=true;
+ }
+ vec4 g=vec4(f,.5);
+ if(t) {
+ float d=1.;
+ if(r<1||i<s)
+ z=normalize(y);
+ else {
+ float h=max(c*.5,1.5e-07);
+ z=normalize(vec3(l(y+vec3(h,0,0)).x-l(y-vec3(h,0,0)).x,l(y+vec3(0,h,0)).x-l(y-vec3(0,h,0)).x,l(y+vec3(0,0,h)).x-l(y-vec3(0,0,h)).x));
+ d=b(y,z,c);
+ }
+ float h=max(dot(z,normalize(vec3(-66,162,-30)-y)),0.);
+ g.xyz=(mix(vec3(.5),f,.3)*vec3(.45)+vec3(.45)*h+pow(h,4.)*.8)*d;
+ g.w=1.;
+ }
+ g.xyz=mix(f,g.xyz,exp(-pow(i,2.)*.01));
+ return g;
+}
+mat3 g(float e) {
+ return mat3(vec3(1.,0.,0.),vec3(0.,cos(e),sin(e)),vec3(0.,-sin(e),cos(e)));
+}
+mat3 d(float e) {
+ return mat3(vec3(cos(e),0.,-sin(e)),vec3(0.,1.,0.),vec3(sin(e),0.,cos(e)));
+}
+vec4 D(vec2 x) {
+ mat3 a=mat3(1,0,0,0,1,0,0,0,1);
+ float t=sin(.1*tm),z=cos(.1*tm);
+ mat3 p=mat3(vec3(z,t,0.),vec3(-t,z,0.),vec3(0.,0.,1.));
+ vec2 f;
+ float s,w;
+ f=c.xy;
+ v=1.;
+ if(en==2)
+ e=vec2(384,384),n=vec3(0.,0.,-2.7);
+ if(en==3)
+ n=vec3(0.,0.,-2.7*(10.-et));
+ if(en==4)
+ n=vec3(0.,0.,-1.89),s=et,w=0.;
+ if(en==5)
+ n=vec3(0.,0.,-.05),s=1.06,w=-1.-et;
+ if(en==6)
+ n=vec3(0.,0.,-1.35),s=et,w=sin(et*.03)-1.;
+ if(en==7)
+ e=vec2(384,384),s=et,w=sin(et*.93)-1.,n=vec3(0.,0.,-2.7);
+ i=g(.1*tm)*d(.1*tm)*p*a;
+ m=g(s)*a;
+ r=g(w)*a;
+ y=d(3.14)*a;
+ vec4 l=h(f);
+ if(l.w<.00392) {
+ discard;
+ }
+ return l;
+}
+vec4 D(vec4 e,vec2 x) {
+ vec2 n=vec2(.24,-.24);
+ float y;
+ if(en==0)
+ y=.625;
+ else
+ y=.325;
+ vec2 v=.5+(x/y-n);
+ vec4 c=texture2D(fb,v);
+ if(c.w>0.)
+ e=mix(e,c,c.w);
+ return e;
+}
+vec4 o(vec2 v) {
+ float n=2.;
+ vec3 e=vec3(1.);
+ vec4 i=vec4(e,0.);
+ float y=0.;
+ vec2 x;
+ if(en==0)
+ x=vec2(sin(et+2.07)*.05,cos(et+2.07));
+ else
+ x=v;
+ for(int f=0;f<128;f++) {
+ y+=1.;
+ float t=pow(length(v),n),c=n*atan(v.y,v.x);
+ v=vec2(cos(c)*t,sin(c)*t)+x;
+ if(y>=1.) {
+ i=D(i,v);
+ if(i.w>=.6) {
+ break;
+ }
+ }
+ }
+ float c=clamp(1.-y/128.*2.,0.,1.);
+ i.xyz=mix(e,i.xyz,c);
+ return i;
+}
+void main() {
+ //vec2 v=vec2(640.0,480.0);
+ vec2 v =resolution;
+ e=v;
+ c=gl_FragCoord.xy;
+ vec4 n;
+ if(en==0||en==1) {
+ vec3 a;
+ if(en==0)
+ a=vec3(-.2,-.515,.095347+et*1.75);
+ else
+ a=vec3(.325895,.049551,.0005+et);
+ vec2 x=(c.xy-v*.5)/v*vec2(v.x/v.y,1.)*a.z+a.xy;
+ n=o(x);
+ } else
+ n=D(c.xy);
+ if(en==2||en==7)
+ gl_FragColor=n;
+ else {
+ vec2 i=c.xy/v.xy;
+ i.y*=-1.;
+ vec3 x=n.xyz;
+ x=clamp(x*.5+.5*x*x*1.2,0.,1.);
+ x*=.5+8.*i.x*i.y*(1.-i.x)*(-1.-i.y);
+ if(en==0||en==3)
+ x*=vec3(.8,1.,.7);
+ if(en==1||en==4)
+ x*=vec3(.95,.85,1.);
+ if(en==5)
+ x*=vec3(1.,.7,1.);
+ if(en==6)
+ x*=vec3(.7,1.,1.);
+ if(en==2)
+ x*=vec3(1.,1.,.7);
+ x*=.9+.1*sin(1.5*tm+i.y*1000.);
+ x*=.97+.13*sin(2.5*tm);
+ x*=br;
+ gl_FragColor=vec4(x,1.);
+ }
+}