Hello.
I'm making example filter with custom fragment shader. This is what I have in terms of shader code so far:
//fragShader
struct SomeInfo
{
vec4 color;
};
uniform SomeInfo c;
void main()
{
gl_FragColor = c.color;
}
The idea is to (eventually) make c into an array of Infos, which would be then operated on by the shader.
What I'm struggling with is the definition of filter:
- how do I declare the uniform to be of type SomeInfo in Js code?
I assume in plain WebGL, I'd have to bind uniform location (of c's property) by calling gl.getUniformLocation(program, "c.color") and create a uniform with appropriate gl.uniform4f(location, /* bunch of values*/),
but can I do something similar via the existing filters means?
Relevant part of my Js code looks like this:
//Define base filter class for our future shaders/filters
PIXI.filters.CustomFilterBase = class CustomFilterBase extends PIXI.Filter
{
constructor({ vertexSrc = null, fragmentSrc = null, uniforms = {}, enabled = true, debug = false, name = null } = {})
{
if(debug && fragmentSrc !== null)
{
fragmentSrc = "#define DEBUG \r\n" + fragmentSrc;
}
//Add dimensions for scaling
uniforms.dimensions = { type: 'vec2', value: { x: 0.0, y: 0.0 } };
super(vertexSrc, fragmentSrc, uniforms);
name ? this._name = name : this._name = "CustomFilterBase";
this.autoFit = false;
this.enabled = enabled;
}
apply(filterManager, input, output)
{
this.uniforms.dimensions.x = input.sourceFrame.width;
this.uniforms.dimensions.y = input.sourceFrame.height;
// draw the filter...
filterManager.applyFilter(this, input, output);
}
}
//Shader for prototyping and testing
PIXI.filters.TestFilter = class TestFilter extends PIXI.filters.CustomFilterBase
{
constructor()
{
let fragmentSrc = document.getElementById('fragShader').innerHTML;
let uniforms =
{
//What do I do here?!
c:
{
type: 'vec4', //Judging by GLSL_SINGLE_SETTERS, only GLSL's primitives are recognized
value: new Float32Array([0.0, 1.0, 0.0, 1.0])
}
};
super({ vertexSrc: null, fragmentSrc: fragmentSrc, uniforms: uniforms, name: 'testfilter' });
}
}
(using pixijs v4.8.7)
The expected result is green screen, as it is if I declare c as vec4 in shader code, but alas the screen is black, hinting on c's value being default constructed / not properly assigned
Any help is appreciated,
cheers!
P.S. I tried to find similar cases from this forum and stackoverflow, but it seems that few people use structs in GLSL code.
P.P.S. If it is of any help, I found that PIXI.glCore.shader removes specific characters from uniform's name (which looks like a hotfix rather than a feature)
and that in fact one of iterations uniformData's name is 'c.color'.
/**
* Extracts the uniforms
* @class
* @memberof PIXI.glCore.shader
* @param gl {WebGLRenderingContext} The current WebGL rendering context
* @param program {WebGLProgram} The shader program to get the uniforms from
* @return uniforms {Object}
*/
var extractUniforms = function(gl, program)
{
var uniforms = {};
var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
for (var i = 0; i < totalUniforms; i++)
{
var uniformData = gl.getActiveUniform(program, i);
var name = uniformData.name.replace(/\[.*?\]/, ""); //<----- Here it is!!
var type = mapType(gl, uniformData.type );
uniforms[name] = {
type:type,
size:uniformData.size,
location:gl.getUniformLocation(program, name),
value:defaultValue(type, uniformData.size)
};
}
return uniforms;
};