LibGDX shaperenderer wrong color - colors

I am in trouble setting the color of my rect. The color of my rect is grey with 0.5f alpha or black with 0. How could I set my color?
This is the code :
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(67 , 34 , 167, 0.5f);
shapeRenderer.rect(0, 0, Width, Height);
shapeRenderer.end();

#Xoppa is right
the r, g, b and a in
shapeRenderer.setColor(r, g, b, a); are always supposed to be between 0 and 1.
In your case it would be
shapeRenderer.setColor(67/255f, 34/255f, 167/255f, 0.5f);
And don't forget to add the f behind the numbers because we need float not double.

Related

Convert 24-bit color to 4-bit RGBI

I need to convert 24-bit colors to 4-bit RGBI (1 bit for Red, Green, Blue + Intensity).
Converting to 3-bit RGB is rather simple: set color bit if greater than 127, clear otherwise. However, there's only one intensity bit for all three channels, so what's the correct way to set it (if any)?
First I thought about dividing 8-bit channel to three parts like below:
if 0 <= color <= 85, then clear rgbi-color bit
if 86 <= color <= 170, then set rgbi-color bit
if 171 <= color <= 255, then set rgbi-color bit and intensity
But then I thought that probably the correct way would be to set intensity bit only if two of three channels are greater than 127. But in that case pure R, G, or B will not have intensity ever set (for example, in case of rbg(0,0,200)
Any advice is highly appreciated
A simple way to find the closest 4-bit RGBI approximation of a color is to consider the two possibilities for the intensity bit separately. That is to say, first find the closest RGB0 and RGB1 approximations for the color (which is easy to do, just by dividing each color axis at the appropriate point), and the determine which of these approximations is better.
Here's a simple C-ish pseudocode description of this algorithm:
// find the closest RGBx approximation of a 24-bit RGB color, for x = 0 or 1
function rgbx_approx(red, green, blue, x) {
threshold = (x + 1) * 255 / 3;
r = (red > threshold ? 1 : 0);
g = (green > threshold ? 1 : 0);
b = (blue > threshold ? 1 : 0);
return (r, g, b);
}
// convert a 4-bit RGBI color back to 24-bit RGB
function rgbi_to_rgb24(r, g, b, i) {
red = (2*r + i) * 255 / 3;
green = (2*g + i) * 255 / 3;
blue = (2*b + i) * 255 / 3;
return (red, green, blue);
}
// return the (squared) Euclidean distance between two RGB colors
function color_distance(red_a, green_a, blue_a, red_b, green_b, blue_b) {
d_red = red_a - red_b;
d_green = green_a - green_b;
d_blue = blue_a - blue_b;
return (d_red * d_red) + (d_green * d_green) + (d_blue * d_blue);
}
// find the closest 4-bit RGBI approximation (by Euclidean distance) to a 24-bit RGB color
function rgbi_approx(red, green, blue) {
// find best RGB0 and RGB1 approximations:
(r0, g0, b0) = rgbx_approx(red, green, blue, 0);
(r1, g1, b1) = rgbx_approx(red, green, blue, 1);
// convert them back to 24-bit RGB:
(red0, green0, blue0) = rgbi_to_rgb24(r0, g0, b0, 0);
(red1, green1, blue1) = rgbi_to_rgb24(r1, g1, b1, 1);
// return the color closer to the original:
d0 = color_distance(red, green, blue, red0, green0, blue0);
d1 = color_distance(red, green, blue, red1, green1, blue1);
if (d0 <= d1) return (r0, g0, b0, 0);
else return (r1, g1, b1, 1);
}
Alternatively, you could simply use any generic fixed-palette color quantization algorithm. This may yield better results if your actual color palette is not a pure evenly spaced RGBI palette like the code above assumes, but rather something like e.g. the CGA tweaked RGBI palette.

How to randomize between two set colors?

I want to know how to be able to have my program generate random color between two set colors and all inbetween the two. For example just the way that I would say:
fill(random(255),0,0));
in order to get a range reds.
I want to be able to choose two colors, let's say orange and blue, and have it generate colors from these two sets of colors. So for it to randomly generate a color from that shade of blue, any shade in between that and into a specific shade of orange.
How do I go about doing that?
Let's say you have 3 variables that hold the "base" color:
float baseR = 50;
float baseG = 100;
float baseB = 200;
You could then add a random number to those values to get a new shade "around" that color:
float shadeDistance = 10;
float r = baseR + random(-shadeDistance, shadeDistance);
float g = baseG + random(-shadeDistance, shadeDistance);
float b = baseB + random(-shadeDistance, shadeDistance);
fill(r, g, b);
Or if you have two colors that you want to blend, you can use the lerpColor() function:
stroke(255);
background(51);
color from = color(204, 102, 0);
color to = color(0, 102, 153);
color interA = lerpColor(from, to, .33);
color interB = lerpColor(from, to, .66);
fill(from);
rect(10, 20, 20, 60);
fill(interA);
rect(30, 20, 20, 60);
fill(interB);
rect(50, 20, 20, 60);
fill(to);
rect(70, 20, 20, 60);
(source: processing.org)

Color over color: how to get the resulting color?

I have the next task:
let's say, there are two colors: color1 and color2
color1 is semi-transparent (color2 maybe too)
I know ARGB values of color1 and color2
how to get the ARGB value of color which you get by overlaying color1 and color2 and vice versa?
Here is an image of what I am looking for:
And here is a code snippet (C#):
private Color getOverlapColor(Color frontColor, Color backColor)
{
//return...
}
The simplest way is to assume a linear scale.
int blend(int front, int back, int alpha)
=> back + (front - back) * alpha / 255;
And then:
Color getOverlapColor(Color front, Color back)
{
var r = blend(front.Red, back.Red, front.Alpha);
var g = blend(front.Green, back.Green, front.Alpha);
var b = blend(front.Blue, back.Blue, front.Alpha);
var a = unsure;
return new Color(r, g, b, a);
}
I'm unsure about how to calculate the resulting alpha:
if both front.Alpha and back.Alpha are 0, the resulting is also 0.
if front.Alpha is 0, the result is back.Alpha.
if front.Alpha is 255, the value of back.Alpha doesn't matter.
if front.Alpha and back.Alpha are both 50%, the result must be larger than 50%.
But I'm sure someone already figured out all of the above. Some SVG renderer, or GIMP, or some other image processing library should already have this code, carefully tested and proven in practice.

DrawText doesn't work, but Graphics::DrawString is ok

I am creating a bitmap in the memory which combine with an image and text. My code is:
HDC hdcWindow = GetDC();
HDC hdcMemDC = CreateCompatibleDC(hdcWindow);
HBITMAP hbmDrag = NULL;
if (!hdcMemDC) {
ReleaseDC(hdcWindow);
return NULL;
}
RECT clientRect = {0};
GetClientRect(&clientRect);
hbmDrag = CreateCompatibleBitmap(hdcWindow, 256, 256);
if(hbmDrag) {
SelectObject(hdcMemDC, hbmDrag);
FillRect(hdcMemDC, &clientRect, mSelectedBkgndBrush);
Graphics graphics(hdcMemDC);
// Draw the icon
graphics.DrawImage(mImage, 100, 100, 50, 50);
#if 1
CRect desktopLabelRect(0, y, clientRect.right, y);
HFONT desktopFont = mNameLabel.GetFont();
HGDIOBJ oldFont = SelectObject(hdcMemDC, desktopFont);
SetTextColor(hdcMemDC, RGB(255,0,0));
DrawText(hdcMemDC, mName, -1, desktopLabelRect, DT_CENTER | DT_END_ELLIPSIS | DT_CALCRECT);
#else
// Set font
Font font(hdcMemDC, mNameLabel.GetFont());
// Set RECT
int y = DEFAULT_ICON_HEIGHT + mMargin;
RectF layoutRect(0, y, clientRect.right, y);
// Set display format
StringFormat format;
format.SetAlignment(StringAlignmentCenter);
// Set brush
SolidBrush blackBrush(Color(255, 0, 0, 0));
// Draw the label
int labelWide = DEFAULT_ICON_WIDTH + mMargin;
CString labelName = GetLayOutLabelName(hdcMemDC, labelWide, mName);
graphics.DrawString(labelName, -1, &font, layoutRect, &format, &blackBrush);
#endif
}
DeleteDC(hdcMemDC);
ReleaseDC(hdcWindow);
return hbmDrag;
The image can be outputted to the bitmap success.
For the text, if I use "DrawText", it can't be shown in the bitmap although the return value is correct;
But Graphics::DrawString can output the text success.
I don't know the reason. Anybody can pls tell me?
Thanks a lot.
You are passing the DT_CALCRECT flag to DrawText(). This flag is documented as (emphasis mine):
Determines the width and height of the rectangle. If there are
multiple lines of text, DrawText uses the width of the rectangle
pointed to by the lpRect parameter and extends the base of the
rectangle to bound the last line of text. If the largest word is wider
than the rectangle, the width is expanded. If the text is less than
the width of the rectangle, the width is reduced. If there is only one
line of text, DrawText modifies the right side of the rectangle so
that it bounds the last character in the line. In either case,
DrawText returns the height of the formatted text but does not draw
the text.

Partially tinting sprite with pixel shader

I can't tint my sprite with color shader. Here is the problem:
Image on the left is from XNA, and right one is form gimp. Colored sprite still have some blue pixels. Blue color is used to pass tint. I think scalling or anti-aliasing mess it up. Here is my code:
float4 PixelShaderFunction(float2 coords: TEXCOORD0) : COLOR0
{
float4 color = tex2D(s0, coords);
float3 white = {1, 1, 1};
float3 colorTint = { 0.3f, 0, 0 };
if(color.a)
{
if(color.r < 0.1 && color.g < 0.1 && color.b > 0.1)
{
color.rgb = lerp(white, colorTint.rgb, 1 - color.b);
color.a = 1;
}
}
return color;
}
Edit:
Looks like setting sampler state to "SamplerState.PointClamp" is my solution, but maybe someone can tell me what's going on here?

Resources