c# - OpenGL v1.1: Off-screen rendering or render directly to bitmap -
i'm using opengl c#, using csgl12 interface our project. i'm attempting draw number of 4-point free-transformed images onto bitmap in memory.
is there way either:
- directly render bitmap on memory, or,
- render off-screen instance, , convert bitmap? need know how setup off-screen instance conversion.
either method must work on remote desktop, virtual machine, , on panasonic cf-19 toughbook (i.e. opengl v1.1). if possible, providing example code related tremendously.
you know, opengl-1.1 outdated nowadays. crappiest gpus on market can opengl-1.4 now. 1 thing should know first is, opengl has been designed getting pictures on screen, although nature of output backend keept abstract in specification. if want use opengl render 3d stuff accelerated, don't render bitmaps. fall software rasterization mode, extremely slow use pbuffer or framebuffer object. framebuffer objects straigtforward use. pbuffers little bit tricky.
in windows need take detour on creating dummy window opengl context first, can request , use opengl extensions. using x11/glx 1 can create pbuffer without dummy window. usual use pbuffer used place contents dynamic textures created.
the following code wrote ages ago, , silently assumes existing, validly initialized opengl context active on current thread, , configure pbuffer context share opengl objects original context. depends on library glew.
pbuffer.h
#ifndef pbuffer_h #define pbuffer_h #ifdef win32 #include <gl/wglew.h> #endif #ifdef glx #ifdef noglew #include <gl/glx.h> #else #include <gl/glxew.h> #endif #endif class pbuffer { public: pbuffer(int width, int height); virtual ~pbuffer(); void use(); void release(); int const get_width() const { return width; } int const get_height() const { return height; } private: void create(); void destroy(); protected: int width; int height; bool initialized; #ifdef win32 hpbufferarb hpb; hglrc hpbrc; hdc hpbdc; hdc hgldc; hglrc hglrc; #endif #ifdef glx display *dpy; int scrnum; glxcontext pbrc; glxpbuffer pbdc; glxcontext fbrc; glxdrawable fbdc; #endif }; #endif/*pbuffer_h*/
pbuffer.cpp
#include <stdexcept> #include <gl/glew.h> #include "pbuffer.h" using namespace std; #ifdef win32 pbuffer::pbuffer(int width, int height) { initialized=false; this->width=width; this->height=height; hgldc = wglgetcurrentdc(); hglrc = wglgetcurrentcontext(); create(); } pbuffer::~pbuffer() { destroy(); } void pbuffer::use() { // make sure pbuffer has been initialized if (!initialized) { throw runtime_error("pbuffer not initialized"); } // make sure haven't lost our pbuffer due display mode change int flag = 0; wglquerypbufferarb(hpb, wgl_pbuffer_lost_arb, &flag); if (flag) { throw runtime_error("pbuffer became invalid"); } wglmakecurrent(hpbdc, hpbrc); glviewport(0, 0, width, height); gldrawbuffer(gl_front); glreadbuffer(gl_front); } void pbuffer::release() { // make sure pbuffer has been initialized if ( !initialized ) { throw runtime_error("pbuffer not initialized"); } // make sure haven't lost our pbuffer due display mode change int flag = 0; wglquerypbufferarb(hpb, wgl_pbuffer_lost_arb, &flag); if (flag) { throw runtime_error("pbuffer became invalid"); } wglmakecurrent(hgldc, hglrc); } void pbuffer::create() { if(initialized) { destroy(); } if (hgldc == null) { throw runtime_error("unable device context"); } if (hglrc == null) { throw runtime_error("unable render context"); } // define minimum pixel format requirements need our pbuffer // pbuffer frame buffer, can have depth buffer associated // , can double buffered. int attr[] = { wgl_support_opengl_arb, true, // pbuffer used gl wgl_draw_to_pbuffer_arb, true, // enable render pbuffer wgl_red_bits_arb, 16, // @ least 8 bits red channel wgl_green_bits_arb, 16, // @ least 8 bits green channel wgl_blue_bits_arb, 16, // @ least 8 bits blue channel wgl_alpha_bits_arb, 16, // @ least 8 bits alpha channel wgl_depth_bits_arb, 24, // @ least 24 bits depth buffer wgl_double_buffer_arb, false, // dont require double buffering 0 // 0 terminates list }; // choose pixel format meets our minimum requirements unsigned int count = 0; int pixelformat; wglchoosepixelformatarb(hgldc,(const int*)attr, null, 1,&pixelformat,&count); if(count == 0) { throw runtime_error("no matching pbuffer pixel format found"); } int attribs[]={0,0}; // allocate pbuffer hpb = wglcreatepbufferarb(hgldc, pixelformat, width, height, attribs); hpbdc = wglgetpbufferdcarb(hpb); hpbrc = wglcreatecontext(hpbdc); wglsharelists(hglrc, hpbrc); initialized=true; } void pbuffer::destroy() { // make sure pbuffer has been initialized if ( !initialized ) { throw runtime_error("pbuffer not initialized"); } release(); wgldeletecontext(hpbrc); wglreleasepbufferdcarb(hpb, hpbdc); wgldestroypbufferarb(hpb); initialized = false; } #endif #ifdef glx pbuffer::pbuffer(int width, int height) { initialized=false; this->width=width; this->height=height; dpy = glxgetcurrentdisplay(); scrnum = defaultscreen( dpy ); fbrc = glxgetcurrentcontext(); fbdc = glxgetcurrentdrawable(); create(); } pbuffer::~pbuffer() { destroy(); } void pbuffer::use() { // make sure pbuffer has been initialized if (!initialized) { throw runtime_error("pbuffer not initialized"); } // make sure haven't lost our pbuffer due display mode change // resize view port. you'll want set // size of pbuffer render entire pbuffer // there cases might want render // sub-region of pbuffer. glxmakecontextcurrent(dpy, pbdc, pbdc, pbrc); glviewport(0, 0, width, height); gldrawbuffer(gl_front); glreadbuffer(gl_front); } void pbuffer::release() { // make sure pbuffer has been initialized if ( !initialized ) { throw runtime_error("pbuffer not initialized"); } // make sure haven't lost our pbuffer due display mode change glxmakecontextcurrent(dpy, fbdc, fbdc, fbrc); } void pbuffer::create() { if(initialized) { destroy(); } if (dpy == null) { throw runtime_error("unable device context"); } if (!fbdc) { throw runtime_error("unable render context"); } // define minimum pixel format requirements need our pbuffer // pbuffer frame buffer, can have depth buffer associated // , can double buffered. /*int attr[] = { glx_render_type, glx_rgba_bit, glx_drawable_type, glx_pbuffer_bit | glx_window_bit, glx_doublebuffer, false, glx_red_size, 1, glx_green_size, 1, glx_blue_size, 1, glx_alpha_size, 1, glx_depth_size, 1, 0 // 0 terminates list };*/ int attrib[] = { glx_doublebuffer, false, glx_red_size, 8, glx_green_size, 8, glx_blue_size, 8, glx_alpha_size, 8, glx_stencil_size, 1, glx_depth_size, 24, glx_render_type, glx_rgba_bit, glx_drawable_type, glx_pbuffer_bit | glx_window_bit, none }; int pbattrib[] = { glx_pbuffer_width, width, glx_pbuffer_height, height, glx_largest_pbuffer, false, none }; // choose pixel format meets our minimum requirements int count = 0; //glxfbconfigsgix *config= // glxchoosefbconfigsgix(dpy, scrnum, attrib, &count); glxfbconfig *config= glxchoosefbconfig(dpy, scrnum, attrib, &count); if(config == null || count == 0) { throw runtime_error("no matching pbuffer pixel format found"); } // allocate pbuffer //pbdc=glxcreateglxpbuffersgix(dpy, config[0], width, height, pbattrib); //pbrc=glxcreatecontextwithconfigsgix(dpy, config[0], glx_rgba_type_sgix, fbrc, true); pbdc=glxcreatepbuffer(dpy, config[0], pbattrib); pbrc=glxcreatenewcontext(dpy, config[0], glx_rgba_type, fbrc, true); xfree(config); initialized=true; } void pbuffer::destroy() { // make sure pbuffer has been initialized if ( !initialized ) { throw runtime_error("pbuffer not initialized"); } release(); glxdestroycontext(dpy, pbrc); glxdestroypbuffer(dpy, pbdc); initialized = false; } #endif
Comments
Post a Comment