Client LuaCsForBarotrauma
WaterRenderer.cs
1 using Microsoft.Xna.Framework;
2 using Microsoft.Xna.Framework.Graphics;
3 using System;
4 using System.Collections.Generic;
5 
6 namespace Barotrauma
7 {
9  {
13  float WaterAlpha;
14 
15  public WaterVertexData(float distortStrengthX, float distortStrengthY, float waterColorStrength, float waterAlpha)
16  {
17  DistortStrengthX = distortStrengthX;
18  DistortStrengthY = distortStrengthY;
19  WaterColorStrength = waterColorStrength;
20  WaterAlpha = waterAlpha;
21  }
22 
23  public static implicit operator Color(WaterVertexData wd)
24  {
25  return new Color(wd.DistortStrengthX, wd.DistortStrengthY, wd.WaterColorStrength, wd.WaterAlpha);
26  }
27  }
28 
29  class WaterRenderer : IDisposable
30  {
31  public static WaterRenderer Instance;
32 
33  public const int DefaultBufferSize = 2000;
34  public const int DefaultIndoorsBufferSize = 3000;
35 
36  public static Vector2 DistortionScale = new Vector2(2f, 1.5f);
37  public static Vector2 DistortionStrength = new Vector2(0.01f, 0.33f);
38  public static float BlurAmount = 0.0f;
39 
40  public Vector2 WavePos
41  {
42  get;
43  private set;
44  }
45 
46  public readonly Color waterColor = new Color(0.75f * 0.5f, 0.8f * 0.5f, 0.9f * 0.5f, 1.0f);
47 
48  public readonly WaterVertexData IndoorsWaterColor = new WaterVertexData(0.1f, 0.1f, 0.5f, 1.0f);
49  public readonly WaterVertexData IndoorsSurfaceTopColor = new WaterVertexData(0.5f, 0.5f, 0.0f, 1.0f);
50  public readonly WaterVertexData IndoorsSurfaceBottomColor = new WaterVertexData(0.2f, 0.1f, 0.9f, 1.0f);
51 
52  public VertexPositionTexture[] vertices = new VertexPositionTexture[DefaultBufferSize];
53  public Dictionary<EntityGrid, VertexPositionColorTexture[]> IndoorsVertices = new Dictionary<EntityGrid, VertexPositionColorTexture[]>();
54 
55  public Effect WaterEffect
56  {
57  get;
58  private set;
59  }
60  private BasicEffect basicEffect;
61 
62  public int PositionInBuffer = 0;
63  public Dictionary<EntityGrid, int> PositionInIndoorsBuffer = new Dictionary<EntityGrid, int>();
64 
65  public Texture2D WaterTexture { get; }
66 
67  public WaterRenderer(GraphicsDevice graphicsDevice)
68  {
69  WaterEffect = EffectLoader.Load("Effects/watershader");
70 
71  WaterTexture = TextureLoader.FromFile("Content/Effects/waterbump.png");
72  WaterEffect.Parameters["xWaterBumpMap"].SetValue(WaterTexture);
73  WaterEffect.Parameters["waterColor"].SetValue(waterColor.ToVector4());
74 
75  if (basicEffect == null)
76  {
77  basicEffect = new BasicEffect(GameMain.Instance.GraphicsDevice)
78  {
79  VertexColorEnabled = false,
80  TextureEnabled = true
81  };
82  }
83  }
84 
85  private readonly VertexPositionColorTexture[] tempVertices = new VertexPositionColorTexture[6];
86  private readonly Vector3[] tempCorners = new Vector3[4];
87 
88  public void RenderWater(SpriteBatch spriteBatch, RenderTarget2D texture, Camera cam)
89  {
90  spriteBatch.GraphicsDevice.BlendState = BlendState.NonPremultiplied;
91 
92  WaterEffect.Parameters["xTexture"].SetValue(texture);
93  Vector2 distortionStrength = cam == null ? DistortionStrength : DistortionStrength * cam.Zoom;
94  WaterEffect.Parameters["xWaveWidth"].SetValue(distortionStrength.X);
95  WaterEffect.Parameters["xWaveHeight"].SetValue(distortionStrength.Y);
96  if (BlurAmount > 0.0f)
97  {
98  WaterEffect.CurrentTechnique = WaterEffect.Techniques["WaterShaderBlurred"];
99  WaterEffect.Parameters["xBlurDistance"].SetValue(BlurAmount / 100.0f);
100  }
101  else
102  {
103  WaterEffect.CurrentTechnique = WaterEffect.Techniques["WaterShader"];
104  }
105 
106  Vector2 offset = WavePos;
107  if (cam != null)
108  {
109  offset += (cam.Position - new Vector2(cam.WorldView.Width / 2.0f, -cam.WorldView.Height / 2.0f));
110  offset.Y += cam.WorldView.Height;
111  offset.X += cam.WorldView.Width;
112 #if LINUX || OSX
113  offset.X += cam.WorldView.Width;
114 #endif
115  offset *= DistortionScale;
116  }
117  offset.Y = -offset.Y;
118  WaterEffect.Parameters["xUvOffset"].SetValue(new Vector2((offset.X / GameMain.GraphicsWidth) % 1.0f, (offset.Y / GameMain.GraphicsHeight) % 1.0f));
119  WaterEffect.Parameters["xBumpPos"].SetValue(Vector2.Zero);
120 
121  if (cam != null)
122  {
123  WaterEffect.Parameters["xBumpScale"].SetValue(new Vector2(
124  (float)cam.WorldView.Width / GameMain.GraphicsWidth * DistortionScale.X,
125  (float)cam.WorldView.Height / GameMain.GraphicsHeight * DistortionScale.Y));
126  WaterEffect.Parameters["xTransform"].SetValue(cam.ShaderTransform
127  * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f);
128  WaterEffect.Parameters["xUvTransform"].SetValue(cam.ShaderTransform
129  * Matrix.CreateOrthographicOffCenter(0, spriteBatch.GraphicsDevice.Viewport.Width * 2, spriteBatch.GraphicsDevice.Viewport.Height * 2, 0, 0, 1) * Matrix.CreateTranslation(0.5f, 0.5f, 0.0f));
130  }
131  else
132  {
133  WaterEffect.Parameters["xBumpScale"].SetValue(new Vector2(1.0f, 1.0f));
134  WaterEffect.Parameters["xTransform"].SetValue(Matrix.Identity * Matrix.CreateTranslation(-1.0f, 1.0f, 0.0f));
135  WaterEffect.Parameters["xUvTransform"].SetValue(Matrix.CreateScale(0.5f, -0.5f, 0.0f));
136  }
137 
138  WaterEffect.CurrentTechnique.Passes[0].Apply();
139 
140  Rectangle view = cam != null ? cam.WorldView : spriteBatch.GraphicsDevice.Viewport.Bounds;
141 
142  tempCorners[0] = new Vector3(view.X, view.Y, 0.1f);
143  tempCorners[1] = new Vector3(view.Right, view.Y, 0.1f);
144  tempCorners[2] = new Vector3(view.Right, view.Y - view.Height, 0.1f);
145  tempCorners[3] = new Vector3(view.X, view.Y - view.Height, 0.1f);
146 
147  WaterVertexData backGroundColor = new WaterVertexData(0.1f, 0.1f, 0.5f, 1.0f);
148  tempVertices[0] = new VertexPositionColorTexture(tempCorners[0], backGroundColor, Vector2.Zero);
149  tempVertices[1] = new VertexPositionColorTexture(tempCorners[1], backGroundColor, Vector2.Zero);
150  tempVertices[2] = new VertexPositionColorTexture(tempCorners[2], backGroundColor, Vector2.Zero);
151  tempVertices[3] = new VertexPositionColorTexture(tempCorners[0], backGroundColor, Vector2.Zero);
152  tempVertices[4] = new VertexPositionColorTexture(tempCorners[2], backGroundColor, Vector2.Zero);
153  tempVertices[5] = new VertexPositionColorTexture(tempCorners[3], backGroundColor, Vector2.Zero);
154 
155  spriteBatch.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, tempVertices, 0, 2);
156 
157  foreach (KeyValuePair<EntityGrid, VertexPositionColorTexture[]> subVerts in IndoorsVertices)
158  {
159  if (!PositionInIndoorsBuffer.ContainsKey(subVerts.Key) || PositionInIndoorsBuffer[subVerts.Key] == 0) { continue; }
160 
161  offset = WavePos;
162  if (subVerts.Key.Submarine != null) { offset -= subVerts.Key.Submarine.WorldPosition; }
163  if (cam != null)
164  {
165  offset += cam.Position - new Vector2(cam.WorldView.Width / 2.0f, -cam.WorldView.Height / 2.0f);
166  offset.Y += cam.WorldView.Height;
167  offset.X += cam.WorldView.Width;
168  offset *= DistortionScale;
169  }
170  offset.Y = -offset.Y;
171  WaterEffect.Parameters["xUvOffset"].SetValue(new Vector2((offset.X / GameMain.GraphicsWidth) % 1.0f, (offset.Y / GameMain.GraphicsHeight) % 1.0f));
172 
173  WaterEffect.CurrentTechnique.Passes[0].Apply();
174 
175  spriteBatch.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, subVerts.Value, 0, PositionInIndoorsBuffer[subVerts.Key] / 3);
176  }
177 
178  WaterEffect.Parameters["xTexture"].SetValue((Texture2D)null);
179  WaterEffect.CurrentTechnique.Passes[0].Apply();
180  }
181 
182  public void ScrollWater(Vector2 vel, float deltaTime)
183  {
184  WavePos = WavePos - vel * deltaTime;
185  }
186 
187  public void RenderAir(GraphicsDevice graphicsDevice, Camera cam, RenderTarget2D texture, Matrix transform)
188  {
189  if (vertices == null || vertices.Length < 0 || PositionInBuffer <= 0) return;
190 
191  basicEffect.Texture = texture;
192 
193  basicEffect.View = Matrix.Identity;
194  basicEffect.World = transform
195  * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f * Matrix.CreateTranslation(0.0f,0.0f,0f);
196  basicEffect.CurrentTechnique.Passes[0].Apply();
197 
198  graphicsDevice.SamplerStates[0] = SamplerState.PointWrap;
199  graphicsDevice.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, vertices, 0, PositionInBuffer / 3);
200 
201  basicEffect.Texture = null;
202  basicEffect.CurrentTechnique.Passes[0].Apply();
203  }
204 
205  private readonly List<EntityGrid> buffersToRemove = new List<EntityGrid>();
206  public void ResetBuffers()
207  {
208  PositionInBuffer = 0;
209  PositionInIndoorsBuffer.Clear();
210  buffersToRemove.Clear();
211  foreach (var buffer in IndoorsVertices.Keys)
212  {
213  if (buffer.Submarine?.Removed ?? false)
214  {
215  buffersToRemove.Add(buffer);
216  }
217  }
218  foreach (var bufferToRemove in buffersToRemove)
219  {
220  IndoorsVertices.Remove(bufferToRemove);
221  }
222  }
223 
224  public void Dispose()
225  {
226  if (WaterEffect != null)
227  {
228  WaterEffect.Dispose();
229  WaterEffect = null;
230  }
231 
232  if (basicEffect != null)
233  {
234  basicEffect.Dispose();
235  basicEffect = null;
236  }
237  }
238  }
239 }
float? Zoom
Definition: Camera.cs:78
Vector2 Position
Definition: Camera.cs:398
Rectangle WorldView
Definition: Camera.cs:123
Matrix ShaderTransform
Definition: Camera.cs:141
static int GraphicsWidth
Definition: GameMain.cs:162
static int GraphicsHeight
Definition: GameMain.cs:168
static GameMain Instance
Definition: GameMain.cs:144
void RenderAir(GraphicsDevice graphicsDevice, Camera cam, RenderTarget2D texture, Matrix transform)
const int DefaultIndoorsBufferSize
VertexPositionTexture[] vertices
readonly WaterVertexData IndoorsSurfaceBottomColor
WaterRenderer(GraphicsDevice graphicsDevice)
void ScrollWater(Vector2 vel, float deltaTime)
void RenderWater(SpriteBatch spriteBatch, RenderTarget2D texture, Camera cam)
static Vector2 DistortionStrength
static Vector2 DistortionScale
Dictionary< EntityGrid, int > PositionInIndoorsBuffer
static WaterRenderer Instance
readonly Color waterColor
Dictionary< EntityGrid, VertexPositionColorTexture[]> IndoorsVertices
readonly WaterVertexData IndoorsWaterColor
readonly WaterVertexData IndoorsSurfaceTopColor
WaterVertexData(float distortStrengthX, float distortStrengthY, float waterColorStrength, float waterAlpha)