两幅图像相乘的animation

我有两个图像:
bg Image1和叠加Image2(高度大于bg image1)

现在,我需要将[Image2]放在[Image1]上,并使用混合模式乘法。 但之后,我需要animationImage2的Y位置,但保持混合模式,以获得这样的animation: https : //www.youtube.com/watch?v=D4Gqm9_Eo68

那我该怎么做到呢?
可能是我应该使用OpenGL? 如果是,那么究竟是如何?

我不会为IOS编码,也不知道您正在编码的平台(内存,速度,gfxfunction)。 从你的问题我得到的印象你没有线索渲染,也是animation的一部分…

  1. 最简单的方法是自己编码

    如果你有像素访问,那么它只是一个2嵌套循环的问题复制/组合像素的纹理目标颜色。 我通常使用GDIBitmap->ScanLine[] ,但如前所述,我不知道如果你有类似的IOS。

  2. OpenGL的

    因为你没有OpenGL的经验,所以我不build议使用GLSL,因为它可能从一开始就太多了。 像设置OpenGL环境和解释OpenGL程序如何工作对我来说太长了(我习惯了冗长的回答)。 所以我会跳过(你需要谷歌一些教程)无论如何看到:

    • 在Borland C ++中设置OpenGL

    • 在OpenGL中简单的渲染

    因为这需要MultiTexturing,所以你也需要这个扩展(至less我认为那些本身不在OpenGL 1.0中 )。 我build议像GLEW或其他任何使用lib。

    这个想法是使用2个纹理渲染四边形(矩形),就像这样:

    影响

    四维顶点坐标是固定的(取决于屏幕和图像分辨率/宽高比)。 Texture0也是固定的而且Texture1固定了一个轴,第二个正在改变…其中:

    • t是animation参数t=<0,1>
    • T使用梯度块大小T<1.0

    animation是通过改变每个帧一小步,例如增加和环绕或使用窦…

    你需要记住,标准的OpenGL只知道2个纹理的权力,所以你需要调整/裁剪/重新采样你的纹理,以符合这个标准。 我这样做是这样的:

    此外,您还需要处理您的应用程序OpenGL屏幕和图像之间的宽高比差异…我使用了快捷方式,所以OpenGL视图是正方形的,图像的大小也是正方形。

    现在,当使用MultiTexturing时,您需要正确设置纹理组合器来满足您的需求。 我已经使用过这么多年了,所以我根本不记得这一点,也懒得学习,因为我现在使用GLSL …

    • 无论如何,看到纹理组合,如果你需要一些指导

    幸运的是,这看起来像这个默认的OpenGL设置做你想要的。 所以这里有一些基于C ++ / VCL的代码(没有依赖于平台的OpenGL环境设置):

     //--------------------------------------------------------------------------- const int _txrs=2; // max number of textures GLuint txrid[_txrs],txrids=0; // texture ids GLfloat t=0.0,T=0.1,dt=0.1; // animation texture coordinates void init() { glGenTextures(_txrs,txrid); // textures Byte q; unsigned int *pp; int xs,ys,x,y,adr,*txr; union { unsigned int c32; Byte db[4]; } c; Graphics::TBitmap *bmp=new Graphics::TBitmap; // new bmp // image texture bmp->LoadFromFile("effect_image.bmp"); // load from file bmp->HandleType=bmDIB; // allow direct access to pixels bmp->PixelFormat=pf32bit; // set pixel to 32bit so int is the same size as pixel xs=bmp->Width; // resolution should be power of 2 ys=bmp->Height; txr=new int[xs*ys]; // create linear framebuffer for(adr=0,y=0;y<ys;y++) { pp=(unsigned int*)bmp->ScanLine[y]; for(x=0;x<xs;x++,adr++) { // rgb2bgr and copy bmp -> txr[] c.c32=pp[x]; q =c.db[2]; c.db[2]=c.db[0]; c.db[0]=q; txr[adr]=c.c32; } } glEnable(GL_TEXTURE_2D); // copy it to gfx card glBindTexture(GL_TEXTURE_2D,txrid[txrids]); txrids++; glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xs, ys, 0, GL_RGBA, GL_UNSIGNED_BYTE, txr); glDisable(GL_TEXTURE_2D); delete[] txr; // gradient texture bmp->LoadFromFile("effect_mask.bmp"); // load from file bmp->HandleType=bmDIB; // allow direct access to pixels bmp->PixelFormat=pf32bit; // set pixel to 32bit so int is the same size as pixel xs=bmp->Width; // resolution should be power of 2 ys=bmp->Height; txr=new int[xs*ys]; // create linear framebuffer for(adr=0,y=0;y<ys;y++) { pp=(unsigned int*)bmp->ScanLine[y]; for(x=0;x<xs;x++,adr++) { // rgb2bgr and copy bmp -> txr[] c.c32=pp[x]; q =c.db[2]; c.db[2]=c.db[0]; c.db[0]=q; txr[adr]=c.c32; } } glEnable(GL_TEXTURE_2D); // copy it to gfx card glBindTexture(GL_TEXTURE_2D,txrid[txrids]); txrids++; glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xs, ys, 0, GL_RGBA, GL_UNSIGNED_BYTE, txr); glDisable(GL_TEXTURE_2D); delete[] txr; T=0.4; // 40% of gradient height cover the whole image dt=0.015*T; // animation step 1.5% of image delete bmp; } //--------------------------------------------------------------------------- void TForm1::ogl_draw() { // clear buffers glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); // unit matrices ... no projections ... so view is just <-1,+1> glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glDisable(GL_DEPTH_TEST); // no Z-buffer for 2D glDisable(GL_CULL_FACE); // no strict polygon winding glDisable(GL_TEXTURE_2D); // bind textures glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,txrid[1]); glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,txrid[0]); glColor3f(1.0,0.0,1.0); // render QUAD glColor3f(1.0,1.0,1.0); GLfloat t0=t,t1=t+T; glBegin(GL_QUADS); glMultiTexCoord2f(GL_TEXTURE0,0.0,0.0); glMultiTexCoord2f(GL_TEXTURE1,0.0,t0); glVertex3f(-1.0,+1.0,0.0); glMultiTexCoord2f(GL_TEXTURE0,0.0,1.0); glMultiTexCoord2f(GL_TEXTURE1,0.0,t1); glVertex2f(-1.0,-1.0); glMultiTexCoord2f(GL_TEXTURE0,1.0,1.0); glMultiTexCoord2f(GL_TEXTURE1,1.0,t1); glVertex2f(+1.0,-1.0); glMultiTexCoord2f(GL_TEXTURE0,1.0,0.0); glMultiTexCoord2f(GL_TEXTURE1,1.0,t0); glVertex2f(+1.0,+1.0); glEnd(); // unbind textures so it does not mess any rendering after this (texture unit 0 at the end !!!) glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,0); glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,0); // force to render qued OpenGL rendering and swap double buffers glFlush(); SwapBuffers(hdc); // this is platform dependend !!! } //--------------------------------------------------------------------------- void __fastcall TForm1::Timer1Timer(TObject *Sender) { ogl_draw(); t+=dt; // step the animation if ((dt>0.0)&&(t+T>1.0)) { t=1.0-T; dt=-dt; } // handle if hit top if ((dt<0.0)&&(t <0.0)) { t=0.0; dt=-dt; } // handle if hit bottom } //--------------------------------------------------------------------------- 

    正如你可以看到它是相当多的代码。 如果你使用一些lib加载纹理和处理东西,大部分将会消失(我使用我的引擎,所以它花费了很多时间再次把它们拼凑起来,所以它可以单独使用而不需要lib)。 不要忘记初始化GLEW或任何获得访问MultiTexturing

这是简单的VCL单表格应用程序与它的单个计时器( interval=20ms )。

  • init()只是为gfx卡中的纹理分配空间并将图像加载到它。
  • ogl_draw()呈现你的效果…
  • Timer1Timer(TObject *Sender)在每个定时器事件上被调用,只是强制渲染帧和更新animation…它通过渐变然后向下…

    这是结果:

    结果

    粗糙它是animation,但我懒得赶上这个video…

[EDIT1]

这里链接下载整个BDS2006项目下载

你需要的是:

 - drawInRect:blendMode:alpha: