// 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;
	}
Beispiel #2
0
Object *SceneParser::loadObject(KeyValues *data)
{
  const char *format = data->getString("format");
  if(!format) {
    fprintf(stderr, "Key 'format' not found on Object\n");
    return NULL;
  }

  Mesh *mesh;
  if(strcmp("OFF", format) == 0 || strcmp("PLY", format) == 0) {
    const char *file = data->getString("file");
    if(!file) {
      fprintf(stderr, "Key 'file' not found on Object\n");
      return NULL;
    }
    char *filename = resolvePath(file);

    MeshData *meshData;

    if(strcmp("OFF", format) == 0) {
      meshData = MeshLoaderOFF::load(filename);
    }
    else if(strcmp("PLY", format) == 0) {
      meshData = MeshLoaderPLY::load(filename);
    }

    if(!meshData) {
      fprintf(stderr, "Failed to load MeshData of %s\n", filename);
      delete[] filename;
      return NULL;
    }

    if(data->getInt("normalize", 1)) {
      meshData->normalize();
    }
    if(data->getInt("normals", 0)) {
      meshData->computeNormals();
    }

    const char *texcoords = data->getString("texcoords");
    if(texcoords) {
      MeshData::TexCoordsMethod method;
      if(strcmp(texcoords, "sphere") == 0) {
        method = MeshData::TexCoordsSphere;
      }
      else if(strcmp(texcoords, "cylinder") == 0) {
        method = MeshData::TexCoordsCylinder;
      }
      meshData->genTexCoords(method);
    }

    if(data->getInt("tangents", 0)) {
      meshData->genTangents();
    }

    mesh = new Mesh(meshData);

    delete meshData;
    delete[] filename;
  }
  else {
    fprintf(stderr, "Invalid object format: %s\n", format);
    return NULL;
  }

  Material *material = NULL;
  QGLShaderProgram *shaderProgram = new QGLShaderProgram();

  KeyValues *key;

  bool error = false;
  key = data->firstSubKey();
  while(key) {
    if(strcmp(key->name(), "shader") == 0) {
      QGLShader *shader = loadShader(key);
      if(shader) {
        shaderProgram->addShader(shader);
      }
      else {
        fprintf(stderr, "Failed to load shader\n");
        error = true;
        break;
      }
    }
    else if (strcmp(key->name(), "material") == 0) {
      if(material) {
        fprintf(stderr, "Duplicated material definition\n");
      }
      else {
        material = loadMaterial(key);
      }
    }
    key = key->nextKey();
  }

  if(!shaderProgram->link()) {
    fprintf(stderr, "Failed to link shader program\n");
    error = true;
  }

  if(error) {
    if(material) {
      delete material;
    }
    delete shaderProgram;
    delete mesh;
    return NULL;
  }

  Object *object = new Object(mesh, shaderProgram, material);

  object->scale(data->getFloat("scale", 1.0));

  float pitch = data->getFloat("pitch", 0.0);
  float yaw = data->getFloat("yaw", 0.0);
  object->rotation(pitch, yaw);

  const char *position = data->getString("position");
  if(position) {
    object->position(strtoV3D(position));
  }

  key = data->firstSubKey();
  while(key) {
    if (strcmp(key->name(), "texture") == 0) {
      Texture *texture = loadTexture(key);
      if(texture) {
        object->addTexture(texture);
      }
      else {
        fprintf(stderr, "Failed to load texture\n");
        error = true;
        break;
      }
    }
    key = key->nextKey();
  }

  if(error) {
    return object;
  }

  return object;
}
Beispiel #3
0
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;
}
Beispiel #4
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;
}
Beispiel #5
0
void GLWidget::drawPoint(const Vector& pos, float r, float g, float b) 
{
    static bool created = false;
    static QGLShaderProgram program;
    static GLuint VAO;

    if (!created)
    {
        created = true;
        // 1. Create shaders
        QGLShader vs(QGLShader::Vertex);
        vs.compileSourceCode("#version 330 core \n in vec3 vertex; in vec3 color; uniform mat4 modelViewProjectionMatrix; out vec4 frontColor;    void main() { frontColor = vec4(color,1); gl_Position = modelViewProjectionMatrix * vec4(vertex, 1.0); }");
        QGLShader fs(QGLShader::Fragment);
        fs.compileSourceCode("#version 330 core \n in vec4 frontColor; out vec4 FragColor; void main() {FragColor = frontColor;}");	
        program.addShader(&vs);
        program.addShader(&fs);
        program.link();

        // Get location of VS attributes
        GLuint vertexLoc = program.attributeLocation("vertex");
        GLuint colorLoc  = program.attributeLocation("color");

        // 2. Create VBO Buffers

        // Create & bind empty VAO
        glGenVertexArrays(1, &VAO);
        glBindVertexArray(VAO);
        // Create VBO with (x,y,z) coordinates
        float coords[] = { 0, 0, 0}; 
        GLuint VBO_coords;
        glGenBuffers(1, &VBO_coords);
        glBindBuffer(GL_ARRAY_BUFFER, VBO_coords);
        glBufferData(GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW);
        glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(vertexLoc);
        // Create VBO with (r,g,b) color
        float colors[] = {r, g, b};
        GLuint VBO_colors;
        glGenBuffers(1, &VBO_colors);
        glBindBuffer(GL_ARRAY_BUFFER, VBO_colors);
        glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
        glVertexAttribPointer(colorLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(colorLoc);

        glBindVertexArray(0);
    }

    program.bind();

    // 1. Define uniforms
    QMatrix4x4 T;
    T.translate(pos); 
    QMatrix4x4 MVP = camera()->projectionMatrix() * camera()->modelviewMatrix()*T;
    program.setUniformValue("modelViewProjectionMatrix", MVP);    

    // 2. Draw
    glPointSize(8);
    glBindVertexArray (VAO);
    glDrawArrays(GL_POINTS, 0, 1);
    glBindVertexArray(0);
    program.release();
}
Beispiel #6
0
void GLWidget::drawAxes() 
{
    float L = 1;

    static bool created = false;
    static QGLShaderProgram program;
    static GLuint VAO_axes;

    if (!created)
    {
        created = true;
        // 1. Create shaders

        // VS 
        QGLShader vs(QGLShader::Vertex);
        vs.compileSourceCode("#version 330 core \n in vec3 vertex; in vec3 color; uniform mat4 modelViewProjectionMatrix; out vec4 frontColor;    void main() { frontColor = vec4(color,1); gl_Position = modelViewProjectionMatrix * vec4(vertex, 1.0); }");

        // FS    
        QGLShader fs(QGLShader::Fragment);
        fs.compileSourceCode("#version 330 core \n in vec4 frontColor; out vec4 FragColor; void main() {FragColor = frontColor;}");	

        // Program
        program.addShader(&vs);
        program.addShader(&fs);
        program.link();

        // Get location of VS attributes
        GLuint vertexLoc = program.attributeLocation("vertex");
        GLuint colorLoc  = program.attributeLocation("color");

        // 2. Create VBO Buffers

        // Create & bind empty VAO
        glGenVertexArrays(1, &VAO_axes);
        glBindVertexArray(VAO_axes);


        // Create VBO with (x,y,z) coordinates
        
        float coords[] = { 0, 0, 0, 
                           L, 0, 0, 
                           0, 0, 0, 
                           0, L, 0,
                           0, 0, 0,
                           0, 0, L};

        GLuint VBO_coords;
        glGenBuffers(1, &VBO_coords);
        glBindBuffer(GL_ARRAY_BUFFER, VBO_coords);
        glBufferData(GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW);
        glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(vertexLoc);

        // Create VBO with (r,g,b) color
        float colors[] = {1, 0, 0, 1, 0, 0, 
                          0, 1, 0, 0, 1, 0,
                          0, 0, 1, 0, 0, 1};
        GLuint VBO_colors;
        glGenBuffers(1, &VBO_colors);
        glBindBuffer(GL_ARRAY_BUFFER, VBO_colors);
        glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
        glVertexAttribPointer(colorLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(colorLoc);

        glBindVertexArray(0);


    }

    program.bind();

    // 1. Define uniforms 
    float r = max(MIN_AXES_LENGTH, scene()->boundingBox().radius());
    QMatrix4x4 scale;
    scale.scale(r,r,r);
    QMatrix4x4 MVP = camera()->projectionMatrix() * camera()->modelviewMatrix()*scale;
    program.setUniformValue("modelViewProjectionMatrix", MVP);    

    // 2. Draw
    glBindVertexArray (VAO_axes);
    glDrawArrays(GL_LINES, 0, 6);
    glBindVertexArray(0);

    program.release();

    // 5. CleanUp
    /*
    glDeleteVertexArrays(1, &VAO_axes);
    glDeleteBuffers(1, &VBO_coords);
    glDeleteBuffers(1, &VBO_colors);
    */
    
/* 
    glDisable(GL_LIGHTING);
    glBegin(GL_LINES);
    glColor3f(1,0,0); glVertex3f(0,0,0); glVertex3f(L,0,0); // X
    glColor3f(0,1,0); glVertex3f(0,0,0); glVertex3f(0,L,0); // Y
    glColor3f(0,0,1); glVertex3f(0,0,0); glVertex3f(0,0,L); // Z
    glEnd();
    glEnable(GL_LIGHTING);
   */ 

}