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 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.
Kind Regards,
Michael McGeagh
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