Add Z coordinate to Light.

This eliminates relief being partially resolution-dependent.
This commit is contained in:
Ben Richards 2024-07-05 13:18:25 +12:00
parent bc30f4a9f7
commit acaa8b553f
5 changed files with 97 additions and 9 deletions

View file

@ -16,7 +16,10 @@ var Utils = require('../../renderer/webgl/Utils');
*
* These are created by the {@link Phaser.GameObjects.LightsManager}, available from within a scene via `this.lights`.
*
* Any Game Objects using the Light2D pipeline will then be affected by these Lights as long as they have a normal map.
* Any Game Objects with the Lighting Component, and `setLighting(true)`,
* will then be affected by these Lights.
* If they have a normal map, it will be used.
* If they don't, the Lights will use the default normal map, a flat surface.
*
* They can also simply be used to represent a point light for your own purposes.
*
@ -39,6 +42,7 @@ var Utils = require('../../renderer/webgl/Utils');
* @param {number} g - The green color of the light. A value between 0 and 1.
* @param {number} b - The blue color of the light. A value between 0 and 1.
* @param {number} intensity - The intensity of the light.
* @param {number} [z] - The z position of the light. If not given, it will be set to `radius * 0.1`.
*/
var Light = new Class({
@ -52,7 +56,7 @@ var Light = new Class({
initialize:
function Light (x, y, radius, r, g, b, intensity)
function Light (x, y, radius, r, g, b, intensity, z)
{
Circle.call(this, x, y, radius);
@ -74,6 +78,27 @@ var Light = new Class({
*/
this.intensity = intensity;
/**
* The z position of the light.
* This affects the relief effect created by the light.
* A higher value will make the light appear more raised.
*
* Lit game objects are considered to be at z=0.
* Thus, if z is larger than the radius of the light,
* the light will not affect them.
* Strong values are in the range of 0 to radius/2.
*
* This is not a true position, and won't be affected by
* perspective or camera position. It won't be set by `setTo`.
* Use `setZ` to set it, or `setZNormal` to set it to a fraction
* of the radius.
*
* @name Phaser.GameObjects.Light#z
* @type {number}
* @since 3.90.0
*/
this.z = z === undefined ? radius * 0.1 : z;
/**
* The flags that are compared against `RENDER_MASK` to determine if this Game Object will render or not.
* The bits are 0001 | 0010 | 0100 | 1000 set by the components Visible, Alpha, Transform and Texture respectively.
@ -190,6 +215,29 @@ var Light = new Class({
},
/**
* The z position of the light, as a fraction of the radius.
* This affects the relief effect created by the light.
* A higher value will make the light appear more raised.
* Strong values are in the range of 0 to 0.5.
*
* @name Phaser.GameObjects.Light#zNormal
* @type {number}
* @since 3.90.0
*/
zNormal: {
get: function ()
{
return this.z / this.radius;
},
set: function (value)
{
this.z = value * this.radius;
}
},
/**
* Compares the renderMask with the renderFlags to see if this Game Object will render or not.
* Also checks the Game Object against the given Cameras exclusion list.
@ -256,6 +304,43 @@ var Light = new Class({
{
this.radius = radius;
return this;
},
/**
* Set the z position of the light.
*
* @method Phaser.GameObjects.Light#setZ
* @since 3.90.0
*
* @param {number} z - The z position of the light.
*
* @return {this} This Light object.
*/
setZ: function (z)
{
this.z = z;
return this;
},
/**
* Set the z position of the light as a fraction of the radius.
* This affects the relief effect created by the light.
* A higher value will make the light appear more raised.
* Strong values are in the range of 0 to 0.5.
*
* @method Phaser.GameObjects.Light#setZNormal
* @since 3.90.0
*
* @param {number} z - The normalized z position of the light.
*
* @return {this} This Light object.
*/
setZNormal: function (z)
{
this.z = z * this.radius;
return this;
}

View file

@ -281,20 +281,22 @@ var LightsManager = new Class({
* @param {number} [radius=128] - The radius of the Light.
* @param {number} [rgb=0xffffff] - The integer RGB color of the light.
* @param {number} [intensity=1] - The intensity of the Light.
* @param {number} [z] - The z position of the light. If omitted, it will be set to `radius * 0.1`.
*
* @return {Phaser.GameObjects.Light} The Light that was added.
*/
addLight: function (x, y, radius, rgb, intensity)
addLight: function (x, y, radius, rgb, intensity, z)
{
if (x === undefined) { x = 0; }
if (y === undefined) { y = 0; }
if (radius === undefined) { radius = 128; }
if (rgb === undefined) { rgb = 0xffffff; }
if (intensity === undefined) { intensity = 1; }
if (z === undefined) { z = radius * 0.1; }
var color = Utils.getFloatsFromUintRGB(rgb);
var light = new Light(x, y, radius, color[0], color[1], color[2], intensity);
var light = new Light(x, y, radius, color[0], color[1], color[2], intensity, z);
this.lights.push(light);

View file

@ -190,7 +190,8 @@ var BatchHandlerQuadLight = new Class({
lightName + 'position',
[
vec.x - (camera.scrollX * light.scrollFactorX * camera.zoom),
height - (vec.y - (camera.scrollY * light.scrollFactorY * camera.zoom))
height - (vec.y - (camera.scrollY * light.scrollFactorY * camera.zoom)),
light.z
]
);
program.setUniform(

View file

@ -3,7 +3,7 @@ module.exports = [
'precision mediump float;',
'struct Light',
'{',
' vec2 position;',
' vec3 position;',
' vec3 color;',
' float intensity;',
' float radius;',
@ -42,7 +42,7 @@ module.exports = [
' if (index < uLightCount)',
' {',
' Light light = uLights[index];',
' vec3 lightDir = vec3((light.position.xy / res) - (gl_FragCoord.xy / res), 0.1);',
' vec3 lightDir = vec3((light.position.xy / res) - (gl_FragCoord.xy / res), light.position.z / res.x);',
' vec3 lightNormal = normalize(lightDir);',
' float distToSurf = length(lightDir) * uCamera.w;',
' float diffuseFactor = max(dot(normal, lightNormal), 0.0);',

View file

@ -4,7 +4,7 @@ precision mediump float;
struct Light
{
vec2 position;
vec3 position;
vec3 color;
float intensity;
float radius;
@ -54,7 +54,7 @@ void main ()
if (index < uLightCount)
{
Light light = uLights[index];
vec3 lightDir = vec3((light.position.xy / res) - (gl_FragCoord.xy / res), 0.1);
vec3 lightDir = vec3((light.position.xy / res) - (gl_FragCoord.xy / res), light.position.z / res.x);
vec3 lightNormal = normalize(lightDir);
float distToSurf = length(lightDir) * uCamera.w;
float diffuseFactor = max(dot(normal, lightNormal), 0.0);