moderngl / moderngl-window

A cross platform utility library for ModernGL making window creation and resource loading simple
MIT License
244 stars 57 forks source link

windows size problem when loading a texture #127

Closed dgiunchi closed 3 years ago

dgiunchi commented 3 years ago

In image_shader_example.py I try to visualise different images with different sizes, but for some reason, they got stretched or misaligned and even if I try to force the window size to the right value, black bands appear, and the ratio of the image is not always correct. If I try with a 1920x1080 for example it seems to be ok, but if I try with a 720x1440 I have those issues. My aim is to load an image and having the viewport/window of the size of the image.

einarf commented 3 years ago

Can you link to the example and possibly also include a screenshot? It's probably a trivial thing and this makes it easier for me to understand what the problem is.

dgiunchi commented 3 years ago

image this is what is displaying. pic

The code is taken from moderngl examples (image_shader_example.py)

# This example opens an image, and offsets the red, green, and blue channels to create a glitchy RGB split effect.
from pathlib import Path
from array import array

from PIL import Image

import moderngl
import moderngl_window

class ImageProcessing(moderngl_window.WindowConfig):
    window_size = 720, 1440
    resource_dir = Path(__file__).parent.resolve()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.image_processing = ImageTransformer(self.ctx, self.window_size)
        self.texture = self.load_texture_2d("./data/pic.png")

    def render(self, time, frame_time):
        self.image_processing.render(self.texture, target=self.ctx.screen)

        # Headless
        self.image_processing.render(self.texture)
        self.image_processing.write("output.png")

class ImageTransformer:

    def __init__(self, ctx, size, program=None):
        self.ctx = ctx
        self.size = size
        self.program = None
        self.fbo = self.ctx.framebuffer(
            color_attachments=[self.ctx.texture(self.size, 4)]
        )

        # Create some default program if needed
        if not program:
            self.program = self.ctx.program(
                vertex_shader="""
                    #version 330

                    in vec2 in_position;
                    in vec2 in_uv;
                    out vec2 uv;

                    void main() {
                        gl_Position = vec4(in_position, 0.0, 1.0);
                        uv = in_uv;
                    }
                """,
                fragment_shader = """
                    #version 330

                    uniform sampler2D image;
                    in vec2 uv;
                    out vec4 out_color;

                    void main() {

                        out_color = texture(image, uv);
                    }
                """,          
            )

        # Fullscreen quad in NDC
        self.vertices = self.ctx.buffer(
            array(
                'f',
                [
                    # Triangle strip creating a fullscreen quad
                    # x, y, u, v
                    -1,  1, 0, 1,  # upper left
                    -1, -1, 0, 0, # lower left
                     1,  1, 1, 1, # upper right
                     1, -1, 1, 0, # lower right
                ]
            )
        )
        self.quad = self.ctx.vertex_array(
            self.program,
            [
                (self.vertices, '2f 2f', 'in_position', 'in_uv'),
            ]
        )

    def render(self, texture, target=None):
        if target:
            target.use()
        else:
            self.fbo.use()

        texture.use(0)
        self.quad.render(mode=moderngl.TRIANGLE_STRIP)

    def write(self, name):
        image = Image.frombytes("RGBA", self.fbo.size, self.fbo.read(components=4))
        image = image.transpose(Image.FLIP_TOP_BOTTOM)
        image.save(name, format="png")

if __name__ == "__main__":
    ImageProcessing.run()`
einarf commented 3 years ago

aha! Set aspect_ratio to None to not enforce the default aspect ratio

class ImageProcessing(moderngl_window.WindowConfig):
    window_size = 720, 1440
    resource_dir = Path(__file__).parent.resolve()
    aspect_ratio = None
einarf commented 3 years ago

I set this by default in https://github.com/moderngl/moderngl/commit/dbaa064be2bbc3222c0421780d08d7e5a5071b28

This image processing example is a fairly quick and dirty setup, but it works. Don't hesisitate to reopen or create a new issue if needed. We also have a discord server linked in README.

dgiunchi commented 3 years ago

aha! Set aspect_ratio to None to not enforce the default aspect ratio

class ImageProcessing(moderngl_window.WindowConfig):
    window_size = 720, 1440
    resource_dir = Path(__file__).parent.resolve()
    aspect_ratio = None

thank you! brilliant!

einarf commented 3 years ago

No problem. Again, this example is very rough, but at least it works!

It would be more fun if it showed changes every frame instead of dumping the image to disk. There is so much fun stuff that can be done with image processing and shaders.