我正在使用HTML5画布写一个简单的2D游戏引擎。我现在需要添加一个照明引擎。每个光源都有半径值和亮度值(0-1,例如1表示非常亮)。还有一个环境光值,用于照亮世界中没有靠近光源的其他物体(0-1,例如0.1表示月光)。照明过程在主画布上面完成:
然而,与我想要从引擎中获得的内容(左侧)不同,我得到了一种相反的渐变效果(右侧)。我认为这是因为当我使用“source-out”混合模式绘制矩形时,它会影响渐变本身的颜色,因为它们是半透明的。
有没有更好或不同的方法?也许使用裁剪,或者首先在所有东西上绘制矩形?
另外,我修改了Mozila Dev Centre的示例来复制我需要做的事情,但没有一个混合模式似乎起作用,请查看是否有帮助。
非常感谢,任何答案都很棒 :)
- 对于每个光源,会在该位置绘制一个具有与光源相同半径的径向渐变。该渐变会给定两个停止点:中心为黑色,透明度为1-光强度,末端/边缘为黑色,透明度为1-环境光值。这一步很顺利。
- 这是出错的地方:/ 我需要用透明度为1-环境光值的黑色填充整个画布,目前我通过将context.globalCompositeOperation设置为source-out然后fillRect整个画布来实现。
var amb = 'rgba(0,0,0,' + (1-f.ambientLight) + ')';
for(i in f.entities) {
var e = f.entities[i], p = f.toScreenPoint(e.position.x, e.position.y), radius = e.light.radius;
if(radius > 0) {
var g = cxLighting.createRadialGradient(p.x, p.y, 0, p.x, p.y, radius);
g.addColorStop(0, 'rgba(0,0,0,' + (1-e.light.intensity) + ')');
g.addColorStop(1, amb);
cxLighting.fillStyle = g;
cxLighting.beginPath();
cxLighting.arc(p.x, p.y, radius, 0, Math.PI*2, true);
cxLighting.closePath();
cxLighting.fill();
}
}
//Ambient light
cxLighting.globalCompositeOperation = 'source-out';
cxLighting.fillStyle = amb;
cxLighting.fillRect(0, 0, f.width, f.height);
cxLighting.globalCompositeOperation = 'source-over';
然而,与我想要从引擎中获得的内容(左侧)不同,我得到了一种相反的渐变效果(右侧)。我认为这是因为当我使用“source-out”混合模式绘制矩形时,它会影响渐变本身的颜色,因为它们是半透明的。
![期望的光照效果](https://istack.dev59.com/T6fsx.webp)
![我得到的](https://istack.dev59.com/u6itZ.webp)
另外,我修改了Mozila Dev Centre的示例来复制我需要做的事情,但没有一个混合模式似乎起作用,请查看是否有帮助。
非常感谢,任何答案都很棒 :)
ctx.createRadialGradient()
就是模糊一个形状/圆形的方法。 - Christopher