// // Load shader // void Ex07opengl::Shader(QGLShaderProgram& shader,QString vert,QString frag) { // Vertex shader if (vert.length() && !shader.addShaderFromSourceFile(QGLShader::Vertex,vert)) Fatal("Error compiling "+vert+"\n"+shader.log()); // Fragment shader if (frag.length() && !shader.addShaderFromSourceFile(QGLShader::Fragment,frag)) Fatal("Error compiling "+frag+"\n"+shader.log()); // Link if (!shader.link()) Fatal("Error linking shader\n"+shader.log()); }
// See programCache doc comments to see how caching works here. bool StelQGLGLSLShader::build() { // Unlocked - i.e. not Modified if(state == State_Unlocked && program != NULL) { state = State_Built; return true; } QGLShaderProgram* cached = getProgramFromCache(); // No matching program in cache, need to link a new program. if(cached == NULL) { uintptr_t id = 0; QGLShaderProgram* newProgram = new QGLShaderProgram(renderer->getGLContext()); // Add all the shaders to the program. foreach(QGLShader* shader, defaultVertexShaders) { if(!newProgram->addShader(shader)) {goto FAILED;} id += reinterpret_cast<uintptr_t>(shader); } foreach(OptionalShader shader, namedVertexShaders) { if(shader.enabled) { if(!newProgram->addShader(shader.shader)) {goto FAILED;} id += reinterpret_cast<uintptr_t>(shader.shader); } } foreach(QGLShader* shader, defaultFragmentShaders) { if(!newProgram->addShader(shader)) {goto FAILED;} id += reinterpret_cast<uintptr_t>(shader); } Q_ASSERT_X(id > 0, Q_FUNC_INFO, "Trying to build() a StelQGLGLSLShader " "but no vertex or fragment shaders were added"); // Link the program. if(!newProgram->link()) {goto FAILED;} aggregatedLog += "Built successfully"; // Add the program to the cache, and set the current program to it. programCache.insert(id, newProgram); program = newProgram; state = State_Built; return true; // And here I present to you a viable application of the fabled GOTO statement and a label. // (good way to do error recovery in plan C and when using return codes, BTW) FAILED: aggregatedLog += newProgram->log(); delete newProgram; return false; }
bool prepareShaderProgram( QGLShaderProgram& program, const QString& vertexShaderPath, const QString& fragmentShaderPath ) { // First we load and compile the vertex shader... bool result = program.addShaderFromSourceFile( QGLShader::Vertex, vertexShaderPath ); if ( !result ) qWarning() << program.log(); // ...now the fragment shader... result = program.addShaderFromSourceFile( QGLShader::Fragment, fragmentShaderPath ); if ( !result ) qWarning() << program.log(); // ...and finally we link them to resolve any references. result = program.link(); if ( !result ) qWarning() << "Could not link shader program:" << program.log(); return result; }
bool GLWidgetRendererPrivate::prepareShaderProgram(const VideoFormat &fmt, ColorTransform::ColorSpace cs) { // isSupported(pixfmt) if (!fmt.isValid()) return false; releaseShaderProgram(); video_format.setPixelFormatFFmpeg(fmt.pixelFormatFFmpeg()); colorTransform.setInputColorSpace(cs); // TODO: only to kinds, packed.glsl, planar.glsl QString frag; if (fmt.isPlanar()) { frag = getShaderFromFile("shaders/planar.f.glsl"); } else { frag = getShaderFromFile("shaders/rgb.f.glsl"); } if (frag.isEmpty()) return false; if (fmt.isRGB()) { frag.prepend("#define INPUT_RGB\n"); } else { frag.prepend(QString("#define YUV%1P\n").arg(fmt.bitsPerPixel(0))); } if (fmt.isPlanar() && fmt.bytesPerPixel(0) == 2) { if (fmt.isBigEndian()) frag.prepend("#define LA_16BITS_BE\n"); else frag.prepend("#define LA_16BITS_LE\n"); } if (cs == ColorTransform::BT601) { frag.prepend("#define CS_BT601\n"); } else if (cs == ColorTransform::BT709) { frag.prepend("#define CS_BT709\n"); } #if NO_QGL_SHADER program = createProgram(kVertexShader, frag.toUtf8().constData()); if (!program) { qWarning("Could not create shader program."); return false; } // vertex shader. we can set attribute locations calling glBindAttribLocation a_Position = glGetAttribLocation(program, "a_Position"); a_TexCoords = glGetAttribLocation(program, "a_TexCoords"); u_matrix = glGetUniformLocation(program, "u_MVP_matrix"); u_bpp = glGetUniformLocation(program, "u_bpp"); u_opacity = glGetUniformLocation(program, "u_opacity"); // fragment shader u_colorMatrix = glGetUniformLocation(program, "u_colorMatrix"); #else if (!shader_program->addShaderFromSourceCode(QGLShader::Vertex, kVertexShader)) { qWarning("Failed to add vertex shader: %s", shader_program->log().toUtf8().constData()); return false; } if (!shader_program->addShaderFromSourceCode(QGLShader::Fragment, frag)) { qWarning("Failed to add fragment shader: %s", shader_program->log().toUtf8().constData()); return false; } if (!shader_program->link()) { qWarning("Failed to link shader program...%s", shader_program->log().toUtf8().constData()); return false; } // vertex shader a_Position = shader_program->attributeLocation("a_Position"); a_TexCoords = shader_program->attributeLocation("a_TexCoords"); u_matrix = shader_program->uniformLocation("u_MVP_matrix"); u_bpp = shader_program->uniformLocation("u_bpp"); u_opacity = shader_program->uniformLocation("u_opacity"); // fragment shader u_colorMatrix = shader_program->uniformLocation("u_colorMatrix"); #endif //NO_QGL_SHADER qDebug("glGetAttribLocation(\"a_Position\") = %d\n", a_Position); qDebug("glGetAttribLocation(\"a_TexCoords\") = %d\n", a_TexCoords); qDebug("glGetUniformLocation(\"u_MVP_matrix\") = %d\n", u_matrix); qDebug("glGetUniformLocation(\"u_bpp\") = %d\n", u_bpp); qDebug("glGetUniformLocation(\"u_opacity\") = %d\n", u_opacity); qDebug("glGetUniformLocation(\"u_colorMatrix\") = %d\n", u_colorMatrix); if (fmt.isRGB()) u_Texture.resize(1); else u_Texture.resize(fmt.channels()); for (int i = 0; i < u_Texture.size(); ++i) { QString tex_var = QString("u_Texture%1").arg(i); #if NO_QGL_SHADER u_Texture[i] = glGetUniformLocation(program, tex_var.toUtf8().constData()); #else u_Texture[i] = shader_program->uniformLocation(tex_var); #endif qDebug("glGetUniformLocation(\"%s\") = %d\n", tex_var.toUtf8().constData(), u_Texture[i]); } return true; }
QGLPEXShaderManager::QGLPEXShaderManager(const QGLContext* context) { ctx = const_cast<QGLContext*>(context); defaultVertexShader= new QGLShader(QGLShader::VertexShader, context); defaultVertexShader->addSource(QLatin1String(qglslDefaultVertexShader)); if (!defaultVertexShader->compile()) qWarning() << "Default vertex shader failed to compile: " << defaultVertexShader->log(); noBrushShader = new QGLShader(QGLShader::FragmentShader, context); noBrushShader->addSource(QLatin1String(qglslFragmentShaderMain)); noBrushShader->addSource(QLatin1String(qglslNoBrushFragmentShader)); if (!noBrushShader->compile()) qWarning() << "No brush shader failed to compile:" << noBrushShader->log(); // Create a program for noBrush: QGLShaderProgram* noBrushProg = new QGLShaderProgram(ctx); noBrushProg->addShader(defaultVertexShader); noBrushProg->addShader(noBrushShader); if (!noBrushProg->link()) qWarning() << "NoBrush shader program failed to link:" << noBrushProg->log(); // Add noBrush Program to cache: QGLCachedShaderProg cachedProg; cachedProg.vertexShader = defaultVertexShader; cachedProg.brushShader = noBrushShader; cachedProg.compositionShader = 0; cachedProg.shader = noBrushProg; cachedPrograms.append(cachedProg); // Set state useGlobalOpacity = true; currentBrushStyle = Qt::NoBrush; currentTransformType = FullTransform; shaderProgNeedsChanging = false; activeProgram = noBrushProg; solidBrushShader = 0; conicalBrushVertexShader = 0; conicalBrushFragmentShader = 0; radialBrushVertexShader = 0; radialBrushFragmentShader = 0; linearBrushVertexShader = 0; linearBrushFragmentShader = 0; patternBrushVertexShader = 0; patternBrushFragmentShader = 0; textureBrushFragmentShader = 0; textureBrushVertexShader = 0; simpleFragmentShader = 0; simpleShaderProgram = 0; imageVertexShader = 0; imageFragmentShader = 0; imageShaderProgram = 0; textVertexShader = 0; textFragmentShader = 0; textShaderProgram = 0; }
bool QGLPEXShaderManager::useCorrectShaderProg() { if (!shaderProgNeedsChanging) { activeProgram->use(); return false; } const char* fragmentShaderMainSrc = qglslFragmentShaderMain; QGLShader* vertexShader = defaultVertexShader; QGLShader* fragmentShader = noBrushShader; // Make sure we compile up the correct brush shader switch (currentBrushStyle) { case Qt::NoBrush: break; case Qt::SolidPattern: if (!solidBrushShader) { qDebug("Compiling qglslSolidBrushFragmentShader"); solidBrushShader = new QGLShader(QGLShader::FragmentShader, ctx); solidBrushShader->addSource(QLatin1String(qglslNoOpacityFragmentShaderMain)); solidBrushShader->addSource(QLatin1String(qglslSolidBrushFragmentShader)); if (!solidBrushShader->compile()) qWarning() << "qglslSolidBrush failed to compile:" << solidBrushShader->log(); } fragmentShader = solidBrushShader; break; case Qt::TexturePattern: if (!textureBrushVertexShader) { qDebug("Compiling qglslTextureBrushVertexShader"); textureBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx); textureBrushVertexShader->addSource(QLatin1String(qglslTextureBrushVertexShader)); if (!textureBrushVertexShader->compile()) { qWarning() << "qglslTextureBrushVertexShader failed to compile: " << textureBrushVertexShader->log(); } } vertexShader = textureBrushVertexShader; if (!textureBrushFragmentShader) { qDebug("Compiling qglslTextureBrushFragmentShader"); textureBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx); textureBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc)); textureBrushFragmentShader->addSource(QLatin1String(qglslTextureBrushFragmentShader)); if (!textureBrushFragmentShader->compile()) { qWarning() << "qglslTextureBrushFragmentShader failed to compile:" << textureBrushFragmentShader->log(); } } fragmentShader = textureBrushFragmentShader; break; case Qt::LinearGradientPattern: if (!linearBrushVertexShader) { qDebug("Compiling qglslLinearGradientBrushVertexShader"); linearBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx); linearBrushVertexShader->addSource(QLatin1String(qglslLinearGradientBrushVertexShader)); if (!linearBrushVertexShader->compile()) { qWarning() << "qglslLinearGradientBrushVertexShader failed to compile: " << linearBrushVertexShader->log(); } } vertexShader = linearBrushVertexShader; if (!linearBrushFragmentShader) { qDebug("Compiling qglslLinearGradientBrushFragmentShader"); linearBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx); linearBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc)); linearBrushFragmentShader->addSource(QLatin1String(qglslLinearGradientBrushFragmentShader)); if (!linearBrushFragmentShader->compile()) { qWarning() << "qglslLinearGradientBrushFragmentShader failed to compile:" << linearBrushFragmentShader->log(); } } fragmentShader = linearBrushFragmentShader; break; case Qt::RadialGradientPattern: if (!radialBrushVertexShader) { qDebug("Compiling qglslRadialGradientBrushVertexShader"); radialBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx); radialBrushVertexShader->addSource(QLatin1String(qglslRadialGradientBrushVertexShader)); if (!radialBrushVertexShader->compile()) { qWarning() << "qglslRadialGradientBrushVertexShader failed to compile: " << radialBrushVertexShader->log(); } } vertexShader = radialBrushVertexShader; if (!radialBrushFragmentShader) { qDebug("Compiling qglslRadialGradientBrushFragmentShader"); radialBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx); radialBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc)); radialBrushFragmentShader->addSource(QLatin1String(qglslRadialGradientBrushFragmentShader)); if (!radialBrushFragmentShader->compile()) { qWarning() << "qglslRadialGradientBrushFragmentShader failed to compile:" << radialBrushFragmentShader->log(); } } fragmentShader = radialBrushFragmentShader; break; case Qt::ConicalGradientPattern: // FIXME: We currently use the same vertex shader as radial brush if (!conicalBrushVertexShader) { qDebug("Compiling qglslConicalGradientBrushVertexShader"); conicalBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx); conicalBrushVertexShader->addSource(QLatin1String(qglslConicalGradientBrushVertexShader)); if (!conicalBrushVertexShader->compile()) { qWarning() << "qglslConicalGradientBrushVertexShader failed to compile: " << conicalBrushVertexShader->log(); } } vertexShader = conicalBrushVertexShader; if (!conicalBrushFragmentShader) { qDebug("Compiling qglslConicalGradientBrushFragmentShader"); conicalBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx); conicalBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc)); conicalBrushFragmentShader->addSource(QLatin1String(qglslConicalGradientBrushFragmentShader)); if (!conicalBrushFragmentShader->compile()) { qWarning() << "qglslConicalGradientBrushFragmentShader failed to compile:" << conicalBrushFragmentShader->log(); } } fragmentShader = conicalBrushFragmentShader; break; case Qt::Dense1Pattern: case Qt::Dense2Pattern: case Qt::Dense3Pattern: case Qt::Dense4Pattern: case Qt::Dense5Pattern: case Qt::Dense6Pattern: case Qt::Dense7Pattern: case Qt::HorPattern: case Qt::VerPattern: case Qt::CrossPattern: case Qt::BDiagPattern: case Qt::FDiagPattern: case Qt::DiagCrossPattern: if (!patternBrushVertexShader) { qDebug("Compiling qglslPatternBrushVertexShader"); patternBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx); patternBrushVertexShader->addSource(QLatin1String(qglslPatternBrushVertexShader)); if (!patternBrushVertexShader->compile()) { qWarning() << "qglslPatternBrushVertexShader failed to compile: " << patternBrushVertexShader->log(); } } vertexShader = patternBrushVertexShader; if (!patternBrushFragmentShader) { qDebug("Compiling qglslPatternBrushFragmentShader"); patternBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx); patternBrushFragmentShader->addSource(QLatin1String(qglslNoOpacityFragmentShaderMain)); patternBrushFragmentShader->addSource(QLatin1String(qglslPatternBrushFragmentShader)); if (!patternBrushFragmentShader->compile()) { qWarning() << "qglslPatternBrushFragmentShader failed to compile:" << patternBrushFragmentShader->log(); } } fragmentShader = patternBrushFragmentShader; break; default: qWarning("Unimplemented brush style (%d)", currentBrushStyle); } // Now newBrushShader is set correctly, check to see if we already have the program // already linked and ready to go in the cache: bool foundProgram = false; foreach (QGLCachedShaderProg cachedProg, cachedPrograms) { if ((cachedProg.vertexShader == vertexShader) && (cachedProg.brushShader == fragmentShader) && (cachedProg.compositionShader == 0) ) { activeProgram = cachedProg.shader; foundProgram = true; break; } } if (!foundProgram) { qDebug() << "Linking shader program for " << currentBrushStyle; // Required program not found - create it. QGLShaderProgram* newProg = new QGLShaderProgram(ctx); newProg->addShader(vertexShader); newProg->addShader(fragmentShader); if (!newProg->link()) qWarning() << "Shader program for " << currentBrushStyle << "failed to link:" << newProg->log(); QGLCachedShaderProg cachedProg; cachedProg.vertexShader = vertexShader; cachedProg.brushShader = fragmentShader; cachedProg.compositionShader = 0; cachedProg.shader = newProg; cachedPrograms.append(cachedProg); activeProgram = newProg; } activeProgram->use(); shaderProgNeedsChanging = false; return true; }
// // Initialize // void Hw1opengl::initializeGL() { if (init) return; init = true; // Enable Z-buffer depth testing glEnable(GL_DEPTH_TEST); // Build shaders QGLShaderProgram* shader = new QGLShaderProgram(); if (!shader->addShaderFromSourceFile(QGLShader::Vertex,":/ex01.vert")) Fatal("Error compiling ex01.vert\n"+shader->log()); if (!shader->addShaderFromSourceFile(QGLShader::Fragment,":/ex01.frag")) Fatal("Error compiling ex01.frag\n"+shader->log()); if (!shader->link()) Fatal("Error linking shader\n"+shader->log()); shaders.push_back(shader); shader = new QGLShaderProgram(); if (!shader->addShaderFromSourceFile(QGLShader::Vertex,":/hw1.vert")) Fatal("Error compiling hw1.vert\n"+shader->log()); if (!shader->addShaderFromSourceFile(QGLShader::Fragment,":/hw1.frag")) Fatal("Error compiling hw1.frag\n"+shader->log()); if (!shader->link()) Fatal("Error linking shader\n"+shader->log()); shaders.push_back(shader); // Cube objects.push_back(new Cube()); // Teapot Teapot* pot = new Teapot(8); pot->scale(0.5); pot->color(0,1,1); objects.push_back(pot); // Tyra WaveOBJ* tyra=0; try { tyra = new WaveOBJ(":/tyra.obj"); } catch (QString err) { Fatal("Error loading object\n"+err); } if (tyra) { tyra->color(1,1,0); objects.push_back(tyra); } // Set initial object obj = objects[0]; // Start 100 fps timer connected to updateGL timer.setInterval(10); connect(&timer,SIGNAL(timeout()),this,SLOT(updateGL())); timer.start(); time.start(); }