Пример #1
0
  void doCompute(TTile &tile, double frame, const TRenderSettings &info) {
    bool isWarped = m_warped.isConnected();

    if (!isWarped) return;

    if (fabs(m_intensity->getValue(frame)) < 0.01) {
      m_warped->compute(tile, frame, info);
      return;
    }

    int shrink      = (info.m_shrinkX + info.m_shrinkY) / 2;
    double scale    = sqrt(fabs(info.m_affine.det()));
    double gridStep = 1.5 * m_gridStep->getValue(frame);

    WarpParams params;
    params.m_intensity   = m_intensity->getValue(frame) / gridStep;
    params.m_warperScale = scale * gridStep;
    params.m_sharpen     = m_sharpen->getValue();
    params.m_shrink      = shrink;
    double period        = m_period->getValue(frame) / info.m_shrinkX;
    double count         = m_count->getValue(frame);
    double cycle         = m_cycle->getValue(frame) / info.m_shrinkX;
    double scaleX        = m_scaleX->getValue(frame) / 100.0;
    double scaleY        = m_scaleY->getValue(frame) / 100.0;
    double angle         = -m_angle->getValue(frame);
    TPointD center       = m_center->getValue(frame) * (1.0 / info.m_shrinkX);

    // The warper is calculated on a standard reference, with fixed dpi. This
    // makes sure
    // that the lattice created for the warp does not depend on camera
    // transforms and resolution.
    TRenderSettings warperInfo(info);
    double warperScaleFactor = 1.0 / params.m_warperScale;
    warperInfo.m_affine      = TScale(warperScaleFactor) * info.m_affine;

    // Retrieve tile's geometry
    TRectD tileRect;
    {
      TRasterP tileRas = tile.getRaster();
      tileRect =
          TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy()));
    }

    // Build the compute rect
    TRectD warpedBox, warpedComputeRect, tileComputeRect;
    m_warped->getBBox(frame, warpedBox, info);

    getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect,
                        params);

    if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return;
    if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0)
      return;

    TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect);
    double warperEnlargement = getWarperEnlargement(params);
    warperComputeRect        = warperComputeRect.enlarge(warperEnlargement);
    warperComputeRect.x0     = tfloor(warperComputeRect.x0);
    warperComputeRect.y0     = tfloor(warperComputeRect.y0);
    warperComputeRect.x1     = tceil(warperComputeRect.x1);
    warperComputeRect.y1     = tceil(warperComputeRect.y1);

    // Compute the warped tile
    TTile tileIn;
    m_warped->allocateAndCompute(
        tileIn, warpedComputeRect.getP00(),
        TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()),
        tile.getRaster(), frame, info);
    TRasterP rasIn = tileIn.getRaster();

    // Compute the warper tile
    TSpectrum::ColorKey colors[] = {TSpectrum::ColorKey(0, TPixel32::White),
                                    TSpectrum::ColorKey(0.5, TPixel32::Black),
                                    TSpectrum::ColorKey(1, TPixel32::White)};

    TSpectrumParamP ripplecolors = TSpectrumParamP(tArrayCount(colors), colors);

    // Build the multiradial
    warperInfo.m_affine = warperInfo.m_affine * TTranslation(center) *
                          TRotation(angle) * TScale(scaleX, scaleY);
    TAffine aff      = warperInfo.m_affine.inv();
    TPointD posTrasf = aff * (warperComputeRect.getP00());
    TRasterP rasWarper =
        rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy());
    multiRadial(rasWarper, posTrasf, ripplecolors, period, count, cycle, aff,
                frame);
    // TImageWriter::save(TFilePath("C:\\ripple.tif"), rasWarper);

    // Warp
    TPointD db;
    TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db));
    TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI);

    TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00());
    TPointD warperPos(
        (TScale(params.m_warperScale) * warperComputeRect.getP00()) -
        tileComputeRect.getP00());
    warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params);
  }
