Skip to content

OpenGLRenderer.get_texture_id sometimes returns wrong tid #3368

Open
@mkuehne-git

Description

@mkuehne-git

Description of bug / unexpected behavior

I have posted this issue on Discord #helpForum a couple of days ago. I also posted the video showing the poorly rendered video. After analyzing this a bit further, I think it is worth to file an issue for it.

I have created a 3D scene showing a torus with textured surface. For each frame of the animation I replace the torus with a new one having a slightly different texture. The resulting video flickers and the animation seems to frequently jump back and forth.

Expected behavior

The animation should create a smooth, flicker free video, in this case a winding line around the torus starting at the red dot towards the blue dot.

Analysis

I have modified OpenGLRenderer.get_texture_id with some print() statements to see, what is going on.

    def get_texture_id(self, path):
        if repr(path) not in self.path_to_texture_id:
            tid = len(self.path_to_texture_id)
            texture = self.context.texture(
                size=path.size,
                components=len(path.getbands()),
                data=path.tobytes(),
            )
            texture.repeat_x = False
            texture.repeat_y = False
            texture.filter = (moderngl.NEAREST, moderngl.NEAREST)
            texture.swizzle = "RRR1" if path.mode == "L" else "RGBA"
            texture.use(location=tid)
            self.path_to_texture_id[repr(path)] = tid

        texture_id = self.path_to_texture_id[repr(path)]
        print("OpenGLRenderer.get_texture_id", repr(path), path.file_name, "->", texture_id)
        if self.texture_id > texture_id:
            print(f">>> OpenGLRenderer.get_texture_id wants to return {texture_id}, but it should return {self.cnt-1} instead!")
        self.texture_id = texture_id
        return texture_id

I also modified OpenGLTexturedSurface.get_image_from_file to make file_name available.

    def get_image_from_file(
        self,
        image_name: str | Path,
        image_mode: str,
    ):
        image_file = get_full_raster_image_path(image_name)
        image = Image.open(image_file).convert(image_mode)
        image.file_name = image_name
        return image

Below you can see the output for rendering frame #184. You can see that the key into self.path_to_texture_id is somehow flawed. The only discriminator between the images is the reported address of the Image object. However an image might be subject for garbage collection, and therefore the object address is probably not a good hash for the image.

For frame #184 the method should return tid=184.

#184 OpenGLRenderer.render scene: </.home.mk.dev.manim.ecc.gist.torus.AnimateTorusTexture object at 0x7f2a2c472430>
OpenGLMobject.get_shader_wrapper OpenGLFrameTexturedSurface
ShaderWrapper <manim.renderer.shader_wrapper.ShaderWrapper object at 0x7f2a3bbc78b0> texture_path: /home/mk/dev/manim/ecc/gist/assets/MainScene0184.png
OpenGlRenderer.render_mobject mobject: OpenGLFrameTexturedSurface shader_wrapper_list: [<manim.renderer.shader_wrapper.ShaderWrapper object at 0x7f2a3bbc78b0>]
OpenGLRenderer.get_texture_id <PIL.Image.Image image mode=RGBA size=854x480 at 0x7F2A3BBC70D0> /home/mk/dev/manim/ecc/gist/assets/MainScene0184.png -> 128
>>> OpenGLRenderer.get_texture_id wants to return 128, but it should return 184 instead!
OpenGLRenderer.get_texture_id <PIL.Image.Image image mode=RGBA size=854x480 at 0x7F2A3BBC76A0> /home/mk/dev/manim/ecc/gist/assets/MainScene0184.png -> 154
Mesh.render <manim.renderer.shader.Mesh object at 0x7f2a3bbc79d0> self.shader: <manim.renderer.shader.Shader object at 0x7f2a3bbc7a00>
OpenGLMobject.get_shader_wrapper OpenGLFrameTexturedSurface
ShaderWrapper <manim.renderer.shader_wrapper.ShaderWrapper object at 0x7f2a3bbc7e20> texture_path: /home/mk/dev/manim/ecc/gist/assets/MainScene0185.png

After replacing repr(path) with hash(path.file_name) the video renders nicely as expected. However I don't think, that this is an appropriate fix.

If an OpenGLMobject gets removed (e.g. via Scene.replace) from the scene, I assume the textures should also be released.

Also OpenGLRenderer.path_to_texture_id should not be constantly growing. Some housekeeping might be required.

How to reproduce the issue

In order to run this code you need images assets/MainScene0000.png ... assets/MainScene0195.png. Then render the script with low quality, i.e. 15 frames/second, resulting in 13s video output.

Code for reproducing the problem
from manim import *
from manim.opengl import *
import os
from pathlib import Path

config.renderer = "opengl"

def texture(frame):
  return (
    Path(os.path.realpath(__file__)).parent
    / "assets"
    / ("MainScene%04d.png" % frame)
  )

