pudding texture from image

This commit is contained in:
frank 2021-09-01 00:08:45 -04:00
parent c7ea3aee6f
commit b8baf6802b
9 changed files with 107 additions and 76 deletions

View File

@ -45,7 +45,7 @@ $(SFW_SRC_DIR)Game.o : $(addprefix $(SFW_SRC_DIR),extension.hpp Node.hpp Sprite.
$(SFW_SRC_DIR)Animation.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Timer.hpp)
$(SFW_SRC_DIR)Recorder.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Game.hpp Configuration.hpp Delegate.hpp Animation.hpp extension.hpp)
$(SFW_SRC_DIR)Input.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Animation.hpp Configuration.hpp Delegate.hpp)
$(SFW_SRC_DIR)Configuration.o : $(addprefix $(SFW_SRC_DIR),Node.hpp)
$(SFW_SRC_DIR)Configuration.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Animation.hpp)
$(SFW_SRC_DIR)Delegate.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Game.hpp Input.hpp)
$(SFW_SRC_DIR)Display.o : $(addprefix $(SFW_SRC_DIR),Node.hpp Game.hpp Box.hpp Configuration.hpp Delegate.hpp)
$(SFW_SRC_DIR)Box.o : $(addprefix $(SFW_SRC_DIR),extension.hpp Segment.hpp)
@ -63,8 +63,7 @@ linux : CFLAGS = -g3 -Wall -Wextra -Og -c -I$(SFW_LIB_DIR) -I$(SFW_SRC_DIR) $(SD
linux : CPP_FLAGS = $(CFLAGS) --std=c++17
linux : LFLAGS = $(shell $(SDLCONFIG) --libs) -lpthread -lGL -lGLESv2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lcurl -lstdc++fs \
-L/home/frank/local/opencv/lib -Wl,-rpath,/home/frank/local/opencv/lib -Wl,--enable-new-dtags -lopencv_videoio -lopencv_core \
-lopencv_highgui -lopencv_imgproc \
-L/home/frank/local/zbar/lib -Wl,-rpath,/home/frank/local/zbar/lib -Wl,--enable-new-dtags -lzbar
-lopencv_highgui -lopencv_imgproc -L/home/frank/local/zbar/lib -Wl,-rpath,/home/frank/local/zbar/lib -Wl,--enable-new-dtags -lzbar
linux : $(GLEW_DIR)glew.o $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) \
$(SFW_O_FILES) $(GAME_O_FILES)
$(CREATE_FONT_SYMLINK)

View File

@ -7,6 +7,10 @@
"debug": false,
"render driver": "opengl"
},
"configuration":
{
"auto-refresh": true
},
"keys":
{
"print-video-memory-size": ["CTRL", "v"],
@ -39,7 +43,7 @@
{
"json-save": true,
"json-save-directory": "local/scans",
"barcode": "",
"barcode": "2430373621232",
"capture-device": "/dev/video0"
},
"api":

@ -1 +1 @@
Subproject commit fe3e0bf27f8ab45edcb322ab89bc79a6fe15d8bf
Subproject commit c8bc86cab729a26cc7563c7177c42f919b47df07

View File

@ -1,6 +1,6 @@
/*
______________
//````````````\\ + by @ohsqueezy [http://ohsqueezy.itch.io] & @sleepin [http://instagram.com/sleepin]
//````````````\\ + a game by @ohsqueezy [http://ohsqueezy.itch.io] & @sleepin [http://instagram.com/sleepin]
//~~~~~~~~~~~~~~\\ + custom pudding code provided by Nuggets Select [http://nugget.fun]
//================\\ + available for copy, modification and redistribution [http://git.nugget.fun/pudding]
// \\
@ -39,13 +39,14 @@ Pudding::Pudding()
initialize_camera();
}
/* Assign vertices, colors and texture UV coordinates to the pudding model */
void Pudding::set_pudding_model(
float top_radius, float base_radius, int ring_vertex_count, int layer_count, float min_y, float max_y, float gradient_position)
{
size_t ii;
const glm::vec3 *layer_top_color, *layer_bottom_color;
const glm::vec2 *start_vertex, *end_vertex;
float layer_top_y, layer_top_percent, layer_base_y, layer_base_percent;
float layer_top_y, layer_top_percent, layer_base_y, layer_base_percent, u_step = 1.0f / ring_vertex_count, ring_start_vertex_u;
std::vector<glm::vec2> layer_top_ring, layer_base_ring;
layer_top_ring.reserve(ring_vertex_count);
layer_base_ring.reserve(ring_vertex_count);
@ -83,46 +84,60 @@ void Pudding::set_pudding_model(
layer_top_color = &PUDDING_YELLOW;
layer_bottom_color = &PUDDING_YELLOW;
}
/* go through top and base ring vertices simultaneously to build side triangles */
/* u coordinate will increase toward 1.0f as we go around the ring */
ring_start_vertex_u = 0.0f;
for (ii = 0; ii < layer_top_ring.size(); ii++)
{
/* triangle that includes top two vertices and first base vertex */
start_vertex = &layer_top_ring[ii];
end_vertex = &layer_top_ring[(ii + 1) % layer_top_ring.size()];
pudding_vertices.push_back({start_vertex->x, layer_top_y, start_vertex->y});
pudding_uv.push_back({ring_start_vertex_u, layer_top_percent});
pudding_vertices.push_back({end_vertex->x, layer_top_y, end_vertex->y});
pudding_uv.push_back({ring_start_vertex_u + u_step, layer_top_percent});
pudding_colors.insert(pudding_colors.end(), 2, *layer_top_color);
pudding_vertices.push_back({layer_base_ring[ii].x, layer_base_y, layer_base_ring[ii].y});
pudding_uv.push_back({ring_start_vertex_u, layer_base_percent});
pudding_colors.push_back(*layer_bottom_color);
/* triangle that includes bottom two vertices and second top vertex */
start_vertex = &layer_base_ring[ii];
pudding_vertices.push_back({start_vertex->x, layer_base_y, start_vertex->y});
pudding_uv.push_back({ring_start_vertex_u, layer_base_percent});
pudding_colors.push_back(*layer_bottom_color);
pudding_vertices.push_back({end_vertex->x, layer_top_y, end_vertex->y});
pudding_uv.push_back({ring_start_vertex_u + u_step, layer_top_percent});
pudding_colors.push_back(*layer_top_color);
end_vertex = &layer_base_ring[(ii + 1) % layer_base_ring.size()];
pudding_vertices.push_back({end_vertex->x, layer_base_y, end_vertex->y});
pudding_uv.push_back({ring_start_vertex_u + u_step, layer_base_percent});
pudding_colors.push_back(*layer_bottom_color);
ring_start_vertex_u += u_step;
}
}
/* process the top and bottom of pudding, filling each face with a triangle fan */
layer_top_ring.clear();
sfw::points_on_circle(layer_top_ring, ring_vertex_count, top_radius);
float y = max_y;
const glm::vec3* face_color = &PUDDING_BROWN;
for (const std::vector<glm::vec2>& face : {layer_top_ring, layer_base_ring})
Box texture_box = Box({0, 0}, {1, 1});
for (float radius : {top_radius, base_radius})
{
sfw::points_on_circle(layer_top_ring, ring_vertex_count, radius);
/* loop through points on the face */
for (ii = 0; ii < face.size(); ii++)
for (ii = 0; ii < layer_top_ring.size(); ii++)
{
start_vertex = &face[ii];
end_vertex = &face[(ii + 1) % face.size()];
/* triangle from the center of the face to the edge */
start_vertex = &layer_top_ring[ii];
end_vertex = &layer_top_ring[(ii + 1) % layer_top_ring.size()];
/* triangle from the center of the layer_top_ring to the edge */
pudding_vertices.push_back({start_vertex->x, y, start_vertex->y});
pudding_vertices.push_back({end_vertex->x, y, end_vertex->y});
pudding_vertices.push_back({0, y, 0});
/* map circle points to UV points of the texture */
pudding_uv.push_back(*start_vertex);
pudding_uv.push_back(*end_vertex);
pudding_uv.push_back({0, 0});
}
/* single color for the entire face */
pudding_colors.insert(pudding_colors.end(), 3 * face.size(), *face_color);
/* single color for the entire layer_top_ring */
pudding_colors.insert(pudding_colors.end(), 3 * layer_top_ring.size(), *face_color);
y = min_y;
face_color = &PUDDING_YELLOW;
}
@ -133,18 +148,13 @@ void Pudding::load_gl_context()
{
super::load_gl_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("resource/mario_3_star_background.png"), SDL_FreeSurface);
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);
// SDL_Surface* surface = zoomSurface(
// rotateSurface90Degrees(IMG_Load("resource/tile.png"), 2), -1, 1, SMOOTHING_OFF);
/* load as an SDL surface to translate image format into pixel data, flip, and get dimensions */
// SDL_RWops* rw = SDL_RWFromConstMem(storage.data(), storage.size());
// SDL_Surface* surface = IMG_Load_RW(rw, 0);
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;
@ -166,15 +176,16 @@ void Pudding::load_gl_context()
/* Generate one vertex buffer object to hold all vertices and rectangle UV map. Since we're using one buffer, data
* will be copied in one after the other, offset to after the previous data location. The same buffer offset will
* be passed to the vertex attributes for each data. */
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
/* allocate space for vertices, UV and colors, and copy rectangle vertices in at initialization */
GLsizeiptr vbo_size = (rectangle_vertices.size() + rectangle_uv.size()) * sizeof(glm::vec2) +
GLsizeiptr vbo_size = (rectangle_vertices.size() + rectangle_uv.size() + pudding_uv.size()) * sizeof(glm::vec2) +
(pudding_vertices.size() + pudding_colors.size()) * sizeof(glm::vec3);
glBufferData(GL_ARRAY_BUFFER, vbo_size, rectangle_vertices.data(), GL_STATIC_DRAW);
/* specify the rectangle vertex attributes as consecutive 2D float coords */
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
/* copy rectangle UV data into the VBO, offset to after the vertex data, set up vertex attributes */
/* copy rectangle UV data into the VBO, offset to after the vertex data, set up attributes */
GLintptr offset = rectangle_vertices.size() * sizeof(glm::vec2);
glBufferSubData(GL_ARRAY_BUFFER, offset, rectangle_uv.size() * sizeof(glm::vec2), rectangle_uv.data());
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<GLvoid*>(offset));
@ -186,6 +197,10 @@ void Pudding::load_gl_context()
offset += pudding_vertices.size() * sizeof(glm::vec3);
glBufferSubData(GL_ARRAY_BUFFER, offset, pudding_colors.size() * sizeof(glm::vec3), pudding_colors.data());
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<GLvoid*>(offset));
/* copy pudding UV values into VBO, offset to after pudding color vertices and set as 2D */
offset += pudding_colors.size() * sizeof(glm::vec3);
glBufferSubData(GL_ARRAY_BUFFER, offset, pudding_uv.size() * sizeof(glm::vec2), pudding_uv.data());
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<GLvoid*>(offset));
/* Load two shader programs, one for rendering the flat objects, and one for rendering the 3D model. Load, configure,
* and link the flat shader program first. */
GLuint vertex_shader = load_shader("src/flat.vert", GL_VERTEX_SHADER);
@ -193,8 +208,8 @@ void Pudding::load_gl_context()
flat_program = glCreateProgram();
glAttachShader(flat_program, vertex_shader);
glAttachShader(flat_program, fragment_shader);
glBindAttribLocation(flat_program, 0, "in_Position");
glBindAttribLocation(flat_program, 1, "vertexUV");
glBindAttribLocation(flat_program, 0, "in_position");
glBindAttribLocation(flat_program, 1, "vertex_uv");
link_shader(flat_program);
/* load, configure and link the 3D world program */
vertex_shader = load_shader("src/mvp.vert", GL_VERTEX_SHADER);
@ -202,10 +217,11 @@ void Pudding::load_gl_context()
mvp_program = glCreateProgram();
glAttachShader(mvp_program, vertex_shader);
glAttachShader(mvp_program, fragment_shader);
glBindAttribLocation(mvp_program, 2, "in_Position");
glBindAttribLocation(mvp_program, 3, "in_Color");
glBindAttribLocation(mvp_program, 2, "in_position");
glBindAttribLocation(mvp_program, 3, "in_color");
glBindAttribLocation(mvp_program, 4, "vertex_uv");
link_shader(mvp_program);
mvp_id = glGetUniformLocation(mvp_program, "MVP");
mvp_id = glGetUniformLocation(mvp_program, "mvp");
log_gl_errors();
}
@ -604,9 +620,6 @@ Item& Pudding::get_current_item()
/* Update parameters and draw the screen */
void Pudding::update()
{
/* reload the config file every frame to check for changes */
get_root()->configuration.load("config.json");
get_root()->configuration.merge();
if (current_config_barcode != get_configuration()["scan"]["barcode"])
{
current_config_barcode = get_configuration()["scan"]["barcode"];
@ -616,13 +629,13 @@ void Pudding::update()
log(message.str());
}
/* viewport box will be used to tell GL where to draw */
Box viewport_box = get_window_box();
Box viewport_box = window_box();
/* shrink viewport if item texture or camera will be displayed */
if (items.size() > 0 || capture.isOpened())
{
viewport_box.set_right(get_window_box().get_center_x(), true);
viewport_box.right(window_box().cx(), true);
}
glViewport(viewport_box.get_x(), viewport_box.get_y(), viewport_box.get_w(), viewport_box.get_h());
glViewport(viewport_box.left(), viewport_box.top(), viewport_box.width(), viewport_box.height());
glDisable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -648,7 +661,7 @@ void Pudding::update()
/* 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(
glm::radians(viewport_box.get_w() > viewport_box.get_h() ? 40.0f : 45.0f), viewport_box.aspect(), 0.1f, 100.0f);
glm::radians(viewport_box.width() > viewport_box.height() ? 40.0f : 45.0f), viewport_box.aspect(), 0.1f, 100.0f);
mvp = projection * VIEW_MATRIX * model;
/* pass the mvp matrix to the shader */
glUniformMatrix4fv(mvp_id, 1, GL_FALSE, &mvp[0][0]);
@ -656,7 +669,18 @@ void Pudding::update()
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
if (items.size() == 0)
{
glEnableVertexAttribArray(3);
}
else
{
glEnableVertexAttribArray(4);
GLuint pudding_texture_location = glGetUniformLocation(mvp_program, "pudding_texture");
glUniform1i(pudding_texture_location, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, *get_current_item().get_active_image_texture().get());
}
/* draw pudding model */
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glEnable(GL_DEPTH_TEST);
@ -677,7 +701,7 @@ void Pudding::update()
glUniform1i(base_texture_location, 0);
glActiveTexture(GL_TEXTURE0);
/* move viewport to the right side of screen */
viewport_box.set_left(get_window_box().get_center_x());
viewport_box.left(window_box().cx());
/* reset blend to display the original texture colors */
GLint blend_min_location = glGetUniformLocation(flat_program, "blend_min_hsv");
glUniform3f(blend_min_location, 1, 0, 1);
@ -687,9 +711,9 @@ void Pudding::update()
/* shrink viewport to half size if camera will also be displayed */
if (capture.isOpened())
{
viewport_box.set_top(get_window_box().get_center_y(), true);
viewport_box.top(window_box().cy(), true);
}
glViewport(viewport_box.get_x(), viewport_box.get_y(), viewport_box.get_w(), viewport_box.get_h());
glViewport(viewport_box.left(), viewport_box.top(), viewport_box.width(), viewport_box.height());
glBindTexture(GL_TEXTURE_2D, *get_current_item().get_active_image_texture().get());
/* draws rectangle vertices and rectangle texture using UV coords */
glDrawArrays(GL_TRIANGLES, 0, 6);
@ -698,12 +722,12 @@ void Pudding::update()
if (capture.isOpened())
{
capture.read(capture_frame);
viewport_box.set_top(get_window_box().get_top());
viewport_box.top(window_box().top());
if (!capture_frame.empty())
{
/* rotate the opencv matrix 180 to work with opengl coords */
cv::flip(capture_frame, capture_frame, -1);
glViewport(viewport_box.get_x(), viewport_box.get_y(), viewport_box.get_w(), viewport_box.get_h());
glViewport(viewport_box.left(), viewport_box.top(), viewport_box.width(), viewport_box.height());
/* bind texture, binding it to accept pixel data and to GLSL sampler */
glBindTexture(GL_TEXTURE_2D, video_capture_texture_id);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, capture_frame.cols, capture_frame.rows, GL_BGR, GL_UNSIGNED_BYTE, capture_frame.ptr());

View File

@ -46,9 +46,10 @@ private:
cv::VideoCapture capture;
cv::Mat capture_frame;
zbar::ImageScanner image_scanner;
GLuint vbo, flat_program, mvp_program, video_capture_texture_id, mvp_id, background_texture_id;
GLuint flat_program, mvp_program, video_capture_texture_id, mvp_id, background_texture_id;
glm::mat4 projection, model = glm::mat4(1.0f), mvp;
std::vector<glm::vec3> pudding_vertices, pudding_colors;
std::vector<glm::vec2> pudding_uv;
void set_pudding_model(float, float, int, int = 1, float = -1, float = 1, float = 0.3f);
void load_gl_context();
@ -72,7 +73,7 @@ public:
void increment_item_index(int = 1);
Item& get_current_item();
void update();
virtual std::string get_class_name() const { return "Pudding"; }
virtual std::string class_name() const { return "Pudding"; }
};

View File

@ -1,6 +1,6 @@
#version 130
in vec2 UV;
in vec2 uv;
uniform sampler2D base_texture;
uniform vec3 blend_min_hsv;
@ -14,6 +14,6 @@ vec3 hsv2rgb(vec3 c)
void main(void)
{
gl_FragColor = texture(base_texture, UV);
gl_FragColor = texture(base_texture, uv);
gl_FragColor = min(gl_FragColor, vec4(hsv2rgb(blend_min_hsv), 1));
}

View File

@ -1,11 +1,11 @@
#version 130
in vec2 in_Position;
in vec2 vertexUV;
out vec2 UV;
in vec2 in_position;
in vec2 vertex_uv;
out vec2 uv;
void main(void)
{
gl_Position = vec4(in_Position, 0, 1);
UV = vertexUV;
gl_Position = vec4(in_position, 0, 1);
uv = vertex_uv;
}

View File

@ -1,25 +1,25 @@
#version 130
in vec3 ex_Color;
in vec3 ex_color;
in float x;
in vec2 uv;
uniform sampler2D pudding_texture;
void main(void)
{
vec3 shadowed = ex_Color;
float r = min(1, shadowed[0]);
float g = min(1, shadowed[1]);
float b = min(1, shadowed[2]);
float dx = abs(floor(gl_FragCoord[0]) - 480) / 480.0;
if (int(floor(gl_FragCoord[0] / 3) + floor(gl_FragCoord[1]) / 3) % 2 == 0)
{
gl_FragColor = vec4(vec3(r, g, b) * 1.3, 1);
}
else
{
gl_FragColor = vec4(vec3(r, g, b) * 0.6, 1);
}
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;
// vec3 shadowed = min(ex_color, 1.0);
// float dx = abs(floor(gl_FragCoord[0]) - 480) / 480.0;
// if (int(floor(gl_FragCoord[0] / 3) + floor(gl_FragCoord[1]) / 3) % 2 == 0)
// {
// gl_FragColor = vec4(shadowed * 1.3, 1);
// }
// else
// {
// gl_FragColor = vec4(shadowed * 0.6, 1);
// }
// 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 = texture(pudding_texture, uv);
}

View File

@ -1,14 +1,17 @@
#version 130
in vec3 in_Position;
in vec3 in_Color;
uniform mat4 MVP;
out vec3 ex_Color;
in vec3 in_position;
in vec3 in_color;
in vec2 vertex_uv;
uniform mat4 mvp;
out vec3 ex_color;
out float x;
out vec2 uv;
void main(void)
{
gl_Position = MVP * vec4(in_Position, 1);
ex_Color = in_Color;
x = 1.8 - abs(in_Position[0]);
gl_Position = mvp * vec4(in_position, 1);
ex_color = in_color;
x = 1.8 - abs(in_position[0]);
uv = vertex_uv;
}