imx6 GPU 后台离屏绘制3D图

2023-10-31 11:40
文章标签 3d gpu 绘制 后台 imx6 离屏

本文主要是介绍imx6 GPU 后台离屏绘制3D图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

fsl的官方资料可以作为参考:https://download.csdn.net/download/ruhailiu126/10864713

官方并未提供offscreen离屏渲染例子

以下采用c++操作,后台离屏将3D图存储为图片。关键代码记录笔记如下:

初始化:

  static const EGLint s_configAttribs[] =
    {
        EGL_SURFACE_TYPE,  EGL_PBUFFER_BIT,
        EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT,
        EGL_RED_SIZE,  8,
        EGL_GREEN_SIZE,  8,
        EGL_BLUE_SIZE,  8,
        EGL_ALPHA_SIZE,  8,
   //   #  EGL_SAMPLES,  0,
        EGL_NONE
    };

 

    EGLint numconfigs;

 


    eglNativeDisplayType = fsl_getNativeDisplay();
    egldisplay = eglGetDisplay(eglNativeDisplayType);
    eglInitialize(egldisplay, NULL, NULL);
    assert(eglGetError() == EGL_SUCCESS);
    eglBindAPI(EGL_OPENGL_ES_API);

 

    eglChooseConfig(egldisplay, s_configAttribs, &eglconfig, 1, &numconfigs);
    assert(eglGetError() == EGL_SUCCESS);
    assert(numconfigs == 1);

 

    eglNativeWindow = fsl_createwindow(egldisplay, eglNativeDisplayType);
    assert(eglNativeWindow);

 

#if 0
    eglsurface = eglCreateWindowSurface(egldisplay, eglconfig, eglNativeWindow, NULL);
#else
    EGLint attribListPbuffer[] = {
            // The NDK code would never draw to Pbuffer, so it's not neccessary to
            // match anything.
            EGL_WIDTH, width,
            EGL_HEIGHT, height,
            EGL_NONE };
    eglsurface = eglCreatePbufferSurface(egldisplay,eglconfig,attribListPbuffer);
#endif

 

    assert(eglGetError() == EGL_SUCCESS);
    EGLint ContextAttribList[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };

 

    eglcontext = eglCreateContext( egldisplay, eglconfig, EGL_NO_CONTEXT, ContextAttribList );
    assert(eglGetError() == EGL_SUCCESS);
    eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglcontext);
    assert(eglGetError() == EGL_SUCCESS);

 

   GLuint texture,renderBuffer,frameBuffer;
   glActiveTexture(GL_TEXTURE0);
   glGenTextures(1,&texture);
   glBindTexture(GL_TEXTURE_2D,texture);
   glPixelStorei(GL_UNPACK_ALIGNMENT,1);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,pImageData);

 

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

 

   glGenFramebuffers(1, &frameBuffer);
   glGenRenderbuffers(1, &renderBuffer);
   glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
   glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
   glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, width,height);
   glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
          GL_RENDERBUFFER, renderBuffer);

 

   if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
   {
          qDebug()<<"Image Handler initImageFBO failed!\n";
          return -1;
   }

 

    {
       glViewport(0,0,width,height);

 

        // Compile the shaders
        GLuint hVertexShader = glCreateShader( GL_VERTEX_SHADER );
        glShaderSource( hVertexShader, 1, &g_strVertexShader, NULL );
        glCompileShader( hVertexShader );

 

        // Check for compile success
        GLint nCompileResult = 0;
        glGetShaderiv( hVertexShader, GL_COMPILE_STATUS, &nCompileResult );
        if( 0 == nCompileResult )
        {
            char  strLog[1024];
            GLint nLength;
            glGetShaderInfoLog( hVertexShader, 1024, &nLength, strLog );
            return FALSE;
        }

 

        GLuint hFragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
        glShaderSource( hFragmentShader, 1, &g_strFragmentShader, NULL );
        glCompileShader( hFragmentShader );

 

        // Check for compile success
        glGetShaderiv( hFragmentShader, GL_COMPILE_STATUS, &nCompileResult );
        if( 0 == nCompileResult )
        {
            char  strLog[1024];
            GLint nLength;
            glGetShaderInfoLog( hFragmentShader, 1024, &nLength, strLog );
            return FALSE;
        }

 

        // Attach the individual shaders to the common shader program
        g_hShaderProgram = glCreateProgram();
        glAttachShader( g_hShaderProgram, hVertexShader );
        glAttachShader( g_hShaderProgram, hFragmentShader );

 

        // Init attributes BEFORE linking
        glBindAttribLocation( g_hShaderProgram, g_hVertexLoc,   "g_vPosition" );
        glBindAttribLocation( g_hShaderProgram, g_hColorLoc,    "g_vColor" );

 

        // Link the vertex shader and fragment shader together
        glLinkProgram( g_hShaderProgram );

 

        // Check for link success
        GLint nLinkResult = 0;
        glGetProgramiv( g_hShaderProgram, GL_LINK_STATUS, &nLinkResult );
        if( 0 == nLinkResult )
        {
            char strLog[1024];
            GLint nLength;
            glGetProgramInfoLog( g_hShaderProgram, 1024, &nLength, strLog );
            return FALSE;
        }

 

        // Get uniform locations
        g_hModelViewMatrixLoc = glGetUniformLocation( g_hShaderProgram, "g_matModelView" );
        g_hProjMatrixLoc      = glGetUniformLocation( g_hShaderProgram, "g_matProj" );

 

        glDeleteShader( hVertexShader );
        glDeleteShader( hFragmentShader );

 


        //gen textures

    }

 

