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 }