1 /*
2 Copyright (c) 2019-2020 Timur Gafarov
3 
4 Boost Software License - Version 1.0 - August 17th, 2003
5 Permission is hereby granted, free of charge, to any person or organization
6 obtaining a copy of the software and accompanying documentation covered by
7 this license (the "Software") to use, reproduce, display, distribute,
8 execute, and transmit the Software, and to prepare derivative works of the
9 Software, and to permit third-parties to whom the Software is furnished to
10 do so, all subject to the following:
11 
12 The copyright notices in the Software and this entire statement, including
13 the above license grant, this restriction and the following disclaimer,
14 must be included in all copies of the Software, in whole or in part, and
15 all derivative works of the Software, unless such copies or derivative
16 works are solely in the form of machine-executable object code generated by
17 a source language processor.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 */
27 
28 module dagon.render.gbuffer;
29 
30 import std.stdio;
31 
32 import dlib.core.memory;
33 import dlib.core.ownership;
34 import dlib.image.color;
35 
36 import dagon.core.bindings;
37 import dagon.render.framebuffer;
38 
39 class GBuffer: Owner
40 {
41     uint width;
42     uint height;
43 
44     GLuint framebuffer;
45     GLuint colorTexture = 0;
46     GLuint depthTexture = 0;
47     GLuint normalTexture = 0;
48     GLuint pbrTexture = 0;
49     GLuint velocityTexture = 0;
50     Framebuffer radiance;
51     
52     this(uint w, uint h, Framebuffer radiance, Owner owner)
53     {
54         super(owner);
55         
56         width = w;
57         height = h;
58         this.radiance = radiance;
59         createFramebuffer();
60     }
61     
62     void createFramebuffer()
63     {
64         releaseFramebuffer();
65         
66         glActiveTexture(GL_TEXTURE0);
67         
68         glGenTextures(1, &colorTexture);
69         glBindTexture(GL_TEXTURE_2D, colorTexture);
70         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
71         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
72         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
73         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
74         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
75         glBindTexture(GL_TEXTURE_2D, 0);
76         
77         glGenTextures(1, &depthTexture);
78         glBindTexture(GL_TEXTURE_2D, depthTexture);
79         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
80         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
81         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
82         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
83         glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, null);
84         glBindTexture(GL_TEXTURE_2D, 0);
85         
86         glGenTextures(1, &normalTexture);
87         glBindTexture(GL_TEXTURE_2D, normalTexture);
88         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
89         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
90         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
91         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
92         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, null);
93         glBindTexture(GL_TEXTURE_2D, 0);
94         
95         glGenTextures(1, &pbrTexture);
96         glBindTexture(GL_TEXTURE_2D, pbrTexture);
97         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
98         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
99         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
100         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
101         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
102         glBindTexture(GL_TEXTURE_2D, 0);
103         
104         glGenTextures(1, &velocityTexture);
105         glBindTexture(GL_TEXTURE_2D, velocityTexture);
106         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
107         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
108         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
109         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
110         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, null);
111         glBindTexture(GL_TEXTURE_2D, 0);
112         
113         glGenFramebuffers(1, &framebuffer);
114         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
115         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
116         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, normalTexture, 0);
117         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, pbrTexture, 0);
118         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, radiance.colorTexture(), 0);
119         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, velocityTexture, 0);
120         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
121         
122         GLenum[5] drawBuffers = 
123         [
124             GL_COLOR_ATTACHMENT0, 
125             GL_COLOR_ATTACHMENT1, 
126             GL_COLOR_ATTACHMENT2, 
127             GL_COLOR_ATTACHMENT3, 
128             GL_COLOR_ATTACHMENT4
129         ];
130         
131         glDrawBuffers(drawBuffers.length, drawBuffers.ptr);
132 
133         GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
134         if (status != GL_FRAMEBUFFER_COMPLETE)
135             writeln(status);
136 
137         glBindFramebuffer(GL_FRAMEBUFFER, 0);
138     }
139     
140     void releaseFramebuffer()
141     {
142         if (glIsFramebuffer(framebuffer))
143             glDeleteFramebuffers(1, &framebuffer);
144         
145         if (glIsTexture(colorTexture))
146             glDeleteTextures(1, &colorTexture);
147         
148         if (glIsTexture(depthTexture))
149             glDeleteTextures(1, &depthTexture);
150             
151         if (glIsTexture(normalTexture))
152             glDeleteTextures(1, &normalTexture);
153             
154         if (glIsTexture(pbrTexture))
155             glDeleteTextures(1, &pbrTexture);
156             
157         if (glIsTexture(velocityTexture))
158             glDeleteTextures(1, &velocityTexture);
159     }
160     
161     ~this()
162     {
163         releaseFramebuffer();
164     }
165     
166     void bind()
167     {
168         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
169     }
170 
171     void unbind()
172     {
173         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
174     }
175     
176     void clear()
177     {
178         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
179 
180         glScissor(0, 0, width, height);
181         glViewport(0, 0, width, height);
182 
183         glClear(GL_DEPTH_BUFFER_BIT);
184         
185         Color4f zero = Color4f(0, 0, 0, 0);
186         glClearBufferfv(GL_COLOR, 0, zero.arrayof.ptr);
187         glClearBufferfv(GL_COLOR, 1, zero.arrayof.ptr);
188         glClearBufferfv(GL_COLOR, 2, zero.arrayof.ptr);
189         
190         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
191     }
192     
193     void resize(uint w, uint h)
194     {
195         width = w;
196         height = h;
197         createFramebuffer();
198     }
199 }