summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Korpipää <tomi.korpipaa@digia.com>2013-04-11 10:20:33 +0300
committerTomi Korpipää <tomi.korpipaa@digia.com>2013-04-11 10:21:00 +0300
commit645e55729f5b1eb40699b426e0828e2fc448b5a4 (patch)
tree6345da16485609ff01f71f24293fd519c5528cde
parent268f96670c05719d14775aeb3c80b58b9421c990 (diff)
Texture stuff added (lots of test hacks still included, to be removed)
Change-Id: Ib6a68df778970a3339ed16cd579f0bd9fa411e0b Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
-rw-r--r--examples/datavis3d/spectrum/spectrum.pro3
-rw-r--r--src/datavis3d/datavis3d.pro2
-rw-r--r--src/datavis3d/engine/engine.qrc3
-rw-r--r--src/datavis3d/engine/q3dbars.cpp36
-rw-r--r--src/datavis3d/engine/shaders/fragmentShaderTexture39
-rw-r--r--src/datavis3d/engine/textures/cube.pngbin0 -> 30341 bytes
-rw-r--r--src/datavis3d/utils/texturehelper.cpp208
-rw-r--r--src/datavis3d/utils/texturehelper_p.h66
-rw-r--r--src/datavis3d/utils/utils.pri2
9 files changed, 325 insertions, 34 deletions
diff --git a/examples/datavis3d/spectrum/spectrum.pro b/examples/datavis3d/spectrum/spectrum.pro
index 747985a9..9a8d45ae 100644
--- a/examples/datavis3d/spectrum/spectrum.pro
+++ b/examples/datavis3d/spectrum/spectrum.pro
@@ -1,3 +1,4 @@
+qtHaveModule(multimedia) {
include(spectrum.pri)
TEMPLATE = subdirs
@@ -9,4 +10,4 @@ SUBDIRS += 3rdparty/fftreal
SUBDIRS += spectrumapp
TARGET = spectrum
-
+}
diff --git a/src/datavis3d/datavis3d.pro b/src/datavis3d/datavis3d.pro
index 43b4642f..b4169c4e 100644
--- a/src/datavis3d/datavis3d.pro
+++ b/src/datavis3d/datavis3d.pro
@@ -1,5 +1,5 @@
TARGET = QtDataVis3D
-QT = core gui #qml
+QT = core gui opengl #qml
DEFINES += QTCOMMERCIALDATAVIS3D_LIBRARY
diff --git a/src/datavis3d/engine/engine.qrc b/src/datavis3d/engine/engine.qrc
index 8e781f05..6803d1b7 100644
--- a/src/datavis3d/engine/engine.qrc
+++ b/src/datavis3d/engine/engine.qrc
@@ -22,4 +22,7 @@
<file alias="fragmentTexture">shaders/fragmentShaderTexture</file>
<file alias="vertexTexture">shaders/vertexShaderTexture</file>
</qresource>
+ <qresource prefix="/textures">
+ <file alias="cubetex">textures/cube.png</file>
+ </qresource>
</RCC>
diff --git a/src/datavis3d/engine/q3dbars.cpp b/src/datavis3d/engine/q3dbars.cpp
index 5965cc37..9a72bd1a 100644
--- a/src/datavis3d/engine/q3dbars.cpp
+++ b/src/datavis3d/engine/q3dbars.cpp
@@ -47,6 +47,7 @@
#include "qdataset_p.h"
#include "shaderhelper_p.h"
#include "objecthelper_p.h"
+#include "texturehelper_p.h"
#include "utils_p.h"
#include <QMatrix4x4>
@@ -85,8 +86,11 @@ void Q3DBars::initialize()
d_ptr->initShaders(QStringLiteral(":/shaders/vertex")
, QStringLiteral(":/shaders/fragment"));
}
- d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertex")
- , QStringLiteral(":/shaders/fragment"));
+ // TODO: Texture test
+ d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture")
+ , QStringLiteral(":/shaders/fragmentTexture"));
+// d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture")
+// , QStringLiteral(":/shaders/fragmentTexture"));
d_ptr->initSelectionShader();
#ifndef USE_HAX0R_SELECTION
@@ -623,11 +627,9 @@ void Q3DBars::drawScene()
// Bind background shader
d_ptr->m_backgroundShader->bind();
- // Texture test
- //glEnable(GL_TEXTURE_2D);
- //GLuint bgrTexture = QGLContext::bindTexture(QImage(":/cube.png"));
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ // TODO: Texture test
+ glEnable(GL_TEXTURE_2D);
+ GLuint bgrTexture = TextureHelper::create2DTexture(QImage(QStringLiteral(":/textures/cubetex")));
// Draw background
if (d_ptr->m_backgroundObj) {
@@ -660,11 +662,11 @@ void Q3DBars::drawScene()
, d_ptr->m_lightStrength);
d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->ambientS()
, d_ptr->m_ambientStrength);
-
- // Bind the texture in texture unit 0
-// glActiveTexture(GL_TEXTURE0);
-// glBindTexture(GL_TEXTURE_2D, bgrTexture);
-// glUniform1i(d_ptr->m_backgroundShader->texture(), 0);
+ // TODO: Texture test
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, bgrTexture);
+ d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->texture()
+ , 0);
// 1st attribute buffer : vertices
glEnableVertexAttribArray(d_ptr->m_backgroundShader->posAtt());
@@ -678,6 +680,7 @@ void Q3DBars::drawScene()
glVertexAttribPointer(d_ptr->m_backgroundShader->normalAtt()
, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
+ // TODO: Texture test
// 3rd attribute buffer : UVs
glEnableVertexAttribArray(d_ptr->m_backgroundShader->uvAtt());
glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_backgroundObj->uvBuf());
@@ -695,11 +698,18 @@ void Q3DBars::drawScene()
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- //glDisableVertexAttribArray(d_ptr->m_backgroundShader->uvAtt());
+ // TODO: Texture test
+ glDisableVertexAttribArray(d_ptr->m_backgroundShader->uvAtt());
+
glDisableVertexAttribArray(d_ptr->m_backgroundShader->normalAtt());
glDisableVertexAttribArray(d_ptr->m_backgroundShader->posAtt());
}
+ // TODO: Texture test
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &bgrTexture);
+ glDisable(GL_TEXTURE_2D);
+
// Release background shader
d_ptr->m_backgroundShader->release();
diff --git a/src/datavis3d/engine/shaders/fragmentShaderTexture b/src/datavis3d/engine/shaders/fragmentShaderTexture
index f1b11908..9f2692f2 100644
--- a/src/datavis3d/engine/shaders/fragmentShaderTexture
+++ b/src/datavis3d/engine/shaders/fragmentShaderTexture
@@ -10,24 +10,25 @@ uniform highp float lightStrength;
uniform highp float ambientStrength;
uniform sampler2D textureSampler;
void main() {
- highp vec3 materialDiffuseColor = texture2D(textureSampler, UV);
- highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
- highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
- highp float distance = length(lightPosition_wrld - position_wrld);
- highp vec3 n = normalize(normal_cmr);
- highp vec3 l = normalize(lightDirection_cmr);
- highp float cosTheta = dot(n, l);
- if (cosTheta < 0.0) { cosTheta = 0.0; }
- if (cosTheta > 1.0) { cosTheta = 1.0; }
- highp vec3 E = normalize(eyeDirection_cmr);
- highp vec3 R = reflect(-l, n);
- highp float cosAlpha = dot(E, R);
- if (cosAlpha < 0.0) { cosAlpha = 0.0; }
- if (cosAlpha > 1.0) { cosAlpha = 1.0; }
- gl_FragColor.rgb = //color_mdl + color_mdl * vec3(cosTheta * cosTheta) / (distance * distance) + vec3(cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / (distance * distance);
- materialAmbientColor +
- materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance +
- materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance;//(distance * distance);
- gl_FragColor.a = 1.0;
+ //highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb;
+ //highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
+ //highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
+ //highp float distance = length(lightPosition_wrld - position_wrld);
+ //highp vec3 n = normalize(normal_cmr);
+ //highp vec3 l = normalize(lightDirection_cmr);
+ //highp float cosTheta = dot(n, l);
+ //if (cosTheta < 0.0) { cosTheta = 0.0; }
+ //if (cosTheta > 1.0) { cosTheta = 1.0; }
+ //highp vec3 E = normalize(eyeDirection_cmr);
+ //highp vec3 R = reflect(-l, n);
+ //highp float cosAlpha = dot(E, R);
+ //if (cosAlpha < 0.0) { cosAlpha = 0.0; }
+ //if (cosAlpha > 1.0) { cosAlpha = 1.0; }
+ //gl_FragColor.rgb = //color_mdl + color_mdl * vec3(cosTheta * cosTheta) / (distance * distance) + vec3(cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / (distance * distance);
+ // materialAmbientColor +
+ // materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance +
+ // materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance;//(distance * distance);
+ //gl_FragColor.a = 1.0;
+ gl_FragColor = texture2D(textureSampler, UV);
}
diff --git a/src/datavis3d/engine/textures/cube.png b/src/datavis3d/engine/textures/cube.png
new file mode 100644
index 00000000..42c8c51b
--- /dev/null
+++ b/src/datavis3d/engine/textures/cube.png
Binary files differ
diff --git a/src/datavis3d/utils/texturehelper.cpp b/src/datavis3d/utils/texturehelper.cpp
new file mode 100644
index 00000000..395ed1f3
--- /dev/null
+++ b/src/datavis3d/utils/texturehelper.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "texturehelper_p.h"
+
+#include <QImage>
+
+//#include <QDebug>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+GLuint TextureHelper::create2DTexture(const QImage &image, bool useTrilinearFiltering)
+{
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ QImage glTexture = TextureHelper::convertToGLFormat(image);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glTexture.width(), glTexture.height()
+ , 0, GL_RGBA, GL_UNSIGNED_BYTE, glTexture.bits());
+ if (useTrilinearFiltering) {
+// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+// glGenerateMipmap(GL_TEXTURE_2D);
+ } else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return textureId;
+}
+
+GLuint TextureHelper::createCubeMapTexture(const QImage &image, bool useTrilinearFiltering)
+{
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+// glBindTexture(GL_TEXTURE_CUBE_MAP, textureId);
+// QImage glTexture = convertToGLFormat(image);
+// glTexImage2D(GL_TEXTURE_CUBE_MAP, 0, GL_RGB, glTexture.width(), glTexture.height()
+// , 0, GL_RGB, GL_UNSIGNED_BYTE, glTexture.bits());
+// if (useTrilinearFiltering) {
+// glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+// glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+// glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+// } else {
+// glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+// glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+// }
+// glBindTexture(GL_TEXTURE_2D, 0);
+ return textureId;
+}
+
+QImage TextureHelper::convertToGLFormat(const QImage &srcImage)
+{
+ QImage res(srcImage.size(), QImage::Format_ARGB32);
+ convertToGLFormatHelper(res, srcImage.convertToFormat(QImage::Format_ARGB32), GL_RGBA);
+ return res;
+}
+
+void TextureHelper::convertToGLFormatHelper(QImage &dstImage, const QImage &srcImage
+ , GLenum texture_format)
+{
+ Q_ASSERT(dstImage.depth() == 32);
+ Q_ASSERT(srcImage.depth() == 32);
+
+ if (dstImage.size() != srcImage.size()) {
+ int target_width = dstImage.width();
+ int target_height = dstImage.height();
+ qreal sx = target_width / qreal(srcImage.width());
+ qreal sy = target_height / qreal(srcImage.height());
+
+ quint32 *dest = (quint32 *) dstImage.scanLine(0); // NB! avoid detach here
+ uchar *srcPixels = (uchar *) srcImage.scanLine(srcImage.height() - 1);
+ int sbpl = srcImage.bytesPerLine();
+ int dbpl = dstImage.bytesPerLine();
+
+ int ix = int(0x00010000 / sx);
+ int iy = int(0x00010000 / sy);
+
+ quint32 basex = int(0.5 * ix);
+ quint32 srcy = int(0.5 * iy);
+
+ // scale, swizzle and mirror in one loop
+ while (target_height--) {
+ const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl);
+ int srcx = basex;
+ for (int x=0; x<target_width; ++x) {
+ dest[x] = qt_gl_convertToGLFormatHelper(src[srcx >> 16], texture_format);
+ srcx += ix;
+ }
+ dest = (quint32 *)(((uchar *) dest) + dbpl);
+ srcy += iy;
+ }
+ } else {
+ const int width = srcImage.width();
+ const int height = srcImage.height();
+ const uint *p = (const uint*) srcImage.scanLine(srcImage.height() - 1);
+ uint *q = (uint*) dstImage.scanLine(0);
+
+ if (texture_format == GL_BGRA) {
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ // mirror + swizzle
+ for (int i=0; i < height; ++i) {
+ const uint *end = p + width;
+ while (p < end) {
+ *q = ((*p << 24) & 0xff000000)
+ | ((*p >> 24) & 0x000000ff)
+ | ((*p << 8) & 0x00ff0000)
+ | ((*p >> 8) & 0x0000ff00);
+ p++;
+ q++;
+ }
+ p -= 2 * width;
+ }
+ } else {
+ const uint bytesPerLine = srcImage.bytesPerLine();
+ for (int i=0; i < height; ++i) {
+ memcpy(q, p, bytesPerLine);
+ q += width;
+ p -= width;
+ }
+ }
+ } else {
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ for (int i=0; i < height; ++i) {
+ const uint *end = p + width;
+ while (p < end) {
+ *q = (*p << 8) | ((*p >> 24) & 0xff);
+ p++;
+ q++;
+ }
+ p -= 2 * width;
+ }
+ } else {
+ for (int i=0; i < height; ++i) {
+ const uint *end = p + width;
+ while (p < end) {
+ *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
+ p++;
+ q++;
+ }
+ p -= 2 * width;
+ }
+ }
+ }
+ }
+}
+
+QRgb TextureHelper::qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
+{
+ if (texture_format == GL_BGRA) {
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return ((src_pixel << 24) & 0xff000000)
+ | ((src_pixel >> 24) & 0x000000ff)
+ | ((src_pixel << 8) & 0x00ff0000)
+ | ((src_pixel >> 8) & 0x0000ff00);
+ } else {
+ return src_pixel;
+ }
+ } else { // GL_RGBA
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
+ } else {
+ return ((src_pixel << 16) & 0xff0000)
+ | ((src_pixel >> 16) & 0xff)
+ | (src_pixel & 0xff00ff00);
+ }
+ }
+}
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/utils/texturehelper_p.h b/src/datavis3d/utils/texturehelper_p.h
new file mode 100644
index 00000000..ac86bccf
--- /dev/null
+++ b/src/datavis3d/utils/texturehelper_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTUREHELPER_P_H
+#define TEXTUREHELPER_P_H
+
+#include "qdatavis3dglobal.h"
+#include <QOpenGLFunctions>
+#include <QRgb>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+class TextureHelper
+{
+public:
+ // Ownership of created texture is transferred to caller
+ static GLuint create2DTexture(const QImage &image, bool useTrilinearFiltering = false);
+ static GLuint createCubeMapTexture(const QImage &image, bool useTrilinearFiltering = false);
+
+private:
+ static QImage convertToGLFormat(const QImage &srcImage);
+ static void convertToGLFormatHelper(QImage &dstImage, const QImage &srcImage, GLenum texture_format);
+ static QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format);
+};
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
+
+#endif
diff --git a/src/datavis3d/utils/utils.pri b/src/datavis3d/utils/utils.pri
index 62134c71..566af55f 100644
--- a/src/datavis3d/utils/utils.pri
+++ b/src/datavis3d/utils/utils.pri
@@ -3,6 +3,7 @@ HEADERS += $$PWD/meshloader_p.h \
$$PWD/camerahelper_p.h \
$$PWD/shaderhelper_p.h \
$$PWD/objecthelper_p.h \
+ $$PWD/texturehelper_p.h \
$$PWD/utils_p.h
SOURCES += $$PWD/meshloader.cpp \
@@ -10,4 +11,5 @@ SOURCES += $$PWD/meshloader.cpp \
$$PWD/camerahelper.cpp \
$$PWD/shaderhelper.cpp \
$$PWD/objecthelper.cpp \
+ $$PWD/texturehelper.cpp \
$$PWD/utils.cpp