// This code example is created for educational purpose // by Thorsten Thormaehlen (contact: www.thormae.de). // It is distributed without any warranty. #include #include #include #include #include #include #include #include #include #include using namespace std; #include class Renderer : protected QOpenGLFunctions_2_0 { public: float t; GLuint texID0, texID1; public: Renderer() : t(0.0), texID0(0), texID1(0) {} public: void display() { glClearColor(0.8f, 0.8f, 0.8f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // set camera gluLookAt(0.0, 0.0, 8.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0); // draw scene glPushMatrix(); glTranslatef(0.0f, -t*0.015f, 0.0f); drawTexturedPlaneBackground(); glPopMatrix(); glPushMatrix(); glRotatef(-t, 0.0f, 0.0f, 1.0f); drawTexturedPlaneForeground(); glPopMatrix(); } void init() { initializeOpenGLFunctions(); glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); texID0 = loadTexture(findFile("foreground.png", "qt", 5)); texID1 = loadTexture(findFile("background.png", "qt", 5)); } void resize(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (30.0, (float)w/(float)h, 0.1, 50.0); } void dispose() { if(texID0 !=0) glDeleteTextures(1, &texID0); if(texID1 !=0) glDeleteTextures(1, &texID1); } private: void drawTexturedPlaneForeground() { glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); //GL_MODULATE glBindTexture(GL_TEXTURE_2D, texID0); glColor4f(1.0f,0.0f,0.0f,1.0f); glBegin(GL_POLYGON); glTexCoord2f(0.05f,0.95f); glVertex3f(-1.0f, 1.0f, 0.1f); glTexCoord2f(0.95f,0.95f); glVertex3f(-1.0f,-1.0f, 0.1f); glTexCoord2f(0.95f,0.05f); glVertex3f( 1.0f,-1.0f, 0.1f); glTexCoord2f(0.05f,0.05f); glVertex3f( 1.0f, 1.0f, 0.1f); glEnd(); glDisable(GL_TEXTURE_2D); } void drawTexturedPlaneBackground() { glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); //GL_MODULATE glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, texID1); glColor4f(0.0f,1.0f,0.0f,1.0f); glBegin(GL_POLYGON); glTexCoord2f(0.00f,1.00f); glVertex3f(-2.0f, 16.0f, 0.0f); glTexCoord2f(8.00f,1.00f); glVertex3f(-2.0f,-16.0f, 0.0f); glTexCoord2f(8.00f,0.00f); glVertex3f( 2.0f,-16.0f, 0.0f); glTexCoord2f(0.00f,0.00f); glVertex3f( 2.0f, 16.0f, 0.0f); glEnd(); glDisable(GL_TEXTURE_2D); } GLuint loadTexture(const std::string &filename) { unsigned width; unsigned height; int level = 0; int border = 0; std::vector imgData; QString fileName0(filename.c_str()); QImage img(fileName0); if(img.isNull()) { return -1; } width = img.width(); height = img.height(); if(img.format() != QImage::Format_RGBA8888) { img = img.convertToFormat(QImage::Format_RGBA8888); } img = img.mirrored(); // data is aligned in byte order glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //request textureID GLuint textureID; glGenTextures( 1, &textureID); // bind texture glBindTexture( GL_TEXTURE_2D, textureID); //define how to filter the texture (important but ignore for now) glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //texture colors should modulate the original color values glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // specify the 2D texture map glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, border, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); // return unique texture identifier return textureID; } bool fileExists(const std::string& filename) { ifstream myfile(filename.c_str()); if (!myfile.is_open()) { return false; } myfile.close(); return true; } std::string findFile(const std::string& filename, const std::string& subdir, int depth) { int counter = 0; std::string path(""); while (counter < depth) { if (fileExists(path + filename)) return path + filename; if (fileExists(path + "/" + subdir + "/" + filename)) return path + "/" + subdir + "/" + filename; path += "../"; counter++; } return filename; } }; class MyWidget : public QOpenGLWidget { private: Renderer *renderer; QTimer *timer; public: MyWidget(QWidget *parent = NULL) : QOpenGLWidget(parent) { this->setWindowTitle("Blending of textures"); this->resize(320, 320); renderer = new Renderer(); timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer->start(30); } ~MyWidget() { makeCurrent(); renderer->dispose(); doneCurrent(); delete renderer; delete timer; } protected: void initializeGL() { renderer->init(); } void resizeGL(int w, int h){ renderer->resize(w, h); } void paintGL() { float offset = 1.0f; renderer->t += offset; renderer->display(); } }; int main (int argc, char* argv[]) { // create a QApplication object that handles initialization, // finalization, and the main event loop QApplication appl(argc, argv); MyWidget widget; // create a widget widget.show(); //show the widget and its children return appl.exec(); // execute the application }