Skip to content

Commit

Permalink
Feature/stencil testing (#244)
Browse files Browse the repository at this point in the history
* stencil testing

* typo

* type fix

* oopsie

* fix missing gl references

* fix missing js extension

* remove redudndant clear bits
  • Loading branch information
DougLilliequist authored Jan 2, 2025
1 parent 31abd49 commit bcd38cc
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 7 deletions.
22 changes: 22 additions & 0 deletions src/core/Program.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export class Program {
this.depthFunc = depthFunc;
this.blendFunc = {};
this.blendEquation = {};
this.stencilFunc = {};
this.stencilOp = {}

// set default blendFunc if transparent flagged
if (this.transparent && !this.blendFunc.src) {
Expand Down Expand Up @@ -125,6 +127,19 @@ export class Program {
this.blendEquation.modeAlpha = modeAlpha;
}

setStencilFunc(func, ref, mask) {
this.stencilRef = ref;
this.stencilFunc.func = func;
this.stencilFunc.ref = ref;
this.stencilFunc.mask = mask;
}

setStencilOp(stencilFail, depthFail, depthPass) {
this.stencilOp.stencilFail = stencilFail;
this.stencilOp.depthFail = depthFail;
this.stencilOp.depthPass = depthPass;
}

applyState() {
if (this.depthTest) this.gl.renderer.enable(this.gl.DEPTH_TEST);
else this.gl.renderer.disable(this.gl.DEPTH_TEST);
Expand All @@ -141,6 +156,13 @@ export class Program {
this.gl.renderer.setDepthFunc(this.depthFunc);
if (this.blendFunc.src) this.gl.renderer.setBlendFunc(this.blendFunc.src, this.blendFunc.dst, this.blendFunc.srcAlpha, this.blendFunc.dstAlpha);
this.gl.renderer.setBlendEquation(this.blendEquation.modeRGB, this.blendEquation.modeAlpha);

if(this.stencilFunc.func || this.stencilOp.stencilFail) this.gl.renderer.enable(this.gl.STENCIL_TEST)
else this.gl.renderer.disable(this.gl.STENCIL_TEST)

this.gl.renderer.setStencilFunc(this.stencilFunc.func, this.stencilFunc.ref, this.stencilFunc.mask)
this.gl.renderer.setStencilOp(this.stencilOp.stencilFail, this.stencilOp.depthFail, this.stencilOp.depthPass)

}

use({ flipFaces = false } = {}) {
Expand Down
16 changes: 9 additions & 7 deletions src/core/RenderTarget.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// TODO: test stencil and depth
import { Texture } from './Texture.js';
import { Texture } from './Texture.js'

export class RenderTarget {
constructor(
Expand All @@ -11,9 +10,10 @@ export class RenderTarget {
color = 1, // number of color attachments
depth = true,
stencil = false,
depthTexture = false, // note - stencil breaks
depthTexture = false,
wrapS = gl.CLAMP_TO_EDGE,
wrapT = gl.CLAMP_TO_EDGE,
wrapR = gl.CLAMP_TO_EDGE,
minFilter = gl.LINEAR,
magFilter = minFilter,
type = gl.UNSIGNED_BYTE,
Expand All @@ -27,6 +27,7 @@ export class RenderTarget {
this.width = width;
this.height = height;
this.depth = depth;
this.stencil = stencil;
this.buffer = this.gl.createFramebuffer();
this.target = target;
this.gl.renderer.bindFramebuffer(this);
Expand All @@ -42,6 +43,7 @@ export class RenderTarget {
height,
wrapS,
wrapT,
wrapR,
minFilter,
magFilter,
type,
Expand Down Expand Up @@ -71,12 +73,12 @@ export class RenderTarget {
height,
minFilter: this.gl.NEAREST,
magFilter: this.gl.NEAREST,
format: this.gl.DEPTH_COMPONENT,
internalFormat: gl.renderer.isWebgl2 ? this.gl.DEPTH_COMPONENT16 : this.gl.DEPTH_COMPONENT,
type: this.gl.UNSIGNED_INT,
format: this.stencil ? this.gl.DEPTH_STENCIL : this.gl.DEPTH_COMPONENT,
internalFormat: gl.renderer.isWebgl2 ? (this.stencil ? this.gl.DEPTH24_STENCIL8 : this.gl.DEPTH_COMPONENT16) : this.gl.DEPTH_COMPONENT,
type: this.stencil ? this.gl.UNSIGNED_INT_24_8 : this.gl.UNSIGNED_INT,
});
this.depthTexture.update();
this.gl.framebufferTexture2D(this.target, this.gl.DEPTH_ATTACHMENT, this.gl.TEXTURE_2D, this.depthTexture.texture, 0 /* level */);
this.gl.framebufferTexture2D(this.target, this.stencil ? this.gl.DEPTH_STENCIL_ATTACHMENT : this.gl.DEPTH_ATTACHMENT, this.gl.TEXTURE_2D, this.depthTexture.texture, 0 /* level */);
} else {
// Render buffers
if (depth && !stencil) {
Expand Down
42 changes: 42 additions & 0 deletions src/core/Renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,41 @@ export class Renderer {
this.gl.depthFunc(value);
}

setStencilMask(value) {
if(this.state.stencilMask === value) return;
this.state.stencilMask = value;
this.gl.stencilMask(value)
}

setStencilFunc(func, ref, mask) {

if((this.state.stencilFunc === func) &&
(this.state.stencilRef === ref) &&
(this.state.stencilFuncMask === mask)
) return;

this.state.stencilFunc = func || this.gl.ALWAYS;
this.state.stencilRef = ref || 0;
this.state.stencilFuncMask = mask || 0;

this.gl.stencilFunc(func || this.gl.ALWAYS, ref || 0, mask || 0);
}

setStencilOp(stencilFail, depthFail, depthPass) {

if(this.state.stencilFail === stencilFail &&
this.state.stencilDepthFail === depthFail &&
this.state.stencilDepthPass === depthPass
) return;

this.state.stencilFail = stencilFail;
this.state.stencilDepthFail = depthFail;
this.state.stencilDepthPass = depthPass;

this.gl.stencilOp(stencilFail, depthFail, depthPass);

}

activeTexture(value) {
if (this.state.activeTextureUnit === value) return;
this.state.activeTextureUnit = value;
Expand Down Expand Up @@ -334,6 +369,13 @@ export class Renderer {
this.enable(this.gl.DEPTH_TEST);
this.setDepthMask(true);
}

// Same for stencil
if(this.stencil || (!target || target.stencil)) {
this.enable(this.gl.STENCIL_TEST);
this.setStencilMask(0xff)
}

this.gl.clear(
(this.color ? this.gl.COLOR_BUFFER_BIT : 0) |
(this.depth ? this.gl.DEPTH_BUFFER_BIT : 0) |
Expand Down

0 comments on commit bcd38cc

Please sign in to comment.