Java GP/GPU:JOGL乒乓球技术

Java GP/GPU:JOGL乒乓球技术,java,opengl,glsl,gpgpu,jogl,Java,Opengl,Glsl,Gpgpu,Jogl,我试着用JOGL和GLSL在GPU上实现一个反应扩散模型 我使用乒乓球技术和两个FramebufferObject(我也尝试过使用一个FBO和两种颜色的附件,但都没有成功)。 着色器似乎是正确的,因为我在unity中尝试过它(经过一些修改),并且它可以工作。 经过一周的尝试,我完全不知道如何让这段代码工作。我真的不是慢跑专家,所以我可能错过了一些明显的东西 结果是图像随着时间变白:没有反应扩散行为,我不明白为什么 提前谢谢你的帮助。这是我的密码: package gpu2; import ja

我试着用JOGL和GLSL在GPU上实现一个反应扩散模型

我使用乒乓球技术和两个FramebufferObject(我也尝试过使用一个FBO和两种颜色的附件,但都没有成功)。 着色器似乎是正确的,因为我在unity中尝试过它(经过一些修改),并且它可以工作。 经过一周的尝试,我完全不知道如何让这段代码工作。我真的不是慢跑专家,所以我可能错过了一些明显的东西

结果是图像随着时间变白:没有反应扩散行为,我不明白为什么

提前谢谢你的帮助。这是我的密码:

package gpu2;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.nio.IntBuffer;
import java.nio.FloatBuffer;
import java.io.File;

import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.GLFBODrawable;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.FBObject.Colorbuffer;
import com.jogamp.opengl.FBObject.ColorAttachment;
import com.jogamp.opengl.FBObject.TextureAttachment;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.glsl.ShaderUtil;
import com.jogamp.opengl.util.GLBuffers; 
import com.jogamp.opengl.util.texture.Texture; 
import com.jogamp.opengl.util.texture.TextureIO; 

import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLOffscreenAutoDrawable;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
import com.jogamp.opengl.GLDrawableFactory;

import static com.jogamp.opengl.GL.*;  // GL constants
import static com.jogamp.opengl.GL2.*; // GL2 constants

import gpu2.ModelParam;

/**
 * JOGL 2.0 Program Template (GLCanvas)
 * This is a "Component" which can be added into a top-level "Container".
 * It also handles the OpenGL events to render graphics.
 */
@SuppressWarnings("serial")
public class JOGL2Setup_GLCanvas extends GLCanvas implements GLEventListener {
   // Define constants for the top-level container
   private static String TITLE = "JOGL 2.0 Setup (GLCanvas)";  // window's title
   private static final int CANVAS_WIDTH = 512;  // width of the drawable
   private static final int CANVAS_HEIGHT = 512; // height of the drawable
   private static final int FPS = 30; // animator's target frames per second

   private final float[] canvasVertices = {
           -1f, -1f, 0.0f,
           -1f, 1f, 0.0f,
           1f, -1f, 0.0f,
           1f,  1f, 0.0f, 
   };

   private final float[] canvasTexCoords = {
           0.0f, 0.0f,
           0.0f, 1.0f,
           1.0f, 0.0f,
           1.0f, 1.0f,
};

   /** The entry main() method to setup the top-level container and animator */
   public static void main(String[] args) {
      // Run the GUI codes in the event-dispatching thread for thread safety
      SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
            // Create the OpenGL rendering canvas
            GLCanvas canvas = new JOGL2Setup_GLCanvas();
            canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));

            // Create a animator that drives canvas' display() at the specified FPS.
            final FPSAnimator animator = new FPSAnimator(canvas, FPS, true);

            // Create the top-level container
            final JFrame frame = new JFrame(); // Swing's JFrame or AWT's Frame
            frame.getContentPane().add(canvas);
            frame.addWindowListener(new WindowAdapter() {
               @Override
               public void windowClosing(WindowEvent e) {
                  // Use a dedicate thread to run the stop() to ensure that the
                  // animator stops before program exits.
                  new Thread() {
                     @Override
                     public void run() {
                        if (animator.isStarted()) animator.stop();
                        System.exit(0);
                     }
                  }.start();
               }
            });
            frame.setTitle(TITLE);
            frame.pack();
            frame.setVisible(true);
            animator.start(); // start the animation loop
         }
      });
   }

   // Setup OpenGL Graphics Renderer

   private GLU glu;  // for the GL Utility
   private GL2 gl;

   //OpenGl data
   private int vboVertices;
   private int vboTextCoord;
   private Texture textureFile;

   private FBObject fbo[];

   private ShaderProgram shaderCompute;
   private ShaderProgram shaderVisu;
   private ShaderProgram shaderComputeInit;

   private int currentSourceBuffer = 0;
   private int currentDestBuffer = 1;

   private int currentFrame = 0;
   private int maxFrameCount = 5000000;
   private float clearUniform = 0;

   ModelParam params = new ModelParam();

   public JOGL2Setup_GLCanvas() {
      this.addGLEventListener(this);
   }

   @Override
   public void init(GLAutoDrawable drawable) {
      gl = drawable.getGL().getGL2();      // get the OpenGL graphics context
      glu = new GLU();                         // get GL Utilities
      gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // set background (clear) color

      gl.glEnable(GL_TEXTURE_2D);

      gl.glEnable( GL_COLOR_MATERIAL );
      gl.glEnable( GL_FRAMEBUFFER );
      gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NEAREST); // best perspective correction

      viewOrtho(gl);

      gl.glViewport(0,0,CANVAS_WIDTH,CANVAS_HEIGHT);

      int[] buffers = new int[2];
      gl.glGenBuffers(2, buffers, 0);

      vboVertices = buffers[0];
      vboTextCoord = buffers[1];

      gl.glBindBuffer(GL_ARRAY_BUFFER, vboVertices);
      gl.glBufferData(GL_ARRAY_BUFFER, canvasVertices.length*(Float.SIZE/Byte.SIZE)*3, FloatBuffer.wrap(canvasVertices), GL_STATIC_DRAW);

      gl.glBindBuffer(GL_ARRAY_BUFFER, vboTextCoord);
      gl.glBufferData(GL_ARRAY_BUFFER, canvasTexCoords.length*(Float.SIZE/Byte.SIZE)*2, FloatBuffer.wrap(canvasTexCoords), GL_STATIC_DRAW);

      gl.glBindBuffer( GL_ARRAY_BUFFER, 0 );

      // ------------ create Texture Source------------------------
      textureFile = initializeTexture(); 
      if (textureFile==null) {
        System.out.println("cannot load texture from disk");  
      }

      // ------------ load shaders ------------------------
      shaderCompute = loadShader(gl, "compute.vsh", "compute.fsh");
      shaderComputeInit = loadShader(gl, "compute.vsh", "computeInit.fsh");
      shaderVisu    = loadShader(gl, "visu.vsh", "visu.fsh");

      // ------------ create FBO ------------------------

        initFBO();


   }

   /**
    * Called back by the animator to perform rendering.
    */
   @Override
   public void display(GLAutoDrawable drawable) {

       if (currentFrame < maxFrameCount) {
           prepareNextStep();

           renderToFBO();
           currentFrame++;

       }
       renderFBOToScreen();  
   }

     private void prepareNextStep() {
           currentSourceBuffer = 1 - currentSourceBuffer;
           currentDestBuffer = 1 - currentDestBuffer;
      }

   private void renderToFBO()
    {
        fbo[currentDestBuffer].bind(gl);
        //gl.glClear(GL_COLOR_BUFFER_BIT);

        viewOrtho(gl);

        shaderCompute.useProgram(gl, true);

        setShaderUniformFloat(gl, shaderCompute.program(), "diffuseU", 0.211f);
        setShaderUniformFloat(gl, shaderCompute.program(), "diffuseV", 0.088f);
        setShaderUniformFloat(gl, shaderCompute.program(), "feed", 0.007f);
        setShaderUniformFloat(gl, shaderCompute.program(), "kill", 0.08f);
        setShaderUniformFloat(gl, shaderCompute.program(), "Tech", 1f);

        setShaderUniformFloat(gl, shaderCompute.program(), "currentFrame", currentFrame);
        setShaderUniformFloat2(gl, shaderCompute.program(), "resolution", CANVAS_WIDTH, CANVAS_HEIGHT);

        drawDataBuffer(shaderCompute, true);

        shaderCompute.useProgram(gl, false);
        fbo[currentDestBuffer].unbind(gl);
    }

   void drawDataBuffer(ShaderProgram currentShader, boolean sencondImage) {
       // --- draw vbo
        gl.glEnableClientState(GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        //textcoords
        gl.glBindBuffer(GL_ARRAY_BUFFER,vboTextCoord);
        gl.glTexCoordPointer(2, GL_FLOAT, 0, 0); 
       //vertices
        gl.glBindBuffer( GL_ARRAY_BUFFER, vboVertices );
        gl.glVertexPointer(3, GL_FLOAT, 0, 0);

        //activate texture data from last fbo
        final FBObject.Colorbuffer texSource = (FBObject.Colorbuffer) fbo[currentSourceBuffer].getColorbuffer(0);
        gl.glActiveTexture(GL_TEXTURE0);
        gl.glBindTexture(GL_TEXTURE_2D, texSource.getName());
        setShaderUniform1i(gl, currentShader.program(), "textureData", 0);

        if (sencondImage) {
            //activate texture with image from file
            gl.glActiveTexture(GL_TEXTURE1);
            gl.glBindTexture(GL_TEXTURE_2D, textureFile.getTextureObject());
            textureFile.bind(gl);
            setShaderUniform1i(gl, currentShader.program(), "textureImage", 1);
        }

        //draw buffer on screens
       gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, canvasVertices.length / 3);

       //disable texture image
       if (sencondImage) {
           gl.glActiveTexture(GL_TEXTURE1);
           textureFile.disable(gl);
       }
       //disable texture data
       gl.glActiveTexture(GL_TEXTURE0);
       gl.glDisable(texSource.getName());

       gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       gl.glDisableClientState(GL_VERTEX_ARRAY);

   }

  public void renderFBOToScreen()
    {
         gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear color and depth buffers
         gl.glLoadIdentity();  // reset the model-view matrix

         viewOrtho(gl);
        gl.glEnable(GL_TEXTURE_2D); 

        final FBObject.Colorbuffer tex0 = (FBObject.Colorbuffer) fbo[currentDestBuffer].getColorbuffer(0);
        gl.glActiveTexture(GL_TEXTURE0);
        gl.glBindTexture(GL_TEXTURE_2D, tex0.getName());

        //activate shader
        shaderVisu.useProgram(gl, true);

        // --- draw vbo
        gl.glEnableClientState(GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        //textcoords
        gl.glBindBuffer(GL_ARRAY_BUFFER, vboTextCoord);
        gl.glTexCoordPointer(2, GL_FLOAT, 0, 0); 
       //vertices
        gl.glBindBuffer( GL_ARRAY_BUFFER, vboVertices );
        gl.glVertexPointer(3, GL_FLOAT, 0, 0);

        //draw buffer on screens
       gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, canvasVertices.length / 3);

       gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       gl.glDisableClientState(GL_VERTEX_ARRAY);

        gl.glBindBuffer( GL_ARRAY_BUFFER, 0 );
        //desactivate shader
        shaderVisu.useProgram(gl, false);

    }

   private void initFBO()
   {
       try {

       gl.glEnable(GL_TEXTURE_2D);

       fbo = new FBObject[2];

       //first fbo
       fbo[currentSourceBuffer] = new FBObject(); // Create FrameBuffer
       fbo[currentSourceBuffer].init(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0);
       fbo[currentSourceBuffer].reset(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); // int width, height - size of FBO, can be resized with the same call
       fbo[currentSourceBuffer].bind(gl);

       int tex = genTexture(gl);
       gl.glBindTexture(GL_TEXTURE_2D, tex);
       gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_RGBA, GL_FLOAT, null);
       fbo[currentSourceBuffer].attachTexture2D(gl, 0, GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
       //gl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
       int DrawBuffers[] = {GL_COLOR_ATTACHMENT0};
       gl.glDrawBuffers(1, DrawBuffers, 0); // "1" is the size of DrawBuffers
       fbo[currentSourceBuffer].unbind(gl);

       //second fbo
       fbo[currentDestBuffer] = new FBObject(); // Create FrameBuffer
       fbo[currentDestBuffer].init(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0);
       fbo[currentDestBuffer].reset(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); // int width, height - size of FBO, can be resized with the same call
       fbo[currentDestBuffer].bind(gl);

       tex = genTexture(gl);
       gl.glBindTexture(GL_TEXTURE_2D, tex);
       gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_RGBA, GL_FLOAT, null);
       fbo[currentDestBuffer].attachTexture2D(gl, 0, GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
       //ogl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
       gl.glDrawBuffers(1, DrawBuffers, 1); // "1" is the size of DrawBuffers
       fbo[currentDestBuffer].unbind(gl);

       } catch (Exception e) {
           System.out.println("Problem with fbo init " + e);
           e.printStackTrace();
       }

   }

   private Texture initializeTexture() { 

       Texture t = null; 

       try { 
           t = TextureIO.newTexture(new File("e:/shaders/wiki.jpg"), false); 

           t.setTexParameteri(gl, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
           t.setTexParameteri(gl, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
           t.setTexParameteri(gl, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
           t.setTexParameteri(gl, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

       } catch (Exception e) {
           System.out.println("Unable to read texture file: " + e);
           e.printStackTrace();
       }

       return t; 
   } 

   private ShaderProgram loadShader(GL2 gl, String vertexShader, String fragmentShader)
   {
           ShaderCode vertShader = ShaderCode.create(gl, GL2.GL_VERTEX_SHADER, 1, getClass(), new String[]{"e:/shaders/"+vertexShader},false);
           vertShader.compile(gl);

           ShaderCode fragShader = ShaderCode.create(gl, GL2.GL_FRAGMENT_SHADER, 1, getClass(), new String[]{"e:/shaders/"+fragmentShader},false);
           fragShader.compile(gl);

           ShaderProgram newShader = new ShaderProgram();
           newShader.init(gl);
           newShader.add(vertShader);
           newShader.add(fragShader);

           newShader.link(gl, System.out);

           vertShader.destroy(gl);
           fragShader.destroy(gl);

           return newShader;
   }

   public static void setShaderUniform1i(GL2 inGL,int inProgramID,String inName,int inValue) {
       int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName);
       if (tUniformLocation != -1) {
           inGL.glUniform1i(tUniformLocation, inValue);
       } else {
           System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName);
       }
   }

   public static void setShaderUniformFloat(GL2 inGL,int inProgramID,String inName,float inValue) {
       int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName);
       if (tUniformLocation != -1) {
           inGL.glUniform1f(tUniformLocation, inValue);
       } else {
           System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName);
       }
   }
   public static void setShaderUniformFloat2(GL2 inGL,int inProgramID,String inName,float inValue1 ,float inValue2) {
       int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName);
       if (tUniformLocation != -1) {
           inGL.glUniform2f(tUniformLocation, inValue1, inValue2);
       } else {
           System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName);
       }
   }

   private void viewOrtho(GL2 gl)  // Set Up An Ortho View
   {
       gl.glMatrixMode(GL_PROJECTION);  // Select Projection
       gl.glPushMatrix();      // Push The Matrix
       gl.glLoadIdentity();      // Reset The Matrix
       gl.glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 
       gl.glMatrixMode(GL_MODELVIEW);  // Select Modelview Matrix
       gl.glPushMatrix();      // Push The Matrix
       gl.glLoadIdentity();     // Reset The Matrix
   }

   private int genTexture(GL2 gl) {
        final int[] tmp = new int[1];
        gl.glGenTextures(1, tmp, 0);
        return tmp[0];
    }

   /**
    * Called back before the OpenGL context is destroyed. Release resource such as buffers.
    */
   @Override
   public void dispose(GLAutoDrawable drawable) { }
}
包gpu2;
导入java.awt.*;
导入java.awt.event.*;
导入javax.swing.*;
导入java.nio.IntBuffer;
导入java.nio.FloatBuffer;
导入java.io.File;
导入com.jogamp.opengl.GL2;
导入com.jogamp.opengl.GLAutoDrawable;
导入com.jogamp.opengl.GLEventListener;
导入com.jogamp.opengl.awt.GLCanvas;
导入com.jogamp.opengl.glu.glu;
导入com.jogamp.opengl.util.FPSAnimator;
导入com.jogamp.opengl.GLFBODrawable;
导入com.jogamp.opengl.FBObject;
导入com.jogamp.opengl.FBObject.Colorbuffer;
导入com.jogamp.opengl.FBObject.ColorAttachment;
导入com.jogamp.opengl.FBObject.TextureAttachment;
导入com.jogamp.opengl.util.glsl.ShaderCode;
导入com.jogamp.opengl.util.glsl.ShaderProgram;
导入com.jogamp.opengl.util.glsl.ShaderUtil;
导入com.jogamp.opengl.util.GLBuffers;
导入com.jogamp.opengl.util.texture.texture;
导入com.jogamp.opengl.util.texture.TextureIO;
导入com.jogamp.opengl.gl功能;
导入com.jogamp.opengl.gloffscreen自动绘图;
导入com.jogamp.opengl.GLProfile;
导入com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
导入com.jogamp.opengl.GLDrawableFactory;
导入静态com.jogamp.opengl.GL.*;//GL常数
导入静态com.jogamp.opengl.GL2.*//GL2常数
导入gpu2.ModelParam;
/**
*JOGL 2.0程序模板(GLCanvas)
*这是一个“组件”,可以添加到顶级“容器”中。
*它还处理OpenGL事件以渲染图形。
*/
@抑制警告(“串行”)
公共类JOGL2Setup_GLCanvas扩展了GLCanvas实现了GLEventListener{
//为顶级容器定义常量
私有静态字符串TITLE=“JOGL 2.0设置(GLCanvas)”;//窗口的标题
私有静态final int CANVAS_WIDTH=512;//可绘制图形的宽度
private static final int CANVAS_HEIGHT=512;//可绘制图形的高度
private static final int FPS=30;//动画师每秒的目标帧数
私有最终浮动[]画布顶点={
-1f,-1f,0.0f,
-一层,一层,0.0层,
1f,-1f,0.0f,
一层,一层,0.0层,
};
私人最终浮动[]canvasTexCoords={
0.0f,0.0f,
0.0f,1.0f,
1.0f,0.0f,
1.0f,1.0f,
};
/**entry main()方法来设置顶级容器和动画师*/
公共静态void main(字符串[]args){
//在事件调度线程中运行GUI代码以确保线程安全
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
//创建OpenGL渲染画布
GLCanvas canvas=新JOGL2Setup_GLCanvas();
setPreferredSize(新维度(画布宽度、画布高度));
//创建一个动画制作程序,以指定的FPS驱动画布的display()。
最终FPSAnimator animator=新FPSAnimator(画布,FPS,真);
//创建顶级容器
final JFrame=new JFrame();//Swing的JFrame或AWT的frame
frame.getContentPane().add(画布);
frame.addWindowListener(新的WindowAdapter(){
@凌驾
公共无效窗口关闭(WindowEvent e){
//使用专用线程运行stop(),以确保
//动画师在程序退出前停止。
新线程(){
@凌驾
公开募捐{
如果(animator.isStarted())animator.stop();
系统出口(0);
}
}.start();
}
});
frame.setTitle(标题);
frame.pack();
frame.setVisible(true);
animator.start();//启动动画循环
}
});
}
//设置OpenGL图形渲染器
专用GLU GLU;//用于GL实用程序
私人GL2 gl;
//OpenGl数据
私人收费;
私人内部vboTextCoord;
私有纹理文件;
专用fbo对象fbo[];
私有着色器程序着色器计算机;
私有ShaderProgram shaderVisu;
私有着色器程序着色器组件;
私有int currentSourceBuffer=0;
private int currentDestBuffer=1;
私有int currentFrame=0;
私有整数maxFrameCount=5000000;
私有浮动clearUniform=0;
ModelParam params=新的ModelParam();
公共JOGL2设置_GLCanvas(){
this.addGLEventListener(this);
}
@凌驾
公共void init(GLAutoDrawable){
gl=drawable.getGL().getGL2();//获取OpenGL图形上下文
glu=new glu();//获取GL实用程序
gl.glClearColor(0.0f,0.0f,0.0f,0.0f);//设置背景(清晰)颜色
glEnable总图(总图纹理图2D);
glEnable玻璃钢(玻璃钢颜色材料);
gl.glEnable(gl_帧缓冲区);
gl.glHint(gl_PERSPECTIVE_CORRECTION_HINT,gl_NEAREST);//最佳透视校正
viewOrtho(德国劳埃德船级社);
gl.glViewport(0,0,画布宽度,画布高度);
int[]缓冲区=新的int[2];
gl.glGenBuffers(2,buffers,0);
vboVertices=缓冲区[0];
vboTextCoord=缓冲区[1];
gl.glBindBuffer(gl_数组_BUFFER,vboVertices);
gl.glBufferData(gl\u数组\u BUFFER,canvasVertices.length*(Float.SIZE/Byte.SIZE)*3,FloatBuffer.wrap(canvasVertices),gl\u ST
#version 120

uniform sampler2D textureData;
uniform sampler2D textureImage;


uniform vec2 resolution;

uniform float diffuseU;
uniform float diffuseV;
uniform float feed;
uniform float kill;
uniform float Tech = 1.0;
uniform float currentFrame = 0.0;

void main() {
    //coords
    vec2 position = ( gl_FragCoord.xy / resolution.xy );
    vec2 pixel = 1./resolution;

    //get data from texture
    vec4 imgSource = texture2D(textureImage, gl_TexCoord[0].st);
    vec2 oldUV = texture2D(textureData, gl_TexCoord[0].st).rg;

    if(currentFrame<10){
        if (distance(position,vec2(0.5,0.5 - currentFrame * 0.01f)) < 0.2f)
            oldUV =  vec2(0.0,0.2);
        else if (distance(position,vec2(0.5,0.5 - currentFrame * 0.01f)) < 0.3f)
            oldUV =  vec2(0.5,0.1);
        else
            oldUV =  vec2(0.1,0.0);

        gl_FragColor =  vec4(oldUV.rg, 0.0, 1.0);
        return;
    }

    //get neightboors
    vec2 dataUp = texture2D(textureData, position + pixel * vec2(0., 1.)).rg;
    vec2 dataDown = texture2D(textureData, position + pixel * vec2(0., -1.)).rg;
    vec2 dataLeft = texture2D(textureData, position + pixel * vec2(-1., 0.)).rg;
    vec2 dataRight = texture2D(textureData, position + pixel * vec2(1., 0.)).rg;
    //adapt parameters
    vec2 imgParam = imgSource.rg;
    float dU = diffuseU ;//+ 0.01 * (imgParam - 0.5);
    float dV = diffuseV ;//+ 0.01 * (imgParam - 0.5);
    float F = feed ;//+ 0.01 * (imgParam - 0.5);
    float K = kill ;//+ 0.01 * (imgParam - 0.5);
    //compute new values
    vec2 laplace = (dataUp+dataDown+dataLeft+dataRight) - 4.0 * oldUV;
    float uvv = oldUV.r * oldUV.g * oldUV.g;
    // calculate delta quantities
    float du = dU * laplace.r - uvv + F*(1.0 - oldUV.r);
    float dv = dV * laplace.g + uvv - (F+K)*oldUV.g;
    vec2 newUV = oldUV + vec2(du, dv)* Tech;

    gl_FragColor =  vec4(newUV.rg, 0.0, 1.0);
}