如何使用melonjs将玩家位置绑定到着色器?

时间:2018-04-25 07:25:18

标签: webgl shader melonjs

我创建了一个glsl着色器:

<script id="player-fragment-shader" type="x-shader/x-fragment">
precision highp float;

varying vec3 fNormal;
uniform vec2 resolution;

float circle(in vec2 _pos, in float _radius) {
  vec2 dist = _pos - vec2(0.5);
  return 1.-smoothstep(_radius - (_radius * 0.5),
                       _radius + (_radius * 0.5),
                       dot(dist, dist) * 20.0);
}

void main() {
  vec2 pos = gl_FragCoord.xy/resolution.xy;

  // Subtract the inverse of orange from white to get an orange glow
  vec3 color = vec3(circle(pos, 0.8)) - vec3(0.0, 0.25, 0.5);

  gl_FragColor = vec4(color, 0.8);
}
</script>
<script id="player-vertex-shader" type="x-shader/x-vertex">
precision highp float;

attribute vec3 position;
attribute vec3 normal;

uniform mat3 normalMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

void main() {
  vec4 pos = modelViewMatrix * vec4(position, 0.25);
  gl_Position = projectionMatrix * pos;
}
</script>

我通过运行来在游戏加载中初始化它:

var vertShader = document.getElementById("player-vertex-shader").text;
var fragShader = document.getElementById("player-fragment-shader").text;
var shader = me.video.shader.createShader(me.video.renderer.compositor.gl, vertShader, fragShader);

这是在视频初始化之后完成的,并且似乎编译着色器程序并加载正常。在shaderfrog.com和其他类似网站上加载时,着色器似乎也能正常工作。

问题是,在我移动角色并重绘之前,它会让我看到一个全黑的屏幕。我已经阅读了webgl基础知识网站,而我似乎缺少的是将字符位置绑定到GL缓冲区。

我如何在melonjs中这样做。

1 个答案:

答案 0 :(得分:0)

嗨,我为melonJS编写了原始的WebGL合成器。

tl; dr:通过从角色的true方法返回entity.update()来强制重绘帧。 (或者,增加动画帧速率以匹配游戏帧速率。)

覆盖update方法的示例:

update: function (dt) {
    this._super(me.Entity, "update", [dt]);
    return true;
}

这允许更新继续正常运行(例如更新动画状态等),但返回true以强制每次重绘帧。

了解合成器的工作原理以及着色器如何与melonJS实体进行交互可能会有所帮助。这描述了WebGL与melonJS集成的内部工作原理。简而言之,没有明确的步骤将位置绑定到着色器。位置通过顶点属性缓冲区发送,该缓冲区被批量处理(通常用于整个帧)并作为一个大数组发送到WebGL。

如果您需要更多地控制构建顶点缓冲区,或者您想要执行其他自定义渲染过程,则可以替换默认合成器。这是通过在me.video.init参数中将类引用传递给options.compositor来完成的。默认值为me.WebGLRenderer.Compositor

me.video.init(width, height, {
    wrapper: "screen",
    renderer : me.video.WEBGL,
    compositor: me.WebGLRenderer.Compositor
});

在绘制循环期间,默认合成器为每个me.WebGLRenderer.drawImage调用向顶点属性数组缓冲区添加一个新的四元素。此方法模拟同名的DOM canvas method。实施非常简单;它只是将参数转换为四元组并调用合成器的addQuad方法。这是实际填充顶点属性缓冲区的地方。

顶点属性缓冲区完成后,将调用flush方法,该方法使用gl.drawElements将顶点缓冲区发送到GPU。

melonJS将绘图优化发挥到极致。它不仅可以批量渲染,而且可以减少绘制调用的次数(如上所述),但如果没有任何内容可以绘制,它也不会发送任何绘制调用。当帧与绘制的最后一帧相同时,会发生这种情况。例如,没有实体移动,视口没有滚动,空闲动画没有前进到下一个状态,屏幕上的计时器没有经过一整秒等等。

可以通过让场景中的任何实体从其true方法返回update来强制重绘帧。这是游戏引擎发出的信号,需要重新绘制框架。该过程在the wiki上有更详细的描述。