Commit 734b5b7a authored by Shu's avatar Shu 🍠
Browse files

Entities dynamic buffer and stochastic texture

parent 3b4e9fd9
......@@ -38,27 +38,70 @@ vec3 expand(vec3 v) {
return (v - 0.5) * 2;
}
vec2 hash2D(vec2 s) {
// magic numbers
return fract(sin(mod(vec2(dot(s, vec2(127.1, 311.7)), dot(s, vec2(269.5, 183.3))), 3.14159)) * 43758.5453);
}
vec4 textureStochastic(sampler2DArray sample, vec3 UV) {
#ifdef STOCHASTIC
// triangular by approx 2*sqrt(3)
vec2 skewUV = mat2(1.0, 0.0, -0.57735027, 1.15470054) * (UV.xy * 3.46400);
// vertex id and barrycentric coords
vec2 vxID = vec2(floor(skewUV));
vec3 barry = vec3(fract(skewUV), 0);
barry.z = 1.0 - barry.x - barry.y;
vec3 BW_vx0;
vec3 BW_vx1;
vec3 BW_vx2;
vec3 BW_vx3;
if(barry.z > 0) {
BW_vx0 = vec3(vxID, 0);
BW_vx1 = vec3(vxID + vec2(0, 1), 0);
BW_vx2 = vec3(vxID + vec2(1, 0), 0);
BW_vx3 = barry.zyx;
} else {
BW_vx0 = vec3(vxID + vec2(1, 1), 0);
BW_vx1 = vec3(vxID + vec2(1, 0), 0);
BW_vx2 = vec3(vxID + vec2(0, 1), 0);
BW_vx3 = vec3(-barry.z, 1.0 - barry.y, 1.0 - barry.x);
}
vec2 dx = dFdx(UV.xy);
vec2 dy = dFdy(UV.xy);
return textureGrad(sample, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x +
textureGrad(sample, vec3(UV.xy + hash2D(BW_vx1.xy), UV.z), dx, dy) * BW_vx3.y +
textureGrad(sample, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z;
#else
return texture(sample, UV);
#endif
}
vec4 getTexture(sampler2DArray sample, vec2 UV) {
#ifdef GEOMETRY
#ifdef BLEND
vec4 colx = texture(sample, vec3(UV, vs.Textures[0]));
vec4 colx = textureStochastic(sample, vec3(UV, vs.Textures[0]));
if(vs.Textures[1] == vs.Textures[0]) {
return vs.Textures[2] == vs.Textures[0] ? colx :
mix(colx, texture(sample, vec3(UV, vs.Textures[2])), vs.TextureRatio.z);
mix(colx, textureStochastic(sample, vec3(UV, vs.Textures[2])), vs.TextureRatio.z);
} else {
vec4 coly = texture(sample, vec3(UV, vs.Textures[1]));
vec4 coly = textureStochastic(sample, vec3(UV, vs.Textures[1]));
return vs.Textures[2] == vs.Textures[0] ? mix(colx, coly, vs.TextureRatio.y) : (
vs.Textures[2] == vs.Textures[1] ? mix(coly, colx, vs.TextureRatio.x) :
colx * vs.TextureRatio.x + coly * vs.TextureRatio.y + texture(sample, vec3(UV, vs.Textures[2])) * vs.TextureRatio.z);
colx * vs.TextureRatio.x + coly * vs.TextureRatio.y + textureStochastic(sample, vec3(UV, vs.Textures[2])) * vs.TextureRatio.z);
}
#else
int mainTexture = vs.TextureRatio.x >= vs.TextureRatio.y ?
(vs.TextureRatio.x >= vs.TextureRatio.z ? 0 : 2) :
(vs.TextureRatio.y >= vs.TextureRatio.z ? 1 : 2);
return texture(sample, vec3(UV, vs.Textures[mainTexture]));
return textureStochastic(sample, vec3(UV, vs.Textures[mainTexture]));
#endif
#else
return texture(sample, vec3(UV, vs.Texture));
return textureStochastic(sample, vec3(UV, vs.Texture));
#endif
}
......
......@@ -74,6 +74,10 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
changeRenderer |= ImGui::Checkbox("PBR", &options.renderer.voxel.pbr);
ImGui::SameLine();
changeRenderer |= ImGui::Checkbox("Triplanar", &options.renderer.voxel.triplanar);
ImGui::SameLine();
changeRenderer |= ImGui::Checkbox("Stochastic", &options.renderer.voxel.stochastic);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Hide textures tilling\nMay cause visible inconsistances on chunk borders");
changeRenderer |= ImGui::Checkbox("Geometry", &options.renderer.voxel.geometry);
ImGui::SameLine();
......
......@@ -4,8 +4,16 @@
using namespace pass;
EntityProgram::EntityProgram(const EntityProgram::options& opts): VoxelProgram(opts, {"INSTANCED"}) {
ModelsBufferID = 0;
inline void createBuffer(GLuint *id, const GLfloat *data, size_t count) {
glGenBuffers(1, id);
glBindBuffer(GL_ARRAY_BUFFER, *id);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * count, data, GL_STREAM_DRAW);
}
EntityProgram::EntityProgram(const EntityProgram::options &opts) : VoxelProgram(opts, {"INSTANCED"}) {
constexpr auto INIT_SIZE = 100;
createBuffer(&ModelsBufferID, NULL, INIT_SIZE);
ModelBufferSize = INIT_SIZE;
}
EntityProgram::~EntityProgram() { }
......@@ -17,12 +25,14 @@ buffer::params EntityProgram::setup(Renderer *renderer, const std::vector<glm::m
}
void EntityProgram::setModels(const GLfloat *matrices, size_t count) {
if (ModelsBufferID != 0) { //MAYBE: writable buffer
glDeleteBuffers(1, &ModelsBufferID);
if (count > ModelBufferSize) {
glDeleteBuffers(1, &ModelsBufferID); // Replace buffer
createBuffer(&ModelsBufferID, matrices, count);
ModelBufferSize = count;
} else {
glBindBuffer(GL_ARRAY_BUFFER, ModelsBufferID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::mat4) * count, matrices);
}
glGenBuffers(1, &ModelsBufferID);
glBindBuffer(GL_ARRAY_BUFFER, ModelsBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * count, matrices, GL_STATIC_DRAW);
glEnableVertexAttribArray(LOCATION + 0);
glVertexAttribPointer(LOCATION + 0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(glm::vec4), (void *)0);
......
......@@ -18,6 +18,7 @@ namespace pass {
void setModels(const GLfloat *matrices, size_t count);
private:
GLuint ModelsBufferID;
GLuint ModelsBufferID = 0;
size_t ModelBufferSize = 0;
};
}
\ No newline at end of file
......@@ -6,10 +6,12 @@ using namespace pass;
VoxelProgram::VoxelProgram(const VoxelProgram::options& opts, std::vector<std::string> flags): Program() {
if(opts.pbr)
if (opts.pbr)
flags.emplace_back("PBR");
if(opts.triplanar)
if (opts.triplanar)
flags.emplace_back("TRIPLANAR");
if (opts.stochastic)
flags.emplace_back("STOCHASTIC");
if (opts.fog)
flags.emplace_back("FOG");
if (opts.geometry) {
......
......@@ -12,6 +12,8 @@ namespace pass {
bool pbr = true;
/// Triplanar texture mapping
bool triplanar = false;
/// Transform texture UV
bool stochastic = false;
/// Active geometry pass
bool geometry = false;
/// Blend voxel with mixed materials (requires geometry)
......
......@@ -41,12 +41,15 @@ struct options {
renderer.mipMapLOD = config["render"]["texture_quality"].value_or(renderer.mipMapLOD);
renderer.voxel.pbr = config["render"]["pbr"].value_or(renderer.voxel.pbr);
renderer.voxel.triplanar = config["render"]["triplanar"].value_or(renderer.voxel.triplanar);
renderer.voxel.stochastic = config["render"]["stochastic"].value_or(renderer.voxel.stochastic);
renderer.voxel.geometry = config["render"]["geometry"].value_or(renderer.voxel.geometry);
renderer.voxel.blend = config["render"]["blend"].value_or(renderer.voxel.blend);
renderer.voxel.fog = config["render"]["fog"].value_or(renderer.voxel.fog);
const std::string fog = config["render"]["fog_color"].value_or(std::string{"#000000"});
renderer.clear_color = fromHex(fog);
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);
world.loadDistance = config["world"]["load_distance"].value_or(world.loadDistance);
world.keepDistance = config["world"]["keep_distance"].value_or(world.keepDistance);
......@@ -93,11 +96,14 @@ struct options {
{"texture_quality", renderer.mipMapLOD},
{"pbr", renderer.voxel.pbr},
{"triplanar", renderer.voxel.triplanar},
{"stochastic", renderer.voxel.stochastic},
{"geometry", renderer.voxel.geometry},
{"blend", renderer.voxel.blend},
{"fog", renderer.voxel.fog},
{"fog_color", toHexa(renderer.clear_color)},
{"skybox", renderer.skybox}
{"skybox", renderer.skybox},
{"curvature", renderer.voxel.curvature},
{"curvature_depth", renderer.voxel.curv_depth}
}));
config.insert_or_assign("world", toml::table({
{"load_distance", world.loadDistance},
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment