summaryrefslogtreecommitdiff
path: root/tests/OffscreenContext.cc
blob: f2a7e9c274b223404c82270d94ec819c379eba54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "OffscreenContext.h"

#include <GL/gl.h>
#include <GL/glu.h>      // for gluCheckExtension
#include <SDL.h>

// Simple error reporting macros to help keep the sample code clean
#define REPORT_ERROR_AND_EXIT(desc) { std::cout << desc << "\n"; return false; }
#define NULL_ERROR_EXIT(test, desc) { if (!test) REPORT_ERROR_AND_EXIT(desc); }

struct OffscreenContext
{
  int width;
  int height;
  GLuint fbo;
  GLuint colorbo;
  GLuint depthbo;
};


OffscreenContext *create_offscreen_context(int w, int h)
{
  OffscreenContext *ctx = new OffscreenContext;
  ctx->width = w;
  ctx->height = h;

  // dummy window 
  SDL_Init(SDL_INIT_VIDEO);
  SDL_SetVideoMode(10,10,32,SDL_OPENGL);

  /*
   * Test if framebuffer objects are supported
   */
  const GLubyte* strExt = glGetString(GL_EXTENSIONS);
  GLboolean fboSupported = gluCheckExtension((const GLubyte*)"GL_EXT_framebuffer_object", strExt);
  if (!fboSupported)
    REPORT_ERROR_AND_EXIT("Your system does not support framebuffer extension - unable to render scene");
  /*
   * Create an FBO
   */
  GLuint renderBuffer = 0;
  GLuint depthBuffer = 0;
  // Depth buffer to use for depth testing - optional if you're not using depth testing
  glGenRenderbuffersEXT(1, &depthBuffer);
  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24,  w, h);
  REPORTGLERROR("creating depth render buffer");

  // Render buffer to use for imaging
  glGenRenderbuffersEXT(1, &renderBuffer);
  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderBuffer);
  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, w, h);
  REPORTGLERROR("creating color render buffer");
  ctx->fbo = 0;
  glGenFramebuffersEXT(1, &ctx->fbo);
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->fbo);
  REPORTGLERROR("binding framebuffer");

  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 
                               GL_RENDERBUFFER_EXT, renderBuffer);
  REPORTGLERROR("specifying color render buffer");

  if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != 
      GL_FRAMEBUFFER_COMPLETE_EXT)
    REPORT_ERROR_AND_EXIT("Problem with OpenGL framebuffer after specifying color render buffer.");

  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 
                               GL_RENDERBUFFER_EXT, depthBuffer);
  REPORTGLERROR("specifying depth render buffer");

  if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != 
      GL_FRAMEBUFFER_COMPLETE_EXT)
    REPORT_ERROR_AND_EXIT("Problem with OpenGL framebuffer after specifying depth render buffer.");

  return ctx;
}

bool teardown_offscreen_context(OffscreenContext *ctx)
{
  // "un"bind my FBO
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

  /*
   * Cleanup
   */
  return true;
}

void write_targa(const char *filename, GLubyte *pixels, int width, int height)
{
	FILE *f = fopen( filename, "w" );
	int y;
	if (f) {
		GLubyte header[] = {
			00,00,02, 00,00,00, 00,00,00, 00,00,00,
			0xff & width, 0xff & width >> 8,
			0xff & height, 0xff & height >> 8,
			32, 0x20 }; // next-to-last = bit depth
		fwrite( header, sizeof(header), 1, f);
		for (y=height-1; y>=0; y--)
			fwrite( pixels + y*width*4, 4, width, f);
		fclose(f);
	}
}

bool save_framebuffer(OffscreenContext *ctx, const char *filename)
{
  /*
   * Extract the resulting rendering as an image
   */

  int samplesPerPixel = 4; // R, G, B and A

  GLubyte pixels[ ctx->width * ctx->height * samplesPerPixel ];
  glReadPixels(0, 0, ctx->width, ctx->height, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
  printf("writing %s\n",filename);
  write_targa(filename,pixels,ctx->width, ctx->height);

  return true;
}

void bind_offscreen_context(OffscreenContext *ctx)
{
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->fbo);
}
contact: Jan Huwald // Impressum