Lazarus

Programming => Graphics and Multimedia => Graphics => Topic started by: Handoko on October 07, 2017, 10:39:36 pm

Title: A Graphics Effect Challenge
Post by: Handoko on October 07, 2017, 10:39:36 pm
Are you dare to take this challenge?

Hello friends.
Do you remember the teen that created the game "Dino" a year ago? I still contact with him. His programming skills advance fast and he now use C++, which he think is more suitable for him. He sometimes asks me something about programming.

Recently he asked me how to create a 2D effect that he wants to use in his game. He provided me the video explaining the effect. I watched it and I think I can do it in Pascal (without using shader) but I currently a bit busy. So I post it here, hope anyone can write the code that showing that effect.

Here is the video:
https://www.youtube.com/results?search_query=Tj5NV0sVtQE

- Please don't use OpenGL nor any hard-to-understand graphics libraries
- Don't use shader programming
- Performance is not important
- In Pascal only

I want to provide him the code in Pascal in the easy to understand code, so the performance is not important. It will let him to study and understand how the concept of the effect works. Can you help me?
Title: Re: A Graphics Effect Challenge
Post by: Akira1364 on October 09, 2017, 02:45:54 am
The code required to implement lighting as shown in the video in the context of a software renderer would be significantly more "hard-to-understand" than the code required to implement it with OpenGL, though. Also if you're trying to prove that it would be somehow easier to do it in Pascal than C++, it really wouldn't be, as the code would be fundamentally identical in both languages apart from the obvious syntax differences.

Lastly you might want to provide a link to this Dino game, as I actually have no idea who you're talking about and feel like others might not either.
Title: Re: A Graphics Effect Challenge
Post by: User137 on October 09, 2017, 11:47:43 am
The video explained enough, looks like light is being stopped by each pixel in the map. Challenge worth trying. I have only done similar with polygons and opengl before, those principles don't work here.
Title: Re: A Graphics Effect Challenge
Post by: molly on October 09, 2017, 11:57:23 am
Lastly you might want to provide a link to this Dino game, as I actually have no idea who you're talking about and feel like others might not either.
Dunno if there is a better link but the discussion on dinoland can be found here (http://forum.lazarus.freepascal.org/index.php/topic,33960.0.html?PHPSESSID=b5908l0hkpq70uea60anslsn06).
Title: Re: A Graphics Effect Challenge
Post by: User137 on October 09, 2017, 12:10:47 pm
Could we all have some same picture to use as a map? The dinoland download links i tried are broken.
Title: Re: A Graphics Effect Challenge
Post by: lainz on October 09, 2017, 01:29:38 pm
I made a video of the game
https://www.youtube.com/watch?v=EtdqRpaKwRU

But that game has nothing to do with the effect, must be for a new game.
Title: Re: A Graphics Effect Challenge
Post by: Handoko on October 09, 2017, 01:33:44 pm
The dino game (DinoLand) was one of the games he ever created. Actually the game has nothing to do with this challenge I submitted. If anyone interested to see his latest game (some months ago), this is the link:
https://gamejolt.com/games/gh/263866

Although he decided not to use Pascal, but I'm still glad to see a teen who has such passion to learn game programming. He asked me many questions about the calculations that needed in game programming, I explained but I doubted he can understand. For example I ever replied his question about one of the case he needed to solve with Trigonometry. He can't understand, I guess it had not been taught in his class yet.

He is young but want to try the things that he possibly can't understand. For this challenge, I know it actually better to solve with OpenGL shader (although I'm not good in using shader), but I think he may not able to understand how to use shader. Last time I knew him, he uses SDL not OpenGL.

But if you can create that 2D lighting effect using OpenGL shader, it's okay too. I will try using the default Lazarus drawing components. I think it will have several tabs. The first tab will show how to use trigonometry to shot a single ray from a fixed point. The second tab will show multiple rays shot with increment of 10 degree. On the third tab, the point (that shoots rays) can be move. And so on. There will explanation each tab.

