Something weird is going on. If I make the viewport bigger when drawing to the screen then I see the blue triangle:
; switch to screen framebuffer (glBindFramebuffer GL_DRAW_FRAMEBUFFER 0) (glViewport 0 0 1000 1000) ; somehow this makes a difference? If I make the viewport exactly match the window size, then as I make the window bigger the blue triangle slowly fades in once it gets near to fullscreen. Do you see this as well? On Sun, Apr 8, 2018 at 9:45 AM, Jens Axel Søgaard <[email protected]> wrote: > Hi David, > > Thanks for the viewport suggestion. > I have made a version below that sets the viewport. > Saving the logo+triangle shows that the blue triangle has been drawn on > the frame buffer. > It disappears (?!) when I try to copy contents from the framebuffer to > screen though. > > #lang racket/gui > (require opengl opengl/util ffi/vector) > > (define logo-texture #f) > (define (load-logo-texture) > (unless logo-texture > (set! logo-texture (load-texture "plt-logo-red-gradient.png" #:repeat > 'both))) > logo-texture) > > (define (clear r g b a) > (glClearColor r g b a) > (glClear (bitwise-ior GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT))) > > (define (set-color r g b) > (glColor3f r g b)) > > (define (reset-color) > (set-color 1. 1. 1.)) > > (define (draw-triangle x1 y1 x2 y2 x3 y3) > (glBegin GL_TRIANGLES) > (glVertex3d x1 y1 0.) > (glVertex3d x2 y2 0.) > (glVertex3d x3 y3 0.) > (glEnd)) > > (define sanity #f) > > (define snapshot? #f) > (define bs (make-bytes (* 4 (* 256 256)) 0)) > (define (example) > ; make framebuffer > (define fbo-ids (glGenFramebuffers 1)) > (define fbo (u32vector-ref fbo-ids 0)) > ; swith to the new framebuffer > (glBindFramebuffer GL_FRAMEBUFFER fbo) > ; load logo texture (it is cached, so only loaded once) > (load-logo-texture) (unless logo-texture (error)) > ; use texture as color attachment 0 > (glFramebufferTexture2D GL_FRAMEBUFFER GL_COLOR_ATTACHMENT0 > GL_TEXTURE_2D logo-texture 0) > (glBindTexture GL_TEXTURE_2D logo-texture) > (glDrawBuffer GL_COLOR_ATTACHMENT0) > ; we will now draw on the texture > (glViewport 0 0 256 256) ; size of logo is 256x256 > (set-color 0.0 0.0 1.0) ; blue color > (draw-triangle 0.0 0.0 200.0 200.0 200.0 -200.) > (glFinish) > ; let's make a snapshot of what we have > (unless snapshot? > (set! snapshot? #t) > (glGetTexImage GL_TEXTURE_2D 0 GL_RGBA GL_UNSIGNED_BYTE bs) > (rgba->argb! bs)) > ; Note: (bytes->bitmap bs 256 256) in the repl > ; shows the logo with a blue triangle on top (as expected) > > ;;; *** Now we want to transfer the logo+triangle to the screen > > ; switch to screen framebuffer > (glBindFramebuffer GL_DRAW_FRAMEBUFFER 0) > ; draw something to the screen, so we can see that the switch works > ; red screen background > (clear 1.0 0.0 0.0 0.0) > ; green triangle > (set-color 0.0 1.0 0.0) > (draw-triangle 0.0 0.0 0.3 0.0 0.0 0.3) > ; we do see the green triangle in the result > > ; reset color in order for the transparency blending to work > (reset-color) > ; read from the texture in the framebuffer > (glBindFramebuffer GL_READ_FRAMEBUFFER fbo) > (glEnable GL_TEXTURE_2D) > (glEnable GL_BLEND) > (glBlendFunc GL_ONE GL_ONE_MINUS_SRC_ALPHA) ; This is the correct > setting for pre-multiplied alpha. > ; This is a square containing 2x2 copies of the logo > (define texcoord-array (s16vector 0 2 2 2 2 0 0 > 0)) > ; This is a square in the middle of the screen > (define vertex-array (f64vector -0.5 -0.5 0.5 -0.5 0.5 0.5 -0.5 > 0.5)) > (let-values (((type cptr) (gl-vector->type/cpointer vertex-array))) > (glVertexPointer 2 type 0 cptr)) > (let-values (((type cptr) (gl-vector->type/cpointer texcoord-array))) > (glTexCoordPointer 2 type 0 cptr)) > (glEnableClientState GL_VERTEX_ARRAY) > (glEnableClientState GL_TEXTURE_COORD_ARRAY) > ; Now draw the square on screen using the prepared texture > (glDrawArrays GL_QUADS 0 4) > ; clean up > (glDisableClientState GL_TEXTURE_COORD_ARRAY) > (glDisableClientState GL_VERTEX_ARRAY) > (glDisable GL_TEXTURE_2D) > (void)) > > ;;; > ;;; MODEL > ;;; > > (define frames-per-second 60.) > (define milliseconds-per-frame (/ 1000. frames-per-second)) > (define time 0.) > > (define (on-tick) > (set! time (+ time 1.)) > (send gl on-paint)) > > ;;; > ;;; GUI > ;;; > > (define (resize w h) > (glViewport 0 0 w h)) > > (define (example2) > (define v (* 2. pi (/ time 60))) > (define c (cos v)) > (define s (sin v)) > > (glClearColor 0.0 0.0 0.0 0.0) > (glClear GL_COLOR_BUFFER_BIT) > > (glBegin GL_TRIANGLES) > (glColor3f c 0. 0.) > (glVertex3d c 0 0) > (glColor3f 0. s 0.) > (glVertex3d 0. s 0.) > (glColor3f 0. 0. 1.) > (glVertex3d -1. -1. 0.) > (glEnd)) > > (define my-canvas% > (class* canvas% () > (inherit with-gl-context swap-gl-buffers) > (define/override (on-paint) (with-gl-context (λ() > (example) (swap-gl-buffers)))) > (define/override (on-size width height) (with-gl-context (λ() (resize > width height) (on-paint)))) > (super-instantiate () (style '(gl))))) > > (define win (new frame% [label "Racket Rosetta Code OpenGL example"] > [min-width 200] [min-height 200])) > (define gl (new my-canvas% [parent win])) > > (new timer% > [interval (exact-floor milliseconds-per-frame)] ; in milliseconds > [notify-callback on-tick]) > > (send win show #t) > > (define (bytes->bitmap bs width height) > (define bm (make-bitmap width height)) > (send bm set-argb-pixels 0 0 width height bs) > bm) > > (define (rgba->argb! pixels) > (for ((i (in-range (/ (bytes-length pixels) 4)))) > (let* ((offset (* 4 i)) > ( red (bytes-ref pixels (+ 0 offset))) > (green (bytes-ref pixels (+ 1 offset))) > ( blue (bytes-ref pixels (+ 2 offset))) > (alpha (bytes-ref pixels (+ 3 offset)))) > (bytes-set! pixels (+ 0 offset) alpha) > (bytes-set! pixels (+ 1 offset) red) > (bytes-set! pixels (+ 2 offset) green) > (bytes-set! pixels (+ 3 offset) blue)))) > > > > > 2018-04-08 0:49 GMT+02:00 David Vanderson <[email protected]>: > >> I'm also learning, but I think in this case the viewport is not sized >> correctly to draw to the texture. I think you need something like this: >> >> ; Draw a blue triangle ***this is the part that isn't working*** >> (glDrawBuffer GL_COLOR_ATTACHMENT0) ; draw to color attachment 0 >> (glDisable GL_TEXTURE_2D) ; do not use the texture when >> drawing the triangle >> (glViewport 0 0 tw th) ; set the viewport to the size of the texture >> (get tw and th from the size of the png file bitmap) >> (clear 0.0 0.0 1.0 1.0) >> (set-color 0.0 1.0 0.0) >> (glDisable GL_BLEND) >> (draw-triangle -1.0 0.0 1.0 0.0 1.0 1.0) >> >> ; switch to screen framebuffer >> (glBindFramebuffer GL_FRAMEBUFFER 0) >> (glViewport 0 0 W H) ; set the viewport to the size of the framebuffer >> (set W and H from resize handler) >> >> Does that help? >> >> Thanks, >> Dave >> >> On Fri, Apr 6, 2018 at 2:05 PM, Jens Axel Søgaard <[email protected]> >> wrote: >> >>> Hi All, >>> >>> I am looking into opengl and have so far learned to draw directly to the >>> screen. >>> However I'd like to do some offscreen rendering and have therefore tried >>> to use a framebuffer. >>> The program below does the following: >>> >>> 1. Makes a framebuffer >>> 2. Adds a texture (a plt logo) >>> 3. Draws a blue triangle on top of the logo >>> 4. Switches to the screen >>> 5. Draw a green triangle >>> 6. Copies the logo with the blue triangle to the screen. >>> >>> My problem is that the blue triangle is missing in the result. >>> >>> The result: https://imgur.com/NBJf2DG >>> See program below. >>> >>> Ideas welcome. >>> >>> /Jens Axel >>> >>> >>> >>> #lang racket/gui >>> (require opengl opengl/util ffi/vector) >>> >>> (define logo-texture #f) >>> (define (load-logo-texture) >>> (unless logo-texture >>> (set! logo-texture (load-texture "plt-logo-red-gradient.png" >>> #:repeat 'both))) >>> logo-texture) >>> >>> (define (clear r g b a) >>> (glClearColor r g b a) >>> (glClear (bitwise-ior GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT))) >>> >>> (define (set-color r g b) >>> (glColor3f r g b)) >>> >>> (define (reset-color) >>> (set-color 1. 1. 1.)) >>> >>> (define (draw-triangle x1 y1 x2 y2 x3 y3) >>> (glBegin GL_TRIANGLES) >>> (glVertex3d x1 y1 0.) >>> (glVertex3d x2 y2 0.) >>> (glVertex3d x3 y3 0.) >>> (glEnd)) >>> >>> (define (example) >>> ; make framebuffer >>> (define fbo-ids (glGenFramebuffers 1)) ; this returns a vector of >>> names >>> (define fbo (u32vector-ref fbo-ids 0)) ; get the first framebuffer >>> ; swith to the new framebuffer >>> (glBindFramebuffer GL_FRAMEBUFFER fbo) ; initialize framebuffer object >>> ; load logo texture if needed >>> (load-logo-texture) (unless logo-texture (error)) >>> (glFramebufferTexture2D GL_FRAMEBUFFER GL_COLOR_ATTACHMENT0 >>> GL_TEXTURE_2D logo-texture 0) >>> (define status (glCheckFramebufferStatus GL_FRAMEBUFFER_EXT)) >>> (define status-complete? (= status GL_FRAMEBUFFER_COMPLETE_EXT)) >>> >>> ; Draw a blue triangle ***this is the part that isn't working*** >>> (glDrawBuffer GL_COLOR_ATTACHMENT0) ; draw to color attachment 0 >>> (glDisable GL_TEXTURE_2D) ; do not use the texture when >>> drawing the triangle >>> (clear 0.0 0.0 1.0 1.0) >>> (set-color 0.0 1.0 0.0) >>> (glDisable GL_BLEND) >>> (draw-triangle -1.0 0.0 1.0 0.0 1.0 1.0) >>> >>> ; switch to screen framebuffer >>> (glBindFramebuffer GL_FRAMEBUFFER 0) >>> ; red background >>> (clear 1.0 0.0 0.0 0.0) >>> ; green triangle >>> (set-color 0.0 1.0 0.0) (draw-triangle 0.0 0.0 1.0 0.0 0.0 1.0) >>> ; Copy logo with blue triangle to screen >>> (reset-color) >>> (glEnable GL_TEXTURE_2D) >>> (glEnable GL_BLEND) >>> (glBlendFunc GL_ONE GL_ONE_MINUS_SRC_ALPHA) ; settings for >>> pre-multiplied alpha. >>> (define vertex-array (f64vector -0.5 -0.5 0.5 -0.5 0.5 0.5 -0.5 >>> 0.5)) >>> (define texcoord-array (s16vector 0 2 2 2 2 0 0 >>> 0)) >>> (let-values (((type cptr) (gl-vector->type/cpointer vertex-array))) >>> (glVertexPointer 2 type 0 cptr)) >>> (let-values (((type cptr) (gl-vector->type/cpointer texcoord-array))) >>> (glTexCoordPointer 2 type 0 cptr)) >>> (glEnableClientState GL_VERTEX_ARRAY) >>> (glEnableClientState GL_TEXTURE_COORD_ARRAY) >>> >>> (glDrawArrays GL_QUADS 0 4) >>> (glDisableClientState GL_TEXTURE_COORD_ARRAY) >>> (glDisableClientState GL_VERTEX_ARRAY) >>> (glDisable GL_TEXTURE_2D) >>> (void)) >>> >>> ;;; >>> ;;; MODEL >>> ;;; >>> >>> (define frames-per-second 60.) >>> (define milliseconds-per-frame (/ 1000. frames-per-second)) >>> (define time 0.) >>> >>> (define (on-tick) >>> (set! time (+ time 1.)) >>> (send gl on-paint)) >>> >>> ;;; >>> ;;; GUI >>> ;;; >>> >>> (define (resize w h) >>> (glViewport 0 0 w h)) >>> >>> (define (example2) >>> (define v (* 2. pi (/ time 60))) >>> (define c (cos v)) >>> (define s (sin v)) >>> >>> (glClearColor 0.0 0.0 0.0 0.0) >>> (glClear GL_COLOR_BUFFER_BIT) >>> >>> (glBegin GL_TRIANGLES) >>> (glColor3f c 0. 0.) >>> (glVertex3d c 0 0) >>> (glColor3f 0. s 0.) >>> (glVertex3d 0. s 0.) >>> (glColor3f 0. 0. 1.) >>> (glVertex3d -1. -1. 0.) >>> (glEnd)) >>> >>> (define my-canvas% >>> (class* canvas% () >>> (inherit with-gl-context swap-gl-buffers) >>> (define/override (on-paint) (with-gl-context (λ() >>> (example) (swap-gl-buffers)))) >>> (define/override (on-size width height) (with-gl-context (λ() >>> (resize width height) (on-paint)))) >>> (super-instantiate () (style '(gl))))) >>> >>> (define win (new frame% [label "Racket Rosetta Code OpenGL example"] >>> [min-width 200] [min-height 200])) >>> (define gl (new my-canvas% [parent win])) >>> >>> (new timer% >>> [interval (exact-floor milliseconds-per-frame)] ; in milliseconds >>> [notify-callback on-tick]) >>> >>> (send win show #t) >>> >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Racket Users" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Racket Users" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> For more options, visit https://groups.google.com/d/optout. >> > > > > -- > -- > Jens Axel Søgaard > > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.

