Appearance.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import clone from '../Core/clone.js';
  2. import combine from '../Core/combine.js';
  3. import defaultValue from '../Core/defaultValue.js';
  4. import defined from '../Core/defined.js';
  5. import defineProperties from '../Core/defineProperties.js';
  6. import BlendingState from './BlendingState.js';
  7. import CullFace from './CullFace.js';
  8. /**
  9. * An appearance defines the full GLSL vertex and fragment shaders and the
  10. * render state used to draw a {@link Primitive}. All appearances implement
  11. * this base <code>Appearance</code> interface.
  12. *
  13. * @alias Appearance
  14. * @constructor
  15. *
  16. * @param {Object} [options] Object with the following properties:
  17. * @param {Boolean} [options.translucent=true] When <code>true</code>, the geometry is expected to appear translucent so {@link Appearance#renderState} has alpha blending enabled.
  18. * @param {Boolean} [options.closed=false] When <code>true</code>, the geometry is expected to be closed so {@link Appearance#renderState} has backface culling enabled.
  19. * @param {Material} [options.material=Material.ColorType] The material used to determine the fragment color.
  20. * @param {String} [options.vertexShaderSource] Optional GLSL vertex shader source to override the default vertex shader.
  21. * @param {String} [options.fragmentShaderSource] Optional GLSL fragment shader source to override the default fragment shader.
  22. * @param {RenderState} [options.renderState] Optional render state to override the default render state.
  23. *
  24. * @see MaterialAppearance
  25. * @see EllipsoidSurfaceAppearance
  26. * @see PerInstanceColorAppearance
  27. * @see DebugAppearance
  28. * @see PolylineColorAppearance
  29. * @see PolylineMaterialAppearance
  30. * @see PerInstanceColorAppearance
  31. *
  32. * @demo {@link https://sandcastle.cesium.com/index.html?src=Geometry%20and%20Appearances.html|Geometry and Appearances Demo}
  33. */
  34. function Appearance(options) {
  35. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  36. /**
  37. * The material used to determine the fragment color. Unlike other {@link Appearance}
  38. * properties, this is not read-only, so an appearance's material can change on the fly.
  39. *
  40. * @type Material
  41. *
  42. * @see {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric|Fabric}
  43. */
  44. this.material = options.material;
  45. /**
  46. * When <code>true</code>, the geometry is expected to appear translucent.
  47. *
  48. * @type {Boolean}
  49. *
  50. * @default true
  51. */
  52. this.translucent = defaultValue(options.translucent, true);
  53. this._vertexShaderSource = options.vertexShaderSource;
  54. this._fragmentShaderSource = options.fragmentShaderSource;
  55. this._renderState = options.renderState;
  56. this._closed = defaultValue(options.closed, false);
  57. }
  58. defineProperties(Appearance.prototype, {
  59. /**
  60. * The GLSL source code for the vertex shader.
  61. *
  62. * @memberof Appearance.prototype
  63. *
  64. * @type {String}
  65. * @readonly
  66. */
  67. vertexShaderSource : {
  68. get : function() {
  69. return this._vertexShaderSource;
  70. }
  71. },
  72. /**
  73. * The GLSL source code for the fragment shader. The full fragment shader
  74. * source is built procedurally taking into account the {@link Appearance#material}.
  75. * Use {@link Appearance#getFragmentShaderSource} to get the full source.
  76. *
  77. * @memberof Appearance.prototype
  78. *
  79. * @type {String}
  80. * @readonly
  81. */
  82. fragmentShaderSource : {
  83. get : function() {
  84. return this._fragmentShaderSource;
  85. }
  86. },
  87. /**
  88. * The WebGL fixed-function state to use when rendering the geometry.
  89. *
  90. * @memberof Appearance.prototype
  91. *
  92. * @type {Object}
  93. * @readonly
  94. */
  95. renderState : {
  96. get : function() {
  97. return this._renderState;
  98. }
  99. },
  100. /**
  101. * When <code>true</code>, the geometry is expected to be closed.
  102. *
  103. * @memberof Appearance.prototype
  104. *
  105. * @type {Boolean}
  106. * @readonly
  107. *
  108. * @default false
  109. */
  110. closed : {
  111. get : function() {
  112. return this._closed;
  113. }
  114. }
  115. });
  116. /**
  117. * Procedurally creates the full GLSL fragment shader source for this appearance
  118. * taking into account {@link Appearance#fragmentShaderSource} and {@link Appearance#material}.
  119. *
  120. * @returns {String} The full GLSL fragment shader source.
  121. */
  122. Appearance.prototype.getFragmentShaderSource = function() {
  123. var parts = [];
  124. if (this.flat) {
  125. parts.push('#define FLAT');
  126. }
  127. if (this.faceForward) {
  128. parts.push('#define FACE_FORWARD');
  129. }
  130. if (defined(this.material)) {
  131. parts.push(this.material.shaderSource);
  132. }
  133. parts.push(this.fragmentShaderSource);
  134. return parts.join('\n');
  135. };
  136. /**
  137. * Determines if the geometry is translucent based on {@link Appearance#translucent} and {@link Material#isTranslucent}.
  138. *
  139. * @returns {Boolean} <code>true</code> if the appearance is translucent.
  140. */
  141. Appearance.prototype.isTranslucent = function() {
  142. return (defined(this.material) && this.material.isTranslucent()) || (!defined(this.material) && this.translucent);
  143. };
  144. /**
  145. * Creates a render state. This is not the final render state instance; instead,
  146. * it can contain a subset of render state properties identical to the render state
  147. * created in the context.
  148. *
  149. * @returns {Object} The render state.
  150. */
  151. Appearance.prototype.getRenderState = function() {
  152. var translucent = this.isTranslucent();
  153. var rs = clone(this.renderState, false);
  154. if (translucent) {
  155. rs.depthMask = false;
  156. rs.blending = BlendingState.ALPHA_BLEND;
  157. } else {
  158. rs.depthMask = true;
  159. }
  160. return rs;
  161. };
  162. /**
  163. * @private
  164. */
  165. Appearance.getDefaultRenderState = function(translucent, closed, existing) {
  166. var rs = {
  167. depthTest : {
  168. enabled : true
  169. }
  170. };
  171. if (translucent) {
  172. rs.depthMask = false;
  173. rs.blending = BlendingState.ALPHA_BLEND;
  174. }
  175. if (closed) {
  176. rs.cull = {
  177. enabled : true,
  178. face : CullFace.BACK
  179. };
  180. }
  181. if (defined(existing)) {
  182. rs = combine(existing, rs, true);
  183. }
  184. return rs;
  185. };
  186. export default Appearance;