18
18
import com .badlogic .gdx .math .Vector3 ;
19
19
import com .badlogic .gdx .utils .Disposable ;
20
20
21
+ import com .badlogic .gdx .utils .TimeUtils ;
21
22
import org .jrenner .fps .entity .Entity ;
22
23
import org .jrenner .fps .graphics .EntityModel ;
23
24
import org .jrenner .fps .graphics .ModelManager ;
25
+ import org .jrenner .fps .net .packages .ChatMessage ;
24
26
import org .jrenner .fps .particles .Particles ;
25
27
26
28
public class View implements Disposable {
27
29
public static View inst ;
28
30
private GL20 gl ;
29
31
public static int width , height ;
30
32
private PerspectiveCamera camera ;
31
- private Environment environ ;
33
+ private Environment environ , basicEnviron ;
32
34
private PointLight camLight ;
33
35
private DirectionalLight dirLight ;
34
36
public HUD hud ;
@@ -39,8 +41,6 @@ public class View implements Disposable {
39
41
40
42
private DefaultShaderProvider shaderProvider ;
41
43
42
- private static final int MAX_POINTLIGHTS = 1 ;
43
- private static final int MAX_DIRECTIONAL_LIGHTS = 2 ;
44
44
45
45
private void initShaders () {
46
46
FileHandle vertexFile = Gdx .files .internal ("shaders/vertex.glsl" );
@@ -51,7 +51,8 @@ private void initShaders() {
51
51
shaderProvider .config .numDirectionalLights = 2 ;
52
52
53
53
54
- // I don't remember what I was doing with this but it seems like it could be useful later
54
+ // check shader compile logs
55
+
55
56
/*shader = new ShaderProgram(vertexFile, fragFile);
56
57
ShaderProgram.pedantic = false;
57
58
String log = shader.getLog();
@@ -69,18 +70,20 @@ public View() {
69
70
gl = Gdx .graphics .getGL20 ();
70
71
float fov = 67f ;
71
72
camera = new PerspectiveCamera (fov , width (), height ());
72
- camera .far = 50f ;
73
+ // camera.far affects frustrum culling, so a shorter distance can boost performance
74
+ camera .far = 60f ;
73
75
camera .near = 0.01f ;
74
76
resetCamera ();
75
77
76
78
initShaders ();
77
79
modelBatch = new ModelBatch (shaderProvider );
78
80
79
81
environ = new Environment ();
82
+ basicEnviron = new Environment ();
80
83
camLight = new PointLight ();
81
84
float intensity = 100f ;
82
85
camLight .set (new Color (0.2f , 0.2f , 0.2f , 1f ), 0f , 0f , 0f , intensity );
83
- ColorAttribute ambientLight = new ColorAttribute ( ColorAttribute . AmbientLight , new Color (0.1f , 0.1f , 0.1f , 1f ));
86
+ ColorAttribute ambientLight = ColorAttribute . createAmbient ( new Color (0.1f , 0.1f , 0.1f , 1f ));
84
87
environ .set (ambientLight );
85
88
ColorAttribute fog = new ColorAttribute (ColorAttribute .Fog );
86
89
fog .color .set (fogColor );
@@ -90,6 +93,8 @@ public View() {
90
93
dirLight .set (new Color (0.3f , 0.3f , 0.35f , 1f ), -0.25f , -0.75f , 0.25f );
91
94
environ .add (dirLight );
92
95
96
+ basicEnviron .set (ColorAttribute .createAmbient (0.3f , 0.3f , 0.3f , 1f ));
97
+
93
98
if (Toggleable .profileGL ()) {
94
99
Profiler .enable ();
95
100
}
@@ -117,7 +122,50 @@ private void updateCamera() {
117
122
camera .update ();
118
123
}
119
124
125
+ long lastSwitch = -1 ;
126
+ RollingArray renderTimes = new RollingArray ();
127
+ RollingArray hudTimes = new RollingArray ();
128
+ RollingArray entityTimes = new RollingArray ();
129
+ RollingArray staticTimes = new RollingArray ();
130
+ RollingArray boxTimes = new RollingArray ();
131
+ RollingArray skyTimes = new RollingArray ();
132
+ RollingArray groundTimes = new RollingArray ();
133
+
134
+ private void debugRenderTimes () {
135
+ // tied in with the profileGL toggleable for now
136
+ long now = TimeUtils .millis ();
137
+ long passed = now - lastSwitch ;
138
+ if (passed >= 1000 || lastSwitch < 0 ) {
139
+ float totalTime = renderTimes .getAverage ();
140
+ float hudTime = hudTimes .getAverage ();
141
+ float entityTime = entityTimes .getAverage ();
142
+ float staticTime = staticTimes .getAverage ();
143
+ float boxTime = boxTimes .getAverage ();
144
+ float skyTime = skyTimes .getAverage ();
145
+ float groundTime = groundTimes .getAverage ();
146
+ renderTimes .clear ();
147
+ hudTimes .clear ();
148
+ entityTimes .clear ();
149
+ staticTimes .clear ();
150
+ boxTimes .clear ();
151
+ skyTimes .clear ();
152
+ groundTimes .clear ();
153
+ lastSwitch = now ;
154
+ String text = String .format ("render-times(ms), total: %.1f, hud: %.1f, entity: %.1f, static: %.1f\n " +
155
+ " boxes: %.1f, sky: %.1f, ground: %.1f" ,
156
+ totalTime , hudTime , entityTime , staticTime , boxTime , skyTime , groundTime );
157
+ Main .inst .client .sendChatMessage (new ChatMessage (text ));
158
+ Log .debug (text );
159
+ }
160
+ }
161
+
162
+ boolean debugRenderPerformance = false ;
163
+
120
164
public void render () {
165
+ if (debugRenderPerformance ) {
166
+ debugRenderTimes ();
167
+ }
168
+ long start = TimeUtils .millis ();
121
169
boolean profileGL = Toggleable .profileGL ();
122
170
updateLights ();
123
171
if (profileGL ) {
@@ -128,42 +176,56 @@ public void render() {
128
176
gl .glClear (GL20 .GL_COLOR_BUFFER_BIT | GL20 .GL_DEPTH_BUFFER_BIT );
129
177
camera .up .set (Vector3 .Y );
130
178
updateCamera ();
131
- updateSky ();
132
179
180
+ long skyStart = TimeUtils .millis ();
181
+ updateSky ();
133
182
modelBatch .begin (camera );
134
183
if (Sky .isEnabled ()) {
135
184
modelBatch .render (Sky .modelInstance );
136
185
}
186
+ skyTimes .add ((int ) TimeUtils .timeSinceMillis (skyStart ));
137
187
138
188
// includes 3d models and billboards
189
+ long entityStart = TimeUtils .millis ();
190
+ visibleEntities = 0 ;
139
191
for (EntityModel entityModel : EntityModel .list ) {
140
192
entityModel .update ();
141
193
// don't draw self when in FPS mode
142
194
if (!entityModel .isClientEntity () || Toggleable .freeCamera ()) {
143
- modelBatch .render (entityModel .modelInstance , environ );
195
+ if (entityVisibilityCheck (entityModel )) {
196
+ visibleEntities ++;
197
+ modelBatch .render (entityModel .modelInstance , environ );
198
+ }
144
199
}
145
200
}
201
+ entityTimes .add ((int ) TimeUtils .timeSinceMillis (entityStart ));
202
+
203
+ long boxStart = TimeUtils .millis ();
146
204
if (Box .instance != null ) {
147
205
modelBatch .render (Box .instance , environ );
148
206
}
207
+ boxTimes .add ((int ) TimeUtils .timeSinceMillis (boxStart ));
208
+
209
+ long staticStart = TimeUtils .millis ();
149
210
if (LevelBuilder .staticGeometry != null ) {
150
211
for (ModelInstance staticGeo : LevelBuilder .staticGeometry ) {
151
212
modelBatch .render (staticGeo , environ );
152
213
}
153
214
}
215
+ staticTimes .add ((int ) TimeUtils .timeSinceMillis (staticStart ));
154
216
155
- totalGroundPieces = 0 ;
217
+ long groundStart = TimeUtils . millis () ;
156
218
visibleGroundPieces = 0 ;
157
219
for (ModelInstance groundPiece : LevelBuilder .groundPieces ) {
158
- totalGroundPieces ++;
159
220
if (groundPieceVisibilityCheck (groundPiece )) {
160
221
visibleGroundPieces ++;
161
222
modelBatch .render (groundPiece , environ );
162
223
}
163
224
}
225
+ groundTimes .add ((int ) TimeUtils .timeSinceMillis (groundStart ));
164
226
modelBatch .end ();
165
227
166
- // draw particle effects in a separate batch to make depth testing work correctly
228
+ // draw particle effects in a separate batch to make depth testing work better
167
229
modelBatch .begin (camera );
168
230
for (Shadow shadow : Shadow .list ) {
169
231
modelBatch .render (shadow .modelInstance , environ );
@@ -179,7 +241,13 @@ public void render() {
179
241
Physics .inst .debugDraw ();
180
242
}
181
243
244
+ long hudStart = TimeUtils .millis ();
182
245
hud .draw ();
246
+ long hudTime = TimeUtils .timeSinceMillis (hudStart );
247
+ hudTimes .add ((int ) hudTime );
248
+
249
+ long time = TimeUtils .timeSinceMillis (start );
250
+ renderTimes .add ((int ) time );
183
251
}
184
252
185
253
private void drawParticleEffects () {
@@ -287,18 +355,25 @@ public void storeSize() {
287
355
height = Gdx .graphics .getHeight ();
288
356
}
289
357
290
- public static int totalGroundPieces ;
291
358
public static int visibleGroundPieces ;
292
359
private boolean groundPieceVisibilityCheck (ModelInstance modelInst ) {
293
360
float halfWidth = LevelBuilder .groundPieceSize / 2f ;
294
361
modelInst .transform .getTranslation (tmp );
295
362
// we want the center of the piece
296
363
tmp .add (halfWidth , 0 , halfWidth );
364
+ float radius = LevelBuilder .groundPieceSize ;
297
365
return camera .frustum .sphereInFrustum (tmp , LevelBuilder .groundPieceSize );
298
366
// this naive method is useful for debugging to see pop-in/pop-out
299
367
//return camera.frustum.pointInFrustum(tmp);
300
368
}
301
369
370
+ public static int visibleEntities ;
371
+ private boolean entityVisibilityCheck (EntityModel entModel ) {
372
+ entModel .modelInstance .transform .getTranslation (tmp );
373
+ float radius = entModel .entity .getRadius ();
374
+ return camera .frustum .sphereInFrustum (tmp , radius );
375
+ }
376
+
302
377
@ Override
303
378
public void dispose () {
304
379
Tools .dispose (modelBatch );
0 commit comments