Sophie

Sophie

distrib > Mageia > 7 > armv7hl > media > core-release > by-pkgid > 0a1223a3e4bb8a61fd0c6bd9fadbd0af > files > 205

qtcanvas3d5-doc-5.12.2-2.mga7.noarch.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- textureandlight.qdoc -->
  <title>Lit and Textured Cube Example | Qt Canvas 3D (deprecated) 5.12.2</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td >Qt 5.12</td><td ><a href="qtcanvas3d-index.html">Qt Canvas 3D (deprecated)</a></td><td ><a href="qtcanvas3d-examples.html">Qt Canvas 3D Examples</a></td><td >Lit and Textured Cube Example</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtcanvas3d-index.html">Qt 5.12.2 Reference Documentation</a></td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#qt-quick-implementation">Qt Quick Implementation</a></li>
<li class="level2"><a href="#creating-canvas3d">Creating Canvas3D</a></li>
<li class="level2"><a href="#importing-the-javascript-file">Importing the JavaScript File</a></li>
<li class="level1"><a href="#javascript-implementation">JavaScript Implementation</a></li>
<li class="level2"><a href="#matrix-library">Matrix Library</a></li>
<li class="level2"><a href="#initializegl-function">initializeGL Function</a></li>
<li class="level2"><a href="#paintgl-function">paintGL Function</a></li>
<li class="level1"><a href="#logging">Logging</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Lit and Textured Cube Example</h1>
<span class="subtitle"></span>
<!-- $$$textureandlight-brief -->
<p>A simple cube with texturing and lighting.</p>
<!-- @@@textureandlight -->
<!-- $$$textureandlight-description -->
<div class="descr"> <a name="details"></a>
<p>The Lit and Textured Cube example goes through the basics of using Qt Canvas 3D.</p>
<p class="centerAlign"><img src="images/textureandlight-example.png" alt="" /></p><a name="qt-quick-implementation"></a>
<h2 id="qt-quick-implementation">Qt Quick Implementation</h2>
<a name="creating-canvas3d"></a>
<h3 >Creating Canvas3D</h3>
<p>In <a href="qtcanvas3d-textureandlight-qml-textureandlight-main-qml.html">main.qml</a>, we add a Canvas3D under the root <code>Item</code>:</p>
<pre class="qml">

  Canvas3D {
      id: canvas3d
      anchors.fill:parent
      ...

</pre>
<p>Inside it, we catch the <code>initializeGL</code> and <code>paintGL</code> signals to forward the initialization and rendering calls to the js object:</p>
<pre class="qml">

  // Emitted when one time initializations should happen
  onInitializeGL: {
      GLCode.initializeGL(canvas3d);
  }

  // Emitted each time Canvas3D is ready for a new frame
  onPaintGL: {
      GLCode.paintGL(canvas3d);
  }

</pre>
<a name="importing-the-javascript-file"></a>
<h3 >Importing the JavaScript File</h3>
<p>We import the JavaScript file in the QML:</p>
<pre class="qml">

  import "textureandlight.js" as GLCode

</pre>
<p>In the <code>initializeGL</code> function of the JavaScript, we initialize the OpenGL state. We also create the TextureImage and register handlers for image load success and fail signals. If the load succeeds, the OpenGL texture is created and filled with pixel data from the loaded image.</p>
<a name="javascript-implementation"></a>
<h2 id="javascript-implementation">JavaScript Implementation</h2>
<a name="matrix-library"></a>
<h3 >Matrix Library</h3>
<p>In <a href="qtcanvas3d-textureandlight-qml-textureandlight-textureandlight-js.html">textureandlight.js</a>, we first include a fast matrix library. Using this makes it a lot easier to handle 3D math operations such as matrix transformations:</p>
<pre class="js">

  Qt.include("gl-matrix.js")

</pre>
<a name="initializegl-function"></a>
<h3 >initializeGL Function</h3>
<p>Let's take a closer look at the <code>initializeGL</code> function. It is called by Canvas3D once the render node is ready.</p>
<p>First of all, we need to get a Context3D from our Canvas3D. We want a context that supports depth buffer and antialising:</p>
<pre class="js">

  // Get the OpenGL context object that represents the API we call
  gl = canvas.getContext("canvas3d", {depth:true, antialias:true, alpha:false});

</pre>
<p>Then we initialize the OpenGL state for the context:</p>
<pre class="js">

  // Setup the OpenGL state
  gl.enable(gl.DEPTH_TEST);
  gl.depthFunc(gl.LESS);
  gl.enable(gl.CULL_FACE);
  gl.cullFace(gl.BACK);
  gl.clearColor(0.98, 0.98, 0.98, 1.0);
  gl.clearDepth(1.0);
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);

