Filter system


Before reading, please make sure you update PixelsWorld to v3.6.0+

Filter system is a kind of encapsulation of quad shader, it allows you to build post-processing shader fast.

By reading this section, you will learn how to use Filter system in PixelsWorld.

Create a filter

Call newFilter(glslCode) to create a filter program.

  • Return: a random integer that represents the filter. (filterID)

glslCode will be inserted into the following context:

glslcode_context.glsl


#version 330 core
in vec2 uv;
out vec4 outColor;

// Your glslCode here!

Example

Note: In lua, we use [[...]] to quote a multiple-line-string.

newFilter.lua

version3()
filterID = newFilter([[
    void main(){
        outColor = vec4(uv,0,1);
    }
]])

Run a filter

Call runFilter(filterID) to run a filter program.

Example

runFilter.lua

version3()

filterID = newFilter([[
    void main(){
        outColor = vec4(uv,0,1);
    }
]])

runFilter(filterID)

Delete a filter

Call delFilter(filterID) to delete a filter.

Normally, you don't have to delete filters. PixelsWorld deletes all filters at the end of every frame automatically. However, it's still a nice habit to delete filters by hand when it's not in used.

Example

delFilter.lua

version3()
filterID = newFilter([[
    void main(){
        outColor = vec4(uv,0,1);
    }
]])
delFilter(filterID)

Set uniforms of filter

Call setFilterUniform(filterID, uniformType, uniformName, data0, data1, data2, ...) to set the value of uniform data.

  • filterID: Id of the filter.
  • uniformType: A string that represents the data type. It can be 1d-data ("int","float","bool"), vectors ("vec2","vec3","vec4","ivec2"...), matrices ("mat2, mat4x3, ..."), or texture ("sampler2D")
  • uniformName: Name of the data you want to set.
  • data0,data1,...: Float data. (See example)

Example

setFilterUniform.lua

version3()


filterID = newFilter([[

    uniform float myfloat;
    uniform vec2 myvec;
    uniform mat3x2 mymat;
    uniform sampler2D mytex1;

    void main(){
        outColor = vec4(myfloat,myvec[0],mymat[0][1],1) + texture(mytex1,uv);
    }
]])



setFilterUniform(filterID, "float", "myfloat", math.sin(time)*0.5 + 0.5)

setFilterUniform(filterID, "vec2", "myvec", 1,2)

-- Column major, namely mymat[0][0]==1, mymat[0][1]==slider(0), mymat[0][2]==2, mymat[1][0]==3, ...
setFilterUniform(filterID, "mat3x2", "mymat", 1, slider(0), 2, 3, 4, 5)

-- Use INPUT texture as mytex1
setFilterUniform(filterID, "sampler2D", "mytex1", INPUT)

-- ** You can also set the texture you created as mytex1 **
-- myInputTexID = newTex(512,256)
-- setFilterUniform(filterID, "sampler2D", "mytex1", myInputTexID)

runFilter(filterID)

Set output texture

Call setFilterDrawto(filterID, texID) to specify the output texture the result will be written. About texID, see also: Texture system

The default Drawto is OUTPUT

You can even apply a filter iteratively to a texture.

See also: Advanced application

Create a filter module

Call newFilterModule(glslCode) to create a filter module.

  • Return: A table contains filterID and some utility functions.

The main usage of the filter module is to simplify your code.

Normally, if you don't use the filter module, you should create and apply a filter in this way:

no_module.lua


version3()


filterID = newFilter([[

    uniform float myfloat;

    void main(){
        outColor = vec4(myfloat,0,0,1);
    }
]])

setFilterUniform(filterID, "float", "myfloat", math.sin(time)*0.5 + 0.5)

setFilterDrawto(filterID, OUTPUT)

runFilter(filterID)

delFilter(filterID)

Things will be easier if you use the filter module.

no_module.lua


version3()


filter = newFilterModule([[

    uniform float myfloat;

    void main(){
        outColor = vec4(myfloat,0,0,1);
    }
]])

filter.set("float", "myfloat", math.sin(time)*0.5 + 0.5)

filter.drawto(OUTPUT)

filter.run()

filter.del()

Advanced application

Here is a example of the famous channel blur effect.

  • slider 0: Blur intensity.
  • layer 0: Blur mask layer.

channel blur preview

iterateFilter.lua


version3()

-- Create a temp texture
tempTexID = newTex(width,height)

-- Copy input to temp texture
castTex(tempTexID, INPUT)


-- Blur code
blurGLSLCode = [[
    uniform sampler2D in_tex;
    uniform mat3 kernel;
    uniform vec2 resolution;
    void main()
    {
        vec2 xy = resolution * uv;
        vec4 res = vec4(0,0,0,0);
        for(int x = 0; x < 3; x++)
        {
            for(int y = 0; y < 3; y++)
            {
                vec2 curxy = xy + vec2(x-1,y-1);
                res += texture(in_tex,curxy/resolution) * kernel[x][y];
            }
        }
        outColor = res;
    }
]]


-- Combine code
combineGLSLCode = [[
    uniform sampler2D images[4];
    uniform sampler2D masktex;
    uniform mat2 uvcoord;
    void main()
    {
        vec2 newuv = floor(uvcoord * uv * 128);
        float maskv = clamp(texture(masktex, uv).r,0,1);
        int maski = int(floor(maskv * images.length()));
        float maskw = fract(maskv * images.length());
        if(maski == images.length) maski--;
        vec4 c1 = texture(images[maski], uv);
        vec4 c2 = c1;
        if(maski+1<images.length) 
            c2 = texture(images[maski+1], uv);

        outColor = mix(c1, c2, maskw);
    }
]]

blurFilter = newFilterModule(blurGLSLCode)

-- Set the kernel data of 3x3 gaussian blur 
-- The data can be found at https://en.wikipedia.org/wiki/Kernel_(image_processing)
blurFilter.set("mat3", "kernel", 
    1.0/16, 2.0/16, 1.0/16, -- kernel[0][0], kernel[0][1], kernel[0][2]
    2.0/16, 4.0/16, 2.0/16, -- kernel[1][0], kernel[1][1], kernel[1][2]
    1.0/16, 2.0/16, 1.0/16) -- kernel[2][0], kernel[2][1], kernel[2][2]

blurFilter.set("vec2", "resolution", width, height)

-- Set temp texture as in_tex
blurFilter.set("sampler2D", "in_tex", tempTexID)

-- Set the temp texture as the Drawto
blurFilter.drawto(tempTexID)


middleResultTex = {}
for i=1,3 do
    middleResultTex[i] = newTex(width,height)
end


-- blur power
substep = slider(0)

-- Iterate filter 3*substep times
for i=1,3*substep do
    blurFilter.run()
    if i % substep == 0 then
        castTex(middleResultTex[i//substep], tempTexID)
    end
end


combineFilter = newFilterModule(combineGLSLCode)

combineFilter.set("sampler2D", "images", 
    INPUT,
    middleResultTex[1],
    middleResultTex[2],
    middleResultTex[3]
    )

combineFilter.set("sampler2D", "masktex",  PARAM0)

combineFilter.drawto(OUTPUT)

combineFilter.run()

results matching ""

    No results matching ""