Need help - Sharing texture b/w contexts

classic Classic list List threaded Threaded
1 message Options
gfs
Reply | Threaded
Open this post in threaded view
|

Need help - Sharing texture b/w contexts

gfs
This post was updated on .
I want to reuse my textures when my GLCanvas is moved to another AWT container, for this I'm trying to use shared contexts but my textures are lost when changing container. I can't figure out what I'm doing wrong or how to properly conserve my textures so they are not lost.

import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.DefaultGLCapabilitiesChooser;
import static com.jogamp.opengl.GL.GL_ARRAY_BUFFER;
import static com.jogamp.opengl.GL.GL_COLOR_BUFFER_BIT;
import static com.jogamp.opengl.GL.GL_DEPTH_BUFFER_BIT;
import static com.jogamp.opengl.GL.GL_DEPTH_TEST;
import static com.jogamp.opengl.GL.GL_FLOAT;
import static com.jogamp.opengl.GL.GL_LEQUAL;
import static com.jogamp.opengl.GL.GL_STATIC_DRAW;
import static com.jogamp.opengl.GL.GL_TEXTURE0;
import static com.jogamp.opengl.GL.GL_TEXTURE_2D;
import static com.jogamp.opengl.GL.GL_TRIANGLES;
import static com.jogamp.opengl.GL2ES2.GL_COMPILE_STATUS;
import static com.jogamp.opengl.GL2ES2.GL_FRAGMENT_SHADER;
import static com.jogamp.opengl.GL2ES2.GL_LINK_STATUS;
import static com.jogamp.opengl.GL2ES2.GL_VERTEX_SHADER;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GL4;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLOffscreenAutoDrawable;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.awt.AWTTextureIO;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.joml.Matrix4f;
import org.joml.Vector3f;

public class textureShare implements GLEventListener {

  private final int vao[] = new int[1];
  private final int vbo[] = new int[2];
  private int rendering_program;
  private final FloatBuffer vals = Buffers.newDirectFloatBuffer(16);
  private Matrix4f pMat = new Matrix4f();
  private final Matrix4f mMat = new Matrix4f();
  private int mvLoc, projLoc;
  private float aspect;
  private final Vector3f sphereLoc;
  private Texture texture;
  private TextureData textureData;
  private boolean updateImage;
  private final int fov;

  public static void main(String[] args) {
    BufferedImage img;
    try {
      Class currentClass = new Object() {
      }.getClass().getEnclosingClass();
      ClassLoader classLoader = currentClass.getClassLoader();
      img = ImageIO.read(classLoader.getResourceAsStream(("earth.jpg")));
    } catch (IOException ex) {
      Class currentClass = new Object() {
      }.getClass().getEnclosingClass();
      Logger.getLogger(currentClass.getName()).log(Level.SEVERE, null, ex);
      return;
    }
    GLProfile profile = GLProfile.get(GLProfile.GL2);
    GLCapabilities caps = new GLCapabilities(profile);
    caps.setOnscreen(false);
    caps.setHardwareAccelerated(true);
    caps.setDoubleBuffered(true);
    caps.setBackgroundOpaque(false);
    GLDrawableFactory factory = GLDrawableFactory.getFactory(profile);

    GLOffscreenAutoDrawable offScreenDrawable = factory.createOffscreenAutoDrawable(factory.getDefaultDevice(), caps, new DefaultGLCapabilitiesChooser(), 300, 300);
    textureShare ts = new textureShare(img);
    offScreenDrawable.addGLEventListener(ts);
    offScreenDrawable.display();

    GLCanvas glc2 = new GLCanvas();
    JFrame jFrame = new JFrame();
    JPanel jp = new JPanel(new BorderLayout());
    JButton jb = new JButton("New Frame");
    jp.add(jb, BorderLayout.SOUTH);
    jp.add(glc2, BorderLayout.CENTER);
    jFrame.add(jp);
    jFrame.setSize(600, 600);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    textureShare ts2 = new textureShare();
    glc2.setSharedContext(offScreenDrawable.getContext());
    ts2.setShared(ts);
    glc2.addGLEventListener(ts2);
    jFrame.setVisible(true);
    jb.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        jFrame.getContentPane().removeAll();
        jFrame.add(jp);
        jFrame.setSize(600, 600);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setVisible(true);
      }
    });
  }
  private textureShare sharedSphere;
  private BufferedImage image;

  public textureShare() {
    sphereLoc = new Vector3f(0, 0, -2);
    fov = 90;
  }

  public textureShare(BufferedImage image) {
    this();
    this.image = image;
  }

  @Override
  public void init(GLAutoDrawable glad) {
    rendering_program = createShaderProgram();
    GL4 gl = glad.getContext().getGL().getGL4();
    setupVertices(gl);
    mMat.translation(sphereLoc);
    texture = new Texture(GL_TEXTURE_2D);
    if (image != null) {
      textureData = AWTTextureIO.newTextureData(gl.getGLProfile(),
              image, true);
      texture.updateImage(gl, textureData);
    }
  }

  public void setShared(textureShare shared) {
    sharedSphere = shared;
  }

  @Override
  public void dispose(GLAutoDrawable glad) {
    GL4 gl = glad.getGL().getGL4();
    gl.glDeleteProgram(rendering_program);
    gl.glDeleteVertexArrays(vao.length, vao, 0);
    gl.glDeleteBuffers(vbo.length, vbo, 0);
    texture.destroy(gl);
  }

  @Override
  public void display(GLAutoDrawable glad) {
    GL4 gl = glad.getGL().getGL4();
    if (sharedSphere != null) {
      texture = sharedSphere.getTexture();
    }
    gl.glClear(GL_DEPTH_BUFFER_BIT);
    gl.glClear(GL_COLOR_BUFFER_BIT);
    gl.glUseProgram(rendering_program);
    mvLoc = gl.glGetUniformLocation(rendering_program, "mv_matrix");
    projLoc = gl.glGetUniformLocation(rendering_program, "proj_matrix");

    gl.glUniformMatrix4fv(mvLoc, 1, false, mMat.get(vals));
    gl.glUniformMatrix4fv(projLoc, 1, false, pMat.get(vals));

    gl.glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    gl.glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
    gl.glEnableVertexAttribArray(0);

    gl.glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    gl.glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
    gl.glEnableVertexAttribArray(1);

    gl.glEnable(GL_DEPTH_TEST);
    gl.glDepthFunc(GL_LEQUAL);
//    gl.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    gl.glActiveTexture(GL_TEXTURE0);
    texture.enable(gl);
    texture.bind(gl);
    gl.glDrawArrays(GL_TRIANGLES, 0, 18);
    texture.disable(gl);
  }

  @Override
  public void reshape(GLAutoDrawable glad, int x, int y, int widht, int height) {
    /*http://forum.jogamp.org/canvas-not-filling-frame-td4040092.html#a4040138*/
    GL4 gl = glad.getGL().getGL4();
    gl.glViewport(0, 0, widht, height);
    aspect = (float) widht / (float) height;
    pMat.setPerspective((float) Math.toRadians(fov), aspect, 0.1f, 1000.0f);
  }

  private void setupVertices(GL4 gl) {
    float[] pyramid_positions
            = {-1, -1, 1, 1, -1, 1, 0, 1, 0, //front
              1, -1, 1, 1, -1, -1, 0, 1, 0,//right face
              1, -1, -1, -1, -1, -1, 0, 1, 0, //back face
              -1, -1, -1, -1, -1, 1, 0, 1, 0, //left face
              -1, -1, -1, 1, -1, 1, -1, -1, 1, // base-left block
              1, -1, 1, -1, -1, -1, 1, -1, -1 // base - right block
          };
    float[] pyr_texture_coordinates
            = {0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 1.0f,
              0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 1.0f,
              0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f};

    gl.glGenVertexArrays(vao.length, vao, 0);
    gl.glBindVertexArray(vao[0]);
    gl.glGenBuffers(vbo.length, vbo, 0);

    gl.glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    FloatBuffer pyrBuf = Buffers.newDirectFloatBuffer(pyramid_positions);
    gl.glBufferData(GL_ARRAY_BUFFER, pyrBuf.limit() * 4, pyrBuf,
            GL_STATIC_DRAW);
    gl.glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    FloatBuffer pTexBuf
            = Buffers.newDirectFloatBuffer(pyr_texture_coordinates);
    gl.glBufferData(GL_ARRAY_BUFFER, pTexBuf.limit() * 4, pTexBuf,
            GL_STATIC_DRAW);
  }

  public Texture getTexture() {
    return texture;
  }

  public static int createShaderProgram() {
    int[] vertCompiled = new int[1];
    int[] fragCompiled = new int[1];
    int[] linked = new int[1];
    GL3 gl = (GL3) GLContext.getCurrentGL();
    String[] vshaderSource = new String[]{"#version 400\n"
      + "layout (location=0) in vec3 pos;\n"
      + "layout (location=1) in vec2 texCoord;\n"
      + "out vec2 tc; \n"
      + "uniform mat4 mv_matrix;\n"
      + "uniform mat4 proj_matrix;\n"
      + "void main(void)\n"
      + "{ gl_Position = proj_matrix * mv_matrix * vec4(pos,1.0);\n"
      + "tc = texCoord;\n"
      + "}"};
    String[] fshaderSource = new String[]{"#version 400\n"
      + "in vec2 tc; \n"
      + "out vec4 color;\n"
      + "uniform sampler2D samp;\n"
      + "void main(void)\n"
      + "{ color = texture(samp, tc);\n"
      + "}\n"
      + ""};
    int vShader = gl.glCreateShader(GL_VERTEX_SHADER);
    gl.glShaderSource(vShader, vshaderSource.length, vshaderSource, null, 0);
    gl.glCompileShader(vShader);
    gl.glGetShaderiv(vShader, GL_COMPILE_STATUS, vertCompiled, 0);
    if (vertCompiled[0] != 1) {
      System.out.println("vertex compilation failed.");
    }

    int fShader = gl.glCreateShader(GL_FRAGMENT_SHADER);
    gl.glShaderSource(fShader, fshaderSource.length, fshaderSource, null, 0);
    gl.glCompileShader(fShader);
    gl.glGetShaderiv(fShader, GL_COMPILE_STATUS, fragCompiled, 0);
    if (fragCompiled[0] != 1) {
      System.out.println("fragment compilation failed.");
    }

    if ((vertCompiled[0] != 1) || (fragCompiled[0] != 1)) {
      System.out.println("\nCompilation error; return-flags:");
      System.out.println(" vertCompiled = " + vertCompiled[0]
              + "fragCompiled =  " + fragCompiled[0]);
    }

    int vfprogram = gl.glCreateProgram();
    gl.glAttachShader(vfprogram, vShader);
    gl.glAttachShader(vfprogram, fShader);
    gl.glLinkProgram(vfprogram);

    gl.glGetProgramiv(vfprogram, GL_LINK_STATUS, linked, 0);
    if (linked[0] != 1) {
      System.out.println("vfprogram linking failed.");
    }
    gl.glDeleteShader(vShader);
    gl.glDeleteShader(fShader);
    return vfprogram;
  }
}