Пример #2
0
void subCompute(TRasterFxPort &m_input, TTile &tile, double frame,
                const TRenderSettings &ri, TPointD p00, TPointD p01,
                TPointD p11, TPointD p10, int details, bool wireframe,
                TDimension m_offScreenSize, bool isCast) {
  TPixel32 bgColor;
  TRectD outBBox, inBBox;
  outBBox = inBBox = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(),
                                                    tile.getRaster()->getLy()));
  m_input->getBBox(frame, inBBox, ri);
  if (inBBox == TConsts::infiniteRectD)  // e' uno zerario
    inBBox = outBBox;

  int inBBoxLx = (int)inBBox.getLx() / ri.m_shrinkX;
  int inBBoxLy = (int)inBBox.getLy() / ri.m_shrinkY;

  if (inBBox.isEmpty()) return;

  if (p00 == p01 && p00 == p10 && p00 == p11 &&
      !isCast)  // significa che non c'e' deformazione
  {
    m_input->compute(tile, frame, ri);
    return;
  }

  TRaster32P rasIn;
  TPointD rasInPos;

  if (!wireframe) {
    if (ri.m_bpp == 64 || ri.m_bpp == 48) {
      TRaster64P aux = TRaster64P(inBBoxLx, inBBoxLy);
      rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY);
      TTile tmp(aux, rasInPos);
      m_input->compute(tmp, frame, ri);
      rasIn = TRaster32P(inBBoxLx, inBBoxLy);
      TRop::convert(rasIn, aux);
    } else {
      rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY);
      TTile tmp(TRaster32P(inBBoxLx, inBBoxLy), rasInPos);
      m_input->allocateAndCompute(tmp, rasInPos, TDimension(inBBoxLx, inBBoxLy),
                                  TRaster32P(), frame, ri);
      rasIn = tmp.getRaster();
    }
  }

  unsigned int texWidth  = 2;
  unsigned int texHeight = 2;

  while (texWidth < (unsigned int)inBBoxLx) texWidth = texWidth << 1;

  while (texHeight < (unsigned int)inBBoxLy) texHeight = texHeight << 1;

  while (texWidth > 1024 || texHeight > 1024)  // avevo usato la costante
                                               // GL_MAX_TEXTURE_SIZE invece di
                                               // 1024, ma non funzionava!
  {
    inBBoxLx  = inBBoxLx >> 1;
    inBBoxLy  = inBBoxLy >> 1;
    texWidth  = texWidth >> 1;
    texHeight = texHeight >> 1;
  }

  if (rasIn->getLx() != inBBoxLx || rasIn->getLy() != inBBoxLy) {
    TRaster32P rasOut = TRaster32P(inBBoxLx, inBBoxLy);
    TRop::resample(rasOut, rasIn,
                   TScale((double)rasOut->getLx() / rasIn->getLx(),
                          (double)rasOut->getLy() / rasIn->getLy()));
    rasIn = rasOut;
  }

  int rasterWidth  = tile.getRaster()->getLx() + 2;
  int rasterHeight = tile.getRaster()->getLy() + 2;
  assert(rasterWidth > 0);
  assert(rasterHeight > 0);

  TRectD clippingRect =
      TRectD(tile.m_pos,
             TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy()));
#ifdef CREATE_GL_CONTEXT_ONE_TIME
  int ret = wglMakeCurrent(m_offScreenGL.m_offDC, m_offScreenGL.m_hglRC);
  assert(ret == TRUE);
#else
  TOfflineGL offScreenRendering(TDimension(rasterWidth, rasterHeight));
  //#ifdef _WIN32
  offScreenRendering.makeCurrent();
//#else
//#if defined(LINUX) || defined(MACOSX)
// offScreenRendering.m_offlineGL->makeCurrent();
//#endif
#endif

  checkErrorsByGL
      // disabilito quello che non mi serve per le texture
      glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
  glDisable(GL_DITHER);
  glDisable(GL_DEPTH_TEST);
  glCullFace(GL_FRONT);
  glDisable(GL_STENCIL_TEST);
  glDisable(GL_LOGIC_OP);

  // creo la texture in base all'immagine originale
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  checkErrorsByGL
#ifndef CREATE_GL_CONTEXT_ONE_TIME
      TRaster32P rasaux;
  if (!wireframe) {
    TRaster32P texture(texWidth, texHeight);
    texture->clear();
    rasaux = texture;
    rasaux->lock();
    texture->copy(rasIn);

    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    glTexImage2D(GL_TEXTURE_2D, 0, 4, texWidth, texHeight, 0, GL_RGBA,
                 GL_UNSIGNED_BYTE, texture->getRawData());
  }