It does not need to be realtime, performance is not important. It is like a educational presentation slide show. It is for educational purpose. You know, it will be awesome if it is write in Pascal and put on the Lazarus component/tutorial repository.
Title: Re: A Graphics Effect Challenge
Post by: User137 on October 09, 2017, 02:54:12 pm
Here's 3 images i'll test with. I included also a non-black background if i could additionally make it act like light effect with additional coloring. I'm aware that could make it even slower so will see how it goes. Front and back images are double the size of shapes file, which should only be used to make a 2-dimensional boolean array for the lightrays collision map. You will want to avoid reading pixel colors from lazarus components for realtime rendering if it's possible. Even the background if making additive lights should probably be cached in array, and sin/cos functions.
Title: Re: A Graphics Effect Challenge
Post by: Handoko on October 09, 2017, 03:17:49 pm
Cool.
After you finished it, you should add this feature to your game engine.

I'm still busy doing non-programming projects. I'll catch up later.
Title: Re: A Graphics Effect Challenge
Post by: User137 on October 09, 2017, 04:23:49 pm
I'm going to upload what i have so far, before the code goes too crazy. It's not using any graphics engines, just TImage from Lazarus. So far it's incredibly fast, but that's because it's not drawing the color fade pixel by pixel. It is doing a full redraw everytime cursor moves. Feel free to carry on if want to.

(Add those 3 .png files to same folder. Forum upload limitations won't let me put them in.)

And a sidenote. OpenGL could already draw that shaded and add-blended as light, using GL_TRIANGLE_FAN as render mode.
Title: Re: A Graphics Effect Challenge
Post by: Handoko on October 09, 2017, 04:50:53 pm
Wow, you're really a master in graphics/game programming.
You can solve the problem just in hours.  :o

Respect and bow.
Title: Re: A Graphics Effect Challenge
Post by: User137 on October 09, 2017, 07:13:45 pm
Thanks  :D

Here's the next one. Additive blend and fade done, and i will say it was not easy to figure out. I drew the light polygon in temporary bitmap and with a 0..1 fademap representing 1 quarter of the glow, multiplied with the background. It came down to roughly 2 frames per second as expected.

Some code is still left commented so you can test different things if want, change colors and so on. I set the light color a bit dim yellow, so it's clear that the background is still visible through it.

And really it's just some kind of proof of the concept, with vector map and GPU one could get significant speed boost to it. This is some sort of 2D ray-tracing.
Title: Re: A Graphics Effect Challenge
Post by: Handoko on October 09, 2017, 07:22:23 pm
Tested your new code. But nothing shows up.
Title: Re: A Graphics Effect Challenge
Post by: User137 on October 09, 2017, 07:43:43 pm
Odd, i tested on empty folder and it worked. Try disabling the TTimer and draw when clicking mouse, so:
Code: Pascal  [Select]
  1. procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  2.   Shift: TShiftState; X, Y: Integer);
  3. begin
  4.   DrawScreen;
  5.   //lightPic.SaveToFile('_lightPic_temp.png');
  6. end;

This version added BeginUpdate and EndUpdate pairs which should be like doublebuffering, preventing it from starting to show things on screen before drawing is even finished. But there are other ways to do the same still, if that even is the problem. I have i5 cpu which shouldn't be anything out of ordinary.
Title: Re: A Graphics Effect Challenge
Post by: Handoko on October 09, 2017, 08:01:35 pm
Still no luck.

But so far I found that the running trapped in the loop in DrawScreen:

Code: Pascal  [Select]
  1.     for j:=0 to lightPic.Height-1 do
  2.       for i:=0 to lightPic.Width-1 do begin
  3.         cb:=back.Bitmap.Canvas.Colors[i, j];
  4.         cl:=lightPic.Bitmap.Canvas.Colors[i, j];
  5.         if cl.red > 0 then begin
  6.           //Colors[i, j]:=TColorToFPColor(clBlack);
  7.           f:=fade[min(LightDist, abs(i-mx)), min(LightDist, abs(j-my))];
  8.           c.red:=min(65535, cb.red+round(cl.red*f));
  9.           c.green:=min(65535, cb.green+round(cl.green*f));
  10.           c.blue:=min(65535, cb.blue+round(cl.blue*f));
  11.           Colors[i, j]:=c;
  12.         end else Colors[i, j]:=cb;
  13.       end;

Note: I use Linux.
Title: Re: A Graphics Effect Challenge
Post by: Akira1364 on October 10, 2017, 12:59:45 am
The video explained enough, looks like light is being stopped by each pixel in the map. Challenge worth trying. I have only done similar with polygons and opengl before, those principles don't work here.

