レイマーチング

 投稿者:しばっち  投稿日:2018年 4月 9日(月)20時11分57秒
  ネット上のサンプルを基にしてレイマーチング法(ray marching)で箱(box)をレンダリングしています。
レイ・マーチング法はレイ・トレーシング法(ray tracing)の一種です。

※厳密にはレイマーチング法の中のスフィアトレーシング法(sphere tracing)です。
二進モードで実行してください。

DIM P(2),V(2),CPOS(3),CDIR(3),CUP(3),CSIDE(3),RAY(3),R1(3),R2(3),R3(3),LIGHTDIR(3),RPOS(3)
DIM NORMAL(3)
ASK BITMAP SIZE XSIZE,YSIZE
SET COLOR MODE "NATIVE"
SET POINT STYLE 1
SET WINDOW -XSIZE/MIN(XSIZE,YSIZE),XSIZE/MIN(XSIZE,YSIZE),-YSIZE/MIN(XSIZE,YSIZE),YSIZE/MIN(XSIZE,YSIZE)
CALL VEC3(CPOS,0,0,2)
CALL VEC3(LIGHTDIR,-.577,.577,.577)
LET ANG=60            !'視野角
LET FOV=ANG*.5*PI/180
FOR YY=0 TO YSIZE-1
   FOR XX=0 TO XSIZE-1
      LET X=(XX*2-XSIZE)/MIN(XSIZE,YSIZE)
      LET Y=(YY*2-YSIZE)/MIN(XSIZE,YSIZE)
      CALL VEC3(RAY,SIN(FOV)*X,SIN(FOV)*Y,-COS(FOV))
      CALL NORMALIZE(RAY)
      LET DISTANCE=0
      LET RLEN=0
      MAT RPOS=CPOS
      FOR I=0 TO 127
         LET DISTANCE=DISTANCEFUNC(RPOS)
         LET RLEN=RLEN+DISTANCE
         MAT RPOS=RLEN*RAY
         MAT RPOS=RPOS+CPOS
         IF ABS(DISTANCE)<.001 THEN EXIT FOR
      NEXT I
      IF ABS(DISTANCE)<.001 THEN
         CALL GETNORMAL(RPOS,NORMAL)
         LET DIFF=CLAMP(DOT(LIGHTDIR,NORMAL),.1,1)
         CALL SETCOLOR(DIFF,DIFF,DIFF)
      ELSE
         CALL SETCOLOR(0,0,0)
      END IF
      PLOT POINTS:X,Y
   NEXT XX
NEXT YY
END

EXTERNAL  SUB TRANS(P())
FOR I=1 TO 3
   LET P(I)=MOD(P(I),4)-2
NEXT I
END SUB

EXTERNAL  FUNCTION DISTANCEFUNC(PP())
DIM V(3),A(3),B(3),P(3)
CALL VEC3(B,.5,.5,.5)
MAT P=PP
CALL TRANS(P)
CALL VABS(V,P)
MAT V=V-B
CALL NMAX(A,V,0)
LET DISTANCEFUNC=LENGTH(A)-.5
END FUNCTION

EXTERNAL  SUB GETNORMAL(P(),N())
DIM X1(3),X2(3),Y1(3),Y2(3),Z1(3),Z2(3),PX1(3),PX2(3),PY1(3),PY2(3),PZ1(3),PZ2(3)
LET D=.0001
CALL VEC3(X1,D,0,0)
CALL VEC3(X2,-D,0,0)
MAT PX1=P+X1
MAT PX2=P+X2
CALL VEC3(Y1,0,D,0)
CALL VEC3(Y2,0,-D,0)
MAT PY1=P+Y1
MAT PY2=P+Y2
CALL VEC3(Z1,0,0,D)
CALL VEC3(Z2,0,0,-D)
MAT PZ1=P+Z1
MAT PZ2=P+Z2
CALL VEC3(N,DISTANCEFUNC(PX1)-DISTANCEFUNC(PX2),DISTANCEFUNC(PY1)-DISTANCEFUNC(PY2),DISTANCEFUNC(PZ1)-DISTANCEFUNC(PZ2))
CALL NORMALIZE(N)
END SUB

EXTERNAL  SUB NORMALIZE(RAY())
LET S=LENGTH(RAY)
IF S<>0 THEN
   MAT RAY=(1/S)*RAY
ELSE
   MAT RAY=ZER
END IF
END SUB

EXTERNAL  SUB SETCOLOR(R,G,B)
SET COLOR COLORINDEX(CLAMP(R,0,1),CLAMP(G,0,1),CLAMP(B,0,1))
END SUB

EXTERNAL  SUB VEC3(V(),X,Y,Z)
LET V(1)=X
LET V(2)=Y
LET V(3)=Z
END SUB

EXTERNAL  FUNCTION LENGTH(A())
LET LENGTH=SQR(A(1)^2+A(2)^2+A(3)^2)
END FUNCTION

EXTERNAL  FUNCTION CLAMP(X,A,B)
LET CLAMP=MIN(B,MAX(X,A))
END FUNCTION

EXTERNAL  SUB VABS(A(),B())
FOR I=1 TO 3
   LET A(I)=ABS(B(I))
NEXT I
END SUB

EXTERNAL  SUB NMAX(A(),B(),N)
FOR I=1 TO 3
   LET A(I)=MAX(B(I),N)
NEXT I
END SUB
 

レイマーチング

 投稿者:しばっち  投稿日:2018年 4月 9日(月)20時12分42秒
  ネット上のサンプルを基にレイマーチング法によりトーラス(ドーナツ型)をレンダリングしています。
二進モードで実行してください。

DIM CPOS(3),CDIR(3),CUP(3),CSIDE(3),RAY(3),R1(3),R2(3),R3(3),LIGHTDIR(3),RPOS(3),HALF(3)
DIM NORMAL(3),DPOS(3),COL(3)
ASK BITMAP SIZE XSIZE,YSIZE
SET COLOR MODE "NATIVE"
SET POINT STYLE 1
SET WINDOW -XSIZE/MIN(XSIZE,YSIZE),XSIZE/MIN(XSIZE,YSIZE),-YSIZE/MIN(XSIZE,YSIZE),YSIZE/MIN(XSIZE,YSIZE)
CALL VEC3(CPOS,0,5,5)         !'カメラ
CALL VEC3(CDIR,0,-.707,-.707) !'カメラの向き(視線)
CALL VEC3(CUP,0,.707,-.707)   !'カメラの上方向
CALL VEC3(LIGHTDIR,-.577,.577,.577)
MAT CSIDE=CROSS(CDIR,CUP)     !'横方向
LET TARGETDEPTH=1             !'フォーカス深度
CALL NORMALIZE(LIGHTDIR)
FOR YY=0 TO YSIZE-1
   FOR XX=0 TO XSIZE-1
      LET X=(XX*2-XSIZE)/MIN(XSIZE,YSIZE)
      LET Y=(YY*2-YSIZE)/MIN(XSIZE,YSIZE)
      MAT R1=X*CSIDE
      MAT R2=Y*CUP
      MAT R3=TARGETDEPTH*CDIR
      MAT RAY=R1
      MAT RAY=RAY+R2
      MAT RAY=RAY+R3
      CALL NORMALIZE(RAY) !'レイの定義
      LET DIST=0
      LET RLEN=0
      MAT RPOS=CPOS
      LET SHADOW=1
      FOR I=0 TO 255 !'マーチングループ(marching loop)
         CALL DISTANCE(RPOS,DIST,COL)
         LET RLEN=RLEN+DIST
         MAT RPOS=RLEN*RAY
         MAT RPOS=RPOS+CPOS
         IF DIST<.001 THEN EXIT FOR
      NEXT I
      IF ABS(DIST)<.001 THEN !'レイとの距離
         CALL GETNORMAL(RPOS,NORMAL)
         MAT HALF=LIGHTDIR-RAY
         CALL NORMALIZE(HALF)
         LET DIFF=CLAMP(DOT(LIGHTDIR,NORMAL),.1,1)
         LET SPEC=CLAMP(DOT(HALF,NORMAL),0,1)^50
         MAT DPOS=(1/1000)*NORMAL
         MAT DPOS=DPOS+RPOS
         LET SHADOW=GENSHADOW(DPOS,LIGHTDIR) !'シャドウ
         FOR I=1 TO 3
            LET COL(I)=COL(I)*DIFF+SPEC
         NEXT I
      ELSE
         CALL VEC3(COL,0,0,0)
      END IF
      FOR I=1 TO 3
         LET COL(I)=COL(I)*MAX(.5,SHADOW)
      NEXT I
      CALL SETCOLOR(COL(1),COL(2),COL(3))
      PLOT POINTS:X,Y
   NEXT XX
NEXT YY
END

EXTERNAL  FUNCTION TORUS(P()) !'距離関数(トーラス)
DIM T(3),R(3)
CALL VEC2(T,3,1)
CALL VEC2(R,LENGTH2(P(1),P(3),0)-T(1),P(2))
LET TORUS=LENGTH(R)-T(2)
END FUNCTION

EXTERNAL  FUNCTION FLOOR(P()) !'距離関数(床)
DIM V(3)
CALL VEC3(V,0,1,0)
LET FLOOR=DOT(P,V)+1
END FUNCTION

EXTERNAL  SUB DISTANCE(P(),DIST,COL())
LET D1=TORUS(P)
LET D2=FLOOR(P)
IF D1<D2 THEN
   LET DIST=D1
   CALL VEC3(COL,1,1,.25) !'色
ELSE
   LET DIST=D2
   LET U=1-IP(MOD(P(1),2))
   LET V=1-IP(MOD(P(3),2))
   IF U+V=1 THEN CALL VEC3(COL,.7,.7,.7) ELSE CALL VEC3(COL,1,1,1) !'色(市松模様)
END IF
END SUB

EXTERNAL  SUB NMAX(A(),B(),N)
FOR I=1 TO 3
   LET A(I)=MAX(B(I),N)
NEXT I
END SUB

EXTERNAL  SUB GETNORMAL(P(),N()) !'法線ベクトル
DIM X1(3),X2(3),Y1(3),Y2(3),Z1(3),Z2(3),PX1(3),PX2(3),PY1(3),PY2(3),PZ1(3),PZ2(3),DMY(3)
LET D=.0001
CALL VEC3(X1,D,0,0)
CALL VEC3(X2,-D,0,0)
MAT PX1=P+X1
MAT PX2=P+X2
CALL VEC3(Y1,0,D,0)
CALL VEC3(Y2,0,-D,0)
MAT PY1=P+Y1
MAT PY2=P+Y2
CALL VEC3(Z1,0,0,D)
CALL VEC3(Z2,0,0,-D)
MAT PZ1=P+Z1
MAT PZ2=P+Z2
CALL DISTANCE(PX1,XS,DMY)
CALL DISTANCE(PX2,XE,DMY)
CALL DISTANCE(PY1,YS,DMY)
CALL DISTANCE(PY2,YE,DMY)
CALL DISTANCE(PZ1,ZS,DMY)
CALL DISTANCE(PZ2,ZE,DMY)
CALL VEC3(N,XS-XE,YS-YE,ZS-ZE)
CALL NORMALIZE(N)
END SUB

EXTERNAL  SUB NORMALIZE(RAY()) !'正規化
LET S=LENGTH(RAY)
IF S<>0 THEN
   MAT RAY=(1/S)*RAY
ELSE
   MAT RAY=ZER
END IF
END SUB

EXTERNAL  SUB VABS(A(),B())
FOR I=1 TO 3
   LET A(I)=ABS(B(I))
NEXT I
END SUB

EXTERNAL  SUB SETCOLOR(R,G,B)
SET COLOR COLORINDEX(CLAMP(R,0,1),CLAMP(G,0,1),CLAMP(B,0,1))
END SUB

EXTERNAL  SUB VEC3(V(),X,Y,Z)
LET V(1)=X
LET V(2)=Y
LET V(3)=Z
END SUB

EXTERNAL  SUB VEC2(A(),X,Y)
LET A(1)=X
LET A(2)=Y
END SUB

EXTERNAL  FUNCTION LENGTH(A()) !'長さ
LET LENGTH=SQR(A(1)^2+A(2)^2+A(3)^2)
END FUNCTION

EXTERNAL  FUNCTION LENGTH2(X,Y,Z)
LET LENGTH2=SQR(X^2+Y^2+Z^2)
END FUNCTION

EXTERNAL  FUNCTION CLAMP(X,A,B)
LET CLAMP=MIN(B,MAX(X,A))
END FUNCTION

EXTERNAL  FUNCTION GENSHADOW(RO(),RD()) !'シャドウ
DIM RAY(3),DMY(3)
LET R=1
LET C=.001
LET SHADOWCOEF=.5
FOR T=0 TO 49
   MAT RAY=C*RD
   MAT RAY=RAY+RO
   CALL DISTANCE(RAY,H,DMY)
   IF H<.001 THEN
      LET GENSHADOW=SHADOWCOEF
      EXIT FUNCTION
   END IF
   LET R=MIN(R,H*32/C)
   LET C=C+H
NEXT T
LET GENSHADOW=1-SHADOWCOEF+R*SHADOWCOEF
END FUNCTION
 

レイマーチング

 投稿者:しばっち  投稿日:2018年 4月 9日(月)20時13分32秒
  ネット上のサンプルを基にレイマーチング法で鉄骨?をレンダリングしています。
二進モードで実行してください。

DIM P(2),V(2),CPOS(3),CDIR(3),CUP(3),CSIDE(3),RAY(3),R1(3),R2(3),R3(3),LIGHTDIR(3),DPOS(3)
DIM NORMAL(3),COL(3)
ASK BITMAP SIZE XSIZE,YSIZE
SET COLOR MODE "NATIVE"
SET POINT STYLE 1
SET WINDOW -XSIZE/MIN(XSIZE,YSIZE),XSIZE/MIN(XSIZE,YSIZE),-YSIZE/MIN(XSIZE,YSIZE),YSIZE/MIN(XSIZE,YSIZE)
CALL VEC3(CPOS,5,5,.5)
CALL VEC3(CUP,.1,.4,0)
CALL NORMALIZE(CUP)
CALL VEC3(CDIR,-1,0,0)
MAT CDIR=CROSS(CUP,CDIR)
CALL VEC3(LIGHTDIR,1,1,-2)
CALL NORMALIZE(LIGHTDIR)
MAT CSIDE=CROSS(CDIR,CUP)
LET TARGETDEPTH=1
LET EPS=.001
FOR YY=0 TO YSIZE-1
   FOR XX=0 TO XSIZE-1
      LET X=(XX*2-XSIZE)/MIN(XSIZE,YSIZE)
      LET Y=(YY*2-YSIZE)/MIN(XSIZE,YSIZE)
      MAT R1=X*CSIDE
      MAT R2=Y*CUP
      MAT R3=TARGETDEPTH*CDIR
      MAT RAY=R1
      MAT RAY=RAY+R2
      MAT RAY=RAY+R3
      CALL NORMALIZE(RAY)
      LET DEPTH=0
      MAT DPOS=CPOS
      FOR I=0 TO 63
         LET DIST=DISTANCEFUNC(DPOS)
         LET DEPTH=DEPTH+DIST
         MAT DPOS=DEPTH*RAY
         MAT DPOS=DPOS+CPOS
         IF ABS(DIST)<EPS THEN EXIT FOR
      NEXT I
      IF ABS(DIST)<EPS THEN
         CALL GETNORMAL(DPOS,NORMAL)
         LET DIFFUSE=CLAMP(DOT(LIGHTDIR,NORMAL),.1,1)
         CALL VEC3(COL,1,.1,.1)
         MAT COL=DIFFUSE*COL
         CALL SETCOLOR(COL(1)+.05*DEPTH,COL(2)+.05*DEPTH,COL(3)+.05*DEPTH)
      ELSE
         CALL SETCOLOR(.05*DEPTH,.05*DEPTH,.05*DEPTH)
      END IF
      PLOT POINTS:X,Y
   NEXT XX
NEXT YY
END

EXTERNAL  SUB  ONREP(P(), INTERVAL,PP())
FOR I=1 TO UBOUND(P,1)
   LET PP(I)=MOD(P(I),INTERVAL)- INTERVAL * 0.5
NEXT I
END SUB

EXTERNAL  FUNCTION BARDIST(X,Y,INTERVAL,WIDTH)
DIM PP(2),P(2)
CALL VEC2(P,X,Y)
CALL ONREP(P, INTERVAL,PP)
CALL VABS(PP)
FOR I=1 TO 2
   LET PP(I)=PP(I)-WIDTH
NEXT I
CALL VMAX(PP,0)
LET BARDIST=LENGTH(PP)
END FUNCTION

EXTERNAL  FUNCTION TUBEDIST(X,Y, INTERVAL, WIDTH)
DIM PP(2),P(2)
CALL VEC2(P,X,Y)
CALL ONREP(P, INTERVAL,PP)
LET TUBEDIST=LENGTH(PP) - WIDTH
END FUNCTION

EXTERNAL  FUNCTION DISTANCEFUNC(P())
LET BARX=BARDIST(P(2),P(3),1,.1)
LET BARY=BARDIST(P(1),P(3),1,.1)
LET BARZ=BARDIST(P(1),P(2),1,.1)
LET TUBEX=TUBEDIST(P(2),P(3),.1,.025)
LET TUBEY=TUBEDIST(P(1),P(3),.1,.025)
LET TUBEZ=TUBEDIST(P(1),P(2),.1,.025)
LET DISTANCEFUNC=MAX(MAX(MAX(MIN(MIN(BARX, BARY),BARZ), -TUBEX), -TUBEY), -TUBEZ)
END FUNCTION

EXTERNAL  SUB GETNORMAL(P(),N())
DIM X1(3),X2(3),Y1(3),Y2(3),Z1(3),Z2(3),PX1(3),PX2(3),PY1(3),PY2(3),PZ1(3),PZ2(3)
LET D=.001
CALL VEC3(X1,D,0,0)
CALL VEC3(X2,-D,0,0)
MAT PX1=P+X1
MAT PX2=P+X2
CALL VEC3(Y1,0,D,0)
CALL VEC3(Y2,0,-D,0)
MAT PY1=P+Y1
MAT PY2=P+Y2
CALL VEC3(Z1,0,0,D)
CALL VEC3(Z2,0,0,-D)
MAT PZ1=P+Z1
MAT PZ2=P+Z2
CALL VEC3(N,DISTANCEFUNC(PX1)-DISTANCEFUNC(PX2),DISTANCEFUNC(PY1)-DISTANCEFUNC(PY2),DISTANCEFUNC(PZ1)-DISTANCEFUNC(PZ2))
CALL NORMALIZE(N)
END SUB

EXTERNAL  SUB NORMALIZE(RAY())
LET S=LENGTH(RAY)
IF S<>0 THEN
   MAT RAY=(1/S)*RAY
ELSE
   MAT RAY=ZER
END IF
END SUB

EXTERNAL  SUB SETCOLOR(R,G,B)
SET COLOR COLORINDEX(CLAMP(R,0,1),CLAMP(G,0,1),CLAMP(B,0,1))
END SUB

EXTERNAL  SUB VEC2(V(),X,Y)
LET V(1)=X
LET V(2)=Y
END SUB

EXTERNAL  SUB VEC3(V(),X,Y,Z)
LET V(1)=X
LET V(2)=Y
LET V(3)=Z
END SUB

EXTERNAL  FUNCTION LENGTH(A())
FOR I=1 TO UBOUND(A,1)
   LET S=S+A(I)^2
NEXT I
LET LENGTH=SQR(S)
END FUNCTION

EXTERNAL  FUNCTION CLAMP(X,A,B)
LET CLAMP=MIN(B,MAX(X,A))
END FUNCTION

EXTERNAL  SUB VABS(A())
FOR I=1 TO UBOUND(A,1)
   LET A(I)=ABS(A(I))
NEXT I
END SUB

EXTERNAL  SUB VMAX(A(),N)
FOR I=1 TO UBOUND(A,1)
   LET A(I)=MAX(A(I),N)
NEXT I
END SUB


このプログラムの原版はこちら(※マウスでいじれます)

GLSL言語でのGPUによるレンダリングです(WebGL)

※凄すぎるので上記BASICプログラム実行前のアクセス禁止です(笑)
 

レイマーチング

 投稿者:しばっち  投稿日:2018年 4月 9日(月)20時14分28秒
  ネット上のサンプルを基にレイマーチング法で球?をレンダリングしています。
二進モードで実行してください。

PUBLIC NUMERIC EPS,OFFSET
DIM POS(3),CPOS(3),CDIR(3),CUP(3),CSIDE(3),RAY(3),R1(3),R2(3),R3(3),LIGHTDIR(3)
DIM NORMAL(3),COL(3),C(3),V(3),R(3),CC(3),CAMERA(3)
ASK BITMAP SIZE XSIZE,YSIZE
SET COLOR MODE "NATIVE"
SET POINT STYLE 1
SET WINDOW -XSIZE/MIN(XSIZE,YSIZE),XSIZE/MIN(XSIZE,YSIZE),-YSIZE/MIN(XSIZE,YSIZE),YSIZE/MIN(XSIZE,YSIZE)
CALL VEC3(CDIR,0,0,1)
CALL VEC3(CUP,0,1,0)
CALL VEC3(CAMERA,0,1,0)
MAT CSIDE=CROSS(CDIR,CUP)
LET EPS=.01
LET TARGETDEPTH=1.3
LET OFFSET = EPS * 100
FOR YY=0 TO YSIZE-1
   FOR XX=0 TO XSIZE-1
      LET X=(XX*2-XSIZE)/MIN(XSIZE,YSIZE)
      LET Y=(YY*2-YSIZE)/MIN(XSIZE,YSIZE)
      MAT R1=X*CSIDE
      MAT R2=Y*CUP
      MAT R3=TARGETDEPTH*CDIR
      MAT RAY=R1
      MAT RAY=RAY+R2
      MAT RAY=RAY+R3
      MAT CPOS=CAMERA
      CALL NORMALIZE(RAY)
      LET ALPHA=1
      MAT COL=ZER
      FOR I=0 TO 2
         CALL GETRAYCOLOR(CPOS, RAY, POS, NORMAL, HIT,CC)
         MAT C=ALPHA*CC
         MAT COL=COL+C
         LET ALPHA=ALPHA*.3
         CALL REFLECT(RAY, NORMAL ,R)
         CALL NORMALIZE(R)
         MAT RAY=R
         MAT CPOS=OFFSET*NORMAL
         MAT CPOS=CPOS+POS
         IF HIT=0 THEN EXIT FOR
      NEXT I
      CALL SETCOLOR(COL(1),COL(2),COL(3))
      PLOT POINTS:X,Y
   NEXT XX
NEXT YY
END

EXTERNAL  SUB  ONREP(P(), INTERVAL,PP())
DIM Q(2)
LET Q(1)=MOD(P(1),INTERVAL)- INTERVAL * 0.5
LET Q(2)=MOD(P(3),INTERVAL)- INTERVAL * 0.5
CALL VEC3(PP,Q(1),P(2),Q(2))
END SUB

EXTERNAL  FUNCTION SPHEREDIST(P(),R)
DIM PP(3)
CALL ONREP(P,3,PP)
LET SPHEREDIST=LENGTH(PP)-R
END FUNCTION

EXTERNAL  FUNCTION FLOORDIST(P())
DIM V(3)
CALL VEC3(V,0,1,0)
LET FLOORDIST=DOT(P,V)+1
END FUNCTION

EXTERNAL  SUB MINVEC4(A(),B(),C())
IF A(4)<B(4) THEN MAT C=A ELSE MAT C=B
END SUB

EXTERNAL  FUNCTION CHECKEREDPATTERN(P())
LET U=1-IP(MOD(P(1),2))
LET V=1-IP(MOD(P(3),2))
IF U=1 AND V<1 OR U<1 AND V=1 THEN LET CHECKEREDPATTERN=.2 ELSE LET CHECKEREDPATTERN=1
END FUNCTION

EXTERNAL  SUB HSV2RGB(C(),RGB())
DIM K(4),P(3)
CALL VEC4(K,1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0)
FOR I=1 TO 3
   LET P(I)=ABS(FRACT(C(1)+K(I))*6-K(4))
NEXT I
FOR I=1 TO 3
   LET RGB(I)=C(3)*MIX(K(1),CLAMP(P(I)-K(1),0,1),C(2))
NEXT I
END SUB

EXTERNAL  FUNCTION SCENEDIST(P())
LET SCENEDIST=MIN(SPHEREDIST(P,1),FLOORDIST(P))
END FUNCTION

EXTERNAL  SUB SCENECOLOR(P(),PP())
DIM A(4),B(4),C(3),COL(3)
CALL VEC3(C,(P(3) + P(1)) / 9.0, 1.0, 1.0 )
CALL HSV2RGB(C,COL)
CALL VEC4(A,COL(1),COL(2),COL(3), SPHEREDIST(P,1.0))
LET L=CHECKEREDPATTERN(P)
CALL VEC4(B,.5*L,.5*L,.5*L,FLOORDIST(P))
CALL MINVEC4(A,B,PP)
END SUB

EXTERNAL  SUB GETNORMAL(P(),N())
DIM X1(3),X2(3),Y1(3),Y2(3),Z1(3),Z2(3),PX1(3),PX2(3),PY1(3),PY2(3),PZ1(3),PZ2(3)
CALL VEC3(X1,EPS,0,0)
CALL VEC3(X2,-EPS,0,0)
MAT PX1=P+X1
MAT PX2=P+X2
CALL VEC3(Y1,0,EPS,0)
CALL VEC3(Y2,0,-EPS,0)
MAT PY1=P+Y1
MAT PY2=P+Y2
CALL VEC3(Z1,0,0,EPS)
CALL VEC3(Z2,0,0,-EPS)
MAT PZ1=P+Z1
MAT PZ2=P+Z2
CALL VEC3(N,SCENEDIST(PX1)-SCENEDIST(PX2),SCENEDIST(PY1)-SCENEDIST(PY2),SCENEDIST(PZ1)-SCENEDIST(PZ2))
CALL NORMALIZE(N)
END SUB

EXTERNAL  FUNCTION GETSHADOW(RO(),RD())
DIM RAY(3),DMY(3)
LET R=1
LET SHADOWCOEF=.5
FOR T=0 TO 49
   MAT RAY=C*RD
   MAT RAY=RAY+RO
   LET H=SCENEDIST(RAY)
   IF H<EPS THEN
      LET GETSHADOW=SHADOWCOEF
      EXIT FUNCTION
   END IF
   IF C<>0 THEN LET R=MIN(R,H*16/C)
   LET C=C+H
NEXT T
LET GETSHADOW=1-SHADOWCOEF+R*SHADOWCOEF
END FUNCTION

EXTERNAL  SUB GETRAYCOLOR(ORIGIN(),RAY(),POS(),NORMAL(),HIT,COL())
DIM P(3),S(3),V(3),LIGHTDIR(3),CL(4)
MAT POS=ORIGIN
CALL VEC3(LIGHTDIR,-0.48666426339228763, 0.8111071056538127, -0.3244428422615251)
FOR I=0 TO 63
   LET DIST = SCENEDIST(POS)
   LET DEPTH =DEPTH+ DIST
   MAT POS=DEPTH*RAY
   MAT POS=POS+ORIGIN
   IF ABS(DIST)<EPS  THEN EXIT FOR
NEXT I
IF ABS(DIST)<EPS THEN
   CALL GETNORMAL(POS,NORMAL)
   LET DIFFUSE = CLAMP(DOT(LIGHTDIR, NORMAL), 0.1, 1.0 )
   CALL REFLECT(LIGHTDIR, NORMAL,V)
   LET SPECULAR = CLAMP(DOT(V,RAY),0, 1)^10
   CALL VEC3(S,SPECULAR*.8,SPECULAR*.8,SPECULAR*.8)
   MAT P=OFFSET*NORMAL
   MAT P=P+POS
   LET SHADOW = GETSHADOW(P, LIGHTDIR)
   CALL SCENECOLOR(POS ,CL)
   FOR I=1 TO 3
      LET COL(I)=CL(I)
   NEXT I
   MAT COL=DIFFUSE*COL
   MAT COL=COL+S
   MAT COL=(MAX(0.5,SHADOW))*COL
   LET HIT = 1
ELSE
   MAT COL=ZER
   LET HIT=0
END IF
LET K= CLAMP(.05 * DEPTH, 0, .6)^2
FOR I=1 TO 3
   LET COL(I)=COL(I)-K
NEXT I
END SUB

EXTERNAL  SUB REFLECT(I(),N(),V())
DIM C(3),VV(3)
LET K=2*DOT(N,I)
MAT C=K*N
MAT VV=I-C
MAT V=VV
END SUB

EXTERNAL  SUB NORMALIZE(RAY())
LET S=LENGTH(RAY)
IF S<>0 THEN
   MAT RAY=(1/S)*RAY
ELSE
   MAT RAY=ZER
END IF
END SUB

EXTERNAL  SUB SETCOLOR(R,G,B)
SET COLOR COLORINDEX(CLAMP(R,0,1),CLAMP(G,0,1),CLAMP(B,0,1))
END SUB

EXTERNAL  SUB VEC2(V(),X,Y)
LET V(1)=X
LET V(2)=Y
END SUB

EXTERNAL  SUB VEC3(V(),X,Y,Z)
LET V(1)=X
LET V(2)=Y
LET V(3)=Z
END SUB

EXTERNAL  SUB VEC4(V(),X,Y,Z,W)
LET V(1)=X
LET V(2)=Y
LET V(3)=Z
LET V(4)=W
END SUB

EXTERNAL  FUNCTION LENGTH(A())
FOR I=1 TO UBOUND(A,1)
   LET S=S+A(I)^2
NEXT I
LET LENGTH=SQR(S)
END FUNCTION

EXTERNAL  FUNCTION CLAMP(X,A,B)
LET CLAMP=MIN(B,MAX(X,A))
END FUNCTION

EXTERNAL  FUNCTION FRACT(X)
LET FRACT=FP(X)
END FUNCTION

EXTERNAL  FUNCTION MIX(X,Y,A)
LET MIX=X*(1-A)+Y*A
END FUNCTION



上記プログラムの原版はこちら(※マウスでいじれます)

GLSL言語でのGPUによるレンダリングです(WebGL)

※凄すぎるので上記BASICプログラム実行前のアクセス禁止です(笑)
 

戻る