jeudi 29 juin 2017

Soft shading using SSE2 SIMD technology purely in assembly language !!

 note: my 3D rendering software engine  in real time (Fast3D/2D) powered with SSE4



 // function returns the mixing of 2 3d vectors = (1-u)*a+u*b
 // function returns the mixing of 3 3d vector = (1-u-v)*a+u*b+v*c
// this application is useful for the smooth shading of the triangle

inline vec mix(float u,vec a,vec b) {
__asm {
            mov        eax, 03F800000h // 1.0f
            movd      xmm0,eax
            movss     xmm1,u
            subss      xmm0,xmm1 /// 1-u
            shufps     xmm0,xmm0,_MM_SHUFFLE(3, 0, 0, 0) // xmm0 =0,1-u,1-u,1-u
            shufps     xmm1,xmm1,_MM_SHUFFLE(3, 0, 0, 0) // xmm1 =0,u,u,u
            movaps   xmm2,a
            movaps   xmm3,b
            mulps      xmm0,xmm2 /// xmm0 = (1-u)*a
            mulps      xmm1,xmm3 /// xmm1 = u*b
            addps      xmm0,xmm1 // (1-u)*a+u*b
       }
}


// supports only SSE4.2
inline vec mix2(float u,float v,vec a,vec b,vec c)   {
......
}

mercredi 7 juin 2017

filling a triangle with shader color interpolation very useful for Zbuffer algorithm

Type pixel
x as integer
y as integer
r as integer
g as integer
b as integer
end type

ScreenRes 640, 480, 16,2,0
'screenset 1,0
FUNCTION max(x as integer,y as integer) as integer
 if (x>y) then return x else return y
end function    

FUNCTION min(x as integer,y as integer) as integer
 if (x>y) then return y else return x
end function    

sub triangle(a as pixel, b as pixel, c as pixel)
 dim as single xmin,ymin,xmax,ymax,x,y
 dim as single u,v,det
 dim as pixel am,ab,ac,m
 dim as integer red,green,blue

 xmin = min(a.x,min(b.x,c.x)):xmax = max(a.x,max(b.x,c.x))
 ymin = min(a.y,min(b.y,c.y)):ymax = max(a.y,max(b.y,c.y))

  ab.x = b.x-a.x: ab.y = b.y-a.y
  ac.x = c.x-a.x: ac.y = c.y-a.y
  
 for y = ymin to ymax
     for x = xmin to xmax
         m.x = x:m.y= y 
         am.x = x-a.x: am.y = y-a.y
         det  = ab.x*ac.y-ac.x*ab.y
         u  = (am.x*ac.y-ac.x*am.y)/det: v  = -(am.x*ab.y-ab.x*am.y)/det
         
         red  = u*b.r+v*c.r+(1-u-v)*a.r:
         green  = u*b.g+v*c.g+(1-u-v)*a.g
         blue  = u*b.b+v*c.b+(1-u-v)*a.b
         
         if ( (u>=0) and ( v>=0) and ( u+v<=1))  then pset (x,y),RGB(red,green,blue) 
           
       next x
   next y

end sub

dim as single i
dim as pixel a,b,c


for i = 0 to  2000 
a.x = 640*rnd: a.y = 480*rnd
b.x = 640*rnd:b.y = 480*rnd
c.x = 640*rnd:c.y = 480*rnd

 a.r = 255*rnd: a.g = 255*rnd: a.b = 255*rnd
 b.r = 255*rnd: b.g = 255*rnd: b.b = 255*rnd
 c.r = 255*rnd: c.g = 255*rnd: c.b = 255*rnd
triangle(a,b,c)

next i



sleep

vendredi 19 mai 2017

FastMath 3D Geometry in pure inline assembly language supports SIMD SSE 4.1

//  3D geometry   support SIMD SSE4.1
//  programmed by delta fares

#include <emmintrin.h>
#include <stdio.h>

typedef __m128 vec;
typedef struct {
__m128 x;
__m128 y;
__m128 z;}  matrix;

// 3D  Math 

vec vec4(float x,float y, float z,float w);
vec vec3(float x,float y, float z);
vec vec2(float x,float y);
inline vec operator +(vec a,vec b);
inline vec operator -(vec a,vec b);
inline vec operator *(float k,vec v);
inline vec operator *(vec v,float k);
inline vec operator /(vec v,float k);
inline vec cross(vec a, vec b);
inline float norm(vec v);
inline float norm2(vec v);  // SSE4.1
inline float dot(vec a,vec b);
inline float dot2(vec a,vec b); //SSE4.1
inline float  dist2(vec a,vec b); //SSE41
inline void normalize(vec& v);
inline void normalize2(vec& v);  //SSE4.1
inline vec reflect(vec v,vec n);  //SSE4.1

