5
\$\begingroup\$

Thanks for wanting to help!

I'm trying to create a circular, repeating ring (that moves outward) on a texture. I've achieved this, to a degree, with the following code:

float distance = length(inTex - in_ShipCenter);
float time = in_Time;

///* Simple distance/time combination */
float2 colorIndex = float2(distance - time, .3);    

float4 shipColor = tex2D(BaseTexture, inTex);
float4 ringColor = tex2D(ringTexture, colorIndex);

float4 finalColor;
finalColor.rgb = (shipColor.rgb) + (ringColor.rgb);
finalColor.a = shipColor.a; // Use the base texture's alpha (transparency).


return finalColor; 

This works, and works how I want it to. The ring moves outward from the center of the texture at a steady rate, and is constrained to the edges of the base texture (i.e. it won't continue past an edge). However, there are a few issues with it that I would like some help on, though. They are:

  1. By combining the color additively (when I set finalColor.rgb), it makes the resulting ring color much lighter than I want (which, is pretty much the definition of additive blending, but I don't really want additive blending in this case).

  2. I would really like to be able to pass in the color that I want the ring to be. Currently, I have to pass in a texture that contains the color of the ring, but I think that doing it that way is kind of wasteful and overly-cumbersome.

I know that I'm probably being an idiot over this, so I greatly appreciate the help.

Some other (possibly relevant) information:

  • I'm using XNA.

  • I'm applying this by providing it to a SpriteBatch (as an Effect).

  • The SpriteBatch is using BlendState.NonPremultiplied.

Thanks in advance!

EDIT: Thanks for the answers thus far, as they've helped me get a better grasp of the color issue. However, I'm still unsure of how to pass a color in and not use a texture. i.e. Can I create a tex2D by using a float4 instead of a texture? Or can I make a texture from a float4 and pass the texture in to the tex2D?

DOUBLE EDIT: Here's some example pictures:

With the effect off:

Off

With the effect on:

On

With the effect on, but with the color weighting set to full:

On, With Full Color Weighting

As you can see, the color weighting makes the base texture completely black (The background is black, so it looks transparent). You can also see the red it's supposed to be, and then the white-ish it really is when blended additively.

\$\endgroup\$
2
  • \$\begingroup\$ What kind of ring texture are you using right now? Could you add a picture? (If you're trying to recreate the texture, I'd be nice to know what it looks like, so we can help you better) \$\endgroup\$
    – Msonic
    Sep 7, 2012 at 18:48
  • \$\begingroup\$ It's also important to note that the effect isn't using a round texture. All the texture is used for is to grab the color of the texture so the ring can be colored. \$\endgroup\$ Sep 7, 2012 at 21:07

1 Answer 1

2
\$\begingroup\$

You might want to set weights to the colors of the ring and the ship's texture so that they can cancel each other out and don't blend additively.

Make a white ring for the ring texture which would serve as a color mask, and use a float3 uniform variable to change it's color.

float3 newColor;

float4 ringColorMask = tex2D(ringTexture, colorIndex);
float4 ringColor = ringColorMask * newColor;

// All rgb channels have the same values for the max texture,
// so just sample the first one
float ringWeight = ringColorMask.r;
finalColor.rgb = (shipColor.rgb * (1 - ringWeight) + ringColor.rgb * ringWeight);

It's hard to visualize whether the ring is supposed to just expand, or both move away and expand, but it seems like you would want to set ringWeight according to the color mask

\$\endgroup\$
4
  • \$\begingroup\$ This sort-of helps. The only problem with it is that as I cancel out the ship texture, it becomes more and more transparent, eventually disappearing all together. There's a picture of it in my original question. \$\endgroup\$ Sep 7, 2012 at 20:45
  • \$\begingroup\$ The color weight needs to correspond to the presence of color in the ring. In places where the ring's color exists, set the weight to 1, and where the pixels are completely black or transparent, the weight should be 0. \$\endgroup\$
    – ChrisC
    Sep 7, 2012 at 21:19
  • \$\begingroup\$ What's the best way to do that, since I'm essentially returning the whole texture? Would it be easier to just create the ring separately, and then use the base texture as a mask? (Although I'm not quite sure how that would work...) \$\endgroup\$ Sep 7, 2012 at 21:23
  • \$\begingroup\$ Use the white ring texture for a mask. RGB values would be the same for a given pixel since mask textures are usually grayscale. The R component represents the luminance value of the mask, and the color weight also equals luminance. \$\endgroup\$
    – ChrisC
    Sep 10, 2012 at 15:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .