opengl osmesa - Serbipunk/notes GitHub Wiki

https://learnopengl-cn.readthedocs.io/zh/latest/

https://github.com/devernay/osmesa-install

/*
based on: 
 
https://github.com/JoakimSoderberg/mesademos/blob/master/src/osdemos/osdemo32.c
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <GL/osmesa.h>
#include <GL/glu.h>     //replaced by default header in linux
 
#define SAVE_TARGA
 
#define WIDTH 400
#define HEIGHT 400
 
static void render_image( void )
{
   GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
   GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
   GLfloat red_mat[]   = { 1.0, 0.2, 0.2, 1.0 };
   GLfloat green_mat[] = { 0.2, 1.0, 0.2, 0.5 };
   GLfloat blue_mat[]  = { 0.2, 0.2, 1.0, 1.0 };
   GLfloat white_mat[]  = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat purple_mat[] = { 1.0, 0.2, 1.0, 1.0 };
   GLUquadricObj *qobj = gluNewQuadric();
 
   glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
   glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
 
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_DEPTH_TEST);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0);
   glMatrixMode(GL_MODELVIEW);
 
   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
   glPushMatrix();
   glRotatef(20.0, 1.0, 0.0, 0.0);
 
#if 0
   glPushMatrix();
   glTranslatef(-0.75, 0.5, 0.0); 
   glRotatef(90.0, 1.0, 0.0, 0.0);
   glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat );
   glutSolidTorus(0.275, 0.85, 20, 20);
   glPopMatrix();
#endif
 
   /* red square */
   glPushMatrix();
   glTranslatef(0.0, -0.5, 0.0); 
   glRotatef(90, 1, 0.5, 0);
   glScalef(3, 3, 3);
   glDisable(GL_LIGHTING);
   glColor4f(1, 0, 0, 0.5);
   glBegin(GL_POLYGON);
   glVertex2f(-1, -1);
   glVertex2f( 1, -1);
   glVertex2f( 1,  1);
   glVertex2f(-1,  1);
   glEnd();
   glEnable(GL_LIGHTING);
   glPopMatrix();
 
#if 0
   /* green square */
   glPushMatrix();
   glTranslatef(0.0, 0.5, 0.1); 
   glDisable(GL_LIGHTING);
   glColor3f(0, 1, 0);
   glBegin(GL_POLYGON);
   glVertex2f(-1, -1);
   glVertex2f( 1, -1);
   glVertex2f( 1,  1);
   glVertex2f(-1,  1);
   glEnd();
   glEnable(GL_LIGHTING);
   glPopMatrix();
   /* blue square */
   glPushMatrix();
   glTranslatef(0.75, 0.5, 0.3); 
   glDisable(GL_LIGHTING);
   glColor3f(0, 0, 0.5);
   glBegin(GL_POLYGON);
   glVertex2f(-1, -1);
   glVertex2f( 1, -1);
   glVertex2f( 1,  1);
   glVertex2f(-1,  1);
   glEnd();
   glEnable(GL_LIGHTING);
   glPopMatrix();
#endif
   glPushMatrix();
   glTranslatef(-0.75, -0.5, 0.0); 
   glRotatef(270.0, 1.0, 0.0, 0.0);
   glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat );
   glColor4f(0,1,0,0.5);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   gluCylinder(qobj, 1.0, 0.0, 2.0, 16, 1);
   glDisable(GL_BLEND);
   glPopMatrix();
 
   glPushMatrix();
   glTranslatef(0.75, 1.0, 1.0); 
   glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
   gluSphere(qobj, 1.0, 20, 20);
   glPopMatrix();
 
   glPopMatrix();
 
   /* This is very important!!!
    * Make sure buffered commands are finished!!!
    */
   glFinish();
 
   gluDeleteQuadric(qobj);
 
   {
      GLint r, g, b, a;
      glGetIntegerv(GL_RED_BITS, &r);
      glGetIntegerv(GL_GREEN_BITS, &g);
      glGetIntegerv(GL_BLUE_BITS, &b);
      glGetIntegerv(GL_ALPHA_BITS, &a);
      printf("channel sizes: %d %d %d %d\n", r, g, b, a);
   }
}
 
 
 
