Commit 7920e8b4 authored by Shu's avatar Shu 🍠
Browse files

Two pass transparency

parent 9a095a09
......@@ -29,7 +29,7 @@
- [~] Occlusion Culling
- [ ] Iterator ray
- [ ] Cast from chunk center
- [ ] Transparency
- [x] Transparency
- [ ] Entities
## Hello universe
......@@ -64,6 +64,7 @@
## Hello darkness
- [ ] Slash screen
- [ ] Start/Pause menu
- [ ] QUIC protocal
- [ ] Use in memory protocol (to replace server_handle)
- [ ] Octree
......@@ -88,3 +89,5 @@
- [ ] Deferred
- [ ] Cascaded shadow maps
- [ ] Ray Tracing
- [ ] Translucency
- Back face Depth based
......@@ -3,7 +3,7 @@
#define UNIT_SIZE 8
// Ouput data
layout(location = 0) out vec3 color;
layout(location = 0) out vec4 color;
uniform sampler2DArray TextureAtlas;
uniform sampler2DArray NormalAtlas;
......@@ -107,10 +107,10 @@ vec4 getTexture(sampler2DArray sample, vec2 UV) {
#endif
}
vec3 getTriTexture(sampler2DArray sample, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
return getTexture(sample, crdx).rgb * weights.x +
getTexture(sample, crdy).rgb * weights.y +
getTexture(sample, crdz).rgb * weights.z;
vec4 getTriTexture(sampler2DArray sample, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
return getTexture(sample, crdx) * weights.x +
getTexture(sample, crdy) * weights.y +
getTexture(sample, crdz) * weights.z;
}
void main() {
......@@ -127,7 +127,7 @@ void main() {
vec2 UVy = vs.Position_modelspace.zx * texScale;
vec2 UVz = vs.Position_modelspace.xy * texScale;
vec3 tex = getTriTexture(TextureAtlas, UVx, UVy, UVz, blendWeights);
vec4 tex = getTriTexture(TextureAtlas, UVx, UVy, UVz, blendWeights);
#ifdef PBR
// Whiteout normal blend
......@@ -141,7 +141,7 @@ void main() {
// Swizzle tangent normals to match world orientation and triblend
vec3 worldNormal = normalize(texNx.zyx * blendWeights.x + texNy.xzy * blendWeights.y +texNz.xyz * blendWeights.z);
vec3 texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights);
vec3 texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights).rgb;
#endif
#else
// Cheap planar
......@@ -149,7 +149,7 @@ void main() {
vec3 nrm = normalize(pow(blendWeights, vec3(80 / sqrt(UNIT_SIZE))));
vec2 UV = (vec2(vs.Position_modelspace.xy * nrm.z) + vec2(vs.Position_modelspace.yz * nrm.x) + vec2(vs.Position_modelspace.zx * nrm.y)) * texScale;
vec3 tex = getTexture(TextureAtlas, UV).rgb;
vec4 tex = getTexture(TextureAtlas, UV);
#ifdef PBR
vec3 texN = expand(getTexture(NormalAtlas, UV).rgb);
// Swizzle world normals into tangent space and apply Whiteout blend
......@@ -165,7 +165,7 @@ void main() {
// Colors
#ifdef PBR
// Texture properties
vec3 TextureDiffuseColor = tex;
vec3 TextureDiffuseColor = vec3(tex);
vec3 TextureAmbientColor = vec3(.1) * TextureDiffuseColor * texHOS.y;
vec3 TextureSpecularColor = vec3(.8) * texHOS.z;
......@@ -202,22 +202,21 @@ void main() {
// MAYBE: shadow
color =
color = vec4(
// Ambient : simulates indirect lighting
TextureAmbientColor +
// Diffuse : "color" of the object
visibility * TextureDiffuseColor * LightColor * LightPower * cosTheta / (distance * distance) +
// Specular : reflective highlight, like a mirror
visibility * TextureSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance * distance);
visibility * TextureSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance * distance),
// Restore alpha
tex.a);
#else
color = tex;
#endif
#if FOG
float ratio = exp(vs.Depth * 0.69)-1;
color = mix(color, pow(FogColor, vec3(2.2)), clamp(ratio, 0, 1));
color = mix(color, vec4(pow(FogColor, vec3(2.2)), 1), clamp(ratio, 0, 1));
#endif
color = pow(color, vec3(1.0 / 2.2));
if(color.r > 1 || color.g > 1 || color.b > 1) {
color = vec3(1, 0, 0); //TODO: bloom
}
color = pow(color, vec4(vec3(1.0 / 2.2), 1));
}
\ No newline at end of file
......@@ -116,15 +116,16 @@ if(BLEND) {
#endif
}
vec3 getTriTexture(sampler2DArray smpl, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
return getTexture(smpl, crdx).rgb * weights.x +
getTexture(smpl, crdy).rgb * weights.y +
getTexture(smpl, crdz).rgb * weights.z;
vec4 getTriTexture(sampler2DArray smpl, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
return getTexture(smpl, crdx) * weights.x +
getTexture(smpl, crdy) * weights.y +
getTexture(smpl, crdz) * weights.z;
}
void main() {
float texScale = 1. / UNIT_SIZE;
vec3 tex, worldNormal, texHOS;
vec4 tex;
vec3 worldNormal, texHOS;
if(TRIPLANAR) {
// Triplanar
......@@ -152,7 +153,7 @@ if(PBR) {
// Swizzle tangent normals to match world orientation and triblend
worldNormal = normalize(texNx.zyx * blendWeights.x + texNy.xzy * blendWeights.y +texNz.xyz * blendWeights.z);
texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights);
texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights).rgb;
}
} else {
// Cheap planar
......@@ -160,7 +161,7 @@ if(PBR) {
vec3 nrm = normalize(pow(blendWeights, vec3(80 / sqrt(UNIT_SIZE))));
vec2 UV = (vec2(vs.Position_modelspace.xy * nrm.z) + vec2(vs.Position_modelspace.yz * nrm.x) + vec2(vs.Position_modelspace.zx * nrm.y)) * texScale;
tex = getTexture(TextureAtlas, UV).rgb;
tex = getTexture(TextureAtlas, UV);
if(PBR) {
vec3 texN = expand(getTexture(NormalAtlas, UV).rgb);
// Swizzle world normals into tangent space and apply Whiteout blend
......@@ -176,7 +177,7 @@ if(PBR) {
// Colors
if(PBR) {
// Texture properties
vec3 TextureDiffuseColor = tex;
vec3 TextureDiffuseColor = tex.rgb;
vec3 TextureAmbientColor = vec3(.1) * TextureDiffuseColor * texHOS.y;
vec3 TextureSpecularColor = vec3(.8) * texHOS.z;
......@@ -213,21 +214,20 @@ if(PBR) {
// MAYBE: shadow
tex =
color = vec4(
// Ambient : simulates indirect lighting
TextureAmbientColor +
// Diffuse : "color" of the object
visibility * TextureDiffuseColor * LightColor * LightPower * cosTheta / (distance * distance) +
// Specular : reflective highlight, like a mirror
visibility * TextureSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance * distance);
visibility * TextureSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance * distance),
// Restore alpha
tex.a);
} else {
color = tex;
}
if(FOG) {
float ratio = exp(vs.Depth * 0.69)-1;
tex = mix(tex, UBO.fog.rgb, clamp(ratio, 0, 1));
color = mix(color, vec4(UBO.fog.rgb, 1), clamp(ratio, 0, 1));
}
//TODO: check gamma color = pow(color, vec3(1.0 / 2.2));
color = vec4(tex, 1);
/*if(color.r > 1 || color.g > 1 || color.b > 1) {
color = vec4(1, 0, 0, 1); //TODO: bloom
}*/
}
\ No newline at end of file
......@@ -34,7 +34,7 @@ Stone_Path_004_normal.jpg terrain/Stone_path.nrm.dds
Stone_Wall_008_COLOR.jpg terrain/Stone_wall.dds
Stone_Wall_008_HOS.jpg terrain/Stone_wall.hos.dds
Stone_Wall_008_NORM.jpg terrain/Stone_wall.nrm.dds
Water_002_COLOR.jpg terrain/Water.dds
Water_002_COLOR.png terrain/Water.dds
Water_002_HOS.jpg terrain/Water.hos.dds
Water_002_NORM.jpg terrain/Water.nrm.dds
Debug.cube.back.png sky/Debug.cube.back.dds
......
......@@ -137,18 +137,13 @@ void Client::run(server_handle* const localHandle) {
reports.models_count = 0;
reports.tris_count = 0;
std::optional<geometry::Frustum> frustum;
if(options.culling >= 0) {
if(options.culling <= 0) {
frustum = {camera.getFrustum()};
}
const auto offset = state.position.raw_as_long();
{ // Chunks
const auto pass = pipeline->beginWorldPass();
const auto draw = [&](glm::mat4 model, render::LodModel *const buffer, const contouring::Abstract::area_info &area, const voxel_pos &pos) {
reports.models_count++;
reports.tris_count += pass(buffer, model, glm::vec4(pos, std::get<1>(area)), std::get<2>(area));
};
std::vector<glm::vec3> occlusion;
if (options.culling > 0) {
std::vector<glm::vec3> occlusion;
const auto ratio = options.culling * 2;
occlusion.reserve(glm::pow2(ratio * 2 - 1));
const auto [ch, cv] = player.getAngles();
......@@ -160,9 +155,30 @@ void Client::run(server_handle* const localHandle) {
occlusion.emplace_back(cos(v) * sin(h), sin(v), cos(v) * cos(h));
}
}
state.contouring->getModels(draw, player.position, options.camera.far, occlusion, offset, options.voxel_density);
} else {
state.contouring->getModels(draw, frustum, offset, options.voxel_density);
}
{ // Solid
const auto pass = pipeline->beginWorldPass(true);
const auto draw = [&](glm::mat4 model, render::LodModel *const buffer, const contouring::Abstract::area_info &area, const voxel_pos &pos) {
reports.models_count++;
reports.tris_count += pass(buffer, model, glm::vec4(pos, std::get<1>(area)), std::get<2>(area));
};
if (options.culling > 0) {
state.contouring->getModels(draw, player.position, options.camera.far, occlusion, offset, options.voxel_density, true);
} else {
state.contouring->getModels(draw, frustum, offset, options.voxel_density, true);
}
}
if (options.renderer.voxel.transparency) {
const auto pass = pipeline->beginWorldPass(false);
const auto draw = [&](glm::mat4 model, render::LodModel *const buffer, const contouring::Abstract::area_info &area, const voxel_pos &pos) {
reports.models_count++;
reports.tris_count += pass(buffer, model, glm::vec4(pos, std::get<1>(area)), std::get<2>(area));
};
if (options.culling > 0) {
state.contouring->getModels(draw, player.position, options.camera.far, occlusion, offset, options.voxel_density, false);
} else {
state.contouring->getModels(draw, frustum, offset, options.voxel_density, false);
}
}
}
{ // Entities
......
......@@ -49,6 +49,7 @@ public:
renderer.skybox = config["render"]["skybox"].value_or(renderer.skybox);
renderer.voxel.curvature = config["render"]["curvature"].value_or(renderer.voxel.curvature);
renderer.voxel.curv_depth = config["render"]["curvature_depth"].value_or(renderer.voxel.curv_depth);
renderer.voxel.transparency = config["render"]["transparency"].value_or(renderer.voxel.transparency);
culling = config["render"]["culling"].value_or(culling);
contouring = config["contouring"].value_or(std::string(""));
......@@ -120,6 +121,7 @@ public:
{"skybox", renderer.skybox},
{"curvature", renderer.voxel.curvature},
{"curvature_depth", renderer.voxel.curv_depth},
{"transparency", renderer.voxel.transparency},
{"culling", culling}
}));
config.insert_or_assign("contouring", contouring);
......@@ -191,7 +193,7 @@ public:
windowOptions window;
bool preferVulkan = true;
bool preferVulkan = false;
render::renderOptions renderer;
int culling = 0;
......
......@@ -39,9 +39,9 @@ namespace contouring {
/// Get buffers in frustum with model matrices
/// @note buffers invalidated after update
virtual void getModels(draw_call draw, const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density) = 0;
virtual void getModels(draw_call draw, const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density, bool solid) = 0;
/// Get buffers hitting occlusion rays with model matrices
/// @note buffers invalidated after update
virtual void getModels(draw_call draw, const glm::ifvec3 &from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density) = 0;
virtual void getModels(draw_call draw, const glm::ifvec3 &from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) = 0;
};
}
\ No newline at end of file
......@@ -47,8 +47,13 @@ namespace contouring {
loadQueue.wait();
if (loadQueue.pop(ctx)) {
ZoneScopedN("ProcessContouring");
render::LodModel::LodData data;
render(ctx.second, data, tmp);
std::pair<render::LodModel::LodData, render::LodModel::LodData> data;
if (transparency) {
render(ctx.second, data.first, tmp, Layer::Solid);
render(ctx.second, data.second, tmp, Layer::Transparent);
} else {
render(ctx.second, data.first, tmp, Layer::Both);
}
//TODO: direct upload with vulkan
loadedQueue.emplace(ctx.first, data);
}
......@@ -68,7 +73,8 @@ namespace contouring {
//TODO: prefer unique_ptr
for(auto& buffer: buffers) {
for(auto& val: buffer.second.second) {
delete val.second;
delete val.second.first;
delete val.second.second;
}
}
}
......@@ -129,20 +135,24 @@ namespace contouring {
void FlatDualMC::update(const voxel_pos& pos, const world::client::area_map& areas) {
ZoneScopedN("Ct");
std::pair<area_<chunk_pos>, render::LodModel::LodData> out;
std::pair<area_<chunk_pos>, std::pair<render::LodModel::LodData, render::LodModel::LodData>> out;
TracyPlot("CtLoad", static_cast<int64_t>(loadQueue.size()));
//MAYBE: clear out of range loadQueue.trim(keepDistance * keepDistance)
TracyPlot("CtLoaded", static_cast<int64_t>(loadedQueue.size()));
for(auto handle = loadedQueue.extractor(); handle.first(out);) {
const auto buffer = out.second.first.empty() ? NULL : render::LodModel::Create(out.second).release();
const auto bufferSolid = out.second.first.first.empty() ? NULL : render::LodModel::Create(out.second.first).release();
const auto bufferTrans = out.second.second.first.empty() ? NULL : render::LodModel::Create(out.second.second).release();
auto &bfs = buffers[out.first.first].second; //NOTE: buffer.first uninitialized (will be set in clear())
if (const auto it = bfs.find(out.first.second); it != bfs.end()) {
if(it->second != NULL)
delete it->second;
if (it->second.first != NULL)
delete it->second.first;
if (it->second.second != NULL)
delete it->second.second;
it->second = buffer;
it->second.first = bufferSolid;
it->second.second = bufferTrans;
} else {
bfs.emplace(out.first.second, buffer);
bfs.emplace(out.first.second, std::make_pair(bufferSolid, bufferTrans));
}
}
size_t buffer_count = 0;
......@@ -165,13 +175,20 @@ namespace contouring {
auto it = bfs.begin();
while(it != bfs.end()) {
if (const auto distRatio = glm::length(glm::dvec3(center - it->first)) / keepDistance; distRatio > 1) {
if(it->second != NULL)
delete it->second;
if(it->second.first != NULL)
delete it->second.first;
if (it->second.second != NULL)
delete it->second.second;
it = bfs.erase(it);
} else {
if(it->second != NULL) {
it->second->setLevel(std::clamp<size_t>((1+lod_quality-distRatio)*levelMax*(1+lod_strength), 0, levelMax));
const auto level = std::clamp<size_t>((1 + lod_quality - distRatio) * levelMax * (1 + lod_strength), 0, levelMax);
if (it->second.first != NULL) {
it->second.first->setLevel(level);
buffer_count++;
}
if (it->second.second != NULL) {
it->second.second->setLevel(level);
buffer_count++;
}
++it;
......@@ -180,8 +197,10 @@ namespace contouring {
++it_a;
} else {
for(auto& buffer: it_a->second.second) {
if(buffer.second != NULL)
delete buffer.second;
if (buffer.second.first != NULL)
delete buffer.second.first;
if(buffer.second.second != NULL)
delete buffer.second.second;
}
it_a = buffers.erase(it_a);
}
......@@ -220,7 +239,7 @@ namespace contouring {
}
}
void FlatDualMC::render(const surrounding::corners &surrounding, render::LodModel::LodData &out, std::vector<render::VertexData> &tmp) const {
void FlatDualMC::render(const surrounding::corners &surrounding, render::LodModel::LodData &out, std::vector<render::VertexData> &tmp, Layer layer) const {
const int SIZE = CHUNK_LENGTH + 3;
std::array<dualmc::DualMC<float>::Point, SIZE * SIZE * SIZE> grid;
{
......@@ -228,7 +247,9 @@ namespace contouring {
const auto setCell = [&](int x, int y, int z, const world::Voxel &voxel) {
auto &cell = grid[((z * SIZE) + y) * SIZE + x];
cell.w = voxel.material();
cell.x = voxel.density_ratio() * (!world::materials::invisibility[cell.w] && (transparency || !world::materials::transparency[cell.w]));
cell.x = voxel.density_ratio() * (!world::materials::invisibility[cell.w] &&
((world::materials::transparency[cell.w] && (layer && Layer::Transparent)) ||
(!world::materials::transparency[cell.w] && (layer && Layer::Solid))));
};
for (int z = 0; z < SIZE; z++) {
for (int y = 0; y < SIZE; y++) {
......@@ -303,18 +324,19 @@ namespace contouring {
}
}
void FlatDualMC::getModels(draw_call out, const std::optional<geometry::Frustum> &frustum, const glm::llvec3& offset, int density) {
void FlatDualMC::getModels(draw_call out, const std::optional<geometry::Frustum> &frustum, const glm::llvec3& offset, int density, bool solid) {
const auto scaling = glm::scale(glm::mat4(1), glm::vec3(1.f / density));
for (const auto [_, area] : buffers) {
for (const auto [pos, buffer] : area.second) {
for (const auto [pos, buf] : area.second) {
const auto vPos = glm::multiply(pos);
const glm::vec3 fPos = (glm::vec3(std::get<0>(area.first).raw_as_long() + vPos - offset * glm::llvec3(density)) + std::get<0>(area.first).offset) / glm::vec3(density);
const auto buffer = solid ? buf.first : buf.second;
if (buffer != NULL && (!frustum.has_value() || frustum.value().contains(geometry::Box::fromMin(fPos, glm::vec3(CHUNK_LENGTH / (float)density)))))
out(glm::translate(scaling, fPos * (float)density), buffer, area.first, vPos);
}}
}
void FlatDualMC::getModels(draw_call out, const glm::ifvec3& from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density) {
void FlatDualMC::getModels(draw_call out, const glm::ifvec3& from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) {
const auto scaling = glm::scale(glm::mat4(1), glm::vec3(1.f / density));
const auto start = glm::ifvec3(glm::divide(from.as_voxel(density)));
const auto dist = far * density / CHUNK_LENGTH;
......@@ -327,10 +349,11 @@ namespace contouring {
ray.grid(points);
for(auto& point: points) {
auto it = area.second.find(glm::lvec3(point) - area_offset);
if(it != area.second.end() && it->second != NULL && done.insert(it->first).second) {
const auto buffer = solid ? it->second.first : it->second.second;
if(it != area.second.end() && buffer != NULL && done.insert(it->first).second) {
const auto vPos = glm::multiply(it->first);
const glm::vec3 fPos = glm::vec3(std::get<0>(area.first).raw_as_long() + vPos - offset * glm::llvec3(density)) + std::get<0>(area.first).offset;
out(glm::translate(scaling, fPos), it->second, area.first, vPos);
out(glm::translate(scaling, fPos), buffer, area.first, vPos);
break;
}
}
......
......@@ -33,17 +33,17 @@ namespace contouring {
/// Get buffers in frustum with model matrices
/// @note buffers invalidated after update
void getModels(draw_call draw, const std::optional<geometry::Frustum> &frustum, const glm::llvec3 &offset, int density) override;
void getModels(draw_call draw, const std::optional<geometry::Frustum> &frustum, const glm::llvec3 &offset, int density, bool solid) override;
/// Get buffers hitting occlusion rays with model matrices
/// @note buffers invalidated after update
void getModels(draw_call draw, const glm::ifvec3 &from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density) override;
void getModels(draw_call draw, const glm::ifvec3 &from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) override;
protected:
//FIXME: use unique_ptr
robin_hood::unordered_map<area_id, robin_hood::pair<area_info, robin_hood::unordered_map<chunk_pos, render::LodModel*>>> buffers;
robin_hood::unordered_map<area_id, robin_hood::pair<area_info, robin_hood::unordered_map<chunk_pos, std::pair<render::LodModel *, render::LodModel *>>>> buffers;
safe_priority_queue_map<area_<chunk_pos>, surrounding::corners, int, area_hash> loadQueue;
safe_queue<std::pair<area_<chunk_pos>, render::LodModel::LodData>> loadedQueue;
safe_queue<std::pair<area_<chunk_pos>, std::pair<render::LodModel::LodData, render::LodModel::LodData>>> loadedQueue;
bool running = true;
std::vector<std::thread> workers;
......@@ -62,6 +62,15 @@ namespace contouring {
std::vector<std::pair<float, float>> loadedLevels;
void render(const surrounding::corners &surrounding, render::LodModel::LodData& out, std::vector<render::VertexData>& tmp) const;
enum class Layer {
Solid = 1,
Transparent = 2,
Both = Solid | Transparent,
};
friend inline bool operator&&(Layer a, Layer b) {
return static_cast<int>(a) & static_cast<int>(b);
}
void render(const surrounding::corners &surrounding, render::LodModel::LodData& out, std::vector<render::VertexData>& tmp, Layer layer) const;
};
}
......@@ -31,6 +31,8 @@ struct passOptions {
bool curvature = true;
/// Keep depth in sphere
bool curv_depth = true;
/// Alpha blend
bool transparency = false;
};
/// Rendering options
......@@ -68,7 +70,7 @@ public:
virtual void beginFrame() = 0;
/// Get started world program
/// (vertex buffer, model matrix, sphereProj, curvature)
virtual std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> beginWorldPass() = 0;
virtual std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> beginWorldPass(bool solid) = 0;
/// Get started entity program
virtual std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> beginEntityPass() = 0;
/// Draw cube indicator
......
......@@ -109,6 +109,8 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
ImGui::TextDisabled("Depth");
}
changeRenderer |= ImGui::Checkbox("Transparency", &options.renderer.voxel.transparency);
changeRenderer |= ImGui::Checkbox("Fog", &options.renderer.voxel.fog);
ImGui::SameLine();
ImGui::Checkbox("Skybox", &options.renderer.skybox);
......
......@@ -37,6 +37,7 @@ public:
Control = 1 << 7,
FillMode = 1 << 8,
Message = 1 << 9,
Transparency = 1 << 10,
};
friend inline void operator|=(Actions& a, Actions b) {
a = static_cast<Actions>(static_cast<int>(a) | static_cast<int>(b));
......
......@@ -72,6 +72,9 @@ bool Renderer::Load(Window& window, const renderOptions& opt, const windowOption
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
GLint smp;
glGetIntegerv(GL_SAMPLES, &smp);
if (smp > 0) {
......@@ -98,9 +101,11 @@ void Renderer::beginFrame() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> Renderer::beginWorldPass() {
WorldPass->useIt();
WorldPass->start(this);
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> Renderer::beginWorldPass(bool solid) {
if (solid) {
WorldPass->useIt();
WorldPass->start(this);
}
return [&](render::LodModel *const buf, glm::mat4 model, glm::vec4 sph, float curv) {
WorldPass->setup(model, sph, curv);
return dynamic_cast<LodModel *const>(buf)->draw();
......@@ -138,6 +143,11 @@ void Renderer::swapBuffer(Window& w) {
}
void Renderer::reloadShaders(const pass::VoxelProgram::options& options) {
if (options.transparency) {
glEnable(GL_BLEND);
} else {
glDisable(GL_BLEND);
}
WorldPass = std::make_unique<pass::WorldProgram>(options);
EntityPass = std::make_unique<pass::EntityProgram>(options);
}
......
......@@ -43,7 +43,7 @@ public:
}
void beginFrame() override;
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> beginWorldPass() override;
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> beginWorldPass(bool solid) override;
std::function<size_t(render::Model *const, const std::vector<glm::mat4>&)> beginEntityPass() override;
std::function<size_t(glm::mat4)> beginIndicatorPass() override;
void postProcess() override;
......