issue with GL_STIPPLE

When drawing GL_STIPPLE line connected between two solid lines using primitives or using texturemap, the number of dashes in the stipple line gets changing when your perform rotation.

How can I draw the connecting dash-line between two solid lines such it won’t change the number of dashes when performing rotation?

Following is the entire code

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>

/* Create checkerboard texture /
/
#define checkImageWidth 4
#define checkImageHeight 4
static GLubyte checkImage[checkImageHeight][checkImageWidth][4];*/

#define myImageW 1
#define myImageH 1
static GLubyte myImage[myImageW][myImageH][4];
static float h_rot = 0.0;
static int width, height;

static GLuint texName;

void MouseEvent(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON) {
h_rot += 15;
} else if (button == GLUT_RIGHT_BUTTON) {
h_rot += 15;
}
glutPostRedisplay();
}

void makeImage(void)
{
/*for (int i = 0; i < checkImageHeight; i++) {
for (int j = 0; j < checkImageWidth; j++) {
int c = ((((i&0x0001)==0)^((j&0x0001))==0))255;
printf("i=%d, j =%d, c=%d
" , i, j, c);
checkImage[i][j][0] = (GLubyte) c;
checkImage[i][j][1] = (GLubyte) c;
checkImage[i][j][2] = (GLubyte) 0;
checkImage[i][j][3] = (GLubyte) 255;
}
}
/

for (int i = 0; i &lt; myImageW; i++) {
    for (int j = 0; j &lt; myImageH; j++) {
        if(myImageW == 1 && myImageH == 1) {
            myImage[i][j][0] = (GLubyte) 255;
            myImage[i][j][1] = (GLubyte) 255;
            myImage[i][j][2] = (GLubyte) 0;
            myImage[i][j][3] = (GLubyte) 255;
        } else {
           int c = ((((i&0x0001)==0)^((j&0x0001))==0))*255;
            printf("i=%d, j =%d, c=%d

" , i, j, c);
myImage[i][j][0] = (GLubyte) c;
myImage[i][j][1] = (GLubyte) c;
myImage[i][j][2] = (GLubyte) c;
myImage[i][j][3] = (GLubyte) 255;
}
}
}
}

void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);

makeImage();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
                                                                                                                                           
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
                                                                                                                                           
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                                                                                                                                           
/*glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth,
        checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
        checkImage);*/
                                                                                                                                           
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myImageW,
        myImageH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
        myImage);

}

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glViewport(0, 0, (GLsizei) width, (GLsizei) height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat) width/(GLfloat) height, 1.0, 30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -8);
                                                                                                                                           
glRotatef(h_rot, 1, 0, 0);
glRotatef(h_rot, 0, 1, 0);
glRotatef(h_rot, 0, 0, 1);
                                                                                                                                           
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, texName);
                                                                                                                                           
glEnable(GL_POINT_SPRITE);
glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
                                                                                                                                           
glPointSize(6);
glBegin(GL_POINTS);
glColor3d(0.5f, 0.05f, 1.0f);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, 1.0, 0.0);
glEnd();
glBegin(GL_POINTS);
glColor3d(0.5f, 0.05f, 1.0f);
glTexCoord2f(0.0, 0.0); glVertex3f(2.0, 2.0, 0.0);
glEnd();
                                                                                                                                           
glDisable(GL_TEXTURE_2D);
glLineWidth(4);
glLineStipple (1, 0x00FF);
glEnable(GL_LINE_STIPPLE);
glBegin(GL_LINE);
glColor3d(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
glColor3d(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0, 1.0); glVertex3f(3.0, 3.0, 0.0);
glEnd();
glDisable(GL_TEXTURE_2D);
                                                                                                                                           
glLineWidth(2);
glDisable(GL_LINE_STIPPLE);
                                                                                                                                           
glBegin(GL_LINE);
glColor3d(1.0f, 0.0f, 0.0f);
//glTexCoord2f(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glColor3d(0.0f, 0.0f, 1.0f);
//glTexCoord2f(0.0, 1.0);
glVertex3f(0.0, -2.0, 0.0);
glEnd();
glBegin(GL_LINE);
glColor3d(0.0f, 0.0f, 1.0f);
//glTexCoord2f(0.0, 0.0);
glVertex3f(0.0, -2.0, 0.0);
glColor3d(1.0f, 0.0f, 0.0f);
//glTexCoord2f(0.0, 1.0);
glVertex3f(3.0, 3.0, 0.0);
glEnd();
                                                                                                                                           
                                                                                                                                           
/*glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-2.0, 1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(0.0, 1.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(0.0, -1.0, 0.0);
                                                                                                                                           
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(2.41421, 1.0, -1.41421);
glTexCoord2f(1.0, 0.0); glVertex3f(2.41421, -1.0, -1.41421);
glEnd();*/
glFlush();

}

void reshape(int w, int h)
{
width = w;
height = h;
/glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -3.6);
/
}

void keyboard (unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
default:
break;
}
}

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(250, 250);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(MouseEvent);
glutMainLoop();
return 0;
}

Thank you.
-hiral

Stipple is defined to be per-fragment, not per-unit along an arbitrary oriented line, so what you’re seeing is the correct behavior.

You can get what you want by creating a texture with your stipple pattern in it and drawing textured lines. You’ll have to manually calculate texture coordinates using the length of each line segment.

Hi arekkusu,

Thank you for reply.

Can you please paste some code snippet.

Thank you again.

Hi arekkusu,

I m now doing following…
But still while rotating some dots gets visible in the window…

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, (GLsizei) width, (GLsizei) height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat) width/(GLfloat) height, 1.0, 30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -8);

glRotatef(h_rot, 1, 0, 0);
glRotatef(h_rot, 0, 1, 0);
glRotatef(h_rot, 0, 0, 1);

glColor3d(1.0f, 0.0f, 0.0f);
glBegin(GL_LINE);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(2.0, 2.0, 0.0);
glEnd();

glColor3d(0.0f, 1.0f, 0.0f);
glBegin(GL_LINE);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(-2.0, 2.0, 0.0);
glEnd();

glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, texName);

glBegin(GL_LINE);
glTexCoord2f(0.0, 1.0); gl
glBegin(GL_LINE);
glTexCoord2f(0.0, 1.0); glVertex3f(-2.0, 2.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(2.0, 2.0, 0.0);
glEnd();

glDisable(GL_TEXTURE_2D);

glFlush();

}

Here’s a simplified version of your code, showing the basic idea of textured lines:


#include <GLUT/glut.h>
#include <stdlib.h>
#include <stdio.h>

#define USE_TEXTURED_LINES 1

void init(void)
{
#if USE_TEXTURED_LINES
	GLubyte stipple[] = { 0x00, 0xFF };
	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexImage1D(GL_TEXTURE_1D, 0, GL_ALPHA, 2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, stipple);
	glAlphaFunc(GL_LESS, 0x80);
#else
	glLineStipple (1, 0x00FF);
#endif
}

void display(void)
{
	static float h_rot = 0.0;

	glClear(GL_COLOR_BUFFER_BIT);
	
	glLoadIdentity();
	glTranslatef(0.0, 0.0, -8);	
//	glRotatef(h_rot, 1, 0, 0);
//	glRotatef(h_rot, 0, 1, 0);
	glRotatef(h_rot, 0, 0, 1);
		
	glLineWidth(4);
#if USE_TEXTURED_LINES
	glEnable(GL_TEXTURE_1D);
	glEnable(GL_ALPHA_TEST);
	glBegin(GL_LINES);
		glColor3f(0.0f, 1.0f, 0.0f);
		glTexCoord1f(0.0); glVertex3f(0.0, 0.0, 0.0);
		glTexCoord1f(8.0); glVertex3f(3.0, 3.0, 0.0);
	glEnd();
	glDisable(GL_TEXTURE_1D);
	glDisable(GL_ALPHA_TEST);
#else
	glEnable(GL_LINE_STIPPLE);
	glBegin(GL_LINES);
		glColor3f(0.0f, 1.0f, 0.0f);
		glVertex3f(0.0, 0.0, 0.0);
		glVertex3f(3.0, 3.0, 0.0);
	glEnd();
	glDisable(GL_LINE_STIPPLE);
#endif
	
	glLineWidth(2);
	glBegin(GL_LINES);
		glColor3f(0.0f, 0.0f, 1.0f);
		glVertex3f(0.0, 0.0, 0.0);
		glVertex3f(0.0, -2.0, 0.0);
		glColor3f(1.0f, 0.0f, 0.0f); 
		glVertex3f(0.0, -2.0, 0.0);
		glVertex3f(3.0, 3.0, 0.0);
	glEnd();
	
	glutSwapBuffers();
	h_rot += 1;
	glutPostRedisplay();
}

void reshape(int w, int h)
{
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 1.0, 30.0);
	glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(250, 250);
	glutInitWindowPosition(100, 100);
	glutCreateWindow(argv[0]);
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	init();
	glutMainLoop();
	return 0;
}

I limited the rotation to a single axis to better see the stipple length changing.
You should see that the textured version always uses the same stipple length regardless of line orientation. However, if you rotate around arbitrary axes in 3D, that will no longer be true, because the texture coordinates are perspective interpolated. You could calculate the texture coordinates so that the stipple pattern ends up being correctly defined in screen space, but it depends on what sort of look you’re trying to achieve. For a real 3D scene, texturing the lines in 3D space is probably fine.

There are also some bugs in your code, like glBegin(GL_LINE). That throws INVALID_ENUM.

Hi arekkusu,

Thank you for this simple example.

This what I was looking to implement.

Do you have any idea, how the thing can be implemented with point sprites.

Thank you once again.

What do point sprites have to do with drawing lines?

Hi arekkusu,

The example that you shared is working fine, but when I use it for my application it gives stipple lines (using 1D texMap) as shown in this image .

Any idea why it disaplays two parallel lines ???

Thank you.

Hi arekkusu,

I observed that if I set the glLineWidth(8) then 1d texture displays two parallel lines (see image in previous post).
And if I set the glLineWidth(32), it would loook like…

But the same is not observed on you program.

Do you have any idea, why this is happening ???

Thank you.