From 0e7d34f685349e15083c28b6d1ee906dd4e7de31 Mon Sep 17 00:00:00 2001 From: Daniel Pope Date: Sun, 26 Jul 2020 18:04:21 +0100 Subject: [PATCH] Add lighting to Pong --- examples/pong/images/bat_light.png | Bin 0 -> 12100 bytes examples/pong/images/point_light.png | Bin 0 -> 4453 bytes examples/pong/lights.svg | 136 +++++++++++++++++++++++++++ examples/pong/pong.py | 46 ++++++--- wasabi2d/chain.py | 56 +++++++++++ wasabi2d/effects/additive.py | 24 +++++ wasabi2d/scene.py | 2 +- wasabi2d/shaders.py | 8 +- 8 files changed, 255 insertions(+), 17 deletions(-) create mode 100644 examples/pong/images/bat_light.png create mode 100644 examples/pong/images/point_light.png create mode 100644 examples/pong/lights.svg create mode 100644 wasabi2d/effects/additive.py diff --git a/examples/pong/images/bat_light.png b/examples/pong/images/bat_light.png new file mode 100644 index 0000000000000000000000000000000000000000..a4d3c1b4e6f2f3fa5c597938724abedd1a9d5690 GIT binary patch literal 12100 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 literal 0 HcmV?d00001 diff --git a/examples/pong/lights.svg b/examples/pong/lights.svg new file mode 100644 index 0000000..f80d6bc --- /dev/null +++ b/examples/pong/lights.svg @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/examples/pong/pong.py b/examples/pong/pong.py index 91cbbf3..899f250 100644 --- a/examples/pong/pong.py +++ b/examples/pong/pong.py @@ -2,15 +2,30 @@ import random from pygame.math import Vector2 from wasabi2d.keyboard import keys +from wasabi2d import chain mode_1080p = 1920, 1080 scene = w2d.Scene( *mode_1080p, fullscreen=True, - background='#444455' ) scene.layers[0].set_effect('dropshadow', opacity=0.5) +scene.layers[99].set_effect('additive') +scene.chain = [ + chain.Light( + light=[ + chain.Layers([99]), + ], + diffuse=[ + chain.Fill('#444455'), + chain.LayerRange(stop=10), + ], + ambient='#444444' + ) +] + + center = Vector2(scene.width, scene.height) / 2 red_score = scene.layers[-1].add_label( @@ -31,27 +46,36 @@ color='cyan' ) -red = scene.layers[0].add_sprite( - 'bat_red', - pos=(50, center.y) -) +red = w2d.Group( + [ + scene.layers[0].add_sprite('bat_red'), + scene.layers[99].add_sprite('bat_light', color=(1, 0, 0, 0.5)), + ], + pos=(50, center.y)) + red.up_key = keys.Q red.down_key = keys.A -blue = scene.layers[0].add_sprite( - 'bat_blue', +blue = w2d.Group( + [ + scene.layers[0].add_sprite('bat_blue'), + scene.layers[99].add_sprite('bat_light', color=(0, 1, 1, 0.5)), + ], pos=(scene.width - 50, center.y) ) blue.up_key = keys.I blue.down_key = keys.K -ball = scene.layers[0].add_sprite( - 'ball', +ball = w2d.Group( + [ + scene.layers[0].add_sprite('ball'), + scene.layers[99].add_sprite('point_light', scale=5, color=(1, 1, 1, 0.3)), + ], pos=center ) SPEED = 1000 -BALL_RADIUS = ball.width / 2 +BALL_RADIUS = ball[0].width / 2 def start(): @@ -63,7 +87,7 @@ def start(): def collide_bat(bat): - bounds = bat.bounds.inflate(BALL_RADIUS, BALL_RADIUS) + bounds = bat[0].bounds.inflate(BALL_RADIUS, BALL_RADIUS) if bounds.collidepoint(ball.pos): x, y = ball.pos vx, vy = ball.vel diff --git a/wasabi2d/chain.py b/wasabi2d/chain.py index 1833f30..aa9b4de 100644 --- a/wasabi2d/chain.py +++ b/wasabi2d/chain.py @@ -219,6 +219,62 @@ def draw(self, scene): ) +LIGHT_PROG = """ \ +#version 330 core + +in vec2 uv; +out vec4 f_color; +uniform sampler2D diffuse; +uniform sampler2D light; +uniform vec4 ambient; + +vec4 unpremultiply(vec4 val) { + if (val.a < 1e-6) { + return vec4(0.0, 0.0, 0.0, 0.0); + } + return vec4(val.rgb / val.a, val.a); +} + +vec4 sample_unmul(sampler2D sampler) { + //return unpremultiply(texture(sampler, uv)); + return texture(sampler, uv); +} + +void main() +{ + vec4 diffuse_frag = sample_unmul(diffuse); + vec4 light_frag = sample_unmul(light); + + f_color = (light_frag + ambient) * diffuse_frag; +} +""" + + +@dataclass +class Light(ChainNode): + """Light one 'diffuse' layer using the 'light' layer.""" + + light: ChainNode + diffuse: ChainNode + ambient: Tuple[float, float, float, float] + + def __post_init__(self): + self.light = to_node(self.light) + self.diffuse = to_node(self.diffuse) + self.ambient = convert_color(self.ambient) + + def draw(self, scene): + """Draw the effect.""" + with rendered_node(scene, self.diffuse) as diffuse, \ + rendered_node(scene, self.light) as light: + scene.camera.run_shader( + LIGHT_PROG, + diffuse=diffuse, + light=light, + ambient=self.ambient, + ) + + class Fill(ChainNode): """Fill the screen with a single colour. diff --git a/wasabi2d/effects/additive.py b/wasabi2d/effects/additive.py new file mode 100644 index 0000000..5583047 --- /dev/null +++ b/wasabi2d/effects/additive.py @@ -0,0 +1,24 @@ +from dataclasses import dataclass + +import moderngl + +from ..shaders import blend_func + + +@dataclass +class Additive: + ctx: moderngl.Context + + def _set_camera(self, camera: 'wasabi2d.scene.Camera'): + """Nothing to do here.""" + + def draw(self, draw_layer): + """Draw the wrapped effects with additive blending.""" + with blend_func( + self.ctx, + src=moderngl.SRC_ALPHA, + dest=moderngl.ONE, + src_a=moderngl.ONE, + dest_a=moderngl.ONE, + ): + draw_layer() diff --git a/wasabi2d/scene.py b/wasabi2d/scene.py index 9176fd3..04fecee 100644 --- a/wasabi2d/scene.py +++ b/wasabi2d/scene.py @@ -106,7 +106,7 @@ def __init__( self.layers = LayerGroup(ctx, self.camera) ctx.enable(moderngl.BLEND) - self.ctx.blend_func = ( + self.ctx.extra['blend_func'] = self.ctx.blend_func = ( moderngl.SRC_ALPHA, moderngl.ONE_MINUS_SRC_ALPHA, moderngl.ONE, moderngl.ONE_MINUS_SRC_ALPHA, ) diff --git a/wasabi2d/shaders.py b/wasabi2d/shaders.py index bd3c1f6..2cdafa4 100644 --- a/wasabi2d/shaders.py +++ b/wasabi2d/shaders.py @@ -167,11 +167,9 @@ def blend_func( src_a = blend_aliases.get(src_a, src_a) dest_a = blend_aliases.get(dest_a, dest_a) - ctx.blend_func = src, dest, src_a, dest_a + prev_blend = ctx.extra['blend_func'] + ctx.extra['blend_func'] = ctx.blend_func = src, dest, src_a, dest_a try: yield finally: - ctx.blend_func = ( - moderngl.SRC_ALPHA, moderngl.ONE_MINUS_SRC_ALPHA, - moderngl.ONE, moderngl.ONE_MINUS_SRC_ALPHA - ) + ctx.blend_func = prev_blend