#else

      unsigned int texWidth = 1024;
  unsigned int texHeight    = 1024;
  rasaux                    = rasIn;
  rasaux->lock();

  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rasIn->getLx(), rasIn->getLy(),
                  GL_RGBA, GL_UNSIGNED_BYTE, rasIn->getRawData());

#endif
  checkErrorsByGL

      glEnable(GL_TEXTURE_2D);

  // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-rasterWidth * 0.5, rasterWidth * 0.5, -rasterHeight * 0.5,
          rasterHeight * 0.5, -1, 1);
  glViewport(0, 0, rasterWidth, rasterHeight);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  glClear(GL_COLOR_BUFFER_BIT);

  // do OpenGL draw

  double lwTex = (double)(inBBoxLx - 1) / (double)(texWidth - 1);
  double lhTex = (double)(inBBoxLy - 1) / (double)(texHeight - 1);

  TPointD tex00 = TPointD(0.0, 0.0);
  TPointD tex10 = TPointD(lwTex, 0.0);
  TPointD tex11 = TPointD(lwTex, lhTex);
  TPointD tex01 = TPointD(0.0, lhTex);

  GLenum polygonStyle;
  if (wireframe) {
    polygonStyle = GL_LINE;
    glDisable(GL_TEXTURE_2D);
  } else
    polygonStyle = GL_FILL;
  checkErrorsByGL p00.x /= ri.m_shrinkX;
  p00.y /= ri.m_shrinkY;

  p10.x /= ri.m_shrinkX;
  p10.y /= ri.m_shrinkY;

  p11.x /= ri.m_shrinkX;
  p11.y /= ri.m_shrinkY;

  p01.x /= ri.m_shrinkX;
  p01.y /= ri.m_shrinkY;

  TPointD translate = TPointD(tile.m_pos.x + tile.getRaster()->getLx() * 0.5,
                              tile.m_pos.y + tile.getRaster()->getLy() * 0.5);
  glTranslated(-translate.x, -translate.y, 0.0);

  // disegno il poligono
  double dist_p00_p01                 = tdistance2(p00, p01);
  double dist_p10_p11                 = tdistance2(p10, p11);
  double dist_p01_p11                 = tdistance2(p01, p11);
  double dist_p00_p10                 = tdistance2(p00, p10);
  bool vertical                       = (dist_p00_p01 == dist_p10_p11);
  bool horizontal                     = (dist_p00_p10 == dist_p01_p11);
  if (vertical && horizontal) details = 1;
  glPolygonMode(GL_FRONT_AND_BACK, polygonStyle);
  subdivision(p00, p10, p11, p01, tex00, tex10, tex11, tex01, clippingRect,
              details);

  if (!wireframe) {
    // abilito l'antialiasing delle linee
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

    // disegno il bordo del poligono
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glBegin(GL_QUADS);
    glTexCoord2d(tex00.x, tex00.y);
    tglVertex(p00);
    glTexCoord2d(tex10.x, tex10.y);
    tglVertex(p10);
    glTexCoord2d(tex11.x, tex11.y);
    tglVertex(p11);
    glTexCoord2d(tex01.x, tex01.y);
    tglVertex(p01);
    glEnd();

    // disabilito l'antialiasing per le linee
    glDisable(GL_LINE_SMOOTH);
    glDisable(GL_BLEND);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_TEXTURE_2D);
  }

  // force to finish
  glFlush();

  // rimetto il disegno dei poligoni a GL_FILL
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

  // metto il frame buffer nel raster del tile
  glPixelStorei(GL_UNPACK_ROW_LENGTH, rasterWidth);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

  TRaster32P newRas(tile.getRaster()->getLx(), tile.getRaster()->getLy());
  newRas->lock();
  glReadPixels(1, 1, newRas->getLx(), newRas->getLy(), GL_RGBA,
               GL_UNSIGNED_BYTE, (void *)newRas->getRawData());
  newRas->unlock();
  checkErrorsByGL

      rasaux->unlock();

  tile.getRaster()->copy(newRas);
}
QScriptValue Transform::scale(double sx, double sy) {
  return create(engine(), new Transform(TScale(sx, sy) * m_affine));
}
Пример #4
0
	void doCompute(TTile &tile, double frame, const TRenderSettings &info)
	{
		bool isWarped = m_warped.isConnected();

		if (!isWarped)
			return;

		if (fabs(m_intensity->getValue(frame)) < 0.01) {
			m_warped->compute(tile, frame, info);
			return;
		}

		int shrink = (info.m_shrinkX + info.m_shrinkY) / 2;
		double scale = sqrt(fabs(info.m_affine.det()));
		double gridStep = 1.5 * m_gridStep->getValue(frame);

		WarpParams params;
		params.m_intensity = m_intensity->getValue(frame) / gridStep;
		params.m_warperScale = scale * gridStep;
		params.m_sharpen = m_sharpen->getValue();
		params.m_shrink = shrink;
		double evolution = m_evol->getValue(frame);
		double size = 100.0 / info.m_shrinkX;
		TPointD pos(m_posx->getValue(frame), m_posy->getValue(frame));

		//The warper is calculated on a standard reference, with fixed dpi. This makes sure
		//that the lattice created for the warp does not depend on camera transforms and resolution.
		TRenderSettings warperInfo(info);
		double warperScaleFactor = 1.0 / params.m_warperScale;
		warperInfo.m_affine = TScale(warperScaleFactor) * info.m_affine;

		//Retrieve tile's geometry
		TRectD tileRect;
		{
			TRasterP tileRas = tile.getRaster();
			tileRect = TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy()));
		}

		//Build the compute rect
		TRectD warpedBox, warpedComputeRect, tileComputeRect;
		m_warped->getBBox(frame, warpedBox, info);

		getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect, params);

		if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0)
			return;
		if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0)
			return;

		TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect);
		double warperEnlargement = getWarperEnlargement(params);
		warperComputeRect = warperComputeRect.enlarge(warperEnlargement);
		warperComputeRect.x0 = tfloor(warperComputeRect.x0);
		warperComputeRect.y0 = tfloor(warperComputeRect.y0);
		warperComputeRect.x1 = tceil(warperComputeRect.x1);
		warperComputeRect.y1 = tceil(warperComputeRect.y1);

		//Compute the warped tile
		TTile tileIn;
		m_warped->allocateAndCompute(tileIn, warpedComputeRect.getP00(),
									 TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()),
									 tile.getRaster(), frame, info);
		TRasterP rasIn = tileIn.getRaster();

		//Compute the warper tile
		TSpectrum::ColorKey colors[] = {
			TSpectrum::ColorKey(0, TPixel32::White),
			TSpectrum::ColorKey(1, TPixel32::Black)};

		TSpectrumParamP cloudscolors = TSpectrumParamP(tArrayCount(colors), colors);

		//Build the warper
		warperInfo.m_affine = warperInfo.m_affine;
		TAffine aff = warperInfo.m_affine.inv();

		TTile warperTile;
		TRasterP rasWarper = rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy());
		warperTile.m_pos = warperComputeRect.getP00();
		warperTile.setRaster(rasWarper);

		{
			TRenderSettings info2(warperInfo);

			//Now, separate the part of the affine the Fx can handle from the rest.
			TAffine fxHandledAffine = handledAffine(warperInfo, frame);
			info2.m_affine = fxHandledAffine;

			TAffine aff = warperInfo.m_affine * fxHandledAffine.inv();
			aff.a13 /= warperInfo.m_shrinkX;
			aff.a23 /= warperInfo.m_shrinkY;

			TRectD rectIn = aff.inv() * warperComputeRect;

			//rectIn = rectIn.enlarge(getResampleFilterRadius(info));  //Needed to counter the resample filter

			TRect rectInI(tfloor(rectIn.x0), tfloor(rectIn.y0), tceil(rectIn.x1) - 1, tceil(rectIn.y1) - 1);

			// rasIn e' un raster dello stesso tipo di tile.getRaster()

			TTile auxtile(warperTile.getRaster()->create(rectInI.getLx(), rectInI.getLy()), convert(rectInI.getP00()));

			TPointD mypos(auxtile.m_pos - pos);

			double scale2 = sqrt(fabs(info2.m_affine.det()));
			doClouds(auxtile.getRaster(), cloudscolors, mypos, evolution, size, 0.0, 1.0, PNOISE_CLOUDS, scale2, frame);

			info2.m_affine = aff;
			TRasterFx::applyAffine(warperTile, auxtile, info2);
		}

		//Warp
		TPointD db;
		TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db));
		TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI);

		TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00());
		TPointD warperPos((TScale(params.m_warperScale) * warperComputeRect.getP00()) - tileComputeRect.getP00());
		warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params);
	}
