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;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
#include "compute_sky_color.glsl"
|
||||
|
||||
void main(void) {
|
||||
|
||||
vec3 sky = computeSkyColor(dir);
|
||||
|
||||
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 float waterDensity;
|
||||
|
||||
float hash(vec2 p) {
|
||||
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;
|
||||
}
|
||||
#include "noise.glsl"
|
||||
|
||||
float getCausticValue(float x, float y, float z) {
|
||||
float w = 8.0;
|
||||
|
||||
@@ -42,82 +42,15 @@ uniform float refractStrength;
|
||||
|
||||
uniform bool enablePerturb;
|
||||
uniform bool enableDepthFade;
|
||||
|
||||
#include "compute_sky_color.glsl"
|
||||
|
||||
float weight(float z, float a) {
|
||||
float intermediate = 0.03 / (1e-5 + pow(z / 200.0, 4.0));
|
||||
|
||||
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
|
||||
vec3 reconstructViewPos(vec2 uv, float depth) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/path_point.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
|
||||
@@ -9,8 +8,6 @@
|
||||
namespace Cubed {
|
||||
|
||||
class CavePath {
|
||||
using ChunkPosSet =
|
||||
tbb::concurrent_hash_map<ChunkPos, bool, ChunkPos::TBBHash>;
|
||||
|
||||
public:
|
||||
CavePath(unsigned int chunk_seed, unsigned world_seed,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/path_point.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
|
||||
@@ -9,8 +8,6 @@
|
||||
|
||||
namespace Cubed {
|
||||
class RiverPath {
|
||||
using ChunkPosSet =
|
||||
tbb::concurrent_hash_map<ChunkPos, bool, ChunkPos::TBBHash>;
|
||||
|
||||
public:
|
||||
RiverPath(unsigned int chunk_seed, unsigned world_seed,
|
||||
@@ -46,8 +43,6 @@ private:
|
||||
Random m_random;
|
||||
|
||||
std::vector<PathPoint> m_points;
|
||||
ChunkPosSet m_pending_chunks;
|
||||
void collect_path_points();
|
||||
void precompute_chunk_coverage();
|
||||
};
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/path.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <tbb/concurrent_hash_map.h>
|
||||
@@ -25,7 +24,6 @@ public:
|
||||
|
||||
private:
|
||||
std::atomic<unsigned> m_world_seed{0};
|
||||
Random m_random;
|
||||
std::atomic<float> m_probability{0.01f};
|
||||
};
|
||||
|
||||
|
||||
@@ -7,11 +7,7 @@ namespace Cubed {
|
||||
RiverWorm::RiverWorm() {}
|
||||
RiverWorm::~RiverWorm() {}
|
||||
|
||||
void RiverWorm::init(unsigned world_seed) {
|
||||
m_world_seed = world_seed;
|
||||
|
||||
m_random.init(m_world_seed);
|
||||
}
|
||||
void RiverWorm::init(unsigned world_seed) { m_world_seed = world_seed; }
|
||||
|
||||
void RiverWorm::reload(unsigned world_seed) {
|
||||
|
||||
|
||||
@@ -63,6 +63,9 @@ void VertexData::upload() {
|
||||
glEnableVertexAttribArray(5);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
// Release memory
|
||||
m_vertices.clear();
|
||||
}
|
||||
void VertexData::update_sum() { m_sum = m_vertices.size(); }
|
||||
} // namespace Cubed
|
||||
@@ -5,11 +5,70 @@
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
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 {
|
||||
|
||||
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 content;
|
||||
std::ifstream file_stream(file_path, std::ios::in);
|
||||
|
||||
if (!file_stream.is_open()) {
|
||||
Logger::error("{} not exist", file_path);
|
||||
}
|
||||
|
||||
std::string line = "";
|
||||
while (!file_stream.eof()) {
|
||||
|
||||
getline(file_stream, line);
|
||||
content.append(line + "\n");
|
||||
}
|
||||
file_stream.close();
|
||||
fs::path path(file_path);
|
||||
std::unordered_set<fs::path> included;
|
||||
load_shader(content, path, included);
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user