Skip to main content

Light

Struct Light 

Source
pub struct Light { /* private fields */ }
Expand description

One light for one frame.

A frame is lit by exactly what it submits; submitting none keeps the default environment.

Implementations§

Source§

impl Light

Source

pub fn directional(direction: Vec3, color: Color) -> Self

A sun: parallel light along direction.

Examples found in repository?
examples/flock-parallelism.rs (line 748)
741    fn frame(&mut self, ctx: &mut FrameContext<'_, Self>) {
742        self.apply_settings();
743
744        let center = Vec3::from(self.butterflies.center());
745        let elapsed = ctx.elapsed().as_secs_f32();
746        ctx.set_camera(Self::camera(center, self.world, elapsed));
747        ctx.set_skybox(Sky::Day);
748        ctx.light(Light::directional(SUN_DIRECTION, SUN_COLOR).shadow());
749
750        Self::draw_ground(ctx);
751        self.draw_butterflies(ctx);
752        self.panel(ctx);
753    }
More examples
Hide additional examples
examples/sprite-adventure.rs (line 1725)
1722    fn frame_overworld(&mut self, ctx: &mut FrameContext<'_, Keep>) {
1723        let drawn_at = self.previous.lerp(self.position, ctx.alpha());
1724        ctx.set_camera(Self::camera(drawn_at, OVERWORLD_CAMERA_OFFSET));
1725        ctx.light(Light::directional(SUN_DIRECTION, SUN_COLOR).shadow());
1726
1727        self.draw_ground(ctx);
1728        self.draw_hedgerow(ctx);
1729        self.draw_pond(ctx);
1730        self.draw_crates(ctx);
1731        self.draw_well(ctx);
1732        self.draw_flora(ctx);
1733        Self::draw_mouth(ctx, ENTRANCE);
1734        self.draw_walker(ctx, drawn_at);
1735    }
examples/isometric-board.rs (line 823)
819    fn frame(&mut self, ctx: &mut FrameContext<'_, Board>) {
820        let camera = Self::camera();
821        ctx.set_camera(camera);
822        ctx.set_skybox(Sky::Day);
823        ctx.light(Light::directional(Vec3::new(-0.35, -1.0, -0.5), SUN_COLOR).shadow());
824        ctx.set_bloom(BLOOM);
825
826        let hover = self.hovered(ctx);
827        self.draw_ground(ctx);
828        self.draw_board(ctx, hover);
829        self.draw_current_mark(ctx);
830        self.draw_rocks(ctx);
831        self.draw_sprite(ctx, hover);
832        self.draw_block(ctx, hover);
833        self.draw_prompt(ctx, camera, hover);
834
835        self.overlay(ctx);
836    }
examples/stress-preview.rs (line 612)
602    fn frame(&mut self, ctx: &mut FrameContext<'_, Self>) {
603        self.apply_settings();
604        self.frame_times.record(ctx.dt());
605
606        let elapsed = ctx.elapsed().as_secs_f32();
607        self.handle_camera(ctx, elapsed);
608        let camera = self.camera(elapsed);
609        ctx.set_camera(camera);
610        ctx.set_skybox(Sky::Day);
611
612        let sun = Light::directional(SUN_DIRECTION, SUN_COLOR);
613        ctx.light(if self.settings.sun_shadow {
614            sun.shadow()
615        } else {
616            sun
617        });
618
619        Self::draw_ground(ctx);
620        self.draw_field(ctx, elapsed);
621        self.controls(ctx, &camera);
622    }
examples/material-playground.rs (line 1026)
1002    fn lights(&self) -> Vec<Light> {
1003        let lamp = Light::point(LAMP_POSITION, self.lamp.scaled(), LAMP_RANGE);
1004        let spotlight = Light::spot(Spot {
1005            position: SPOT_POSITION,
1006            direction: SPOT_DIRECTION,
1007            color: self.spotlight.scaled(),
1008            range: SPOT_RANGE,
1009            angle: SPOT_ANGLE,
1010        });
1011
1012        let mut lights = vec![
1013            if self.lamp.shadow {
1014                lamp.shadow()
1015            } else {
1016                lamp
1017            },
1018            if self.spotlight.shadow {
1019                spotlight.shadow()
1020            } else {
1021                spotlight
1022            },
1023        ];
1024
1025        if let Some((direction, color, strength)) = self.sky.sun() {
1026            let sun = Light::directional(direction, scaled(color, strength));
1027            lights.push(if self.sun_shadow { sun.shadow() } else { sun });
1028        }
1029
1030        lights
1031    }
examples/post-effects.rs (line 91)
90    fn draw_scene(&self, ctx: &mut FrameContext<'_, Self>) {
91        ctx.light(Light::directional(SUN_DIRECTION, SUN_COLOR).shadow());
92
93        ctx.draw(
94            Plane
95                .at(Transform::from_scale(Vec3::new(
96                    GROUND_SIZE,
97                    1.0,
98                    GROUND_SIZE,
99                )))
100                .material(Material::lit(GROUND_COLOR)),
101        );
102        ctx.draw(
103            Cube.at(Transform::from_scale_rotation_translation(
104                Vec3::splat(GLOW_SIZE),
105                Quat::IDENTITY,
106                GLOW_POSITION,
107            ))
108            .material(Material::color(Color::BLACK).emissive(GLOW_COLOR)),
109        );
110        for position in SPHERE_POSITIONS {
111            ctx.draw(
112                Sphere {
113                    subdivisions: SPHERE_SUBDIVISIONS,
114                }
115                .at(position)
116                .material(Material::lit(SPHERE_COLOR)),
117            );
118        }
119    }
Source

pub fn point(position: Vec3, color: Color, range: f32) -> Self

A lamp at position, fading to nothing range meters out.

A surface takes the square of the fraction of range left at its distance from position: the whole of the light at position, a quarter of it halfway out, and none of it at range or past it.

Examples found in repository?
examples/material-playground.rs (line 1003)
1002    fn lights(&self) -> Vec<Light> {
1003        let lamp = Light::point(LAMP_POSITION, self.lamp.scaled(), LAMP_RANGE);
1004        let spotlight = Light::spot(Spot {
1005            position: SPOT_POSITION,
1006            direction: SPOT_DIRECTION,
1007            color: self.spotlight.scaled(),
1008            range: SPOT_RANGE,
1009            angle: SPOT_ANGLE,
1010        });
1011
1012        let mut lights = vec![
1013            if self.lamp.shadow {
1014                lamp.shadow()
1015            } else {
1016                lamp
1017            },
1018            if self.spotlight.shadow {
1019                spotlight.shadow()
1020            } else {
1021                spotlight
1022            },
1023        ];
1024
1025        if let Some((direction, color, strength)) = self.sky.sun() {
1026            let sun = Light::directional(direction, scaled(color, strength));
1027            lights.push(if self.sun_shadow { sun.shadow() } else { sun });
1028        }
1029
1030        lights
1031    }
More examples
Hide additional examples
examples/sprite-adventure.rs (line 1553)
1531    fn draw_torches(&self, ctx: &mut FrameContext<'_, Keep>) {
1532        let elapsed = self.simulated.as_secs_f32();
1533        let loop_cells = Sheet::new(UVec2::new(FLAME_CELLS, 1));
1534
1535        for (index, &(x, z)) in TORCH_POSITIONS.iter().enumerate() {
1536            let base = Vec3::new(x, 0.0, z);
1537            ctx.draw(
1538                Torch
1539                    .at(Transform::from_scale_rotation_translation(
1540                        Vec3::new(TORCH_SPRITE_WIDTH, TORCH_STAND_HEIGHT, 1.0),
1541                        Quat::IDENTITY,
1542                        base + Vec3::Y * (TORCH_STAND_HEIGHT * 0.5),
1543                    ))
1544                    .upright(),
1545            );
1546
1547            let phase = index as f32 * 2.1;
1548            let flicker = (elapsed * FLAME_FLICKER_SPEED + phase).sin();
1549            let flame_pos =
1550                base + Vec3::Y * (TORCH_STAND_HEIGHT + FLAME_LIFT + flicker * FLAME_BOB);
1551
1552            let light_pos = flame_pos + Vec3::new(0.0, TORCH_LIGHT_LIFT, TORCH_LIGHT_STANDOFF);
1553            ctx.light(Light::point(light_pos, TORCH_LIGHT_COLOR, TORCH_LIGHT_RANGE).shadow());
1554            // The pair burn an even share of the loop apart.
1555            let offset = index as u32 * FLAME_CELLS / TORCH_POSITIONS.len() as u32;
1556            ctx.draw(
1557                Flame
1558                    .at(Transform::from_scale_rotation_translation(
1559                        Vec3::splat(FLAME_SIZE),
1560                        Quat::IDENTITY,
1561                        flame_pos,
1562                    ))
1563                    .billboard()
1564                    .roll(flicker * FLAME_ROLL)
1565                    .frame(loop_cells.cell((elapsed * FLAME_RATE) as u32 + offset)),
1566            );
1567        }
1568    }
1569
1570    /// The door at its hinge — swung back against the wall once opened —
1571    /// drawn through alongside its wall, faded by `ghost`.
1572    fn draw_door(&self, ctx: &mut FrameContext<'_, Keep>, ghost: f32) {
1573        let fade = ghost_alpha(ghost);
1574        let swung = if self.door_opening {
1575            Quat::from_rotation_y(core::f32::consts::FRAC_PI_2)
1576        } else {
1577            Quat::IDENTITY
1578        };
1579
1580        ctx.draw(
1581            Door.at(Transform::from_rotation_translation(swung, DOOR_HINGE))
1582                .material(Material::shaded(DOOR_COLOR, DOOR_LITNESS))
1583                .faded(fade),
1584        );
1585    }
1586
1587    /// The posts and lintel framing the doorway, in a color the stone never
1588    /// is, standing clear of the wall so the opening reads as a door from
1589    /// across the chamber. Glowing of their own while the door is closed and
1590    /// within [`INTERACT_RADIUS`], the cue that it opens.
1591    fn draw_door_frame(&self, ctx: &mut FrameContext<'_, Keep>, ghost: f32) {
1592        let reachable =
1593            !self.door_opening && self.position.distance(INTERACT_POINT) < INTERACT_RADIUS;
1594        let material =
1595            Material::shaded(DOOR_FRAME_COLOR, DOOR_FRAME_LITNESS).emissive(if reachable {
1596                DOOR_FRAME_GLOW
1597            } else {
1598                Color::BLACK
1599            });
1600        let fade = ghost_alpha(ghost);
1601        let z = DOOR_WALL_NEAR_Z + DOOR_FRAME_STANDOFF;
1602        let jamb_height = DOOR_HEIGHT + DOOR_FRAME_THICKNESS;
1603
1604        for side in SIDES {
1605            ctx.draw(
1606                Cube.at(Transform::from_scale_rotation_translation(
1607                    Vec3::new(DOOR_FRAME_THICKNESS, jamb_height, DOOR_FRAME_THICKNESS),
1608                    Quat::IDENTITY,
1609                    Vec3::new(
1610                        side * (DOORWAY_HALF + DOOR_FRAME_THICKNESS * 0.5),
1611                        jamb_height * 0.5,
1612                        z,
1613                    ),
1614                ))
1615                .material(material)
1616                .faded(fade),
1617            );
1618        }
1619        ctx.draw(
1620            Cube.at(Transform::from_scale_rotation_translation(
1621                Vec3::new(
1622                    DOOR_WIDTH + DOOR_FRAME_THICKNESS * 2.0,
1623                    DOOR_FRAME_THICKNESS,
1624                    DOOR_FRAME_THICKNESS,
1625                ),
1626                Quat::IDENTITY,
1627                Vec3::new(0.0, DOOR_HEIGHT + DOOR_FRAME_THICKNESS * 0.5, z),
1628            ))
1629            .material(material)
1630            .faded(fade),
1631        );
1632    }
1633
1634    /// A world prompt over the door: what opens it while the player is
1635    /// within [`INTERACT_RADIUS`] and it is closed, and that it swings while
1636    /// it does; gone once it has swung [`DOOR_SWING_TICKS`]. Laid out and
1637    /// placed like `examples/animation.rs`'s own prompt.
1638    fn draw_door_prompt(&self, ctx: &mut FrameContext<'_, Keep>, camera: Camera) {
1639        let near = self.position.distance(INTERACT_POINT) < INTERACT_RADIUS;
1640        let swinging = self.door_opening && self.swing_ticks < DOOR_SWING_TICKS;
1641        let text = if swinging {
1642            "opening"
1643        } else if near && !self.door_opening {
1644            "e opens the door"
1645        } else {
1646            return;
1647        };
1648
1649        let galley = ctx.text_layout(text, egui::FontId::proportional(DOOR_PROMPT_SIZE));
1650        let point = INTERACT_POINT + Vec3::Y * (DOOR_HEIGHT + DOOR_PROMPT_LIFT);
1651        let window_size = ctx.window_size();
1652        let pixels_per_point = ctx.pixels_per_point();
1653        let Some(pixel) = camera.pixel_of(point, window_size) else {
1654            return;
1655        };
1656
1657        ctx.ui(|ui| {
1658            let painter = ui.painter();
1659            let at = logical(pixel, pixels_per_point);
1660            let ink = galley.mesh_bounds;
1661            let pos = egui::pos2(at.x - ink.center().x, at.y - ink.center().y);
1662            let backdrop = egui::Rect::from_center_size(
1663                at,
1664                ink.size() + egui::Vec2::splat(DOOR_PROMPT_PADDING * 2.0),
1665            );
1666            painter.rect_filled(
1667                backdrop,
1668                DOOR_PROMPT_PADDING,
1669                egui::Color32::from_black_alpha(DOOR_PROMPT_BACKDROP),
1670            );
1671            painter.galley(pos, galley, DOOR_PROMPT_COLOR);
1672        });
1673    }
1674
1675    /// The gem, spinning and bobbing over the chamber's floor, and the light
1676    /// it casts over it.
1677    fn draw_gem(&self, ctx: &mut FrameContext<'_, Keep>) {
1678        let t = self.simulated.as_secs_f32();
1679        let bob = (t * 2.0).sin() * GEM_BOB_HEIGHT;
1680        ctx.light(
1681            Light::point(
1682                GEM_POSITION + Vec3::Y * (bob + GEM_LIGHT_LIFT),
1683                GEM_LIGHT_COLOR,
1684                GEM_LIGHT_RANGE,
1685            )
1686            .shadow(),
1687        );
1688        ctx.draw(
1689            Gem.at(Transform::from_scale_rotation_translation(
1690                Vec3::ONE,
1691                Quat::from_rotation_y(t * GEM_SPIN_SPEED),
1692                GEM_POSITION + Vec3::Y * bob,
1693            ))
1694            .material(Material::shaded(GEM_COLOR, 0.7).emissive(GEM_COLOR.dimmed(1.6))),
1695        );
1696    }
examples/breakout-game.rs (line 1020)
995    fn frame(&mut self, ctx: &mut FrameContext<'_, Breakout>) {
996        if matches!(self.phase, Phase::Serving | Phase::Playing) && ctx.pressed(Button::Pause) {
997            self.paused = !self.paused;
998        }
999
1000        ctx.set_volume(self.master_volume);
1001        self.sustain_music(ctx);
1002
1003        ctx.set_camera(Self::camera());
1004
1005        let brick_pulse = (self.brick_flash / BRICK_FLASH).clamp(0.0, 1.0);
1006        ctx.set_bloom((BLOOM_BASE + brick_pulse * BLOOM_PULSE_PEAK).clamp(0.0, 1.0));
1007
1008        let life_lost_t = (self.life_lost_flash / LIFE_LOST_FLASH).clamp(0.0, 1.0);
1009        ctx.set_exposure((1.0 - life_lost_t * EXPOSURE_DIP_DEPTH).clamp(0.0, 1.0));
1010
1011        // The tick moves nothing behind a menu, so a frame there draws the last
1012        // step whole rather than interpolating from the one before.
1013        let alpha = match self.phase {
1014            Phase::Serving | Phase::Playing if !self.paused => ctx.alpha(),
1015            _ => 1.0,
1016        };
1017        let paddle_x = self.paddle_prev_x.lerp(self.paddle_x, alpha);
1018        let ball_pos = self.ball_prev.lerp(self.ball_pos, alpha);
1019
1020        ctx.light(Light::point(ball_pos, BALL_GLOW, BALL_LIGHT_RANGE).shadow());
1021
1022        self.draw_court(ctx);
1023        self.draw_bricks(ctx);
1024        self.draw_sparks(ctx);
1025        self.draw_lives(ctx);
1026
1027        ctx.draw(
1028            Paddle
1029                .at(Transform::from_translation(Vec3::new(
1030                    paddle_x,
1031                    PADDLE_HALF_HEIGHT,
1032                    PADDLE_Z,
1033                )))
1034                .material_of(PaddlePart::Face, self.paddle_face_material()),
1035        );
1036
1037        self.draw_trail(ctx, alpha);
1038        ctx.draw(
1039            Sphere { subdivisions: 2 }
1040                .at(Transform::from_scale_rotation_translation(
1041                    Vec3::splat(BALL_RADIUS * 2.0),
1042                    Quat::IDENTITY,
1043                    ball_pos,
1044                ))
1045                .material(
1046                    Material::color(BALL_GLOW)
1047                        .emissive(BALL_EMISSIVE)
1048                        .additive(),
1049                ),
1050        );
1051
1052        self.overlay(ctx);
1053    }
examples/animation.rs (lines 940-944)
920    fn frame(&mut self, ctx: &mut FrameContext<'_, Scene>) {
921        self.steer_camera(ctx);
922
923        let alpha = ctx.alpha();
924        let elf_pos = self.elf_prev.lerp(self.elf_pos, alpha);
925        let elf_height = self.elf_height_prev + (self.elf_height - self.elf_height_prev) * alpha;
926        let (butterfly_pos, butterfly_yaw) = butterfly_pose(ctx.elapsed().as_secs_f32());
927
928        let camera = orbit_camera(elf_pos, self.camera_yaw, self.camera_pitch);
929        ctx.set_camera(camera);
930        ctx.set_cursor(if self.holding {
931            Cursor::Held
932        } else {
933            Cursor::Arrow
934        });
935        ctx.set_skybox(Sky::Day);
936        ctx.set_exposure(3.0);
937        ctx.set_bloom(0.2);
938        ctx.light(Light::directional(SUN_DIRECTION, SUN_COLOR).shadow());
939        ctx.light(
940            Light::point(
941                LAMP_POST_POSITION + Vec3::Y * (LAMP_POST_HEIGHT + LAMP_HEAD_GAP * 0.5),
942                LAMP_LIGHT_COLOR,
943                LAMP_LIGHT_RANGE,
944            )
945            .shadow(),
946        );
947        ctx.light(
948            Light::spot(Spot {
949                position: SPOT_POSITION,
950                direction: SPOT_DIRECTION,
951                color: SPOT_COLOR,
952                range: SPOT_RANGE,
953                angle: SPOT_ANGLE,
954            })
955            .shadow(),
956        );
957        ctx.light(
958            Light::point(butterfly_pos, BUTTERFLY_LIGHT_COLOR, BUTTERFLY_LIGHT_RANGE).shadow(),
959        );
960
961        ctx.draw(
962            Plane
963                .at(Transform::from_scale(Vec3::new(
964                    GROUND_SIZE,
965                    1.0,
966                    GROUND_SIZE,
967                )))
968                .material(Material::lit(GROUND_COLOR)),
969        );
970        for patch in HURT_PATCHES {
971            ctx.draw(
972                Plane
973                    .at(Transform::from_scale_rotation_translation(
974                        Vec3::splat(HURT_RADIUS * 2.0),
975                        Quat::IDENTITY,
976                        patch,
977                    ))
978                    .material(Material::lit(HURT_COLOR)),
979            );
980        }
981        ctx.draw(
982            Cube.at(Transform::from_scale_rotation_translation(
983                Vec3::new(SEAT_FOOTPRINT, SEAT_HEIGHT, SEAT_FOOTPRINT),
984                Quat::IDENTITY,
985                SEAT_POSITION + Vec3::Y * SEAT_HEIGHT * 0.5,
986            ))
987            .material(Material::lit(SEAT_COLOR)),
988        );
989        ctx.draw(
990            Cube.at(Transform::from_scale_rotation_translation(
991                Vec3::new(LAMP_POST_THICKNESS, LAMP_POST_HEIGHT, LAMP_POST_THICKNESS),
992                Quat::IDENTITY,
993                LAMP_POST_POSITION + Vec3::Y * LAMP_POST_HEIGHT * 0.5,
994            ))
995            .material(Material::lit(LAMP_POST_COLOR)),
996        );
997        ctx.draw(
998            Cube.at(Transform::from_scale_rotation_translation(
999                Vec3::splat(LAMP_HEAD_SIZE),
1000                Quat::IDENTITY,
1001                LAMP_POST_POSITION
1002                    + Vec3::Y * (LAMP_POST_HEIGHT + LAMP_HEAD_GAP + LAMP_HEAD_SIZE * 0.5),
1003            ))
1004            .material(Material::color(Color::BLACK).emissive(LAMP_LIGHT_COLOR)),
1005        );
1006        ctx.draw(
1007            Cube.at(Transform::from_scale_rotation_translation(
1008                Vec3::splat(SPOT_FIXTURE_SIZE),
1009                Quat::IDENTITY,
1010                SPOT_POSITION + Vec3::Y * SPOT_FIXTURE_SIZE * 0.5,
1011            ))
1012            .material(Material::lit(SPOT_FIXTURE_COLOR)),
1013        );
1014
1015        ctx.draw(
1016            Elf.at(Transform::from_rotation_translation(
1017                Quat::from_rotation_y(self.elf_yaw),
1018                elf_pos + Vec3::Y * elf_height,
1019            ))
1020            .posed(&self.elf_animator),
1021        );
1022        ctx.draw(
1023            Elf.at(Transform::from_rotation_translation(
1024                Quat::from_rotation_y(core::f32::consts::PI),
1025                SCRUBBED_ELF_POSITION,
1026            ))
1027            .posed(&self.scrubbed_animator),
1028        );
1029        ctx.draw(
1030            Butterfly
1031                .at(Transform::from_rotation_translation(
1032                    Quat::from_rotation_y(butterfly_yaw),
1033                    butterfly_pos,
1034                ))
1035                .posed(&self.butterfly_animator)
1036                .material(Material::lit(Color::WHITE).emissive(BUTTERFLY_EMISSIVE)),
1037        );
1038
1039        self.draw_prompts(ctx, camera);
1040        self.panel(ctx);
1041    }
Source

pub fn spot(spot: Spot) -> Self

A point light within spot’s cone.

Examples found in repository?
examples/material-playground.rs (lines 1004-1010)
1002    fn lights(&self) -> Vec<Light> {
1003        let lamp = Light::point(LAMP_POSITION, self.lamp.scaled(), LAMP_RANGE);
1004        let spotlight = Light::spot(Spot {
1005            position: SPOT_POSITION,
1006            direction: SPOT_DIRECTION,
1007            color: self.spotlight.scaled(),
1008            range: SPOT_RANGE,
1009            angle: SPOT_ANGLE,
1010        });
1011
1012        let mut lights = vec![
1013            if self.lamp.shadow {
1014                lamp.shadow()
1015            } else {
1016                lamp
1017            },
1018            if self.spotlight.shadow {
1019                spotlight.shadow()
1020            } else {
1021                spotlight
1022            },
1023        ];
1024
1025        if let Some((direction, color, strength)) = self.sky.sun() {
1026            let sun = Light::directional(direction, scaled(color, strength));
1027            lights.push(if self.sun_shadow { sun.shadow() } else { sun });
1028        }
1029
1030        lights
1031    }
More examples
Hide additional examples
examples/animation.rs (lines 948-954)
920    fn frame(&mut self, ctx: &mut FrameContext<'_, Scene>) {
921        self.steer_camera(ctx);
922
923        let alpha = ctx.alpha();
924        let elf_pos = self.elf_prev.lerp(self.elf_pos, alpha);
925        let elf_height = self.elf_height_prev + (self.elf_height - self.elf_height_prev) * alpha;
926        let (butterfly_pos, butterfly_yaw) = butterfly_pose(ctx.elapsed().as_secs_f32());
927
928        let camera = orbit_camera(elf_pos, self.camera_yaw, self.camera_pitch);
929        ctx.set_camera(camera);
930        ctx.set_cursor(if self.holding {
931            Cursor::Held
932        } else {
933            Cursor::Arrow
934        });
935        ctx.set_skybox(Sky::Day);
936        ctx.set_exposure(3.0);
937        ctx.set_bloom(0.2);
938        ctx.light(Light::directional(SUN_DIRECTION, SUN_COLOR).shadow());
939        ctx.light(
940            Light::point(
941                LAMP_POST_POSITION + Vec3::Y * (LAMP_POST_HEIGHT + LAMP_HEAD_GAP * 0.5),
942                LAMP_LIGHT_COLOR,
943                LAMP_LIGHT_RANGE,
944            )
945            .shadow(),
946        );
947        ctx.light(
948            Light::spot(Spot {
949                position: SPOT_POSITION,
950                direction: SPOT_DIRECTION,
951                color: SPOT_COLOR,
952                range: SPOT_RANGE,
953                angle: SPOT_ANGLE,
954            })
955            .shadow(),
956        );
957        ctx.light(
958            Light::point(butterfly_pos, BUTTERFLY_LIGHT_COLOR, BUTTERFLY_LIGHT_RANGE).shadow(),
959        );
960
961        ctx.draw(
962            Plane
963                .at(Transform::from_scale(Vec3::new(
964                    GROUND_SIZE,
965                    1.0,
966                    GROUND_SIZE,
967                )))
968                .material(Material::lit(GROUND_COLOR)),
969        );
970        for patch in HURT_PATCHES {
971            ctx.draw(
972                Plane
973                    .at(Transform::from_scale_rotation_translation(
974                        Vec3::splat(HURT_RADIUS * 2.0),
975                        Quat::IDENTITY,
976                        patch,
977                    ))
978                    .material(Material::lit(HURT_COLOR)),
979            );
980        }
981        ctx.draw(
982            Cube.at(Transform::from_scale_rotation_translation(
983                Vec3::new(SEAT_FOOTPRINT, SEAT_HEIGHT, SEAT_FOOTPRINT),
984                Quat::IDENTITY,
985                SEAT_POSITION + Vec3::Y * SEAT_HEIGHT * 0.5,
986            ))
987            .material(Material::lit(SEAT_COLOR)),
988        );
989        ctx.draw(
990            Cube.at(Transform::from_scale_rotation_translation(
991                Vec3::new(LAMP_POST_THICKNESS, LAMP_POST_HEIGHT, LAMP_POST_THICKNESS),
992                Quat::IDENTITY,
993                LAMP_POST_POSITION + Vec3::Y * LAMP_POST_HEIGHT * 0.5,
994            ))
995            .material(Material::lit(LAMP_POST_COLOR)),
996        );
997        ctx.draw(
998            Cube.at(Transform::from_scale_rotation_translation(
999                Vec3::splat(LAMP_HEAD_SIZE),
1000                Quat::IDENTITY,
1001                LAMP_POST_POSITION
1002                    + Vec3::Y * (LAMP_POST_HEIGHT + LAMP_HEAD_GAP + LAMP_HEAD_SIZE * 0.5),
1003            ))
1004            .material(Material::color(Color::BLACK).emissive(LAMP_LIGHT_COLOR)),
1005        );
1006        ctx.draw(
1007            Cube.at(Transform::from_scale_rotation_translation(
1008                Vec3::splat(SPOT_FIXTURE_SIZE),
1009                Quat::IDENTITY,
1010                SPOT_POSITION + Vec3::Y * SPOT_FIXTURE_SIZE * 0.5,
1011            ))
1012            .material(Material::lit(SPOT_FIXTURE_COLOR)),
1013        );
1014
1015        ctx.draw(
1016            Elf.at(Transform::from_rotation_translation(
1017                Quat::from_rotation_y(self.elf_yaw),
1018                elf_pos + Vec3::Y * elf_height,
1019            ))
1020            .posed(&self.elf_animator),
1021        );
1022        ctx.draw(
1023            Elf.at(Transform::from_rotation_translation(
1024                Quat::from_rotation_y(core::f32::consts::PI),
1025                SCRUBBED_ELF_POSITION,
1026            ))
1027            .posed(&self.scrubbed_animator),
1028        );
1029        ctx.draw(
1030            Butterfly
1031                .at(Transform::from_rotation_translation(
1032                    Quat::from_rotation_y(butterfly_yaw),
1033                    butterfly_pos,
1034                ))
1035                .posed(&self.butterfly_animator)
1036                .material(Material::lit(Color::WHITE).emissive(BUTTERFLY_EMISSIVE)),
1037        );
1038
1039        self.draw_prompts(ctx, camera);
1040        self.panel(ctx);
1041    }
Source

