Plasma

Discussions related to graphics (2D and 3D), animation and games programming
David Williams

Plasma

Post by David Williams »

BASIC + GfxLib, no assembly language:

http://www.proggies.uk/temp/plasma.zip

Have fun guessing how it was done.
p_m21987
Posts: 177
Joined: Mon 02 Apr 2018, 21:51

Re: Plasma

Post by p_m21987 »

If someone guesses correctly, will you share source code?
David Williams

Re: Plasma

Post by David Williams »

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. :cry:
David Williams

Re: Plasma

Post by David Williams »

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 ""
DDRM

Re: Plasma

Post by DDRM »

These shaders are quite something, aren't they?

:-)

D
David Williams

Re: Plasma

Post by David Williams »

DDRM wrote: Mon 15 Jul 2019, 08:38 These shaders are quite something, aren't they?
Visually impressive results with (often) only a few lines of GLSL.


David.
--