两个图像的多次混合的动画 [英] Animation of multiply blending of two images
问题描述
我有两张图片:
bg Image1和叠加Image2(高度大于bg image1)
现在我需要将[Image2]放在[Image1]上并混合使用混合模式。
但是之后我需要为Image2的Y位置设置动画,但保持混合模式以获得这样的动画:
Quad Vertex坐标是固定的(dependend)屏幕和图像分辨率/宽高比)。 Texture0也是固定的,而Texture1固定了一个轴,第二个正在改变......其中:
-
t
是动画参数t =< 0,1>
-
T
使用渐变块大小T< 1.0
动画是通过每帧更改 t
一小步来完成的,例如增量和环绕或使用正弦...
您需要记住,标准OpenGL只知道2个纹理的强大功能,因此您需要调整/裁剪/重新采样纹理以符合此条件。我是这样做的:
您还需要处理App OpenGL 屏幕和图像之间的宽高比差异...我使用了快捷方式,因此 OpenGL 视图为方形,图像也调整为方形。
现在使用 MultiTexturing 时,需要正确设置纹理组合以匹配您的需求。这已经是我用过的年龄了,所以我根本不记得它而且懒得再研究一下,因为我现在使用GLSL ......
- 无论如何,如果你需要一些指导,请参见
粗略的它是动画但我懒得看到这个视频......
[edit1]
此处链接下载整个BDS2006项目下载
I have two images:
bg Image1 And overlay Image2 (which height is bigger than bg image1)
Now I need to place [Image2] over [Image1] with blend mode multiply. But after that I need to animate Image2's Y position but keep blend mode so to get an animation like this: https://www.youtube.com/watch?v=D4Gqm9_Eo68
So how can I achieve that?
May be I should use OpenGL? If yes, then how exactly?
I do not code for IOS and have no clue of platform you are coding for (memory,speed,gfx capabilities). From your Question I got the impression you have no clue of rendering and also the animating part...
the easiest way would be encode it yourself
If you got pixel access then it is just a matter of 2 nested for loops copying/combining pixels of texture to target color. I usually use GDI and
Bitmap->ScanLine[]
for this but as mentioned I have no clue if you have something similar on IOS.OpenGL
as you have no OpenGL experience then I do not advice to use GLSL as it could be too much from start. Things like setting up OpenGL environment and explaining how OpenGL program works would be too long even for me (and I am used to lengthy answers). So I would skip that (you need to google some tutorial for it) anyway see:
As this require MultiTexturing you will also need that extension (At least I think those are not in OpenGL 1.0 natively). I advice to use lib for it like GLEW or whatever else.
The idea is to render quad (rectangle) with 2 textures at once something like this:
The Quad Vertex coordinates are fixed (dependend on screen and image resolution/aspect ratio). Texture0 is also fixed And Texture1 has fixed one axis and the second is changing... where:
t
is the animation parametert=<0,1>
T
is used gradient chunk sizeT<1.0
The animation is done by changing
t
by some small step each frame for example increment and wrap around or use sinus...You need to remember that standard OpenGL knows only power of 2 textures so you need to resize/crop/resample your textures to match this criteria. I do this like this:
Also you need to handle aspect ratio difference between your App OpenGL screen and image ... I used a short cut so the OpenGL view is square and the image is resized to square too.
Now when using MultiTexturing you need to properly set up the Texture combiners to match your needs. It has been ages I used that so I do not remember it at all and too lazy to study that again as I use GLSL now ...
- anyway see Texture Combiners if you need some guidience
Luckily it looks like that default OpenGL settings of this do just what you want. So here some C++/VCL based code (without the OpenGL environment setup which is platform dependent):
//--------------------------------------------------------------------------- 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 } //---------------------------------------------------------------------------
As you can see it is quite a bit of code. If you use some lib to load textures and handle stuff most of it will go away (I use mine engine for this so it took mi while to get the pieces together again so it is usable standalone without lib). Do not forget to init GLEW or whatever to get access to MultiTexturing ...
This is simple VCL single form app with single timer in it (interval=20ms
).
init()
just allocates space for textures in gfx card and load the images to it.ogl_draw()
renders the effect of yours ...Timer1Timer(TObject *Sender)
is called on each timer event and just force to render frame and update animation ... it goes up through the gradient and then down ...This is the result:
Of coarse it is animated but I am to lazy to catch a video of this...
[edit1]
Here link to download the whole BDS2006 project download
这篇关于两个图像的多次混合的动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!