This commit is contained in:
Daniel Ledda
2025-02-17 20:06:23 +01:00
parent 95b781a4b9
commit 6958228da7
4 changed files with 167 additions and 35 deletions

View File

@@ -1,8 +1,55 @@
#version 330 core
out vec4 frag_color;
out vec4 pixel_color;
in vec4 fragment_color;
in vec4 frag_color;
in vec2 frag_dest_position;
in vec2 frag_dest_center;
in vec2 frag_dest_half_size;
in float frag_softness;
in float frag_border_radius;
in float frag_border_thickness;
float roundedRectSDF(vec2 sample_pos, vec2 rect_center, vec2 rect_half_size, float r) {
vec2 d2 = (abs(rect_center - sample_pos) - rect_half_size + vec2(r, r));
return min(max(d2.x, d2.y), 0.0) + length(max(d2, 0.0)) - r;
}
void main() {
frag_color = fragment_color;
vec2 softness_padding = vec2(
max(0, frag_softness*2-1),
max(0, frag_softness*2-1));
float border_factor = 1.0f;
if (frag_border_thickness != 0) {
vec2 interior_half_size = frag_dest_half_size - vec2(frag_border_thickness);
float interior_radius_reduce_f = min(
interior_half_size.x / frag_dest_half_size.x,
interior_half_size.y / frag_dest_half_size.y);
float interior_corner_radius = frag_border_radius * interior_radius_reduce_f * interior_radius_reduce_f;
float inside_d = roundedRectSDF(
frag_dest_position,
frag_dest_center,
interior_half_size - softness_padding,
interior_corner_radius);
float inside_f = smoothstep(0, 2*frag_softness, inside_d);
border_factor = inside_f;
}
float dist = roundedRectSDF(
frag_dest_position,
frag_dest_center,
frag_dest_half_size - softness_padding,
frag_border_radius);
// For texturing later
float sample = 1;
float sdf_factor = 1.0f - smoothstep(0, 2*frag_softness, dist);
pixel_color = frag_color * sample * sdf_factor * border_factor;
};

View File

@@ -2,10 +2,19 @@
layout (location = 0) in vec2 p0;
layout (location = 1) in vec2 p1;
layout (location = 2) in vec4 color;
layout (location = 3) in float border_radius;
layout (location = 4) in float border_thickness;
layout (location = 6) in float edge_softness;
uniform mat4 projection;
out vec4 fragment_color;
out vec4 frag_color;
out vec2 frag_dest_position;
out vec2 frag_dest_center;
out vec2 frag_dest_half_size;
out float frag_softness;
out float frag_border_radius;
out float frag_border_thickness;
const vec2 rectangle_vertices[4] = vec2[](
vec2(-1, -1),
@@ -25,5 +34,11 @@ void main() {
1
);
fragment_color = color;
frag_color = color;
frag_dest_position = dest_position;
frag_dest_center = dest_center;
frag_dest_half_size = dest_half_size;
frag_border_radius = border_radius;
frag_border_thickness = border_thickness;
frag_softness = edge_softness;
}

View File

@@ -94,13 +94,25 @@ struct Polycube {
struct RenderObjects_Rectangle {
uint32 vao;
uint64 count;
list<Vector2<real32>> p0;
uint32 p0BufferId;
list<Vector2<real32>> p1;
uint32 p1BufferId;
list<Vector4<real32>> color;
uint32 colorBufferId;
uint64 count;
list<real32> borderRadius;
uint32 borderRadiusBufferId;
list<real32> borderThickness;
uint32 borderThicknessBufferId;
list<real32> edgeSoftness;
uint32 edgeSoftnessBufferId;
};
struct Input {
@@ -225,6 +237,7 @@ GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
}
glViewport(0, 0, 800, 600);
glfwSwapInterval(0);
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
glfwSetInputMode(window, GLFW_CURSOR | GLFW_RAW_MOUSE_MOTION, GLFW_CURSOR_NORMAL);
glEnable(GL_DEPTH_TEST);
@@ -340,24 +353,24 @@ void processInput(Soma *soma) {
}
}
Polycube createPolycubeFromRepr(Soma *soma, Space *repr, Vector4<real32> color) {
uint32 polycubeMainEntityHandle = createEntity(soma->scene);
Entity *polycubeMainEntity = getEntity(soma->scene, polycubeMainEntityHandle);
Polycube createPolycubeFromRepr(Scene *s, Space *repr, Vector4<real32> color) {
uint32 polycubeMainEntityHandle = createEntity(s);
Entity *polycubeMainEntity = getEntity(s, polycubeMainEntityHandle);
for (int x = 0; x < repr->dim_x; x++) {
for (int y = 0; y < repr->dim_y; y++) {
for (int z = 0; z < repr->dim_z; z++) {
if (filledAt(repr, x, y, z)) {
uint32 segmentEntityHandle = createEntity(soma->scene);
Entity *polycubeSegment = getEntity(soma->scene, segmentEntityHandle);
uint32 segmentEntityHandle = createEntity(s);
Entity *polycubeSegment = getEntity(s, segmentEntityHandle);
polycubeSegment->mesh = &cubeMesh;
polycubeSegment->tex = &wallTex;
SceneGraphNode *graphNode = getSceneGraphNode(soma->scene, polycubeSegment->graphNodeHandle);
SceneGraphNode *graphNode = getSceneGraphNode(s, polycubeSegment->graphNodeHandle);
graphNode->translation = glm::vec3(
-((repr->dim_z - 1)/2.0f) + z,
((repr->dim_x - 1)/2.0f) - x,
-((repr->dim_y - 1)/2.0f) + y
);
sceneNodeAddEntity(soma->scene, polycubeMainEntity->graphNodeHandle, segmentEntityHandle);
sceneNodeAddEntity(s, polycubeMainEntity->graphNodeHandle, segmentEntityHandle);
}
}
}
@@ -366,6 +379,9 @@ Polycube createPolycubeFromRepr(Soma *soma, Space *repr, Vector4<real32> color)
result.entityHandle = polycubeMainEntityHandle;
result.color = color;
result.repr = *repr;
SceneGraphNode *graphNode = getSceneGraphNodeForEntity(s, polycubeMainEntityHandle);
graphNode->rotation *= glm::angleAxis(PI / 4, glm::vec3(1, 0, 0));
graphNode->rotation *= glm::angleAxis(PI / 4, glm::vec3(0, 1, 0));
return result;
}
@@ -376,16 +392,18 @@ RenderObjects_Rectangle createRectangleObjects(Arena *arena, size_t count) {
result.p0 = PushFullList(arena, Vector2<real32>, count);
result.p1 = PushFullList(arena, Vector2<real32>, count);
result.color = PushFullList(arena, Vector4<real32>, count);
result.borderRadius = PushFullList(arena, real32, count);
result.borderThickness = PushFullList(arena, real32, count);
result.edgeSoftness = PushFullList(arena, real32, count);
glGenVertexArrays(1, &result.vao);
uint32 p0Buffer;
uint32 p1Buffer;
uint32 colorBuffer;
glGenBuffers(1, &result.p0BufferId);
glGenBuffers(1, &result.p1BufferId);
glGenBuffers(1, &result.colorBufferId);
glGenBuffers(1, &result.borderRadiusBufferId);
glGenBuffers(1, &result.borderThicknessBufferId);
glGenBuffers(1, &result.edgeSoftnessBufferId);
glBindVertexArray(result.vao);
@@ -407,6 +425,24 @@ RenderObjects_Rectangle createRectangleObjects(Arena *arena, size_t count) {
glVertexAttribDivisor(2, 1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, result.borderRadiusBufferId);
glBufferData(GL_ARRAY_BUFFER, result.borderRadius.length * sizeof(real32), 0, GL_DYNAMIC_DRAW);
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(real32), (void*)0);
glVertexAttribDivisor(3, 1);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ARRAY_BUFFER, result.borderThicknessBufferId);
glBufferData(GL_ARRAY_BUFFER, result.borderThickness.length * sizeof(real32), 0, GL_DYNAMIC_DRAW);
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(real32), (void*)0);
glVertexAttribDivisor(4, 1);
glEnableVertexAttribArray(4);
glBindBuffer(GL_ARRAY_BUFFER, result.edgeSoftnessBufferId);
glBufferData(GL_ARRAY_BUFFER, result.edgeSoftness.length * sizeof(real32), 0, GL_DYNAMIC_DRAW);
glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(real32), (void*)0);
glVertexAttribDivisor(5, 1);
glEnableVertexAttribArray(5);
return result;
}
@@ -421,6 +457,15 @@ void reinitRectangleObjectBuffers(Renderer *r) {
glBindBuffer(GL_ARRAY_BUFFER, r->rects.colorBufferId);
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.color.head * sizeof(Vector4<real32>), r->rects.color.data);
glBindBuffer(GL_ARRAY_BUFFER, r->rects.borderRadiusBufferId);
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.borderRadius.head * sizeof(real32), r->rects.borderRadius.data);
glBindBuffer(GL_ARRAY_BUFFER, r->rects.borderThicknessBufferId);
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.borderThickness.head * sizeof(real32), r->rects.borderThickness.data);
glBindBuffer(GL_ARRAY_BUFFER, r->rects.edgeSoftnessBufferId);
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.edgeSoftness.head * sizeof(real32), r->rects.edgeSoftness.data);
}
Renderer createRenderer(Arena *arena, Scene *scene) {
@@ -436,6 +481,9 @@ void renderBegin(Renderer *r) {
r->rects.p0.head = 0;
r->rects.p1.head = 0;
r->rects.color.head = 0;
r->rects.borderRadius.head = 0;
r->rects.borderThickness.head = 0;
r->rects.edgeSoftness.head = 0;
}
void renderEnd(Soma *soma, Renderer *renderer) {
@@ -478,10 +526,13 @@ void renderEnd(Soma *soma, Renderer *renderer) {
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, renderer->rects.p0.head);
}
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, Vector4<real32> color) {
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, Vector4<real32> color, real32 borderRadius, real32 borderThickness) {
appendList(&r->rects.p0, vec2<real32>(x, y));
appendList(&r->rects.p1, vec2<real32>(x + width, y + height));
appendList(&r->rects.color, color);
appendList(&r->rects.borderRadius, borderRadius);
appendList(&r->rects.borderThickness, borderThickness);
appendList(&r->rects.edgeSoftness, 0.0f);
}
inline bool pointInRect(Vector2<real32> point, UI_Rect rect) {
@@ -497,7 +548,25 @@ bool ui_checkboxRect(UI_Context *ui, bool *value, UI_Rect rect) {
clicked = true;
}
}
rendererPlaceRectangle(ui->renderer, rect.x, rect.y, rect.width, rect.height, *value ? rect.color : vec4<real32>(1, 1, 1, 1));
if (*value) {
rendererPlaceRectangle(ui->renderer,
rect.x, rect.y,
rect.width, rect.height,
rect.color,
5, 0);
} else {
rendererPlaceRectangle(ui->renderer,
rect.x, rect.y,
rect.width, rect.height,
rect.color,
5, 2);
rendererPlaceRectangle(ui->renderer,
rect.x, rect.y,
rect.width, rect.height,
COLOR_WHITE,
5, 0);
}
return clicked;
}
@@ -593,7 +662,7 @@ int mainGfx() {
Vector4<real32> color = colorFromIndex(i);
appendList(&soma.state.polycubeInput, PolycubeInput{ voxelSpace, color });
cullEmptySpace(&voxelSpace);
Polycube polycube = createPolycubeFromRepr(&soma, &voxelSpace, color);
Polycube polycube = createPolycubeFromRepr(soma.scene, &voxelSpace, color);
polycube.color = color;
appendList(&soma.state.polycubes, polycube);
sceneNodeAddEntity(renderer.scene, renderer.scene->sceneRoot, polycube.entityHandle);
@@ -607,20 +676,11 @@ int mainGfx() {
glm::vec3 eyes = glm::normalize(soma.state.camera->pos - reference_polycube_gn->translation);
soma.state.rotAxisX = glm::normalize(glm::cross(eyes, soma.state.rotAxisY));
for (int i = 0; i < ArrayCount(STD_SOMA); i++) {
auto gn = getSceneGraphNodeForEntity(soma.scene, soma.state.polycubes.data[i].entityHandle);
gn->rotation *= glm::angleAxis(PI / 4, glm::vec3(1, 0, 0));
gn->rotation *= glm::angleAxis(PI / 4, glm::vec3(0, 1, 0));
}
real64 lastFrame = glfwGetTime();
real64 timeDelta = 1.0f/60.0f;
while (!glfwWindowShouldClose(soma.window.handle)) {
real64 currTime = glfwGetTime();
timeDelta = currTime - lastFrame;
lastFrame = currTime;
//print("%.7f\n", timeDelta);
real64 frameStart = glfwGetTime();
glfwPollEvents();
soma.currInput = getCurrentInput(soma.window.handle);
@@ -632,14 +692,18 @@ int mainGfx() {
soma.state.lastPolycubeVisible = soma.state.currentPolycube;
}
if (soma.state.polycubeDirty) {
Polycube *currentPolycube = &soma.state.polycubes.data[soma.state.currentPolycube];
PolycubeInput *pinput = &soma.state.polycubeInput.data[soma.state.currentPolycube];
removeEntity(soma.scene, soma.state.polycubes.data[soma.state.currentPolycube].entityHandle);
removeEntity(soma.scene, currentPolycube->entityHandle);
Space culledRepr = pinput->repr;
cullEmptySpace(&culledRepr);
Polycube polycube = createPolycubeFromRepr(&soma, &culledRepr, pinput->color);
soma.state.polycubes.data[soma.state.currentPolycube] = polycube;
sceneNodeAddEntity(soma.scene, soma.scene->sceneRoot, polycube.entityHandle);
Polycube newPolycube = createPolycubeFromRepr(soma.scene, &culledRepr, pinput->color);
SceneGraphNode *graphNode = getSceneGraphNodeForEntity(soma.scene, newPolycube.entityHandle);
graphNode->rotation = getSceneGraphNodeForEntity(soma.scene, currentPolycube->entityHandle)->rotation;
soma.state.polycubes.data[soma.state.currentPolycube] = newPolycube;
sceneNodeAddEntity(soma.scene, soma.scene->sceneRoot, newPolycube.entityHandle);
soma.state.polycubeDirty = false;
showEntity(soma.scene, newPolycube.entityHandle);
}
updateViewportFromFrame(soma.window.width, soma.window.height, &mainFrame);
@@ -660,7 +724,13 @@ int mainGfx() {
renderEnd(&soma, &renderer);
real64 frameEnd = glfwGetTime();
real64 frameTime = frameEnd - frameStart;
lastFrame = frameStart;
// print("FPS: %.7f\n", 1 / frameTime);
glfwSwapBuffers(soma.window.handle);
soma.prevInput = soma.currInput;
}

View File

@@ -77,7 +77,7 @@ void removeEntity(Scene *s, uint32 entityHandle) {
if (graphNode->parentHandle) {
SceneGraphNode *parentNode = getSceneGraphNode(s, graphNode->parentHandle);
for (int i = 0; i < parentNode->children.size(); i++) {
if (parentNode->children.at(i) == entityHandle) {
if (parentNode->children.at(i) == entity->graphNodeHandle) {
parentNode->children.erase(parentNode->children.begin() + i);
graphNode->parentHandle = 0;
break;