</pre>
<p>Next, let's take a look into shader initialization in the <code>initShaders</code> function, which we call in <code>initializeGL</code>. First we define the vertex shader:</p>
<pre class="js">

  var vertexShader = getShader(gl,
                               "attribute highp vec3 aVertexNormal;    \
                                attribute highp vec3 aVertexPosition;  \
                                attribute highp vec2 aTextureCoord;    \
                                                                       \
                                uniform highp mat4 uNormalMatrix;      \
                                uniform mat4 uMVMatrix;                \
                                uniform mat4 uPMatrix;                 \
                                                                       \
                                varying mediump vec4 vColor;           \
                                varying highp vec2 vTextureCoord;      \
                                varying highp vec3 vLighting;          \
                                                                       \
                                void main(void) {                      \
                                    gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); \
                                    vTextureCoord = aTextureCoord;                                   \
                                    highp vec3 ambientLight = vec3(0.5, 0.5, 0.5);                   \
                                    highp vec3 directionalLightColor = vec3(0.75, 0.75, 0.75);       \
                                    highp vec3 directionalVector = vec3(0.85, 0.8, 0.75);            \
                                    highp vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0); \
                                    highp float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0); \
                                    vLighting = ambientLight + (directionalLightColor * directional); \
                                }", gl.VERTEX_SHADER);

</pre>
<p>We follow that up by defining a fragment shader:</p>
<pre class="js">

  var fragmentShader = getShader(gl,
                                 "varying highp vec2 vTextureCoord;  \
                                  varying highp vec3 vLighting;      \
                                                                     \
                                  uniform sampler2D uSampler;        \
                                                                     \
                                  void main(void) {                  \
                                      mediump vec3 texelColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)).rgb; \
                                      gl_FragColor = vec4(texelColor * vLighting, 1.0);                                      \
                                  }", gl.FRAGMENT_SHADER);

</pre>
<p>Then we need to create the shader program (Canvas3DProgram), attach the shaders to it, and then link and use the program:</p>
<pre class="js">

  // Create the Canvas3DProgram for shader
  var shaderProgram = gl.createProgram();

  // Attach the shader sources to the shader program
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);

  // Link the program
  gl.linkProgram(shaderProgram);

  // Check the linking status
  if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
      console.log("Could not initialise shaders");
      console.log(gl.getProgramInfoLog(shaderProgram));
  }

  // Take the shader program into use
  gl.useProgram(shaderProgram);

</pre>
<p>And finally, look up and store the vertex attributes and uniform locations:</p>
<pre class="js">

  // Look up where the vertex data needs to go
  vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
  gl.enableVertexAttribArray(vertexPositionAttribute);
  textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
  gl.enableVertexAttribArray(textureCoordAttribute);
  vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
  gl.enableVertexAttribArray(vertexNormalAttribute);

  // Get the uniform locations
  pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
  mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
  nUniform = gl.getUniformLocation(shaderProgram, "uNormalMatrix");

  // Setup texture sampler uniform
  var textureSamplerUniform = gl.getUniformLocation(shaderProgram, "uSampler")
  gl.activeTexture(gl.TEXTURE0);
  gl.uniform1i(textureSamplerUniform, 0);
  gl.bindTexture(gl.TEXTURE_2D, 0);

</pre>
<p>After initializing the shader program, we set up the vertex buffer in <code>initBuffers</code> function. Let's look at the vertex index buffer creation as an example:</p>
<pre class="js">

  var cubeVertexIndexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
                new Uint16Array([
                                          0,  1,  2,      0,  2,  3,    // front
                                          4,  5,  6,      4,  6,  7,    // back
                                          8,  9,  10,     8,  10, 11,   // top
                                          12, 13, 14,     12, 14, 15,   // bottom
                                          16, 17, 18,     16, 18, 19,   // right
                                          20, 21, 22,     20, 22, 23    // left
                                      ]),
                gl.STATIC_DRAW);

</pre>
<p>Above, first we create the buffer, then bind it and finally insert the data into it. Other buffers are all handled in a similar fashion.</p>
<p>As the final step in <code>initializeGL</code>, we create a texture image from TextureImageFactory, and register handlers for <code>imageLoaded</code> and <code>imageLoadingFailed</code> signals. Once the texture image is successfully loaded, we create the actual texture:</p>
<pre class="js">

  qtLogoImage.imageLoaded.connect(function() {
      console.log("Texture loaded, "+qtLogoImage.src);
      // Create the Canvas3DTexture object
      cubeTexture = gl.createTexture();
      // Bind it
      gl.bindTexture(gl.TEXTURE_2D, cubeTexture);
      // Set the properties
      gl.texImage2D(gl.TEXTURE_2D,    // target
                    0,                // level
                    gl.RGBA,          // internalformat
                    gl.RGBA,          // format
                    gl.UNSIGNED_BYTE, // type
                    qtLogoImage);     // pixels
      // Set texture filtering parameters
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
      // Generate mipmap
      gl.generateMipmap(gl.TEXTURE_2D);
  });

