Masking a mesh to an image

As I’m finishing up my app and working on the graphic effects, I’ve run into questions I can’t figure out. My question is is there a way to mask one mesh over an image? In other words, one mesh’s outline would be the mask to an image. For example, you have a triangle, that is a mesh, and you have an image. I want to only see the triangle part of the image below it.
Any help would be wonderful.

I am not sure i uderstand your problem.
If you draw the mesh after the image, then it will mask the image? You have to leave a triangle hole in you mesh however, but you already know that…?
Or if your image is not too big, you can add it in your mesh texture image, and add a rectangle fit onto this part or the texture, and put the rectangle below the rest of the mesh triangles. But you know that too.

@Ignatz - I swear I’m blind. I scavenged your site for something like that, but you can’t input a mesh and an image, right?
@Jmv38 - I’m not the best at explaining things. If you look at Ignatz’s link, I basically want the same thing, just with the mesh texture to be the mesh outline.
Thanks for the help!


Try this. Note you can adjust the mask position using an offset

-- StencilMask

function setup()
    stencilImg=readImage("Cargo Bot:Starry Background") 
    img=readImage("Planet Cute:Character Princess Girl") 
    --create your mesh any way you want
    --this is the extra bit you need
    m.shader = shader(stencilShader.vertexShader, stencilShader.fragmentShader)
    m.shader.negative=true --false inverts the mask
    --offset lets you cut out your image at a selected place in the mesh

function draw()

stencilShader = {
vertexShader = [[
// A basic vertex shader

//This is the current model * view * projection matrix
// Codea sets it automatically
uniform mat4 modelViewProjection;

//This is the current mesh vertex position, color and tex coord
// Set automatically
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;

//This is an output variable that will be passed to the fragment shader
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
    //Pass the mesh color to the fragment shader
    vColor = color;
    vTexCoord = texCoord;

    //Multiply the vertex position by our combined transform
    gl_Position = modelViewProjection * position;

fragmentShader = [[
// A basic fragment shader

//Default precision qualifier
precision highp float;

//This represents the current texture on the mesh
uniform lowp sampler2D texture;

uniform lowp sampler2D texture2;
uniform bool negative;
uniform vec2 offset;

//The interpolated vertex color for this fragment
varying lowp vec4 vColor;

//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;

void main()
    //Sample the texture at the interpolated coordinate
    lowp vec4 col1 = texture2D( texture, vTexCoord );
    lowp vec4 col2 = texture2D( texture2, vec2(vTexCoord.x-offset.x,vTexCoord.y-offset.y));
    if (negative)
        {if (col2.a>0.)  gl_FragColor = col1; else discard;} 
    else if (col2.a==0.) gl_FragColor = col1; else discard;


@Zoyt you can also do this without using shaders, what you need to do is map the texture coordinates of each vertex in the mesh from 0 to 1 based on the mesh’s extents.

If you copy the mapMeshCoords and meshBounds functions to your own projects you can generate this mapping for any mesh by calling mapMeshCoords( myMesh ).

(The image to be masked is simply set as the texture of the mesh. However the image will be scaled to match the mesh extents.)

Here is the example code:

-- Mesh Mask

-- This function iterates through the mesh
--  and returns two values defining the bounds
--  returns lower left (vec3), upper right (vec3)
function meshBounds( m )
    local verts = m.vertices
    local ll = vec3( math.huge, math.huge, math.huge )
    local ur = -ll
    local v
    for i = 1,#verts do
        v = verts[i]
        if v.x < ll.x then ll.x = v.x end
        if v.y < ll.y then ll.y = v.y end
        if v.z < ll.z then ll.z = v.z end
        if v.x > ur.x then ur.x = v.x end
        if v.y > ur.y then ur.y = v.y end
        if v.z > ur.z then ur.z = v.z end
    return ll, ur

-- This function normalizes the texture coordinates
--  of all the vertices within a mesh bassed on their
--  spatial position
function mapMeshCoords( m )
    local ll, ur = meshBounds( m )
    local bounds = vec2( ur.x - ll.x, ur.y - ll.y )
    local v, tx, ty
    for i = 1,m.size do
        v = m:vertex(i)
        tx = (v.x - ll.x) / bounds.x
        ty = (v.y - ll.y) / bounds.y
        m:texCoord( i, tx, ty )

function setup()
    m = mesh()
    parameter.action( "Texture 1",
        m.texture = "Cargo Bot:Codea Icon"
     end )
    parameter.action( "Texture 2",
        m.texture = "Cargo Bot:Starry Background"
     end )
    m.texture = "Cargo Bot:Codea Icon"
    m:addRect(-50, -50, 150, 150, 0.5)
    m:addRect( 50,  80, 200, 200, 1.1)
    m:addRect(-70, 100,  80,  80, 0.5)
    mapMeshCoords( m )

function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    translate(WIDTH/2, HEIGHT/2)


Thanks a lot guys. I’ll be using @Simeon’s because it’s a bit cleaner and uses less code.

@MMGames - Do you mean “why”? And if you are trying to make a code section, you need to put a return between the ~~~, code, and ~~~.
I need this because I use meshes to create shapes of any polygon. I need to texture the shapes so they look good, but if I just normally apply a texture to the shape, it will look distorted.