我有两张图片:
bg Image1和叠加Image2(高度大于bg image1)
现在我需要将[Image2]放在[Image1]上,并使用混合模式。 但之后我需要为Image2的Y位置设置动画,但保持混合模式以获得这样的动画: https://www.youtube.com/watch?v=D4Gqm9_Eo68
那我怎么能实现呢? 可能我应该使用OpenGL?如果是,那究竟是怎么回事?
答案 0 :(得分:2)
我不编码 IOS ,并且不知道您编写的平台(内存,速度,gfx功能)。从你的问题我得到的印象是你不知道渲染和动画部分......
最简单的方法就是自己编码
如果你有像素访问那么只需要2个嵌套for循环复制/组合纹理像素到目标颜色。我通常使用 GDI 和Bitmap->ScanLine[]
,但如上所述,如果您在IOS上有类似内容,我不知道。
<强>的OpenGL 强>
由于您没有 OpenGL 经验,因此我不建议使用 GLSL ,因为从一开始就可能太多了。设置 OpenGL 环境和解释 OpenGL 程序如何工作的事情对我来说太长了(我习惯了很长的答案)。所以我会跳过它(你需要谷歌一些教程),无论如何看看:
由于这需要MultiTexturing,您还需要该扩展(至少我认为那些不在 OpenGL 1.0 本机)。我建议使用lib作为 GLEW 或其他任何东西。
这个想法是一次渲染带有2个纹理的四边形(矩形):
Quad Vertex坐标是固定的(取决于屏幕和图像分辨率/宽高比)。 Texture0也是固定的,而Texture1固定了一个轴,第二个正在改变......其中:
t
是动画参数t=<0,1>
T
使用渐变块大小T<1.0
动画是通过每帧改变t
一小步来完成的,例如增量和环绕或使用正弦......
您需要记住,标准OpenGL只知道2个纹理的强大功能,因此您需要调整/裁剪/重新采样纹理以符合此条件。我是这样做的:
此外,您需要处理App 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)
在每个计时器事件上被调用,只是强制渲染帧并更新动画......它通过渐变然后向上...
结果如下:
粗略的它是动画但我懒得看到这个视频...
<强> [EDIT1] 强>
此处链接下载整个BDS2006项目download
答案 1 :(得分:0)
您需要的是:
- drawInRect:blendMode:alpha: