簡體   English   中英

使用OpenGL寫入文件而不是在屏幕上繪制

[英]Using OpenGL to write to a file rather than draw on the screen

我正在嘗試創建一個RGB到yuv圖像着色器。 我使用SDL在屏幕上繪制了圖像,但我不希望將着色器的輸出寫入到test.yuv文件中。 我仍然是OpenGL的初學者,我想知道是否可行? 我試圖將輸出放入緩沖區,但是沒有成功。 在我的代碼中標有“ MY ATTEMPT”

int main()
{
    void* buf //raw image file

    SDL_Surface *Win=NULL;
    SDL_Event evt;
    int i;
    GLhandleARB FSHandle,PHandle;
    char *s;

    const char *FProgram=
            "uniform sampler2DRect rgba;\n"
            "vec4 YUV;\n"

            "void main(void) {\n"
            "vec4 new_rgba = texture2DRect(rgba, gl_TexCoord[0].xy);\n"

            "mat4 RGBtoYUV = mat4(0.257,  0.439, -0.148, 0.0, 0.504, -0.368, -0.291, 0.0, 0.098, -0.071,  0.439, 0.0, 0.0625, 0.500,  0.500, 1.0 );\n"

            "YUV = RGBtoYUV * new_rgba;"

            "gl_FragColor = YUV;"

            "}\n";

    if(!SDL_Init(SDL_INIT_VIDEO)) {

        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);

        Win=SDL_SetVideoMode(B_WIDTH,B_HEIGHT,32,SDL_HWSURFACE|SDL_ANYFORMAT|SDL_OPENGL);

        if(Win) {


            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glOrtho(0,B_WIDTH,0,B_HEIGHT,-1,1);
            glViewport(0,0,B_WIDTH,B_HEIGHT);
            glClearColor(0,0,0,0);
            glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);

            /* Set up program objects. */
            PHandle=glCreateProgramObjectARB();
            FSHandle=glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

            /* Compile the shader. */
            glShaderSourceARB(FSHandle,1,&FProgram,NULL);
            glCompileShaderARB(FSHandle);

            /* Print the compilation log. */
            glGetObjectParameterivARB(FSHandle,GL_OBJECT_COMPILE_STATUS_ARB,&i);
            s=new char(32768);
            glGetInfoLogARB(FSHandle,32768,NULL,s);
            printf("Compile Log: %s\n", s);
            delete[] s;

            /* Create a complete program object. */
            glAttachObjectARB(PHandle,FSHandle);
            glLinkProgramARB(PHandle);

            /* And print the link log. */
            s=new char(32768);
            glGetInfoLogARB(PHandle,32768,NULL,s);
            printf("Link Log: %s\n", s);
            delete[] s;

            /* Finally, use the program. */
            glUseProgramObjectARB(PHandle);

            /* This might not be required, but should not hurt. */
            glEnable(GL_TEXTURE_2D);

            /* Select texture unit 1 as the active unit and bind the U texture. */
            glActiveTexture(GL_TEXTURE1);

            GLuint texColorBuffer;
            glGenTextures(1, &texColorBuffer);

            glBindTexture(GL_TEXTURE_RECTANGLE_NV,texColorBuffer);
            glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
            glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
            glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
            glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA8,1920,1080,0,GL_BGRA,GL_UNSIGNED_BYTE, buf);


            i=glGetUniformLocationARB(PHandle,"rgba");
            glUniform1iARB(i,1);

//MY ATTEMPT TO GET THE BUFFER TO WRITE INTO A FILE.
            QByteArray* raw_img;
            glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8,GL_UNSIGNED_BYTE, raw_img);

            QFile test("/tmp/wajeeh.yuv");
            test.open(QFile::WriteOnly);
            test.write(*raw_img);
            test.close();

            /* Simple loop, just draws the image and waits for quit. */
            while(!Quit) {
                if(SDL_PollEvent(&evt)) {
                    switch(evt.type) {
                    case  SDL_KEYDOWN:
                    case  SDL_QUIT:
                        Quit=1;
                        break;
                    }
                }


                glClear(GL_COLOR_BUFFER_BIT);

                /* Draw image (again and again). */

                glBegin(GL_QUADS);
                glTexCoord2i(0,1080);
                glVertex2i(0,0);
                glTexCoord2i(1920,1080);
                glVertex2i(B_WIDTH,0);
                glTexCoord2i(1920,0);
                glVertex2i(B_WIDTH,B_HEIGHT);
                glTexCoord2i(0,0);
                glVertex2i(0,B_HEIGHT);
                glEnd();



                /* Flip buffers. */

                glFlush();
                SDL_GL_SwapBuffers();

                SDL_Delay(50);
            } /* while(!Quit) */

            /* Clean up before exit. */

            glUseProgramObjectARB(0);
            glDeleteObjectARB(PHandle);



        } else {
            fprintf(stderr,"Unable to create primary surface. \"%s\".\n",SDL_GetError());
        }
        SDL_Quit();
    } else {
        fprintf(stderr,"Initialisation failed. \"%s\".\n",SDL_GetError());
    }

    return(0);
}

您應該尋找的總體思路是屏幕外渲染 您可以使用所需大小創建其他幀緩沖區,然后將其設置為渲染目標,而不使用opengl提供的默認幀緩沖區。 之后,您可以glReadPixels並將像素圖保存為所需的格式。

這里有更多示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM