diff options
Diffstat (limited to 'src/glesrenderer.cpp')
| -rw-r--r-- | src/glesrenderer.cpp | 776 |
1 files changed, 776 insertions, 0 deletions
diff --git a/src/glesrenderer.cpp b/src/glesrenderer.cpp new file mode 100644 index 0000000..7d7339d --- /dev/null +++ b/src/glesrenderer.cpp @@ -0,0 +1,776 @@ +/*************************************************************************** + * Copyright (C) 2008, 2012 by Walter Roth * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "glesrenderer.h" + +#include <math.h> + +//#define DEBUG_GLESRENDERER + +//#ifdef DEBUG_GLESRENDERER +#include "shaderdebugger.h" +//#endif + +#ifdef Q_OS_ANDROID +#ifndef GLES + #define GLES //Android uses GLES 2.0 +#endif +#endif + + +GLESRenderer::GLESRenderer(QObject *parent, + const QString & vShaderFilename, + const QString & fShaderFilename ) + :QObject(parent) +{ + this->m_vShaderFileName = vShaderFilename; + this->m_fShaderFileName = fShaderFilename; + + //flags + m_initialized = false; + m_bound = false; + m_lightingEnabled = false; // flag for lighting + m_colorArrayEnabled = false; + m_invertedMvpMatrixValid = false; //delay matrix inversion until it is really neccessary + m_textureEnabled = false; + + m_lightDirection = QVector3D(1.0,1.0,1.0); //position of directional light + m_pointSize = 4.0; + m_shininess = 200.0; + m_ambientAndDiffuseColor = cl_White; + m_ambientLightBrightness = 0.2; + m_specularColor = cl_White; + + m_vShader = NULL; //vertex shader, render thread + m_fShader = NULL; // fragment shader, render thread + m_renderProgram = NULL;// GUI-Thread + + // Locations of shader variables + //attributes + m_location_aVertex = -1; + m_location_aColor = -1; + m_location_aNormal = -1; + m_location_aTexCoord = -1; + //uniforms + //flags + m_location_uColorArrayEnabled = -1; + m_location_uTextureEnabled = -1; + m_location_uLightingEnabled = -1; + //matrices + m_location_uNormalMatrix = -1; + m_location_uMvpMatrix = -1; + //lighting + m_location_uAmbientAndDiffuseColor = -1; + m_location_uAmbientLightBrightness = -1; + m_location_uSpecularColor = -1; + m_location_uLightDirection = -1; + m_location_uHalfPlaneVector = -1; + //texture + m_location_uTextureSampler = -1; + + //viewport + m_viewportX = 0; + m_viewportY = 0; + m_viewportW = 100; + m_viewportH = 100; + + //clippings + m_fovy = 45.0; + m_aspect = 1.0; + m_nearClip = 1.0; + m_farClip = 10.0; + +} +/** + * @brief GLESRenderer::~GLESRenderer + * We need to delete the shaders here. They can not be added to the child list, because they live in render thread. + */ +GLESRenderer::~GLESRenderer() +{ + if(m_vShader) + delete m_vShader; + if(m_fShader) + delete m_fShader; +} + +/** + * Set modelview matrix. Updates mvpMatrix and normalMatrix too. + * Call setPMatrix first. + */ +void GLESRenderer::setMvMatrix(const QMatrix4x4 newVal) +{ + m_mvMatrix = newVal; + m_normalMatrix = m_mvMatrix.normalMatrix(); //invert and transpose mvMatrix + m_invertedMvpMatrixValid = false; //delay matrix inversion until it is really neccessary + + if(m_bound && (m_location_uNormalMatrix != -1)) + m_renderProgram->setUniformValue(m_location_uNormalMatrix, m_normalMatrix); + + m_mvpMatrix = m_pMatrix * m_mvMatrix; + if(m_bound && (m_location_uMvpMatrix != -1)) + m_renderProgram->setUniformValue(m_location_uMvpMatrix, m_mvpMatrix); +#ifdef DEBUG_GLESRENDERER + ShaderDebugger::debugMatrix4x4(m_mvMatrix, "GLESRenderer uses modelview matrix:"); + ShaderDebugger::debugMatrix3x3(m_normalMatrix, "GLESRenderer uses normal matrix:"); + ShaderDebugger::debugMatrix4x4(m_mvpMatrix, "GLESRenderer uses MVP matrix:"); +#endif +} + +/** + * Sets mvMatrix to a lookAt transformation. + * Call setPMatrix or setPerspective first. + */ +void GLESRenderer::setLookAt(const QVector3D & eye,const QVector3D & center,const QVector3D & up ) +{ + QMatrix4x4 m; + m.setToIdentity(); + m.lookAt(eye, center, up); + setMvMatrix(m); +} + +/** + * Set projection matrix. Call setMvMatrix after this. + */ +void GLESRenderer::setPMatrix(const QMatrix4x4 newVal) +{ + m_pMatrix = newVal; + m_mvpMatrix = m_pMatrix * m_mvMatrix; + if(m_bound && (m_location_uMvpMatrix != -1)) + m_renderProgram->setUniformValue(m_location_uMvpMatrix, m_mvpMatrix); +} + +/** + * Setup projection matrix. Call setMvMatrix after this. + */ +void GLESRenderer::setPerspective(GLfloat fovy, GLfloat aspect, GLfloat nearClip, GLfloat farClip) +{ + m_fovy = fovy; + m_aspect = aspect; + m_nearClip = nearClip; + m_farClip = farClip; + m_pMatrix.setToIdentity(); + m_pMatrix.perspective(m_fovy, m_aspect, m_nearClip, m_farClip); + m_mvpMatrix = m_pMatrix * m_mvMatrix; + if(m_bound && (m_location_uMvpMatrix != -1)) + m_renderProgram->setUniformValue(m_location_uMvpMatrix, m_mvpMatrix); +#ifdef DEBUG_GLESRENDERER + ShaderDebugger::debugMatrix4x4(m_pMatrix, "GLESRenderer uses projection matrix:"); +#endif +} + +void GLESRenderer::setOrtho(float left, float right, float bottom, float top, float nearPlane, float farPlane) +{ + m_fovy = 0.0; + m_aspect = (left - right) / (top - bottom); + m_nearClip = nearPlane; + m_farClip = farPlane; + m_pMatrix.setToIdentity(); + m_pMatrix.ortho(left, right, bottom, top, nearPlane, farPlane); + m_mvpMatrix = m_pMatrix * m_mvMatrix; + if(m_bound && (m_location_uMvpMatrix != -1)) + m_renderProgram->setUniformValue(m_location_uMvpMatrix, m_mvpMatrix); +#ifdef DEBUG_GLESRENDERER + ShaderDebugger::debugMatrix4x4(m_pMatrix, "GLESRenderer uses projection matrix:"); +#endif +} + +/** + * Set viewport + */ +void GLESRenderer::setViewport(int x, int y, int w, int h) +{ + m_viewportX = x; + m_viewportY = y; + m_viewportW = w; + m_viewportH = h; + //qDebug() << "GLESRenderer::setViewport x:" << x << " y: " << y << " w: " << w << " h: " << h; +} + +/** + * Uses viewport and matrix settings to reverse the vertex transformation chain. + * WinX, winY, winZ are the coordinates in window coordinates. Lower left of viewport + * is winX = 0, winY = 0. Use winZ = 0.0 for a point on near clipping plane + * and winZ = 1.0 for a point on far clipping plane. + * This function assumes, that the vertex shader computes gl_positon as v * mvpMatrix. + * Use a custom shader reverse function, if this is not true. + * Returns coordinate in object space. + */ +QVector3D GLESRenderer::unProjectViewportPoint(const QVector3D & vWin) +{ + QVector3D vClip = viewportToClip(vWin); + if(!m_invertedMvpMatrixValid) + { + m_invertedMvpMatrix = m_mvpMatrix.inverted(); + m_invertedMvpMatrixValid = true; + } + ShaderDebugger::debugMatrix4x4(m_mvpMatrix, "MVP Matrix:"); + ShaderDebugger::debugMatrix4x4(m_invertedMvpMatrix, "Inverted MVP Matrix:"); + QVector3D result = m_invertedMvpMatrix * vClip; + ShaderDebugger::debugVector3D(result, "Vector in model space:"); + return result; +} + +/** + * Performs inverse viewport transform. + */ +QVector3D GLESRenderer::viewportToClip(const QVector3D & vWin) +{ + //reverse viewport transformation, for original code see below + float xClip = (vWin.x() - (float)m_viewportX) / (float)m_viewportW * 2.0 - 1.0; + float yClip = (vWin.y() - (float)m_viewportY) / (float)m_viewportH * 2.0 - 1.0; + float zClip = 2.0 * vWin.z() - 1.0; + + // original code from gluUnproject + //Transformation of normalized coordinates between -1 and 1 + // in[0]=(winx-(float)viewport[0])/(float)viewport[2]*2.0-1.0; + // in[1]=(winy-(float)viewport[1])/(float)viewport[3]*2.0-1.0; + // in[2]=2.0*winz-1.0; + // in[3]=1.0; + + QVector3D result = QVector3D(xClip, yClip, zClip); + ShaderDebugger::debugVector3D(result, "Vector in clip space:"); + return result; +} + +/** + * Returns the points on near and far clipping plane, that correspond to the + * mouseX and mouseY coordinates of a mouse click. + * mouseX and mouseY are coordinates as delivered by QMouseEvent or QDeclarativeMouseEvent. + */ +void GLESRenderer::calculateMousePoints(QVector3D * nearPoint, QVector3D * farPoint, const QPoint & mousePos) +{ + float winX = m_viewportX + mousePos.x(); + float winY = m_viewportY + (m_viewportH - mousePos.y()); + * nearPoint = unProjectViewportPoint(QVector3D(winX, winY, 0.0)); + * farPoint = unProjectViewportPoint(QVector3D(winX, winY, 1.0)); +} + +/** + * Calculate the distance of the "mouse ray line" to point p in model space. + * mouseX, mouseY are the coordinates of the mouse click as delivered by QMouseEvent. + * Returns distance. + */ +float GLESRenderer::distanceToMouseClick(QVector3D p, const QPoint & mousePos) +{ + QVector3D nearPoint, farPoint; + calculateMousePoints(&nearPoint, &farPoint, mousePos); + + QVector3D lineVector = nearPoint - farPoint; + float area = QVector3D::crossProduct(p - nearPoint, lineVector).length(); + float distance = area / lineVector.length(); + + return distance; +} + +/** + * Calculates intersection of "mouse ray line" with the plane defined by normal and d. + * mouseX, mouseY are the coordinates of the mouse click as delivered by QMouseEvent. + * Returns true, if intersection is in the visible frustum, else returns false. + * If return value is true, *intersection is the intersection of the mouse ray line with + * the plane normal*(x,y,z) + d = 0. + * If return value is false, *intersection is not modified. + */ +bool GLESRenderer::mouseIntersection(QVector3D * intersection, QVector3D normal, float d, const QPoint & mousePos) +{ + float m0, m15; + QVector3D pNear, pFar; //mouse intersections on near and far clipping plane + calculateMousePoints(&pNear, &pFar, mousePos); + QVector3D v = pFar - pNear; //vector from near to far clipping plane + m15 = d + QVector3D::dotProduct(normal, pNear); + m0 = QVector3D::dotProduct( normal, v); + if(fabs(m0) < fabs(m15)) //we have no intersection in frustum (lambda will be > 1.0) + { + return false; + } + float lambda = -m15 / m0; + * intersection = pNear + lambda * v; + return true; +} + +/** + * Set the color for ambient and diffuse lighting (or no lighting). + * Alternatively use a color array and color attribute. + */ +void GLESRenderer::setAmbientAndDiffuseColor(const GLColorRgba newVal) +{ + m_ambientAndDiffuseColor = newVal; + if(m_bound && m_location_uAmbientAndDiffuseColor != -1) + m_renderProgram->setUniformValue(m_location_uAmbientAndDiffuseColor, m_ambientAndDiffuseColor); +} + +/** + * Set the dimming factor for ambient light. + * Defaults to 0.2. + */ +void GLESRenderer::setAmbientLightBrightness(float newVal) +{ + m_ambientLightBrightness = newVal; + if(m_bound && m_location_uAmbientLightBrightness != -1) + m_renderProgram->setUniformValue(m_location_uAmbientLightBrightness, m_ambientLightBrightness); +} + +/** + * Set the color for specular lighting. + */ +void GLESRenderer::setSpecularColor(const GLColorRgba newVal) +{ + m_specularColor = newVal; + if(m_bound && (m_location_uSpecularColor != -1)) + m_renderProgram->setUniformValue(m_location_uSpecularColor, + m_specularColor.red(), m_specularColor.green(), + m_specularColor.blue(), m_specularColor.alpha()); +} + +/** + * Set the shininess for specular lighting. + */ +void GLESRenderer::setShininess(float newVal) +{ + m_shininess = newVal; + if(m_bound && (m_location_uShininess != -1)) + m_renderProgram->setUniformValue(m_location_uShininess, m_shininess); +} + +/** + * Enable / disable lighting. + */ +void GLESRenderer::setLightingEnabled(bool newVal) +{ + m_lightingEnabled = newVal; + if(m_bound && (m_location_uLightingEnabled != -1)) + m_renderProgram->setUniformValue(m_location_uLightingEnabled, m_lightingEnabled); +} + +/** + * Enable / disable color array. + */ +void GLESRenderer::setColorArrayEnabled(bool newVal) +{ + m_colorArrayEnabled = newVal; + if(m_bound && (m_location_uColorArrayEnabled != -1)) + m_renderProgram->setUniformValue(m_location_uColorArrayEnabled, m_colorArrayEnabled); +} + +/** + * Set the texture flag. + */ +void GLESRenderer::setTextureEnabled(bool newVal) +{ + m_textureEnabled = newVal; + if(m_bound && (m_location_uTextureEnabled != -1)) + m_renderProgram->setUniformValue(m_location_uTextureEnabled, m_textureEnabled); +} + +/** + * Set light direction. + */ +void GLESRenderer::setLightDirection(const QVector3D & newVal) +{ + m_lightDirection = newVal; +#ifdef DEBUG_GLESRENDERER + ShaderDebugger::debugVector3D(m_lightDirection, "GLESRenderer uses lightDirection in object space:"); +#endif + QMatrix4x4 nMatrix = QMatrix4x4(m_normalMatrix); + m_lightDirection = (nMatrix * m_lightDirection).normalized();//transform to eye space + m_halfPlaneVector = (m_lightDirection + QVector3D(0.0,0.0,1.0)).normalized();//eye direction is 0,0,1 in eye space +#ifdef DEBUG_GLESRENDERER + ShaderDebugger::debugVector3D(m_lightDirection, "GLESRenderer uses lightDirection in eye space:"); + ShaderDebugger::debugVector3D(m_lightDirection, "GLESRenderer uses halfplane vector in eye space:"); +#endif + if(m_bound && (m_location_uLightDirection != -1)) + m_renderProgram->setUniformValue(m_location_uLightDirection, m_lightDirection); + if(m_location_uHalfPlaneVector != -1) + m_renderProgram->setUniformValue(m_location_uHalfPlaneVector, m_halfPlaneVector); +} + +/** + * Set size of points drawn with GL_POINTS. + */ +void GLESRenderer::setPointSize(int newVal) +{ + m_pointSize = newVal; + if(m_bound && (m_location_uPointSize != -1)) + m_renderProgram->setUniformValue(m_location_uPointSize, m_pointSize); +#ifndef GLES + glPointSize(m_pointSize); //set point size independent of vertex shader +#endif +} + +/** + * Pops mvMatrix from stack and updates normalMatrix and mvpMatrix. + */ +void GLESRenderer::popMvMatrix() +{ + setMvMatrix(m_mvMatrixStack.pop()); +} + +/** + * Translates mvMatrix by v + */ +void GLESRenderer::translate(const QVector3D & v) +{ + m_mvMatrix.translate(v); + setMvMatrix(m_mvMatrix); //update normalMatrix and mvpMatrix and copy to shader +} + +/** + * Rotates mvMatrix by angle around axis + */ +void GLESRenderer::rotate(GLfloat angle, const QVector3D & axis) +{ + m_mvMatrix.rotate(angle, axis); + setMvMatrix(m_mvMatrix); //update normalMatrix and mvpMatrix and copy to shader +} + +void GLESRenderer::addTransformation(const QMatrix4x4 additionalTransformation) +{ + setMvMatrix(m_mvMatrix * additionalTransformation); //update normalMatrix and mvpMatrix and copy to shader +} + +/** + * Scales mvMatrix. + */ +void GLESRenderer::scale(const QVector3D & v ) +{ + m_mvMatrix.scale(v); + setMvMatrix(m_mvMatrix);//update normalMatrix and mvpMatrix and copy to shader +} + +void GLESRenderer::rotate( float angle, float x, float y, float z ) { + m_mvMatrix.rotate ( angle, x, y, z ); + setMvMatrix( m_mvMatrix ); +} /* ----- end of method mvRotate ----- */ + +void GLESRenderer::zoom( float zoomFactor ) { + // Es muss vor dem Zoom die Einheitsmatrix generiert werden. Ansonsten wird das vorherige Zoomen dazu addiert + m_pMatrix.setToIdentity(); + m_pMatrix.perspective ( m_fovy * zoomFactor, m_aspect, m_nearClip, m_farClip ); + // Auch hier muss die ProjectionModelView Matrix neu berechnet werden + m_mvpMatrix = m_pMatrix * m_mvMatrix; +} + + +void GLESRenderer::translate( float x, float y, float z ) { + m_mvMatrix.translate( x, y, z ); + setMvMatrix( m_mvMatrix); +} /* ----- end of method translate ----- */ + + +/** + * Compile shaders, get attribute and uniform locations. + * This function needs an active OpenGL context. + */ +bool GLESRenderer::initialize() +{ + if(m_initialized) + return true; + //Setup shaders and program + m_vShader = new QOpenGLShader(QOpenGLShader::Vertex,this); //vertex shader + m_vShader->compileSourceFile(m_vShaderFileName); + if(!m_vShader->isCompiled()) + { + qDebug("GLESRenderer::initialize: Compiling vertex shader failed. Log follows:\n%s", + qPrintable(m_vShader->log())); + return false; + } + m_fShader = new QOpenGLShader(QOpenGLShader::Fragment,this); // fragment shader + m_fShader->compileSourceFile(m_fShaderFileName); + if(!m_fShader->isCompiled()) + { + qDebug("GLESRenderer::initialize: Compiling fragment shader failed. Log follows:\n%s", + qPrintable(m_fShader->log())); + return false; + } + + m_renderProgram = new QOpenGLShaderProgram(this); + m_renderProgram->addShader(m_vShader); + m_renderProgram->addShader(m_fShader); + m_renderProgram->link(); + if(!m_renderProgram->isLinked()) + { + qDebug("GLESRenderer::initialize: Linking program failed. Log follows:\n%s", + qPrintable(m_renderProgram->log())); + return false; + } + + // Get all locations of shader variables + //Get locations of attributes and uniforms + //Non existing attributes and uniforms will return -1 + //Attributes + m_location_aVertex = m_renderProgram->attributeLocation("a_Vertex"); + m_location_aColor = m_renderProgram->attributeLocation("a_Color"); + m_location_aNormal = m_renderProgram->attributeLocation("a_Normal"); + m_location_aTexCoord = m_renderProgram->attributeLocation("a_TexCoord"); + //Uniforms + //flags + m_location_uLightingEnabled = m_renderProgram->uniformLocation("u_LightingEnabled"); + m_location_uColorArrayEnabled = m_renderProgram->uniformLocation("u_ColorArrayEnabled"); + m_location_uTextureEnabled = m_renderProgram->uniformLocation("u_TextureEnabled"); + //matrices + m_location_uNormalMatrix = m_renderProgram->uniformLocation("u_NormalMatrix"); + m_location_uMvpMatrix = m_renderProgram->uniformLocation("u_MvpMatrix"); + //lighting + m_location_uAmbientAndDiffuseColor = m_renderProgram->uniformLocation("u_AmbientAndDiffuseColor"); + m_location_uAmbientLightBrightness = m_renderProgram->uniformLocation("u_AmbientLightBrightness"); + m_location_uLightDirection = m_renderProgram->uniformLocation("u_LightDirection"); + m_location_uSpecularColor = m_renderProgram->uniformLocation("u_SpecularColor"); + m_location_uShininess = m_renderProgram->uniformLocation("u_Shininess"); + m_location_uHalfPlaneVector = m_renderProgram->uniformLocation("u_HalfPlaneVector"); + //texture + m_location_uTextureSampler = m_renderProgram->uniformLocation("s_Texture"); + //point size + m_location_uPointSize = m_renderProgram->uniformLocation("u_PointSize"); + +#ifdef DEBUG_GLESRENDERER + ShaderDebugger::setEnabled(true); + ShaderDebugger::debugUniforms(m_renderProgram->programId()); + ShaderDebugger::setEnabled(false); +#endif + + //get present viewport settings + readGLViewportSettings(); + m_initialized = true; + return true; +} + +/** + * Bind program and transfer attribute and uniform data to the shaders. + * Calls initialize, if not already initialized. + */ +bool GLESRenderer::bind() +{ + bool ok = true; + if(!m_initialized) + ok = initialize(); + if(!ok) + return false; + m_renderProgram->bind(); + //Activate uniforms + //flags + if(m_location_uColorArrayEnabled != -1) + m_renderProgram->setUniformValue(m_location_uColorArrayEnabled, m_colorArrayEnabled); + if(m_location_uLightingEnabled != -1) + m_renderProgram->setUniformValue(m_location_uLightingEnabled, m_lightingEnabled); + if(m_location_uTextureEnabled != -1) + m_renderProgram->setUniformValue(m_location_uTextureEnabled, m_textureEnabled); + //matrices + if( m_location_uNormalMatrix != -1) + m_renderProgram->setUniformValue(m_location_uNormalMatrix, m_normalMatrix); + if(m_location_uMvpMatrix != -1) + m_renderProgram->setUniformValue(m_location_uMvpMatrix, m_mvpMatrix); + //lighting + if(m_location_uAmbientAndDiffuseColor != -1) + m_renderProgram->setUniformValue(m_location_uAmbientAndDiffuseColor, + m_ambientAndDiffuseColor.red(), m_ambientAndDiffuseColor.green(), + m_ambientAndDiffuseColor.blue(), m_ambientAndDiffuseColor.alpha()); + if(m_location_uAmbientLightBrightness != -1) + m_renderProgram->setUniformValue(m_location_uAmbientLightBrightness, m_ambientLightBrightness); + if(m_location_uLightDirection != -1) + m_renderProgram->setUniformValue(m_location_uLightDirection, m_lightDirection); + if(m_location_uSpecularColor != -1) + m_renderProgram->setUniformValue(m_location_uSpecularColor, + m_specularColor.red(), m_specularColor.green(), + m_specularColor.blue(), m_specularColor.alpha()); + if(m_location_uShininess != -1) + m_renderProgram->setUniformValue(m_location_uShininess, m_shininess); + if(m_location_uHalfPlaneVector != -1) + m_renderProgram->setUniformValue(m_location_uHalfPlaneVector, m_halfPlaneVector); + //texture + if(m_location_uTextureSampler != -1) + m_renderProgram->setUniformValue(m_location_uTextureSampler, 0); //set sampler to use texture unit 0 + //point size + if(m_location_uPointSize != -1) + m_renderProgram->setUniformValue(m_location_uPointSize, m_pointSize); +#ifndef GLES + glPointSize(m_pointSize); //set point size independent of vertex shader +#endif + + m_renderProgram->setUniformValue("u_viewPortCenter", + QVector2D(m_viewportW / 2, m_viewportH /2)); + GLfloat diameterSquare = 200.0 * 200.0; + m_renderProgram->setUniformValue("u_diameterSquare", diameterSquare); + + + m_bound = true; + return m_bound; +} + +/** + * Enables Vertex, normal, color or texCoord arrays and sets start adresses of arrays + * arrayLocation may be: VERTEX_LOCATION, NORMAL_LOCATION, COLOR_LOCATION, TEXCOORD_LOCATION + */ +bool GLESRenderer::activateAttributeArray (AttributeLocation arrayLocation, const QVector2D *values, int stride ) +{ + return activateAttributeArray(arrayLocation, (float*)values, 2, stride); +} +/** + * Enables Vertex, normal, color or texCoord arrays and sets start adresses of arrays + * arrayLocation may be: VERTEX_LOCATION, NORMAL_LOCATION, COLOR_LOCATION, TEXCOORD_LOCATION + */ +bool GLESRenderer::activateAttributeArray (AttributeLocation arrayLocation, const QVector3D *values, int stride ) +{ + return activateAttributeArray(arrayLocation, (float*)values, 3, stride); +} +/** + * Enables Vertex, normal, color or texCoord arrays and sets start adresses of arrays + * arrayLocation may be: VERTEX_LOCATION, NORMAL_LOCATION, COLOR_LOCATION, TEXCOORD_LOCATION + */ +bool GLESRenderer::activateAttributeArray (AttributeLocation arrayLocation, const QVector4D *values, int stride ) +{ + return activateAttributeArray(arrayLocation, (float*)values, 4, stride); +} + +/** + * Enables Vertex, normal, color or texCoord arrays and sets start adresses of arrays + * arrayLocation may be: VERTEX_LOCATION, NORMAL_LOCATION, COLOR_LOCATION, TEXCOORD_LOCATION + */ +bool GLESRenderer::activateAttributeArray (AttributeLocation arrayLocation, const float * values, int tupleSize, int stride ) +{ + int location = -1; + switch(arrayLocation){ + case VERTEX_LOCATION: location = m_location_aVertex; break; + case NORMAL_LOCATION: location = m_location_aNormal; break; + case COLOR_LOCATION : location = m_location_aColor; break; + case TEXCOORD_LOCATION : location = m_location_aTexCoord; break; + default: return false; + } + + if(values && (location != -1)) + { + m_renderProgram->enableAttributeArray(location); + m_renderProgram->setAttributeArray(location, values, tupleSize, stride); + m_activeAttributeLocations.append(location); + return true; + } + else return false; +} + +///** +// * Enables Vertex, normal, color or texCoord arrays and sets start adresses of arrays +// * Type may be: VERTEX_LOCATION, COLOR_LOCATION +// */ +//bool GLESRenderer::activateAttributeArray (AttributeLocation arrayLocation, const QVector4D * values, int stride ) +//{ +// if(!m_initialized) +// return false; +// int location = -1; +// switch(arrayLocation){ +// case VERTEX_LOCATION: location = m_location_aVertex; break; +// case COLOR_LOCATION : location = m_location_aColor; break; +// default: return false; +// } + +// if(values && (location != -1)) +// { +// m_renderProgram->enableAttributeArray(location); +// m_renderProgram->setAttributeArray(location, GL_FLOAT, values, 4, stride); +// m_activeAttributeLocations.append(location); +// return true; +// } +// else return false; +//} + +bool GLESRenderer::activateAttributeBuffer(GLESRenderer::AttributeLocation bufferLocation, int bufferId, int stride) +{ + int location = -1; + int elements = 3; + int offset = 0; + switch(bufferLocation){ + case VERTEX_LOCATION: location = m_location_aVertex; break; + case NORMAL_LOCATION: location = m_location_aNormal; break; + case COLOR_LOCATION : { + location = m_location_aColor; + elements = 4; //RGBA colors + }break; + case TEXCOORD_LOCATION : location = m_location_aTexCoord; break; + default: return false; + } + if( bufferId != 0 ) { + m_renderProgram->setAttributeBuffer(location, GL_FLOAT, offset, elements, stride); + m_renderProgram->enableAttributeArray( location ); + return true; + } + else { + qDebug() << "GLESRenderer::activateAttributeBuffer: Error, invalid buffer id"; + return false; + } +} + +/** + * Disables all enabled attribute arrays. + */ +void GLESRenderer::disableAttributeArrays() +{ + for(int i = 0; i < m_activeAttributeLocations.size(); i++) + m_renderProgram->disableAttributeArray(m_activeAttributeLocations[i]); + m_activeAttributeLocations.clear(); +} + +/** + * Releases program. To be called, when all rendering is finished. + */ +void GLESRenderer::release() +{ + disableAttributeArrays(); + if(m_renderProgram) + m_renderProgram->release(); + else qDebug() << "GLESRenderer::release() called without valid render program."; + m_bound = false; +} + +/** + * get the present settings from GL engine + */ +void GLESRenderer::readGLViewportSettings() +{ + GLint vp[4]; + glGetIntegerv(GL_VIEWPORT, vp); + m_viewportX = vp[0]; + m_viewportY = vp[1]; + m_viewportW = vp[2]; + m_viewportH = vp[3]; +} + +/** + * Multiplies current mvp matrix with v. Mainly for debugging. + */ +QVector3D GLESRenderer::modelToClip(const QVector3D & v) +{ + ShaderDebugger::debugVector3D(v, "Vector in model space:"); + QVector3D result = m_mvpMatrix * v; + ShaderDebugger::debugVector3D(result, "Vector in clip space:"); + return result; +} + +/** + * Performs viewport transform. Mainly for debugging. + */ +QVector3D GLESRenderer::clipToViewport(const QVector3D & v) +{ + float ox = (m_viewportX + m_viewportW) / 2.0; + float oy = (m_viewportY + m_viewportH) / 2.0; + ShaderDebugger::debugVector3D(v, "Vector in clip space:"); + float xw = (m_viewportW / 2.0) * v.x() + ox; + float yw = (m_viewportH / 2.0) * v.y() + oy; + float zw = ((m_farClip - m_nearClip) / 2.0) * v.z() + (m_nearClip + m_farClip) / 2.0; + QVector3D result = QVector3D(xw, yw, zw); + ShaderDebugger::debugVector3D(result, "Vector in viewport space:"); + return result; +} + + |
