GLUSuint initWaterTexture(GLUSfloat waterPlaneLength) { GLfloat projectionMatrixWaterTexture[16]; GLfloat modelViewMatrixWaterTexture[16]; GLUSshape plane; GLUStextfile vertexSource; GLUStextfile fragmentSource; glusFileLoadText("../Example15/shader/WaterTexture.vert.glsl", &vertexSource); glusFileLoadText("../Example15/shader/WaterTexture.frag.glsl", &fragmentSource); glusProgramBuildFromSource(&g_programWaterTexture, (const GLUSchar**) &vertexSource.text, 0, 0, 0, (const GLUSchar**) &fragmentSource.text); glusFileDestroyText(&vertexSource); glusFileDestroyText(&fragmentSource); // g_projectionMatrixWaterTextureLocation = glGetUniformLocation(g_programWaterTexture.program, "u_projectionMatrix"); g_modelViewMatrixWaterTextureLocation = glGetUniformLocation(g_programWaterTexture.program, "u_modelViewMatrix"); g_waterPlaneLengthWaterTextureLocation = glGetUniformLocation(g_programWaterTexture.program, "u_waterPlaneLength"); g_passedTimeWaterTextureLocation = glGetUniformLocation(g_programWaterTexture.program, "u_passedTime"); g_waveParametersWaterTextureLocation = glGetUniformLocation(g_programWaterTexture.program, "u_waveParameters"); g_waveDirectionsWaterTextureLocation = glGetUniformLocation(g_programWaterTexture.program, "u_waveDirections"); g_vertexWaterTextureLocation = glGetAttribLocation(g_programWaterTexture.program, "a_vertex"); g_texCoordWaterTextureLocation = glGetAttribLocation(g_programWaterTexture.program, "a_texCoord"); // glGenTextures(1, &g_mirrorTexture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, g_mirrorTexture); glTexImage2D(GL_TEXTURE_2D, 0, GLUS_RGB, TEXTURE_SIZE, TEXTURE_SIZE, 0, GLUS_RGB, GL_UNSIGNED_BYTE, 0); 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_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, 0); // glGenRenderbuffers(1, &g_depthMirrorTexture); glBindRenderbuffer(GL_RENDERBUFFER, g_depthMirrorTexture); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, TEXTURE_SIZE, TEXTURE_SIZE); glBindRenderbuffer(GL_RENDERBUFFER, 0); // glGenFramebuffers(1, &g_fboWaterTexture); glBindFramebuffer(GL_FRAMEBUFFER, g_fboWaterTexture); // Attach the color buffer ... glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_mirrorTexture, 0); // ... and the depth buffer, glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, g_depthMirrorTexture); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { printf("GL_FRAMEBUFFER_COMPLETE error 0x%x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); return GLUS_FALSE; } glBindFramebuffer(GL_FRAMEBUFFER, 0); // glBindVertexArray(0); // glusShapeCreatePlanef(&plane, TEXTURE_SIZE / 2.0f); g_numberIndicesWaterTexture = plane.numberIndices; glGenBuffers(1, &g_verticesWaterTextureVBO); glBindBuffer(GL_ARRAY_BUFFER, g_verticesWaterTextureVBO); glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 4 * sizeof(GLfloat), (GLfloat*) plane.vertices, GL_STATIC_DRAW); glGenBuffers(1, &g_texCoordsWaterTextureVBO); glBindBuffer(GL_ARRAY_BUFFER, g_texCoordsWaterTextureVBO); glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 2 * sizeof(GLfloat), (GLfloat*) plane.texCoords, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenBuffers(1, &g_indicesWaterTextureVBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesWaterTextureVBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, plane.numberIndices * sizeof(GLuint), (GLuint*) plane.indices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glusShapeDestroyf(&plane); // glUseProgram(g_programWaterTexture.program); glusMatrix4x4LookAtf(modelViewMatrixWaterTexture, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); glUniformMatrix4fv(g_modelViewMatrixWaterTextureLocation, 1, GL_FALSE, modelViewMatrixWaterTexture); glusMatrix4x4Orthof(projectionMatrixWaterTexture, -(GLfloat) TEXTURE_SIZE / 2, (GLfloat) TEXTURE_SIZE / 2, -(GLfloat) TEXTURE_SIZE / 2, (GLfloat) TEXTURE_SIZE / 2, 1.0f, 100.0f); glUniformMatrix4fv(g_projectionMatrixWaterTextureLocation, 1, GL_FALSE, projectionMatrixWaterTexture); glUniform1f(g_waterPlaneLengthWaterTextureLocation, waterPlaneLength); // glGenVertexArrays(1, &g_vaoWaterTexture); glBindVertexArray(g_vaoWaterTexture); glBindBuffer(GL_ARRAY_BUFFER, g_verticesWaterTextureVBO); glVertexAttribPointer(g_vertexWaterTextureLocation, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_vertexWaterTextureLocation); glBindBuffer(GL_ARRAY_BUFFER, g_texCoordsWaterTextureVBO); glVertexAttribPointer(g_texCoordWaterTextureLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_texCoordWaterTextureLocation); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesWaterTextureVBO); // glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); return g_mirrorTexture; }
OculusManager& OculusManager::getOculusManager() { static OculusManager* oculusManager = NULL; if (oculusManager == NULL) { oculusManager = new OculusManager(); if (!ovr_Initialize()) { fprintf(stderr, "Failed to initialize the Oculus SDK"); } //= *OculusManager::getHmd(); g_Hmd = ovrHmd_Create(0); if (!g_Hmd) { printf("No Oculus Rift device attached, using virtual version...\n"); g_Hmd = ovrHmd_CreateDebug(ovrHmd_DK2); } printf("initialized HMD: %s - %s\n", g_Hmd->Manufacturer, g_Hmd->ProductName); if (!glfwInit()) exit(EXIT_FAILURE); if (l_MultiSampling) glfwWindowHint(GLFW_SAMPLES, 4); else glfwWindowHint(GLFW_SAMPLES, 0); bool l_DirectMode = ((g_Hmd->HmdCaps & ovrHmdCap_ExtendDesktop) == 0); GLFWmonitor* l_Monitor; ovrSizei l_ClientSize; if (l_DirectMode) { printf("Running in \"Direct\" mode...\n"); l_Monitor = NULL; l_ClientSize.w = g_Hmd->Resolution.w / 2; // Something reasonable, smaller, but maintain aspect ratio... l_ClientSize.h = g_Hmd->Resolution.h / 2; // Something reasonable, smaller, but maintain aspect ratio... } else // Extended Desktop mode... { printf("Running in \"Extended Desktop\" mode...\n"); int l_Count; GLFWmonitor** l_Monitors = glfwGetMonitors(&l_Count); switch (l_Count) { case 0: printf("No monitors found, exiting...\n"); exit(EXIT_FAILURE); break; case 1: printf("Two monitors expected, found only one, using primary...\n"); l_Monitor = glfwGetPrimaryMonitor(); break; case 2: printf("Two monitors found, using second monitor...\n"); l_Monitor = l_Monitors[1]; break; default: printf("More than two monitors found, using second monitor...\n"); l_Monitor = l_Monitors[1]; } l_ClientSize.w = g_Hmd->Resolution.w; // 1920 for DK2... l_ClientSize.h = g_Hmd->Resolution.h; // 1080 for DK2... } l_Window = glfwCreateWindow(l_ClientSize.w, l_ClientSize.h, "GLFW Oculus Rift Test", l_Monitor, NULL); if (!l_Window) { glfwTerminate(); exit(EXIT_FAILURE); } #if defined(_WIN32) if (l_DirectMode) { ovrBool l_AttachResult = ovrHmd_AttachToWindow(g_Hmd, glfwGetWin32Window(l_Window), NULL, NULL); if (!l_AttachResult) { printf("Could not attach to window..."); exit(EXIT_FAILURE); } } #endif glfwMakeContextCurrent(l_Window); glewExperimental = GL_TRUE; GLenum l_GlewResult = glewInit(); if (l_GlewResult != GLEW_OK) { printf("glewInit() error.\n"); exit(EXIT_FAILURE); } int l_Major = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MAJOR); int l_Minor = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MINOR); int l_Profile = glfwGetWindowAttrib(l_Window, GLFW_OPENGL_PROFILE); printf("OpenGL: %d.%d ", l_Major, l_Minor); if (l_Major >= 3) // Profiles introduced in OpenGL 3.0... { if (l_Profile == GLFW_OPENGL_COMPAT_PROFILE) printf("GLFW_OPENGL_COMPAT_PROFILE\n"); else printf("GLFW_OPENGL_CORE_PROFILE\n"); } printf("Vendor: %s\n", (char*)glGetString(GL_VENDOR)); printf("Renderer: %s\n", (char*)glGetString(GL_RENDERER)); ovrSizei l_EyeTextureSizes[2]; l_EyeTextureSizes[ovrEye_Left] = ovrHmd_GetFovTextureSize(g_Hmd, ovrEye_Left, g_Hmd->MaxEyeFov[ovrEye_Left], 1.0f); l_EyeTextureSizes[ovrEye_Right] = ovrHmd_GetFovTextureSize(g_Hmd, ovrEye_Right, g_Hmd->MaxEyeFov[ovrEye_Right], 1.0f); // Combine for one texture for both eyes... g_RenderTargetSize.w = l_EyeTextureSizes[ovrEye_Left].w + l_EyeTextureSizes[ovrEye_Right].w; g_RenderTargetSize.h = (l_EyeTextureSizes[ovrEye_Left].h > l_EyeTextureSizes[ovrEye_Right].h ? l_EyeTextureSizes[ovrEye_Left].h : l_EyeTextureSizes[ovrEye_Right].h); // Create the FBO being a single one for both eyes (this is open for debate)... glGenFramebuffers(1, &l_FBOId); glBindFramebuffer(GL_FRAMEBUFFER, l_FBOId); // The texture we're going to render to... glGenTextures(1, &l_TextureId); // "Bind" the newly created texture : all future texture functions will modify this texture... glBindTexture(GL_TEXTURE_2D, l_TextureId); // Give an empty image to OpenGL (the last "0") glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g_RenderTargetSize.w, g_RenderTargetSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // Linear filtering... glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Create Depth Buffer... glGenRenderbuffers(1, &l_DepthBufferId); glBindRenderbuffer(GL_RENDERBUFFER, l_DepthBufferId); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, g_RenderTargetSize.w, g_RenderTargetSize.h); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, l_DepthBufferId); // Set the texture as our colour attachment #0... glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, l_TextureId, 0); // Set the list of draw buffers... GLenum l_GLDrawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; glDrawBuffers(1, l_GLDrawBuffers); // "1" is the size of DrawBuffers // Check if everything is OK... GLenum l_Check = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (l_Check != GL_FRAMEBUFFER_COMPLETE) { printf("There is a problem with the FBO.\n"); exit(EXIT_FAILURE); } // Unbind... glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); // Setup textures for each eye... // Left eye... g_EyeTextures[ovrEye_Left].Header.API = ovrRenderAPI_OpenGL; g_EyeTextures[ovrEye_Left].Header.TextureSize = g_RenderTargetSize; g_EyeTextures[ovrEye_Left].Header.RenderViewport.Pos.x = 0; g_EyeTextures[ovrEye_Left].Header.RenderViewport.Pos.y = 0; g_EyeTextures[ovrEye_Left].Header.RenderViewport.Size = l_EyeTextureSizes[ovrEye_Left]; ((ovrGLTexture&)(g_EyeTextures[ovrEye_Left])).OGL.TexId = l_TextureId; // Right eye (mostly the same as left but with the viewport on the right side of the texture)... g_EyeTextures[ovrEye_Right] = g_EyeTextures[ovrEye_Left]; g_EyeTextures[ovrEye_Right].Header.RenderViewport.Pos.x = (g_RenderTargetSize.w + 1) / 2; g_EyeTextures[ovrEye_Right].Header.RenderViewport.Pos.y = 0; // Oculus Rift eye configurations... g_Cfg.OGL.Header.API = ovrRenderAPI_OpenGL; g_Cfg.OGL.Header.RTSize.w = l_ClientSize.w; g_Cfg.OGL.Header.RTSize.h = l_ClientSize.h; g_Cfg.OGL.Header.Multisample = (l_MultiSampling ? 1 : 0); #if defined(_WIN32) g_Cfg.OGL.Window = glfwGetWin32Window(l_Window); g_Cfg.OGL.DC = GetDC(g_Cfg.OGL.Window); #elif defined(__linux__) l_Cfg.OGL.Win = glfwGetX11Window(l_Window); l_Cfg.OGL.Disp = glfwGetX11Display(); #endif // Enable capabilities... // ovrHmd_SetEnabledCaps(g_Hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); ovrBool l_ConfigureResult = ovrHmd_ConfigureRendering(g_Hmd, &g_Cfg.Config, g_DistortionCaps, g_Hmd->MaxEyeFov, g_EyeRenderDesc); glUseProgram(0); // Avoid OpenGL state leak in ovrHmd_ConfigureRendering... if (!l_ConfigureResult) { printf("Configure failed.\n"); exit(EXIT_FAILURE); } // Start the sensor which provides the Rift’s pose and motion... uint32_t l_SupportedSensorCaps = ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position; uint32_t l_RequiredTrackingCaps = 0; ovrBool l_TrackingResult = ovrHmd_ConfigureTracking(g_Hmd, l_SupportedSensorCaps, l_RequiredTrackingCaps); if (!l_TrackingResult) { printf("Could not start tracking..."); exit(EXIT_FAILURE); } // Projection matrici for each eye will not change at runtime, we can set them here... g_ProjectionMatrici[ovrEye_Left] = ovrMatrix4f_Projection(g_EyeRenderDesc[ovrEye_Left].Fov, 0.3f, 100.0f, true); g_ProjectionMatrici[ovrEye_Right] = ovrMatrix4f_Projection(g_EyeRenderDesc[ovrEye_Right].Fov, 0.3f, 100.0f, true); // IPD offset values will not change at runtime, we can set them here... g_EyeOffsets[ovrEye_Left] = g_EyeRenderDesc[ovrEye_Left].HmdToEyeViewOffset; g_EyeOffsets[ovrEye_Right] = g_EyeRenderDesc[ovrEye_Right].HmdToEyeViewOffset; ovrHmd_RecenterPose(g_Hmd); return *oculusManager; } }
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 = (unsigned int)(w + 1) / 2; powW *= 2; unsigned int powH = (unsigned int)(h + 1) / 2; powH *= 2; data = (unsigned char *)malloc((unsigned long)(powW * powH * 4)); CC_BREAK_IF(! data); memset(data, 0, (unsigned long)(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(DRect(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; }
FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { CheckGLExtensions(); #ifndef USING_GLES2 if(!gl_extensions.FBO_ARB) return fbo_ext_create(width, height, num_color_textures, z_stencil, colorDepth); #endif FBO *fbo = new FBO(); fbo->width = width; fbo->height = height; fbo->colorDepth = colorDepth; // Color texture is same everywhere glGenFramebuffers(1, &fbo->handle); glGenTextures(1, &fbo->color_texture); // Create the surfaces. glBindTexture(GL_TEXTURE_2D, fbo->color_texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // TODO: We could opt to only create 16-bit render targets on slow devices. For later. switch (colorDepth) { case FBO_8888: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); break; case FBO_4444: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); break; case FBO_5551: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); break; case FBO_565: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); break; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); #ifdef USING_GLES2 if (gl_extensions.OES_packed_depth_stencil) { ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", width, height); // Standard method fbo->stencil_buffer = 0; fbo->z_buffer = 0; // 24-bit Z, 8-bit stencil combined glGenRenderbuffers(1, &fbo->z_stencil_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); // Bind it all together glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); } else { ILOG("Creating %i x %i FBO using separate stencil", width, height); // TEGRA fbo->z_stencil_buffer = 0; // 16/24-bit Z, separate 8-bit stencil glGenRenderbuffers(1, &fbo->z_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer); glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, width, height); // 8-bit stencil buffer glGenRenderbuffers(1, &fbo->stencil_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); // Bind it all together glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); } #else fbo->stencil_buffer = 0; fbo->z_buffer = 0; // 24-bit Z, 8-bit stencil glGenRenderbuffers(1, &fbo->z_stencil_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); // Bind it all together glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); #endif GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { case GL_FRAMEBUFFER_COMPLETE: // ILOG("Framebuffer verified complete."); break; case GL_FRAMEBUFFER_UNSUPPORTED: ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); break; default: FLOG("Other framebuffer error: %i", status); break; } // Unbind state we don't need glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); return fbo; }
void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, QGLFramebufferObject::Attachment attachment, GLenum texture_target, GLenum internal_format, GLint samples, bool mipmap) { 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); if (mipmap) glGenerateMipmap(GL_TEXTURE_2D); #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 { mipmap = false; GLint maxSamples; glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples); samples = qBound(0, int(samples), int(maxSamples)); glGenRenderbuffers(1, &color_buffer); glBindRenderbuffer(GL_RENDERBUFFER_EXT, color_buffer); if (glRenderbufferStorageMultisampleEXT && samples > 0) { 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); } // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer // might not be supported while separate buffers are, according to QTBUG-12861. if (attachment == QGLFramebufferObject::CombinedDepthStencil && (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) { // depth and stencil buffer needs another extension glGenRenderbuffers(1, &depth_buffer); Q_ASSERT(!glIsRenderbuffer(depth_buffer)); glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer); Q_ASSERT(glIsRenderbuffer(depth_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()); stencil_buffer = depth_buffer; glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, stencil_buffer); valid = checkFramebufferStatus(); if (!valid) { glDeleteRenderbuffers(1, &depth_buffer); stencil_buffer = depth_buffer = 0; } } if (depth_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil || (attachment == QGLFramebufferObject::Depth))) { glGenRenderbuffers(1, &depth_buffer); Q_ASSERT(!glIsRenderbuffer(depth_buffer)); glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer); Q_ASSERT(glIsRenderbuffer(depth_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) { #ifdef QT_OPENGL_ES if (QGLExtensions::glExtensions() & QGLExtensions::Depth24) { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH_COMPONENT24_OES, size.width(), size.height()); } else { 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 if (QGLExtensions::glExtensions() & QGLExtensions::Depth24) { glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_OES, size.width(), size.height()); } else { glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height()); } #else glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif } glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_buffer); valid = checkFramebufferStatus(); if (!valid) { glDeleteRenderbuffers(1, &depth_buffer); depth_buffer = 0; } } if (stencil_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil)) { glGenRenderbuffers(1, &stencil_buffer); Q_ASSERT(!glIsRenderbuffer(stencil_buffer)); glBindRenderbuffer(GL_RENDERBUFFER_EXT, stencil_buffer); Q_ASSERT(glIsRenderbuffer(stencil_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) { #ifdef QT_OPENGL_ES glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_STENCIL_INDEX8_EXT, size.width(), size.height()); #else glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_STENCIL_INDEX, size.width(), size.height()); #endif } else { #ifdef QT_OPENGL_ES glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, size.width(), size.height()); #else glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, size.width(), size.height()); #endif } glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, stencil_buffer); valid = checkFramebufferStatus(); if (!valid) { glDeleteRenderbuffers(1, &stencil_buffer); stencil_buffer = 0; } } // The FBO might have become valid after removing the depth or stencil buffer. valid = checkFramebufferStatus(); if (depth_buffer && stencil_buffer) { fbo_attachment = QGLFramebufferObject::CombinedDepthStencil; } else if (depth_buffer) { fbo_attachment = QGLFramebufferObject::Depth; } 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); if (depth_buffer) glDeleteRenderbuffers(1, &depth_buffer); if (stencil_buffer && depth_buffer != stencil_buffer) glDeleteRenderbuffers(1, &stencil_buffer); 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); format.setMipmap(mipmap); }
void NGLScene::createFrameBuffer() { // create a framebuffer object this is deleted in the dtor int w=width()*devicePixelRatio(); int h=height()*devicePixelRatio(); 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); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rboID); // 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_RGB16F, 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_RGB16F, 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_RGB16F, 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_RGB16F, 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, 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 // 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); }