Skip to content

Commit

Permalink
Show selected circle
Browse files Browse the repository at this point in the history
  • Loading branch information
deluksic committed Jan 11, 2025
1 parent 6b863ed commit ce067b3
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 55 deletions.
66 changes: 25 additions & 41 deletions docs/assets/index-jgfTJMVF.js → docs/assets/index-DoezzRr4.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta name="theme-color" content="#000000" />
<link rel="shortcut icon" type="image/ico" href="./assets/favicon-mtvwWgEY.ico" />
<title>Solid App</title>
<script type="module" crossorigin src="./assets/index-jgfTJMVF.js"></script>
<script type="module" crossorigin src="./assets/index-DoezzRr4.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-B4HUgb0J.css">
</head>
<body>
Expand Down
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createSignal, For } from 'solid-js'
import ui from './App.module.css'
import { frags } from './frags'
import { frags } from './demo/frags'
import { Root } from './lib/Root'
import { AutoCanvas } from './lib/AutoCanvas'

Expand Down
2 changes: 1 addition & 1 deletion src/Test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createMemo } from 'solid-js'
import { createAnimationFrame } from './utils/createAnimationFrame'
import { TestFrag, VertexOutput } from './frags'
import { TestFrag, VertexOutput } from './demo/frags'
import { wgsl } from './utils/wgsl'
import { struct, v2f, vec2f } from 'typegpu/data'
import tgpu from 'typegpu/experimental'
Expand Down
22 changes: 18 additions & 4 deletions src/demo/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ import {
closestFirstCircle,
closestSecondCircle,
closestThirdCircle,
debug,
growUntilRadius,
nextAnimationFrame,
setDebug,
} from './state'
import { useCanvas } from '@/lib/CanvasContext'
import { createPromiseCallbacks } from '@/utils/createPromiseCallbacks'
Expand All @@ -20,7 +18,7 @@ import { Root } from '@/lib/Root'
import { AutoCanvas } from '@/lib/AutoCanvas'
import { WheelZoomCamera2D } from './WheelZoomCamera2D'
import { Circles } from '@/demo/Circles'
import { frags } from '@/frags'
import { vec4f } from 'typegpu/data'

function Inside() {
const {
Expand Down Expand Up @@ -63,6 +61,7 @@ function Inside() {
return
}
setThirdCircleIndex(third.index)
setSelectedCircleIndex(undefined)

{
const circle = circles[index]!
Expand Down Expand Up @@ -100,7 +99,22 @@ function Inside() {
})
})

return <Circles circles={circles} frag={frags.frag4} />
return (
<Circles
circles={circles}
highlighted={
selectedCircleIndex()
? {
index: selectedCircleIndex()!,
color_: {
rim: vec4f(0, 0, 0, 1),
fade: vec4f(0.5, 0.8, 1, 1),
},
}
: undefined
}
/>
)
}

