feat: recompiling shaders
This commit is contained in:
parent
5751802da2
commit
96a94aa33c
@ -11,10 +11,7 @@ uniform float u_shadowsOpacity;
|
|||||||
uniform float u_shadowsSoftness;
|
uniform float u_shadowsSoftness;
|
||||||
|
|
||||||
float calc_shadow() {
|
float calc_shadow() {
|
||||||
if (!u_enableShadows) {
|
#ifdef ENABLE_SHADOWS
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float step = 1.0 / float(u_shadowsRes);
|
float step = 1.0 / float(u_shadowsRes);
|
||||||
float s = pow(abs(cos(u_dayTime * PI2)), 0.25) * u_shadowsOpacity;
|
float s = pow(abs(cos(u_dayTime * PI2)), 0.25) * u_shadowsOpacity;
|
||||||
vec3 normalOffset = a_realnormal * (a_distance > 64.0 ? 0.2 : 0.04);
|
vec3 normalOffset = a_realnormal * (a_distance > 64.0 ? 0.2 : 0.04);
|
||||||
@ -39,6 +36,9 @@ float calc_shadow() {
|
|||||||
shadow = 0.5;
|
shadow = 0.5;
|
||||||
}
|
}
|
||||||
return 0.5 * (1.0 + s * shadow);
|
return 0.5 * (1.0 + s * shadow);
|
||||||
|
#else
|
||||||
|
return 1.0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SHADOWS_GLSL_
|
#endif // SHADOWS_GLSL_
|
||||||
|
|||||||
@ -76,6 +76,14 @@ static auto process_program(const ResPaths& paths, const std::string& filename)
|
|||||||
return std::make_pair(vertex, fragment);
|
return std::make_pair(vertex, fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static auto read_program(const ResPaths& paths, const std::string& filename) {
|
||||||
|
io::path vertexFile = paths.find(filename + ".glslv");
|
||||||
|
io::path fragmentFile = paths.find(filename + ".glslf");
|
||||||
|
return std::make_pair(
|
||||||
|
io::read_string(vertexFile), io::read_string(fragmentFile)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
assetload::postfunc assetload::shader(
|
assetload::postfunc assetload::shader(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths& paths,
|
const ResPaths& paths,
|
||||||
@ -83,21 +91,18 @@ assetload::postfunc assetload::shader(
|
|||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>&
|
const std::shared_ptr<AssetCfg>&
|
||||||
) {
|
) {
|
||||||
auto [vertex, fragment] = process_program(paths, filename);
|
auto result = read_program(paths, filename);
|
||||||
|
auto vertex = result.first;
|
||||||
|
auto fragment = result.second;
|
||||||
|
|
||||||
io::path vertexFile = paths.find(filename + ".glslv");
|
io::path vertexFile = paths.find(filename + ".glslv");
|
||||||
io::path fragmentFile = paths.find(filename + ".glslf");
|
io::path fragmentFile = paths.find(filename + ".glslf");
|
||||||
|
|
||||||
std::string vertexSource = std::move(vertex.code);
|
|
||||||
std::string fragmentSource = std::move(fragment.code);
|
|
||||||
|
|
||||||
return [=](auto assets) {
|
return [=](auto assets) {
|
||||||
assets->store(
|
assets->store(
|
||||||
Shader::create(
|
Shader::create(
|
||||||
vertexFile.string(),
|
{vertexFile.string(), vertex},
|
||||||
fragmentFile.string(),
|
{fragmentFile.string(), fragment}
|
||||||
vertexSource,
|
|
||||||
fragmentSource
|
|
||||||
),
|
),
|
||||||
name
|
name
|
||||||
);
|
);
|
||||||
@ -127,10 +132,8 @@ assetload::postfunc assetload::posteffect(
|
|||||||
|
|
||||||
return [=](auto assets) {
|
return [=](auto assets) {
|
||||||
auto program = Shader::create(
|
auto program = Shader::create(
|
||||||
effectFile.string(),
|
{effectFile.string(), vertexSource},
|
||||||
effectFile.string(),
|
{effectFile.string(), fragmentSource}
|
||||||
vertexSource,
|
|
||||||
fragmentSource
|
|
||||||
);
|
);
|
||||||
bool advanced = false;
|
bool advanced = false;
|
||||||
if (settings) {
|
if (settings) {
|
||||||
|
|||||||
@ -12,20 +12,25 @@
|
|||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
#include "coders/GLSLExtension.hpp"
|
#include "coders/GLSLExtension.hpp"
|
||||||
|
#include "debug/Logger.hpp"
|
||||||
|
|
||||||
|
static debug::Logger logger("gl-shader");
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
GLSLExtension* Shader::preprocessor = new GLSLExtension();
|
GLSLExtension* Shader::preprocessor = new GLSLExtension();
|
||||||
Shader* Shader::used = nullptr;
|
Shader* Shader::used = nullptr;
|
||||||
|
|
||||||
Shader::Shader(uint id) : id(id){
|
Shader::Shader(uint id, Source&& vertexSource, Source&& fragmentSource)
|
||||||
}
|
: id(id),
|
||||||
|
vertexSource(std::move(vertexSource)),
|
||||||
|
fragmentSource(std::move(fragmentSource)) {}
|
||||||
|
|
||||||
Shader::~Shader(){
|
Shader::~Shader() {
|
||||||
glDeleteProgram(id);
|
glDeleteProgram(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::use(){
|
void Shader::use() {
|
||||||
used = this;
|
used = this;
|
||||||
glUseProgram(id);
|
glUseProgram(id);
|
||||||
}
|
}
|
||||||
@ -40,8 +45,10 @@ uint Shader::getUniformLocation(const std::string& name) {
|
|||||||
return found->second;
|
return found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::uniformMatrix(const std::string& name, const glm::mat4& matrix){
|
void Shader::uniformMatrix(const std::string& name, const glm::mat4& matrix) {
|
||||||
glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix));
|
glUniformMatrix4fv(
|
||||||
|
getUniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::uniform1i(const std::string& name, int x){
|
void Shader::uniform1i(const std::string& name, int x){
|
||||||
@ -96,7 +103,7 @@ void Shader::uniform4v(const std::string& name, int length, const float* v) {
|
|||||||
glUniform4fv(getUniformLocation(name), length, v);
|
glUniform4fv(getUniformLocation(name), length, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto shader_deleter = [](GLuint* shader) {
|
static inline auto shader_deleter = [](GLuint* shader) {
|
||||||
glDeleteShader(*shader);
|
glDeleteShader(*shader);
|
||||||
delete shader;
|
delete shader;
|
||||||
};
|
};
|
||||||
@ -112,45 +119,73 @@ glshader compile_shader(GLenum type, const GLchar* source, const std::string& fi
|
|||||||
glShaderSource(shader, 1, &source, nullptr);
|
glShaderSource(shader, 1, &source, nullptr);
|
||||||
glCompileShader(shader);
|
glCompileShader(shader);
|
||||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||||
if (!success){
|
if (!success) {
|
||||||
GLchar infoLog[GL_LOG_LEN];
|
GLchar infoLog[GL_LOG_LEN];
|
||||||
glGetShaderInfoLog(shader, GL_LOG_LEN, nullptr, infoLog);
|
glGetShaderInfoLog(shader, GL_LOG_LEN, nullptr, infoLog);
|
||||||
glDeleteShader(shader);
|
glDeleteShader(shader);
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"vertex shader compilation failed ("+file+"):\n"+std::string(infoLog)
|
"vertex shader compilation failed (" + file + "):\n" +
|
||||||
|
std::string(infoLog)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return glshader(new GLuint(shader), shader_deleter); //-V508
|
return glshader(new GLuint(shader), shader_deleter); //-V508
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Shader> Shader::create(
|
static GLuint compile_program(
|
||||||
const std::string& vertexFile,
|
const Shader::Source& vertexSource, const Shader::Source& fragmentSource
|
||||||
const std::string& fragmentFile,
|
|
||||||
const std::string& vertexCode,
|
|
||||||
const std::string& fragmentCode
|
|
||||||
) {
|
) {
|
||||||
|
auto& preprocessor = *Shader::preprocessor;
|
||||||
|
|
||||||
|
auto vertexCode = std::move(
|
||||||
|
preprocessor.process(vertexSource.file, vertexSource.code).code
|
||||||
|
);
|
||||||
|
auto fragmentCode = std::move(
|
||||||
|
preprocessor.process(fragmentSource.file, fragmentSource.code).code
|
||||||
|
);
|
||||||
|
|
||||||
const GLchar* vCode = vertexCode.c_str();
|
const GLchar* vCode = vertexCode.c_str();
|
||||||
const GLchar* fCode = fragmentCode.c_str();
|
const GLchar* fCode = fragmentCode.c_str();
|
||||||
|
|
||||||
glshader vertex = compile_shader(GL_VERTEX_SHADER, vCode, vertexFile);
|
glshader vertex =
|
||||||
glshader fragment = compile_shader(GL_FRAGMENT_SHADER, fCode, fragmentFile);
|
compile_shader(GL_VERTEX_SHADER, vCode, vertexSource.file);
|
||||||
|
glshader fragment =
|
||||||
|
compile_shader(GL_FRAGMENT_SHADER, fCode, fragmentSource.file);
|
||||||
|
|
||||||
// Shader Program
|
// Shader Program
|
||||||
GLint success;
|
GLint success;
|
||||||
GLuint id = glCreateProgram();
|
GLuint program = glCreateProgram();
|
||||||
glAttachShader(id, *vertex);
|
glAttachShader(program, *vertex);
|
||||||
glAttachShader(id, *fragment);
|
glAttachShader(program, *fragment);
|
||||||
glLinkProgram(id);
|
glLinkProgram(program);
|
||||||
|
|
||||||
glGetProgramiv(id, GL_LINK_STATUS, &success);
|
glGetProgramiv(program, GL_LINK_STATUS, &success);
|
||||||
if (!success){
|
|
||||||
|
if (!success) {
|
||||||
GLchar infoLog[GL_LOG_LEN];
|
GLchar infoLog[GL_LOG_LEN];
|
||||||
glGetProgramInfoLog(id, GL_LOG_LEN, nullptr, infoLog);
|
glGetProgramInfoLog(program, GL_LOG_LEN, nullptr, infoLog);
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"shader program linking failed:\n"+std::string(infoLog)
|
"shader program linking failed:\n" + std::string(infoLog)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return std::make_unique<Shader>(id);
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::recompile() {
|
||||||
|
GLuint newProgram = compile_program(vertexSource, fragmentSource);
|
||||||
|
glDeleteProgram(id);
|
||||||
|
id = newProgram;
|
||||||
|
uniformLocations.clear();
|
||||||
|
logger.info() << "shader " << id << " has been recompiled";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Shader> Shader::create(
|
||||||
|
Source&& vertexSource, Source&& fragmentSource
|
||||||
|
) {
|
||||||
|
return std::make_unique<Shader>(
|
||||||
|
compile_program(vertexSource, fragmentSource),
|
||||||
|
std::move(vertexSource),
|
||||||
|
std::move(fragmentSource)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader& Shader::getUsed() {
|
Shader& Shader::getUsed() {
|
||||||
|
|||||||
@ -10,15 +10,25 @@
|
|||||||
class GLSLExtension;
|
class GLSLExtension;
|
||||||
|
|
||||||
class Shader {
|
class Shader {
|
||||||
|
public:
|
||||||
|
struct Source {
|
||||||
|
std::string file;
|
||||||
|
std::string code;
|
||||||
|
};
|
||||||
|
private:
|
||||||
static Shader* used;
|
static Shader* used;
|
||||||
uint id;
|
uint id;
|
||||||
std::unordered_map<std::string, uint> uniformLocations;
|
std::unordered_map<std::string, uint> uniformLocations;
|
||||||
|
|
||||||
|
// source code used for re-compiling shaders after updating defines
|
||||||
|
Source vertexSource;
|
||||||
|
Source fragmentSource;
|
||||||
|
|
||||||
uint getUniformLocation(const std::string& name);
|
uint getUniformLocation(const std::string& name);
|
||||||
public:
|
public:
|
||||||
static GLSLExtension* preprocessor;
|
static GLSLExtension* preprocessor;
|
||||||
|
|
||||||
Shader(uint id);
|
Shader(uint id, Source&& vertexSource, Source&& fragmentSource);
|
||||||
~Shader();
|
~Shader();
|
||||||
|
|
||||||
void use();
|
void use();
|
||||||
@ -38,17 +48,13 @@ public:
|
|||||||
void uniform3v(const std::string& name, int length, const float* v);
|
void uniform3v(const std::string& name, int length, const float* v);
|
||||||
void uniform4v(const std::string& name, int length, const float* v);
|
void uniform4v(const std::string& name, int length, const float* v);
|
||||||
|
|
||||||
|
/// @brief Re-preprocess source code and re-compile shader program
|
||||||
|
void recompile();
|
||||||
|
|
||||||
/// @brief Create shader program using vertex and fragment shaders source.
|
/// @brief Create shader program using vertex and fragment shaders source.
|
||||||
/// @param vertexFile vertex shader file name
|
|
||||||
/// @param fragmentFile fragment shader file name
|
|
||||||
/// @param vertexSource vertex shader source code
|
|
||||||
/// @param fragmentSource fragment shader source code
|
|
||||||
/// @return linked shader program containing vertex and fragment shaders
|
/// @return linked shader program containing vertex and fragment shaders
|
||||||
static std::unique_ptr<Shader> create(
|
static std::unique_ptr<Shader> create(
|
||||||
const std::string& vertexFile,
|
Source&& vertexSource, Source&& fragmentSource
|
||||||
const std::string& fragmentFile,
|
|
||||||
const std::string& vertexSource,
|
|
||||||
const std::string& fragmentSource
|
|
||||||
);
|
);
|
||||||
|
|
||||||
static Shader& getUsed();
|
static Shader& getUsed();
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include "assets/assets_util.hpp"
|
#include "assets/assets_util.hpp"
|
||||||
#include "content/Content.hpp"
|
#include "content/Content.hpp"
|
||||||
#include "engine/Engine.hpp"
|
#include "engine/Engine.hpp"
|
||||||
|
#include "coders/GLSLExtension.hpp"
|
||||||
#include "frontend/LevelFrontend.hpp"
|
#include "frontend/LevelFrontend.hpp"
|
||||||
#include "frontend/ContentGfxCache.hpp"
|
#include "frontend/ContentGfxCache.hpp"
|
||||||
#include "items/Inventory.hpp"
|
#include "items/Inventory.hpp"
|
||||||
@ -434,6 +435,7 @@ void WorldRenderer::draw(
|
|||||||
const auto& vp = pctx.getViewport();
|
const auto& vp = pctx.getViewport();
|
||||||
camera.setAspectRatio(vp.x / static_cast<float>(vp.y));
|
camera.setAspectRatio(vp.x / static_cast<float>(vp.y));
|
||||||
|
|
||||||
|
auto& mainShader = assets.require<Shader>("main");
|
||||||
const auto& settings = engine.getSettings();
|
const auto& settings = engine.getSettings();
|
||||||
gbufferPipeline = settings.graphics.advancedRender.get();
|
gbufferPipeline = settings.graphics.advancedRender.get();
|
||||||
int shadowsQuality = settings.graphics.shadowsQuality.get();
|
int shadowsQuality = settings.graphics.shadowsQuality.get();
|
||||||
@ -442,10 +444,14 @@ void WorldRenderer::draw(
|
|||||||
shadowMap = std::make_unique<ShadowMap>(resolution);
|
shadowMap = std::make_unique<ShadowMap>(resolution);
|
||||||
wideShadowMap = std::make_unique<ShadowMap>(resolution);
|
wideShadowMap = std::make_unique<ShadowMap>(resolution);
|
||||||
shadows = true;
|
shadows = true;
|
||||||
} else if (shadowsQuality == 0) {
|
Shader::preprocessor->define("ENABLE_SHADOWS", "true");
|
||||||
|
mainShader.recompile();
|
||||||
|
} else if (shadowsQuality == 0 && shadows) {
|
||||||
shadowMap.reset();
|
shadowMap.reset();
|
||||||
wideShadowMap.reset();
|
wideShadowMap.reset();
|
||||||
shadows = false;
|
shadows = false;
|
||||||
|
Shader::preprocessor->undefine("ENABLE_SHADOWS");
|
||||||
|
mainShader.recompile();
|
||||||
}
|
}
|
||||||
if (shadows && shadowMap->getResolution() != resolution) {
|
if (shadows && shadowMap->getResolution() != resolution) {
|
||||||
shadowMap = std::make_unique<ShadowMap>(resolution);
|
shadowMap = std::make_unique<ShadowMap>(resolution);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user