Пример #5
0
void tglDraw(const TMeshImage &meshImage, const DrawableTextureData &texData,
             const TAffine &meshToTexAff,
             const PlasticDeformerDataGroup &group) {
  typedef MeshTexturizer::TextureData::TileData TileData;

  // Prepare OpenGL
  glPushAttrib(GL_COLOR_BUFFER_BIT | GL_LINE_BIT |
               GL_HINT_BIT);  // Preserve original status bits

  glEnable(GL_BLEND);

  glEnable(GL_LINE_SMOOTH);
  glLineWidth(1.0f);

  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

  // Prepare variables
  const std::vector<TTextureMeshP> &meshes = meshImage.meshes();
  const TTextureMesh *mesh;

  typedef std::vector<std::pair<int, int>> SortedFacesVector;
  const SortedFacesVector &sortedFaces = group.m_sortedFaces;

  const MeshTexturizer::TextureData *td = texData.m_textureData;
  int t, tCount = td->m_tileDatas.size();

  GLuint texId = -1;
  int m        = -1;
  const double *dstCoords;

  int v0, v1, v2;
  int e1ovi, e2ovi;  // Edge X's Other Vertex Index (see below)

  // Prepare each tile's affine
  std::vector<TAffine> tileAff(tCount);
  for (t = 0; t != tCount; ++t) {
    const TileData &tileData = td->m_tileDatas[t];
    const TRectD &tileRect   = tileData.m_tileGeometry;

    tileAff[t] = TScale(1.0 / (tileRect.x1 - tileRect.x0),
                        1.0 / (tileRect.y1 - tileRect.y0)) *
                 TTranslation(-tileRect.x0, -tileRect.y0) * meshToTexAff;
  }

  // Draw each face individually, according to the group's sorted faces list.
  // Change tile and mesh data only if they change - improves performance

  SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end());
  for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) {
    int f = sft->first, m_ = sft->second;

    if (m != m_) {
      // Change mesh if different from current
      m = m_;

      mesh      = meshes[m].getPointer();
      dstCoords = group.m_datas[m].m_output.get();
    }

    // Draw each face
    const TTextureMesh::face_type &fc = mesh->face(f);

    const TTextureMesh::edge_type &ed0 = mesh->edge(fc.edge(0)),
                                  &ed1 = mesh->edge(fc.edge(1)),
                                  &ed2 = mesh->edge(fc.edge(2));

    {
      v0 = ed0.vertex(0);
      v1 = ed0.vertex(1);
      v2 = ed1.vertex((ed1.vertex(0) == v0) | (ed1.vertex(0) == v1));

      e1ovi = (ed1.vertex(0) == v1) |
              (ed1.vertex(1) == v1);  // ed1 and ed2 will refer to vertexes
      e2ovi = 1 - e1ovi;              // with index 2 and these.
    }

    const TPointD &p0 = mesh->vertex(v0).P(), &p1 = mesh->vertex(v1).P(),
                  &p2 = mesh->vertex(v2).P();

    for (t = 0; t != tCount; ++t) {
      // Draw face against tile
      const TileData &tileData = td->m_tileDatas[t];

      // Map each face vertex to tile coordinates
      TPointD s[3] = {tileAff[t] * p0, tileAff[t] * p1, tileAff[t] * p2};

      // Test the face bbox - tile intersection
      if (std::min({s[0].x, s[1].x, s[2].x}) > 1.0 ||
          std::min({s[0].y, s[1].y, s[2].y}) > 1.0 ||
          std::max({s[0].x, s[1].x, s[2].x}) < 0.0 ||
          std::max({s[0].y, s[1].y, s[2].y}) < 0.0)
        continue;

      // If the tile has changed, interrupt the glBegin/glEnd block and bind the
      // OpenGL texture corresponding to the new tile
      if (tileData.m_textureId != texId) {
        texId = tileData.m_textureId;

        glBindTexture(
            GL_TEXTURE_2D,
            tileData
                .m_textureId);  // This must be OUTSIDE a glBegin/glEnd block
      }

      const double *d[3] = {dstCoords + (v0 << 1), dstCoords + (v1 << 1),
                            dstCoords + (v2 << 1)};

      /*
Now, draw primitives. A note about pixel arithmetic, here.

Since line antialiasing in OpenGL just manipulates output fragments' alpha
components,
we must require that the input texture is NONPREMULTIPLIED.

Furthermore, this function does not rely on the assumption that the output alpha
component
is discarded (as it happens when drawing on screen). This means that just using
a simple
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) is not an option, since this
way THE INPUT
SRC ALPHA GETS MULTIPLIED BY ITSELF - see glBlendFunc's docs - and that shows.

The solution is to separate the rendering of RGB and M components - the formers
use
GL_SRC_ALPHA, while the latter uses GL_ONE. The result is a PREMULTIPLIED image.
*/

      // First, draw antialiased face edges on the mesh border.
      bool drawEd0 = (ed0.facesCount() < 2), drawEd1 = (ed1.facesCount() < 2),
           drawEd2 = (ed2.facesCount() < 2);

      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

      glBegin(GL_LINES);
      {
        if (drawEd0) {
          glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
          glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
        }

        if (drawEd1) {
          glTexCoord2d(s[e1ovi].x, s[e1ovi].y),
              glVertex2d(*d[e1ovi], *(d[e1ovi] + 1));
          glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
        }

        if (drawEd2) {
          glTexCoord2d(s[e2ovi].x, s[e2ovi].y),
              glVertex2d(*d[e2ovi], *(d[e2ovi] + 1));
          glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
        }
      }
      glEnd();

      glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);

      glBegin(GL_LINES);
      {
        if (drawEd0) {
          glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
          glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
        }

        if (drawEd1) {
          glTexCoord2d(s[e1ovi].x, s[e1ovi].y),
              glVertex2d(*d[e1ovi], *(d[e1ovi] + 1));
          glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
        }

        if (drawEd2) {
          glTexCoord2d(s[e2ovi].x, s[e2ovi].y),
              glVertex2d(*d[e2ovi], *(d[e2ovi] + 1));
          glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
        }
      }
      glEnd();

      // Finally, draw the face
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

      glBegin(GL_TRIANGLES);
      {
        glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
        glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
        glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
      }
      glEnd();

      glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);

      glBegin(GL_TRIANGLES);
      {
        glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
        glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
        glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
      }
      glEnd();
    }
  }

  glBindTexture(GL_TEXTURE_2D, 0);  // Unbind texture

  glPopAttrib();
}
Пример #6
0
  bool addFrame(ToonzScene &scene, int row, bool isLast) {
    assert(m_status == 3);
    if (!m_started) start(scene);

    TDimension cameraRes   = scene.getCurrentCamera()->getRes();
    TDimensionD cameraSize = scene.getCurrentCamera()->getSize();

    TPointD center(0.5 * cameraSize.lx, 0.5 * cameraSize.ly);

    double sx = (double)m_offlineGlContext.getLx() / (double)cameraRes.lx;
    double sy = (double)m_offlineGlContext.getLy() / (double)cameraRes.ly;
    double sc = std::min(sx, sy);

    // TAffine cameraAff =
    // scene.getXsheet()->getPlacement(TStageObjectId::CameraId(0), row);
    TAffine cameraAff = scene.getXsheet()->getCameraAff(row);

    double dpiScale =
        (1.0 / Stage::inch) * (double)cameraRes.lx / cameraSize.lx;

    // TAffine viewAff = TScale(dpiScale*sc) * TTranslation(center)*
    // cameraAff.inv();
    TAffine viewAff = TTranslation(0.5 * cameraRes.lx, 0.5 * cameraRes.ly) *
                      TScale(dpiScale * sc) * cameraAff.inv();

    TRect clipRect(m_offlineGlContext.getBounds());
    TPixel32 bgColor = scene.getProperties()->getBgColor();

    m_offlineGlContext.makeCurrent();
    TPixel32 bgClearColor = m_bgColor;

    if (m_alphaEnabled && m_alphaNeeded) {
      const double maxValue = 255.0;
      double alpha          = (double)bgClearColor.m / maxValue;
      bgClearColor.r *= alpha;
      bgClearColor.g *= alpha;
      bgClearColor.b *= alpha;
    }
    m_offlineGlContext.clear(bgClearColor);

    Stage::VisitArgs args;
    args.m_scene = &scene;
    args.m_xsh   = scene.getXsheet();
    args.m_row   = row;
    args.m_col   = m_columnIndex;
    args.m_osm   = &m_osMask;

    ImagePainter::VisualSettings vs;
    Stage::OpenGlPainter painter(viewAff, clipRect, vs, false, true);

    Stage::visit(painter, args);
    /*
painter,
&scene,
scene.getXsheet(), row,
m_columnIndex, m_osMask,
false,0);
*/
    TImageWriterP writer = m_lw->getFrameWriter(m_frameIndex++);
    if (!writer) return false;

#ifdef MACOSX
    glFinish();  // per fissare il bieco baco su Mac/G3
#endif

    TRaster32P raster = m_offlineGlContext.getRaster();

#ifdef MACOSX
    if (m_alphaEnabled && m_alphaNeeded)
      checkAndCorrectPremultipliedImage(raster);
#endif

    if (Preferences::instance()->isSceneNumberingEnabled())
      TRasterImageUtils::addSceneNumbering(TRasterImageP(raster),
                                           m_frameIndex - 1,
                                           scene.getSceneName(), row + 1);
    TRasterImageP img(raster);
    writer->save(img);

    return true;
  }
