I am trying to implement anti aliasing using multisampling. Here i have used FBO1(fboID) for multisampling.I am reendering my texture image to a multisampled render buffer(colorBufID) and using it as an attachment point
for FBO. Then i have created another FBO2(frameBUfID) and blit from FBO1 to FBO2 but i get error at glBlitFrameBuffer.
Could you please explain if the implementation is correct .
#include <math.h> #include "Timer.h" #include <time.h> #include <string> #include "win_process.h" #include "Matrix.h" #include "ETCHeader.h" #include "gts_log.h" //#include "Texture.h" #include "imageload.h" #define EGL_EGLEXT_PROTOTYPES 1 #define GL_GLEXT_PROTOTYPES 1 #include "GLES3/gl3.h" #include "GLES3/gl3ext.h" #include "EGL/egl.h" #include "EGL/eglext.h" //#include <stdbool.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> //#include <GLES/gl.h> //#include <GLES/glext.h> using namespace std; #define WINDOW_W 1920 #define WINDOW_H 1080 #define FRAMECOUNT 500 unsigned int uiWidth = WINDOW_W; unsigned int uiHeight = WINDOW_H; extern EGLDisplay sEGLDisplay; extern EGLContext sEGLContext; extern EGLSurface sEGLSurface; char *bmp_texpath = { "./assets/Raw1.bmp", }; ImageData img ; GLuint bmp_texid; GLuint depthTexID; GLuint texId[5]; std::string asset = "assets/"; GLuint bufferObjectIds[2] = {0}; GLuint texbuf ; GLuint vertexArrayId; float scalingFactor = 0.75f; Timer fpsTimer; GLuint uiProgramObject; //GLuint modelViewMatrixLocation; GLuint fboID; GLuint colorBufID; GLuint defaultDepthBuffer; GLuint frameBufID; GLuint positionLocation; GLuint textureCoordinateLocation; GLuint textureLocation; int num_textures = 5; int cur_index = 0; bool compress = false; float fps_time = 0.0,cur_time = 0.0; int framecount = 0; int angle = 0 ; clock_t curTime,lastTime; GLuint esLoadShader ( GLenum type, const char *shaderSrc ) { GLuint shader; GLint compiled; shader = glCreateShader ( type ); if ( shader == 0 ) { return 0; } glShaderSource ( shader, 1, &shaderSrc, NULL ); glCompileShader ( shader ); glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); if ( !compiled ) { GLint infoLen = 0; glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen ); if ( infoLen > 1 ) { char *infoLog =(char *) malloc ( sizeof ( char ) * infoLen ); glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); printf("Log START:\n%s\nLog END\n\n", infoLog); free ( infoLog ); } glDeleteShader ( shader ); return 0; } return shader; } GLuint esLoadProgram ( char *vertShaderSrc, char *fragShaderSrc ) { GLint uprogramObject; GLint linked; GLuint vertexShader; GLuint fragmentShader; vertexShader = esLoadShader ( GL_VERTEX_SHADER, vertShaderSrc ); if ( vertexShader == 0 ) { return 0; } fragmentShader = esLoadShader ( GL_FRAGMENT_SHADER, fragShaderSrc ); if ( fragmentShader == 0 ) { glDeleteShader ( vertexShader ); return 0; } uprogramObject = glCreateProgram ( ); if ( uprogramObject == 0 ) { return 0; } glAttachShader ( uprogramObject, vertexShader ); glAttachShader ( uprogramObject, fragmentShader ); glLinkProgram ( uprogramObject ); glGetProgramiv ( uprogramObject, GL_LINK_STATUS, &linked ); if ( !linked ) { GLint infoLen = 0; glGetProgramiv ( uprogramObject, GL_INFO_LOG_LENGTH, &infoLen ); if ( infoLen > 1 ) { char *infoLog = (char *)malloc ( sizeof ( char ) * infoLen ); glGetProgramInfoLog ( uprogramObject, infoLen, NULL, infoLog ); printf("Log START:\n%s\nLog END\n\n", infoLog); free ( infoLog ); } glDeleteProgram ( uprogramObject ); return 0; } glDeleteShader ( vertexShader ); glDeleteShader ( fragmentShader ); return uprogramObject; } int loadBMPTexture() { GLint maxSamples; glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); printf("%d\n",maxSamples); GL_CHECK(glGenFramebuffers(1, &fboID)); printf("here\n"); GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER,fboID)); printf("3\n"); printf("2"); GL_CHECK(glGenRenderbuffers(1,&colorBufID)); GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, colorBufID)); printf("4\n"); GL_CHECK(glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8,img.OriginalImageWidth ,img.OriginalImageHeight )); printf("6\n"); GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufID)); printf("7\n"); GetImageFromBMP(&img,bmp_texpath); if(img.imagedata != NULL) { GL_CHECK(glGenTextures(1,&bmp_texid)); GL_CHECK(glActiveTexture(GL_TEXTURE0)); GL_CHECK(glBindTexture(GL_TEXTURE_2D, bmp_texid)); GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.OriginalImageWidth, img.OriginalImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.imagedata)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); printf("1\n"); //GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0)); /* glGenTextures( 1, &depthTexID ); GL_CHECK(glBindTexture( GL_TEXTURE_2D, depthTexID )); GL_CHECK(glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, img.OriginalImageWidth, img.OriginalImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.imagedata )); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); 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_DEPTH_TEXTURE_MODE, GL_INTENSITY ); */ } else { printf("Could not load %s",bmp_texpath); return -1; } GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bmp_texid, 0)); printf("15\n"); if( GL_FRAMEBUFFER_COMPLETE== glCheckFramebufferStatus( GL_FRAMEBUFFER )) {printf("\nFBO crreation complete\n"); } else { printf("not complete"); } GL_CHECK(glGenRenderbuffers(1,&defaultDepthBuffer)); printf("8\n"); GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, defaultDepthBuffer)); printf("9\n"); GL_CHECK(glRenderbufferStorageMultisample(GL_RENDERBUFFER,4, GL_DEPTH_COMPONENT16, img.OriginalImageWidth,img.OriginalImageHeight)); GL_CHECK(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, defaultDepthBuffer )); GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0)); /* GetImageFromBMP(&img,bmp_texpath); if(img.imagedata != NULL) { GL_CHECK(glGenTextures( 1, &depthTexID )); GL_CHECK(glBindTexture( GL_TEXTURE_2D, depthTexID )); GL_CHECK(glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, img.OriginalImageWidth, img.OriginalImageHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL )); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); } else { printf("Could not load %s",bmp_texpath); return -1; } GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexID, 0)); */ //glBindRenderbuffer( GL_RENDERBUFFER, 0 ); glBindFramebuffer(GL_FRAMEBUFFER, 0); printf("11\n"); printf("12\n"); //GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexID, 0)); glGenFramebuffers(1, &frameBufID); GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, frameBufID)); printf("14\n"); GL_CHECK(glBindFramebuffer( GL_FRAMEBUFFER,fboID )); //glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); //glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); //} return 0; } int multisample_init() { if(loadBMPTexture() == -1) return -1; GLfloat vertices[] = { -1, -1, 0, // bottom-left -1, 1, 0, // bottom-right 1, 1, 0, // top-right 1, -1, 0, // top-left }; GLfloat texcoords_bmp[] = { 0, 0, 0, 1, 1, 1, 1, 0 }; GLushort indices[] = { 0, 2, 1, 0, 3, 2 }; GL_CHECK(glGenVertexArrays(1, &vertexArrayId)); GL_CHECK(glBindVertexArray(vertexArrayId)); GL_CHECK(glGenBuffers(2, bufferObjectIds)); GL_CHECK(glGenBuffers(1, &texbuf)); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, bufferObjectIds[0])); GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW)); GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObjectIds[1])); GL_CHECK(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW)); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, texbuf)); GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords_bmp), texcoords_bmp, GL_STATIC_DRAW)); positionLocation = GL_CHECK(glGetAttribLocation (uiProgramObject, "attributePosition")); printf("\nvalue of positionLocation:%d\n",positionLocation); textureCoordinateLocation = GL_CHECK(glGetAttribLocation (uiProgramObject, "attributeTextureCoordinate")); printf("\nvalue of textureCoordinateLocation:%d\n",textureCoordinateLocation); textureLocation = GL_CHECK(glGetUniformLocation(uiProgramObject, "uniformTexture")); printf("\nvalue of textureLocation:%d\n",textureLocation); glEnableVertexAttribArray(positionLocation); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, bufferObjectIds[0])); GL_CHECK(glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0)); return 0; } int multisample_render() { GLubyte *pixels; pixels = (GLubyte*) malloc(img.OriginalImageWidth * img.OriginalImageHeight * 4); printf("16\n"); GL_CHECK(glEnableVertexAttribArray(textureCoordinateLocation)); lastTime = clock(); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, texbuf)); GL_CHECK(glVertexAttribPointer(textureCoordinateLocation, 2, GL_FLOAT, GL_FALSE, 0, 0)); //GL_CHECK(glBindTexture(GL_TEXTURE_2D, bmp_texid)); //GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; //glDrawBuffers(1, DrawBuffers[0]); /* const GLenum attachments[1] = { GL_COLOR_ATTACHMENT0, }; */ curTime = clock(); double deltaTime = (double)(curTime - lastTime) / (double)CLOCKS_PER_SEC; //printf("Time : %f\tCompression:%d\n",deltaTime,compress); // } if (textureLocation != -1) { printf("\nvalue of texturelocation%d\n",textureLocation); GL_CHECK(glUniform1i(textureLocation, 0)); } GL_CHECK(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0)); GL_CHECK(glBindFramebuffer( GL_FRAMEBUFFER, 0 )); GL_CHECK(glBindFramebuffer( GL_READ_FRAMEBUFFER, fboID)); GL_CHECK(glBindFramebuffer( GL_DRAW_FRAMEBUFFER,frameBufID)); //GL_CHECK(glBindFramebuffer( GL_DRAW_FRAMEBUFFER,0)); //GL_CHECK(glDrawBuffers(1,attachments)); //GL_CHECK(glReadBuffer(GL_COLOR_ATTACHMENT0)); GL_CHECK(glBlitFramebuffer( 0, 0, img.OriginalImageWidth, img.OriginalImageHeight, 0, 0, img.OriginalImageWidth, img.OriginalImageHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST )); // GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, fboID)); //glReadPixels(0, 0, img.OriginalImageWidth, img.OriginalImageHeight, GL_RGBA8, GL_UNSIGNED_BYTE, pixels); //glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 ); //glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 ); //} EGL_CHECK(eglSwapBuffers(sEGLDisplay,sEGLSurface)); angle+=2; if(angle > 360) angle = 0; return 0; } int MultiSample() { char fstr[]= "#version 300 es \n" "precision mediump float;\n" "uniform sampler2D uniformTexture;\n" "in vec2 varyingTextureCoordinate;\n" "out vec4 colour;\n" "void main()\n" "{\n" " colour = texture(uniformTexture, varyingTextureCoordinate);\n" "}\n"; char vstr[]= "#version 300 es \n" "in vec4 attributePosition; \n" "in vec2 attributeTextureCoordinate;\n" "out vec2 varyingTextureCoordinate;\n" "void main()\n" "{\n" " varyingTextureCoordinate = attributeTextureCoordinate;\n" " gl_Position = attributePosition;\n" "}\n"; uiProgramObject=esLoadProgram ( vstr, fstr ); GL_CHECK(glUseProgram(uiProgramObject)); GL_CHECK(glViewport(0, 0, uiWidth,uiHeight)); if(!multisample_init()) { while(1) { float a = 0.0,r = 0.0,g = 0.0,b = 0.0; //for(int fp =0;fp < FRAMECOUNT;fp++) //{ //GL_CHECK(glClearColor(r,g,b,a)); //GL_CHECK(glClear(GL_COLOR_BUFFER_BIT)); multisample_render(); // a += 0.01; // if( a > 1.0) // a = 0.0; //r=g=b=a; //} compress =1; angle = 0; } } GL_CHECK(glDeleteProgram(uiProgramObject)); GL_CHECK(glDeleteBuffers(2,bufferObjectIds)); GL_CHECK(glDeleteBuffers(1,&texbuf)); return 0; }
Hi SHSANk,
Could you please help us understand your problem by describing what your code is trying to achieve? Also, you mention you get an error... what is this error exactly?
You also seem to be using a Multisampled buffer with 4xAA enabled, (samples is set to 4 in glRenderbufferStorageMultisample), and then you are doing a 'resolve' pass, blitting to a second FBO? Can you please explain why?
Please refer to these error explanations to determine the cause of your error:
GL_INVALID_OPERATION is generated if mask contains any of the GL_DEPTH_BUFFER_BIT or GL_STENCIL_BUFFER_BIT and filter is not GL_NEAREST. GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT and any of the following conditions hold: The read buffer contains fixed-point or floating-point values and any draw buffer contains neither fixed-point nor floating-point values. The read buffer contains unsigned integer values and any draw buffer does not contain unsigned integer values. The read buffer contains signed integer values and any draw buffer does not contain signed integer values. GL_INVALID_OPERATION is generated if mask contains GL_DEPTH_BUFFER_BIT or GL_DEPTH_BUFFER_BIT and the source and destination depth and stencil formats do not match. GL_INVALID_OPERATION is generated if filter is GL_LINEAR and the read buffer contains integer data. GL_INVALID_OPERATION is generated if the value of GL_SAMPLE_BUFFERS for the draw buffer is greater than zero. GL_INVALID_OPERATION is generated if GL_SAMPLE_BUFFERS for the read buffer is greater than zero and the formats of draw and read buffers are not identical, or the source and destination rectangles are not defined with the same (X0, Y0) and (X1, Y1) bounds. GL_INVALID_FRAMEBUFFER_OPERATION is generated if the objects bound to GL_DRAW_FRAMEBUFFER_BINDING or GL_READ_FRAMEBUFFER_BINDING are not framebuffer complete.
Kind Regards,
Michael McGeagh
Hi Michael,
I was following this openGL wiki and trying to implement the same .
https://www.opengl.org/wiki/GL_EXT_framebuffer_multisample.
regards
shshank
Hi shsank,
That link is specific for OpenGL, and not OpenGL ES. They are different APIs and as such operate differently, since the target hardware is designed differently.
Can I ask what outcome you are wanting? If we know more about your desired output, we can suggest what GLES techniques would be recommended.
Hi Michael ,
Thanks alot for replying.
All the APIs listed on the link i provided are supported by opengl es provided you remove "EXT" from their names.
I am just trying to implement a test case for multisample Antialiasing (MSAA) in opengl es (ARM platform). Please help in any way you can.
I need a sample to test MSAA.
Hi shanksanghoi,
In GLES on Mali GPUs, the simplest case for 4xMSAA would be to render directly to the window surface (FB0), having set EGL_SAMPLES to 4. This will do all multisampling and resolving in the GPU registers, and will only flush the resolved buffer to memory. This is the most efficient way to implement MSAA on a Mali GPU, and comes at almost no performance cost compared to rendering to a normal window surface. Note that this does not expose the sample buffers themselves to you, and does not require an explicit resolve. Do you require MSAA on an FBO or was this just to enable your testing of MSAA?
P.S. What was the error you received when calling glBlitFramebuffer?
Hth,
Chris