Merge pull request #101 from Bottinator22/main
Post-processing layer support for mods
This commit is contained in:
commit
4496cc17af
@ -9,5 +9,6 @@
|
|||||||
"deployCinematicBase" : {
|
"deployCinematicBase" : {
|
||||||
"scissor" : false,
|
"scissor" : false,
|
||||||
"letterbox" : false
|
"letterbox" : false
|
||||||
}
|
},
|
||||||
|
"postProcessLayers": []
|
||||||
}
|
}
|
7
assets/opensb/rendering/effects/basic.vert
Normal file
7
assets/opensb/rendering/effects/basic.vert
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#version 140
|
||||||
|
|
||||||
|
in vec2 vertexPosition;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(vertexPosition, 0.0, 1.0);
|
||||||
|
}
|
@ -153,12 +153,32 @@ OpenGlRenderer::GlFrameBuffer::GlFrameBuffer(Json const& fbConfig) : config(fbCo
|
|||||||
GLenum target = multisample ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
|
GLenum target = multisample ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
|
||||||
glBindTexture(target, texture->glTextureId());
|
glBindTexture(target, texture->glTextureId());
|
||||||
|
|
||||||
Vec2U size = jsonToVec2U(config.getArray("size", { 256, 256 }));
|
sizeDiv = config.getUInt("sizeDiv",1);
|
||||||
|
Vec2U size = jsonToVec2U(config.getArray("size", { 256, 256 }))/sizeDiv;
|
||||||
|
|
||||||
if (multisample)
|
if (multisample)
|
||||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, multisample, GL_RGBA8, size[0], size[1], GL_TRUE);
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, multisample, GL_RGBA8, size[0], size[1], GL_TRUE);
|
||||||
else
|
else {
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size[0], size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size[0], size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
}
|
||||||
|
auto addressing = TextureAddressingNames.getLeft(config.getString("textureAddressing", "clamp"));
|
||||||
|
auto filtering = TextureFilteringNames.getLeft(config.getString("textureFiltering", "nearest"));
|
||||||
|
if (addressing == TextureAddressing::Clamp) {
|
||||||
|
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
} else {
|
||||||
|
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
}
|
||||||
|
if (!multisample) {
|
||||||
|
if (filtering == TextureFiltering::Nearest) {
|
||||||
|
glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
} else {
|
||||||
|
glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glGenFramebuffers(1, &id);
|
glGenFramebuffers(1, &id);
|
||||||
if (!id)
|
if (!id)
|
||||||
@ -184,6 +204,7 @@ void OpenGlRenderer::loadConfig(Json const& config) {
|
|||||||
for (auto& pair : config.getObject("frameBuffers", {})) {
|
for (auto& pair : config.getObject("frameBuffers", {})) {
|
||||||
Json config = pair.second;
|
Json config = pair.second;
|
||||||
config = config.set("multisample", m_multiSampling);
|
config = config.set("multisample", m_multiSampling);
|
||||||
|
Logger::info("Creating framebuffer {}", pair.first);
|
||||||
m_frameBuffers[pair.first] = make_ref<GlFrameBuffer>(config);
|
m_frameBuffers[pair.first] = make_ref<GlFrameBuffer>(config);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -257,8 +278,9 @@ void OpenGlRenderer::loadEffectConfig(String const& name, Json const& effectConf
|
|||||||
auto& effect = m_effects.emplace(name, Effect()).first->second;
|
auto& effect = m_effects.emplace(name, Effect()).first->second;
|
||||||
effect.program = m_program;
|
effect.program = m_program;
|
||||||
effect.config = effectConfig;
|
effect.config = effectConfig;
|
||||||
|
effect.includeVBTextures = effectConfig.getBool("includeVBTextures",true);
|
||||||
m_currentEffect = &effect;
|
m_currentEffect = &effect;
|
||||||
setupGlUniforms(effect);
|
setupGlUniforms(effect,m_screenSize);
|
||||||
|
|
||||||
for (auto const& p : effectConfig.getObject("effectParameters", {})) {
|
for (auto const& p : effectConfig.getObject("effectParameters", {})) {
|
||||||
EffectParameter effectParameter;
|
EffectParameter effectParameter;
|
||||||
@ -307,7 +329,7 @@ void OpenGlRenderer::loadEffectConfig(String const& name, Json const& effectConf
|
|||||||
// Assign each texture parameter a texture unit starting with MultiTextureCount, the first
|
// Assign each texture parameter a texture unit starting with MultiTextureCount, the first
|
||||||
// few texture units are used by the primary textures being drawn. Currently,
|
// few texture units are used by the primary textures being drawn. Currently,
|
||||||
// maximum texture units are not checked.
|
// maximum texture units are not checked.
|
||||||
unsigned parameterTextureUnit = MultiTextureCount;
|
unsigned parameterTextureUnit = effect.includeVBTextures ? MultiTextureCount : 0;
|
||||||
|
|
||||||
for (auto const& p : effectConfig.getObject("effectTextures", {})) {
|
for (auto const& p : effectConfig.getObject("effectTextures", {})) {
|
||||||
EffectTexture effectTexture;
|
EffectTexture effectTexture;
|
||||||
@ -394,19 +416,39 @@ bool OpenGlRenderer::switchEffectConfig(String const& name) {
|
|||||||
if (auto blitFrameBufferId = effect.config.optString("blitFrameBuffer"))
|
if (auto blitFrameBufferId = effect.config.optString("blitFrameBuffer"))
|
||||||
blitGlFrameBuffer(getGlFrameBuffer(*blitFrameBufferId));
|
blitGlFrameBuffer(getGlFrameBuffer(*blitFrameBufferId));
|
||||||
|
|
||||||
if (auto frameBufferId = effect.config.optString("frameBuffer"))
|
auto effectScreenSize = m_screenSize;
|
||||||
switchGlFrameBuffer(getGlFrameBuffer(*frameBufferId));
|
if (auto frameBufferId = effect.config.optString("frameBuffer")) {
|
||||||
else {
|
auto buf = getGlFrameBuffer(*frameBufferId);
|
||||||
|
switchGlFrameBuffer(buf);
|
||||||
|
effectScreenSize = m_screenSize/(buf->sizeDiv);
|
||||||
|
} else {
|
||||||
m_currentFrameBuffer.reset();
|
m_currentFrameBuffer.reset();
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
glUseProgram(m_program = effect.program);
|
glUseProgram(m_program = effect.program);
|
||||||
setupGlUniforms(effect);
|
setupGlUniforms(effect,effectScreenSize);
|
||||||
m_currentEffect = &effect;
|
m_currentEffect = &effect;
|
||||||
|
|
||||||
setEffectParameter("vertexRounding", m_multiSampling > 0);
|
setEffectParameter("vertexRounding", m_multiSampling > 0);
|
||||||
|
if (auto fbts = effect.config.optArray("frameBufferTextures")) {
|
||||||
|
for (auto const& fbt : *fbts) {
|
||||||
|
if (auto frameBufferId = fbt.optString("framebuffer")) {
|
||||||
|
auto textureUniform=fbt.getString("texture");
|
||||||
|
auto ptr = m_currentEffect->textures.ptr(textureUniform);
|
||||||
|
if (ptr) {
|
||||||
|
if (!ptr->textureValue || ptr->textureValue->textureId == 0) {
|
||||||
|
auto texture = getGlFrameBuffer(*frameBufferId)->texture;
|
||||||
|
ptr->textureValue = texture;
|
||||||
|
if (ptr->textureSizeUniform != -1) {
|
||||||
|
auto textureSize = ptr->textureValue->glTextureSize();
|
||||||
|
glUniform2f(ptr->textureSizeUniform, textureSize[0], textureSize[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,10 +549,10 @@ void OpenGlRenderer::setScreenSize(Vec2U screenSize) {
|
|||||||
for (auto& frameBuffer : m_frameBuffers) {
|
for (auto& frameBuffer : m_frameBuffers) {
|
||||||
if (unsigned multisample = frameBuffer.second->multisample) {
|
if (unsigned multisample = frameBuffer.second->multisample) {
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, frameBuffer.second->texture->glTextureId());
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, frameBuffer.second->texture->glTextureId());
|
||||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, multisample, GL_RGBA8, m_screenSize[0], m_screenSize[1], GL_TRUE);
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, multisample, GL_RGBA8, m_screenSize[0]/frameBuffer.second->sizeDiv, m_screenSize[1]/frameBuffer.second->sizeDiv, GL_TRUE);
|
||||||
} else {
|
} else {
|
||||||
glBindTexture(GL_TEXTURE_2D, frameBuffer.second->texture->glTextureId());
|
glBindTexture(GL_TEXTURE_2D, frameBuffer.second->texture->glTextureId());
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_screenSize[0], m_screenSize[1], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_screenSize[0]/frameBuffer.second->sizeDiv, m_screenSize[1]/frameBuffer.second->sizeDiv, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -963,11 +1005,13 @@ void OpenGlRenderer::renderGlBuffer(GlRenderBuffer const& renderBuffer, Mat3F co
|
|||||||
for (auto const& vb : renderBuffer.vertexBuffers) {
|
for (auto const& vb : renderBuffer.vertexBuffers) {
|
||||||
glUniformMatrix3fv(m_vertexTransformUniform, 1, GL_TRUE, transformation.ptr());
|
glUniformMatrix3fv(m_vertexTransformUniform, 1, GL_TRUE, transformation.ptr());
|
||||||
|
|
||||||
|
if (m_currentEffect->includeVBTextures) {
|
||||||
for (size_t i = 0; i < vb.textures.size(); ++i) {
|
for (size_t i = 0; i < vb.textures.size(); ++i) {
|
||||||
glUniform2f(m_textureSizeUniforms[i], vb.textures[i].size[0], vb.textures[i].size[1]);
|
glUniform2f(m_textureSizeUniforms[i], vb.textures[i].size[0], vb.textures[i].size[1]);
|
||||||
glActiveTexture(GL_TEXTURE0 + i);
|
glActiveTexture(GL_TEXTURE0 + i);
|
||||||
glBindTexture(GL_TEXTURE_2D, vb.textures[i].texture);
|
glBindTexture(GL_TEXTURE_2D, vb.textures[i].texture);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto const& p : m_currentEffect->textures) {
|
for (auto const& p : m_currentEffect->textures) {
|
||||||
if (p.second.textureValue) {
|
if (p.second.textureValue) {
|
||||||
@ -993,7 +1037,7 @@ void OpenGlRenderer::renderGlBuffer(GlRenderBuffer const& renderBuffer, Mat3F co
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Assumes the passed effect program is currently in use.
|
//Assumes the passed effect program is currently in use.
|
||||||
void OpenGlRenderer::setupGlUniforms(Effect& effect) {
|
void OpenGlRenderer::setupGlUniforms(Effect& effect, Vec2U screenSize) {
|
||||||
m_positionAttribute = effect.getAttribute("vertexPosition");
|
m_positionAttribute = effect.getAttribute("vertexPosition");
|
||||||
m_colorAttribute = effect.getAttribute("vertexColor");
|
m_colorAttribute = effect.getAttribute("vertexColor");
|
||||||
m_texCoordAttribute = effect.getAttribute("vertexTextureCoordinate");
|
m_texCoordAttribute = effect.getAttribute("vertexTextureCoordinate");
|
||||||
@ -1001,17 +1045,21 @@ void OpenGlRenderer::setupGlUniforms(Effect& effect) {
|
|||||||
|
|
||||||
m_textureUniforms.clear();
|
m_textureUniforms.clear();
|
||||||
m_textureSizeUniforms.clear();
|
m_textureSizeUniforms.clear();
|
||||||
|
if (effect.includeVBTextures) {
|
||||||
for (size_t i = 0; i < MultiTextureCount; ++i) {
|
for (size_t i = 0; i < MultiTextureCount; ++i) {
|
||||||
m_textureUniforms.append(effect.getUniform(strf("texture{}", i).c_str()));
|
m_textureUniforms.append(effect.getUniform(strf("texture{}", i).c_str()));
|
||||||
m_textureSizeUniforms.append(effect.getUniform(strf("textureSize{}", i).c_str()));
|
m_textureSizeUniforms.append(effect.getUniform(strf("textureSize{}", i).c_str()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
m_screenSizeUniform = effect.getUniform("screenSize");
|
m_screenSizeUniform = effect.getUniform("screenSize");
|
||||||
m_vertexTransformUniform = effect.getUniform("vertexTransform");
|
m_vertexTransformUniform = effect.getUniform("vertexTransform");
|
||||||
|
|
||||||
|
if (effect.includeVBTextures) {
|
||||||
for (size_t i = 0; i < MultiTextureCount; ++i)
|
for (size_t i = 0; i < MultiTextureCount; ++i)
|
||||||
glUniform1i(m_textureUniforms[i], i);
|
glUniform1i(m_textureUniforms[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
glUniform2f(m_screenSizeUniform, m_screenSize[0], m_screenSize[1]);
|
glUniform2f(m_screenSizeUniform, screenSize[0], screenSize[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<OpenGlRenderer::GlFrameBuffer> OpenGlRenderer::getGlFrameBuffer(String const& id) {
|
RefPtr<OpenGlRenderer::GlFrameBuffer> OpenGlRenderer::getGlFrameBuffer(String const& id) {
|
||||||
|
@ -180,6 +180,7 @@ private:
|
|||||||
Json config;
|
Json config;
|
||||||
bool blitted = false;
|
bool blitted = false;
|
||||||
unsigned multisample = 0;
|
unsigned multisample = 0;
|
||||||
|
unsigned sizeDiv = 1;
|
||||||
|
|
||||||
GlFrameBuffer(Json const& config);
|
GlFrameBuffer(Json const& config);
|
||||||
~GlFrameBuffer();
|
~GlFrameBuffer();
|
||||||
@ -197,6 +198,7 @@ private:
|
|||||||
|
|
||||||
GLuint getAttribute(String const& name);
|
GLuint getAttribute(String const& name);
|
||||||
GLuint getUniform(String const& name);
|
GLuint getUniform(String const& name);
|
||||||
|
bool includeVBTextures;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool logGlErrorSummary(String prefix);
|
static bool logGlErrorSummary(String prefix);
|
||||||
@ -211,7 +213,7 @@ private:
|
|||||||
|
|
||||||
void renderGlBuffer(GlRenderBuffer const& renderBuffer, Mat3F const& transformation);
|
void renderGlBuffer(GlRenderBuffer const& renderBuffer, Mat3F const& transformation);
|
||||||
|
|
||||||
void setupGlUniforms(Effect& effect);
|
void setupGlUniforms(Effect& effect, Vec2U screenSize);
|
||||||
|
|
||||||
RefPtr<OpenGlRenderer::GlFrameBuffer> getGlFrameBuffer(String const& id);
|
RefPtr<OpenGlRenderer::GlFrameBuffer> getGlFrameBuffer(String const& id);
|
||||||
void blitGlFrameBuffer(RefPtr<OpenGlRenderer::GlFrameBuffer> const& frameBuffer);
|
void blitGlFrameBuffer(RefPtr<OpenGlRenderer::GlFrameBuffer> const& frameBuffer);
|
||||||
|
@ -400,6 +400,17 @@ void ClientApplication::render() {
|
|||||||
});
|
});
|
||||||
LogMap::set("client_render_world_painter", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - paintStart));
|
LogMap::set("client_render_world_painter", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - paintStart));
|
||||||
LogMap::set("client_render_world_total", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - totalStart));
|
LogMap::set("client_render_world_total", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - totalStart));
|
||||||
|
|
||||||
|
auto size = Vec2F(renderer->screenSize());
|
||||||
|
auto quad = renderFlatRect(RectF::withSize(size/-2, size), Vec4B(0.0f,0.0f,0.0f,0.0f), 0.0f);
|
||||||
|
for (auto& layer : m_postProcessLayers) {
|
||||||
|
for(unsigned i = 0; i < layer.passes; i++) {
|
||||||
|
for (auto& effect : layer.effects) {
|
||||||
|
renderer->switchEffectConfig(effect);
|
||||||
|
renderer->render(quad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
renderer->switchEffectConfig("interface");
|
renderer->switchEffectConfig("interface");
|
||||||
auto start = Time::monotonicMicroseconds();
|
auto start = Time::monotonicMicroseconds();
|
||||||
@ -451,6 +462,18 @@ void ClientApplication::renderReload() {
|
|||||||
renderer->loadConfig(assets->json("/rendering/opengl.config"));
|
renderer->loadConfig(assets->json("/rendering/opengl.config"));
|
||||||
|
|
||||||
loadEffectConfig("world");
|
loadEffectConfig("world");
|
||||||
|
|
||||||
|
m_postProcessLayers.clear();
|
||||||
|
auto postProcessLayers = assets->json("/client.config:postProcessLayers").toArray();
|
||||||
|
for (auto& layer : postProcessLayers) {
|
||||||
|
List<String> effects;
|
||||||
|
for (auto& effect : layer.getArray("effects")) {
|
||||||
|
auto effectStr = effect.toString();
|
||||||
|
loadEffectConfig(effectStr);
|
||||||
|
effects.append(effectStr);
|
||||||
|
}
|
||||||
|
m_postProcessLayers.append(PostProcessLayer{effects,layer.getUInt("passes",1)});
|
||||||
|
}
|
||||||
loadEffectConfig("interface");
|
loadEffectConfig("interface");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,11 @@ private:
|
|||||||
String password;
|
String password;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PostProcessLayer {
|
||||||
|
List<String> effects;
|
||||||
|
unsigned passes;
|
||||||
|
};
|
||||||
|
|
||||||
void renderReload();
|
void renderReload();
|
||||||
|
|
||||||
void changeState(MainAppState newState);
|
void changeState(MainAppState newState);
|
||||||
@ -99,6 +104,8 @@ private:
|
|||||||
WorldRenderData m_renderData;
|
WorldRenderData m_renderData;
|
||||||
MainInterfacePtr m_mainInterface;
|
MainInterfacePtr m_mainInterface;
|
||||||
|
|
||||||
|
List<PostProcessLayer> m_postProcessLayers;
|
||||||
|
|
||||||
// Valid if main app state == SinglePlayer
|
// Valid if main app state == SinglePlayer
|
||||||
UniverseServerPtr m_universeServer;
|
UniverseServerPtr m_universeServer;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user