matrix mat3(float a11,float a21,float a31,
                   float a12,float a22,float a32,
                   float a13,float a23,float a33);

matrix mat4(float a11,float a21,float a31,float a41,
                   float a12,float a22,float a32,float a42,
                   float a13,float a23,float a33,float a43);


inline vec  operator *(matrix& mat,vec v);
.
.
// body program

vec vec3(float x,float y, float z) {
return _mm_set_ps(0,z,y,x);}
.
.
inline vec operator +(vec a,vec b) {
__asm {
             movaps xmm0,a
             movaps xmm1,b
             addps xmm0,xmm1
      }
};

inline vec operator -(vec a,vec b) {
__asm {
             movaps xmm0,a
             movaps xmm1,b
             subps xmm0,xmm1
      }
};

.
.
inline vec operator *(vec v,float k) {
_asm {
            movss xmm0,k
            shufps xmm0,xmm0,00h
            movaps xmm1,v
            mulps xmm0,xmm1
     }
};
.
.
inline void normalize(vec& v) {
  _asm {
              mov    eax,v
              movaps xmm1,[eax]
              movaps xmm0,xmm1   //  xmm0 = v
              mulps  xmm1,xmm1  //  x² y² z²
              movaps xmm2,xmm1
              movaps xmm3,xmm1
              shufps xmm1,xmm1,_MM_SHUFFLE(0, 0, 0, 0)   //  xmm1 = x²
              shufps xmm2,xmm2,_MM_SHUFFLE(1, 1, 1, 1)   //  xmm2 = y²
              shufps xmm3,xmm3,_MM_SHUFFLE(2, 2, 2, 2)   //  xmm3 = z²
              addps  xmm1,xmm2            
              addps  xmm1,xmm3            // xmm1 = x²+y²+z²
              sqrtps xmm1,xmm1             // xmm1= sqrt(v*v)
              divps  xmm0,xmm1              // xmm0 = v/sqrt(v*v)
              movaps [eax],xmm0
       }

}
.
.
.
inline vec reflect(vec v,vec n) {

    return 2*dot2(v,n)*n-v;
}

inline vec  operator *(matrix& mat,vec v) {
    vec res;
    res.m128_f32[0] = dot2(mat.x,v);
    res.m128_f32[1] = dot2(mat.y,v);
    res.m128_f32[2] = dot2(mat.z,v);
    res.m128_f32[3] = 0;
    return res;
}


int main(int argc, char* argv[])  {

matrix mat = mat3(1 , 8,3,
                             3,-1,1,
                             4, 2,1);

vec a,b,c,V;

a = vec3(51,13,10);
b = vec3(1,1,0);

c =dot(a,b)*cross(a,b)+3*b+a;
show(c);
normalize2(c);
show(c);

vec r = reflect(b,a);
show(r);

printf("%f %f %f\n", dot(a,b),dot2(a,b));   //  compare SSE2 with SSE4.1

V = mat*a;
show(V);
return 0;
}

vendredi 21 avril 2017

PinBall with RFO BASIC! on smartphone!

REM Start of BASIC! Program


Wakelock 3

dim xc[10]
dim yc[10]
dim Rc[10],r[10],g[10],b[10],a[10]
dim xa[10],ya[10],xb[10],yb[10]

choc =1
dim s[3]
gravity =0.3

radius =50


GR.OPEN 255, 0, 0,0
GR.ORIENTATION 1
GR.SCREEN sx, sy

ARRAY.LOAD Pattern[],100,10

sensors.open 1

GR.BITMAP.LOAD ptr_ball, "billet.png"
gR.BITMAP.LOAD ptr_wood, "wood.jpg"
AUDIO.LOAD whee, "flip-on3.ogg.mp3"
AUDIO.LOAD boing, "boing.mp3"
AUDIO.LOAD wall0,"wall0.ogg.mp3"
AUDIO.LOAD goal,"goal.mp3"
AUDIO.LOAD music,"1.ogg.mp3"
dim ball[1],WOOD[1]


begin:

score = 0
alpha =255

x=rnd()*sx
y=450
vx=15
vy=20

KX=KY=0

k =1

dt=0
vmin =15
n=3
xc[1]=sx/2:yc[1]= 300:Rc[1]=60
r[1]=255:g[1]=0:b[1]=0:a[1]=255

xc[2]=sx/2-200:yc[2]= 600:Rc[2]=40
r[2]=0:g[2]=255:b[2]=0:a[2]=255

xc[3]=sx/2+200:yc[3]= 600:Rc[3]=40
r[3]=0:g[3]=0:b[3]=255:a[3]=255

xc[4]=sx/2:yc[4]= 900:Rc[4]=60
r[4]=255:g[4]=0:b[4]=255:a[4]=255

xb= sx/2:yb=sy-70
lx=100:ly=25

do

!start =time()


!sensors.read 1, s[1],s[2],s[3]
!gr.rotate.start s[1],sx/2,0

!gr.rotate.end


x+= vx
y+= vy

if x<radius then
AUDIO.STOP
AUDIO.PLAY wall0
vx=-k*vx
!if abs(vx)> vmin then vibrate Pattern[],-1
x=radius
endif
if x>sx-radius then
AUDIO.STOP
AUDIO.PLAY wall0
!if abs(vx)>vmin then vibrate Pattern[],-1
vx=-k*vx
x= sx-radius
endif

if y<radius then
AUDIO.STOP
AUDIO.PLAY wall0
!if abs(vy)>vmin then vibrate Pattern[],-1
vy=-k*vy
y=radius
endif
!if y>sy-radius then

!if abs(vy)>vmin then vibrate Pattern[],-1
!vy=-k*vy
!y= sy-radius
!endif


gr.touch touched, xt, yt
if touched & abs(xt-xb)<=lx & abs(yt-yb)<=ly+50 then
xb= xt:yb=yt
endif

gosub collision


!xb+=-8*s[1]

if xb+lx>sx then xb=sx-lx
if xb-lx<0 then xb=lx

if (x>=xb-lx-20) & (x<=xb+lx+20) & (abs(y+radius-yb+ly)<=40) & (vy>=0) then
vy=-vy+0.1*(yt-ytp)
vx+=0.1*(xt-xtp)
y= yb-ly-radius
!vibrate Pattern[],-1
endif

if y>=sy then
gr.cls
GR.TEXT.SIZE 100
GR.TEXT.DRAW nc,100,600,"YOU LOSE"
gr.render
AUDIO.STOP
AUDIO.PLAY goal
pause 2000

goto begin
endif


if touched=0 then
KX=KY=0
endif

xtp=xt:ytp=yt

!dt=(time()-start)/1000


xtp=xt:ytp=yt


gosub render
!gr.render

until 0

exit:
END


collision:
for i=1 to n
tx = x-xc[i]
ty = y-yc[i]
t = (tx*tx+ty*ty)^0.5
tx=tx/t
ty=ty/t
nx=-ty
ny=tx
vt = vx*tx+vy*ty
vn = vx*nx+vy*ny
if (t<=radius+Rc[i]) & (vt<0) & (a[i]>30) then

gr.color 255,255,255,255
gr.circle nc,xc[i],yc[i],Rc[i]

gr.render
AUDIO.STOP
AUDIO.PLAY whee
vx = 1.0*(-vt*tx+vn*nx)
vy= 1.0*(-vt*ty+vn*ny)
score+=10
if (a[i]>30) then a[i]=a[i]-20.
w =(a[1]<=30) & (a[2]<=30) & (a[3]<=30) & (a[4]<=30)
if w then
AUDIO.STOP
AUDIO.PLAY music
gr.cls
gr.color 255,255,255,255
GR.TEXT.SIZE 100
GR.TEXT.DRAW nc,100,600,"YOU WIN"
gr.render
pause 1000*60
goto begin
endif
!vibrate Pattern[],-1
endif
next i
return

render:
gr.color 255,0,0,0
gr.cls

gr.bitmap.draw WOOD[1],PTR_wood,0,0
gr.bitmap.draw ball[1],ptr_ball,x-radius,y-radius
gr.color 255,255,255,0,1
gr.rect nc, xb-lx, yb-ly, xb+lx, yb+ly

for i=1 to n
gr.color a[i],r[i],g[i],b[i]
gr.circle nc,xc[i],yc[i],Rc[i]
next i

gr.color 255,255,255,1
GR.TEXT.SIZE 50
GR.TEXT.DRAW nc,10,50,"SCORE="
GR.TEXT.DRAW nc,200,50,str$(score)
gr.render

return


line:
for k=1 to nl
tx = xa[k]-xb[k]
ty= ya[k]-yb[k]
t = sqrt(tx*tx+ty*ty)
tx=tx/t:ty=ty/t
nx = -ty: ny= tx
return