Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ with how far their tips move and a weight from roots to tips, and `draw()` right

## Scrim

Text gets a soft scrim that fades the scene toward a dark color around it. `scrim` gives that color (0 to 255) for
each time of day at the top, middle and bottom of the screen. Darker, more saturated versions of the scene's own colors
The whole scene fades part of the way toward a dark color, so text reads on top of it. `scrim` gives that color (0 to
255) for each time of day at the top, middle and bottom of the screen. Darker, more saturated versions of the scene's own colors
at those depths read better than black: dark sky blue at the top and dark green over grass by day, deep navy at night.
Check that text stays readable with `bun dev/preview.ts` at every time of day.

Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ Type `/wallpaper` to open the wallpaper menu:
Use ↑/↓ to pick a setting, and Enter or ←/→ to change it. The wallpaper crossfades to each choice as you go, and
Escape closes the menu. Your choices are kept across restarts.

- **Brightness** is subtle, normal or vivid. Brighter scenes get a firmer scrim behind text, so it stays readable.
- **Brightness** is subtle, normal or vivid. Brighter scenes are dimmed more, so text stays readable.
- **Shuffle** switches to a different wallpaper every hour, or each time OpenCode starts.
- **Per project** remembers a wallpaper for each project directory. A project starts from the global choice until you
pick one there.

With a light OpenCode theme the scene is washed out toward white and text gets a pale scrim instead of a dark one.
With a light OpenCode theme the scene is washed out toward white instead of dimmed.

## Wallpapers

Expand Down Expand Up @@ -182,10 +182,10 @@ variables tune rendering:
## How it works

The plugin post-processes each frame OpenCode draws. Cells painted with OpenCode's neutral surface colors are replaced
by the scene, while colored backgrounds such as diffs and selections are left alone. Text keeps a soft scrim that fades
the scene toward a dark tint around it. Scenes render in HDR with bloom and tone mapping, then are fitted to two colors
per character cell. While one look fades into another, both scenes render and blend, scrim included, so only
transitions cost extra. Scenes keep their landmarks toward the edges, and the engine tells them where text sits, so
by the scene, while colored backgrounds such as diffs and selections are left alone. The whole scene is dimmed evenly
toward a dark tint, so text reads anywhere without a backing of its own. Scenes render in HDR with bloom and tone
mapping, then are fitted to two colors per character cell. While one look fades into another, both scenes render and
blend, scrim included, so only transitions cost extra. Scenes keep their landmarks toward the edges, and the engine tells them where text sits, so
creatures and visitors stop where they can be seen. Outdoor scenes share one wind: now and then a gust rolls across
the screen, bending plants and carrying petals, snow and dust.

Expand Down
20 changes: 13 additions & 7 deletions src/dots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,14 @@ function addDot(size: Uint8Array, sub: Uint8Array, light: Float32Array, i: numbe

// Writes cell i as a dot if it is flat enough and clear of the scrim's strongest part: the cell's mean color behind,
// the point's color in front. q holds the cell's eight sub-pixels as displayed (curve and scrim applied), grid the
// scene before the curve, st and sb the scrim over the top and bottom halves. held says it showed a dot last frame.
export function placeDot(dots: Dots, i: number, x: number, y: number, q: Float32Array, grid: Float32Array, GW: number, st: number, sb: number, curve: Uint8Array, held: boolean, char: Uint32Array, fg: Uint16Array, bg: Uint16Array, o: number) {
if (st > SCRIM || sb > SCRIM) return false
// scene before the curve, scrim the text scrim's strength per sub-pixel. held says it showed a dot last frame.
export function placeDot(dots: Dots, i: number, x: number, y: number, q: Float32Array, grid: Float32Array, scrim: Float32Array, GW: number, curve: Uint8Array, held: boolean, char: Uint32Array, fg: Uint16Array, bg: Uint16Array, o: number) {
let cover = 0
for (let s = 0; s < 8; s++) {
const k = scrim[(y * 4 + (s >> 1)) * GW + x * 2 + (s & 1)]
if (k > SCRIM) return false
cover += k / 8
}
let r = 0
let g = 0
let b = 0
Expand All @@ -94,7 +99,7 @@ export function placeDot(dots: Dots, i: number, x: number, y: number, q: Float32
let err = 0
for (let s = 0; s < 8; s++) err += (q[s * 3] - r) ** 2 + (q[s * 3 + 1] - g) ** 2 + (q[s * 3 + 2] - b) ** 2
if (err > (held ? FLAT * 2 : FLAT)) return false
const k = (1 - (st + sb) / 2) * GAINS[dots.size[i] - 1]
const k = (1 - cover) * GAINS[dots.size[i] - 1]
char[i] = GLYPHS[dots.size[i] - 1]
bg[o] = r
bg[o + 1] = g
Expand All @@ -117,10 +122,11 @@ export function placeDot(dots: Dots, i: number, x: number, y: number, q: Float32
const lift = new Float32Array(3)

// Paints cell i's point into its sub-pixel q, as it would look drawn into the scene.
export function lightDot(dots: Dots, i: number, x: number, y: number, q: Float32Array, grid: Float32Array, GW: number, st: number, sb: number, curve: Uint8Array) {
export function lightDot(dots: Dots, i: number, x: number, y: number, q: Float32Array, grid: Float32Array, scrim: Float32Array, GW: number, curve: Uint8Array) {
const s = dots.sub[i]
const a = ((y * 4 + (s >> 1)) * GW + x * 2 + (s & 1)) * 3
const k = 1 - (s < 4 ? st : sb)
const g = (y * 4 + (s >> 1)) * GW + x * 2 + (s & 1)
const a = g * 3
const k = 1 - scrim[g]
for (let c = 0; c < 3; c++) {
const under = grid[a + c]
q[s * 3 + c] += (curve[Math.min(255, under + dots.light[i * 3 + c] * SHARPENED) | 0] - curve[under | 0]) * k
Expand Down
Loading
Loading