0
votes

I'm trying to write simple shader to put some "mark"(64*64) on base texture(128*128), to indicate where mark must be, i use cyan colored mark-sized(64*64) region on base texture.
base image
mark image
becomes
desired result

Fragment shader

precision lowp float;

uniform sampler2D us_base_tex;
uniform sampler2D us_mark_tex;

varying vec2 vv_base_tex;
varying vec2 vv_mark_tex;

const vec4 c_mark_col = vec4(0.0, 1.0, 1.0, 1.0);//CYAN

void main()
{
 vec4 base_col = texture2D(us_base_tex, vv_base_tex);

if(base_col == c_mark_col)
{
 vec4 mark_col = texture2D(us_mark_tex, vv_mark_tex);//texelFetch magic overhere must be
 base_col = mix(base_col, mark_col, mark_col.a);
}
 gl_FragColor = base_col;
}

Of course, it not works as it should, i got something like this (transperity only for demonstration, there is no cyan region, only piece of "T"):
problem

I try to figure it and only something like texelFetch will help me, but i can't figure out, how get tex coord of base texture cyan texel and converted it to get - first col/first row cyan base texel = first col/first row mark texel, second col/first row base = second col/first row of mark. e.t.c.

1
If you have the image coordinates of the "mark" why can't you simply adjust the texture coordinates (and addressing mode) of the "T" texture so it sits in the right place? The geometry you're using is just a quad, right?Ani
Yeah just quad, you mean changing vv_mark_tex coordinates? And what about addressing mode? "T" is different texture i must put it in cyan region, i don't know cyan region texture position only what it is same size with mark.Aristarhys
Let me simplify my question - do you know the pixel/image-coordinates of the cyan rectangle?Ani
No, cyan region can be anywhere at base texture where it fits - upper right corner, center, bottom left etc. Whole thing was about writing a shader which use some colored region to determine place for mark(decal). I can use some uniforms for this, but this is different case. In theory - artist use such color regions for placing various decals on sprites, so them became customizable.Aristarhys
You can't solve this problem this way because the pixel shader is invoked in parallel and each instance has no way of knowing where they are in relation to the cyan square. The only image-space information each pixel shader has is the current (varying) texcoords which is relative to the top left of the texture. Are you open to a multi-pass approach or something that involves a little texture pre-processing? Is this meant for mobile or PCs?Ani

1 Answers

2
votes

I think there's a way to do this in a single pass - but it involves using another texture that is capable of holding the information presented below. So you're going to increase your texture memory usage.

In this approach, the second texture (it can be generated by post-processing the original texture either offline or somehow) contains the UV map for the decal

  1. R = normalized distance from left of cyan square
  2. G = normalized distance from the top of the cyan square
  3. B = don't care

Now the pixel shader is simple, all it needs to do is to see if the current texel is cyan, pick the R and G from the "decal-uvmap" texture and use those as texture coords to sample the decal texture.

Note that the bit depth of this texture (and it's size) is related to the size of the original texture so it may be possible to get away with a much smaller "decal-uvmap" texture than the original.