Lighting in 2D with Direct3D using SlimDX

Started by
4 comments, last by OrangyTang 13 years, 7 months ago
First and foremost, I can handle all the actual drawing in Direct3D and have done it before, so none of this is a problem. What I am having a problem with is lighting.

I've read many tutorials that focus on lighting in a 3D environment and can't seem to get it to apply to my 2D world on large scale. So my first question is, does anyone have any good tutorials or books on lighting (possibly including setting up the camera as well, as this is my big problem with setting up lighting to work properly) specifically in a 2D environment? I know this first question is a lot to ask for, so here's my other one.

Rather than going with a complex lighting, I decided on using another type of method using simple lightmaps. I didn't want to go terribly complex with this, so I created a sample lightmap as seen on the first link below. My goal was to make it look something like the 2nd link (done in photoshop using, multiply filter and opacity set to 90%). However, I can only seem to get it at best to look like the 3rd link. My code for drawing the lightmap is below, can anyone give me any pointers on how to make it look more like the 2nd link?

Also I do need to mention, for the 1st result (3rd image), to get the correct opacity, I did have to change the alpha values for the drawmap to 20. While the inverted image has no change in opacity.

Please ignore changes in the background tiles, I just generated a random multi-colored floor for testing purposes.

My sample lightmap:


What I want to look like:


What it does look like:


Without the lightmap:


Inverted lightmap is almost what I want:


The drawing code (createmap/drawmap just draws multicolored rectangles at 32x32 intervals for the size of the form):

    Public Structure ColorVertex        Public Position As Vector4        Public Color As Integer        Public TexturePos As Vector2    End Structure    Public Structure Vertex        Public Position As Vector4        Public TexturePos As Vector2    End Structure    Shared Sub Main()            form = New RenderForm("Test Build " & My.Application.Info.Version.ToString())            form.MaximizeBox = False            form.FormBorderStyle = FormBorderStyle.FixedSingle            form.ClientSize = New Size(800, 608)            'Create a device passing the device and form.            _Device = CreateDevice(form)            CreateMap()            Dim lightMap As Texture = Texture.FromFile(_Device, "lightmap.png")            Dim lightVertices() As Vertex = {                New Vertex() With {.Position = New Vector4(0, 0, 0, 1), .TexturePos = New Vector2(0, 0)},                New Vertex() With {.Position = New Vector4(800, 0, 0, 1), .TexturePos = New Vector2(1, 0)},                New Vertex() With {.Position = New Vector4(0, 608, 0, 1), .TexturePos = New Vector2(0, 1)},                New Vertex() With {.Position = New Vector4(800, 608, 0, 1), .TexturePos = New Vector2(1, 1)}            }            MessagePump.Run(form,                Sub()                    _Device.Clear(ClearFlags.Target, Color.Black, 1.0F, 0)                    _Device.BeginScene()                    DrawMap()                    _Device.SetRenderState(RenderState.AlphaBlendEnable, True)                    _Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha)                    _Device.SetRenderState(RenderState.DestinationBlend, Blend.One)                    _Device.VertexFormat = VertexFormat.PositionRhw Or VertexFormat.Texture1                    _Device.SetTexture(0, lightMap)                    _Device.DrawUserPrimitives(PrimitiveType.TriangleStrip, 2, lightVertices)                    _Device.EndScene()                    _Device.Present()                End Sub            )            For Each item As Object In ObjectTable.Objects                item.dispose()            Next        End Sub


If you need any of my other source for this project let me know. I only included what I thought was relevant.
Advertisement
Your images are broken. Appears to be hotlinking protection.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Sorry about that, my IP is allowed on the hotlink protection so I always forget. The images should be fixed now. If not, each image is click-able to a bigger version. If that still doesn't work, I'll upload them to somewhere else.
You need a 'multiply' blend state (ie. you multiply your full colour texture by your lightmap texture). I'm not familiar with the VB syntax for that, but you'll need something like:

instead of: _Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha) _Device.SetRenderState(RenderState.DestinationBlend, Blend.One)something like: _Device.SetRenderState(RenderState.SourceBlend, Blend.DestinationColor) _Device.SetRenderState(RenderState.DestinationBlend, Blend.Zero)
Thank you for the response. Don't worry about the difference in languages. I am familiar with C# and C++ as well as VB. I just prefer VB.

WOW! That is exactly what I was going for! Thank you so much. Could you perhaps tell me how or why that is a multiply blend state? I guess I should probably check the DirectX documentation <_<.

Thanks again! :D
Quote:Original post by BigRedPK
WOW! That is exactly what I was going for! Thank you so much. Could you perhaps tell me how or why that is a multiply blend state? I guess I should probably check the DirectX documentation

The blend equation is a bit tricky to explain, but it's basically:

finalPixelColour = (sourceColour * sourceFactor) + (destColour * destFactor)

'sourceColour' is the colour from whatever you're drawing, in this case it's the colour from your lightmap.

'destColour' is whatever is already in the backbuffer/framebuffer that you're blending with.

'sourceFactor' and 'destFactor' are the ones you can control, via RenderState.SourceBlend and RenderState.DestinationBlend respectively.

Since you want lightmap * colourmap, we set 'sourceFactor' to be DestinationColor (this does the multiplication in the first half of the equation). Then we set the destFactor to Zero so that the right side of the equation has no effect. The final equation becomes:

finalPixelColour = (lightmapColour * framebuffer) + (framebuffer * 0)

HTH.

This topic is closed to new replies.

Advertisement