glViewport 错误地将法线坐标映射到 window 坐标?
glViewport incorrectly mapping normal coordinates to window coordinates?
我想我可以通过这些调用使 opengl 将坐标 (-1, -1) 和 (1, 1) 映射到像素 (0,0) 和 (width,height):
(gl-viewport 0 0 width height)
(gl-ortho -1 1 -1 1 -1 1)
然而,从 (-1,-1) 到 (1,1) 绘制的矩形仅跨越 window 左边缘和下边缘的三分之二。我可以使用
来解决这个问题
(gl-viewport 0 0 (* 3/2 width) (* 3/2 height))
但这对我来说似乎不正确。我做错了什么?
这是 DrRacket 的片段
#lang racket/base
(require racket/class)
(require racket/gui/base)
(require sgl)
(require sgl/gl-vectors)
(define game-canvas%
(class canvas%
(inherit refresh with-gl-context swap-gl-buffers)
(super-new)
(define (next x)
(modulo (+ 1 x) 100))
(define x-factor 0)
(define/override (on-paint)
(with-gl-context
(lambda ()
(gl-clear-color 0.0 0.0 0.0 0.0)
(gl-clear 'color-buffer-bit 'depth-buffer-bit)
(gl-color 1 1 0) (gl-rect -1 -1 (+ -1 (* 2 x-factor 1/100)) 1)
(swap-gl-buffers)
(gl-flush))))
(define/public (STEP)
(set! x-factor (next x-factor))
(refresh)
(sleep/yield 1/60)
(queue-callback (lambda _ (send this STEP) #f)))
(define/override (on-event e)
(when (is-a? e mouse-event%)
(when (eq? (send e get-event-type) 'left-down)
(exit 0))))
(define/override (on-size width height)
(with-gl-context
(lambda ()
(let ((aspect (/ width height)))
;(gl-viewport 0 0 width height)
(gl-viewport 0 0 (* 3/2 width) (* 3/2 height))
(gl-matrix-mode 'projection)
(gl-load-identity)
(gl-ortho (* aspect -1) (* aspect 1) -1 1 -1 1)
(gl-enable 'depth-test))))
(refresh))))
(module+ main
(define-values (W H) (get-display-size #t))
(define f (new frame%
[style '(no-resize-border
no-caption
no-system-menu
hide-menu-bar)]
[label "glui"]
[width (/ W 2)]
[height (/ H 2)]))
(define c (new game-canvas%
[parent f]
[style '(gl)]))
(send f show #t)
(send f center 'both)
(send c STEP))
看来您没有直接使用(gl-ortho -1 1 -1 1 -1 1)
,而是在(gl-ortho (* aspect -1) (* aspect 1) -1 1 -1 1)
中将左右值分别乘以aspect
。这是错误的,因为 -1 和 1 将始终指向左右边框(如果指定了其他值),而与您的纵横比无关。所以我会完全删除 aspect
并使用 -1 和 1。这是适用于我的 16/9 显示器的代码:
#lang racket/base
(require racket/class)
(require racket/gui/base)
(require sgl)
(require sgl/gl-vectors)
(define game-canvas%
(class canvas%
(inherit refresh with-gl-context swap-gl-buffers)
(super-new)
(define (next x)
(modulo (+ 1 x) 100))
(define x-factor 0)
(define/override (on-paint)
(with-gl-context
(lambda ()
(gl-clear-color 0.0 0.0 0.0 0.0)
(gl-clear 'color-buffer-bit 'depth-buffer-bit)
(gl-color 1 1 0) (gl-rect -1 -1 (+ -1 (* 2 x-factor 1/100)) 1)
(swap-gl-buffers)
(gl-flush))))
(define/public (STEP)
(set! x-factor (next x-factor))
(refresh)
(sleep/yield 1/60)
(queue-callback (lambda _ (send this STEP) #f)))
(define/override (on-event e)
(when (is-a? e mouse-event%)
(when (eq? (send e get-event-type) 'left-down)
(exit 0))))
(define/override (on-size width height)
(with-gl-context
(lambda ()
;; Changes here
(gl-viewport 0 0 width height)
(gl-matrix-mode 'projection)
(gl-load-identity)
(gl-ortho -1 1 -1 1 -1 1)
(gl-enable 'depth-test)))
;; End of changes
(refresh))))
(module+ main
(define-values (W H) (get-display-size #t))
(define f (new frame%
[style '(no-resize-border
no-caption
no-system-menu
hide-menu-bar)]
[label "glui"]
[width (/ W 2)]
[height (/ H 2)]))
(define c (new game-canvas%
[parent f]
[style '(gl)]))
(send f show #t)
(send f center 'both)
(send c STEP))
您的 Windows 系统似乎将显示缩放设置为 150%。 OpenGL 并不知道,您需要手动缩放。
(define/override (on-size width height)
...
(let ([scale (get-display-backing-scale)]
[scaled-width (exact-truncate (* width scale))]
[scaled-height (exact-truncate (* height scale))])
...
(gl-viewport 0 0 scaled-width scaled-height)
我想我可以通过这些调用使 opengl 将坐标 (-1, -1) 和 (1, 1) 映射到像素 (0,0) 和 (width,height):
(gl-viewport 0 0 width height)
(gl-ortho -1 1 -1 1 -1 1)
然而,从 (-1,-1) 到 (1,1) 绘制的矩形仅跨越 window 左边缘和下边缘的三分之二。我可以使用
来解决这个问题(gl-viewport 0 0 (* 3/2 width) (* 3/2 height))
但这对我来说似乎不正确。我做错了什么?
这是 DrRacket 的片段
#lang racket/base
(require racket/class)
(require racket/gui/base)
(require sgl)
(require sgl/gl-vectors)
(define game-canvas%
(class canvas%
(inherit refresh with-gl-context swap-gl-buffers)
(super-new)
(define (next x)
(modulo (+ 1 x) 100))
(define x-factor 0)
(define/override (on-paint)
(with-gl-context
(lambda ()
(gl-clear-color 0.0 0.0 0.0 0.0)
(gl-clear 'color-buffer-bit 'depth-buffer-bit)
(gl-color 1 1 0) (gl-rect -1 -1 (+ -1 (* 2 x-factor 1/100)) 1)
(swap-gl-buffers)
(gl-flush))))
(define/public (STEP)
(set! x-factor (next x-factor))
(refresh)
(sleep/yield 1/60)
(queue-callback (lambda _ (send this STEP) #f)))
(define/override (on-event e)
(when (is-a? e mouse-event%)
(when (eq? (send e get-event-type) 'left-down)
(exit 0))))
(define/override (on-size width height)
(with-gl-context
(lambda ()
(let ((aspect (/ width height)))
;(gl-viewport 0 0 width height)
(gl-viewport 0 0 (* 3/2 width) (* 3/2 height))
(gl-matrix-mode 'projection)
(gl-load-identity)
(gl-ortho (* aspect -1) (* aspect 1) -1 1 -1 1)
(gl-enable 'depth-test))))
(refresh))))
(module+ main
(define-values (W H) (get-display-size #t))
(define f (new frame%
[style '(no-resize-border
no-caption
no-system-menu
hide-menu-bar)]
[label "glui"]
[width (/ W 2)]
[height (/ H 2)]))
(define c (new game-canvas%
[parent f]
[style '(gl)]))
(send f show #t)
(send f center 'both)
(send c STEP))
看来您没有直接使用(gl-ortho -1 1 -1 1 -1 1)
,而是在(gl-ortho (* aspect -1) (* aspect 1) -1 1 -1 1)
中将左右值分别乘以aspect
。这是错误的,因为 -1 和 1 将始终指向左右边框(如果指定了其他值),而与您的纵横比无关。所以我会完全删除 aspect
并使用 -1 和 1。这是适用于我的 16/9 显示器的代码:
#lang racket/base
(require racket/class)
(require racket/gui/base)
(require sgl)
(require sgl/gl-vectors)
(define game-canvas%
(class canvas%
(inherit refresh with-gl-context swap-gl-buffers)
(super-new)
(define (next x)
(modulo (+ 1 x) 100))
(define x-factor 0)
(define/override (on-paint)
(with-gl-context
(lambda ()
(gl-clear-color 0.0 0.0 0.0 0.0)
(gl-clear 'color-buffer-bit 'depth-buffer-bit)
(gl-color 1 1 0) (gl-rect -1 -1 (+ -1 (* 2 x-factor 1/100)) 1)
(swap-gl-buffers)
(gl-flush))))
(define/public (STEP)
(set! x-factor (next x-factor))
(refresh)
(sleep/yield 1/60)
(queue-callback (lambda _ (send this STEP) #f)))
(define/override (on-event e)
(when (is-a? e mouse-event%)
(when (eq? (send e get-event-type) 'left-down)
(exit 0))))
(define/override (on-size width height)
(with-gl-context
(lambda ()
;; Changes here
(gl-viewport 0 0 width height)
(gl-matrix-mode 'projection)
(gl-load-identity)
(gl-ortho -1 1 -1 1 -1 1)
(gl-enable 'depth-test)))
;; End of changes
(refresh))))
(module+ main
(define-values (W H) (get-display-size #t))
(define f (new frame%
[style '(no-resize-border
no-caption
no-system-menu
hide-menu-bar)]
[label "glui"]
[width (/ W 2)]
[height (/ H 2)]))
(define c (new game-canvas%
[parent f]
[style '(gl)]))
(send f show #t)
(send f center 'both)
(send c STEP))
您的 Windows 系统似乎将显示缩放设置为 150%。 OpenGL 并不知道,您需要手动缩放。
(define/override (on-size width height)
...
(let ([scale (get-display-backing-scale)]
[scaled-width (exact-truncate (* width scale))]
[scaled-height (exact-truncate (* height scale))])
...
(gl-viewport 0 0 scaled-width scaled-height)