9#include "io/FileSystem.h"
16constexpr const char *kOutlineVertPath =
"shaders/outline.vert";
17constexpr const char *kOutlineFragPath =
"shaders/outline.frag";
21 GLuint s = glCreateShader(stage);
22 glShaderSource(s, 1, &src,
nullptr);
25 glGetShaderiv(s, GL_COMPILE_STATUS, &ok);
29 glGetShaderInfoLog(s,
sizeof(log),
nullptr, log);
30 LOG_ERROR(
"Outline shader compile failed: %s", log);
37 GLuint p = glCreateProgram();
38 glAttachShader(p, vs);
39 glAttachShader(p, fs);
42 glGetProgramiv(p, GL_LINK_STATUS, &ok);
46 glGetProgramInfoLog(p,
sizeof(log),
nullptr, log);
47 LOG_ERROR(
"Outline program link failed: %s", log);
54const char *FramebufferStatusName(
GLenum status)
58 case GL_FRAMEBUFFER_COMPLETE:
60 case GL_FRAMEBUFFER_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:
72 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
73 return "incomplete multisample";
74 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
75 return "incomplete layer targets";
86 auto fsSrc = fs.LoadAssetFileText(kOutlineFragPath);
87 if (vsSrc.empty() || fsSrc.empty())
89 LOG_ERROR(
"PostProcess: failed to load outline shader sources");
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);
103 glGenVertexArrays(1, &m_vao);
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");
121 glDeleteVertexArrays(1, &m_vao);
126 glDeleteProgram(m_program);
131void PostProcess::DestroyFBO()
133 if (m_color != 0) glDeleteTextures(1, &m_color);
134 if (m_fbo != 0) glDeleteFramebuffers(1, &m_fbo);
139bool PostProcess::CreateFBO(
int w,
int h)
141 if (w <= 0 || h <= 0)
143 LOG_ERROR(
"PostProcess::CreateFBO called with invalid size %dx%d", w, h);
148 glGenFramebuffers(1, &m_fbo);
149 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
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);
161 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
162 glBindFramebuffer(GL_FRAMEBUFFER, 0);
163 if (status != GL_FRAMEBUFFER_COMPLETE)
165 LOG_ERROR(
"PostProcess FBO incomplete (%s, 0x%x) at %dx%d",
166 FramebufferStatusName(status),
180 if (w == m_w && h == m_h && m_fbo != 0)
189 if (m_program == 0 || m_vao == 0 || !scene.
IsValid())
195 if (m_fbo == 0 || m_color == 0 || m_w <= 0 || m_h <= 0)
206 else if (pixelSize > 32)
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);
218 glUseProgram(m_program);
220 glActiveTexture(GL_TEXTURE0);
221 glBindTexture(GL_TEXTURE_2D, scene.
ColorTex());
222 if (m_locColor >= 0) glUniform1i(m_locColor, 0);
224 glActiveTexture(GL_TEXTURE1);
225 glBindTexture(GL_TEXTURE_2D, scene.
NormalTex());
226 if (m_locNormal >= 0) glUniform1i(m_locNormal, 1);
228 glActiveTexture(GL_TEXTURE2);
229 glBindTexture(GL_TEXTURE_2D, scene.
DepthTex());
230 if (m_locDepth >= 0) glUniform1i(m_locDepth, 2);
232 if (m_locTexel >= 0) glUniform2f(m_locTexel, 1.0F /
static_cast<float>(m_w), 1.0F /
static_cast<float>(m_h));
235 if (m_locPixelSize >= 0) glUniform1f(m_locPixelSize,
static_cast<float>(pixelSize));
237 glBindVertexArray(m_vao);
238 glDrawArrays(GL_TRIANGLES, 0, 3);
239 glBindVertexArray(0);
242 glEnable(GL_DEPTH_TEST);
Engine-wide compile-time tunables and ANSI colour codes.
constexpr mnd::i32 kShaderInfoLogSize
Console logging macros for all engine and game code.
#define LOG_ERROR(fmt,...)
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.
static Engine & GetInstance()
Returns the single Engine instance (created on first call).
RenderSettings & GetRenderSettings()
Mutable render settings edited by the Editor's Render panel.
std::string LoadAssetFileText(const std::string &relativePath)
Load a text file from the assets directory into a string.
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.
Per-frame camera matrices and world-space position.