Compare commits
21 Commits
greenkeepe
...
brightness
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01f42ddf85 | ||
|
|
e616ab5d35 | ||
|
|
6e072ea026 | ||
|
|
230a68d564 | ||
|
|
a0ce9e3dca | ||
|
|
0676e0f54a | ||
|
|
ba93f21795 | ||
|
|
5be561133d | ||
|
|
bfa90a07cc | ||
|
|
5f38cd1ee1 | ||
|
|
7d8bcafe2b | ||
|
|
770ae92b25 | ||
|
|
401c368ebc | ||
|
|
4eb04896d3 | ||
|
|
ca488e6439 | ||
|
|
0de5befa4f | ||
|
|
322e311b17 | ||
|
|
2394fb5610 | ||
|
|
109507f6fe | ||
|
|
9292bacdae | ||
|
|
c6a4aa870e |
@@ -53,7 +53,7 @@
|
||||
"minilog": "3.1.0",
|
||||
"raw-loader": "^0.5.1",
|
||||
"scratch-storage": "^1.0.0",
|
||||
"scratch-svg-renderer": "0.2.0-prerelease.20181126212715",
|
||||
"scratch-svg-renderer": "0.2.0-prerelease.20181220183040",
|
||||
"twgl.js": "4.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,16 +426,16 @@ class Drawable {
|
||||
* Should the drawable use NEAREST NEIGHBOR or LINEAR INTERPOLATION mode
|
||||
*/
|
||||
get useNearest () {
|
||||
// We can't use nearest neighbor unless we are a multiple of 90 rotation
|
||||
if (this._direction % 90 !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Raster skins (bitmaps) should always prefer nearest neighbor
|
||||
if (this.skin.isRaster) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We can't use nearest neighbor unless we are a multiple of 90 rotation
|
||||
if (this._direction % 90 !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the scale of the skin is very close to 100 (0.99999 variance is okay I guess)
|
||||
if (Math.abs(this.scale[0]) > 99 && Math.abs(this.scale[0]) < 101 &&
|
||||
Math.abs(this.scale[1]) > 99 && Math.abs(this.scale[1]) < 101) {
|
||||
@@ -536,13 +536,15 @@ class Drawable {
|
||||
_getTransformedHullPoints () {
|
||||
const projection = twgl.m4.ortho(-1, 1, -1, 1, -1, 1);
|
||||
const skinSize = this.skin.size;
|
||||
const halfXPixel = 1 / skinSize[0] / 2;
|
||||
const halfYPixel = 1 / skinSize[1] / 2;
|
||||
const tm = twgl.m4.multiply(this._uniforms.u_modelMatrix, projection);
|
||||
const transformedHullPoints = [];
|
||||
for (let i = 0; i < this._convexHullPoints.length; i++) {
|
||||
const point = this._convexHullPoints[i];
|
||||
const glPoint = twgl.v3.create(
|
||||
0.5 + (-point[0] / skinSize[0]),
|
||||
(point[1] / skinSize[1]) - 0.5,
|
||||
0.5 + (-point[0] / skinSize[0]) - halfXPixel,
|
||||
(point[1] / skinSize[1]) - 0.5 + halfYPixel,
|
||||
0
|
||||
);
|
||||
twgl.m4.transformPoint(tm, glPoint, glPoint);
|
||||
|
||||
@@ -931,7 +931,11 @@ class RenderWebGL extends EventEmitter {
|
||||
const worldPos = twgl.v3.create();
|
||||
|
||||
drawable.updateMatrix();
|
||||
drawable.skin.updateSilhouette();
|
||||
if (drawable.skin) {
|
||||
drawable.skin.updateSilhouette();
|
||||
} else {
|
||||
log.warn(`Could not find skin for drawable with id: ${drawableID}`);
|
||||
}
|
||||
|
||||
for (worldPos[1] = bounds.bottom; worldPos[1] <= bounds.top; worldPos[1]++) {
|
||||
for (worldPos[0] = bounds.left; worldPos[0] <= bounds.right; worldPos[0]++) {
|
||||
@@ -963,7 +967,11 @@ class RenderWebGL extends EventEmitter {
|
||||
// default pick list ignores visible and ghosted sprites.
|
||||
if (drawable.getVisible() && drawable.getUniforms().u_ghost !== 0) {
|
||||
drawable.updateMatrix();
|
||||
drawable.skin.updateSilhouette();
|
||||
if (drawable.skin) {
|
||||
drawable.skin.updateSilhouette();
|
||||
} else {
|
||||
log.warn(`Could not find skin for drawable with id: ${id}`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -54,39 +54,24 @@ varying vec2 v_texCoord;
|
||||
// Smaller values can cause problems with "color" and "brightness" effects on some mobile devices
|
||||
const float epsilon = 1e-3;
|
||||
|
||||
// Convert an RGB color to Hue, Saturation, and Value.
|
||||
// Convert an RGB color to Hue, Chroma, and Value.
|
||||
// All components of input and output are expected to be in the [0,1] range.
|
||||
vec3 convertRGB2HSV(vec3 rgb)
|
||||
vec3 convertRGB2HCV(vec3 rgb)
|
||||
{
|
||||
// Hue calculation has 3 cases, depending on which RGB component is largest, and one of those cases involves a "mod"
|
||||
// operation. In order to avoid that "mod" we split the M==R case in two: one for G<B and one for B>G. The B>G case
|
||||
// will be calculated in the negative and fed through abs() in the hue calculation at the end.
|
||||
// See also: https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma
|
||||
const vec4 hueOffsets = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
// Based on work by Sam Hocevar and Emil Persson
|
||||
vec4 P = (rgb.g < rgb.b) ? vec4(rgb.bg, -1.0, 2.0/3.0) : vec4(rgb.gb, 0.0, -1.0/3.0);
|
||||
vec4 Q = (rgb.r < P.x) ? vec4(P.xyw, rgb.r) : vec4(rgb.r, P.yzx);
|
||||
float C = Q.x - min(Q.w, Q.y);
|
||||
float H = abs((Q.w - Q.y) / (6.0 * C + epsilon) + Q.z);
|
||||
return vec3(H, C, Q.x);
|
||||
}
|
||||
|
||||
// temp1.xy = sort B & G (largest first)
|
||||
// temp1.z = the hue offset we'll use if it turns out that R is the largest component (M==R)
|
||||
// temp1.w = the hue offset we'll use if it turns out that R is not the largest component (M==G or M==B)
|
||||
vec4 temp1 = rgb.b > rgb.g ? vec4(rgb.bg, hueOffsets.wz) : vec4(rgb.gb, hueOffsets.xy);
|
||||
|
||||
// temp2.x = the largest component of RGB ("M" / "Max")
|
||||
// temp2.yw = the smaller components of RGB, ordered for the hue calculation (not necessarily sorted by magnitude!)
|
||||
// temp2.z = the hue offset we'll use in the hue calculation
|
||||
vec4 temp2 = rgb.r > temp1.x ? vec4(rgb.r, temp1.yzx) : vec4(temp1.xyw, rgb.r);
|
||||
|
||||
// m = the smallest component of RGB ("min")
|
||||
float m = min(temp2.y, temp2.w);
|
||||
|
||||
// Chroma = M - m
|
||||
float C = temp2.x - m;
|
||||
|
||||
// Value = M
|
||||
float V = temp2.x;
|
||||
|
||||
return vec3(
|
||||
abs(temp2.z + (temp2.w - temp2.y) / (6.0 * C + epsilon)), // Hue
|
||||
C / (temp2.x + epsilon), // Saturation
|
||||
V); // Value
|
||||
vec3 convertRGB2HSL(vec3 rgb)
|
||||
{
|
||||
vec3 hcv = convertRGB2HCV(rgb);
|
||||
float L = hcv.z - hcv.y * 0.5;
|
||||
float S = hcv.y / (1.0 - abs(L * 2.0 - 1.0) + epsilon);
|
||||
return vec3(hcv.x, S, L);
|
||||
}
|
||||
|
||||
vec3 convertHue2RGB(float hue)
|
||||
@@ -97,11 +82,11 @@ vec3 convertHue2RGB(float hue)
|
||||
return clamp(vec3(r, g, b), 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 convertHSV2RGB(vec3 hsv)
|
||||
vec3 convertHSL2RGB(vec3 hsl)
|
||||
{
|
||||
vec3 rgb = convertHue2RGB(hsv.x);
|
||||
float c = hsv.z * hsv.y;
|
||||
return rgb * c + hsv.z - c;
|
||||
vec3 rgb = convertHue2RGB(hsl.x);
|
||||
float C = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;
|
||||
return (rgb - 0.5) * C + hsl.z;
|
||||
}
|
||||
#endif // !defined(DRAW_MODE_silhouette) && (defined(ENABLE_color) || defined(ENABLE_brightness))
|
||||
|
||||
@@ -166,7 +151,7 @@ void main()
|
||||
|
||||
#if defined(ENABLE_color) || defined(ENABLE_brightness)
|
||||
{
|
||||
vec3 hsv = convertRGB2HSV(gl_FragColor.xyz);
|
||||
vec3 hsl = convertRGB2HSL(gl_FragColor.xyz);
|
||||
|
||||
#ifdef ENABLE_color
|
||||
{
|
||||
@@ -174,19 +159,19 @@ void main()
|
||||
// so that some slight change of hue will be visible
|
||||
const float minLightness = 0.11 / 2.0;
|
||||
const float minSaturation = 0.09;
|
||||
if (hsv.z < minLightness) hsv = vec3(0.0, 1.0, minLightness);
|
||||
else if (hsv.y < minSaturation) hsv = vec3(0.0, minSaturation, hsv.z);
|
||||
if (hsl.z < minLightness) hsl = vec3(0.0, 1.0, minLightness);
|
||||
else if (hsl.y < minSaturation) hsl = vec3(0.0, minSaturation, hsl.z);
|
||||
|
||||
hsv.x = mod(hsv.x + u_color, 1.0);
|
||||
if (hsv.x < 0.0) hsv.x += 1.0;
|
||||
hsl.x = mod(hsl.x + u_color, 1.0);
|
||||
if (hsl.x < 0.0) hsl.x += 1.0;
|
||||
}
|
||||
#endif // ENABLE_color
|
||||
|
||||
#ifdef ENABLE_brightness
|
||||
hsv.z = clamp(hsv.z + u_brightness, 0.0, 1.0);
|
||||
hsl.z = clamp(hsl.z + u_brightness, 0.0, 1.0);
|
||||
#endif // ENABLE_brightness
|
||||
|
||||
gl_FragColor.rgb = convertHSV2RGB(hsv);
|
||||
gl_FragColor.rgb = convertHSL2RGB(hsl);
|
||||
}
|
||||
#endif // defined(ENABLE_color) || defined(ENABLE_brightness)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user