Qt 4.5: glshaders.cpp Example File (demos/boxes/glshaders.cpp)

|  | Home · All Namespaces · All Classes · Main Classes · Grouped Classes · Modules · Functions |

# glshaders.cpp Example File
demos/boxes/glshaders.cpp

     /****************************************************************************
     **
     ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     ** All rights reserved.
     ** Contact: Nokia Corporation (qt-info@nokia.com)
     **
     ** This file is part of the demonstration applications of the Qt Toolkit.
     **
     ** $QT_BEGIN_LICENSE:LGPL$
     ** Commercial Usage
     ** Licensees holding valid Qt Commercial licenses may use this file in
     ** accordance with the Qt Commercial License Agreement provided with the
     ** Software or, alternatively, in accordance with the terms contained in
     ** a written agreement between you and Nokia.
     **
     ** 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, Nokia gives you certain additional
     ** rights.  These rights are described in the Nokia 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.
     **
     ** If you have questions regarding the use of this file, please contact
     ** Nokia at qt-info@nokia.com.
     ** $QT_END_LICENSE$
     **
     ****************************************************************************/

     #include "glshaders.h"

     #define GLSHADERS_ASSERT_OPENGL(prefix, assertion, returnStatement)                         \
     if (m_failed || !(assertion)) {                                                             \
         if (!m_failed) qCritical(prefix ": The necessary OpenGL functions are not available."); \
         m_failed = true;                                                                        \
         returnStatement;                                                                        \
     }

     GLShader::GLShader(const char *data, int size, GLenum shaderType)
     : m_compileError(false), m_failed(false)
     {
         GLSHADERS_ASSERT_OPENGL("GLShader::GLShader",
             glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glGetObjectParameterivARB, return)

         m_shader = glCreateShaderObjectARB(shaderType);

         GLint glSize = size;
         glShaderSourceARB(m_shader, 1, reinterpret_cast<const GLcharARB**>(&data), &glSize);
         glCompileShaderARB(m_shader);
         int status;
         glGetObjectParameterivARB(m_shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
         m_compileError = (status != 1);
     }

     GLShader::GLShader(const QString& fileName, GLenum shaderType)
         : m_compileError(false), m_failed(false)
     {
         GLSHADERS_ASSERT_OPENGL("GLShader::GLShader",
             glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glGetObjectParameterivARB, return)

         m_shader = glCreateShaderObjectARB(shaderType);

         QFile file(fileName);
         if (file.open(QIODevice::ReadOnly)) {
             QByteArray bytes = file.readAll();
             GLint size = file.size();
             const char *p = bytes.data();
             file.close();
             glShaderSourceARB(m_shader, 1,  reinterpret_cast<const GLcharARB**>(&p), &size);
             glCompileShaderARB(m_shader);
             int status;
             glGetObjectParameterivARB(m_shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
             m_compileError = (status != 1);
         } else {
             m_compileError = true;
         }
     }

     GLShader::~GLShader()
     {
         GLSHADERS_ASSERT_OPENGL("GLShader::~GLShader", glDeleteObjectARB, return)

         glDeleteObjectARB(m_shader);
     }

     QString GLShader::log()
     {
         GLSHADERS_ASSERT_OPENGL("GLShader::log", glGetObjectParameterivARB
             && glGetInfoLogARB, return QLatin1String("GLSL not supported."))

         int length;
         glGetObjectParameterivARB(m_shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
         char *log = new char[length + 1];
         GLsizei glLength = length;
         glGetInfoLogARB(m_shader, glLength, &glLength,  reinterpret_cast<GLcharARB*>(log));
         log[glLength] = '\0';
         QString result(log);
         delete log;
         return result;
     }

     GLVertexShader::GLVertexShader(const char *data, int size) : GLShader(data, size, GL_VERTEX_SHADER_ARB)
     {
     }

     GLVertexShader::GLVertexShader(const QString& fileName) : GLShader(fileName, GL_VERTEX_SHADER_ARB)
     {
     }

     GLFragmentShader::GLFragmentShader(const char *data, int size) : GLShader(data, size, GL_FRAGMENT_SHADER_ARB)
     {
     }

     GLFragmentShader::GLFragmentShader(const QString& fileName) : GLShader(fileName, GL_FRAGMENT_SHADER_ARB)
     {
     }

     GLProgram::GLProgram() : m_linked(false), m_linkError(false), m_failed(false)
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::GLProgram", glCreateProgramObjectARB, return)

         m_program = glCreateProgramObjectARB();
     }

     GLProgram::~GLProgram()
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::~GLProgram", glDeleteObjectARB, return)

         glDeleteObjectARB(m_program);
     }

     void GLProgram::attach(const GLShader &shader)
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::attach", glAttachObjectARB, return)

         glAttachObjectARB(m_program, shader.m_shader);
         m_linked = m_linkError = false;
     }

     void GLProgram::detach(const GLShader &shader)
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::detach", glDetachObjectARB, return)

         glDetachObjectARB(m_program, shader.m_shader);
         m_linked = m_linkError = false;
     }

     bool GLProgram::failed()
     {
         if (m_failed || m_linkError)
             return true;

         if (m_linked)
             return false;

         GLSHADERS_ASSERT_OPENGL("GLProgram::failed", glLinkProgramARB && glGetObjectParameterivARB, return true)

         glLinkProgramARB(m_program);
         int status;
         glGetObjectParameterivARB(m_program, GL_OBJECT_LINK_STATUS_ARB, &status);
         m_linkError = !(m_linked = (status == 1));
         return m_linkError;
     }

     QString GLProgram::log()
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::log", glGetObjectParameterivARB && glGetInfoLogARB,
             return QLatin1String("Failed."))

         int length;
         glGetObjectParameterivARB(m_program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
         char *log = new char[length + 1];
         GLsizei glLength = length;
         glGetInfoLogARB(m_program, glLength, &glLength,  reinterpret_cast<GLcharARB*>(log));
         log[glLength] = '\0';
         QString result(log);
         delete log;
         return result;
     }

     void GLProgram::bind()
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::bind", glUseProgramObjectARB, return)

         if (!failed())
             glUseProgramObjectARB(m_program);
     }

     void GLProgram::unbind()
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::bind", glUseProgramObjectARB, return)

         glUseProgramObjectARB(0);
     }

     bool GLProgram::hasParameter(const QString& name)
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::hasParameter", glGetUniformLocationARB, return false)

         if (!failed()) {
             QByteArray asciiName = name.toAscii();
             return -1 != glGetUniformLocationARB(m_program, reinterpret_cast<const GLcharARB*>(asciiName.data()));
         }
         return false;
     }

     void GLProgram::setInt(const QString& name, int value)
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::setInt", glGetUniformLocationARB && glUniform1iARB, return)

         if (!failed()) {
             QByteArray asciiName = name.toAscii();
             int loc = glGetUniformLocationARB(m_program,  reinterpret_cast<const GLcharARB*>(asciiName.data()));
                 glUniform1iARB(loc, value);
         }
     }

     void GLProgram::setFloat(const QString& name, float value)
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::setFloat", glGetUniformLocationARB && glUniform1fARB, return)

         if (!failed()) {
             QByteArray asciiName = name.toAscii();
             int loc = glGetUniformLocationARB(m_program, reinterpret_cast<const GLcharARB*>(asciiName.data()));
                 glUniform1fARB(loc, value);
         }
     }

     void GLProgram::setColor(const QString& name, QRgb value)
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::setColor", glGetUniformLocationARB && glUniform4fARB, return)

         //qDebug() << "Setting color" << name;
         if (!failed()) {
             QByteArray asciiName = name.toAscii();
             int loc = glGetUniformLocationARB(m_program, reinterpret_cast<const GLcharARB*>(asciiName.data()));
             //qDebug() << "Location of" << name << "is" << loc;
             QColor color(value);
                 glUniform4fARB(loc, color.redF(), color.greenF(), color.blueF(), color.alphaF());
         }
     }

     void GLProgram::setMatrix(const QString& name, const gfx::Matrix4x4f &mat)
     {
         GLSHADERS_ASSERT_OPENGL("GLProgram::setMatrix", glGetUniformLocationARB && glUniformMatrix4fvARB, return)

         if (!failed()) {
             QByteArray asciiName = name.toAscii();
             int loc = glGetUniformLocationARB(m_program,  reinterpret_cast<const GLcharARB*>(asciiName.data()));
             //qDebug() << "Location of" << name << "is" << loc;
                 glUniformMatrix4fvARB(loc, 1, GL_FALSE, mat.bits());
         }
     }