tiling effect using original texture size

This commit is contained in:
frank 2021-09-14 20:14:15 -04:00
parent be7b750e89
commit b22302a021
10 changed files with 66 additions and 30 deletions

View File

@ -17,7 +17,8 @@
"print-frame-length-history": ["CTRL", "SHIFT", "h"],
"toggle-camera": ["CTRL", "c"],
"toggle-item": ["CTRL", "i"],
"effect": ["CTRL", "e"]
"effect": ["CTRL", "e"],
"tile": ["CTRL", "t"]
},
"recording":
{
@ -72,5 +73,9 @@
"layer-count": 12,
"y-range": [-0.6, 0.6],
"gradient-position": 0.25
},
"resource":
{
"tile-path": "resource/tile"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

BIN
resource/tile/teapot.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
resource/tile/utensil1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
resource/tile/vase.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -19,6 +19,7 @@
#include <functional>
#include <SDL.h>
#include <extension.hpp>
#include "json/json.hpp"
#include "Node.hpp"
class Item : public Node
@ -26,6 +27,7 @@ class Item : public Node
private:
nlohmann::json json = {};
std::vector<std::shared_ptr<GLuint>> image_textures;
std::string brand_name = "", product_name = "", upc = "";
int current_image_index = 0;

View File

@ -38,6 +38,7 @@ Pudding::Pudding()
pudding["y-range"][0], pudding["y-range"][1], pudding["gradient-position"]);
/* use gl context so we can draw 3D */
load_gl_context();
load_tiles();
}
/* Assign vertices, colors and texture UV coordinates to the pudding model */
@ -160,18 +161,6 @@ void Pudding::load_gl_context()
{
log("could not create capture frame thread context");
}
/* load background as surface, generate texture to load pixel data into, allocate storage, bind and edit texture properties */
std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> surface(IMG_Load("local/tptile.jpg"), SDL_FreeSurface);
std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> flipped_surface(rotozoomSurfaceXY(surface.get(), 0, 1, -1, 0), SDL_FreeSurface);
glGenTextures(1, &background_texture_id);
glBindTexture(GL_TEXTURE_2D, background_texture_id);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, flipped_surface->w, flipped_surface->h);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, flipped_surface->w, flipped_surface->h, GL_RGBA, GL_UNSIGNED_BYTE, flipped_surface->pixels);
std::ostringstream message;
message << "loaded background image " << flipped_surface->w << "x" << flipped_surface->h;
log(message.str());
/* Allocate a vertex array object, bind it as current, doesn't need to be a member var because the same one is always bound */
GLuint vao;
glGenVertexArrays(1, &vao);
@ -225,6 +214,8 @@ void Pudding::load_gl_context()
glBindAttribLocation(flat_program, 1, "vertex_uv");
link_shader(flat_program);
flat_texture_uniform_location = glGetUniformLocation(flat_program, "base_texture");
flat_time_uniform_location = glGetUniformLocation(flat_program, "time");
scroll_uniform_location = glGetUniformLocation(flat_program, "scroll");
/* 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);
@ -243,6 +234,30 @@ void Pudding::load_gl_context()
log_gl_errors();
}
/* Read every resource/tile/.*.jpg into a GL texture, storing the texture pointer and file name in a std::map */
void Pudding::load_tiles()
{
for (fs::path path : sb::glob(get_configuration()["resource"]["tile-path"].get<fs::path>() / ".*.jpg"))
{
/* load background as surface */
std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> surface(IMG_Load(path.c_str()), SDL_FreeSurface);
std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> flipped_surface(rotozoomSurfaceXY(surface.get(), 0, 1, -1, 0), SDL_FreeSurface);
/* generate a GL texture, allocate space and set properties */
std::shared_ptr<GLuint> texture_id(new GLuint, Pudding::destroy_texture);
glGenTextures(1, texture_id.get());
glBindTexture(GL_TEXTURE_2D, *texture_id);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, flipped_surface->w, flipped_surface->h);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, flipped_surface->w, flipped_surface->h, GL_RGBA, GL_UNSIGNED_BYTE, flipped_surface->pixels);
log_gl_errors();
std::ostringstream message;
message << "loaded background image " << path.stem() << " from " << path << "(" << flipped_surface->w << "x" << flipped_surface->h << ")";
log(message.str());
tiles.push_back(texture_id);
}
}
/* Try to create cv::VideoCapture object using device ID #0. If successful, this will create GL texture IDs and storage
* for the camera frames, so it must be called after GL context has been created. Two textures will be created, so they
* can be used as a double buffer.
@ -319,6 +334,10 @@ void Pudding::respond(SDL_Event& event)
glUseProgram(mvp_program);
glUniform1i(effect_uniform_location, effect_id);
}
else if (get_delegate().compare(event, "tile"))
{
current_tile_index = ++current_tile_index % tiles.size();
}
}
/* Build an Item object by submitting the upc parameter to multiple APIs and taking
@ -720,6 +739,8 @@ int Pudding::capture_frame(void* game)
/* Update parameters and draw the screen */
void Pudding::update()
{
/* number of seconds we've been running for */
float time_seconds = SDL_GetTicks() / 1000.0f;
/* launch the camera capture thread if it is not currently running */
if (capture.isOpened() && !reading_capture_frame)
{
@ -755,6 +776,7 @@ void Pudding::update()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* switch to flat shader for background */
glUseProgram(flat_program);
glUniform1f(flat_time_uniform_location, time_seconds);
/* disable pudding attributes and enable rectangle attributes */
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
@ -762,16 +784,17 @@ void Pudding::update()
glEnableVertexAttribArray(1);
glUniform1i(flat_texture_uniform_location, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, background_texture_id);
glBindTexture(GL_TEXTURE_2D, *tiles[current_tile_index]);
/* 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");
/* 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.0f, 0.0f, 1.0f);
glUniform1i(scroll_uniform_location, true);
/* draws rectangle vertices and rectangle texture using UV coords */
glDrawArrays(GL_TRIANGLES, 0, 6);
glUniform1i(scroll_uniform_location, false);
/* draw pudding model using MVP shader */
glUseProgram(mvp_program);
glUniform1f(time_uniform_location, SDL_GetTicks() / 1000.0f);
glUniform1f(time_uniform_location, time_seconds);
/* calculate the transformation matrix for displaying pudding in viewport */
model = glm::rotate(model, weight(get_configuration()["pudding"]["rotation-speed"].get<float>()), Y_UNIT_NORMAL_3D);
projection = glm::perspective(

View File

@ -61,20 +61,24 @@ 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,
current_tile_index = 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, uv_transformation_uniform_location,
flat_texture_uniform_location, coordinate_bound_uniform_location;
mvp_uniform_location, time_uniform_location, effect_uniform_location, uv_transformation_uniform_location,
flat_texture_uniform_location, coordinate_bound_uniform_location, flat_time_uniform_location,
scroll_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;
bool show_item = false, reading_capture_frame = false;
SDL_GLContext capture_frame_thread_context = nullptr;
std::vector<std::shared_ptr<GLuint>> tiles;
void set_pudding_model(float, float, int, int = 1, float = -1, float = 1, float = 0.3f);
void load_gl_context();
void load_tiles();
void initialize_camera();
void incorporate_open_food_api(Item&);
void incorporate_nutronix_api(Item&);

View File

@ -3,6 +3,8 @@
in vec2 uv;
uniform sampler2D base_texture;
uniform vec3 blend_min_hsv;
uniform float time;
uniform bool scroll = false;
/* from http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl, licensed under WTFPL */
vec3 hsv2rgb(vec3 c)
@ -14,6 +16,15 @@ vec3 hsv2rgb(vec3 c)
void main(void)
{
gl_FragColor = texture(base_texture, uv);
if (scroll)
{
ivec2 texture_size = textureSize(base_texture, 0);
float speed = time * 35.0;
gl_FragColor = texelFetch(base_texture, ivec2(mod(vec2(gl_FragCoord.x + speed, gl_FragCoord.y - speed), texture_size)), 0);
}
else
{
gl_FragColor = texture(base_texture, uv);
}
gl_FragColor = min(gl_FragColor, vec4(hsv2rgb(blend_min_hsv), 1));
}

View File

@ -1,9 +0,0 @@
#version 130
in vec3 ex_Color;
in float x;
void main(void)
{
gl_FragColor = vec4(1, 1, 1, 1);
}