squircle top and bottom of pudding

This commit is contained in:
frank 2021-09-10 18:03:06 -04:00
parent 9271ba9226
commit be7b750e89
5 changed files with 96 additions and 26 deletions

View File

@ -46,7 +46,7 @@
"enabled": true, "enabled": true,
"json-save": true, "json-save": true,
"json-save-directory": "local/scans", "json-save-directory": "local/scans",
"barcode": "1703543090000", "barcode": "",
"capture-device": "/dev/video0" "capture-device": "/dev/video0"
}, },
"api": "api":
@ -65,6 +65,12 @@
}, },
"pudding": "pudding":
{ {
"rotation-speed": 0.005 "rotation-speed": 0.005,
"top-radius": 1.0,
"base-radius": 1.6,
"ring-vertex-count": 10,
"layer-count": 12,
"y-range": [-0.6, 0.6],
"gradient-position": 0.25
} }
} }

View File

@ -33,7 +33,9 @@ Pudding::Pudding()
/* initialize a zbar image scanner for reading barcodes of any format */ /* initialize a zbar image scanner for reading barcodes of any format */
image_scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); image_scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
/* set up pudding model */ /* set up pudding model */
set_pudding_model(1.0f, 1.6f, 10, 12, -.6, .6, .25); nlohmann::json pudding = get_configuration()["pudding"];
set_pudding_model(pudding["top-radius"], pudding["base-radius"], pudding["ring-vertex-count"], pudding["layer-count"],
pudding["y-range"][0], pudding["y-range"][1], pudding["gradient-position"]);
/* use gl context so we can draw 3D */ /* use gl context so we can draw 3D */
load_gl_context(); load_gl_context();
} }
@ -222,6 +224,7 @@ void Pudding::load_gl_context()
glBindAttribLocation(flat_program, 0, "in_position"); glBindAttribLocation(flat_program, 0, "in_position");
glBindAttribLocation(flat_program, 1, "vertex_uv"); glBindAttribLocation(flat_program, 1, "vertex_uv");
link_shader(flat_program); link_shader(flat_program);
flat_texture_uniform_location = glGetUniformLocation(flat_program, "base_texture");
/* load, configure and link the 3D world program */ /* load, configure and link the 3D world program */
vertex_shader = load_shader("src/mvp.vert", GL_VERTEX_SHADER); vertex_shader = load_shader("src/mvp.vert", GL_VERTEX_SHADER);
fragment_shader = load_shader("src/mvp.frag", GL_FRAGMENT_SHADER); fragment_shader = load_shader("src/mvp.frag", GL_FRAGMENT_SHADER);
@ -235,6 +238,8 @@ void Pudding::load_gl_context()
mvp_uniform_location = glGetUniformLocation(mvp_program, "mvp"); mvp_uniform_location = glGetUniformLocation(mvp_program, "mvp");
time_uniform_location = glGetUniformLocation(mvp_program, "time"); time_uniform_location = glGetUniformLocation(mvp_program, "time");
effect_uniform_location = glGetUniformLocation(mvp_program, "effect"); effect_uniform_location = glGetUniformLocation(mvp_program, "effect");
uv_transformation_uniform_location = glGetUniformLocation(mvp_program, "uv_transformation");
coordinate_bound_uniform_location = glGetUniformLocation(mvp_program, "coordinate_bound");
log_gl_errors(); log_gl_errors();
} }
@ -310,7 +315,7 @@ void Pudding::respond(SDL_Event& event)
/* The effect command switches the active effect to the next in the list, wrapping around at the end */ /* The effect command switches the active effect to the next in the list, wrapping around at the end */
else if (get_delegate().compare(event, "effect")) else if (get_delegate().compare(event, "effect"))
{ {
effect_id = ++effect_id % Effect::COUNT; effect_id = ++effect_id % EFFECT_COUNT;
glUseProgram(mvp_program); glUseProgram(mvp_program);
glUniform1i(effect_uniform_location, effect_id); glUniform1i(effect_uniform_location, effect_id);
} }
@ -755,13 +760,12 @@ void Pudding::update()
glDisableVertexAttribArray(3); glDisableVertexAttribArray(3);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
GLint base_texture_location = glGetUniformLocation(flat_program, "base_texture"); glUniform1i(flat_texture_uniform_location, 0);
glUniform1i(base_texture_location, 0);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, background_texture_id); glBindTexture(GL_TEXTURE_2D, background_texture_id);
/* set blend to modify white part of background, color passed is in HSV format */ /* set blend to modify white part of background, color passed is in HSV format */
GLint blend_min_hsv_location = glGetUniformLocation(flat_program, "blend_min_hsv"); GLint blend_min_hsv_location = glGetUniformLocation(flat_program, "blend_min_hsv");
float hue = std::abs(std::abs(model[0][0]) - 0.5) * 2; /* blend min with black will create a black blackground regardless of texture */
glUniform3f(blend_min_hsv_location, 0, 0, 0); glUniform3f(blend_min_hsv_location, 0, 0, 0);
/* draws rectangle vertices and rectangle texture using UV coords */ /* draws rectangle vertices and rectangle texture using UV coords */
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
@ -796,9 +800,16 @@ void Pudding::update()
} }
/* draw pudding model */ /* draw pudding model */
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
/* draw the sides of the pudding */
glDrawArrays(GL_TRIANGLES, 0, pudding_triangle_vertex_count); glDrawArrays(GL_TRIANGLES, 0, pudding_triangle_vertex_count);
/* enable squircling and draw the top and bottom of pudding */
glUniform1i(uv_transformation_uniform_location, UV_SQUIRCLE);
glUniform1f(coordinate_bound_uniform_location, get_configuration()["pudding"]["top-radius"]);
glDrawArrays(GL_TRIANGLE_FAN, pudding_triangle_vertex_count, pudding_fan_vertex_count); glDrawArrays(GL_TRIANGLE_FAN, pudding_triangle_vertex_count, pudding_fan_vertex_count);
glUniform1f(coordinate_bound_uniform_location, get_configuration()["pudding"]["base-radius"]);
glDrawArrays(GL_TRIANGLE_FAN, pudding_triangle_vertex_count + pudding_fan_vertex_count, pudding_fan_vertex_count); glDrawArrays(GL_TRIANGLE_FAN, pudding_triangle_vertex_count + pudding_fan_vertex_count, pudding_fan_vertex_count);
/* disable squircling for all other drawing */
glUniform1i(uv_transformation_uniform_location, UV_NONE);
/* regular fill mode enabled for all other drawing */ /* regular fill mode enabled for all other drawing */
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
/* only do more drawing if items are downloaded or camera is enabled */ /* only do more drawing if items are downloaded or camera is enabled */
@ -813,8 +824,7 @@ void Pudding::update()
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
/* just need to set these once since we're drawing one texture per viewport */ /* just need to set these once since we're drawing one texture per viewport */
GLint base_texture_location = glGetUniformLocation(flat_program, "base_texture"); glUniform1i(flat_texture_uniform_location, 0);
glUniform1i(base_texture_location, 0);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
/* move viewport to the bottom of screen */ /* move viewport to the bottom of screen */
viewport_box.top(viewport_box.bottom(), true); viewport_box.top(viewport_box.bottom(), true);

View File

@ -33,10 +33,17 @@ private:
* is the default integer, it will define the number of effects available */ * is the default integer, it will define the number of effects available */
enum Effect enum Effect
{ {
NONE, EFFECT_NONE,
SNAKE, EFFECT_SNAKE,
WOBBLE, EFFECT_WOBBLE,
COUNT EFFECT_COUNT
};
/* Defines for UV transformations available in the fragment shader program */
enum UVTransformation
{
UV_NONE,
UV_SQUIRCLE
}; };
typedef Game super; typedef Game super;
@ -54,11 +61,12 @@ private:
const glm::vec3 PUDDING_YELLOW = glm::vec3(0.878f, 0.859f, 0.122f); const glm::vec3 PUDDING_YELLOW = glm::vec3(0.878f, 0.859f, 0.122f);
std::string current_barcode, previous_barcode, current_config_barcode, current_camera_barcode; std::string current_barcode, previous_barcode, current_config_barcode, current_camera_barcode;
std::vector<Item> items; std::vector<Item> items;
int current_item_index = 0, effect_id = Effect::NONE, pudding_triangle_vertex_count = 0, pudding_fan_vertex_count = 0; int current_item_index = 0, effect_id = EFFECT_NONE, pudding_triangle_vertex_count = 0, pudding_fan_vertex_count = 0;
cv::VideoCapture capture; cv::VideoCapture capture;
zbar::ImageScanner image_scanner; zbar::ImageScanner image_scanner;
GLuint flat_program, mvp_program, capture_texture_front_buffer_id, capture_texture_back_buffer_id, capture_texture_id, GLuint flat_program, mvp_program, capture_texture_front_buffer_id, capture_texture_back_buffer_id, capture_texture_id,
mvp_uniform_location, background_texture_id, time_uniform_location, effect_uniform_location; mvp_uniform_location, background_texture_id, time_uniform_location, effect_uniform_location, uv_transformation_uniform_location,
flat_texture_uniform_location, coordinate_bound_uniform_location;
glm::mat4 projection, model = glm::mat4(1.0f), mvp; glm::mat4 projection, model = glm::mat4(1.0f), mvp;
std::vector<glm::vec3> pudding_vertices, pudding_colors; std::vector<glm::vec3> pudding_vertices, pudding_colors;
std::vector<glm::vec2> pudding_uv; std::vector<glm::vec2> pudding_uv;

View File

@ -1,11 +1,46 @@
#version 130 #version 130
in vec3 ex_color; #define TRANSFORMATION_NONE 0
in float x; #define TRANSFORMATION_SQUIRCLE 1
in vec2 uv;
uniform sampler2D pudding_texture;
void color() in vec2 fragment_uv;
in vec3 ex_color;
in float x_center_proximity;
in vec3 original_coordinates;
in vec3 clip_coordinates;
uniform sampler2D pudding_texture;
uniform int uv_transformation = TRANSFORMATION_NONE;
uniform float coordinate_bound;
/* [-coordinate_bound, coordinate_bound] arbitrary box coordinates to [-1, 1] normalized coordinates */
vec2 normalize_coordinates(vec2 coordinates)
{
return coordinates / coordinate_bound;
}
/* [-1, 1] box coordinates to [0, 1] UV coordinates */
vec2 coordinates_to_uv(vec2 coordinates)
{
return (coordinates + 1) / 2;
}
/* coordinates in circle with radius <= 1 to box coordinates in [-1, 1] */
vec2 circle_to_box(vec2 circle)
{
float u = circle.x;
float v = circle.y;
float u_sq = pow(u, 2);
float v_sq = pow(v, 2);
float rt_2 = sqrt(2);
float x = .5 * sqrt(2 + 2 * u * rt_2 + u_sq - v_sq) - .5 * sqrt(2 - 2 * u * rt_2 + u_sq - v_sq);
float y = .5 * sqrt(2 + 2 * v * rt_2 - u_sq + v_sq) - .5 * sqrt(2 - 2 * v * rt_2 - u_sq + v_sq);
return vec2(x, y);
}
/* Apply color passed in from the vertex shader, compressing to one of 16 colors. Add retro effect
* by alternately darkening and lightening 2x2 pixel areas in a checker pattern. Add shadowing by
* brightening the color based on how near it is to the center in the X-dimension */
void retro()
{ {
vec3 shadowed = min(ex_color, 1.0); vec3 shadowed = min(ex_color, 1.0);
float dx = abs(floor(gl_FragCoord[0]) - 480) / 480.0; float dx = abs(floor(gl_FragCoord[0]) - 480) / 480.0;
@ -20,10 +55,16 @@ void color()
gl_FragColor[0] = int(gl_FragColor[0] * 4) / 4.0; gl_FragColor[0] = int(gl_FragColor[0] * 4) / 4.0;
gl_FragColor[1] = int(gl_FragColor[1] * 4) / 4.0; gl_FragColor[1] = int(gl_FragColor[1] * 4) / 4.0;
gl_FragColor[2] = int(gl_FragColor[2] * 4) / 4.0; gl_FragColor[2] = int(gl_FragColor[2] * 4) / 4.0;
gl_FragColor *= x; gl_FragColor *= x_center_proximity;
} }
void main() void main()
{ {
vec2 uv = fragment_uv;
if (uv_transformation == TRANSFORMATION_SQUIRCLE)
{
vec2 normalized_circle_coordinates = normalize_coordinates(vec2(original_coordinates.x, original_coordinates.z));
uv = coordinates_to_uv(circle_to_box(normalized_circle_coordinates));
}
gl_FragColor = texture(pudding_texture, uv); gl_FragColor = texture(pudding_texture, uv);
} }

View File

@ -15,8 +15,10 @@ uniform mat4 mvp;
uniform float time; uniform float time;
uniform int effect = EFFECT_NONE; uniform int effect = EFFECT_NONE;
out vec3 ex_color; out vec3 ex_color;
out float x; out float x_center_proximity;
out vec2 uv; out vec2 fragment_uv;
out vec3 original_coordinates;
out vec3 clip_coordinates;
/* Offset X-coordinate according to the time step and Y-coordinate to create a wobble effect when run on /* Offset X-coordinate according to the time step and Y-coordinate to create a wobble effect when run on
* flattened coordinates (after projection matrix has been applied) */ * flattened coordinates (after projection matrix has been applied) */
@ -47,11 +49,14 @@ void main()
gl_Position = vec4(in_position, 1); gl_Position = vec4(in_position, 1);
} }
gl_Position = mvp * gl_Position; gl_Position = mvp * gl_Position;
ex_color = in_color;
x = 1.8 - abs(in_position[0]);
if (effect == EFFECT_WOBBLE) if (effect == EFFECT_WOBBLE)
{ {
wobble(); wobble();
} }
uv = vertex_uv; /* passing to fragment program */
ex_color = in_color;
x_center_proximity = 1.8 - abs(in_position[0]);
fragment_uv = vertex_uv;
original_coordinates = in_position;
clip_coordinates = gl_Position.xyz;
} }