Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Voxel Rendering in Symta

Name: Anonymous 2020-07-04 11:38

https://www.youtube.com/watch?v=SB6NXGXBhsE

//for testing purposes; including from main.s
use fxn gui gfx util macros rgb

WD = No

D = 50
Cube = dup D: dup D: 0
//projections
PF =
PT =
PS =

voxelator.init InitWD =
| WD <= InitWD
| PF <= gfx "[WD]disc.png"
| PT <= PF
| PS <= PT

voxelator.get_d = D

//cut by projecions
prjcut =
| times Y D: times X D:
| when PF.get{X Y}&&&#FF000000:
| Cube.X.Y <= 0
| pass
| Zs = 0
| times Z D:
| B = (PT.get{D-1-Z X}&&&#FF000000)><0
and (PS.get{D-1-Z Y}&&&#FF000000)><0
| Zs <= Zs.bitSet{Z B}
| Cube.X.Y <= Zs

cuberender_xy G =
| G.clear{0}
| G.pixels //sync
| times Y D: times X D:
| Zs = Cube.X.Y
| times Z D:
| B = Zs.bit{Z}
| C = #FF*Z/D
| Color = rgb{C C C}
| when B: G.set{X Y Color}


//vector cross product
list.cross V = [$1*V.2 - $2*V.1
$2*V.0 - $0*V.2
$0*V.1 - $1*V.0]

list.dot V = $0*V.0 + $1*V.1 + $2*V.2

list.angle V = $dot{V}/($abs*V.abs)

//to rotate around specific origin use: (P-O).rotate3d{I A}+O
list.rotate3d Axis A =
| DX,DY,DZ = Me
| CosA = A.cos
| SinA = A.sin
| if Axis >< 0 then
//| NY = DY*CosA - DZ*SinA
//| NZ = DY*SinA + DZ*CosA
| NY = DZ*SinA + DY*CosA
| NZ = DZ*CosA - DY*SinA
| DX,NY,NZ
else if Axis >< 1 then
| NX = DX*CosA + DZ*SinA
| NZ = DZ*CosA - DX*SinA
| NX,DY,NZ
else
| NX = DX*CosA - DY*SinA
| NY = DX*SinA + DY*CosA
| NX,NY,DZ

rotatePlane O Angle Plane =
| Vs = Plane.deep_copy
| Vs.1 += Vs.0 //basis vectors are relative to the origin
| Vs.2 += Vs.0
| Rs = map P Vs:
| times I 3:
| A = Angle.I
| when A<>0.0: P <= (P-O).rotate3d{I A}+O //rotate around origin O
| P
| Rs.1 <= Rs.1-Rs.0
| Rs.2 <= Rs.2-Rs.0
| Rs

MarchXYZ = [0 0 0]
march_fn X Y Z =
| when X<0 or Y<0 or Z<0 or X>>D or Y>>D or Z>>D: leave 1
| Zs = Cube.X.Y
| B = Zs.bit{Z}
| less B: leave 1
| 0

sample_cube Src Dir L =
| P = Src.copy
| while L>0:
| less march_fn P.0.int P.1.int P.2.int: done
| L--
| P.0 += Dir.0
| P.1 += Dir.1
| P.2 += Dir.2
| less L>0: leave 0
| MarchXYZ.init{P}
| (MarchXYZ-Src).abs

cuberender Angle G =
| G.clear{0}
| G.pixels //sync
| O = [D.float*0.5 D.float*0.5 D.float*0.5] //scene origin
| Camera = [[O.0 O.1 -10.0] [1.0 0.0 0.0] [0.0 1.0 0.0]]
| Angle <= Angle{?*PI2/360.0}
| SO,SBX,SBY = rotatePlane O Angle Camera
| SBZ = SBX.cross{SBY}
/*| say SO
| say SBX
| say SBY
| say SBZ*/
| Scale = 2.0
| SBX *= Scale
| SBY *= Scale
| SYP = SO.copy
| SYP -= SBX*(G.w.float/2.0)
| SYP -= SBY*(G.h.float/2.0)
| SXP = [0.0 0.0 0.0]
| MarchL = D
| times SY G.h:
| SXP.init{SYP}
| times SX G.w:
| Dist = sample_cube SXP SBZ MarchL
| if Dist then
| B = 110.0-Dist
| when B<0.0: B <= 0.0
| C = @int B*255.0/110.0
| G.set{SX SY C}
else
| G.set{SX SY #000000}
| SXP.init{SXP + SBX}
| SYP.init{SYP + SBY}

NeedsCut = 1

voxelator.render_hm =
| when NeedsCut:
| prjcut
| NeedsCut <= 0
| Angle = [35.264+($cycle*4).float 45.0+($cycle*6).float ($cycle*3).float]
//| Angle = [35.264 45.0 0.0]
//| Angle = [0.0 0.0 0.0]
//| Angle = [90.0 90.0 0.0]
//| Angle = [0.0 0.0 0.0]
| cuberender Angle $hm

type voxelator.widget{} cm hm cycle mice_x mice_y d
| $d <= $get_d
| $init{WD}
| $hm <= gfx $d $d

voxelator.w = 256
voxelator.h = 256

voxelator.input In =
| case In
[mice_move _ X,Y]
| $mice_x <= X
| $mice_y <= Y

//calculate angle between the point light and the surface normal
calc_angle X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 L =
| V0 = [X0.float Y0.float Z0.float]
| A = fxn [X1-X0 Y1-Y0 Z1-Z0]
| B = fxn [X2-X0 Y2-Y0 Z2-Z0]
| N = (A.float).cross{B.float} //surface normal
| LDir = L-V0
| LDir.angle{N} //sin of angle with normal is the light intensity

voxelator.lighten_hm Color =
//| BG = $cm
| HM = $hm
| HMW = HM.w
| HMH = HM.h
| Out = gfx HMW HMH
| Out.clear{#B000B0}
| Out.pixels
| LX = $mice_x*HM.w/$w
| LY = $mice_y*HM.h/$h
| LZ = 500
| Light = [LX LY LZ].float
| Intensity = 2.0
| Y = 1
| fxn: while Y < HMH:
| SY = Y-1
| X = 1
| while X < HMW:
| NC = HM.get{X Y}
//| Color = BG.get{X Y}
| unrgba Color R G B A
| when A: _goto end
| when NC:
| SX = X-1
| NX = HM.get{SX Y}
| NY = HM.get{X SY}
| esc
| Angle = calc_angle X Y NC SX Y NX X SY NY Light
| Light = Angle*Intensity
| R <= @int R.float*Light
| G <= @int G.float*Light
| B <= @int B.float*Light
| when R>255: R<=255
| when G>255: G<=255
| when B>255: B<=255
| when R<0: R<=0
| when G<0: G<=0
| when B<0: B<=0
| Out.set{X Y rgb{R G B}}
| _label end
| X++
| Y++
| Out

voxelator.draw FB BX BY =
//| FB.clear{#B000B0}
| $render_hm
//| $hm.quad{[-3 -3] [FB.w -3] [-3 FB.h] [FB.w FB.h]}
//| FB.blit{0 0 $hm}
//| leave
| Out = $lighten_hm{#639bff}
| FB.pixels
| Out.quad{[-3 -3] [FB.w -3] [-3 FB.h] [FB.w FB.h]}
| FB.blit{0 0 Out}
| Out.free
| 0

voxelator.render =
| get_gui{}.sleep{1.0/48.0}
| $cycle++
| Me

invert_gfx G =
| for Y G.h: for X G.w: G.set{X Y 255-G.get{X Y}}
| G

hm_to_gray HM =
| for Y HM.h: for X HM.w:
| unrgb HM.get{X Y} R G B
| HM.set{X Y (R+G+B)/3}
| HM

voxelator_run =
| CH = gfx "[WD]ch.png"
| T = voxelator
| gui T cursor/CH

Name: Anonymous 2020-07-04 15:26

Ok. I got better visual results by returning the distance to the center of voxel, instead of the place ray hit it.

And at larger resolutions it looks a bit nicer.
https://i.imgur.com/Vc2eT5I.png

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List