How do I specify the bar colors in ImPlot::DrawBarGroups? - imgui

I'm struggling to understand how the colors work in ImPlot.
Here, I'm plotting bars in groups of 3.
static const char* labels[] = {"X", "Y", "Z"};
if (ImPlot::BeginPlot("Sensor activity"))
{
ImPlot::PlotBarGroups(labels, &(barData[0]), 3, numGroups, 1.0f, 0, 0);
ImPlot::EndPlot();
}
I would like the X, Y, and Z bars to be plotted in Red, Green and Blue respectively. How would I do that?

Related

OpenGL overlapping ugly rendering

I'm trying to render a scene with OpenGL 2.1 but the borders on overlapping shapes are weird. I tested some OpenGL initialisations but without any change. I reduce my issue to a simple test application with 2 sphere with the same result.
I tried several things about Gl_DEPTH_TEST, enable/disable smoothing without success.
Here is my result with 2 gluSphere :
We can see some sort of aliasing when a line will be enough to separate blue and red faces...
I use SharpGL but I think that it's not significant (as I use it only as a an OpenGL wrapper). Here my simplest code to render the same thing (You can copy it in a Form to test it) :
OpenGL gl;
IntPtr hdc;
int cpt;
private void Init()
{
cpt = 0;
hdc = this.Handle;
gl = new OpenGL();
gl.Create(SharpGL.Version.OpenGLVersion.OpenGL2_1, RenderContextType.NativeWindow, 500, 500, 32, hdc);
gl.Enable(OpenGL.GL_DEPTH_TEST);
gl.DepthFunc(OpenGL.GL_LEQUAL);
gl.ClearColor(1.0F, 1.0F, 1.0F, 0);
gl.ClearDepth(1);
gl.MatrixMode(OpenGL.GL_PROJECTION);
gl.Perspective(30, 1, 0.1F, 1.0E+7F);
gl.MatrixMode(OpenGL.GL_MODELVIEW);
gl.LookAt(0, 3000, 0, 0, 0, 0, 0, 0, 1);
}
private void Render(int angle)
{
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT | OpenGL.GL_STENCIL_BUFFER_BIT);
RenderSphere(gl, 0, 0, 0, 0, 300, Color.Red);
RenderSphere(gl, 0, 0, 100, angle, 300, Color.Blue);
gl.Blit(hdc);
}
private void RenderSphere(OpenGL gl, int x, int y, int z, int angle, int radius, Color col)
{
IntPtr obj = gl.NewQuadric();
gl.PushMatrix();
gl.Translate(x, y, z);
gl.Rotate(angle, 0, 0);
gl.Color(new float[] { col.R / 255f, col.G / 255f, col.B / 255f, col.A / 255f });
gl.QuadricDrawStyle(obj, OpenGL.GLU_FILL);
gl.Sphere(obj, radius, 20, 10);
gl.Color(new float[] { 0, 0, 0, 1 });
gl.QuadricDrawStyle(obj, OpenGL.GLU_SILHOUETTE);
gl.Sphere(obj, radius, 20, 10);
gl.DeleteQuadric(obj);
gl.PopMatrix();
}
Thanks in advance for your advices !
EDIT :
I tested that without success :
gl.Enable(OpenGL.GL_LINE_SMOOTH);
gl.Enable(OpenGL.GL_POLYGON_SMOOTH);
gl.ShadeModel(OpenGL.GL_SMOOTH);
gl.Hint(OpenGL.GL_LINE_SMOOTH_HINT, OpenGL.GL_NICEST);
gl.Hint(OpenGL.GL_POLYGON_SMOOTH_HINT, OpenGL.GL_NICEST);
gl.Hint(OpenGL.GL_PERSPECTIVE_CORRECTION_HINT, OpenGL.GL_NICEST);
EDIT2 : With more faces, image with and without lines
It is ... different... but not pleasing.
The issue has 2 reasons.
The first one indeed is a Z-fighting issue, which is cause by the monstrous distance between the near and far plane
gl.Perspective(30, 1, 0.1F, 1.0E+7F);
and the fact that at perspective projection, the depth is not linear. See also How to render depth linearly ....
This can be improved by putting the near plane as close as possible to the geometry. Since the distance to the object is 3000.0 and the radius of the sphere is 300, the near plane has to be less than 2700.0:
e.g.
gl.Perspective(30, 1, 2690.0F, 5000.0F);
The second issue is caused by the fact, that the sphere consist of triangle primitives. As you suggested in your answer, you can improve that by increasing the number of primitives.
I will provide an alternative solution, by using a clip plane. Clip the red sphere at the bottom and the blue sphere at the top. Exactly in the plane where the spheres are intersecting, so that a cap is cut off from each sphere.
A clip plane can be set by glClipPlane and to be enabled by glEnable.
The parameters to the clipping plane are interpreted as a Plane Equation.
The first 3 components of the plane equation are the normal vector to the clipping plane. The 4th component is the distance to the origin.
So the clip plane equation for the red sphere has to be {0, 0, -1, 50} and for the blue sphere {0, 0, 1, -50}.
Note, when glClipPlane is called, then the equation is transformed by the inverse of the modelview matrix. So the clip plane has to be set before the model transformations like rotation, translation and scale.
e.g.
private void Render(int angle)
{
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT | OpenGL.GL_STENCIL_BUFFER_BIT);
double[] plane1 = new double[] {0, 0, -1, 50};
RenderSphere(gl, 0, 0, 0, 0, 300, Color.Red, plane1);
double[] plane2 = new double[] {0, 0, 1, -50};
RenderSphere(gl, 0, 0, 100, angle, 300, Color.Blue, plane2);
gl.Blit(hdc);
}
private void RenderSphere(
OpenGL gl, int x, int y, int z, int angle, int radius,
Color col, double[] plane)
{
IntPtr obj = gl.NewQuadric();
gl.ClipPlane(OpenGL.GL_CLIP_PLANE0, plane);
gl.Enable(OpenGL.GL_CLIP_PLANE0);
gl.PushMatrix();
gl.Translate(x, y, z);
gl.Rotate(angle, 0, 0);
gl.Color(new float[] { col.R / 255f, col.G / 255f, col.B / 255f, col.A / 255f });
gl.QuadricDrawStyle(obj, OpenGL.GLU_FILL);
gl.Sphere(obj, radius, 20, 10);
gl.Color(new float[] { 0, 0, 0, 1 });
gl.QuadricDrawStyle(obj, OpenGL.GLU_SILHOUETTE);
gl.Sphere(obj, radius, 20, 10);
gl.DeleteQuadric(obj);
gl.PopMatrix();
gl.Disable(OpenGL.GL_CLIP_PLANE0);
}
Solution 1 (not a good one): Applying gl.Scale(0.0001, 0.0001, 0.0001); to the ModelView matrix
Solution 2 : The near plane has to be as far as possible to avoid compressing z value in a small range. In this case, use 10 instead of 0.1 is enough. The best is to compute an adapted value depending on objects distance (in this case the nearest object is at 2700)
I think we can focus on z is stored non-linearly in the #PikanshuKumar link and the implicit consequencies.
Result :
Only the faces are cutted by a line: there is a straight line as separator at the equator.
Those lines disappear as expected when we increase the number of faces.
You're killing depth buffer precision with the way you setup your projection matrix
gl.MatrixMode(OpenGL.GL_PROJECTION);
gl.Perspective(30, 1, 0.1F, 1.0E+7F);
Essentially this compresses almost all of the depth buffer precision into the range 0.1 to 0.2 or so (I didn't do the math, just eyeballing it here).
In general you should choose the distance for the near clip plane to be as far away as possible, still keeping all the objects in your scene. The distance of the far plane doesn't matter that much (in fact, with the right matrix magic you can place it at infinity), but in general it's also a good idea to keep it as close as possible.

DirectX primitive rendering at the wrong position

So I'm recoding my rendering engine, starting with the basics. I'm running is to a very weird issue. I'm simply rendering a triangle, but the position is all wrong.
Here's what I'm getting (can't post image cause I don't have enough rep yet):
Incorrect Result
That's obviously not what I'm trying to do.
Here's are my vertices I'm defining, what my vertex structure looks like, and what my FVF looks like:
CDirect3DHelper::VERTEX vertices[] =
{
{ 300, -300, 0, 1, D3DCOLOR_XRGB(0, 0, 255) },
{ 0, 300, 0, 1, D3DCOLOR_XRGB(0, 255, 0) },
{ -300, -300, 0, 1, D3DCOLOR_XRGB(255, 0, 0) }
}
struct VERTEX
{
float x, y, z, rhw;
DWORD color;
};
static const DWORD FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
Anyone have any idea what's wrong? I feel like I'm missing something really stupid.
Thanks!
The coordinates are outside your screen. The X and Y value of the vertex are in screen space where top left is 0,0 and right bottom is width,height

glColor3f does not change the color

I'm working on a Win32 app in C/C++ with SDL.
I have a weird problem with glColor3f command.
I want to print some text on my screen, it is working but the color of the text stay white.
The only way I have found so far to change the color is that : glColor3f(255,0,0);
I have tried this but the text still white :
// 1 try :
GLfloat Red = static_cast<GLfloat>(Objet.GetCouleurMenuRed()); // 255
GLfloat Green = static_cast<GLfloat>(Objet.GetCouleurMenuGreen()); // 0
GLfloat Blue = static_cast<GLfloat>(Objet.GetCouleurMenuBlue()); // 0
// 2 try :
float Red = static_cast<float>(Objet.GetCouleurMenuRed()); // 255
float Green = static_cast<float>(Objet.GetCouleurMenuGreen()); // 0
float Blue = static_cast<float>(Objet.GetCouleurMenuBlue()); // 0
// 3 try :
int Red = Objet.GetCouleurMenuRed(); // 255
int Green = Objet.GetCouleurMenuGreen(); // 0
int Blue = Objet.GetCouleurMenuBlue(); // 0
glColor3i(Red, Green, Blue); // --> Nothing on the screen
glColor3f(Red, Green, Blue); // --> Text OK but still white
I watch with a debug point the value in Red, Green, Blue : It is good.
So what is wrong with this?
EDIT : Thanks to derhass : works with glColor3ub();

DirectX9 C++ Recoloring Vertex data in real time

I'm very new to DirectX and I'm starting to get a grasp on how the API functions.
I've managed to get triangles showing and rendering properly using these functions:
Initializing the vertices:
void Menu::InitializeMenu(float x, float y, float width, float height, D3DCOLOR color, IDirect3DDevice9* d3dDevice)
{
CUSTOMVERTEX vertices[] =
{
{ x, y, 0.5f, 1.0f, color },
{ x + width, y, 0.5f, 1.0f, color },
{ x + width, y + height, 0.5f, 1.0f, color },
{ x, y, 0.5f, 1.0f, color },
{ x , y + height, 0.5f, 1.0f, color },
{ x + width, y + height, 0.5f, 1.0f, color },
};
if (FAILED(d3dDevice->CreateVertexBuffer(6 * sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_vertexBuffer, NULL)))
return;
void *locked_buffer;
if (FAILED(m_vertexBuffer->Lock(0, sizeof(vertices), (void **)&locked_buffer, 0)))
return;
memcpy(locked_buffer, vertices, sizeof(vertices));
m_vertexBuffer->Unlock();
}
Everything here is defined within the Menu class.
Drawing:
void Menu::RenderMenu(IDirect3DDevice9 *d3dDevice)
{
d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
d3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DRS_DESTBLENDALPHA);
d3dDevice->SetStreamSource(0, m_vertexBuffer, 0, sizeof(CUSTOMVERTEX));
d3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
d3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
}
Everything works perfect, I get my two triangles rendered, which in turn produce a semi-transparent quad.
Now the Issue:
I want to be able to change the colors of the vertices in my triangles after the program has started rendering (everything has been initialized already and rendered at least once).
Things I've thought about:
-I've thought about calling the InitializeMenu function with different parameters to reinitialize the vertices with different color, reason I haven't done it is because it seems very inefficient and not practical.
-Materials: I have not implemented materials, this is because I don't know how (yet) and because I'm hoping to find a simpler alternative. All I need is the vertex colors. If materials are the only way to accomplish this, I will implement.
-Shaders: I understand you can color vertices with shaders, but I have very little shader experience, and as stated before I'd rather find a simpler alternative. Yes, I know shaders are simple, I've gotten to the point where I can change the color of vertices in a shader in real time. It was in GLSL but I'm sure it doesn't differ too much. Issue comes when I want to add multiple quads (collection of 2 triangles for ea quad). I only know how to change the color of all vertices coming into the vertex shader. As before though, if shaders is the only way to accomplish, I'll implement. Please just point me in the right direction. I have VERY little understanding on how shaders work on the low level (I understand the concept and flow, just don't know how to use to my advantage to use effectively).
-Research: I've looked everywhere, maybe I'm not asking my question properly, but I cannot find an answer anywhere.
This is actually my first time posting a question, usually someone has already asked my questions. I've tried to explain my problem as best as I could, but if it's still unclear feel free to ask for more code or information.
P.S: I'm using windows 8 desktop, not sure if that really matters.
To update the vertices, you will need to do something similar to InitializeMenu, but without calling CreateVertexBuffer again. You will also need make a slight modification to how you create the vertex buffer.
There are two types of vertex buffers: static and dynamic. A static vertex buffer does not allow access by the CPU to make changes whereas a dynamic vertex buffer does.
To create a dynamic vertex buffer, add D3DUSAGE_DYNAMIC to CreateVertexBuffer:
d3dDevice->CreateVertexBuffer(6 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_vertexBuffer, NULL)
You can then make a new function like this to change color:
void Menu::ChangeColor(D3DColor color) {
CUSTOMVERTEX *locked_buffer;
if (FAILED(m_vertexBuffer->Lock(0, 0, (void **)&locked_buffer, 0))) {
return;
}
for (int i=0; i<6; i++) {
// use whatever you called color in your CUSTOMVERTEX struct
locked_buffer[i].color = color;
}
m_vertexBuffer->Unlock();
}
This code essentially gets the vertex data from the GPU and allows you to update it on the CPU. You don't need to recreate the vertex buffer, you just update the values you want.
You can define a random function and then add color elements i.e: Green, Blue, Yellow, Red, Purple etc into an array. Then you call the random function to randomly select the colors inside an array.
Like this:
int arr[15] = {10, 210, 140, 180, 250, 189, 183, 107, 183, 107, 60, 2, 55, 85, 48};
D3DCOLOR color1; D3DCOLOR color2; D3DCOLOR color3; D3DCOLOR color4;
srand(time(NULL));
CUSTOMVERTEX vertices[] =
{{ x, y, 0.5f, 1.0f, color = D3DCOLOR_XRGB(arr[rand() % 14 + 0], arr[rand() % 14 + 0], arr[rand() % 14 + 0])},
{ x + width, y, 0.5f, 1.0f, color = D3DCOLOR_XRGB(arr[rand() % 14 + 0], arr[rand() % 14 + 0], arr[rand() % 14 + 0])},
{ x + width, y + height, 0.5f, 1.0f, color = D3DCOLOR_XRGB(arr[rand() % 14 + 0], arr[rand() % 14 + 0], arr[rand() % 14 + 0])},
{ x, y, 0.5f, 1.0f, color = D3DCOLOR_XRGB(arr[rand() % 14 + 0], arr[rand() % 14 + 0], arr[rand() % 14 + 0])},
{ x , y + height, 0.5f, 1.0f, color = D3DCOLOR_XRGB(arr[rand() % 14 + 0], arr[rand() % 14 + 0], arr[rand() % 14 + 0])},
{ x + width, y + height, 0.5f, 1.0f, color = D3DCOLOR_XRGB(arr[rand() % 14 + 0], arr[rand() % 14 + 0], arr[rand() % 14 + 0])},
};
One thing, you might have to use different D3DCOLOR color variables i.e; color1, color2, color3 etc to avoid dereferencing and value overwritting.

How can I copy parts of an image from the buffer into a texture to render?

I have been searching around for a simple solution, but I have not found anything. Currently I am loading a texture from a file and rendering it into the buffer using C++ 2012 Express DirectX9. But what I want to do is be able to copy parts of the buffer, and use the part that is copied as the texture, instead of the loaded texture.
I want to be able to copy/select like a map-editor would do.
EDIT: Problem Solves :) It was just dumb mistakes.
You can use the StretchRect function (see documentation).
You should copy a subset of the source buffer into the whole destination buffer (which is the new texture's buffer in your case). Something like this:
LPDIRECT3DTEXTURE9 pTexSrc, // source texture
pTexDst; // new texture (a subset of the source texture)
// create the textures
// ...
LPDIRECT3DSURFACE9 pSrc, pDst;
pTexSrc->GetSurfaceLevel(0, &pSrc);
pTexDst->GetSurfaceLevel(0, &pDst);
RECT rect; // (x0, y0, x1, y1) - coordinates of the subset to copy
rect.left = x0;
rect.right = x1;
rect.top = y0;
rect.bottom = y1;
pd3dDevice->StretchRect(pSrc, &rect, pDst, NULL, D3DTEXF_NONE);
// the last parameter could be also D3DTEXF_POINT or D3DTEXF_LINEAR
pSrc->Release();
pDst->Release(); // remember to release the surfaces when done !!!
EDIT:
OK, I've just got through the tones of your code and I think the best solution would be to use uv coordinates instead of copying subsets of the palette texture. You should calculate the appropriate uv coordinates for a given tile in game_class:: game_gui_add_current_graphic and use them in the CUSTOMVERTEX structure:
float width; // the width of the palette texture
float height; // the height of the palette texture
float tex_x, tex_y; // the coordinates of the upper left corner
// of the palette texture's subset to use for
// the current tile texturing
float tex_w, tex_h; // the width and height of the above mentioned subset
float u0, u1, v0, v1;
u0 = tex_x / width;
v0 = tex_y / height;
u1 = u0 + tex_w / width;
v1 = v0 + tex_h / height;
// create the vertices using the CUSTOMVERTEX struct
CUSTOMVERTEX vertices[] = {
{ 0.0f, 32.0f, 1.0f, u0, v1, D3DCOLOR_XRGB(255, 0, 0), },
{ 0.0f, 0.0f, 1.0f, u0, v0, D3DCOLOR_XRGB(255, 0, 0), },
{ 32.0f, 32.0f, 1.0f, u1, v1, D3DCOLOR_XRGB(0, 0, 255), },
{ 32.0f, 0.0f, 1.0f, u1, v0, D3DCOLOR_XRGB(0, 255, 0), } };
Example: Your palette consists of 3 rows and 4 columns with the 12 possible cell textures. Each texture is 32 x 32. So tex_w = tex_h = 32;, width = 4 * tex_w; and height = 3 * tex_h;. Suppose you want to calculate uv coordinates for a tile which should be textured with the image in the second row and the third column of the palette. Then tex_x = (3-1)*tex_w; and tex_y = (2-1)*tex_h;. Finally, you calculate the UVs as in the code above (in this example you'll get {u0,v0,u1,v1} = {(3-1)/4, (2-1)/3, 3/4, 2/3} = {0.5, 0.33, 0.75, 0.66}).