B20. Muovere l'acqua
L'effetto fresnel è completo, le increspature ci sono. Manca solo un po' di movimento. Il codice che segue è preso dal solito sito a cui faccio riferimento: per questa volta non l'ho scritto io, anche perchè il principio su cui si basa è lo stesso e alcuni passaggi rimangono un po' oscuri. In sostanza, presi in input il tempo passato dall'inizio del gioco, la direzione del vento e la sua forza, muove l'acqua di conseguenza. Ecco il codice modificato del file shader:
E ora si modifica anche il codice xna:float Time;float WindForce;float3 WindDirection;//... WaterVertexToPixel WaterVertexShader(float4 inPos :POSITIO ,float2 inTex:TEXCOORD ) {WaterVertexToPixel Output = (WaterVertexToPixel )0;float4x4 ViewProjection = mul(View, Projection);float4x4 WorldViewProjection = mul(World, ViewProjection);float4x4 ReflectionViewProjection = mul(ReflectionView, Projection);float4x4 WorldReflectionViewProjection = mul(World, ReflectionViewProjection); Output.Position = mul(inPos, WorldViewProjection); Output.ReflectionPos = mul(inPos, WorldReflectionViewProjection); Output.RefractionPos = mul(inPos, WorldViewProjection);//Normalizza la direzione float3 windDir = normalize(WindDirection);//Calcola la perpendicolare alla direzione del vento float3 perpDir = cross(WindDirection, float3(0,1,0));//Ottiene le componenti x e y del vettore risultante float ydot = dot(inTex, WindDirection.xz);float xdot = dot(inTex, perpDir.xz);float2 moveVector = float2(xdot, ydot);//Aumenta la componente y di un fattore pari a Time * WindForce. //Questo è il passaggio più importante e, volendo, //si potrebbe usare solo questo tralasciando ciò che //viene prima. Più WindForce è grande, maggiore //sarà lo spostamento compiuto dall'acqua in un //secondo. moveVector.y += Time * WindForce;//Imposta le coordinate della bump map Output.BumpPos = (moveVector) / WaveLength; Output.PointPosition = mul(inPos, World);return Output; }
'Non dimenticate di passare al metodo DrawWater il parametro corretto:... Private Sub DrawWater(ByVal TimeAs Single ) Shader.CurrentTechnique = Shader.Techniques("Water") Shader.Parameters("View").SetValue(ViewMatrix) Shader.Parameters("Projection").SetValue(ProjectionMatrix) Shader.Parameters("World").SetValue(Matrix.Identity) Shader.Parameters("ReflectionView").SetValue(ReflectionViewMatrix) Shader.Parameters("RefractionMap").SetValue(RefractionMap) Shader.Parameters("ReflectionMap").SetValue(ReflectionMap) Shader.Parameters("BumpMap").SetValue(BumpMap) Shader.Parameters("WaveLength").SetValue(0.01F) Shader.Parameters("WaveHeight").SetValue(0.3F) Shader.Parameters("CameraPosition").SetValue(CameraPosition) 'Imposta i nuovi parametri Shader.Parameters("Time").SetValue(Time) Shader.Parameters("WindDirection").SetValue(New Vector3(0, 0, 1)) Shader.Parameters("WindForce").SetValue(0.0002F)Dim PrevAs CullMode =Me .GraphicsDevice.RenderState.CullModeMe .GraphicsDevice.RenderState.CullMode = CullMode.NoneMe .GraphicsDevice.Vertices(0).SetSource( _ WaterVBuffer, 0, VertexPositionTexture.SizeInBytes) Shader.Begin()For Each PassAs EffectPassIn Shader.CurrentTechnique.Passes Pass.Begin()With Me .GraphicsDevice .VertexDeclaration = WDeclarationMe .GraphicsDevice.DrawPrimitives( _ PrimitiveType.TriangleList, 0, WaterVertices.Length / 3)End With Pass.End()Next Shader.End()Me .GraphicsDevice.RenderState.CullMode = PrevEnd Sub '...
gameTime.TotalGameTime.TotalMilliseconds restituisce il numero totale di millisecondi passati dall'inizio del gioco. Il risultato che si dovrebbe ottenere è questo.Protected Overrides Sub Draw(ByVal gameTimeAs GameTime)Me .Graphics.GraphicsDevice.Clear(Color.CornflowerBlue) DrawRefractionMap() DrawReflectionMap() DrawSky(ViewMatrix) DrawTerrain(ViewMatrix) DrawWater(gameTime.TotalGameTime.TotalMilliseconds / 100.0F)My Base.Draw(gameTime)End Sub
Imports Microsoft.Xna.FrameworkImports Microsoft.Xna.Framework.InputImports Microsoft.Xna.Framework.GraphicsImports System.Runtime.InteropServicesPublic Class GameInherits Microsoft.Xna.Framework.Game#Region "Strutture aggiuntive"Private Shared DoubleSizeAs Byte = Marshal.SizeOf(GetType(Double ))Private Structure VertexPositionNormalColorPublic PositionAs Vector3Public NormalAs Vector3Public ColorAs ColorPublic Shared SizeInBytesAs Int16 = 7 * 4Public Shared VertexElements()As VertexElement =New VertexElement() _ { _New VertexElement(0, 0, VertexElementFormat.Vector3, _ VertexElementMethod.Default, _ VertexElementUsage.Position, 0), _New VertexElement(0, DoubleSize * 3, _ VertexElementFormat.Color, _ VertexElementMethod.Default, _ VertexElementUsage.Color, 0), _New VertexElement(0, DoubleSize * 4, _ VertexElementFormat.Vector3, _ VertexElementMethod.Default, _ VertexElementUsage.Normal, 0) _ }End Structure Private Structure VertexPositionNormalMultitexturePublic PositionAs Vector3Public NormalAs Vector3Public TextureCoordinateAs Vector4Public TextureWeightAs Vector4Public Shared SizeInBytesAs Int16 = (3 + 3 + 4 + 4) * 4Public Shared VertexElementsAs VertexElement() =New VertexElement() _ { _New VertexElement(0, 0, VertexElementFormat.Vector3, _ VertexElementMethod.Default, _ VertexElementUsage.Position, 0), _New VertexElement(0, 4 * 3, _ VertexElementFormat.Vector3, _ VertexElementMethod.Default, _ VertexElementUsage.Normal, 0), _New VertexElement(0, 4 * 6, _ VertexElementFormat.Vector4, _ VertexElementMethod.Default, _ VertexElementUsage.TextureCoordinate, 0), _New VertexElement(0, 4 * 10, _ VertexElementFormat.Vector4, _ VertexElementMethod.Default, _ VertexElementUsage.TextureCoordinate, 1) _ }End Structure Private Structure SkyCubeFacePublic Vertices()As VertexPositionTexturePublic Indices()As Int32Public TextureAs Texture2DEnd Structure #End Region #Region "Variabili globali"Private AppPathAs String = _My .Application.Info.DirectoryPathPrivate GraphicsAs GraphicsDeviceManager 'VERTICI, INDICI E BUFFER ------------------------ Private ShaderAs EffectPrivate Vertices()As VertexPositionNormalMultitexturePrivate Indices()As Int32Private VBufferAs VertexBufferPrivate IBufferAs IndexBufferPrivate VDeclarationAs VertexDeclarationPrivate SDeclarationAs VertexDeclarationPrivate WDeclarationAs VertexDeclaration 'MATRICI ----------------------------------------- Private ViewMatrixAs MatrixPrivate ProjectionMatrixAs MatrixPrivate WorldMatrixAs MatrixPrivate ReflectionViewMatrixAs Matrix 'HEIGHTDATA -------------------------------------- Private HeightData(,)As Single Private Const MinHeightAs Single = 0Private Const MaxHeightAs Single = 30Private TerrainWidth, TerrainLengthAs Int32 'TELECAMERA ------------------------------------- Private PrevMouseStateAs MouseStatePrivate LeftRightRotationAs Single = MathHelper.PiOver2Private UpDownRotationAs Single = -MathHelper.Pi / 10.0FPrivate CameraPositionAs Vector3Private RotationSpeedAs Single = 0.3Private MoveSpeedAs Single = 1 'TEXTURE ---------------------------------------- Private GrassAs Texture2DPrivate SandAs Texture2DPrivate RockAs Texture2DPrivate SnowAs Texture2D 'CIELO ------------------------------------------ Private SkyFaces(4)As Texture2DPrivate SkyCube(4)As SkyCubeFace 'ACQUA ------------------------------------------ Private WaterHeightAs Single = 5.0Private RefractionTargetAs RenderTarget2DPrivate RefractionMapAs Texture2DPrivate ReflectionTargetAs RenderTarget2DPrivate ReflectionMapAs Texture2DPrivate WaterVertices()As VertexPositionTexturePrivate WaterVBufferAs VertexBufferPrivate BumpMapAs Texture2D#End Region #Region "Funzioni utili"Private Function GetEffect(ByVal FileNameAs String )As EffectDim CompEffectAs CompiledEffect = _ Effect.CompileEffectFromFile(FileName, _ Nothing, Nothing, _ CompilerOptions.None, _ TargetPlatform.Windows)Return New Effect(Me .GraphicsDevice, _ CompEffect.GetEffectCode, _ CompilerOptions.None,Nothing )End Function Private Function GetTexture(ByVal FileNameAs String )Return Texture2D.FromFile(Me .GraphicsDevice, FileName)End Function #End Region #Region "Caricamento Heightmap"Private Sub LoadHeightMap(ByVal HeightMapAs Texture2D) TerrainWidth = HeightMap.Width TerrainLength = HeightMap.HeightDim Colors(TerrainWidth * TerrainLength - 1)As Color HeightMap.GetData(Colors)For IAs Int32 = 0To TerrainWidth - 1 ReDim HeightData(I, TerrainLength - 1)Next For XAs Int32 = 0To TerrainWidth - 1For ZAs Int32 = 0To TerrainLength - 1 HeightData(X, Z) = MinHeight + _ (Colors(X + Z * TerrainWidth).R / 255) * _ (MaxHeight - MinHeight)Next Next VDeclaration =New VertexDeclaration(Me .GraphicsDevice, _ VertexPositionNormalMultitexture.VertexElements)End Sub Private Sub SetVertices() ReDim Vertices(TerrainWidth * TerrainLength - 1)Dim StripAs Single = (MaxHeight - MinHeight) / 4For XAs Int32 = 0To TerrainWidth - 1For ZAs Int32 = 0To TerrainLength - 1With Vertices(X + Z * TerrainWidth)Dim YAs Single = HeightData(X, Z) .Position =New Vector3(X, Y, -Z) .TextureCoordinate.X = X / 32 .TextureCoordinate.Y = Z / 32 .TextureWeight.X = MathHelper.Clamp(1.0F - Math.Abs(Y - 0) / 8.0F, 0, 1) .TextureWeight.Y = MathHelper.Clamp(1.0F - Math.Abs(Y - 12) / 6.0F, 0, 1) .TextureWeight.Z = MathHelper.Clamp(1.0F - Math.Abs(Y - 20) / 6.0F, 0, 1) .TextureWeight.W = MathHelper.Clamp(1.0F - Math.Abs(Y - 30) / 6.0F, 0, 1)Dim TotalAs Single = .TextureWeight.X Total += .TextureWeight.Y Total += .TextureWeight.Z Total += .TextureWeight.W .TextureWeight.X /= Total .TextureWeight.Y /= Total .TextureWeight.Z /= Total .TextureWeight.W /= TotalEnd With Next Next End Sub Private Sub SetIndices() ReDim Indices((TerrainWidth - 1) * (TerrainLength - 1) * 6 - 1)Dim CounterAs Int32 = 0For XAs Int32 = 0To TerrainWidth - 2For ZAs Int32 = 0To TerrainLength - 2Dim LowerLeftAs Int16 = X + Z * TerrainWidthDim LowerRightAs Int16 = (X + 1) + Z * TerrainWidthDim TopLeftAs Int16 = X + (Z + 1) * TerrainWidthDim TopRightAs Int16 = (X + 1) + (Z + 1) * TerrainWidth Indices(Counter) = TopLeft Indices(Counter + 1) = LowerRight Indices(Counter + 2) = LowerLeft Counter += 3 Indices(Counter) = TopLeft Indices(Counter + 1) = TopRight Indices(Counter + 2) = LowerRight Counter += 3Next Next End Sub Private Sub SetNormals()For IAs Int32 = 0To Vertices.Length - 1 Vertices(I).Normal =New Vector3(0, 0, 0)Next For IAs Int16 = 0To (Indices.Length / 3) - 1Dim Index1As Int16 = Indices(I * 3)Dim Index2As Int16 = Indices(I * 3 + 1)Dim Index3As Int16 = Indices(I * 3 + 2)Dim Side1As Vector3 = _ Vertices(Index1).Position - Vertices(Index3).PositionDim Side2As Vector3 = _ Vertices(Index1).Position - Vertices(Index2).PositionDim NormalAs Vector3 = Vector3.Cross(Side1, Side2) Vertices(Index1).Normal += Normal Vertices(Index2).Normal += Normal Vertices(Index3).Normal += NormalNext For Each VAs VertexPositionNormalMultitextureIn Vertices V.Normal.Normalize()Next End Sub Private Sub CopyToBuffer() VBuffer =New VertexBuffer(Me .GraphicsDevice, _ Vertices.Length * VertexPositionNormalMultitexture.SizeInBytes, _ BufferUsage.WriteOnly) VBuffer.SetData(Vertices) IBuffer =New IndexBuffer(Me .GraphicsDevice, _ GetType(Int32), Indices.Length, BufferUsage.WriteOnly) IBuffer.SetData(Indices)Me .GraphicsDevice.Indices = IBufferMe .GraphicsDevice.Vertices(0).SetSource( _ VBuffer, 0, VertexPositionNormalMultitexture.SizeInBytes)End Sub #End Region #Region "Cielo"Private Function GetElements(Of T)(ByVal Sources()As T,ByVal ParamArray Indices()As Int32)As T()Dim Result(Indices.Length - 1)As TFor IAs Int16 = 0To Indices.Length - 1 Result(I) = Sources(Indices(I))Next Return ResultEnd Function Private Sub LoadSkyDome()Dim SkyVertices(7)As VertexPositionTextureDim HalfSizeAs Int16 = 200Dim HalfHeightAs Int16 = 150 SkyVertices(0).Position =New Vector3(-HalfSize, 200, HalfSize) SkyVertices(1).Position =New Vector3(-HalfSize, 200, -HalfSize) SkyVertices(2).Position =New Vector3(HalfSize, 200, HalfSize) SkyVertices(3).Position =New Vector3(HalfSize, 200, -HalfSize) SkyVertices(4).Position =New Vector3(-HalfSize, 0, HalfSize) SkyVertices(5).Position =New Vector3(-HalfSize, 0, -HalfSize) SkyVertices(6).Position =New Vector3(HalfSize, 0, HalfSize) SkyVertices(7).Position =New Vector3(HalfSize, 0, -HalfSize) SkyCube(0).Vertices = GetElements(SkyVertices, 0, 1, 2, 3) SkyCube(1).Vertices = GetElements(SkyVertices, 5, 1, 4, 0) SkyCube(2).Vertices = GetElements(SkyVertices, 4, 0, 6, 2) SkyCube(3).Vertices = GetElements(SkyVertices, 6, 2, 7, 3) SkyCube(4).Vertices = GetElements(SkyVertices, 7, 3, 5, 1)With SkyCube(0) .Indices =New Int32() {0, 1, 2, 2, 1, 3} .Texture = SkyFaces(0) .Vertices(0).TextureCoordinate =New Vector2(0, 1) .Vertices(1).TextureCoordinate =New Vector2(0, 0) .Vertices(2).TextureCoordinate =New Vector2(1, 1) .Vertices(3).TextureCoordinate =New Vector2(1, 0)End With For IAs Byte = 1To 4With SkyCube(I) .Indices =New Int32() {0, 1, 2, 2, 1, 3} .Texture = SkyFaces(I) .Vertices(0).TextureCoordinate =New Vector2(0, 0.5) .Vertices(1).TextureCoordinate =New Vector2(0, 0) .Vertices(2).TextureCoordinate =New Vector2(1, 0.5) .Vertices(3).TextureCoordinate =New Vector2(1, 0)End With Next SDeclaration =New VertexDeclaration(Me .GraphicsDevice, VertexPositionTexture.VertexElements)End Sub Private Sub DrawSky(ByVal ViewAs Matrix)Dim PrevAs CullMode =Me .GraphicsDevice.RenderState.CullModeMe .GraphicsDevice.RenderState.CullMode = CullMode.NoneFor IAs Byte = 0To 4 Shader.CurrentTechnique = Shader.Techniques("Textured") Shader.Parameters("View").SetValue(View) Shader.Parameters("Projection").SetValue(ProjectionMatrix) Shader.Parameters("World").SetValue(Matrix.Identity) Shader.Parameters("LightEnabled").SetValue(False) Shader.Parameters("ATexture").SetValue(SkyFaces(I)) Shader.Begin()For Each PassAs EffectPassIn Shader.CurrentTechnique.Passes Pass.Begin()With Me .GraphicsDevice .VertexDeclaration = SDeclaration .DrawUserIndexedPrimitives(PrimitiveType.TriangleList, SkyCube(I).Vertices, 0, SkyCube(I).Vertices.Length, SkyCube(I).Indices, 0, SkyCube(I).Indices.Length / 3)End With Pass.End()Next Shader.End()Next Me .GraphicsDevice.RenderState.CullMode = PrevEnd Sub #End Region #Region "Acqua"Private Function CreatePlane(ByVal HeightAs Single ,ByVal ViewAs Matrix, _ByVal NormalAs Vector3,ByVal ClipAboveAs Boolean ) Normal.Normalize()Dim PlaneCoefAs New Vector4(Normal, Height)Dim HSMatrixAs Matrix = _ Matrix.Transpose( _ Matrix.Invert(View * ProjectionMatrix))If ClipAboveThen PlaneCoef *= -1End If PlaneCoef = Vector4.Transform(PlaneCoef, HSMatrix)Return New Plane(PlaneCoef)End Function Private Sub DrawRefractionMap()Dim RefractionPlaneAs Plane = _ CreatePlane(WaterHeight + 1.5F, ViewMatrix,New Vector3(0, -1, 0), False)Me .GraphicsDevice.ClipPlanes(0).Plane = RefractionPlaneMe .GraphicsDevice.ClipPlanes(0).IsEnabled = TrueMe .GraphicsDevice.SetRenderTarget(0, RefractionTarget)Me .GraphicsDevice.Clear(ClearOptions.TargetOr ClearOptions.DepthBuffer, Color.Black, 1.0F, 0) DrawTerrain(ViewMatrix)Me .GraphicsDevice.ClipPlanes(0).IsEnabled = FalseMe .GraphicsDevice.SetRenderTarget(0,Nothing ) RefractionMap = RefractionTarget.GetTexture()Me .GraphicsDevice.Clear(Color.CornflowerBlue)End Sub Private Sub DrawReflectionMap()Dim RotationAs Matrix = _ Matrix.CreateRotationX(UpDownRotation) * _ Matrix.CreateRotationY(LeftRightRotation)Dim ForwardAs New Vector3(0, 0, -1)Dim RightAs New Vector3(1, 0, 0)Dim TargetPosAs Vector3 = _ CameraPosition + Vector3.Transform(Forward, Rotation)Dim ReflectionPosAs Vector3 = CameraPositionDim ReflectionTargetPosAs Vector3 = TargetPos ReflectionPos.Y = 2 * WaterHeight - ReflectionPos.Y ReflectionTargetPos.Y = 2 * WaterHeight - ReflectionTargetPos.YDim ReflectionUpAs Vector3 = Vector3.Cross( _ Vector3.Transform(Right, Rotation), ReflectionTargetPos - ReflectionPos) ReflectionViewMatrix = Matrix.CreateLookAt( _ ReflectionPos, ReflectionTargetPos, ReflectionUp)Dim ReflectionPlaneAs Plane = _ CreatePlane(WaterHeight - 0.5F, ReflectionViewMatrix,New Vector3(0, -1, 0), True)Me .GraphicsDevice.ClipPlanes(0).Plane = ReflectionPlaneMe .GraphicsDevice.ClipPlanes(0).IsEnabled = TrueMe .GraphicsDevice.SetRenderTarget(0, ReflectionTarget)Me .GraphicsDevice.Clear(ClearOptions.TargetOr _ ClearOptions.DepthBuffer, Color.Black, 1.0F, 0) DrawTerrain(ReflectionViewMatrix) DrawSky(ReflectionViewMatrix)Me .GraphicsDevice.ClipPlanes(0).IsEnabled = FalseMe .GraphicsDevice.SetRenderTarget(0,Nothing ) ReflectionMap = ReflectionTarget.GetTexture()Me .GraphicsDevice.Clear(Color.CornflowerBlue)End Sub Private Sub SetWaterVertices() ReDim WaterVertices(5)Dim HalfSizeAs Int16 = 400 WaterVertices(0).Position =New Vector3(-HalfSize, WaterHeight, HalfSize) WaterVertices(1).Position =New Vector3(-HalfSize, WaterHeight, -HalfSize) WaterVertices(2).Position =New Vector3(HalfSize, WaterHeight, HalfSize) WaterVertices(3).Position =New Vector3(HalfSize, WaterHeight, HalfSize) WaterVertices(4).Position =New Vector3(-HalfSize, WaterHeight, -HalfSize) WaterVertices(5).Position =New Vector3(HalfSize, WaterHeight, -HalfSize) WaterVertices(0).TextureCoordinate =New Vector2(0, 1) WaterVertices(1).TextureCoordinate =New Vector2(0, 0) WaterVertices(2).TextureCoordinate =New Vector2(1, 1) WaterVertices(3).TextureCoordinate =New Vector2(1, 1) WaterVertices(4).TextureCoordinate =New Vector2(0, 0) WaterVertices(5).TextureCoordinate =New Vector2(1, 0) WaterVBuffer =New VertexBuffer(Me .GraphicsDevice, _ WaterVertices.Length * VertexPositionTexture.SizeInBytes, _ BufferUsage.WriteOnly) WaterVBuffer.SetData(WaterVertices) WDeclaration =New VertexDeclaration(Me .GraphicsDevice, VertexPositionTexture.VertexElements)End Sub Private Sub DrawWater(ByVal TimeAs Single ) Shader.CurrentTechnique = Shader.Techniques("Water") Shader.Parameters("View").SetValue(ViewMatrix) Shader.Parameters("Projection").SetValue(ProjectionMatrix) Shader.Parameters("World").SetValue(Matrix.Identity) Shader.Parameters("ReflectionView").SetValue(ReflectionViewMatrix) Shader.Parameters("RefractionMap").SetValue(RefractionMap) Shader.Parameters("ReflectionMap").SetValue(ReflectionMap) Shader.Parameters("BumpMap").SetValue(BumpMap) Shader.Parameters("WaveLength").SetValue(0.01F) Shader.Parameters("WaveHeight").SetValue(0.3F) Shader.Parameters("CameraPosition").SetValue(CameraPosition) Shader.Parameters("Time").SetValue(Time) Shader.Parameters("WindDirection").SetValue(New Vector3(0, 0, 1)) Shader.Parameters("WindForce").SetValue(0.0002F)Dim PrevAs CullMode =Me .GraphicsDevice.RenderState.CullModeMe .GraphicsDevice.RenderState.CullMode = CullMode.NoneMe .GraphicsDevice.Vertices(0).SetSource( _ WaterVBuffer, 0, VertexPositionTexture.SizeInBytes) Shader.Begin()For Each PassAs EffectPassIn Shader.CurrentTechnique.Passes Pass.Begin()With Me .GraphicsDevice .VertexDeclaration = WDeclarationMe .GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, WaterVertices.Length / 3)End With Pass.End()Next Shader.End()Me .GraphicsDevice.RenderState.CullMode = PrevEnd Sub #End Region #Region "Gestione telecamera"Private Sub ProcessMouseInput(ByVal ElapsedTimeAs Single )Dim CurrentMouseStateAs MouseState = Mouse.GetStateIf CurrentMouseState <> PrevMouseStateThen Dim DXAs Single = _ CurrentMouseState.X - PrevMouseState.XDim DYAs Single = _ CurrentMouseState.Y - PrevMouseState.Y LeftRightRotation -= DX * RotationSpeed * ElapsedTime UpDownRotation -= DY * RotationSpeed * ElapsedTime Mouse.SetPosition(Me .GraphicsDevice.Viewport.Width / 2, _Me .GraphicsDevice.Viewport.Height / 2) UpdateView()End If End Sub Private Sub ProcessKeyboardInput()Dim MotionAs New Vector3(0, 0, 0)Dim KeyStateAs KeyboardState = Keyboard.GetStateIf KeyState.IsKeyDown(Keys.W)Then Motion +=New Vector3(0, 0, -1)End If If KeyState.IsKeyDown(Keys.S)Then Motion +=New Vector3(0, 0, 1)End If If KeyState.IsKeyDown(Keys.D)Then Motion +=New Vector3(1, 0, 0)End If If KeyState.IsKeyDown(Keys.A)Then Motion +=New Vector3(-1, 0, 0)End If If KeyState.IsKeyDown(Keys.Up)Then Motion +=New Vector3(0, 1, 0)End If If KeyState.IsKeyDown(Keys.Down)Then Motion +=New Vector3(0, -1, 0)End If UpdatePosition(Motion)End Sub Private Sub UpdateView()Dim RotationAs Matrix = _ Matrix.CreateRotationX(UpDownRotation) * _ Matrix.CreateRotationY(LeftRightRotation)Dim ForwardAs New Vector3(0, 0, -1)Dim UpAs New Vector3(0, 1, 0)Dim RotForwardAs Vector3 = _ Vector3.Transform(Forward, Rotation)Dim RotUpAs Vector3 = Vector3.Transform(Up, Rotation)Dim TargetAs Vector3 = CameraPosition + RotForward ViewMatrix = Matrix.CreateLookAt(CameraPosition, Target, RotUp)End Sub Private Sub UpdatePosition(ByVal MotionAs Vector3)Dim RotationAs Matrix = _ Matrix.CreateRotationX(UpDownRotation) * _ Matrix.CreateRotationY(LeftRightRotation)Dim RotMotionAs Vector3 = Vector3.Transform(Motion, Rotation) CameraPosition += RotMotion * MoveSpeed UpdateView()End Sub #End Region #Region "Gestione risorse"Sub New ()Me .Graphics =New GraphicsDeviceManager(Me )Me .Content.RootDirectory = "content"End Sub Protected Overrides Sub Initialize()My Base.Initialize()End Sub Protected Overrides Sub LoadContent() Shader = GetEffect(AppPath & "\SimpleShader.fx") Grass = GetTexture(AppPath & "\grass.dds") Sand = GetTexture(AppPath & "\sand.dds") Rock = GetTexture(AppPath & "\rock.dds") Snow = GetTexture(AppPath & "\snow.dds") BumpMap = GetTexture(AppPath & "\BumpMap.jpg")For IAs Byte = 0To 4 SkyFaces(I) = GetTexture(AppPath & "\skyface" & (I + 1) & ".png")Next Dim ParamsAs PresentationParameters = _Me .GraphicsDevice.PresentationParameters RefractionTarget =New RenderTarget2D(Me .GraphicsDevice, _ Params.BackBufferWidth, Params.BackBufferHeight, 1, _Me .GraphicsDevice.DisplayMode.Format) ReflectionTarget =New RenderTarget2D(Me .GraphicsDevice, _ Params.BackBufferWidth, Params.BackBufferHeight, 1, _Me .GraphicsDevice.DisplayMode.Format) LoadHeightMap(GetTexture(AppPath & "\HeightMap.bmp")) LoadSkyDome() SetVertices() SetIndices() SetNormals() SetWaterVertices() CopyToBuffer() ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView( _ MathHelper.PiOver4, _Me .GraphicsDevice.Viewport.AspectRatio, _ 1, 1000) CameraPosition =New Vector3(0, 40, TerrainLength / 2) Mouse.SetPosition(Me .GraphicsDevice.Viewport.Width / 2, _Me .GraphicsDevice.Viewport.Height / 2) PrevMouseState = Mouse.GetState UpdateView()My Base.LoadContent()End Sub Protected Overrides Sub UnloadContent()My Base.UnloadContent()End Sub #End Region #Region "Aggiornamento mondo 3D"Private Sub DrawTerrain(ByVal ViewAs Matrix) Shader.CurrentTechnique = Shader.Techniques("MultiTextured") Shader.Parameters("View").SetValue(View) Shader.Parameters("Projection").SetValue(ProjectionMatrix) Shader.Parameters("World").SetValue( _ Matrix.CreateTranslation( _New Vector3(-TerrainWidth / 2, 0, TerrainLength / 2)))Dim LightDirectionAs New Vector3(27.73, -17.67, 6.14) LightDirection.Normalize() Shader.Parameters("LightEnabled").SetValue(True) Shader.Parameters("LightDirection").SetValue(LightDirection) Shader.Parameters("AmbientFactor").SetValue(0.3F) Shader.Parameters("Texture0").SetValue(Sand) Shader.Parameters("Texture1").SetValue(Grass) Shader.Parameters("Texture2").SetValue(Rock) Shader.Parameters("Texture3").SetValue(Snow)Me .GraphicsDevice.Indices = IBufferMe .GraphicsDevice.Vertices(0).SetSource( _ VBuffer, 0, VertexPositionNormalMultitexture.SizeInBytes) Shader.Begin()For Each PassAs EffectPassIn Shader.CurrentTechnique.Passes Pass.Begin()With Me .GraphicsDevice .VertexDeclaration = VDeclarationMe .GraphicsDevice.DrawIndexedPrimitives( _ PrimitiveType.TriangleList, 0, 0, _ Vertices.Length, 0, Indices.Length / 3)End With Pass.End()Next Shader.End()End Sub Protected Overrides Sub Update(ByVal GameTimeAs GameTime) ProcessMouseInput(GameTime.ElapsedGameTime.TotalSeconds) ProcessKeyboardInput()Dim kAs KeyboardState = Keyboard.GetStateIf k.IsKeyDown(Keys.M)Then ReflectionMap.Save("prova.jpg", ImageFileFormat.Jpg)Me .Exit()End If My Base.Update(GameTime)End Sub Protected Overrides Sub Draw(ByVal gameTimeAs GameTime)Me .Graphics.GraphicsDevice.Clear(Color.CornflowerBlue) DrawRefractionMap() DrawReflectionMap() DrawSky(ViewMatrix) DrawTerrain(ViewMatrix) DrawWater(gameTime.TotalGameTime.TotalMilliseconds / 100.0F)My Base.Draw(gameTime)End Sub #End Region End Class
struct VertexToPixel
{
float4 Position : POSITION;
float4 Color : COLOR0;
float LightingFactor : TEXCOORD0;
float2 TextureCoords : TEXCOORD1;
};
struct PixelToFrame
{
float4 Color : COLOR0;
};
float4x4 View;
float4x4 Projection;
float4x4 World;
float3 LightDirection;
float AmbientFactor;
bool LightEnabled;
texture ATexture;
sampler TextureSampler = sampler_state
{
Texture = ;
Magfilter = Linear;
Minfilter = Linear;
Mipfilter = Linear;
AddressU = Mirror;
AddressV = Mirror;
};
//--------------------------------------------
//Tecnica 1 : Colore
//--------------------------------------------
VertexToPixel ColoredVertexShader(float4 inPos : POSITION, float4 inColor: COLOR)
{
VertexToPixel Output = (VertexToPixel)0;
float4x4 ViewProjection = mul(View, Projection);
float4x4 WorldViewProjection = mul(World, ViewProjection);
Output.Position = mul(inPos, WorldViewProjection);
Output.Color = inColor;
return Output;
}
PixelToFrame ColoredPixelShader(VertexToPixel inPixel)
{
PixelToFrame Output = (PixelToFrame)0;
Output.Color = inPixel.Color;
return Output;
}
technique Colored
{
pass Pass0
{
VertexShader = compile vs_1_1 ColoredVertexShader();
PixelShader = compile ps_1_1 ColoredPixelShader();
}
}
//--------------------------------------------
//Tecnica 2 : Colore + Luce
//--------------------------------------------
VertexToPixel ColoredPlusVertexShader(float4 inPos : POSITION, float4 inColor: COLOR, float3 inNormal: NORMAL)
{
VertexToPixel Output = (VertexToPixel)0;
float4x4 ViewProjection = mul(View, Projection);
float4x4 WorldViewProjection = mul(World, ViewProjection);
Output.Position = mul(inPos, WorldViewProjection);
Output.Color = inColor;
Output.LightingFactor = 1;
if (LightEnabled)
{
float3 Normal = normalize(mul(normalize(inNormal), World));
Output.LightingFactor = saturate(dot(Normal, -LightDirection));
}
return Output;
}
PixelToFrame ColoredPlusPixelShader(VertexToPixel inPixel)
{
PixelToFrame Output = (PixelToFrame)0;
Output.Color = inPixel.Color;
Output.Color.rgb *= saturate(inPixel.LightingFactor + AmbientFactor);
return Output;
}
technique ColoredPlus
{
pass Pass0
{
VertexShader = compile vs_1_1 ColoredPlusVertexShader();
PixelShader = compile ps_1_1 ColoredPlusPixelShader();
}
}
//--------------------------------------------
//Tecnica 3 : Textured
//--------------------------------------------
VertexToPixel TexturedVertexShader(float4 inPos : POSITION, float3 inNormal: NORMAL, float2 inTexCoords: TEXCOORD0)
{
VertexToPixel Output = (VertexToPixel)0;
float4x4 ViewProjection = mul (View, Projection);
float4x4 WorldViewProjection = mul (World, ViewProjection);
Output.Position = mul(inPos, WorldViewProjection);
Output.TextureCoords = inTexCoords;
Output.LightingFactor = 1;
if (LightEnabled)
{
float3 Normal = normalize(mul(normalize(inNormal), World));
Output.LightingFactor = saturate(dot(Normal, -LightDirection));
}
return Output;
}
PixelToFrame TexturedPixelShader(VertexToPixel inPixel)
{
PixelToFrame Output = (PixelToFrame)0;
Output.Color = tex2D(TextureSampler, inPixel.TextureCoords);
Output.Color.rgb *= saturate(inPixel.LightingFactor + AmbientFactor);
return Output;
}
technique Textured
{
pass Pass0
{
VertexShader = compile vs_1_1 TexturedVertexShader();
PixelShader = compile ps_1_1 TexturedPixelShader();
}
}
//--------------------------------------------
//Tecnica 4 : MultiTextured
//--------------------------------------------
struct MultiVertexToPixel
{
float4 Position : POSITION;
float4 Color : COLOR0;
float3 Normal : TEXCOORD0;
float2 TextureCoords : TEXCOORD1;
float4 LightDirection : TEXCOORD2;
float4 TextureWeights : TEXCOORD3;
float Depth : TEXCOORD4;
};
struct MultiPixelToFrame
{
float4 Color : COLOR0;
};
Texture Texture0;
Texture Texture1;
Texture Texture2;
Texture Texture3;
sampler TextureSampler0 = sampler_state
{
Texture = ;
Magfilter = Linear;
Minfilter = Linear;
Mipfilter = Linear;
AddressU = Wrap;
AddressV = Wrap;
};
sampler TextureSampler1 = sampler_state
{
Texture = ;
Magfilter = Linear;
Minfilter = Linear;
Mipfilter = Linear;
AddressU = Wrap;
AddressV = Wrap;
};
sampler TextureSampler2 = sampler_state
{
Texture = ;
Magfilter = Linear;
Minfilter = Linear;
Mipfilter = Linear;
AddressU = Mirror;
AddressV = Mirror;
};
sampler TextureSampler3 = sampler_state
{
Texture = ;
Magfilter = Linear;
Minfilter = Linear;
Mipfilter = Linear;
AddressU = Mirror;
AddressV = Mirror;
};
MultiVertexToPixel MultiTexturedVertexShader(float4 inPos : POSITION, float3 inNormal: NORMAL, float4 inTexCoords: TEXCOORD0, float4 inTexWeights: TEXCOORD1)
{
MultiVertexToPixel Output = (MultiVertexToPixel)0;
float4x4 ViewProjection = mul(View, Projection);
float4x4 WorldViewProjection = mul(World, ViewProjection);
Output.Position = mul(inPos, WorldViewProjection);
Output.Normal = mul(normalize(inNormal), World);
Output.TextureCoords = inTexCoords;
Output.LightDirection.xyz = -LightDirection;
Output.LightDirection.w = 1;
Output.TextureWeights = inTexWeights;
Output.Depth = Output.Position.z / Output.Position.w;
return Output;
}
MultiPixelToFrame MultiTexturedPixelShader(MultiVertexToPixel inPixel)
{
MultiPixelToFrame Output = (MultiPixelToFrame)0;
float lightingFactor = 1;
if (LightEnabled)
lightingFactor = saturate(saturate(dot(inPixel.Normal, inPixel.LightDirection)) + AmbientFactor);
float blendDistance = 0.99f;
float blendWidth = 0.005f;
float blendFactor = clamp((inPixel.Depth - blendDistance) / blendWidth, 0, 1);
float4 farColor;
farColor = tex2D(TextureSampler0, inPixel.TextureCoords) * inPixel.TextureWeights.x;
farColor += tex2D(TextureSampler1, inPixel.TextureCoords) * inPixel.TextureWeights.y;
farColor += tex2D(TextureSampler2, inPixel.TextureCoords) * inPixel.TextureWeights.z;
farColor += tex2D(TextureSampler3, inPixel.TextureCoords) * inPixel.TextureWeights.w;
float4 nearColor;
float2 nearTextureCoords = inPixel.TextureCoords * 3;
nearColor = tex2D(TextureSampler0, nearTextureCoords) * inPixel.TextureWeights.x;
nearColor += tex2D(TextureSampler1, nearTextureCoords) * inPixel.TextureWeights.y;
nearColor += tex2D(TextureSampler2, nearTextureCoords) * inPixel.TextureWeights.z;
nearColor += tex2D(TextureSampler3, nearTextureCoords) * inPixel.TextureWeights.w;
Output.Color = lerp(nearColor, farColor, blendFactor);
Output.Color *= lightingFactor;
return Output;
}
technique MultiTextured
{
pass Pass0
{
VertexShader = compile vs_2_0 MultiTexturedVertexShader();
PixelShader = compile ps_2_0 MultiTexturedPixelShader();
}
}
//--------------------------------------------
//Tecnica 5 : Acqua
//--------------------------------------------
float4x4 ReflectionView;
Texture ReflectionMap;
Texture RefractionMap;
Texture BumpMap;
float WaveLength;
float WaveHeight;
float3 CameraPosition;
float Time;
float WindForce;
float3 WindDirection;
sampler ReflectionSampler = sampler_state
{
texture = ;
Magfilter = Linear;
Minfilter = Linear;
Mipfilter = Linear;
AddressU = Mirror;
AddressV = Mirror;
};
sampler RefractionSampler = sampler_state
{
texture = ;
Magfilter = Linear;
Minfilter = Linear;
Mipfilter = Linear;
AddressU = Mirror;
AddressV = Mirror;
};
sampler BumpSampler = sampler_state
{
texture = ;
Magfilter = Linear;
Minfilter = Linear;
Mipfilter = Linear;
AddressU = mirror;
AddressV = mirror;
};
struct WaterVertexToPixel
{
float4 Position : POSITION;
float4 ReflectionPos : TEXCOORD1;
float2 BumpPos : TEXCOORD2;
float4 RefractionPos : TEXCOORD3;
float4 PointPosition : TEXCOORD4;
};
struct WaterPixelToFrame
{
float4 Color : COLOR0;
};
WaterVertexToPixel WaterVertexShader(float4 inPos : POSITION, float2 inTex: TEXCOORD)
{
WaterVertexToPixel Output = (WaterVertexToPixel)0;
float4x4 ViewProjection = mul(View, Projection);
float4x4 WorldViewProjection = mul(World, ViewProjection);
float4x4 ReflectionViewProjection = mul(ReflectionView, Projection);
float4x4 WorldReflectionViewProjection = mul(World, ReflectionViewProjection);
Output.Position = mul(inPos, WorldViewProjection);
Output.ReflectionPos = mul(inPos, WorldReflectionViewProjection);
Output.RefractionPos = mul(inPos, WorldViewProjection);
float3 windDir = normalize(WindDirection);
float3 perpDir = cross(WindDirection, float3(0,1,0));
float ydot = dot(inTex, WindDirection.xz);
float xdot = dot(inTex, perpDir.xz);
float2 moveVector = float2(xdot, ydot);
moveVector.y += Time * WindForce;
Output.BumpPos = (moveVector) / WaveLength;
Output.PointPosition = mul(inPos, World);
return Output;
}
WaterPixelToFrame WaterPixelShader(WaterVertexToPixel inPixel)
{
WaterPixelToFrame Output = (WaterPixelToFrame)0;
float2 TexCoords;
TexCoords.x = (inPixel.ReflectionPos.x / inPixel.ReflectionPos.w) / 2.0f + 0.5f;
TexCoords.y = -(inPixel.ReflectionPos.y / inPixel.ReflectionPos.w) / 2.0f + 0.5f;
float4 BumpColor = tex2D(BumpSampler, inPixel.BumpPos);
float2 Perturbation = WaveHeight * (BumpColor.rg - 0.5f) * 2.0f;
float2 NewTexCoords = TexCoords + Perturbation;
float4 ReflectionColor = tex2D(ReflectionSampler, NewTexCoords);
float2 RefractionTexCoords;
RefractionTexCoords.x = (inPixel.RefractionPos.x / inPixel.RefractionPos.w) / 2.0f + 0.5f;
RefractionTexCoords.y = -(inPixel.RefractionPos.y / inPixel.RefractionPos.w) / 2.0f + 0.5f;
float2 RefractionNewTexCoords = RefractionTexCoords + Perturbation;
float4 RefractionColor = tex2D(RefractionSampler, RefractionNewTexCoords);
float3 Vector = normalize(CameraPosition - inPixel.PointPosition);
float3 Normal = float3(0, 1, 0);
float FresnelFactor = dot(Vector, Normal);
float4 Result = lerp(ReflectionColor, RefractionColor, FresnelFactor);
float4 WaterColor = float4(0.35f, 0.35f, 0.55f, 0.9f);
Output.Color = lerp(Result, WaterColor, 0.15f);
return Output;
}
technique Water
{
pass Pass0
{
VertexShader = compile vs_2_0 WaterVertexShader();
PixelShader = compile ps_2_0 WaterPixelShader();
}
} The Totem's Lair - Copyright (C) 2009
È vietata la riproduzione sia totale che parziale del sito.



