Simple per pixel lighting system
BlitzMax Forums/BlitzMax Programming/Simple per pixel lighting system
| ||
I thought I would post the source to the lighting system I've been working on. I'm sure it could be improved upon. Basicly how it work is this: * Create an image which is 1/32 the size of the screen * Set blend to LightBlend * Draw all your lights on it(could be images, shapes, whatever) * Grab the lights image * Cls * Draw all your other stuff * Set blend to ShadeBlend * Draw the scaled up version of the lights image Here is the system: And here is an example: Strict SetGraphicsDriver GLMax2DDriver() Graphics 640, 480,0 Import "light.bmx" AmbientLight = [200,200,200] TLight.InitBuffer TLight.DefaultImage = LoadImage("light.png") MidHandleImage TLight.DefaultImage Local Light1:TLight = TLight.Create(MouseX(),MouseY(),[255,255,255],1,4,4) While Not KeyHit (KEY_ESCAPE) Light1.X = MouseX() Light1.Y = MouseY() TLight.UpdateBuffer Cls 'Render your other stuff here TLight.RenderBuffer Flip FlushMem Wend Screenshot: ![]() |
| ||
heh, clever. |
| ||
Thanks. Like I said it is very simple. I only wish GrabImage wasn't so slow. But that will be the case until GPU hardware changes. |
| ||
Yeah, render to texture would be nice to have. |
| ||
You can use the AccumBuffer instead of grabbing images, I did that for a project, and it worked very well. (AccumBuffer is only present in OpenGL as far as I know) |
| ||
Very nice. Is the bufferscale to maintain a decent fps? It seems quite possible to add a changestatus and deletelight function to turn off or permanently destroy a light. How would defining a light as static or dynamic help framerate. If there are no dynamic lights and the screen hasn't scrolled then you wouldn't have to call updatebuffer. Lots of possibilities as well as using the lightbuffer to add shadows. |
| ||
@fredborg I will look into the AccumBuffer buffer some more. It does sound like it would be much faster. But then we would have to resort to using opengl outside of max2d and eliminating any use of DX. I'm not sure if that is the best. But I think I will create a version which uses the accumilation buffer anyway. @tonyg Yes, I scale the buffer to achieve better framerates, but also to use less video ram. GrabImage/Pixmap is extremly slow. Light states are very easily added, I just forgot to do so for this upload. I did a test where the image buffer was only updated when a light actualy moved. While the buffer stayed the same the frame rate was near 1000fps when a light moved it dropped very quickly to ~200fps. |
| ||
Given it's 3D I would have looked into ver colours first before this. And beyond that, looked into modulate2X as you would only need to draw the lights on top then as sprites. for instance, there is nothing stopping you in both DX and opengl, from overlaying a nice subdivided mesh and changing the vert cols. This way, although there is upload to the card, it is minimal and possibly faster. |
| ||
All I get when I run the code above is a blank screen in a single shade of color? Anything special about the light.png file? |
| ||
Try using the light.png from "C:\Program file\BlitzMax\samples\birdie\misc\lightImage\media\light.png" and changing the X/Y scale to 1. It also shows better if you load a background image or use another image with tileimage. |
| ||
Got it to work now -- nice! also looks good if you chance the ambient light variable to something like [125,125,255], to give a blueish hue to the 'dark' parts, and have more of a night-time look to it. |
| ||
Simple turnon, turnoff, switchstatus and destroy...Strict Global LightList:TList = New TList Global AmbientLight:Int[3] Type TLight Global BufferScale:Int = 8 Global BufferImage:TImage = Null Global DefaultImage:TImage = Null Field Image:TImage Field X:Float Field Y:Float Field Color:Int[3] Field ScaleX:Float Field ScaleY:Float Field Alpha:Float Field status:Int Function Create:TLight (_X:Float, _Y:Float, _Color:Int[],_Alpha:Float = 1.0,_ScaleX:Float = 1.0,_ScaleY:Float = 1,_Image:TImage = Null,_status=1) Local Light:TLight = New TLight Light.X = _X Light.Y = _Y Light.Color = _Color Light.ScaleX = _ScaleX Light.ScaleY = _ScaleY Light.Alpha = _Alpha Light.Image = _Image Light.status = _status If Not Light.Image If Not DefaultImage Return Null Else Light.Image = DefaultImage End If End If LightList.AddLast(Light) Return Light End Function Function InitBuffer() BufferImage = CreateImage(GraphicsWidth()/BufferScale, GraphicsHeight()/BufferScale) SetImageHandle BufferImage, 0,0 End Function Function UpdateBuffer() SetClsColor AmbientLight[0],AmbientLight[1],AmbientLight[2] Cls Local _Blend:Int = GetBlend() SetBlend LightBlend For Local Light:TLight = EachIn LightList If light.status=1 SetAlpha Light.Alpha SetColor Light.Color[0],Light.Color[1],Light.Color[2] SetScale Light.ScaleX/BufferScale, Light.ScaleY/BufferScale DrawImage Light.Image,Light.X/BufferScale, Light.Y/BufferScale EndIf Next GrabImage(TLight.BufferImage,0,0) SetBlend _Blend SetColor 255,255,255 SetScale 1,1 End Function Function RenderBuffer() Local _Blend:Int = GetBlend() Local _SX:Float,_SY:Float GetScale _SX, _SY SetBlend shadeBlend SetScale TLight.BufferScale,TLight.BufferScale DrawImage TLight.BufferImage,0,0 SetBlend _Blend SetScale _SX,_SY End Function Function lighton(Light:TLight) light.status=1 End Function Function lightoff(Light:TLight) light.status=-1 End Function Function switchstatus(Light:TLight) light.status=-light.status End Function Function destroylight(Light:TLight) ListRemove lightlist,Light End Function End Type |
| ||
Thanks tonyg. @Fish Per vertex is cool and all, but much harder to impliment. I like to take things easy :). Maybe some day I will make a per vert system. |
| ||
altidumens, nice screenshot, love the artwork |
| ||
awsome, looks like you can use it for the "fog of war" effect too. |
| ||
Altitudems, what plans have you got to develop this? |
| ||
@Jeroen The artwork is not mine its from Zelda 3: A link to the past But I'll take the credit, sure :) @tonyg My plan is to get a good amount of source code and graphics ready for a community project. The project should a tile-based game engine. My hope is that beginners will be able to learn how to program games from it. It will sort of be a framework to create games off of. Here are some things I had in mind: * Console System - Will provide debugging and other functionality. Variables can be viewed and changed, commands can be issued, etc. * Vector Math - Library with easy helper functions (Finding angles, etc) * Entity System - Each game object will be an entity at the core * Entity Collision - Box vs. Box(possible rotation support), Ellipse vs. Ellipse, Ellipse vs. Box, Poly vs. Poly All routines will detect overlap and will work with high speed objects. Each test will also return the smallest vector required to separate objects making collision response a lot easier * Basic Collision Response - An object's response type will determine what will happen when a collision occurs. Objects should also support bounce and friction. * Sprite System - Easier (animated) image handling. Some added special effects. * Model System - This will handle each game characters animations. For each state the character can have an animation played. Each model can be saved to disk. So creating a character animation set can be done easily with a separate tool. * Camera System - This will allow for multiple viewports in the game. Each camera will be able to follow a game object, zoom in and out, move(scroll), shake, etc. * Tile Object - These can be animated, or static. * Tile Map System - This will display all the map information, and will provide coordinate conversion routines. Each map can have multiple floors with a various amount of detail/overlay layers. Each floor will have a Collision map attached to it. Things like bridges will be easily achieved. * Player object - Will handle each player. Players will be updated via Finite State Machine AI, which will be triggered by Input from the user. Controls will be easily defined and changed on the fly. * Game characters - Will handle each character. They will also be updated via Finite State Machine AI loaded from external files. Each character will have different attributes applied to it, that will affect its decisions. When enabled to do so characters will be able to communicate with each other, group together, etc. * Particle System - This will allow for various special effects in game. * Lighting System - Per pixel lighting for creating atmosphere in game. Image based for flexibility. Ambient light can be set. * Weather/Day-Night - This system will allow for additional special effects like rain, clouds, fog, night, day, etc. It will use the other special effect systems to achieve this. * In addition a Game Object will control the flow of the game and its different levels and objectives. Thats the plan anyway. I hope to most of it implemented before any project is started. If there is a solid base code a community project will be much more successful. |
| ||
@Altitudems, maybe you can take a look at my Console Mod. It already provides WatchFunctions for Variables and also it supports direct passing Functions to specified Commands. |
| ||
It sounds like a pretty nice tile engine. |
| ||
@Klepto Your console mod is great, I have looked at it. But the console mod I have works just as well and fits more tightly into the system. |
| ||
No problem. Was just an idea to help you saveing a bit of time. |
| ||
It does sound great. If you do your own map-editor couldn't you also add a pathfinding function? |