收藏
评论

(16)小游戏渲染官方

《跳一跳》小游戏在 2017年12月28日正式发布,一周内 DAU 突破一亿,为小游戏开放生态赢得口碑。它操作简单,节奏轻快,凭借着快速复活机制以及强大的社交属性掀起了一股全民潮流。


其实,这个小游戏里仅有两个元素,黑色小人和各色基座。游戏规则也很简单,起跳前,小黑人压缩自己的身体来蓄力,根据蓄力时间决定距离来跳到下一个基座上。


今天的小故事,想要跟大家分享小游戏的渲染能力,我们以跳一跳唱片机为例,简要介绍一下如何展现一个三维物体~ ( 3D渲染引擎选用 Three.js )



步骤一

创建一个场景 Scene



游戏的容器,用来放置光源,照相机和唱片机。


let scene = new THREE.Scene()


步骤二

选择合适的照相机 Camera


抽象来说,照相机定义了三维空间到二维屏幕的投影方式。


因投影方式不同,相机又分为透视投影相机正交投影相机


透视投影中的四棱柱和正交投影中的立方体被称为视景体,它是三维世界里屏幕上可见的区域,也就是照相机的视野。


视景体外的物体会被剪裁掉不参与渲染。透视投影更接近真实世界,有近大远小的感觉。而正交投影将物体以原比例平行投影到近剪裁面上,不会有大小缩放。


在跳一跳中我们使用了正交投影相机。




let camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, near, far )



步骤三

创建光源 light


let ambientLight = new THREE.AmbientLight(0xffffff, 0.8);

let directionalLight = new THREE.DirectionalLight(0xffffff, 0.28);


创建一个环境光和直射光, 环境光没有特定光源,它将光线均匀照射在场景中。直射光模拟真实世界太阳光。


步骤四

定义几何体 Geometry,

材质 Material,合成 Mesh


Geometry 几何体,定义了一个物体的形状,包含顶点,线,面和法向量等信息。


let boxGeometry = new THREE.BoxGeometry(2, 2, 2)


对于唱片机我们创建了三个几何体,两个长方体和一个圆柱体。





Material 材质,定义了一个物体的外观,例如颜色,透明度,光照属性,融合模式。


顶部透明盖子,底座和唱片的使用的Lambert材质,这种材质只考虑漫反射而不考虑镜面反射, 通常用于创建较暗淡无高光的物体, 其中 texture 是纹理贴图,我们通过纹理映射将这个二维图像贴到三维的方块上。



let transparentMaterial = new THREE.MeshLambertMaterial({ color: ‘white’, transparent: true, opacity: 0.5, map: texture })


最后我们通过 Mesh 我们将材质应用到几何体上。


let box = new THREE.Mesh(boxGeometry, transparentMaterial)


步骤五

使用渲染器 Renderer 渲染整个场景


最后我们将 box,camera 设置合适的位置后加入到场景中,再使用 Three.js 的渲染器 renderer 之后就可以看到音乐盒了~


renderer.render(scene, camera)



至此,我们完成了一个 3D 场景渲染到 2D 屏幕的渲染流水线中的应用程序阶段,这个阶段我们将渲染所需的几何信息(点,线,面,法线等信息)传递到渲染流水线的后续阶段。后续的小故事我们会介绍调用渲染器 render 方法后 GPU 是如何处理几何信息并最终渲染图像到屏幕上的。


Q
A
&

共性问题


Q   一般的 3D 游戏 HUD 层(平视显示器)采用 DOM 来显示,例如排行榜,交互按钮。或者使用另一个 canvas 叠在游戏 canvas 上。但是小游戏只支持一个可见 canvas,并且不支持 DOM。这种情况在小游戏里面,应该如何处理呢?


A   可以封装 HUD 层并将其放在游戏 canvas 中,将整个HUD画在了一张离屏 canvas 中,然后将该 canvas 转化为纹理贴图,再将其贴在游戏的 3D 平面模型上。


后续的小故事会介绍如何将 HUD 分解为 3D 组件的形式来开发。


21733浏览
最后一次编辑于  2018-08-17
知识库内容非实时更新,可能已过期、失效或不适用于当前情形,请谨慎参考
收藏
反馈

11 个评论

  • 袁述~
    袁述~
    2018-07-03

    我想问一下,我用小程序的API开发出来的小游戏。是小程序还是小游戏?能不能发布?(顺便占个一楼)

    2018-07-03
    赞同 3
    回复 7
    • 毛毛
      毛毛
      2018-07-03

      同问

      2018-07-03
      回复
    • 咖啡有点甜
      咖啡有点甜
      2018-07-03

      你用小程序的api开发的必然使用的appid对应的服务品类不属于小游戏,自然发布就无法发布成小游戏,虽然是可以做成游戏玩法但实则还是普通小程序,一般都是选择在线教育类目进行提交审核发布,而真正的小游戏的首先是账号服务类目设置的是游戏类目,其次使用的api是游戏api,审核发布时需要提交相应资质,这样的才是小游戏

      2018-07-03
      5
      回复
    • 袁述~
      袁述~
      2018-07-03

      感谢解答,看来还要自学一套小游戏。

      2018-07-03
      1
      回复
    • 王祥
      王祥
      2018-07-09

      three.js


      2018-07-09
      回复
    • 袁述~
      袁述~
      2018-07-09回复王祥

      啥意思?3D渲染?


      2018-07-09
      回复
    查看更多(2)
  • 朱元峰
    朱元峰
    2018-08-10

    请问用threejs如何反锯齿?我载入几个png图片,圆形物体的边缘全是锯齿。

    THREE.WebGLRenderer 和 canvas.getContext enable 反锯齿也没有用


    2018-08-10
    赞同 2
    回复 2
    • 好日子还在后头恁
      好日子还在后头恁
      2019-03-13

      同样发现这个问题, 锯齿现象十分验证,即使开启了antialias

      2019-03-13
      回复
    • 沙隆巴斯
      沙隆巴斯
      2019-09-16
      如果是纹理贴图有锯齿的话,我们一般把贴图边缘2到3个像素的透明度设为0,这样效果要好很多,而且比打开反锯齿效率高
      2019-09-16
      回复
  • happyfire
    happyfire
    2018-07-03

    可以封装 HUD 层并将其放在游戏 canvas 中,将整个HUD画在了一张离屏 canvas 中,然后将该 canvas 转化为纹理贴图,再将其贴在游戏的 3D 平面模型上

    ----为啥要搞这么复杂呢?直接用平面作为UI渲染不行吗,如果主场景用透视投影,则UI用一个独立的平行投影camera渲染,或者你也可以做3d UI。参考Unity

    2018-07-03
    赞同 2
    回复 1
    • 唐波
      唐波
      2018-07-18

      跳一跳内其实也有些部分是这样做的. 这样做文本性能比较差, 对于实时变化的文本更是这样. 对于一直变化的分数可能需要为每个数字创建多个mesh做为缓存, 再组合显示

      2018-07-18
      回复
  • 2018-08-17

    可不可以让webgl在一个离线canvas上渲染然后再drawimage到显示的canvas上,然后再骑上在绘制HUD,我在模拟器上试过运行的还行,但是到了手机上显示就不正常了,郁闷啊。

    2018-08-17
    赞同
    回复
  • 铭懿翡翠
    铭懿翡翠
    2018-08-09

    现在刚起步里面的东西都看不懂明天就交作业请指教

    2018-08-09
    赞同
    回复
  • 小玩躺
    小玩躺
    2018-07-27

    后续的小故事会介绍如何将 HUD 分解为 3D 组件的形式来开发。

    期待早点出来,这个地方不太明白

    2018-07-27
    赞同
    回复
  • 王祥
    王祥
    2018-07-09

    three.js


    2018-07-09
    赞同
    回复
  • 壹零贰肆℃
    壹零贰肆℃
    2018-07-04

    像开发一款小程序

    2018-07-04
    赞同
    回复
  • 席文楷
    席文楷
    2018-07-03

    var c = wx.createCanvas()

    var ctx = c.getContext("2d");

    ctx.fillStyle = "#FF0000";

    ctx.fillRect(0, 0, c.width, c.height);

    ctx.lineWidth = 1;

    //画直线

    ctx.moveTo(0, 0);

    ctx.lineTo(c.width, c.height);

    ctx.stroke();


    我想请问一下在虚拟机显示直线没有问题,大神真机就显示不出来,这是什么原因?

    2018-07-03
    赞同
    回复
  • 紫薯蛋挞
    紫薯蛋挞
    2018-07-03

    期待后续~

    2018-07-03
    赞同
    回复

正在加载...

登录 后发表内容