void MyGLWidget::carregaShaders() { // Creem els shaders per al fragment shader i el vertex shader QGLShader fs (QGLShader::Fragment, this); QGLShader vs (QGLShader::Vertex, this); // Carreguem el codi dels fitxers i els compilem fs.compileSourceFile("shaders/fragshad.frag"); vs.compileSourceFile("shaders/vertshad.vert"); // Creem el program program = new QGLShaderProgram(this); // Li afegim els shaders corresponents program->addShader(&fs); program->addShader(&vs); // Linkem el program program->link(); // Indiquem que aquest és el program que volem usar program->bind(); // Obtenim identificador per a l'atribut “vertex” del vertex shader vertexLoc = glGetAttribLocation (program->programId(), "vertex"); // Obtenim identificador per a l'atribut “color” del vertex shader colorLoc = glGetAttribLocation (program->programId(), "color"); // Uniform locations transLoc = glGetUniformLocation(program->programId(), "TG"); projLoc = glGetUniformLocation(program->programId(), "proj"); }
void MyGLWidget::initializeGL () { // glew és necessari per cridar funcions de les darreres versions d'OpenGL glewExperimental = GL_TRUE; glewInit(); glGetError(); // Reinicia la variable d'error d'OpenGL glClearColor (0.5, 0.7, 1.0, 1.0); // defineix color de fons (d'esborrat) //afegim shaders QGLShader fs (QGLShader::Fragment,this); fs.compileSourceFile ("./fragshad.frag"); QGLShader vs (QGLShader::Vertex,this); vs.compileSourceFile ("./vertshad.vert"); QGLShaderProgram program(this); program.addShader(&fs); program.addShader(&vs); program.link(); program.bind(); //creem els buffers createBuffers(); }
/**************************************************************************** ** ** Copyright (C) 2015 ** ** This file is generated by the Magus toolkit ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ #include <QtWidgets> #include <QtOpenGL> #include <QMessageBox> #include "tool_glspherewidget.h" namespace Magus { //****************************************************************************/ QtGLSphereWidget::QtGLSphereWidget(QWidget *parent, QGLWidget *shareWidget) : QGLWidget(parent, shareWidget) { clearColor = Qt::black; xRot = 0; yRot = 0; zRot = 0; program = 0; } //****************************************************************************/ QtGLSphereWidget::~QtGLSphereWidget() { } //****************************************************************************/ QSize QtGLSphereWidget::minimumSizeHint() const { return QSize(16, 16); } //****************************************************************************/ QSize QtGLSphereWidget::sizeHint() const { return QSize(200, 200); } //****************************************************************************/ void QtGLSphereWidget::rotateBy(int xAngle, int yAngle, int zAngle) { xRot += xAngle; yRot += yAngle; zRot += zAngle; updateGL(); } //****************************************************************************/ void QtGLSphereWidget::setClearColor(const QColor &color) { clearColor = color; updateGL(); } //****************************************************************************/ void QtGLSphereWidget::setPixmap(const QPixmap& pixmap, const QString& fullName, const QString& baseName) { mPixmap = pixmap; mFullName = fullName; mBaseName = baseName; } //****************************************************************************/ const QString& QtGLSphereWidget::getFullName(void) const { return mFullName; } //****************************************************************************/ const QString& QtGLSphereWidget::getBaseName(void) const { return mBaseName; } //****************************************************************************/ void QtGLSphereWidget::initializeGL() { initializeOpenGLFunctions(); buildSphere(); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); #ifdef GL_TEXTURE_2D glEnable(GL_TEXTURE_2D); #endif #define PROGRAM_VERTEX_ATTRIBUTE 0 #define PROGRAM_TEXCOORD_ATTRIBUTE 1 QGLShader *vshader = new QGLShader(QGLShader::Vertex, this); const char *vsrc = "attribute highp vec4 vertex;\n" "attribute mediump vec4 texCoord;\n" "varying mediump vec4 texc;\n" "uniform mediump mat4 matrix;\n" "void main(void)\n" "{\n" " gl_Position = matrix * vertex;\n" " texc = texCoord;\n" "}\n"; vshader->compileSourceCode(vsrc); QGLShader *fshader = new QGLShader(QGLShader::Fragment, this); const char *fsrc = "uniform sampler2D texture;\n" "varying mediump vec4 texc;\n" "void main(void)\n" "{\n" " gl_FragColor = texture2D(texture, texc.st);\n" "}\n"; fshader->compileSourceCode(fsrc); program = new QGLShaderProgram(this); program->addShader(vshader); program->addShader(fshader); program->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE); program->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE); program->link(); program->bind(); program->setUniformValue("texture", 0); // Set the clear color and rotate the sphere QColor clearColor; clearColor = Qt::black; setClearColor(clearColor); rotateBy(0 * 16, -90 * 16, 180 * 16); }
void GLWidget::initializeGL() { makeObject(); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); #ifndef QT_OPENGL_ES_2 glEnable(GL_TEXTURE_2D); #endif #ifdef QT_OPENGL_ES_2 #define PROGRAM_VERTEX_ATTRIBUTE 0 #define PROGRAM_TEXCOORD_ATTRIBUTE 1 QGLShader *vshader = new QGLShader(QGLShader::Vertex, this); const char *vsrc = "attribute highp vec4 vertex;\n" "attribute mediump vec4 texCoord;\n" "varying mediump vec4 texc;\n" "uniform mediump mat4 matrix;\n" "void main(void)\n" "{\n" " gl_Position = matrix * vertex;\n" " texc = texCoord;\n" "}\n"; vshader->compileSourceCode(vsrc); QGLShader *fshader = new QGLShader(QGLShader::Fragment, this); const char *fsrc = "uniform sampler2D texture;\n" "varying mediump vec4 texc;\n" "void main(void)\n" "{\n" " gl_FragColor = texture2D(texture, texc.st);\n" "}\n"; fshader->compileSourceCode(fsrc); program = new QGLShaderProgram(this); program->addShader(vshader); program->addShader(fshader); program->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE); program->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE); program->link(); program->bind(); program->setUniformValue("texture", 0); #endif }
PlainShader::PlainShader() { QGLShader* vert = new QGLShader(QGLShader::Vertex); QGLShader* frag = new QGLShader(QGLShader::Fragment); vert->compileSourceFile("./shaders/plain.vert"); frag->compileSourceFile("./shaders/plain.frag"); m_shaderProg = new QGLShaderProgram(); m_shaderProg->addShader(vert); m_shaderProg->addShader(frag); m_shaderProg->link(); m_shaderFogFlag = m_shaderProg->uniformLocation("fog_enabled"); m_shaderProg->setUniformValue(m_shaderFogFlag, false); }
QGLShader* StelQGLGLSLShader::createVertexShader(const QString& source) { Q_ASSERT_X(state == State_Unlocked || state == State_Modified, Q_FUNC_INFO, "Can't add a vertex shader to a built shader program"); state = State_Modified; QGLShader* shader = new QGLShader(QGLShader::Vertex, renderer->getGLContext()); aggregatedLog += shader->log(); if(shader->compileSourceCode(source)) { return shader; } else { delete shader; return NULL; } }
// Metode per a carregar de fitxers el vertex i el fragment shader void GLWidget::InitShader(const char* vShaderFile, const char* fShaderFile, QGLShaderProgram * prgm ) { struct Shader { const char* filename; GLenum type; GLchar* source; } shaders[2] = { { vShaderFile, GL_VERTEX_SHADER, NULL }, { fShaderFile, GL_FRAGMENT_SHADER, NULL } }; QGLShader *vshader = new QGLShader(QGLShader::Vertex, this); QGLShader *fshader = new QGLShader(QGLShader::Fragment, this); // Es llegeixen els dos shaders: el vertex i el fragment shader for ( int i = 0; i < 2; ++i ) { Shader& s = shaders[i]; s.source = Common::readShaderSource( s.filename ); if ( shaders[i].source == NULL ) { std::cerr << "Failed to read " << s.filename << std::endl; exit( EXIT_FAILURE ); } } // Es compilen els programes en temps d'execucio de l'aplicacio vshader->compileSourceCode(shaders[0].source); fshader->compileSourceCode(shaders[1].source); // S'afegeixen unes variables de classe program = new QGLShaderProgram(this); program->addShader(vshader); program->addShader(fshader); program->bindAttributeLocation("vPosition", PROGRAM_VERTEX_ATTRIBUTE); program->bindAttributeLocation("vNormal", PROGRAM_COLOR_ATTRIBUTE); // Es munta el programa program->link(); // Es vincula el programa al context de GL per a ser executat amb les comandes GL program->bind(); }
void RenderViewWidget::initShaders(){ Assert(QGLContext::currentContext() != 0); //First, check if we can even use OpenGL shader programs const bool canUseShaders = QGLShaderProgram::hasOpenGLShaderPrograms(); Assert(canUseShaders); //Fragment shader(s) QGLShader* shader = new QGLShader(QGLShader::Fragment, this); const bool ok1 = shader->compileSourceCode( "//Simple Vertex Shader" \ "\n"\ "uniform sampler2D sampler;\n"\ "\n"\ "void main(void)\n" \ "{\n" \ "// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" \ "\n"\ " vec4 c = texture2D(sampler, gl_TexCoord[0].st);\n" \ " gl_FragColor = vec4(c.x, c.y, c.z, 1.0);\n"\ "}\n" \ ); std::cout << shader->log().toStdString() << std::endl; Assert(ok1); hdrFragShaders.push_back(shader); //Vertex shader hdrVertShader = new QGLShader(QGLShader::Vertex, this); const bool ok2 = hdrVertShader->compileSourceCode( "//Simple fragment shader\n"\ "\n"\ "\n"\ "void main(void){\n"\ " gl_TexCoord[0] = gl_MultiTexCoord0;\n"\ " gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n"\ "}\n"\ "\n"\ ); std::cout << hdrVertShader->log().toStdString() << std::endl; Assert(ok2); hdrFragShaders.push_back(hdrVertShader); }
void VideoViewer::makeShaders() { _shaderProgram = new QGLShaderProgram(this); QGLShader *vertexShader = new QGLShader(QGLShader::Vertex, this); QGLShader *fragmentShader = new QGLShader(QGLShader::Fragment, this); QString vertexShaderSource; QString fragmentShaderSource; vertexShaderSource.append("#version 110\n"); vertexShaderSource.append("attribute vec2 position;\n"); vertexShaderSource.append("uniform mat2 matrix;\n"); vertexShaderSource.append("varying vec2 texcoord;\n"); vertexShaderSource.append("void main()\n"); vertexShaderSource.append("{\n"); vertexShaderSource.append( "gl_Position = vec4(matrix * position, 0.0, 1.0);\n"); vertexShaderSource.append("texcoord = vec2(position.x, -position.y) " "* vec2(0.5) + vec2(0.5);\n"); vertexShaderSource.append("}\n"); fragmentShaderSource.append("#version 110\n"); fragmentShaderSource.append("uniform sampler2D texture;\n"); fragmentShaderSource.append("varying vec2 texcoord;\n"); fragmentShaderSource.append("void main()\n"); fragmentShaderSource.append("{\n"); fragmentShaderSource.append( "gl_FragColor = texture2D(texture, texcoord);\n"); fragmentShaderSource.append("}\n"); vertexShader->compileSourceCode(vertexShaderSource); fragmentShader->compileSourceCode(fragmentShaderSource); if (!vertexShader->isCompiled()) { qDebug() << "Could not compile vertex shader:\n" << vertexShader->log(); } if (!fragmentShader->isCompiled()) { qDebug() << "Could not compile fragment shader:\n" << fragmentShader->log(); } _shaderProgram->addShader(fragmentShader); _shaderProgram->addShader(vertexShader); _shaderProgram->link(); _shaderProgram->bind(); }
bool StelQGLGLSLShader::addFragmentShader(const QString& source) { Q_ASSERT_X(state == State_Unlocked || state == State_Modified, Q_FUNC_INFO, "Can't add a fragment shader to a built shader program"); state = State_Modified; QGLShader* shader = new QGLShader(QGLShader::Fragment, renderer->getGLContext()); const bool success = shader->compileSourceCode(source); aggregatedLog += shader->log(); if(success) { defaultFragmentShaders.append(shader); } else { delete shader; } return success; }
QGLShader *SceneParser::loadShader(KeyValues *data) { const char *type = data->getString("type"); if(!type) { fprintf(stderr, "Key 'type' not found on Shader\n"); return NULL; } const char *file = data->getString("file"); if(!file) { fprintf(stderr, "Key 'file' not found on Shader\n"); return NULL; } char *filename = resolvePath(file); QGLShader::ShaderType shaderType; if(strcmp(type, "vertex") == 0) { shaderType = QGLShader::Vertex; } else if(strcmp(type, "fragment") == 0) { shaderType = QGLShader::Fragment; } else { fprintf(stderr, "Invalid shader type: %s\n", type); delete[] filename; return NULL; } QGLShader *shader = new QGLShader(shaderType); if(!shader->compileSourceFile(filename)) { fprintf(stderr, "Failed to load shader %s\n", filename); fprintf(stdout, shader->log().toStdString().c_str()); delete shader; delete[] filename; return NULL; } delete[] filename; return shader; }
void GLWidget::initializeGL() { initializeGLFunctions(); makeObject(); // opengl settings glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); // transform matrices glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1.0, +1.0, +1.0, -1.0, 4.0, 15.0); glMatrixMode(GL_MODELVIEW); // shaders QGLShader *vshader = new QGLShader(QGLShader::Vertex, this); vshader->compileSourceFile(":/glsl/passThru_vert.glsl"); QGLShader *fshader = new QGLShader(QGLShader::Fragment, this); fshader->compileSourceFile(":/glsl/uvMap_frag.glsl"); m_uvMapProgram = new QGLShaderProgram(this); m_uvMapProgram->addShader(vshader); m_uvMapProgram->addShader(fshader); m_uvMapProgram->link(); fshader = new QGLShader(QGLShader::Fragment, this); fshader->compileSourceFile(":/glsl/transparencyGrid_frag.glsl"); m_gridProgram = new QGLShaderProgram(this); m_gridProgram->addShader(vshader); m_gridProgram->addShader(fshader); m_gridProgram->link(); emit initialized(); }
void Widget::initializeGL() { qDebug() << "isValid:" << this->context()->isValid(); qDebug() << "isSharing:" << this->context()->isSharing(); qDebug() << "hasOpenGL:" << this->context()->format().hasOpenGL(); qDebug() << "Format:" << this->context()->format(); glEnable(GL_DEPTH_TEST); QString vertexShaderSource( "uniform mat4 modelViewMatrix;\n" "uniform mat4 projectionMatrix;\n" "attribute vec4 vertexPosition;\n" "\n" "void main(void)\n" "{\n" " gl_Position = projectionMatrix * modelViewMatrix * vertexPosition;\n" "}\n"); QString fragmentShaderSource( "precision mediump float;\n" "\n" "void main(void)\n" "{\n" "gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n" "}\n"); QGLShader *vertexShader = new QGLShader(QGLShader::Vertex, this); QGLShader *fragmentShader = new QGLShader(QGLShader::Fragment, this); qDebug() << "After constuctor Shaders."; qDebug() << vertexShader->log(); vertexShader->compileSourceCode(vertexShaderSource); fragmentShader->compileSourceCode(fragmentShaderSource); _shaderProgram = new QGLShaderProgram(this); _shaderProgram->addShader(vertexShader); _shaderProgram->addShader(fragmentShader); _shaderProgram->link(); _shaderProgram->bind(); qglClearColor(Qt::gray); _timer->start(10); qDebug() << vertexShader->log(); }
void GLWidget::loadShaders(QGLShaderProgram* program, QString vShaderFileName, QString fShaderFileName) { QGLShader* vertexShader = NULL; QGLShader* fragmentShader = NULL; QFileInfo vsh(vShaderFileName); if(vsh.exists()) { vertexShader = new QGLShader(QGLShader::Vertex); if(vertexShader->compileSourceFile(vShaderFileName)) { program->addShader(vertexShader); qDebug() << "Vertex shader compiled successfully."; } else { qWarning() << "Vertex Shader Error" << vertexShader->log(); } } else { qWarning() << "Vertex Shader source file " << fShaderFileName << " not found."; } QFileInfo fsh(fShaderFileName); if(fsh.exists()) { fragmentShader = new QGLShader(QGLShader::Fragment); if(fragmentShader->compileSourceFile(fShaderFileName)) { program->addShader(fragmentShader); qDebug() << "Fragment shader compiled successfully."; } else { qWarning() << "Fragment Shader Error" << fragmentShader->log(); } } else { qWarning() << "Fragment Shader source file " << fShaderFileName << " not found."; } if(!program->link()){ qWarning() << "Shader Program Linker Error" << program->log(); } }
void QGLTextureGlyphCache::resizeTextureData(int width, int height) { if (ctx == 0) { qWarning("QGLTextureGlyphCache::resizeTextureData: Called with no context"); return; } QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); int oldWidth = glyphTexture->m_width; int oldHeight = glyphTexture->m_height; // Make the lower glyph texture size 16 x 16. if (width < 16) width = 16; if (height < 16) height = 16; GLuint oldTexture = glyphTexture->m_texture; createTextureData(width, height); if (ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::resizeTextureData(width, height); Q_ASSERT(image().depth() == 8); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); glDeleteTextures(1, &oldTexture); return; } // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail glBindFramebuffer(GL_FRAMEBUFFER_EXT, glyphTexture->m_fbo); GLuint tmp_texture; glGenTextures(1, &tmp_texture); glBindTexture(GL_TEXTURE_2D, tmp_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); m_filterMode = Nearest; glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tmp_texture, 0); glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); glBindTexture(GL_TEXTURE_2D, oldTexture); if (pex != 0) pex->transferMode(BrushDrawingMode); glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glViewport(0, 0, oldWidth, oldHeight); QGLShaderProgram *blitProgram = 0; if (pex == 0) { if (m_blitProgram == 0) { m_blitProgram = new QGLShaderProgram(ctx); { QString source; source.append(QLatin1String(qglslMainWithTexCoordsVertexShader)); source.append(QLatin1String(qglslUntransformedPositionVertexShader)); QGLShader *vertexShader = new QGLShader(QGLShader::Vertex, m_blitProgram); vertexShader->compileSourceCode(source); m_blitProgram->addShader(vertexShader); } { QString source; source.append(QLatin1String(qglslMainFragmentShader)); source.append(QLatin1String(qglslImageSrcFragmentShader)); QGLShader *fragmentShader = new QGLShader(QGLShader::Fragment, m_blitProgram); fragmentShader->compileSourceCode(source); m_blitProgram->addShader(fragmentShader); } m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); m_blitProgram->link(); } glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_vertexCoordinateArray); glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_textureCoordinateArray); m_blitProgram->bind(); m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); m_blitProgram->disableAttributeArray(int(QT_OPACITY_ATTR)); blitProgram = m_blitProgram; } else { pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, m_vertexCoordinateArray); pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, m_textureCoordinateArray); pex->shaderManager->useBlitProgram(); blitProgram = pex->shaderManager->blitProgram(); } blitProgram->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, 0); glDeleteTextures(1, &tmp_texture); glDeleteTextures(1, &oldTexture); glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); if (pex != 0) { glViewport(0, 0, pex->width, pex->height); pex->updateClipScissorTest(); } }
QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) : ctxGuard(context) , blitShaderProg(0) , simpleShaderProg(0) { /* Rather than having the shader source array statically initialised, it is initialised here instead. This is to allow new shader names to be inserted or existing names moved around without having to change the order of the glsl strings. It is hoped this will make future hard-to-find runtime bugs more obvious and generally give more solid code. */ static bool snippetsPopulated = false; if (!snippetsPopulated) { const char** code = qShaderSnippets; // shortcut code[MainVertexShader] = qglslMainVertexShader; code[MainWithTexCoordsVertexShader] = qglslMainWithTexCoordsVertexShader; code[MainWithTexCoordsAndOpacityVertexShader] = qglslMainWithTexCoordsAndOpacityVertexShader; code[UntransformedPositionVertexShader] = qglslUntransformedPositionVertexShader; code[PositionOnlyVertexShader] = qglslPositionOnlyVertexShader; code[PositionWithPatternBrushVertexShader] = qglslPositionWithPatternBrushVertexShader; code[PositionWithLinearGradientBrushVertexShader] = qglslPositionWithLinearGradientBrushVertexShader; code[PositionWithConicalGradientBrushVertexShader] = qglslPositionWithConicalGradientBrushVertexShader; code[PositionWithRadialGradientBrushVertexShader] = qglslPositionWithRadialGradientBrushVertexShader; code[PositionWithTextureBrushVertexShader] = qglslPositionWithTextureBrushVertexShader; code[AffinePositionWithPatternBrushVertexShader] = qglslAffinePositionWithPatternBrushVertexShader; code[AffinePositionWithLinearGradientBrushVertexShader] = qglslAffinePositionWithLinearGradientBrushVertexShader; code[AffinePositionWithConicalGradientBrushVertexShader] = qglslAffinePositionWithConicalGradientBrushVertexShader; code[AffinePositionWithRadialGradientBrushVertexShader] = qglslAffinePositionWithRadialGradientBrushVertexShader; code[AffinePositionWithTextureBrushVertexShader] = qglslAffinePositionWithTextureBrushVertexShader; code[MainFragmentShader_CMO] = qglslMainFragmentShader_CMO; code[MainFragmentShader_CM] = qglslMainFragmentShader_CM; code[MainFragmentShader_MO] = qglslMainFragmentShader_MO; code[MainFragmentShader_M] = qglslMainFragmentShader_M; code[MainFragmentShader_CO] = qglslMainFragmentShader_CO; code[MainFragmentShader_C] = qglslMainFragmentShader_C; code[MainFragmentShader_O] = qglslMainFragmentShader_O; code[MainFragmentShader] = qglslMainFragmentShader; code[MainFragmentShader_ImageArrays] = qglslMainFragmentShader_ImageArrays; code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader; code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader; code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader; code[CustomImageSrcFragmentShader] = qglslCustomSrcFragmentShader; // Calls "customShader", which must be appended code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader; code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader; code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader; code[PatternBrushSrcFragmentShader] = qglslPatternBrushSrcFragmentShader; code[LinearGradientBrushSrcFragmentShader] = qglslLinearGradientBrushSrcFragmentShader; code[RadialGradientBrushSrcFragmentShader] = qglslRadialGradientBrushSrcFragmentShader; code[ConicalGradientBrushSrcFragmentShader] = qglslConicalGradientBrushSrcFragmentShader; code[ShockingPinkSrcFragmentShader] = qglslShockingPinkSrcFragmentShader; code[NoMaskFragmentShader] = ""; code[MaskFragmentShader] = qglslMaskFragmentShader; code[RgbMaskFragmentShaderPass1] = qglslRgbMaskFragmentShaderPass1; code[RgbMaskFragmentShaderPass2] = qglslRgbMaskFragmentShaderPass2; code[RgbMaskWithGammaFragmentShader] = ""; //### code[NoCompositionModeFragmentShader] = ""; code[MultiplyCompositionModeFragmentShader] = ""; //### code[ScreenCompositionModeFragmentShader] = ""; //### code[OverlayCompositionModeFragmentShader] = ""; //### code[DarkenCompositionModeFragmentShader] = ""; //### code[LightenCompositionModeFragmentShader] = ""; //### code[ColorDodgeCompositionModeFragmentShader] = ""; //### code[ColorBurnCompositionModeFragmentShader] = ""; //### code[HardLightCompositionModeFragmentShader] = ""; //### code[SoftLightCompositionModeFragmentShader] = ""; //### code[DifferenceCompositionModeFragmentShader] = ""; //### code[ExclusionCompositionModeFragmentShader] = ""; //### #if defined(QT_DEBUG) // Check that all the elements have been filled: for (int i = 0; i < TotalSnippetCount; ++i) { if (qShaderSnippets[i] == 0) { qFatal("Shader snippet for %s (#%d) is missing!", snippetNameStr(SnippetName(i)).constData(), i); } } #endif snippetsPopulated = true; } QGLShader* fragShader; QGLShader* vertexShader; QByteArray source; // Compile up the simple shader: source.clear(); source.append(qShaderSnippets[MainVertexShader]); source.append(qShaderSnippets[PositionOnlyVertexShader]); vertexShader = new QGLShader(QGLShader::Vertex, context, this); vertexShader->compileSourceCode(source); source.clear(); source.append(qShaderSnippets[MainFragmentShader]); source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]); fragShader = new QGLShader(QGLShader::Fragment, context, this); fragShader->compileSourceCode(source); simpleShaderProg = new QGLShaderProgram(context, this); simpleShaderProg->addShader(vertexShader); simpleShaderProg->addShader(fragShader); simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); simpleShaderProg->link(); if (!simpleShaderProg->isLinked()) { qCritical() << "Errors linking simple shader:" << simpleShaderProg->log(); } // Compile the blit shader: source.clear(); source.append(qShaderSnippets[MainWithTexCoordsVertexShader]); source.append(qShaderSnippets[UntransformedPositionVertexShader]); vertexShader = new QGLShader(QGLShader::Vertex, context, this); vertexShader->compileSourceCode(source); source.clear(); source.append(qShaderSnippets[MainFragmentShader]); source.append(qShaderSnippets[ImageSrcFragmentShader]); fragShader = new QGLShader(QGLShader::Fragment, context, this); fragShader->compileSourceCode(source); blitShaderProg = new QGLShaderProgram(context, this); blitShaderProg->addShader(vertexShader); blitShaderProg->addShader(fragShader); blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); blitShaderProg->link(); if (!blitShaderProg->isLinked()) { qCritical() << "Errors linking blit shader:" << simpleShaderProg->log(); } }
// The address returned here will only be valid until next time this function is called. QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog) { for (int i = 0; i < cachedPrograms.size(); ++i) { QGLEngineShaderProg *cachedProg = cachedPrograms[i]; if (*cachedProg == prog) { // Move the program to the top of the list as a poor-man's cache algo cachedPrograms.move(i, 0); return cachedProg; } } QByteArray source; source.append(qShaderSnippets[prog.mainFragShader]); source.append(qShaderSnippets[prog.srcPixelFragShader]); if (prog.srcPixelFragShader == CustomImageSrcFragmentShader) source.append(prog.customStageSource); if (prog.compositionFragShader) source.append(qShaderSnippets[prog.compositionFragShader]); if (prog.maskFragShader) source.append(qShaderSnippets[prog.maskFragShader]); QGLShader* fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); fragShader->compileSourceCode(source); source.clear(); source.append(qShaderSnippets[prog.mainVertexShader]); source.append(qShaderSnippets[prog.positionVertexShader]); QGLShader* vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); vertexShader->compileSourceCode(source); #if defined(QT_DEBUG) // Name the shaders for easier debugging QByteArray description; description.append("Fragment shader: main="); description.append(snippetNameStr(prog.mainFragShader)); description.append(", srcPixel="); description.append(snippetNameStr(prog.srcPixelFragShader)); if (prog.compositionFragShader) { description.append(", composition="); description.append(snippetNameStr(prog.compositionFragShader)); } if (prog.maskFragShader) { description.append(", mask="); description.append(snippetNameStr(prog.maskFragShader)); } fragShader->setObjectName(QString::fromLatin1(description)); description.clear(); description.append("Vertex shader: main="); description.append(snippetNameStr(prog.mainVertexShader)); description.append(", position="); description.append(snippetNameStr(prog.positionVertexShader)); vertexShader->setObjectName(QString::fromLatin1(description)); #endif QGLEngineShaderProg* newProg = new QGLEngineShaderProg(prog); // If the shader program's not found in the cache, create it now. newProg->program = new QGLShaderProgram(ctxGuard.context(), this); newProg->program->addShader(vertexShader); newProg->program->addShader(fragShader); // We have to bind the vertex attribute names before the program is linked: newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); if (newProg->useTextureCoords) newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); if (newProg->useOpacityAttribute) newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); newProg->program->link(); if (!newProg->program->isLinked()) { QLatin1String none("none"); QLatin1String br("\n"); QString error; error = QLatin1String("Shader program failed to link,") #if defined(QT_DEBUG) + br + QLatin1String(" Shaders Used:") + br + QLatin1String(" ") + vertexShader->objectName() + QLatin1String(": ") + br + QLatin1String(vertexShader->sourceCode()) + br + QLatin1String(" ") + fragShader->objectName() + QLatin1String(": ") + br + QLatin1String(fragShader->sourceCode()) + br #endif + QLatin1String(" Error Log:\n") + QLatin1String(" ") + newProg->program->log(); qWarning() << error; delete newProg; // Deletes the QGLShaderProgram in it's destructor newProg = 0; } else { if (cachedPrograms.count() > 30) { // The cache is full, so delete the last 5 programs in the list. // These programs will be least used, as a program us bumped to // the top of the list when it's used. for (int i = 0; i < 5; ++i) { delete cachedPrograms.last(); cachedPrograms.removeLast(); } } cachedPrograms.insert(0, newProg); } return newProg; }
// The address returned here will only be valid until next time this function is called. // The program is return bound. QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog) { for (int i = 0; i < cachedPrograms.size(); ++i) { QGLEngineShaderProg *cachedProg = cachedPrograms[i]; if (*cachedProg == prog) { // Move the program to the top of the list as a poor-man's cache algo cachedPrograms.move(i, 0); cachedProg->program->bind(); return cachedProg; } } QScopedPointer<QGLEngineShaderProg> newProg; do { QByteArray fragSource; // Insert the custom stage before the srcPixel shader to work around an ATI driver bug // where you cannot forward declare a function that takes a sampler as argument. if (prog.srcPixelFragShader == CustomImageSrcFragmentShader) fragSource.append(prog.customStageSource); fragSource.append(qShaderSnippets[prog.mainFragShader]); fragSource.append(qShaderSnippets[prog.srcPixelFragShader]); if (prog.compositionFragShader) fragSource.append(qShaderSnippets[prog.compositionFragShader]); if (prog.maskFragShader) fragSource.append(qShaderSnippets[prog.maskFragShader]); QByteArray vertexSource; vertexSource.append(qShaderSnippets[prog.mainVertexShader]); vertexSource.append(qShaderSnippets[prog.positionVertexShader]); QScopedPointer<QGLShaderProgram> shaderProgram(new QGLShaderProgram); CachedShader shaderCache(fragSource, vertexSource); bool inCache = shaderCache.load(shaderProgram.data(), QGLContext::currentContext()); if (!inCache) { QScopedPointer<QGLShader> fragShader(new QGLShader(QGLShader::Fragment)); QByteArray description; #if defined(QT_DEBUG) // Name the shader for easier debugging description.append("Fragment shader: main="); description.append(snippetNameStr(prog.mainFragShader)); description.append(", srcPixel="); description.append(snippetNameStr(prog.srcPixelFragShader)); if (prog.compositionFragShader) { description.append(", composition="); description.append(snippetNameStr(prog.compositionFragShader)); } if (prog.maskFragShader) { description.append(", mask="); description.append(snippetNameStr(prog.maskFragShader)); } fragShader->setObjectName(QString::fromLatin1(description)); #endif if (!fragShader->compileSourceCode(fragSource)) { qWarning() << "Warning:" << description << "failed to compile!"; break; } QScopedPointer<QGLShader> vertexShader(new QGLShader(QGLShader::Vertex)); #if defined(QT_DEBUG) // Name the shader for easier debugging description.clear(); description.append("Vertex shader: main="); description.append(snippetNameStr(prog.mainVertexShader)); description.append(", position="); description.append(snippetNameStr(prog.positionVertexShader)); vertexShader->setObjectName(QString::fromLatin1(description)); #endif if (!vertexShader->compileSourceCode(vertexSource)) { qWarning() << "Warning:" << description << "failed to compile!"; break; } shaders.append(vertexShader.data()); shaders.append(fragShader.data()); shaderProgram->addShader(vertexShader.take()); shaderProgram->addShader(fragShader.take()); // We have to bind the vertex attribute names before the program is linked: shaderProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); if (prog.useTextureCoords) shaderProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); if (prog.useOpacityAttribute) shaderProgram->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); if (prog.usePmvMatrixAttribute) { shaderProgram->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); shaderProgram->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); shaderProgram->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); } } newProg.reset(new QGLEngineShaderProg(prog)); newProg->program = shaderProgram.take(); newProg->program->link(); if (newProg->program->isLinked()) { if (!inCache) shaderCache.store(newProg->program, QGLContext::currentContext()); } else { QLatin1String none("none"); QLatin1String br("\n"); QString error; error = QLatin1String("Shader program failed to link,"); #if defined(QT_DEBUG) error += QLatin1String("\n Shaders Used:\n"); for (int i = 0; i < newProg->program->shaders().count(); ++i) { QGLShader *shader = newProg->program->shaders().at(i); error += QLatin1String(" ") + shader->objectName() + QLatin1String(": \n") + QLatin1String(shader->sourceCode()) + br; } #endif error += QLatin1String(" Error Log:\n") + QLatin1String(" ") + newProg->program->log(); qWarning() << error; break; } newProg->program->bind(); if (newProg->maskFragShader != QGLEngineSharedShaders::NoMaskFragmentShader) { GLuint location = newProg->program->uniformLocation("maskTexture"); newProg->program->setUniformValue(location, QT_MASK_TEXTURE_UNIT); } if (cachedPrograms.count() > 30) { // The cache is full, so delete the last 5 programs in the list. // These programs will be least used, as a program us bumped to // the top of the list when it's used. for (int i = 0; i < 5; ++i) { delete cachedPrograms.last(); cachedPrograms.removeLast(); } } cachedPrograms.insert(0, newProg.data()); } while (false); return newProg.take(); }
void GLWidget::InitShaders() { QGLShader *vshader = new QGLShader(QGLShader::Vertex, this); const char *vsrc = "attribute highp vec4 vertex;\n" "attribute mediump vec4 texCoord;\n" "varying mediump vec4 texc;\n" "uniform mediump mat4 matrix;\n" "uniform mediump vec4 color;\n" "varying mediump vec4 color1;\n" // "vec4 col2;\n" "void main(void)\n" "{\n" " gl_Position = matrix * vertex;\n" " texc = texCoord;\n" " color1 = color;\n" "}\n"; vshader->compileSourceCode(vsrc); QGLShader *fshader = new QGLShader(QGLShader::Fragment, this); const char *fsrc = "uniform sampler2D texture;\n" "varying vec4 color1;\n" "varying mediump vec4 texc;\n" "vec4 cl; \n" "void main(void)\n" "{\n" " cl = texture2D(texture, texc.st); \n" " gl_FragColor = cl * color1; \n" "}\n"; fshader->compileSourceCode(fsrc); program2 = new QGLShaderProgram(this); program2->addShader(vshader); program2->addShader(fshader); program2->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE); program2->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE); program2->link(); //********************************************************************** vshader = new QGLShader(QGLShader::Vertex, this); vsrc = "attribute highp vec4 vertex;\n" "varying mediump vec4 colorout;\n" "uniform mediump mat4 matrix;\n" "uniform mediump vec4 color;\n" "void main(void)\n" "{\n" " colorout = color;\n" " gl_Position = matrix * vertex;\n" "}\n"; vshader->compileSourceCode(vsrc); fshader = new QGLShader(QGLShader::Fragment, this); fsrc = "varying mediump vec4 colorout;\n" "vec4 color;\n" "void main(void)\n" "{\n" " gl_FragColor = colorout ;\n" "}\n"; fshader->compileSourceCode(fsrc); solidcolorp = new QGLShaderProgram(this); solidcolorp->addShader(vshader); solidcolorp->addShader(fshader); solidcolorp->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE); solidcolorp->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE); solidcolorp->link(); /* * *************************************/ vshader = new QGLShader(QGLShader::Vertex, this); vsrc = "attribute highp vec4 vertex;\n" "attribute mediump vec4 texCoord;\n" "varying mediump vec4 texc;\n" "uniform mediump mat4 matrix;\n" "void main(void)\n" "{\n" " gl_Position = matrix * vertex;\n" " texc = texCoord;\n" "}\n"; vshader->compileSourceCode(vsrc); fshader = new QGLShader(QGLShader::Fragment, this); fsrc = "uniform sampler2D texture;\n" "varying mediump vec4 texc;\n" "vec4 col;\n" "void main(void)\n" "{\n" " col = texture2D(texture, texc.st);\n" // " if ( col.r < 0.1 && col.g < 0.1 ) col *= vec4(1,1,1,0.2 ); \n" " gl_FragColor = col;\n" "}\n"; fshader->compileSourceCode(fsrc); program = new QGLShaderProgram(this); program->addShader(vshader); program->addShader(fshader); program->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE); program->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE); program->link(); }
const bool CCDeviceRenderer::loadShader(CCShader *shader) { // Create shader program shader->program = new QGLShaderProgram(); // Create and compile vertex shader CCText shaderFilename( "Resources/Shaders/" ); shaderFilename += shader->name; shaderFilename += ".fx"; const char *qtDefines = "#define QT\r\n"; QGLShader *vertexShader = new QGLShader( QGLShader::Vertex ); QGLShader *fragmentShader = new QGLShader( QGLShader::Fragment ); { char *fileData = NULL; CCFileManager::getPackagedFile( shaderFilename.buffer, &fileData ); { QString shaderData = QString( qtDefines ); shaderData.append( "#define VERTEX_SHADER\r\n" ); shaderData.append( fileData ); if( vertexShader->compileSourceCode( shaderData ) == false ) { QString error( "CCDeviceRenderer::Failed to compile vertex shader.\n" ); error.append( vertexShader->log() ); ASSERT_MESSAGE( false, error.toUtf8().constData() ); delete vertexShader; vertexShader = NULL; } } { QString shaderData = QString( qtDefines ); shaderData.append( "#define PIXEL_SHADER\r\n" ); shaderData.append( fileData ); if( fragmentShader->compileSourceCode( shaderData ) == false ) { QString error( "CCDeviceRenderer::Failed to compile pixel shader.\n" ); error.append( fragmentShader->log() ); ASSERT_MESSAGE( false, error.toUtf8().constData() ); delete fragmentShader; fragmentShader = NULL; } } FREE_POINTER( fileData ); } // Attach vertex shader to program shader->program->addShader( vertexShader ); // Attach fragment shader to program shader->program->addShader( fragmentShader ); // Bind attribute locations // this needs to be done prior to linking shader->program->bindAttributeLocation( "vs_position", ATTRIB_VERTEX ); shader->program->bindAttributeLocation( "vs_color", ATTRIB_COLOR ); shader->program->bindAttributeLocation( "vs_texCoord", ATTRIB_TEXCOORD ); // Link program if( !shader->program->link() ) { // Should log: "Failed to link program"; return false; } return true; }
QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) : blitShaderProg(0) , simpleShaderProg(0) { /* Rather than having the shader source array statically initialised, it is initialised here instead. This is to allow new shader names to be inserted or existing names moved around without having to change the order of the glsl strings. It is hoped this will make future hard-to-find runtime bugs more obvious and generally give more solid code. */ static bool snippetsPopulated = false; if (!snippetsPopulated) { const char** code = qShaderSnippets; // shortcut code[MainVertexShader] = qglslMainVertexShader; code[MainWithTexCoordsVertexShader] = qglslMainWithTexCoordsVertexShader; code[MainWithTexCoordsAndOpacityVertexShader] = qglslMainWithTexCoordsAndOpacityVertexShader; code[UntransformedPositionVertexShader] = qglslUntransformedPositionVertexShader; code[PositionOnlyVertexShader] = qglslPositionOnlyVertexShader; code[ComplexGeometryPositionOnlyVertexShader] = qglslComplexGeometryPositionOnlyVertexShader; code[PositionWithPatternBrushVertexShader] = qglslPositionWithPatternBrushVertexShader; code[PositionWithLinearGradientBrushVertexShader] = qglslPositionWithLinearGradientBrushVertexShader; code[PositionWithConicalGradientBrushVertexShader] = qglslPositionWithConicalGradientBrushVertexShader; code[PositionWithRadialGradientBrushVertexShader] = qglslPositionWithRadialGradientBrushVertexShader; code[PositionWithTextureBrushVertexShader] = qglslPositionWithTextureBrushVertexShader; code[AffinePositionWithPatternBrushVertexShader] = qglslAffinePositionWithPatternBrushVertexShader; code[AffinePositionWithLinearGradientBrushVertexShader] = qglslAffinePositionWithLinearGradientBrushVertexShader; code[AffinePositionWithConicalGradientBrushVertexShader] = qglslAffinePositionWithConicalGradientBrushVertexShader; code[AffinePositionWithRadialGradientBrushVertexShader] = qglslAffinePositionWithRadialGradientBrushVertexShader; code[AffinePositionWithTextureBrushVertexShader] = qglslAffinePositionWithTextureBrushVertexShader; code[MainFragmentShader_CMO] = qglslMainFragmentShader_CMO; code[MainFragmentShader_CM] = qglslMainFragmentShader_CM; code[MainFragmentShader_MO] = qglslMainFragmentShader_MO; code[MainFragmentShader_M] = qglslMainFragmentShader_M; code[MainFragmentShader_CO] = qglslMainFragmentShader_CO; code[MainFragmentShader_C] = qglslMainFragmentShader_C; code[MainFragmentShader_O] = qglslMainFragmentShader_O; code[MainFragmentShader] = qglslMainFragmentShader; code[MainFragmentShader_ImageArrays] = qglslMainFragmentShader_ImageArrays; code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader; code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader; code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader; code[CustomImageSrcFragmentShader] = qglslCustomSrcFragmentShader; // Calls "customShader", which must be appended code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader; if (!context->contextHandle()->isOpenGLES()) code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader_desktop; else code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader_ES; code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader; code[PatternBrushSrcFragmentShader] = qglslPatternBrushSrcFragmentShader; code[LinearGradientBrushSrcFragmentShader] = qglslLinearGradientBrushSrcFragmentShader; code[RadialGradientBrushSrcFragmentShader] = qglslRadialGradientBrushSrcFragmentShader; code[ConicalGradientBrushSrcFragmentShader] = qglslConicalGradientBrushSrcFragmentShader; code[ShockingPinkSrcFragmentShader] = qglslShockingPinkSrcFragmentShader; code[NoMaskFragmentShader] = ""; code[MaskFragmentShader] = qglslMaskFragmentShader; code[RgbMaskFragmentShaderPass1] = qglslRgbMaskFragmentShaderPass1; code[RgbMaskFragmentShaderPass2] = qglslRgbMaskFragmentShaderPass2; code[RgbMaskWithGammaFragmentShader] = ""; //### code[NoCompositionModeFragmentShader] = ""; code[MultiplyCompositionModeFragmentShader] = ""; //### code[ScreenCompositionModeFragmentShader] = ""; //### code[OverlayCompositionModeFragmentShader] = ""; //### code[DarkenCompositionModeFragmentShader] = ""; //### code[LightenCompositionModeFragmentShader] = ""; //### code[ColorDodgeCompositionModeFragmentShader] = ""; //### code[ColorBurnCompositionModeFragmentShader] = ""; //### code[HardLightCompositionModeFragmentShader] = ""; //### code[SoftLightCompositionModeFragmentShader] = ""; //### code[DifferenceCompositionModeFragmentShader] = ""; //### code[ExclusionCompositionModeFragmentShader] = ""; //### #if defined(QT_DEBUG) // Check that all the elements have been filled: for (int i = 0; i < TotalSnippetCount; ++i) { if (qShaderSnippets[i] == 0) { qFatal("Shader snippet for %s (#%d) is missing!", snippetNameStr(SnippetName(i)).constData(), i); } } #endif snippetsPopulated = true; } QGLShader* fragShader; QGLShader* vertexShader; QByteArray vertexSource; QByteArray fragSource; // Compile up the simple shader: vertexSource.append(qShaderSnippets[MainVertexShader]); vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]); fragSource.append(qShaderSnippets[MainFragmentShader]); fragSource.append(qShaderSnippets[ShockingPinkSrcFragmentShader]); simpleShaderProg = new QGLShaderProgram(context, 0); CachedShader simpleShaderCache(fragSource, vertexSource); bool inCache = simpleShaderCache.load(simpleShaderProg, context); if (!inCache) { vertexShader = new QGLShader(QGLShader::Vertex, context, 0); shaders.append(vertexShader); if (!vertexShader->compileSourceCode(vertexSource)) qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile"); fragShader = new QGLShader(QGLShader::Fragment, context, 0); shaders.append(fragShader); if (!fragShader->compileSourceCode(fragSource)) qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile"); simpleShaderProg->addShader(vertexShader); simpleShaderProg->addShader(fragShader); simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); } simpleShaderProg->link(); if (simpleShaderProg->isLinked()) { if (!inCache) simpleShaderCache.store(simpleShaderProg, context); } else { qCritical("Errors linking simple shader: %s", qPrintable(simpleShaderProg->log())); } // Compile the blit shader: vertexSource.clear(); vertexSource.append(qShaderSnippets[MainWithTexCoordsVertexShader]); vertexSource.append(qShaderSnippets[UntransformedPositionVertexShader]); fragSource.clear(); fragSource.append(qShaderSnippets[MainFragmentShader]); fragSource.append(qShaderSnippets[ImageSrcFragmentShader]); blitShaderProg = new QGLShaderProgram(context, 0); CachedShader blitShaderCache(fragSource, vertexSource); inCache = blitShaderCache.load(blitShaderProg, context); if (!inCache) { vertexShader = new QGLShader(QGLShader::Vertex, context, 0); shaders.append(vertexShader); if (!vertexShader->compileSourceCode(vertexSource)) qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile"); fragShader = new QGLShader(QGLShader::Fragment, context, 0); shaders.append(fragShader); if (!fragShader->compileSourceCode(fragSource)) qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile"); blitShaderProg->addShader(vertexShader); blitShaderProg->addShader(fragShader); blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); } blitShaderProg->link(); if (blitShaderProg->isLinked()) { if (!inCache) blitShaderCache.store(blitShaderProg, context); } else { qCritical("Errors linking blit shader: %s", qPrintable(blitShaderProg->log())); } #ifdef QT_GL_SHARED_SHADER_DEBUG qDebug(" -> QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread()); #endif }
// The address returned here will only be valid until next time this function is called. // The program is return bound. QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog) { for (int i = 0; i < cachedPrograms.size(); ++i) { QGLEngineShaderProg *cachedProg = cachedPrograms[i]; if (*cachedProg == prog) { // Move the program to the top of the list as a poor-man's cache algo cachedPrograms.move(i, 0); cachedProg->program->bind(); return cachedProg; } } QGLShader *vertexShader = 0; QGLShader *fragShader = 0; QGLEngineShaderProg *newProg = 0; bool success = false; do { QByteArray source; // Insert the custom stage before the srcPixel shader to work around an ATI driver bug // where you cannot forward declare a function that takes a sampler as argument. if (prog.srcPixelFragShader == CustomImageSrcFragmentShader) source.append(prog.customStageSource); source.append(qShaderSnippets[prog.mainFragShader]); source.append(qShaderSnippets[prog.srcPixelFragShader]); if (prog.compositionFragShader) source.append(qShaderSnippets[prog.compositionFragShader]); if (prog.maskFragShader) source.append(qShaderSnippets[prog.maskFragShader]); fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); QByteArray description; #if defined(QT_DEBUG) // Name the shader for easier debugging description.append("Fragment shader: main="); description.append(snippetNameStr(prog.mainFragShader)); description.append(", srcPixel="); description.append(snippetNameStr(prog.srcPixelFragShader)); if (prog.compositionFragShader) { description.append(", composition="); description.append(snippetNameStr(prog.compositionFragShader)); } if (prog.maskFragShader) { description.append(", mask="); description.append(snippetNameStr(prog.maskFragShader)); } fragShader->setObjectName(QString::fromLatin1(description)); #endif if (!fragShader->compileSourceCode(source)) { qWarning() << "Warning:" << description << "failed to compile!"; break; } source.clear(); source.append(qShaderSnippets[prog.mainVertexShader]); source.append(qShaderSnippets[prog.positionVertexShader]); vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); #if defined(QT_DEBUG) // Name the shader for easier debugging description.clear(); description.append("Vertex shader: main="); description.append(snippetNameStr(prog.mainVertexShader)); description.append(", position="); description.append(snippetNameStr(prog.positionVertexShader)); vertexShader->setObjectName(QString::fromLatin1(description)); #endif if (!vertexShader->compileSourceCode(source)) { qWarning() << "Warning:" << description << "failed to compile!"; break; } newProg = new QGLEngineShaderProg(prog); // If the shader program's not found in the cache, create it now. newProg->program = new QGLShaderProgram(ctxGuard.context(), this); newProg->program->addShader(vertexShader); newProg->program->addShader(fragShader); // We have to bind the vertex attribute names before the program is linked: newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); if (newProg->useTextureCoords) newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); if (newProg->useOpacityAttribute) newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); if (newProg->usePmvMatrixAttribute) { newProg->program->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); newProg->program->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); newProg->program->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); } newProg->program->link(); if (!newProg->program->isLinked()) { QLatin1String none("none"); QLatin1String br("\n"); QString error; error = QLatin1String("Shader program failed to link,") #if defined(QT_DEBUG) + br + QLatin1String(" Shaders Used:") + br + QLatin1String(" ") + vertexShader->objectName() + QLatin1String(": ") + br + QLatin1String(vertexShader->sourceCode()) + br + QLatin1String(" ") + fragShader->objectName() + QLatin1String(": ") + br + QLatin1String(fragShader->sourceCode()) + br #endif + QLatin1String(" Error Log:\n") + QLatin1String(" ") + newProg->program->log(); qWarning() << error; break; } newProg->program->bind(); if (newProg->maskFragShader != QGLEngineSharedShaders::NoMaskFragmentShader) { GLuint location = newProg->program->uniformLocation("maskTexture"); newProg->program->setUniformValue(location, QT_MASK_TEXTURE_UNIT); } if (cachedPrograms.count() > 30) { // The cache is full, so delete the last 5 programs in the list. // These programs will be least used, as a program us bumped to // the top of the list when it's used. for (int i = 0; i < 5; ++i) { delete cachedPrograms.last(); cachedPrograms.removeLast(); } } cachedPrograms.insert(0, newProg); success = true; } while (false); // Clean up everything if we weren't successful if (!success) { if (newProg) { delete newProg; // Also deletes the QGLShaderProgram which in turn deletes the QGLShaders newProg = 0; } else { if (vertexShader) delete vertexShader; if (fragShader) delete fragShader; } } return newProg; }