1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include "cuberenderer.h"
52#include <QOpenGLContext>
53#include <QOpenGLFunctions>
54#include <QOpenGLShaderProgram>
55#include <QOpenGLVertexArrayObject>
56#include <QOpenGLBuffer>
57#include <QOpenGLVertexArrayObject>
58#include <QOffscreenSurface>
59#include <QWindow>
60
61CubeRenderer::CubeRenderer(QOffscreenSurface *offscreenSurface)
62 : m_offscreenSurface(offscreenSurface),
63 m_context(nullptr),
64 m_program(nullptr),
65 m_vbo(nullptr),
66 m_vao(nullptr),
67 m_matrixLoc(0)
68{
69}
70
71CubeRenderer::~CubeRenderer()
72{
73 // Use a temporary offscreen surface to do the cleanup.
74 // There may not be a native window surface available anymore at this stage.
75 m_context->makeCurrent(surface: m_offscreenSurface);
76
77 delete m_program;
78 delete m_vbo;
79 delete m_vao;
80
81 m_context->doneCurrent();
82 delete m_context;
83}
84
85void CubeRenderer::init(QWindow *w, QOpenGLContext *share)
86{
87 m_context = new QOpenGLContext;
88 m_context->setShareContext(share);
89 m_context->setFormat(w->requestedFormat());
90 m_context->create();
91 if (!m_context->makeCurrent(surface: w))
92 return;
93
94 QOpenGLFunctions *f = m_context->functions();
95 f->glClearColor(red: 0.0f, green: 0.1f, blue: 0.25f, alpha: 1.0f);
96 f->glViewport(x: 0, y: 0, width: w->width() * w->devicePixelRatio(), height: w->height() * w->devicePixelRatio());
97
98 static const char *vertexShaderSource =
99 "attribute highp vec4 vertex;\n"
100 "attribute lowp vec2 coord;\n"
101 "varying lowp vec2 v_coord;\n"
102 "uniform highp mat4 matrix;\n"
103 "void main() {\n"
104 " v_coord = coord;\n"
105 " gl_Position = matrix * vertex;\n"
106 "}\n";
107 static const char *fragmentShaderSource =
108 "varying lowp vec2 v_coord;\n"
109 "uniform sampler2D sampler;\n"
110 "void main() {\n"
111 " gl_FragColor = vec4(texture2D(sampler, v_coord).rgb, 1.0);\n"
112 "}\n";
113 m_program = new QOpenGLShaderProgram;
114 m_program->addCacheableShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertexShaderSource);
115 m_program->addCacheableShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragmentShaderSource);
116 m_program->bindAttributeLocation(name: "vertex", location: 0);
117 m_program->bindAttributeLocation(name: "coord", location: 1);
118 m_program->link();
119 m_matrixLoc = m_program->uniformLocation(name: "matrix");
120
121 m_vao = new QOpenGLVertexArrayObject;
122 m_vao->create();
123 QOpenGLVertexArrayObject::Binder vaoBinder(m_vao);
124
125 m_vbo = new QOpenGLBuffer;
126 m_vbo->create();
127 m_vbo->bind();
128
129 GLfloat v[] = {
130 -0.5, 0.5, 0.5, 0.5,-0.5,0.5,-0.5,-0.5,0.5,
131 0.5, -0.5, 0.5, -0.5,0.5,0.5,0.5,0.5,0.5,
132 -0.5, -0.5, -0.5, 0.5,-0.5,-0.5,-0.5,0.5,-0.5,
133 0.5, 0.5, -0.5, -0.5,0.5,-0.5,0.5,-0.5,-0.5,
134
135 0.5, -0.5, -0.5, 0.5,-0.5,0.5,0.5,0.5,-0.5,
136 0.5, 0.5, 0.5, 0.5,0.5,-0.5,0.5,-0.5,0.5,
137 -0.5, 0.5, -0.5, -0.5,-0.5,0.5,-0.5,-0.5,-0.5,
138 -0.5, -0.5, 0.5, -0.5,0.5,-0.5,-0.5,0.5,0.5,
139
140 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5,
141 -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5,
142 -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5,
143 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5
144 };
145 GLfloat texCoords[] = {
146 0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
147 1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f,
148 1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f,
149 0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f,
150
151 1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f,
152 0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f,
153 0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
154 1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f,
155
156 0.0f,1.0f, 1.0f,0.0f, 1.0f,1.0f,
157 1.0f,0.0f, 0.0f,1.0f, 0.0f,0.0f,
158 1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f,
159 0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f
160 };
161
162 const int vertexCount = 36;
163 m_vbo->allocate(count: sizeof(GLfloat) * vertexCount * 5);
164 m_vbo->write(offset: 0, data: v, count: sizeof(GLfloat) * vertexCount * 3);
165 m_vbo->write(offset: sizeof(GLfloat) * vertexCount * 3, data: texCoords, count: sizeof(GLfloat) * vertexCount * 2);
166 m_vbo->release();
167
168 if (m_vao->isCreated())
169 setupVertexAttribs();
170}
171
172void CubeRenderer::resize(int w, int h)
173{
174 m_proj.setToIdentity();
175 m_proj.perspective(verticalAngle: 45, aspectRatio: w / float(h), nearPlane: 0.01f, farPlane: 100.0f);
176}
177
178void CubeRenderer::setupVertexAttribs()
179{
180 m_vbo->bind();
181 m_program->enableAttributeArray(location: 0);
182 m_program->enableAttributeArray(location: 1);
183 m_context->functions()->glVertexAttribPointer(indx: 0, size: 3, GL_FLOAT, GL_FALSE, stride: 0, ptr: nullptr);
184 m_context->functions()->glVertexAttribPointer(indx: 1, size: 2, GL_FLOAT, GL_FALSE, stride: 0,
185 ptr: (const void *)(36 * 3 * sizeof(GLfloat)));
186 m_vbo->release();
187}
188
189void CubeRenderer::render(QWindow *w, QOpenGLContext *share, uint texture)
190{
191 if (!m_context)
192 init(w, share);
193
194 if (!m_context->makeCurrent(surface: w))
195 return;
196
197 QOpenGLFunctions *f = m_context->functions();
198 f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
199
200 if (texture) {
201 f->glBindTexture(GL_TEXTURE_2D, texture);
202 f->glFrontFace(GL_CW); // because our cube's vertex data is such
203 f->glEnable(GL_CULL_FACE);
204 f->glEnable(GL_DEPTH_TEST);
205
206 m_program->bind();
207 QOpenGLVertexArrayObject::Binder vaoBinder(m_vao);
208 // If VAOs are not supported, set the vertex attributes every time.
209 if (!m_vao->isCreated())
210 setupVertexAttribs();
211
212 static GLfloat angle = 0;
213 QMatrix4x4 m;
214 m.translate(x: 0, y: 0, z: -2);
215 m.rotate(angle: 90, x: 0, y: 0, z: 1);
216 m.rotate(angle, x: 0.5, y: 1, z: 0);
217 angle += 0.5f;
218
219 m_program->setUniformValue(location: m_matrixLoc, value: m_proj * m);
220
221 // Draw the cube.
222 f->glDrawArrays(GL_TRIANGLES, first: 0, count: 36);
223 }
224
225 m_context->swapBuffers(surface: w);
226}
227

source code of qtdeclarative/examples/quick/rendercontrol/cuberenderer.cpp