Jump to content

Apply an outline shader on a sprite


fabien_
 Share

Recommended Posts

Hello,

 

I have a sprite build that way :

 

var cat = new PIXI.Sprite( textureCat );cat.anchor.x = 0;cat.anchor.y = 0;cat.position.x = tileSideWidth * 10;cat.position.y = tileSideWidth * 6;cat.width = tileSideWidth * 2;cat.height = tileSideWidth;
This is a cat obviously. And I try to apply this wonderfull outline shader : http://jsfiddle.net/Eskel/g593q/9/ (except I want it white)
 
I initialized and appliyed a filter with the fragment shader and it kinda works. The whole rectangle is now white :
let CustomFilter = function CustomFilter() {	PIXI.AbstractFilter.call( this,		// vertex shader		null,		// fragment shader		`			void main(){				gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );			}		`,		// set the uniforms		{			customUniform: {				type: '1f',				value: 0			}		}	);}CustomFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );CustomFilter.prototype.constructor = CustomFilter;lzt filter = new CustomFilter();cat.filters = [ filter ];
When I add the following vertex shader :
// vertex shader`	uniform float offset;	void main() {	vec4 pos = modelViewMatrix * vec4( position + normal * offset, 1.0 );		gl_Position = projectionMatrix * pos;	}`,
It crashes the code and I have the following error popping in the console :
ERROR: 0:4: 'modelViewMatrix' : undeclared identifier ERROR: 0:4: 'position' : undeclared identifier ERROR: 0:4: 'normal' : undeclared identifier ERROR: 0:4: 'constructor' : not enough data provided for construction ERROR: 0:5: 'projectionMatrix' : undeclared identifier WebGL: INVALID_VALUE: attachShader: no object or object deletedPixi.js Error: Could not initialize shadergl.VALIDATE_STATUS falsegl.getError()Pixi.js Warning: gl.getProgramInfoLog() missing shadersWebGL: INVALID_VALUE: getUniformLocation: no object or object deletedWebGL: INVALID_VALUE: getAttribLocation: no object or object deletedWebGL: INVALID_OPERATION: drawElements: no valid shader program in useWebGL: too many errors, no more errors will be reported to the console for this context.

I don't know much about shaders. What am I doing wrong ?

 

Link to comment
Share on other sites

Those errors are telling you that you are using variables that don't actually exist in the final shader (because you didn't declare them). The confusing part is because Three.js inserts a bunch of uniforms magically at the top of shaders you pass into it. Pixi.js doesn't do that!

 

You probably want something more like:

 

precision lowp float;// these attributes & uniforms are set in by Pixi.js for you,// but you have to declare them yourself!attribute vec2 aVertexPosition;attribute vec2 aTextureCoord;attribute vec4 aColor;uniform mat3 projectionMatrix;// these are your custom uniforms you add in the filter class// it should be named "offset" in your class.uniform float offset;void main(void){   gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);}
(that is the default sprite shader we use in pixi, with some comments and "offset" put in there)

I'll try to get an outline filter running post back when it works.

Link to comment
Share on other sites

Though now that I think about it, this probably won't do what you want. The reason that shader you linked looks good is it outlines the geometry that it is drawing, but for a sprite the geometry is a square. So you will just draw a red square behind what your texture, and not actually outline it.

Instead you can try this outline filter someone made a while ago:

http://codepen.io/anon/pen/RPRNdE

You will have to update it for v3, it was written for v2.

Here was the original thread: http://www.html5gamedevs.com/topic/10640-outline-a-sprite-change-certain-colors/

Link to comment
Share on other sites

Hi, thank you for your answer.

 

I simplified the pen you linked a little bit : http://codepen.io/anon/pen/VLjvxm to make it more understandable and to try to migrate it to pixi v3. But I think I'm missing something :)

 

By the way, all those glow, shadow, outline, shifting, embossing... filters could be managed by the dropShadowFilter if it had a little more options : color and spread ; plus if you can add multiple of them.

 

The CSS box-shadow property kicks ass for that : https://developer.mozilla.org/en/docs/Web/CSS/box-shadow : with only 6 params (inset, x, y, blur, spread and color). See on that very ugly page what you can do with it : http://elektronotdienst-nuernberg.de/bugs/box-shadow_inset.html .

 

I realy know nothing about open gl but is the current dropshadow filter far from that ? From what I understand : https://github.com/GoodBoyDigital/pixi.js/blob/master/src/filters/dropshadow/DropShadowFilter.js it mostly miss the spread.

Link to comment
Share on other sites

Ok, so I remembered a method that mishaa came up with a while ago using a convolution filter and colormatrix filter to draw the outline. I've updated it for use in v3:

http://codepen.io/anon/pen/rVLejp?editors=101

I also updated his OutlineFilter for v3, and included it below. Remember to use this shader you need to assign it to `sprite.shader` and not `sprite.filters`...
 

function OutlineFilter(viewWidth, viewHeight, thickness, color) {    PIXI.filters.AbstractFilter.call(this,        // vertex shader        null,        // fragment shader        [            'precision mediump float;',            'varying vec2 vTextureCoord;',            'uniform sampler2D uSampler;',            'uniform float thickness;',            'uniform vec4 outlineColor;',            'uniform float pixelWidth;',            'uniform float pixelHeight;',            'vec2 px = vec2(pixelWidth, pixelHeight);',            'void main(void) {',            '    const float PI = 3.14159265358979323846264;',            '    vec4 ownColor = texture2D(uSampler, vTextureCoord);',            '    vec4 curColor;',            '    float maxAlpha = 0.;',            '    for (float angle = 0.; angle < PI * 2.; angle += ' + (1 / thickness).toFixed(7) + ') {',            '        curColor = texture2D(uSampler, vec2(vTextureCoord.x + thickness * px.x * cos(angle), vTextureCoord.y + thickness * px.y * sin(angle)));',            '        maxAlpha = max(maxAlpha, curColor.a);',            '    }',            '    float resultAlpha = max(maxAlpha, ownColor.a);',            '    gl_FragColor = vec4((ownColor.rgb + outlineColor.rgb * (1. - ownColor.a)) * resultAlpha, resultAlpha);',            '}'        ].join('\n'),        // custom uniforms        {            thickness: { type: '1f', value: thickness },            outlineColor: { type: '4f', value: new Float32Array([0, 0, 0, 1]) },            pixelWidth: { type: '1f', value: null },            pixelHeight: { type: '1f', value: null },        }    );    this.color = color;    this.viewWidth = viewWidth;    this.viewHeight = viewHeight;};OutlineFilter.prototype = Object.create(PIXI.filters.AbstractFilter.prototype);OutlineFilter.prototype.constructor = OutlineFilter;module.exports = OutlineFilter;Object.defineProperties(OutlineFilter.prototype, {    color: {        get: function () {            return PIXI.utils.rgb2hex(this.uniforms.outlineColor.value);        },        set: function (value) {            PIXI.utils.hex2rgb(value, this.uniforms.outlineColor.value);        }    },        viewWidth: {        get: function () {            return 1 / this.uniforms.pixelWidth.value;        },        set: function(value) {            this.uniforms.pixelWidth.value = 1 / value;        }    },        viewHeight: {        get: function () {            return 1 / this.uniforms.pixelHeight.value;        },        set: function(value) {            this.uniforms.pixelHeight.value = 1 / value;        }    }});

Either one of these methods should work for you.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...