#include #include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN 1 #define NOMINMAX 1 #include #endif #if defined(__APPLE__) #include #include #else #include #include #endif #include "opencv2/core.hpp" #include "opencv2/core/opengl.hpp" #include "opencv2/core/cuda.hpp" #include "opencv2/highgui.hpp" using namespace std; using namespace cv; using namespace cv::cuda; const int win_width = 800; const int win_height = 640; struct DrawData { GLuint vao, vbo, program, textureID; }; static cv::Mat rot(float angle) { cv::Mat R_y = (cv::Mat_(4,4) << cos(angle), 0, sin(angle), 0, 0, 1, 0, 0, -sin(angle), 0, cos(angle), 0, 0, 0, 0, 1); return R_y; } static GLuint create_shader(const char* source, GLenum type) { GLuint shader = glCreateShader(type); glShaderSource(shader, 1, &source, NULL); glCompileShader(shader); return shader; } static void draw(void* userdata) { DrawData* data = static_cast(userdata); static float angle = 0.0f; angle += 1.f; cv::Mat trans = rot(CV_PI * angle / 360.f); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(data->program); glUniformMatrix4fv(glGetUniformLocation(data->program, "transform"), 1, GL_FALSE, trans.ptr()); glBindTexture(GL_TEXTURE_2D, data->textureID); glBindVertexArray(data->vao); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); } int main(int argc, char* argv[]) { string filename; if (argc < 2) { cout << "Usage: " << argv[0] << " image" << endl; filename = "baboon.jpg"; } else filename = argv[1]; Mat img = imread(samples::findFile(filename)); if (img.empty()) { cerr << "Can't open image " << filename << endl; return -1; } flip(img, img, 0); namedWindow("OpenGL", WINDOW_OPENGL); resizeWindow("OpenGL", win_width, win_height); DrawData data; glEnable(GL_DEPTH_TEST); const char *vertex_shader_source = "#version 330 core\n" "layout (location = 0) in vec3 position;\n" "layout (location = 1) in vec2 texCoord;\n" "out vec2 TexCoord;\n" "uniform mat4 transform;\n" "void main() {\n" " gl_Position = transform * vec4(position, 1.0);\n" " TexCoord = texCoord;\n" "}\n"; const char *fragment_shader_source = "#version 330 core\n" "in vec2 TexCoord;\n" "out vec4 color;\n" "uniform sampler2D ourTexture;\n" "void main() {\n" " color = texture(ourTexture, TexCoord);\n" "}\n"; data.program = glCreateProgram(); GLuint vertex_shader = create_shader(vertex_shader_source, GL_VERTEX_SHADER); GLuint fragment_shader = create_shader(fragment_shader_source, GL_FRAGMENT_SHADER); glAttachShader(data.program, vertex_shader); glAttachShader(data.program, fragment_shader); glLinkProgram(data.program); glUseProgram(data.program); GLfloat vertices[] = { // Positions // Texture Coords 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top Right 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Left -1.0f, -1.0f, 0.0f, 0.0f, 0.0f // Bottom Left }; glGenVertexArrays(1, &data.vao); glGenBuffers(1, &data.vbo); glBindVertexArray(data.vao); glBindBuffer(GL_ARRAY_BUFFER, data.vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // Texture Coord attribute glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); glBindVertexArray(0); // Unbind VAO // Image to texture glGenTextures(1, &data.textureID); glBindTexture(GL_TEXTURE_2D, data.textureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.cols, img.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, img.data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); setOpenGlDrawCallback("OpenGL", draw, &data); for (;;) { updateWindow("OpenGL"); char key = (char)waitKey(40); if (key == 27) break; } setOpenGlDrawCallback("OpenGL", 0, 0); destroyAllWindows(); return 0; }