I just saw a cool video introduction to shaders (well, fragment shaders) that mentioned shadertoy. Cool, but if you’re hanging out around here, you probably want to dive right into doing that stuff with Panda3D. So, here’s your panda3dtoy.py:
from direct.showbase.ShowBase import ShowBase
from panda3d.core import CardMaker
from panda3d.core import Shader
from panda3d.core import Vec2
from panda3d.core import WindowProperties
vertex_shader_source = """#version 430
uniform mat4 p3d_ModelViewProjectionMatrix;
in vec4 vertex;
in vec2 texcoord;
out vec2 uv;
void main() {
gl_Position = p3d_ModelViewProjectionMatrix * vertex;
uv = texcoord;
}
"""
fragment_shader_source = """#version 430
uniform float dt;
uniform float time;
uniform vec2 aspect;
in vec2 uv;
out vec4 fragColor;
void main() {
float d = length((uv*2-1) * aspect);
fragColor = vec4(sin(d*2*3.141592 * 10 + time * 20), 0, 0, 1);
}
"""
ShowBase()
base.accept('escape', base.task_mgr.stop)
base.disableMouse()
card_maker = CardMaker('card')
card_maker.set_frame(-1, 1, -1, 1)
card = base.render2d.attach_new_node(card_maker.generate())
shader = Shader.make(
Shader.SL_GLSL,
vertex=vertex_shader_source,
fragment=fragment_shader_source,
)
card.set_shader(shader)
def update_shader_inputs(task):
card.set_shader_input('dt', globalClock.dt)
card.set_shader_input('time', task.time)
top_right = base.a2dTopRight.get_pos()
card.set_shader_input('aspect', Vec2(top_right.x, top_right.z))
return task.cont
fullscreen = [False]
def toggle_fullscreen():
fullscreen[0] = not fullscreen[0]
wp = WindowProperties()
wp.fullscreen = fullscreen[0]
wp.cursor_hidden = fullscreen[0]
base.win.requestProperties(wp)
base.task_mgr.add(update_shader_inputs)
base.accept('f', toggle_fullscreen)
base.run()
Press escape to exit, and f to toggle fullscreen mode.