summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/AssetManager.cpp32
-rw-r--r--src/AssetManager.hpp5
-rw-r--r--src/RendererWorld.cpp34
-rw-r--r--src/RendererWorld.hpp1
-rw-r--r--src/Shader.cpp85
-rw-r--r--src/Shader.hpp40
6 files changed, 178 insertions, 19 deletions
diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp
index 03a672e..5f2a160 100644
--- a/src/AssetManager.cpp
+++ b/src/AssetManager.cpp
@@ -34,6 +34,7 @@ void ParseAsset(AssetTreeNode &node);
void ParseAssetTexture(AssetTreeNode &node);
void ParseAssetBlockModel(AssetTreeNode &node);
void ParseAssetBlockState(AssetTreeNode &node);
+void ParseAssetShader(AssetTreeNode &node);
void ParseBlockModels();
@@ -132,6 +133,11 @@ void ParseAsset(AssetTreeNode &node) {
ParseAssetTexture(node);
return;
}
+
+ if (node.parent->name == "shaders") {
+ ParseAssetShader(node);
+ return;
+ }
}
void ParseAssetTexture(AssetTreeNode &node) {
@@ -339,6 +345,32 @@ void ParseAssetBlockState(AssetTreeNode &node) {
node.data.shrink_to_fit();
}
+void ParseAssetShader(AssetTreeNode &node) {
+ try {
+ nlohmann::json j = nlohmann::json::parse(node.data);
+
+ std::string vertPath = j["vert"].get<std::string>();
+ std::string fragPath = j["frag"].get<std::string>();
+
+ AssetTreeNode *vertAsset = AssetManager::GetAssetByAssetName(vertPath);
+ AssetTreeNode *fragAsset = AssetManager::GetAssetByAssetName(fragPath);
+ std::string vertSource((char*)vertAsset->data.data(), (char*)vertAsset->data.data() + vertAsset->data.size());
+ std::string fragSource((char*)fragAsset->data.data(), (char*)fragAsset->data.data() + fragAsset->data.size());
+
+ std::vector<std::string> uniforms;
+
+ for (auto &it : j["uniforms"]) {
+ uniforms.push_back(it.get<std::string>());
+ }
+
+ node.asset = std::make_unique<AssetShader>();
+ AssetShader *asset = dynamic_cast<AssetShader*>(node.asset.get());
+ asset->shader = std::make_unique<NewShader>(vertSource, fragSource, uniforms);
+ } catch (...) {
+ return;
+ }
+}
+
void ParseBlockModels() {
std::string textureName;
diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp
index 3ecff25..3b4ad2f 100644
--- a/src/AssetManager.hpp
+++ b/src/AssetManager.hpp
@@ -14,6 +14,7 @@
#include "Vector.hpp"
#include "Block.hpp"
#include "TextureAtlas.hpp"
+#include "Shader.hpp"
enum FaceDirection {
down,
@@ -160,6 +161,10 @@ struct AssetTexture : Asset {
size_t id;
};
+struct AssetShader : Asset {
+ std::unique_ptr<NewShader> shader;
+};
+
namespace AssetManager {
void InitAssetManager();
diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp
index e1dd52c..7f47a1e 100644
--- a/src/RendererWorld.cpp
+++ b/src/RendererWorld.cpp
@@ -265,7 +265,6 @@ RendererWorld::~RendererWorld() {
workers[i].join();
delete blockShader;
delete entityShader;
- delete skyShader;
DebugInfo::renderSections = 0;
DebugInfo::readyRenderer = 0;
}
@@ -339,11 +338,10 @@ void RendererWorld::Render(RenderState & renderState) {
//Render sky
renderState.TimeOfDay = gs->TimeOfDay;
- renderState.SetActiveShader(skyShader->Program);
- projectionLoc = glGetUniformLocation(skyShader->Program, "projection");
- viewLoc = glGetUniformLocation(skyShader->Program, "view");
- glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
- glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
+ NewShader *skyShader = AssetManager::GetAsset<AssetShader>("/altcraft/shaders/sky")->shader.get();
+ skyShader->Activate();
+ skyShader->SetUniform("projection", projection);
+ skyShader->SetUniform("view", view);
glm::mat4 model = glm::mat4(1.0);
model = glm::translate(model, gs->player->pos.glm());
const float scale = 1000000.0f;
@@ -353,8 +351,7 @@ void RendererWorld::Render(RenderState & renderState) {
shift *= -1.0f;
model = glm::rotate(model, glm::radians(90.0f), glm::vec3(0, 1.0f, 0.0f));
model = glm::rotate(model, glm::radians(360.0f * shift), glm::vec3(-1.0f, 0.0f, 0.0f));
- modelLoc = glGetUniformLocation(skyShader->Program, "model");
- glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
+ skyShader->SetUniform("model", model);
glCheckError();
@@ -382,7 +379,7 @@ void RendererWorld::Render(RenderState & renderState) {
mixLevel = 1.0 - (timePassed / moonriseLength);
}
- glUniform1f(glGetUniformLocation(skyShader->Program, "DayTime"), mixLevel);
+ skyShader->SetUniform("DayTime", mixLevel);
rendererSky.Render(renderState);
glCheckError();
@@ -429,17 +426,18 @@ void RendererWorld::PrepareRender() {
entityShader = new Shader("./shaders/entity.vs", "./shaders/entity.fs");
- skyShader = new Shader("./shaders/sky.vs", "./shaders/sky.fs");
- skyShader->Use();
- glUniform1i(glGetUniformLocation(skyShader->Program, "textureAtlas"), 0);
TextureCoord sunTexture = AssetManager::GetTexture("/minecraft/textures/environment/sun");
- glUniform4f(glGetUniformLocation(skyShader->Program, "sunTexture"), sunTexture.x, sunTexture.y, sunTexture.w, sunTexture.h);
- glUniform1f(glGetUniformLocation(skyShader->Program, "sunTextureLayer"), sunTexture.layer);
TextureCoord moonTexture = AssetManager::GetTexture("/minecraft/textures/environment/moon_phases");
- moonTexture.w /= 4.0f; //First phase will be fine for now
- moonTexture.h /= 2.0f;
- glUniform4f(glGetUniformLocation(skyShader->Program, "moonTexture"), moonTexture.x, moonTexture.y, moonTexture.w, moonTexture.h);
- glUniform1f(glGetUniformLocation(skyShader->Program, "moonTextureLayer"), moonTexture.layer);
+ moonTexture.w /= 4.0f; //First phase will be fine for now
+ moonTexture.h /= 2.0f;
+
+ NewShader *sky = AssetManager::GetAsset<AssetShader>("/altcraft/shaders/sky")->shader.get();
+ sky->Activate();
+ sky->SetUniform("textureAtlas", 0);
+ sky->SetUniform("sunTexture", glm::vec4(sunTexture.x, sunTexture.y, sunTexture.w, sunTexture.h));
+ sky->SetUniform("sunTextureLayer", (float)sunTexture.layer);
+ sky->SetUniform("moonTexture", glm::vec4(moonTexture.x, moonTexture.y, moonTexture.w, moonTexture.h));
+ sky->SetUniform("moonTextureLayer", (float)moonTexture.layer);
}
void RendererWorld::Update(double timeToUpdate) {
diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp
index 2dab4f0..d8b74e6 100644
--- a/src/RendererWorld.hpp
+++ b/src/RendererWorld.hpp
@@ -50,7 +50,6 @@ class RendererWorld {
std::vector<RendererEntity> entities;
//Sky
Texture *skyTexture;
- Shader *skyShader;
RendererSky rendererSky;
public:
RendererWorld(GameState* ptr);
diff --git a/src/Shader.cpp b/src/Shader.cpp
index d637c3b..9447131 100644
--- a/src/Shader.cpp
+++ b/src/Shader.cpp
@@ -111,3 +111,88 @@ void Shader::Reload() {
new(this) Shader(vertexPath, fragmentPath);
LOG(INFO) << "Shader is realoded!";
}
+
+GLuint NewShader::GetUniformLocation(const std::string &name) {
+ auto it = uniforms.find(name);
+ if (it == uniforms.end()) {
+ LOG(ERROR) << "Accessed not existing uniform " << name;
+ return 0;
+ }
+ return it->second;
+}
+
+NewShader::NewShader(const std::string &vertSource, const std::string &fragSource, const std::vector<std::string> &uniformsNames)
+{
+ bool vertFailed = false, fragFailed = false, linkFailed = false, uniformsFailed = false;
+ const GLchar *vertSourcePtr = vertSource.c_str();
+ const GLchar *fragSourcePtr = fragSource.c_str();
+
+ GLuint vertex, fragment;
+ GLint success;
+ GLchar infoLog[512];
+
+ vertex = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vertex, 1, &vertSourcePtr, NULL);
+ glCompileShader(vertex);
+
+ glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(vertex, 512, NULL, infoLog);
+ LOG(ERROR) << "Vertex shader compilation failed: " << std::endl << infoLog;
+ vertFailed = true;
+ };
+
+ fragment = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fragment, 1, &fragSourcePtr, NULL);
+ glCompileShader(fragment);
+
+ glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(fragment, 512, NULL, infoLog);
+ LOG(ERROR) << "Fragment shader compilation failed: " << std::endl << infoLog;
+ fragFailed = true;
+ };
+
+ if (vertFailed || fragFailed)
+ throw std::runtime_error("Shaders not compiled");
+
+ program = glCreateProgram();
+ glAttachShader(program, vertex);
+ glAttachShader(program, fragment);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &success);
+ if (!success) {
+ glGetProgramInfoLog(program, 512, NULL, infoLog);
+ LOG(ERROR) << "Shader program not linked: " << std::endl << infoLog;
+ linkFailed = true;
+ }
+
+ glDeleteShader(vertex);
+ glDeleteShader(fragment);
+
+ if (linkFailed)
+ throw std::runtime_error("Shader not linked");
+
+
+ for (auto &it : uniformsNames) {
+ GLuint location = glGetUniformLocation(program, it.c_str());
+ if (location == -1) {
+ glDeleteProgram(program);
+ LOG(ERROR) << "Uniform name \"" << it << "\" not found in shader";
+ throw std::runtime_error("Invalid uniform");
+ }
+
+ uniforms[it] = location;
+ }
+}
+
+NewShader::~NewShader()
+{
+ if (program)
+ glDeleteProgram(program);
+}
+
+void NewShader::Activate()
+{
+ glUseProgram(program);
+}
diff --git a/src/Shader.hpp b/src/Shader.hpp
index d6d59eb..b551602 100644
--- a/src/Shader.hpp
+++ b/src/Shader.hpp
@@ -1,6 +1,11 @@
#pragma once
+#include <map>
+#include <vector>
+
#include <GL/glew.h>
+#include <glm/glm.hpp>
+#include <glm/gtc/type_ptr.hpp>
class Shader
{
@@ -13,4 +18,39 @@ public:
void Use();
void Reload();
+};
+
+class NewShader {
+ std::map<std::string, GLuint> uniforms;
+ GLuint program = 0;
+
+ GLuint GetUniformLocation(const std::string &name);
+
+public:
+ NewShader(const NewShader &) = delete;
+ NewShader(NewShader &&other) = delete;
+ NewShader &operator=(const NewShader &) = delete;
+ NewShader &operator=(NewShader &&other) = delete;
+
+ NewShader(const std::string &vertSource, const std::string &fragSource, const std::vector<std::string> &uniformsNames);
+
+ ~NewShader();
+
+ void Activate();
+
+ inline void SetUniform(const std::string &name, int val) {
+ glUniform1i(GetUniformLocation(name), val);
+ }
+
+ inline void SetUniform(const std::string &name, float val) {
+ glUniform1f(GetUniformLocation(name), val);
+ }
+
+ inline void SetUniform(const std::string &name, glm::vec4 val) {
+ glUniform4f(GetUniformLocation(name), val.x, val.y, val.z, val.w);
+ }
+
+ inline void SetUniform(const std::string &name, glm::mat4 val) {
+ glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, glm::value_ptr(val));
+ }
}; \ No newline at end of file