Computer Graphics Exercise – Jakob Wagner
Total Page:16
File Type:pdf, Size:1020Kb
Computer Graphics Exercise – Jakob Wagner Computer Graphics Exercise 7. Framebuffers & Offscreen Rendering Jakob Wagner for internal use only 7 – Framebuffers & Offscreen Rendering Computer Graphics Exercise – Jakob Wagner Fragment Submission Vertex Specification Vertex Processing Vertex Post-processing Primitive Assembly define vertex format & data in transform to clip space clipping, perspective divide, build points/lines/triangles model space viewport transform from vertices Vertex Shader Rasterisation Fragment Processing Fragment Submission scan-convert primitives to computer fragment properties testing and blending fragments, property transfer write to buffer Fragment Shader https://glumpy.github.io/modern-gl.html 7 – Framebuffers & Offscreen Rendering 2 Computer Graphics Exercise – Jakob Wagner Fragment Submission - happens after the fragment attribute computations - performed on each fragment submitted by the shader - defines if and how the fragment is applied to the drawing buffer - stages: a. pixel ownership test - check if display pixels are covered by other window b. scissor test - discard fragments outside specified rectangle c. stencil test - check if fragment fulfills custom condition d. depth test - check if fragment is occluded by buffer pixel e. blending - blend fragment with buffer pixel 7 – Framebuffers & Offscreen Rendering 3 Computer Graphics Exercise – Jakob Wagner color buffer Depth Test - necessary for occlusion culling - submitted fragment’s depth values are stored in a 1 channel Depth Buffer - depth value of fragment is compared with current value of the pixel at fragment position in Depth Buffer - smaller: fragment is closer to camera -> in front of pixel in buffer -> fragment passes - bigger: fragment further from camera -> occluded by pixel in buffer -> fragment fails depth buffer (linearized) fragment comparison value in buffer depth 0.7 0.3 ✗ 0.1 ✓ 7 – Framebuffers & Offscreen Rendering 4 Computer Graphics Exercise – Jakob Wagner Framebuffer - is the target of fragment submissions Framebuffer - can contain three types of attachments: - color_attachment: stores pixel color ColorColor Depth Stencil - depth_attachment: stores pixel depth AttachmentAttachment Attachment Attachment - stencil attachment: stores additional pixel value - attachments can be Textures and Renderbuffers - there are two types: - the default Framebuffer Texture/ Texture Renderbuffer Renderbuffer bind - Framebuffer Objects Object Object Object - there is always 1 active/bound Framebuffer - the bound Framebuffer is cleared using glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 7 – Framebuffers & Offscreen Rendering 5 Computer Graphics Exercise – Jakob Wagner Renderbuffers - are OpenGL objects similar to textures - used for depth and stencil buffer - specialized as render targets, no sampling support, no data initialisation possible - only usable when attached to a Framebuffer - can only be bound to the GL_RENDERBUFFER binding point - format is either depth or stencil with varying bit-depths or both combined creation: glGenRenderbuffers(1, &rb_handle) 1. generate Renderbuffer Object 2. bind RBO for formatting glBindRenderbuffer(GL_RENDERBUFFER, rb_handle) 3. specify RBO properties: glRenderbufferStorage(GL_RENDERBUFFER, - format, e.g. GL_DEPTH_COMPONENT24 format, - horizontal resolution width, - vertical resolution height) 7 – Framebuffers & Offscreen Rendering 6 Computer Graphics Exercise – Jakob Wagner Default Framebuffer scene objectobject - created with OpenGL context objectobject - configured during context creation render - index is 0, bound by default GL_BACK - content is what is visible on screen - automatically resized with window frame n - either single or double buffered: - single: objects rendered directly to screen swap - double: objects rendered to backbuffer, when finished, it is swapped with front buffer GL_FRONT - 1 buffer for mono, or 2 buffers for stereo rendering - no generic color attachments but specific buffers: GL_FRONT_LEFT, GL_FRONT_RIGHT, GL_BACK… frame n - 1 - only one active Draw Buffer possible 7 – Framebuffers & Offscreen Rendering 7 Computer Graphics Exercise – Jakob Wagner Framebuffer Object Context - is OpenGL object - created and configured by user at runtime GL_FRAMEBUFFER - can hold: n color attachment Textures DrawBuffer Framebuffer Object 1 depth attachment Texture/Renderbuffer ... 1 stencil attachment Renderbuffer GL_COLOR_ATTACHMENT1 GL_STENCIL_ATTACHMENT - color attachments specified as Draw Buffers will be targets of GL_COLOR_ATTACHMENTn GL_DEPTH_ATTACHMENT fragment submissions Texture Renderbuffer - all attachments must have the same dimensions Object Object Shader out vec4 out_Color; out float gl_FragDepth; 7 – Framebuffers & Offscreen Rendering 8 Computer Graphics Exercise – Jakob Wagner Framebuffer Specification define Framebuffer 1. generate Frame Buffer Object glGenFramebuffers(1, &fbo_handle) 2. bind FBO for configuration glBindFramebuffer(GL_FRAMEBUFFER, fbo_handle) define attachments glFramebufferTexture(GL_FRAMEBUFFER, 3. specify Texture Object attachments - to color or depth attachment GL_COLOR_ATTACHMENTi / GL_DEPTH_ATTACHMENT, - texture handle tex_handle, - highest level of texture (no mipmap) 0) 4. specify Renderbuffer Object attachments glFramebufferRenderbuffer(GL_FRAMEBUFFER, - to depth or stencil attachment GL_DEPTH_ATTACHMENT / GL_STENCIL_ATTACHMENT, - value must be GL_RENDERBUFFER GL_RENDERBUFFER - handle of RBO rb_handle) define draw buffers 5. create array containing enums representing color attachments GLenum draw_buffers[n] = {GL_COLOR_ATTACHMENT0, ...} 6. set these color attachments to receive fragments glDrawBuffers(n, draw_buffers) check validity GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) 7. get the FBO status 8. compare return value with the valid status value if (status != GL_FRAMEBUFFER_COMPLETE) {/*output error*/} 7 – Framebuffers & Offscreen Rendering 9 Computer Graphics Exercise – Jakob Wagner Offscreen rendering - only the default Framebuffers content is visible on screen -> when rendering to a FBO, results are not visible - rendering results stored in an FBO must be transferred to default Framebuffer - direct pixel transfer by blitting is slow and not very convenient - indirect transfer through triangle rendering works best: render to the default Framebuffer a a quadrangle covering the screen, sample the FBOs color texture at each create fragment - allows post-processing with global knowledge (color values of neighbour pixels etc.) scene Framebuffer Object apply screen quad default Framebuffer render render color buffer depth buffer texture color buffer depth buffer 7 – Framebuffers & Offscreen Rendering 10 Computer Graphics Exercise – Jakob Wagner Screen quad - does not require any transformation - can be defined directly in normalized device space (window edges at 1.0 and -1.0) - vertices can be defined in order {v1, v2, v4, v3} and rendered as GL_TRIANGLE_STRIP -> only 4 vertices required - texture coordinates can be computed in the vertex shader - fragment shader has the FBO color texture as sampler - the pixel value of the color texture at the texture coordinate is sampled and assigned to out_Color v4 v3 pos (-1.0, 1.0, 0.0) pos (1.0, 1.0, 0.0) uv (0.0, 1.0) uv (1.0, 1.0) pos (-1.0, -1.0, 0.0) pos (1.0, -1.0, 0.0) uv (0.0, 0.0) v1 v2 uv (1.0, 0.0) 7 – Framebuffers & Offscreen Rendering 11 Computer Graphics Exercise – Jakob Wagner Post-processing Effects luminance preserving grayscale: channels are weighted because their perceived luminance is not uniform: luminance = 0.2126 ∙ cr + 0.7152 ∙ cg + 0.0722 ∙ cb mirroring: the texture coordinates are inverted (1 becomes 0 and 0 becomes 1) 1 / 16 1 / 8 1 / 16 Gaussian Blur: 1 / 8 1 / 4 1 / 8 the resulting color of the target pixel is the weighted sum of the neighbouring pixels target pixel 3x3 blurring kernel: 9 texture lookups per pixel 1 / 16 1 / 8 1 / 16 requires knowledge of pixel size in texture space to compute the offset of neighbours -> can be computed using pass_TexCoord (position in texture space) and gl_FragCoord (position in window space) -> relation: pass_TexCoord = pixel_size · gl_FragCoord 7 – Framebuffers & Offscreen Rendering 12 Computer Graphics Exercise – Jakob Wagner Assignment 5 – Offscreen Rendering Framebuffer creation - on startup, create a texture and a renderbuffer object - format these buffers in the update_projection() function (so that they are resized every time when window size changes) - create a FBO and attach the texture as color- and the renderbuffer as depth-attachment, specify the texture as draw buffer Screenquad creation - create a new model object for the screen quad as explained - create a new Shader Program for the quad, without any transformations in the vertex shader - upload the Texture Unit of the color texture as uniform sampler and do a texture lookup in the fragment shader Rendering - bind the new FBO and render the scene as usual - bind the default Framebuffer and render the screen quad - when everything works, there will be no visible difference between rendering to the FBO or directly to the default Framebuffer 7 – Framebuffers & Offscreen Rendering 13.