1 /******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.graphics.g3d.shaders; 18 19 import com.badlogic.gdx.Gdx; 20 import com.badlogic.gdx.graphics.Camera; 21 import com.badlogic.gdx.graphics.GL20; 22 import com.badlogic.gdx.graphics.VertexAttribute; 23 import com.badlogic.gdx.graphics.VertexAttributes.Usage; 24 import com.badlogic.gdx.graphics.g3d.Attribute; 25 import com.badlogic.gdx.graphics.g3d.Attributes; 26 import com.badlogic.gdx.graphics.g3d.Environment; 27 import com.badlogic.gdx.graphics.g3d.Renderable; 28 import com.badlogic.gdx.graphics.g3d.Shader; 29 import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute; 30 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute; 31 import com.badlogic.gdx.graphics.g3d.attributes.CubemapAttribute; 32 import com.badlogic.gdx.graphics.g3d.attributes.DepthTestAttribute; 33 import com.badlogic.gdx.graphics.g3d.attributes.DirectionalLightsAttribute; 34 import com.badlogic.gdx.graphics.g3d.attributes.FloatAttribute; 35 import com.badlogic.gdx.graphics.g3d.attributes.IntAttribute; 36 import com.badlogic.gdx.graphics.g3d.attributes.PointLightsAttribute; 37 import com.badlogic.gdx.graphics.g3d.attributes.SpotLightsAttribute; 38 import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute; 39 import com.badlogic.gdx.graphics.g3d.environment.AmbientCubemap; 40 import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight; 41 import com.badlogic.gdx.graphics.g3d.environment.PointLight; 42 import com.badlogic.gdx.graphics.g3d.environment.SpotLight; 43 import com.badlogic.gdx.graphics.g3d.utils.RenderContext; 44 import com.badlogic.gdx.graphics.glutils.ShaderProgram; 45 import com.badlogic.gdx.math.Matrix3; 46 import com.badlogic.gdx.math.Matrix4; 47 import com.badlogic.gdx.math.Vector3; 48 import com.badlogic.gdx.utils.Array; 49 import com.badlogic.gdx.utils.GdxRuntimeException; 50 51 public class DefaultShader extends BaseShader { 52 public static class Config { 53 /** The uber vertex shader to use, null to use the default vertex shader. */ 54 public String vertexShader = null; 55 /** The uber fragment shader to use, null to use the default fragment shader. */ 56 public String fragmentShader = null; 57 /** The number of directional lights to use */ 58 public int numDirectionalLights = 2; 59 /** The number of point lights to use */ 60 public int numPointLights = 5; 61 /** The number of spot lights to use */ 62 public int numSpotLights = 0; 63 /** The number of bones to use */ 64 public int numBones = 12; 65 /** */ 66 public boolean ignoreUnimplemented = true; 67 /** Set to 0 to disable culling, -1 to inherit from {@link DefaultShader#defaultCullFace} */ 68 public int defaultCullFace = -1; 69 /** Set to 0 to disable depth test, -1 to inherit from {@link DefaultShader#defaultDepthFunc} */ 70 public int defaultDepthFunc = -1; 71 Config()72 public Config () { 73 } 74 Config(final String vertexShader, final String fragmentShader)75 public Config (final String vertexShader, final String fragmentShader) { 76 this.vertexShader = vertexShader; 77 this.fragmentShader = fragmentShader; 78 } 79 } 80 81 public static class Inputs { 82 public final static Uniform projTrans = new Uniform("u_projTrans"); 83 public final static Uniform viewTrans = new Uniform("u_viewTrans"); 84 public final static Uniform projViewTrans = new Uniform("u_projViewTrans"); 85 public final static Uniform cameraPosition = new Uniform("u_cameraPosition"); 86 public final static Uniform cameraDirection = new Uniform("u_cameraDirection"); 87 public final static Uniform cameraUp = new Uniform("u_cameraUp"); 88 public final static Uniform cameraNearFar = new Uniform("u_cameraNearFar"); 89 90 public final static Uniform worldTrans = new Uniform("u_worldTrans"); 91 public final static Uniform viewWorldTrans = new Uniform("u_viewWorldTrans"); 92 public final static Uniform projViewWorldTrans = new Uniform("u_projViewWorldTrans"); 93 public final static Uniform normalMatrix = new Uniform("u_normalMatrix"); 94 public final static Uniform bones = new Uniform("u_bones"); 95 96 public final static Uniform shininess = new Uniform("u_shininess", FloatAttribute.Shininess); 97 public final static Uniform opacity = new Uniform("u_opacity", BlendingAttribute.Type); 98 public final static Uniform diffuseColor = new Uniform("u_diffuseColor", ColorAttribute.Diffuse); 99 public final static Uniform diffuseTexture = new Uniform("u_diffuseTexture", TextureAttribute.Diffuse); 100 public final static Uniform diffuseUVTransform = new Uniform("u_diffuseUVTransform", TextureAttribute.Diffuse); 101 public final static Uniform specularColor = new Uniform("u_specularColor", ColorAttribute.Specular); 102 public final static Uniform specularTexture = new Uniform("u_specularTexture", TextureAttribute.Specular); 103 public final static Uniform specularUVTransform = new Uniform("u_specularUVTransform", TextureAttribute.Specular); 104 public final static Uniform emissiveColor = new Uniform("u_emissiveColor", ColorAttribute.Emissive); 105 public final static Uniform emissiveTexture = new Uniform("u_emissiveTexture", TextureAttribute.Emissive); 106 public final static Uniform emissiveUVTransform = new Uniform("u_emissiveUVTransform", TextureAttribute.Emissive); 107 public final static Uniform reflectionColor = new Uniform("u_reflectionColor", ColorAttribute.Reflection); 108 public final static Uniform reflectionTexture = new Uniform("u_reflectionTexture", TextureAttribute.Reflection); 109 public final static Uniform reflectionUVTransform = new Uniform("u_reflectionUVTransform", TextureAttribute.Reflection); 110 public final static Uniform normalTexture = new Uniform("u_normalTexture", TextureAttribute.Normal); 111 public final static Uniform normalUVTransform = new Uniform("u_normalUVTransform", TextureAttribute.Normal); 112 public final static Uniform ambientTexture = new Uniform("u_ambientTexture", TextureAttribute.Ambient); 113 public final static Uniform ambientUVTransform = new Uniform("u_ambientUVTransform", TextureAttribute.Ambient); 114 public final static Uniform alphaTest = new Uniform("u_alphaTest"); 115 116 public final static Uniform ambientCube = new Uniform("u_ambientCubemap"); 117 public final static Uniform dirLights = new Uniform("u_dirLights"); 118 public final static Uniform pointLights = new Uniform("u_pointLights"); 119 public final static Uniform spotLights = new Uniform("u_spotLights"); 120 public final static Uniform environmentCubemap = new Uniform("u_environmentCubemap"); 121 } 122 123 public static class Setters { 124 public final static Setter projTrans = new GlobalSetter() { 125 @Override 126 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 127 shader.set(inputID, shader.camera.projection); 128 } 129 }; 130 public final static Setter viewTrans = new GlobalSetter() { 131 @Override 132 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 133 shader.set(inputID, shader.camera.view); 134 } 135 }; 136 public final static Setter projViewTrans = new GlobalSetter() { 137 @Override 138 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 139 shader.set(inputID, shader.camera.combined); 140 } 141 }; 142 public final static Setter cameraPosition = new GlobalSetter() { 143 @Override 144 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 145 shader.set(inputID, shader.camera.position.x, shader.camera.position.y, shader.camera.position.z, 146 1.1881f / (shader.camera.far * shader.camera.far)); 147 } 148 }; 149 public final static Setter cameraDirection = new GlobalSetter() { 150 @Override 151 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 152 shader.set(inputID, shader.camera.direction); 153 } 154 }; 155 public final static Setter cameraUp = new GlobalSetter() { 156 @Override 157 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 158 shader.set(inputID, shader.camera.up); 159 } 160 }; 161 public final static Setter cameraNearFar = new GlobalSetter() { 162 @Override 163 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 164 shader.set(inputID, shader.camera.near, shader.camera.far); 165 } 166 }; 167 public final static Setter worldTrans = new LocalSetter() { 168 @Override 169 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 170 shader.set(inputID, renderable.worldTransform); 171 } 172 }; 173 public final static Setter viewWorldTrans = new LocalSetter() { 174 final Matrix4 temp = new Matrix4(); 175 176 @Override 177 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 178 shader.set(inputID, temp.set(shader.camera.view).mul(renderable.worldTransform)); 179 } 180 }; 181 public final static Setter projViewWorldTrans = new LocalSetter() { 182 final Matrix4 temp = new Matrix4(); 183 184 @Override 185 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 186 shader.set(inputID, temp.set(shader.camera.combined).mul(renderable.worldTransform)); 187 } 188 }; 189 public final static Setter normalMatrix = new LocalSetter() { 190 private final Matrix3 tmpM = new Matrix3(); 191 192 @Override 193 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 194 shader.set(inputID, tmpM.set(renderable.worldTransform).inv().transpose()); 195 } 196 }; 197 198 public static class Bones extends LocalSetter { 199 private final static Matrix4 idtMatrix = new Matrix4(); 200 public final float bones[]; 201 Bones(final int numBones)202 public Bones (final int numBones) { 203 this.bones = new float[numBones * 16]; 204 } 205 206 @Override set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes)207 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 208 for (int i = 0; i < bones.length; i++) { 209 final int idx = i / 16; 210 bones[i] = (renderable.bones == null || idx >= renderable.bones.length || renderable.bones[idx] == null) ? idtMatrix.val[i % 16] 211 : renderable.bones[idx].val[i % 16]; 212 } 213 shader.program.setUniformMatrix4fv(shader.loc(inputID), bones, 0, bones.length); 214 } 215 } 216 217 public final static Setter shininess = new LocalSetter() { 218 @Override 219 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 220 shader.set(inputID, ((FloatAttribute)(combinedAttributes.get(FloatAttribute.Shininess))).value); 221 } 222 }; 223 public final static Setter diffuseColor = new LocalSetter() { 224 @Override 225 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 226 shader.set(inputID, ((ColorAttribute)(combinedAttributes.get(ColorAttribute.Diffuse))).color); 227 } 228 }; 229 public final static Setter diffuseTexture = new LocalSetter() { 230 @Override 231 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 232 final int unit = shader.context.textureBinder.bind(((TextureAttribute)(combinedAttributes 233 .get(TextureAttribute.Diffuse))).textureDescription); 234 shader.set(inputID, unit); 235 } 236 }; 237 public final static Setter diffuseUVTransform = new LocalSetter() { 238 @Override 239 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 240 final TextureAttribute ta = (TextureAttribute)(combinedAttributes.get(TextureAttribute.Diffuse)); 241 shader.set(inputID, ta.offsetU, ta.offsetV, ta.scaleU, ta.scaleV); 242 } 243 }; 244 public final static Setter specularColor = new LocalSetter() { 245 @Override 246 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 247 shader.set(inputID, ((ColorAttribute)(combinedAttributes.get(ColorAttribute.Specular))).color); 248 } 249 }; 250 public final static Setter specularTexture = new LocalSetter() { 251 @Override 252 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 253 final int unit = shader.context.textureBinder.bind(((TextureAttribute)(combinedAttributes 254 .get(TextureAttribute.Specular))).textureDescription); 255 shader.set(inputID, unit); 256 } 257 }; 258 public final static Setter specularUVTransform = new LocalSetter() { 259 @Override 260 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 261 final TextureAttribute ta = (TextureAttribute)(combinedAttributes.get(TextureAttribute.Specular)); 262 shader.set(inputID, ta.offsetU, ta.offsetV, ta.scaleU, ta.scaleV); 263 } 264 }; 265 public final static Setter emissiveColor = new LocalSetter() { 266 @Override 267 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 268 shader.set(inputID, ((ColorAttribute)(combinedAttributes.get(ColorAttribute.Emissive))).color); 269 } 270 }; 271 public final static Setter emissiveTexture = new LocalSetter() { 272 @Override 273 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 274 final int unit = shader.context.textureBinder.bind(((TextureAttribute)(combinedAttributes 275 .get(TextureAttribute.Emissive))).textureDescription); 276 shader.set(inputID, unit); 277 } 278 }; 279 public final static Setter emissiveUVTransform = new LocalSetter() { 280 @Override 281 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 282 final TextureAttribute ta = (TextureAttribute)(combinedAttributes.get(TextureAttribute.Emissive)); 283 shader.set(inputID, ta.offsetU, ta.offsetV, ta.scaleU, ta.scaleV); 284 } 285 }; 286 public final static Setter reflectionColor = new LocalSetter() { 287 @Override 288 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 289 shader.set(inputID, ((ColorAttribute)(combinedAttributes.get(ColorAttribute.Reflection))).color); 290 } 291 }; 292 public final static Setter reflectionTexture = new LocalSetter() { 293 @Override 294 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 295 final int unit = shader.context.textureBinder.bind(((TextureAttribute)(combinedAttributes 296 .get(TextureAttribute.Reflection))).textureDescription); 297 shader.set(inputID, unit); 298 } 299 }; 300 public final static Setter reflectionUVTransform = new LocalSetter() { 301 @Override 302 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 303 final TextureAttribute ta = (TextureAttribute)(combinedAttributes.get(TextureAttribute.Reflection)); 304 shader.set(inputID, ta.offsetU, ta.offsetV, ta.scaleU, ta.scaleV); 305 } 306 }; 307 public final static Setter normalTexture = new LocalSetter() { 308 @Override 309 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 310 final int unit = shader.context.textureBinder.bind(((TextureAttribute)(combinedAttributes 311 .get(TextureAttribute.Normal))).textureDescription); 312 shader.set(inputID, unit); 313 } 314 }; 315 public final static Setter normalUVTransform = new LocalSetter() { 316 @Override 317 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 318 final TextureAttribute ta = (TextureAttribute)(combinedAttributes.get(TextureAttribute.Normal)); 319 shader.set(inputID, ta.offsetU, ta.offsetV, ta.scaleU, ta.scaleV); 320 } 321 }; 322 public final static Setter ambientTexture = new LocalSetter() { 323 @Override 324 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 325 final int unit = shader.context.textureBinder.bind(((TextureAttribute)(combinedAttributes 326 .get(TextureAttribute.Ambient))).textureDescription); 327 shader.set(inputID, unit); 328 } 329 }; 330 public final static Setter ambientUVTransform = new LocalSetter() { 331 @Override 332 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 333 final TextureAttribute ta = (TextureAttribute)(combinedAttributes.get(TextureAttribute.Ambient)); 334 shader.set(inputID, ta.offsetU, ta.offsetV, ta.scaleU, ta.scaleV); 335 } 336 }; 337 338 public static class ACubemap extends LocalSetter { 339 private final static float ones[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; 340 private final AmbientCubemap cacheAmbientCubemap = new AmbientCubemap(); 341 private final static Vector3 tmpV1 = new Vector3(); 342 public final int dirLightsOffset; 343 public final int pointLightsOffset; 344 ACubemap(final int dirLightsOffset, final int pointLightsOffset)345 public ACubemap (final int dirLightsOffset, final int pointLightsOffset) { 346 this.dirLightsOffset = dirLightsOffset; 347 this.pointLightsOffset = pointLightsOffset; 348 } 349 350 @Override set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes)351 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 352 if (renderable.environment == null) 353 shader.program.setUniform3fv(shader.loc(inputID), ones, 0, ones.length); 354 else { 355 renderable.worldTransform.getTranslation(tmpV1); 356 if (combinedAttributes.has(ColorAttribute.AmbientLight)) 357 cacheAmbientCubemap.set(((ColorAttribute)combinedAttributes.get(ColorAttribute.AmbientLight)).color); 358 359 if (combinedAttributes.has(DirectionalLightsAttribute.Type)) { 360 Array<DirectionalLight> lights = ((DirectionalLightsAttribute)combinedAttributes 361 .get(DirectionalLightsAttribute.Type)).lights; 362 for (int i = dirLightsOffset; i < lights.size; i++) 363 cacheAmbientCubemap.add(lights.get(i).color, lights.get(i).direction); 364 } 365 366 if (combinedAttributes.has(PointLightsAttribute.Type)) { 367 Array<PointLight> lights = ((PointLightsAttribute)combinedAttributes.get(PointLightsAttribute.Type)).lights; 368 for (int i = pointLightsOffset; i < lights.size; i++) 369 cacheAmbientCubemap.add(lights.get(i).color, lights.get(i).position, tmpV1, lights.get(i).intensity); 370 } 371 372 cacheAmbientCubemap.clamp(); 373 shader.program.setUniform3fv(shader.loc(inputID), cacheAmbientCubemap.data, 0, cacheAmbientCubemap.data.length); 374 } 375 } 376 } 377 378 public final static Setter environmentCubemap = new LocalSetter() { 379 @Override 380 public void set (BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) { 381 if (combinedAttributes.has(CubemapAttribute.EnvironmentMap)) { 382 shader.set(inputID, shader.context.textureBinder.bind(((CubemapAttribute)combinedAttributes 383 .get(CubemapAttribute.EnvironmentMap)).textureDescription)); 384 } 385 } 386 }; 387 } 388 389 private static String defaultVertexShader = null; 390 getDefaultVertexShader()391 public static String getDefaultVertexShader () { 392 if (defaultVertexShader == null) 393 defaultVertexShader = Gdx.files.classpath("com/badlogic/gdx/graphics/g3d/shaders/default.vertex.glsl").readString(); 394 return defaultVertexShader; 395 } 396 397 private static String defaultFragmentShader = null; 398 getDefaultFragmentShader()399 public static String getDefaultFragmentShader () { 400 if (defaultFragmentShader == null) 401 defaultFragmentShader = Gdx.files.classpath("com/badlogic/gdx/graphics/g3d/shaders/default.fragment.glsl").readString(); 402 return defaultFragmentShader; 403 } 404 405 protected static long implementedFlags = BlendingAttribute.Type | TextureAttribute.Diffuse | ColorAttribute.Diffuse 406 | ColorAttribute.Specular | FloatAttribute.Shininess; 407 408 /** @deprecated Replaced by {@link Config#defaultCullFace} Set to 0 to disable culling */ 409 @Deprecated public static int defaultCullFace = GL20.GL_BACK; 410 /** @deprecated Replaced by {@link Config#defaultDepthFunc} Set to 0 to disable depth test */ 411 @Deprecated public static int defaultDepthFunc = GL20.GL_LEQUAL; 412 413 // Global uniforms 414 public final int u_projTrans; 415 public final int u_viewTrans; 416 public final int u_projViewTrans; 417 public final int u_cameraPosition; 418 public final int u_cameraDirection; 419 public final int u_cameraUp; 420 public final int u_cameraNearFar; 421 public final int u_time; 422 // Object uniforms 423 public final int u_worldTrans; 424 public final int u_viewWorldTrans; 425 public final int u_projViewWorldTrans; 426 public final int u_normalMatrix; 427 public final int u_bones; 428 // Material uniforms 429 public final int u_shininess; 430 public final int u_opacity; 431 public final int u_diffuseColor; 432 public final int u_diffuseTexture; 433 public final int u_diffuseUVTransform; 434 public final int u_specularColor; 435 public final int u_specularTexture; 436 public final int u_specularUVTransform; 437 public final int u_emissiveColor; 438 public final int u_emissiveTexture; 439 public final int u_emissiveUVTransform; 440 public final int u_reflectionColor; 441 public final int u_reflectionTexture; 442 public final int u_reflectionUVTransform; 443 public final int u_normalTexture; 444 public final int u_normalUVTransform; 445 public final int u_ambientTexture; 446 public final int u_ambientUVTransform; 447 public final int u_alphaTest; 448 // Lighting uniforms 449 protected final int u_ambientCubemap; 450 protected final int u_environmentCubemap; 451 protected final int u_dirLights0color = register(new Uniform("u_dirLights[0].color")); 452 protected final int u_dirLights0direction = register(new Uniform("u_dirLights[0].direction")); 453 protected final int u_dirLights1color = register(new Uniform("u_dirLights[1].color")); 454 protected final int u_pointLights0color = register(new Uniform("u_pointLights[0].color")); 455 protected final int u_pointLights0position = register(new Uniform("u_pointLights[0].position")); 456 protected final int u_pointLights0intensity = register(new Uniform("u_pointLights[0].intensity")); 457 protected final int u_pointLights1color = register(new Uniform("u_pointLights[1].color")); 458 protected final int u_spotLights0color = register(new Uniform("u_spotLights[0].color")); 459 protected final int u_spotLights0position = register(new Uniform("u_spotLights[0].position")); 460 protected final int u_spotLights0intensity = register(new Uniform("u_spotLights[0].intensity")); 461 protected final int u_spotLights0direction = register(new Uniform("u_spotLights[0].direction")); 462 protected final int u_spotLights0cutoffAngle = register(new Uniform("u_spotLights[0].cutoffAngle")); 463 protected final int u_spotLights0exponent = register(new Uniform("u_spotLights[0].exponent")); 464 protected final int u_spotLights1color = register(new Uniform("u_spotLights[1].color")); 465 protected final int u_fogColor = register(new Uniform("u_fogColor")); 466 protected final int u_shadowMapProjViewTrans = register(new Uniform("u_shadowMapProjViewTrans")); 467 protected final int u_shadowTexture = register(new Uniform("u_shadowTexture")); 468 protected final int u_shadowPCFOffset = register(new Uniform("u_shadowPCFOffset")); 469 // FIXME Cache vertex attribute locations... 470 471 protected int dirLightsLoc; 472 protected int dirLightsColorOffset; 473 protected int dirLightsDirectionOffset; 474 protected int dirLightsSize; 475 protected int pointLightsLoc; 476 protected int pointLightsColorOffset; 477 protected int pointLightsPositionOffset; 478 protected int pointLightsIntensityOffset; 479 protected int pointLightsSize; 480 protected int spotLightsLoc; 481 protected int spotLightsColorOffset; 482 protected int spotLightsPositionOffset; 483 protected int spotLightsDirectionOffset; 484 protected int spotLightsIntensityOffset; 485 protected int spotLightsCutoffAngleOffset; 486 protected int spotLightsExponentOffset; 487 protected int spotLightsSize; 488 489 protected final boolean lighting; 490 protected final boolean environmentCubemap; 491 protected final boolean shadowMap; 492 protected final AmbientCubemap ambientCubemap = new AmbientCubemap(); 493 protected final DirectionalLight directionalLights[]; 494 protected final PointLight pointLights[]; 495 protected final SpotLight spotLights[]; 496 497 /** The renderable used to create this shader, invalid after the call to init */ 498 private Renderable renderable; 499 /** The attributes that this shader supports */ 500 protected final long attributesMask; 501 private final long vertexMask; 502 protected final Config config; 503 /** Attributes which are not required but always supported. */ 504 private final static long optionalAttributes = IntAttribute.CullFace | DepthTestAttribute.Type; 505 DefaultShader(final Renderable renderable)506 public DefaultShader (final Renderable renderable) { 507 this(renderable, new Config()); 508 } 509 DefaultShader(final Renderable renderable, final Config config)510 public DefaultShader (final Renderable renderable, final Config config) { 511 this(renderable, config, createPrefix(renderable, config)); 512 } 513 DefaultShader(final Renderable renderable, final Config config, final String prefix)514 public DefaultShader (final Renderable renderable, final Config config, final String prefix) { 515 this(renderable, config, prefix, config.vertexShader != null ? config.vertexShader : getDefaultVertexShader(), 516 config.fragmentShader != null ? config.fragmentShader : getDefaultFragmentShader()); 517 } 518 DefaultShader(final Renderable renderable, final Config config, final String prefix, final String vertexShader, final String fragmentShader)519 public DefaultShader (final Renderable renderable, final Config config, final String prefix, final String vertexShader, 520 final String fragmentShader) { 521 this(renderable, config, new ShaderProgram(prefix + vertexShader, prefix + fragmentShader)); 522 } 523 DefaultShader(final Renderable renderable, final Config config, final ShaderProgram shaderProgram)524 public DefaultShader (final Renderable renderable, final Config config, final ShaderProgram shaderProgram) { 525 final Attributes attributes = combineAttributes(renderable); 526 this.config = config; 527 this.program = shaderProgram; 528 this.lighting = renderable.environment != null; 529 this.environmentCubemap = attributes.has(CubemapAttribute.EnvironmentMap) 530 || (lighting && attributes.has(CubemapAttribute.EnvironmentMap)); 531 this.shadowMap = lighting && renderable.environment.shadowMap != null; 532 this.renderable = renderable; 533 attributesMask = attributes.getMask() | optionalAttributes; 534 vertexMask = renderable.meshPart.mesh.getVertexAttributes().getMask(); 535 536 this.directionalLights = new DirectionalLight[lighting && config.numDirectionalLights > 0 ? config.numDirectionalLights : 0]; 537 for (int i = 0; i < directionalLights.length; i++) 538 directionalLights[i] = new DirectionalLight(); 539 this.pointLights = new PointLight[lighting && config.numPointLights > 0 ? config.numPointLights : 0]; 540 for (int i = 0; i < pointLights.length; i++) 541 pointLights[i] = new PointLight(); 542 this.spotLights = new SpotLight[lighting && config.numSpotLights > 0 ? config.numSpotLights : 0]; 543 for (int i = 0; i < spotLights.length; i++) 544 spotLights[i] = new SpotLight(); 545 546 if (!config.ignoreUnimplemented && (implementedFlags & attributesMask) != attributesMask) 547 throw new GdxRuntimeException("Some attributes not implemented yet (" + attributesMask + ")"); 548 549 // Global uniforms 550 u_projTrans = register(Inputs.projTrans, Setters.projTrans); 551 u_viewTrans = register(Inputs.viewTrans, Setters.viewTrans); 552 u_projViewTrans = register(Inputs.projViewTrans, Setters.projViewTrans); 553 u_cameraPosition = register(Inputs.cameraPosition, Setters.cameraPosition); 554 u_cameraDirection = register(Inputs.cameraDirection, Setters.cameraDirection); 555 u_cameraUp = register(Inputs.cameraUp, Setters.cameraUp); 556 u_cameraNearFar = register(Inputs.cameraNearFar, Setters.cameraNearFar); 557 u_time = register(new Uniform("u_time")); 558 // Object uniforms 559 u_worldTrans = register(Inputs.worldTrans, Setters.worldTrans); 560 u_viewWorldTrans = register(Inputs.viewWorldTrans, Setters.viewWorldTrans); 561 u_projViewWorldTrans = register(Inputs.projViewWorldTrans, Setters.projViewWorldTrans); 562 u_normalMatrix = register(Inputs.normalMatrix, Setters.normalMatrix); 563 u_bones = (renderable.bones != null && config.numBones > 0) ? register(Inputs.bones, new Setters.Bones(config.numBones)) 564 : -1; 565 566 u_shininess = register(Inputs.shininess, Setters.shininess); 567 u_opacity = register(Inputs.opacity); 568 u_diffuseColor = register(Inputs.diffuseColor, Setters.diffuseColor); 569 u_diffuseTexture = register(Inputs.diffuseTexture, Setters.diffuseTexture); 570 u_diffuseUVTransform = register(Inputs.diffuseUVTransform, Setters.diffuseUVTransform); 571 u_specularColor = register(Inputs.specularColor, Setters.specularColor); 572 u_specularTexture = register(Inputs.specularTexture, Setters.specularTexture); 573 u_specularUVTransform = register(Inputs.specularUVTransform, Setters.specularUVTransform); 574 u_emissiveColor = register(Inputs.emissiveColor, Setters.emissiveColor); 575 u_emissiveTexture = register(Inputs.emissiveTexture, Setters.emissiveTexture); 576 u_emissiveUVTransform = register(Inputs.emissiveUVTransform, Setters.emissiveUVTransform); 577 u_reflectionColor = register(Inputs.reflectionColor, Setters.reflectionColor); 578 u_reflectionTexture = register(Inputs.reflectionTexture, Setters.reflectionTexture); 579 u_reflectionUVTransform = register(Inputs.reflectionUVTransform, Setters.reflectionUVTransform); 580 u_normalTexture = register(Inputs.normalTexture, Setters.normalTexture); 581 u_normalUVTransform = register(Inputs.normalUVTransform, Setters.normalUVTransform); 582 u_ambientTexture = register(Inputs.ambientTexture, Setters.ambientTexture); 583 u_ambientUVTransform = register(Inputs.ambientUVTransform, Setters.ambientUVTransform); 584 u_alphaTest = register(Inputs.alphaTest); 585 586 u_ambientCubemap = lighting ? register(Inputs.ambientCube, new Setters.ACubemap(config.numDirectionalLights, 587 config.numPointLights)) : -1; 588 u_environmentCubemap = environmentCubemap ? register(Inputs.environmentCubemap, Setters.environmentCubemap) : -1; 589 } 590 591 @Override init()592 public void init () { 593 final ShaderProgram program = this.program; 594 this.program = null; 595 init(program, renderable); 596 renderable = null; 597 598 dirLightsLoc = loc(u_dirLights0color); 599 dirLightsColorOffset = loc(u_dirLights0color) - dirLightsLoc; 600 dirLightsDirectionOffset = loc(u_dirLights0direction) - dirLightsLoc; 601 dirLightsSize = loc(u_dirLights1color) - dirLightsLoc; 602 if (dirLightsSize < 0) dirLightsSize = 0; 603 604 pointLightsLoc = loc(u_pointLights0color); 605 pointLightsColorOffset = loc(u_pointLights0color) - pointLightsLoc; 606 pointLightsPositionOffset = loc(u_pointLights0position) - pointLightsLoc; 607 pointLightsIntensityOffset = has(u_pointLights0intensity) ? loc(u_pointLights0intensity) - pointLightsLoc : -1; 608 pointLightsSize = loc(u_pointLights1color) - pointLightsLoc; 609 if (pointLightsSize < 0) pointLightsSize = 0; 610 611 spotLightsLoc = loc(u_spotLights0color); 612 spotLightsColorOffset = loc(u_spotLights0color) - spotLightsLoc; 613 spotLightsPositionOffset = loc(u_spotLights0position) - spotLightsLoc; 614 spotLightsDirectionOffset = loc(u_spotLights0direction) - spotLightsLoc; 615 spotLightsIntensityOffset = has(u_spotLights0intensity) ? loc(u_spotLights0intensity) - spotLightsLoc : -1; 616 spotLightsCutoffAngleOffset = loc(u_spotLights0cutoffAngle) - spotLightsLoc; 617 spotLightsExponentOffset = loc(u_spotLights0exponent) - spotLightsLoc; 618 spotLightsSize = loc(u_spotLights1color) - spotLightsLoc; 619 if (spotLightsSize < 0) spotLightsSize = 0; 620 } 621 and(final long mask, final long flag)622 private static final boolean and (final long mask, final long flag) { 623 return (mask & flag) == flag; 624 } 625 or(final long mask, final long flag)626 private static final boolean or (final long mask, final long flag) { 627 return (mask & flag) != 0; 628 } 629 630 private final static Attributes tmpAttributes = new Attributes(); 631 632 // TODO: Perhaps move responsibility for combining attributes to RenderableProvider? combineAttributes(final Renderable renderable)633 private static final Attributes combineAttributes (final Renderable renderable) { 634 tmpAttributes.clear(); 635 if (renderable.environment != null) tmpAttributes.set(renderable.environment); 636 if (renderable.material != null) tmpAttributes.set(renderable.material); 637 return tmpAttributes; 638 } 639 createPrefix(final Renderable renderable, final Config config)640 public static String createPrefix (final Renderable renderable, final Config config) { 641 final Attributes attributes = combineAttributes(renderable); 642 String prefix = ""; 643 final long attributesMask = attributes.getMask(); 644 final long vertexMask = renderable.meshPart.mesh.getVertexAttributes().getMask(); 645 if (and(vertexMask, Usage.Position)) prefix += "#define positionFlag\n"; 646 if (or(vertexMask, Usage.ColorUnpacked | Usage.ColorPacked)) prefix += "#define colorFlag\n"; 647 if (and(vertexMask, Usage.BiNormal)) prefix += "#define binormalFlag\n"; 648 if (and(vertexMask, Usage.Tangent)) prefix += "#define tangentFlag\n"; 649 if (and(vertexMask, Usage.Normal)) prefix += "#define normalFlag\n"; 650 if (and(vertexMask, Usage.Normal) || and(vertexMask, Usage.Tangent | Usage.BiNormal)) { 651 if (renderable.environment != null) { 652 prefix += "#define lightingFlag\n"; 653 prefix += "#define ambientCubemapFlag\n"; 654 prefix += "#define numDirectionalLights " + config.numDirectionalLights + "\n"; 655 prefix += "#define numPointLights " + config.numPointLights + "\n"; 656 prefix += "#define numSpotLights " + config.numSpotLights + "\n"; 657 if (attributes.has(ColorAttribute.Fog)) { 658 prefix += "#define fogFlag\n"; 659 } 660 if (renderable.environment.shadowMap != null) prefix += "#define shadowMapFlag\n"; 661 if (attributes.has(CubemapAttribute.EnvironmentMap)) prefix += "#define environmentCubemapFlag\n"; 662 } 663 } 664 final int n = renderable.meshPart.mesh.getVertexAttributes().size(); 665 for (int i = 0; i < n; i++) { 666 final VertexAttribute attr = renderable.meshPart.mesh.getVertexAttributes().get(i); 667 if (attr.usage == Usage.BoneWeight) 668 prefix += "#define boneWeight" + attr.unit + "Flag\n"; 669 else if (attr.usage == Usage.TextureCoordinates) prefix += "#define texCoord" + attr.unit + "Flag\n"; 670 } 671 if ((attributesMask & BlendingAttribute.Type) == BlendingAttribute.Type) 672 prefix += "#define " + BlendingAttribute.Alias + "Flag\n"; 673 if ((attributesMask & TextureAttribute.Diffuse) == TextureAttribute.Diffuse) { 674 prefix += "#define " + TextureAttribute.DiffuseAlias + "Flag\n"; 675 prefix += "#define " + TextureAttribute.DiffuseAlias + "Coord texCoord0\n"; // FIXME implement UV mapping 676 } 677 if ((attributesMask & TextureAttribute.Specular) == TextureAttribute.Specular) { 678 prefix += "#define " + TextureAttribute.SpecularAlias + "Flag\n"; 679 prefix += "#define " + TextureAttribute.SpecularAlias + "Coord texCoord0\n"; // FIXME implement UV mapping 680 } 681 if ((attributesMask & TextureAttribute.Normal) == TextureAttribute.Normal) { 682 prefix += "#define " + TextureAttribute.NormalAlias + "Flag\n"; 683 prefix += "#define " + TextureAttribute.NormalAlias + "Coord texCoord0\n"; // FIXME implement UV mapping 684 } 685 if ((attributesMask & TextureAttribute.Emissive) == TextureAttribute.Emissive) { 686 prefix += "#define " + TextureAttribute.EmissiveAlias + "Flag\n"; 687 prefix += "#define " + TextureAttribute.EmissiveAlias + "Coord texCoord0\n"; // FIXME implement UV mapping 688 } 689 if ((attributesMask & TextureAttribute.Reflection) == TextureAttribute.Reflection) { 690 prefix += "#define " + TextureAttribute.ReflectionAlias + "Flag\n"; 691 prefix += "#define " + TextureAttribute.ReflectionAlias + "Coord texCoord0\n"; // FIXME implement UV mapping 692 } 693 if ((attributesMask & TextureAttribute.Ambient) == TextureAttribute.Ambient) { 694 prefix += "#define " + TextureAttribute.AmbientAlias + "Flag\n"; 695 prefix += "#define " + TextureAttribute.AmbientAlias + "Coord texCoord0\n"; // FIXME implement UV mapping 696 } 697 if ((attributesMask & ColorAttribute.Diffuse) == ColorAttribute.Diffuse) 698 prefix += "#define " + ColorAttribute.DiffuseAlias + "Flag\n"; 699 if ((attributesMask & ColorAttribute.Specular) == ColorAttribute.Specular) 700 prefix += "#define " + ColorAttribute.SpecularAlias + "Flag\n"; 701 if ((attributesMask & ColorAttribute.Emissive) == ColorAttribute.Emissive) 702 prefix += "#define " + ColorAttribute.EmissiveAlias + "Flag\n"; 703 if ((attributesMask & ColorAttribute.Reflection) == ColorAttribute.Reflection) 704 prefix += "#define " + ColorAttribute.ReflectionAlias + "Flag\n"; 705 if ((attributesMask & FloatAttribute.Shininess) == FloatAttribute.Shininess) 706 prefix += "#define " + FloatAttribute.ShininessAlias + "Flag\n"; 707 if ((attributesMask & FloatAttribute.AlphaTest) == FloatAttribute.AlphaTest) 708 prefix += "#define " + FloatAttribute.AlphaTestAlias + "Flag\n"; 709 if (renderable.bones != null && config.numBones > 0) prefix += "#define numBones " + config.numBones + "\n"; 710 return prefix; 711 } 712 713 @Override canRender(final Renderable renderable)714 public boolean canRender (final Renderable renderable) { 715 final Attributes attributes = combineAttributes(renderable); 716 return (attributesMask == (attributes.getMask() | optionalAttributes)) 717 && (vertexMask == renderable.meshPart.mesh.getVertexAttributes().getMask()) && (renderable.environment != null) == lighting; 718 } 719 720 @Override compareTo(Shader other)721 public int compareTo (Shader other) { 722 if (other == null) return -1; 723 if (other == this) return 0; 724 return 0; // FIXME compare shaders on their impact on performance 725 } 726 727 @Override equals(Object obj)728 public boolean equals (Object obj) { 729 return (obj instanceof DefaultShader) ? equals((DefaultShader)obj) : false; 730 } 731 equals(DefaultShader obj)732 public boolean equals (DefaultShader obj) { 733 return (obj == this); 734 } 735 736 private final Matrix3 normalMatrix = new Matrix3(); 737 private float time; 738 private boolean lightsSet; 739 740 @Override begin(final Camera camera, final RenderContext context)741 public void begin (final Camera camera, final RenderContext context) { 742 super.begin(camera, context); 743 744 for (final DirectionalLight dirLight : directionalLights) 745 dirLight.set(0, 0, 0, 0, -1, 0); 746 for (final PointLight pointLight : pointLights) 747 pointLight.set(0, 0, 0, 0, 0, 0, 0); 748 for (final SpotLight spotLight : spotLights) 749 spotLight.set(0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0); 750 lightsSet = false; 751 752 if (has(u_time)) set(u_time, time += Gdx.graphics.getDeltaTime()); 753 } 754 755 @Override render(Renderable renderable, Attributes combinedAttributes)756 public void render (Renderable renderable, Attributes combinedAttributes) { 757 if (!combinedAttributes.has(BlendingAttribute.Type)) 758 context.setBlending(false, GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); 759 bindMaterial(combinedAttributes); 760 if (lighting) bindLights(renderable, combinedAttributes); 761 super.render(renderable, combinedAttributes); 762 } 763 764 @Override end()765 public void end () { 766 super.end(); 767 } 768 bindMaterial(final Attributes attributes)769 protected void bindMaterial (final Attributes attributes) { 770 int cullFace = config.defaultCullFace == -1 ? defaultCullFace : config.defaultCullFace; 771 int depthFunc = config.defaultDepthFunc == -1 ? defaultDepthFunc : config.defaultDepthFunc; 772 float depthRangeNear = 0f; 773 float depthRangeFar = 1f; 774 boolean depthMask = true; 775 776 for (final Attribute attr : attributes) { 777 final long t = attr.type; 778 if (BlendingAttribute.is(t)) { 779 context.setBlending(true, ((BlendingAttribute)attr).sourceFunction, ((BlendingAttribute)attr).destFunction); 780 set(u_opacity, ((BlendingAttribute)attr).opacity); 781 } else if ((t & IntAttribute.CullFace) == IntAttribute.CullFace) 782 cullFace = ((IntAttribute)attr).value; 783 else if ((t & FloatAttribute.AlphaTest) == FloatAttribute.AlphaTest) 784 set(u_alphaTest, ((FloatAttribute)attr).value); 785 else if ((t & DepthTestAttribute.Type) == DepthTestAttribute.Type) { 786 DepthTestAttribute dta = (DepthTestAttribute)attr; 787 depthFunc = dta.depthFunc; 788 depthRangeNear = dta.depthRangeNear; 789 depthRangeFar = dta.depthRangeFar; 790 depthMask = dta.depthMask; 791 } else if (!config.ignoreUnimplemented) throw new GdxRuntimeException("Unknown material attribute: " + attr.toString()); 792 } 793 794 context.setCullFace(cullFace); 795 context.setDepthTest(depthFunc, depthRangeNear, depthRangeFar); 796 context.setDepthMask(depthMask); 797 } 798 799 private final Vector3 tmpV1 = new Vector3(); 800 bindLights(final Renderable renderable, final Attributes attributes)801 protected void bindLights (final Renderable renderable, final Attributes attributes) { 802 final Environment lights = renderable.environment; 803 final DirectionalLightsAttribute dla = attributes.get(DirectionalLightsAttribute.class, DirectionalLightsAttribute.Type); 804 final Array<DirectionalLight> dirs = dla == null ? null : dla.lights; 805 final PointLightsAttribute pla = attributes.get(PointLightsAttribute.class, PointLightsAttribute.Type); 806 final Array<PointLight> points = pla == null ? null : pla.lights; 807 final SpotLightsAttribute sla = attributes.get(SpotLightsAttribute.class, SpotLightsAttribute.Type); 808 final Array<SpotLight> spots = sla == null ? null : sla.lights; 809 810 if (dirLightsLoc >= 0) { 811 for (int i = 0; i < directionalLights.length; i++) { 812 if (dirs == null || i >= dirs.size) { 813 if (lightsSet && directionalLights[i].color.r == 0f && directionalLights[i].color.g == 0f 814 && directionalLights[i].color.b == 0f) continue; 815 directionalLights[i].color.set(0, 0, 0, 1); 816 } else if (lightsSet && directionalLights[i].equals(dirs.get(i))) 817 continue; 818 else 819 directionalLights[i].set(dirs.get(i)); 820 821 int idx = dirLightsLoc + i * dirLightsSize; 822 program.setUniformf(idx + dirLightsColorOffset, directionalLights[i].color.r, directionalLights[i].color.g, 823 directionalLights[i].color.b); 824 program.setUniformf(idx + dirLightsDirectionOffset, directionalLights[i].direction.x, 825 directionalLights[i].direction.y, directionalLights[i].direction.z); 826 if (dirLightsSize <= 0) break; 827 } 828 } 829 830 if (pointLightsLoc >= 0) { 831 for (int i = 0; i < pointLights.length; i++) { 832 if (points == null || i >= points.size) { 833 if (lightsSet && pointLights[i].intensity == 0f) continue; 834 pointLights[i].intensity = 0f; 835 } else if (lightsSet && pointLights[i].equals(points.get(i))) 836 continue; 837 else 838 pointLights[i].set(points.get(i)); 839 840 int idx = pointLightsLoc + i * pointLightsSize; 841 program.setUniformf(idx + pointLightsColorOffset, pointLights[i].color.r * pointLights[i].intensity, 842 pointLights[i].color.g * pointLights[i].intensity, pointLights[i].color.b * pointLights[i].intensity); 843 program.setUniformf(idx + pointLightsPositionOffset, pointLights[i].position.x, pointLights[i].position.y, 844 pointLights[i].position.z); 845 if (pointLightsIntensityOffset >= 0) program.setUniformf(idx + pointLightsIntensityOffset, pointLights[i].intensity); 846 if (pointLightsSize <= 0) break; 847 } 848 } 849 850 if (spotLightsLoc >= 0) { 851 for (int i = 0; i < spotLights.length; i++) { 852 if (spots == null || i >= spots.size) { 853 if (lightsSet && spotLights[i].intensity == 0f) continue; 854 spotLights[i].intensity = 0f; 855 } else if (lightsSet && spotLights[i].equals(spots.get(i))) 856 continue; 857 else 858 spotLights[i].set(spots.get(i)); 859 860 int idx = spotLightsLoc + i * spotLightsSize; 861 program.setUniformf(idx + spotLightsColorOffset, spotLights[i].color.r * spotLights[i].intensity, 862 spotLights[i].color.g * spotLights[i].intensity, spotLights[i].color.b * spotLights[i].intensity); 863 program.setUniformf(idx + spotLightsPositionOffset, spotLights[i].position); 864 program.setUniformf(idx + spotLightsDirectionOffset, spotLights[i].direction); 865 program.setUniformf(idx + spotLightsCutoffAngleOffset, spotLights[i].cutoffAngle); 866 program.setUniformf(idx + spotLightsExponentOffset, spotLights[i].exponent); 867 if (spotLightsIntensityOffset >= 0) 868 program.setUniformf(idx + spotLightsIntensityOffset, spotLights[i].intensity); 869 if (spotLightsSize <= 0) break; 870 } 871 } 872 873 if (attributes.has(ColorAttribute.Fog)) { 874 set(u_fogColor, ((ColorAttribute)attributes.get(ColorAttribute.Fog)).color); 875 } 876 877 if (lights != null && lights.shadowMap != null) { 878 set(u_shadowMapProjViewTrans, lights.shadowMap.getProjViewTrans()); 879 set(u_shadowTexture, lights.shadowMap.getDepthMap()); 880 set(u_shadowPCFOffset, 1.f / (2f * lights.shadowMap.getDepthMap().texture.getWidth())); 881 } 882 883 lightsSet = true; 884 } 885 886 @Override dispose()887 public void dispose () { 888 program.dispose(); 889 super.dispose(); 890 } 891 getDefaultCullFace()892 public int getDefaultCullFace () { 893 return config.defaultCullFace == -1 ? defaultCullFace : config.defaultCullFace; 894 } 895 setDefaultCullFace(int cullFace)896 public void setDefaultCullFace (int cullFace) { 897 config.defaultCullFace = cullFace; 898 } 899 getDefaultDepthFunc()900 public int getDefaultDepthFunc () { 901 return config.defaultDepthFunc == -1 ? defaultDepthFunc : config.defaultDepthFunc; 902 } 903 setDefaultDepthFunc(int depthFunc)904 public void setDefaultDepthFunc (int depthFunc) { 905 config.defaultDepthFunc = depthFunc; 906 } 907 } 908