1 /* 2 Inochi2D Mask 3 4 Copyright © 2020, Inochi2D Project 5 Distributed under the 2-Clause BSD License, see LICENSE file. 6 7 Authors: Luna Nielsen 8 */ 9 module inochi2d.core.nodes.mask; 10 import inochi2d.core.nodes.drawable; 11 import inochi2d.core; 12 import inochi2d.math; 13 import bindbc.opengl; 14 import std.exception; 15 import std.algorithm.mutation : copy; 16 17 public import inochi2d.core.meshdata; 18 19 20 package(inochi2d) { 21 private { 22 Shader maskShader; 23 } 24 25 /* GLSL Uniforms (Normal) */ 26 GLint mvp; 27 GLint offset; 28 29 void inInitMask() { 30 inRegisterNodeType!Part; 31 maskShader = new Shader(import("mask.vert"), import("mask.frag")); 32 offset = maskShader.getUniformLocation("offset"); 33 mvp = maskShader.getUniformLocation("mvp"); 34 } 35 } 36 37 /** 38 Dynamic Mask Part 39 */ 40 @TypeId("Mask") 41 class Mask : Drawable { 42 private: 43 this() { } 44 45 /* 46 RENDERING 47 */ 48 void drawSelf() { 49 50 // Bind the vertex array 51 incDrawableBindVAO(); 52 53 maskShader.use(); 54 maskShader.setUniform(offset, data.origin); 55 maskShader.setUniform(mvp, inGetCamera().matrix * transform.matrix()); 56 57 // Enable points array 58 glEnableVertexAttribArray(0); 59 glBindBuffer(GL_ARRAY_BUFFER, vbo); 60 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, null); 61 62 // Bind index buffer 63 this.bindIndex(); 64 65 // Disable the vertex attribs after use 66 glDisableVertexAttribArray(0); 67 } 68 69 protected: 70 override 71 void renderMask(bool dodge = false) { 72 73 // Enable writing to stencil buffer and disable writing to color buffer 74 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 75 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); 76 glStencilFunc(GL_ALWAYS, dodge ? 0 : 1, 0xFF); 77 glStencilMask(0xFF); 78 79 // Draw ourselves to the stencil buffer 80 drawSelf(); 81 82 // Disable writing to stencil buffer and enable writing to color buffer 83 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 84 } 85 86 override 87 string typeId() { return "Mask"; } 88 89 public: 90 91 /** 92 Constructs a new mask 93 */ 94 this(MeshData data, Node parent = null) { 95 this(data, inCreateUUID(), parent); 96 } 97 98 /** 99 Constructs a new mask 100 */ 101 this(MeshData data, uint uuid, Node parent = null) { 102 super(data, uuid, parent); 103 } 104 105 override 106 void rebuffer(ref MeshData data) { 107 super.rebuffer(data); 108 } 109 110 override 111 void drawOne() { 112 super.drawOne(); 113 } 114 115 override 116 void drawOneDirect(bool forMasking) { 117 this.drawSelf(); 118 } 119 120 override 121 void draw() { 122 if (!enabled) return; 123 foreach(child; children) { 124 child.draw(); 125 } 126 } 127 128 }