虚拟展厅,WebGL,Three.js - 星空最新版本是多少 //www.rxniqiu.com/ zh-hans 虚拟展厅技术:WebGL完整工作流程以及 Three.js 原理 //www.rxniqiu.com/news/512 <span>虚拟展厅技术:WebGL完整工作流程以及 Three.js 原理</span> <span><span lang="" about="//www.rxniqiu.com/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">Jyadmin</span></span> <span>周五, 02/19/2021 - 16:42</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p> </p> <h4><strong>虚拟展厅技术:WebGL的完整工作流程</strong></h4> <p>1、准备数据阶段</p> <p>在这个阶段,我们需要提供顶点坐标、索引(三角形绘制顺序)、uv(决定贴图坐标)、法线(决定光照效果),以及各种矩阵(比如投影矩阵)。</p> <p>其中顶点数据存储在缓存区(因为数量巨大),以修饰符attribute传递给顶点着色器;</p> <p>矩阵则以修饰符uniform传递给顶点着色器。</p> <p>2、生成顶点着色器</p> <p>根据我们需要,由Javascript定义一段顶点着色器(opengl es)程序的字符串,生成并且编译成一段着色器程序传递给GPU。</p> <p>3、图元装配</p> <p>GPU根据顶点数量,挨个执行顶点着色器程序,生成顶点最终的坐标,完成坐标转换。</p> <p>4、生成片元着色器</p> <p>模型是什么颜色,看起来是什么质地,光照效果,阴影(流程较复杂,需要先渲染到纹理,可以先不关注),都在这个阶段处理。</p> <p>5、光栅化</p> <p>能过片元着色器,我们确定好了每个片元的颜色,以及根据深度缓存区判断哪些片元被挡住了,不需要渲染,最终将片元信息存储到颜色缓存区,最终完成整个渲染。</p> <p><img alt="光栅化" data-entity-type="file" data-entity-uuid="eeccf534-ffd3-49d4-a7b6-2aef854c7a42" src="//www.rxniqiu.com/sites/default/files/inline-images/%E5%85%89%E6%A0%85%E5%8C%96.jpg" width="727" height="299" loading="lazy" /></p> <h4><strong>虚拟展厅技术:Three.js 原理</strong></h4> <p>three.js参与的流程:</p> <p><img alt="three.js参与的流程" data-entity-type="file" data-entity-uuid="aa6f5fa7-e71a-4133-87be-57e71d88cd3c" src="//www.rxniqiu.com/sites/default/files/inline-images/three.js%E5%8F%82%E4%B8%8E%E7%9A%84%E6%B5%81%E7%A8%8B.jpg" width="712" height="244" loading="lazy" /></p> <p>黄色和绿色部分,都是three.js参与的部分,其中黄色是javascript部分,绿色是opengl es部分。</p> <p>three.js可以实现:</p> <ul><li> <p>辅助我们导出了模型数据;</p> </li> <li> <p>自动生成了各种矩阵;</p> </li> <li> <p>生成了顶点着色器;</p> </li> <li> <p>辅助我们生成材质,配置灯光;</p> </li> <li> <p>根据我们设置的材质生成了片元着色器。</p> </li> <li> <p>而且将webGL基于光栅化的2D API,封装成了我们人类能看懂的 3D API。</p> </li> </ul><h5><strong> Three.js顶点处理流程</strong></h5> <p>从WebGL工作原理的章节中,我们已经知道了顶点着色器会将三维世界坐标转换成屏幕坐标,但实际上,坐标转换不限于投影矩阵。</p> <p>如下图:</p> <p><img alt="Three.js顶点处理流程" data-entity-type="file" data-entity-uuid="f4315902-b88b-415c-8782-0aba132ccc34" src="//www.rxniqiu.com/sites/default/files/inline-images/Three.js%E9%A1%B6%E7%82%B9%E5%A4%84%E7%90%86%E6%B5%81%E7%A8%8B.jpg" width="709" height="202" loading="lazy" /></p> <p>之前WebGL在图元装配之后的结果,由于我们认为模型是固定在坐标原点,并且相机在x轴和y轴坐标都是0,其实正常的结果是这样的:</p> <p><img alt="WebGL在图元装配之后的结果" data-entity-type="file" data-entity-uuid="c4615c8b-2c34-494c-b971-7bd12ae60dd4" src="//www.rxniqiu.com/sites/default/files/inline-images/WebGL%E5%9C%A8%E5%9B%BE%E5%85%83%E8%A3%85%E9%85%8D%E4%B9%8B%E5%90%8E%E7%9A%84%E7%BB%93%E6%9E%9C.jpg" width="676" height="181" loading="lazy" /></p> <h5><strong>模型矩阵</strong></h5> <p><strong><img alt="模型矩阵" data-entity-type="file" data-entity-uuid="0bc27d25-073f-4b55-86aa-7308e0fc225f" src="//www.rxniqiu.com/sites/default/files/inline-images/%E6%A8%A1%E5%9E%8B%E7%9F%A9%E9%98%B5.jpg" width="639" height="183" loading="lazy" /></strong></p> <p>现在,将模型顺时针旋转Math.PI/6,所有顶点位置肯定都变化了。</p> <blockquote> <p>box.rotation.y = Math.PI/6;</p> </blockquote> <p> 但是,如果我们直接将顶点位置用javascript计算出来,那性能会很低(顶点通常成千上万),而且,这些数据也非常不利于维护。</p> <h5><strong>视图矩阵</strong></h5> <p><strong><img alt="视图矩阵" data-entity-type="file" data-entity-uuid="ca7509e5-3ab0-484b-b4fb-aa6c59437b4c" src="//www.rxniqiu.com/sites/default/files/inline-images/%E8%A7%86%E5%9B%BE%E7%9F%A9%E9%98%B5.jpg" width="677" height="230" loading="lazy" /></strong></p> <p>将相机往上偏移30。</p> <blockquote> <blockquote> <p>camera.position.y = 30;</p> </blockquote> </blockquote> <p> 同理,我们用矩阵viewMatrix将移动信息记录下来。</p> <h5><strong>投影矩阵</strong></h5> <p><strong><img alt="投影矩阵" data-entity-type="file" data-entity-uuid="abd24d16-b371-4ac1-807b-1136ed4a67d1" src="//www.rxniqiu.com/sites/default/files/inline-images/%E6%8A%95%E5%BD%B1%E7%9F%A9%E9%98%B5.jpg" width="677" height="218" loading="lazy" /></strong></p> <p>用projectMatrix记录。</p> <h5><strong>应用矩阵</strong></h5> <p>编写顶点着色器:</p> <blockquote> <p>gl_Position = position * modelMatrix * viewMatrix * projectionMatrix;</p> </blockquote> <p> </p> <p>这样,我们就在GPU中,将最终顶点位置计算出来了。</p> <p>实际上,上面所有步骤,three.js都帮我们完成了。</p> <p><img alt="应用矩阵" data-entity-type="file" data-entity-uuid="1c71ec1e-e9a0-4462-9d7f-8fbd81903665" src="//www.rxniqiu.com/sites/default/files/inline-images/%E5%BA%94%E7%94%A8%E7%9F%A9%E9%98%B5.jpg" width="723" height="361" loading="lazy" /></p> <h4><strong>片元着色器处理流程</strong></h4> <p>片元着色器负责处理材质、灯光等信息,但具体是怎么处理呢?</p> <p>如下图:</p> <p><img alt="片元着色器处理流程" data-entity-type="file" data-entity-uuid="94f1bd98-fb5f-46d5-933a-2ced20baea40" src="//www.rxniqiu.com/sites/default/files/inline-images/%E7%89%87%E5%85%83%E7%9D%80%E8%89%B2%E5%99%A8%E5%A4%84%E7%90%86%E6%B5%81%E7%A8%8B.jpg" width="712" height="334" loading="lazy" /></p> <h4><strong>three.js完整运行流程</strong></h4> <p><img alt="three.js完整运行流程" data-entity-type="file" data-entity-uuid="90ade1ce-0dc6-42e4-9152-732bfa431a5f" src="//www.rxniqiu.com/sites/default/files/inline-images/three.js%E5%AE%8C%E6%95%B4%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B.jpg" width="711" height="272" loading="lazy" /></p> <p>当选择材质后,three.js会根据所选的材质,选择对应的顶点着色器和片元着色器。</p> <p>three.js中已经内置了我们常用着色器。</p> <p> </p> <p> </p> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="//www.rxniqiu.com/taxonomy/term/21" hreflang="zh-hans">虚拟展厅,WebGL,Three.js</a></div> </div> </div> Fri, 19 Feb 2021 08:42:37 +0000 Jyadmin 512 at //www.rxniqiu.com