当前位置: 首页 > Web前端 > JavaScript

Graphics的WebGL实现3D效果-纹理的使用

时间:2023-03-27 16:05:42 JavaScript

背景本文收录于《前端读书会》专栏。上面介绍了纹理相关的内容,使用WebGL实现2D。今天针对贴图继续上一课的内容。3D的实现也算是吸取了MDN-Tutorial的模式,感觉这种学习轨迹算是初衷了(每次长篇大论讲图形理论,怕是你我都坚持不下去了)。目前最好的方式,你可以对WebGL学习或者图形学习有所了解。话不多说,开始今天的内容(主要是代码讲解,尽快过一遍一些基础的API。。。成为API工程师的第一步)以上介绍了纹理相关的内容,有需要的可以参考上文大纲2D和3D的区别?绘画的想法?编码(WebGL中纹理的简单使用)编码部分介绍webgl-utils(一些useprograms,linkProgram缩写没有太大魔力)&martix(一些生成/计算矩阵..)工具类库1.2d的区别而3d首先,我们都知道2D只是一个平面,3D可以理解为6个平面,所以本文主要解决如何添加5个平面(当然添加会伴随一些问题,没关系Stepbystep)本文会修正上面的一些反馈,比如代码注释太少。.好的,我尝试尽可能多地编写WebGl代码。首先回顾一下shader创建程序处理坐标和纹理相关的获取绑定坐标信息进行绘制的步骤。看起来很简单。那我们一起写代码吧。在编码之前,我们先看看效果。明天在有电脑的地方补一张gif图片。1.有shader的朋友反馈说shader部分要照顾新手,所以我会逐行加注释介绍。当然,更详细的还是要看相关资料。我说不好(——主要是懒癌患者)//vertexshader//attributevariable只能应用于vertexshadervec4isvectora_position,avariablenameisattributevec4a_position;//attribute变量只能应用于vertexshadertovertexshadervec4是向量a_position,一个变量名属性vec2a_texcoord;//统一变量(global)可以在顶点和片元中使用(如果两个着色名重名,可以共享)mat4是矩阵u_matrixvariablenameuniformmat4u_matrix;//varying变量(global)的目的是将数据传输到fragmentvec2vectorv_texcoordvariablenamevaryingvec2v_texcoord;//main类似于主执行函数但是是必要的C/C++用法类似于voidmain(){//gl_Position顶点坐标gl_Position=u_matrix*a_position;//将纹理坐标传递给片段着色器v_texcoord=a_texcoord;}//片段着色器//精度有限mediumpmediumprecisionfloat数据类型在SL语言中是正确的,它区分了整数和浮点类型~precisionmediumpfloat;//varyingvariable(global)receivestransmitteddatavec2vectorv_texcoordvariablevec2v_texcoord;//uniformvariable(read-onlyglobal)sampler2Dtextureu_texture变量名uniformsampler2Du_texture;//主执行函数voidmain(){//gl_FragColorcolor这里的信息是纹理texture2D是采样器纹理v_texcoord纹理坐标看js代码穿插理解gl_FragColor=texture2D(u_texture,v_texcoord);}我很佩服这个评论。哈哈不懂记得留言哦。我叫你问,你不问。知不知道,问也不丢人。如果你学会了,那是你自己的力量。你可以升职加薪。2.创建程序//使用webgl-Utils其实就是useVertex和useFragment然后linkProgram...varprogram=webglUtils.createProgramFromScripts(gl,["vertex-shader-3d","fragment-shader-3d"]);3.处理坐标和贴图相关//顶点坐标已经对6个面进行了变换varpositions=newFloat32Array([-0.5,-0.5,-0.5,-0.5,0.5,-0.5,0.5,-0.5,-0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,0.5,-0.5,-0.5,-0.5,-0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,0.5,0.5,0.5,-0.5,0.5,0.5,0.5,0.5,-0.5,0.5,-0.5,-0.5,0.5,0.5,0.5,0.5,-0.5,-0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,-0.5,-0.5,-0.5,-0.5,0.5,-0.5,-0.5,-0.5,-0.5,0.5,-0.5,-0.5,0.5,0.5,-0.5,-0.5,0.5,-0.5,0.5,-0.5,-0.5,-0.5,-0.5,-0.5,0.5,-0.5,0.5,-0.5,-0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,-0.5,-0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,0.5,0.5,0.5,-0.5,0.5,0.5,0.5,]);//解决图片跨域问题的方法有很多种,当然可以绘制canvas2d,然后创建纹理。Canvas标准支持图片跨域。如果您有兴趣,可以查看functionrequestCORSIfNotSameOrigin(img,url){if((newURL(url,window.location.href)).origin!==window.location.origin){img.crossOrigin="";}}//加载图像并在加载时完成绑定纹理functionloadImageAndCreateTextureInfo(url){vartex=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,tex);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,1,1,0,gl.RGBA,gl.UNSIGNED_BYTE,newUint8Array([0,0,255,255]));gl.texParameteri(gl.TEXTURE_2Dgl.texParameteri(gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);1,高度:1,纹理:tex,};varimg=newImage();img.addEventListener('load',function(){textureInfo.width=img.width;textureInfo.height=img.height;gl.bindTexture(gl.TEXTURE_2D,textureInfo.texture);//调用texImage2D()转换加载的图片将图形数据写入纹理gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,img);});requestCORSIfNotSameOrigin(img,url);img.src=网址;返回纹理信息;}vartexInfo=loadImageAndCreateTextureInfo('https://webglfundamentals.org/webgl/resources/leaves.jpg');4。获取并绑定坐标信息varpositionLocation=gl.getAttribLocation(program,"a_position");vartexcoordLocation=gl.getAttribLocation(program,"a_texcoord");varmatrixLocation=gl.getUniformLocation(program,"u_matrix");vartextureLocation=gl.getUniformLocation(program,"u_texture");varpositionBuffer=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);设置几何(gl);vartexcoordBuffer=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,texcoordBuffer);x坐标(gl);vartexture=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,纹理);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,1,1,0,gl.RGBA,gl.UNSIGNED_BYTE,newUint8Array([0,0,255,255]));5。使用程序并提供缓冲区来获取数据然后绘制gl.vertexAttribPointer(positionLocation,size,type,normalize,stride,offset);//启用texcoord属性gl.enableVertexAttribArray(texcoordLocation);//绑定texcoordbuffer.gl.bindBuffer(gl.ARRAY_BUFFER,texcoordBuffer);....gl.drawArrays(gl.TRIANGLES,0,6*6);ok,效果是这样的已经实现了。为了大家的实践,我先说明一下,上面的代码贴图使用的是一张贴图。如果要改变多张图片,可以使用多张贴图或者合并成一张贴图,通过坐标信息进行调整。所有代码请到github下载使用。最后,强烈希望大家学习相关的理论知识;这个理论在日常生活中可能很少用到,但它可以决定你能走多远。(有人问怎么办,勤练),写速度呢?我会加快本栏目(每周1-2篇)和其他栏目(1篇)的速度,将计算机图形学相关的基础知识再覆盖一遍。然后后续主要写数据可视化方向。下一篇应该写什么?我个人打算结束MDN-Tutorial部分的内容。然后开始正式的可视化链接(可以介绍几个常用的库,2D的和3D的都有,看看有没有有用的库需要一起过一遍)。或者让我们知道您的意见!