Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

SetPixel()

Discussion in 'Scripting' started by bronxbomber92, Jun 24, 2007.

  1. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    888
    Hey, I'm trying to just draw a simple rectangle. I've allocated a new global Texture2D object in my start function that is 500x50. Than, I try to use the SetPixel method(I tried the SetPixels, but the function didn't seem intiutive, as I need to interpolate between red and green based on the width of the rectangle) like so:
    Code (csharp):
    1. function DrawPowerBar( pos, width, height, RGBA )
    2. {
    3.   /*GL.PushMatrix();
    4.   GL.LoadOrtho();
    5.   GL.LoadIdentity();
    6.  
    7.   GL.Color(RGBA);
    8.   GL.Begin(GL.QUADS);
    9.     GL.Vertex3(pos.x, pos.y + height, 0 );
    10.     GL.Vertex3(pos.x + width, pos.y + height, 0 );
    11.     GL.Vertex3(pos.x + width, pos.y, 0 );
    12.     GL.Vertex3(0, 0, 0);
    13.   GL.End();
    14.   GL.PopMatrix();*/
    15.    
    16.    
    17.     for( var x = pos.x; x < width; x++ )
    18.     {
    19.         for( var y = pos.y; y < height; y++ )
    20.         {
    21.             var color = Color.Lerp(Color.red, Color.green, width );
    22.             powerBarTexture.SetPixel( x, y, RGBA );
    23.             powerBarTexture.Apply();
    24.         }
    25.     }
    26.    
    27. }
    (As you can see, I tried the GL class also, but it didn't work also :( )
    I have no idea why this doesn't work, and it seems that the x, y location is relative to the it's own dimension, is this true?

    Thanks,
    Jedd
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You don't seem to be using the variable "color". Shouldn't that be:

    Code (csharp):
    1. powerBarTexture.SetPixel( x, y, color );
    And you really don't want Apply() inside any loops...make that the last thing you do, or else it might be a tad bit slow. ;) And since color doesn't change, put that outside the loops too. x and y are absolute values...(0,0) is one corner and (127,127) is the opposite corner for a 128x128 texture. If x or y goes over the size of the texture, it either repeats or clamps depending on what the texture is set to do.

    --Eric
     
  3. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    888
    Actualy, I'm feeding it the interpolated color, so I don't need the "color" var. But if x and y are it's own coordinates, how do you draw where the texture is located on the screen? I want thi texture to be orthographic for part of the GUI...

    Also, I just tried what you suggested and it doesn't draw anything. (This is when I really wish the GL class was available for Indie >_>... and no, the above GL code doesn't work on indie.). I tried just drawing a set rectangle, and it didn't work, so something is up...
     
  4. socksy

    socksy

    Joined:
    May 21, 2005
    Posts:
    244
    Yeah, that's annoying. But their problem is, if they allow GL code then someone could program in render to textures, and the vast majority of features that pro has over indie would just disappear :(
     
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Does the color have any opacity? Otherwise it won't show up.

    Not sure I understand...don't you just move the GUITexture to where you want it?

    --Eric
     
  6. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    What is the "RGBA" that you're passing? Now you're doing three almost separate things:
    1) you are passing some "RGBA" (Color?) and setting pixels to that color.
    2) you are interpolating between red and green, storing the result in variable named 'color', but not actually using it anywhere.
    3) the interpolation is probably not what you want. To interpolate between red and green, the last argument should go from 0.0 to 1.0. Now it goes from zero to width.

    So here is the code that would actually fill the texture with a gradient:
    Code (csharp):
    1. function DrawPowerBar( pos, width, height )
    2. {
    3.     var dx = 1.0/width;
    4.     for( var x = pos.x; x < width; x++ )
    5.     {
    6.         var color = Color.Lerp( Color.red, Color.green, x * dx );
    7.         for( var y = pos.y; y < height; y++ )
    8.             powerBarTexture.SetPixel( x, y, color );
    9.     }
    10.     powerBarTexture.Apply();  
    11. }
    12.  
    But then still, I don't quite understand what you're trying to do. This code will always fill the texture with the same gradient (and the 'pos' parameter is not used in any way). So you could just draw such texture in Photoshop, that would be easier and faster.
     
  7. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    888
    Sorry, I sould of never posted the "color" variable. As I I'm not using it.

    Here's the context of how I wa using it (powerBar is of a custom class):
    Code (csharp):
    1. function UsePowerBar()
    2. {
    3.   DrawPowerBar( powerBar.bottomLeft, powerBar.width, powerBar.height, Color( red, green, 0, 1) );
    4.  
    5.   if( Input.GetKey("space") )
    6.   {
    7.     StartPowerBar = true;
    8.   }
    9.  
    10.   if( Input.GetMouseButtonUp(0) )
    11.   {
    12.     StartPowerBar = false;
    13.     BallSpeed = powerBar.width/10;
    14.     KickBall();
    15.   }
    16.  
    17.   if( bIncrement )
    18.   {
    19.     increment = 6.0;
    20.   }
    21.   else if( !bIncrement )
    22.   {
    23.     increment = -6.0;
    24.   }
    25.  
    26.   if( powerBar.width > 500 ) bIncrement = false;
    27.   if( powerBar.width <= 0 )   bIncrement = true;
    28.  
    29.   if( StartPowerBar )
    30.   {
    31.     powerBar.color = Color(red, green, 0, 255  );
    32.     if( bIncrement )
    33.     {
    34.       if( red > 0 )
    35.         red -= (powerBar.width/255);
    36.       if( green < 255 )
    37.         green += (powerBar.width/255);
    38.     }
    39.  
    40.     if( !bIncrement )
    41.     {
    42.       if( red < 255 )
    43.         red += (powerBar.width/255);
    44.       if( green > 0 )
    45.         green -= (powerBar.width/255);
    46.     }
    47.  
    48.     powerBar.width += increment;
    49.   }
    50. }
    This worked perfectly in C++/OGL. Same exact method. The RGBA parameter is just a Color. I guess it's not really interpolation, as the greater the width becomes, the more green it becomes, the smaller the width is the more red it becomes. I'll try your code out Aras, Thanks!

    Erich, I'm creating the texture on the fly. There is no "actual" texture this is attached to :/

    edit - Yeah, Aras's code doesn't draw anything either :/ Does this need to be attached to actual texture in the scene? I thought the whole point was to be able to create them on the fly...
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Code (csharp):
    1. var tex = new Texture2D(256, 128, TextureFormat.ARGB32, false);
    2. guiTexture.texture = tex;
    3. // tex.SetPixel() stuff
    4. tex.Apply();
    However, I wouldn't bother drawing textures for a power bar like this. Just make a small square white texture, and scale the GUITexture on the x axis to make it bigger or smaller, and do a Color.Lerp between red and green. Or make a gradient from red to green like Aras said and then stretch it; no lerping required.

    --Eric
     
  9. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    888
    Thanks guys! I just ended up using the scaled texture :p... Only problem is getting the color to change from red to green (and yellow in and green in the middle, having it changed smoothly). I can get it to change from red to green, but it's not like I described above... Any suggestion (basically I need to increase the red component, and decrease the green component or vice-versa)?
     
  10. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Color.Lerp, like I said. ;) This would change from red to green and then start over again every (1/rate) seconds:

    Code (csharp):
    1. var rate : float = .5;
    2. private var t: float;
    3.  
    4. function Update() {
    5.     t += Time.deltaTime * rate;
    6.     t = t%1;
    7.     renderer.material.color = Color.Lerp(Color.red, Color.green, t);
    8. }
    --Eric
     
  11. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    888
    Hmm, I did try Lerp, but, I think I used it incorrectly (I wasn't continually applying it). I'll give it a try again :)
     
  12. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    888
    Is there a way to cap the interpolation, instead of clamping it? I tried checking to see if it was the desireed color, and if not then you it would interpolate more. But, it was never equal to Color.green.
     
  13. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I must be kind of slow today...not sure what you mean exactly. The thing with lerp is that you want to feed it a control value from 0 to 1, with 0 returning 100% of the first value and none of the second value, and 1 returning 100% of the second value and none of the first. So giving it .75 would give you 25% of the first value and 75% of the second. With a power bar you typically have some maximum value, so you'd do something like:

    Code (csharp):
    1. var maxStrength : float = 100;
    2.  
    3. function PowerBar(strength : float) {
    4.     var powerValue = strength/maxStrength;
    5.     renderer.material.color = Color.Lerp(Color.red, Color.green, powerValue);
    6. }
    7.  
    So doing "PowerBar(50);" in that case would get you halfway between red and green. Apologies if you knew all that. :)

    --Eric
     
  14. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Not sure what you're trying to do... do you want to interpolate between red and green through yellow (instead of through muddy brown that a simple Lerp does)? That would be probably easiest by interpolating in two steps: from red to yellow, and from yellow to green from there. Or just draw the texture in Photoshop :)
     
  15. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    888
    See the attached zip file. That has a demo of what I want to do. I was able to create with OGL perfectly...

    Right now, this is what I have.
    Code (csharp):
    1. function UsePowerBar()
    2. {
    3.    
    4.     PowerBarGUITexture.guiTexture.pixelInset = Rect( powerBar.bottomLeft.x, powerBar.bottomLeft.y , powerBar.width, powerBar.height );
    5.  
    6.   if( Input.GetKey("space") )
    7.   {
    8.     StartPowerBar = true;
    9.   }
    10.  
    11.   if( Input.GetMouseButtonUp(0) )
    12.   {
    13.     StartPowerBar = false;
    14.     BallSpeed = powerBar.width/15;
    15.     KickBall();
    16.   }
    17.  
    18.   if( bIncrement )
    19.   {
    20.     increment = 5.0;
    21.   }
    22.   else if( !bIncrement )
    23.   {
    24.     increment = -5  .0;
    25.   }
    26.  
    27.   if( powerBar.width > 500 ) bIncrement = false;
    28.   if( powerBar.width <= 0 )   bIncrement = true;
    29.  
    30.   if( StartPowerBar )
    31.   {
    32.    
    33.     if( bIncrement )
    34.     {
    35.             PowerBarGUITexture.guiTexture.color = Color.Lerp( Color.red, Color.green, powerBar.width/500 );
    36.     }
    37.  
    38.     if( !bIncrement )
    39.     {  
    40.                 PowerBarGUITexture.guiTexture.color = Color.Lerp( Color.green, Color.red, powerBar.width/500 );
    41.     }
    42.  
    43.     powerBar.width += increment;
    44.   }
    45. }
    46.  
    Here it pretty much always stays red.. As for creating a texture gradient, that wouldn't work, since never that would make the powerbar all the colors at once (ie, the gradient)...

    The longer the width becomes, the greener it becomes. The smaller it becomes, the redder it becomes.
     

    Attached Files: