void Canvas::text_transparent(PixelScalar x, PixelScalar y, const TCHAR *text) { assert(text != NULL); assert(ValidateUTF8(text)); #ifdef HAVE_GLES assert(x_offset == OpenGL::translate_x); assert(y_offset == OpenGL::translate_y); #endif if (font == NULL) return; GLTexture *texture = TextCache::Get(font, text); if (texture == NULL) return; GLEnable scope(GL_TEXTURE_2D); texture->Bind(); GLLogicOp logic_op(GL_AND_INVERTED); /* cut out the shape in black */ OpenGL::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); texture->Draw(x, y); if (text_color != COLOR_BLACK) { /* draw the text color on top */ OpenGL::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); logic_op.set(GL_OR); text_color.Set(); texture->Draw(x, y); } }
void Canvas::DrawText(int x, int y, const TCHAR *text) { assert(text != nullptr); assert(ValidateUTF8(text)); #ifdef HAVE_GLES assert(offset == OpenGL::translate); #endif if (font == nullptr) return; GLTexture *texture = TextCache::Get(*font, text); if (texture == nullptr) return; if (background_mode == OPAQUE) DrawFilledRectangle(x, y, x + texture->GetWidth(), y + texture->GetHeight(), background_color); PrepareColoredAlphaTexture(text_color); #ifndef USE_GLSL GLEnable scope(GL_TEXTURE_2D); #endif const GLBlend blend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); texture->Bind(); texture->Draw(x, y); }
bool GLVideo::BeginTargetScene(const Color& dwBGColor, const bool clear) { // explicit static cast for better performance TexturePtr texturePtr = m_currentTarget.lock(); if (!texturePtr) { Message(GS_L("There's no render target"), GSMT_ERROR); } Texture *pTexture = texturePtr.get(); // safety compile-time error checking GLTexture *pGLTexture = static_cast<GLTexture*>(pTexture); // safer direct cast const GLuint target = pGLTexture->GetTextureInfo().m_frameBuffer; glBindFramebuffer(GL_FRAMEBUFFER, target); CheckFrameBufferStatus(target, pGLTexture->GetTextureInfo().m_texture, false); if (clear) { math::Vector4 color; color.SetColor(dwBGColor); glClearColor(color.x, color.y, color.z, color.w); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } UpdateInternalShadersViewData(GetScreenSizeF(), true); m_rendering = true; return true; }
void GLBackend::setResourceTexture(unsigned int slot, const TexturePointer& resourceTexture) { // check cache before thinking if (_resource._textures[slot] == resourceTexture) { return; } // One more True texture bound _stats._RSNumTextureBounded++; // Always make sure the GLObject is in sync GLTexture* object = syncGPUObject(resourceTexture); if (object) { GLuint to = object->_texture; GLuint target = object->_target; glActiveTexture(GL_TEXTURE0 + slot); glBindTexture(target, to); (void)CHECK_GL_ERROR(); _resource._textures[slot] = resourceTexture; _stats._RSAmountTextureMemoryBounded += (int)object->size(); } else { releaseResourceTexture(slot); return; } }
void Canvas::DrawTransparentText(int x, int y, const TCHAR *text) { assert(text != nullptr); assert(ValidateUTF8(text)); #ifdef HAVE_GLES assert(offset == OpenGL::translate); #endif if (font == nullptr) return; GLTexture *texture = TextCache::Get(*font, text); if (texture == nullptr) return; PrepareColoredAlphaTexture(text_color); #ifndef USE_GLSL GLEnable scope(GL_TEXTURE_2D); #endif const GLBlend blend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); texture->Bind(); texture->Draw(x, y); }
BitmapPtr BmpTextureMover::moveTextureToBmp(GLTexture& tex, int mipmapLevel) { GLContext* pContext = GLContext::getCurrent(); unsigned fbo = pContext->genFBO(); glproc::BindFramebuffer(GL_FRAMEBUFFER, fbo); glproc::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.getID(), mipmapLevel); FBO::checkError("BmpTextureMover::moveTextureToBmp"); IntPoint size = tex.getMipmapSize(mipmapLevel); BitmapPtr pBmp(new Bitmap(size, getPF())); if (GLContext::getMain()->isGLES() && getPF() == B5G6R5) { BitmapPtr pTmpBmp(new Bitmap(size, R8G8B8)); glReadPixels(0, 0, size.x, size.y, GL_RGB, GL_UNSIGNED_BYTE, pTmpBmp->getPixels()); FilterFlipRGB().applyInPlace(pTmpBmp); pBmp->copyPixels(*pTmpBmp); } else { int glPixelFormat = tex.getGLFormat(getPF()); glReadPixels(0, 0, size.x, size.y, glPixelFormat, tex.getGLType(getPF()), pBmp->getPixels()); } GLContext::checkError("BmpTextureMover::moveTextureToBmp: glReadPixels()"); glproc::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); pContext->returnFBOToCache(fbo); glproc::BindFramebuffer(GL_FRAMEBUFFER, 0); return pBmp; }
void Canvas::Stretch(PixelScalar dest_x, PixelScalar dest_y, UPixelScalar dest_width, UPixelScalar dest_height, const GLTexture &texture) { Stretch(dest_x, dest_y, dest_width, dest_height, texture, 0, 0, texture.GetWidth(), texture.GetHeight()); }
GLTexture* TexturesMap::TextureConstructor::construct (const TextureKey& key) { GLTexture* texture = new GLTexture(key.first, key.second); if (m_cache->realised()) { texture->realise(); } return texture; }
void Canvas::Stretch(int dest_x, int dest_y, unsigned dest_width, unsigned dest_height, const GLTexture &texture) { Stretch(dest_x, dest_y, dest_width, dest_height, texture, 0, 0, texture.GetWidth(), texture.GetHeight()); }
// Read framebuffer to 'pixelsOut' via glCopyTexSubImage3D. void TestCopyTexSubImage3D(int x, int y, int z, PixelRect *pixelsOut) { // Init texture with given pixels. GLTexture destTexture; pixelsOut->toTexture3D(destTexture.get(), kTextureDepth); // Read framebuffer -> texture -> 'pixelsOut' glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, z, x, y, kReadWidth, kReadHeight); readTexture3D(destTexture, kReadWidth, kReadHeight, z, pixelsOut); }
// Read framebuffer to 'pixelsOut' via glCopyTexImage2D and GL_TEXTURE_2D. void TestCopyTexImage2D(int x, int y, int, PixelRect *pixelsOut) { // Init texture with given pixels. GLTexture destTexture; pixelsOut->toTexture2D(GL_TEXTURE_2D, destTexture.get()); // Read framebuffer -> texture -> 'pixelsOut' glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, kReadWidth, kReadHeight, 0); readTexture2D(GL_TEXTURE_2D, destTexture.get(), kReadWidth, kReadHeight, pixelsOut); }
void UniformVar::_lua_getter_samplers(const gb::utils::luatable_mapper & mapper, const char * name) { std::vector<string> ret = mapper.get_strings_by_key(name); const std::size_t minCount = ret.size() > count ? count : ret.size(); for (std::size_t i = 0; i < minCount; i++) { GLTexture * tex = resource::Res<GLTexture>::Instance().Get(ret[i]); textureObjs[i] = { tex->GetTarget(), tex->GetTextureObj() }; } }
// Read framebuffer to 'pixelsOut' via glCopyTexSubImage2D and cube map. void TestCopyTexSubImageCube(int x, int y, int, PixelRect *pixelsOut) { // Init texture with given pixels. GLTexture destTexture; pixelsOut->toTexture2D(GL_TEXTURE_CUBE_MAP, destTexture.get()); // Read framebuffer -> texture -> 'pixelsOut' glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, x, y, kReadWidth, kReadHeight); readTexture2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, destTexture.get(), kReadWidth, kReadHeight, pixelsOut); }
void AtlasTexture::commit(Image const &image, Vector2i const &topLeft) const { GLTexture *tex = const_cast<AtlasTexture *>(this); if(size() == GLTexture::Size(0, 0)) { // Hasn't been full-committed yet. tex->setUndefinedImage(totalSize(), Image::RGBA_8888); } tex->setSubImage(image, topLeft); }
void AtlasTexture::commit(Image const &fullImage, Rectanglei const &subregion) const { GLTexture *tex = const_cast<AtlasTexture *>(this); if (size() == GLTexture::Size(0, 0)) { // Hasn't been full-committed yet. tex->setUndefinedImage(totalSize(), Image::RGBA_8888); } tex->setSubImage(fullImage, subregion); }
void GLFramebuffer::setWidthAndHeight(unsigned int width, unsigned int height) { mWidth = std::max(width, 1u); mHeight = std::max(height, 1u); if (not mFinished) { return; } glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); if (mDepthTexture != NULL) { GLTexture *glDepthTex = (GLTexture *)mDepthTexture; glBindTexture(GL_TEXTURE_2D, glDepthTex->mTexture); glDepthTex->allocData2D(mWidth, mHeight, mDepthFormat, Texture::Depth32F_Format, NULL); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, glDepthTex->mTexture, 0); } if (glIsRenderbuffer(mDepthRBO) and mDepthTexture == NULL) { glBindRenderbuffer(GL_RENDERBUFFER, mDepthRBO); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mWidth, mHeight); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRBO); } unsigned int i=0; GLenum drawBuffers[mColorTextures.size()]; for (std::vector<ColorTexture>::iterator it = mColorTextures.begin(); it != mColorTextures.end(); ++it) { GLTexture *glTexture = (GLTexture *)it->texture; glBindTexture(GL_TEXTURE_2D, glTexture->mTexture); glTexture->allocData2D(mWidth*it->scale.x, mHeight*it->scale.y, it->format, Texture::RGBU8_Format, NULL); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_2D, glTexture->mTexture, 0); drawBuffers[i] = GL_COLOR_ATTACHMENT0+i; ++i; } glDrawBuffers(mColorTextures.size(), drawBuffers); }
void GLBackend::do_generateTextureMips(const Batch& batch, size_t paramOffset) { TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); if (!resourceTexture) { return; } // DO not transfer the texture, this call is expected for rendering texture GLTexture* object = syncGPUObject(resourceTexture); if (!object) { return; } object->generateMips(); }
void GL::GLProgram::setUniform(const char* name, const GLTexture& tex, int iTextureSlot) { int loc = getUniformByName(name); //assert(loc > -1); tex.bind(iTextureSlot); glUniform1i(loc, iTextureSlot); }
void GLSLProgram::SetTexture(const string& name, const GLTexture& pTexture) { if (m_mBindings.find(name) == m_mBindings.end ()) { // find a free texture unit int iUnusedTexUnit = 0; for (texMap::iterator i = m_mBindings.begin();i != m_mBindings.end();++i){ if (i->second <= iUnusedTexUnit) iUnusedTexUnit = i->second+1; } ConnectTextureID(name, iUnusedTexUnit); pTexture.Bind(iUnusedTexUnit); } else { pTexture.Bind(m_mBindings[name]); } }
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels) { bool is_set = false; #ifdef _DEBUG return; #endif #if 1 // no mipmap if (level > 0) return; #endif if (!GLImpl.tmus[GLImpl.current_tmu].boundtexture) { printf("Not texture binded\n"); return; } GLImpl.device->SetTexture(0, NULL); GLTexture * surf = NULL; if (GLImpl.tmus[GLImpl.current_tmu].boundtexture && GLImpl.tmus[GLImpl.current_tmu].boundtexture->teximg ) { surf = GLImpl.tmus[GLImpl.current_tmu].boundtexture->teximg; } if (surf) { int srcbytes = src_format_to_bypp(format); int dstbytes = dst_format_to_bypp(GLImpl.tmus[GLImpl.current_tmu].boundtexture->internalformat); BYTE * surfbuf; BYTE * srcdata = (BYTE*) pixels; BYTE * dstdata; surf->lockTexture(level); srcdata = (BYTE*) pixels; surfbuf = (BYTE*)surf->getData(); dstdata = (BYTE*)surf->getData(); check_format(srcbytes, dstbytes); copyImage(xoffset, yoffset, width, height, srcdata, srcbytes, surfbuf, dstbytes); surf->unlockTexture(level); GLImpl.tmus[GLImpl.current_tmu].boundtexture->dirty = 1; } }
void GLFramebuffer::setDepthbufferTexture(GLTexture& a_texture) { assert(m_initialized); assert(uint(m_multiSampleType) == uint(a_texture.getMultiSampleType())); m_depthTexture = a_texture.getTextureID(); CHECK_GL_ERROR() glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, a_texture.getTextureID(), 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); assert(status == GL_FRAMEBUFFER_COMPLETE); glBindFramebuffer(GL_FRAMEBUFFER, 0); CHECK_GL_ERROR(); }
bool RayTracer::init_gl() { glGenTextures(1, &texture.value()); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glEnable(GL_TEXTURE_2D); glColor3f(1, 1, 1); return true; }
void Surface::initTexture(const AttributeSet& attributes, GLTexture& texture, int line, int column, ErrorManager* errorManager) { for(unsigned int i=0; i< attributes.size(); i++) { if (attributes[i].attribute == "file") texture.setTexName(attributes[i].value); else if(attributes[i].attribute == "mode") { if(attributes[i].value == "GL_MODULATE") texture.setMode(GL_MODULATE); else if(attributes[i].value == "GL_REPLACE") texture.setMode(GL_REPLACE); else if(attributes[i].value == "GL_ADD") texture.setMode(GL_ADD); else if(attributes[i].value == "GL_DECAL") texture.setMode(GL_DECAL); } else if (attributes[i].attribute == "wrapS") { GLenum mode = (GLenum)ParserUtilities::toTextureWrapMode(attributes[i].value); if(mode == GL_NONE) errorManager->addError("Unknown Texture Mode", "Unknown Texture Mode \"" + attributes[i].value + "\". Try( GL_CLAMP | GL_CLAMP_TO_EDGE | GL_CLAMP_TO_BORDER | GL_MIRRORED_REPEAT | GL_REPEAT)", line, column); else texture.setWrapS(mode); } else if (attributes[i].attribute == "wrapT") { GLenum mode = (GLenum)ParserUtilities::toTextureWrapMode(attributes[i].value); if(mode == GL_NONE) errorManager->addError("Unknown Texture Mode", "Unknown Texture Mode \"" + attributes[i].value + "\". Try( GL_CLAMP | GL_CLAMP_TO_EDGE | GL_CLAMP_TO_BORDER | GL_MIRRORED_REPEAT | GL_REPEAT)", line, column); else texture.setWrapT(mode); } else if (attributes[i].attribute == "wrapR") { GLenum mode = (GLenum)ParserUtilities::toTextureWrapMode(attributes[i].value); if(mode == GL_NONE) errorManager->addError("Unknown Texture Mode", "Unknown Texture Mode \"" + attributes[i].value + "\". Try( GL_CLAMP | GL_CLAMP_TO_EDGE | GL_CLAMP_TO_BORDER | GL_MIRRORED_REPEAT | GL_REPEAT)", line, column); else texture.setWrapR(mode); } else if (attributes[i].attribute == "priority") diffuseTexture.setPriority((GLclampf)ParserUtilities::toDouble(attributes[i].value)); else { errorManager->addError("Unknown Texture Parameter", "The provided texture parameter \"" + name + "\" is unknown", line, column); } } }
GLFrameBuffer::GLFrameBuffer(const GLTexture & texture, const GLRenderBuffer & depthBuffer) : mFrameBufferId((GLuint)-1) { GCLAssert(texture.IsValid()); RenderPipe::SendCommand([&](){ glGenFramebuffers(1, &mFrameBufferId); glErrorCheck(); glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferId); glErrorCheck(); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.GetTextureIdUnsafe(), 0); glErrorCheck(); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer.GetRenderBufferId());glErrorCheck(); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); checkFrameBufferStatus(status); glBindFramebuffer(GL_FRAMEBUFFER, 0);glErrorCheck(); }); }
int main(int argc, char** argv) { glutInit(&argc, argv); cameraX = 0; cameraY = 30; cameraZ = 150; eyeX = 0; eyeY = 0; eyeZ = 0; lastLevel = 0; cameraAcceleration = 0.1; timerTime = 2 * 1000; lastLevel += ((rand() % 10) + 40); jump = false; characterSpeed = 0.8; jumpTime = clock(); jumpBeginY = clock(); /* int x = ((rand() % 10) + 45); int direction = ((rand() % 10) - 15);*/ int x = ((rand() % 10) + 705); int direction = 0; character.x = direction; character.y = lastLevel + 5; Level level1 = *new Level(x, lastLevel, direction); level1.levelBefore = new Level(-1000021, -111, 0); Levels.push_back(level1); character.setLevel(level1); glutInitWindowSize(800, 1000); glutInitWindowPosition(50, 50); glutCreateWindow("Icy Tower"); glutDisplayFunc(Display); glutIdleFunc(Anim); glutKeyboardFunc(key); glutMouseFunc(Mouse); glutTimerFunc(0, Timer, 0); glutTimerFunc(0, Timer2, 0); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glClearColor(1.0f, 1.0f, 1.0f, 0.0f); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glEnable(GL_NORMALIZE); glEnable(GL_COLOR_MATERIAL); glShadeModel(GL_SMOOTH); character.c.Load("Models/character.3ds"); banana.Load("Models/banana.3ds"); level.Load("Textures/brick3.bmp"); skyFront.Load("Textures/brick.bmp"); skyBack.Load("Textures/brick.bmp"); skyLeft.Load("Textures/brick2.bmp"); skyRight.Load("Textures/brick2.bmp"); skyUp.Load("Textures/brick.bmp"); skyDown.Load("Textures/grass2.bmp"); glutMainLoop(); }
void Canvas::text_clipped(int x, int y, unsigned width, const TCHAR *text) { #ifdef HAVE_GLES assert(x_offset == OpenGL::translate_x); assert(y_offset == OpenGL::translate_y); #endif if (font == NULL) return; GLTexture *texture = TextCache::get(font, COLOR_BLACK, COLOR_WHITE, text); if (texture == NULL) return; GLEnable scope(GL_TEXTURE_2D); texture->bind(); GLLogicOp logic_op(GL_AND_INVERTED); unsigned height = texture->get_height(); if (texture->get_width() < width) width = texture->get_width(); /* cut out the shape in black */ OpenGL::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); texture->draw(x, y, width, height, 0, 0, width, height); if (text_color != COLOR_BLACK) { /* draw the text color on top */ OpenGL::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); logic_op.set(GL_OR); text_color.set(); texture->draw(x, y, width, height, 0, 0, width, height); } }
void Canvas::DrawClippedText(int x, int y, unsigned width, unsigned height, const TCHAR *text) { assert(text != nullptr); assert(ValidateUTF8(text)); #ifdef HAVE_GLES assert(offset == OpenGL::translate); #endif if (font == nullptr) return; GLTexture *texture = TextCache::Get(*font, text); if (texture == nullptr) return; if (texture->GetHeight() < height) height = texture->GetHeight(); if (texture->GetWidth() < width) width = texture->GetWidth(); PrepareColoredAlphaTexture(text_color); #ifndef USE_GLSL GLEnable scope(GL_TEXTURE_2D); #endif const GLBlend blend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); texture->Bind(); texture->Draw(x, y, width, height, 0, 0, width, height); }
void drawLevel() { level.Use(); glPushMatrix(); glTranslated(this->direction, this->y, 0); glScaled(this->x, 3, 3); drawBox(1, GL_QUADS); glPopMatrix(); }
/* MCAThingSelection::draw * Draws the animation *******************************************************************/ void MCAThingSelection::draw() { // Setup colour rgba_t col; if (select) col.set(255, 255, 255, 255*fade, 1); else { col = ColourConfiguration::getColour("map_selection"); col.a *= fade; } OpenGL::setColour(col); // Get texture if needed if (!thing_overlay_square) { // Get thing selection texture GLTexture* tex = NULL; if (thing_drawtype == TDT_ROUND || thing_drawtype == TDT_SPRITE) tex = MapEditor::textureManager().getEditorImage("thing/hilight"); else tex = MapEditor::textureManager().getEditorImage("thing/square/hilight"); if (!tex) return; // Bind the texture glEnable(GL_TEXTURE_2D); tex->bind(); } // Animate radius double r = radius; if (select) r += radius*0.2*fade; // Draw glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2d(x - r, y - r); glTexCoord2f(0.0f, 1.0f); glVertex2d(x - r, y + r); glTexCoord2f(1.0f, 1.0f); glVertex2d(x + r, y + r); glTexCoord2f(1.0f, 0.0f); glVertex2d(x + r, y - r); glEnd(); }
void GLFramebuffer::addFramebufferTexture(GLTexture& a_texture, EAttachment a_attachment) { assert(m_initialized); assert(uint(m_multiSampleType) == uint(a_texture.getMultiSampleType())); m_textures.push_back(a_texture.getTextureID()); m_drawBuffers.push_back(a_attachment); CHECK_GL_ERROR(); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glFramebufferTexture(GL_FRAMEBUFFER, GLenum(a_attachment), a_texture.getTextureID(), 0); glDrawBuffers(uint(m_drawBuffers.size()), rcast<GLenum*>(&m_drawBuffers[0])); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); assert(status == GL_FRAMEBUFFER_COMPLETE); glBindFramebuffer(GL_FRAMEBUFFER, 0); CHECK_GL_ERROR(); }