Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-30 05:55:41 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-30 05:55:41 +1000
commitfd5247321f36e7cb50dd90cb9bd1b5d60a3a289f (patch)
tree8603fa144341728da19da8df5d6790be792ceef1
parentd5fbd2001b0ad3591a7f969dfd75c809ab55b40e (diff)
Split world & interface shaders
-rw-r--r--assets/opensb/rendering/default.config9
-rw-r--r--assets/opensb/rendering/default.frag27
-rw-r--r--assets/opensb/rendering/default.vert35
-rw-r--r--assets/opensb/rendering/world.config (renamed from assets/opensb/rendering/opengl20.config)8
-rw-r--r--assets/opensb/rendering/world.frag (renamed from assets/opensb/rendering/opengl20.frag)4
-rw-r--r--assets/opensb/rendering/world.vert (renamed from assets/opensb/rendering/opengl20.vert)0
-rw-r--r--source/application/StarRenderer.hpp4
-rw-r--r--source/application/StarRenderer_opengl20.cpp92
-rw-r--r--source/application/StarRenderer_opengl20.hpp19
-rw-r--r--source/client/StarClientApplication.cpp46
-rw-r--r--source/rendering/StarEnvironmentPainter.cpp1
11 files changed, 180 insertions, 65 deletions
diff --git a/assets/opensb/rendering/default.config b/assets/opensb/rendering/default.config
new file mode 100644
index 0000000..5e51afc
--- /dev/null
+++ b/assets/opensb/rendering/default.config
@@ -0,0 +1,9 @@
+{
+ "effectParameters" : {},
+ "effectTextures" : {},
+
+ "effectShaders" : {
+ "vertex" : "default.vert",
+ "fragment" : "default.frag"
+ }
+} \ No newline at end of file
diff --git a/assets/opensb/rendering/default.frag b/assets/opensb/rendering/default.frag
new file mode 100644
index 0000000..0ba2d60
--- /dev/null
+++ b/assets/opensb/rendering/default.frag
@@ -0,0 +1,27 @@
+#version 110
+
+uniform sampler2D texture0;
+uniform sampler2D texture1;
+uniform sampler2D texture2;
+uniform sampler2D texture3;
+
+varying vec2 fragmentTextureCoordinate;
+varying float fragmentTextureIndex;
+varying vec4 fragmentColor;
+
+void main() {
+ vec4 texColor;
+ if (fragmentTextureIndex > 2.9) {
+ texColor = texture2D(texture3, fragmentTextureCoordinate);
+ } else if (fragmentTextureIndex > 1.9) {
+ texColor = texture2D(texture2, fragmentTextureCoordinate);
+ } else if (fragmentTextureIndex > 0.9) {
+ texColor = texture2D(texture1, fragmentTextureCoordinate);
+ } else {
+ texColor = texture2D(texture0, fragmentTextureCoordinate);
+ }
+ if (texColor.a <= 0.0)
+ discard;
+
+ gl_FragColor = texColor * fragmentColor;
+} \ No newline at end of file
diff --git a/assets/opensb/rendering/default.vert b/assets/opensb/rendering/default.vert
new file mode 100644
index 0000000..a8b2751
--- /dev/null
+++ b/assets/opensb/rendering/default.vert
@@ -0,0 +1,35 @@
+#version 110
+
+uniform vec2 textureSize0;
+uniform vec2 textureSize1;
+uniform vec2 textureSize2;
+uniform vec2 textureSize3;
+uniform vec2 screenSize;
+uniform mat3 vertexTransform;
+
+attribute vec2 vertexPosition;
+attribute vec2 vertexTextureCoordinate;
+attribute float vertexTextureIndex;
+attribute vec4 vertexColor;
+attribute float vertexParam1;
+
+varying vec2 fragmentTextureCoordinate;
+varying float fragmentTextureIndex;
+varying vec4 fragmentColor;
+
+void main() {
+ vec2 screenPosition = (vertexTransform * vec3(vertexPosition, 1.0)).xy;
+
+ if (vertexTextureIndex > 2.9) {
+ fragmentTextureCoordinate = vertexTextureCoordinate / textureSize3;
+ } else if (vertexTextureIndex > 1.9) {
+ fragmentTextureCoordinate = vertexTextureCoordinate / textureSize2;
+ } else if (vertexTextureIndex > 0.9) {
+ fragmentTextureCoordinate = vertexTextureCoordinate / textureSize1;
+ } else {
+ fragmentTextureCoordinate = vertexTextureCoordinate / textureSize0;
+ }
+ fragmentTextureIndex = vertexTextureIndex;
+ fragmentColor = vertexColor;
+ gl_Position = vec4(screenPosition / screenSize * 2.0 - 1.0, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/assets/opensb/rendering/opengl20.config b/assets/opensb/rendering/world.config
index 70ff6c7..8dcc3cb 100644
--- a/assets/opensb/rendering/opengl20.config
+++ b/assets/opensb/rendering/world.config
@@ -2,7 +2,7 @@
"effectParameters" : {
"lightMapEnabled" : {
"type" : "bool",
- "default" : false,
+ "default" : true,
"uniform" : "lightMapEnabled"
},
"lightMapScale" : {
@@ -38,7 +38,7 @@
},
"effectShaders" : {
- "vertex" : "opengl20.vert",
- "fragment" : "opengl20.frag"
+ "vertex" : "world.vert",
+ "fragment" : "world.frag"
}
-}
+} \ No newline at end of file
diff --git a/assets/opensb/rendering/opengl20.frag b/assets/opensb/rendering/world.frag
index a57c029..ed197c3 100644
--- a/assets/opensb/rendering/opengl20.frag
+++ b/assets/opensb/rendering/world.frag
@@ -77,7 +77,9 @@ void main() {
vec4 finalColor = texColor * fragmentColor;
float finalLightMapMultiplier = fragmentLightMapMultiplier * lightMapMultiplier;
- if (lightMapEnabled && finalLightMapMultiplier > 0.0)
+ if (texColor.a == 0.99607843137)
+ finalColor.a = fragmentColor.a;
+ else if (lightMapEnabled && finalLightMapMultiplier > 0.0)
finalColor.rgb *= sampleLightMap(fragmentLightMapCoordinate, 1.0 / lightMapSize).rgb * finalLightMapMultiplier;
gl_FragColor = finalColor;
} \ No newline at end of file
diff --git a/assets/opensb/rendering/opengl20.vert b/assets/opensb/rendering/world.vert
index 67998bc..67998bc 100644
--- a/assets/opensb/rendering/opengl20.vert
+++ b/assets/opensb/rendering/world.vert
diff --git a/source/application/StarRenderer.hpp b/source/application/StarRenderer.hpp
index 908f121..58c1c27 100644
--- a/source/application/StarRenderer.hpp
+++ b/source/application/StarRenderer.hpp
@@ -135,13 +135,15 @@ public:
// specific to each type of renderer, so it will be necessary to key the
// configuration off of the renderId string. This should not be called every
// frame, because it will result in a recompile of the underlying shader set.
- virtual void setEffectConfig(Json const& effectConfig, StringMap<String> const& shaders) = 0;
+ virtual void loadEffectConfig(String const& name, Json const& effectConfig, StringMap<String> const& shaders) = 0;
// The effect config will specify named parameters and textures which can be
// set here.
virtual void setEffectParameter(String const& parameterName, RenderEffectParameter const& parameter) = 0;
virtual void setEffectTexture(String const& textureName, Image const& image) = 0;
+ virtual bool switchEffectConfig(String const& name) = 0;
+
// Any further rendering will be scissored based on this rect, specified in
// pixels
virtual void setScissorRect(Maybe<RectI> const& scissorRect) = 0;
diff --git a/source/application/StarRenderer_opengl20.cpp b/source/application/StarRenderer_opengl20.cpp
index 375149e..70185cc 100644
--- a/source/application/StarRenderer_opengl20.cpp
+++ b/source/application/StarRenderer_opengl20.cpp
@@ -93,7 +93,7 @@ OpenGl20Renderer::OpenGl20Renderer() {
TextureFiltering::Nearest);
m_immediateRenderBuffer = createGlRenderBuffer();
- setEffectConfig(JsonObject(), {{"vertex", DefaultVertexShader}, {"fragment", DefaultFragmentShader}});
+ loadEffectConfig("internal", JsonObject(), {{"vertex", DefaultVertexShader}, {"fragment", DefaultFragmentShader}});
m_limitTextureGroupSize = false;
m_useMultiTexturing = true;
@@ -102,7 +102,8 @@ OpenGl20Renderer::OpenGl20Renderer() {
}
OpenGl20Renderer::~OpenGl20Renderer() {
- glDeleteProgram(m_program);
+ for (auto& effect : m_effects)
+ glDeleteProgram(effect.second.program);
logGlErrorSummary("OpenGL errors during shutdown");
}
@@ -115,8 +116,13 @@ Vec2U OpenGl20Renderer::screenSize() const {
return m_screenSize;
}
-void OpenGl20Renderer::setEffectConfig(Json const& effectConfig, StringMap<String> const& shaders) {
- flushImmediatePrimitives();
+void OpenGl20Renderer::loadEffectConfig(String const& name, Json const& effectConfig, StringMap<String> const& shaders) {
+ if (m_effects.contains(name)) {
+ Logger::warn("OpenGL effect {} already exists", name);
+ switchEffectConfig(name);
+ return;
+ }
+
GLint status = 0;
char logBuffer[1024];
@@ -161,32 +167,11 @@ void OpenGl20Renderer::setEffectConfig(Json const& effectConfig, StringMap<Strin
throw RendererException(strf("Failed to link program: {}\n", logBuffer));
}
- if (m_program != 0)
- glDeleteProgram(m_program);
- m_program = program;
- glUseProgram(m_program);
-
- m_positionAttribute = glGetAttribLocation(m_program, "vertexPosition");
- m_texCoordAttribute = glGetAttribLocation(m_program, "vertexTextureCoordinate");
- m_texIndexAttribute = glGetAttribLocation(m_program, "vertexTextureIndex");
- m_colorAttribute = glGetAttribLocation(m_program, "vertexColor");
- m_param1Attribute = glGetAttribLocation(m_program, "vertexParam1");
+ glUseProgram(m_program = program);
+ setupGlUniforms(m_program);
- m_textureUniforms.clear();
- m_textureSizeUniforms.clear();
- for (size_t i = 0; i < MultiTextureCount; ++i) {
- m_textureUniforms.append(glGetUniformLocation(m_program, strf("texture{}", i).c_str()));
- m_textureSizeUniforms.append(glGetUniformLocation(m_program, strf("textureSize{}", i).c_str()));
- }
- m_screenSizeUniform = glGetUniformLocation(m_program, "screenSize");
- m_vertexTransformUniform = glGetUniformLocation(m_program, "vertexTransform");
-
- for (size_t i = 0; i < MultiTextureCount; ++i) {
- glUniform1i(m_textureUniforms[i], i);
- }
- glUniform2f(m_screenSizeUniform, m_screenSize[0], m_screenSize[1]);
-
- m_effectParameters.clear();
+ auto& effect = m_effects.emplace(name, Effect{ program, effectConfig, {}, {} }).first->second;
+ m_currentEffect = &effect;
for (auto const& p : effectConfig.getObject("effectParameters", {})) {
EffectParameter effectParameter;
@@ -212,7 +197,7 @@ void OpenGl20Renderer::setEffectConfig(Json const& effectConfig, StringMap<Strin
throw RendererException::format("Unrecognized effect parameter type '{}'", type);
}
- m_effectParameters[p.first] = effectParameter;
+ effect.parameters[p.first] = effectParameter;
if (Json def = p.second.get("default", {})) {
if (type == "bool") {
@@ -232,8 +217,6 @@ void OpenGl20Renderer::setEffectConfig(Json const& effectConfig, StringMap<Strin
}
}
- m_effectTextures.clear();
-
// Assign each texture parameter a texture unit starting with MultiTextureCount, the first
// few texture units are used by the primary textures being drawn. Currently,
// maximum texture units are not checked.
@@ -256,7 +239,7 @@ void OpenGl20Renderer::setEffectConfig(Json const& effectConfig, StringMap<Strin
Logger::warn("OpenGL20 effect parameter '{}' has textureSizeUniform '{}' with no associated uniform", p.first, *tsu);
}
- m_effectTextures[p.first] = effectTexture;
+ effect.textures[p.first] = effectTexture;
}
}
@@ -265,7 +248,7 @@ void OpenGl20Renderer::setEffectConfig(Json const& effectConfig, StringMap<Strin
}
void OpenGl20Renderer::setEffectParameter(String const& parameterName, RenderEffectParameter const& value) {
- auto ptr = m_effectParameters.ptr(parameterName);
+ auto ptr = m_currentEffect->parameters.ptr(parameterName);
if (!ptr || (ptr->parameterValue && *ptr->parameterValue == value))
return;
@@ -291,7 +274,7 @@ void OpenGl20Renderer::setEffectParameter(String const& parameterName, RenderEff
}
void OpenGl20Renderer::setEffectTexture(String const& textureName, Image const& image) {
- auto ptr = m_effectTextures.ptr(textureName);
+ auto ptr = m_currentEffect->textures.ptr(textureName);
if (!ptr)
return;
@@ -311,6 +294,21 @@ void OpenGl20Renderer::setEffectTexture(String const& textureName, Image const&
}
}
+bool OpenGl20Renderer::switchEffectConfig(String const& name) {
+ flushImmediatePrimitives();
+ auto find = m_effects.find(name);
+ if (find == m_effects.end())
+ return false;
+
+ Effect& effect = find->second;
+
+ glUseProgram(m_program = effect.program);
+ setupGlUniforms(m_program);
+ m_currentEffect = &effect;
+
+ return true;
+}
+
void OpenGl20Renderer::setScissorRect(Maybe<RectI> const& scissorRect) {
if (scissorRect == m_scissorRect)
return;
@@ -798,7 +796,7 @@ void OpenGl20Renderer::renderGlBuffer(GlRenderBuffer const& renderBuffer, Mat3F
glBindTexture(GL_TEXTURE_2D, vb.textures[i].texture);
}
- for (auto const& p : m_effectTextures) {
+ for (auto const& p : m_currentEffect->textures) {
if (p.second.textureValue) {
glActiveTexture(GL_TEXTURE0 + p.second.textureUnit);
glBindTexture(GL_TEXTURE_2D, p.second.textureValue->textureId);
@@ -823,4 +821,26 @@ void OpenGl20Renderer::renderGlBuffer(GlRenderBuffer const& renderBuffer, Mat3F
}
}
+void OpenGl20Renderer::setupGlUniforms(GLuint program) {
+ m_positionAttribute = glGetAttribLocation(program, "vertexPosition");
+ m_texCoordAttribute = glGetAttribLocation(program, "vertexTextureCoordinate");
+ m_texIndexAttribute = glGetAttribLocation(program, "vertexTextureIndex");
+ m_colorAttribute = glGetAttribLocation(program, "vertexColor");
+ m_param1Attribute = glGetAttribLocation(program, "vertexParam1");
+
+ m_textureUniforms.clear();
+ m_textureSizeUniforms.clear();
+ for (size_t i = 0; i < MultiTextureCount; ++i) {
+ m_textureUniforms.append(glGetUniformLocation(program, strf("texture{}", i).c_str()));
+ m_textureSizeUniforms.append(glGetUniformLocation(program, strf("textureSize{}", i).c_str()));
+ }
+ m_screenSizeUniform = glGetUniformLocation(program, "screenSize");
+ m_vertexTransformUniform = glGetUniformLocation(program, "vertexTransform");
+
+ for (size_t i = 0; i < MultiTextureCount; ++i)
+ glUniform1i(m_textureUniforms[i], i);
+
+ glUniform2f(m_screenSizeUniform, m_screenSize[0], m_screenSize[1]);
+}
+
}
diff --git a/source/application/StarRenderer_opengl20.hpp b/source/application/StarRenderer_opengl20.hpp
index ff82d3a..5add227 100644
--- a/source/application/StarRenderer_opengl20.hpp
+++ b/source/application/StarRenderer_opengl20.hpp
@@ -20,12 +20,15 @@ public:
String rendererId() const override;
Vec2U screenSize() const override;
- void setEffectConfig(Json const& effectConfig, StringMap<String> const& shaders) override;
+ void loadEffectConfig(String const& name, Json const& effectConfig, StringMap<String> const& shaders) override;
+
void setEffectParameter(String const& parameterName, RenderEffectParameter const& parameter) override;
void setEffectTexture(String const& textureName, Image const& image) override;
void setScissorRect(Maybe<RectI> const& scissorRect) override;
+ bool switchEffectConfig(String const& name) override;
+
TexturePtr createTexture(Image const& texture, TextureAddressing addressing, TextureFiltering filtering) override;
void setSizeLimitEnabled(bool enabled) override;
void setMultiTexturingEnabled(bool enabled) override;
@@ -155,6 +158,13 @@ private:
RefPtr<GlLoneTexture> textureValue;
};
+ struct Effect {
+ GLuint program;
+ Json config;
+ StringMap<EffectParameter> parameters;
+ StringMap<EffectTexture> textures;
+ };
+
static void logGlErrorSummary(String prefix);
static void uploadTextureImage(PixelFormat pixelFormat, Vec2U size, uint8_t const* data);
@@ -166,6 +176,8 @@ private:
void renderGlBuffer(GlRenderBuffer const& renderBuffer, Mat3F const& transformation);
+ void setupGlUniforms(GLuint program);
+
Vec2U m_screenSize;
GLuint m_program = 0;
@@ -181,10 +193,11 @@ private:
GLint m_screenSizeUniform = -1;
GLint m_vertexTransformUniform = -1;
+ StringMap<Effect> m_effects;
+ Effect* m_currentEffect;
+
RefPtr<GlTexture> m_whiteTexture;
- StringMap<EffectParameter> m_effectParameters;
- StringMap<EffectTexture> m_effectTextures;
Maybe<RectI> m_scissorRect;
bool m_limitTextureGroupSize;
diff --git a/source/client/StarClientApplication.cpp b/source/client/StarClientApplication.cpp
index 14af82e..562128c 100644
--- a/source/client/StarClientApplication.cpp
+++ b/source/client/StarClientApplication.cpp
@@ -207,25 +207,31 @@ void ClientApplication::renderInit(RendererPtr renderer) {
Application::renderInit(renderer);
auto assets = m_root->assets();
- String rendererConfig = strf("/rendering/{}.config", renderer->rendererId());
- if (assets->assetExists(rendererConfig)) {
- StringMap<String> shaders;
- auto config = assets->json(rendererConfig);
- auto shaderConfig = config.getObject("effectShaders");
- for (auto& entry : shaderConfig) {
- if (entry.second.isType(Json::Type::String)) {
- String shader = entry.second.toString();
- if (!shader.hasChar('\n')) {
- auto shaderBytes = assets->bytes(AssetPath::relativeTo(rendererConfig, shader));
- shader = std::string(shaderBytes->ptr(), shaderBytes->size());
+ auto loadConfig = [&](String const& name) {
+ String path = strf("/rendering/{}.config", name);
+ if (assets->assetExists(path)) {
+ StringMap<String> shaders;
+ auto config = assets->json(path);
+ auto shaderConfig = config.getObject("effectShaders");
+ for (auto& entry : shaderConfig) {
+ if (entry.second.isType(Json::Type::String)) {
+ String shader = entry.second.toString();
+ if (!shader.hasChar('\n')) {
+ auto shaderBytes = assets->bytes(AssetPath::relativeTo(path, shader));
+ shader = std::string(shaderBytes->ptr(), shaderBytes->size());
+ }
+ shaders[entry.first] = shader;
}
- shaders[entry.first] = shader;
}
+
+ renderer->loadEffectConfig(name, config, shaders);
}
- renderer->setEffectConfig(config, shaders);
- }
- else
- Logger::warn("No rendering config found for renderer with id '{}'", renderer->rendererId());
+ else
+ Logger::warn("No rendering config found for renderer with id '{}'", renderer->rendererId());
+ };
+
+ loadConfig("world");
+ loadConfig("default");
if (m_root->configuration()->get("limitTextureAtlasSize").optBool().value(false))
renderer->setSizeLimitEnabled(true);
@@ -365,13 +371,13 @@ void ClientApplication::render() {
RendererPtr renderer = Application::renderer();
if (worldClient) {
int64_t start = Time::monotonicMilliseconds();
- if (renderer)
- renderer->setEffectParameter("lightMapEnabled", true);
+
+ renderer->switchEffectConfig("world");
worldClient->render(m_renderData, TilePainter::BorderTileSize);
m_worldPainter->render(m_renderData, [&]() { worldClient->waitForLighting(); });
m_mainInterface->renderInWorldElements();
- if (renderer)
- renderer->setEffectParameter("lightMapEnabled", false);
+ renderer->switchEffectConfig("default");
+
LogMap::set("render_world", strf("{}ms", Time::monotonicMilliseconds() - start));
}
int64_t start = Time::monotonicMilliseconds();
diff --git a/source/rendering/StarEnvironmentPainter.cpp b/source/rendering/StarEnvironmentPainter.cpp
index 94bf364..6d1f029 100644
--- a/source/rendering/StarEnvironmentPainter.cpp
+++ b/source/rendering/StarEnvironmentPainter.cpp
@@ -231,6 +231,7 @@ void EnvironmentPainter::renderSky(Vec2F const& screenSize, SkyRenderData const&
m_renderer->flush();
}
+// TODO: Fix this to work with decimal zoom levels. Currently, the clouds shake rapidly when interpolating between zoom levels.
void EnvironmentPainter::renderParallaxLayers(
Vec2F parallaxWorldPosition, WorldCamera const& camera, ParallaxLayers const& layers, SkyRenderData const& sky) {