export function App() {
Expand Down
105 changes: 99 additions & 6 deletions src/demo/Circles.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,92 @@
import { createEffect, createMemo } from 'solid-js'
import { createAnimationFrame } from '../utils/createAnimationFrame'
import { TestFrag, VertexOutput } from '../frags'
import { wgsl } from '../utils/wgsl'
import { arrayOf, f32, struct, vec2f, Infer } from 'typegpu/data'
import {
arrayOf,
f32,
struct,
vec2f,
Infer,
vec4f,
u32,
builtin,
location,
} from 'typegpu/data'
import tgpu from 'typegpu/experimental'
import { useRootContext } from '../lib/RootContext'
import { useCanvas } from '../lib/CanvasContext'
import { premultipliedAlphaBlend } from '../utils/blendModes'
import { useCamera } from '../lib/CameraContext'

const VertexOutput = struct({
position: builtin.position,
positionOriginal: location(0, vec2f),
innerRatio: location(1, f32),
vHighlighted: location(2, f32),
})

type Circle = Infer<typeof Circle>
const Circle = struct({
center: vec2f,
radius: f32,
}).$name('Circle')
type Circle = Infer<typeof Circle>

type CircleColor = Infer<typeof CircleColor>
const CircleColor = struct({
rim: vec4f,
fade: vec4f,
})

type HighlightedCircle = Infer<typeof HighlightedCircle>
const HighlightedCircle = struct({
index: u32,
color_: CircleColor,
})

const N = 10000
const SUBDIVS = 24

const uniformBindGroupLayout = tgpu.bindGroupLayout({
circles: { storage: (length) => arrayOf(Circle, length) },
color: { uniform: CircleColor },
highlighted: { uniform: HighlightedCircle },
})

const linearstep = tgpu.fn([f32, f32, f32], f32).does(/* wgsl */ `
(edge0: f32, edge1: f32, x: f32) -> f32 {
return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
}`)

const fadeFragmentShader = tgpu
.fn([VertexOutput], vec4f)
.does(
/* wgsl */ `
(in: VertexOutput) -> vec4f {
const OUTER_RADIUS = 1.0;
let dist = length(in.positionOriginal);
let distWidth = fwidth(dist);
// adding half a distWidth in order for circles to touch fully
let disk = clamp((0.5*distWidth + OUTER_RADIUS - dist) / distWidth, 0, 1);
let fade = linearstep(in.innerRatio, OUTER_RADIUS, dist);
if in.vHighlighted != 0.0 {
return mix(highlighted.color_.fade, highlighted.color_.rim, fade * fade) * vec4f(1, 1, 1, disk * fade);
} else {
return mix(color.fade, color.rim, fade * fade) * vec4f(1, 1, 1, disk * fade);
};
}
`,
)
.$uses({
VertexOutput,
color: uniformBindGroupLayout.bound.color,
highlighted: uniformBindGroupLayout.bound.highlighted,
linearstep,
})

type CirclesProps = {
frag: TestFrag
circles: Circle[]
highlighted?: HighlightedCircle
color?: CircleColor
clearColor?: [number, number, number, number]
}

Expand All @@ -39,19 +101,47 @@ export function Circles(props: CirclesProps) {
const circlesBuffer = root
.createBuffer(arrayOf(Circle, N))
.$usage('storage')
.$name('Circles')
.$name('circles')

createEffect(() => {
circlesBuffer.write(props.circles)
})

const colorBuffer = root
.createBuffer(CircleColor)
.$usage('uniform')
.$name('color')

createEffect(() => {
colorBuffer.write(
props.color ?? {
rim: vec4f(0, 0, 0, 1),
fade: vec4f(0, 0, 0, 1),
},
)
})

const highlightedBuffer = root
.createBuffer(HighlightedCircle)
.$usage('uniform')
.$name('highlighted')

createEffect(() => {
highlightedBuffer.write(
props.highlighted ?? {
index: -1,
color_: { rim: vec4f(), fade: vec4f() },
},
)
})

const stuff = createMemo(() => {
const shaderCode = wgsl/* wgsl */ `
${{
VertexOutput,
frag: props.frag,
worldToClip,
clipToPixels,
frag: fadeFragmentShader,
...camera.BindGroupLayout.bound,
...uniformBindGroupLayout.bound,
}}
Expand Down Expand Up @@ -80,6 +170,7 @@ export function Circles(props: CirclesProps) {
out.position = vec4f(clip, 0, 1);
out.positionOriginal = mix(vec2f(0,0), unitCircle, ratio);
out.innerRatio = innerRatio;
out.vHighlighted = f32(instanceIndex == highlighted.index);
return out;
}
Expand Down Expand Up @@ -122,6 +213,8 @@ export function Circles(props: CirclesProps) {

const uniformBindGroup = uniformBindGroupLayout.populate({
circles: circlesBuffer.buffer,
color: colorBuffer,
highlighted: highlightedBuffer,
})

return { pipeline, uniformBindGroup }
Expand Down
2 changes: 1 addition & 1 deletion src/frags.ts → src/demo/frags.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import tgpu from 'typegpu/experimental'
import { struct, builtin, vec2f, vec4f, location, f32 } from 'typegpu/data'

export const VertexOutput = struct({
const VertexOutput = struct({
position: builtin.position,
positionOriginal: location(0, vec2f),
innerRatio: location(1, f32),
Expand Down
5 changes: 5 additions & 0 deletions src/demo/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ function vec2AddScaled2(a: v2f, b: v2f, bs: number, c: v2f, cs: number): v2f {
return vec2f(a.x + b.x * bs + c.x * cs, a.y + b.y * bs + c.y * cs)
}

// const { random } = Math
// const initialCircles: Circle[] = Array.from({ length: 5000 }).map(() => ({
// center: vec2f(random() * 10 - 5, random() * 10 - 5),
// radius: random() * 0.05 + 0.05,
// }))
export const [circles, setCircles] = createStore<Circle[]>([])
export const [debug, setDebug] = createSignal(false)

Expand Down
1 change: 1 addition & 0 deletions src/lib/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function Root(props: ParentProps<RootProps>) {
`Failed to get GPUAdapter, make sure to use a browser with WebGPU support.`,
)
}
console.info(`Using ${adapter.info.vendor} adapter.`)
const device = await adapter?.requestDevice()
if (!device) {
throw new Error(
Expand Down

0 comments on commit ce067b3

Please sign in to comment.