Entities dynamic buffer and stochastic texture
This commit is contained in:
parent
3b4e9fd940
commit
734b5b7ac5
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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},
|
||||
|
|
Loading…
Reference in New Issue