Don't think you got my point... I was saying that the idea that implementing the lighting in OpenGL would be somehow more "hard to understand" doesn't make sense. As shown by your example code, doing it in software requires a whole lot of manual math that wouldn't be necessary if you did use OpenGL.
Title: Re: A Graphics Effect Challenge
Post by: taazz on October 10, 2017, 02:07:26 am
The video explained enough, looks like light is being stopped by each pixel in the map. Challenge worth trying. I have only done similar with polygons and opengl before, those principles don't work here.

Don't think you got my point... I was saying that the idea that implementing the lighting in OpenGL would be somehow more "hard to understand" doesn't make sense. As shown by your example code, doing it in software requires a whole lot of manual math that wouldn't be necessary if you did use OpenGL.
actually it would make things harder to learn for any one that has no idea what opengl does and how.
Title: Re: A Graphics Effect Challenge
Post by: User137 on October 10, 2017, 03:20:01 am
Still no luck.

But so far I found that the running trapped in the loop in DrawScreen:
If you change this:
Code: Pascal  [Select]
  1. with image1.Picture.Bitmap.Canvas do begin
  2.     image1.Picture.Bitmap.BeginUpdate(true);
  3.     ...
  4.     image1.Picture.Bitmap.EndUpdate();
  5.   end;
Into this:
Code: Pascal  [Select]
  1.   image1.Picture.Bitmap.BeginUpdate(true);
  2.   with image1.Picture.Bitmap.Canvas do begin
  3.     ...
  4.   end;
  5.   image1.Picture.Bitmap.EndUpdate(false);
Will it work? I don't actually know what BeginUpdate does internally, maybe even changing the TCanvas reference to something else temporarily just for the doublebuffering effect. It led to virtual method so it has to have some platform specifics. To me adding BeginUpdate had biggest impact when i maximize the window. It has same speed as small window now.

You can also manually draw it to a temporary bitmap and then while removing BeginUpdate/EndUpdate's, just call 1 line to draw the temp bitmap to image.bitmap.canvas. Or 3rd option for setting DoubleBuffered:=true; for the form and also trying with and without the update pair.

Lastly i hope it's not coming down to the speed of the cpu. You could debug i and j getting bigger if you paused? It's not infinite loop especially if you changed it to click. Maybe it's the debugging feature itself that's dragging it down. Let operating system start the binary software file.
Title: Re: A Graphics Effect Challenge
Post by: Akira1364 on October 10, 2017, 04:43:33 am
The video explained enough, looks like light is being stopped by each pixel in the map. Challenge worth trying. I have only done similar with polygons and opengl before, those principles don't work here.

Don't think you got my point... I was saying that the idea that implementing the lighting in OpenGL would be somehow more "hard to understand" doesn't make sense. As shown by your example code, doing it in software requires a whole lot of manual math that wouldn't be necessary if you did use OpenGL.
actually it would make things harder to learn for any one that has no idea what opengl does and how.

Still makes no sense. You're saying that you think implementing something from scratch using entirely custom math is easier than using a graphics API that has built-in functions specifically meant for those purposes.

That being said, for the sake of Handoko's original challenge, I made a reworked version of User137's example that uses TBGRABitmaps and a TBGRAVirtualScreeen (instead of TBitmaps and a TImage), and have attached a zip file that contains my modified project files as well as the PNG backgrounds to this post. You'll need the "BGRAControls" package installed, obviously.

This version actually runs at what I would call "full speed", although I would still strongly recommend that nobody ever attempt to actually write real games using software imaging techniques. Use OpenGL or a similiar hardware graphics API. There is nothing harder or "scarier" about them then any other aspect of programming you'd need to know to make games...
Title: Re: A Graphics Effect Challenge
Post by: User137 on October 10, 2017, 09:34:56 am
Don't think you got my point... I was saying that the idea that implementing the lighting in OpenGL would be somehow more "hard to understand" doesn't make sense. As shown by your example code, doing it in software requires a whole lot of manual math that wouldn't be necessary if you did use OpenGL.
I haven't been debating against that, and i completely agree that doing lights with pixels and software rendering is not something you do or want to see in any real games. It was just an experiment and he wanted to see how it can be done. What the app does is send a thousand or more rays to different directions, move them 1 pixel at the time and define polygon by where they end up unrestricted or collisioned. It is only feasible for 1 light source even if the fade was rendered by OpenGL. Games can have hundreds of lights at same camera distance, and without having much of an effect on performance it means very different approaches.

About hard to understand... i actually still don't understand how shadows work in most of 3D. This app however, as you noticed came up in a matter of hours.