Demo Scene Perspective Animated Lines lazarus / 39-Graphics ---------------------------------------------------------------------- Gigatron · 2024-06-26 17:37 So, A quick code ported from anywhere in www; The entry point of the project is started here Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls,  BGRAVirtualScreen, BGRABitmap, BGRABitmapTypes; type   { TForm1 }   TForm1 = class(TForm)    BGRAVirtualScreen1: TBGRAVirtualScreen;    Timer1: TTimer;    procedure BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);    procedure FormCreate(Sender: TObject);    procedure Timer1Timer(Sender: TObject);  private   public   end; var  Form1: TForm1;  v1,v2,yy : integer;  x: single; implementation {$R *.lfm} { TForm1 } procedure TForm1.Timer1Timer(Sender: TObject);begin       BGRAVirtualScreen1.RedrawBitmap;end; procedure TForm1.FormCreate(Sender: TObject);begin      v1 := 8;      v2 := 32;      x  := 0;end; procedure TForm1.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);var  i: integer;begin     // first horizontal lines     for i:=0 to 16 do     begin      Bitmap.DrawLine( 0,200+(i+2)*i,800,200+(i+2)*i,BGRA(255,255,255),false,dmSet);     end;     // perspective lines     for i:=-60 to 60 do     begin       Bitmap.DrawLine( 320 +Round(v1 * (i - Frac(x))), 200,320+ Round(v2 * (i - Frac(x))), 480,BGRA(255,255,255),true,dmSet);     end;      x:=x + 0.06; end; end. ---------------------------------------------------------------------- Gigatron · 2024-06-26 21:47 After that ; Added y movement variable, with space picture behind; We can now stop vertical lines movment and perform horizontal lines moves ! Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls,  BGRAVirtualScreen, BGRABitmap, BGRABitmapTypes; type   { TForm1 }   TForm1 = class(TForm)    BGRAVirtualScreen1: TBGRAVirtualScreen;    Timer1: TTimer;    procedure BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);    procedure FormCreate(Sender: TObject);    procedure Timer1Timer(Sender: TObject);  private   public   end; var  Form1: TForm1;  space : TBGRABitmap;  // lines vars  v1,v2,yy : integer;  x,y: single;  // added y movement implementation {$R *.lfm} { TForm1 } procedure TForm1.Timer1Timer(Sender: TObject);begin       BGRAVirtualScreen1.RedrawBitmap;end; procedure TForm1.FormCreate(Sender: TObject);begin      space := TBGRABitmap.Create('space.png');       // lines vars init      v1 := 8;      v2 := 64;      x  := 0;      y  := 0;end; procedure TForm1.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);var  i: integer;begin      // first horizontal lines     for i:=0 to 40 do     begin      Bitmap.DrawLine(0, 200 + Round(Sqr(i + Frac(y))), 800, 200 + Round(Sqr(i + Frac(y))),BGRA(255,255,255),false,dmSet);     end;     // perspective lines Vertical     for i:=-60 to 60 do     begin       Bitmap.DrawLine( 320 +Round(v1 * (i - Frac(x))), 200,320+ Round(v2 * (i - Frac(x))), 480,BGRA(255,255,255),false,dmSet);     end;     x := x + 0.00;   // move vertical lines  0 to stop     y := y + 0.06;   // move horizontal lines      // space pic     Bitmap.StretchPutImage(rect(0,0,800,210),space,dmSet); end; end. ---------------------------------------------------------------------- Gigatron · 2024-06-28 14:18 Hi, So this project is now finished with an Intro ; Will record a video for the result soon; * Ok here is the result on YT: https://www.youtube.com/watch?v=gSn9fpocV3o Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls,  BGRAVirtualScreen, BGRABitmap, BGRABitmapTypes,BGRATransform,BGRAGradientScanner,mmsystem; type  TWaveScanner = class(TBGRAAffineBitmapTransform)    Time: integer;    function GetOffset({%H-}X, Y: Single): Single;    { fast integer scanning (used by PutImage) }    procedure ScanMoveTo(X, Y: Integer); override;    { slow floating point scanning }    function ScanAt(X, Y: Single): TBGRAPixel; override;    constructor Create(ASource: TBGRACustomBitmap; ARepeatX,ARepeatY: boolean);  end; type   { TForm1 }   TForm1 = class(TForm)    BGRAVirtualScreen1: TBGRAVirtualScreen;  Timer1: TTimer;    procedure BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);    procedure FormCreate(Sender: TObject);    procedure Timer1Timer(Sender: TObject);  private   public    txt_scanner: TWaveScanner;   procedure DrawNormalScroller;   function drawFontChar(charek: Char; x: Integer): Integer;   end; var  Form1: TForm1;  space,gtr,gtr_shadow : TBGRABitmap;  // lines vars  v1,v2,yy : integer;  x,y: single;  // added y movement  l_timer : integer;  sn : single;  // sin counter for bouncy logo  // scroll text   bitmap_font,tx_scroll_bitmap,logo,dest_bitmap: TBGRABitmap; // images  charek : char;  offset: Char;  charSet: String;  fonts_width, fonts_height,pos_y: Integer;  sx, tx, scroll_speed : Integer;  s_text : string = 'HELLO BEFORE HUMAN MADNESS ON 24.06.2024 GIGATRON PRESENTS PERSPECTIVE ANIMATED LINES DEMO PROGRAMMED BY GIGATRON WITH LAZARUS FPC SFX BY KARSTEN OBARSKI GREETINGS ALL MEMBERS OF LAZARUS FPC FORUM SEE YOU ON ANOTHER PRODUCTION BYE BYE .......       ';   // audio stream  MyAudio_File: AnsiString;  WavStream : TMemoryStream; implementation {$R *.lfm} { TForm1 } procedure TForm1.Timer1Timer(Sender: TObject);begin       inc(txt_scanner.Time,1); // scroller horizontal sinus       sn := sn + 0.05;        inc(l_timer);        BGRAVirtualScreen1.RedrawBitmap;end; procedure TForm1.FormCreate(Sender: TObject);begin    space        := TBGRABitmap.Create('space.png');    gtr          := TBGRABitmap.Create('gtr.png');    gtr_shadow   := TBGRABitmap.Create('gtr_shadow.png');       // lines vars init      v1 := 8;      v2 := 64;      x  := 0;      y  := 0;      l_timer :=0;     // scroll text      dest_bitmap := TBGRABitmap.Create(740,32);     bitmap_font := TBGRABitmap.Create('mbifnt.png');      fonts_width  := 16;     fonts_height := 32;     sx := 750;  // start scroll pos x   right     charek :=' '; // void always !     offset := ' '; // the first char on s_text = ' ' = space     scroll_speed := 2;     pos_y := 0;      txt_scanner := TWaveScanner.Create(dest_bitmap,false,false);   txt_scanner.Translate(0,400); // scroll text      // audio stream  MyAudio_File := 'blueberry.wav';    WavStream    := TMemoryStream.Create;    WavStream.LoadFromFile(MyAudio_File);    PlaySound(WavStream.Memory, 0, SND_LOOP  or SND_NODEFAULT or SND_ASYNC or SND_MEMORY); end; procedure TForm1.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);var  i,j: integer;begin    for i:=0 to 19 do     begin        for j:=-60 to 60 do         begin          Bitmap.DrawLine(0,200 + Round(Sqr(i + Frac(y))),800,200 + Round(Sqr(i + Frac(y))),BGRA(0+i*14,0+i*14,0+i*14),false,dmSet);          Bitmap.DrawLine( 320 +Round(v1*(j-Frac(x))),200,320+ Round(v2*(j- Frac(x))), 480,BGRA(75,75,75),false,dmSet);        end;     end;      if(l_timer>=500) then      begin       y := y + 0.08;  // move horizontal lines       x := x + 0.00;   // move vertical lines  0 to stop      end;      if(l_timer>=1500) then      begin       y := y - 0.08;  // move horizontal lines       x := x + 0.10;   // move vertical lines  0 to stop       if(l_timer>2500) then l_timer:=0;    end;       // space pic     Bitmap.StretchPutImage(rect(0,0,800,204),space,dmSet);     // gtr    Bitmap.PutImage(120,160+Round(- abs(sin(sn)*30)),gtr,dmDrawWithTransparency);      Bitmap.PutImage(120 ,210+Round(abs(sin(sn)*30)),gtr_shadow,dmDrawWithTransparency);     // scroll text     DrawNormalScroller;  // normal text scrolling     Bitmap.Fill(txt_scanner,dmLinearBlend);  end; function TForm1.drawFontChar(charek: Char; x: Integer): Integer;var  p, cx, cy, l, r: Integer;begin  if (x > width) and (x > 0) then  begin    Result := 0;    Exit;  end;   // 16x16   p := Ord(charek) ;   r :=  (p - Ord(offset)) div (bitmap_font.Width div fonts_width); // nb char 40*8   cx := (p - Ord(offset) -r * (bitmap_font.Width div fonts_width) )  * fonts_width;   // dans ce cas là * 40   cy := 0 + (r * fonts_height); // 0    // 8x8   //p := Ord(charek);   //cx := (p - Ord(offset)  )  * fonts_width;   //cy :=  0; // 0   for l := 0 to fonts_width-1   do  begin    if (cx >= 0) and (x + l <= width) then    begin        dest_bitmap.PutImagePart(x + l  , pos_y , bitmap_font, Rect(cx + l, cy, cx + l + 1, cy + fonts_height), dmSet);    end;  end;  Result := 1;end; procedure TForm1.DrawNormalScroller;var  last_char: Char;  x, i: Integer;  koda: Char;  xLimit: Integer;begin   dec(sx, scroll_speed);  x := sx;  xLimit := width + fonts_width;   for i := 1 to Length(s_text) do  begin    koda := s_text[i];    x := x + fonts_width;   if (x > -fonts_width) and (x < xLimit) then    begin    if drawFontChar(koda, x) = 0 then        Break;      last_char := koda;    end;  end;  if x < 0 then sx := xLimit; end; { TWaveScanner } function TWaveScanner.GetOffset(X, Y: Single): Single;begin  result := 10 * sin((Y + Time) * 30/6 * PI / 180);   // no sinus * 0end; procedure TWaveScanner.ScanMoveTo(X, Y: Integer);begin  inherited ScanMoveTo(X + round(GetOffset(X, Y)), Y);end; function TWaveScanner.ScanAt(X, Y: Single): TBGRAPixel;begin  Result:=inherited ScanAt(X + GetOffset(X, Y), Y);end; constructor TWaveScanner.Create(ASource: TBGRACustomBitmap;  ARepeatX,ARepeatY: boolean);begin  inherited Create(ASource, ARepeatX, ARepeatY);  Time := 0;end; end. ---------------------------------------------------------------------- circular · 2024-06-29 07:35 Hi Gigatron, Very cool, with the module music, that brings back nostalgic memories.  Have you considered DrawLineAntialias with integer coordinates instead of DrawLine? I would probably be quite fast as well. Warm regards ---------------------------------------------------------------------- Gigatron · 2024-06-30 05:12 Thank you @circular , I'm going to optimize all of that. By the way , Do you think you will one day include the GLSL shader in the BGRA component?  Regards GTR ---------------------------------------------------------------------- circular · 2024-07-01 10:57 Hi Gigatron, In fact, shaders are already supported by BGRABitmap, though I guess it hasn't been used much yet. I've added an example called opengltest4 for you in test/test4lcl_opengl that makes use of a shader to blur an image. Note: I've fixed some issue with texture size, so I suggest to use the dev branch. Regards ---------------------------------------------------------------------- Gigatron · 2024-07-01 18:13 Good , thank you @circular, i've learned just 2% of BGRA component, will now study the shaders Regards A nice demo made under 1 hour with Raylaz ; https://www.youtube.com/watch?v=ebYEE6PnAKg ---------------------------------------------------------------------- Gigatron · 2024-07-01 21:44 Ah, yes  this is my first shader with BGRA component ; it's animated and running smooth ; The code is the same at shadertoy; https://www.shadertoy.com/new Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i void mainImage( out vec4 fragColor, in vec2 fragCoord ){    // Normalized pixel coordinates (from 0 to 1)    vec2 uv = fragCoord/iResolution.xy;     // Time varying pixel color    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));     // Output to screen    fragColor = vec4(col,1.0);} @circular you are a master !!! Reverse code of glblurshader of BGRA : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 'vec3 col = 0.5 + 0.5*cos(radius+texCoord.xyx+vec3(0,2,4));'+  '       FragmentColor  = vec4(col,1.0);'#10 +'}', ---------------------------------------------------------------------- circular · 2024-07-02 01:04 Hi Gigatron, I am glad to hear that the shader compiles and gives a smooth animation. It seems you've hacked the radius variable to express time.  Even though I am a bit embarassed to be called a master, I am happy to offer some guidance. There are some subtleties if you're trying to write shader code. For example, it may seem a little detail, but using version parameter '130' makes it much easier. With version '120', one need to write explicit conversions between integers and floats. You would have to write 1./2.5 instead of 1/2.5. The latter is supposed to compile only from version '130' on. This requires OpenGL version 3 but anyway, when using framebuffers, one need at least this version. Cheers ---------------------------------------------------------------------- Gigatron · 2024-07-02 13:12 Thank you again @circular without you and your work what I code would not exist however I understood your explanation of the fact that I have a vague knowledge of shaders 1% and the compiler gives me the right errors for the fragment shader correction. And the result is now awesome ... This shader is animated with 'time' float uniform You can see the animated version on glslsandbox : Bamiga sector 1 effect here https://glslsandbox.com/e#69288.1 And the demo made to tribute Bamiga Sector 1 using three.js https://www.youtube.com/watch?v=q94Cb42tdeI Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i constructor TBGLCheckerBoardShader.Create(ACanvas: TBGLCustomCanvas); begin// vertex + fragmentinherited Create(ACanvas,'void main(void) {'#10 +'     gl_Position = gl_ProjectionMatrix * gl_Vertex;'#10 +'    texCoord = vec2(gl_MultiTexCoord0);'#10 +'}', 'uniform sampler2D image;'#10 +'uniform ivec2 textureSize;'#10 +'uniform ivec2 allocatedTextureSize;'#10 +'uniform vec2 direction;'#10 +'uniform float time;'#10 +'out vec4 FragmentColor;'#10 +  'void main(void)'#10 +'{'#10 + '       vec2 pos = texCoord - vec2(0.0,0.7);'#10 +  '       float t = time*0.1 ; '#10 +'       float horizon = 0.0; '#10 +'       float fov = 0.9;     '#10 +'       float scaling = 0.1; '#10 + '     vec3 p = vec3(pos.x, fov, pos.y - horizon); '#10 +'       vec2 s = vec2(p.x/p.z, p.y/p.z) * scaling;  '#10 + '       float c = 0.0; '#10 + '       if(pos.y<-0.1){  '#10 +'       if (pos.y > 0.) c  = sign((mod(s.x, 0.05) - 0.05) * (mod(s.y+t, 0.1) - 0.04));else      c = sign((mod(s.x, 0.05) - 0.05) * (mod(s.y-t, 0.1) - 0.04)); '#10 + '             float d =  sign((mod(s.x, 0.05) - 0.05) * (mod(s.y-t+0.003, 0.1) - 0.045));'#10 + '               FragmentColor = vec4( vec3(c*0.6,c*0.6,c*0.6), 1.0 )+0.90+c-d;'#10 +'       } '#10 +'       else'#10 + '       FragmentColor = vec4( vec3(0.1,pos.y*3.0,1.0), 1.0 ); '#10 +  '//     FragmentColor = texture2D( image, texCoord ) ;'#10 +  '}', 'varying vec2 texCoord;', '130');   FImageIndex := UniformInteger['image'];  FTextureSize := UniformPoint['textureSize'];  FAllocatedTextureSize := UniformPoint['allocatedTextureSize'];  FDirection := UniformPointF['direction'];  FTime := UniformSingle['time'];      // float uniform   ImageIndex:= 0;  Direction := PointF(0,0);  TextureSize := Point(1,1);  AllocatedTextureSize := Point(1,1);  Time := 0;end; ---------------------------------------------------------------------- circular · 2024-07-03 13:28 It is heart-warming for me to hear it makes it possible.  About the modification of the code, that's right. You've added the time variable as a uniform float. Now you can tidy up a bit by removing the unused uniform variables. Actually you just need time here. I love the idea of introducing a time variable to make an animated shader. Regards