You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
letimage=newImage()image.src='./cubetexture.png'image.onload=function(){lettextureRef=createTexture(gl,gl.LINEAR,image1);gl.activeTexture(gl.TEXTURE0)gl.bindTexture(gl.TEXTURE_2D,textureRef)gl.uniform1i(u_Sampler,0);// texture unit 0gl.drawArrays(gl.TRIANGLE_STRIP,0,4);}
lettextures=[]image.onload=function(){lettextureRef=createTexture(gl,gl.LINEAR,image);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,textureRef)textures.push(textureRef)}image.src='./cubetexture.png'letimage1=newImage();image1.onload=function(){lettextureRef1=createTexture(gl,gl.LINEAR,image1);gl.activeTexture(gl.TEXTURE1)gl.bindTexture(gl.TEXTURE_2D,textureRef1)textures.push(textureRef1)}image1.src='./img.png'//激活纹理单元并且绘制gl.uniform1i(u_Sampler,0);// texture unit 0gl.uniform1i(u_Sampler1,1);// texture unit 1gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,textures[0]);gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D,textures[1]);
vec4transition(vec2uv){floattime=progress;floatstime=sin(time*PI/2.);floatphase=time*PI*bounces;floaty=(abs(cos(phase)))*(1.0-stime);floatd=uv.y-y;returnmix(mix(getToColor(uv),shadow_colour,step(d,shadow_height)*(1.-mix(((d/shadow_height)*shadow_colour.a)+(1.0-shadow_colour.a),1.0,smoothstep(0.95,1.,progress)// fade-out the shadow at the end))),getFromColor(vec2(uv.x,uv.y+(1.0-y))),step(d,0.0));}
setInterval(()=>{if(textures.length===2){if(i>=1){i=0.01}gl.uniform1i(u_Sampler,0);// texture unit 0gl.uniform1i(u_Sampler1,1);// texture unit 1gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,textures[0]);gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D,textures[1]);letprogress=gl.getUniformLocation(shaderProgram,'progress')gl.uniform1f(progress,i)i+=0.05gl.drawArrays(gl.TRIANGLE_STRIP,0,4);}},100)
通过webgl中的纹理贴图来自定义图片间的转场效果
本章节建立我们基本上掌握了如何在2D或者3D平面中绘制图形的基础上(当然不了解2D和3D平面绘制图片也可以往下阅读),我们在2D平面中,可以用webgl去绘制我们所需要的图案,但实际中我们用到某个图形时不可能全部一一的去绘制,纹理贴图解决了这个问题,我们可以用已有的图片来填充webgl中的图形。
这个系列的源码地址为:源码的地址为: https://github.com/forthealllight/webgl-demo
一、纹理基础
在了解纹理贴图之前,我们先来了解一下预备知识,首先什么是纹理贴图或者说纹理映射呢?
将一张图像贴到一个几何体的表面
这就是纹理贴图的含义,这张图像我们就成为纹理,这个工作我们就称为纹理贴图,其本质就是提取图像中的颜色,然后对应的赋予给几何平面的某个位置,从而将图像在几何体表面完成渲染。
这里从纹理(图像)到几何体表面之间有一个映射,为了了解这个映射是怎么发生的,我们必须了解一下纹理坐标和裁剪坐标。
裁剪坐标
webgl中的裁剪面坐标如下所示:
从上述裁剪坐标系统的示意图中我们可以看出,webgl中整个裁剪平面的中心坐标是(0,0),对于二维的裁剪平面而言其水平方向从(-1,0)到(1,0),其竖直方向从(0,-1)到(0,1).
也就是说其裁剪坐标任何方向的值在区间[-1,1]内。
注意一点:裁剪平面是决定如何映射到画布上,因为画布是二维的,因此裁剪平面也是二维的。webgl中z轴的坐标并不限制在(-1,1),可以为任何值。
纹理坐标
纹理坐标跟裁剪坐标不一样,其值不是从[-1,1]而是从[0,1]:
在贴图过程中,我们需要使裁剪坐标中的顶点坐标,与纹理坐标系统点一一对应。也就是如何截取纹理坐标中的纹理,贴到几何图形中。
需要注意的是,图片本身的坐标与纹理的坐标是左右相等,上下相反的,因此,存在一个上下方向的坐标变换。在webgl中的纹理 中,通过:
来反转Y轴上的方向。
禁用Chrome的安全性检测
本文的例子中,直接本地通过file文件打开html,如果在这个html文件中有ajax跨域请求,那么因为浏览器的安全性检测,会提示如下信息的错误:
当然如果启动一个本地server就不会有影响。这里有种懒人解决方案,就是通过禁用安全性检测的方法,以mac为例,从命令行窗口中启动chrome,启动命令为
此外,也可以安装http-server,快速在本地启一个server.
二、2D图形的纹理贴图
下面我们以2D几何图形的纹理贴图来介绍一下,在webgl中如何实现纹理贴图。
(1).首先创建一个纹理缓冲
上述就是一个创建纹理缓存的例子,通过gl.createTexture()创建一个纹理缓存,并关联系统变量gl.TEXTURE_2D. 此外,因为在纹理的渲染中,在Y轴方向与图片是完全相反的,因此如果需要正相呈现纹理渲染结果,比如进行Y轴方向的反转,即gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)。
此外我们可以通过gl.texParameteri函数,指定当图片纹理大于渲染区域,或者图片纹理小于渲染区域时,如何去正确的渲染。
最后通过:
提取data中的元素保存到纹理缓存中,data可以是image,也可以是video,甚至是另一个canvas的渲染结果。也就是说,webgl的纹理贴图的源,不仅仅可以是图片,还可以是视频的一帧,甚至是另一个cavans。
(2).加载图片使用纹理缓冲
上述代码加载image图片,在onload的时候,通过之前定义的createTexture创建纹理,然后激活使用0号纹理单元,webgl可以同时支持多个纹理单元,可以同时将多个纹理渲染到同一个可视区。激活纹理单元后,我们将0传递给着色器中的取样器变量u_Sampler.
最后我们在片元着色器中接受纹理单元编号,以及纹理坐标,最后贴图渲染到渲染区:
我们最终得到了在所指定的区域,渲染了正确的一张图片,渲染结果如下所示:
三、多纹理单元的纹理贴图
前面说到webgl可以同时支持多个纹理单元,webgl可以同时处理多幅纹理,纹理单元就是为了这个目的而设计的。在上述的例子中,我们只用了一个纹理单元,将一张纹理渲染到了渲染区。接下来我们尝试使用两个纹理单元,将两张图片,渲染到同一个区域。
纹理图片1
纹理图片2
我们使用webgl中国的两个纹理单元,分别为gl.TEXTURE0和gl.TEXTURE1,修改代码如下。
首先是加载和渲染的逻辑:
最后修改片元着色器:
最后的渲染结果为:
最后双纹理单元合成渲染结果
完成的代码 地址为:https://github.com/forthealllight/webgl-demo/tree/master/demo13
四、不同纹理间实现转场效果
通过使用多纹理单元,我们可以实现图片间的转场效果,首先我们来看什么是转场效果。
转场效果顾名思义,就是从图片A切换到图片B之间的动画特效,类似与我们在做PPT的时候,一些淡入淡出等等动效。在webgl中,渲染的纹理本质也是图片,因此可以在不同纹理间,按时间顺序控制不同纹理的渲染结果,可以实现转场的效果。
如上所示的动图就是列出了一些转场特效。
我们以同样前面的两张图片为例,研究一下图片或者说纹理间的转场效果。
直接看片元着色器中的代码:
我们看到这个transition函数就是一个转换函数,决定了随着时间,如何切换纹理,从而进行渲染,我们通过getFromColor和getToColor指定了两个不同纹理单元的纹理:
最后片元着色器的颜色就是调用transition函数后的结果,在调用transition的时候我们传入了纹理坐标。
最后要想要渲染结果动起来,就必须写一个定时器,动态改变transition中的参数progress,是其从0到1的变化。
最后的渲染结果我们可以看到的动画结果如下:
完成的代码 地址为:https://github.com/forthealllight/webgl-demo/tree/master/demo12
此外,在https://github.com/gl-transitions/gl-transitions 上收录了各色各样的转场效果,转场不仅仅可以应用于图片,还可以应用于视频的不同帧间,下篇文章将具体讲讲如何实现在webgl中渲染video,以及video的帧间动画。
The text was updated successfully, but these errors were encountered: