0

我创建了一个 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 中做到这一点。

4

1 回答 1

0

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

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

覆盖update方法的示例:

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

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


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

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

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

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

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

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

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

于 2018-04-25T17:04:17.280 回答