BASIC + GfxLib, no assembly language:
http://www.proggies.uk/temp/plasma.zip
Have fun guessing how it was done.
Plasma
-
- Posts: 177
- Joined: Mon 02 Apr 2018, 21:51
Re: Plasma
If someone guesses correctly, will you share source code?
Re: Plasma
More efficient, includes source:
http://www.proggies.uk/temp/plasma.zip
EDIT: Full-screen version (uses DirectX9), press Escape to close the program:
http://www.proggies.uk/temp/plasma_fs.zip
Some unsightly artefacts are present.
http://www.proggies.uk/temp/plasma.zip
EDIT: Full-screen version (uses DirectX9), press Escape to close the program:
http://www.proggies.uk/temp/plasma_fs.zip
Some unsightly artefacts are present.

Re: Plasma
This code, from Richard, works beautifully (i.e. fast & smooth) on my Android-based Motorola Moto G7+ (it's full screen, too). Also tested under BBCSDL (Windows). Thanks to Richard for this instructive piece of code.
Code: Select all
ON ERROR IF ERR=17 CHAIN @lib$+"../examples/tools/touchide" ELSE MODE 3 : PRINT REPORT$ : END
REM Plasma effect from https://www.shadertoy.com/view/MdXGDH
REM BBCSDL version by Richard Russell, www.rtrussell.co.uk, 8-Feb-2019
REM This version has been adapted to work in both OpenGL and OpenGL ES2
REM Install libraries:
INSTALL @lib$ + "ogllib"
REM Create arrays:
DIM Object%(0), nVert%(0), vFormat%(0), vSize%(0), Material%(0), Texture%(0)
DIM Pan(0), Tilt(0), Roll(0), Xpos(0), Ypos(0), Zpos(0), Camera(2), LookAt(2)
DIM Light%(0), Vertex$(10), Fragment$(999), Float{0%,1%}
REM Fill vertex and fragment shader arrays from DATA statements:
PROCreadshader(Vertex$())
PROCreadshader(Fragment$())
REM Create a simple square object:
F% = OPENOUT(@tmp$+"square.fvf")
BPUT#F%,6 MOD 256 : BPUT#F%,6 DIV 256 : BPUT#F%,0 : BPUT#F%,0 : REM vertex count
BPUT#F%,2 : BPUT#F%,0 : BPUT#F%,12 : BPUT#F%,0 : REM vertex format and size
PROC4(F%,+1) : PROC4(F%,+1) : PROC4(F%,0)
PROC4(F%,-1) : PROC4(F%,+1) : PROC4(F%,0)
PROC4(F%,-1) : PROC4(F%,-1) : PROC4(F%,0)
PROC4(F%,-1) : PROC4(F%,-1) : PROC4(F%,0)
PROC4(F%,+1) : PROC4(F%,-1) : PROC4(F%,0)
PROC4(F%,+1) : PROC4(F%,+1) : PROC4(F%,0)
CLOSE #F%
REM Set OpenGL constants:
SDL_GL_CONTEXT_MAJOR_VERSION = &11
GL_FRAGMENT_SHADER = &8B30
GL_VERTEX_SHADER = &8B31
GL_COMPILE_STATUS = &8B81
GL_LINK_STATUS = &8B82
GL_INFO_LOG_LENGTH = &8B84
GL_TEXTURE0 = &84C0
REM Initialise window and get its size:
ON MOVE IF @msg% <> 5 RETURN ELSE PROCcleanup
VDU 26
REM Ensure cleanup on exit:
ON CLOSE PROCcleanup : QUIT
ON ERROR PROCcleanup : IF ERR=17 CHAIN @lib$+"../examples/tools/touchide" ELSE MODE 3 : PRINT REPORT$ : END
REM Initialise OpenGL (GLES 2.0 on Android or iOS):
SYS "SDL_GL_SetAttribute", SDL_GL_CONTEXT_MAJOR_VERSION, 2, @memhdc%
pDevice% = FN_initgl(@hwnd%, 1, 0)
IF pDevice% = 0 ERROR 100, "Couldn't initialise OpenGL"
SYS "SDL_GL_SetSwapInterval", 1, @memhdc%
REM Get addresses of OpenGL/GLES functions:
`glCreateShader` = FNgpa("glCreateShader")
`glAttachShader` = FNgpa("glAttachShader")
`glDeleteShader` = FNgpa("glDeleteShader")
`glShaderSource` = FNgpa("glShaderSource")
`glCompileShader` = FNgpa("glCompileShader")
`glGetShaderiv` = FNgpa("glGetShaderiv")
`glCreateProgram` = FNgpa("glCreateProgram")
`glDeleteProgram` = FNgpa("glDeleteProgram")
`glLinkProgram` = FNgpa("glLinkProgram")
`glGetProgramiv` = FNgpa("glGetProgramiv")
`glGetShaderInfoLog` = FNgpa("glGetShaderInfoLog")
`glGetProgramInfoLog` = FNgpa("glGetProgramInfoLog")
`glUseProgram` = FNgpa("glUseProgram")
`glGetUniformLocation`= FNgpa("glGetUniformLocation")
`glBindAttribLocation`= FNgpa("glBindAttribLocation")
`glVertexAttribPointer`= FNgpa("glVertexAttribPointer")
`glEnableVertexAttribArray`= FNgpa("glEnableVertexAttribArray")
`glUniform1fv` = FNgpa("glUniform1fv")
REM Create shader objects:
SYS `glCreateShader`, GL_VERTEX_SHADER, @memhdc% TO oVertex%
SYS `glCreateShader`, GL_FRAGMENT_SHADER, @memhdc% TO oFragment%
REM Compile shaders:
PROCcompileshader(oVertex%, Vertex$())
PROCcompileshader(oFragment%, Fragment$())
REM Create program object and link:
SYS `glCreateProgram`, @memhdc% TO oProgram%
SYS `glAttachShader`, oProgram%, oVertex%, @memhdc%
SYS `glAttachShader`, oProgram%, oFragment%, @memhdc%
SYS `glBindAttribLocation`, oProgram%, 0, "vPosition", @memhdc%
SYS `glLinkProgram`, oProgram%, @memhdc%
SYS `glGetProgramiv`, oProgram%, GL_LINK_STATUS, ^linked%, @memhdc%
IF linked% = 0 THEN
SYS `glGetProgramiv`, oProgram%, GL_INFO_LOG_LENGTH, ^blen%, @memhdc%
DIM plog%% blen%
SYS `glGetProgramInfoLog`, oProgram%, blen%, ^slen%, plog%%, @memhdc%
ERROR 100, "Program object failed to link:" + CHR$&D + CHR$&A + LEFT$($$plog%%,220)
ENDIF
REM Load dummy 3D object:
Object%(0) = FN_load3d(pDevice%, @tmp$+"square.fvf", nVert%(0), vFormat%(0), vSize%(0))
IF Object%(0) = 0 ERROR 100, "Couldn't load square.fvf"
REM Use shaders:
SYS `glUseProgram`, oProgram%, @memhdc%
SYS `glGetUniformLocation`, oProgram%, "iTime", @memhdc% TO pTime%
REM Set and enable vertex array pointer:
IF @platform% AND &40 x%% = ](Object%(0) + PAGE - !340) ELSE x%% = !Object%(0)
SYS `glVertexAttribPointer`, 0, 3, GL_FLOAT, FALSE, 0, x%%, @memhdc%
SYS `glEnableVertexAttribArray`, 0, @memhdc%
REM Render loop:
fov = 0.4
mindist = 0.1
maxdist = 10
camroll = 0
Camera() = 0, 0, -5.0
LookAt() = 0, 0, 0
aspect = 1.0
REPEAT
Float.0% = FN_f4(TIME/100)
SYS `glUniform1fv`, pTime%, 1, Float{}, @memhdc%
PROC_render(pDevice%, &00385080, 0, Light%(), 1, Material%(), Texture%(), Object%(), \
\ nVert%(), vFormat%(), vSize%(), Pan(), Tilt(), Roll(), Xpos(), Ypos(), Zpos(), \
\ Camera(), LookAt(), fov, aspect, mindist, maxdist, camroll)
UNTIL FALSE
END
DEF PROCcleanup
ON ERROR OFF
*REFRESH ON
IF !^Texture%() : IF Texture%(0)PROC_release(Texture%(0))
IF !^Object%() : IF Object%(0) PROC_release(Object%(0))
oProgram% += 0 : IF oProgram% SYS `glDeleteProgram`, oProgram%, @memhdc%
oVertex% += 0 : IF oVertex% SYS `glDeleteShader`, oVertex%, @memhdc%
oFragment% += 0 : IF oFragment% SYS `glDeleteShader`, oFragment%, @memhdc%
pDevice% += 0 : IF pDevice% PROC_release(pDevice%)
SYS "SDL_GL_SetAttribute", SDL_GL_CONTEXT_MAJOR_VERSION, 1, @memhdc%
ENDPROC
DEF PROCreadshader(shader$())
LOCAL I%, a$
IF (@platform% AND &F) >= 3 THEN
shader$(0) = "#version 100" + CHR$&A
shader$(1) = "precision highp float;" + CHR$&A
I% = 1
ELSE
shader$(0) = "#version 110" + CHR$&A
ENDIF
REPEAT
READ a$
I% += 1
shader$(I%) = a$ + CHR$&A : REM LF-terminate
UNTIL a$ = ""
ENDPROC
DEF PROCcompileshader(object%, shader$())
LOCAL compiled%, blen%, slen%, code%%, plog%%, code$
code$ = SUM(shader$()) + CHR$0
code%% = PTR(code$)
SYS `glShaderSource`, object%, 1, ^code%%, FALSE, @memhdc%
SYS `glCompileShader`, object%, @memhdc%
SYS `glGetShaderiv`, object%, GL_COMPILE_STATUS, ^compiled%, @memhdc%
IF compiled% = 0 THEN
SYS `glGetShaderiv`, object%, GL_INFO_LOG_LENGTH, ^blen%, @memhdc%
DIM plog%% blen%
SYS `glGetShaderInfoLog`, object%, blen%, ^slen%, plog%%, @memhdc%
ERROR 100, "Shader failed to compile:" + CHR$&D + CHR$&A + LEFT$($$plog%%,220)
ENDIF
ENDPROC
DEF FNgpa(function$)
LOCAL function%%
SYS "SDL_GL_GetProcAddress", function$, @memhdc% TO function%%
IF @platform% AND &40 ELSE function%% = !^function%%
= function%%
DEF PROC4(F%,a) : LOCAL A% : A%=FN_f4(a)
BPUT #F%,A% : BPUT #F%,A%>>8 : BPUT#F%,A%>>16 : BPUT#F%,A%>>24
ENDPROC
REM Minimal vertex shader:
DATA "attribute vec4 vPosition;"
DATA "void main()"
DATA "{"
DATA "gl_Position = vPosition ;"
DATA "}"
DATA ""
REM Fragment Shader code from https://www.shadertoy.com/view/MdXGDH
DATA "uniform float iTime;"
DATA "void main()"
DATA "{"
DATA "const float PI = 3.141592654;"
DATA "float time = iTime *0.2;"
DATA "float color1, color2, color;"
DATA "color1 = (sin(dot(gl_FragCoord.xy,vec2(sin(time*3.0),cos(time*3.0)))*0.02+time*3.0)+1.0)/2.0;"
DATA "vec2 center = vec2(640.0/2.0, 360.0/2.0) + vec2(640.0/2.0*sin(-time*3.0),360.0/2.0*cos(-time*3.0));"
DATA "color2 = (cos(length(gl_FragCoord.xy - center)*0.03)+1.0)/2.0;"
DATA "color = (color1+ color2)/2.0;"
DATA "float red= (cos(PI*color/0.5+time*3.0)+1.0)/2.0;"
DATA "float green= (sin(PI*color/0.5+time*3.0)+1.0)/2.0;"
DATA "float blue= (sin(+time*3.0)+1.0)/2.0;"
DATA "gl_FragColor = vec4(red, green, blue, 1.0);"
DATA "}"
DATA ""