SDL3窗口缩放时正方形变形问题及解决方案咨询
SDL3窗口缩放时保持图形比例的问题
我尝试使用SDL3及SDL_SetRenderLogicalPresentation()函数,搭配SDL_LOGICAL_PRESENTATION_LETTERBOX模式,实现窗口缩放时保持正方形的尺寸与比例,编写的Python代码如下:
import sdl3 # Function to draw a square def draw_square(renderer, x, y, size): sdl3.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255) # White color rect = sdl3.SDL_FRect(x=x, y=y, w=size, h=size) sdl3.SDL_RenderFillRect(renderer, rect) # Initialize SDL3 if sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO) < 0: print(f"SDL initialization error: {sdl3.SDL_GetError().decode()}") exit(1) # Create window window = sdl3.SDL_CreateWindow(b"Hello World", 640, 480, sdl3.SDL_WINDOW_RESIZABLE) if not window: print(f"Window creation error: {sdl3.SDL_GetError().decode()}") exit(1) # Create renderer renderer = sdl3.SDL_CreateRenderer(window, b"metal") if not renderer: print(f"Renderer creation error: {sdl3.SDL_GetError().decode()}") exit(1) # Set logical rendering size logical_width, logical_height = 640, 480 sdl3.SDL_SetRenderLogicalPresentation(renderer, logical_width, logical_height, sdl3.SDL_LOGICAL_PRESENTATION_LETTERBOX) # Parameters for positioning the square square_size = 100 # Fixed square size square_x = (logical_width - square_size) / 2 # Center horizontally square_y = (logical_height - square_size) / 2 # Center vertically running = True while running: # Event handling event = sdl3.SDL_Event() while sdl3.SDL_PollEvent(event): if event.type == sdl3.SDL_EVENT_QUIT: running = False # Rendering sdl3.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) # Black background sdl3.SDL_RenderClear(renderer) # Draw square with fixed size and centered position draw_square(renderer, square_x, square_y, square_size) sdl3.SDL_RenderPresent(renderer) # Cleanup sdl3.SDL_DestroyRenderer(renderer) sdl3.SDL_DestroyWindow(window) sdl3.SDL_Quit()
目前,正方形仅在释放鼠标(缩放结束)后才会恢复原有宽高,而在缩放过程中会被拉伸或挤压出现变形。
请问:
- 这是
SDL_SetRenderLogicalPresentation的预期行为吗? - 如何实现窗口缩放全程无变形的正方形?是否有可行的解决方法或最佳实践(我是Mac用户)?
- 将正方形转换为纹理是否有助于稳定其比例?
解答
1. 这是预期行为吗?
是的,这种现象在SDL3搭配macOS Metal渲染器的场景下属于预期行为。默认情况下,SDL不会在窗口拖动缩放的每一步自动更新逻辑渲染的映射关系,仅在缩放操作完成(鼠标释放)时才重新计算适配规则,目的是避免频繁更新带来的性能开销。
2. 实现全程无变形的解决方法
核心思路是监听窗口尺寸变化事件,实时更新逻辑渲染设置。具体操作:
- 在事件循环中监听
SDL_EVENT_WINDOW_SIZE_CHANGED事件(该事件会在窗口尺寸发生任何变化时触发,包括拖动缩放的过程中) - 每次触发事件时,重新调用
SDL_SetRenderLogicalPresentation,强制SDL更新逻辑坐标到窗口坐标的映射
修改后的Python代码示例:
import sdl3 # Function to draw a square def draw_square(renderer, x, y, size): sdl3.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255) # White color rect = sdl3.SDL_FRect(x=x, y=y, w=size, h=size) sdl3.SDL_RenderFillRect(renderer, rect) # Initialize SDL3 if sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO) < 0: print(f"SDL initialization error: {sdl3.SDL_GetError().decode()}") exit(1) # Create window window = sdl3.SDL_CreateWindow(b"Hello World", 640, 480, sdl3.SDL_WINDOW_RESIZABLE) if not window: print(f"Window creation error: {sdl3.SDL_GetError().decode()}") exit(1) # Create renderer renderer = sdl3.SDL_CreateRenderer(window, b"metal") if not renderer: print(f"Renderer creation error: {sdl3.SDL_GetError().decode()}") exit(1) # Set logical rendering size logical_width, logical_height = 640, 480 sdl3.SDL_SetRenderLogicalPresentation(renderer, logical_width, logical_height, sdl3.SDL_LOGICAL_PRESENTATION_LETTERBOX) # Parameters for positioning the square square_size = 100 # Fixed square size square_x = (logical_width - square_size) / 2 # Center horizontally square_y = (logical_height - square_size) / 2 # Center vertically running = True while running: # Event handling event = sdl3.SDL_Event() while sdl3.SDL_PollEvent(event): if event.type == sdl3.SDL_EVENT_QUIT: running = False # 监听窗口尺寸变化事件,实时更新逻辑渲染设置 elif event.type == sdl3.SDL_EVENT_WINDOW_SIZE_CHANGED: sdl3.SDL_SetRenderLogicalPresentation(renderer, logical_width, logical_height, sdl3.SDL_LOGICAL_PRESENTATION_LETTERBOX) # Rendering sdl3.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) # Black background sdl3.SDL_RenderClear(renderer) # Draw square with fixed size and centered position draw_square(renderer, square_x, square_y, square_size) sdl3.SDL_RenderPresent(renderer) # Cleanup sdl3.SDL_DestroyRenderer(renderer) sdl3.SDL_DestroyWindow(window) sdl3.SDL_Quit()
3. 转换为纹理是否有用?
作用不大。问题的根源是逻辑渲染的映射关系没有实时更新,而非绘制方式的问题。即使将正方形转为纹理,它依然会受到逻辑坐标到窗口坐标映射的影响,缩放过程中同样会出现变形。因此,核心解决方案还是实时更新逻辑渲染设置。
内容的提问来源于stack exchange,提问作者werwer werwer
相关产品推荐
相关产品推荐

