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,
"json-save": true,
"json-save-directory": "local/scans",
"barcode": "1703543090000",
"barcode": "",
"capture-device": "/dev/video0"
},
"api":
@ -65,6 +65,12 @@
},
"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 */
image_scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
/* 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 */
load_gl_context();
}
@ -222,6 +224,7 @@ void Pudding::load_gl_context()
glBindAttribLocation(flat_program, 0, "in_position");
glBindAttribLocation(flat_program, 1, "vertex_uv");
link_shader(flat_program);
flat_texture_uniform_location = glGetUniformLocation(flat_program, "base_texture");
/* load, configure and link the 3D world program */
vertex_shader = load_shader("src/mvp.vert", GL_VERTEX_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");
time_uniform_location = glGetUniformLocation(mvp_program, "time");
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();
}
@ -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 */
else if (get_delegate().compare(event, "effect"))
{
effect_id = ++effect_id % Effect::COUNT;
effect_id = ++effect_id % EFFECT_COUNT;
glUseProgram(mvp_program);
glUniform1i(effect_uniform_location, effect_id);
}
@ -755,13 +760,12 @@ void Pudding::update()
glDisableVertexAttribArray(3);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
GLint base_texture_location = glGetUniformLocation(flat_program, "base_texture");
glUniform1i(base_texture_location, 0);
glUniform1i(flat_texture_uniform_location, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, background_texture_id);
/* 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");
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);
/* draws rectangle vertices and rectangle texture using UV coords */
glDrawArrays(GL_TRIANGLES, 0, 6);
@ -796,9 +800,16 @@ void Pudding::update()
}
/* draw pudding model */
glEnable(GL_DEPTH_TEST);
/* draw the sides of the pudding */
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);
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);
/* disable squircling for all other drawing */
glUniform1i(uv_transformation_uniform_location, UV_NONE);
/* regular fill mode enabled for all other drawing */
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
/* only do more drawing if items are downloaded or camera is enabled */
@ -813,8 +824,7 @@ void Pudding::update()
glEnableVertexAttribArray(1);
glDisable(GL_DEPTH_TEST);
/* just need to set these once since we're drawing one texture per viewport */
GLint base_texture_location = glGetUniformLocation(flat_program, "base_texture");
glUniform1i(base_texture_location, 0);
glUniform1i(flat_texture_uniform_location, 0);
glActiveTexture(GL_TEXTURE0);
/* move viewport to the bottom of screen */
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 */
enum Effect
{
NONE,
SNAKE,
WOBBLE,
COUNT
EFFECT_NONE,
EFFECT_SNAKE,
EFFECT_WOBBLE,
EFFECT_COUNT
};
/* Defines for UV transformations available in the fragment shader program */
enum UVTransformation
{
UV_NONE,
UV_SQUIRCLE
};
typedef Game super;
@ -54,11 +61,12 @@ private:
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::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;
zbar::ImageScanner image_scanner;
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;
std::vector<glm::vec3> pudding_vertices, pudding_colors;
std::vector<glm::vec2> pudding_uv;

View File

@ -1,11 +1,46 @@
#version 130
in vec3 ex_color;
in float x;
in vec2 uv;
uniform sampler2D pudding_texture;
#define TRANSFORMATION_NONE 0
#define TRANSFORMATION_SQUIRCLE 1
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);
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[1] = int(gl_FragColor[1] * 4) / 4.0;
gl_FragColor[2] = int(gl_FragColor[2] * 4) / 4.0;
gl_FragColor *= x;
gl_FragColor *= x_center_proximity;
}
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);
}

View File

@ -15,8 +15,10 @@ uniform mat4 mvp;
uniform float time;
uniform int effect = EFFECT_NONE;
out vec3 ex_color;
out float x;
out vec2 uv;
out float x_center_proximity;
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
* flattened coordinates (after projection matrix has been applied) */
@ -47,11 +49,14 @@ void main()
gl_Position = vec4(in_position, 1);
}
gl_Position = mvp * gl_Position;
ex_color = in_color;
x = 1.8 - abs(in_position[0]);
if (effect == EFFECT_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;
}