But the in-browser edition of BBCSDL is not so lucky. The 3D rendering capabilities of browsers come from WebGL, which is compatible with OpenGLES 2.0 and doesn't support the Fixed Function Pipeline at all: everything has to be done using shaders! At first sight this suggests that BBC BASIC programs which generate 3D graphics (via the relevant library) won't run. But I don't give up that easily, and I have written an (admittedly quick and dirty) emulation of the basic FFP capabilities using shaders!
My code is encapsulated in the new webgllib.bbc library, which presents an identical interface to the older BB4W and BBCSDL libraries. It's very limited: it doesn't support lighting or materials - that would be much harder - just plain diffuse coloured surfaces and textures. But it works, and for those programs which don't use (or at least don't rely on) lighting it works surprisingly well. If you have a suitable desktop browser (Chrome, Edge, Firefox or Opera) you can try running Rubik.bbc, pyramid.bbc, world.bbc and soldiers.bbc (the last of these needs Firefox for the music to work properly).
As you can imagine writing shader code, even for this limited subset of 3D functionality, was not easy for somebody almost entirely unfamiliar with it. But it was made easier by being able to call upon BBC BASIC's matrix arithmetic capabilities to perform the calculations which convert world-space into screen-space. Here's a snippet of the code:
Code: Select all
REM Projection matrix (perspective):
fh=TAN(fv/2) * zn
fw=fh * ar
v(0,0) = zn/fw
v(1,1) = zn/fh
v(2,2) = -1
v(3,2) = 2*zf*zn/(zn-zf)
v(2,3) = -1
REM Rotation matrix (camera roll):
s = SIN(-cr) : c = COS(cr)
w(0,0) = c
w(1,0) = -s
w(0,1) = s
w(1,1) = c
w(2,2) = 1
w(3,3) = 1
w() = w() . v()
REM View matrix:
f()=a() - e()
f() /= MOD(f())
s()=f(2),0,-f(0)
s() /= MOD(s())
u()=s(2)*f(1),s(0)*f(2)-s(2)*f(0),-s(0)*f(1)
v()=s(0),u(0),-f(0),0,s(1),u(1),-f(1),0,s(2),u(2),-f(2),0,0,0,0,1
v() = v() . w()
REM Translation matrix:
w() = 1,0,0,0,0,1,0,0,0,0,1,0,-e(0),-e(1),-e(2),1
w() = w() . v()
REM Object matrix:
sy=SINp(I%)
cy=COSp(I%)
sp=SINt(I%)
cp=COSt(I%)
sr=SINr(I%)
cr=COSr(I%)
v() = cr*cy+sr*sp*sy,sr*cp,sr*sp*cy-cr*sy,0,\
\ cr*sp*sy-sr*cy,cr*cp,sr*sy+cr*sp*cy,0,\
\ cp*sy,-sp,cp*cy,0,x(I%),y(I%),z(I%),1
v() = v() . w()