How to draw a single pixel in OpenGL?
Asked Answered
S

3

21

Can someone tell me how to draw a single white pixel at a coordinate, say (100,200)?

I am using GLUT and so far have figured out how to open a blank window. Once I figure out how to draw pixels, I will use that to implement the Bresenham line drawing algorithm. (Yes, I am aware OpenGL can draw lines. I am required to implement this myself).

#include <stdio.h>
#include <GL/glut.h>

static int win(0);

int main(int argc, char* argv[]){
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_RGBA|GLUT_SINGLE);
    glutInitWindowSize(500,500);
    glutInitWindowPosition(100,100);

    //step 2. Open a window named "GLUT DEMO"
    win = glutCreateWindow("GLUT DEMO");
    glClearColor(0.0,0.0,0.0,0.0); //set background

    glClear(GL_COLOR_BUFFER_BIT);
    glFlush();
    glutMainLoop();
}
Scrofula answered 23/2, 2017 at 1:27 Comment(2)
This is an odd thing to do with OpenGL, and not really what it's designed for. Why are you using OpenGL for it? I suppose you could create a texture with your line pixels and draw a triangle/quad with that texture, or you could render a point for each pixel.Acolyte
Are you required to use Deprecated Legacy OpenGL 1.0 or can you use Modern OpenGL v3.3 or higher?Jarrad
S
31

glVertex2i(x,y);

Here is the context it needs to work:

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

glutInitWindowPosition(80, 80);
glutInitWindowSize(500,500);

glutCreateWindow("A Simple OpenGL Program");

glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D( 0.0, 500.0, 500.0,0.0 );

glBegin(GL_POINTS);
   glColor3f(1,1,1);
   glVertex2i(100,100);
glEnd();
Scrofula answered 23/2, 2017 at 4:12 Comment(2)
Also a valid answer, although, note that, you could draw more than just the one pixel, if glPointSize is not 1 (which it is by default).Otha
Note that this answer as far as I understand OpenGL, uses legacy code. The driver of the device it's running on must support a compatibility Profile of OpenGL for this to work.Oracular
O
5

This can be done easily by setting the scissor rectangle, and then clearing, which will only clear the specified area in the scissor rectangle. For example:

glEnable(GL_SCISSOR_TEST);
glScissor(100, 200, 1, 1);
glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT);
// Remember to disable scissor test, or, perhaps reset the scissor rectangle:
glDisable(GL_SCISSOR_TEST); 
Otha answered 23/2, 2017 at 4:13 Comment(1)
this is brilliant, now i have a crosshair, without introducing complex UI layerSupererogate
W
2

Using modern OpenGL you can combine glScissor() with a quad that fills the entire screen.

The shaders can be as simple as:

// Vertex Shader
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
// Fragment Shader
#version 330 core
out vec4 FragColor;
uniform vec4 inColor;
void main()
{
    FragColor = inColor;
}

After doing OpenGL and Windows initialization with your preferred method (GLFW, GLAD, GLEN, etc.), create a quad (really two triangles) to cover the entire screen like:

float vertices[] = {
    -1.0f, -1.0f, 0.0f,
     1.0f, -1.0f, 0.0f,
     1.0f,  1.0f, 0.0f,
    -1.0f, -1.0f, 0.0f,
     1.0f,  1.0f, 0.0f,
    -1.0f,  1.0f, 0.0f
};

Then create your buffers, compile your shaders and bind your shader program and VAO.
Then use:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Your drawing code would look something like this to draw a green pixel at x = 100, y = 100:

GLint transformLoc = glGetUniformLocation(shaderProgramId, "inColor");
glUniform4f(transformLoc, 0.0f, 1.0f, 0.0f, 1.0f);

glEnable(GL_SCISSOR_TEST);
glScissor(100, 100, 1, 1); // position of pixel
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisable(GL_SCISSOR_TEST);

I wrote a tiny graphics rendering class built on top of OpenGL that has code doing exatly that. Its core function is putPixel(), which receives the x/y coordinates and a color to draw a single pixel on the screen. Feel free to take a look at the code: https://github.com/amengol/MinGL

Wearproof answered 5/5, 2021 at 17:40 Comment(1)
Not sure why you'd use a shader to draw a fullscreen quad, instead of just a using clear, as in my answer. Clear will be more efficient, easier to implement, and will work in both legacy and modern OGL.Otha

© 2022 - 2024 — McMap. All rights reserved.