From 0281ef57f64b672f045b890acb5be743effaa2b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=2E=20R=C3=B8dseth?= Date: Thu, 4 Jan 2024 18:44:28 +0100 Subject: [PATCH] Update documentation --- README.md | 186 +++++++++++------------------------------------------- 1 file changed, 37 insertions(+), 149 deletions(-) diff --git a/README.md b/README.md index 0266f4a..24e01fc 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,6 @@ Concurrent software rendering, triangle rasterization and pixel buffer manipulat ![software rendered duck with glitch effect](img/glitch.png) ![software rendered beveled cube](img/cube.png) - ## Features and limitations * Can draw software-rendered triangles concurrently, using goroutines. The work of drawing the triangles is divided on the available CPU cores. @@ -22,180 +21,69 @@ Concurrent software rendering, triangle rasterization and pixel buffer manipulat * Tested together with SDL2, but can be used with any graphics library that can output pixels from a pixel buffer. * The software rendering of 3D graphics in the screenshot above is provided by [fauxgl](https://github.com/fogleman/fauxgl). The outputs from this can be combined with effects from `pixelpusher`. -Requires Go 1.3 or later, and SDL2. +## Getting started -## Example, using pixelpusher and [SDL2](https://github.com/veandco/go-sdl2): +A single red pixel in the upper left corner: -```go +``` package main import ( - "fmt" - "image/color" - "math/rand" - "os" - "runtime" - "time" - - "github.com/veandco/go-sdl2/sdl" "github.com/xyproto/pixelpusher" - "github.com/xyproto/sdl2utils" ) -const ( - // Size of "worldspace pixels", measured in "screenspace pixels" - pixelscale = 4 +func onDraw(gfx *pixelpusher.Config) error { + // x, y, r, g, b + return pixelpusher.Plot(gfx, 0, 0, 255, 0, 0) +} - // The resolution (worldspace) - width = 320 - height = 200 +func main() { + gfx := pixelpusher.New("Red Pixel") + gfx.Run(onDraw, nil, nil, nil) +} +``` - // The width of the pixel buffer, used when calculating where to place pixels (y*pitch+x) - pitch = width +A very simple drawing program: - // Target framerate - frameRate = 60 +```go +package main - // Alpha value for opaque colors - opaque = 255 -) +import ( + "errors" -var ( - // Convenience functions for returning random numbers - rw = func() int32 { return rand.Int31n(width) } - rh = func() int32 { return rand.Int31n(height) } - rb = func() uint8 { return uint8(rand.Intn(255)) } + "github.com/xyproto/pixelpusher" ) -// DrawAll fills the pixel buffer with pixels. -// "cores" is how many CPU cores should be targeted when drawing triangles, -// by launching the same number of goroutines. -func DrawAll(pixels []uint32, cores int) { - - // Draw a triangle, concurrently - pixelpusher.Triangle(cores, pixels, rw(), rh(), rw(), rh(), rw(), rh(), color.RGBA{rb(), rb(), rb(), opaque}, pitch) +var x, y = 160, 100 - // Draw a line and a red pixel, without caring about which order they appear in, or if they will complete before the next frame is drawn - go pixelpusher.Line(pixels, rw(), rh(), rw(), rh(), color.RGBA{0xff, 0xff, 0, opaque}, pitch) - go pixelpusher.Pixel(pixels, rw(), rh(), color.RGBA{0xff, 0x0, 0x0, opaque}, pitch) +func onDraw(gfx *pixelpusher.Config) error { + return pixelpusher.Plot(gfx, x, y, 255, 0, 0) } -func run() int { - - sdl.Init(uint32(sdl.INIT_VIDEO)) - - var ( - window *sdl.Window - renderer *sdl.Renderer - err error - ) - - window, err = sdl.CreateWindow("Pixels!", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, int32(width*pixelscale), int32(height*pixelscale), sdl.WINDOW_SHOWN) - if err != nil { - fmt.Fprintf(os.Stderr, "Failed to create window: %s\n", err) - return 1 +func onPress(left, right, up, down, space, enter, esc bool) error { + if up { + y-- + } else if down { + y++ } - defer window.Destroy() - - renderer, err = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED) - if err != nil { - fmt.Fprintf(os.Stderr, "Failed to create renderer: %s\n", err) - return 1 + if left { + x-- + } else if right { + x++ } - defer renderer.Destroy() - - // Fill the render buffer with color #FF00CC - renderer.SetDrawColor(0xff, 0, 0xcc, opaque) - renderer.Clear() - - texture, err := renderer.CreateTexture(sdl.PIXELFORMAT_ARGB8888, sdl.TEXTUREACCESS_STREAMING, width, height) - if err != nil { - panic(err) - } - - texture.SetBlendMode(sdl.BLENDMODE_BLEND) // sdl.BLENDMODE_ADD is also possible - - rand.Seed(time.Now().UnixNano()) - - var ( - pixels = make([]uint32, width*height) - cores = runtime.NumCPU() - event sdl.Event - quit bool - pause bool - ) - - // Innerloop - for !quit { - - if !pause { - // Draw to pixel buffer - DrawAll(pixels, cores) - - // Draw pixel buffer to screen - texture.UpdateRGBA(nil, pixels, width) - - // Clear the render buffer between each frame - renderer.Clear() - - renderer.Copy(texture, nil, nil) - renderer.Present() - } - - // Check for events - for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() { - switch event.(type) { - case *sdl.QuitEvent: - quit = true - case *sdl.KeyboardEvent: - ke := event.(*sdl.KeyboardEvent) - if ke.Type == sdl.KEYDOWN { - ks := ke.Keysym - switch ks.Sym { - case sdl.K_ESCAPE: - quit = true - case sdl.K_q: - quit = true - case sdl.K_RETURN: - altHeldDown := ks.Mod == sdl.KMOD_LALT || ks.Mod == sdl.KMOD_RALT - if !altHeldDown { - // alt+enter is not pressed - break - } - // alt+enter is pressed - fallthrough - case sdl.K_f, sdl.K_F11: - sdl2utils.ToggleFullscreen(window) - case sdl.K_SPACE, sdl.K_p: - pause = !pause - case sdl.K_s: - ctrlHeldDown := ks.Mod == sdl.KMOD_LCTRL || ks.Mod == sdl.KMOD_RCTRL - if !ctrlHeldDown { - // ctrl+s is not pressed - break - } - // ctrl+s is pressed - fallthrough - case sdl.K_F12: - // screenshot - sdl2utils.Screenshot(renderer, "screenshot.png", true) - } - } - } - } - sdl.Delay(1000 / frameRate) + if esc { + return errors.New("quit") } - return 0 + return nil } func main() { - // This is to allow the deferred functions in run() to kick in at exit - os.Exit(run()) + pixelpusher.New("Simple Draw").Run(onDraw, onPress, nil, nil) } ``` # General information -* Version: 1.0.1 -* License: 3-clause BSD -* Author: Alexander F. Rødseth <rodseth@gmail.com> +* Version: 1.1.0 +* License: BSD-3 +* Author: Alexander F. Rødseth <xyproto@archlinux.org>