diff --git a/include/weird-engine/Scene.h b/include/weird-engine/Scene.h index 0a33040..941b16b 100644 --- a/include/weird-engine/Scene.h +++ b/include/weird-engine/Scene.h @@ -27,10 +27,10 @@ namespace WeirdEngine void get2DShapesData(WeirdRenderer::Dot2D*& data, uint32_t& size); - Scene(const Scene&) = default; // Deleted copy constructor + Scene(const Scene&) = default; // Deleted copy constructor Scene& operator=(const Scene&) = default; // Deleted copy assignment operator - Scene(Scene&&) = default; // Defaulted move constructor - Scene& operator=(Scene&&) = default; // Defaulted move assignment operator + Scene(Scene&&) = default; // Defaulted move constructor + Scene& operator=(Scene&&) = default; // Defaulted move assignment operator WeirdRenderer::Camera& getCamera(); std::vector& getLigths(); @@ -64,8 +64,7 @@ namespace WeirdEngine std::vector> m_sdfs; - Entity addShape(int shapeId, float* variables); - Entity addScreenSpaceShape(int shapeId, float* variables); + Entity addShape(ShapeId shapeId, float* variables, CombinationType combination = CombinationType::Addition, bool hasCollision = true, int group = 0); void lookAt(Entity entity); diff --git a/include/weird-engine/ecs/Components/CustomShape.h b/include/weird-engine/ecs/Components/CustomShape.h index 2c86495..48f3d2e 100644 --- a/include/weird-engine/ecs/Components/CustomShape.h +++ b/include/weird-engine/ecs/Components/CustomShape.h @@ -4,14 +4,27 @@ namespace WeirdEngine { + using ShapeId = std::uint16_t; + + enum class CombinationType : uint16_t + { + Addition, + Subtraction, + Intersection, + SmoothAddition + }; + struct CustomShape : public Component { public: uint16_t m_distanceFieldId; + CombinationType m_combination; float m_parameters[8]; bool m_isDirty; bool m_screenSpace; + bool m_hasCollision; + uint16_t m_groupId; CustomShape() : m_distanceFieldId(0), m_isDirty(true), m_screenSpace(false) { @@ -22,5 +35,12 @@ namespace WeirdEngine std::copy(params, params + 8, m_parameters); } + static constexpr ShapeId CIRCLE = 2; + static constexpr ShapeId BOX = 3; + static constexpr ShapeId SINE = 0; + static constexpr ShapeId STAR = 1; + + static constexpr uint16_t GLOBAL_GROUP = std::numeric_limits::max(); + }; -} \ No newline at end of file +} diff --git a/include/weird-engine/ecs/Systems/SDFRenderSystem2D.h b/include/weird-engine/ecs/Systems/SDFRenderSystem2D.h index 969e0f2..cc344c8 100644 --- a/include/weird-engine/ecs/Systems/SDFRenderSystem2D.h +++ b/include/weird-engine/ecs/Systems/SDFRenderSystem2D.h @@ -98,7 +98,7 @@ namespace WeirdEngine return closestIndex; } - bool shaderNeedsUpdate() const + bool& shaderNeedsUpdate() { return m_customShapesNeedUpdate; } diff --git a/include/weird-physics/Simulation2D.h b/include/weird-physics/Simulation2D.h index 879f91e..2ad4a87 100644 --- a/include/weird-physics/Simulation2D.h +++ b/include/weird-physics/Simulation2D.h @@ -256,9 +256,11 @@ namespace WeirdEngine { Entity owner; uint16_t distanceFieldId; + CombinationType combinationId; + uint16_t groupId; float parameters[11]; - DistanceFieldObject2D(Entity owner, uint16_t id, float* params) : distanceFieldId(id), owner(owner) + DistanceFieldObject2D(Entity owner, uint16_t id, CombinationType combinationId, uint16_t groupId, float* params) : distanceFieldId(id), combinationId(combinationId), groupId(groupId), owner(owner) { std::copy(params, params + 8, parameters); // Copy params into parameters } diff --git a/src/weird-engine/Scene.cpp b/src/weird-engine/Scene.cpp index 3f75385..27a553d 100644 --- a/src/weird-engine/Scene.cpp +++ b/src/weird-engine/Scene.cpp @@ -13,7 +13,7 @@ namespace WeirdEngine void Scene::handleCollision(CollisionEvent &event, void *userData) { // Unsafe cast! Prone to error. - Scene* self = static_cast(userData); + Scene *self = static_cast(userData); self->onCollision(event); } @@ -21,9 +21,8 @@ namespace WeirdEngine vec3 g_cameraPosition(0, 1, 20); Scene::Scene() - : m_simulation2D(MAX_ENTITIES), m_sdfRenderSystem(m_ecs), m_sdfRenderSystem2D(m_ecs), m_renderSystem(m_ecs), m_instancedRenderSystem(m_ecs), m_rbPhysicsSystem2D(m_ecs), m_physicsInteractionSystem(m_ecs), m_playerMovementSystem(m_ecs), m_cameraSystem(m_ecs), m_runSimulationInThread(true) + : m_simulation2D(MAX_ENTITIES), m_sdfRenderSystem(m_ecs), m_sdfRenderSystem2D(m_ecs), m_renderSystem(m_ecs), m_instancedRenderSystem(m_ecs), m_rbPhysicsSystem2D(m_ecs), m_physicsInteractionSystem(m_ecs), m_playerMovementSystem(m_ecs), m_cameraSystem(m_ecs), m_runSimulationInThread(true) { - // Custom component managers std::shared_ptr rbManager = std::make_shared(m_simulation2D); m_ecs.registerComponent(rbManager); @@ -67,12 +66,12 @@ namespace WeirdEngine case WeirdEngine::Scene::RenderMode::RayMarching3D: case WeirdEngine::Scene::RenderMode::RayMarchingBoth: { - FlyMovement& fly = m_ecs.addComponent(m_mainCamera); + FlyMovement &fly = m_ecs.addComponent(m_mainCamera); break; } case WeirdEngine::Scene::RenderMode::RayMarching2D: { - FlyMovement2D& fly = m_ecs.addComponent(m_mainCamera); + FlyMovement2D &fly = m_ecs.addComponent(m_mainCamera); // fly.targetPosition = g_cameraPosition; break; } @@ -83,9 +82,9 @@ namespace WeirdEngine } // TODO: pass render target instead of shader. Shaders should be accessed in a different way, through the resource manager - void Scene::renderModels(WeirdRenderer::RenderTarget& renderTarget, WeirdRenderer::Shader& shader, WeirdRenderer::Shader& instancingShader) + void Scene::renderModels(WeirdRenderer::RenderTarget &renderTarget, WeirdRenderer::Shader &shader, WeirdRenderer::Shader &instancingShader) { - WeirdRenderer::Camera& camera = m_ecs.getComponent(m_mainCamera).camera; + WeirdRenderer::Camera &camera = m_ecs.getComponent(m_mainCamera).camera; m_renderSystem.render(m_ecs, m_resourceManager, shader, camera, m_lights); onRender(renderTarget); @@ -93,7 +92,7 @@ namespace WeirdEngine // m_instancedRenderSystem.render(m_ecs, m_resourceManager, instancingShader, camera, m_lights); } - void replaceSubstring(std::string& str, const std::string& from, const std::string& to) + void replaceSubstring(std::string &str, const std::string &from, const std::string &to) { size_t start_pos = str.find(from); if (start_pos != std::string::npos) @@ -102,88 +101,170 @@ namespace WeirdEngine } } - void Scene::updateCustomShapesShader(WeirdRenderer::Shader& shader) + void Scene::updateCustomShapesShader(WeirdRenderer::Shader &shader) { + auto sdfBalls = m_ecs.getComponentManager()->getComponentArray(); + int32_t ballsCount = sdfBalls->getSize(); + auto componentArray = m_ecs.getComponentManager()->getComponentArray(); + shader.setUniform("u_customShapeCount", componentArray->getSize()); + if (!m_sdfRenderSystem2D.shaderNeedsUpdate()) { return; } + m_sdfRenderSystem2D.shaderNeedsUpdate() = false; + std::string str = shader.getFragmentCode(); std::string toReplace("/*ADD_SHAPES_HERE*/"); std::ostringstream oss; - auto atomArray = m_ecs.getComponentManager()->getComponentArray(); - int32_t atomCount = atomArray->getSize(); - auto componentArray = m_ecs.getComponentManager()->getComponentArray(); - shader.setUniform("u_customShapeCount", componentArray->getSize()); - oss << "int dataOffset = u_loadedObjects - (2 * u_customShapeCount);"; + + oss << "///////////////////////////////////////////\n"; + + oss << "int dataOffset = u_loadedObjects - (2 * u_customShapeCount);\n"; + + int currentGroup = -1; + std::string groupDistanceVariable; for (size_t i = 0; i < componentArray->getSize(); i++) { - auto& shape = componentArray->getDataAtIdx(i); + // Get shape + auto &shape = componentArray->getDataAtIdx(i); - oss << "{"; + // Get group + int group = shape.m_groupId; + // Start new group if necessary + if(group != currentGroup) + { + // If this is not the first group, combine current group distance with global minDistance + if(currentGroup != -1) + { + oss << "if(minDist >"<< groupDistanceVariable <<"){ minDist = "<< groupDistanceVariable <<";\n"; + oss << "col = getMaterial(p," << 3 << ");}\n"; + } + + // Next group + currentGroup = group; + groupDistanceVariable = "d" + std::to_string(currentGroup); + + // Initialize distance with big value + oss << "float " << groupDistanceVariable << "= 10000;\n"; + } + + // Start shape + oss << "{\n"; + + // Calculate data position in array oss << "int idx = dataOffset + " << 2 * i << ";\n"; // Fetch parameters - oss << "vec4 parameters0 = texelFetch(t_shapeBuffer, idx);"; - oss << "vec4 parameters1 = texelFetch(t_shapeBuffer, idx + 1);"; + oss << "vec4 parameters0 = texelFetch(t_shapeBuffer, idx);\n"; + oss << "vec4 parameters1 = texelFetch(t_shapeBuffer, idx + 1);\n"; + // Get distance function auto fragmentCode = m_sdfs[shape.m_distanceFieldId]->print(); + // Use screen space coords (DEPRECATED) if (shape.m_screenSpace) { replaceSubstring(fragmentCode, "var9", "var11"); replaceSubstring(fragmentCode, "var10", "var12"); } + bool globalEffect = group == CustomShape::GLOBAL_GROUP; + + // Shape distance calculation oss << "float dist = " << fragmentCode << ";" << std::endl; - /*if (shape.m_screenSpace) + // Apply globalEffect logic + oss << "float currentMinDistance = " << (globalEffect ? "minDist" : groupDistanceVariable) << ";" << std::endl; + + // Combine shape distance + switch (shape.m_combination) { - oss << "dist = dist * u_uiScale;" << std::endl; - }*/ + case CombinationType::Addition: + { + // Scale negative distances + oss << "dist = dist > 0 ? dist : 0.1 * dist;" << std::endl; + oss << "currentMinDistance = min(currentMinDistance, dist);\n"; + break; + } + case CombinationType::Subtraction: + { + oss << "currentMinDistance = max(currentMinDistance, -dist);\n"; + break; + } + case CombinationType::Intersection: + { + oss << "currentMinDistance = max(currentMinDistance, dist);\n"; + break; + } + case CombinationType::SmoothAddition: + { + oss << "currentMinDistance = fOpUnionSoft(currentMinDistance, dist, 1.0);\n"; + break; + } + default: + break; + } - oss << "dist = dist > 0 ? dist : 0.1 * dist;" << std::endl; + // Assign back to the correct target + oss << (globalEffect ? "minDist" : groupDistanceVariable) << " = currentMinDistance;\n"; + oss << "}\n\n"; + } - oss << "d = min(d, dist);\n"; - // oss << "col = d == (dist) ? getMaterial(p," << (i % 12) + 4 << ") : col;\n"; - oss << "col = d == (dist) ? getMaterial(p," << 3 << ") : col;\n"; - oss << "}\n" - << std::endl; + // Combine last group + if (componentArray->getSize() > 0) + { + oss << "if(minDist >" << groupDistanceVariable << "){ minDist = " << groupDistanceVariable << ";\n"; + oss << "col = getMaterial(p," << 3 << ");}\n"; } + // oss << "minDist -= 1.5;\n"; + + // Get string std::string replacement = oss.str(); + // Print + std::cout << replacement << std::endl; + + // Replace in shader source code size_t pos = str.find(toReplace); + // Check if the substring was found if (pos != std::string::npos) - { // Check if the substring was found + { // Replace the substring str.replace(pos, toReplace.length(), replacement); } + // Set new source code and recompile shader shader.setFragmentCode(str); } - void Scene::updateRayMarchingShader(WeirdRenderer::Shader& shader) + void Scene::updateRayMarchingShader(WeirdRenderer::Shader &shader) { m_sdfRenderSystem2D.updatePalette(shader); updateCustomShapesShader(shader); } - void Scene::get2DShapesData(WeirdRenderer::Dot2D*& data, uint32_t& size) + void Scene::get2DShapesData(WeirdRenderer::Dot2D *&data, uint32_t &size) { m_sdfRenderSystem2D.fillDataBuffer(data, size); } void Scene::update(double delta, double time) { + if (Input::GetKeyDown((Input::V))) + { + m_sdfRenderSystem2D.shaderNeedsUpdate() = true; + } + // Update systems if (m_debugFly) { @@ -207,12 +288,12 @@ namespace WeirdEngine m_ecs.freeRemovedComponents(); } - WeirdRenderer::Camera& Scene::getCamera() + WeirdRenderer::Camera &Scene::getCamera() { return m_ecs.getComponent(m_mainCamera).camera; } - std::vector& Scene::getLigths() + std::vector &Scene::getLigths() { return m_lights; } @@ -222,7 +303,7 @@ namespace WeirdEngine return m_simulation2D.getSimulationTime(); } - void Scene::fillShapeDataBuffer(WeirdRenderer::Dot2D*& data, uint32_t& size) + void Scene::fillShapeDataBuffer(WeirdRenderer::Dot2D *&data, uint32_t &size) { m_sdfRenderSystem2D.fillDataBuffer(data, size); } @@ -232,42 +313,34 @@ namespace WeirdEngine return m_renderMode; } - Entity Scene::addShape(int shapeId, float* variables) + Entity Scene::addShape(ShapeId shapeId, float* variables, CombinationType combination, bool hasCollision, int group) { Entity entity = m_ecs.createEntity(); - CustomShape& shape = m_ecs.addComponent(entity); + CustomShape &shape = m_ecs.addComponent(entity); shape.m_distanceFieldId = shapeId; + shape.m_combination = combination; + shape.m_hasCollision = hasCollision; + shape.m_groupId = group; std::copy(variables, variables + 8, shape.m_parameters); // CustomShape shape(shapeId, variables); // check old constructor for references - return entity; - } - - Entity Scene::addScreenSpaceShape(int shapeId, float* variables) - { - Entity entity = m_ecs.createEntity(); - CustomShape& shape = m_ecs.addComponent(entity); - shape.m_screenSpace = true; - shape.m_distanceFieldId = shapeId; - std::copy(variables, variables + 8, shape.m_parameters); - - // CustomShape shape(shapeId, variables); // check old constructor for references + m_sdfRenderSystem2D.shaderNeedsUpdate() = true; return entity; } void Scene::lookAt(Entity entity) { - FlyMovement2D& fly = m_ecs.getComponent(m_mainCamera); - Transform& target = m_ecs.getComponent(entity); + FlyMovement2D &fly = m_ecs.getComponent(m_mainCamera); + Transform &target = m_ecs.getComponent(entity); float oldZ = fly.targetPosition.z; fly.targetPosition = target.position; fly.targetPosition.z = oldZ; }; - void Scene::loadScene(std::string& sceneFileContent) + void Scene::loadScene(std::string &sceneFileContent) { // json scene = json::parse(sceneFileContent); @@ -279,11 +352,11 @@ namespace WeirdEngine // Create camera object m_mainCamera = m_ecs.createEntity(); - Transform& t = m_ecs.addComponent(m_mainCamera); + Transform &t = m_ecs.addComponent(m_mainCamera); t.position = g_cameraPosition; t.rotation = vec3(0, 0, -1.0f); - ECS::Camera& c = m_ecs.addComponent(m_mainCamera); + ECS::Camera &c = m_ecs.addComponent(m_mainCamera); // Add a light WeirdRenderer::Light light; @@ -418,7 +491,7 @@ namespace WeirdEngine constexpr int INVALID_INDEX = -1; - void Scene::print(const std::string& text) + void Scene::print(const std::string &text) { float offset = 0; for (auto i : text) @@ -433,10 +506,10 @@ namespace WeirdEngine float y = vec2.y; Entity entity = m_ecs.createEntity(); - Transform& t = m_ecs.addComponent(entity); + Transform &t = m_ecs.addComponent(entity); t.position = vec3(x, y, -10.0f); - SDFRenderer& sdfRenderer = m_ecs.addComponent(entity); + SDFRenderer &sdfRenderer = m_ecs.addComponent(entity); sdfRenderer.materialId = 4 + idx % 12; } @@ -444,10 +517,10 @@ namespace WeirdEngine } } - void Scene::loadFont(const char* imagePath, int charWidth, int charHeight, const char* characters) + void Scene::loadFont(const char *imagePath, int charWidth, int charHeight, const char *characters) { // Set all to INVALID_INDEX initially - for (int& val : m_CharLookUpTable) + for (int &val : m_CharLookUpTable) { val = INVALID_INDEX; } @@ -464,7 +537,7 @@ namespace WeirdEngine // Load the image int width, height, channels; - unsigned char* img = wstbi_load(imagePath, &width, &height, &channels, 0); + unsigned char *img = wstbi_load(imagePath, &width, &height, &channels, 0); if (img == nullptr) { diff --git a/src/weird-physics/Simulation2D.cpp b/src/weird-physics/Simulation2D.cpp index 179d399..5c1178c 100644 --- a/src/weird-physics/Simulation2D.cpp +++ b/src/weird-physics/Simulation2D.cpp @@ -333,12 +333,24 @@ namespace WeirdEngine } } + static float fOpUnionSoft(float a, float b, float r) + { + float e = std::max(r - std::abs(a - b), 0.0f); + return std::min(a, b) - e * e * 0.25 / r; + } + float Simulation2D::map(vec2 p) { float d = 1.0f; + float currentGroupMinDistance = 1.0f; - for (DistanceFieldObject2D& obj : m_objects) + auto currentGroup = 0; + + for (int i = 0; i < m_objects.size(); i++) { + + + DistanceFieldObject2D& obj = m_objects[i]; if (obj.distanceFieldId >= m_sdfs->size()) { continue; @@ -348,13 +360,53 @@ namespace WeirdEngine obj.parameters[9] = p.x; obj.parameters[10] = p.y; + if (obj.groupId != currentGroup) + { + currentGroup = obj.groupId; + d = std::min(d, currentGroupMinDistance); + currentGroupMinDistance = 100000.0f; + } + + // Distance (*m_sdfs)[obj.distanceFieldId]->propagateValues(obj.parameters); float dist = (*m_sdfs)[obj.distanceFieldId]->getValue(); - d = std::min(d, dist); + bool globalEffect = obj.groupId == CustomShape::GLOBAL_GROUP; + + float currentMinDistance = globalEffect ? d : currentGroupMinDistance; + + // Combination + switch (obj.combinationId) { + case CombinationType::Addition: { + currentMinDistance = std::min(currentMinDistance, dist); + break; + } + case CombinationType::Subtraction: { + currentMinDistance = std::max(currentMinDistance, -dist); + break; + } + case CombinationType::Intersection: { + currentMinDistance = std::max(currentMinDistance, dist); + break; + } + case CombinationType::SmoothAddition: { + currentMinDistance = fOpUnionSoft(currentMinDistance, dist, 1.0f); + break; + } + default: + break; + } + + if (globalEffect) { + d = currentMinDistance; + } else { + currentGroupMinDistance = currentMinDistance; + } } + d = std::min(d, currentGroupMinDistance); + return d; } @@ -452,7 +504,7 @@ namespace WeirdEngine m_forces[col.B] += m_mass[col.B] * penalty; // Notify collision callback - if (m_collisionCallback) + if (m_collisionCallback) { CollisionEvent event{ col.A, col.B }; m_collisionCallback(event, m_callbackUserData); @@ -806,10 +858,10 @@ namespace WeirdEngine void Simulation2D::updateShape(CustomShape& shape) { - if (shape.m_screenSpace) + if (shape.m_screenSpace || !shape.m_hasCollision) return; - DistanceFieldObject2D sdf(shape.Owner, shape.m_distanceFieldId, shape.m_parameters); + DistanceFieldObject2D sdf(shape.Owner, shape.m_distanceFieldId, shape.m_combination, shape.m_groupId, shape.m_parameters); // Check if the key exists auto it = m_entityToObjectsIdx.find(shape.Owner); diff --git a/src/weird-renderer/shaders/raymarching2d.frag b/src/weird-renderer/shaders/raymarching2d.frag index 273ab75..9a4eb52 100644 --- a/src/weird-renderer/shaders/raymarching2d.frag +++ b/src/weird-renderer/shaders/raymarching2d.frag @@ -140,75 +140,66 @@ vec3 getMaterial(vec2 p, int materialId) vec4 getColor(vec2 p, vec2 uv) { - float d = 100000.0; + float minDist = 100000.0; - vec3 col = vec3(0.0); - float minZ = 1000.0f; + vec3 col = vec3(0.0); + float minZ = 1000.0f; - float zoom = -u_camMatrix[3].z; - - float aspectRatio = u_resolution.x / u_resolution.y; - vec2 zoomVec = vec2((zoom * aspectRatio) - 1.0, zoom); + float zoom = -u_camMatrix[3].z; - bool bestIsScreenSpace = false; + float aspectRatio = u_resolution.x / u_resolution.y; + vec2 zoomVec = vec2((zoom * aspectRatio) - 1.0, zoom); - for (int i = 0; i < u_loadedObjects - (2 * u_customShapeCount); i++) - { - vec4 positionSizeMaterial = texelFetch(t_shapeBuffer, i); - int materialId = int(positionSizeMaterial.w); - // vec4 extraParameters = texelFetch(t_shapeBuffer, (2 * i) + 1); + bool bestIsScreenSpace = false; - float z = positionSizeMaterial.z; - bool screenSpace = z < 0.0f; + /*ADD_SHAPES_HERE*/ - + if(minDist < EPSILON) + { + return vec4(col, minDist); + } - float objectDist = shape_circle((screenSpace ? u_uiScale * uv : p) - positionSizeMaterial.xy); + for (int i = 0; i < u_loadedObjects - (2 * u_customShapeCount); i++) + { + vec4 positionSizeMaterial = texelFetch(t_shapeBuffer, i); + int materialId = int(positionSizeMaterial.w); + // vec4 extraParameters = texelFetch(t_shapeBuffer, (2 * i) + 1); - if(z < minZ) - { + float z = positionSizeMaterial.z; -#if BLEND_SHAPES + float objectDist = shape_circle(p - positionSizeMaterial.xy); - d = fOpUnionSoft(objectDist, d, u_k); - float delta = 1 - (max(u_k - abs(objectDist - d), 0.0) / u_k); // After new d is calculated - col = mix(getMaterial(p, materialId), col, delta); + #if BLEND_SHAPES -#else + minDist = fOpUnionSoft(objectDist, minDist, u_k); + float delta = 1 - (max(u_k - abs(objectDist - minDist), 0.0) / u_k); // After new d is calculated + col = mix(getMaterial(p, materialId), col, delta); - d = min(d, objectDist); - - if(objectDist < 0) - { - col = getMaterial(positionSizeMaterial.xy, materialId); - minZ = z; - bestIsScreenSpace = screenSpace; - } - -#endif + #else - } - } + if(objectDist < minDist) + { + minDist = objectDist; + col = getMaterial(positionSizeMaterial.xy, materialId); + minZ = z; - if(bestIsScreenSpace) - return vec4(col, d); + if(minDist < EPSILON) + { + break; + } + } - /*ADD_SHAPES_HERE*/ + #endif - // Repetition - // float scale = 1.0 / 10.0; - // vec2 pp = p + 5.0; - // vec2 roundPos = ((scale * pp) - round(scale * pp)) * 10.0; - // roundPos.x += cos(u_time + round(0.1 * pp.x)); - // roundPos.y += sin(u_time + round(0.1 * pp.x)); + } - // Set bacu_kground color - // vec3 bacu_kground = mix(u_staticColors[2], u_staticColors[3], mod(floor(.1 * p.x) + floor(.1 * p.y), 2.0)); - float pixel = 0.2 / u_resolution.y; - vec3 bacu_kground = mix(u_staticColors[3], u_staticColors[2], min(fract(0.1 * p.x), fract(0.1 * p.y)) > pixel * zoom ? 1.0 : 0.0); - col = d > 0.0 ? bacu_kground : col; + // Set bacu_kground color + // vec3 bacu_kground = mix(u_staticColors[2], u_staticColors[3], mod(floor(.1 * p.x) + floor(.1 * p.y), 2.0)); + float pixel = 0.2 / u_resolution.y; + vec3 background = mix(u_staticColors[3], u_staticColors[2], min(fract(0.1 * p.x), fract(0.1 * p.y)) > pixel * zoom ? 1.0 : 0.0); + col = minDist > 0.0 ? background : col; - return vec4(col, d); + return vec4(col, minDist); } void main()