2016-04-18 11 views
1

JOGLとGLSLを使ってGPUに反応拡散モデルを実装しようとしました。GP/GPU:JOGLを使ったピンポン技術

私は2つのFramebufferObjectを持つピンポン技術を使用しています(私は1つのFBOと2つの色の添付ファイルで成功しませんでした)。 Shaderは私が統一的に(いくつかの順応で)試してきたので正しいと思われ、動作します。 多くのことを試してから1週間後、私はこのコードを動作させるために完全に考えていません。私は本当にJOGLの専門家ではないので、明らかに何かが間違っているかもしれません。

結果は、時間の経過と共に白くなる画像です:反応拡散現象がなく、なぜわかりません!

ご協力いただきありがとうございます。

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) { } 
} 

と、対応するGLSLシェーダ:

#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); 
} 

答えて

0

少数の考慮事項:

  • 回避のOpenGL(およびGLU)非推奨、GL4(またはGL3)を使用

    ここに私のコードです
  • awt/swt/swingが必要な場合を除き、newtを好む場合以外はhere

  • は、そうでない場合JOGLは、下にそれらを作成する必要があり、あなたが跡を維持することはできませんので、よりhere

  • は、配列の代わりに直接バッファを好む、代わりにFPSAnimatorAnimator好むネイティブ割り当ての(= DEALLOCATE行われたときに)

  • GL4はあなたにも、すべてのものを均一オーバーヘッド(とも潜在的なバグを)避けることができますあなたは(ランタイム時に特に)に対処する必要が、明示的な場所のおかげ

  • PRあなたが実際にFBObjectが何をしているのか分からない限り、FBObjectの代わりに直接バッファ管理を行います。一旦それを働かせたら、あなたはそのクラスを使って進むことができます。これは、あなたが必要とするようなものがセットアップされていないため、コードが機能しない(原因の1つ)ことがあります。また、FBObjectを交換するために必要なコードの行は本質的に同じ

  • (あなたが何らかの理由で明示的な場所を使用できない場合)、それは通常、原因別のトリッキーな部分である、テクスチャ均一な場所を定義するためにいくつかのリテラルの方法を好みますバグ、this

  • のようなものでもテクスチャのサンプラーを好むが、あなたはより多くの柔軟性を提供します

  • は、私たちが先に知らせて、1週間次の時間を待ってはいけません! :)挫折は簡単にあなたを落とす厄介なことになる可能性があります。一緒に私たちはあなたがそれが働くことを手助けすることができます;)

+0

うわー!これらのすべての考慮事項のために多くのありがとう。特に最後のもの;)私はそれが動作するようにしようとそれに従います – Konzto