I'm experimenting with GLSL shaders in Pixi 4.4, and was trying to make some that would take in two images, the base and an overlay. The shaders would then replace either the Hue, Saturation, or Value of the pixels in the base image with the H/S/V of the corresponding pixel in the overlay image. Transparency on the overlay means "no change."
For my tests, I used a 100x100 red square, and the following 100x100 "striped" overlays:
![stripesHue.png.0be7f60b48964b955397daf626de4ac5.png]()
![stripesSat.png.a5dca7f672ee175308bf589c741e2373.png]()
![stripesVal.png.d014039e15eeb9729ed1d9e11eac17d6.png]()
That's the Hue overlay, Saturation overlay, and Value overlay respectively.
Results were only partially consistent, and all wrong. Here are the results of the Hue and Saturation shaders against a black background.
![Screenshot_10.png.b1c030900f3a09b84f40f901e78884f0.png]()
![Screenshot_11.png.f92646dda8f259454134faf1016eafe0.png]()
Okay, so the stripes are twice as tall as they should be and the bottom-most stripe is outright missing, as though either the overlay or base were resized as some point in the process. But Value takes the cake:
![Screenshot_12.png.c86ad4dd40fb5d0b24f613feb82fb0ca.png]()
Not only do we have the same problem as above, but there are "teeth" that have appeared off the edge of the 100x100 image (4px in each direction, making a 108x100 image), and there are outlines around every stripe, and if you zoom in especially close you can see that some of the outlines are actually 2 pixels tall, one of near-black, and one of another dark colour, none of which is in the original Value overlay!
I'm at a loss to tell if the problem(s) originates in my shader code or in Pixi, especially since tutorials around the net are mum about how to create a second shader2D uniform in any other setup but Pixi. I do want to work with Pixi for this project, however, so a fix for Pixi would be appreciated if the problem really is from there.
Here's the HTML/GLSL code. Please don't mind the If statement, I've already had a few ideas on how to get rid of it:
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<style>
body {
background-color: black;
margin: 0;
overflow: hidden;
}
p {
color: white;
}
</style>
</head>
<body>
<script type="text/javascript" src="libs/pixi.js"></script>
<script id="shader" type="shader">
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 vTextureCoord;
uniform sampler2D uSampler; //The base image
uniform sampler2D overlay; //The overlay
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void main(void) {
vec4 baseRGB = texture2D(uSampler, vTextureCoord);
vec4 overlayRGB = texture2D(overlay, vTextureCoord);
if(overlayRGB.a > 0.0) {
vec3 baseHSV = rgb2hsv(baseRGB.rgb);
vec3 overlayHSV = rgb2hsv(overlayRGB.rgb);
// Hue
// vec3 resultHSV = vec3(overlayHSV.x, baseHSV.y, baseHSV.z);
// Saturation
// vec3 resultHSV = vec3(baseHSV.x, overlayHSV.y, baseHSV.z);
// Value
vec3 resultHSV = vec3(baseHSV.x, baseHSV.y, overlayHSV.z);
vec3 resultRGB = hsv2rgb(resultHSV);
gl_FragColor = vec4(resultRGB.rgb, baseRGB.a);
}
else {
gl_FragColor = baseRGB;
}
}
</script>
<script type="text/javascript" src="replaceTest.js"></script>
</body>
</html>
And here's the JS:
var width = window.innerWidth;
var height = window.innerHeight;
var renderer = new PIXI.WebGLRenderer(width, height);
document.body.appendChild(renderer.view);
var stage = new PIXI.Container();
var sprite = PIXI.Sprite.fromImage('flat.png');
sprite.x = width / 2;//Set it at the center of the screen
sprite.y = height / 2;
sprite.anchor.set(0.5);//Make sure the center point of the image is at its center, instead of the default top left
stage.addChild(sprite);
//Create a uniforms object to send to the shader
var uniforms = {}
uniforms.overlay = {
type:'sampler2D',
value: PIXI.Texture.fromImage('stripesVal.png') // or stripesSat, stripesHue, etc
}
//Get shader code as a string
var shaderCode = document.getElementById("shader").innerHTML;
//Create our Pixi filter using our custom shader code
var rasShader = new PIXI.Filter(null,shaderCode,uniforms);
console.log(rasShader.uniforms);
sprite.filters = [rasShader];
function update() {
requestAnimationFrame(update);
renderer.render(stage);
}
update();
Any help would be appreciated!