绘制:

 static float fAngle = 0.0f;
    fAngle += 0.01f;

 

 

 

    // Rotate and translate the model view matrix
    float matModelView[16] = {0};
    matModelView[ 0] = +cosf( fAngle );
    matModelView[ 2] = +sinf( fAngle );
    matModelView[ 5] = 1.0f;
    matModelView[ 8] = -sinf( fAngle );
    matModelView[10] = +cosf( fAngle );
    matModelView[12] = 1.5f;
    matModelView[14] = -6.0f;
    matModelView[15] = 1.0f;

 


    // Build a perspective projection matrix
    float matProj[16] = {0};
    matProj[ 0] = cosf( 0.5f ) / sinf( 0.5f );
    matProj[ 5] = matProj[0] * (w/h) ;
    matProj[10] = -( 10.0f ) / ( 9.0f );
    matProj[11] = -1.0f;
    matProj[14] = -( 10.0f ) / ( 9.0f );

 


    // Clear the colorbuffer and depth-buffer
    glClearColor( 0.0f, 0.0f, 0.5f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

 

    // Set some state
    glEnable( GL_DEPTH_TEST );
    glEnable( GL_CULL_FACE );
    glCullFace( GL_BACK );

 

    // Set the shader program
    glUseProgram( g_hShaderProgram );
    glUniformMatrix4fv( g_hModelViewMatrixLoc, 1, 0, matModelView );
    glUniformMatrix4fv( g_hProjMatrixLoc,      1, 0, matProj );

 

    // Bind the vertex attributes
    glVertexAttribPointer( g_hVertexLoc, 3, GL_FLOAT, 0, 0, VertexPositions );
    glEnableVertexAttribArray( g_hVertexLoc );

 

    glVertexAttribPointer( g_hColorLoc, 4, GL_FLOAT, 0, 0, VertexColors );
    glEnableVertexAttribArray( g_hColorLoc );

 


    glDrawArrays( GL_TRIANGLES, 0, 12 );

 

 

 

 

 

    matModelView[12] = -1.5f;
    // Set the shader program

 

    glUniformMatrix4fv( g_hModelViewMatrixLoc, 1, 0, matModelView );

 


    // Bind the vertex attributes
    glVertexAttribPointer( g_hVertexLoc, 3, GL_FLOAT, 0, 0, VertexPositions2 );

 


    glVertexAttribPointer( g_hColorLoc, 4, GL_FLOAT, 0, 0, VertexColors2 );

 

 

 

    /* Drawing Using Triangle strips, draw triangle strips using 4 vertices */
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
    glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
    glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
    glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
    glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);

 

    //!wait
    glFinish();

 

    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,pImageData);

 

    QFile file("openesRaw.bat");
    if(!file.open(QIODevice::WriteOnly))
    {
        qDebug()<<"open file err"<<endl;
        return;
    }

 

    int writebyte =file.write((const char*)pImageData,4*800*600);
    qDebug()<<writebyte<<endl;
    file.flush();
    file.close();

 

  // QImage saveImage(pImageData, w, h, QImage::Format_RGB888);
    QImage saveImage(800,600,QImage::Format_RGB888);
    for(int ih=0;ih<600;ih++)
    {
        for(int iw=0;iw<800;iw++)
        {
            UN_RGBA rgba;
            rgba.m_rgba=pImageData[800*ih+iw];
            int r= (int)rgba.m_rgbaArray[0];
            int g=(int)rgba.m_rgbaArray[1];
            int b=(int)rgba.m_rgbaArray[2];

 

            saveImage.setPixel(iw,ih,qRgb(r,g,b));
        }
    }

   saveImage.save("opengs.png");

 

