Hi David.

Heureka! I think I figured it out. When load-texture defined in
opengl/utils loads an image
it automatically generates an mimap, which are smaller versions of the same
image.
When I draw I am drawing on the full size image - so all I need to do is to
generate
a new mimap.

    (glGenerateMipmap GL_TEXTURE_2D)

This explains why you are seeing different results depending on the size of
the window.

Thanks for the hint.

Jens Axel






2018-04-08 20:23 GMT+02:00 David Vanderson <david.vander...@gmail.com>:

> 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 <jensa...@soegaard.net>
> 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 <david.vander...@gmail.com>:
>>
>>> 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 <jensa...@soegaard.net
>>> > 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 racket-users+unsubscr...@googlegroups.com.
>>>> 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 racket-users+unsubscr...@googlegroups.com.
>>> 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 racket-users+unsubscr...@googlegroups.com.
> 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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to