/* * Copyright (c) 2010 Petr Mrázek (peterix) * See LICENSE for details. */ #include "glwidget.h" #include #include #include #include #include #include struct Vertex { float texcoord[2]; float color[3]; float position[3]; }; #define FRS 0.0625 #define FRX FRS/2 // this is crap const Vertex house_vert[] = { // walls { { 0.0, 0.0 }, { 0.0, 0.0, 1.0 }, { -4.0, -4.0, -4.0 } }, { { 0.0, FRS }, { 0.0, 1.0, 0.0 }, { -4.0, -4.0, 4.0 } }, { { FRS, FRS }, { 0.0, 1.0, 1.0 }, { 4.0, -4.0, 4.0 } }, { { FRS, 0.0 }, { 1.0, 0.0, 0.0 }, { 4.0, -4.0, -4.0 } }, { { 0.0, 0.0 }, { 1.0, 0.0, 1.0 }, { -4.0, 4.0, -4.0 } }, { { 0.0, FRS }, { 1.0, 1.0, 0.0 }, { -4.0, 4.0, 4.0 } }, { { FRS, FRS }, { 1.0, 1.0, 1.0 }, { 4.0, 4.0, 4.0 } }, { { FRS, 0.0 }, { 0.0, 0.0, 1.0 }, { 4.0, 4.0, -4.0 } }, { { 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { -4.0, -4.0, -4.0 } }, { { 0.0, FRS }, { 0.0, 1.0, 1.0 }, { -4.0, -4.0, 4.0 } }, { { FRS, FRS }, { 1.0, 0.0, 0.0 }, { -4.0, 4.0, 4.0 } }, { { FRS, 0.0 }, { 1.0, 0.0, 1.0 }, { -4.0, 4.0, -4.0 } }, { { 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 4.0, -4.0, -4.0 } }, { { 0.0, FRS }, { 0.0, 1.0, 1.0 }, { 4.0, -4.0, 4.0 } }, { { FRS, FRS }, { 1.0, 0.0, 0.0 }, { 4.0, 4.0, 4.0 } }, { { FRS, 0.0 }, { 1.0, 0.0, 1.0 }, { 4.0, 4.0, -4.0 } }, // roof { { 0.0, 0.0 }, { 0.0, 0.0, 1.0 }, { -4.0, 4.0, -4.0 } }, { { FRS, 0.0 }, { 0.0, 1.0, 1.0 }, { 4.0, 4.0, -4.0 } }, { { FRX, FRX }, { 1.0, 1.0, 1.0 }, { 0.0, 9.0, 0.0 } }, { { FRS, 0.0 }, { 1.0, 0.0, 0.0 }, { 4.0, 4.0, -4.0 } }, { { FRS, FRS }, { 1.0, 1.0, 0.0 }, { 4.0, 4.0, 4.0 } }, { { FRX, FRX }, { 1.0, 1.0, 1.0 }, { 0.0, 9.0, 0.0 } }, { { FRS, FRS }, { 0.0, 1.0, 0.0 }, { 4.0, 4.0, 4.0 } }, { { 0.0, FRS }, { 0.0, 1.0, 1.0 }, { -4.0, 4.0, 4.0 } }, { { FRX, FRX }, { 1.0, 1.0, 1.0 }, { 0.0, 9.0, 0.0 } }, { { 0.0, FRS }, { 0.0, 1.0, 0.0 }, { -4.0, 4.0, 4.0 } }, { { 0.0, 0.0 }, { 1.0, 1.0, 0.0 }, { -4.0, 4.0, -4.0 } }, { { FRX, FRX }, { 1.0, 1.0, 1.0 }, { 0.0, 9.0, 0.0 } } }; const unsigned char house_idx[] = { // walls 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, // roof 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }; class GLWPrivate { public: QGLBuffer *VBO; QGLBuffer *EBO; QGLShaderProgram prog; int positionAttrib; int colorAttrib; int texcoordsAttrib; int mvpUniform; int textureUniform; int terrain; float pz,rx,ry; QPoint lastMouse; }; GLWidget::GLWidget() { d = new GLWPrivate; d->pz = -140.0f; d->rx = d->ry = 0.0f; d->VBO = d->EBO = 0; startTimer( 10 ); } GLWidget::~GLWidget() { if(d->VBO) delete d->VBO; if(d->EBO) delete d->EBO; delete d; } const char * VS_src = "#version 130\n" "in vec3 position; in vec3 color; uniform mat4 mvp; out vec3 c;" "in vec2 tc_in; out vec2 coord;" "void main()" "{" "gl_Position = mvp*vec4(position,1);" "c = color;" "coord = tc_in;" "}"; const char * FS_src = "#version 130\n" "in vec3 c;" //"out vec4 gl_FragColor;" "in vec2 coord; uniform sampler2D tex;" "void main()" "{" // "gl_FragColor = vec4(c,1);" // "gl_FragColor = mix( texture(tex, coord), vec4(c,1), 0.5);" // "gl_FragColor = vec4(c,1) - texture(tex, coord);" "gl_FragColor = vec4(c,1) * texture(tex, coord);" "}"; //initialization of OpenGL void GLWidget::initializeGL() { bool test = 1; test &= d->prog.addShaderFromSourceCode(QGLShader::Vertex,VS_src); test &= d->prog.addShaderFromSourceCode(QGLShader::Fragment,FS_src); test &= d->prog.link(); if(!test) std::cout << "OUCH!" << std::endl; d->positionAttrib = d->prog.attributeLocation("position"); d->colorAttrib = d->prog.attributeLocation("color"); d->texcoordsAttrib = d->prog.attributeLocation("tc_in"); d->mvpUniform = d->prog.uniformLocation("mvp"); d->textureUniform = d->prog.uniformLocation("tex"); if(d->positionAttrib == -1 || d->colorAttrib == -1 || d->mvpUniform == -1) std::cout << "Bad attribs!" << std::endl; QGLBuffer &VBO = *(d->VBO = new QGLBuffer(QGLBuffer::VertexBuffer)); VBO.create(); VBO.bind(); VBO.allocate(sizeof(house_vert)); VBO.write(0,house_vert,sizeof(house_vert)); QGLBuffer &EBO = *(d->EBO = new QGLBuffer(QGLBuffer::IndexBuffer)); EBO.create(); EBO.bind(); EBO.allocate(sizeof(house_idx)); EBO.write(0,house_idx,sizeof(house_idx)); QImage texture; texture.load("terrain.png"); d->terrain = bindTexture(texture); glClearColor(0.0f, 0.0f, 0.0f, 0.f); glShadeModel( GL_SMOOTH ); glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); glEnable( GL_TEXTURE_2D ); glEnable( GL_DEPTH_TEST ); } void GLWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); d->prog.bind(); QMatrix4x4 projection; QMatrix4x4 mvp; //projection.ortho(-10,10,-10,10,1,1000); float aspect = (float)width()/(float)height(); projection.perspective(10,aspect,1,1000); mvp = projection; mvp.translate(0,0,d->pz); mvp.rotate(d->ry,1,0,0); mvp.rotate(d->rx,0,1,0); d->prog.setUniformValue(d->mvpUniform,mvp); //glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, d->terrain); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); d->prog.setUniformValue(d->textureUniform,0); d->prog.enableAttributeArray(d->positionAttrib); d->prog.enableAttributeArray(d->colorAttrib); d->prog.enableAttributeArray(d->texcoordsAttrib); d->VBO->bind(); d->prog.setAttributeBuffer(d->texcoordsAttrib, GL_FLOAT, offsetof(Vertex, texcoord), 2, sizeof(Vertex)); d->prog.setAttributeBuffer(d->positionAttrib, GL_FLOAT, offsetof(Vertex, position), 3, sizeof(Vertex)); d->prog.setAttributeBuffer(d->colorAttrib, GL_FLOAT, offsetof(Vertex, color), 3, sizeof(Vertex)); d->EBO->bind(); glDrawElements(GL_TRIANGLES, d->EBO->size(), GL_UNSIGNED_BYTE, NULL); d->prog.release(); } void GLWidget::resizeGL(int width, int height) { glViewport(0, 0, width, height); } void GLWidget::mousePressEvent(QMouseEvent *event) { d->lastMouse = event->pos(); } void GLWidget::mouseMoveEvent(QMouseEvent *event) { int dx = event->x() - d->lastMouse.x(); int dy = event->y() - d->lastMouse.y(); if (event->buttons() & Qt::LeftButton) { d->rx = d->rx + dx; d->ry = d->ry + dy; } d->lastMouse = event->pos(); } void GLWidget::timerEvent(QTimerEvent *event) { updateGL(); }