附录:

    1. OpenGL ES

OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。OpenGL ES 是从 OpenGL 裁剪的定制而来的,去除了四边形、多边形等复杂图元等许多非绝对必要的特性。OpenGL ES 1.x 针对固定pipeline硬件,OpenGL ES 2.x 针对可编程pipeline硬件。

    1. EGL

OpenGL是一个操作GPU的API,它通过驱动向GPU发送相关指令,控制pipeline状态机的运行状态。但OpenGL需要与本地视窗系统进行交互,这就需要一个中间控制层,最好与平台无关,EGL因此被独立的设计出来,它作为OpenGL ES和本地窗口的桥梁。

EGL API 是独立于OpenGL ES各版本标准的独立API ,其主要作用是为OpenGL指令创建 Context 、绘制目标Surface 、配置Framebuffer属性、Swap提交绘制结果等。此外,EGL为GPU厂商和OS窗口系统之间提供了一个标准配置接口。一般来说,OpenGL ES中pipeline的状态被存储于EGL管理的一个Context中。而Frame Buffers 和其他绘制Surfaces 通过EGL API进行创建、管理和销毁。 EGL 同时也控制和提供了对设备显示和可能的设备渲染配置的访问。

图 1为一个典型的EGL系统布局。应用程序通过调用EGL API进行window、surface、context的初始化,接着通过调用OpenGL ES的API进行设置context等,最后调用GPU渲染API进行渲染。

 

 

图 1 典型EGL系统布局

    1. Vivante GPU软件框架

图 2表示的是Vivante GPU的软件框架。GAL Driver是为了降低跨平台(操作系统,硬件平台)移植的难度而设计的一套API,包括用户层驱动:主要提供GAL API给开发者使用;内核层驱动:主要负责管理对GPU硬件的操作。

在实际使用中,图中的EGL、OpenGL ES等图形库以动态库形式被使用,用户层的GAL Driver也以动态库形式被使用,内核层的GAL Driver以内核模块驱动形式被使用。

https://img-blog.csdn.net/20170615185713121

 

    1. EGL要做什么?

EGL既然做平台和OpenGL ES的中间件那EGL做的就肯定是和平台息息相关的事:

创建绘图窗口也就是所谓的FrameBuffer,FrameBuffer可以显示到屏幕上(SurfaceView)

创建渲染环境(Context上下文)渲染环境指OpenGL ES的所有项目运行需要的数据结构。如顶点、片段着色器、顶点数据矩阵。

https://img-blog.csdnimg.cn/2018122016163530

 

1. 获取Display。
Display代表显示器,在有些系统上可以有多个显示器,也就会有多个Display。获得Display要调用EGLboolean eglGetDisplay(NativeDisplay dpy),参数一般为 EGL_DEFAULT_DISPLAY 。该参数实际的意义是平台实现相关的,在X-Window下是XDisplay ID,在MS Windows下是Window DC。

