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!Mask; 31 version(InDoesRender) { 32 maskShader = new Shader(import("mask.vert"), import("mask.frag")); 33 offset = maskShader.getUniformLocation("offset"); 34 mvp = maskShader.getUniformLocation("mvp"); 35 } 36 } 37 } 38 39 /** 40 Dynamic Mask Part 41 */ 42 @TypeId("Mask") 43 class Mask : Drawable { 44 private: 45 this() { } 46 47 /* 48 RENDERING 49 */ 50 void drawSelf() { 51 52 // Bind the vertex array 53 incDrawableBindVAO(); 54 55 maskShader.use(); 56 maskShader.setUniform(offset, data.origin); 57 maskShader.setUniform(mvp, inGetCamera().matrix * transform.matrix()); 58 59 // Enable points array 60 glEnableVertexAttribArray(0); 61 glBindBuffer(GL_ARRAY_BUFFER, vbo); 62 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, null); 63 64 // Bind index buffer 65 this.bindIndex(); 66 67 // Disable the vertex attribs after use 68 glDisableVertexAttribArray(0); 69 } 70 71 protected: 72 73 override 74 string typeId() { return "Mask"; } 75 76 public: 77 /** 78 Constructs a new mask 79 */ 80 this(Node parent = null) { 81 MeshData empty; 82 this(empty, inCreateUUID(), parent); 83 } 84 85 /** 86 Constructs a new mask 87 */ 88 this(MeshData data, Node parent = null) { 89 this(data, inCreateUUID(), parent); 90 } 91 92 /** 93 Constructs a new mask 94 */ 95 this(MeshData data, uint uuid, Node parent = null) { 96 super(data, uuid, parent); 97 } 98 99 override 100 void renderMask(bool dodge = false) { 101 102 // Enable writing to stencil buffer and disable writing to color buffer 103 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 104 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); 105 glStencilFunc(GL_ALWAYS, dodge ? 0 : 1, 0xFF); 106 glStencilMask(0xFF); 107 108 // Draw ourselves to the stencil buffer 109 drawSelf(); 110 111 // Disable writing to stencil buffer and enable writing to color buffer 112 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 113 } 114 115 override 116 void rebuffer(ref MeshData data) { 117 super.rebuffer(data); 118 } 119 120 override 121 void drawOne() { 122 super.drawOne(); 123 } 124 125 override 126 void drawOneDirect(bool forMasking) { 127 this.drawSelf(); 128 } 129 130 override 131 void draw() { 132 if (!enabled) return; 133 foreach(child; children) { 134 child.draw(); 135 } 136 } 137 138 }