简体   繁体   English

使用OpenGL写入文件而不是在屏幕上绘制

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

I'm trying to create an rgb to yuv image shader. 我正在尝试创建一个RGB到yuv图像着色器。 I have the image drawn on the screen using SDL but rather than that I want the output of the shader to be written into a test.yuv file. 我使用SDL在屏幕上绘制了图像,但我不希望将着色器的输出写入到test.yuv文件中。 I'm still a beginner in OpenGL, I was wondering if that is possible or not? 我仍然是OpenGL的初学者,我想知道是否可行? I made an attempt to get the output into a buffer but it was unsucessful. 我试图将输出放入缓冲区,但是没有成功。 Its in my code labelled "MY ATTEMPT" 在我的代码中标有“ 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);
}

The general idea you should look for is the offscreen rendering . 您应该寻找的总体思路是屏幕外渲染 Instead of using the default framebuffer opengl provides you to render to, you can create other framebuffers with desired size, and set them as render targets. 您可以使用所需大小创建其他帧缓冲区,然后将其设置为渲染目标,而不使用opengl提供的默认帧缓冲区。 After that you can glReadPixels and save the pixmap to the format you need. 之后,您可以glReadPixels并将像素图保存为所需的格式。

More examples here . 这里有更多示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM