package tiny_libs

  1. Overview
  2. Docs
From-scratch libraries for teaching: graphics, audio, compression, crypto, networking and more

Install

dune-project
 Dependency

Authors

Maintainers

Sources

0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0

doc/src/tiny_libs.graphics_3d_geometry/Lighting.ml.html

Source file Lighting.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(* Claude Code
 *
 * Copyright (C) 2026 Yoann Padioleau
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public License
 * (LGPL) as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *)

(* See Lighting.mli *)

(* claude: this is a DIRECTIONAL light -- a "sun" -- not a light at a
 * position. There are 3 common kinds of light in 3D graphics, in
 * increasing order of realism/cost:
 *  - directional (what this is): infinitely far away, so its rays are
 *    effectively parallel everywhere in the scene -- there is no
 *    "origin point" to specify, only a *direction* it shines from,
 *    the same for every face regardless of where that face is. The
 *    real sun works this way for all practical purposes (it's ~150
 *    million km away), which is why this is the natural choice for an
 *    outdoor scene. Cheapest to compute: one constant vector, reused
 *    for every face, no per-face distance/attenuation math at all.
 *  - point light: sits at an actual 3D position (e.g. a lightbulb or
 *    torch); the direction *to* it, and therefore how a face is lit,
 *    is different for every face depending on where that face is
 *    relative to the light, and realistically its brightness also
 *    falls off with distance ("attenuation"). More expensive (a
 *    per-face, or per-pixel, direction+distance calculation instead of
 *    one shared constant) and not implemented here.
 *  - spotlight: a point light further restricted to a cone (a
 *    direction plus a cutoff angle) -- even more parameters, also not
 *    implemented here.
 *
 * The vector itself is a DIRECTION, not a position: by convention here
 * it points FROM a lit surface TOWARDS the light (so
 * [dot normal light_dir] below is large/positive exactly when a face's
 * normal points roughly *at* the light, i.e. is well-lit -- see
 * brightness_of_normal). (1., 1.3, 0.6) reads as "the sun sits up and
 * off to the +X/+Z side" -- an arbitrary but reasonable-looking choice,
 * not derived from anything; e.g. changing it to (0., 1., 0.) would put
 * the sun straight overhead instead (top faces bright, sides dimmer,
 * undersides at the `ambient` floor below). Not exposed to the public
 * API yet -- a game can't configure this per scene, only by editing
 * this constant and recompiling. *)
let light_dir : Vec3.t = Vec3.normalize (1., 1.3, 0.6)

(* claude: never fully black (a face directly facing away from the
 * light stays at least at ambient brightness) -- a real scene has some
 * ambient/bounced light even on surfaces not directly facing the sun,
 * and a fully-black face would look like a hole rather than a shaded
 * surface *)
let ambient = 0.25

(* claude: pure -- "how lit is a surface facing this direction",
 * independent of any shading mode: whether to call it once per face,
 * once per vertex, or once per pixel with an interpolated normal (or
 * not at all, without lighting) is the shading's decision, not the
 * lighting's (see the software rasterizer's make_shader). *)
let brightness_of_normal (normal : Vec3.t) : float =
  let lit = Stdlib.max 0. (Vec3.dot normal light_dir) in
  ambient +. ((1. -. ambient) *. lit)