1
0

More than 1 year has passed since last update.

DearPyGuiでshadertoyのshaderを描画

Posted at

pyimguiではOpenGLのコンテキストが喧嘩して諦めた。DearPyGuiではOpenGLを使っていない記事を発見。もしかしたら、OpenGLが使えるのではで試して成功。
まあ、説明がどうこうではないのでサンプルだけ。

import dearpygui.dearpygui as dpg
from OpenGL.GL import *
from OpenGL.WGL import *
from ctypes import *
import numpy as np

# OpenGL Context init
xsc, ysc =windll.user32.GetSystemMetrics(0),windll.user32.GetSystemMetrics(1)
hwnd = windll.user32.CreateWindowExA(0,0xC018,0,0,0,0,xsc,ysc,0,0,0,0)
hdc = windll.user32.GetDC(hwnd)
pfd = PIXELFORMATDESCRIPTOR()
SetPixelFormat(hdc, ChoosePixelFormat(hdc, pfd), pfd)
wglc = wglCreateContext(hdc)
wglMakeCurrent(hdc, wglc)

# OpenGL init
program = glCreateProgram()
shader = glCreateShader(GL_FRAGMENT_SHADER)
glsl = '''
#version 300 es
precision highp float;
out vec4 fragColor;
uniform vec2 iResolution;
uniform float iTime;

void mainImage(out vec4 fragColor, in vec2 fragCoord);

void main() {
      mainImage(fragColor,gl_FragCoord.xy);
}

// shadertoy code

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord/iResolution.xy;
    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
    fragColor = vec4(col,1.0);
}
'''
glShaderSource(shader, glsl)
glCompileShader(shader)
if glGetShaderiv(shader, GL_COMPILE_STATUS) != GL_TRUE:
    raise RuntimeError(glGetShaderInfoLog(shader).decode())
glAttachShader(program, shader)
glLinkProgram(program)
glUseProgram(program)
glViewport(0, 0, 200, 200)

dpg.create_context()
dpg.create_viewport(title='Shader Window Test', width=500, height=500)
dpg.setup_dearpygui()
dpg.show_viewport()

with dpg.texture_registry(show=False):
    dpg.add_raw_texture(width=200, height=200, default_value=np.zeros(200*200*4), tag="shader_texture")
with dpg.window(label="shader"):
    dpg.add_image("shader_texture")

while dpg.is_dearpygui_running():
    glUniform2f(glGetUniformLocation(program, "iResolution"), 200, 200)
    glUniform1f(glGetUniformLocation(program, "iTime"), dpg.get_total_time())
    glRects(1, 1, -1, -1)
    pixels = glReadPixels(0, 0, 200, 200, GL_RGBA, GL_UNSIGNED_BYTE)
    pixels = np.frombuffer(pixels,dtype=np.uint8).astype(np.float32)/255.
    dpg.set_value("shader_texture", pixels)
    dpg.render_dearpygui_frame()

dpg.destroy_context()
wglMakeCurrent(0, 0)
wglDeleteContext(wglc)

これはshaderだけの描画だけど、OpenGLが使えるので、後はどうにでも展開できる。pyopenglはCのOpenGLのライブラリーのラッパーなので、作法はCと同じ。速さはCで書くには負けると思うが、気楽に書けるのが良い。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0