</pre>
<a name="paintgl-function"></a>
<h3 >paintGL Function</h3>
<p><code>paintGL</code> is called by Canvas3D whenever it is ready to receive a new frame. Let's go through the steps that are done in each render cycle.</p>
<p>First we check if canvas has been resized or if pixel ratio has changed, and update the projection matrix if necessary:</p>
<pre class="js">

  var pixelRatio = canvas.devicePixelRatio;
  var currentWidth = canvas.width * pixelRatio;
  var currentHeight = canvas.height * pixelRatio;
  if (currentWidth !== width || currentHeight !== height ) {
      width = currentWidth;
      height = currentHeight;
      gl.viewport(0, 0, width, height);
      mat4.perspective(pMatrix, degToRad(45), width / height, 0.1, 500.0);
      gl.uniformMatrix4fv(pMatrixUniform, false, pMatrix);
  }

</pre>
<p>Then we clear the render area using the clear color set in <code>initializeGL</code>:</p>
<pre class="js">

  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

</pre>
<p>Next we reset the model view matrix and apply translation and rotations:</p>
<pre class="js">

  mat4.identity(mvMatrix);
  mat4.translate(mvMatrix, mvMatrix, [(canvas.yRotAnim - 120.0) / 120.0,
                                      (canvas.xRotAnim -  60.0) / 50.0,
                                      -10.0]);
  mat4.rotate(mvMatrix, mvMatrix, degToRad(canvas.xRotAnim), [0, 1, 0]);
  mat4.rotate(mvMatrix, mvMatrix, degToRad(canvas.yRotAnim), [1, 0, 0]);
  mat4.rotate(mvMatrix, mvMatrix, degToRad(canvas.zRotAnim), [0, 0, 1]);
  gl.uniformMatrix4fv(mvMatrixUniform, false, mvMatrix);

</pre>
<p>As we have a lit cube, we invert and transpose the model view matrix to be used for lighting calculations:</p>
<pre class="js">

  mat4.invert(nMatrix, mvMatrix);
  mat4.transpose(nMatrix, nMatrix);
  gl.uniformMatrix4fv(nUniform, false, nMatrix);

</pre>
<p>And finally we draw the cube:</p>
<pre class="js">

  gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);

</pre>
<a name="logging"></a>
<h2 id="logging">Logging</h2>
<p>Qt Canvas 3D uses Qt's categorized logging feature. This example enables all Qt Canvas 3D log output with the code shown below. For more on Canvas3D's logging features refer to <a href="qtcanvas3d-logging.html">Qt Canvas 3D Logging</a>.</p>
<pre class="cpp">

  <span class="comment">// Uncomment to turn on all the logging categories of Canvas3D</span>
  <span class="comment">//    QString loggingFilter = QString(&quot;qt.canvas3d.info.debug=true\n&quot;);</span>
  <span class="comment">//    loggingFilter += QStringLiteral(&quot;qt.canvas3d.rendering.debug=true\n&quot;)</span>
  <span class="comment">//            + QStringLiteral(&quot;qt.canvas3d.rendering.warning=true\n&quot;)</span>
  <span class="comment">//            + QStringLiteral(&quot;qt.canvas3d.glerrors.debug=true&quot;);</span>
  <span class="comment">//    QLoggingCategory::setFilterRules(loggingFilter);</span>

</pre>
<p>Files:</p>
<ul>
<li><a href="qtcanvas3d-textureandlight-main-cpp.html">textureandlight/main.cpp</a></li>
<li><a href="qtcanvas3d-textureandlight-qml-textureandlight-main-qml.html">textureandlight/qml/textureandlight/main.qml</a></li>
<li><a href="qtcanvas3d-textureandlight-qml-textureandlight-textureandlight-js.html">textureandlight/qml/textureandlight/textureandlight.js</a></li>
<li><a href="qtcanvas3d-textureandlight-textureandlight-pro.html">textureandlight/textureandlight.pro</a></li>
<li><a href="qtcanvas3d-textureandlight-textureandlight-qrc.html">textureandlight/textureandlight.qrc</a></li>
</ul>
<p>Images:</p>
<ul>
<li><a href="images/used-in-examples/textureandlight/qml/textureandlight/qtlogo.png">textureandlight/qml/textureandlight/qtlogo.png</a></li>
</ul>
</div>
<!-- @@@textureandlight -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2019 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>