diff --git a/config.json b/config.json index 40922b8..c31331f 100644 --- a/config.json +++ b/config.json @@ -20,7 +20,8 @@ "enabled": true, "write-mp4": true, "video-frame-length": 33.333, - "max-video-memory": 2000 + "max-video-memory": 2000, + "mp4-pixel-format": "yuv420p" }, "input": { diff --git a/resource/mario_3_star_background.png b/resource/mario_3_star_background.png new file mode 100644 index 0000000..55e81e5 Binary files /dev/null and b/resource/mario_3_star_background.png differ diff --git a/src/Pudding.cpp b/src/Pudding.cpp index 51dd708..09cf719 100644 --- a/src/Pudding.cpp +++ b/src/Pudding.cpp @@ -33,7 +33,7 @@ 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, 12, 5, -.6, .6, .25); + set_pudding_model(1.0f, 1.6f, 10, 12, -.6, .6, .25); /* use gl context so we can draw 3D */ load_gl_context(); initialize_camera(); @@ -68,7 +68,7 @@ void Pudding::set_pudding_model( sfw::points_on_circle(layer_base_ring, ring_vertex_count, layer_base_percent * (base_radius - top_radius) + top_radius); /* layers above gradient position are brown, layers below are yellow, and the layer that contains gradient positon * is a gradient from brown to yellow */ - if (layer_top_percent <= gradient_position && layer_base_percent >= gradient_position) + if (layer_top_percent <= gradient_position && layer_base_percent > gradient_position) { layer_top_color = &PUDDING_BROWN; layer_bottom_color = &PUDDING_YELLOW; @@ -132,6 +132,23 @@ void Pudding::set_pudding_model( 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 surface(IMG_Load("resource/mario_3_star_background.png"), SDL_FreeSurface); + std::unique_ptr 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; + 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); @@ -606,14 +623,32 @@ void Pudding::update() viewport_box.set_right(get_window_box().get_center_x(), true); } glViewport(viewport_box.get_x(), viewport_box.get_y(), viewport_box.get_w(), viewport_box.get_h()); - glClearColor(1.0, 0.5, 0.8, 1.0f); glDisable(GL_DEPTH_TEST); + glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + /* switch to flat shader for background */ + glUseProgram(flat_program); + /* disable pudding attributes and enable rectangle attributes */ + glDisableVertexAttribArray(2); + glDisableVertexAttribArray(3); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + GLint base_texture_location = glGetUniformLocation(flat_program, "base_texture"); + glUniform1i(base_texture_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; + glUniform3f(blend_min_hsv_location, hue, 0.9, 1); + /* draws rectangle vertices and rectangle texture using UV coords */ + glDrawArrays(GL_TRIANGLES, 0, 6); /* draw pudding model using MVP shader */ glUseProgram(mvp_program); /* calculate the transformation matrix for displaying pudding in viewport */ model = glm::rotate(model, weight(get_configuration()["pudding"]["rotation-speed"].get()), Y_UNIT_NORMAL_3D); - projection = glm::perspective(glm::radians(45.0f), viewport_box.aspect(), 0.1f, 100.0f); + projection = glm::perspective( + glm::radians(viewport_box.get_w() > viewport_box.get_h() ? 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]); @@ -638,11 +673,14 @@ 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, "baseTexture"); + GLint base_texture_location = glGetUniformLocation(flat_program, "base_texture"); 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()); + /* 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); /* draw the current item image if items have been downloaded */ if (items.size() > 0) { diff --git a/src/Pudding.hpp b/src/Pudding.hpp index 86feefd..087b0ee 100644 --- a/src/Pudding.hpp +++ b/src/Pudding.hpp @@ -46,7 +46,7 @@ private: cv::VideoCapture capture; cv::Mat capture_frame; zbar::ImageScanner image_scanner; - GLuint vbo, flat_program, mvp_program, video_capture_texture_id, mvp_id; + GLuint vbo, flat_program, mvp_program, video_capture_texture_id, mvp_id, background_texture_id; glm::mat4 projection, model = glm::mat4(1.0f), mvp; std::vector pudding_vertices, pudding_colors; diff --git a/src/flat.frag b/src/flat.frag index a48288c..8db5178 100644 --- a/src/flat.frag +++ b/src/flat.frag @@ -1,9 +1,19 @@ #version 130 in vec2 UV; -uniform sampler2D baseTexture; +uniform sampler2D base_texture; +uniform vec3 blend_min_hsv; + +/* from http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl, licensed under WTFPL */ +vec3 hsv2rgb(vec3 c) +{ + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} void main(void) { - gl_FragColor = texture(baseTexture, UV); + gl_FragColor = texture(base_texture, UV); + gl_FragColor = min(gl_FragColor, vec4(hsv2rgb(blend_min_hsv), 1)); } diff --git a/src/flat.vert b/src/flat.vert index 7edfcb9..69414b8 100644 --- a/src/flat.vert +++ b/src/flat.vert @@ -2,7 +2,6 @@ in vec2 in_Position; in vec2 vertexUV; - out vec2 UV; void main(void) diff --git a/src/mvp.frag b/src/mvp.frag index 98014fc..bc433c5 100644 --- a/src/mvp.frag +++ b/src/mvp.frag @@ -5,5 +5,21 @@ in float x; void main(void) { - gl_FragColor = vec4(ex_Color * x, 1); + 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; } diff --git a/src/white.frag b/src/white.frag new file mode 100644 index 0000000..8daf986 --- /dev/null +++ b/src/white.frag @@ -0,0 +1,9 @@ +#version 130 + +in vec3 ex_Color; +in float x; + +void main(void) +{ + gl_FragColor = vec4(1, 1, 1, 1); +}