From 6a3be55fe2949df4908a04683dfb6a4d67f34f06 Mon Sep 17 00:00:00 2001 From: Matt Lebrun Date: Sat, 19 Sep 2020 16:02:17 +0800 Subject: [PATCH 1/2] More core examples (#13) * Added core_input_keys example * Added core_basic_window example * Added core_input_mouse example * Added core_input_mouse_wheel example * Added Rectangle struct * Added core_input_gestures example to utilize the Rectangle struct * Removed unused imports * Used the right draw function for the example * PEP8 fixes * Added core 2d camera examples * Added core 2d camera examples --- examples/core/core_2d_camera.py | 137 +++++++++ examples/core/core_2d_camera_platformer.py | 314 +++++++++++++++++++++ examples/core/core_input_gestures.py | 9 +- examples/core/core_input_keys.py | 12 +- 4 files changed, 462 insertions(+), 10 deletions(-) create mode 100644 examples/core/core_2d_camera.py create mode 100644 examples/core/core_2d_camera_platformer.py diff --git a/examples/core/core_2d_camera.py b/examples/core/core_2d_camera.py new file mode 100644 index 0000000..ece199e --- /dev/null +++ b/examples/core/core_2d_camera.py @@ -0,0 +1,137 @@ +""" + +raylib [core] example - 2d camera + +""" +from raylib.pyray import PyRay +from raylib.colors import ( + RAYWHITE, + DARKGRAY, + RED, + GREEN, + SKYBLUE, + BLUE, + BLACK, +) + + +pyray = PyRay() + +# Initialization +MAX_BUILDINGS = 100 +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 450 + +pyray.init_window(SCREEN_WIDTH, SCREEN_HEIGHT, + 'raylib [core] example - 2d camera') + +player = pyray.Rectangle(400, 280, 40, 40) +buildings = [] +build_colors = [] +spacing = 0 + +for i in range(MAX_BUILDINGS): + width = pyray.get_random_value(50, 200) + height = pyray.get_random_value(100, 800) + y = SCREEN_HEIGHT - 130 - height + x = -6000 + spacing + + buildings.append(pyray.Rectangle(x, y, width, height)) + + spacing += width + + build_colors.append(pyray.Color( + pyray.get_random_value(200, 240), + pyray.get_random_value(200, 240), + pyray.get_random_value(200, 250), + 255 + )) + +camera = pyray.Camera2D() +camera.target = pyray.Vector2(player.x + 20, player.y + 20) +camera.offset = pyray.Vector2(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2) +camera.rotation = 0.0 +camera.zoom = 1.0 + +pyray.set_target_fps(60) # Set our game to run at 60 frames-per-second + + +# Main game loop +while not pyray.window_should_close(): # Detect window close button or ESC key + # Update + + # Player movement + if pyray.is_key_down(pyray.KEY_RIGHT): + player.x += 2 + elif pyray.is_key_down(pyray.KEY_LEFT): + player.x -= 2 + + # Camera target follows player + camera.target = pyray.Vector2(player.x + 20, player.y + 20) + + # Camera rotation controls + if pyray.is_key_down(pyray.KEY_A): + camera.rotation -= 1 + elif pyray.is_key_down(pyray.KEY_S): + camera.rotation += 1 + + # Limit camera rotation to 80 degrees (-40 to 40) + if camera.rotation > 40: + camera.rotation = 40 + elif camera.rotation < -40: + camera.rotation = -40 + + # Camera zoom controls + camera.zoom += pyray.get_mouse_wheel_move() * 0.05 + + if camera.zoom > 3.0: + camera.zoom = 3.0 + elif camera.zoom < 0.1: + camera.zoom = 0.1 + + # Camera reset (zoom and rotation) + if pyray.is_key_pressed(pyray.KEY_R): + camera.zoom = 1.0 + camera.rotation = 0.0 + + # Draw + pyray.begin_drawing() + pyray.clear_background(RAYWHITE) + + pyray.begin_mode_2d(camera) + + pyray.draw_rectangle(-6000, 320, 13000, 8000, DARKGRAY) + + for i in range(MAX_BUILDINGS): + pyray.draw_rectangle_rec(buildings[i], build_colors[i]) + + pyray.draw_rectangle_rec(player, RED) + + x = int(camera.target.x) + y = int(camera.target.y) + pyray.draw_line(x, -SCREEN_HEIGHT * 10, x, SCREEN_HEIGHT * 10, GREEN) + pyray.draw_line(-SCREEN_WIDTH * 10, y, SCREEN_WIDTH * 10, y, GREEN) + + pyray.end_mode_2d() + + pyray.draw_text('SCREEN AREA', 640, 10, 20, RED) + + pyray.draw_rectangle(0, 0, SCREEN_WIDTH, 5, RED) + pyray.draw_rectangle(0, 5, 5, SCREEN_HEIGHT - 10, RED) + pyray.draw_rectangle(SCREEN_WIDTH - 5, 5, 5, SCREEN_HEIGHT - 10, RED) + pyray.draw_rectangle(0, SCREEN_HEIGHT - 5, SCREEN_WIDTH, 5, RED) + + pyray.draw_rectangle(10, 10, 250, 113, pyray.fade(SKYBLUE, 0.5)) + pyray.draw_rectangle_lines(10, 10, 250, 113, BLUE) + + pyray.draw_text('Free 2d camera controls:', 20, 20, 10, BLACK) + pyray.draw_text('- Right/Left to move Offset', 40, 40, 10, DARKGRAY) + pyray.draw_text('- Mouse Wheel to Zoom in-out', 40, 60, 10, DARKGRAY) + pyray.draw_text('- A / S to Rotate', 40, 80, 10, DARKGRAY) + pyray.draw_text('- R to reset Zoom and Rotation', 40, 100, 10, DARKGRAY) + + pyray.end_drawing() + + +# De-Initialization +pyray.close_window() # Close window and OpenGL context diff --git a/examples/core/core_2d_camera_platformer.py b/examples/core/core_2d_camera_platformer.py new file mode 100644 index 0000000..4737798 --- /dev/null +++ b/examples/core/core_2d_camera_platformer.py @@ -0,0 +1,314 @@ +""" + +raylib [core] example - 2d camera platformer + +""" +from math import sqrt + +from raylib.pyray import PyRay +from raylib.colors import ( + DARKGRAY, + RED, + BLACK, + GRAY, + LIGHTGRAY, +) + + +pyray = PyRay() + +# Initialization +global g_evening_out, g_even_out_target +g_evening_out = False + +G = 400 +PLAYER_JUMP_SPD = 350.0 +PLAYER_HOR_SPD = 200.0 + +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 450 + +pyray.init_window(SCREEN_WIDTH, SCREEN_HEIGHT, + 'raylib [core] example - 2d camera') + + +# Raylib Math +def vector2_subtract(v1, v2): + return pyray.Vector2(v1.x - v2.x, v1.y - v2.y) + + +def vector2_add(v1, v2): + return pyray.Vector2(v1.x + v2.x, v1.y + v2.y) + + +def vector2_length(v): + return sqrt((v.x * v.x) + (v.y * v.y)) + + +def vector2_scale(v, scale): + return pyray.Vector2(v.x * scale, v.y * scale) + + +class Player: + + def __init__(self, position, speed, can_jump): + self.position = position + self.speed = speed + self.can_jump = can_jump + + +class EnvItem: + + def __init__(self, rect, blocking, color): + self.rect = rect + self.blocking = blocking + self.color = color + + +def update_player(player, env_items, delta): + if pyray.is_key_down(pyray.KEY_LEFT): + player.position.x -= PLAYER_HOR_SPD * delta + if pyray.is_key_down(pyray.KEY_RIGHT): + player.position.x += PLAYER_HOR_SPD * delta + if pyray.is_key_down(pyray.KEY_SPACE) and player.can_jump: + player.speed = -PLAYER_JUMP_SPD + player.can_jump = False + + hit_obstacle = False + for ei in env_items: + p = player.position + if ( + ei.blocking and + ei.rect.x <= p.x and + ei.rect.x + ei.rect.width >= p.x and + ei.rect.y >= p.y and + ei.rect.y < p.y + player.speed * delta + ): + hit_obstacle = True + player.speed = 0.0 + p.y = ei.rect.y + + if not hit_obstacle: + player.position.y += player.speed * delta + player.speed += G * delta + player.can_jump = False + else: + player.can_jump = True + + +def update_camera_center( + camera, player, env_items, delta, width, height +): + camera.offset = pyray.Vector2(width / 2, height / 2) + camera.target = player.position + + +def update_camera_center_inside_map( + camera, player, env_items, delta, width, height +): + camera.target = player.position + camera.offset = pyray.Vector2(width / 2, height / 2) + + minX = 1000 + minY = 1000 + maxX = -1000 + maxY = -1000 + + for ei in env_items: + minX = min(ei.rect.x, minX) + maxX = max(ei.rect.x + ei.rect.width, maxX) + + minY = min(ei.rect.y, minY) + maxY = max(ei.rect.y + ei.rect.height, maxY) + + wmax = pyray.get_world_to_screen_2d(pyray.Vector2(maxX, maxY), camera) + wmin = pyray.get_world_to_screen_2d(pyray.Vector2(minX, minY), camera) + + if wmax.x < width: + camera.offset.x = width - (wmax.x - width / 2) + if wmax.y < height: + camera.offset.y = height - (wmax.y - height / 2) + if wmin.x > 0: + camera.offset.x = width / 2 - wmin.x + if wmin.y > 0: + camera.offset.y = height / 2 - wmin.y + + +def update_camera_center_smooth_follow( + camera, player, env_items, delta, width, height +): + min_speed = 30 + min_effect_length = 10 + fraction_speed = 0.8 + + camera.offset = pyray.Vector2(width / 2, height / 2) + diff = vector2_subtract(player.position, camera.target) + length = vector2_length(diff) + + if length > min_effect_length: + speed = max(fraction_speed * length, min_speed) + camera.target = vector2_add( + camera.target, vector2_scale(diff, speed * delta / length) + ) + + +def update_camera_even_out_on_landing( + camera, player, env_items, delta, width, height +): + global g_evening_out, g_even_out_target + + even_out_speed = 700 + + camera.offset = pyray.Vector2(width / 2, height / 2) + camera.target.x = player.position.x + + if g_evening_out: + if g_even_out_target > camera.target.y: + camera.target.y += even_out_speed * delta + + if camera.target.y > g_even_out_target: + camera.target.y = g_even_out_target + g_evening_out = False + else: + camera.target.y -= even_out_speed * delta + if camera.target.y < g_even_out_target: + camera.target.y = g_even_out_target + g_evening_out = False + else: + if ( + player.can_jump and + (player.speed == 0) and + (player.position.y != camera.target.y) + ): + g_evening_out = True + g_even_out_target = player.position.y + + +def update_camera_player_bounds_push( + camera, player, env_items, delta, width, height +): + bbox = pyray.Vector2(0.2, 0.2) + + bbox_world_min = pyray.get_world_to_screen_2d( + pyray.Vector2((1 - bbox.x) * 0.5 * width, + (1 - bbox.y) * 0.5 * height), + camera + ) + bbox_world_max = pyray.get_world_to_screen_2d( + pyray.Vector2((1 + bbox.x) * 0.5 * width, + (1 + bbox.y) * 0.5 * height), + camera + ) + camera.offset = pyray.Vector2((1 - bbox.x) * 0.5 * width, + (1 - bbox.y) * 0.5 * height) + + if player.position.x < bbox_world_min.x: + camera.target.x = player.position.x + if player.position.y < bbox_world_min.y: + camera.target.y = player.position.y + if player.position.x > bbox_world_max.x: + camera.target.x = ( + bbox_world_min.x + (player.position.x - bbox_world_max.x) + ) + if player.position.y > bbox_world_max.y: + camera.target.y = ( + bbox_world_min.y + (player.position.y - bbox_world_max.y) + ) + + +# Main intialization +player = Player(pyray.Vector2(400, 280), 0, False) +env_items = ( + EnvItem(pyray.Rectangle(0, 0, 1000, 400), 0, LIGHTGRAY), + EnvItem(pyray.Rectangle(0, 400, 1000, 200), 1, GRAY), + EnvItem(pyray.Rectangle(300, 200, 400, 10), 1, GRAY), + EnvItem(pyray.Rectangle(250, 300, 100, 10), 1, GRAY), + EnvItem(pyray.Rectangle(650, 300, 100, 10), 1, GRAY), +) + +camera = pyray.Camera2D() +camera.target = player.position +camera.offset = pyray.Vector2(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2) +camera.rotation = 0.0 +camera.zoom = 1.0 + +pyray.set_target_fps(60) # Set our game to run at 60 frames-per-second + +# Store pointers to the multiple update camera functions +camera_updaters = ( + update_camera_center, + update_camera_center_inside_map, + update_camera_center_smooth_follow, + update_camera_even_out_on_landing, + update_camera_player_bounds_push, +) +camera_option = 0 +camera_updaters_length = len(camera_updaters) + +camera_descriptions = ( + 'Follow player center', + 'Follow player center, but clamp to map edges', + 'Follow player center smoothed', + ('Follow player center horizontally ' + 'update player center vertically after landing'), + 'Player push camera on getting too close to screen edge', +) + +# Main game loop +while not pyray.window_should_close(): # Detect window close button or ESC key + # Update + delta_time = pyray.get_frame_time() + + update_player(player, env_items, delta_time) + + camera.zoom += pyray.get_mouse_wheel_move() * 0.05 + + if camera.zoom > 3.0: + camera.zoom = 3.0 + elif camera.zoom < 0.25: + camera.zoom = 0.25 + + if pyray.is_key_pressed(pyray.KEY_R): + camera.zoom = 1.0 + player.position = pyray.Vector2(400, 280) + + if pyray.is_key_pressed(pyray.KEY_C): + camera_option = (camera_option + 1) % camera_updaters_length + + # Call update camera function by its pointer + camera_updaters[camera_option]( + camera, player, env_items, delta_time, + SCREEN_WIDTH, SCREEN_HEIGHT + ) + + # Draw + pyray.begin_drawing() + pyray.clear_background(LIGHTGRAY) + + pyray.begin_mode_2d(camera) + + for env_item in env_items: + pyray.draw_rectangle_rec(env_item.rect, env_item.color) + + player_rect = pyray.Rectangle( + int(player.position.x) - 20, + int(player.position.y) - 40, + 40, 40 + ) + pyray.draw_rectangle_rec(player_rect, RED) + + pyray.end_mode_2d() + + pyray.draw_text('Controls:', 20, 20, 10, BLACK) + pyray.draw_text('- Right/Left to move', 40, 40, 10, DARKGRAY) + pyray.draw_text('- Space to jump', 40, 60, 10, DARKGRAY) + pyray.draw_text('- Mouse Wheel to Zoom in-out, R to reset zoom', + 40, 80, 10, DARKGRAY) + pyray.draw_text('- C to change camera mode', 40, 100, 10, DARKGRAY) + pyray.draw_text('Current camera mode:', 20, 120, 10, BLACK) + pyray.draw_text(camera_descriptions[camera_option], 40, 140, 10, DARKGRAY) + + pyray.end_drawing() + +# De-Initialization +pyray.close_window() # Close window and OpenGL context diff --git a/examples/core/core_input_gestures.py b/examples/core/core_input_gestures.py index 765654b..9d60bfd 100644 --- a/examples/core/core_input_gestures.py +++ b/examples/core/core_input_gestures.py @@ -3,7 +3,7 @@ raylib [core] example - Input Gestures Detection """ -from raylib.pyray import PyRay, makeStructHelper +from raylib.pyray import PyRay from raylib.colors import ( RAYWHITE, LIGHTGRAY, @@ -73,15 +73,11 @@ while not pyray.window_should_close(): # Detect window close button or ESC key pyray.draw_rectangle_rec(touch_area, GRAY) pyray.draw_rectangle(225, 15, SCREEN_WIDTH - 240, SCREEN_HEIGHT - 30, RAYWHITE) - pyray.draw_text( 'GESTURES TEST AREA', SCREEN_WIDTH - 270, SCREEN_HEIGHT - 40, 20, pyray.fade(GRAY, 0.5) ) - pyray.draw_rectangle(10, 29, 200, SCREEN_HEIGHT - 50, GRAY) - pyray.draw_text('DETECTED GESTURES', 50, 15, 10, GRAY) - for i, val in enumerate(gesture_strings): if i % 2 == 0: pyray.draw_rectangle( @@ -95,11 +91,12 @@ while not pyray.window_should_close(): # Detect window close button or ESC key else: pyray.draw_text(val, 35, 36 + 20 * i, 10, MAROON) + pyray.draw_rectangle_lines(10, 29, 200, SCREEN_HEIGHT - 50, GRAY) + pyray.draw_text('DETECTED GESTURES', 50, 15, 10, GRAY) if current_gesture != pyray.GESTURE_NONE: pyray.draw_circle_v(touch_position, 30, MAROON) - pyray.end_drawing() diff --git a/examples/core/core_input_keys.py b/examples/core/core_input_keys.py index 3680d6e..87883e0 100644 --- a/examples/core/core_input_keys.py +++ b/examples/core/core_input_keys.py @@ -28,10 +28,14 @@ pyray.set_target_fps(60) # Set our game to run at 60 frames-per-second # Main game loop while not pyray.window_should_close(): # Detect window close button or ESC key # Update - if pyray.is_key_down(pyray.KEY_RIGHT): ball_position.x += 2 - if pyray.is_key_down(pyray.KEY_LEFT): ball_position.x -= 2 - if pyray.is_key_down(pyray.KEY_UP): ball_position.y -= 2 - if pyray.is_key_down(pyray.KEY_DOWN): ball_position.y += 2 + if pyray.is_key_down(pyray.KEY_RIGHT): + ball_position.x += 2 + if pyray.is_key_down(pyray.KEY_LEFT): + ball_position.x -= 2 + if pyray.is_key_down(pyray.KEY_UP): + ball_position.y -= 2 + if pyray.is_key_down(pyray.KEY_DOWN): + ball_position.y += 2 # Draw pyray.begin_drawing() From e49e2b4d65039c523d12754c96a865282238373d Mon Sep 17 00:00:00 2001 From: chriscamacho Date: Sat, 19 Sep 2020 09:07:39 +0100 Subject: [PATCH 2/2] completed fog example (#18) * complete fog example as both fog and basic lighting need the light system it made sense to seperate it out, there are a few functions from raymath int rlmath.py * added shaders custom uniform * added shaders_texture_waves.py * added shaders_texture_drawing.py * bug fix - unwanted transparent effect! Co-authored-by: codifies --- examples/shaders/fog.py | 94 ------ examples/shaders/light_system.py | 99 ++++++ .../shaders/resources/shaders/fogLight.fs | 2 + examples/shaders/rlmath.py | 93 ++++++ examples/shaders/shaders_basic_lighting.py | 287 ++++-------------- examples/shaders/shaders_custom_uniform.py | 99 ++++++ examples/shaders/shaders_fog.py | 106 +++++++ examples/shaders/shaders_texture_drawing.py | 75 +++++ examples/shaders/shaders_texture_waves.py | 90 ++++++ 9 files changed, 617 insertions(+), 328 deletions(-) delete mode 100644 examples/shaders/fog.py create mode 100644 examples/shaders/light_system.py create mode 100644 examples/shaders/rlmath.py mode change 100644 => 100755 examples/shaders/shaders_basic_lighting.py create mode 100755 examples/shaders/shaders_custom_uniform.py create mode 100755 examples/shaders/shaders_fog.py create mode 100644 examples/shaders/shaders_texture_drawing.py create mode 100755 examples/shaders/shaders_texture_waves.py diff --git a/examples/shaders/fog.py b/examples/shaders/fog.py deleted file mode 100644 index 3cc18b1..0000000 --- a/examples/shaders/fog.py +++ /dev/null @@ -1,94 +0,0 @@ -""" -Example converted to Python from: -http://bedroomcoders.co.uk/raylib-fog/ -""" - -from raylib.dynamic import raylib as rl, ffi -from raylib.colors import * - -rl.SetConfigFlags(rl.FLAG_MSAA_4X_HINT | rl.FLAG_WINDOW_RESIZABLE) -rl.InitWindow(1280, 768, b'Fog Test') - -camera = ffi.new('struct Camera3D *', [ - [2, 2, 6], - [0, 5, 0], - [0, 1, 0], - 45, - rl.CAMERA_PERSPECTIVE -]) - -model = rl.LoadModelFromMesh(rl.GenMeshTorus(0.4, 1, 16, 32)) -model2 = rl.LoadModelFromMesh(rl.GenMeshCube(1, 1, 1)) -model3 = rl.LoadModelFromMesh(rl.GenMeshSphere(0.5, 32, 32)) - -texture = rl.LoadTexture(b'resources/test.png') - -model.materials[0].maps[rl.MAP_DIFFUSE].texture = texture -model2.materials[0].maps[rl.MAP_DIFFUSE].texture = texture -model3.materials[0].maps[rl.MAP_DIFFUSE].texture = texture - -shader = rl.LoadShader(b'resources/shaders/fogLight.vs', b'resources/shaders/fogLight.fs') -shader.locs[rl.LOC_MATRIX_MODEL] = rl.GetShaderLocation(shader, b'matModel') -shader.locs[rl.LOC_VECTOR_VIEW] = rl.GetShaderLocation(shader, b'viewPos') - -amb = rl.GetShaderLocation(shader, b'ambient') -rl.SetShaderValue(shader, amb, ffi.new('float[]', [0.2, 0.2, 0.2, 1.0]), rl.UNIFORM_VEC4) - -fog_color = [0.2, 0.2, 1.0, 1.0] -fogC = rl.GetShaderLocation(shader, b'fogColor') -rl.SetShaderValue(shader, fogC, ffi.new('float[]', fog_color), rl.UNIFORM_VEC4) - -fogD = rl.GetShaderLocation(shader, b'FogDensity') -fogDensity = 0.12 -rl.SetShaderValue(shader, fogD, ffi.new('float[]', [fogDensity]), rl.UNIFORM_FLOAT) - - -model.materials[0].shader = shader -model2.materials[0].shader = shader -model3.materials[0].shader = shader - -rl.SetCameraMode(camera[0], rl.CAMERA_ORBITAL) -rl.SetTargetFPS(60) - -while not rl.WindowShouldClose(): - rl.UpdateCamera(camera) - - if rl.IsKeyDown(rl.KEY_UP): - fogDensity = min(fogDensity + 0.001, 1) - - if rl.IsKeyDown(rl.KEY_DOWN): - fogDensity = max(fogDensity - 0.001, 0) - - rl.SetShaderValue(shader, fogD, ffi.new('float[]', [fogDensity]), rl.UNIFORM_FLOAT) - - rl.SetShaderValue(shader, shader.locs[rl.LOC_VECTOR_VIEW], ffi.new('float[]', [camera.position.x]), rl.UNIFORM_VEC3) - - rl.BeginDrawing() - - rl.ClearBackground([int(255 * i) for i in fog_color]) - - rl.BeginMode3D(camera[0]) - rl.DrawModel(model, [0] * 3, 1, WHITE) - rl.DrawModel(model2, [-2.6, 0, 0], 1, WHITE) - rl.DrawModel(model3, [ 2.6, 0, 0], 1, WHITE) - - for i in range(-20, 20, 2): - rl.DrawModel(model, [i, 0, 2], 1, WHITE) - - - rl.DrawGizmo([1000, 1000, 1000]) - - rl.EndMode3D() - - rl.DrawFPS(10, 10) - rl.DrawText(f'Up/Down to change fog density: {fogDensity}'.encode('utf-8'), 10, 30, 20, WHITE) - - rl.EndDrawing() - - -rl.CloseWindow() -rl.UnloadModel(model) -rl.UnloadModel(model2) -rl.UnloadModel(model3) -rl.UnloadTexture(texture) -rl.UnloadShader(shader) diff --git a/examples/shaders/light_system.py b/examples/shaders/light_system.py new file mode 100644 index 0000000..25ebfcd --- /dev/null +++ b/examples/shaders/light_system.py @@ -0,0 +1,99 @@ +from raylib.dynamic import raylib as rl, ffi + + +class LightSystem: + MAX_LIGHTS = 4 #// Max dynamic lights supported by shader + lightsCount = 0 + lights = [] + + def __init__(self, ambient = [ 0.2, 0.2, 0.2, 1.0 ], *ls): + self.shader = rl.LoadShader(b"resources/shaders/fogLight.vs", + b"resources/shaders/fogLight.fs"); + + #// Get some shader loactions + self.shader.locs[rl.LOC_MATRIX_MODEL] = rl.GetShaderLocation(self.shader, b"matModel"); + self.shader.locs[rl.LOC_VECTOR_VIEW] = rl.GetShaderLocation(self.shader, b"viewPos"); + + #// ambient light level + self.ambientLoc = rl.GetShaderLocation(self.shader, b"ambient"); + v = ffi.new("struct Vector4 *", ambient) + rl.SetShaderValue(self.shader, self.ambientLoc, v, rl.UNIFORM_VEC4); + + for light in ls: + self.add(light) + + def add(self, light): + light.configure(len(self.lights), self.shader) + self.lights.append(light) + if len(self.lights) > self.MAX_LIGHTS: + raise Exception("Too many lights") + + def update(self, cameraPos): + rl.SetShaderValue(self.shader, self.shader.locs[rl.LOC_VECTOR_VIEW], ffi.new("struct Vector3 *",cameraPos), rl.UNIFORM_VEC3) + for light in self.lights: + light.UpdateLightValues() + + def draw(self): + for light in self.lights: + if light.enabled: + rl.DrawSphereEx(light.position[0], 0.2, 8, 8, light.color) + + + + +LIGHT_DIRECTIONAL=0 +LIGHT_POINT=1 + + +class Light: + def __init__(self, type, position, target, color): + self.enabled = True + self.type = type + self.position = ffi.new("struct Vector3 *",position) + self.target = target + self.color = color + + + + + def configure(self, id, shader): + self.shader = shader + #// TODO: Below code doesn't look good to me, + #// it assumes a specific shader naming and structure + #// Probably this implementation could be improved + self.enabledName = f"lights[{id}].enabled" + self.typeName = f"lights[{id}].type" + self.posName = f"lights[{id}].position" + self.targetName = f"lights[{id}].target" + self.colorName = f"lights[{id}].color" + + self.enabledLoc = rl.GetShaderLocation(shader, self.enabledName.encode('utf-8')) + self.typeLoc = rl.GetShaderLocation(shader, self.typeName.encode('utf-8')) + self.posLoc = rl.GetShaderLocation(shader, self.posName.encode('utf-8')) + self.targetLoc = rl.GetShaderLocation(shader, self.targetName.encode('utf-8')) + self.colorLoc = rl.GetShaderLocation(shader, self.colorName.encode('utf-8')) + + self.UpdateLightValues() + + + #// Send light properties to shader + #// NOTE: Light shader locations should be available + def UpdateLightValues(self): + #// Send to shader light enabled state and type + rl.SetShaderValue(self.shader, self.enabledLoc, ffi.new("int *",self.enabled), rl.UNIFORM_INT) + rl.SetShaderValue(self.shader, self.typeLoc, ffi.new("int *",self.type), rl.UNIFORM_INT) + + #// Send to shader light position values + position = [ self.position.x, self.position.y, self.position.z] + rl.SetShaderValue(self.shader, self.posLoc, ffi.new("struct Vector3 *",position), rl.UNIFORM_VEC3) + + #// Send to shader light target position values + target =[ self.target.x, self.target.y, self.target.z ] + rl.SetShaderValue(self.shader, self.targetLoc, ffi.new("struct Vector3 *",target), rl.UNIFORM_VEC3) + + #// Send to shader light color values + color = [self.color[0]/255.0, self.color[1]/255.0, self.color[2]/255.0, self.color[3]/255.0] + rl.SetShaderValue(self.shader, self.colorLoc, ffi.new("struct Vector4 *",color), rl.UNIFORM_VEC4) + + + diff --git a/examples/shaders/resources/shaders/fogLight.fs b/examples/shaders/resources/shaders/fogLight.fs index 652143c..3841329 100644 --- a/examples/shaders/resources/shaders/fogLight.fs +++ b/examples/shaders/resources/shaders/fogLight.fs @@ -78,6 +78,7 @@ void main() // gamma finalColor = pow(finalColor, vec4(1.0/2.2)); + float dist = length(viewPos - fragPosition) ; float fogFactor = 1.0 / exp( (dist * FogDensity) * (dist * FogDensity)); @@ -88,4 +89,5 @@ void main() fogFactor = clamp( fogFactor, 0.0, 1.0 ); finalColor = mix(fogColor, finalColor, fogFactor); + } diff --git a/examples/shaders/rlmath.py b/examples/shaders/rlmath.py new file mode 100644 index 0000000..fd8a1ce --- /dev/null +++ b/examples/shaders/rlmath.py @@ -0,0 +1,93 @@ +# just a few functions from raymath +from raylib.dynamic import raylib as rl, ffi +import math + +PI = 3.14159265358979323846 +DEG2RAD = (PI/180.0) +RAD2DEG = (180.0/PI) + +def Clamp(value: float, minv: float, maxv: float): + #res = value < minv ? minv : value + res = minv if value < minv else value + #return res > maxv ? maxv : res + return maxv if res > maxv else res + +def Lerp(start: float, end: float, amount: float): + return start + amount*(end - start) + + +def Vector2Zero(): + return ffi.new("struct Vector2 *",[ 0, 0]) + +def Vector3Zero(): + return ffi.new("struct Vector3 *",[ 0, 0, 0]) + +def MatrixRotateX(angle): + result = MatrixIdentity(); + + cosres = math.cos(angle); + sinres = math.sin(angle); + + result.m5 = cosres; + result.m6 = -sinres; + result.m9 = sinres; + result.m10 = cosres; + + return result; + + + +def MatrixRotateY(angle): + result = MatrixIdentity() + + cosres = math.cos(angle); + sinres = math.sin(angle); + + result.m0 = cosres; + result.m2 = sinres; + result.m8 = -sinres; + result.m10 = cosres; + + return result; + + +def MatrixIdentity(): + result = ffi.new("struct Matrix *",[ 1.0, 0.0, 0.0, 0.0,0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ]) + return result + + + +def MatrixRotateZ(angle): + result = MatrixIdentity(); + + cosres = math.cos(angle); + sinres = math.sin(angle); + + result.m0 = cosres; + result.m1 = -sinres; + result.m4 = sinres; + result.m5 = cosres; + + return result + + +def MatrixMultiply(left, right): + result = ffi.new("struct Matrix *") + result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; + result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; + result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14; + result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15; + result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12; + result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13; + result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14; + result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15; + result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12; + result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13; + result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14; + result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15; + result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12; + result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; + result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; + result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15; + + return result diff --git a/examples/shaders/shaders_basic_lighting.py b/examples/shaders/shaders_basic_lighting.py old mode 100644 new mode 100755 index 7bcffcd..d119c6f --- a/examples/shaders/shaders_basic_lighting.py +++ b/examples/shaders/shaders_basic_lighting.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 # /******************************************************************************************* # * # * raylib [shaders] example - basic lighting @@ -23,259 +24,82 @@ # * # * Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) # * +# * # ********************************************************************************************/ -from raylib.static import * +from raylib.static import rl, ffi +from raylib.colors import * from dataclasses import dataclass from enum import Enum from typing import Any import math +# a few functions ported from raymath +from rlmath import * - - -def MatrixRotateX(angle): - result = MatrixIdentity(); - - cosres = math.cos(angle); - sinres = math.sin(angle); - - result.m5 = cosres; - result.m6 = -sinres; - result.m9 = sinres; - result.m10 = cosres; - - return result; - - - -def MatrixRotateY(angle): - result = MatrixIdentity() - - cosres = math.cos(angle); - sinres = math.sin(angle); - - result.m0 = cosres; - result.m2 = sinres; - result.m8 = -sinres; - result.m10 = cosres; - - return result; - - -def MatrixIdentity(): - result = ffi.new("struct Matrix *",[ 1.0, 0.0, 0.0, 0.0,0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ]) - return result - - - -def MatrixRotateZ(angle): - result = MatrixIdentity(); - - cosres = math.cos(angle); - sinres = math.sin(angle); - - result.m0 = cosres; - result.m1 = -sinres; - result.m4 = sinres; - result.m5 = cosres; - - return result - - -def MatrixMultiply(left, right): - result = ffi.new("struct Matrix *") - result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; - result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; - result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14; - result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15; - result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12; - result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13; - result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14; - result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15; - result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12; - result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13; - result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14; - result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15; - result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12; - result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; - result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; - result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15; - - return result - - -#//---------------------------------------------------------------------------------- -#// Types and Structures Definition -#//---------------------------------------------------------------------------------- - -class LightSystem: - MAX_LIGHTS = 4 #// Max dynamic lights supported by shader - lightsCount = 0 - lights = [] - - def __init__(self, ambient = [ 0.2, 0.2, 0.2, 1.0 ], *ls): - self.shader = LoadShader(b"resources/shaders/glsl330/basic_lighting.vs", - b"resources/shaders/glsl330/basic_lighting.fs"); - - #// Get some shader loactions - self.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(self.shader, b"matModel"); - self.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(self.shader, b"viewPos"); - - #// ambient light level - self.ambientLoc = GetShaderLocation(self.shader, b"ambient"); - v = ffi.new("struct Vector4 *", ambient) - SetShaderValue(self.shader, self.ambientLoc, v, UNIFORM_VEC4); - - for light in ls: - self.add(light) - - def add(self, light): - light.configure(len(self.lights), self.shader) - self.lights.append(light) - if len(self.lights) > self.MAX_LIGHTS: - raise Exception("Too many lights") - - def update(self, cameraPos): - SetShaderValue(self.shader, self.shader.locs[LOC_VECTOR_VIEW], ffi.new("struct Vector3 *",cameraPos), UNIFORM_VEC3) - for light in self.lights: - light.UpdateLightValues() - - def draw(self): - for light in self.lights: - if light.enabled: - DrawSphereEx(light.position[0], 0.2, 8, 8, light.color) - - - - -LIGHT_DIRECTIONAL=0 -LIGHT_POINT=1 - - -class Light: - def __init__(self, type, position, target, color): - self.enabled = True - self.type = type - self.position = ffi.new("struct Vector3 *",position) - self.target = target - self.color = color - - - - - def configure(self, id, shader): - self.shader = shader - #// TODO: Below code doesn't look good to me, - # // it assumes a specific shader naming and structure - # // Probably this implementation could be improved - self.enabledName = f"lights[{id}].enabled" - self.typeName = f"lights[{id}].type" - self.posName = f"lights[{id}].position" - self.targetName = f"lights[{id}].target" - self.colorName = f"lights[{id}].color" - - self.enabledLoc = GetShaderLocation(shader, self.enabledName.encode('utf-8')) - self.typeLoc = GetShaderLocation(shader, self.typeName.encode('utf-8')) - self.posLoc = GetShaderLocation(shader, self.posName.encode('utf-8')) - self.targetLoc = GetShaderLocation(shader, self.targetName.encode('utf-8')) - self.colorLoc = GetShaderLocation(shader, self.colorName.encode('utf-8')) - - self.UpdateLightValues() - - - #// Send light properties to shader - #// NOTE: Light shader locations should be available - def UpdateLightValues(self): - #// Send to shader light enabled state and type - SetShaderValue(self.shader, self.enabledLoc, ffi.new("int *",self.enabled), UNIFORM_INT) - SetShaderValue(self.shader, self.typeLoc, ffi.new("int *",self.type), UNIFORM_INT) - - #// Send to shader light position values - position = [ self.position.x, self.position.y, self.position.z] - SetShaderValue(self.shader, self.posLoc, ffi.new("struct Vector3 *",position), UNIFORM_VEC3) - - #// Send to shader light target position values - target =[ self.target.x, self.target.y, self.target.z ] - SetShaderValue(self.shader, self.targetLoc, ffi.new("struct Vector3 *",target), UNIFORM_VEC3) - - #// Send to shader light color values - color = [self.color[0]/255.0, self.color[1]/255.0, self.color[2]/255.0, self.color[3]/255.0] - SetShaderValue(self.shader, self.colorLoc, ffi.new("struct Vector4 *",color), UNIFORM_VEC4) - - - -def Vector3Zero(): - return ffi.new("struct Vector3 *",[ 0, 0, 0]) +# lighting system +from light_system import * #// Initialization #//-------------------------------------------------------------------------------------- screenWidth = 800; screenHeight = 450; -SetConfigFlags(FLAG_MSAA_4X_HINT); # Enable Multi Sampling Anti Aliasing 4x (if available) -InitWindow(screenWidth, screenHeight, b"raylib [shaders] example - basic lighting") +rl.SetConfigFlags(rl.FLAG_MSAA_4X_HINT| rl.FLAG_WINDOW_RESIZABLE); # Enable Multi Sampling Anti Aliasing 4x (if available) +rl.InitWindow(screenWidth, screenHeight, b"raylib [shaders] example - basic lighting") -#// Define the camera to look into our 3d world -cameraPtr = ffi.new("struct Camera3D *") -camera = cameraPtr[0] -camera.position = [ 2.0, 2.0, 6.0 ] # // Camera position -camera.target = [ 0.0, 0.5, 0.0]# // Camera looking at point -camera.up = [ 0.0, 1.0, 0.0]# // Camera up vector (rotation towards target) -camera.fovy = 45.0 # // Camera field-of-view Y -camera.type = CAMERA_PERSPECTIVE # // Camera mode type +camera = ffi.new('struct Camera3D *', [ + [2, 2, 6], + [0, .5, 0], + [0, 1, 0], + 45, + rl.CAMERA_PERSPECTIVE +]) - #// Load models -modelA = LoadModelFromMesh(GenMeshTorus(0.4, 1.0, 16, 32)) -modelB = LoadModelFromMesh(GenMeshCube(1.0, 1.0, 1.0)) -modelC = LoadModelFromMesh(GenMeshSphere(0.5, 32, 32)) +#// Load models +modelA = rl.LoadModelFromMesh(rl.GenMeshTorus(0.4, 1.0, 16, 32)) +modelB = rl.LoadModelFromMesh(rl.GenMeshCube(1.0, 1.0, 1.0)) +modelC = rl.LoadModelFromMesh(rl.GenMeshSphere(0.5, 32, 32)) #// Load models texture -texture = LoadTexture(b"resources/texel_checker.png") +texture = rl.LoadTexture(b"resources/texel_checker.png") #// Assign texture to default model material -modelA.materials[0].maps[MAP_DIFFUSE].texture = texture -modelB.materials[0].maps[MAP_DIFFUSE].texture = texture -modelC.materials[0].maps[MAP_DIFFUSE].texture = texture - - - - +modelA.materials[0].maps[rl.MAP_DIFFUSE].texture = texture +modelB.materials[0].maps[rl.MAP_DIFFUSE].texture = texture +modelC.materials[0].maps[rl.MAP_DIFFUSE].texture = texture angle = 6.282; - #// Using 4 point lights, white, red, green and blue -#lights[0] = Light(LIGHT_POINT, ffi.new("struct Vector3 *",[ 400, 400, 400 ]), Vector3Zero(), WHITE, shader) lights0 = Light(LIGHT_POINT, [ 4, 2, 4 ], Vector3Zero(), WHITE) lights1 = Light(LIGHT_POINT, [4, 2, 4 ], Vector3Zero(), RED) lights2 = Light(LIGHT_POINT, [ 0, 4, 2 ], Vector3Zero(), GREEN) lights3 = Light(LIGHT_POINT, [ 0, 4, 2 ], Vector3Zero(), BLUE) lightSystem = LightSystem([ 0.2, 0.2, 0.2, 1.0 ], lights0, lights1, lights2, lights3) +fogD = rl.GetShaderLocation(lightSystem.shader, b'FogDensity') +fogDensity = 0.0 -#// All models use the same shader +#// All models use the same shader - which lights them modelA.materials[0].shader = lightSystem.shader modelB.materials[0].shader = lightSystem.shader modelC.materials[0].shader = lightSystem.shader - -SetCameraMode(camera, CAMERA_ORBITAL) #// Set an orbital camera mode - -SetTargetFPS(60) # // Set our game to run at 60 frames-per-second +rl.SetTargetFPS(60) # // Set our game to run at 60 frames-per-second #//-------------------------------------------------------------------------------------- #// Main game loop -while not WindowShouldClose(): #// Detect window close button or ESC key +while not rl.WindowShouldClose(): #// Detect window close button or ESC key #// Update #//---------------------------------------------------------------------------------- - if IsKeyPressed(KEY_W): lights0.enabled = not lights0.enabled - if IsKeyPressed(KEY_R): lights1.enabled = not lights1.enabled - if IsKeyPressed(KEY_G): lights2.enabled = not lights2.enabled - if IsKeyPressed(KEY_B): lights3.enabled = not lights3.enabled + if rl.IsKeyPressed(rl.KEY_W): lights0.enabled = not lights0.enabled + if rl.IsKeyPressed(rl.KEY_R): lights1.enabled = not lights1.enabled + if rl.IsKeyPressed(rl.KEY_G): lights2.enabled = not lights2.enabled + if rl.IsKeyPressed(rl.KEY_B): lights3.enabled = not lights3.enabled - UpdateCamera(cameraPtr); #// Update camera + rl.UpdateCamera(camera) #// Update camera #// Make the lights do differing orbits angle -= 0.02 @@ -292,54 +116,49 @@ while not WindowShouldClose(): #// Detect window close button or ESC lightSystem.update(camera.position) - - #// Rotate the torus - modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateX(-0.025))[0] modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateZ(0.012))[0] - - - #//---------------------------------------------------------------------------------- #// Draw #//---------------------------------------------------------------------------------- - BeginDrawing() + rl.BeginDrawing() - ClearBackground(RAYWHITE) + rl.ClearBackground(RAYWHITE) - BeginMode3D(camera) + rl.BeginMode3D(camera[0]) #// Draw the three models - DrawModel(modelA, [0,0,0], 1.0, WHITE) - DrawModel(modelB, [-1.6,0,0], 1.0, WHITE) - DrawModel(modelC, [ 1.6,0,0], 1.0, WHITE) + rl.DrawModel(modelA, [0,0,0], 1.0, WHITE) + rl.DrawModel(modelB, [-1.6,0,0], 1.0, WHITE) + rl.DrawModel(modelC, [ 1.6,0,0], 1.0, WHITE) #// Draw markers to show where the lights are lightSystem.draw() - DrawGrid(10, 1.0) + rl.DrawGrid(10, 1.0) - EndMode3D() + rl.EndMode3D() - DrawFPS(10, 10) + rl.DrawFPS(10, 10) - DrawText(b"Keys RGB & W toggle lights", 10, 30, 20, DARKGRAY) + rl.DrawText(b"Keys RGB & W toggle lights", 10, 30, 20, DARKGRAY) - EndDrawing() + rl.EndDrawing() #//---------------------------------------------------------------------------------- #// De-Initialization #//-------------------------------------------------------------------------------------- -UnloadModel(modelA) # // Unload the modelA -UnloadModel(modelB) # // Unload the modelB -UnloadModel(modelC) # // Unload the modelC +rl.UnloadModel(modelA) # // Unload the modelA +rl.UnloadModel(modelB) # // Unload the modelB +rl.UnloadModel(modelC) # // Unload the modelC -UnloadTexture(texture) #// Unload the texture -UnloadShader(shader) #// Unload shader +rl.UnloadTexture(texture) #// Unload the texture -CloseWindow(); #// Close window and OpenGL context +rl.UnloadShader(lightSystem.shader) + +rl.CloseWindow() #// Close window and OpenGL context diff --git a/examples/shaders/shaders_custom_uniform.py b/examples/shaders/shaders_custom_uniform.py new file mode 100755 index 0000000..57ee2fe --- /dev/null +++ b/examples/shaders/shaders_custom_uniform.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + + +from raylib.dynamic import raylib as rl, ffi +from raylib.colors import * +import math + +# a few functions ported from raymath +from rlmath import * + + +#// Initialization +#//-------------------------------------------------------------------------------------- +screenWidth = 800; +screenHeight = 450; + +rl.SetConfigFlags(rl.FLAG_MSAA_4X_HINT| rl.FLAG_WINDOW_RESIZABLE); # Enable Multi Sampling Anti Aliasing 4x (if available) +rl.InitWindow(screenWidth, screenHeight, b"raylib [shaders] example - basic lighting") + +camera = ffi.new('struct Camera3D *', [ + [2, 12, 6], + [0, .5, 0], + [0, 1, 0], + 45, + rl.CAMERA_PERSPECTIVE +]) + +model = rl.LoadModel(b"resources/models/barracks.obj") # // Load OBJ model +texture = rl.LoadTexture(b"resources/models/barracks_diffuse.png") # // Load model texture (diffuse map) + +#// Assign texture to default model material +model.materials[0].maps[rl.MAP_DIFFUSE].texture = texture +#// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader +shader = rl.LoadShader(b"", b"resources/shaders/glsl330/swirl.fs") +swirlCenterLoc = rl.GetShaderLocation(shader, b"center") +angle = 6.282; + + + +swirl = ffi.new("struct Vector2 *", [0,0]) + +target = rl.LoadRenderTexture(screenWidth, screenHeight) + +rl.SetTargetFPS(60) # // Set our game to run at 60 frames-per-second +#//-------------------------------------------------------------------------------------- + +#// Main game loop +while not rl.WindowShouldClose(): #// Detect window close button or ESC key + #// Update + #//---------------------------------------------------------------------------------- + + angle -= 0.002 + camera.position.x = math.sin(angle) * 30.0 + camera.position.z = math.cos(angle) * 30.0 + rl.UpdateCamera(camera) #// Update camera + + swirl.x = rl.GetMouseX() + swirl.y = screenHeight - rl.GetMouseY() + rl.SetShaderValue(shader, swirlCenterLoc, swirl, rl.UNIFORM_VEC2); + #//---------------------------------------------------------------------------------- + + #// Draw + #//---------------------------------------------------------------------------------- + rl.BeginDrawing() + + + rl.BeginTextureMode(target) + rl.ClearBackground(RAYWHITE) + rl.BeginMode3D(camera[0]) + + #// Draw the three models + rl.DrawModel(model, [0,0,0], 1.0, WHITE) + + rl.DrawGrid(10, 1.0) + + rl.EndTextureMode() + rl.EndMode3D() + + rl.BeginShaderMode(shader) + #// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) + rl.DrawTextureRec(target.texture, [ 0, 0, target.texture.width,-target.texture.height], [0.0], WHITE) + rl.EndShaderMode() + #// Draw some 2d text over drawn texture + rl.DrawText(b"(c) Barracks 3D model by Alberto Cano", screenWidth - 220, screenHeight - 20, 10, GRAY); + + + rl.DrawFPS(10, 10) + + rl.EndDrawing() +#//---------------------------------------------------------------------------------- + + +#// De-Initialization +#//-------------------------------------------------------------------------------------- +rl.UnloadModel(model) # // Unload the model + +rl.UnloadTexture(texture) #// Unload the texture + +rl.CloseWindow() #// Close window and OpenGL context diff --git a/examples/shaders/shaders_fog.py b/examples/shaders/shaders_fog.py new file mode 100755 index 0000000..876f599 --- /dev/null +++ b/examples/shaders/shaders_fog.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +""" + +Example converted to Python from: +http://bedroomcoders.co.uk/raylib-fog/ + + port to python completed by codifies - dont know who started it + + +""" + +from raylib.static import rl, ffi +from raylib.colors import * +import math + +from rlmath import * +from light_system import * + +rl.SetConfigFlags(rl.FLAG_MSAA_4X_HINT | rl.FLAG_WINDOW_RESIZABLE) +rl.InitWindow(1280, 768, b'Fog Test') + +camera = ffi.new('struct Camera3D *', [ + [6, 2, 6], + [0, .5, 0], + [0, 1, 0], + 45, + rl.CAMERA_PERSPECTIVE +]) + +model = rl.LoadModelFromMesh(rl.GenMeshTorus(0.4, 1, 16, 32)) +model2 = rl.LoadModelFromMesh(rl.GenMeshCube(1, 1, 1)) +model3 = rl.LoadModelFromMesh(rl.GenMeshSphere(0.5, 32, 32)) + +texture = rl.LoadTexture(b'resources/test.png') + +model.materials[0].maps[rl.MAP_DIFFUSE].texture = texture +model2.materials[0].maps[rl.MAP_DIFFUSE].texture = texture +model3.materials[0].maps[rl.MAP_DIFFUSE].texture = texture + +light = Light(LIGHT_POINT, [ 0, 4, 0 ], Vector3Zero(), WHITE) +lightSystem = LightSystem([ 0.2, 0.2, 0.2, 1.0 ], light) + +fog_color = ffi.new('float[]', [0.2,0.2,1.0,1.0]) +fogC = rl.GetShaderLocation(lightSystem.shader, b'fogColor') +rl.SetShaderValue(lightSystem.shader, fogC, fog_color, rl.UNIFORM_VEC4); +fogD = rl.GetShaderLocation(lightSystem.shader, b'FogDensity') +fogDensity = 0.12 + +model.materials[0].shader = lightSystem.shader +model2.materials[0].shader = lightSystem.shader +model3.materials[0].shader = lightSystem.shader + +rl.SetTargetFPS(60) +a=0.0 +while not rl.WindowShouldClose(): + + a+=0.01 + camera.position.x = math.sin(a)*6 + camera.position.z = math.cos(a)*6 + rl.UpdateCamera(camera) + + lightSystem.update(camera.position) + + + model.transform = MatrixMultiply(model.transform, MatrixRotateX(-0.025))[0] + model.transform = MatrixMultiply(model.transform, MatrixRotateZ(0.012))[0] + + if rl.IsKeyDown(rl.KEY_UP): + fogDensity = min(fogDensity + 0.001, 1) + + if rl.IsKeyDown(rl.KEY_DOWN): + fogDensity = max(fogDensity - 0.001, 0) + + rl.SetShaderValue(lightSystem.shader, fogD, ffi.new('float[]', [fogDensity]), rl.UNIFORM_FLOAT) + + rl.BeginDrawing() + + rl.ClearBackground([int(255 * i) for i in fog_color]) + if rl.IsKeyDown(rl.KEY_SPACE): + rl.ClearBackground(BLACK) + + rl.BeginMode3D(camera[0]) + rl.DrawModel(model, [0] * 3, 1, WHITE) + rl.DrawModel(model2, [-2.6, 0, 0], 1, WHITE) + rl.DrawModel(model3, [ 2.6, 0, 0], 1, WHITE) + + for i in range(-20, 20, 2): + rl.DrawModel(model, [i, 0, 2], 1, WHITE) + + + rl.DrawGizmo([1000, 1000, 1000]) + + rl.EndMode3D() + + rl.DrawFPS(10, 10) + rl.DrawText(f'Up/Down to change fog density: {fogDensity}'.encode('utf-8'), 10, 30, 20, WHITE) + + rl.EndDrawing() + +rl.UnloadModel(model) +rl.UnloadModel(model2) +rl.UnloadModel(model3) +rl.UnloadTexture(texture) +rl.UnloadShader(lightSystem.shader) +rl.CloseWindow() + diff --git a/examples/shaders/shaders_texture_drawing.py b/examples/shaders/shaders_texture_drawing.py new file mode 100644 index 0000000..7110ae4 --- /dev/null +++ b/examples/shaders/shaders_texture_drawing.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 + + +from raylib.dynamic import raylib as rl, ffi +from raylib.colors import * + + +# a few functions ported from raymath +from rlmath import * + + +#// Initialization +#//-------------------------------------------------------------------------------------- +screenWidth = 800; +screenHeight = 450; + +rl.SetConfigFlags(rl.FLAG_MSAA_4X_HINT| rl.FLAG_WINDOW_RESIZABLE); # Enable Multi Sampling Anti Aliasing 4x (if available) +rl.InitWindow(screenWidth, screenHeight, b"raylib [shaders] example - basic lighting") + +camera = ffi.new('struct Camera3D *', [ + [2, 12, 6], + [0, .5, 0], + [0, 1, 0], + 45, + rl.CAMERA_PERSPECTIVE +]) + +imBlank = rl.GenImageColor(1024, 1024, BLANK) +texture = rl.LoadTextureFromImage(imBlank) #// Load blank texture to fill on shader +rl.UnloadImage(imBlank); + +#// NOTE: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version +shader = rl.LoadShader(b"", b"resources/shaders/glsl330/cubes_panning.fs"); + +time = ffi.new("float *", 0.0) +timeLoc = rl.GetShaderLocation(shader, b"uTime"); +rl.SetShaderValue(shader, timeLoc, time, rl.UNIFORM_FLOAT); + + +rl.SetTargetFPS(60) # // Set our game to run at 60 frames-per-second +#//-------------------------------------------------------------------------------------- + +#// Main game loop +while not rl.WindowShouldClose(): #// Detect window close button or ESC key + #// Update + #//---------------------------------------------------------------------------------- + time[0] = rl.GetTime(); + rl.SetShaderValue(shader, timeLoc, time, rl.UNIFORM_FLOAT); + + #//---------------------------------------------------------------------------------- + + #// Draw + #//---------------------------------------------------------------------------------- + rl.BeginDrawing() + + rl.ClearBackground(RAYWHITE) + + rl.BeginShaderMode(shader) #// Enable our custom shader for next shapes/textures drawings + rl.DrawTexture(texture, 0, 0, WHITE) #// Drawing BLANK texture, all magic happens on shader + rl.EndShaderMode() #// Disable our custom shader, return to default shader + + rl.DrawText(b"BACKGROUND is PAINTED and ANIMATED on SHADER!", 10, 10, 20, MAROON); + + + rl.EndDrawing() +#//---------------------------------------------------------------------------------- + + +#// De-Initialization +#//-------------------------------------------------------------------------------------- + + +rl.UnloadTexture(texture) #// Unload the texture + +rl.CloseWindow() #// Close window and OpenGL context diff --git a/examples/shaders/shaders_texture_waves.py b/examples/shaders/shaders_texture_waves.py new file mode 100755 index 0000000..aa2753b --- /dev/null +++ b/examples/shaders/shaders_texture_waves.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 + +from raylib.static import rl, ffi +from raylib.colors import * +import math + +# a few functions ported from raymath +from rlmath import * + +from ctypes import byref + +#// Initialization +#//-------------------------------------------------------------------------------------- +screenWidth = 800; +screenHeight = 450; + +rl.SetConfigFlags(rl.FLAG_MSAA_4X_HINT| rl.FLAG_WINDOW_RESIZABLE); # Enable Multi Sampling Anti Aliasing 4x (if available) +rl.InitWindow(screenWidth, screenHeight, b"raylib [shaders]") + +camera = ffi.new('struct Camera3D *', [ + [2, 12, 6], + [0, .5, 0], + [0, 1, 0], + 45, + rl.CAMERA_PERSPECTIVE +]) + +texture = rl.LoadTexture(b"resources/space.png") + +shader = rl.LoadShader(b"", b"resources/shaders/glsl330/wave.fs") +secondsLoc = rl.GetShaderLocation(shader, b"secondes") +freqXLoc = rl.GetShaderLocation(shader, b"freqX") +freqYLoc = rl.GetShaderLocation(shader, b"freqY") +ampXLoc = rl.GetShaderLocation(shader, b"ampX") +ampYLoc = rl.GetShaderLocation(shader, b"ampY") +speedXLoc = rl.GetShaderLocation(shader, b"speedX") +speedYLoc = rl.GetShaderLocation(shader, b"speedY") + +freqX = ffi.new("float *", 25.0) +freqY = ffi.new("float *", 25.0) +ampX = ffi.new("float *", 5.0) +ampY = ffi.new("float *", 5.0) +speedX = ffi.new("float *", 8.0) +speedY = ffi.new("float *", 8.0) + +screenSize = ffi.new("struct Vector2 *",[ rl.GetScreenWidth(), rl.GetScreenHeight() ]) +rl.SetShaderValue(shader, rl.GetShaderLocation(shader, b"size"), screenSize, rl.UNIFORM_VEC2) + +rl.SetShaderValue(shader, freqXLoc, freqX, rl.UNIFORM_FLOAT) +rl.SetShaderValue(shader, freqYLoc, freqY, rl.UNIFORM_FLOAT) +rl.SetShaderValue(shader, ampXLoc, ampX, rl.UNIFORM_FLOAT) +rl.SetShaderValue(shader, ampYLoc, ampY, rl.UNIFORM_FLOAT) +rl.SetShaderValue(shader, speedXLoc, speedX, rl.UNIFORM_FLOAT) +rl.SetShaderValue(shader, speedYLoc, speedY, rl.UNIFORM_FLOAT) + +seconds = ffi.new("float *", 0.0) + +rl.SetTargetFPS(60) # // Set our game to run at 60 frames-per-second +#//-------------------------------------------------------------------------------------- + +#// Main game loop +while not rl.WindowShouldClose(): #// Detect window close button or ESC key + #// Update + #//---------------------------------------------------------------------------------- + seconds[0] += rl.GetFrameTime() + rl.SetShaderValue(shader, secondsLoc, seconds, rl.UNIFORM_FLOAT) + #//---------------------------------------------------------------------------------- + + #// Draw + #//---------------------------------------------------------------------------------- + rl.BeginDrawing() + + + rl.ClearBackground(RAYWHITE) + rl.BeginShaderMode(shader); + + rl.DrawTexture(texture, 0, 0, WHITE); + rl.DrawTexture(texture, texture.width, 0, WHITE); + + rl.EndShaderMode(); + + rl.EndDrawing() +#//---------------------------------------------------------------------------------- + + +#// De-Initialization +#//-------------------------------------------------------------------------------------- + + +rl.CloseWindow() #// Close window and OpenGL context