webgl 游戏_webgl 和 声明式 和 ecs

8b186f56fae1b7b4e66b3aa769cc3511.png

halo,大家好,俺又回来了,好久不贱哇

今天这篇文章是关于 webgl 的,起因最近在玩一个小游戏,然后突发奇想,想写写 webgl 试试手感,然后引发了一些思考

webgl 对我一个数学不及格的人来说,其实乍一看还是很难的,但好在我是动画专业,对 3d 软件比较熟悉……所以碰到模型,贴图(纹理),灯光等概念还不算陌生

但是真的当我开始写的时候,我快疯了:

  const drawImage = (tex, h, w, x, y) => {
    gl.bindTexture(gl.TEXTURE_2D, tex)
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
    gl.enableVertexAttribArray(positionLocation)
    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0)
    gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer)
    gl.enableVertexAttribArray(texcoordLocation)
    gl.vertexAttribPointer(texcoordLocation, 2, gl.FLOAT, false, 0, 0)
    gl.uniformMatrix4fv(matrixLocation, false, matrix(gl.canvas.width, gl.canvas.height, h, w, x, y))
    gl.uniform1i(textureLocation, 0)
    gl.drawArrays(gl.TRIANGLES, 0, 6)
  }

如上,仅仅是画一张图片,就要一堆 gl.xxxxxxxxxxxx,我一直以为 canvas 的命令式代码已经够瞎了,没想到它只是个弟弟,webgl 才是真的惨绝人寰

所以到了这个时候,我第一感觉,就是有一个声明式的封装就好了

Elm

提到声明式,elm 可以说是做的最好的,后来居上的有 redux,dva 等

const reducer = (state, action) => {
  switch (action.type) {
    case 'ADD':
      return state + action.payload;
    default: 
      return state
  }
}
const state = reducer(0, {
  type: 'ADD',
  payload: 2
})

let store = createStore(reducer)
store.subscribe(listener)
store.dispatch({ type:'ADD' })

通过 state 控制 UI,然后只能通过 dispatch 来修改 UI,通过 effects 来管理副作用

经常和发布订阅、memo 等特性联用

如果我们的 webgl 库也能拥有类似的模型就太好了,答案是有的

import { create } from './src/index.js'
const stage = create('#canvas')
const sprite = stage.add('hj.png') // 发布
function loop() {
  sprite.x = Math.random() * stage.gl.canvas.width // 修改 state
  sprite.y = Math.random() * stage.gl.canvas.height
  stage.draw() // 订阅
  requestAnimationFrame(loop)
}
loop()

是不是很熟悉,有点 redux 的样子了,唯一的区别在于 state 可以通过 sprite.xxx 这样修改

这里有一个误解,就是为什么 react 不使用 this.state.xxx 这样直接修改,而必须通过 setState

其实 react 是可以使用 this.state.xxx 修改的,只需要这样用:

this.state.x = 0
this.state.y = 1
this.setState(this.state)

它和 vue 的 Proxy 的方式的区别在于多了一个订阅函数(setState)

所以上面的 gei 的代码是一样的,必须有个 draw() 函数去订阅,当然这里可以使用 immer 等库,让它变成劫持状态,但是 core 中没有必要内置

经过一顿封装,终于有了一个声明式的 API,但我们的初衷其实是做游戏,在游戏领域内有没有类似的思想呢?

答案还是有的,就是 ecs

将游戏分为 entity、component、system

component 和 state 一样,它是纯状态,无逻辑,system 和 action 差不多,纯逻辑,无状态,entity 可有可无,和 effect 差不多,用来处理 component 和 system 的副作用(有点状态,有点逻辑)

好了,饶了一圈,又回到了我熟悉的东西,突然领悟了万变不离其宗的真谛::>_<::

总结

经过一番摸索,大概有了思路,我开了个新坑:

https://github.com/yisar/gei

因为我有写 fre 的经验,所以架构思路可以比较流畅,但是总归在 3d 领域我是个新人……只能慢慢来

尤其是思想要转变过来,我们平时写 UI 时刻面对的是 html 元素和 css 布局,但是在 3d 领域,我们时刻想的应该是 canvas,模型,贴图,灯光

p.s. 最近失业了::>_<:: 又要准备面试了,希望能有个好归宿了

等基本稳定后再贱!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值