1
0
Fork 0

Planet sphere

This commit is contained in:
May B. 2020-08-14 18:56:28 +02:00
parent bfba0544d6
commit b7669df9ed
15 changed files with 130 additions and 43 deletions

18
TODO.md
View File

@ -29,13 +29,19 @@
- [x] Offset
- [ ] Rotation
- [~] Planet
- [ ] CubicSphere
- [ ] Healpix
- Render
- [x] CubeSphere
- [ ] Area corrected CubeSphere
- [ ] Corrected Normals
- [ ] Surface curvature
- [ ] Curvature avare frustum
- [ ] Healpix
- [ ] Surface features
- [ ] Biomes
- https://imgur.com/kM8b5Zq
- https://imgur.com/a/bh2iy
- https://speciesdevblog.files.wordpress.com/2012/11/biomemap.png
- [ ] Galaxy
- [ ] Biomes
- https://imgur.com/kM8b5Zq
- https://imgur.com/a/bh2iy
- https://speciesdevblog.files.wordpress.com/2012/11/biomemap.png
- [ ] Leak test
- Valgrind
- Xtree-memory

View File

@ -18,31 +18,49 @@ out VertexData {
#endif
} vs;
uniform mat4 MVP;
uniform mat4 Model;
uniform mat4 View;
uniform mat4 Proj;
uniform vec4 SphereProj;
uniform float Curvature;
uniform vec3 LightInvDirection_worldspace;
uniform float FogDepth;
void main(){
gl_Position = MVP * vec4(Position_modelspace, 1);
vs.Position_modelspace = Position_modelspace;
vec3 Position_worldspace = (Model * vec4(Position_modelspace,1)).xyz;
#ifdef CURVATURE
if(Curvature > 0) {
vec3 Position_areaspace = Position_modelspace + SphereProj.xyz;
vec2 sph = vec2(acos(Position_areaspace.z / length(Position_areaspace.xyz)), atan(Position_areaspace.y, Position_areaspace.x));
#ifdef CURV_DEPTH
float radius = max(max(abs(Position_areaspace.x), abs(Position_areaspace.y)), abs(Position_areaspace.z));
#else
float radius = SphereProj.w;
#endif
vs.Position_modelspace = mix(vs.Position_modelspace, vec3(sin(sph.x)*cos(sph.y), sin(sph.x)*sin(sph.y), cos(sph.x)) * radius - SphereProj.xyz, Curvature);
}
#endif
vec4 Position_cameraspace = View * Model * vec4(vs.Position_modelspace, 1);
gl_Position = Proj * Position_cameraspace;
#ifdef FOG
vs.Depth = length((View * vec4(Position_worldspace,1)).xyz) / FogDepth;
vs.Depth = length(Position_cameraspace.xyz) / FogDepth;
#endif
vs.Material = Material_model;
vs.FaceNormal_modelspace = normalize(Normal_modelspace);
#ifdef PBR
// TODO: correct normal
vs.FaceNormal_worldspace = normalize((Model * vec4(vs.FaceNormal_modelspace, 0)).xyz);
// Vector that goes from the vertex to the camera, in camera space.
// In camera space, the camera is at the origin (0,0,0).
vs.EyeDirection_cameraspace = vec3(0,0,0) - (View * Model * vec4(Position_modelspace,1)).xyz;
vs.EyeDirection_cameraspace = vec3(0,0,0) - Position_cameraspace.xyz;
// Vector that goes from the vertex to the light, in camera space
vs.LightDirection_cameraspace = (View * vec4(LightInvDirection_worldspace,0)).xyz;

View File

@ -31,11 +31,14 @@ namespace contouring {
// Get camera recommended far range
virtual std::pair<float, float> getFarRange() const = 0;
using area_info = std::tuple<area_pos, voxel_pos::value_type, float>;
using draw_call = const std::function<void(glm::mat4, buffer::Abstract *const, const area_info&, const voxel_pos&)> &;
/// Get buffers in frustum with model matrices
/// @note buffers invalidated after update
virtual void getModels(const std::function<void(glm::mat4, buffer::Abstract *const)> &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) = 0;
/// Get buffers hitting occlusion rays with model matrices
/// @note buffers invalidated after update
virtual void getModels(const std::function<void(glm::mat4, buffer::Abstract *const)> &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) = 0;
};
}

View File

@ -12,8 +12,16 @@ namespace contouring {
while (it_a != buffers.end()) { // Remove out of range buffers
if (const auto area = areas.find(it_a->first); area != areas.end()) {
//Update
it_a->second.first = area->second->getOffset();
const auto center = glm::divide(pos - it_a->second.first.as_voxel());
std::get<0>(it_a->second.first) = area->second->getOffset();
std::get<1>(it_a->second.first) = area->second->getChunks().getRadius() * static_cast<long long>(CHUNK_LENGTH);
const auto centerV = pos - std::get<0>(it_a->second.first).as_voxel();
if (auto planet = std::get_if<world::Generator::Properties::planet>(
&area->second->getGenerator().getProperties().shape)) {
const auto dist = glm::max_axis(glm::abs(centerV));
const auto surface = planet->height * planet->surface_roughness;
std::get<2>(it_a->second.first) = std::clamp((dist - surface) / (std::get<1>(it_a->second.first) - surface), -0.1f, 1.f);
}
const auto center = glm::divide(centerV);
auto &bfs = it_a->second.second;
auto it = bfs.begin();
while(it != bfs.end()) {
@ -61,22 +69,23 @@ namespace contouring {
ImGui::SliderInt("Keep Distance", &keepDistance, loadDistance+1, 21);
}
void AbstractFlat::getModels(const std::function<void(glm::mat4, buffer::Abstract *const)> &out, const std::optional<geometry::Frustum> &frustum, const glm::llvec3& offset, int density) {
void AbstractFlat::getModels(draw_call out, const std::optional<geometry::Frustum> &frustum, const glm::llvec3& offset, int density) {
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) {
const glm::vec3 fPos = (glm::vec3(area.first.raw_as_long() + glm::multiply(pos) - offset * glm::llvec3(density)) + area.first.offset) / glm::vec3(density);
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);
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);
out(glm::translate(scaling, fPos * (float)density), buffer, area.first, vPos);
}}
}
void AbstractFlat::getModels(const std::function<void(glm::mat4, buffer::Abstract *const)> &out, const glm::ifvec3& from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density) {
void AbstractFlat::getModels(draw_call out, const glm::ifvec3& from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density) {
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;
for (const auto [_, area] : buffers) {
const auto area_offset = glm::divide(area.first.as_voxel());
const auto area_offset = glm::divide(std::get<0>(area.first).as_voxel());
robin_hood::unordered_set<chunk_pos> done;
for (const auto& occ: occlusion) {
const geometry::Ray ray(start, occ, dist);
@ -85,8 +94,9 @@ namespace contouring {
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 glm::vec3 fPos = glm::vec3(area.first.raw_as_long() + glm::multiply(it->first) - offset * glm::llvec3(density)) + area.first.offset;
out(glm::translate(scaling, fPos), it->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);
break;
}
}

View File

@ -18,15 +18,15 @@ namespace contouring {
/// Get buffers in frustum with model matrices
/// @note buffers invalidated after update
void getModels(const std::function<void(glm::mat4, buffer::Abstract *const)> &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) override;
/// Get buffers hitting occlusion rays with model matrices
/// @note buffers invalidated after update
void getModels(const std::function<void(glm::mat4, buffer::Abstract *const)> &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) override;
protected:
size_t clear(const voxel_pos &, const world::area_map &areas);
robin_hood::unordered_map<area_id, robin_hood::pair<area_pos, robin_hood::unordered_map<chunk_pos, buffer::Abstract *>>> buffers;
robin_hood::unordered_map<area_id, robin_hood::pair<area_info, robin_hood::unordered_map<chunk_pos, buffer::Abstract *>>> buffers;
int loadDistance = 3;
int keepDistance = 4;

View File

@ -15,7 +15,7 @@ namespace contouring {
void onGui() override { }
std::string getOptions() const override { return ""; }
std::pair<float, float> getFarRange() const override { return std::make_pair(0, 0); }
void getModels(const std::function<void(glm::mat4, buffer::Abstract *const)> &, const std::optional<geometry::Frustum> &, const glm::llvec3 &, int) override {}
void getModels(const std::function<void(glm::mat4, buffer::Abstract *const)> &, const glm::ifvec3 &, float, const std::vector<glm::vec3> &, const glm::llvec3 &, int) override {}
void getModels(draw_call, const std::optional<geometry::Frustum> &, const glm::llvec3 &, int) override {}
void getModels(draw_call, const glm::ifvec3 &, float, const std::vector<glm::vec3> &, const glm::llvec3 &, int) override {}
};
}

View File

@ -133,8 +133,16 @@ namespace contouring {
while (it_a != buffers.end()) { // Remove out of range buffers
if (const auto area = areas.find(it_a->first); area != areas.end()) {
//Update
it_a->second.first = area->second->getOffset();
const auto center = glm::divide(pos - it_a->second.first.as_voxel());
std::get<0>(it_a->second.first) = area->second->getOffset();
std::get<1>(it_a->second.first) = area->second->getChunks().getRadius() * static_cast<long long>(CHUNK_LENGTH);
const auto centerV = pos - std::get<0>(it_a->second.first).as_voxel();
if (auto planet = std::get_if<world::Generator::Properties::planet>(
&area->second->getGenerator().getProperties().shape)) {
const auto dist = glm::max_axis(glm::abs(centerV));
const auto surface = planet->height * (1.1+planet->surface_roughness);
std::get<2>(it_a->second.first) = std::clamp<float>((dist - surface) / (std::get<1>(it_a->second.first) - surface), -0.1f, 1.f);
}
const auto center = glm::divide(centerV);
auto &bfs = it_a->second.second;
auto it = bfs.begin();
while(it != bfs.end()) {

View File

@ -40,7 +40,7 @@ private:
GLFWwindow *window;
const InputMap &inputs;
float HorizontalAngle = 3.14f;
float HorizontalAngle = 3.14f / 2;
float VerticalAngle = 0.0f;
bool capturingMouse = false;

View File

@ -200,7 +200,9 @@ int main(int /*unused*/, char */*unused*/[]){
}
const auto offset = state.position.raw_as_long();
{ // Chunks
const auto draw = [&](glm::mat4 model, buffer::Abstract *const buffer) {
const auto draw = [&](glm::mat4 model, buffer::Abstract *const buffer, const contouring::Abstract::area_info &area, const voxel_pos &pos) {
renderer->SphereProj = glm::vec4(pos, std::get<1>(area));
renderer->Curvature = std::get<2>(area);
reports.models_count++;
reports.tris_count += buffer->draw(pass.setup(model));
};

View File

@ -36,6 +36,12 @@ public:
glm::vec3 FogColor;
GLfloat FogDepth;
/// Sphere bending
/// offset.xyz radius.w
glm::vec4 SphereProj;
/// Ratio between spherical and cartesian
float Curvature;
bool SkyEnable;
glm::mat4 getProjectionMatrix() const {

View File

@ -83,6 +83,14 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
ImGui::TextDisabled("Blend");
}
changeRenderer |= ImGui::Checkbox("Curvature", &options.renderer.main.curvature);
ImGui::SameLine();
if(options.renderer.main.curvature) {
changeRenderer |= ImGui::Checkbox("Depth", &options.renderer.main.curv_depth);
} else {
ImGui::TextDisabled("Depth");
}
changeRenderer |= ImGui::Checkbox("Fog", &options.renderer.main.fog);
ImGui::SameLine();
ImGui::Checkbox("Skybox", &options.renderer.skybox);

View File

@ -27,7 +27,7 @@ namespace buffer {
Nrm[3] = nw;
}
GLushort PosMat[4];
GLushort Nrm[4];
GLushort Nrm[4]; //NOTE: Triplanar does not handle 10_10_10_2_REV
bool operator<(const PackedVertexData that) const {
return memcmp((void *)this, (void *)&that, sizeof(PackedVertexData)) > 0;
};

View File

@ -18,6 +18,11 @@ MainProgram::MainProgram(const MainProgram::options& opts): Program() {
if (opts.blend)
flags.emplace_back("BLEND");
}
if (opts.curvature) {
flags.emplace_back("CURVATURE");
if (opts.curv_depth)
flags.emplace_back("CURV_DEPTH");
}
std::vector<Shader*> shaders;
shaders.push_back(loadShader(GL_VERTEX_SHADER, flags));
@ -26,9 +31,9 @@ MainProgram::MainProgram(const MainProgram::options& opts): Program() {
shaders.push_back(loadShader(GL_GEOMETRY_SHADER, flags));
load(shaders);
MVPMatrixID = glGetUniformLocation(ProgramID, "MVP");
ModelMatrixID = glGetUniformLocation(ProgramID, "Model");
ViewMatrixID = glGetUniformLocation(ProgramID, "View");
ProjMatrixID = glGetUniformLocation(ProgramID, "Proj");
TextureID = glGetUniformLocation(ProgramID, "TextureAtlas");
NormalID = glGetUniformLocation(ProgramID, "NormalAtlas");
@ -38,6 +43,9 @@ MainProgram::MainProgram(const MainProgram::options& opts): Program() {
FogDepthID = glGetUniformLocation(ProgramID, "FogDepth");
FogColorID = glGetUniformLocation(ProgramID, "FogColor");
SphereProjID = glGetUniformLocation(ProgramID, "SphereProj");
CurvatureID = glGetUniformLocation(ProgramID, "Curvature");
}
MainProgram::~MainProgram() { }
@ -51,17 +59,18 @@ void MainProgram::start(Renderer *renderer) {
bindHOS(renderer->getHOSAtlas());
setLightInvDir(&renderer->LightInvDir[0]);
setFog(&renderer->FogColor[0], renderer->FogDepth);
setView(&renderer->getViewMatrix()[0][0]);
setProj(&renderer->getProjectionMatrix()[0][0]);
}
buffer::params MainProgram::setup(Renderer *renderer, glm::mat4 modelMatrix) {
setModel(&modelMatrix[0][0]);
setView(&renderer->getViewMatrix()[0][0]);
const auto mvp = renderer->getProjectionMatrix() * renderer->getViewMatrix() * modelMatrix;
setMVP(&mvp[0][0]);
setSphereProj(&renderer->SphereProj[0]);
setCurvature(renderer->Curvature);
return buffer::params{.vertexOnly = false};
}
void MainProgram::setMVP(const GLfloat *matrix) {
glUniformMatrix4fv(MVPMatrixID, 1, GL_FALSE, matrix);
void MainProgram::setProj(const GLfloat *matrix) {
glUniformMatrix4fv(ProjMatrixID, 1, GL_FALSE, matrix);
}
void MainProgram::setModel(const GLfloat *matrix) {
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, matrix);
@ -92,4 +101,11 @@ void MainProgram::setLightInvDir(const GLfloat *pos) {
void MainProgram::setFog(const GLfloat *color, const GLfloat depth) {
glUniform3fv(FogColorID, 1, color);
glUniform1f(FogDepthID, depth);
}
void MainProgram::setSphereProj(const GLfloat *posRad) {
glUniform4fv(SphereProjID, 1, posRad);
}
void MainProgram::setCurvature(GLfloat ratio) {
glUniform1f(CurvatureID, ratio);
}

View File

@ -18,6 +18,10 @@ namespace pass {
bool blend = true;
/// Depth fog
bool fog = true;
/// Map planets to sphere
bool curvature = true;
/// Keep depth in sphere
bool curv_depth = true;
};
MainProgram(const options &opts);
@ -27,9 +31,9 @@ namespace pass {
void start(Renderer *) override;
buffer::params setup(Renderer *, glm::mat4 modelMatrix) override;
void setMVP(const GLfloat *matrix);
void setModel(const GLfloat *matrix);
void setView(const GLfloat *matrix);
void setProj(const GLfloat *matrix);
void bindTexture(const GLuint textureID);
void bindNormal(const GLuint textureID);
@ -38,10 +42,13 @@ namespace pass {
void setLightInvDir(const GLfloat *pos);
void setFog(const GLfloat *color, GLfloat depth);
void setSphereProj(const GLfloat *offRad);
void setCurvature(GLfloat ratio);
private:
GLuint MVPMatrixID;
GLuint ModelMatrixID;
GLuint ViewMatrixID;
GLuint ProjMatrixID;
GLuint TextureID;
GLuint NormalID;
@ -50,5 +57,8 @@ namespace pass {
GLuint LightInvDirID;
GLuint FogDepthID;
GLuint FogColorID;
GLuint SphereProjID;
GLuint CurvatureID;
};
}

View File

@ -48,9 +48,9 @@ Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"
} else {
LOG_E("No index file!!! Probably a new world...");
//TODO: generate universe
/*const auto radius = 1 << 4;
far_areas.emplace(Area::params{glm::multiply(voxel_pos(radius)), radius, Generator::Properties(radius * CHUNK_LENGTH * 3 / 4, 42)});*/
far_areas.emplace(Area::params{voxel_pos(0), 1 << 20, Generator::Properties(42)});
const auto radius = 1 << 4;
far_areas.emplace(Area::params{glm::multiply(voxel_pos(radius, 0, 0)), radius, Generator::Properties(radius * CHUNK_LENGTH * 3 / 4, 42)});
//far_areas.emplace(Area::params{voxel_pos(0), 1 << 20, Generator::Properties(42)});
}
index.close();
}