summaryrefslogtreecommitdiffstats
path: root/src/glesrenderer.h
blob: e5cc723f66ec7c08258f4a4ac36f73f0d427c104 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
/***************************************************************************
 *   Copyright (C) 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.             *
 ***************************************************************************/
#ifndef GLESRENDERER_H
#define GLESRENDERER_H

#include <QOpenGLShaderProgram>
#include <QList>
#include <QStack>

#include "glcolorrgba.h"
#include "gldefines.h"

/** \brief A render program that can be used as a simple replacement for the OpenGL fixed
  * function pipeline.
  * \author Walter Roth, 2014
  *
  * GLESRenderer supports vertex, colors, normals, texCoords, textures and matrix manipulation.
  * It owns a modelview and a projection matrix which can be used like in the old days of OpenGL 1.
  * The vertex shader program needs to stick to the following variable names:
  * attribute highp vec4 a_Vertex;
  * attribute highp vec4 a_Color;
  * attribute highp vec3 a_Normal;
  * attribute highp vec2 a_TexCoord;
  *
  * uniform bool u_ColorArrayEnabled
  * uniform bool u_LightingEnabled;
  * uniform highp mat4 u_MvpMatrix;
  * uniform highp mat3 u_NormalMatrix;
  * uniform highp vec3 u_LightDirection;
  * uniform highp vec4 u_AmbientAndDiffuseColor;
  * uniform highp vec4 u_SpecularColor;
  * uniform highp float u_Shininess;
  * uniform mediump float int u_PointSize;
  *
  * The fragment shader texture variable must have the following name:
  * uniform sampler2d s_Texture;
  *
  * These names are used to determine the locations of the varables in the shaders.
  * If you need more variables, subclass GLESRenderer and add new variable(s) to
  * location_XXX variables. Extend virtual intialize(), bind() and disableAttributeArrays() functions
  * to support the new variable(s).
  *
  * The shader source should be in a separate file (e.g. added to the resources).
  * Example shaders vshader1 and fshader1 emulate a simple fixed-function lighted OpenGL 1 scene.
  *
  * Call initialize, after a valid OpenGL context has been made current.
  * Setup viewing with setViewport, setLookAt and setPerspective.
  * Viewport coordinates must be given as
  * GL-viewport coordinates, where lower left is (0,0).
  * Call bind to bind the program and set the uniform values you need.
  * After this, call activateAttributeLocation to enable the attribute arrays.
  * To change attribute arrays, call disableAttributeArrays and then again activateAttributeLocations.
  * Finally call release.
  *
  * GLESRenderer contains functions for projecting points from modelspace to screen and unprojecting points
  * from screen to model space. These functions use the current matrix settings. Therefore, you have to
  * (re)set the matrices to the values that are used to paint the model, before you call the project and
  * unproject functions.
  *
  * For convenient mouse interaction, GLESRenderer supplies the calculateMousePoints(), distanceToMouseClick()
  * and mouseIntersection() functions. These functions use the unproject functions and therefore do also need
  * valid model painting matrix settings.
  */
class GLESRenderer  : public QObject
{
    Q_OBJECT
public:
    typedef enum{
        VERTEX_LOCATION,
        NORMAL_LOCATION,
        COLOR_LOCATION,
        TEXCOORD_LOCATION
    }AttributeLocation;

    explicit GLESRenderer(QObject *parent,
                          const QString & vShaderFilename = ":/src/vshader.vsh",
                          const QString & fShaderFilename = ":/src/fshader.fsh");

    virtual ~GLESRenderer();

    //=========================================================================
    /**
      * \name Initialization, binding and releasing
      */
    ///@{
    /**
      * Compile shaders, get attribute and uniform locations of shaders.
      * This function needs an active OpenGL context.
      * Returns false, if initialization failed.
      */
    virtual bool initialize();

    /**
      * Bind program and transfer attribute and uniform data to the shaders.
      * Calls initialize, if not alraedy initialized.
      * Returns false, if binding failed.
      */
    virtual bool bind();

    /**
      * Releases program. To be called, when all rendering is finished.
      * Calls disableAttributeArrays and releases program.
      */
    void release();
    ///@}

    //=================================================================
    /**
      * \name Unproject, project and mouse interaction functions
      */
    ///@{
    /**
      * Uses viewport and matrix settings to reverse the vertex transformation chain.
      * vWin x,y and z 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 unProjectViewportPoint(const QVector3D & vWin);

    /**
      * Performs inverse viewport transform.
      */
    QVector3D viewportToClip(const QVector3D & v);

    /**
      * 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 calculateMousePoints(QVector3D * nearPoint, QVector3D * farPoint, const QPoint &mousePos );

    /**
      * 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 distanceToMouseClick(QVector3D p, const QPoint &mousePos);

    /**
      * 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 mouseIntersection(QVector3D * intersection, QVector3D normal, float d, const QPoint &mousePos);
    ///@}


    //======================================================================================
    ///@{

      /** Getters and setters for uniforms
       */
    /**
      * Set modelview matrix. Updates mvpMatrix and normalMatrix too.
      * Call setPMatrix or setPerspective first.
      */
    void setMvMatrix(const QMatrix4x4 newVal);
    /**
      * Getter for debugging.
      */
    const QMatrix4x4 & getMvMatrix(){return m_mvMatrix;}
     /**
       * Getter for debugging.
       */
     const QMatrix3x3 & getNormalMatrix(){return m_normalMatrix;}

    /**
      * Sets mvMatrix to a lookAt transformation.
      * Call setPMatrix or setPerspective first.
      */
    void setLookAt(const QVector3D & eye,const QVector3D & center,const QVector3D & up );

    /**
      * Set projection matrix. Call setMvMatrix after this.
      */
    void setPMatrix(const QMatrix4x4 newVal);
    /**
      * Getter for debugging.
      */
    const QMatrix4x4 & getPMatrix(){return m_pMatrix;}
    /**
      * Setup projection matrix. Call setMvMatrix after this.
      */
    void setPerspective(GLfloat fovy, GLfloat aspect, GLfloat nearClip, GLfloat farClip);
    /**
     * @brief setOrtho Set pMatrix to an orthogonal projection.
     * @param left
     * @param right
     * @param bottom
     * @param top
     * @param nearPlane
     * @param farPlane
     */
    void setOrtho(float left, float right, float bottom, float top, float nearPlane, float farPlane);
    /**
      * Set viewport
      * Viewport coordinates must be given as
      * GL-viewport coordinates, where lower left is (0,0).
      */
    void setViewport(int x, int y, int w, int h);
    /**
      * Get the present viewport settings from GL engine
      */
    void readGLViewportSettings();

    /**
      * Set the color for ambient and diffuse lighting (or no lighting).
      * Alternatively use a color array and color attribute.
      * Defaults to white.
      */
    void setAmbientAndDiffuseColor(const GLColorRgba newVal);
    /**
      * Set the dimming factor for ambient light.
      * Defaults to 0.2.
      */
    void setAmbientLightBrightness(float newVal);

    /**
      * Set the color for specular lighting.
      * Defaults to white.
      */
    void setSpecularColor(const GLColorRgba newVal);
    /**
      * Set the shininess (exponent) for specular lighting.
      * Defaults to 200.
      */
    void setShininess(float newVal);

    /**
      * Enable / disable lighting.
      * Defaults to false.
      */
    void setLightingEnabled(bool newVal);
    /**
      * Returns lighting flag.
      */
    bool isLightingEnabled(){return m_lightingEnabled;}
    /**
      * Enable / disable color array.
      * Defaults to false.
      */
    void setColorArrayEnabled(bool newVal);
    /**
      * Returns lighting flag.
      */
    bool isColorArrayEnabled(){return m_colorArrayEnabled;}
    /**
      * Set the texture flag.
      * Defaults to false.
      */
    void setTextureEnabled(bool newVal);
    /**
      * Returns texture flag;
      */
    bool isTextureEnabled(){return m_textureEnabled;}
    /**
      * Set light direction.
      * Defaults to (1.0, 1.0, 1.0)
      */
    void setLightDirection(const QVector3D & newVal);
    /**
      * Getter.
      */
    const QVector3D getLightDirection(){return m_lightDirection;}

    /**
      * Set size of points drawn with GL_POINTS.
      * Defaults to 2.0.
      */
    void setPointSize(int newVal);

    /**
      * Returns pointSize;
      */
    int getPointSize(){return m_pointSize;}

    /**
      * Pushes mvMatrix.
      */
    void pushMvMatrix(){m_mvMatrixStack.push(m_mvMatrix);}

    /**
      * Pops mvMatrix from stack and updates normalMatrix and mvpMatrix.
      */
    void popMvMatrix();

    /**
      * Translates mvMatrix by v
      */
    void translate(const QVector3D & v);
    void translate(float x, float y, float z);
    /**
      * Rotates mvMatrix by angle around axis
      */
    void rotate(GLfloat angle, const QVector3D & axis);    
    /**
      * Rotates mvMatrix by angle around axis (x,y,z)
      */
    void rotate(float angle, float x, float y, float z);
    void zoom(float zoomFactor);

    /**
     * @brief addTransformation
     * Multiplies additionalTransformation to mvMatrix.
     * @param additionalTransformation
     */
    void addTransformation(const QMatrix4x4 additionalTransformation);

    /**
      * Scales mvMatrix.
      */
    void scale(const QVector3D & v );

    ///@}

    //======================================================================================

    ///@{
    /**
      * \name Attribute setters
      */

    /**
      * Enables 2D Vertex, normal, color or texCoord arrays and sets start adresses of arrays
      * Type may be: VERTEX_LOCATION, NORMAL_LOCATION, COLOR_LOCATION, TEXCOORD_LOCATION
      */
    bool activateAttributeArray (AttributeLocation location, const QVector2D * values, int stride = 0 );
    /**
      * Enables 3D Vertex, normal, color or texCoord arrays and sets start adresses of arrays
      * Type may be: VERTEX_LOCATION, NORMAL_LOCATION, COLOR_LOCATION, TEXCOORD_LOCATION
      */
    bool activateAttributeArray (AttributeLocation location, const QVector3D * values, int stride = 0 );
     /**
      * Enables 4D Vertex or color arrays and sets start adresses of arrays
      * Type may be: VERTEX_LOCATION, COLOR_LOCATION
      */
    bool activateAttributeArray (AttributeLocation location, const QVector4D * values, int stride = 0 );
    /**
      * Enables 3D Vertex, normal, color or texCoord buffer
      * location may be: VERTEX_LOCATION, NORMAL_LOCATION, COLOR_LOCATION, TEXCOORD_LOCATION
      * numbersPerElement: 3 for vertex, 2 or 3 for texture, 3 or 4 for color
      */
    bool activateAttributeBuffer (AttributeLocation location, int numbersPerElement, int bufferId);
    /**
      * Disables all enabled attribute arrays.
      * To be called after rendering an object.
      */
    virtual void disableAttributeArrays();
    ///@}

    //==============================================================
    ///@{

    /**
      * \name Debugging
      */

    /**
      * Multiplies current mvp matrix with v. Mainly for debugging.
      */
    QVector3D modelToClip(const QVector3D & v);
    /**
      * Performs viewport transform. Mainly for debugging.
      */
    QVector3D clipToViewport(const QVector3D & v);
    ///@}

protected:

    /**
     * @brief activateAttributeArray
     * Enables  Vertex, normal, color or texCoord arrays and sets start adresses of arrays
     * location may be: VERTEX_LOCATION, NORMAL_LOCATION, COLOR_LOCATION, TEXCOORD_LOCATION
     * @param location
     * @param values Address of first number
     * @param tupleSize Numbers per vertex
     * @param stride Distance to next tuple
     * @return
     */
    bool activateAttributeArray (AttributeLocation location, const float * values, int tupleSize, int stride = 0 );

    bool m_initialized;
    bool m_bound;

    //Uniforms to be passed to the shader
    //flags
    bool m_lightingEnabled; // flag for lighting
    bool m_colorArrayEnabled; //flag for a valid color array
    bool m_textureEnabled; //flag for active texturing
    bool m_invertedMvpMatrixValid; //flag for a valid inverted ModelViewProjection matrix
    //matrices
    QMatrix4x4 m_mvpMatrix; //combined modelview and projection matrix
    //The inverted mvp matrix for unproject purposes
    //Use the invertedMvpMatrixValid flag for calculating it when required.
    QMatrix4x4 m_invertedMvpMatrix;
    QStack <QMatrix4x4>m_mvMatrixStack;
    QMatrix4x4 m_mvMatrix; //modelview matrix
    QMatrix4x4 m_pMatrix;  //projection matrix
    float m_fovy;
    float m_aspect;
    float m_nearClip; //near clipping plane
    float m_farClip;  //far clipping plane
    bool m_OrthoMode;
    QMatrix3x3 m_normalMatrix; //matrix for normal transformation
    //lighting
    QVector3D m_lightDirection; //direction of directional light
    QVector3D m_halfPlaneVector; //half plane vector for specular light calculation
    GLColorRgba m_ambientAndDiffuseColor;
    float m_ambientLightBrightness;
    GLColorRgba m_specularColor;
    float m_shininess;
    //texturing
    int m_pointSize;

    //Shaders and program
    QString m_vShaderFileName; //vertex shader
    QString m_fShaderFileName; //fragment shader
    QOpenGLShader * m_vShader; //vertex shader
    QOpenGLShader * m_fShader; // fragment shader
    QOpenGLShaderProgram * m_renderProgram;

    // Locations of shader variables
    int m_location_aVertex;
    int m_location_aColor;
    int m_location_aNormal;
    int m_location_aTexCoord;
    int m_location_uColorArrayEnabled;
    int m_location_uLightingEnabled;
    int m_location_uNormalMatrix;
    int m_location_uMvpMatrix;
    int m_location_uAmbientAndDiffuseColor;
    int m_location_uAmbientLightBrightness;
    int m_location_uSpecularColor;
    int m_location_uShininess;
    int m_location_uLightDirection;
    int m_location_uHalfPlaneVector;
    int m_location_uPointSize;
    int m_location_uTextureSampler;
    int m_location_uTextureEnabled;

    //The list of enabled attribute locations
    QList<int>m_activeAttributeLocations;
    //viewport
    int m_viewportX;
    int m_viewportY;
    int m_viewportW;
    int m_viewportH;
};

#endif // GLESRENDERER_H