int Splat_Prepare(SDL_Window *userWindow, int userViewportWidth, int userViewportHeight) { int width, height; window = userWindow; viewportWidth = userViewportWidth; viewportHeight = userViewportHeight; SDL_GetWindowSize(userWindow, &width, &height); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 4); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 4); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 4); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 4); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); window_glcontext = SDL_GL_CreateContext(window); if (!window_glcontext) { Splat_SetError("OpenGL context creation failed. Check glGetError() and/or SDL_GetError() for more information."); Splat_Finish(); return -1; } // Our shading model--Flat glShadeModel(GL_FLAT); // Default the clear color to black. glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Setup our viewport. glViewport(0, 0, viewportWidth, viewportHeight); // Change to the projection matrix and set up our ortho view glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, width, 0, height); // Set up modelview for 2D integer coordinates glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.375f, height + 0.375f, 0.0f); glScalef(1.0f, -1.0f, 0.001f); // Make the positive Z-axis point "out" from the view (e.g images at depth 4 will be higher than those at depth 0), and swap the Y axis /* Deactivate the system cursor */ SDL_ShowCursor(SDL_DISABLE); glDisable(GL_DITHER); /* Create the frame buffer for rendering to texture*/ glGenFramebuffers(1, &framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); /* Set up the texture to which we're going to render */ glGenTextures(1, &frameTexture); glBindTexture(GL_TEXTURE_2D, frameTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, viewportWidth, viewportHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); /* Configure the framebuffer texture */ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, frameTexture, 0); GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; glDrawBuffers(1, DrawBuffers); GLenum err = glGetError(); if (err != GL_NO_ERROR) { Splat_SetError("OpenGL error occurred during initialization"); Splat_Finish(); return -1; } return 0; }
void nativeRecord::init(){ _eglCreateImageKHR = ( PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress ( "eglCreateImageKHR" ); _eglDestroyImageKHR = ( PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress( "eglDestroyImageKHR" ); _glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress( "glEGLImageTargetTexture2DOES" ); if(_eglCreateImageKHR == NULL){ LOGD("_eglCreateImageKHR error"); exit(1); } if(_eglDestroyImageKHR == NULL){ LOGD("_eglDestroyImageKHR error"); exit(1); } if(_glEGLImageTargetTexture2DOES == NULL){ LOGD("_glEGLImageTargetTexture2DOES error"); exit(1); } buffer = new GraphicBuffer ( gWidth , gHeight , HAL_PIXEL_FORMAT_BGRA_8888, GraphicBuffer :: USAGE_SW_READ_OFTEN | GraphicBuffer :: USAGE_HW_TEXTURE ); if((buffer->initCheck ()) != NO_ERROR) exit (1); android_native_buffer_t * anb = buffer->getNativeBuffer(); const EGLint attrs [] = { EGL_IMAGE_PRESERVED_KHR , EGL_TRUE, EGL_NONE, EGL_NONE }; pEGLImage = _eglCreateImageKHR(eglGetCurrentDisplay(),EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)anb, attrs); if(EGL_SUCCESS != eglGetError()) { LOGI("_eglCreateImageKHR failed."); return; } glGenTextures(1 , &iFBOTex ); checkGlError("glGenTextures(1 , &iFBOTex );"); glBindTexture(GL_TEXTURE_2D , iFBOTex); checkGlError("glBindTexture(GL_TEXTURE_2D , iFBOTex);"); // glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); // glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, gWidth, gHeight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL); if(GL_NO_ERROR != glGetError()) { LOGI("glTexImage2D failed."); return; } glGenFramebuffers (1, &iFBO); checkGlError("glGenFramebuffers (1, &iFBO);"); glBindFramebuffer (GL_FRAMEBUFFER, iFBO); checkGlError("glBindFramebuffer (GL_FRAMEBUFFER, iFBO)"); glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, iFBOTex, 0); GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(status != GL_FRAMEBUFFER_COMPLETE) { LOGI("glCheckFramebufferStatus %d", status); } checkGlError("glFramebufferTexture2D"); _glEGLImageTargetTexture2DOES (GL_TEXTURE_2D, pEGLImage); checkGlError("_glEGLImageTargetTexture2DOES"); glBindFramebuffer (GL_FRAMEBUFFER,0); checkGlError("glBindFramebuffer (GL_FRAMEBUFFER,0)"); pixels = (char*)malloc(720*1280*4); memset(pixels,0,720*1280*4); }
static int get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { int error = 0; // Get the b frame from the stack mlt_frame b_frame = (mlt_frame) mlt_frame_pop_frame( a_frame ); // Get the transition object mlt_transition transition = (mlt_transition) mlt_frame_pop_service( a_frame ); // Get the properties of the transition mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); // Get the properties of the a frame mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame ); // Get the movit objects mlt_service service = MLT_TRANSITION_SERVICE( transition ); mlt_service_lock( service ); EffectChain* chain = GlslManager::get_chain( service ); Effect* effect = (Effect*) mlt_properties_get_data( properties, "movit effect", NULL ); MltInput* a_input = GlslManager::get_input( service ); MltInput* b_input = (MltInput*) mlt_properties_get_data( properties, "movit input B", NULL ); mlt_image_format output_format = *format; if ( !chain || !a_input ) { mlt_service_unlock( service ); return 2; } // Get the transition parameters int reverse = mlt_properties_get_int( properties, "reverse" ); double mix = mlt_properties_get( properties, "mix" ) ? mlt_properties_get_double( properties, "mix" ) : mlt_transition_get_progress( transition, a_frame ); double inverse = 1.0 - mix; // Set the movit parameters bool ok = effect->set_float( "strength_first", reverse ? mix : inverse ); ok |= effect->set_float( "strength_second", reverse ? inverse : mix ); assert( ok ); // Get the frames' textures GLuint* texture_id[2] = {0, 0}; *format = mlt_image_glsl_texture; mlt_frame_get_image( a_frame, (uint8_t**) &texture_id[0], format, width, height, 0 ); a_input->useFBOInput( chain, *texture_id[0] ); *format = mlt_image_glsl_texture; mlt_frame_get_image( b_frame, (uint8_t**) &texture_id[1], format, width, height, 0 ); b_input->useFBOInput( chain, *texture_id[1] ); // Set resolution to that of the a_frame *width = mlt_properties_get_int( a_props, "width" ); *height = mlt_properties_get_int( a_props, "height" ); // Setup rendering to an FBO GlslManager* glsl = GlslManager::get_instance(); glsl_fbo fbo = glsl->get_fbo( *width, *height ); if ( output_format == mlt_image_glsl_texture ) { glsl_texture texture = glsl->get_texture( *width, *height, GL_RGBA ); glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo ); check_error(); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 ); check_error(); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); check_error(); GlslManager::render( service, chain, fbo->fbo, *width, *height ); glFinish(); check_error(); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); check_error(); *image = (uint8_t*) &texture->texture; mlt_frame_set_image( a_frame, *image, 0, NULL ); mlt_properties_set_data( properties, "movit.convert", texture, 0, (mlt_destructor) GlslManager::release_texture, NULL ); *format = output_format; } else { // Use a PBO to hold the data we read back with glReadPixels() // (Intel/DRI goes into a slow path if we don't read to PBO) GLenum gl_format = ( output_format == mlt_image_rgb24a || output_format == mlt_image_opengl )? GL_RGBA : GL_RGB; int img_size = *width * *height * ( gl_format == GL_RGB? 3 : 4 ); glsl_pbo pbo = glsl->get_pbo( img_size ); glsl_texture texture = glsl->get_texture( *width, *height, gl_format ); if ( fbo && pbo && texture ) { // Set the FBO glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo ); check_error(); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 ); check_error(); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); check_error(); GlslManager::render( service, chain, fbo->fbo, *width, *height ); // Read FBO into PBO glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo->pbo ); check_error(); glBufferData( GL_PIXEL_PACK_BUFFER_ARB, img_size, NULL, GL_STREAM_READ ); check_error(); glReadPixels( 0, 0, *width, *height, gl_format, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0) ); check_error(); // Copy from PBO uint8_t* buf = (uint8_t*) glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY ); check_error(); *format = gl_format == GL_RGBA ? mlt_image_rgb24a : mlt_image_rgb24; *image = (uint8_t*) mlt_pool_alloc( img_size ); mlt_frame_set_image( a_frame, *image, img_size, mlt_pool_release ); memcpy( *image, buf, img_size ); // Release PBO and FBO glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB ); check_error(); glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 ); check_error(); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); check_error(); glBindTexture( GL_TEXTURE_2D, 0 ); check_error(); GlslManager::release_texture( texture ); } else { error = 1; } } if ( fbo ) GlslManager::release_fbo( fbo ); mlt_service_unlock( service ); return error; }
bool LLRenderTarget::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { return true; } U32 offset = mTex.size(); if (offset >= 4 || (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) { llerrs << "Too many color attachments!" << llendl; } U32 tex; LLImageGL::generateTextures(1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); stop_glerror(); { clear_glerror(); LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); if (glGetError() != GL_NO_ERROR) { llwarns << "Could not allocate color buffer for render target." << llendl; return false; } } sBytesAllocated += mResX*mResY*4; stop_glerror(); if (offset == 0) { //use bilinear filtering on single texture render targets that aren't multisampled gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); stop_glerror(); } else { //don't filter data attachments gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); stop_glerror(); } if (mUsage != LLTexUnit::TT_RECT_TEXTURE) { gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); stop_glerror(); } else { // ATI doesn't support mirrored repeat for rectangular textures. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); } if (mFBO) { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, LLTexUnit::getInternalType(mUsage), tex, 0); stop_glerror(); check_framebuffer_status(); glBindFramebuffer(GL_FRAMEBUFFER, 0); } mTex.push_back(tex); if (gDebugGL) { //bind and unbind to validate target bindTarget(); flush(); } return true; }
bool RenderTexture::initWithWidthAndHeight(int w, int h, Texture2D::PixelFormat eFormat, GLuint uDepthStencilFormat) { CCASSERT(eFormat != Texture2D::PixelFormat::A8, "only RGB and RGBA formats are valid for a render texture"); bool bRet = false; void *data = NULL; do { w = (int)(w * CC_CONTENT_SCALE_FACTOR()); h = (int)(h * CC_CONTENT_SCALE_FACTOR()); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO); // textures must be power of two squared unsigned int powW = 0; unsigned int powH = 0; if (Configuration::getInstance()->supportsNPOT()) { powW = w; powH = h; } else { powW = ccNextPOT(w); powH = ccNextPOT(h); } int dataLen = (int)(powW * powH * 4); data = malloc(dataLen); CC_BREAK_IF(! data); memset(data, 0, dataLen); _pixelFormat = eFormat; _texture = new Texture2D(); if (_texture) { _texture->initWithData(data, dataLen, (Texture2D::PixelFormat)_pixelFormat, powW, powH, Size((float)w, (float)h)); } else { break; } GLint oldRBO; glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldRBO); if (Configuration::getInstance()->checkForGLExtension("GL_QCOM")) { _textureCopy = new Texture2D(); if (_textureCopy) { _textureCopy->initWithData(data, dataLen, (Texture2D::PixelFormat)_pixelFormat, powW, powH, Size((float)w, (float)h)); } else { break; } } // generate FBO glGenFramebuffers(1, &_FBO); glBindFramebuffer(GL_FRAMEBUFFER, _FBO); // associate texture with FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0); if (uDepthStencilFormat != 0) { //create and attach depth buffer glGenRenderbuffers(1, &_depthRenderBufffer); glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBufffer); glRenderbufferStorage(GL_RENDERBUFFER, uDepthStencilFormat, (GLsizei)powW, (GLsizei)powH); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer); // if depth format is the one with stencil part, bind same render buffer as stencil attachment if (uDepthStencilFormat == GL_DEPTH24_STENCIL8) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer); } } // check if it worked (probably worth doing :) ) CCASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer"); _texture->setAliasTexParameters(); // retained setSprite(Sprite::createWithTexture(_texture)); _texture->release(); _sprite->setScaleY(-1); _sprite->setBlendFunc( BlendFunc::ALPHA_PREMULTIPLIED ); glBindRenderbuffer(GL_RENDERBUFFER, oldRBO); glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO); // Diabled by default. _autoDraw = false; // add sprite for backward compatibility addChild(_sprite); bRet = true; } while (0); CC_SAFE_FREE(data); return bRet; }
void RenderTexture::onBegin() { // Director *director = Director::getInstance(); _oldProjMatrix = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, _projectionMatrix); _oldTransMatrix = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _transformMatrix); if(!_keepMatrix) { director->setProjection(director->getProjection()); #if CC_TARGET_PLATFORM == CC_PLATFORM_WP8 Mat4 modifiedProjection = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); modifiedProjection = GLViewImpl::sharedOpenGLView()->getReverseOrientationMatrix() * modifiedProjection; director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,modifiedProjection); #endif const Size& texSize = _texture->getContentSizeInPixels(); // Calculate the adjustment ratios based on the old and new projections Size size = director->getWinSizeInPixels(); float widthRatio = size.width / texSize.width; float heightRatio = size.height / texSize.height; Mat4 orthoMatrix; Mat4::createOrthographicOffCenter((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1, 1, &orthoMatrix); director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix); } else { #if CC_TARGET_PLATFORM == CC_PLATFORM_WP8 Mat4 modifiedProjection = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); modifiedProjection = GLViewImpl::sharedOpenGLView()->getReverseOrientationMatrix() * modifiedProjection; director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, modifiedProjection); #endif } //calculate viewport { Rect viewport; viewport.size.width = _fullviewPort.size.width; viewport.size.height = _fullviewPort.size.height; float viewPortRectWidthRatio = float(viewport.size.width)/_fullRect.size.width; float viewPortRectHeightRatio = float(viewport.size.height)/_fullRect.size.height; viewport.origin.x = (_fullRect.origin.x - _rtTextureRect.origin.x) * viewPortRectWidthRatio; viewport.origin.y = (_fullRect.origin.y - _rtTextureRect.origin.y) * viewPortRectHeightRatio; //glViewport(_fullviewPort.origin.x, _fullviewPort.origin.y, (GLsizei)_fullviewPort.size.width, (GLsizei)_fullviewPort.size.height); glViewport(viewport.origin.x, viewport.origin.y, (GLsizei)viewport.size.width, (GLsizei)viewport.size.height); } // Adjust the orthographic projection and viewport glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO); glBindFramebuffer(GL_FRAMEBUFFER, _FBO); //TODO move this to configration, so we don't check it every time /* Certain Qualcomm Andreno gpu's will retain data in memory after a frame buffer switch which corrupts the render to the texture. The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture. Create a temporary texture to overcome this. At the end of RenderTexture::begin(), switch the attached texture to the second one, call glClear, and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers. */ if (Configuration::getInstance()->checkForGLExtension("GL_QCOM")) { // -- bind a temporary texture so we can clear the render buffer without losing our texture glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureCopy->getName(), 0); CHECK_GL_ERROR_DEBUG(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0); } }
bool Framebuffer::init(unsigned int width, unsigned int height, unsigned int layerNumber) { // todo clear all if allready initilized _width = width; _height = height; _layerNumber = layerNumber; glGenFramebuffers(1, &_handle); glBindFramebuffer(GL_FRAMEBUFFER, _handle); _layers = new unsigned int[_layerNumber]; glGenTextures(_layerNumber, _layers); for (unsigned int i = 0; i < _layerNumber; ++i) { _layerNames.push_back("layer" + std::to_string(i)); glBindTexture(GL_TEXTURE_2D, _layers[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glFramebufferTexture2D(GL_FRAMEBUFFER, (GLenum)(GL_COLOR_ATTACHMENT0 + i), GL_TEXTURE_2D, _layers[i], 0); } glBindTexture(GL_TEXTURE_2D, 0); glGenRenderbuffers(1, &_depth); glBindRenderbuffer(GL_RENDERBUFFER, _depth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, _width, _height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depth); glBindRenderbuffer(GL_RENDERBUFFER, 0); if (!checkStatus()) return false; glBindFramebuffer(GL_FRAMEBUFFER, 0); // x,y vertex positions float ss_quad_pos[] = { -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0 }; // per-vertex texture coordinates float ss_quad_st[] = { 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0 }; unsigned int indice[] = {0,1,2,3,4,5}; _vbo.init(6, &indice[0]); _vbo.addAttribute(OpenGLTools::Attribute(sizeof(float) * 2, 2, GL_FLOAT)); _vbo.addAttribute(OpenGLTools::Attribute(sizeof(float) * 2, 2, GL_FLOAT)); _vbo.setBuffer(0, reinterpret_cast<byte *>(&ss_quad_pos)); _vbo.setBuffer(1, reinterpret_cast<byte *>(&ss_quad_st)); return true; }
static FboDesc CreateSurfaces(GLsizei width, GLsizei height, int numComponents, int numTargets) { FboDesc surface; glGenFramebuffers(1, &surface.FboHandle); glBindFramebuffer(GL_FRAMEBUFFER, surface.FboHandle); for (int attachment = 0; attachment < numTargets; ++attachment) { GLuint textureHandle; glGenTextures(1, &textureHandle); glBindTexture(GL_TEXTURE_2D, textureHandle); 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); surface.TextureHandle[attachment] = textureHandle; switch (numComponents) { case 1: glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, 0); break; case 2: glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, width, height, 0, GL_RG, GL_FLOAT, 0); break; case 3: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, 0); break; case 4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, 0); break; default: pezFatal("Illegal slab format."); } pezCheck(GL_NO_ERROR == glGetError(), "Unable to create FBO texture"); // glTexImage2DMultisample // GL_TEXTURE_2D_MULTISAMPLE // glRenderbufferStorageMultisample GLuint colorbuffer; glGenRenderbuffers(1, &colorbuffer); glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachment, GL_TEXTURE_2D, textureHandle, 0); pezCheck(GL_NO_ERROR == glGetError(), "Unable to attach color buffer"); } // Create a depth texture: glGenTextures(1, &surface.DepthTexture); glBindTexture(GL_TEXTURE_2D, surface.DepthTexture); 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); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0); pezCheck(GL_NO_ERROR == glGetError(), "Unable to create depth texture"); // Create a FBO and attach the depth texture: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, surface.DepthTexture, 0); pezCheck(GL_NO_ERROR == glGetError(), "Unable to attach depth texture"); pezCheck(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER), "Unable to create FBO."); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); glBindFramebuffer(GL_FRAMEBUFFER, 0); return surface; }
bool RenderTargetTexture::Init(RenderTarget::Properties* props) { m_properties = *static_cast<RenderTargetTextureProperties*>(props); Clear(); // generate frame buffer glGenFramebuffers(1, &m_fb); // create color texture if (m_color_texture) safe_delete(m_color_texture); m_color_texture = new Texture2D; m_color_texture->Create(m_properties.m_texture_width, m_properties.m_texture_height, ImageModule::IMAGE_FORMAT_RGBA8, 0, false); // if multisample // generate render buffers glGenRenderbuffers(1, &m_depth_rb); glGenRenderbuffers(1, &m_color_rb); // generate resolve frame buffer glGenFramebuffers(1, &m_resolve_fb); // tune resolve frame buffer glBindFramebuffer(GL_FRAMEBUFFER, m_resolve_fb); // bind color texture glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture->GetCode(), 0); Check(); // tune render frame buffer glBindFramebuffer(GL_FRAMEBUFFER, m_fb); // tune color render buffer glBindRenderbuffer(GL_RENDERBUFFER, m_color_rb); int max_samples; glGetIntegerv(GL_MAX_SAMPLES, &max_samples); // for csaa some extra staff needed // create a regular MSAA color buffer glRenderbufferStorageMultisample(GL_RENDERBUFFER, max_samples, GL_RGBA8, m_color_texture->GetWidth(), m_color_texture->GetHeight()); // check the number of samples glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &max_samples); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_rb); Check(); // tune depth render buffer glBindRenderbuffer(GL_RENDERBUFFER, m_depth_rb); // for csaa another method should be used // create a regular MSAA depth buffer glRenderbufferStorageMultisample(GL_RENDERBUFFER, max_samples, GL_DEPTH_COMPONENT24, m_color_texture->GetWidth(), m_color_texture->GetHeight()); // attach depth buffer to frame buffer glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depth_rb); Check(); glBindFramebuffer(GL_FRAMEBUFFER, 0); return true; }
static enum piglit_result exec_test(struct test_info *info, int sample_count) { GLuint fb, tex, rb; GLint result; struct attachment_info *att; GLint maxColorSamples, maxDepthSamples; glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorSamples); glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthSamples); glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER, fb); printf("Testing fbo completeness for config '%s'\n", info->name); for (att=info->attachments; att->target; att++) { int attachment_sample_count = att->multisample ? sample_count : 0; printf(" Att target=%s att=%s samples=%d dims=%d,%d,%d fixed=%d\n", piglit_get_gl_enum_name(att->target), piglit_get_gl_enum_name(att->attachment), attachment_sample_count, SURFACE_WIDTH, SURFACE_HEIGHT, att->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY ? SURFACE_DEPTH : 1, att->fixedsamplelocations); switch (att->target) { case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: if (att->attachment == GL_DEPTH_ATTACHMENT && sample_count > maxDepthSamples) return PIGLIT_SKIP; if ((att->attachment == GL_COLOR_ATTACHMENT0 || att->attachment == GL_COLOR_ATTACHMENT1) && sample_count > maxColorSamples) return PIGLIT_SKIP; } switch (att->target) { case GL_TEXTURE_2D_MULTISAMPLE: glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, attachment_sample_count, choose_format(att), SURFACE_WIDTH, SURFACE_HEIGHT, att->fixedsamplelocations); if (!piglit_check_gl_error(GL_NO_ERROR)) return PIGLIT_FAIL; glFramebufferTexture2D(GL_FRAMEBUFFER, att->attachment, att->target, tex, 0); break; case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, tex); glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, attachment_sample_count, choose_format(att), SURFACE_WIDTH, SURFACE_HEIGHT, SURFACE_DEPTH, att->fixedsamplelocations); if (!piglit_check_gl_error(GL_NO_ERROR)) return PIGLIT_FAIL; glFramebufferTextureLayer(GL_FRAMEBUFFER, att->attachment, tex, 0, att->layer); break; case GL_RENDERBUFFER: /* RENDERBUFFER has fixedsamplelocations implicitly */ assert(att->fixedsamplelocations); glGenRenderbuffers(1, &rb); glBindRenderbuffer(GL_RENDERBUFFER, rb); if (att->multisample) { glRenderbufferStorageMultisample(GL_RENDERBUFFER, attachment_sample_count, choose_format(att), SURFACE_WIDTH, SURFACE_HEIGHT); } else { /* non-MSAA renderbuffer */ glRenderbufferStorage(GL_RENDERBUFFER, choose_format(att), SURFACE_WIDTH, SURFACE_HEIGHT); } glFramebufferRenderbuffer(GL_FRAMEBUFFER, att->attachment, att->target, rb); if (!piglit_check_gl_error(GL_NO_ERROR)) return PIGLIT_FAIL; break; default: assert(!"Unsupported target"); } } result = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (result != info->expected) { printf("glCheckFramebufferStatus: expected %s, got %s\n", piglit_get_gl_enum_name(info->expected), piglit_get_gl_enum_name(result)); return PIGLIT_FAIL; } if (result == GL_FRAMEBUFFER_COMPLETE && info->attachments->multisample) return check_sample_positions(sample_count); return PIGLIT_PASS; }
/* Run through multiple variants to detect mrt settings */ void test_srgb_fbo(GLint ifmt, GLenum fmt, GLenum type) { GLint width, height; GLuint fbo, fbotex; GLenum mrt_bufs[16]; GLfloat quad_color[] = {1.0, 0.0, 0.0, 1.0}; GLfloat vertices[] = { -0.45, -0.75, 0.1, 0.45, -0.75, 0.1, -0.45, 0.75, 0.1, 0.45, 0.75, 0.1 }; EGLSurface surface; RD_START("srgb-fbo", "fmt=%s (%x), ifmt=%s (%x), type=%s (%x)", formatname(fmt), fmt, formatname(ifmt), ifmt, typename(type), type); display = get_display(); /* get an appropriate EGL frame buffer configuration */ ECHK(eglChooseConfig(display, config_attribute_list, &config, 1, &num_config)); DEBUG_MSG("num_config: %d", num_config); /* create an EGL rendering context */ ECHK(context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attribute_list)); surface = make_window(display, config, 64, 64); ECHK(eglQuerySurface(display, surface, EGL_WIDTH, &width)); ECHK(eglQuerySurface(display, surface, EGL_HEIGHT, &height)); DEBUG_MSG("Buffer: %dx%d", width, height); /* connect the context to the surface */ ECHK(eglMakeCurrent(display, surface, surface, context)); program = get_program(vertex_shader_source, fragment_shader_source); GCHK(glBindAttribLocation(program, 0, "aPosition")); link_program(program); GCHK(glGenFramebuffers(1, &fbo)); GCHK(glGenTextures(1, &fbotex)); GCHK(glBindFramebuffer(GL_FRAMEBUFFER, fbo)); GCHK(glBindTexture(GL_TEXTURE_2D, fbotex)); GCHK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); GCHK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); GCHK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); GCHK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); GCHK(glTexImage2D(GL_TEXTURE_2D, 0, ifmt, width, height, 0, fmt, type, 0)); GCHK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbotex, 0)); DEBUG_MSG("status=%04x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); GCHK(glBindFramebuffer(GL_FRAMEBUFFER, fbo)); GCHK(glDrawBuffers(1, (const GLenum[]){GL_COLOR_ATTACHMENT0}));
/*!**************************************************************************** @Function InitView @Return bool true if no error occured @Description Code in InitView() will be called by PVRShell upon initialization or after a change in the rendering context. Used to initialize variables that are dependant on the rendering context (e.g. textures, vertex buffers, etc.) ******************************************************************************/ bool OGLES2RenderToTexture::InitView() { // Find the largest square power of two texture that fits into the viewport m_i32TexSize = 1; int iSize = PVRT_MIN(PVRShellGet(prefWidth), PVRShellGet(prefHeight)); while (m_i32TexSize * 2 < iSize) m_i32TexSize *= 2; srand(PVRShellGetTime()); m_ui32Framenum = rand() % 5000; // Get the initial time m_ui32Time = PVRShellGetTime(); /* Initialize VBO data and load textures */ LoadVbos(); LoadTextures(); /* Load and compile the shaders & link programs */ CPVRTString ErrorStr; if (!LoadShaders(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } // Set the sampler2D uniforms to corresponding texture units glUniform1i(glGetUniformLocation(m_ShaderProgram.uiId, "sTexture"), 0); /* Initialize Print3D */ // Is the screen rotated? bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } glClearColor(0.0f, 0.0f, 0.0f, 0.0f); /* Create two handles for a frame buffer object. */ glGenFramebuffers(2, m_auiFbo); m_i32CurrentFbo = 1; /* Get the currently bound frame buffer object. On most platforms this just gives 0. */ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFbo); /* Attach the renderable objects (e.g. textures) to the frame buffer object now as they will stay attached to the frame buffer object even when it is not bound. */ // We have two FBOs so we're doing the same for each for(int i = 0; i < 2; ++i) { /* Firstly, to do anything with a frame buffer object we need to bind it. In the case below we are binding our frame buffer object to the frame buffer. */ glBindFramebuffer(GL_FRAMEBUFFER, m_auiFbo[i]); /* To render to a texture we need to attach it texture to the frame buffer object. GL_COLOR_ATTACHMENT0 tells it to attach the texture to the colour buffer, the 0 on the end refers to the colour buffer we want to attach it to as a frame buffer object can have more than one colour buffer. */ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_auiTexture[i], 0); // Clear the color buffer for this FBO glClear(GL_COLOR_BUFFER_BIT); /* Create and bind a depth buffer to the frame buffer object. A depth buffer isn't needed for this training course but will likely be required for most uses of frame buffer objects so its attachment is being demonstrated here. */ // Generate and bind the handle for the render buffer (which will become our depth buffer) glGenRenderbuffers(1, &m_auiDepthBuffer[i]); glBindRenderbuffer(GL_RENDERBUFFER, m_auiDepthBuffer[i]); /* Currently it is unknown to GL that we want our new render buffer to be a depth buffer. glRenderbufferStorage will fix this and in this case will allocate a depth buffer of m_i32TexSize by m_i32TexSize. */ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_i32TexSize, m_i32TexSize); // Now we have our depth buffer attach it to our frame buffer object. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_auiDepthBuffer[i]); } /* Unbind the frame buffer object so rendering returns back to the backbuffer. */ glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFbo); // Use a nice bright blue as clear colour glClearColor(0.6f, 0.8f, 1.0f, 1.0f); return true; }
void piglit_init(int argc, char**argv) { GLuint tex; piglit_require_extension("GL_ARB_gpu_shader5"); glGenFramebuffers(1, &ms_fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA, 64, 64, GL_TRUE); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0); if (!piglit_check_gl_error(GL_NO_ERROR)) { printf("fbo setup failed.\n"); piglit_report_result(PIGLIT_SKIP); } /* Test quantity varies from -1 to +1 over 64 pixels -- * so moving 1px changes its value by 1/32. */ draw_prog = piglit_build_simple_program( "#version 150\n" "uniform vec2 sample_pos;\n" "in vec2 p;\n" "out vec2 test;\n" "out vec2 ref;\n" "void main() {\n" " gl_Position = vec4(p, 0, 1);\n" " test = p;\n" " ref = p;\n" " ref.xy += sample_pos / 32;\n" "}\n", "#version 150\n" "#extension GL_ARB_gpu_shader5: require\n" "const int sample_id = 0;\n" "in vec2 test;\n" "in vec2 ref;\n" "void main() {\n" " gl_FragColor = vec4(" GAIN " * abs(\n" " interpolateAtSample(test, sample_id) - ref), 0, 1);\n" "}\n"); if (!draw_prog) { printf("draw_prog compile/link failed\n"); piglit_report_result(PIGLIT_FAIL); } test_prog = piglit_build_simple_program( "#version 150\n" "in vec2 p;\n" "void main() {\n" " gl_Position = vec4(p, 0, 1);\n" "}\n", "#version 150\n" "uniform sampler2DMS s;\n" "void main() {\n" " vec4 temp = \n" " texelFetch(s, ivec2(gl_FragCoord.xy), 0) +\n" " texelFetch(s, ivec2(gl_FragCoord.xy), 1) +\n" " texelFetch(s, ivec2(gl_FragCoord.xy), 2) +\n" " texelFetch(s, ivec2(gl_FragCoord.xy), 3);\n" " gl_FragColor = vec4(temp.x, 1-temp.y, temp.z, temp.w);\n" "}\n"); if (!test_prog) { printf("test_prog compile/link failed\n"); piglit_report_result(PIGLIT_FAIL); } sample_pos_loc = glGetUniformLocation(draw_prog, "sample_pos"); glUseProgram(test_prog); glUniform1i(glGetUniformLocation(test_prog, "s"), 0); if (!piglit_check_gl_error(GL_NO_ERROR)) { printf("shader setup failed\n"); piglit_report_result(PIGLIT_SKIP); } glGenVertexArrays(1, &vao); glBindVertexArray(vao); glEnableVertexAttribArray(0); glGenBuffers(1, &bo); glBindBuffer(GL_ARRAY_BUFFER, bo); glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid const *)0); }
void Effects::setup(int w, int h) { width = w; height = h; cracks.setup(w,h); // create fbo glGenFramebuffers(1, &fbo_handle); eglGetError(); glBindFramebuffer(GL_FRAMEBUFFER, fbo_handle); // create texture. glGenTextures(1, &fbo_tex); eglGetError(); glActiveTexture(GL_TEXTURE0); eglGetError(); glBindTexture(GL_TEXTURE_2D, fbo_tex); eglGetError(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); eglGetError(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); eglGetError(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); eglGetError(); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_tex, 0); eglGetError(); glGenRenderbuffers(1, &fbo_depth); eglGetError(); // render buffer glBindRenderbuffer(GL_RENDERBUFFER, fbo_depth); eglGetError(); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo_depth); eglGetError(); GLenum drawbufs[] = {GL_COLOR_ATTACHMENT0}; glDrawBuffers(1, drawbufs); glBindFramebuffer(GL_FRAMEBUFFER, 0); if(!shader.load("effects/effects")) { printf("Error loading effects shader.\n"); } vertices[0].setPos(-1, -1, 0); vertices[1].setPos(1, -1, 0); vertices[2].setPos(1, 1, 0); vertices[3].setPos(-1, 1, 0); float mw = 1; float mh = 1; vertices[0].setTex(0, 0); vertices[1].setTex(mw, 0); vertices[2].setTex(mw, mh); vertices[3].setTex(0, mh); glGenVertexArraysAPPLE(1, &vao); eglGetError(); glBindVertexArrayAPPLE(vao); eglGetError(); GLint pos_attrib = glGetAttribLocation(shader.getProgram(), "pos"); GLint tex_attrib = glGetAttribLocation(shader.getProgram(), "tex"); glEnableVertexAttribArray(pos_attrib); glEnableVertexAttribArray(tex_attrib); glGenBuffers(1, &vbo); eglGetError(); glBindBuffer(GL_ARRAY_BUFFER, vbo); eglGetError(); glBufferData( GL_ARRAY_BUFFER ,sizeof(Vertex) * 4 ,vertices[0].pos ,GL_STATIC_DRAW ); eglGetError(); glVertexAttribPointer( pos_attrib ,3 ,GL_FLOAT ,GL_FALSE ,sizeof(Vertex) ,offsetof(Vertex, pos) ); glVertexAttribPointer( tex_attrib ,2 ,GL_FLOAT ,GL_FALSE ,sizeof(Vertex) ,(GLvoid*)offsetof(Vertex, tex) ); calcCenter(); unbind(); flip(false); mirror(false); crack(false); }
void MediaSurface::Update() { if ( !AndroidSurfaceTexture ) { LOG( "!AndroidSurfaceTexture" ); return; } if ( TexId <= 0 ) { //LOG( "TexId <= 0" ); return; } AndroidSurfaceTexture->Update(); if ( AndroidSurfaceTexture->nanoTimeStamp == LastSurfaceTexNanoTimeStamp ) { return; } LastSurfaceTexNanoTimeStamp = AndroidSurfaceTexture->nanoTimeStamp; // don't mess up Unity state GLStateSave stateSave; // If we haven't allocated our GL objects yet, do it now. // This isn't done at Init, because GL may not be current then. if ( UnitSquare.vertexArrayObject == 0 ) { LOG( "Allocating GL objects" ); UnitSquare = BuildTesselatedQuad( 1, 1 ); CopyMovieProgram = BuildProgram( "uniform highp mat4 Mvpm;\n" "attribute vec4 Position;\n" "attribute vec2 TexCoord;\n" "varying highp vec2 oTexCoord;\n" "void main()\n" "{\n" " gl_Position = Position;\n" " oTexCoord = TexCoord;\n" "}\n" , "#extension GL_OES_EGL_image_external : require\n" "uniform samplerExternalOES Texture0;\n" "varying highp vec2 oTexCoord;\n" "void main()\n" "{\n" " gl_FragColor = texture2D( Texture0, oTexCoord );\n" "}\n" ); } // If the SurfaceTexture has changed dimensions, we need to // reallocate the texture and FBO. glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_EXTERNAL_OES, AndroidSurfaceTexture->textureId ); // FIXME: no way to get texture dimensions even in ES 3.0??? int width = 960; int height = 540; if ( width != TexIdWidth || height != TexIdHeight ) { LOG( "New surface size: %ix%i", width, height ); TexIdWidth = width; TexIdHeight = height; if ( Fbo ) { glDeleteFramebuffers( 1, &Fbo ); } glActiveTexture( GL_TEXTURE1 ); glBindTexture( GL_TEXTURE_2D, TexId ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, TexIdWidth, TexIdHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 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_LINEAR_MIPMAP_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glBindTexture( GL_TEXTURE_2D, 0 ); glActiveTexture( GL_TEXTURE0 ); glGenFramebuffers( 1, &Fbo ); glBindFramebuffer( GL_FRAMEBUFFER, Fbo ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, TexId, 0 ); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); } glBindFramebuffer( GL_FRAMEBUFFER, Fbo ); glDisable( GL_DEPTH_TEST ); glDisable( GL_SCISSOR_TEST ); glDisable( GL_STENCIL_TEST ); glDisable( GL_CULL_FACE ); glDisable( GL_BLEND ); const GLenum fboAttachments[1] = { GL_COLOR_ATTACHMENT0 }; glInvalidateFramebuffer( GL_FRAMEBUFFER, 1, fboAttachments ); glViewport( 0, 0, TexIdWidth, TexIdHeight ); glUseProgram( CopyMovieProgram.program ); UnitSquare.Draw(); glUseProgram( 0 ); glBindTexture( GL_TEXTURE_EXTERNAL_OES, 0 ); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); glBindTexture( GL_TEXTURE_2D, TexId ); glGenerateMipmap( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, 0 ); }
bool setupDeferred(int w, int h) { std::cout << "setupDeferred " << w << " " << h << std::endl; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, deferredFbo); //color glBindTexture(GL_TEXTURE_2D, deferredColorTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_FLOAT,0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,deferredColorTex,0); //normal GLenum normalInnerFormat; GLenum normalType; normalInnerFormat=GL_RGBA32F; normalType=GL_FLOAT; // normalInnerFormat=GL_RGBA16F; // normalType=GL_HALF_FLOAT; glBindTexture(GL_TEXTURE_2D, deferredNormalTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,normalInnerFormat,w,h,0,GL_RGBA,normalType,0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,deferredNormalTex,0); //depth glBindTexture(GL_TEXTURE_2D, deferredDepthTex); glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT32F,w,h,0,GL_DEPTH_COMPONENT,GL_FLOAT,0); 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); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,deferredDepthTex,0); // GLenum drawBufs[]={GL_COLOR_ATTACHMENT0,GL_COLOR_ATTACHMENT1}; glDrawBuffers(2,drawBufs); //check fbo status GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(status == GL_FRAMEBUFFER_COMPLETE) { //restore default FBO glBindFramebuffer(GL_FRAMEBUFFER, 0); return true; } else if(status==GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) { std::cout << "fbo error: incomplete attachment\n"; } else if(status==GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) { std::cout << "fbo error: incomplete missing attachment\n"; } else if(status==GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER) { std::cout << "fbo error: incomplete draw buffer\n"; } else if(status==GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER) { std::cout << "fbo error: incomplete read buffer\n"; } else if(status==GL_FRAMEBUFFER_UNSUPPORTED) { std::cout << "fbo error: unsupported\n"; } return false; }
/* get buffer as Image */ Image* RenderTexture::newImage(bool fliimage) { CCASSERT(_pixelFormat == Texture2D::PixelFormat::RGBA8888, "only RGBA8888 can be saved as image"); if (nullptr == _texture) { return nullptr; } const Size& s = _texture->getContentSizeInPixels(); // to get the image size to save // if the saving image domain exceeds the buffer texture domain, // it should be cut int savedBufferWidth = (int)s.width; int savedBufferHeight = (int)s.height; GLubyte *buffer = nullptr; GLubyte *tempData = nullptr; Image *image = new (std::nothrow) Image(); do { CC_BREAK_IF(! (buffer = new (std::nothrow) GLubyte[savedBufferWidth * savedBufferHeight * 4])); if(! (tempData = new (std::nothrow) GLubyte[savedBufferWidth * savedBufferHeight * 4])) { delete[] buffer; buffer = nullptr; break; } glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO); glBindFramebuffer(GL_FRAMEBUFFER, _FBO); //TODO move this to configration, so we don't check it every time /* Certain Qualcomm Andreno gpu's will retain data in memory after a frame buffer switch which corrupts the render to the texture. The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture. Create a temporary texture to overcome this. At the end of RenderTexture::begin(), switch the attached texture to the second one, call glClear, and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers. */ if (Configuration::getInstance()->checkForGLExtension("GL_QCOM")) { // -- bind a temporary texture so we can clear the render buffer without losing our texture glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureCopy->getName(), 0); CHECK_GL_ERROR_DEBUG(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0); } glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0,0,savedBufferWidth, savedBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE, tempData); glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO); if ( fliimage ) // -- flip is only required when saving image to file { // to get the actual texture data // #640 the image read from rendertexture is dirty for (int i = 0; i < savedBufferHeight; ++i) { memcpy(&buffer[i * savedBufferWidth * 4], &tempData[(savedBufferHeight - i - 1) * savedBufferWidth * 4], savedBufferWidth * 4); } image->initWithRawData(buffer, savedBufferWidth * savedBufferHeight * 4, savedBufferWidth, savedBufferHeight, 8); } else { image->initWithRawData(tempData, savedBufferWidth * savedBufferHeight * 4, savedBufferWidth, savedBufferHeight, 8); } } while (0); CC_SAFE_DELETE_ARRAY(buffer); CC_SAFE_DELETE_ARRAY(tempData); return image; }
void R_AttachFBOTextureDepth(int texId) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, 0); }
GLNonMultiviewRenderTexture::GLNonMultiviewRenderTexture(int width, int height, int sample_count, int jcolor_format, int jdepth_format, bool resolve_depth, const TextureParameters* texture_parameters, int viewport[]):GLRenderTexture(width, height, sample_count, jcolor_format, jdepth_format, resolve_depth, texture_parameters, viewport) { GLRenderImage* colorbuffer = new GLRenderImage(width, height, jcolor_format, texture_parameters); GLenum depth_format; setImage(colorbuffer); initialize(); getImage()->isReady(); switch (jdepth_format) { case DepthFormat::DEPTH_24: depth_format = GL_DEPTH_COMPONENT24_OES; break; case DepthFormat::DEPTH_24_STENCIL_8: depth_format = GL_DEPTH24_STENCIL8_OES; break; default: depth_format = GL_DEPTH_COMPONENT16; break; } if (sample_count <= 1) { generateRenderTextureNoMultiSampling(jdepth_format, depth_format, width, height); } else if (resolve_depth) { generateRenderTexture(sample_count, jdepth_format, depth_format, width, height, jcolor_format); } else { generateRenderTextureEXT(sample_count, jdepth_format, depth_format, width, height); } if (jdepth_format != DepthFormat::DEPTH_0) { GLenum attachment = DepthFormat::DEPTH_24_STENCIL_8 == jdepth_format ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderTexture_gl_render_buffer_->id()); } glScissor(0, 0, width, height); glViewport(0, 0, width, height); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); if (resolve_depth && sample_count > 1) { delete renderTexture_gl_resolve_buffer_; renderTexture_gl_resolve_buffer_ = new GLFrameBuffer(); glBindFramebuffer(GL_FRAMEBUFFER, renderTexture_gl_resolve_buffer_->id()); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorbuffer->getTarget(), colorbuffer->getId(), 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { LOGE("resolve FBO %i is not complete: 0x%x", renderTexture_gl_resolve_buffer_->id(), status); } } glBindFramebuffer(GL_FRAMEBUFFER, 0); checkGLError(" GLNonMultiviewRenderTexture:"); }
void R_AttachFBOTexturePackedDepthStencil(int texId) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, 0); }
void QGLTextureGlyphCache::resizeTextureData(int width, int height) { // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail int oldWidth = m_width; int oldHeight = m_height; GLuint oldTexture = m_texture; createTextureData(width, height); glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); GLuint tmp_texture; glGenTextures(1, &tmp_texture); glBindTexture(GL_TEXTURE_2D, tmp_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tmp_texture, 0); glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); glBindTexture(GL_TEXTURE_2D, oldTexture); pex->transferMode(BrushDrawingMode); glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glViewport(0, 0, oldWidth, oldHeight); GLfloat* vertexCoordinateArray = pex->staticVertexCoordinateArray; vertexCoordinateArray[0] = -1.0f; vertexCoordinateArray[1] = -1.0f; vertexCoordinateArray[2] = 1.0f; vertexCoordinateArray[3] = -1.0f; vertexCoordinateArray[4] = 1.0f; vertexCoordinateArray[5] = 1.0f; vertexCoordinateArray[6] = -1.0f; vertexCoordinateArray[7] = 1.0f; GLfloat* textureCoordinateArray = pex->staticTextureCoordinateArray; textureCoordinateArray[0] = 0.0f; textureCoordinateArray[1] = 0.0f; textureCoordinateArray[2] = 1.0f; textureCoordinateArray[3] = 0.0f; textureCoordinateArray[4] = 1.0f; textureCoordinateArray[5] = 1.0f; textureCoordinateArray[6] = 0.0f; textureCoordinateArray[7] = 1.0f; pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertexCoordinateArray); pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, textureCoordinateArray); pex->shaderManager->useBlitProgram(); pex->shaderManager->blitProgram()->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glBindTexture(GL_TEXTURE_2D, m_texture); #ifdef QT_OPENGL_ES_2 QDataBuffer<uchar> buffer(4*oldWidth*oldHeight); buffer.resize(4*oldWidth*oldHeight); glReadPixels(0, 0, oldWidth, oldHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data()); // do an in-place conversion from GL_RGBA to GL_ALPHA for (int i=0; i<oldWidth*oldHeight; ++i) buffer.data()[i] = buffer.at(4*i + 3); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, buffer.data()); #else glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); #endif glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, 0); glDeleteTextures(1, &tmp_texture); glDeleteTextures(1, &oldTexture); glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); glViewport(0, 0, pex->width, pex->height); pex->updateClipScissorTest(); }
void TerrainQuadtree::generateTextures() { // prepare viewport and projection //glDisable(GL_DEPTH_TEST); // do not setup the proj more than once if (this->parent == NULL) { glViewport(0, 0, this->textureSize, this->textureSize); glMatrixMode(GL_PROJECTION); glPolygonMode(GL_FRONT, GL_FILL); glLoadIdentity(); glOrtho(0.0, (double)this->textureSize, 0.0, (double)this->textureSize, 0.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslated(0.0, 0.0, -1.0); generationScreenList = glGenLists(1); glNewList(generationScreenList, GL_COMPILE); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex3f(this->textureSize, 0.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(this->textureSize, this->textureSize, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(0.0, this->textureSize, 0.0); glEnd(); glEndList(); } // generate topography glBindFramebuffer(GL_FRAMEBUFFER, this->framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->topoTexture->id, 0); this->positionTexture->bind(GL_TEXTURE0); this->generatorShader->bind(); glUniform1i(glGetUniformLocation(this->generatorShader->program, "positionTexture"), 0); glCallList(generationScreenList); this->generatorShader->unbind(); //glBindFramebuffer(GL_FRAMEBUFFER, 0); // generate normals //glBindFramebuffer(GL_FRAMEBUFFER, this->framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->normalTexture->id, 0); this->topoTexture->bind(GL_TEXTURE1); this->generatorShaderN->bind(); glUniform1f(glGetUniformLocation(this->generatorShaderN->program, "size"), (float)this->textureSize); glUniform1f(glGetUniformLocation(this->generatorShaderN->program, "radius"), this->planet->radius); glUniform1i(glGetUniformLocation(this->generatorShaderN->program, "topoTexture"), 1); glUniform1i(glGetUniformLocation(this->generatorShaderN->program, "positionTexture"), 0); glCallList(generationScreenList); this->generatorShaderN->unbind(); //glBindFramebuffer(GL_FRAMEBUFFER, 0); // generate colors //glBindFramebuffer(GL_FRAMEBUFFER, this->framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->colorTexture->id, 0); this->generatorShaderC->bind(); glUniform1i(glGetUniformLocation(this->generatorShaderC->program, "topoTexture"), 1); glCallList(generationScreenList); this->generatorShaderC->unbind(); //glBindFramebuffer(GL_FRAMEBUFFER, 0); //glEnable(GL_DEPTH_TEST); this->ready = true; }
bool WaterBallDrawer::setup(int w, int h) { assert(w && h); win_w = w; win_h = h; pm.ortho(0, w, h, 0, 0.0f, 100.0f); // create basic shader const char* atts[] = { "a_pos", "a_size" } ; const char* frags[] = { "out_normals", "out_alpha" }; basic_prog.create(GL_VERTEX_SHADER, rx_to_data_path("shaders/waterdrop_basic.vert")); basic_prog.create(GL_FRAGMENT_SHADER, rx_to_data_path("shaders/waterdrop_basic.frag")); basic_prog.link(2, atts, 2, frags); glUseProgram(basic_prog.id); glUniformMatrix4fv(glGetUniformLocation(basic_prog.id, "u_pm"), 1, GL_FALSE, pm.ptr()); glUniform1i(glGetUniformLocation(basic_prog.id, "u_normals_tex"), 0); glUniform1i(glGetUniformLocation(basic_prog.id, "u_alpha_tex"), 1); // create water render shader water_prog.create(GL_VERTEX_SHADER, rx_to_data_path("shaders/waterdrop_water.vert")); water_prog.create(GL_FRAGMENT_SHADER, rx_to_data_path("shaders/waterdrop_water.frag")); water_prog.link(); glUseProgram(water_prog.id); glUniform1i(glGetUniformLocation(water_prog.id, "u_normals_tex"), 0); glUniform1i(glGetUniformLocation(water_prog.id, "u_alpha_tex"), 1); glUniform1i(glGetUniformLocation(water_prog.id, "u_background_tex"), 2); glGenVertexArrays(1, &water_vao); glGenVertexArrays(1, &basic_vao); glBindVertexArray(basic_vao); glGenBuffers(1, &basic_vbo); glBindBuffer(GL_ARRAY_BUFFER, basic_vbo); glEnableVertexAttribArray(0); // pos glEnableVertexAttribArray(1); // size glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(WaterDrop), (GLvoid*) 0); glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, sizeof(WaterDrop), (GLvoid*) 32); glVertexAttribDivisor(0, 1); glVertexAttribDivisor(1, 1); normals_tex = rx_create_texture(rx_to_data_path("images/waterdrop_normals.png")); alpha_tex = rx_create_texture(rx_to_data_path("images/waterdrop_alpha.png")); background_tex = rx_create_texture(rx_to_data_path("images/waterdrop_background.png")); glBindTexture(GL_TEXTURE_2D, background_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // fbo glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glGenTextures(1, &scene_normals_tex); glBindTexture(GL_TEXTURE_2D, scene_normals_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, win_w, win_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, scene_normals_tex, 0); glGenTextures(1, &scene_alpha_tex); glBindTexture(GL_TEXTURE_2D, scene_alpha_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, win_w, win_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, scene_alpha_tex, 0); if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { printf("Framebuffer not complete.\n"); return false; } glBindFramebuffer(GL_FRAMEBUFFER, 0); return true; }
int main() { GLsizei multiSamples = 8; GLFWwindow* window = initWindow(); if (window == nullptr) { std::cout << "Unable to initialize window." << std::endl; return -1; } // Start the timer GLfloat deltaTime, lastFrame, currentFrame; lastFrame = 0.0f; currentFrame = 0.0f; // Setup the viewport; GLfloat screenWidth = 800, screenHeight = 600; glViewport(0, 0, screenWidth, screenHeight); // Setup Camera Camera cam = initCamera(); glfwSetWindowUserPointer(window, &cam); // Load Models Model planet = Model("./Models/planet/planet.obj"); Model asteroid = Model("./Models/rock/rock.obj"); // Load and Compile Shaders GLuint program = compileShaders("../OpenGL3-3/shaders/advanced/instance/basic.vert.glsl", "../OpenGL3-3/shaders/advanced/instance/basic.frag.glsl"); GLuint modelShader = compileShaders("../OpenGL3-3/shaders/newModel/model.vert.glsl", "../OpenGL3-3/shaders/newModel/model.frag.glsl"); GLuint instancedModelShader = compileShaders("../OpenGL3-3/shaders/newModel/imodel.vert.glsl", "../OpenGL3-3/shaders/newModel/model.frag.glsl"); GLuint frameBufferShader = compileShaders("../OpenGL3-3/shaders/advanced/fbo.vert.glsl", "../OpenGL3-3/shaders/advanced/fbo.frag.glsl"); // Setup MVP model glm::mat4 model, view, proj; view = cam.GetViewMatrix(); proj = glm::perspective(glm::radians(45.0f), (float)screenWidth / (float)screenHeight, 0.1f, 1000.0f); #pragma region quad GLfloat quadVertices[] = { // Positions // Colors -0.05f, 0.05f, 1.0f, 0.0f, 0.0f, 0.05f, -0.05f, 0.0f, 1.0f, 0.0f, -0.05f, -0.05f, 0.0f, 0.0f, 1.0f, -0.05f, 0.05f, 1.0f, 0.0f, 0.0f, 0.05f, -0.05f, 0.0f, 1.0f, 0.0f, 0.05f, 0.05f, 0.0f, 1.0f, 1.0f }; glm::vec2 translations[100]; int index = 0; GLfloat offset = 0.1f; for (GLint y = -10; y < 10; y += 2) { for (GLint x = -10; x < 10; x += 2) { glm::vec2 translation; translation.x = (GLfloat)x / 10.0f + offset; translation.y = (GLfloat)y / 10.0f + offset; translations[index++] = translation; } } GLfloat fboQuad[] = { -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f }; #pragma endregion GLuint VBO, VAO, instanceVBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &instanceVBO); glBindBuffer(GL_ARRAY_BUFFER, instanceVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * 100, &translations[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); // Create the Framebuffer GLuint FBO; glGenFramebuffers(1, &FBO); glBindFramebuffer(GL_FRAMEBUFFER, FBO); GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, multiSamples, GL_RGB, screenWidth, screenHeight, GL_TRUE);// , GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture, 0); GLuint sampleRBO; glGenRenderbuffers(1, &sampleRBO); glBindRenderbuffer(GL_RENDERBUFFER, sampleRBO); glRenderbufferStorageMultisample(GL_RENDERBUFFER, multiSamples, GL_DEPTH24_STENCIL8, screenWidth, screenHeight); glBindRenderbuffer(GL_RENDERBUFFER, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, sampleRBO); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "FRAMEBUFFER INCOMPLETE!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); GLuint regularFBO; glGenFramebuffers(1, ®ularFBO); glBindFramebuffer(GL_FRAMEBUFFER, regularFBO); GLuint tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "FRAMEBUFFER 2 INCOMPLETE!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); GLuint fboVAO, fboVBO; glGenVertexArrays(1, &fboVAO); glGenBuffers(1, &fboVBO); glBindVertexArray(fboVAO); glBindBuffer(GL_ARRAY_BUFFER, fboVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(fboQuad), fboQuad, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2*sizeof(GLfloat))); glBindVertexArray(0); glBindVertexArray(VAO); { glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLvoid*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLvoid*)(sizeof(GLfloat) * 2)); glEnableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER, instanceVBO); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0); glBindBuffer(GL_ARRAY_BUFFER, 0); glVertexAttribDivisor(2, 1); } glBindVertexArray(0); std::cout << sizeof(glm::mat4) << std::endl; const int amount = 100000; glm::mat4* modelMats; modelMats = new glm::mat4[amount]; srand(glfwGetTime()); GLfloat radius = 150.0f; offset = 25.0f; for (GLuint i = 0; i < amount; i++) { glm::mat4 model; GLfloat angle = (GLfloat)i / (GLfloat)amount * 360.0f; GLfloat displacement = (rand() % (GLint)(2 * offset)) / 100.0f - offset; GLfloat x = sin(angle) * radius + displacement; displacement = (rand() % (GLint)(2 * offset * 100)) / 100.0f - offset; GLfloat y = displacement * 0.4f; displacement = (rand() % (GLint)(2 * offset * 100)) / 100.0f - offset; GLfloat z = cos(angle) * radius + displacement; model = glm::translate(model, glm::vec3(x, y, z)); GLfloat scale = (rand() % 20) / 100.0f + 0.05f; model = glm::scale(model, glm::vec3(scale)); GLfloat rotAngle = (rand() % 360); model = glm::rotate(model, rotAngle, glm::vec3(0.4f, 0.6f, 0.8f)); modelMats[i] = model; } for (GLuint i = 0; i < asteroid.meshes.size(); i++) { GLuint VAO = asteroid.meshes[i].VAO; GLuint buffer; glBindVertexArray(VAO); glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, amount * sizeof(glm::mat4), &modelMats[0], GL_STATIC_DRAW); GLsizei vec4Size = sizeof(glm::vec4); glEnableVertexAttribArray(3); glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)0); glEnableVertexAttribArray(4); glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)(vec4Size)); glEnableVertexAttribArray(5); glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)(2 * vec4Size)); glEnableVertexAttribArray(6); glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)(3 * vec4Size)); glVertexAttribDivisor(3, 1); glVertexAttribDivisor(4, 1); glVertexAttribDivisor(5, 1); glVertexAttribDivisor(6, 1); glBindVertexArray(0); } glUseProgram(modelShader); glUniformMatrix4fv(glGetUniformLocation(modelShader, "projection"), 1, GL_FALSE, glm::value_ptr(proj)); glUseProgram(instancedModelShader); glUniformMatrix4fv(glGetUniformLocation(instancedModelShader, "projection"), 1, GL_FALSE, glm::value_ptr(proj)); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glBindFramebuffer(GL_FRAMEBUFFER, FBO); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); handleMovement(window, deltaTime); glUseProgram(instancedModelShader); glUniformMatrix4fv(glGetUniformLocation(instancedModelShader, "view"), 1, GL_FALSE, glm::value_ptr(cam.GetViewMatrix())); glUseProgram(modelShader); glUniformMatrix4fv(glGetUniformLocation(modelShader, "view"), 1, GL_FALSE, glm::value_ptr(cam.GetViewMatrix())); glm::mat4 model; model = glm::translate(model, glm::vec3(0.0f, -5.0f, 0.0f)); model = glm::scale(model, glm::vec3(4.0f)); glUniformMatrix4fv(glGetUniformLocation(modelShader, "model"), 1, GL_FALSE, glm::value_ptr(model)); planet.draw(modelShader); glUseProgram(instancedModelShader); glBindTexture(GL_TEXTURE_2D, asteroid.textures_loaded[0].id); for (GLuint i = 0; i < asteroid.meshes.size(); i++) { glBindVertexArray(asteroid.meshes[i].VAO); glDrawElementsInstanced(GL_TRIANGLES, asteroid.meshes[i].vertices.size(), GL_UNSIGNED_INT, 0, amount); glBindVertexArray(0); } glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, FBO); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, regularFBO); glBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, 0); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glUseProgram(frameBufferShader); glBindVertexArray(fboVAO); glBindTexture(GL_TEXTURE_2D, tex); //glUniform1i(glGetUniformLocation(frameBufferShader, "myTexture"), 0); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); glBindTexture(GL_TEXTURE_2D, 0); glfwSwapBuffers(window); } glfwTerminate(); return 0; }
int main(int argc, char **argv) { // init global vars initSharedMem(); // register exit callback atexit(exitCB); // init GLUT and GL initGLUT(argc, argv); initGL(); // create a texture object glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 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_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap generation included in OpenGL v1.4 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); // get OpenGL info glInfo glInfo; glInfo.getInfo(); //glInfo.printSelf(); #ifdef _WIN32 // check if FBO is supported by your video card if(glInfo.isExtensionSupported("GL_ARB_framebuffer_object")) { // get pointers to GL functions glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers"); glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffers"); glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer"); glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatus"); glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)wglGetProcAddress("glGetFramebufferAttachmentParameteriv"); glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)wglGetProcAddress("glGenerateMipmap"); glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)wglGetProcAddress("glFramebufferTexture1D"); glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D"); glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)wglGetProcAddress("glFramebufferTexture3D"); glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)wglGetProcAddress("glFramebufferTextureLayer"); glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress("glFramebufferRenderbuffer"); glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)wglGetProcAddress("glIsFramebuffer"); glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)wglGetProcAddress("glBlitFramebuffer"); glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)wglGetProcAddress("glGenRenderbuffers"); glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress("glDeleteRenderbuffers"); glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress("glBindRenderbuffer"); glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)wglGetProcAddress("glRenderbufferStorage"); glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)wglGetProcAddress("glRenderbufferStorageMultisample"); glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)wglGetProcAddress("glGetRenderbufferParameteriv"); glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)wglGetProcAddress("glIsRenderbuffer"); // check once again FBO extension if(glGenFramebuffers && glDeleteFramebuffers && glBindFramebuffer && glCheckFramebufferStatus && glGetFramebufferAttachmentParameteriv && glGenerateMipmap && glFramebufferTexture1D && glFramebufferTexture2D && glFramebufferTexture3D && glFramebufferTextureLayer && glFramebufferRenderbuffer && glIsFramebuffer && glBlitFramebuffer && glGenRenderbuffers && glDeleteRenderbuffers && glBindRenderbuffer && glRenderbufferStorage && glRenderbufferStorageMultisample && glGetRenderbufferParameteriv && glIsRenderbuffer) { fboSupported = fboUsed = true; std::cout << "Video card supports GL_ARB_framebuffer_object." << std::endl; } else { fboSupported = fboUsed = false; std::cout << "Video card does NOT support GL_ARB_framebuffer_object." << std::endl; } } // check EXT_swap_control is supported if(glInfo.isExtensionSupported("WGL_EXT_swap_control")) { // get pointers to WGL functions wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT"); if(wglSwapIntervalEXT && wglGetSwapIntervalEXT) { // disable v-sync wglSwapIntervalEXT(0); std::cout << "Video card supports WGL_EXT_swap_control." << std::endl; } } #else // for linux, do not need to get function pointers, it is up-to-date if(glInfo.isExtensionSupported("GL_ARB_framebuffer_object")) { fboSupported = fboUsed = true; std::cout << "Video card supports GL_ARB_framebuffer_object." << std::endl; } else { fboSupported = fboUsed = false; std::cout << "Video card does NOT support GL_ARB_framebuffer_object." << std::endl; } #endif if(fboSupported) { // create a MSAA framebuffer object // NOTE: All attachment images must have the same # of samples. // Ohterwise, the framebuffer status will not be completed. glGenFramebuffers(1, &fboMsaaId); glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId); // create a MSAA renderbuffer object to store color info glGenRenderbuffers(1, &rboColorId); glBindRenderbuffer(GL_RENDERBUFFER, rboColorId); glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaaCount, GL_RGB8, TEXTURE_WIDTH, TEXTURE_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, 0); // create a MSAA renderbuffer object to store depth info // NOTE: A depth renderable image should be attached the FBO for depth test. // If we don't attach a depth renderable image to the FBO, then // the rendering output will be corrupted because of missing depth test. // If you also need stencil test for your rendering, then you must // attach additional image to the stencil attachement point, too. glGenRenderbuffers(1, &rboDepthId); glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId); glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaaCount, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, 0); // attach msaa RBOs to FBO attachment points glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboColorId); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepthId); // create a normal (no MSAA) FBO to hold a render-to-texture glGenFramebuffers(1, &fboId); glBindFramebuffer(GL_FRAMEBUFFER, fboId); glGenRenderbuffers(1, &rboId); glBindRenderbuffer(GL_RENDERBUFFER, rboId); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, 0); // attach a texture to FBO color attachement point glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); // attach a rbo to FBO depth attachement point glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId); //@@ disable color buffer if you don't attach any color buffer image, //@@ for example, rendering the depth buffer only to a texture. //@@ Otherwise, glCheckFramebufferStatus will not be complete. //glDrawBuffer(GL_NONE); //glReadBuffer(GL_NONE); // check FBO status printFramebufferInfo(fboMsaaId); bool status = checkFramebufferStatus(fboMsaaId); if(!status) fboUsed = false; glBindFramebuffer(GL_FRAMEBUFFER, 0); } // start timer, the elapsed time will be used for rotating the teapot timer.start(); // the last GLUT call (LOOP) // window will be shown and display callback is triggered by events // NOTE: this call never return main(). glutMainLoop(); /* Start GLUT event-processing loop */ return 0; }
int main(int argc, char *argv[]) { auto t_start = std::chrono::high_resolution_clock::now(); GLfloat directionx, directiony, directionz; directionx = 0.0f; directiony = 0.0f; directionz = 1.0f; GLboolean quit = GL_FALSE; GLenum errorValue; // Initialize SDL if (SDL_Init(SDL_INIT_VIDEO) < 0) { std::cerr << "SDL video initialization failed! Error: " << SDL_GetError() << std::endl; quit = GL_TRUE; SDL_Delay(5000); } SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_Window* window = SDL_CreateWindow("OpenGL tutorial", 100, 100, width, height, SDL_WINDOW_OPENGL); SDL_GLContext context = SDL_GL_CreateContext(window); // Initialize GLEW glewExperimental = GL_TRUE; glewInit(); // Error checking errorValue = glGetError(); if (errorValue != 0) { std::cerr << "GL_Error after GLEW init: " << errorValue << std::endl; } // Create Vertex Array Objects, don't bind yet /* VAOs are used to store all of the links between the vertex attributes and VBOs with raw vertex data. Since VBOs are just containers for the raw data that the graphics card reads and manipulates, the meaning and usage of the data has to be specified for each VBO & shader program. This might be quite cumbersome, if many shader programs are used, since the layout of the attributes would have to be specified every time. This is wheree VAOs come in: they can be used to store the links between VBO and the specified attributes. This way, a new VAO can be bound for each different shader program, which can then be changed easily at will by just calling glUseProgram(shaderProg1);. The graphics card then knows how to use the raw data in the VBO, since its usage and meaning has been specified beforehand and the links between VBOs and attributes has been saved to the VAO. As soon as VAO has been bound, all glVertexAttribPointer calls store the information to that VAO. */ GLuint vaoCube, vaoQuad; glGenVertexArrays(1, &vaoCube); glGenVertexArrays(1, &vaoQuad); // Create a Vertex Buffer Objects and upload vertex data /* VBOs are used to upload the vertex data to the graphics card. glGenBuffers(); creates a VBO, which can then be made active by binding it with glBindBuffer();. When the VBO has been set as active by binding it, the vertex data can be loaded to it with glBufferData();. Note that VBO/OpenGL doesn't know what the data means or is used for, it's just raw data. The usage of the data has to be specified, meaning which indices in the data correspond to which attribute (pos, color, texcoord, etc.). */ GLuint vboCube, vboQuad; glGenBuffers(1, &vboCube); glGenBuffers(1, &vboQuad); glBindBuffer(GL_ARRAY_BUFFER, vboCube); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, vboQuad); glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW); // Error checking errorValue = glGetError(); if (errorValue != 0) { std::cerr << "GL_Error after VBOs: " << errorValue << std::endl; } // Generate shader programs GLuint sceneVertexShader, sceneFragmentShader, sceneShaderProgram; createShaderprogram(sceneVertexSource, sceneFragmentSource, sceneVertexShader, sceneFragmentShader, sceneShaderProgram); GLuint screenVertexShader, screenFragmentShader, screenShaderProgram; createShaderprogram(screenVertexSource, screenFragmentSource, screenVertexShader, screenFragmentShader, screenShaderProgram); // Error checking errorValue = glGetError(); if (errorValue != 0) { std::cerr << "GL_Error after generating shader programs: " << errorValue << std::endl; } // Specify the layout of the vertex data (bind vertex arrays) /* Since OpenGL doesn't know how the attributes of the vertices are specified in the arrays containing the vertex information (position, color, texture coordinates), they need to be specified by the user. Each attribute also saves the VBO that's been bound to the current GL_ARRAY_BUFFER. This means different VBOs can be used for each attribute if so desired. Only calls after a VAO has been bound will "stick" to it. As soon as VAO has been bound, all glVertexAttribPointer calls store the information to that VAO. See more complete explanation of VAO above. */ glBindVertexArray(vaoCube); glBindBuffer(GL_ARRAY_BUFFER, vboCube); specifySceneVertexAttributes(sceneShaderProgram); glBindVertexArray(vaoQuad); glBindBuffer(GL_ARRAY_BUFFER, vboQuad); specifyScreenVertexAttributes(screenShaderProgram); // Error checking errorValue = glGetError(); if (errorValue != 0) { std::cerr << "GL_Error after specifying the layout of vertex data: " << errorValue << std::endl; } // Load textures GLuint texKitten = loadTexture("sample.png"); GLuint texPuppy = loadTexture("sample2.png"); glUseProgram(sceneShaderProgram); glUniform1i(glGetUniformLocation(sceneShaderProgram, "texKitten"), 0); glUniform1i(glGetUniformLocation(sceneShaderProgram, "texPuppy"), 1); glUseProgram(screenShaderProgram); glUniform1i(glGetUniformLocation(screenShaderProgram, "texFramebuffer"), 0); GLint uniModel = glGetUniformLocation(sceneShaderProgram, "model"); // Error checking errorValue = glGetError(); if (errorValue != 0) { std::cerr << "GL_Error after loading textures: " << errorValue << std::endl; } // Create frame buffer GLuint frameBuffer; glGenFramebuffers(1, &frameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); // Error checking errorValue = glGetError(); if (errorValue != 0) { std::cerr << "GL_Error after creating a frame buffer: " << errorValue << std::endl; } // Create texture to hold color buffer GLuint texColorBuffer; glGenTextures(1, &texColorBuffer); glBindTexture(GL_TEXTURE_2D, texColorBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0); // Error checking errorValue = glGetError(); if (errorValue != 0) { std::cerr << "GL_Error after color buffer texture creation: " << errorValue << std::endl; } // Create Renderbuffer Object to hold depth and stencil buffers GLuint rboDepthStencil; glGenRenderbuffers(1, &rboDepthStencil); glBindRenderbuffer(GL_RENDERBUFFER, rboDepthStencil); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboDepthStencil); // Error checking errorValue = glGetError(); if (errorValue != 0) { std::cerr << "GL_Error after RBO: " << errorValue << std::endl; } /* Set up projection: View matrix: First vector gives the position of the camera Second vector gives the point where the camera is centered or looking at Third vector defines "up", here up is the z-axis, xy-plane is the "ground" */ glm::mat4 view = glm::lookAt( glm::vec3(2.5f, 2.5f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f) ); glUseProgram(sceneShaderProgram); GLint uniView = glGetUniformLocation(sceneShaderProgram, "view"); glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view)); // Projection matrix glm::mat4 proj = glm::perspective(glm::radians(45.0f), GLfloat(width) / GLfloat(height), 1.0f, 10.0f); GLint uniProj = glGetUniformLocation(sceneShaderProgram, "proj"); glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj)); GLint uniColor = glGetUniformLocation(sceneShaderProgram, "overrideColor"); // Final error check will write errors (if any are encountered at this point) to file GLint status, status2, status3, status4, OpenGLError; OpenGLError = glGetError(); GLenum frameBufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); glGetShaderiv(sceneVertexShader, GL_COMPILE_STATUS, &status); glGetShaderiv(sceneFragmentShader, GL_COMPILE_STATUS, &status2); glGetShaderiv(screenVertexShader, GL_COMPILE_STATUS, &status3); glGetShaderiv(screenFragmentShader, GL_COMPILE_STATUS, &status4); if ( OpenGLError != 0 || status == 0 || status2 == 0 || status3 == 0 || status4 == 0 || frameBufferStatus != GL_FRAMEBUFFER_COMPLETE) { char buffer1[512], buffer2[512], buffer3[512], buffer4[512]; glGetShaderInfoLog(sceneVertexShader, 512, NULL, buffer1); glGetShaderInfoLog(sceneFragmentShader, 512, NULL, buffer2); glGetShaderInfoLog(screenVertexShader, 512, NULL, buffer3); glGetShaderInfoLog(screenFragmentShader, 512, NULL, buffer4); std::ofstream errorOutput; GLchar* errorOutFilename = "shader_errors.txt"; errorOutput.open(errorOutFilename); errorOutput << "GL_Error: " << OpenGLError << "\n Scene vertex shader status: " << status << "\n Scene vertex shader log: " << buffer1 << "\n Scene fragment shader status: " << status2 << "\n Scene fragment shader log: " << buffer2 << "\n Screen vertex shader status: " << status3 << "\n Screen vertex shader log: " << buffer3 << "\n Screen fragment shader status: " << status4 << "\n Screen fragment shader log: " << buffer4 << "\n Frame buffer status: " << frameBufferStatus << "\n OpenGL version: " << glGetString(GL_VERSION); errorOutput.close(); std::cerr << "An error has occured with shaders or frame buffer! See " << errorOutFilename << " for more info!\n Terminating program in 10s!" << std::endl; SDL_Delay(10000); quit = GL_TRUE; } SDL_Event e; while (!quit) { while (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { quit = GL_TRUE; } else if (e.type == SDL_KEYDOWN) { switch (e.key.keysym.sym) { case SDLK_RETURN: directionx = 1.0f; directiony = 0.0f; directionz = 0.0f; break; case SDLK_SPACE: directionx = 0.0f; directiony = 1.0f; directionz = 0.0f; break; case SDLK_LCTRL: directionx = 0.0f; directiony = 0.0f; directionz = 1.0f; default: directionx = 0.0f; directiony = 0.0f; directionz = 1.0f; break; } } } // Bind framebuffer and draw 3D scene glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); glBindVertexArray(vaoCube); glEnable(GL_DEPTH_TEST); glUseProgram(sceneShaderProgram); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texKitten); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texPuppy); // Clear screen to greenish glClearColor(0.15f, 0.7f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Calculate transformation auto t_now = std::chrono::high_resolution_clock::now(); float time = std::chrono::duration_cast<std::chrono::duration<float>>(t_now - t_start).count(); glm::mat4 model; model = glm::rotate(model, time * glm::radians(180.f), glm::vec3(directionx, directiony, directionz)); glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model)); // Draw cube glDrawArrays(GL_TRIANGLES, 0, 36); glEnable(GL_STENCIL_TEST); // Draw floor glStencilFunc(GL_ALWAYS, 1, 0xFF); // Set any stencil to 1 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilMask(0xFF); // Write to stencil buffer glDepthMask(GL_FALSE); // Don't write to depth buffer glClear(GL_STENCIL_BUFFER_BIT); // Clear stencil buffer (0 by default) glDrawArrays(GL_TRIANGLES, 36, 6); // Draw cube reflection glStencilFunc(GL_EQUAL, 1, 0xFF); // Pass test if stencil value is 1 glStencilMask(0x00); // Don't write anything to stencil buffer glDepthMask(GL_TRUE); // Write to depth buffer model = glm::scale(glm::translate(model, glm::vec3(0, 0, -1)), glm::vec3(1, 1, -1)); glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model)); glUniform3f(uniColor, 0.3f, 0.3f, 0.3f); glDrawArrays(GL_TRIANGLES, 0, 36); glUniform3f(uniColor, 1.0f, 1.0f, 1.0f); glDisable(GL_STENCIL_TEST); // Bind default framebuffer and draw contents of our framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindVertexArray(vaoQuad); glDisable(GL_DEPTH_TEST); glUseProgram(screenShaderProgram); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texColorBuffer); glDrawArrays(GL_TRIANGLES, 0, 6); // Swap buffers SDL_GL_SwapWindow(window); } glDeleteRenderbuffers(1, &rboDepthStencil); glDeleteTextures(1, &texColorBuffer); glDeleteFramebuffers(1, &frameBuffer); glDeleteTextures(1, &texKitten); glDeleteTextures(1, &texPuppy); glDeleteProgram(screenShaderProgram); glDeleteShader(screenFragmentShader); glDeleteShader(screenVertexShader); glDeleteProgram(sceneShaderProgram); glDeleteShader(sceneFragmentShader); glDeleteShader(sceneVertexShader); glDeleteBuffers(1, &vboCube); glDeleteBuffers(1, &vboQuad); glDeleteVertexArrays(1, &vaoCube); glDeleteVertexArrays(1, &vaoQuad); SDL_GL_DeleteContext(context); SDL_Quit(); return 0; }
CubeTextureFBO::CubeTextureFBO(unsigned int size, int format, GLuint targets, bool storeDepth) { this->size = size; this->store_depths = storeDepth; const GLenum faces[6] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; texture.resize(targets); // Initialize Texture glGenTextures(targets, &texture[0]); for (size_t i = 0; i < targets; i++) { glBindTexture(GL_TEXTURE_CUBE_MAP, texture[i]); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); for (size_t j = 0; j < 6; j++) { glTexImage2D(faces[j], 0, format, size, size, 0, GL_RGBA, GL_FLOAT, NULL); } } if(!storeDepth) { //Create depth bufferGLuint rboId; glGenRenderbuffers(1, &depth); glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); glBindRenderbuffer(GL_RENDERBUFFER, 0); } else { glGenTextures(targets, &depth); glBindTexture(GL_TEXTURE_CUBE_MAP, depth); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); for (size_t j = 0; j < 6; j++) { glTexImage2D(faces[j], 0, GL_DEPTH_COMPONENT24, size, size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); } } // Create FBO and attach buffers glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); for (uint i = 0; i < targets; i++) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, texture[i], 0); } if (!storeDepth) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); } else { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, depth, 0); } CHECK_GL_ERRORS(); CHECK_GL_FBO_COMPLETENESS(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindFramebuffer(GL_FRAMEBUFFER, 0); }
void ShadowMap::create(const ObjectVec & scene, const gml::mat4x4_t &worldview , const gml::vec3_t & position, const gml::vec3_t & target , const gml::vec3_t & up) { if ( !m_isReady ) { #if !defined(NDEBUG) fprintf(stderr, "Trying to create shadow map when cubemap not ready\n"); #endif return; } glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo); glViewport(0, 0, m_shadowMapSize, m_shadowMapSize); glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); glEnable(GL_DEPTH_TEST); if (isGLError()) return; if (LT_POINT == m_type) { gml::vec3_t _light_pos = gml::extract3(gml::mul(worldview, gml::vec4_t(position, 1.0))); for (unsigned short i = 0; i < 6; ++i) m_cameras[i]->setPosition(_light_pos); } else if (LT_DIRECTIONAL == m_type) { gml::vec3_t _light_pos = gml::extract3(gml::mul(worldview, gml::vec4_t(position, 1.0))); gml::vec3_t _light_target = gml::extract3(gml::mul(worldview, gml::vec4_t(target, 1.0))); gml::vec3_t _light_up = gml::extract3(gml::mul(worldview, gml::vec4_t(up, 1.0))); m_cameras[0]->lookAt(_light_pos, _light_target, _light_up); } const Shader::Shader* _pdptshdr = m_manager->getDepthShader(); if (LT_POINT == m_type) { for (unsigned short i = 0; i < 6; ++i) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, m_shadowmap, 0); if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER)) return; glClear(GL_DEPTH_BUFFER_BIT); if (isGLError()) return; if (_pdptshdr->getIsReady()) { _pdptshdr->bindGL(); if (isGLError()) return; Shader::GLProgUniforms shaderUniforms; shaderUniforms.m_projection = m_cameras[i]->getProjection(); for (ObjectVec::const_iterator itr = scene.begin(); itr != scene.end(); ++itr) { shaderUniforms.m_modelView = gml::mul(m_cameras[i]->getWorldView(), gml::mul(worldview, (*itr)->getObjectToWorld())); shaderUniforms.m_normalTrans = gml::transpose( gml::inverse(shaderUniforms.m_modelView) ); if ( !_pdptshdr->setUniforms(shaderUniforms, false) || isGLError() ) return; (*itr)->rasterize(); if (isGLError()) return; } _pdptshdr->unbindGL(); glFinish(); } } } else if (LT_DIRECTIONAL == m_type) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_shadowmap, 0); if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER)) return; glClear(GL_DEPTH_BUFFER_BIT); if (isGLError()) return; if (_pdptshdr->getIsReady()) { _pdptshdr->bindGL(); if (isGLError()) return; Shader::GLProgUniforms shaderUniforms; shaderUniforms.m_projection = m_cameras[0]->getProjection(); for (ObjectVec::const_iterator itr = scene.begin(); itr != scene.end(); ++itr) { shaderUniforms.m_modelView = gml::mul(m_cameras[0]->getWorldView(), gml::mul(worldview, (*itr)->getObjectToWorld())); shaderUniforms.m_normalTrans = gml::transpose( gml::inverse(shaderUniforms.m_modelView) ); if ( !_pdptshdr->setUniforms(shaderUniforms, false) || isGLError() ) return; (*itr)->rasterize(); if (isGLError()) return; } _pdptshdr->unbindGL(); glFinish(); } } glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); }
void InitGLES(void) { GLint linked; GLuint vertexShader; GLuint fragmentShader; assert((vertexShader = LoadShader("vert.glsl", GL_VERTEX_SHADER)) != 0); assert((fragmentShader = LoadShader("frag.glsl", GL_FRAGMENT_SHADER)) != 0); assert((program = glCreateProgram()) != 0); glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &linked); if (!linked) { GLint infoLen = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { char *infoLog = malloc(infoLen); glGetProgramInfoLog(program, infoLen, NULL, infoLog); fprintf(stderr, "Error linking program:\n%s\n", infoLog); free(infoLog); } glDeleteProgram(program); exit(1); } //* GLuint fbid; glGenFramebuffers(1, &fbid); glBindFramebuffer(GL_FRAMEBUFFER, fbid); GLuint texid; glGenTextures(1, &texid); glBindTexture(GL_TEXTURE_2D, texid); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifdef _OGLES_30_ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, TARGET_SIZE, TARGET_SIZE, 0, GL_RGBA, GL_FLOAT, NULL); #endif #ifdef _OGLES_20_ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TARGET_SIZE, TARGET_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); #endif 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_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texid, 0); GLuint rbid; glGenRenderbuffers(1, &rbid); glBindRenderbuffer(GL_RENDERBUFFER, rbid); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, TARGET_SIZE, TARGET_SIZE); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbid); CheckFrameBufferStatus(); //*/ glClearColor(0, 0, 0, 0); glViewport(0, 0, TARGET_SIZE, TARGET_SIZE); glEnable(GL_DEPTH_TEST); glUseProgram(program); }
void ContextSwitchRenderer::drawWorkload() { SCOPED_TRACE(); if (mWorkload > 8) { return; // This test does not support higher workloads. } // Set the background clear color to black. glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // No culling of back faces glDisable(GL_CULL_FACE); // No depth testing glDisable(GL_DEPTH_TEST); EGLSyncKHR fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL); const int TOTAL_NUM_CONTEXTS = NUM_WORKER_CONTEXTS + 1; const float TRANSLATION = 0.9f - (TOTAL_NUM_CONTEXTS * 0.2f); for (int i = 0; i < TOTAL_NUM_CONTEXTS; i++) { eglWaitSyncKHR(mEglDisplay, fence, 0); eglDestroySyncKHR(mEglDisplay, fence); glUseProgram(mProgramId); // Set the texture. glActiveTexture (GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTextureId); glUniform1i(mTextureUniformHandle, 0); // Set the x translate. glUniform1f(mTranslateUniformHandle, (i * 0.2f) + TRANSLATION); glEnableVertexAttribArray(mPositionHandle); glEnableVertexAttribArray(mTexCoordHandle); glVertexAttribPointer(mPositionHandle, 3, GL_FLOAT, false, 0, CS_VERTICES); glVertexAttribPointer(mTexCoordHandle, 2, GL_FLOAT, false, 0, CS_TEX_COORDS); glDrawArrays(GL_TRIANGLES, 0, CS_NUM_VERTICES); fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL); // Switch to next context. if (i < (mWorkload - 1)) { eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mContexts[i]); // Switch to FBO and re-attach. if (mOffscreen) { glBindFramebuffer(GL_FRAMEBUFFER, mFboIds[i]); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mFboDepthId); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFboTexId, 0); glViewport(0, 0, mFboWidth, mFboHeight); } } GLuint err = glGetError(); if (err != GL_NO_ERROR) { ALOGE("GLError %d in drawWorkload", err); break; } } eglWaitSyncKHR(mEglDisplay, fence, 0); eglDestroySyncKHR(mEglDisplay, fence); // Switch back to the main context. eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); if (mOffscreen) { glBindFramebuffer(GL_FRAMEBUFFER, mFboId); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mFboDepthId); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFboTexId, 0); glViewport(0, 0, mFboWidth, mFboHeight); } }