stencilState.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import { Constants } from "../Engines/constants";
  2. /**
  3. * @hidden
  4. **/
  5. export class StencilState {
  6. /** Passed to depthFunction or stencilFunction to specify depth or stencil tests will always pass. i.e. Pixels will be drawn in the order they are drawn */
  7. public static readonly ALWAYS = Constants.ALWAYS;
  8. /** Passed to stencilOperation to specify that stencil value must be kept */
  9. public static readonly KEEP = Constants.KEEP;
  10. /** Passed to stencilOperation to specify that stencil value must be replaced */
  11. public static readonly REPLACE = Constants.REPLACE;
  12. private _isStencilTestDirty = false;
  13. private _isStencilMaskDirty = false;
  14. private _isStencilFuncDirty = false;
  15. private _isStencilOpDirty = false;
  16. private _stencilTest: boolean;
  17. private _stencilMask: number;
  18. private _stencilFunc: number;
  19. private _stencilFuncRef: number;
  20. private _stencilFuncMask: number;
  21. private _stencilOpStencilFail: number;
  22. private _stencilOpDepthFail: number;
  23. private _stencilOpStencilDepthPass: number;
  24. public get isDirty(): boolean {
  25. return this._isStencilTestDirty || this._isStencilMaskDirty || this._isStencilFuncDirty || this._isStencilOpDirty;
  26. }
  27. public get stencilFunc(): number {
  28. return this._stencilFunc;
  29. }
  30. public set stencilFunc(value: number) {
  31. if (this._stencilFunc === value) {
  32. return;
  33. }
  34. this._stencilFunc = value;
  35. this._isStencilFuncDirty = true;
  36. }
  37. public get stencilFuncRef(): number {
  38. return this._stencilFuncRef;
  39. }
  40. public set stencilFuncRef(value: number) {
  41. if (this._stencilFuncRef === value) {
  42. return;
  43. }
  44. this._stencilFuncRef = value;
  45. this._isStencilFuncDirty = true;
  46. }
  47. public get stencilFuncMask(): number {
  48. return this._stencilFuncMask;
  49. }
  50. public set stencilFuncMask(value: number) {
  51. if (this._stencilFuncMask === value) {
  52. return;
  53. }
  54. this._stencilFuncMask = value;
  55. this._isStencilFuncDirty = true;
  56. }
  57. public get stencilOpStencilFail(): number {
  58. return this._stencilOpStencilFail;
  59. }
  60. public set stencilOpStencilFail(value: number) {
  61. if (this._stencilOpStencilFail === value) {
  62. return;
  63. }
  64. this._stencilOpStencilFail = value;
  65. this._isStencilOpDirty = true;
  66. }
  67. public get stencilOpDepthFail(): number {
  68. return this._stencilOpDepthFail;
  69. }
  70. public set stencilOpDepthFail(value: number) {
  71. if (this._stencilOpDepthFail === value) {
  72. return;
  73. }
  74. this._stencilOpDepthFail = value;
  75. this._isStencilOpDirty = true;
  76. }
  77. public get stencilOpStencilDepthPass(): number {
  78. return this._stencilOpStencilDepthPass;
  79. }
  80. public set stencilOpStencilDepthPass(value: number) {
  81. if (this._stencilOpStencilDepthPass === value) {
  82. return;
  83. }
  84. this._stencilOpStencilDepthPass = value;
  85. this._isStencilOpDirty = true;
  86. }
  87. public get stencilMask(): number {
  88. return this._stencilMask;
  89. }
  90. public set stencilMask(value: number) {
  91. if (this._stencilMask === value) {
  92. return;
  93. }
  94. this._stencilMask = value;
  95. this._isStencilMaskDirty = true;
  96. }
  97. public get stencilTest(): boolean {
  98. return this._stencilTest;
  99. }
  100. public set stencilTest(value: boolean) {
  101. if (this._stencilTest === value) {
  102. return;
  103. }
  104. this._stencilTest = value;
  105. this._isStencilTestDirty = true;
  106. }
  107. public constructor() {
  108. this.reset();
  109. }
  110. public reset() {
  111. this._stencilTest = false;
  112. this._stencilMask = 0xFF;
  113. this._stencilFunc = StencilState.ALWAYS;
  114. this._stencilFuncRef = 1;
  115. this._stencilFuncMask = 0xFF;
  116. this._stencilOpStencilFail = StencilState.KEEP;
  117. this._stencilOpDepthFail = StencilState.KEEP;
  118. this._stencilOpStencilDepthPass = StencilState.REPLACE;
  119. this._isStencilTestDirty = true;
  120. this._isStencilMaskDirty = true;
  121. this._isStencilFuncDirty = true;
  122. this._isStencilOpDirty = true;
  123. }
  124. public apply(gl: WebGLRenderingContext) {
  125. if (!this.isDirty) {
  126. return;
  127. }
  128. // Stencil test
  129. if (this._isStencilTestDirty) {
  130. if (this.stencilTest) {
  131. gl.enable(gl.STENCIL_TEST);
  132. } else {
  133. gl.disable(gl.STENCIL_TEST);
  134. }
  135. this._isStencilTestDirty = false;
  136. }
  137. // Stencil mask
  138. if (this._isStencilMaskDirty) {
  139. gl.stencilMask(this.stencilMask);
  140. this._isStencilMaskDirty = false;
  141. }
  142. // Stencil func
  143. if (this._isStencilFuncDirty) {
  144. gl.stencilFunc(this.stencilFunc, this.stencilFuncRef, this.stencilFuncMask);
  145. this._isStencilFuncDirty = false;
  146. }
  147. // Stencil op
  148. if (this._isStencilOpDirty) {
  149. gl.stencilOp(this.stencilOpStencilFail, this.stencilOpDepthFail, this.stencilOpStencilDepthPass);
  150. this._isStencilOpDirty = false;
  151. }
  152. }
  153. }