Example #1
0
void ShaderEffectSource::updateBackbuffer()
{
    if (!m_sourceItem || !QGLContext::currentContext())
        return;

    // Multisampling is not (for now) supported.
    QSize size = QSize(m_sourceItem->width(), m_sourceItem->height());
    if (!m_textureSize.isEmpty())
        size = m_textureSize;

    if (size.height() > 0 && size.width() > 0) {
        QGLFramebufferObjectFormat format;
        format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
        format.setInternalTextureFormat(m_format);

        if (!m_fbo) {
            m_fbo =  new ShaderEffectBuffer(size, format);
        } else {
            if (!m_fbo->isValid() || m_fbo->size() != size || m_fbo->format().internalTextureFormat() != GLenum(m_format)) {
                delete m_fbo;
                m_fbo = 0;
                m_fbo =  new ShaderEffectBuffer(size, format);
            }
        }
    }

    // Note that real update for the source content happens in shadereffect.cpp
    m_dirtyTexture = false;
}
Example #2
0
void NightModeGraphicsEffect::draw(QPainter* painter)
{
	int pixelRatio = painter->device()->devicePixelRatio();
	QSize size(painter->device()->width() * pixelRatio, painter->device()->height() * pixelRatio);
	if (fbo && fbo->size() != size)
	{
		delete fbo;
		fbo = NULL;
	}
	if (!fbo)
	{
		QGLFramebufferObjectFormat format;
		format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
		format.setInternalTextureFormat(GL_RGBA);
		fbo = new NightModeGraphicsEffectFbo(size, format, pixelRatio);
	}
	QPainter fboPainter(fbo);
	drawSource(&fboPainter);

	painter->save();
	painter->beginNativePainting();
	program->bind();
	const GLfloat pos[] = {-1, -1, +1, -1, -1, +1, +1, +1};
	const GLfloat texCoord[] = {0, 0, 1, 0, 0, 1, 1, 1};
	program->setUniformValue(vars.source, 0);
	program->setAttributeArray(vars.pos, pos, 2);
	program->setAttributeArray(vars.texCoord, texCoord, 2);
	program->enableAttributeArray(vars.pos);
	program->enableAttributeArray(vars.texCoord);
	glBindTexture(GL_TEXTURE_2D, fbo->texture());
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	program->release();
	painter->endNativePainting();
	painter->restore();
}
Example #3
0
QPaintEngine* QGLPixmapData::paintEngine() const
{
    if (!isValid())
        return 0;

    if (m_renderFbo)
        return m_engine;

    if (useFramebufferObjects()) {
        extern QGLWidget* qt_gl_share_widget();

        if (!QGLContext::currentContext())
            qt_gl_share_widget()->makeCurrent();
        QGLShareContextScope ctx(qt_gl_share_widget()->context());

        QGLFramebufferObjectFormat format;
        format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
        format.setSamples(4);
        format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB));

        m_renderFbo = qgl_fbo_pool()->acquire(size(), format);

        if (m_renderFbo) {
            if (!m_engine)
                m_engine = new QGL2PaintEngineEx;
            return m_engine;
        }

        qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine";
    }

    // If the application wants to paint into the QPixmap, we first
    // force it to QImage format and then paint into that.
    // This is simpler than juggling multiple GL contexts.
    const_cast<QGLPixmapData *>(this)->forceToImage();

    if (m_hasFillColor) {
        m_source.fill(PREMUL(m_fillColor.rgba()));
        m_hasFillColor = false;
    }
    return m_source.paintEngine();
}
Example #4
0
QPaintEngine* QGLPixmapData::paintEngine() const
{
    if (!isValid())
        return 0;

    if (m_renderFbo)
        return m_engine;

    if (useFramebufferObjects()) {
        extern QGLWidget* qt_gl_share_widget();

        if (!QGLContext::currentContext())
            const_cast<QGLContext *>(qt_gl_share_context())->makeCurrent();
        QGLShareContextScope ctx(qt_gl_share_context());

        QGLFramebufferObjectFormat format;
        format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
        format.setSamples(4);
        format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB));

        m_renderFbo = qgl_fbo_pool()->acquire(size(), format);

        if (m_renderFbo) {
            if (!m_engine)
                m_engine = new QGL2PaintEngineEx;
            return m_engine;
        }

        qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine";
    }

    m_dirty = true;
    if (m_source.size() != size())
        m_source = QImage(size(), QImage::Format_ARGB32_Premultiplied);
    if (m_hasFillColor) {
        m_source.fill(PREMUL(m_fillColor.rgba()));
        m_hasFillColor = false;
    }
    return m_source.paintEngine();
}
Example #5
0
void FrameInfo::resize(uint w, uint h)
// ----------------------------------------------------------------------------
//   Change the size of the frame buffer used for rendering
// ----------------------------------------------------------------------------
{
    assert(QGLContext::currentContext() ||
           !"FrameInfo::resize without an OpenGL context???");
    
    // Don't change anything if size stays the same
    if (renderFBO && renderFBO->width()==int(w) && renderFBO->height()==int(h))
        return;
    
    IFTRACE(fbo)
        std::cerr << "[FrameInfo] Resize " << w << "x" << h << "\n";

    GraphicSave *save = GL.Save();

    // Delete anything we might have
    purge();

    // If the size is too big, we shouldn't use multisampling, it crashes
    // on MacOSX
    const uint SAMPLES = 4;
    const uint maxTextureSize = GL.MaxTextureSize();
    bool canMultiSample = QGLFramebufferObject::hasOpenGLFramebufferBlit() &&
                          TaoApp->hasFBOMultisample;
    if (w >= maxTextureSize || h >= maxTextureSize)
    {
        IFTRACE(fbo)
            std::cerr << "[FrameInfo] Disable multisample, too big "
                      << maxTextureSize << "\n";
        canMultiSample = false;
    }

    // Select whether we draw directly in texture or blit to it
    // If we can blit and suceed in creating a multisample buffer,
    // we first draw in a multisample buffer
    // with 4 samples per pixel. This cannot be used directly as texture.
    QGLFramebufferObjectFormat format;
    format.setInternalTextureFormat(this->format);

    // Enable mipmap for fbo
    if(PerformancesPage::texture2DMipmap())
        format.setMipmap(true);

    format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
    if (canMultiSample)
    {
        QGLFramebufferObjectFormat mformat(format);
        mformat.setSamples(SAMPLES);
        renderFBO = new QGLFramebufferObject(w, h, mformat);
        // REVISIT: we pass format to have a depth buffer attachment.
        // This is required only when we want to later use depthTexture().
        // TODO: specify at object creation?
        textureFBO = new QGLFramebufferObject(w, h, format);
    }
    else
    {
        renderFBO = new QGLFramebufferObject(w, h, format);
        textureFBO = renderFBO;
    }

    // The value of the min and mag filters of the underlying texture
    // are forced to GL_NEAREST by Qt, which are not the GL defaults.
    // => We must synchronize our cache or some later GL.TexParameter calls
    // may be ignored.
    GLint min, mag;
    GLuint tex = textureFBO->texture();
    glBindTexture(GL_TEXTURE_2D, tex);
    // Query the actual values to be safe
    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min);
    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &mag);
    glBindTexture(GL_TEXTURE_2D, 0);
    GL.BindTexture(GL_TEXTURE_2D, tex);
    GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min);
    GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag);
    if(PerformancesPage::texture2DMipmap())
        GL.GenerateMipmap(GL_TEXTURE_2D);
    GL.Sync(STATE_textures);
    GL.BindTexture(GL_TEXTURE_2D, 0);

    // depthTextureID is optional, resize if we have one
    if (depthTextureID)
        resizeDepthTexture(w, h);
    
    // Store what context we created things in
    this->w = w; this->h = h;
    this->context = (QGLContext *) QGLContext::currentContext();
    IFTRACE(fbo)
        std::cerr << "[FrameInfo] Resized " << w << "x" << h
                  << " in " << context << "\n";

    GL.Restore(save);
    
    // Clear the contents of the newly created frame buffer
    begin(true);
    end();
}
Example #6
0
bool AmbientOcclusionPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
    MeshModel &m=*(md.mm());
    if(ID(filter)==FP_FACE_AMBIENT_OCCLUSION ) perFace=true;
	else perFace = false;
	
	useGPU = par.getBool("useGPU");
	useVBO = par.getBool("useVBO");
	depthTexSize = par.getInt("depthTexSize");
	depthTexArea = depthTexSize*depthTexSize;
	numViews = par.getInt("reqViews");
	errInit = false;
	float dirBias = par.getFloat("dirBias");
	Point3f coneDir = par.getPoint3f("coneDir");
	float coneAngle = par.getFloat("coneAngle");
	
	if(perFace) 
	  m.updateDataMask(MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR);
	else 
		m.updateDataMask(MeshModel::MM_VERTQUALITY | MeshModel::MM_VERTCOLOR);

	
	std::vector<Point3f> unifDirVec;
	GenNormal<float>::Uniform(numViews,unifDirVec);
	
	std::vector<Point3f> coneDirVec;
	GenNormal<float>::UniformCone(numViews, coneDirVec, math::ToRad(coneAngle), coneDir);
	
	std::random_shuffle(unifDirVec.begin(),unifDirVec.end());
	std::random_shuffle(coneDirVec.begin(),coneDirVec.end());

	int unifNum = floor(unifDirVec.size() * (1.0 - dirBias ));
	int coneNum = floor(coneDirVec.size() * (dirBias ));
									
	
	viewDirVec.clear();
	viewDirVec.insert(viewDirVec.end(),unifDirVec.begin(),unifDirVec.begin()+unifNum);
	viewDirVec.insert(viewDirVec.end(),coneDirVec.begin(),coneDirVec.begin()+coneNum);
	
	numViews = viewDirVec.size();


	this->glContext->makeCurrent();
	this->initGL(cb,m.cm.vn);
	unsigned int widgetSize = std::min(maxTexSize, depthTexSize);
	QSize fbosize(widgetSize,widgetSize);
	QGLFramebufferObjectFormat frmt;
	frmt.setInternalTextureFormat(GL_RGBA);
	frmt.setAttachment(QGLFramebufferObject::Depth);
	QGLFramebufferObject fbo(fbosize,frmt);
	qDebug("Start Painting window size %i %i", fbo.width(), fbo.height());
	GLenum err = glGetError();
	fbo.bind();
	processGL(m,viewDirVec);
	fbo.release();
	err = glGetError();
	const GLubyte* errname = gluErrorString(err);
	qDebug("End Painting");
	this->glContext->doneCurrent();
	return !errInit;
}
Example #7
0
void RenderHelper::renderScene(vcg::Shotf &view, MeshModel *mesh, RenderingMode mode, float camNear = 0, float camFar = 0) 
{
  int wt = view.Intrinsics.ViewportPx[0];
  int ht = view.Intrinsics.ViewportPx[1];

  rendmode = mode;

  QSize fbosize(wt, ht);
  QGLFramebufferObjectFormat frmt;
  frmt.setInternalTextureFormat(GL_RGBA);
  frmt.setAttachment(QGLFramebufferObject::Depth);
  QGLFramebufferObject fbo(fbosize,frmt);

  float _near, _far;

  if((camNear <= 0) || (camFar == 0))  // if not provided by caller, then evaluate using bbox
  {
    _near=0.1;
    _far=20000;

    GlShot< vcg::Shot<float> >::GetNearFarPlanes(view, mesh->cm.bbox, _near, _far);
    if(_near <= 0) _near = 0.01;
    if(_far < _near) _far = 1000;
  }
  else
  {
    _near = camNear;
    _far  = camFar;
  }

  assert(_near <= _far);

  GLenum err = glGetError();

  //render to FBO
  fbo.bind();

  glViewport(0, 0, wt, ht);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  GlShot< vcg::Shot<float> >::SetView(view, _near, _far);

	err = glGetError();

  bool use_colors=false;
  bool use_normals=false;

  if(rendmode == NORMAL)
    use_normals = true;

  if(rendmode == COLOR)
    use_colors = true;

  int program = programs[rendmode]; 

  glDisable(GL_LIGHTING);
  //bind indices
  glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo);

  //bind vertices
  glEnable(GL_COLOR_MATERIAL);
  glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
  glEnableClientState(GL_VERTEX_ARRAY);                 // activate vertex coords array
  glVertexPointer(3, GL_FLOAT, 0, 0);                   // last param is offset, not ptr

  err = glGetError();

  glUseProgram(program);

  err = glGetError();

  if(use_colors) 
  {
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, cbo);
    glEnableClientState(GL_COLOR_ARRAY);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
  }
  if(use_normals) 
  {
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, nbo);
    glEnableClientState(GL_NORMAL_ARRAY);
    glNormalPointer(GL_FLOAT, 0, 0);
  }

  err = glGetError();


  if (mesh->cm.fn > 0)
  {
    glDrawElements(GL_TRIANGLES, mesh->cm.fn*3, GL_UNSIGNED_INT, (void *)0); 
  }
  else 
  {
    glDrawArrays(GL_POINTS, 0, mesh->cm.vn);
  }

  if(color != NULL)  delete []color;
  if(depth != NULL)  delete []depth;

  color  = new unsigned char[wt * ht * 3];
  depth  = new floatbuffer();
  depth->init(wt,ht);

  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glPixelStorei(GL_PACK_ALIGNMENT, 1);

  glReadPixels( 0, 0, wt, ht, GL_RGB, GL_UNSIGNED_BYTE, color);
  glReadPixels( 0, 0, wt, ht, GL_DEPTH_COMPONENT, GL_FLOAT, depth->data);


  //----- convert depth in world units
  mindepth =  1000000;
  maxdepth = -1000000;
	for(int pixit = 0; pixit<wt*ht; pixit++)
	{
	 if (depth->data[pixit] == 1.0)
		depth->data[pixit] = 0;
	 else
		depth->data[pixit] = _near*_far / (_far - depth->data[pixit]*(_far-_near));

   // min and max for normalization purposes (e.g. weighting)
   if(depth->data[pixit] > maxdepth)
     maxdepth = depth->data[pixit];
   if(depth->data[pixit] > maxdepth)
     maxdepth = depth->data[pixit];
	}

  //-----

  err = glGetError();

  glDisableClientState(GL_VERTEX_ARRAY);                // deactivate vertex array
  if(use_colors) glDisableClientState(GL_COLOR_ARRAY);
  if(use_normals) glDisableClientState(GL_NORMAL_ARRAY);

  err = glGetError();

  // bind with 0, so, switch back to normal pointer operation
  glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
  glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);

  glEnable(GL_LIGHTING);

  // standard opengl pipeline is re-activated
  glUseProgram(0);

  GlShot< vcg::Shot<float> >::UnsetView();

  glFinish();
  
  //QImage l=fbo.toImage();
  //l.save("rendering.jpg");

  fbo.release();
}