Repository for OpenCV's extra modules
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

253 lines
7.1 KiB

// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
// Copyright Amir Hassan (kallaballa) <amir@viel-zu.org>
#include <opencv2/v4d/v4d.hpp>
//adapted from https://gitlab.com/wikibooks-opengl/modern-tutorials/-/blob/master/tut05_cube/cube.cpp
#include <cstdio>
#include <cstdlib>
#include <cmath>
constexpr long unsigned int WIDTH = 1920;
constexpr long unsigned int HEIGHT = 1080;
constexpr bool OFFSCREEN = false;
#ifndef __EMSCRIPTEN__
constexpr double FPS = 60;
constexpr const char* OUTPUT_FILENAME = "cube-demo.mkv";
#endif
const unsigned long DIAG = hypot(double(WIDTH), double(HEIGHT));
const int GLOW_KERNEL_SIZE = std::max(int(DIAG / 138 % 2 == 0 ? DIAG / 138 + 1 : DIAG / 138), 1);
using std::cerr;
using std::endl;
const unsigned int triangles = 12;
const unsigned int vertices_index = 0;
const unsigned int colors_index = 1;
unsigned int shader_program;
unsigned int vao;
unsigned int uniform_transform;
static cv::Ptr<cv::viz::V4D> v4d = cv::viz::V4D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT),
OFFSCREEN, "Cube Demo");
static GLuint load_shader() {
#ifndef OPENCV_V4D_USE_ES3
const string shaderVersion = "330";
#else
const string shaderVersion = "300 es";
#endif
const string vert =
" #version " + shaderVersion
+ R"(
precision lowp float;
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 vertex_color;
uniform mat4 transform;
out vec3 color;
void main() {
gl_Position = transform * vec4(pos, 1.0);
color = vertex_color;
}
)";
const string frag =
" #version " + shaderVersion
+ R"(
precision lowp float;
in vec3 color;
out vec4 frag_color;
void main() {
frag_color = vec4(color, 1.0);
}
)";
return cv::viz::init_shader(vert.c_str(), frag.c_str(), "fragColor");
}
static void init_scene(const cv::Size& sz) {
glEnable (GL_DEPTH_TEST);
float vertices[] = {
// Front face
1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0,
// Back face
1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, };
float vertex_colors[] = { 1.0, 0.4, 0.6, 1.0, 0.9, 0.2, 0.7, 0.3, 0.8, 0.5, 0.3, 1.0,
0.2, 0.6, 1.0, 0.6, 1.0, 0.4, 0.6, 0.8, 0.8, 0.4, 0.8, 0.8, };
unsigned short triangle_indices[] = {
// Front
0, 1, 2, 2, 3, 0,
// Right
0, 3, 7, 7, 4, 0,
// Bottom
2, 6, 7, 7, 3, 2,
// Left
1, 5, 6, 6, 2, 1,
// Back
4, 7, 6, 6, 5, 4,
// Top
5, 1, 0, 0, 4, 5, };
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
unsigned int triangles_ebo;
glGenBuffers(1, &triangles_ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangles_ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof triangle_indices, triangle_indices,
GL_STATIC_DRAW);
unsigned int verticies_vbo;
glGenBuffers(1, &verticies_vbo);
glBindBuffer(GL_ARRAY_BUFFER, verticies_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW);
glVertexAttribPointer(vertices_index, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(vertices_index);
unsigned int colors_vbo;
glGenBuffers(1, &colors_vbo);
glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof vertex_colors, vertex_colors, GL_STATIC_DRAW);
glVertexAttribPointer(colors_index, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(colors_index);
// Unbind to prevent accidental modification
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
shader_program = load_shader();
uniform_transform = glGetUniformLocation(shader_program, "transform");
glViewport(0,0, sz.width, sz.height);
}
static void render_scene() {
glClearColor(0.1, 0.12, 0.2, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
float angle = fmod(double(cv::getTickCount()) / double(cv::getTickFrequency()), 2 * M_PI);
float scale = 0.25;
cv::Matx44f scaleMat(
scale, 0.0, 0.0, 0.0,
0.0, scale, 0.0, 0.0,
0.0, 0.0, scale, 0.0,
0.0, 0.0, 0.0, 1.0);
cv::Matx44f rotXMat(
1.0, 0.0, 0.0, 0.0,
0.0, cos(angle), -sin(angle), 0.0,
0.0, sin(angle), cos(angle), 0.0,
0.0, 0.0, 0.0, 1.0);
cv::Matx44f rotYMat(
cos(angle), 0.0, sin(angle), 0.0,
0.0, 1.0, 0.0, 0.0,
-sin(angle), 0.0,cos(angle), 0.0,
0.0, 0.0, 0.0, 1.0);
cv::Matx44f rotZMat(cos(angle), -sin(angle), 0.0, 0.0, sin(angle), cos(angle), 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);
cv::Matx44f transform = scaleMat * rotXMat * rotYMat * rotZMat;
glUniformMatrix4fv(uniform_transform, 1, GL_FALSE, transform.val);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, triangles * 3, GL_UNSIGNED_SHORT, NULL);
}
#ifndef __EMSCRIPTEN__
static void glow_effect(const cv::UMat& src, cv::UMat& dst, const int ksize) {
static cv::UMat resize;
static cv::UMat blur;
static cv::UMat dst16;
cv::bitwise_not(src, dst);
//Resize for some extra performance
cv::resize(dst, resize, cv::Size(), 0.5, 0.5);
//Cheap blur
cv::boxFilter(resize, resize, -1, cv::Size(ksize, ksize), cv::Point(-1, -1), true,
cv::BORDER_REPLICATE);
//Back to original size
cv::resize(resize, blur, src.size());
//Multiply the src image with a blurred version of itself
cv::multiply(dst, blur, dst16, 1, CV_16U);
//Normalize and convert back to CV_8U
cv::divide(dst16, cv::Scalar::all(255.0), dst, 1, CV_8U);
cv::bitwise_not(dst, dst);
}
#endif
static bool iteration() {
using namespace cv::viz;
//Render using OpenGL
v4d->gl(render_scene);
//If we have OpenCL and maybe even CL-GL sharing then this is faster than the glow shader. Without OpenCL this is very slow.
#ifndef __EMSCRIPTEN__
//Aquire the frame buffer for use by OpenCL
v4d->fb([&](cv::UMat& frameBuffer) {
//Glow effect (OpenCL)
glow_effect(frameBuffer, frameBuffer, GLOW_KERNEL_SIZE);
});
#endif
updateFps(v4d, true);
v4d->write();
//If onscreen rendering is enabled it displays the framebuffer in the native window. Returns false if the window was closed.
if (!v4d->display())
return false;
return true;
}
#ifndef __EMSCRIPTEN__
int main(int argc, char** argv) {
#else
int main() {
#endif
using namespace cv::viz;
if (!v4d->isOffscreen())
v4d->setVisible(true);
printSystemInfo();
#ifndef __EMSCRIPTEN__
Sink sink = makeWriterSink(OUTPUT_FILENAME, cv::VideoWriter::fourcc('V', 'P', '9', '0'), FPS,
cv::Size(WIDTH, HEIGHT));
v4d->setSink(sink);
#endif
v4d->gl(init_scene);
v4d->run(iteration);
return 0;
}