static void
write_targa(const char *filename, const GLfloat *buffer, int width, int height)
{
   FILE *f = fopen( filename, "w" );
   if (f) {
      int i, x, y;
      const GLfloat *ptr = buffer;
      printf ("osdemo, writing tga file \n");
      fputc (0x00, f);	/* ID Length, 0 => No ID	*/
      fputc (0x00, f);	/* Color Map Type, 0 => No color map included	*/
      fputc (0x02, f);	/* Image Type, 2 => Uncompressed, True-color Image */
      fputc (0x00, f);	/* Next five bytes are about the color map entries */
      fputc (0x00, f);	/* 2 bytes Index, 2 bytes length, 1 byte size */
      fputc (0x00, f);
      fputc (0x00, f);
      fputc (0x00, f);
      fputc (0x00, f);	/* X-origin of Image	*/
      fputc (0x00, f);
      fputc (0x00, f);	/* Y-origin of Image	*/
      fputc (0x00, f);
      fputc (WIDTH & 0xff, f);      /* Image Width	*/
      fputc ((WIDTH>>8) & 0xff, f);
      fputc (HEIGHT & 0xff, f);     /* Image Height	*/
      fputc ((HEIGHT>>8) & 0xff, f);
      fputc (0x18, f);		/* Pixel Depth, 0x18 => 24 Bits	*/
      fputc (0x20, f);		/* Image Descriptor	*/
      fclose(f);
      f = fopen( filename, "ab" );  /* reopen in binary append mode */
      for (y=height-1; y>=0; y--) {
         for (x=0; x<width; x++) { int r, g, b; i = (y*width + x) * 4; r = (int) (ptr[i+0] * 255.0); g = (int) (ptr[i+1] * 255.0); b = (int) (ptr[i+2] * 255.0); if (r > 255) r = 255;
            if (g > 255) g = 255;
            if (b > 255) b = 255;
            fputc(b, f); /* write blue */
            fputc(g, f); /* write green */
            fputc(r, f); /* write red */
         }
      }
   }
}
 
 
static void
write_ppm(const char *filename, const GLfloat *buffer, int width, int height)
{
   const int binary = 0;
   FILE *f = fopen( filename, "w" );
   if (f) {
      int i, x, y;
      const GLfloat *ptr = buffer;
      if (binary) {
         fprintf(f,"P6\n");
         fprintf(f,"# ppm-file created by osdemo.c\n");
         fprintf(f,"%i %i\n", width,height);
         fprintf(f,"255\n");
         fclose(f);
         f = fopen( filename, "ab" );  /* reopen in binary append mode */
         for (y=height-1; y>=0; y--) {
            for (x=0; x<width; x++) { int r, g, b; i = (y*width + x) * 4; r = (int) (ptr[i+0] * 255.0); g = (int) (ptr[i+1] * 255.0); b = (int) (ptr[i+2] * 255.0); if (r > 255) r = 255;
               if (g > 255) g = 255;
               if (b > 255) b = 255;
               fputc(r, f);   /* write red */
               fputc(g, f); /* write green */
               fputc(b, f); /* write blue */
            }
         }
      }
      else {
         /*ASCII*/
         int counter = 0;
         fprintf(f,"P3\n");
         fprintf(f,"# ascii ppm file created by osdemo.c\n");
         fprintf(f,"%i %i\n", width, height);
         fprintf(f,"255\n");
         for (y=height-1; y>=0; y--) {
            for (x=0; x<width; x++) { int r, g, b; i = (y*width + x) * 4; r = (int) (ptr[i+0] * 255.0); g = (int) (ptr[i+1] * 255.0); b = (int) (ptr[i+2] * 255.0); if (r > 255) r = 255;
               if (g > 255) g = 255;
               if (b > 255) b = 255;
               fprintf(f, " %3d %3d %3d", r, g, b);
               counter++;
               if (counter % 5 == 0)
                  fprintf(f, "\n");
            }
         }
      }
      fclose(f);
   }
}
 
 
int main( int argc, char *argv[] )
{
   GLfloat *buffer;
 
   /* Create an RGBA-mode context */
#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
   /* specify Z, stencil, accum sizes */
   OSMesaContext ctx = OSMesaCreateContextExt( GL_RGBA, 16, 0, 0, NULL );
#else
   OSMesaContext ctx = OSMesaCreateContext( GL_RGBA, NULL );
#endif
   if (!ctx) {
      printf("OSMesaCreateContext failed!\n");
      return 0;
   }
 
   /* Allocate the image buffer */
   buffer = (GLfloat *) malloc( WIDTH * HEIGHT * 4 * sizeof(GLfloat));
   if (!buffer) {
      printf("Alloc image buffer failed!\n");
      return 0;
   }
 
   /* Bind the buffer to the context and make it current */
   if (!OSMesaMakeCurrent( ctx, buffer, GL_FLOAT, WIDTH, HEIGHT )) {
      printf("OSMesaMakeCurrent failed!\n");
      return 0;
   }
 
   render_image();
 
   if (argc>1) {
#ifdef SAVE_TARGA
      write_targa(argv[1], buffer, WIDTH, HEIGHT);
#else
      write_ppm(argv[1], buffer, WIDTH, HEIGHT);
#endif
   }
   else {
      printf("Specify a filename if you want to make an image file\n");
   }
 
   printf("all done\n");
 
   /* free the image buffer */
   free( buffer );
 
   /* destroy the context */
   OSMesaDestroyContext( ctx );
 
   return 0;
}
/*
 * Example program for creating an OpenGL context with EGL for offscreen
 * rendering with a framebuffer.
 *
 *
 * The MIT License (MIT)
 * Copyright (c) 2014 Sven-Kristofer Pilz
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <iostream>
#include <sstream>
#include <stdexcept>

/*
 * OpenCV for saving the render target as an image file.
 */
#include <opencv2/opencv.hpp>

/*
 * EGL headers.
 */
#include <EGL/egl.h>

/*
 * OpenGL headers.
 */
#define GL_GLEXT_PROTOTYPES 1
#include <GL/gl.h>
#include <GL/glext.h>

using namespace std;

void assertOpenGLError(const std::string& msg) {
    GLenum error = glGetError();

    if (error != GL_NO_ERROR) {
        stringstream s;
        s << "OpenGL error 0x" << std::hex << error << " at " << msg;
        throw runtime_error(s.str());
    }
}

void assertEGLError(const std::string& msg) {
    EGLint error = eglGetError();

    if (error != EGL_SUCCESS) {
        stringstream s;
        s << "EGL error 0x" << std::hex << error << " at " << msg;
        throw runtime_error(s.str());
    }
}

int main(int argc, char** argv) {
    /*
     * EGL initialization and OpenGL context creation.
     */
    EGLDisplay display;
    EGLConfig config;
    EGLContext context;
    EGLSurface surface;
    EGLint num_config;

    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    assertEGLError("eglGetDisplay");

    eglInitialize(display, nullptr, nullptr);
    assertEGLError("eglInitialize");

    eglChooseConfig(display, nullptr, &config, 1, &num_config);
    assertEGLError("eglChooseConfig");

    eglBindAPI(EGL_OPENGL_API);
    assertEGLError("eglBindAPI");

    context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);
    assertEGLError("eglCreateContext");

    //surface = eglCreatePbufferSurface(display, config, nullptr);
    //assertEGLError("eglCreatePbufferSurface");

    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
    assertEGLError("eglMakeCurrent");


    /*
     * Create an OpenGL framebuffer as render target.
     */
    GLuint frameBuffer;
    glGenFramebuffers(1, &frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
    assertOpenGLError("glBindFramebuffer");


    /*
     * Create a texture as color attachment.
     */
    GLuint t;
    glGenTextures(1, &t);

    glBindTexture(GL_TEXTURE_2D, t);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 500, 500, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    assertOpenGLError("glTexImage2D");

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);


    /*
     * Attach the texture to the framebuffer.
     */
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, t, 0);
    assertOpenGLError("glFramebufferTexture2D");


    /*
     * Render something.
     */
    glClearColor(0.9, 0.8, 0.5, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glFlush();


    /*
     * Read the framebuffer's color attachment and save it as a PNG file.
     */
    cv::Mat image(500, 500, CV_8UC3);
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glReadPixels(0, 0, 500, 500, GL_BGR, GL_UNSIGNED_BYTE, image.data);
    assertOpenGLError("glReadPixels");

    std::string output_dir(argv[1]);
    cv::imwrite(output_dir + "img.png", image);


    /*
     * Destroy context.
     */
    glDeleteFramebuffers(1, &frameBuffer);
    glDeleteTextures(1, &t);

    //eglDestroySurface(display, surface);
    //assertEGLError("eglDestroySurface");

    eglDestroyContext(display, context);
    assertEGLError("eglDestroyContext");

    eglTerminate(display);
    assertEGLError("eglTerminate");

    return 0;
}
find_package(Eigen3)
find_package(OpenCV)
find_package(GLEW)
include_directories(
        ${OpenCV_INCLUDE_DIRS}
        ${EIGEN3_INCLUDE_DIR}
        ${PROJECT_SOURCE_DIR}/include
)
link_directories(
        /usr/local/lib
)

if (POLICY CMP0072)
    set(OpenGL_GL_PREFERENCE LEGACY)
endif()
find_package(OpenGL)
find_library(GLFW3_LIBRARY NAMES glfw3 glfw)

############## fast validation ##############
add_executable(fast_validation_demo fast_validation_demo.cpp)
target_link_libraries(fast_validation_demo
#        X11
#        GLEW
#        GL
        glut
        glutils
        ${OpenCV_LIBS}
        ${OPENGL_gl_LIBRARY}
        )


############## EGL Demo ##############
add_executable(egl_demo egl_demo.cpp)
target_link_libraries(egl_demo
        glutils
        EGL
        ${OpenCV_LIBS}
        ${OPENGL_gl_LIBRARY}
        )


############## glfw demo ##############
include_directories(
        /usr/local/include
)

add_executable(glfw_demo glfw_demo.cpp)
target_link_libraries(glfw_demo
        glutils
        glad
        glfw3
        ${OpenCV_LIBS}
        )

⚠️ **GitHub.com Fallback** ⚠️