Skip to content

Update OpenGL Viewport when Window resizes #2915

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 25, 2024

Conversation

damusss
Copy link
Member

@damusss damusss commented Jun 7, 2024

Fixes #2877
The documentation has been updated by MyreMylar already.

As stated in the issue, the newly functional OpenGL Windows, unlike the display windows, would not resize the OpenGL viewport causing bugs and inconsistencies.

With the addition of a function, used both in the event watch and in the set_size function, the OpenGl viewport is now correctly updated. I tested locally, it works for fullscreen/maximization/autoresize/manualresize.

If it works for you too (should, it's identical to the display's one), I think this should be added not later than 2.5.1

@damusss damusss requested a review from a team as a code owner June 7, 2024 21:09
@oddbookworm
Copy link
Member

I suspect the circleCI failure is unrelated to your changes, looks like it's unable to download the SDL2 dependency. I'm going to wait a while before rerunning it

@damusss
Copy link
Member Author

damusss commented Jun 8, 2024

@oddbookworm Alright, I managed to make glViewport static and I added exceptions to my new function. To note that the window is still resized even if there are problems with opengl, so you could do something like
image
On the event watch, I cleared the errors as I don't know how to stop the python execution with an exception from there. It also seems that another check (for the surface) is returning early without an exception aswell, so I followed the same trend.
Tell me what you think :)

@yunline yunline added opengl window pygame.Window labels Jun 11, 2024
@damusss damusss requested a review from oddbookworm June 13, 2024 12:47
Copy link
Member

@oddbookworm oddbookworm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@damusss damusss added this to the 2.5.1 milestone Jul 9, 2024
@MyreMylar
Copy link
Member

Hi,

What test code are you using for this? When I try it with a resizable Window using the code from the last PR the context doesn't appear to resize and I get some refcount errors popping up. Here is the original PR code:

Open GL triangle code
import pygame
import zengl

window_size = (1280, 720)

pygame.init()

window = pygame.Window(size=window_size, opengl=True)
window.resizable = True

ctx = zengl.context()

image = ctx.image(window_size, "rgba8unorm", samples=4)

pipeline = ctx.pipeline(
    vertex_shader="""
        #version 330 core

        out vec3 v_color;

        vec2 vertices[3] = vec2[](
            vec2(0.0, 0.8),
            vec2(-0.6, -0.8),
            vec2(0.6, -0.8)
        );

        vec3 colors[3] = vec3[](
            vec3(1.0, 0.0, 0.0),
            vec3(0.0, 1.0, 0.0),
            vec3(0.0, 0.0, 1.0)
        );

        void main() {
            gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0);
            v_color = colors[gl_VertexID];
        }
    """,
    fragment_shader="""
        #version 330 core

        in vec3 v_color;

        layout (location = 0) out vec4 out_color;

        void main() {
            out_color = vec4(v_color, 1.0);
            out_color.rgb = pow(out_color.rgb, vec3(1.0 / 2.2));
        }
    """,
    framebuffer=[image],
    topology="triangles",
    vertex_count=3,
)

clock = pygame.Clock()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()

    ctx.new_frame()
    image.clear()
    pipeline.render()
    image.blit()
    ctx.end_frame()

    window.flip()
    clock.tick(60)

After resizing a few times and hitting the close button I have received this on more than one occasion:

Fatal Python error: none_dealloc: deallocating None: bug likely caused by a refcount error in a C extension
Python runtime state: finalizing (tstate=0x00007ff9364f6960)

Current thread 0x0000e614 (most recent call first):
  Garbage-collecting
  <no Python frame>

After resizing the window smaller I sort of expected the triangle to resize to the size of the window:

image

This could be a zenGL issue though I'm not sure.

@MyreMylar
Copy link
Member

After some fiddling this is what I came up with as test code:

import pygame
import zengl

window_size = (1280, 720)

pygame.init()

window = pygame.Window(size=window_size, opengl=True)
window.resizable = True

ctx = zengl.context()

image = ctx.image(window_size, "rgba8unorm", samples=4)
vert_shader = """
        #version 330 core

        out vec3 v_color;

        vec2 vertices[3] = vec2[](
            vec2(0.0, 0.8),
            vec2(-0.6, -0.8),
            vec2(0.6, -0.8)
        );

        vec3 colors[3] = vec3[](
            vec3(1.0, 0.0, 0.0),
            vec3(0.0, 1.0, 0.0),
            vec3(0.0, 0.0, 1.0)
        );

        void main() {
            gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0);
            v_color = colors[gl_VertexID];
        }
    """
frag_shader = """
        #version 330 core

        in vec3 v_color;

        layout (location = 0) out vec4 out_color;

        void main() {
            out_color = vec4(v_color, 1.0);
            out_color.rgb = pow(out_color.rgb, vec3(1.0 / 2.2));
        }
    """
pipeline = ctx.pipeline(
    vertex_shader=vert_shader,
    fragment_shader=frag_shader,
    framebuffer=[image],
    topology="triangles",
    vertex_count=3,
)

clock = pygame.Clock()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()

        if event.type == pygame.WINDOWRESIZED:
            image = ctx.image((event.x, event.y), "rgba8unorm", samples=4)
            pipeline = ctx.pipeline(
                vertex_shader=vert_shader,
                fragment_shader=frag_shader,
                framebuffer=[image],
                topology="triangles",
                vertex_count=3,
            )

    ctx.new_frame()
    image.clear()
    pipeline.render()
    image.blit()
    ctx.end_frame()

    window.flip()
    clock.tick(60)

Which seems to work. Does that seem correct for testing this issue?

@damusss
Copy link
Member Author

damusss commented Jul 25, 2024

@MyreMylar zengl is different from moderngl, so when the window resizes you are required to remake the framebuffer image and threfore the pipeline that uses it. The "correct" version of your code is this:
(failed to make collapsable header)
NOTE: this makes this code work with OR without my PR. You should try with moderngl. hold on while I provide a moderngl example that is impacted by this PR.

import pygame
  import zengl
  
  window_size = (1280, 720)
  
  pygame.init()
  
  window = pygame.Window(size=window_size, opengl=True)
  window.resizable = True
  
  ctx = zengl.context()
  
  image = ctx.image(window_size, "rgba8unorm", samples=4)
  
  def make_pipeline():
      global pipeline
      pipeline = ctx.pipeline(
          vertex_shader="""
              #version 330 core
  
              out vec3 v_color;
  
              vec2 vertices[3] = vec2[](
                  vec2(0.0, 0.8),
                  vec2(-0.6, -0.8),
                  vec2(0.6, -0.8)
              );
  
              vec3 colors[3] = vec3[](
                  vec3(1.0, 0.0, 0.0),
                  vec3(0.0, 1.0, 0.0),
                  vec3(0.0, 0.0, 1.0)
              );
  
              void main() {
                  gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0);
                  v_color = colors[gl_VertexID];
              }
          """,
          fragment_shader="""
              #version 330 core
  
              in vec3 v_color;
  
              layout (location = 0) out vec4 out_color;
  
              void main() {
                  out_color = vec4(v_color, 1.0);
                  out_color.rgb = pow(out_color.rgb, vec3(1.0 / 2.2));
              }
          """,
          framebuffer=[image],
          topology="triangles",
          vertex_count=3,
      )
  make_pipeline()
  
  clock = pygame.Clock()
  
  while True:
      for event in pygame.event.get():
          if event.type == pygame.QUIT:
              pygame.quit()
              quit()
          if event.type == pygame.VIDEORESIZE:
              window_size = event.size
              image = ctx.image(window_size, "rgba8unorm", samples=4)
              make_pipeline()
  
      ctx.new_frame()
      image.clear()
      pipeline.render()
      image.blit()
      ctx.end_frame()
  
      window.flip()
      clock.tick(60)

@MyreMylar
Copy link
Member

OK, looks like the refcount error on window close is also fixed by updating zenGL - so I guess that was on their side not us.

Copy link
Member

@MyreMylar MyreMylar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving, assuming I'm testing this correctly - please let me know if I am not.

@damusss damusss merged commit cd4826f into pygame-community:main Jul 25, 2024
39 checks passed
@damusss damusss deleted the Window-opengl-viewport branch August 3, 2024 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
opengl window pygame.Window
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enhance window with OpenGL with viewport and documentation
5 participants