class OpenGLTorus(OpenGLSurface):
  def func(self, u, v):
    P = np.array([np.cos(u), np.sin(u), 0])
    return (self.R - self.r * np.cos(v)) * P - self.r * np.sin(v) * OUT

  def __init__(self, **kwargs):
    self.R = 4
    self.r = 1

    super().__init__(
      uv_func=self.func,
      u_range=(0, TAU),
      v_range=(0, TAU),
      resolution=(101, 101),
      **kwargs,
    )

def create_torus_surface(torus, frame):
  return OpenGLTexturedSurface(torus, texture(frame)).scale(0.8).set_opacity(0.7)

class AnimateTorusTexture(ThreeDScene):
  def construct(self):
    config.disable_caching = True

    torus = OpenGLTorus()
    frame = 0
    torus_surface = create_torus_surface(torus, frame)

    def replace_torus(dt):
      nonlocal torus_surface, frame
      new_surface = create_torus_surface(torus, frame)
      self.replace(torus_surface, new_surface)
      torus_surface = new_surface
      frame += 1

    trk = ValueTracker()
    self.add(torus_surface)
    self.add_updater(replace_torus)
    self.play(trk.animate.set_value(1), run_time=13)
    self.remove_updater(replace_torus)

Additional media files

Images/GIFs

Logs

Terminal output
PASTE HERE OR PROVIDE LINK TO https://pastebin.com/ OR SIMILAR

System specifications

System Details
  • OS: Arch Linux
  • Kernel: x86_64 Linux 6.5.3-arch1-1
  • RAM: 32G
  • Python version: Python 3.9.18 in .venv
  • Installed modules (provide output from pip list):
Package                        Version
------------------------------ ----------
absl-py                        1.4.0
accelerate                     0.22.0
aiohttp                        3.8.5
aiosignal                      1.3.1
anyascii                       0.3.2
appdirs                        1.4.4
async-timeout                  4.0.3
attrs                          23.1.0
audioread                      3.0.0
azure-cognitiveservices-speech 1.31.0
Babel                          2.12.1
bangla                         0.0.2
blinker                        1.6.2
bnnumerizer                    0.0.2
bnunicodenormalizer            0.1.1
boltons                        23.0.0
cachetools                     5.3.1
certifi                        2023.7.22
cffi                           1.15.1
charset-normalizer             3.2.0
clean-fid                      0.1.35
click                          8.1.7
click-default-group            1.2.4
clip-anytorch                  2.5.2
cloup                          0.13.1
cmake                          3.27.2
colour                         0.1.5
contourpy                      1.1.0
coqpit                         0.0.17
cycler                         0.11.0
Cython                         0.29.30
dateparser                     1.1.8
decorator                      5.1.1
deepl                          1.15.0
docker-pycreds                 0.4.0
docopt                         0.6.2
einops                         0.6.1
encodec                        0.1.1
evdev                          1.6.1
ffmpeg-python                  0.2.0
filelock                       3.12.3
Flask                          2.3.3
fonttools                      4.42.1
frozenlist                     1.4.0
fsspec                         2023.9.0
ftfy                           6.1.1
future                         0.18.3
g2pkk                          0.1.2
gitdb                          4.0.10
GitPython                      3.1.34
glcontext                      2.4.0
google-auth                    2.22.0
google-auth-oauthlib           1.0.0
grpcio                         1.57.0
gruut                          2.2.3
gruut-ipa                      0.13.0
gruut-lang-de                  2.0.0
gruut-lang-en                  2.0.0
gruut-lang-es                  2.0.0
gruut-lang-fr                  2.0.2
gTTS                           2.3.2
huggingface-hub                0.16.4
idna                           3.4
imageio                        2.31.3
importlib-metadata             6.8.0
importlib-resources            6.0.1
inflect                        5.6.0
isosurfaces                    0.1.0
itsdangerous                   2.1.2
jamo                           0.4.1
jieba                          0.42.1
Jinja2                         3.1.2
joblib                         1.3.2
jsonlines                      1.2.0
jsonmerge                      1.9.2
jsonschema                     4.19.0
jsonschema-specifications      2023.7.1
k-diffusion                    0.0.16
kiwisolver                     1.4.5
kornia                         0.7.0
lazy_loader                    0.3
librosa                        0.10.0
lit                            16.0.6
llvmlite                       0.40.1
manim                          0.17.3
manim-voiceover                0.3.4
ManimPango                     0.4.3
mapbox-earcut                  1.0.1
Markdown                       3.4.4
markdown-it-py                 3.0.0
MarkupSafe                     2.1.3
matplotlib                     3.7.2
mdurl                          0.1.2
moderngl                       5.8.2
moderngl-window                2.4.4
more-itertools                 10.1.0
mpmath                         1.3.0
msgpack                        1.0.5
multidict                      6.0.4
multipledispatch               1.0.0
mutagen                        1.47.0
networkx                       2.8.8
nltk                           3.8.1
num2words                      0.5.12
numba                          0.57.0
numpy                          1.22.0
nvidia-cublas-cu11             11.10.3.66
nvidia-cuda-cupti-cu11         11.7.101
nvidia-cuda-nvrtc-cu11         11.7.99
nvidia-cuda-runtime-cu11       11.7.99
nvidia-cudnn-cu11              8.5.0.96
nvidia-cufft-cu11              10.9.0.58
nvidia-curand-cu11             10.2.10.91
nvidia-cusolver-cu11           11.4.0.1
nvidia-cusparse-cu11           11.7.4.91
nvidia-nccl-cu11               2.14.3
nvidia-nvtx-cu11               11.7.91
oauthlib                       3.2.2
openai-whisper                 20230314
packaging                      23.1
pandas                         2.0.3
pathtools                      0.1.2
Pillow                         9.5.0
pip                            23.2.1
platformdirs                   3.10.0
pooch                          1.7.0
protobuf                       4.24.2
psutil                         5.9.5
pyasn1                         0.5.0
pyasn1-modules                 0.3.0
PyAudio                        0.2.13
pycairo                        1.24.0
pycparser                      2.21
pydub                          0.25.1
pyglet                         2.0.9
Pygments                       2.16.1
pynndescent                    0.5.10
pynput                         1.7.6
pyparsing                      3.0.9
pypinyin                       0.49.0
pyrr                           0.10.3
pysbd                          0.3.4
python-crfsuite                0.9.9
python-dateutil                2.8.2
python-dotenv                  0.21.1
python-slugify                 8.0.1
python-xlib                    0.33
pyttsx3                        2.90
pytz                           2023.3
PyWavelets                     1.4.1
PyYAML                         6.0.1
referencing                    0.30.2
regex                          2023.8.8
requests                       2.31.0
requests-oauthlib              1.3.1
resize-right                   0.0.2
rich                           13.5.2
rpds-py                        0.10.0
rsa                            4.9
safetensors                    0.3.3
scikit-image                   0.21.0
scikit-learn                   1.3.0
scipy                          1.11.2
screeninfo                     0.8.1
sentry-sdk                     1.30.0
setproctitle                   1.3.2
setuptools                     59.8.0
six                            1.16.0
skia-pathops                   0.7.4
smmap                          5.0.0
soundfile                      0.12.1
sox                            1.4.1
soxr                           0.3.6
srt                            3.5.3
stable-ts                      2.9.0
svgelements                    1.9.6
sympy                          1.12
tensorboard                    2.14.0
tensorboard-data-server        0.7.1
text-unidecode                 1.3
threadpoolctl                  3.2.0
tifffile                       2023.8.30
tiktoken                       0.3.1
tokenizers                     0.13.3
torch                          2.0.1
torchaudio                     2.0.2
torchdiffeq                    0.2.3
torchsde                       0.2.5
torchvision                    0.15.2
tqdm                           4.66.1
trainer                        0.0.31
trampoline                     0.1.2
transformers                   4.32.1
triton                         2.0.0
TTS                            0.16.5
typing_extensions              4.7.1
tzdata                         2023.3
tzlocal                        5.0.1
umap-learn                     0.5.1
urllib3                        1.26.16
wandb                          0.15.9
watchdog                       2.3.1
wcwidth                        0.2.6
Werkzeug                       2.3.7
wheel                          0.41.0
yarl                           1.9.2
zipp                           3.16.2
LaTeX details
  • LaTeX distribution (e.g. TeX Live 2020):
  • Installed LaTeX packages:
FFMPEG

Output of ffmpeg -version:

ffmpeg version n6.0 Copyright (c) 2000-2023 the FFmpeg developers
built with gcc 13.2.1 (GCC) 20230801
configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libjxl --enable-libmfx --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librav1e --enable-librsvg --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-nvdec --enable-nvenc --enable-opencl --enable-opengl --enable-shared --enable-version3 --enable-vulkan
libavutil      58.  2.100 / 58.  2.100
libavcodec     60.  3.100 / 60.  3.100
libavformat    60.  3.100 / 60.  3.100
libavdevice    60.  1.100 / 60.  1.100
libavfilter     9.  3.100 /  9.  3.100
libswscale      7.  1.100 /  7.  1.100
libswresample   4. 10.100 /  4. 10.100
libpostproc    57.  1.100 / 57.  1.100

Additional comments

Metadata

Metadata

Assignees

No one assigned

    Labels

    issue:bugSomething isn't working... For use in issuesopenglConcerning the OpenGL renderer.

    Type

    No type

    Projects

    Status

    🆕 New

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions