Monad Engine da02fba2
> Undercity Codex_
Loading...
Searching...
No Matches
PostProcess.cpp
Go to the documentation of this file.
2
3#include "Common.h"
4#include "Constants.h"
5#include "Engine.h"
6#include "Log.h"
9#include "io/FileSystem.h"
10
11namespace mnd
12{
13
14namespace
15{
16constexpr const char *kOutlineVertPath = "shaders/outline.vert";
17constexpr const char *kOutlineFragPath = "shaders/outline.frag";
18
19GLuint CompileStage(GLenum stage, const char *src)
20{
21 GLuint s = glCreateShader(stage);
22 glShaderSource(s, 1, &src, nullptr);
23 glCompileShader(s);
24 GLint ok = 0;
25 glGetShaderiv(s, GL_COMPILE_STATUS, &ok);
26 if (ok == 0)
27 {
28 char log[kShaderInfoLogSize];
29 glGetShaderInfoLog(s, sizeof(log), nullptr, log);
30 LOG_ERROR("Outline shader compile failed: %s", log);
31 }
32 return s;
33}
34
35GLuint LinkProgram(GLuint vs, GLuint fs)
36{
37 GLuint p = glCreateProgram();
38 glAttachShader(p, vs);
39 glAttachShader(p, fs);
40 glLinkProgram(p);
41 GLint ok = 0;
42 glGetProgramiv(p, GL_LINK_STATUS, &ok);
43 if (ok == 0)
44 {
45 char log[kShaderInfoLogSize];
46 glGetProgramInfoLog(p, sizeof(log), nullptr, log);
47 LOG_ERROR("Outline program link failed: %s", log);
48 glDeleteProgram(p);
49 return 0;
50 }
51 return p;
52}
53
54const char *FramebufferStatusName(GLenum status)
55{
56 switch (status)
57 {
58 case GL_FRAMEBUFFER_COMPLETE:
59 return "complete";
60 case GL_FRAMEBUFFER_UNDEFINED:
61 return "undefined";
62 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
63 return "incomplete attachment";
64 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
65 return "missing attachment";
66 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
67 return "incomplete draw buffer";
68 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
69 return "incomplete read buffer";
70 case GL_FRAMEBUFFER_UNSUPPORTED:
71 return "unsupported";
72 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
73 return "incomplete multisample";
74 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
75 return "incomplete layer targets";
76 default:
77 return "unknown";
78 }
79}
80} // namespace
81
83{
85 auto vsSrc = fs.LoadAssetFileText(kOutlineVertPath);
86 auto fsSrc = fs.LoadAssetFileText(kOutlineFragPath);
87 if (vsSrc.empty() || fsSrc.empty())
88 {
89 LOG_ERROR("PostProcess: failed to load outline shader sources");
90 return false;
91 }
92
93 GLuint vs = CompileStage(GL_VERTEX_SHADER, vsSrc.c_str());
94 GLuint fs2 = CompileStage(GL_FRAGMENT_SHADER, fsSrc.c_str());
95 m_program = LinkProgram(vs, fs2);
96 glDeleteShader(vs);
97 glDeleteShader(fs2);
98 if (m_program == 0)
99 {
100 return false;
101 }
102
103 glGenVertexArrays(1, &m_vao);
104
105 m_locColor = glGetUniformLocation(m_program, "uColor");
106 m_locNormal = glGetUniformLocation(m_program, "uNormal");
107 m_locDepth = glGetUniformLocation(m_program, "uDepth");
108 m_locTexel = glGetUniformLocation(m_program, "uTexel");
109 m_locDepthStr = glGetUniformLocation(m_program, "uDepthEdgeStrength");
110 m_locNormalStr = glGetUniformLocation(m_program, "uNormalEdgeStrength");
111 m_locPixelSize = glGetUniformLocation(m_program, "uPixelSize");
112
113 return true;
114}
115
117{
118 DestroyFBO();
119 if (m_vao != 0)
120 {
121 glDeleteVertexArrays(1, &m_vao);
122 m_vao = 0;
123 }
124 if (m_program != 0)
125 {
126 glDeleteProgram(m_program);
127 m_program = 0;
128 }
129}
130
131void PostProcess::DestroyFBO()
132{
133 if (m_color != 0) glDeleteTextures(1, &m_color);
134 if (m_fbo != 0) glDeleteFramebuffers(1, &m_fbo);
135 m_color = m_fbo = 0;
136 m_w = m_h = 0;
137}
138
139bool PostProcess::CreateFBO(int w, int h)
140{
141 if (w <= 0 || h <= 0)
142 {
143 LOG_ERROR("PostProcess::CreateFBO called with invalid size %dx%d", w, h);
144 return false;
145 }
146
147 DestroyFBO();
148 glGenFramebuffers(1, &m_fbo);
149 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
150
151 glGenTextures(1, &m_color);
152 glBindTexture(GL_TEXTURE_2D, m_color);
153 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
155 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
156 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
157 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
158 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color, 0);
159 glDrawBuffer(GL_COLOR_ATTACHMENT0);
160
161 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
162 glBindFramebuffer(GL_FRAMEBUFFER, 0);
163 if (status != GL_FRAMEBUFFER_COMPLETE)
164 {
165 LOG_ERROR("PostProcess FBO incomplete (%s, 0x%x) at %dx%d",
166 FramebufferStatusName(status),
167 status,
168 w,
169 h);
170 DestroyFBO();
171 return false;
172 }
173 m_w = w;
174 m_h = h;
175 return true;
176}
177
178void PostProcess::Resize(int w, int h)
179{
180 if (w == m_w && h == m_h && m_fbo != 0)
181 {
182 return;
183 }
184 CreateFBO(w, h);
185}
186
187void PostProcess::RunOutline(const RenderTarget &scene, const CameraData & /*cam*/)
188{
189 if (m_program == 0 || m_vao == 0 || !scene.IsValid())
190 {
191 return;
192 }
193
194 Resize(scene.Width(), scene.Height());
195 if (m_fbo == 0 || m_color == 0 || m_w <= 0 || m_h <= 0)
196 {
197 return;
198 }
199
201 int pixelSize = settings.pixelSize;
202 if (pixelSize < 1)
203 {
204 pixelSize = 1;
205 }
206 else if (pixelSize > 32)
207 {
208 pixelSize = 32;
209 }
210
211 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
212 glDrawBuffer(GL_COLOR_ATTACHMENT0);
213 glViewport(0, 0, m_w, m_h);
214 glDisable(GL_DEPTH_TEST);
215 glDisable(GL_CULL_FACE);
216 glDisable(GL_BLEND);
217
218 glUseProgram(m_program);
219
220 glActiveTexture(GL_TEXTURE0);
221 glBindTexture(GL_TEXTURE_2D, scene.ColorTex());
222 if (m_locColor >= 0) glUniform1i(m_locColor, 0);
223
224 glActiveTexture(GL_TEXTURE1);
225 glBindTexture(GL_TEXTURE_2D, scene.NormalTex());
226 if (m_locNormal >= 0) glUniform1i(m_locNormal, 1);
227
228 glActiveTexture(GL_TEXTURE2);
229 glBindTexture(GL_TEXTURE_2D, scene.DepthTex());
230 if (m_locDepth >= 0) glUniform1i(m_locDepth, 2);
231
232 if (m_locTexel >= 0) glUniform2f(m_locTexel, 1.0F / static_cast<float>(m_w), 1.0F / static_cast<float>(m_h));
233 if (m_locDepthStr >= 0) glUniform1f(m_locDepthStr, depthEdgeStrength);
234 if (m_locNormalStr >= 0) glUniform1f(m_locNormalStr, normalEdgeStrength);
235 if (m_locPixelSize >= 0) glUniform1f(m_locPixelSize, static_cast<float>(pixelSize));
236
237 glBindVertexArray(m_vao);
238 glDrawArrays(GL_TRIANGLES, 0, 3);
239 glBindVertexArray(0);
240
241 glUseProgram(0);
242 glEnable(GL_DEPTH_TEST);
243}
244
245} // namespace mnd
Engine-wide compile-time tunables and ANSI colour codes.
constexpr mnd::i32 kShaderInfoLogSize
Definition Constants.h:57
int GLint
Definition GLForward.h:13
unsigned int GLenum
Definition GLForward.h:12
unsigned int GLuint
Definition GLForward.h:11
Console logging macros for all engine and game code.
#define LOG_ERROR(fmt,...)
Definition Log.h:81
Three.js-style pixel-art post-pass.
Per-frame renderer tuning knobs (PSX-style pixelation, fog, ambient).
Offscreen FBO with colour, view-normal and depth attachments.
FileSystem & GetFileSystem()
Returns the file system helper for asset-relative path resolution.
Definition Engine.cpp:453
static Engine & GetInstance()
Returns the single Engine instance (created on first call).
Definition Engine.cpp:59
RenderSettings & GetRenderSettings()
Mutable render settings edited by the Editor's Render panel.
Definition Engine.h:152
std::string LoadAssetFileText(const std::string &relativePath)
Load a text file from the assets directory into a string.
float normalEdgeStrength
Definition PostProcess.h:43
float depthEdgeStrength
Definition PostProcess.h:42
void Resize(int w, int h)
Lazily resize the internal output FBO to match the scene target.
void RunOutline(const RenderTarget &scene, const CameraData &cam)
Run the outline pass, sampling scene and writing to OutputTex().
Offscreen FBO with MRT colour + sampleable depth for low-resolution rendering.
int Width() const
int Height() const
bool IsValid() const
GLuint NormalTex() const
GLuint DepthTex() const
GLuint ColorTex() const
Per-frame camera matrices and world-space position.
Definition Common.h:35