OpenGL ES2 的Off-Screen实现

Posted on 2012-10-18 15:28  leon_ALiang  阅读(2669)  评论(0编辑  收藏  举报

OpenGL ES2需要的库:libGLESv2, libEGL

其中libEGL是用于和不同系统的窗口打交道的,是一个标准。如果需要让你显示在窗口中,如调用eglCreateWindowSurface;若off-screen,则eglCreatePbufferSurface。

直接上一下代码:

void esInitContext(ESContext *esContext)
{
   if ( esContext != NULL )
   {
      memset( esContext, 0, sizeof( ESContext) );
   }
}

GLboolean esCreateOffScreen( ESContext *esContext, GLint width, GLint height)
{
   EGLint numConfigs;
   EGLint majorVersion;
   EGLint minorVersion;
   EGLDisplay display;
   EGLContext context;
   EGLSurface surface;
   EGLConfig config;
   EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };

   EGLint cfgAttribs[] =  
   {  
        EGL_SURFACE_TYPE,    EGL_PBUFFER_BIT, 
           EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,  
        //EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
        EGL_RED_SIZE,        5,  
        EGL_GREEN_SIZE,      6,  
        EGL_BLUE_SIZE,       5,  
        EGL_DEPTH_SIZE,      1,  
        EGL_NONE  
    };  

    EGLint PBufAttribs[] =  
    {  
        EGL_WIDTH,  width,  
        EGL_HEIGHT, height,  
        EGL_LARGEST_PBUFFER, EGL_TRUE,  
        EGL_NONE  
    };  
   // Get Display
   display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   if ( display == EGL_NO_DISPLAY )
   {
       return EGL_FALSE;
   }
   // Initialize EGL
   if ( !eglInitialize(display, &majorVersion, &minorVersion) )
   {
       return EGL_FALSE;
   }

   // Get configs
   if ( !eglGetConfigs(display, NULL, 0, &numConfigs) )
   {
       return EGL_FALSE;
   }

   // Choose config
   if ( !eglChooseConfig(display, cfgAttribs, &config, 1, &numConfigs) )
   {
       return EGL_FALSE;
   }

   // Create a surface
   //surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, NULL);
   //surface = eglCreatePixmapSurface(display, config, pixmap, NULL);
   surface = eglCreatePbufferSurface(display, config, PBufAttribs);  
   if ( surface == EGL_NO_SURFACE )
   {
       return EGL_FALSE;
   }

   // Check to see what size pbuffer we were allocated
   EGLint os_width;
   EGLint os_height;
   if(!eglQuerySurface(display, surface, EGL_WIDTH, &os_width) ||
        !eglQuerySurface(display, surface, EGL_HEIGHT, &os_height))
   {
       return EGL_FALSE;
   }

   // Create a GL context
   context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs );
   if ( context == EGL_NO_CONTEXT )
   {
       return EGL_FALSE;
   }   ;

   // Make the context current
   if ( !eglMakeCurrent(display, surface, surface, context) )
   {
       return EGL_FALSE;
   }

   esContext->eglContext = context;
   esContext->eglDisplay = display;
   esContext->eglSurface = surface;
   esContext->width = os_width;
   esContext->height = os_height;
}

void esDipose(ESContext *esContext)
{
    if(esContext->eglContext != EGL_NO_CONTEXT)
        eglDestroyContext(esContext->eglDisplay, esContext->eglContext);
    if(esContext->eglSurface != EGL_NO_SURFACE)
        eglDestroySurface(esContext->eglDisplay, esContext->eglSurface);
    if(esContext->eglDisplay != EGL_NO_DISPLAY)
        eglTerminate(esContext->eglDisplay);

    esContext->eglDisplay = EGL_NO_DISPLAY;
    esContext->eglContext = EGL_NO_CONTEXT;
    esContext->eglSurface = EGL_NO_SURFACE;
}

// Drawing something

画完后,可以用glReadPixels来读取

   GLint size;
   size = esContext->width * esContext->height * 4;
   GLubyte *data = (GLubyte*)malloc(size);
   glPixelStorei(GL_PACK_ALIGNMENT, 4);
   glReadPixels(0,0,esContext->width,esContext->height,GL_RGB,GL_UNSIGNED_BYTE,data);

可以把读出来的位图流写到一个bmp文件中(bmp在windows下默认是按BGR存的,故需要RGB->BGR)

bmp_write(data, esContext->width, esContext->height, "C:\\SimpleTexture2D");

int bmp_write(unsigned char *image, int xsize, int ysize, char *filename) 
{
	unsigned char header[54] = 
	{
		0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,
		54, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0, 
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
		0, 0, 0, 0
	};
	long file_size = (long)xsize * (long)ysize * 3 + 54;
	long width, height;
	char fname_bmp[128];
	FILE *fp;

	header[2] = (unsigned char)(file_size &0x000000ff);
	header[3] = (file_size >> 8) & 0x000000ff;
	header[4] = (file_size >> 16) & 0x000000ff;
	header[5] = (file_size >> 24) & 0x000000ff;

	width = xsize;
	header[18] = width & 0x000000ff;
	header[19] = (width >> 8) &0x000000ff;
	header[20] = (width >> 16) &0x000000ff;
	header[21] = (width >> 24) &0x000000ff;

	height = ysize;
	header[22] = height &0x000000ff;
	header[23] = (height >> 8) &0x000000ff;
	header[24] = (height >> 16) &0x000000ff;
	header[25] = (height >> 24) &0x000000ff;

	sprintf(fname_bmp, "%s.bmp", filename);

	if (!(fp = fopen(fname_bmp, "wb"))) 
		return -1;

	// switch the image data from RGB to BGR
	for(unsigned long imageIdx = 0; imageIdx < file_size; imageIdx+=3)
	{
		unsigned char tempRGB = image[imageIdx];
		image[imageIdx] = image[imageIdx + 2];
		image[imageIdx + 2] = tempRGB;
	}
	
	fwrite(header, sizeof(unsigned char), 54, fp);
	fwrite(image, sizeof(unsigned char), (size_t)(long)xsize * ysize * 3, fp);

	fclose(fp);
	return 0;
}

  

Copyright © 2024 leon_ALiang
Powered by .NET 8.0 on Kubernetes