PureBasic Forum https://www.purebasic.fr/english/ |
|
[Library] SPP (SimplePixelProc) - GFX library [Win x64/x86] https://www.purebasic.fr/english/viewtopic.php?f=27&t=76553 |
Page 1 of 1 |
Author: | Mijikai [ Fri Jan 08, 2021 9:08 pm ] |
Post subject: | [Library] SPP (SimplePixelProc) - GFX library [Win x64/x86] |
SPP is a small, experimental gfx library written in PureBasic. Motivation: Shaders are cool! http://www.shadertoy.com For me SPP is a tool to learn glsl shader coding without the need to learn the glsl syntax first ![]() The PixelProc callback is called for every pixel (like a shader would). Doing complex math on every pixel is slow thats why SPP supports multithreading to mitigate performance issues as good as possible. Its good enough to learn, experiment and write small shaderlike programs. Note: Since the backbuffer is fully accessible you can pretty much do whatever you want. You dont need to use the PixelProc callback at all - just fill the backbuffer and render it ![]() Example 'shader': ![]() Include: Code: EnableExplicit ;Name: SPP lib (Simple Pixel Process) ;Version: Alpha (Draft 4) ;Author: Mijikai ;License: CC BY 3.0 / https://creativecommons.org/licenses/by/3.0/ #SPP_VERSION = $0001 CompilerIf #PB_Compiler_Processor = #PB_Processor_x86 Import "spp32.lib" sppContext.i(Hwnd.i,Width.i,Height.i,ColorBack.i = $0,ColorFront.i = $111111) sppVersion.i() EndImport CompilerElse Import "spp64.lib" sppContext.i(Hwnd.i,Width.i,Height.i,ColorBack.i = $0,ColorFront.i = $111111) sppVersion.i() EndImport CompilerEndIf Interface SPP Viewport.i() ;<- updates the viewport when the window/screen is resized (respects the aspect ratio) Clear.i(Color.i = $FF000000) ;<- clears/fills the backbuffer with the specified color SwapBuffer.i() ;<- flips aka. renders the backbuffer Buffer.i(*Buffer = #Null) ;<- returns a pointer to the backbuffer or fills a SPP_BUFFER structure Pixel.i(*Pixel,*Color) ;<- changes the color of the pixel pointet to by *Pixel with the color pointet to by *Color (color has to be a vec4) PixelProc.i(*Callback = #Null,MultiThreaded.i = #False) ;<- creates a callback / if MultiThreaded is #True threading is enabled (1 thread for every physical processor or at least 2) ; if MuliThreaded > 1 threads are created according to the screen size! Event.i(Milliseconds.i = 16) ;<- creates a timed event that can be used with the wait function (returns #True if the event could be created) Wait.i() ;<- waits for a timed event (default 16 ms ~ 60 fps) Info.i(*Frames,*Time) ;<- returns the fps (integer) and time (float) in seconds since the the first frame was rendered Release.i() ;<- releases all EndInterface Structure SPP_RECT x.l y.l w.l h.l EndStructure Structure SPP_BUFFER output.SPP_RECT *bits pitch.i size.i EndStructure ;Procedure.i Callback(*coord.VEC2,*color.VEC4);<- PixelProc ;*coord <- coordinates of the current pixel ;*color <- pointer to a vec4 that receives the color (alpha is ignored) ;ProcedureReturn ;EndProcedure Example Code: Code: EnableExplicit ;Example 'Shader' ;Author: Mijikai XIncludeFile "spp.pbi" Structure VEC2 x.f:y.f EndStructure Structure VEC3 x.f:y.f:z.f EndStructure Structure VEC4 x.f:y.f:z.f:w.f EndStructure Global time.f Macro Vec2(_v_,_x_,_y_) _v_\x = _x_:_v_\y = _y_ EndMacro Macro Vec4(_v_,_x_,_y_,_z_,_w_) _v_\x = _x_:_v_\y = _y_:_v_\z = _z_:_v_\w = _w_ EndMacro Macro Vec2Rotate(_v_,_a_,_out_) _out_\x = _v_\x * Cos(_a_) - _v_\y * Sin(_a_) _out_\y = _v_\x * Sin(_a_) + _v_\y * Cos(_a_) EndMacro Macro Vec2UV(_v_,_w_,_h_,_out_) _out_\x = ((_v_\x / _w_) * 2.0 - 1.0) * (_w_ / _h_) _out_\y = (_v_\y / _h_) * 2.0 - 1.0 EndMacro Procedure.i Callback(*coord.VEC2,*color.VEC4) Protected uv.VEC2,rot.VEC2,col.VEC3,d.f,m.f Vec2UV(*coord,960,600,uv) Vec2Rotate(uv,time,rot) d = 0.6 - Sin(Abs(rot\x) * Cos(Abs(uv\x) + rot\x) * 40.0) * 1.1 d + Cos(Abs(Mod(d,20.0))) If Abs(uv\x + Sin(time * 10.0 + uv\y * 4) / 10.0) < 0.4 col\x = Abs(uv\x + Sin(time * 8.0 + uv\y * 4) / 10.0) + d / 80.0 col\y = col\x / 10.0 col\z = 1.0 - col\x Else col\x = Abs(uv\x) / d - 0.4 col\y = Sin(Sin(time * 2.0) * 5.0 * Abs(rot\y)) - d col\z = 1.0 - col\x + Cos(Abs(rot\y)) - d EndIf Vec4(*color,col\x,col\y,col\z,1.0) ProcedureReturn EndProcedure Procedure.i Main(Width.i,Height.i) Protected *spp.SPP,fps.i If sppVersion() = #SPP_VERSION If OpenWindow(0,0,0,Width,Height,#Null$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget) WindowBounds(0,WindowWidth(0),WindowHeight(0),#PB_Ignore,#PB_Ignore) *spp = sppContext(WindowID(0),WindowWidth(0),WindowHeight(0)) If *spp If *spp\Event() *spp\PixelProc(@Callback(),#True) Repeat Repeat Select WindowEvent() Case #PB_Event_SizeWindow:*spp\Viewport() Case #PB_Event_CloseWindow:Break 2 Case #Null:Break EndSelect ForEver *spp\Clear() *spp\SwapBuffer() *spp\Wait() *spp\Info(@fps,@time) SetWindowTitle(0,"FPS: " + Str(fps)) ForEver EndIf *spp\Release() EndIf CloseWindow(0) EndIf EndIf ProcedureReturn EndProcedure Main(960,600) End Download (Library): https://www.dropbox.com/s/c2nk3mi0pbu3za0/spp_alpha.zip?dl=0 Have fun learning & experimenting ![]() |
Author: | Mijikai [ Sun Jan 10, 2021 10:36 am ] |
Post subject: | Re: [Library] SPP (SimplePixelProc) - GFX library [Win x64/x |
Another example ![]() SDF Raymarching ![]() Code: Code: EnableExplicit
;Example Raymarching ;Infos & Tutorials: ;https://www.iquilezles.org/www/index.htm ;------------------------------------------------------------------------------------ XIncludeFile "spp.pbi" ;------------------------------------------------------------------------------------ Structure VEC2 x.f y.f EndStructure Structure VEC3 x.f y.f z.f EndStructure Structure VEC4 x.f y.f z.f w.f EndStructure ;------------------------------------------------------------------------------------ #SPP_W = 960 #SPP_H = 600 Global time.f ;------------------------------------------------------------------------------------ Macro valMin(_a_,_b_,_out_) If _a_ < _b_ _out_ = _a_ Else _out_ = _b_ EndIf EndMacro Macro valMax(_a_,_b_,_out_) If _a_ > _b_ _out_ = _a_ Else _out_ = _b_ EndIf EndMacro Macro vec2(_v_,_x_,_y_) _v_\x = _x_ _v_\y = _y_ EndMacro Macro vec2Length(_v_) Sqr((_v_\x * _v_\x) + (_v_\y * _v_\y)) EndMacro Macro vec3(_v_,_x_,_y_,_z_) _v_\x = _x_ _v_\y = _y_ _v_\z = _z_ EndMacro Macro vec4(_v_,_x_,_y_,_z_,_w_) _v_\x = _x_ _v_\y = _y_ _v_\z = _z_ _v_\w = _w_ EndMacro Macro vec3MulVal(_v_,_val_,_out_) _out_\x = _v_\x * _val_ _out_\y = _v_\y * _val_ _out_\z = _v_\z * _val_ EndMacro Macro vec3Add(_v1_,_v2_,_out_) _out_\x = _v1_\x + _v2_\x _out_\y = _v1_\y + _v2_\y _out_\z = _v1_\z + _v2_\z EndMacro Macro vec3Sub(_v1_,_v2_,_out_) _out_\x = _v1_\x - _v2_\x _out_\y = _v1_\y - _v2_\y _out_\z = _v1_\z - _v2_\z EndMacro Macro vec3Abs(_v_,_out_) _out_\x = Abs(_v_\x) _out_\y = Abs(_v_\y) _out_\z = Abs(_v_\z) EndMacro Macro vec3SubVal(_v_,_val_,_out_) _out_\x = _v_\x - _val_ _out_\y = _v_\y - _val_ _out_\z = _v_\z - _val_ EndMacro Macro vec3MaxVal(_v_,_val_,_out_) valMax(_v_\x,_val_,_out_\x) valMax(_v_\y,_val_,_out_\y) valMax(_v_\z,_val_,_out_\z) EndMacro Macro vec3RayPos(_ro_,_rd_,_dst_,_out_) vec3MulVal(_rd_,_dst_,_out_) vec3Add(_ro_,_out_,_out_) EndMacro Macro vec3Length(_v_) Sqr((_v_\x * _v_\x) + (_v_\y * _v_\y) + (_v_\z * _v_\z)) EndMacro Macro vec3DivVal(_v_,_val_,_out_) _out_\x = _v_\x / _val_ _out_\y = _v_\y / _val_ _out_\z = _v_\z / _val_ EndMacro Macro rayScreen(_v_,_w_,_h_,_out_) If _w_ > _h_ vec2(_out_,(_v_\x - (0.5 * _w_)) / _h_,(_v_\y - (0.5 * _h_)) / _h_) Else vec2(_out_,(_v_\x - (0.5 * _w_)) / _w_,(_v_\y - (0.5 * _h_)) / _w_) EndIf EndMacro Procedure.i vec3Normalize(*v.vec3) Protected length.f length = vec3Length(*v) vec3DivVal(*v,length,*v) ProcedureReturn EndProcedure ;------------------------------------------------------------------------------------ Procedure.f sdfCube(*ray.VEC3,*pos.VEC3,size.f) Protected mov.VEC3 vec3Sub(*ray,*pos,mov) vec3Abs(mov,mov) vec3SubVal(mov,size,mov) vec3MaxVal(mov,0.0,mov) ProcedureReturn vec3Length(mov) EndProcedure Procedure.f sdfTorus(*ray.VEC3,*pos.VEC3,radius.f,size.f) Protected dst.VEC3 vec2(dst,*ray\x - *pos\x,*ray\z - *pos\z) vec2(dst,vec2Length(dst) - radius,*ray\y - *pos\y) ProcedureReturn vec2Length(dst) - size EndProcedure Procedure.f Scene(*ray.VEC3) Protected a.VEC3,b.VEC3,c.VEC3 Protected cube.f,torus.f,d.f,m.f *ray\z = Mod(*ray\z + Sin(time / 100.0) * 100.0,8.0) - 4.0 *ray\x = Mod(*ray\x + Sin(time / 4.0) * 100,8.0) - 4.0 *ray\y = Mod(Abs(*ray\y) + Sin(time / 10.0),20.0) - 2.0 vec3(a,0.0,4.0,0.0) vec3(b,0.0,6.0,0.0) cube = sdfCube(*ray,@a,1.0) torus = sdfTorus(*ray,@b,2.0,0.4) valMin(cube,torus,d) ProcedureReturn d EndProcedure Procedure.f Raymarch(*ro.VEC3,*rd.VEC3) Protected ray.VEC3,t.f,d.f,i.i For i = 0 To 127 vec3RayPos(*ro,*rd,d,ray) t = Scene(@ray):d + t If t < 0.01 Or d > 128.0 Break EndIf Next ProcedureReturn d EndProcedure Procedure.i Callback(*coord.VEC2,*color.VEC4) Protected uv.VEC2 Protected ro.VEC3 Protected rd.VEC3 Protected d.f rayScreen(*coord,320,200,uv) vec3(ro,1000.0,12.0 * time,48.0 * time) vec3(rd,uv\x,uv\y,1.0) vec3Normalize(rd) d = 1.2 - (Raymarch(@ro,@rd) / 200.0) vec4(*color,Abs(uv\y),d * Sin(time) * Abs(uv\y),d,1.0) ProcedureReturn EndProcedure ;------------------------------------------------------------------------------------ Procedure.i Main() Protected *spp.SPP,fps.i If sppVersion() = #SPP_VERSION If OpenWindow(0,0,0,#SPP_W,#SPP_H,#Null$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget) WindowBounds(0,WindowWidth(0),WindowHeight(0),#PB_Ignore,#PB_Ignore) *spp = sppContext(WindowID(0),320,200) If *spp If *spp\Event() *spp\PixelProc(@Callback(),#True) Repeat Repeat Select WindowEvent() Case #PB_Event_SizeWindow:*spp\Viewport() Case #PB_Event_CloseWindow:Break 2 Case #Null:Break EndSelect ForEver *spp\Clear() *spp\SwapBuffer() *spp\Wait() *spp\Info(@fps,@time) SetWindowTitle(0,"FPS: " + Str(fps)) ForEver EndIf *spp\Release() EndIf CloseWindow(0) EndIf EndIf ProcedureReturn EndProcedure Main() End |
Author: | Mr.L [ Sun Jan 10, 2021 10:51 pm ] |
Post subject: | Re: [Library] SPP (SimplePixelProc) - GFX library [Win x64/x |
Thx, that's really nice! Some time ago I wrote a similar program, but it wasn't quite as fast as your library. |
Author: | Mijikai [ Mon Jan 11, 2021 10:17 pm ] |
Post subject: | Re: [Library] SPP (SimplePixelProc) - GFX library [Win x64/x |
Mr.L wrote: Thx, that's really nice! Some time ago I wrote a similar program, but it wasn't quite as fast as your library. Thank you ![]() -------------------------------------------------------------------------------- Update Alpha 2: I added a new function sppWindow() which creates a window that hosts a PixelProc callback. A very fast and easy way to setup SPP ![]() Quote: sppWindow.i(Title.s,WndWidth.i,WndHeight.i,WndType.i,ScrWidth.i,ScrHeight.i,*Callback,MultiThreaded.i = #False,Milliseconds.i = 16,*Time.Float = #Null,*Frames.Integer = #Null,ShowFrames.i = #True) Following window modes are supported: Code: Enumeration #SPP_WINDOW_NORMAL #SPP_WINDOW_SIZEABLE #SPP_WINDOW_POPUP #SPP_WINDOW_SCREEN EndEnumeration Example: Code: EnableExplicit XIncludeFile "spp.pbi" Global time.f Global fps.i Structure VEC2 x.f y.f EndStructure Structure VEC4 x.f y.f z.f w.f EndStructure Procedure.i Callback(*coord.VEC2,*color.VEC4);<- PixelProc ; vec4(*color,0.3 + Sin(time * 4.0),0.6 - Cos(time * 4.0),0.0,1.0) *color\x = Sin(time * 4.0) *color\y = Cos(time * 4.0) ProcedureReturn;<- fastest way to return EndProcedure Procedure.i Main() Protected state.i If sppVersion() = #SPP_VERSION;<- Check if the version is valid! state = sppWindow("Test Window",960,600,#SPP_WINDOW_SIZEABLE,320,200,@Callback(),#False,16,@time,@fps,#True);<- If the return is > 0 everything worked! ;Note: ;#SPP_WINDOW_POPUP -> pressing [ESC] will close the window! ;#SPP_WINDOW_SCREEN -> pressing [ESC] will toggle between #SPP_WINDOW_SCREEN and #SPP_WINDOW_NORMAL! ;In order to detect [ESC] the window needs to have the input focus! ;Dont use Debug on *Time & *Frames! EndIf If state Debug "All went fine!" Else Debug "There was an error!" EndIf ProcedureReturn EndProcedure Main() End Download Alpha 2: https://www.dropbox.com/s/315f9g9n3imc1ez/spp_alpha_2.zip?dl=0 Have fun ![]() |
Author: | Mijikai [ Fri Jan 15, 2021 4:44 pm ] |
Post subject: | Re: [Library] SPP (SimplePixelProc) - GFX library [Win x64/x |
Update Alpha 3: - fixed a small bug Example Blobs: ![]() Code: Code: EnableExplicit ;Example 'Shader': Blobs ;Original by PauloFalcao: https://www.shadertoy.com/view/lsfGzr XIncludeFile "spp.pbi" Structure VEC2 x.f y.f EndStructure Structure VEC4 x.f y.f z.f w.f EndStructure Global time.f Procedure.f MakePoint(x.f,y.f,fx.f,fy.f,sx.f,sy.f) Protected xx.f,yy.f xx = x + Sin(time * fx) * sx yy = y + Cos(time * fy) * sy If xx Or yy ProcedureReturn 1.0 / Sqr(xx * xx + yy * yy) EndIf ProcedureReturn 0.0 EndProcedure Procedure.i Callback(*coord.VEC2,*color.VEC4) Protected x.f,y.f,a.f,b.f,c.f x = ((*coord\x / 320) * 2.0 - 1.0) * 2.0 y = ((*coord\y / 320) * 2.0 - (200 / 320)) * 2.0 a = MakePoint(x,y,3.3,2.9,0.3,0.3) a + MakePoint(x,y,1.9,2.0,0.4,0.4) a + MakePoint(x,y,0.8,0.7,0.4,0.5) a + MakePoint(x,y,2.3,0.1,0.6,0.3) a + MakePoint(x,y,0.8,1.7,0.5,0.4) a + MakePoint(x,y,0.3,1.0,0.4,0.4) a + MakePoint(x,y,1.4,1.7,0.4,0.5) a + MakePoint(x,y,1.3,2.1,0.6,0.3) a + MakePoint(x,y,1.8,1.7,0.5,0.4) b = MakePoint(x,y,1.2,1.9,0.3,0.3) b + MakePoint(x,y,0.7,2.7,0.4,0.4) b + MakePoint(x,y,1.4,0.6,0.4,0.5) b + MakePoint(x,y,2.6,0.4,0.6,0.3) b + MakePoint(x,y,0.7,1.4,0.5,0.4) b + MakePoint(x,y,0.7,1.7,0.4,0.4) b + MakePoint(x,y,0.8,0.5,0.4,0.5) b + MakePoint(x,y,1.4,0.9,0.6,0.3) b + MakePoint(x,y,0.7,1.3,0.5,0.4) c = MakePoint(x,y,3.7,0.3,0.3,0.3) c + MakePoint(x,y,1.9,1.3,0.4,0.4) c + MakePoint(x,y,0.8,0.9,0.4,0.5) c + MakePoint(x,y,1.2,1.7,0.6,0.3) c + MakePoint(x,y,0.3,0.6,0.5,0.4) c + MakePoint(x,y,0.3,0.3,0.4,0.4) c + MakePoint(x,y,1.4,0.8,0.4,0.5) c + MakePoint(x,y,0.2,0.6,0.6,0.3) c + MakePoint(x,y,1.3,0.5,0.5,0.4) *color\x = a / 32.0 *color\y = b / 32.0 *color\z = c / 32.0 ProcedureReturn EndProcedure sppWindow("Example FPS: ",960,600,#SPP_WINDOW_NORMAL,320,200,@Callback(),#True,16,@time,#Null,#True) End Download Alpha 3: https://www.dropbox.com/s/d0456l8pzsoqxwp/spp_alpha_3.zip?dl=0 |
Author: | Mr.L [ Fri Jan 15, 2021 5:32 pm ] |
Post subject: | Re: [Library] SPP (SimplePixelProc) - GFX library [Win x64/x |
Very nice!!! I got a "division by zero" error in the Procedure MakePoint but it worked well like this: Code: Procedure.f MakePoint(x.f,y.f,fx.f,fy.f,sx.f,sy.f)
Protected xx.f,yy.f xx = x + Sin(time * fx) * sx yy = y + Cos(time * fy) * sy If xx Or yy ProcedureReturn 1.0 / Sqr(xx * xx + yy * yy) EndIf EndProcedure |
Author: | Mijikai [ Fri Jan 15, 2021 5:43 pm ] |
Post subject: | Re: [Library] SPP (SimplePixelProc) - GFX library [Win x64/x |
Mr.L wrote: Very nice!!! I got a "division by zero" error in the Procedure MakePoint but it worked well like this: ... Thx, i edited the example code to include your fix ![]() ![]() |
Page 1 of 1 | All times are UTC + 1 hour |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |