Engine de Raytracing dentro de uma query SELECT de MySQL
MySQL é um banco de dados sensacional, ao ponto de uma pessoa ter conseguido escrever um raytracer dentro de uma query de SELECT
. Ray tracing é um dos algoritmos mais sofisticados de renderização 3D que simula o transporte e reflexo de "raios de luz" se espalhando pela cena.
Segue abaixo a query com parâmetros customizáveis e uma das imagens que foi renderizada utilizando ela.
Imagem resultante
Esta imagem utilizou a query abaixo com a resolução em 1920x1080
e demorou por volta de 10 minutos para renderizar em um Processador Intel Xeon E3-1246.
Query
/* MySQL raytracing engine by Nick ([email protected]) */
Select if(repeat(char(
/* Parameters */
@w := 512, /* width of the output in pixels */
@h := 512, /* height of the output in pixels */
@cam.x := 0.0, /* x-position of the camera */
@cam.y := 0.0, /* y-position of the camera */
@cam.z := -4.5, /* z-position of the camera */
@cam.lookatx := 0.0, /* x-position of a point at which the camera looks at */
@cam.lookaty := 0.0, /* y-position of a point at which the camera looks at */
@cam.lookatz := 0.0, /* z-position of a point at which the camera looks at */
@cam.upx := 0.0, /* x-part of the camera's up vector */
@cam.upy := 1.0, /* y-part of the camera's up vector */
@cam.upz := 0.0, /* z-part of the camera's up vector */
@light.x := 0.0, /* x-position of the lightsource */
@light.y := 0.95, /* y-position of the lightsource */
@light.z := 0.0, /* z-position of the lightsource */
@light.r := 0.35, /* radius of the lightsource */
@fov := 50, /* Field of view in degrees */
@shadows := true, /* shadows enabled? */
@maxRecDepth := 10, /* max. recursion depth for reflections */
/* List of triangles in the scene, separated by semicolons. */
/* Each triangle is given by xyz-coordinates of three vertices, separated by */
/* commas. Then follows the material which can be either "m" for matte or "r" */
/* for reflective. Matte materials are followed by three values representing */
/* the color in r,g,b format. */
@triangles := "-10.0,-1.0,-10.0,10.0,-1.0,-10.0,0.0,-1.0,5.0,m,0.6,0.6,0.6;
-10.0,1.0,-10.0,10.0,1.0,-10.0,0.0,1.0,5.0,m,0.6,0.6,0.6;
-1.0,-10.0,-10.0, -1.0,10.0,-10.0, -1.0,0,5.0, m, 0.85,0.5,0.0;
1.0,-10.0,-10.0, 1.0,10.0,-10.0, 1.0,0,5.0, m, 0.2,0.6,0.75;
-10.0,-10.0,1.0, 10.0,-10.0,1.0, 0.0,5.0,1.0, m, 0.6,0.6,0.6;
-100.0,-100.0,-10.0, 100.0,-100.0,-10.0, 0.0,50.0,-10.0, m, 0.6,0.6,0.6;",
/* List of spheres in the scene, separated by semicolons. */
/* Each sphere is given by its xyz-coordinates and a radius, separated by */
/* commas. Then follows the material which can be either "m" for matte or "r" */
/* for reflective. Matte materials are followed by three values representing */
/* the color in r,g,b format. */
@spheres := "-0.5,-0.6,0.3,0.4,r;
0.4,-0.6,-0.6,0.4,r,3.0;
1.0,0.0,0.5,0.25,m,0.2,0.8,0.2;",
/* end of parameters */
@spheres:=concat(@spheres,@light.x,",",@light.y,",",@light.z,",",@light.r,",l;")
,@triangles:=replace(replace(replace(@triangles," ",""),"\t",""),"\n",""),
@spheres:=replace(replace(replace(@spheres," ",""),"\t",""),"\n",""),@ntriangles
:=(length(@triangles)-length(replace(@triangles,";",""))),@nspheres:=(length(
@spheres)-length(replace(@spheres,";",""))),@nprimitives:=@ntriangles+@nspheres,
@aspectRatio:=@w/@h,@fov:=@fov*(3.14159/180.0),@epsilon:=0.000001,@linelen:=4*
floor((@w*24+31)/32),@cdx:=@cam.lookatx-@cam.x,@cdy:=@cam.lookaty-@cam.y,@cdz:=
@cam.lookatz-@cam.z,@tlen:=sqrt(@cdx*@cdx+@cdy*@cdy+@cdz*@cdz),@rotz1:=@cdx/
@tlen,@rotz2:=@cdy/@tlen,@rotz3:=@cdz/@tlen,@rotx1:=@cam.upy*@rotz3-@cam.upz*
@rotz2,@rotx2:=@cam.upz*@rotz1-@cam.upx*@rotz3,@rotx3:=@cam.upx*@rotz2-@cam.upy*
@rotz1,@tlen:=sqrt(@rotx1*@rotx1+@rotx2*@rotx2+@rotx3*@rotx3),@rotx1:=@rotx1/
@tlen,@rotx2:=@rotx2/@tlen,@rotx3:=@rotx3/@tlen,@roty1:=@rotz2*@rotx3-@rotz3*
@rotx2,@roty2:=@rotz3*@rotx1-@rotz1*@rotx3,@roty3:=@rotz1*@rotx2-@rotz2*@rotx1,
@r:=concat(0x424d,reverse(lpad(char(26+@h*@linelen),4,0x00)),0x00000000,
0x1A000000,0x0C000000,reverse(lpad(char(@w),2,0x00)),reverse(lpad(char(@h),2,
0x00)),0x01001800),@pxy:=0,Benchmark(@h,char(@pxx:=0,@line:=repeat(0xff,0),
Benchmark(@w,char(@degx:=(((@pxx+0.5)/@w)-0.5)*@fov*@aspectRatio,@degy:=(((@pxy+
0.5)/@h)-0.5)*@fov,@tx:=sin(@degx),@ty:=sin(@degy),@tz:=1.0,@rdx:=@tx*@rotx1+@ty
*@roty1+@tz*@rotz1,@rdy:=@tx*@rotx2+@ty*@roty2+@tz*@rotz2,@rdz:=@tx*@rotx3+@ty*
@roty3+@tz*@rotz3,@rox:=@cam.x,@roy:=@cam.y,@roz:=@cam.z,@doray:=true,
@shadowdone:=false,@cr:=0,@cg:=0,@cb:=0,@inside:=false,benchmark(@maxRecDepth+if
(@shadows,2,1),if(@doray,char(@doray:=false,@tlen:=sqrt(@rdx*@rdx+@rdy*@rdy+@rdz
*@rdz),@rdx:=@rdx/@tlen,@rdy:=@rdy/@tlen,@rdz:=@rdz/@tlen,@i:=0,@triangleptr:=1,
@sphereptr:=1,@intersect:=false,@mindist:=999999,@material:="n",@nox:=0,@noy:=0,
@noz:=0,@primitive:="",@ptr:=0,benchmark(@nprimitives,char(@primhit:=false,if(@i
<@ntriangles,concat(@tpos:=locate(";",@triangles,@triangleptr),@primitive:=mid(
@triangles,@triangleptr,@tpos-@triangleptr+1),@triangleptr:=@tpos+1,@tpos:=instr
(@primitive,","),@v1x:=left(@primitive,@tpos-1),@ptr:=@tpos+1,@tpos:=locate(",",
@primitive,@ptr),@v1y:=mid(@primitive,@ptr,@tpos-@ptr),@ptr:=@tpos+1,@tpos:=
locate(",",@primitive,@ptr),@v1z:=mid(@primitive,@ptr,@tpos-@ptr),@ptr:=@tpos+1,
@tpos:=locate(",",@primitive,@ptr),@v2x:=mid(@primitive,@ptr,@tpos-@ptr),@ptr:=
@tpos+1,@tpos:=locate(",",@primitive,@ptr),@v2y:=mid(@primitive,@ptr,@tpos-@ptr)
,@ptr:=@tpos+1,@tpos:=locate(",",@primitive,@ptr),@v2z:=mid(@primitive,@ptr,
@tpos-@ptr),@ptr:=@tpos+1,@tpos:=locate(",",@primitive,@ptr),@v3x:=mid(
@primitive,@ptr,@tpos-@ptr),@ptr:=@tpos+1,@tpos:=locate(",",@primitive,@ptr),
@v3y:=mid(@primitive,@ptr,@tpos-@ptr),@ptr:=@tpos+1,@tpos:=locate(",",@primitive
,@ptr),@v3z:=mid(@primitive,@ptr,@tpos-@ptr),@ptr:=@tpos+1,@e1x:=@v2x-@v1x,@e1y
:=@v2y-@v1y,@e1z:=@v2z-@v1z,@e2x:=@v3x-@v1x,@e2y:=@v3y-@v1y,@e2z:=@v3z-@v1z,@Px
:=@rdy*@e2z-@rdz*@e2y,@Py:=@rdz*@e2x-@rdx*@e2z,@Pz:=@rdx*@e2y-@rdy*@e2x,@det:=
@e1x*@Px+@e1y*@Py+@e1z*@Pz,if(1.0*@det<-1.0*@epsilon||1.0*@det>1.0*@epsilon,char
(@det:=1.0/@det,@Tx:=@rox-@v1x,@Ty:=@roy-@v1y,@Tz:=@roz-@v1z,@u:=(@Tx*@Px+@Ty*
@Py+@Tz*@Pz)*@det,if(1.0*@u>=0.0&&1.0*@u<=1.0,char(@Qx:=@Ty*@e1z-@Tz*@e1y,@Qy:=
@Tz*@e1x-@Tx*@e1z,@Qz:=@Tx*@e1y-@Ty*@e1x,@v:=(@rdx*@Qx+@rdy*@Qy+@rdz*@Qz)*@det,
if(1.0*@v>=0.0&&1.0*(@u+@v)<=1.0,char(@tdist:=(@e2x*@Qx+@e2y*@Qy+@e2z*@Qz)*@det,
if(1.0*@tdist>1.0*@epsilon&&1.0*@tdist<1.0*@mindist,/*Intersection!*/char(
@primhit:=true,@intersect:=true,@mindist:=@tdist,@nox:=@e2y*@e1z-@e2z*@e1y,@noy
:=@e2z*@e1x-@e2x*@e1z,@noz:=@e2x*@e1y-@e2y*@e1x,@tlen:=sqrt(@nox*@nox+@noy*@noy+
@noz*@noz),@nox:=@nox/@tlen,@noy:=@noy/@tlen,@noz:=@noz/@tlen,@tdot:=(@nox*@rdx+
@noy*@rdy+@noz*@rdz),if(1.0*@tdot>0.0,char(@nox:=-1.0*@nox,@noy:=-1.0*@noy,@noz
:=-1.0*@noz),0)),0)),0)),0)),0)),char(@tpos:=locate(";",@spheres,@sphereptr),
@primitive:=mid(@spheres,@sphereptr,@tpos-@sphereptr+1),@sphereptr:=@tpos+1,
@tpos:=instr(@primitive,","),@spx:=left(@primitive,@tpos-1),@ptr:=@tpos+1,@tpos
:=locate(",",@primitive,@ptr),@spy:=mid(@primitive,@ptr,@tpos-@ptr),@ptr:=@tpos+
1,@tpos:=locate(",",@primitive,@ptr),@spz:=mid(@primitive,@ptr,@tpos-@ptr),@ptr
:=@tpos+1,@tpos:=locate(",",@primitive,@ptr),@spr:=mid(@primitive,@ptr,@tpos-
@ptr),@ptr:=@tpos+1,@Lx:=@spx-@rox,@Ly:=@spy-@roy,@Lz:=@spz-@roz,@tca:=@Lx*@rdx+
@Ly*@rdy+@Lz*@rdz,@d2:=@Lx*@Lx+@Ly*@Ly+@Lz*@Lz-@tca*@tca,if(1.0*@d2<=1.0*(@spr*
@spr),char(@thc:=sqrt(@spr*@spr-@d2),@tdist:=if(1.0*@tca-1.0*@thc>0.0,@tca-@thc,
0),@tdist:=if(1.0*@tca+1.0*@thc>0.0,least(@tca+@thc,@tdist),@tdist),if(1.0*
@tdist>0.0&&1.0*@tdist<1.0*@mindist,char(@primhit:=true,@intersect:=true,
@mindist:=@tdist,@nox:=@rox+@tdist*@rdx-@spx,@noy:=@roy+@tdist*@rdy-@spy,@noz:=
@roz+@tdist*@rdz-@spz,@tlen:=sqrt(@nox*@nox+@noy*@noy+@noz*@noz),@nox:=@nox/
@tlen,@noy:=@noy/@tlen,@noz:=@noz/@tlen),0)),0))),if(@primhit,char(@material:=
mid(@primitive,@ptr,1),@ptr:=@ptr+2,if(@material="m",char(@tpos:=locate(",",
@primitive,@ptr),@hor:=mid(@primitive,@ptr,@tpos-@ptr),@ptr:=@tpos+1,@tpos:=
locate(",",@primitive,@ptr),@hog:=mid(@primitive,@ptr,@tpos-@ptr),@ptr:=@tpos+1,
@tpos:=locate(";",@primitive,@ptr),@hob:=mid(@primitive,@ptr,@tpos-@ptr)),0),if(
@material="t",char(@tpos:=locate(";",@primitive,@ptr),@href:=mid(@primitive,@ptr
,@tpos-@ptr)),0)),0),@i:=@i+1)),if(@shadowdone,char(if(@material!="l",char(@cr:=
0.0,@cg:=0.0,@cb:=0.0),0)),char(if(@material="l",char(@cr:=1.0,@cg:=1.0,@cb:=1.0
),0),if(@material="m",char(@lix:=@light.x-(@rox+@rdx*@mindist),@liy:=@light.y-(
@roy+@rdy*@mindist),@liz:=@light.z-(@roz+@rdz*@mindist),@tlen:=sqrt(@lix*@lix+
@liy*@liy+@liz*@liz),@lix:=@lix/@tlen,@liy:=@liy/@tlen,@liz:=@liz/@tlen,@tdot:=
greatest(0.0,(@lix*@nox)+(@liy*@noy)+(@liz*@noz)),@cr:=@hor*@tdot,@cg:=@hog*
@tdot,@cb:=@hob*@tdot,if(@shadows&&@shadowdone=false,char(@shadowdone:=true,@rox
:=@rox+@rdx*@mindist+@nox*@epsilon,@roy:=@roy+@rdy*@mindist+@noy*@epsilon,@roz:=
@roz+@rdz*@mindist+@noz*@epsilon,@rdx:=@light.x-@rox,@rdy:=@light.y-@roy,@rdz:=
@light.z-@roz,@doray:=true),0)),0),if(@material="t",char(if(@inside,char(@nox:=-
@nox,@noy:=-@noy,@noz:=-@noz),0),@tdot:=-(@rdx*@nox)-(@rdy*@noy)-(@rdz*@noz),
@refb:=if(@inside,@href,1.0/@href),@refd2:=1.0-@refb*@refb*(1.0-@tdot*@tdot),if(
1.0*@refd2>=0.0,char(@refa:=@refb*@tdot+if(1.0*@tdot>=0.0,-1.0,1.0)*sqrt(@refd2)
,@rox:=@rox+@rdx*@mindist-@nox*@epsilon,@roy:=@roy+@rdy*@mindist-@noy*@epsilon,
@roz:=@roz+@rdz*@mindist-@noz*@epsilon,@rdx:=@refa*@nox+@refb*@rdx,@rdy:=@refa*
@noy+@refb*@rdy,@rdz:=@refa*@noz+@refb*@rdz,@inside:=!@inside,@doray:=true),char
(@material:="r"))),0),if(@material="r",char(@tdot:=(@rdx*@nox)+(@rdy*@noy)+(@rdz
*@noz),@rox:=@rox+@rdx*@mindist+@nox*@epsilon,@roy:=@roy+@rdy*@mindist+@noy*
@epsilon,@roz:=@roz+@rdz*@mindist+@noz*@epsilon,@rdx:=@rdx-2.0*@nox*@tdot,@rdy:=
@rdy-2.0*@noy*@tdot,@rdz:=@rdz-2.0*@noz*@tdot,@doray:=true),0)))),0)),@line:=
concat(@line,if(@intersect,concat(char(@cb*255),char(@cg*255),char(@cr*255)),
0x000000)),@pxx:=@pxx+1)),@r:=concat(@r,rpad(@line,@linelen,0x00)),@pxy:=@pxy+1)
)),0),0,@r) as bmpdata from (select 1) as tmp INTO DUMPFILE '/var/lib/mysql-files/sqlray.bmp'
Vídeo
Você pode acompanhar nesse vídeo a query sendo rodada em tempo-real numa resolução mais baixa. O vídeo deverá abrir no minuto 1:15
.