LWJGL offscreen rending without any window

Started by Faust, May 24, 2010, 13:36:50

Previous topic - Next topic

Faust

Hi,

i am currently considering using my engine as video streaming server with server side offscreen rendering.
The first task to solve is creating a opengl context in oder to create fbos for offscreen rendering.
But i didn't find a way to create the opengl context without creating a window (or going fullscreen) at the same time...

Is there a way to get an opengl context without the window?

Thanks in advance.

Matzon


Faust

I thought pbuffers were primaly used to do offscreen rendering for dynamic textures (-> shader effects).
With FBO you can do the same, but you can only create FBOs once the gl context has been created.

The magic i was searching for has been hiding behind pbuffer.makeCurrent() (or somewhere in the constructor).

I took a look into the pbuffer test application within package org.lwjgl.test.opengl and extracted the necessary stuff from there.
Below is a simplier version of the code which does not create a window and copies back the pbuffer image but outputs it to jpg files.

The time needed for this simple transformation to BufferedImage Integer Raster takes a lot of time, but this will be handled different anyways.

Thanks.

@Matzen: A full sentence would have been nice.

package test;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;

import javax.imageio.ImageIO;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.Pbuffer;
import org.lwjgl.opengl.PixelFormat;
import org.lwjgl.util.glu.GLU;

public class Test
{
  public static void main(String[] args)
  {
    try
    {
      Test test = new Test();
      test.run();
    }
    catch(Throwable t)
    {
      t.printStackTrace();
    }
  }

  public void run() throws LWJGLException, IOException
  {
    final int width = 512;
    final int height = 512;
    
    // init pbuffer
    Pbuffer pbuffer = new Pbuffer(512, 512, new PixelFormat(), null, null);
    pbuffer.makeCurrent();
    
    if(pbuffer.isBufferLost())
    {
      pbuffer.destroy();
      System.exit(-1);
    }
    
    ByteBuffer pixels = BufferUtils.createByteBuffer(width*height*3);
    BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    (new File("output/")).mkdir();

    // setup gl
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GLU.gluOrtho2D(0, width, 0, height);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glLoadIdentity();
    GL11.glViewport(0, 0, width, height);
    GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    
    // main loop
    long allovertime = 0L;
    for(int i=0; i<60; i++)
    {
      final long starttime = System.currentTimeMillis();
        
      GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
      
      GL11.glPushMatrix();
      GL11.glTranslatef(width/2, height/2, 0);
      float t = (System.currentTimeMillis()%5000)/5000.0f;
      GL11.glRotatef(t*360.0f, 0.0f, 0.0f, 1.0f);
      GL11.glBegin(GL11.GL_QUADS);
      {
        GL11.glColor4f(1.0f, 0.0f, 0.0f, 1.0f); GL11.glVertex2i(-50, -50);
        GL11.glColor4f(0.0f, 1.0f, 0.0f, 1.0f); GL11.glVertex2i(50, -50);
        GL11.glColor4f(0.0f, 0.0f, 1.0f, 1.0f); GL11.glVertex2i(50, 50);
        GL11.glColor4f(1.0f, 1.0f, 0.0f, 1.0f); GL11.glVertex2i(-50, 50);
      }
      GL11.glEnd();
      GL11.glPopMatrix();
      
      GL11.glReadPixels(0, 0, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, pixels);

      for(int x=0; x<width; x++) // flip y
      {
        for(int y=0; y<height; y++)
        {
          int pixel = (0xFF << 24)
                     | (((pixels.get()+256)%256)<<16)
                     | (((pixels.get()+256)%256)<<8)
                     | (((pixels.get()+256)%256)<<0);
          bi.setRGB(x, height - (y+1), pixel);
        }
      }
      pixels.rewind();
      ImageIO.write(bi, "jpg", new File("output/ri_" + i + ".jpg"));
      
      final long timeforframe = System.currentTimeMillis() - starttime;
      System.out.println("Rendering frame " + i + " took " + timeforframe + " ms.");
      allovertime += timeforframe;
    }
    
    System.out.println("allover time needed: " + allovertime + " (" + (allovertime/60.0f) + " meantime per frame)");
    
    pbuffer.destroy();
  }
}


Matzon

Quote from: Faust on May 24, 2010, 16:34:30
@Matzen: A full sentence would have been nice.

sorry - too busy playing Revenge of the titans ;)

glad you documented a solution tho :)

jordiperez

That's great! Two questions:

1. Does PBuffers work with OpenGL 1.2?

2. On the glReadPixels is possible to read the zbuffer component?