pub fn shadow(self) -> Self

Draws what this light covers into a depth map of its own, and darkens this light where the map holds a blocker in front of the surface.

MAX_SHADOWS lights of a frame may cast, in submission order; a point light counts as one and costs six maps. The rest are ignored — warned the first frame. Only opaque draws block a light, and only this light is darkened — the sky’s own light and unlit materials are untouched. A shadow extends no further than the light: past its range there is no light left to block. Both faces of a mesh cast, so a light placed within an opaque mesh is blocked by its own caster.

Examples found in repository?
examples/flock-parallelism.rs (line 748)
741    fn frame(&mut self, ctx: &mut FrameContext<'_, Self>) {
742        self.apply_settings();
743
744        let center = Vec3::from(self.butterflies.center());
745        let elapsed = ctx.elapsed().as_secs_f32();
746        ctx.set_camera(Self::camera(center, self.world, elapsed));
747        ctx.set_skybox(Sky::Day);
748        ctx.light(Light::directional(SUN_DIRECTION, SUN_COLOR).shadow());
749
750        Self::draw_ground(ctx);
751        self.draw_butterflies(ctx);
752        self.panel(ctx);
753    }
More examples
Hide additional examples
examples/isometric-board.rs (line 823)
819    fn frame(&mut self, ctx: &mut FrameContext<'_, Board>) {
820        let camera = Self::camera();
821        ctx.set_camera(camera);
822        ctx.set_skybox(Sky::Day);
823        ctx.light(Light::directional(Vec3::new(-0.35, -1.0, -0.5), SUN_COLOR).shadow());
824        ctx.set_bloom(BLOOM);
825
826        let hover = self.hovered(ctx);
827        self.draw_ground(ctx);
828        self.draw_board(ctx, hover);
829        self.draw_current_mark(ctx);
830        self.draw_rocks(ctx);
831        self.draw_sprite(ctx, hover);
832        self.draw_block(ctx, hover);
833        self.draw_prompt(ctx, camera, hover);
834
835        self.overlay(ctx);
836    }
examples/stress-preview.rs (line 614)
602    fn frame(&mut self, ctx: &mut FrameContext<'_, Self>) {
603        self.apply_settings();
604        self.frame_times.record(ctx.dt());
605
606        let elapsed = ctx.elapsed().as_secs_f32();
607        self.handle_camera(ctx, elapsed);
608        let camera = self.camera(elapsed);
609        ctx.set_camera(camera);
610        ctx.set_skybox(Sky::Day);
611
612        let sun = Light::directional(SUN_DIRECTION, SUN_COLOR);
613        ctx.light(if self.settings.sun_shadow {
614            sun.shadow()
615        } else {
616            sun
617        });
618
619        Self::draw_ground(ctx);
620        self.draw_field(ctx, elapsed);
621        self.controls(ctx, &camera);
622    }
examples/material-playground.rs (line 1014)
1002    fn lights(&self) -> Vec<Light> {
1003        let lamp = Light::point(LAMP_POSITION, self.lamp.scaled(), LAMP_RANGE);
1004        let spotlight = Light::spot(Spot {
1005            position: SPOT_POSITION,
1006            direction: SPOT_DIRECTION,
1007            color: self.spotlight.scaled(),
1008            range: SPOT_RANGE,
1009            angle: SPOT_ANGLE,
1010        });
1011
1012        let mut lights = vec![
1013            if self.lamp.shadow {
1014                lamp.shadow()
1015            } else {
1016                lamp
1017            },
1018            if self.spotlight.shadow {
1019                spotlight.shadow()
1020            } else {
1021                spotlight
1022            },
1023        ];
1024
1025        if let Some((direction, color, strength)) = self.sky.sun() {
1026            let sun = Light::directional(direction, scaled(color, strength));
1027            lights.push(if self.sun_shadow { sun.shadow() } else { sun });
1028        }
1029
1030        lights
1031    }
examples/post-effects.rs (line 91)
90    fn draw_scene(&self, ctx: &mut FrameContext<'_, Self>) {
91        ctx.light(Light::directional(SUN_DIRECTION, SUN_COLOR).shadow());
92
93        ctx.draw(
94            Plane
95                .at(Transform::from_scale(Vec3::new(
96                    GROUND_SIZE,
97                    1.0,
98                    GROUND_SIZE,
99                )))
100                .material(Material::lit(GROUND_COLOR)),
101        );
102        ctx.draw(
103            Cube.at(Transform::from_scale_rotation_translation(
104                Vec3::splat(GLOW_SIZE),
105                Quat::IDENTITY,
106                GLOW_POSITION,
107            ))
108            .material(Material::color(Color::BLACK).emissive(GLOW_COLOR)),
109        );
110        for position in SPHERE_POSITIONS {
111            ctx.draw(
112                Sphere {
113                    subdivisions: SPHERE_SUBDIVISIONS,
114                }
115                .at(position)
116                .material(Material::lit(SPHERE_COLOR)),
117            );
118        }
119    }
examples/ui-fonts.rs (line 822)
816    fn frame(&mut self, ctx: &mut FrameContext<'_, Self>) {
817        self.steer(ctx);
818
819        let camera = self.orbit.camera();
820        ctx.set_camera(camera);
821        ctx.set_skybox(Sky::Dusk);
822        ctx.light(Light::directional(SUN_DIRECTION, SUN_COLOR).shadow());
823
824        ctx.draw(
825            Plane
826                .at(Transform::from_scale(Vec3::new(
827                    PLATFORM_SIZE,
828                    1.0,
829                    PLATFORM_SIZE,
830                )))
831                .material(Material::lit(PLATFORM_COLOR)),
832        );
833        for station in StationKind::ALL {
834            self.draw_station(ctx, station);
835        }
836
837        let hovered = Self::hovered(ctx);
838        if !self.sheet_open {
839            if let Some(station) = hovered {
840                ctx.set_cursor(Cursor::Pointer);
841                self.draw_bracket(ctx, camera, station);
842            }
843            self.draw_prompts(ctx, camera, hovered);
844        }
845        if self.dialogue.is_some() {
846            self.draw_dialogue(ctx);
847        }
848        if self.sheet_open {
849            ctx.ui(sheet);
850        }
851        self.panel(ctx);
852    }

Trait Implementations§

Source§

impl Clone for Light

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Light

Source§

impl Debug for Light

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Light

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Light

Auto Trait Implementations§

§

impl Freeze for Light

§

impl RefUnwindSafe for Light

§

impl Send for Light

§

impl Sync for Light

§

impl Unpin for Light

§

impl UnsafeUnpin for Light

§

impl UnwindSafe for Light

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> SerializableAny for T
where T: 'static + Any + Clone + for<'a> Send + Sync,

Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(_simd: S, value: T) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more