mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
feat: include for glsl (#24)
* refactor(gameplay): remove unused includes and members, clear vertex data after upload * feat(shader-tools): add recursive #include support for shader sources * refactor(shaders): extract noise and sky color functions into shared GLSL includes
This commit is contained in:
46
assets/shaders/compute_sky_color.glsl
Normal file
46
assets/shaders/compute_sky_color.glsl
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include "noise.glsl"
|
||||||
|
|
||||||
|
vec3 computeSkyColor(vec3 dir) {
|
||||||
|
vec3 sund = normalize(sunDir);
|
||||||
|
|
||||||
|
float t =
|
||||||
|
clamp(
|
||||||
|
dir.y * 0.5 + 0.5,
|
||||||
|
0.0,
|
||||||
|
1.0
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
vec3 sky =
|
||||||
|
mix(
|
||||||
|
skyBottom,
|
||||||
|
skyTop,
|
||||||
|
pow(t, horizonSharpness)
|
||||||
|
);
|
||||||
|
|
||||||
|
// cloud
|
||||||
|
if (dir.y > 0.0) {
|
||||||
|
vec2 cloud_uv = dir.xz / (dir.y + 0.15) * 0.5 + vec2(time * 0.005, time * 0.002);
|
||||||
|
float cloud_density = fbm(cloud_uv * 2.0);
|
||||||
|
float safeLow = cloudThresholdLow;
|
||||||
|
float safeHigh = max(cloudThresholdHigh, cloudThresholdLow + 0.001);
|
||||||
|
cloud_density = smoothstep(safeLow,safeHigh, cloud_density);
|
||||||
|
|
||||||
|
|
||||||
|
float fade = smoothstep(0.0, 0.3, dir.y) * (1.0 - smoothstep(0.85, 1.0, dir.y));
|
||||||
|
cloud_density *= fade;
|
||||||
|
|
||||||
|
vec3 cloud_color = mix(skyBottom, vec3(1.0), cloudWhiteMix);
|
||||||
|
sky = mix(sky, cloud_color, cloud_density * 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sunAmount = max(dot(dir, sund), 0.0);
|
||||||
|
|
||||||
|
//float glow = pow(sunAmount, 8.0) * 0.15;
|
||||||
|
|
||||||
|
float glow = pow(sunAmount, 8.0) * 0.15 + pow(sunAmount, 32.0) * 0.3;
|
||||||
|
|
||||||
|
sky += glow * sunColor;
|
||||||
|
|
||||||
|
return sky;
|
||||||
|
}
|
||||||
25
assets/shaders/noise.glsl
Normal file
25
assets/shaders/noise.glsl
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
float hash(vec2 p) {
|
||||||
|
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
|
||||||
|
}
|
||||||
|
|
||||||
|
float noise(vec2 p) {
|
||||||
|
vec2 i = floor(p);
|
||||||
|
vec2 f = fract(p);
|
||||||
|
f = f * f * (3.0 - 2.0 * f);
|
||||||
|
float a = hash(i);
|
||||||
|
float b = hash(i + vec2(1.0, 0.0));
|
||||||
|
float c = hash(i + vec2(0.0, 1.0));
|
||||||
|
float d = hash(i + vec2(1.0, 1.0));
|
||||||
|
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float fbm(vec2 p) {
|
||||||
|
float v = 0.0;
|
||||||
|
float amp = 0.5;
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
v += amp * noise(p);
|
||||||
|
p *= 2.0;
|
||||||
|
amp *= 0.5;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
@@ -19,84 +19,12 @@ uniform float cloudThresholdHigh;
|
|||||||
|
|
||||||
uniform float time;
|
uniform float time;
|
||||||
|
|
||||||
|
#include "compute_sky_color.glsl"
|
||||||
float hash(vec2 p) {
|
|
||||||
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
|
|
||||||
}
|
|
||||||
|
|
||||||
float noise(vec2 p) {
|
|
||||||
vec2 i = floor(p);
|
|
||||||
vec2 f = fract(p);
|
|
||||||
f = f * f * (3.0 - 2.0 * f);
|
|
||||||
float a = hash(i);
|
|
||||||
float b = hash(i + vec2(1.0, 0.0));
|
|
||||||
float c = hash(i + vec2(0.0, 1.0));
|
|
||||||
float d = hash(i + vec2(1.0, 1.0));
|
|
||||||
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
float fbm(vec2 p) {
|
|
||||||
float v = 0.0;
|
|
||||||
float amp = 0.5;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
v += amp * noise(p);
|
|
||||||
p *= 2.0;
|
|
||||||
amp *= 0.5;
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 computeSkyColor(vec3 dir) {
|
|
||||||
vec3 sund = normalize(sunDir);
|
|
||||||
|
|
||||||
float t =
|
|
||||||
clamp(
|
|
||||||
dir.y * 0.5 + 0.5,
|
|
||||||
0.0,
|
|
||||||
1.0
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
vec3 sky =
|
|
||||||
mix(
|
|
||||||
skyBottom,
|
|
||||||
skyTop,
|
|
||||||
pow(t, horizonSharpness)
|
|
||||||
);
|
|
||||||
|
|
||||||
// cloud
|
|
||||||
if (dir.y > 0.0) {
|
|
||||||
vec2 cloud_uv = dir.xz / (dir.y + 0.15) * 0.5 + vec2(time * 0.005, time * 0.002);
|
|
||||||
float cloud_density = fbm(cloud_uv * 2.0);
|
|
||||||
float safeLow = cloudThresholdLow;
|
|
||||||
float safeHigh = max(cloudThresholdHigh, cloudThresholdLow + 0.001);
|
|
||||||
cloud_density = smoothstep(safeLow,safeHigh, cloud_density);
|
|
||||||
|
|
||||||
|
|
||||||
float fade = smoothstep(0.0, 0.3, dir.y) * (1.0 - smoothstep(0.85, 1.0, dir.y));
|
|
||||||
cloud_density *= fade;
|
|
||||||
|
|
||||||
vec3 cloud_color = mix(skyBottom, vec3(1.0), cloudWhiteMix);
|
|
||||||
sky = mix(sky, cloud_color, cloud_density * 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
float sunAmount = max(dot(dir, sund), 0.0);
|
|
||||||
|
|
||||||
//float glow = pow(sunAmount, 8.0) * 0.15;
|
|
||||||
|
|
||||||
float glow = pow(sunAmount, 8.0) * 0.15 + pow(sunAmount, 32.0) * 0.3;
|
|
||||||
|
|
||||||
sky += glow * sunColor;
|
|
||||||
|
|
||||||
return sky;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
|
|
||||||
vec3 sky = computeSkyColor(dir);
|
vec3 sky = computeSkyColor(dir);
|
||||||
|
|
||||||
frag_color = vec4(sky, 1.0);
|
frag_color = vec4(sky, 1.0);
|
||||||
//frag_color = vec4(vec3(sunAmount), 1.0);
|
|
||||||
//frag_color = vec4(t,0,0,1);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -19,33 +19,7 @@ uniform vec3 sunDir;
|
|||||||
uniform vec3 sunColor;
|
uniform vec3 sunColor;
|
||||||
uniform float waterDensity;
|
uniform float waterDensity;
|
||||||
|
|
||||||
float hash(vec2 p) {
|
#include "noise.glsl"
|
||||||
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
|
||||||
}
|
|
||||||
|
|
||||||
float noise(vec2 p) {
|
|
||||||
vec2 i = floor(p);
|
|
||||||
vec2 f = fract(p);
|
|
||||||
f = f * f * (3.0 - 2.0 * f);
|
|
||||||
|
|
||||||
return mix(
|
|
||||||
mix(hash(i), hash(i + vec2(1.0, 0.0)), f.x),
|
|
||||||
mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), f.x),
|
|
||||||
f.y
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
float fbm(vec2 p) {
|
|
||||||
float value = 0.0;
|
|
||||||
float amp = 0.5;
|
|
||||||
float freq = 1.0;
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
value += amp * noise(p * freq);
|
|
||||||
freq *= 2.0;
|
|
||||||
amp *= 0.5;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getCausticValue(float x, float y, float z) {
|
float getCausticValue(float x, float y, float z) {
|
||||||
float w = 8.0;
|
float w = 8.0;
|
||||||
|
|||||||
@@ -42,82 +42,15 @@ uniform float refractStrength;
|
|||||||
|
|
||||||
uniform bool enablePerturb;
|
uniform bool enablePerturb;
|
||||||
uniform bool enableDepthFade;
|
uniform bool enableDepthFade;
|
||||||
|
|
||||||
|
#include "compute_sky_color.glsl"
|
||||||
|
|
||||||
float weight(float z, float a) {
|
float weight(float z, float a) {
|
||||||
float intermediate = 0.03 / (1e-5 + pow(z / 200.0, 4.0));
|
float intermediate = 0.03 / (1e-5 + pow(z / 200.0, 4.0));
|
||||||
|
|
||||||
return a * clamp(intermediate, 1e-2, 3e2);
|
return a * clamp(intermediate, 1e-2, 3e2);
|
||||||
}
|
}
|
||||||
|
|
||||||
float hash(vec2 p) {
|
|
||||||
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
|
|
||||||
}
|
|
||||||
|
|
||||||
float noise(vec2 p) {
|
|
||||||
vec2 i = floor(p);
|
|
||||||
vec2 f = fract(p);
|
|
||||||
f = f * f * (3.0 - 2.0 * f);
|
|
||||||
float a = hash(i);
|
|
||||||
float b = hash(i + vec2(1.0, 0.0));
|
|
||||||
float c = hash(i + vec2(0.0, 1.0));
|
|
||||||
float d = hash(i + vec2(1.0, 1.0));
|
|
||||||
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
float fbm(vec2 p) {
|
|
||||||
float v = 0.0;
|
|
||||||
float amp = 0.5;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
v += amp * noise(p);
|
|
||||||
p *= 2.0;
|
|
||||||
amp *= 0.5;
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 computeSkyColor(vec3 dir) {
|
|
||||||
vec3 sund = normalize(sunDir);
|
|
||||||
|
|
||||||
float t =
|
|
||||||
clamp(
|
|
||||||
dir.y * 0.5 + 0.5,
|
|
||||||
0.0,
|
|
||||||
1.0
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
vec3 sky =
|
|
||||||
mix(
|
|
||||||
skyBottom,
|
|
||||||
skyTop,
|
|
||||||
pow(t, horizonSharpness)
|
|
||||||
);
|
|
||||||
|
|
||||||
// cloud
|
|
||||||
if (dir.y > 0.0) {
|
|
||||||
vec2 cloud_uv = dir.xz / (dir.y + 0.15) * 0.5 + vec2(time * 0.005, time * 0.002);
|
|
||||||
float cloud_density = fbm(cloud_uv * 2.0);
|
|
||||||
float safeLow = cloudThresholdLow;
|
|
||||||
float safeHigh = max(cloudThresholdHigh, cloudThresholdLow + 0.001);
|
|
||||||
cloud_density = smoothstep(safeLow,safeHigh, cloud_density);
|
|
||||||
|
|
||||||
|
|
||||||
float fade = smoothstep(0.0, 0.3, dir.y) * (1.0 - smoothstep(0.85, 1.0, dir.y));
|
|
||||||
cloud_density *= fade;
|
|
||||||
|
|
||||||
vec3 cloud_color = mix(skyBottom, vec3(1.0), cloudWhiteMix);
|
|
||||||
sky = mix(sky, cloud_color, cloud_density * 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
float sunAmount = max(dot(dir, sund), 0.0);
|
|
||||||
|
|
||||||
//float glow = pow(sunAmount, 8.0) * 0.15;
|
|
||||||
|
|
||||||
float glow = pow(sunAmount, 8.0) * 0.15 + pow(sunAmount, 32.0) * 0.3;
|
|
||||||
|
|
||||||
sky += glow * sunColor;
|
|
||||||
|
|
||||||
return sky;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconstruct eye-space coordinates from screen UV and depth buffer value
|
// Reconstruct eye-space coordinates from screen UV and depth buffer value
|
||||||
vec3 reconstructViewPos(vec2 uv, float depth) {
|
vec3 reconstructViewPos(vec2 uv, float depth) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
|
||||||
#include "Cubed/gameplay/path_point.hpp"
|
#include "Cubed/gameplay/path_point.hpp"
|
||||||
#include "Cubed/tools/cubed_random.hpp"
|
#include "Cubed/tools/cubed_random.hpp"
|
||||||
|
|
||||||
@@ -9,8 +8,6 @@
|
|||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
class CavePath {
|
class CavePath {
|
||||||
using ChunkPosSet =
|
|
||||||
tbb::concurrent_hash_map<ChunkPos, bool, ChunkPos::TBBHash>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CavePath(unsigned int chunk_seed, unsigned world_seed,
|
CavePath(unsigned int chunk_seed, unsigned world_seed,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
|
||||||
#include "Cubed/gameplay/path_point.hpp"
|
#include "Cubed/gameplay/path_point.hpp"
|
||||||
#include "Cubed/tools/cubed_random.hpp"
|
#include "Cubed/tools/cubed_random.hpp"
|
||||||
|
|
||||||
@@ -9,8 +8,6 @@
|
|||||||
|
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
class RiverPath {
|
class RiverPath {
|
||||||
using ChunkPosSet =
|
|
||||||
tbb::concurrent_hash_map<ChunkPos, bool, ChunkPos::TBBHash>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RiverPath(unsigned int chunk_seed, unsigned world_seed,
|
RiverPath(unsigned int chunk_seed, unsigned world_seed,
|
||||||
@@ -46,8 +43,6 @@ private:
|
|||||||
Random m_random;
|
Random m_random;
|
||||||
|
|
||||||
std::vector<PathPoint> m_points;
|
std::vector<PathPoint> m_points;
|
||||||
ChunkPosSet m_pending_chunks;
|
|
||||||
void collect_path_points();
|
void collect_path_points();
|
||||||
void precompute_chunk_coverage();
|
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||||
#include "Cubed/gameplay/path.hpp"
|
#include "Cubed/gameplay/path.hpp"
|
||||||
#include "Cubed/tools/cubed_random.hpp"
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <tbb/concurrent_hash_map.h>
|
#include <tbb/concurrent_hash_map.h>
|
||||||
@@ -25,7 +24,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<unsigned> m_world_seed{0};
|
std::atomic<unsigned> m_world_seed{0};
|
||||||
Random m_random;
|
|
||||||
std::atomic<float> m_probability{0.01f};
|
std::atomic<float> m_probability{0.01f};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,7 @@ namespace Cubed {
|
|||||||
RiverWorm::RiverWorm() {}
|
RiverWorm::RiverWorm() {}
|
||||||
RiverWorm::~RiverWorm() {}
|
RiverWorm::~RiverWorm() {}
|
||||||
|
|
||||||
void RiverWorm::init(unsigned world_seed) {
|
void RiverWorm::init(unsigned world_seed) { m_world_seed = world_seed; }
|
||||||
m_world_seed = world_seed;
|
|
||||||
|
|
||||||
m_random.init(m_world_seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RiverWorm::reload(unsigned world_seed) {
|
void RiverWorm::reload(unsigned world_seed) {
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ void VertexData::upload() {
|
|||||||
glEnableVertexAttribArray(5);
|
glEnableVertexAttribArray(5);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
// Release memory
|
||||||
|
m_vertices.clear();
|
||||||
}
|
}
|
||||||
void VertexData::update_sum() { m_sum = m_vertices.size(); }
|
void VertexData::update_sum() { m_sum = m_vertices.size(); }
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -5,11 +5,70 @@
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool is_include(const std::string& line) {
|
||||||
|
|
||||||
|
std::string_view sv(line);
|
||||||
|
|
||||||
|
auto first = sv.find_first_not_of(" \t");
|
||||||
|
|
||||||
|
return first != std::string::npos && sv.substr(first, 8) == "#include";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string parse_include(const std::string& line) {
|
||||||
|
auto pos = line.find("#include");
|
||||||
|
auto start = line.find_first_of("<\"", pos);
|
||||||
|
auto end = line.find_first_of(">\"", start + 1);
|
||||||
|
|
||||||
|
if (start == std::string::npos || end == std::string::npos) {
|
||||||
|
Logger::error("Invalid include: {}", line);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return line.substr(start + 1, end - start - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_shader(std::string& source, const fs::path& file,
|
||||||
|
std::unordered_set<fs::path>& included) {
|
||||||
|
if (!fs::is_regular_file(file)) {
|
||||||
|
Logger::error("File {} don't Exist!", file.string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto canon = fs::canonical(file);
|
||||||
|
if (!included.insert(canon).second) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::ifstream in(file);
|
||||||
|
if (!in.is_open()) {
|
||||||
|
Logger::error("Can't open {}", file.string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(in, line)) {
|
||||||
|
if (is_include(line)) {
|
||||||
|
|
||||||
|
auto include_file = file.parent_path() / parse_include(line);
|
||||||
|
source += "// begin include ";
|
||||||
|
source += include_file.string();
|
||||||
|
source += "\n";
|
||||||
|
load_shader(source, include_file, included);
|
||||||
|
source += "// end include ";
|
||||||
|
source += include_file.string();
|
||||||
|
source += "\n";
|
||||||
|
} else {
|
||||||
|
source.append(line + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace Tools {
|
namespace Tools {
|
||||||
|
|
||||||
GLuint create_shader_program(const std::string& v_shader_path,
|
GLuint create_shader_program(const std::string& v_shader_path,
|
||||||
@@ -102,19 +161,9 @@ bool check_opengl_error() {
|
|||||||
|
|
||||||
std::string read_shader_source(const std::string& file_path) {
|
std::string read_shader_source(const std::string& file_path) {
|
||||||
std::string content;
|
std::string content;
|
||||||
std::ifstream file_stream(file_path, std::ios::in);
|
fs::path path(file_path);
|
||||||
|
std::unordered_set<fs::path> included;
|
||||||
if (!file_stream.is_open()) {
|
load_shader(content, path, included);
|
||||||
Logger::error("{} not exist", file_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string line = "";
|
|
||||||
while (!file_stream.eof()) {
|
|
||||||
|
|
||||||
getline(file_stream, line);
|
|
||||||
content.append(line + "\n");
|
|
||||||
}
|
|
||||||
file_stream.close();
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user