Thursday, December 08, 2005

update

Task list for today:

  • a Seperate RenderToSurface code into a seperate class
  • r Add Environment mapping
    This task is not a high priority, so I'll do it later when the required items are in place and working
  • a Add support for effect files into my DX9_RenderMesh class
    Not quite completed, but a working prototype acheieved


Seperate RenderToSurface code

I've seperated the RenderToSurface code blocks into a seperate class. This class is give at the end of this blog (Appendix A).

To create the class one would write:
---
'Create the class, set the pos and size of the surface
cRts = New DX9_RenderToSurface(160, 120, New Size(160, 120))

'setup the view matrix - if this isn't done then, it just uses the current view settings
cRts .ViewMatrix = Matrix.LookAtLH(New Vector3(0, 2.5, -7), _
New Vector3(0, 0, 0), New Vector3(0, 1, 0))

'change the backcolour from the default DarkBlue
cRts .BackColour = Color.Green
---

In the Levels PreRender sub I now have:
---
cRts .StartRenderIntoSurface()
Draw(True) '<-- internal to the class
cRts .EndRenderIntoSurface()
---

This took me about 2 hours to do, I'm now a little bored of programing for the moment, so I'm off to do something different I might go watch a movie or read one of my Rob Grant books.




Add Environment mapping

I decided not to do this today. I've added the task to my to do list, but I made it a medium priority as it's not vital for the basic functionality of the game.

Add support for effect files

I've got the effect files working. From looking at other code it originally looked like it would be fairly easy to implement. However the need to set values for items in the fx file such as time, WorldView or WorldViewProjection, which is those matrices multiplied together, made it difficult at first.

multipying the matrices like this works:

---
worldViewProj = Matrix.Multiply(worldViewProj, mW)
worldViewProj = Matrix.Multiply(worldViewProj, mV)
worldViewProj = Matrix.Multiply(worldViewProj, mP)
---

However the following will not:

---
worldViewProj = Matrix.Multiply( mW, worldViewProj)
worldViewProj = Matrix.Multiply( mV, worldViewProj)
worldViewProj = Matrix.Multiply( mP, worldViewProj)
---

At the moment before I render my mesh I'm having to set the "effect values" and then begin the effect. This is obviously not a good way to do it, because the "effect values" will change depending on the effect being used.
e.g. The glow.fx requires "WorldView" and "Projection" variables to be set whereas the simple.fx requires "WorldViewProj" to be set.

At the moment I'm thinking I rather:

  • Seperate out the effect into a seperate class
  • Just set these values once when the effect is created and trap errors, errors are thrown when one tries to set the value of a variable that doesn't exist in an effect file. However that wouldn't work for all effects, as some need the "time" variable to be constanly changing.
  • Find a way to detect what type the variables are (PROJECTION, WORLD, VIEW WORLDVIEW, WORLDVIEWPROJECTION, TIME, etc)

Effects can apply their effect to a mesh using different techniques. The reason being, that some cards won't support certain features and so one can choose the effects' technique most suited to a particular card. At the moment I'm setting the effect technique to use manually, by specifying it in a string. I'm not concerned about this yet because I know there is a way to get the first technique in the file, but I can't remember what the call is. I think I read it on the ToyMaker site somewhere, I just need to read the pages again.


Before the effect was implemented


After the glow.fx effect was implemented






Appendix A