2. 初始化egl。
调用 EGLboolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor),该函数会进行一些内部初始化工作,并传回EGL版本号(major.minor)。

3. 选择Config。
所为Config实际指的是FrameBuffer的参数,在MS Windows下对应于PixelFormat,在X-Window下对应Visual。一般用EGLboolean eglChooseConfig(EGLDisplay dpy, const EGLint * attr_list, EGLConfig * config, EGLint config_size, EGLint *num_config),其中attr_list是以EGL_NONE结束的参数数组,通常以id,value依次存放,对于个别标识性的属性可以只有 id,没有value。另一个办法是用EGLboolean eglGetConfigs(EGLDisplay dpy, EGLConfig * config, EGLint config_size, EGLint *num_config) 来获得所有config。这两个函数都会返回不多于config_size个Config,结果保存在config[]中,系统的总Config个数保存在num_config中。可以利用eglGetConfig()中间两个参数为0来查询系统支持的Config总个数。Config有众多的Attribute,这些Attribute决定FrameBuffer的格式和能力,通过eglGetConfigAttrib ()来读取,但不能修改。

4. 构造Surface。

Surface实际上就是一个FrameBuffer,通过 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig confg, NativeWindow win, EGLint *cfg_attr) 来创建一个可实际显示的Surface。系统通常还支持另外两种Surface:PixmapSurface和PBufferSurface,这两种都不是可显示的Surface,PixmapSurface是保存在系统内存中的位图,PBuffer则是保存在显存中的帧。Surface也有一些attribute,基本上都可以故名思意, EGL_HEIGHT EGL_WIDTH EGL_LARGEST_PBUFFER EGL_TEXTURE_FORMAT EGL_TEXTURE_TARGET EGL_MIPMAP_TEXTURE EGL_MIPMAP_LEVEL,通过eglSurfaceAttrib()设置、eglQuerySurface()读取。

5. 创建Context。
OpenGL的pipeline从程序的角度看就是一个状态机,有当前的颜色、纹理坐标、变换矩阵、绚染模式等一大堆状态,这些状态作用于程序提交的顶点坐标等图元从而形成帧缓冲内的像素。在OpenGL的编程接口中,Context就代表这个状态机,程序的主要工作就是向Context提供图元、设置状态,偶尔也从Context里获取一些信息。用EGLContext eglCreateContext(EGLDisplay dpy, EGLSurface write, EGLSurface read, EGLContext * share_list)来创建一个Context。

6. 绘制。
应用程序通过OpenGL API进行绘制,一帧完成之后,调用eglSwapBuffers(EGLDisplay dpy, EGLContext ctx)来显示。

 

