parent
2496042bc4
commit
f4d144e21c
5 changed files with 361 additions and 0 deletions
|
@ -93,6 +93,14 @@ Q,q,T,t | ✅ | quadratic to |
|
||||||
A,a | ✅ | arc to |
|
A,a | ✅ | arc to |
|
||||||
z | ✅ | close path |
|
z | ✅ | close path |
|
||||||
|
|
||||||
|
### Realtime Examples
|
||||||
|
|
||||||
|
Here are some examples of using Pixie for realtime rendering with some popular windowing libraries:
|
||||||
|
|
||||||
|
* [examples/realtime_glfw.nim](examples/realtime_glfw.nim)
|
||||||
|
* [examples/realtime_glut.nim](examples/realtime_glut.nim)
|
||||||
|
* [examples/realtime_sdl.nim](examples/realtime_sdl.nim)
|
||||||
|
* [examples/realtime_win32.nim](examples/realtime_win32.nim)
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
|
|
78
examples/realtime_glfw.nim
Normal file
78
examples/realtime_glfw.nim
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
## This example show how to have real time pixie using glfw API.
|
||||||
|
|
||||||
|
import math, opengl, pixie, staticglfw
|
||||||
|
|
||||||
|
let
|
||||||
|
w: int32 = 256
|
||||||
|
h: int32 = 256
|
||||||
|
|
||||||
|
var
|
||||||
|
screen = newImage(w, h)
|
||||||
|
ctx = newContext(screen)
|
||||||
|
frameCount = 0
|
||||||
|
window: Window
|
||||||
|
|
||||||
|
proc display() =
|
||||||
|
## Called every frame by main while loop
|
||||||
|
|
||||||
|
# draw shiny sphere on gradient background
|
||||||
|
var linerGradient = Paint(kind: pkGradientLinear)
|
||||||
|
linerGradient.gradientHandlePositions.add(vec2(0, 0))
|
||||||
|
linerGradient.gradientHandlePositions.add(vec2(0, 256))
|
||||||
|
linerGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(0, 0, 0, 255), position: 0))
|
||||||
|
linerGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(255, 255, 255, 255), position: 1))
|
||||||
|
ctx.fillStyle = linerGradient
|
||||||
|
ctx.fillRect(0, 0, 256, 256)
|
||||||
|
|
||||||
|
var radialGradient = Paint(kind: pkGradientRadial)
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(128, 128))
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(256, 128))
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(128, 256))
|
||||||
|
radialGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(255, 255, 255, 255), position: 0))
|
||||||
|
radialGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(0, 0, 0, 255), position: 1))
|
||||||
|
ctx.fillStyle = radialGradient
|
||||||
|
ctx.fillCircle(vec2(128.0, 128.0 + sin(float(frameCount)/10.0) * 20), 76.8)
|
||||||
|
|
||||||
|
# update texture with new pixels from surface
|
||||||
|
var dataPtr = ctx.image.data[0].addr
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GLsizei w, GLsizei h, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, dataPtr)
|
||||||
|
|
||||||
|
# draw a quad over the whole screen
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT)
|
||||||
|
glBegin(GL_QUADS)
|
||||||
|
glTexCoord2d(0.0, 0.0); glVertex2d(-1.0, +1.0)
|
||||||
|
glTexCoord2d(1.0, 0.0); glVertex2d(+1.0, +1.0)
|
||||||
|
glTexCoord2d(1.0, 1.0); glVertex2d(+1.0, -1.0)
|
||||||
|
glTexCoord2d(0.0, 1.0); glVertex2d(-1.0, -1.0)
|
||||||
|
glEnd()
|
||||||
|
|
||||||
|
inc frameCount
|
||||||
|
swapBuffers(window)
|
||||||
|
|
||||||
|
if init() == 0:
|
||||||
|
quit("Failed to Initialize GLFW.")
|
||||||
|
|
||||||
|
windowHint(RESIZABLE, false.cint)
|
||||||
|
window = createWindow(w.cint, h.cint, "GLFW/Pixie", nil, nil)
|
||||||
|
|
||||||
|
makeContextCurrent(window)
|
||||||
|
loadExtensions()
|
||||||
|
|
||||||
|
# allocate a texture and bind it
|
||||||
|
var dataPtr = ctx.image.data[0].addr
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, 3, GLsizei w, GLsizei h, 0, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, dataPtr)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
|
||||||
|
glEnable(GL_TEXTURE_2D)
|
||||||
|
|
||||||
|
while windowShouldClose(window) != 1:
|
||||||
|
pollEvents()
|
||||||
|
display()
|
76
examples/realtime_glut.nim
Normal file
76
examples/realtime_glut.nim
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
## This example show how to have real time pixie using glut API.
|
||||||
|
|
||||||
|
import math, opengl, opengl/glu, opengl/glut, pixie
|
||||||
|
|
||||||
|
let
|
||||||
|
w: int32 = 256
|
||||||
|
h: int32 = 256
|
||||||
|
|
||||||
|
var
|
||||||
|
screen = newImage(w, h)
|
||||||
|
ctx = newContext(screen)
|
||||||
|
frameCount = 0
|
||||||
|
|
||||||
|
proc display() {.cdecl.} =
|
||||||
|
## Called every frame by GLUT
|
||||||
|
|
||||||
|
# draw shiny sphere on gradient background
|
||||||
|
var linerGradient = Paint(kind: pkGradientLinear)
|
||||||
|
linerGradient.gradientHandlePositions.add(vec2(0, 0))
|
||||||
|
linerGradient.gradientHandlePositions.add(vec2(0, 256))
|
||||||
|
linerGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(0, 0, 0, 255), position: 0))
|
||||||
|
linerGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(255, 255, 255, 255), position: 1))
|
||||||
|
ctx.fillStyle = linerGradient
|
||||||
|
ctx.fillRect(0, 0, 256, 256)
|
||||||
|
|
||||||
|
var radialGradient = Paint(kind: pkGradientRadial)
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(128, 128))
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(256, 128))
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(128, 256))
|
||||||
|
radialGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(255, 255, 255, 255), position: 0))
|
||||||
|
radialGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(0, 0, 0, 255), position: 1))
|
||||||
|
ctx.fillStyle = radialGradient
|
||||||
|
ctx.fillCircle(vec2(128.0, 128.0 + sin(float(frameCount)/10.0) * 20), 76.8)
|
||||||
|
|
||||||
|
# update texture with new pixels from surface
|
||||||
|
var dataPtr = ctx.image.data[0].addr
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GLsizei w, GLsizei h, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, dataPtr)
|
||||||
|
|
||||||
|
# draw a quad over the whole screen
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT)
|
||||||
|
glBegin(GL_QUADS)
|
||||||
|
glTexCoord2d(0.0, 0.0); glVertex2d(-1.0, +1.0)
|
||||||
|
glTexCoord2d(1.0, 0.0); glVertex2d(+1.0, +1.0)
|
||||||
|
glTexCoord2d(1.0, 1.0); glVertex2d(+1.0, -1.0)
|
||||||
|
glTexCoord2d(0.0, 1.0); glVertex2d(-1.0, -1.0)
|
||||||
|
glEnd()
|
||||||
|
glutSwapBuffers()
|
||||||
|
|
||||||
|
inc frameCount
|
||||||
|
|
||||||
|
glutPostRedisplay() # ask glut to draw next frame
|
||||||
|
|
||||||
|
glutInit()
|
||||||
|
glutInitDisplayMode(GLUT_DOUBLE)
|
||||||
|
glutInitWindowSize(w, h)
|
||||||
|
discard glutCreateWindow("GLUT/Pixie")
|
||||||
|
|
||||||
|
glutDisplayFunc(display)
|
||||||
|
loadExtensions()
|
||||||
|
|
||||||
|
# allocate a texture and bind it
|
||||||
|
var dataPtr = ctx.image.data[0].addr
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, 3, GLsizei w, GLsizei h, 0, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, dataPtr)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
|
||||||
|
glEnable(GL_TEXTURE_2D)
|
||||||
|
|
||||||
|
glutMainLoop()
|
68
examples/realtime_sdl.nim
Normal file
68
examples/realtime_sdl.nim
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
## This example show how to have real time pixie using sdl2 API.
|
||||||
|
|
||||||
|
import math, pixie, sdl2, sdl2/gfx
|
||||||
|
|
||||||
|
let
|
||||||
|
w: int32 = 256
|
||||||
|
h: int32 = 256
|
||||||
|
|
||||||
|
var
|
||||||
|
screen = newImage(w, h)
|
||||||
|
ctx = newContext(screen)
|
||||||
|
frameCount = 0
|
||||||
|
window: WindowPtr
|
||||||
|
render: RendererPtr
|
||||||
|
mainSerface: SurfacePtr
|
||||||
|
mainTexture: TexturePtr
|
||||||
|
evt = sdl2.defaultEvent
|
||||||
|
|
||||||
|
proc display() =
|
||||||
|
## Called every frame by main while loop
|
||||||
|
|
||||||
|
# draw shiny sphere on gradient background
|
||||||
|
var linerGradient = Paint(kind: pkGradientLinear)
|
||||||
|
linerGradient.gradientHandlePositions.add(vec2(0, 0))
|
||||||
|
linerGradient.gradientHandlePositions.add(vec2(0, 256))
|
||||||
|
linerGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(0, 0, 0, 255), position: 0))
|
||||||
|
linerGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(255, 255, 255, 255), position: 1))
|
||||||
|
ctx.fillStyle = linerGradient
|
||||||
|
ctx.fillRect(0, 0, 256, 256)
|
||||||
|
|
||||||
|
var radialGradient = Paint(kind: pkGradientRadial)
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(128, 128))
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(256, 128))
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(128, 256))
|
||||||
|
radialGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(255, 255, 255, 255), position: 0))
|
||||||
|
radialGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(0, 0, 0, 255), position: 1))
|
||||||
|
ctx.fillStyle = radialGradient
|
||||||
|
ctx.fillCircle(vec2(128.0, 128.0 + sin(float(frameCount)/10.0) * 20), 76.8)
|
||||||
|
|
||||||
|
inc frameCount
|
||||||
|
|
||||||
|
var dataPtr = ctx.image.data[0].addr
|
||||||
|
mainSerface.pixels = dataPtr
|
||||||
|
mainTexture = render.createTextureFromSurface(mainSerface)
|
||||||
|
render.copy(mainTexture, nil, nil)
|
||||||
|
render.present()
|
||||||
|
|
||||||
|
discard sdl2.init(INIT_EVERYTHING)
|
||||||
|
window = createWindow("SDL/Pixie", 100, 100, cint w, cint h, SDL_WINDOW_SHOWN)
|
||||||
|
const
|
||||||
|
rmask = uint32 0x000000ff
|
||||||
|
gmask = uint32 0x0000ff00
|
||||||
|
bmask = uint32 0x00ff0000
|
||||||
|
amask = uint32 0xff000000
|
||||||
|
mainSerface = createRGBSurface(0, cint w, cint h, 32, rmask, gmask, bmask, amask)
|
||||||
|
|
||||||
|
render = createRenderer(window, -1, 0)
|
||||||
|
|
||||||
|
while true:
|
||||||
|
while pollEvent(evt):
|
||||||
|
if evt.kind == QuitEvent:
|
||||||
|
quit(0)
|
||||||
|
display()
|
||||||
|
delay(14)
|
131
examples/realtime_win32.nim
Normal file
131
examples/realtime_win32.nim
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
## This example show how to have real time pixie using win32 API.
|
||||||
|
|
||||||
|
import pixie, winim/lean
|
||||||
|
|
||||||
|
let
|
||||||
|
w: int32 = 256
|
||||||
|
h: int32 = 256
|
||||||
|
|
||||||
|
var
|
||||||
|
screen = newImage(w, h)
|
||||||
|
ctx = newContext(screen)
|
||||||
|
frameCount = 0
|
||||||
|
hwnd: HWND
|
||||||
|
running = true
|
||||||
|
|
||||||
|
proc draw() =
|
||||||
|
# draw shiny sphere on gradient background
|
||||||
|
var linerGradient = Paint(kind: pkGradientLinear)
|
||||||
|
linerGradient.gradientHandlePositions.add(vec2(0, 0))
|
||||||
|
linerGradient.gradientHandlePositions.add(vec2(0, 256))
|
||||||
|
linerGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(0, 0, 0, 255), position: 0))
|
||||||
|
linerGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(255, 255, 255, 255), position: 1))
|
||||||
|
ctx.fillStyle = linerGradient
|
||||||
|
ctx.fillRect(0, 0, 256, 256)
|
||||||
|
|
||||||
|
var radialGradient = Paint(kind: pkGradientRadial)
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(128, 128))
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(256, 128))
|
||||||
|
radialGradient.gradientHandlePositions.add(vec2(128, 256))
|
||||||
|
radialGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(255, 255, 255, 255), position: 0))
|
||||||
|
radialGradient.gradientStops.add(
|
||||||
|
ColorStop(color: rgbx(0, 0, 0, 255), position: 1))
|
||||||
|
ctx.fillStyle = radialGradient
|
||||||
|
ctx.fillCircle(vec2(128.0, 128.0 + sin(float(frameCount)/10.0) * 20), 76.8)
|
||||||
|
|
||||||
|
inc frameCount
|
||||||
|
|
||||||
|
# Draw image pixels onto win32 window.
|
||||||
|
let
|
||||||
|
w = screen.width.int32
|
||||||
|
h = screen.height.int32
|
||||||
|
dc = GetDC(hwnd)
|
||||||
|
var info = BITMAPINFO()
|
||||||
|
info.bmiHeader.biBitCount = 32
|
||||||
|
info.bmiHeader.biWidth = w
|
||||||
|
info.bmiHeader.biHeight = h
|
||||||
|
info.bmiHeader.biPlanes = 1
|
||||||
|
info.bmiHeader.biSize = DWORD sizeof(BITMAPINFOHEADER)
|
||||||
|
info.bmiHeader.biSizeImage = w * h * 4
|
||||||
|
info.bmiHeader.biCompression = BI_RGB
|
||||||
|
var bgrBuffer = newSeq[uint8](screen.data.len * 4)
|
||||||
|
# Convert to BGRA.
|
||||||
|
for i, c in screen.data:
|
||||||
|
bgrBuffer[i*4+0] = c.b
|
||||||
|
bgrBuffer[i*4+1] = c.g
|
||||||
|
bgrBuffer[i*4+2] = c.r
|
||||||
|
discard StretchDIBits(
|
||||||
|
dc,
|
||||||
|
0,
|
||||||
|
h - 1,
|
||||||
|
w,
|
||||||
|
-h,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
bgrBuffer[0].addr,
|
||||||
|
info,
|
||||||
|
DIB_RGB_COLORS,
|
||||||
|
SRCCOPY
|
||||||
|
)
|
||||||
|
discard ReleaseDC(hwnd, dc)
|
||||||
|
|
||||||
|
proc windowProc(hwnd: HWND, message: UINT, wParam: WPARAM,
|
||||||
|
lParam: LPARAM): LRESULT {.stdcall.} =
|
||||||
|
case message
|
||||||
|
of WM_DESTROY:
|
||||||
|
PostQuitMessage(0)
|
||||||
|
running = false
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return DefWindowProc(hwnd, message, wParam, lParam)
|
||||||
|
|
||||||
|
proc main() =
|
||||||
|
var
|
||||||
|
hInstance = GetModuleHandle(nil)
|
||||||
|
appName = "Win32/Pixie"
|
||||||
|
msg: MSG
|
||||||
|
wndclass: WNDCLASS
|
||||||
|
|
||||||
|
wndclass.style = CS_HREDRAW or CS_VREDRAW
|
||||||
|
wndclass.lpfnWndProc = windowProc
|
||||||
|
wndclass.cbClsExtra = 0
|
||||||
|
wndclass.cbWndExtra = 0
|
||||||
|
wndclass.hInstance = hInstance
|
||||||
|
wndclass.hIcon = LoadIcon(0, IDI_APPLICATION)
|
||||||
|
wndclass.hCursor = LoadCursor(0, IDC_ARROW)
|
||||||
|
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH)
|
||||||
|
wndclass.lpszMenuName = nil
|
||||||
|
wndclass.lpszClassName = appName
|
||||||
|
|
||||||
|
if RegisterClass(wndclass) == 0:
|
||||||
|
MessageBox(0, "This program requires Windows NT!", appName, MB_ICONERROR)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Figure out the right size of the window we want.
|
||||||
|
var rect: lean.RECT
|
||||||
|
rect.left = 0
|
||||||
|
rect.top = 0
|
||||||
|
rect.right = w
|
||||||
|
rect.bottom = h
|
||||||
|
AdjustWindowRectEx(cast[LPRECT](rect.addr), WS_OVERLAPPEDWINDOW, 0, 0)
|
||||||
|
|
||||||
|
# Open the window.
|
||||||
|
hwnd = CreateWindow(appName, "Win32/Pixie", WS_OVERLAPPEDWINDOW,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top,
|
||||||
|
0, 0, hInstance, nil)
|
||||||
|
|
||||||
|
ShowWindow(hwnd, SW_SHOW)
|
||||||
|
UpdateWindow(hwnd)
|
||||||
|
|
||||||
|
while running:
|
||||||
|
draw()
|
||||||
|
PeekMessage(msg, 0, 0, 0, PM_REMOVE)
|
||||||
|
TranslateMessage(msg)
|
||||||
|
DispatchMessage(msg)
|
||||||
|
|
||||||
|
main()
|
Loading…
Reference in a new issue