Пример #7
0
void TglTessellator::tessellate(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &outline, TRaster32P texture)
{
	//QMutexLocker sl(m_mutex);
	checkErrorsByGL;
	glEnable(GL_TEXTURE_2D);
	glColor4d(1, 1, 1, 1);
	checkErrorsByGL;
	TextureInfoForGL texInfo;

	int pow2Lx = tcg::numeric_ops::GE_2Power((unsigned int)texture->getLx());
	int pow2Ly = tcg::numeric_ops::GE_2Power((unsigned int)texture->getLy());

	TAffine aff;
	if (texture->getLx() != pow2Lx || texture->getLy() != pow2Ly) {
		TRaster32P r(pow2Lx, pow2Ly);
		aff = TScale((double)pow2Lx / texture->getLx(), (double)pow2Ly / texture->getLy());
		TRop::resample(r, texture, aff.place(texture->getCenterD(), r->getCenterD()));
		texture = r;
		glPushMatrix();
		tglMultMatrix(aff.inv());
	}

	// If GL_BRGA isn't present make a proper texture to use (... obsolete?)
	texture->lock();
	TRasterP texImage = prepareTexture(texture, texInfo);
	checkErrorsByGL;
	if (texImage != texture)
		texImage->lock();

	assert(texImage->getLx() == texImage->getWrap());

	GLuint texId;
	glGenTextures(1, &texId); // Generate a texture name
	checkErrorsByGL;
	glBindTexture(GL_TEXTURE_2D, texId); // Bind it 'active'
	checkErrorsByGL;
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	 // These must be invoked
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);	 // on a bound texture
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //
	checkErrorsByGL;
	glTexEnvf(GL_TEXTURE_ENV,	  // This too ?
			  GL_TEXTURE_ENV_MODE, // Better here anyway
			  GL_MODULATE);		   //
	checkErrorsByGL;
	glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
	checkErrorsByGL;
	glTexImage2D(GL_TEXTURE_2D,
				 0,						 // one level only
				 texInfo.internalformat, // pixel channels count
				 texInfo.width,			 // width
				 texInfo.height,		 // height
				 0,						 // border size
				 texInfo.type,			 // pixel format           // crappy names
				 texInfo.format,		 // pixel data type        // oh, SO much
				 texImage->getRawData());
	checkErrorsByGL;
	texture->unlock();
	if (texImage != texture)
		texImage->unlock();

	TglTessellator::GLTess glTess;
	gluTessCallback(glTess.m_tess, GLU_TESS_VERTEX, (GluCallback)tessellateTexture);
	checkErrorsByGL;

	//------------------------//
	if (aff != TAffine())
		doTessellate(glTess, cf, antiAliasing, outline, aff); // Tessellate & render
	else
		doTessellate(glTess, cf, antiAliasing, outline); // Tessellate & render
	checkErrorsByGL;
	//------------------------//
	if (aff != TAffine())
		glPopMatrix();
	glDeleteTextures(1, &texId); // Delete & unbind texture
	checkErrorsByGL;
	glDisable(GL_TEXTURE_2D);
	checkErrorsByGL;
}