bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelFormat eFormat, GLuint uDepthStencilFormat) { CCAssert(eFormat != kCCTexture2DPixelFormat_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, &m_nOldFBO); // textures must be power of two squared unsigned int powW = 0; unsigned int powH = 0; if (CCConfiguration::sharedConfiguration()->supportsNPOT()) { powW = w; powH = h; } else { powW = ccNextPOT(w); powH = ccNextPOT(h); } data = malloc((int)(powW * powH * 4)); CC_BREAK_IF(! data); memset(data, 0, (int)(powW * powH * 4)); m_ePixelFormat = eFormat; m_pTexture = new CCTexture2D(); if (m_pTexture) { m_pTexture->initWithData(data, (CCTexture2DPixelFormat)m_ePixelFormat, powW, powH, CCSizeMake((float)w, (float)h)); } else { break; } GLint oldRBO; glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldRBO); if (CCConfiguration::sharedConfiguration()->checkForGLExtension("GL_QCOM")) { m_pTextureCopy = new CCTexture2D(); if (m_pTextureCopy) { m_pTextureCopy->initWithData(data, (CCTexture2DPixelFormat)m_ePixelFormat, powW, powH, CCSizeMake((float)w, (float)h)); } else { break; } } // generate FBO glGenFramebuffers(1, &m_uFBO); glBindFramebuffer(GL_FRAMEBUFFER, m_uFBO); // associate texture with FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->getName(), 0); if (uDepthStencilFormat != 0) { //create and attach depth buffer glGenRenderbuffers(1, &m_uDepthRenderBufffer); glBindRenderbuffer(GL_RENDERBUFFER, m_uDepthRenderBufffer); glRenderbufferStorage(GL_RENDERBUFFER, uDepthStencilFormat, (GLsizei)powW, (GLsizei)powH); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uDepthRenderBufffer); // 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, m_uDepthRenderBufffer); } } // check if it worked (probably worth doing :) ) CCAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer"); m_pTexture->setAliasTexParameters(); // retained setSprite(CCSprite::createWithTexture(m_pTexture)); m_pTexture->release(); m_pSprite->setScaleY(-1); ccBlendFunc tBlendFunc = {GL_ONE, GL_ONE_MINUS_SRC_ALPHA }; m_pSprite->setBlendFunc(tBlendFunc); glBindRenderbuffer(GL_RENDERBUFFER, oldRBO); glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO); // Diabled by default. m_bAutoDraw = false; // add sprite for backward compatibility addChild(m_pSprite); bRet = true; } while (0); CC_SAFE_FREE(data); return bRet; }
// The MAIN function, from here we start our application and run our Game loop int main() { // Init GLFW glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed glfwMakeContextCurrent(window); // Set the required callback functions glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); // Options glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // Initialize GLEW to setup the OpenGL Function pointers glewExperimental = GL_TRUE; glewInit(); // Define the viewport dimensions glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); // Setup some OpenGL options glEnable(GL_DEPTH_TEST); // Setup and compile our shaders Shader shaderGeometryPass("g_buffer.vs", "g_buffer.frag"); Shader shaderLightingPass("deferred_shading.vs", "deferred_shading.frag"); Shader shaderLightBox("deferred_light_box.vs", "deferred_light_box.frag"); // Set samplers shaderLightingPass.Use(); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gPosition"), 0); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gNormal"), 1); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gAlbedoSpec"), 2); // Models Model cyborg(FileSystem::getPath("resources/objects/nanosuit/nanosuit.obj").c_str()); std::vector<glm::vec3> objectPositions; objectPositions.push_back(glm::vec3(-3.0, -3.0, -3.0)); objectPositions.push_back(glm::vec3(0.0, -3.0, -3.0)); objectPositions.push_back(glm::vec3(3.0, -3.0, -3.0)); objectPositions.push_back(glm::vec3(-3.0, -3.0, 0.0)); objectPositions.push_back(glm::vec3(0.0, -3.0, 0.0)); objectPositions.push_back(glm::vec3(3.0, -3.0, 0.0)); objectPositions.push_back(glm::vec3(-3.0, -3.0, 3.0)); objectPositions.push_back(glm::vec3(0.0, -3.0, 3.0)); objectPositions.push_back(glm::vec3(3.0, -3.0, 3.0)); // - Colors const GLuint NR_LIGHTS = 32; std::vector<glm::vec3> lightPositions; std::vector<glm::vec3> lightColors; srand(13); for (GLuint i = 0; i < NR_LIGHTS; i++) { // Calculate slightly random offsets GLfloat xPos = ((rand() % 100) / 100.0) * 6.0 - 3.0; GLfloat yPos = ((rand() % 100) / 100.0) * 6.0 - 4.0; GLfloat zPos = ((rand() % 100) / 100.0) * 6.0 - 3.0; lightPositions.push_back(glm::vec3(xPos, yPos, zPos)); // Also calculate random color GLfloat rColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0 GLfloat gColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0 GLfloat bColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0 lightColors.push_back(glm::vec3(rColor, gColor, bColor)); } // Set up G-Buffer // 3 textures: // 1. Positions (RGB) // 2. Color (RGB) + Specular (A) // 3. Normals (RGB) GLuint gBuffer; glGenFramebuffers(1, &gBuffer); glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); GLuint gPosition, gNormal, gAlbedoSpec; // - Position color buffer glGenTextures(1, &gPosition); glBindTexture(GL_TEXTURE_2D, gPosition); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0); // - Normal color buffer glGenTextures(1, &gNormal); glBindTexture(GL_TEXTURE_2D, gNormal); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0); // - Color + Specular color buffer glGenTextures(1, &gAlbedoSpec); glBindTexture(GL_TEXTURE_2D, gAlbedoSpec); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gAlbedoSpec, 0); // - Tell OpenGL which color attachments we'll use (of this framebuffer) for rendering GLuint attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; glDrawBuffers(3, attachments); // - Create and attach depth buffer (renderbuffer) GLuint rboDepth; glGenRenderbuffers(1, &rboDepth); glBindRenderbuffer(GL_RENDERBUFFER, rboDepth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth); // - Finally check if framebuffer is complete if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "Framebuffer not complete!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Game loop while (!glfwWindowShouldClose(window)) { // Set frame time GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // Check and call events glfwPollEvents(); Do_Movement(); glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL); // 1. Geometry Pass: render scene's geometry/color data into gbuffer glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)SCR_WIDTH / (GLfloat)SCR_HEIGHT, 0.1f, 100.0f); glm::mat4 view = camera.GetViewMatrix(); glm::mat4 model; shaderGeometryPass.Use(); glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); for (GLuint i = 0; i < objectPositions.size(); i++) { model = glm::mat4(); model = glm::translate(model, objectPositions[i]); model = glm::scale(model, glm::vec3(0.25f)); glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); cyborg.Draw(shaderGeometryPass); } glBindFramebuffer(GL_FRAMEBUFFER, 0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // 2. Lighting Pass: calculate lighting by iterating over a screen filled quad pixel-by-pixel using the gbuffer's content. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shaderLightingPass.Use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gPosition); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, gNormal); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, gAlbedoSpec); // Also send light relevant uniforms for (GLuint i = 0; i < lightPositions.size(); i++) { glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, ("lights[" + std::to_string(i) + "].Position").c_str()), 1, &lightPositions[i][0]); glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, ("lights[" + std::to_string(i) + "].Color").c_str()), 1, &lightColors[i][0]); // Update attenuation parameters and calculate radius const GLfloat constant = 1.0; // Note that we don't send this to the shader, we assume it is always 1.0 (in our case) const GLfloat linear = 0.7; const GLfloat quadratic = 1.8; glUniform1f(glGetUniformLocation(shaderLightingPass.Program, ("lights[" + std::to_string(i) + "].Linear").c_str()), linear); glUniform1f(glGetUniformLocation(shaderLightingPass.Program, ("lights[" + std::to_string(i) + "].Quadratic").c_str()), quadratic); // Then calculate radius of light volume/sphere const GLfloat lightThreshold = 5.0; // 5 / 256 const GLfloat maxBrightness = std::fmaxf(std::fmaxf(lightColors[i].r, lightColors[i].g), lightColors[i].b); GLfloat radius = (-linear + static_cast<float>(std::sqrt(linear * linear - 4 * quadratic * (constant - (256.0 / lightThreshold) * maxBrightness)))) / (2 * quadratic); glUniform1f(glGetUniformLocation(shaderLightingPass.Program, ("lights[" + std::to_string(i) + "].Radius").c_str()), radius); } glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, "viewPos"), 1, &camera.Position[0]); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "draw_mode"), draw_mode); RenderQuad(); // 2.5. Copy content of geometry's depth buffer to default framebuffer's depth buffer glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Write to default framebuffer // blit to default framebuffer. Note that this may or may not work as the internal formats of both the FBO and default framebuffer have to match. // the internal formats are implementation defined. This works on all of my systems, but if it doesn't on yours you'll likely have to write to the // depth buffer in another stage (or somehow see to match the default framebuffer's internal format with the FBO's internal format). glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, 0); // 3. Render lights on top of scene, by blitting shaderLightBox.Use(); glUniformMatrix4fv(glGetUniformLocation(shaderLightBox.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(shaderLightBox.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); for (GLuint i = 0; i < lightPositions.size(); i++) { model = glm::mat4(); model = glm::translate(model, lightPositions[i]); model = glm::scale(model, glm::vec3(0.25f)); glUniformMatrix4fv(glGetUniformLocation(shaderLightBox.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glUniform3fv(glGetUniformLocation(shaderLightBox.Program, "lightColor"), 1, &lightColors[i][0]); RenderCube(); } // Swap the buffers glfwSwapBuffers(window); } glfwTerminate(); return 0; }
void NGLDraw::createFrameBuffer() { // create a framebuffer object this is deleted in the dtor int w=720; int h=576; glGenFramebuffers(1, &m_gbuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_gbuffer); // create a renderbuffer object to store depth info GLuint m_rboID; glGenRenderbuffers(1, &m_rboID); glBindRenderbuffer(GL_RENDERBUFFER, m_rboID); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h); // create a texture object glGenTextures(1, &m_pointTexID); // bind it to make it active glBindTexture(GL_TEXTURE_2D, m_pointTexID); // set params glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); // create a texture object glGenTextures(1, &m_normalTexID); // bind it to make it active glBindTexture(GL_TEXTURE_2D, m_normalTexID); // set params glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glGenTextures(1, &m_colourTexID); // bind it to make it active glBindTexture(GL_TEXTURE_2D, m_colourTexID); // set params glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glGenTextures(1, &m_shadingTexID); // bind it to make it active glBindTexture(GL_TEXTURE_2D, m_shadingTexID); // set params glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); // The depth buffer // glGenTextures(1, &m_depthTex); // glBindTexture(GL_TEXTURE_2D, m_depthTex); // glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, w, h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // attatch the texture we created earlier to the FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pointTexID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_NV , GL_TEXTURE_2D, m_normalTexID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, m_colourTexID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, m_shadingTexID, 0); // glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthTex, 0); // now attach a renderbuffer to depth attachment point glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rboID); // GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0,GL_COLOR_ATTACHMENT1,GL_COLOR_ATTACHMENT2}; // glDrawBuffers (3, drawBuffers); // now we are going to create a buffer for the lighting pass // create a framebuffer object this is deleted in the dtor glGenFramebuffers(1, &m_lightBuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_lightBuffer); // create a renderbuffer object to store depth info glGenRenderbuffers(1, &m_rboID); glBindRenderbuffer(GL_RENDERBUFFER, m_rboID); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h); glGenTextures(1, &m_lightPassTexID); // bind it to make it active glBindTexture(GL_TEXTURE_2D, m_lightPassTexID); // set params glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_lightPassTexID, 0); // GLuint lightBuffers[] = { GL_COLOR_ATTACHMENT0}; // glDrawBuffers (1, lightBuffers); // now got back to the default render context glBindFramebuffer(GL_FRAMEBUFFER, 0); }
bool CARenderImage::initWithWidthAndHeight(int w, int h, CAImage::PixelFormat eFormat, GLuint uDepthStencilFormat) { CCAssert(eFormat != CAImage::PixelFormat_A8, "only RGB and RGBA formats are valid for a render texture"); bool bRet = false; unsigned char *data = NULL; do { glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO); // textures must be power of two squared unsigned int powW = 0; unsigned int powH = 0; { powW = (unsigned int)w; powH = (unsigned int)h; } data = (unsigned char *)malloc((int)(powW * powH * 4)); CC_BREAK_IF(! data); memset(data, 0, (int)(powW * powH * 4)); m_ePixelFormat = eFormat; m_uPixelsWide = powW; m_uPixelsHigh = powH; glPixelStorei(GL_UNPACK_ALIGNMENT, 8); glGenTextures(1, &m_uName); ccGLBindTexture2D(m_uName); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_uPixelsWide, m_uPixelsHigh, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); GLint oldRBO; glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldRBO); // generate FBO glGenFramebuffers(1, &m_uFBO); glBindFramebuffer(GL_FRAMEBUFFER, m_uFBO); // associate Image with FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_uName, 0); if (uDepthStencilFormat != 0) { //create and attach depth buffer glGenRenderbuffers(1, &m_uDepthRenderBufffer); glBindRenderbuffer(GL_RENDERBUFFER, m_uDepthRenderBufffer); glRenderbufferStorage(GL_RENDERBUFFER, uDepthStencilFormat, (GLsizei)powW, (GLsizei)powH); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uDepthRenderBufffer); // 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, m_uDepthRenderBufffer); } } // // check if it worked (probably worth doing :) ) CCAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Could not attach Image to framebuffer"); ccGLBindTexture2D( m_uName ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); CAImageView* imageView = CAImageView::createWithFrame(CCRect(0, 0, m_uPixelsWide, m_uPixelsHigh)); ccBlendFunc tBlendFunc = {GL_ONE, GL_ONE_MINUS_SRC_ALPHA }; imageView->setBlendFunc(tBlendFunc); this->addSubview(imageView); this->setImageView(imageView); glBindRenderbuffer(GL_RENDERBUFFER, oldRBO); glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO); // Diabled by default. m_bAutoDraw = false; bRet = true; } while (0); CC_SAFE_FREE(data); return bRet; }
void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, QGLFramebufferObject::Attachment attachment, GLenum texture_target, GLenum internal_format, GLint samples) { QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); fbo_guard.setContext(ctx); bool ext_detected = (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject); if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx))) return; size = sz; target = texture_target; // texture dimensions QT_RESET_GLERROR(); // reset error state GLuint fbo = 0; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo); fbo_guard.setId(fbo); glDevice.setFBO(q, attachment); QT_CHECK_GLERROR(); // init texture if (samples == 0) { glGenTextures(1, &texture); glBindTexture(target, texture); glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); #ifndef QT_OPENGL_ES glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #else glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #endif glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, texture, 0); QT_CHECK_GLERROR(); valid = checkFramebufferStatus(); glBindTexture(target, 0); color_buffer = 0; } else { GLint maxSamples; glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples); samples = qBound(1, int(samples), int(maxSamples)); glGenRenderbuffers(1, &color_buffer); glBindRenderbuffer(GL_RENDERBUFFER_EXT, color_buffer); if (glRenderbufferStorageMultisampleEXT) { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, internal_format, size.width(), size.height()); } else { samples = 0; glRenderbufferStorage(GL_RENDERBUFFER_EXT, internal_format, size.width(), size.height()); } glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, color_buffer); QT_CHECK_GLERROR(); valid = checkFramebufferStatus(); if (valid) glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &samples); } if (attachment == QGLFramebufferObject::CombinedDepthStencil && (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) { // depth and stencil buffer needs another extension glGenRenderbuffers(1, &depth_stencil_buffer); Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer)); glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer); Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); else glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); GLint i = 0; glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_buffer); fbo_attachment = QGLFramebufferObject::CombinedDepthStencil; valid = checkFramebufferStatus(); if (!valid) glDeleteRenderbuffers(1, &depth_stencil_buffer); } else if (attachment == QGLFramebufferObject::Depth || attachment == QGLFramebufferObject::CombinedDepthStencil) { glGenRenderbuffers(1, &depth_stencil_buffer); Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer)); glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer); Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) { #ifdef QT_OPENGL_ES #define GL_DEPTH_COMPONENT16 0x81A5 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH_COMPONENT16, size.width(), size.height()); #else glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif } else { #ifdef QT_OPENGL_ES #define GL_DEPTH_COMPONENT16 0x81A5 glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height()); #else glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif } GLint i = 0; glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_buffer); fbo_attachment = QGLFramebufferObject::Depth; valid = checkFramebufferStatus(); if (!valid) glDeleteRenderbuffers(1, &depth_stencil_buffer); } else { fbo_attachment = QGLFramebufferObject::NoAttachment; } glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); if (!valid) { if (color_buffer) glDeleteRenderbuffers(1, &color_buffer); else glDeleteTextures(1, &texture); glDeleteFramebuffers(1, &fbo); fbo_guard.setId(0); } QT_CHECK_GLERROR(); format.setTextureTarget(target); format.setSamples(int(samples)); format.setAttachment(fbo_attachment); format.setInternalTextureFormat(internal_format); }
enum piglit_result piglit_display(void) { GLubyte *win_image, *fbo_image; GLuint fbo, rb; bool pass = true; win_image = (GLubyte *) malloc(piglit_width * piglit_height * 3); fbo_image = (GLubyte *) malloc(piglit_width * piglit_height * 3); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glGenRenderbuffers(1, &rb); glBindRenderbuffer(GL_RENDERBUFFER, rb); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, piglit_width, piglit_height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb); assert(glGetError() == 0); assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT); /* draw reference image in the window */ glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo); draw_test_image(); glReadPixels(0, 0, piglit_width, piglit_height, GL_RGB, GL_UNSIGNED_BYTE, win_image); /* draw test image in fbo */ glBindFramebuffer(GL_FRAMEBUFFER, fbo); glReadBuffer(GL_COLOR_ATTACHMENT0); draw_test_image(); glReadPixels(0, 0, piglit_width, piglit_height, GL_RGB, GL_UNSIGNED_BYTE, fbo_image); /* compare images */ if (memcmp(win_image, fbo_image, piglit_width * piglit_height * 3)) { #if 0 /* helpful debug code */ int i, k; for (i = k = 0; i < piglit_width * piglit_height * 3; i++) { if (win_image[i] != fbo_image[i] && k++ < 40) printf("%d: %d vs. %d\n", i, win_image[i], fbo_image[i]); } #endif printf("Image comparison failed!\n"); pass = false; } else if (!piglit_automatic) { printf("Image comparison passed.\n"); } glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo); #if 0 /* for debug/compare (alternate diplaying Window vs. FBO image) */ { int i; glWindowPos2i(0,0); for (i = 0; i < 10; i++) { GLubyte *image = (i & 1) ? fbo_image : win_image; printf("Showing %s image\n", (i & 1) ? "FBO" : "window"); glDrawPixels(piglit_width, piglit_height, GL_RGB, GL_UNSIGNED_BYTE, image); piglit_present_results(); sleep(1); } } #endif piglit_present_results(); glDeleteRenderbuffers(1, &rb); glDeleteFramebuffers(1, &fbo); free(win_image); free(fbo_image); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height) { GLenum status; unsigned i; bool depth = false; bool stencil = false; GLint max_fbo_size = 0; GLint max_renderbuffer_size = 0; struct retro_hw_render_callback *hwr = video_driver_get_hw_context(); /* We can only share texture objects through contexts. * FBOs are "abstract" objects and are not shared. */ context_bind_hw_render(true); RARCH_LOG("[GL]: Initializing HW render (%u x %u).\n", width, height); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_fbo_size); glGetIntegerv(RARCH_GL_MAX_RENDERBUFFER_SIZE, &max_renderbuffer_size); RARCH_LOG("[GL]: Max texture size: %d px, renderbuffer size: %d px.\n", max_fbo_size, max_renderbuffer_size); if (!gl_check_capability(GL_CAPS_FBO)) return false; RARCH_LOG("[GL]: Supports FBO (render-to-texture).\n"); glBindTexture(GL_TEXTURE_2D, 0); glGenFramebuffers(gl->textures, gl->hw_render_fbo); depth = hwr->depth; stencil = hwr->stencil; #ifdef HAVE_OPENGLES if (!gl_check_capability(GL_CAPS_PACKED_DEPTH_STENCIL)) return false; RARCH_LOG("[GL]: Supports Packed depth stencil.\n"); #endif if (depth) { glGenRenderbuffers(gl->textures, gl->hw_render_depth); gl->hw_render_depth_init = true; } for (i = 0; i < gl->textures; i++) { glBindFramebuffer(RARCH_GL_FRAMEBUFFER, gl->hw_render_fbo[i]); glFramebufferTexture2D(RARCH_GL_FRAMEBUFFER, RARCH_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->texture[i], 0); if (depth) { glBindRenderbuffer(RARCH_GL_RENDERBUFFER, gl->hw_render_depth[i]); glRenderbufferStorage(RARCH_GL_RENDERBUFFER, stencil ? RARCH_GL_DEPTH24_STENCIL8 : GL_DEPTH_COMPONENT16, width, height); glBindRenderbuffer(RARCH_GL_RENDERBUFFER, 0); if (stencil) { #if defined(HAVE_OPENGLES2) || defined(HAVE_OPENGLES1) || ((defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__)))) /* GLES2 is a bit weird, as always. * There's no GL_DEPTH_STENCIL_ATTACHMENT like in desktop GL. */ glFramebufferRenderbuffer(RARCH_GL_FRAMEBUFFER, RARCH_GL_DEPTH_ATTACHMENT, RARCH_GL_RENDERBUFFER, gl->hw_render_depth[i]); glFramebufferRenderbuffer(RARCH_GL_FRAMEBUFFER, RARCH_GL_STENCIL_ATTACHMENT, RARCH_GL_RENDERBUFFER, gl->hw_render_depth[i]); #else /* We use ARB FBO extensions, no need to check. */ glFramebufferRenderbuffer(RARCH_GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, RARCH_GL_RENDERBUFFER, gl->hw_render_depth[i]); #endif } else { glFramebufferRenderbuffer(RARCH_GL_FRAMEBUFFER, RARCH_GL_DEPTH_ATTACHMENT, RARCH_GL_RENDERBUFFER, gl->hw_render_depth[i]); } } status = glCheckFramebufferStatus(RARCH_GL_FRAMEBUFFER); if (status != RARCH_GL_FRAMEBUFFER_COMPLETE) { RARCH_ERR("[GL]: Failed to create HW render FBO #%u, error: 0x%u.\n", i, (unsigned)status); return false; } } gl_bind_backbuffer(); gl->hw_render_fbo_init = true; context_bind_hw_render(false); return true; }
FrameBufferObject::FrameBufferObject(int width, int height, int depthBufferBitDepth, int stencilBufferBitDepth, GLenum textureFormat, GLenum textureType, std::string name) : width(width), height(height), textureFormat(textureFormat), textureType(textureType), texNum(0), nextIndex(0), Height(height), Width(width), Bound(bound) { if (!glGenFramebuffers) throw; bound = false; setDrawBuffers = false; if (name == "") { char buf[64]; sprintf(buf, "unnamed%d", ++nextIndex); this->name = buf; } else { this->name = name; } glGenFramebuffers(1, &glID); glBindFramebuffer(GL_FRAMEBUFFER, glID); if (depthBufferBitDepth || stencilBufferBitDepth) { GLenum format = 0; if (depthBufferBitDepth && stencilBufferBitDepth) { if (depthBufferBitDepth == 32 && stencilBufferBitDepth == 8) format = GL_DEPTH32F_STENCIL8; else format = GL_DEPTH24_STENCIL8; GLuint id; glGenRenderbuffers(1, &id); renderBuffers.push_back(id); glBindRenderbuffer(GL_RENDERBUFFER, id); glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, id); } else if (stencilBufferBitDepth == 0) { if (depthBufferBitDepth == 16) format = GL_DEPTH_COMPONENT16; else if (depthBufferBitDepth == 24) format = GL_DEPTH_COMPONENT24; else format = GL_DEPTH_COMPONENT32F; GLuint id; glGenRenderbuffers(1, &id); renderBuffers.push_back(id); glBindRenderbuffer(GL_RENDERBUFFER, id); glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, id); } } glBindFramebuffer(GL_FRAMEBUFFER, 0); }
void GL::renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { GL_CHECK(glRenderbufferStorage(target, internalformat, width, height)); }
void piglit_init(int argc, char **argv) { GLuint vs, fs_paint_red, fs_sample; GLenum fb_status; /* Parse params */ if (argc != 3) print_usage_and_exit(argv[0]); if (strcmp(argv[1], "sample") == 0) subtest = SUBTEST_SAMPLE; else if (strcmp(argv[1], "read_pixels") == 0) subtest = SUBTEST_READ_PIXELS; else if (strcmp(argv[1], "blit") == 0) subtest = SUBTEST_BLIT; else if (strcmp(argv[1], "copy") == 0) subtest = SUBTEST_COPY; else print_usage_and_exit(argv[0]); if (strcmp(argv[2], "rb") == 0) use_texture = false; else if (strcmp(argv[2], "tex") == 0) use_texture = true; else print_usage_and_exit(argv[0]); /* Detect parameter conflicts */ if (subtest == SUBTEST_SAMPLE && !use_texture) { printf("Subtest 'sample' requires buffer_type 'tex'.\n"); piglit_report_result(PIGLIT_FAIL); } /* Requirements */ piglit_require_gl_version(11); piglit_require_GLSL_version(110); piglit_require_extension("GL_ARB_framebuffer_object"); /* Compile shaders */ vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_text); fs_paint_red = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_text_paint_red); prog_paint_red = piglit_link_simple_program(vs, fs_paint_red); if (!prog_paint_red) piglit_report_result(PIGLIT_FAIL); fs_sample = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_text_sample); prog_sample = piglit_link_simple_program(vs, fs_sample); if (!prog_sample) piglit_report_result(PIGLIT_FAIL); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); /* Set up framebuffer */ glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER, fb); if (use_texture) { tex1 = allocate_texture(); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0 /* level */); } else { GLuint rb; glGenRenderbuffers(1, &rb); glBindRenderbuffer(GL_RENDERBUFFER, rb); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, TEX_WIDTH, TEX_HEIGHT); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb); } if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (fb_status != GL_FRAMEBUFFER_COMPLETE) { printf("Framebuffer status: %s\n", piglit_get_gl_enum_name(fb_status)); piglit_report_result(PIGLIT_FAIL); } /* Set up second texture (used by "copy" test only) */ if (subtest == SUBTEST_COPY) tex2 = allocate_texture(); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); }
int main() { // Initialize GLFW and set some hints that will create an OpenGL 3.3 context // using core profile. glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Create a fixed 800x600 window that is not resizable. GLFWwindow* window = glfwCreateWindow(kWindowWidth, kWindowHeight, "LearnGL", nullptr, nullptr); if (window == nullptr) { std::cerr << "Failed to created GLFW window" << std::endl; glfwTerminate(); return 1; } // Create an OpenGL context and pass callbacks to GLFW. glfwMakeContextCurrent(window); glfwSetKeyCallback(window, keyCallback); glfwSetCursorPosCallback(window, mouseCallback); glfwSetScrollCallback(window, scrollCallback); // Lock the mouse in the window. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { std::cerr << "Failed to initialize GLEW" << std::endl; glfwTerminate(); return 1; } // Create a viewport the same size as the window. glfwGetFramebufferSize is // used rather than the size constants since some windowing systems have a // discrepancy between window size and framebuffer size // (e.g HiDPi screen coordinates), int fbWidth, fbHeight; glfwGetFramebufferSize(window, &fbWidth, &fbHeight); glViewport(0, 0, fbWidth, fbHeight); // Enable use of the depth buffer since we're working on 3D and want to // prevent overlapping polygon artifacts. glEnable(GL_DEPTH_TEST); // Read and compile the vertex and fragment shaders using // the shader helper class. Shader shader("glsl/vertex.glsl", "glsl/fragment.glsl", "glsl/geometry.glsl"); Shader lampShader("glsl/lampvertex.glsl", "glsl/lampfragment.glsl"); Shader postShader("glsl/post_vert.glsl", "glsl/post_frag.glsl"); Shader gsShader("glsl/gs_vert.glsl", "glsl/gs_frag.glsl", "glsl/gs_geo.glsl"); GLuint containerTexture = loadTexture("assets/container2.png"); GLuint containerSpecular = loadTexture("assets/container2_specular.png"); GLuint containerEmission = loadTexture("assets/matrix.jpg"); // Create and bind a framebuffer. GLuint FBO; glGenFramebuffers(1, &FBO); glBindFramebuffer(GL_FRAMEBUFFER, FBO); // Create an empty texture to be attached to the framebuffer. // Give a null pointer to glTexImage2D since we want an empty texture. GLuint frameColorBuffer; glGenTextures(1, &frameColorBuffer); glBindTexture(GL_TEXTURE_2D, frameColorBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbWidth, fbHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); // Attach the texture to the framebuffer. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, frameColorBuffer, 0); // Create a renderbuffer to hold our depth and stencil buffers with a size // of the window's framebuffer size. GLuint RBO; glGenRenderbuffers(1, &RBO); glBindRenderbuffer(GL_RENDERBUFFER, RBO); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, fbWidth, fbHeight); glBindRenderbuffer(GL_RENDERBUFFER, 0); // Attach the render buffer (provides depth and stencil) to the framebuffer. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO); // Panic if the framebuffer is somehow incomplete at this stage. This should // never happen if we attached the texture but it's good practice to check. if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { std::cerr << "ERROR: Framebuffer is not complete!" << std::endl; glfwTerminate(); return 1; } // Unbind the framebuffer since we want the main scene to be drawn // to be drawn to the main window. glBindFramebuffer(GL_FRAMEBUFFER, 0); // Container mesh data. GLfloat vertices[] = { // Vertices // Normals // UVs -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }; // Points for the geometry shader tutorial. GLfloat points[] = { -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // Top-left 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Top-right 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right -0.5f, -0.5f, 1.0f, 1.0f, 0.0f // Bottom-left }; // Positions all containers glm::vec3 cubePositions[] = { glm::vec3( 0.0f, 0.0f, 0.0f), glm::vec3( 2.0f, 5.0f, -15.0f), glm::vec3(-1.5f, -2.2f, -2.5f), glm::vec3(-3.8f, -2.0f, -12.3f), glm::vec3( 2.4f, -0.4f, -3.5f), glm::vec3(-1.7f, 3.0f, -7.5f), glm::vec3( 1.3f, -2.0f, -2.5f), glm::vec3( 1.5f, 2.0f, -2.5f), glm::vec3( 1.5f, 0.2f, -1.5f), glm::vec3(-1.3f, 1.0f, -1.5f) }; // Create a VBO to store the vertex data, an EBO to store indice data, and // create a VAO to retain our vertex attribute pointers. GLuint VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // Fill the VBO and set vertex attributes. glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); glEnableVertexAttribArray(2); glBindVertexArray(0); // Create a lamp box thing using the existing container VBO. GLuint lightVAO; glGenVertexArrays(1, &lightVAO); // Use the container's VBO and set vertex attributes. glBindVertexArray(lightVAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); glBindVertexArray(0); // Vertex attributes for the frame quad in NDC. GLfloat frameVertices[] = { // Positions // UVs -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, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f }; // Create a VBO and VAO for the post-processing step. GLuint frameVBO, frameVAO; glGenVertexArrays(1, &frameVAO); glGenBuffers(1, &frameVBO); glBindVertexArray(frameVAO); glBindBuffer(GL_ARRAY_BUFFER, frameVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(frameVertices), frameVertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat))); glEnableVertexAttribArray(1); glBindVertexArray(0); // Create a VBO and VAO for the geometry shader test. The VBO will contain // only the position. GLuint pointsVBO, pointsVAO; glGenVertexArrays(1, &pointsVAO); glGenBuffers(1, &pointsVBO); glBindVertexArray(pointsVAO); glBindBuffer(GL_ARRAY_BUFFER, pointsVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat))); glEnableVertexAttribArray(1); glBindVertexArray(0); // Create a perspective camera to fit the viewport. screenWidth = (GLfloat)fbWidth; screenHeight = (GLfloat)fbHeight; camera = PerspectiveCamera( glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, glm::radians(-90.0f), 0.0f), glm::radians(45.0f), screenWidth / screenHeight, 0.1f, 100.0f ); GLfloat delta = 0.0f; GLfloat lastFrame = 0.0f; // Light information. const glm::vec3 directionalLightDir(0.0f, 1.0f, 0.0f); const glm::vec3 pointLightPositions[] = { glm::vec3( 0.7f, 0.2f, 2.0f), glm::vec3( 2.3f, -3.3f, -4.0f), glm::vec3(-4.0f, 2.0f, -12.0f), glm::vec3( 0.0f, 0.0f, -3.0f) }; // Render loop. while (!glfwWindowShouldClose(window)) { GLfloat currentFrame = glfwGetTime(); delta = currentFrame - lastFrame; lastFrame = currentFrame; // Check and call events. glfwPollEvents(); move(delta); // Bind the off screen framebuffer (for post-processing) and clear the // screen to a nice blue color. glBindFramebuffer(GL_FRAMEBUFFER, FBO); glClearColor(0.1f, 0.15f, 0.15f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); const GLfloat limitTime = 1.0f; fovTime += delta; if (fovTime > limitTime) { fovTime = limitTime; } // Update the perspective to account for changes in fov. camera.fov = easeOutQuart(fovTime, startFov, (startFov - targetFov) * -1, limitTime); camera.update(); // Bind the VAO and shader. glBindVertexArray(VAO); shader.use(); // Pass the view and projection matrices from the camera. GLuint viewMatrix = glGetUniformLocation(shader.program, "view"); glUniformMatrix4fv(viewMatrix, 1, GL_FALSE, glm::value_ptr(camera.view)); GLuint projectionMatrix = glGetUniformLocation(shader.program, "projection"); glUniformMatrix4fv(projectionMatrix, 1, GL_FALSE, glm::value_ptr(camera.projection)); // Generate light colors. glm::vec3 lightColor(1.0f, 1.0f, 1.0f); // Directional light glUniform3f(glGetUniformLocation(shader.program, "dirLight.direction"), -0.2f, -1.0f, -0.3f); glUniform3f(glGetUniformLocation(shader.program, "dirLight.ambient"), 0.05f, 0.05f, 0.05f); glUniform3f(glGetUniformLocation(shader.program, "dirLight.diffuse"), 0.4f, 0.4f, 0.4f); glUniform3f(glGetUniformLocation(shader.program, "dirLight.specular"), 0.5f, 0.5f, 0.5f); // Point light 1 glUniform3f(glGetUniformLocation(shader.program, "pointLights[0].position"), pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z); glUniform3f(glGetUniformLocation(shader.program, "pointLights[0].ambient"), 0.05f, 0.05f, 0.05f); glUniform3f(glGetUniformLocation(shader.program, "pointLights[0].diffuse"), 1.0f, 0.0f, 0.0f); glUniform3f(glGetUniformLocation(shader.program, "pointLights[0].specular"), 1.0f, 1.0f, 1.0f); glUniform1f(glGetUniformLocation(shader.program, "pointLights[0].constant"), 1.0f); glUniform1f(glGetUniformLocation(shader.program, "pointLights[0].linear"), 0.09); glUniform1f(glGetUniformLocation(shader.program, "pointLights[0].quadratic"), 0.032); // Point light 2 glUniform3f(glGetUniformLocation(shader.program, "pointLights[1].position"), pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z); glUniform3f(glGetUniformLocation(shader.program, "pointLights[1].ambient"), 0.05f, 0.05f, 0.05f); glUniform3f(glGetUniformLocation(shader.program, "pointLights[1].diffuse"), 0.0f, 1.0f, 0.0f); glUniform3f(glGetUniformLocation(shader.program, "pointLights[1].specular"), 1.0f, 1.0f, 1.0f); glUniform1f(glGetUniformLocation(shader.program, "pointLights[1].constant"), 1.0f); glUniform1f(glGetUniformLocation(shader.program, "pointLights[1].linear"), 0.09); glUniform1f(glGetUniformLocation(shader.program, "pointLights[1].quadratic"), 0.032); // Point light 3 glUniform3f(glGetUniformLocation(shader.program, "pointLights[2].position"), pointLightPositions[2].x, pointLightPositions[2].y, pointLightPositions[2].z); glUniform3f(glGetUniformLocation(shader.program, "pointLights[2].ambient"), 0.05f, 0.05f, 0.05f); glUniform3f(glGetUniformLocation(shader.program, "pointLights[2].diffuse"), 0.0f, 0.0f, 1.0f); glUniform3f(glGetUniformLocation(shader.program, "pointLights[2].specular"), 1.0f, 1.0f, 1.0f); glUniform1f(glGetUniformLocation(shader.program, "pointLights[2].constant"), 1.0f); glUniform1f(glGetUniformLocation(shader.program, "pointLights[2].linear"), 0.09); glUniform1f(glGetUniformLocation(shader.program, "pointLights[2].quadratic"), 0.032); // Point light 4 glUniform3f(glGetUniformLocation(shader.program, "pointLights[3].position"), pointLightPositions[3].x, pointLightPositions[3].y, pointLightPositions[3].z); glUniform3f(glGetUniformLocation(shader.program, "pointLights[3].ambient"), 0.05f, 0.05f, 0.05f); glUniform3f(glGetUniformLocation(shader.program, "pointLights[3].diffuse"), 0.8f, 0.8f, 0.8f); glUniform3f(glGetUniformLocation(shader.program, "pointLights[3].specular"), 1.0f, 1.0f, 1.0f); glUniform1f(glGetUniformLocation(shader.program, "pointLights[3].constant"), 1.0f); glUniform1f(glGetUniformLocation(shader.program, "pointLights[3].linear"), 0.09); glUniform1f(glGetUniformLocation(shader.program, "pointLights[3].quadratic"), 0.032); // Sport light 1 glUniform3f(glGetUniformLocation(shader.program, "spotLights[0].position"), camera.position.x, camera.position.y, camera.position.z); glUniform3f(glGetUniformLocation(shader.program, "spotLights[0].direction"), camera.front.x, camera.front.y, camera.front.z); glUniform3f(glGetUniformLocation(shader.program, "spotLights[0].ambient"), 0.0f, 0.0f, 0.0f); glUniform3f(glGetUniformLocation(shader.program, "spotLights[0].diffuse"), 1.0f, 1.0f, 1.0f); glUniform3f(glGetUniformLocation(shader.program, "spotLights[0].specular"), 1.0f, 1.0f, 1.0f); glUniform1f(glGetUniformLocation(shader.program, "spotLights[0].constant"), 1.0f); glUniform1f(glGetUniformLocation(shader.program, "spotLights[0].linear"), 0.09); glUniform1f(glGetUniformLocation(shader.program, "spotLights[0].quadratic"), 0.032); glUniform1f(glGetUniformLocation(shader.program, "spotLights[0].cutoff"), glm::cos(glm::radians(12.5f))); glUniform1f(glGetUniformLocation(shader.program, "spotLights[0].outerCutoff"), glm::cos(glm::radians(15.5f))); // Pass material values. GLuint materialShininess = glGetUniformLocation(shader.program, "material.shininess"); GLuint materialDiffuse = glGetUniformLocation(shader.program, "material.diffuse"); GLuint materialSpecular = glGetUniformLocation(shader.program, "material.specular"); GLuint materialEmission = glGetUniformLocation(shader.program, "material.emission"); glUniform1f(materialShininess, 64.0f); glUniform1i(materialDiffuse, 0); glUniform1i(materialSpecular, 1); glUniform1i(materialEmission, 2); // Misc values. GLuint viewPos = glGetUniformLocation(shader.program, "viewPos"); glUniform3f(viewPos, camera.position.x, camera.position.y, camera.position.z); GLuint time = glGetUniformLocation(shader.program, "time"); glUniform1f(time, glfwGetTime()); // Bind the textures. glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, containerTexture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, containerSpecular); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, containerEmission); // Draw multiple containers! GLuint modelMatrix = glGetUniformLocation(shader.program, "model"); GLuint normalMatrix = glGetUniformLocation(shader.program, "normalMatrix"); for (GLuint i = 0; i < 10; i++) { // Apply world transformations. model = glm::mat4(); model = glm::translate(model, cubePositions[i]); model = glm::rotate(model, i * 20.0f, glm::vec3(1.0f, 0.3f, 0.5f)); glUniformMatrix4fv(modelMatrix, 1, GL_FALSE, glm::value_ptr(model)); // Calculate the normal matrix on the CPU (keep them normals perpendicular). normal = glm::mat3(glm::transpose(glm::inverse(model))); glUniformMatrix3fv(normalMatrix, 1, GL_FALSE, glm::value_ptr(normal)); // Draw the container. glDrawArrays(GL_TRIANGLES, 0, 36); } glBindVertexArray(0); // Bind the VAO and shader. glBindVertexArray(lightVAO); lampShader.use(); // Pass the view and projection matrices from the camera. viewMatrix = glGetUniformLocation(lampShader.program, "view"); glUniformMatrix4fv(viewMatrix, 1, GL_FALSE, glm::value_ptr(camera.view)); projectionMatrix = glGetUniformLocation(lampShader.program, "projection"); glUniformMatrix4fv(projectionMatrix, 1, GL_FALSE, glm::value_ptr(camera.projection)); for (GLuint i = 0; i < 4; i++) { // Apply world transformations. model = glm::mat4(); model = glm::translate(model, pointLightPositions[i]); model = glm::scale(model, glm::vec3(0.2f)); modelMatrix = glGetUniformLocation(lampShader.program, "model"); glUniformMatrix4fv(modelMatrix, 1, GL_FALSE, glm::value_ptr(model)); // Draw the lamp. glDrawArrays(GL_TRIANGLES, 0, 36); } glBindVertexArray(0); // Draw something with the geometry shader program. //glDisable(GL_DEPTH_TEST); //gsShader.use(); //glBindVertexArray(pointsVAO); //glDrawArrays(GL_POINTS, 0, 4); //glBindVertexArray(0); //glEnable(GL_DEPTH_TEST); // Unbind the offscreen framebuffer containing the unprocessed frame. glBindFramebuffer(GL_FRAMEBUFFER, 0); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); postShader.use(); glBindVertexArray(frameVAO); // Send the texture sampler to the shader. GLuint frameTexture = glGetUniformLocation(postShader.program, "frameTexture"); time = glGetUniformLocation(postShader.program, "time"); glUniform1i(frameTexture, 0); glUniform1f(time, glfwGetTime()); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, frameColorBuffer); // Render the color buffer in the framebuffer to the quad with post shader. glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); // Swap buffers used for double buffering. glfwSwapBuffers(window); } // Destroy the off screen framebuffer. glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &FBO); // Properly deallocate the VBO and VAO. glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); // Terminate GLFW and clean any resources before exiting. glfwTerminate(); return 0; }
void FrameBufferDemo::Initialize() { fboProgram.AddShaderFile(ShaderType::Vertex,"Assets/Shaders/Vertex/fbo.vert"); fboProgram.AddShaderFile(ShaderType::Fragment,"Assets/Shaders/Fragment/fbo.frag"); fboProgram.Build(); textureProgram.AddShaderFile(ShaderType::Vertex, "Assets/Shaders/Vertex/texture.vert"); textureProgram.AddShaderFile(ShaderType::Fragment, "Assets/Shaders/Fragment/texture.frag"); textureProgram.Build(); textureProgram.AddUniformBlock({ "TransformBlock", { { "TransformBlock.view", &camera->GetView()[0][0], sizeof(camera->GetView()) }, { "TransformBlock.projection", &camera->GetProjection()[0][0], sizeof(camera->GetProjection()) }, } }); fboProgram.AddUniformBlock({ "TransformBlock",{ { "TransformBlock.view", &camera->GetView()[0][0], sizeof(camera->GetView()) }, { "TransformBlock.projection", &camera->GetProjection()[0][0], sizeof(camera->GetProjection()) }, } }); input->addBinding(GLFW_KEY_LEFT, [this](InputInfo info) { camera->MoveLeft(); fboProgram.UpdateUniformBlock("TransformBlock"); textureProgram.UpdateUniformBlock("TransformBlock"); }); input->addBinding(GLFW_KEY_RIGHT, [this](InputInfo info) { camera->MoveRight(); fboProgram.UpdateUniformBlock("TransformBlock"); textureProgram.UpdateUniformBlock("TransformBlock"); }); input->addBinding(GLFW_KEY_UP, [this](InputInfo info) { camera->MoveForward(); textureProgram.UpdateUniformBlock("TransformBlock"); fboProgram.UpdateUniformBlock("TransformBlock"); }); input->addBinding(GLFW_KEY_DOWN, [this](InputInfo info) { camera->MoveBack(); textureProgram.UpdateUniformBlock("TransformBlock"); fboProgram.UpdateUniformBlock("TransformBlock"); }); glGenFramebuffers(1, &fboHandle); glBindFramebuffer(GL_FRAMEBUFFER, fboHandle); glGenTextures(1, &renderTargetTexture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, renderTargetTexture); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 512, 512); 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, renderTargetTexture,0); glGenRenderbuffers(1, &depthBufferTexture); glBindRenderbuffer(GL_RENDERBUFFER, depthBufferTexture); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 512, 512); GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 }; glDrawBuffers(1, drawBufs); glBindFramebuffer(GL_FRAMEBUFFER, 0); Assimp::Importer importer; auto cubeScene = importer.ReadFile("Assets/Models/Obj/box.obj", aiProcess_Triangulate); cube = std::unique_ptr<GameObject>(new GameObject()); cube->GetTransform()->SetPosition({ 0.0f,0.0f,-5.0f }); cube->GetTransform()->SetScale({ 20.0f,20.0f,20.0f }); cube->Update(); if (cubeScene && cubeScene->HasMeshes()) { cubeMesh = std::unique_ptr<MeshComponent>(new MeshComponent(cube.get())); cubeMesh->Initialize(cubeScene->mMeshes[0], fboProgram, { {"world", UniformType::MAT4, &cube->GetWorld()[0][0]}, }); cubeMesh->AddTexture({ renderTargetTexture,GL_TEXTURE_2D, renderer->GetSampler(SamplerType::Linear).sampler }); } auto monkeyScene = importer.ReadFile("Assets/Models/Obj/monkey.obj", aiProcess_Triangulate); monkey = std::unique_ptr<GameObject>(new GameObject()); monkey->GetTransform()->SetPosition({ 2.0f,0.0f,-2.0f }); monkey->Update(); if (monkeyScene && monkeyScene->HasMeshes()) { monkeyMesh = std::unique_ptr<MeshComponent>(new MeshComponent(monkey.get())); monkeyMesh->Initialize(monkeyScene->mMeshes[0], textureProgram, { {"world", UniformType::MAT4, &monkey->GetWorld()[0][0]} }); monkeyMesh->AddTexture("Assets/Textures/brick.jpg"); } importer.FreeScene(); }
bool Context::try_create_fbo( GLsizei width , GLsizei height , int flags ) { tplog2( "CREATING FRAMEBUFFER" ); GLuint fbo; GLuintSet rb; bool h_depth = false; bool h_stencil = false; glGenFramebuffers( 1 , & fbo ); glBindFramebuffer( GL_FRAMEBUFFER , fbo ); glFramebufferTexture2D( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , texture_target , texture , 0 ); if ( flags & FBO_TRY_DEPTH_STENCIL ) { tplog2( " CREATING DEPTH/STENCIL RENDERBUFFERS" ); GLuint depth_stencil_rb; glGenRenderbuffers( 1 , & depth_stencil_rb ); glBindRenderbuffer( GL_RENDERBUFFER , depth_stencil_rb ); glRenderbufferStorage( GL_RENDERBUFFER , GL_DEPTH_STENCIL , width , height ); glBindRenderbuffer( GL_RENDERBUFFER , 0 ); glFramebufferRenderbuffer( GL_FRAMEBUFFER , GL_STENCIL_ATTACHMENT , GL_RENDERBUFFER, depth_stencil_rb ); glFramebufferRenderbuffer( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER , depth_stencil_rb ); rb.insert( depth_stencil_rb ); h_depth = true; h_stencil = true; } if ( flags & FBO_TRY_DEPTH ) { tplog2( " CREATING DEPTH RENDERBUFFER" ); GLuint depth_rb; glGenRenderbuffers( 1 , & depth_rb ); glBindRenderbuffer( GL_RENDERBUFFER , depth_rb ); glRenderbufferStorage( GL_RENDERBUFFER , GL_DEPTH_COMPONENT16 , width , height ); glBindRenderbuffer( GL_RENDERBUFFER , 0 ); glFramebufferRenderbuffer( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER , depth_rb ); rb.insert( depth_rb ); h_depth = true; } if ( flags & FBO_TRY_STENCIL ) { tplog2( " CREATING STENCIL RENDERBUFFER" ); GLuint stencil_rb; glGenRenderbuffers( 1 , & stencil_rb ); glBindRenderbuffer( GL_RENDERBUFFER , stencil_rb ); glRenderbufferStorage( GL_RENDERBUFFER , GL_STENCIL_INDEX8 , width , height ); glBindRenderbuffer( GL_RENDERBUFFER , 0 ); glFramebufferRenderbuffer( GL_FRAMEBUFFER , GL_STENCIL_ATTACHMENT , GL_RENDERBUFFER , stencil_rb ); rb.insert( stencil_rb ); h_stencil = true; } if ( GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus( GL_FRAMEBUFFER ) ) { glBindFramebuffer( GL_FRAMEBUFFER , 0 ); tplog2( " DESTROYING FRAMEBUFFER %u" , fbo ); glDeleteFramebuffers( 1 , & fbo ); for ( GLuintSet::const_iterator it = rb.begin(); it != rb.end(); ++it ) { tplog2( " DESTROYING RENDERBUFFER %u" , *it ); glDeleteRenderbuffers( 1 , & * it ); } tplog2( "* FRAMEBUFFER IS NOT COMPLETE" ); return false; } tplog2( "* FRAMEBUFFER IS COMPLETE" ); framebuffer = fbo; renderbuffers.insert( rb.begin() , rb.end() ); have_depth = h_depth; have_stencil = h_stencil; return true; }
void fboInit( tFBOInfo* pFBOInfo, int iWidth, int iHeight, int iTextureFilter ) { // bind fbo to texture glGenFramebuffers( 1, &pFBOInfo->mFBO ); glBindFramebuffer( GL_FRAMEBUFFER, pFBOInfo->mFBO ); // color buffer for fbo glGenRenderbuffers( 1, &pFBOInfo->mColorRenderBuffer ); glBindRenderbuffer( GL_RENDERBUFFER, pFBOInfo->mColorRenderBuffer ); #if defined( WIN32 ) || defined( MACOS ) glRenderbufferStorage( GL_RENDERBUFFER, GL_RGB8, iWidth, iHeight ); #else glRenderbufferStorage( GL_RENDERBUFFER, GL_RGB8_OES, iWidth, iHeight ); #endif // WIN32 glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, pFBOInfo->mColorRenderBuffer ); // depth buffer for the fbo glGenRenderbuffers( 1, &pFBOInfo->mDepthRenderBuffer ); glBindRenderbuffer( GL_RENDERBUFFER, pFBOInfo->mDepthRenderBuffer ); #if defined( WIN32 ) || defined( MACOS ) glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, iWidth, iHeight ); #else glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, iWidth, iHeight ); #endif // WIN32 glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, pFBOInfo->mDepthRenderBuffer ); // texture glGenTextures( 1, &pFBOInfo->mTexture ); glBindTexture( GL_TEXTURE_2D, pFBOInfo->mTexture ); GLuint iGLFilterType = GL_NEAREST; if( iTextureFilter == FILTER_BILINEAR ) { iGLFilterType = GL_LINEAR; } else if( iTextureFilter == FILTER_NEAREST ) { iGLFilterType = GL_NEAREST; } // attribute 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, iGLFilterType ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iGLFilterType ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, iWidth, iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pFBOInfo->mTexture, 0 ); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); }
bool GBuffer::setupFbo(unsigned int windowWidth, unsigned int windowHeight) { m_buffer_w = windowWidth; m_buffer_h = windowHeight; // delete existing fbo, textures, and render buffer in case we are regenerating at new size glDeleteTextures(GBUFFER_NUM_TEXTURES, m_textures); glDeleteRenderbuffers(1, &m_renderBuffer); glDeleteFramebuffers(1, &m_fbo); // create an fbo glGenFramebuffers(1, &m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // create all gbuffer textures glGenTextures(GBUFFER_NUM_TEXTURES, m_textures); // albedo/diffuse (16-bit channel rgba) glBindTexture(GL_TEXTURE_2D, m_textures[GBUFFER_TEXTURE_TYPE_ALBEDO]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, m_buffer_w, m_buffer_h, 0, GL_RGBA, GL_FLOAT, NULL); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_TEXTURE_TYPE_ALBEDO, GL_TEXTURE_2D, m_textures[GBUFFER_TEXTURE_TYPE_ALBEDO], 0); // normals + depth (32-bit RGBA float for accuracy) glBindTexture(GL_TEXTURE_2D, m_textures[GBUFFER_TEXTURE_TYPE_NORMALS_DEPTH]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_buffer_w, m_buffer_h, 0, GL_RGBA, GL_FLOAT, NULL); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_TEXTURE_TYPE_NORMALS_DEPTH, GL_TEXTURE_2D, m_textures[GBUFFER_TEXTURE_TYPE_NORMALS_DEPTH], 0); // lighting pass (16-bit RGBA) glBindTexture(GL_TEXTURE_2D, m_textures[GBUFFER_TEXTURE_TYPE_LIGHT_PASS]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_buffer_w, m_buffer_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_TEXTURE_TYPE_LIGHT_PASS, GL_TEXTURE_2D, m_textures[GBUFFER_TEXTURE_TYPE_LIGHT_PASS], 0); // create depth texture (we don't use this explicitly, but since we use depth testing when rendering + for our stencil pass, our FBO needs a depth buffer) // we make it a renderbuffer and not a texture as we'll never access it directly in a shader glGenRenderbuffers(1, &m_renderBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_renderBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, m_buffer_w, m_buffer_h); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_renderBuffer); // check status GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); if (status != GL_FRAMEBUFFER_COMPLETE) { ofLogError("GBuffer::setupFbo()", "Could not create framebuffer"); return false; } return true; }
void createFramebuffer() { glActiveTexture(GL_TEXTURE0); glGenTextures(1, &FBOTexture); glBindTexture(GL_TEXTURE_2D, FBOTexture); 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_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, FRAME_BUFFER_WIDTH, FRAME_BUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glGenRenderbuffers(1, &FBODepthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, FBODepthBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, FRAME_BUFFER_WIDTH, FRAME_BUFFER_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, 0); glGenFramebuffers(1, &frameBufferObject); glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, FBOTexture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER, FBODepthBuffer); GLenum status; if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { cout << "Issue with Framebuffers" << endl; } float vertices[] = { -1, -1, 1, -1, -1, 1, 1, 1, }; glGenVertexArrays(1, &fullScreenVAO); glBindVertexArray(fullScreenVAO); glGenBuffers(1, &fullScreenVBO); glBindBuffer(GL_ARRAY_BUFFER, fullScreenVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer( 0, // attribute 2, // number of elements per vertex, here (x,y) GL_FLOAT, // the type of each element GL_FALSE, // take our values as-is 0, // no extra data between each position 0 // offset of first element ); GLuint vertexShaderProgram = 0; string vsPath = ASSET_PATH + SHADER_PATH + "/simplePostProcessVS.glsl"; vertexShaderProgram = loadShaderFromFile(vsPath, VERTEX_SHADER); checkForCompilerErrors(vertexShaderProgram); GLuint fragmentShaderProgram = 0; string fsPath = ASSET_PATH + SHADER_PATH + "/simplePostProcessFS.glsl"; fragmentShaderProgram = loadShaderFromFile(fsPath, FRAGMENT_SHADER); checkForCompilerErrors(fragmentShaderProgram); fullScreenShaderProgram = glCreateProgram(); glAttachShader(fullScreenShaderProgram, vertexShaderProgram); glAttachShader(fullScreenShaderProgram, fragmentShaderProgram); //Link attributes glBindAttribLocation(fullScreenShaderProgram, 0, "vertexPosition"); glLinkProgram(fullScreenShaderProgram); checkForLinkErrors(fullScreenShaderProgram); //now we can delete the VS & FS Programs glDeleteShader(vertexShaderProgram); glDeleteShader(fragmentShaderProgram); }
bool do_blit_test(bool use_es2, bool from_missing_to_complete) { GLuint rb[3]; GLuint fb[2]; GLenum status; GLenum err; const unsigned src = from_missing_to_complete ? 0 : 1; const unsigned dst = 1 - src; const char *const names[] = { "buffer with missing attachment", "complete buffer" }; bool pass = true; printf("Testing blit from %s to %s...\n", names[src], names[dst]); /* Create a depth-only FBO and a depth/color FBO. */ glGenRenderbuffers(ARRAY_SIZE(rb), rb); glBindRenderbuffer(GL_RENDERBUFFER, rb[0]); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, piglit_width, piglit_height); glBindRenderbuffer(GL_RENDERBUFFER, rb[1]); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, piglit_width, piglit_height); glBindRenderbuffer(GL_RENDERBUFFER, rb[2]); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, piglit_width, piglit_height); glGenFramebuffers(ARRAY_SIZE(fb), fb); glBindFramebuffer(GL_FRAMEBUFFER, fb[0]); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb[0]); if (!use_es2) { glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb[1]); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb[1]); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb[2]); err = glGetError(); if (err != 0) { fprintf(stderr, "Unexpected GL error state 0x%04x\n", err); return false; } /* Check completeness of the source surface. */ glBindFramebuffer(GL_READ_FRAMEBUFFER, fb[src]); status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { fprintf(stderr, "Read FBO erroneously incomplete: 0x%04x\n", status); return false; } /* In the source surface, clear the depth buffer and draw a single * rectangle with a constant depth value. The depth test setting here * is correct. */ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb[src]); glClearDepth(0.0); glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); piglit_draw_rect_z(0.5, -0.5, -0.5, 1.0, 1.0); /* Check completeness of the destination surface. */ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb[dst]); status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { fprintf(stderr, "Draw FBO erroneously incomplete: 0x%04x\n", status); return false; } glBlitFramebuffer(0, 0, piglit_width, piglit_height, 0, 0, piglit_width, piglit_height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); err = glGetError(); if (err != 0) { fprintf(stderr, "Unexpected GL error state 0x%04x\n", err); return false; } /* Probe depth values from the destination buffer to make sure the * depth part of the blit actually happened. */ glBindFramebuffer(GL_READ_FRAMEBUFFER, fb[dst]); pass = piglit_probe_rect_depth(0.25 * piglit_width, 0.25 * piglit_height, 0.4 * piglit_width, 0.4 * piglit_height, 0.75); pass = piglit_probe_rect_depth(0, 0, piglit_width, 0.2 * piglit_height, 0.0) && pass; glBindFramebuffer(GL_READ_FRAMEBUFFER, piglit_winsys_fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo); glDeleteFramebuffers(ARRAY_SIZE(fb), fb); glDeleteRenderbuffers(ARRAY_SIZE(rb), rb); return pass; }
bool Init(int w, int h) { // Create a framebuffer object glGenFramebuffers(1, fboId); glBindFramebuffer(GL_FRAMEBUFFER, *fboId); // Create a render buffer glGenRenderbuffers(1, renderBuffer); glBindRenderbuffer(GL_RENDERBUFFER, *renderBuffer); // Create a texture for storing the depth glGenTextures(1, depthTextureId); glBindTexture(GL_TEXTURE_2D, *depthTextureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Remove artifact on the edges of the shadowmap glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); Debug("glGetError() 0 = 0x%x", glGetError()); if ( m_hasDepthTextureExtension ) { // We'll use a depth texture to store the depths in the shadow map glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); // Attach the depth texture to FBO depth attachment point glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, *depthTextureId, 0); } else { // We'll use a RGBA texture into which we pack the depth info glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Attach the RGBA texture to FBO color attachment point glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *depthTextureId, 0); // Allocate 16-bit depth buffer glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); // Attach the render buffer as depth buffer - will be ignored glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *renderBuffer); } // check FBO status GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); if ( fboStatus != GL_FRAMEBUFFER_COMPLETE ) { Debug("FBO not complete: 0x%x", fboStatus); return false; } // Go back to using the default frame buffer glBindFramebuffer(GL_FRAMEBUFFER, DefaultFramebufferId); return true; }
void FBOBJECT::Init(GLSTATEMANAGER & glstate, std::vector <FBTEXTURE*> newtextures, std::ostream & error_output, bool force_multisample_off) { OPENGL_UTILITY::CheckForOpenGLErrors("FBO init start", error_output); const bool verbose = false; if (inited) { if (verbose) error_output << "INFO: deinitializing existing FBO" << std::endl; DeInit(); OPENGL_UTILITY::CheckForOpenGLErrors("FBO deinit", error_output); } textures = newtextures; inited = true; assert(!textures.empty()); // run some sanity checks and find out which textures are for the color attachment and // which are for the depth attachment std::vector <FBTEXTURE*> color_textures; std::vector <FBTEXTURE*> depth_textures; for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++) { if ((*i)->texture_format == FBTEXTURE::DEPTH24) depth_textures.push_back(*i); else color_textures.push_back(*i); //assert(!(*i)->attached || (force_multisample_off && (*i)->renderbuffer_multisample != 0)); (*i)->attached = true; } if (verbose) error_output << "INFO: color textures: " << color_textures.size() << ", depth textures: " << depth_textures.size() << std::endl; //need at least some textures assert(color_textures.size() + depth_textures.size() >= 1); //can't have more than one depth attachment assert(depth_textures.size() < 2); //can't have more than 4 color textures assert(color_textures.size() < 5); for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++) { if ((*i)->texture_target == FBTEXTURE::CUBEMAP) { if (verbose) error_output << "INFO: found cubemap" << std::endl; //can't have MRT with cubemaps assert(color_textures.size() == 1); //can't have multisample with cubemaps assert((*i)->multisample == 0); //can't have depth texture with cubemaps assert(depth_textures.empty()); } } //find what multisample value to use int multisample = 0; if (!color_textures.empty()) { multisample = -1; for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++) { if (multisample == -1) multisample = (*i)->multisample; //all must have the same multisample assert(multisample == (*i)->multisample); } } if (verbose) error_output << "INFO: multisample " << multisample << " found, " << force_multisample_off << std::endl; if (force_multisample_off) multisample = 0; //either we have no multisample //or multisample and no depth texture assert((multisample == 0) || ((multisample > 0) && depth_textures.empty())); //ensure consistent sizes width = -1; height = -1; for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++) { if (width == -1) width = (*i)->sizew; if (height == -1) height = (*i)->sizeh; assert(width == (*i)->sizew); assert(height == (*i)->sizeh); } if (verbose) error_output << "INFO: width " << width << ", height " << height << std::endl; //initialize framebuffer object (FBO) assert(GLEW_ARB_framebuffer_object); glGenFramebuffers(1, &framebuffer_object); if (verbose) error_output << "INFO: generated FBO " << framebuffer_object << std::endl; OPENGL_UTILITY::CheckForOpenGLErrors("FBO generation", error_output); //bind the framebuffer glstate.BindFramebuffer(framebuffer_object); OPENGL_UTILITY::CheckForOpenGLErrors("FBO binding", error_output); //initialize renderbuffer object that's used for our depth buffer if we're not using //a depth texture if (depth_textures.empty()) { glGenRenderbuffers(1, &renderbuffer_depth); glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_depth); if (verbose) error_output << "INFO: generating depth renderbuffer" << std::endl; OPENGL_UTILITY::CheckForOpenGLErrors("FBO renderbuffer generation", error_output); if (multisample > 0) { // need a separate multisample depth buffer glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, GL_DEPTH_COMPONENT, width, height); if (verbose) error_output << "INFO: using multisampling for depth renderbuffer" << std::endl; } else glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); OPENGL_UTILITY::CheckForOpenGLErrors("FBO renderbuffer initialization", error_output); //attach the render buffer to the FBO glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer_depth); if (verbose) error_output << "INFO: depth renderbuffer attached to FBO" << std::endl; OPENGL_UTILITY::CheckForOpenGLErrors("FBO renderbuffer attachment", error_output); } GLenum buffers[4] = {GL_NONE, GL_NONE, GL_NONE, GL_NONE}; { int count = 0; for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++,count++) { buffers[count] = GL_COLOR_ATTACHMENT0+count; } } glDrawBuffers(4, buffers); glReadBuffer(buffers[0]); if (verbose) error_output << "INFO: set draw buffers: " << buffers[0] << ", " << buffers[1] << ", " << buffers[2] << ", " << buffers[3] << std::endl; if (verbose) error_output << "INFO: set read buffer: " << buffers[0] << std::endl; OPENGL_UTILITY::CheckForOpenGLErrors("FBO buffer mask set", error_output); //add separate multisample color buffers for each color texture if (multisample > 0) { int count = 0; for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++,count++) { // need a separate multisample color buffer glGenRenderbuffers(1, &(*i)->renderbuffer_multisample); glBindRenderbuffer(GL_RENDERBUFFER, (*i)->renderbuffer_multisample); glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, (*i)->texture_format, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+count, GL_RENDERBUFFER, (*i)->renderbuffer_multisample); if (verbose) error_output << "INFO: generating separate multisample color buffer " << count << std::endl; OPENGL_UTILITY::CheckForOpenGLErrors("FBO multisample color renderbuffer", error_output); } } //attach any color textures to the FBO { int count = 0; for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++,count++) { int texture_attachment = GL_COLOR_ATTACHMENT0+count; if (multisample == 0) { if ((*i)->texture_target == FBTEXTURE::CUBEMAP) { // if we're using a cubemap, arbitrarily pick one of the faces to activate so we can check that the FBO is complete glFramebufferTexture2D(GL_FRAMEBUFFER, texture_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X, (*i)->fbtexture, 0); if (verbose) error_output << "INFO: attaching arbitrary cubemap face to color attachment " << count << std::endl; } else { glFramebufferTexture2D(GL_FRAMEBUFFER, texture_attachment, (*i)->texture_target, (*i)->fbtexture, 0); if (verbose) error_output << "INFO: attaching texture to color attachment " << count << std::endl; } (*i)->texture_attachment = texture_attachment; } } } //attach the depth texture to the FBO, if there is one { int count = 0; for (std::vector <FBTEXTURE*>::iterator i = depth_textures.begin(); i != depth_textures.end(); i++,count++) { if (multisample == 0) { if ((*i)->texture_target == FBTEXTURE::CUBEMAP) { // if we're using a cubemap, arbitrarily pick one of the faces to activate so we can check that the FBO is complete glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, (*i)->fbtexture, 0); if (verbose) error_output << "INFO: attaching cubemap depth texture" << std::endl; } else { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, (*i)->texture_target, (*i)->fbtexture, 0); if (verbose) error_output << "INFO: attaching depth texture" << std::endl; } } } } OPENGL_UTILITY::CheckForOpenGLErrors("FBO attachment", error_output); bool status_ok = CheckStatus(error_output); if (!status_ok) { error_output << "Error initializing FBO:" << std::endl; int count = 0; for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++) { error_output << "\t" << count << ". " << TargetToString((*i)->texture_target) << ": " << FormatToString((*i)->texture_format) << std::endl; count++; } } assert(status_ok); glstate.BindFramebuffer(0); OPENGL_UTILITY::CheckForOpenGLErrors("FBO unbinding", error_output); // if multisampling is on, create another framebuffer object for the single sample version of these textures if (multisample > 0) { if (verbose) error_output << "INFO: creating secondary single sample framebuffer object" << std::endl; assert(multisample_dest_singlesample_framebuffer_object.empty()); multisample_dest_singlesample_framebuffer_object.push_back(FBOBJECT()); multisample_dest_singlesample_framebuffer_object.back().Init(glstate, newtextures, error_output, true); } }
int main() { // glfw: initialize and configure // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X // glfw window creation // -------------------- GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); // tell GLFW to capture our mouse glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // glad: load all OpenGL function pointers // --------------------------------------- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } // configure global opengl state // ----------------------------- glEnable(GL_DEPTH_TEST); // build and compile shaders // ------------------------- Shader shader("6.lighting.vs", "6.lighting.fs"); Shader hdrShader("6.hdr.vs", "6.hdr.fs"); // load textures // ------------- unsigned int woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str(), true); // note that we're loading the texture as an SRGB texture // configure floating point framebuffer // ------------------------------------ unsigned int hdrFBO; glGenFramebuffers(1, &hdrFBO); // create floating point color buffer unsigned int colorBuffer; glGenTextures(1, &colorBuffer); glBindTexture(GL_TEXTURE_2D, colorBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // create depth buffer (renderbuffer) unsigned int rboDepth; glGenRenderbuffers(1, &rboDepth); glBindRenderbuffer(GL_RENDERBUFFER, rboDepth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); // attach buffers glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "Framebuffer not complete!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); // lighting info // ------------- // positions std::vector<glm::vec3> lightPositions; lightPositions.push_back(glm::vec3( 0.0f, 0.0f, 49.5f)); // back light lightPositions.push_back(glm::vec3(-1.4f, -1.9f, 9.0f)); lightPositions.push_back(glm::vec3( 0.0f, -1.8f, 4.0f)); lightPositions.push_back(glm::vec3( 0.8f, -1.7f, 6.0f)); // colors std::vector<glm::vec3> lightColors; lightColors.push_back(glm::vec3(200.0f, 200.0f, 200.0f)); lightColors.push_back(glm::vec3(0.1f, 0.0f, 0.0f)); lightColors.push_back(glm::vec3(0.0f, 0.0f, 0.2f)); lightColors.push_back(glm::vec3(0.0f, 0.1f, 0.0f)); // shader configuration // -------------------- shader.use(); shader.setInt("diffuseTexture", 0); hdrShader.use(); hdrShader.setInt("hdrBuffer", 0); // render loop // ----------- while (!glfwWindowShouldClose(window)) { // per-frame time logic // -------------------- float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // input // ----- processInput(window); // render // ------ glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 1. render scene into floating point framebuffer // ----------------------------------------------- glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)SCR_WIDTH / (GLfloat)SCR_HEIGHT, 0.1f, 100.0f); glm::mat4 view = camera.GetViewMatrix(); shader.use(); shader.setMat4("projection", projection); shader.setMat4("view", view); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, woodTexture); // set lighting uniforms for (unsigned int i = 0; i < lightPositions.size(); i++) { shader.setVec3("lights[" + std::to_string(i) + "].Position", lightPositions[i]); shader.setVec3("lights[" + std::to_string(i) + "].Color", lightColors[i]); } shader.setVec3("viewPos", camera.Position); // render tunnel glm::mat4 model = glm::mat4(); model = glm::translate(model, glm::vec3(0.0f, 0.0f, 25.0)); model = glm::scale(model, glm::vec3(2.5f, 2.5f, 27.5f)); shader.setMat4("model", model); shader.setInt("inverse_normals", true); renderCube(); glBindFramebuffer(GL_FRAMEBUFFER, 0); // 2. now render floating point color buffer to 2D quad and tonemap HDR colors to default framebuffer's (clamped) color range // -------------------------------------------------------------------------------------------------------------------------- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); hdrShader.use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, colorBuffer); hdrShader.setInt("hdr", hdr); hdrShader.setFloat("exposure", exposure); renderQuad(); std::cout << "hdr: " << (hdr ? "on" : "off") << "| exposure: " << exposure << std::endl; // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) // ------------------------------------------------------------------------------- glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); return 0; }
static enum piglit_result run_multisample_test(struct texture_format *src_format, struct texture_format *dst_format) { bool pass = true; int fbo_width, fbo_height; GLuint fbo, rb, src_tex, dst_tex, res_tex; static const GLfloat verts[] = { 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0 }; /* Upload the source, destination, and expected result */ src_tex = piglit_multisample_texture(GL_TEXTURE_2D_MULTISAMPLE, 0, src_format->internal_format, TEX_SIZE, TEX_SIZE, 1, samples, src_format->format, src_format->data_type, src_data); dst_tex = piglit_multisample_texture(GL_TEXTURE_2D_MULTISAMPLE, 0, dst_format->internal_format, TEX_SIZE, TEX_SIZE, 1, samples, dst_format->format, dst_format->data_type, dst_data); res_tex = piglit_multisample_texture(GL_TEXTURE_2D_MULTISAMPLE, 0, dst_format->internal_format, TEX_SIZE, TEX_SIZE, 1, samples, dst_format->format, dst_format->data_type, res_data); pass &= piglit_check_gl_error(GL_NO_ERROR); /* If any of these are zero, but there was no error, then it must * not be renderable, so we just skip without even reporting the * subtest. */ if ((src_tex == 0 || dst_tex == 0 || res_tex == 0) && pass) return PIGLIT_SKIP; glCopyImageSubData(src_tex, GL_TEXTURE_2D_MULTISAMPLE, 0, TEX_SIZE / 4, TEX_SIZE / 4, 0, dst_tex, GL_TEXTURE_2D_MULTISAMPLE, 0, TEX_SIZE / 4, TEX_SIZE / 4, 0, TEX_SIZE / 2, TEX_SIZE / 2, 1); pass &= piglit_check_gl_error(GL_NO_ERROR); glCopyImageSubData(dst_tex, GL_TEXTURE_2D_MULTISAMPLE, 0, 0, TEX_SIZE / 2, 0, dst_tex, GL_TEXTURE_2D_MULTISAMPLE, 0, TEX_SIZE / 2, 0, 0, TEX_SIZE / 2, TEX_SIZE / 2, 1); pass &= piglit_check_gl_error(GL_NO_ERROR); if (piglit_automatic) { fbo_width = TEX_SIZE; fbo_height = TEX_SIZE; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glGenRenderbuffers(1, &rb); glBindRenderbuffer(GL_RENDERBUFFER, rb); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, fbo_width, fbo_height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb); } else { fbo_width = piglit_width; fbo_height = piglit_height; glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo); } pass &= piglit_check_gl_error(GL_NO_ERROR); glViewport(0, 0, fbo_width, fbo_height); glClearColor(1.0f, 0.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); /* Now we use a comparison shader to check to see if the * destination matches the expected result. */ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, dst_tex); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, res_tex); load_compare_program(dst_format); pass &= piglit_check_gl_error(GL_NO_ERROR); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts); glDrawArrays(GL_TRIANGLES, 0, 6); glDisableVertexAttribArray(0); pass &= piglit_check_gl_error(GL_NO_ERROR); /* If the destination texture matches the expected result, we * should get green. If not, we get red and this test fails. */ pass &= piglit_probe_rect_rgb(0, 0, fbo_width, fbo_height, green); glDeleteTextures(1, &src_tex); glDeleteTextures(1, &dst_tex); glDeleteTextures(1, &res_tex); if (!piglit_automatic) piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
void renderer_cool::draw(int vertex_count) { static bool initial_resize = false; if (!initial_resize) { if (enabler->fullscreen) resize(size_x, size_y); else resize((size_x/init->font.small_font_dispx)*init->font.small_font_dispx, (size_y/init->font.small_font_dispy)*init->font.small_font_dispy); //resize(gps->dimx*init->font.small_font_dispx, gps->dimy*init->font.small_font_dispy); reshape_gl(); initial_resize = true; } static df::viewscreen *prevws = NULL; df::viewscreen *ws = Gui::getCurViewscreen(); is_main_scr = df::viewscreen_dwarfmodest::_identity.is_direct_instance(ws) || df::viewscreen_dungeonmodest::_identity.is_direct_instance(ws); if (ws != prevws) { gps->force_full_display_count = 1; prevws = ws; /*if (is_main_scr) { for (int x = 1; x < gps->dimx-gmenu_w-1; x++) { for (int y = 1; y < gps->dimy-1; y++) { const int tile1 = x * gps->dimy + y; for (int i = 0; i < 6; i++) *(fg + tile * 4 * i + 3) = 0; } } }*/ } display_new(is_main_scr); #ifdef WIN32 // We can't do this in plugin_init() because OpenGL context isn't initialized by that time static bool glew_init = false; if (!glew_init) { GLenum err = glewInit(); if (err != GLEW_OK) *out2 << glewGetErrorString(err); glew_init = true; } #endif static int old_dimx, old_dimy, old_winx, old_winy; if (domapshot) { if (domapshot == 10) { old_dimx = gps->dimx; old_dimy = gps->dimy; old_winx = *df::global::window_x; old_winy = *df::global::window_y; grid_resize(world->map.x_count + 36, world->map.y_count + 2); *df::global::window_x = 0; *df::global::window_y = 0; gps->force_full_display_count = 1; } domapshot--; } GLuint framebuffer, renderbuffer; GLenum status; if (domapshot == 5) { // Set the width and height appropriately for your image GLuint imageWidth = gps->dimx * dispx, imageHeight = gps->dimy * dispy; //Set up a FBO with one renderbuffer attachment glGenFramebuffers(1, &framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); glGenRenderbuffers(1, &renderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, imageWidth, imageHeight); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); glViewport(0, 0, gps->dimx * dispx, gps->dimy * dispy); /*glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,gps->dimx,gps->dimy,0,-1,1);*/ } if (is_main_scr) { bool skip = false; if (df::viewscreen_dungeonmodest::_identity.is_direct_instance(ws)) { int m = df::global::ui_advmode->menu; bool tmode = advmode_needs_map(m); skip = !tmode; } if (!skip) { ///// glViewport(goff_x, goff_y_gl, gdimx * gdispx, gdimy * gdispy); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, gdimx, gdimy, 0, -1, 1); //glTranslatef(1,-1,0); //glScissor(off_x+(float)size_x/gps->dimx, off_y+(float)size_y/gps->dimy, gsize_x, gsize_y); //glEnable(GL_SCISSOR_TEST); //glClearColor(1,0,0,1); //glClear(GL_COLOR_BUFFER_BIT); if (multi_rendered && fogdensity > 0) { glEnable(GL_FOG); glFogfv(GL_FOG_COLOR, fogcolor); glFogf(GL_FOG_DENSITY, fogdensity); glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD); glEnableClientState(GL_FOG_COORD_ARRAY); glFogCoordPointer(GL_FLOAT, 0, fogcoord); } glVertexPointer(2, GL_FLOAT, 0, gvertexes); // Render background colors glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_BLEND); glColorPointer(4, GL_FLOAT, 0, gbg); glDrawArrays(GL_TRIANGLES, 0, gdimx * gdimy * 6); // Render foreground glEnable(GL_TEXTURE_2D); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexCoordPointer(2, GL_FLOAT, 0, gtex); glColorPointer(4, GL_FLOAT, 0, gfg); glDrawArrays(GL_TRIANGLES, 0, gdimx * gdimy * 6); if (multi_rendered) { glDisableClientState(GL_FOG_COORD_ARRAY); glDisable(GL_FOG); } // Prepare and render shadows if (multi_rendered) { int elemcnt = 0; //TODO: don't do this if view not moved and tiles with shadows not changed { gl_texpos *txt = (gl_texpos *) enabler->textures.gl_texpos; int x1 = std::min(gdimx, world->map.x_count-gwindow_x); int y1 = std::min(gdimy, world->map.y_count-gwindow_y); for (int tile = 0; tile < gdimx * gdimy; tile++) { int xx = tile / gdimy; int yy = tile % gdimy; int d = depth[tile]; if (d && d != 0x7f) //TODO: no need for the second check in fort mode { GLfloat *tex = shadowtex + elemcnt * 2; bool top = false, left = false, btm = false, right = false; if (xx > 0 && (depth[((xx - 1)*gdimy + yy)]) < d) { memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float)); SETTEX(shadow_texpos[0]); elemcnt += 6; left = true; } if (yy < y1 - 1 && (depth[((xx)*gdimy + yy + 1)]) < d) { memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float)); SETTEX(shadow_texpos[1]); elemcnt += 6; btm = true; } if (yy > 0 && (depth[((xx)*gdimy + yy - 1)]) < d) { memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float)); SETTEX(shadow_texpos[2]); elemcnt += 6; top = true; } if (xx < x1-1 && (depth[((xx + 1)*gdimy + yy)]) < d) { memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float)); SETTEX(shadow_texpos[3]); elemcnt += 6; right = true; } if (!right && !btm && xx < x1 - 1 && yy < y1 - 1 && (depth[((xx + 1)*gdimy + yy + 1)]) < d) { memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float)); SETTEX(shadow_texpos[4]); elemcnt += 6; } if (!left && !btm && xx > 0 && yy < y1 - 1 && (depth[((xx - 1)*gdimy + yy + 1)]) < d) { memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float)); SETTEX(shadow_texpos[5]); elemcnt += 6; } if (!left && !top && xx > 0 && yy > 0 && (depth[((xx - 1)*gdimy + yy - 1)]) < d) { memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float)); SETTEX(shadow_texpos[6]); elemcnt += 6; } if (!top && !right && xx < x1 - 1 && yy > 0 && (depth[((xx + 1)*gdimy + yy - 1)]) < d) { memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float)); SETTEX(shadow_texpos[7]); elemcnt += 6; } } } } if (elemcnt) { glDisableClientState(GL_COLOR_ARRAY); glColor4fv(shadowcolor); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glTexCoordPointer(2, GL_FLOAT, 0, shadowtex); glVertexPointer(2, GL_FLOAT, 0, shadowvert); glDrawArrays(GL_TRIANGLES, 0, elemcnt); glEnableClientState(GL_COLOR_ARRAY); } } glDisable(GL_SCISSOR_TEST); glViewport(off_x, off_y, size_x, size_y); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, tdimx, tdimy, 0, -1, 1); } } { glVertexPointer(2, GL_FLOAT, 0, vertexes); // Render background colors glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_BLEND); glColorPointer(4, GL_FLOAT, 0, bg); glDrawArrays(GL_TRIANGLES, 0, tdimx*tdimy*6); // Render foreground glEnable(GL_TEXTURE_2D); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexCoordPointer(2, GL_FLOAT, 0, tex); glColorPointer(4, GL_FLOAT, 0, fg); glDrawArrays(GL_TRIANGLES, 0, tdimx*tdimy*6); } if (domapshot == 1) { int w = world->map.x_count * dispx; int h = world->map.y_count * dispy; unsigned char *data = (unsigned char *) malloc(w * h * 3); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, 0); glReadPixels(dispx, dispy, w, h, GL_BGR, GL_UNSIGNED_BYTE, data); #pragma pack(push,1) typedef struct _TgaHeader { unsigned char IDLength; /* 00h Size of Image ID field */ unsigned char ColorMapType; /* 01h Color map type */ unsigned char ImageType; /* 02h Image type code */ unsigned short CMapStart; /* 03h Color map origin */ unsigned short CMapLength; /* 05h Color map length */ unsigned char CMapDepth; /* 07h Depth of color map entries */ unsigned short XOffset; /* 08h X origin of image */ unsigned short YOffset; /* 0Ah Y origin of image */ unsigned short Width; /* 0Ch Width of image */ unsigned short Height; /* 0Eh Height of image */ unsigned char PixelDepth; /* 10h Image pixel size */ unsigned char ImageDescriptor; /* 11h Image descriptor byte */ } TGAHEAD; #pragma pop TGAHEAD hdr; memset(&hdr, 0, sizeof(hdr)); hdr.ImageType = 2; hdr.Width = w; hdr.Height = h; hdr.PixelDepth = 24; *out2 << w << " " << h << std::endl; std::ofstream img("mapshot.tga", std::ofstream::binary); img.write((const char *)&hdr, sizeof(hdr)); /* for (int j = 0; j<w*h*3; j++) { unsigned char c = data[j+0]; data[0] = data[j+2]; data[j+2] = c; }*/ img.write((const char *)data, w * h * 3); glBindFramebuffer(GL_FRAMEBUFFER, 0); // Delete the renderbuffer attachment glDeleteRenderbuffers(1, &renderbuffer); grid_resize(old_dimx, old_dimy); *df::global::window_x = old_winx; *df::global::window_y = old_winy; gps->force_full_display_count = 1; domapshot = 0; } }
void setup(){ // ------------- object object1 = new GLObject( ); object1->draw_mode = GL_TRIANGLE_STRIP; object1->nVert = 4; object1->buffs[0].setup(0,2,GL_FALSE,&vertexes[0][0],'v'); // vertexes object1->init(); // ------------- shader for rendering geometry shader_pre=new Shader(); //shader_pre->init( "shaders/afine2D_vert.c", "shaders/sphere_frag.c" ); shader_pre->init( "shaders/afine2D_vert.c", "shaders/sphereHoled_frag.c" ); //randf( -1.0, 1.0 ); for( int i=0; i<nspheres; i++ ){ int ii = i << 2; spheres[ii+0] = randf( -1.0, 1.0 ); spheres[ii+1] = randf( -1.0, 1.0 ); spheres[ii+2] = randf( -1.0, 1.0 ); //spheres[ii+0] = i*0.1-1.0; //spheres[ii+1] = i*0.1-1.0; //spheres[ii+2] = +i*5 + 0.0; spheres[ii+3] = 0.5; } randf( -0.5, 0.5 ); for( int i=0; i<nholes; i++ ){ int ii = i << 2; holes[ii+0] = randf( -0.5, 0.5 ); holes[ii+1] = randf( -0.5, 0.5 ); holes[ii+2] = randf( -0.5, 0.5 ); holes[ii+3] = 0.3; } Vec3f light_dir_; light_dir_.set( -1, -1, 2 ); light_dir_.normalize(); light_dir[0]=light_dir_.x; light_dir[1]=light_dir_.y; light_dir[2]=light_dir_.z; resolution[0] = (float)WIDTH; resolution[1] = (float)HEIGHT; glUseProgram(shader_pre->shaderprogram); GLuint uloc; uloc = glGetUniformLocation( shader_pre->shaderprogram, "resolution" ); glUniform2fv(uloc, 1, resolution ); uloc = glGetUniformLocation( shader_pre->shaderprogram, "camPos" ); glUniform3fv(uloc, 1, camPos ); uloc = glGetUniformLocation( shader_pre->shaderprogram, "camMat" ); glUniformMatrix3fv( uloc, 1, false, camMat ); uloc = glGetUniformLocation( shader_pre->shaderprogram, "sphere" ); glUniform4fv(uloc, 1, sphere ); uloc = glGetUniformLocation( shader_pre->shaderprogram, "light_dir" ); glUniform3fv(uloc, 1, light_dir ); uloc = glGetUniformLocation( shader_pre->shaderprogram, "afineMat" ); glUniformMatrix2fv(uloc, 1, GL_FALSE, afineMat ); uloc = glGetUniformLocation( shader_pre->shaderprogram, "origin" ); glUniform2fv (uloc, 1, origin ); // ------------- shader for blitting from texture shader_post=new Shader(); shader_post->init( "shaders/plain_vert.c", "shaders/SSAO_frag.c" ); resolution[0] = (float)WIDTH; resolution[1] = (float)HEIGHT; glUseProgram(shader_post->shaderprogram); uloc = glGetUniformLocation( shader_post->shaderprogram, "resolution" ); glUniform2fv(uloc, 1, resolution ); // ------------- texture glGenTextures(1, &texRGB ); glBindTexture(GL_TEXTURE_2D, texRGB ); glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glGenTextures(1, &texZ); glBindTexture(GL_TEXTURE_2D, texZ); glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT, WIDTH, HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // ------------- frameBuffer glGenFramebuffers(1, &FramebufferName); glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); // The depth buffer glGenRenderbuffers(1, &depthrenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, WIDTH, HEIGHT ); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer); // Set "renderedTexture" as our colour attachement #0 glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texZ, 0 ); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texRGB, 0 ); GLenum DrawBuffers[2] = {GL_DEPTH_ATTACHMENT, GL_COLOR_ATTACHMENT0}; glDrawBuffers(2, DrawBuffers); /* glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texZ, 0 ); GLenum DrawBuffers[1] = {GL_DEPTH_ATTACHMENT}; glDrawBuffers(1, DrawBuffers); */ if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){ printf(" problem in FBO ! \n "); checkFramebufferStatus(); } }
void Renderbuffer::storage(unsigned int format, Vec2i size) { bind(); glRenderbufferStorage(GL_RENDERBUFFER, format, size.x, size.y); }
void setStorage(GLenum internalformat, int width, int height) { glRenderbufferStorage(GL_RENDERBUFFER,internalformat,width,height); }
void CoinRiftWidget::initializeGL() { makeCurrent(); // Infer hardware capabilites. #ifdef USE_FRAMEBUFFER OVR::CAPI::GL::InitGLExtensions(); if (OVR::CAPI::GL::glBindFramebuffer == NULL) { qDebug() << "No GL extensions found."; exit(4); } // Store old framebuffer. GLint oldfb; glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb); #endif // Create rendering target textures. glEnable(GL_TEXTURE_2D); for (int eye = 0; eye < 2; eye++) { #ifdef USE_FRAMEBUFFER OVR::CAPI::GL::glGenFramebuffers(1, &frameBufferID[eye]); OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); // Create the render buffer. // TODO: need to check for OpenGl 3 or higher and load the functions JR 2014 /*OVR::CAPI::GL::*/glGenRenderbuffers(1, &depthBufferID[eye]); /*OVR::CAPI::GL::*/glBindRenderbuffer(GL_RENDERBUFFER_EXT, depthBufferID[eye]); /*OVR::CAPI::GL::*/glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, eyeTexture[eye].Header.TextureSize.w, eyeTexture[eye].Header.TextureSize.h); // Attach renderbuffer to framebuffer. OVR::CAPI::GL::glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBufferID[eye]); #endif ovrGLTextureData *texData = reinterpret_cast<ovrGLTextureData*>(&eyeTexture[eye]); texData->Header.API = ovrRenderAPI_OpenGL; texData->Header.TextureSize = eyeTexture[eye].Header.TextureSize; texData->Header.RenderViewport = eyeTexture[eye].Header.RenderViewport; glGenTextures(1, &texData->TexId); glBindTexture(GL_TEXTURE_2D, texData->TexId); Q_ASSERT(!glGetError()); // Allocate storage for the texture. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, eyeTexture[eye].Header.TextureSize.w, eyeTexture[eye].Header.TextureSize.h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); Q_ASSERT(!glGetError()); #ifdef USE_FRAMEBUFFER // Attach texture to framebuffer color object. OVR::CAPI::GL::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texData->TexId, 0); if (OVR::CAPI::GL::glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) qDebug() << "ERROR: FrameBuffer is not operational!"; #endif } glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); #ifdef USE_FRAMEBUFFER // Continue rendering to the orgiginal frame buffer (likely 0, the onscreen buffer). OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, oldfb); #endif doneCurrent(); }
RenderBuffer::RenderBuffer(RenderBufferFormat type, int width, int height, int samples) : Object("RenderBuffer") { int format = 0; switch (type) { case R8: format = GL_R8; break; case R8_SNORM: format = GL_R8_SNORM; break; case R16: format = GL_R16; break; case R16_SNORM: format = GL_R16_SNORM; break; case RG8: format = GL_RG8; break; case RG8_SNORM: format = GL_RG8_SNORM; break; case RG16: format = GL_RG16; break; case RG16_SNORM: format = GL_RG16_SNORM; break; case R3_G3_B2: format = GL_R3_G3_B2; break; case RGB4: format = GL_RGB4; break; case RGB5: format = GL_RGB5; break; case RGB8: format = GL_RGB8; break; case RGB8_SNORM: format = GL_RGB8_SNORM; break; case RGB10: format = GL_RGB10; break; case RGB12: format = GL_RGB12; break; case RGB16: format = GL_RGB16; break; case RGB16_SNORM: format = GL_RGB16_SNORM; break; case RGBA2: format = GL_RGBA2; break; case RGBA4: format = GL_RGBA4; break; case RGB5_A1: format = GL_RGB5_A1; break; case RGBA8: format = GL_RGBA8; break; case RGBA8_SNORM: format = GL_RGBA8_SNORM; break; case RGB10_A2: format = GL_RGB10_A2; break; case RGB10_A2UI: format = GL_RGB10_A2UI; break; case RGBA12: format = GL_RGBA12; break; case RGBA16: format = GL_RGBA16; break; case RGBA16_SNORM: format = GL_RGBA16_SNORM; break; case SRGB8: format = GL_SRGB8; break; case SRGB8_ALPHA8: format = GL_SRGB8_ALPHA8; break; case R16F: format = GL_R16F; break; case RG16F: format = GL_RG16F; break; case RGB16F: format = GL_RGB16F; break; case RGBA16F: format = GL_RGBA16F; break; case R32F: format = GL_R32F; break; case RG32F: format = GL_RG32F; break; case RGB32F: format = GL_RGB32F; break; case RGBA32F: format = GL_RGBA32F; break; case R11F_G11F_B10F: format = GL_R11F_G11F_B10F; break; case RGB9_E5: format = GL_RGB9_E5; break; case R8I: format = GL_R8I; break; case R8UI: format = GL_R8UI; break; case R16I: format = GL_R16I; break; case R16UI: format = GL_R16UI; break; case R32I: format = GL_R32I; break; case R32UI: format = GL_R32UI; break; case RG8I: format = GL_RG8I; break; case RG8UI: format = GL_RG8UI; break; case RG16I: format = GL_RG16I; break; case RG16UI: format = GL_RG16UI; break; case RG32I: format = GL_RG32I; break; case RG32UI: format = GL_RG32UI; break; case RGB8I: format = GL_RGB8I; break; case RGB8UI: format = GL_RGB8UI; break; case RGB16I: format = GL_RGB16I; break; case RGB16UI: format = GL_RGB16UI; break; case RGB32I: format = GL_RGB32I; break; case RGB32UI: format = GL_RGB32UI; break; case RGBA8I: format = GL_RGBA8I; break; case RGBA8UI: format = GL_RGBA8UI; break; case RGBA16I: format = GL_RGBA16I; break; case RGBA16UI: format = GL_RGBA16UI; break; case RGBA32I: format = GL_RGBA32I; break; case RGBA32UI: format = GL_RGBA32UI; break; case DEPTH_COMPONENT: format = GL_DEPTH_COMPONENT; break; case DEPTH_COMPONENT16: format = GL_DEPTH_COMPONENT16; break; case DEPTH_COMPONENT24: format = GL_DEPTH_COMPONENT24; break; case DEPTH_COMPONENT32: format = GL_DEPTH_COMPONENT32; break; case DEPTH_COMPONENT32F: format = GL_DEPTH_COMPONENT32F; break; case DEPTH24_STENCIL8: format = GL_DEPTH24_STENCIL8; break; case DEPTH32F_STENCIL8: format = GL_DEPTH32F_STENCIL8; break; case STENCIL_INDEX: format = GL_STENCIL_INDEX; break; case STENCIL_INDEX1: format = GL_STENCIL_INDEX1; break; case STENCIL_INDEX4: format = GL_STENCIL_INDEX4; break; case STENCIL_INDEX8: format = GL_STENCIL_INDEX8; break; case STENCIL_INDEX16: format = GL_STENCIL_INDEX16; break; default: assert(false); // unsupported format break; } glGenRenderbuffers(1, &bufferId); glBindRenderbuffer(GL_RENDERBUFFER, bufferId); if (samples == 0) { glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); } else { glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height); } assert(FrameBuffer::getError() == GL_NO_ERROR); }
void Texture::CameraToTex(Camera* cam, int frame){ GLenum target; Global::camera_in_use=cam; if(flags&128){ target=GL_TEXTURE_CUBE_MAP; }else{ target=GL_TEXTURE_2D; } glBindTexture (target, texture); if (framebuffer==0){ framebuffer=new unsigned int[1]; glGenFramebuffers(1, &framebuffer[0]); glGenRenderbuffers(1, &framebuffer[1]); if(flags&128){ for (int i=0;i<6;i++){ switch(i){ case 0: glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); break; case 1: glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); break; case 2: glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); break; case 3: glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); break; case 4: glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); break; case 5: glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); break; } } }else{ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); } } glBindFramebuffer(GL_FRAMEBUFFER, framebuffer[0]); if(flags&128){ switch (cube_face){ case 0: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, texture, 0); break; case 1: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, texture, 0); break; case 2: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texture, 0); break; case 3: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, texture, 0); break; case 4: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, texture, 0); break; case 5: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, texture, 0); break; } }else{ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); } //Depth buffer glBindRenderbuffer(GL_RENDERBUFFER, framebuffer[1]); glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height); glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, framebuffer[1]); glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, framebuffer[1]); cam->Render(); if (Global::Shadows_enabled==true) ShadowObject::Update(cam); //glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); glBindTexture (target, texture);// glGenerateMipmap(target); glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0); }
void gl4::FBO::init(GLuint width, GLuint height, GLuint samples, GLuint textures) { _textures = textures; _fboTextureId = new GLuint[textures]; GLuint *_rboId = new GLuint[textures]; GLuint _dboId = -1; GLuint *_rboId_multisampled = new GLuint[textures]; GLuint _dboId_multisampled = -1; _w = width; _h = height; GLenum errorID; GLenum status; std::cout << "FBO: Initialize with size " << width << ", " << height << std::endl; std::cout << " Textures = " << textures << std::endl; GLint MaxSamples; glGetIntegerv(GL_MAX_SAMPLES, &MaxSamples); std::cout << " MaxSamples = " << MaxSamples << std::endl; if (samples < 0) { samples = 0; } if (samples > MaxSamples) { samples = MaxSamples; } if ( samples > 0 && samples <= MaxSamples) { _multisampled = true; std::cout << " Samples = " << samples << std::endl; } glGenFramebuffers(1, &_fboId); glGenTextures(textures, _fboTextureId); glGenRenderbuffers(textures, _rboId); glGenRenderbuffers(1, &_dboId); glBindFramebuffer(GL_FRAMEBUFFER, _fboId); _buffers = new GLenum[_textures]; for (int i = 0; i < textures; ++i) { _buffers[i] = GL_COLOR_ATTACHMENT0+i; glBindRenderbuffer(GL_RENDERBUFFER, _rboId[i]); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, _rboId[i]); } glBindFramebuffer(GL_FRAMEBUFFER, _fboId); glBindRenderbuffer(GL_RENDERBUFFER, _dboId); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER, _dboId); for (int i = 0; i < textures; ++i) { glBindTexture(GL_TEXTURE_2D, _fboTextureId[i]); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_2D, _fboTextureId[i], 0); glBindTexture(GL_TEXTURE_2D, 0); } // check FBO status status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(status != GL_FRAMEBUFFER_COMPLETE) std::cout << " " << "Error creating FBO: " << status << std::endl; else std::cout << " " << "FBO created successfully [" << _fboId << "]" << std::endl; // switch back to window-system-provided framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); if (_multisampled) { glGenFramebuffers(1, &_fboId_multisampled); glGenRenderbuffers(textures, _rboId_multisampled); glGenRenderbuffers(1, &_dboId_multisampled); glBindFramebuffer(GL_FRAMEBUFFER, _fboId_multisampled); for (int i = 0; i < textures; ++i) { glBindRenderbuffer(GL_RENDERBUFFER, _rboId_multisampled[i]); glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, _rboId_multisampled[i]); } glBindFramebuffer(GL_FRAMEBUFFER, _fboId_multisampled); glBindRenderbuffer(GL_RENDERBUFFER, _dboId_multisampled); glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT32, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER, _dboId_multisampled); // check FBO status status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(status != GL_FRAMEBUFFER_COMPLETE) std::cout << " " << "Error creating FBO: " << status << std::endl; else std::cout << " " << "Multisampled FBO created successfully [" << _fboId_multisampled << "]" << std::endl; // switch back to window-system-provided framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); } }
bool RenderTexture::initWithWidthAndHeight(int w, int h, Texture2D::PixelFormat format, GLuint depthStencilFormat) { CCASSERT(format != Texture2D::PixelFormat::A8, "only RGB and RGBA formats are valid for a render texture"); bool ret = false; void *data = nullptr; do { _fullRect = _rtTextureRect = Rect(0,0,w,h); //Size size = Director::getInstance()->getWinSizeInPixels(); //_fullviewPort = Rect(0,0,size.width,size.height); w = (int)(w * CC_CONTENT_SCALE_FACTOR()); h = (int)(h * CC_CONTENT_SCALE_FACTOR()); _fullviewPort = Rect(0,0,w,h); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO); // textures must be power of two squared int powW = 0; int powH = 0; if (Configuration::getInstance()->supportsNPOT()) { powW = w; powH = h; } else { powW = ccNextPOT(w); powH = ccNextPOT(h); } auto dataLen = powW * powH * 4; data = malloc(dataLen); CC_BREAK_IF(! data); memset(data, 0, dataLen); _pixelFormat = format; _texture = new (std::nothrow) 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 (std::nothrow) 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 (depthStencilFormat != 0) { //create and attach depth buffer glGenRenderbuffers(1, &_depthRenderBufffer); glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBufffer); glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, (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 (depthStencilFormat == 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->setFlippedY(true); _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); ret = true; } while (0); CC_SAFE_FREE(data); return ret; }