颜色缓冲区

  颜色缓冲区(COLOR_BUFFER)就是帧缓冲区(FRAME_BUFFER,你需要渲染的场景最终每一个像素都要写入该缓冲区,然后由它在渲染到屏幕上显示.

深度缓冲区

  深度缓冲区(DEPTH_BUFFER)与帧缓冲区对应,用于记录上面每个像素的深度值,通过深度缓冲区,我们可以进行深度测试,从而确定像素的遮挡关系,保证渲染正确.

模板缓冲区

  模版缓冲(STENCIL_BUFFER)与深度缓冲大小相同,通过设置模版缓冲每个像素的值,我们可以指定在渲染的时候只渲染某些像素,从而可以达到一些特殊的效果.

这篇关于imx6 GPU 后台离屏绘制3D图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/315105

相关文章

轻量级在线服装3D定制引擎Myway简介

我写的面向web元宇宙轻量级系列引擎中的另外一个,在线3D定制引擎Myway 3D。 用于在线商品定制,比如个性化服装的定制、日常用品(如杯子)、家装(被套)等物品的在线定制。 特性列表: 可更换衣服款式,按需定制更换模型可实时更改材质颜色可实时添加文本,并可实时修改大小、颜色和角度,支持自定义字体可实时添加艺术图标,并可实时修改大小、颜色和角度,支持翻转、各种对齐可更改衣服图案,按需求定制

以canvas方式绘制粒子背景效果,感觉还可以

这个是看到项目中别人写好的,感觉这种写法效果还可以,就存留记录下 就是这种的背景效果。如果想改背景颜色可以通过canvas.js文件中的fillStyle值改。 附上demo下载地址。 https://download.csdn.net/download/u012138137/11249872

XMG 绘制形状

1. 除非是绘制曲线直接使用原生的。如果绘制形状直接使用UIBezerPath  2. 命名原则,类方法以类名开头 UIBezierPath bezierPathWithRect 3.圆角半径 画圆的大小 以每个顶点为圆心。给定的半径为半径画一个1/4圆。把周边的给切掉 4.只有封闭的形状调用这个方法才有用 [path fill] 5. stroke 描边一下

POLYGON Horror Carnival - Low Poly 3D Art by Synty

465 个独特的预设模型 一个正在运行的摩天轮和旋转木马 包括10个示例脚本,让嘉年华栩栩如生 ◼ 描述◼ 欢迎来到恐怖嘉年华。这个地方曾经有诱人的音乐,现在却有着令人不安的旋律,暗示着其中令人不安的惊喜。 这场险恶的盛会的真正核心在于演示场景。它使用3D低多边形资源构建,具有来自不祥的狂欢帐篷、摊位、摩天轮、旋转木马等游戏开发资源。它是疯狂人物与毫无戒心的寻求刺激者玩捉迷藏游戏的完美狩猎场。

Tkinter和selenium结合实现登录UC后台,最后打包成exe

主要实现的功能:小号模式自动登录UC阿里汇川广告后台,屏蔽账号密码输入 主要用的技术:用Tkinter展示所有的广告账号界面,使用selenium控制谷歌浏览器,打开阿里汇川登录页,登录汇川后台。 第一次写,遇到的坑比较多,三天,搞定。给自己一个棒棒~☺️ import Tkinter as tk import osimport sysimport requestsfrom sel

自动驾驶---Perception之Lidar点云3D检测

1 背景         Lidar点云技术的出现是基于摄影测量技术的发展、计算机及高新技术的推动以及全球定位系统和惯性导航系统的发展,使得通过激光束获取高精度的三维数据成为可能。随着技术的不断进步和应用领域的拓展,Lidar点云技术将在测绘、遥感、环境监测、机器人等领域发挥越来越重要的作用。         目前全球范围内纯视觉方案的车企主要包括特斯拉和集越,在达到同等性能的前提下,纯视觉方

3D模型相关生成

3D模型相关生成 1. DreamFusion Model DreamFusion Model 是一种将文本描述转化为三维模型的技术。你可以想象它是一个“魔法翻译器”,你告诉它一个场景或物体的描述,比如“一个飞翔的龙”,它就能生成一个相应的 3D 模型。 原理: 文本到图像生成:DreamFusion 首先将文本描述转化为一系列可能的 2D 图像。这部分利用了预训练的扩散模型(如 DALL

初学WebGL,使用Three.js开发第一个3d场景示例

使用Three.js 开发3d场景   在图书馆偶然撞见《Three.js开发指南》一书,便试着捣鼓一翻,现将第一个示例的部分代码、注解和相关方法的API记录在此。因为此书发行时是Three.js r69版本,所以当前部分代码有所修改,且所有方法和参数以官方最新版本Three.js r90为准。 <!doctype html><html lang="en"><head><meta char

CesiumJS【Basic】- #008 通过canvas绘制billboard

文章目录 通过canvas绘制billboard1 目标2 实现 通过canvas绘制billboard 1 目标 通过canvas绘制billboard 2 实现 /** @Author: alan.lau* @Date: 2024-06-16 11:15:48* @LastEditTime: 2024-06-16 11:43:02* @LastEditors: al

使用AGG里面的clip_box函数裁剪画布, 绘制裁剪后的图形

// 矩形裁剪图片, 透明void agg_testImageClipbox_rgba32(unsigned char* buffer, unsigned int width, unsigned int height){// ========= 创建渲染缓冲区 =========agg::rendering_buffer rbuf;// BMP是上下倒置的,为了和GDI习惯相同,最后一个参数是