My DX9_RenderToSurface Class - handles drawing to a surface

Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
'at the moment this class is dependant on the DX9_Sprite
' it may be good to cut this class out, and have the DX9_RenderToSurface class
' handle the sprite rendering that way it's all contained.
Public Class DX9_RenderToSurface
'Render to surface vars
Private RenderSurfaceSize As Size '= New Size(160, 120)
Private renderTexture As Texture = Nothing
Private rts As RenderToSurface = Nothing
Private renderSurface As Surface = Nothing
Private spriteSurfaceToRender As DX9_Sprite
Private SurfacePosition As Point
#Region "Public Properties"
Public Active As Boolean = True
Public ProjectionMatrix As Matrix = Nothing
Public ViewMatrix As Matrix = Nothing
Public BackColour As Drawing.Color = Color.DarkBlue
Public ReadOnly Property Texture() As Texture
Get
Return renderTexture
End Get
End Property
Public Property X() As Single
Get
Return SurfacePosition.X
End Get
Set(ByVal Value As Single)
SurfacePosition.X = Value
End Set
End Property
Public Property Y() As Single
Get
Return SurfacePosition.Y
End Get
Set(ByVal Value As Single)
SurfacePosition.Y = Value
End Set
End Property
Public Property Width() As Single
Get
Return RenderSurfaceSize.Width()
End Get
Set(ByVal Value As Single)
RenderSurfaceSize.Width = Value
'recreate the surfaces
InitSurfaces()
End Set
End Property
Public Property Height() As Single
Get
Return RenderSurfaceSize.Height()
End Get
Set(ByVal Value As Single)
RenderSurfaceSize.Height = Value
'recreate the surfaces
InitSurfaces()
End Set
End Property
#End Region
'Setting the ViewMatrix or ProjectionMatrix to Matrix.identity will
' cause them not to be set during render, i.e. it will use the current
' View and Projection settings.
Public Sub New(ByVal x As Single, ByVal y As Single, ByVal SurfaceSize As Drawing.Size)
RenderSurfaceSize = New Size(SurfaceSize.Width, SurfaceSize.Height)
SurfacePosition = New Point(x, y)
InitSurfaces()
'
'default matrices
ProjectionMatrix = Matrix.Identity
ViewMatrix = Matrix.Identity
End Sub
Sub InitSurfaces()
'create surface to render into
rts = New RenderToSurface(d3dDevice, RenderSurfaceSize.Width, RenderSurfaceSize.Height, _
Format.X8R8G8B8, True, DepthFormat.D16)
renderTexture = New Texture(d3dDevice, RenderSurfaceSize.Width, RenderSurfaceSize.Height, 1, _
Usage.RenderTarget, Format.X8R8G8B8, Pool.Default)
renderSurface = renderTexture.GetSurfaceLevel(0)

If Not spriteSurfaceToRender Is Nothing Then spriteSurfaceToRender.Dispose()
spriteSurfaceToRender = New DX9_Sprite(renderTexture, New Vector2(SurfacePosition.X, SurfacePosition.Y), RenderSurfaceSize)
End Sub

'These will render the scene to a surface.
' The actual rendering of the scene must be done by another class
#Region "StartRenderIntoSurface, EndRenderIntoSurface"
'This sub will begin the rendering to a surface, after this sub
' finishes, the calling class will have to render the scene
' and then cal EndRenderIntoSurface to finish it off.
Public Sub StartRenderIntoSurface()
If Not Active Then Exit Sub
' Render to this surface
Dim view As Viewport = New Viewport()
view.Width = RenderSurfaceSize.Width
view.Height = RenderSurfaceSize.Height
view.MaxZ = 1.0F
rts.BeginScene(renderSurface, view)
'clear
d3dDevice.Clear(ClearFlags.Target Or ClearFlags.ZBuffer, BackColour, 1.0F, 0)
'setup the view
If Not ProjectionMatrix.Equals(ProjectionMatrix.Identity) Then d3dDevice.Transform.Projection = ProjectionMatrix
If Not ViewMatrix.Equals(ViewMatrix.Identity) Then d3dDevice.Transform.View = ViewMatrix
End Sub
Public Sub EndRenderIntoSurface()
If Not Active Then Exit Sub
rts.EndScene(Filter.None)
End Sub
#End Region
'This renders the textured surface (sprite) to the screen
Public Sub RenderSurfaceToScreen()
If Not Active Then Exit Sub
'todo:record renderstate before changing
d3dDevice.RenderState.AlphaBlendEnable = False
spriteSurfaceToRender.Render()
End Sub

'The all important Dispose method.
Public Sub Dispose()
renderTexture.Dispose()
rts.Dispose()
renderSurface.Dispose()
spriteSurfaceToRender.Dispose()
End Sub
End Class

0 Comments:

Post a Comment

<< Home


___