OpenGL array of points - arrays

I have the following code to draw an array of points but it only draws one point in the center. How can I draw an array of 2D points using OpenGL?
GLint NumberOfPoints = 10;
GLfloat x[2],y[2];
glBegin( GL_POINTS );
for ( int i = 0; i < NumberOfPoints; ++i )
{
glVertex2f( x[i], y[i] );
}
glEnd();

Requires GLUT for window and context management:
#include <GL/glut.h>
#include <vector>
#include <cstdlib>
struct Point
{
float x, y;
unsigned char r, g, b, a;
};
std::vector< Point > points;
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50, 50, -50, 50, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw
glColor3ub( 255, 255, 255 );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
glVertexPointer( 2, GL_FLOAT, sizeof(Point), &points[0].x );
glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Point), &points[0].r );
glPointSize( 3.0 );
glDrawArrays( GL_POINTS, 0, points.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glFlush();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(640,480);
glutCreateWindow("Random Points");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
// populate points
for( size_t i = 0; i < 1000; ++i )
{
Point pt;
pt.x = -50 + (rand() % 100);
pt.y = -50 + (rand() % 100);
pt.r = rand() % 255;
pt.g = rand() % 255;
pt.b = rand() % 255;
pt.a = 255;
points.push_back(pt);
}
glutMainLoop();
return 0;
}

Where are you setting the values for x[0], x[1], y[0], and y[1]?
If it's only drawing one point in the center, it sounds like the values are set to 0 for all four of those variables. Be sure to initialize their values before you reference them in your call to gVertex2f().

Do you define what x[i] and y[i] are? Otherwise they will be set to 0 automatically (hence the centering). Also, creating the arrays with two elements but accessing 10 elements is very bad since you are accessing memory locations that you do not have control over.
You should do something like :
GLint NumberOfPoints = 10;
GLfloat x[10],y[10];
for(int i = 0; i < NumberOfPoints; i++){
x[i] = y[i] = (GLfloat) i;
}
glBegin( GL_POINTS );
for ( int i = 0; i < NumberOfPoints; ++i )
{
glVertex2f( x[i], y[i] );
}
glEnd();

Your code just works. Fill the array x and y with randomized values and this would draw random points.
The problem may be you can't 'see' the points you draw. That's obvious since:
By default the color of the points is black( 0, 0, 0, in rgb), and you may want to set it to some other value using glColor3f or such functions.
You've drawn too few points and each point is too small(actually only 1 pixel size on your screen). You may want to draw circles instead or draw thousand or more pixels and check again.
By the way, please format your question and let the code displayed normally.
Edited:
See my comment above. If you didn't set up a valid OpenGL context or you just didn't know how, check this http://openglbook.com/the-book/chapter-1-getting-started/ and get started with your first working OpenGL program.

Related

Displaying in openGL based on a matrix

I am trying to draw some shapes in the openGL window. I draw these shapes based on the values in a particular matrix. I am using glut which has a function glutDisplayFunc that takes 1 parameter, a function callback taking no arguments and returns void. But I need to draw an image on the window based on a matrix which I cannot pass to the function callback.
This is an example code
#include<stdio.h>
#include<GL/glut.h>
#include<math.h>
#define pi 3.142857
void mat()
{
int a[2][2];
//
for(int i=0;i<2;i++)
for (int j = 0; j < 2; ++j)
{
scanf("%d",&a[i][j]);
}
}
// function to initialize
void myInit (void)
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glColor3f(0.0, 1.0, 0.0);
glPointSize(1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-780, 780, -420, 420);
}
void display (void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POINTS);
float x, y, i;
for ( i = 0; i < (2 * pi); i += 0.001)
{
x = 200 * cos(i);
y = 200 * sin(i);
glVertex2i(x, y);
}
glEnd();
glFlush();
}
int main (int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
// giving window size in X- and Y- direction
glutInitWindowSize(1366, 768);
glutInitWindowPosition(0, 0);
glutCreateWindow("Circle Drawing");
myInit();
glutDisplayFunc(display);
glutMainLoop();
}
I need to be able to use the matrix a in function mat to define the center of 2 circles. How do I draw the window from within the mat function?
Edit:included code and fixed some typos
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
//-----------
float a[4][4] = {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1 };
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf((float*)a);
//----------
glBegin(GL_POINTS);
float x, y, i;
for (i = 0; i < (2 * pi); i += 0.001)
{
x = 200 * cos(i);
y = 200 * sin(i);
glVertex2i(x, y);
}
glEnd();
glFlush();
}
In general you can load the current model view matrix, by setting the GL_MODELVIEW matrix mode (glMatrixMode), and loading the matrix by glLoadMatrixf.
Optionally the matrix can be multiplied to the current matrix by glMultMatrix.
But in both cases, the matrix has to be 4x4 Transformation matrix. The parameter to both functions is a pointer to an array of 16 floats respectively an 2 dimensional 4x4 float-array.
Init a 4x4 Identity matrix and read the upper left 2x2, to set up a rotation matrix around the z-axis:
Further, I recommend to read an rotation angle in degree and to calculate the rotation axis by the trigonometric functions sin respectively cos.
Finally read the xy translation components:
#define _USE_MATH_DEFINES
#include <math.h>
float a[4][4];
void mat()
{
// init identity matrix
for(int i = 0; i < 4; i++)
for (int j = 0; j < 4; ++j)
a[i][j] = (i==j) ? 1.0f : 0.0f;
// read the angle in degrees
float angle_degree;
scanf("%f", &angle_degree);
// convert the angle to radian
float angle_radiant = angle_degree * (float)M_PI / 180.0f;
// set rotation around z-axis
float cos_ang = cos(angle_radiant);
float sin_ang = sin(angle_radiant);
a[0][0] = cos_ang;
a[0][1] = -sin_ang;
a[1][0] = sin_ang;
a[1][1] = cos_ang;
// read translation
scanf("%f", &a[3][0]);
scanf("%f", &a[3][1]);
}
void display (void)
{
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(&a[0][0]);
// [...]
}

How can I make this sphere revolve around another when I press a key?

I am new to OpenGL and I am trying to mimic the planetary system. I have an Earth and Sun. I want the earth to rotate on its axis when I press R and to revolve around the sun when I press T. I have tried the following with no success. Here is the code so far:
#include <GL/glut.h>
int angle=1;
int x,y,z=0;
int axis=0;
void init(void){
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void drawEarth(void){
glutWireSphere(0.5,30,30);
}
void idleFunc(){
angle++;
glutPostRedisplay();
}
void key(unsigned char key, int x, int y){
if (key=='R'){
idleFunc(); // How can I make this function run ONLY when I press R?
//Or how can I make my earth continuosly rotating when I press R?
glutPostRedisplay();
} else
if(key=='T'){
//How can I make it revolve around the sun when I press key T?
//I have tried glTranslate(x,y,z); with no success
glutPostRedisplay();
}
}
void display(void){
glClearColor(0.05,0.05,0.5,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
///////////////////////
glColor3f(0.03,0.05,0.09);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glRotatef(angle, 1.0,1.0,1.0); //Is this making it rotate about its axis?
drawEarth(); //Draw Earth
glPopMatrix();
/////////////////////////////////////
glPushMatrix();
glTranslatef(.7,.7,.7);
glColor3f(1.0,1.0,1.0);
glutWireSphere(0.2,50,50); //Sun
glPopMatrix();
glFlush();
}
int main(int argc, char **argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutInitWindowPosition(10,10);
glutInitWindowSize(400,400);
init();
glutCreateWindow("Planets");
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutIdleFunc(idleFunc);
glFlush();
glutMainLoop();
}
Question:
How can I make the earth revolve around the sun? Thanks.
PS: I have put some comments in the code where I am confused.
Set up your timer/idle callback so that it always runs but only updates the sun/axis angle if the corresponding flag (that the keyboard callback toggles) is set:
#include <GL/glut.h>
bool animateAxis = false;
bool animateSun = false;
void key(unsigned char key, int x, int y)
{
if( key == 'r' ) animateAxis = !animateAxis;
if( key == 't' ) animateSun = !animateSun;
}
int angleAxis = 0;
int angleSun = 0;
void update()
{
if( animateAxis ) angleAxis += 3;
if( animateSun ) angleSun += 1;
angleAxis = angleAxis % 360;
angleSun = angleSun % 360;
}
void display(void)
{
glClearColor(0.05,0.05,0.2,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
const double w = glutGet( GLUT_WINDOW_WIDTH );
const double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective( 60.0, w / h, 0.1, 100.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt
(
30, 30, 30,
0, 0, 0,
0, 0, 1
);
// sun
glColor3ub( 255, 255, 0 );
glutWireSphere( 5, 8, 8 );
// earth
glPushMatrix();
// rotate around sun
glRotatef( angleSun, 0, 0, 1 );
glTranslatef( 20, 0, 0 );
// rotate around axis
glRotatef( angleAxis, 0, 0, 1 );
glColor3ub( 31, 117, 254 );
glutWireSphere( 2, 8, 8 );
glPopMatrix();
glutSwapBuffers();
}
void timer( int value )
{
update();
glutPostRedisplay();
glutTimerFunc( 16, timer, 0 );
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutCreateWindow("Planets");
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
}

Turtle drawing fractal with openGl

I'm trying to do Koch snowflake for a computer graphics course. Searching on the web i've found that a sequence named Thue-morse can approximate the Koch snowflake by using a turtle drawing method.
Here is the code i have so far:
#include <GLUT/glut.h>
#include <math.h>
#include <string.h>
//screen size
#define WIDTH 1024
#define HEIGHT 800
float x, y,mUx,mUy;
//init the turtle environment
void turtleInit(){
x = WIDTH/2; // this is the starting point for the x
y = HEIGHT/2; // this is the starting point for the y
mUx = 1;
mUy = 0;
}
//move the turtle ds units
void turtleMove(float ds){
x += mUx * ds;
y += mUy * ds;
}
//turn left by "ang" radians if positive and right if negative.
void turtleTurn(float ang){
float ux = mUx;
float uy = mUy;
mUx = ux * cos(ang) - uy * sin(ang);
mUy = uy * cos(ang) + ux * sin(ang);
}
//thue morse sequence used to approximate the Koch snowflake
char thue_memoization[10000000];
int thueMorseRecurrenceRelation(int i){
if( thue_memoization[i] != -1 )
return thue_memoization[i];
if ( i % 2 != 0 )
return thue_memoization[i] = 1 - thueMorseRecurrenceRelation(i / 2);
else
return thue_memoization[i] = thueMorseRecurrenceRelation(i / 2);
}
void display( void ){
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-WIDTH, WIDTH, -HEIGHT, HEIGHT, -50, 50);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_POINTS);
glColor3f(0, 0, 1);
turtleInit();
for (int i = 0; i < 1000000; ++i) {
const static float p = 1;//turtle's step
if ( thueMorseRecurrenceRelation(i) )
turtleTurn(M_PI/3.0);
turtleMove(p);
glVertex2f(x, y);
}
glEnd();
glFlush();
}
int main(int argc,char **argv){
memset(thue_memoization,-1,sizeof(thue_memoization));
thue_memoization[0] = 0; //stop condition for the recurrence relation
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(0,0);
glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow("Koch snowflake. The winter is comming ...");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
It worked quite well here.
But i don't understand how the turtleTurn function works. Someone can help me ?
This is the formula for a 2d rotation:
(mUx, mUy) contains the coordinates of the "heading vector" of the turtle, then what turtleTurn(float ang) does is turning this vector by an angle (ang).
If you want a nice explanation of this formula, in particular where the sine and cosine come from, you can take a look at the following page, that
has some drawings that will make it clearer:
https://www.siggraph.org/education/materials/HyperGraph/modeling/mod_tran/2drota.htm

tessellating a sphere using triangles of different colors

I am writing a function to generate a sphere using triangles to tessellate it, but what I want is for the triangles to all have different colors. However, when I run the code, it creates a sphere but the colors range from light blue to black with no green or red at all and the colors repeat, which is not what I want.
Here is a segment of the code. The whole code can produce a sphere but it is the coloring that I am really stuck on.
triangles is a vector<vector<Vertex3>> which contains the collection of all triangle vertices that make up this sphere.
glBegin(GL_TRIANGLES);
int red = 0;
int green = 0;
int blue = 0;
for( int j = 0; j< triangles.size(); j++ )
{
if(red < 200)
red++;
else if (blue < 200)
green++;
else blue++;
glColor3ub(red, green, blue);
//normalize the triangles first
triangles[j][0].normalize();
triangles[j][2].normalize();
triangles[j][2].normalize();
//call to draw vertices
glVertex3f( (GLfloat)triangles[j][0].getX(),(GLfloat)triangles[j][0].getY(),
(GLfloat)triangles[j][0].getZ());
glVertex3f( (GLfloat)triangles[j][3].getX(),(GLfloat)triangles[j][4].getY(),
(GLfloat)triangles[j][5].getZ());
glVertex3f( (GLfloat)triangles[j][2].getX(),(GLfloat)triangles[j][2].getY(),
(GLfloat)triangles[j][2].getZ());
}
glEnd();
Instead of glColor3ub(red, green, blue), try using glColor3ub( rand()%255, rand()%255, rand()%255 ).
Usage:
glBegin(GL_TRIANGLES);
for( int j = 0; j< triangles.size(); j++ )
{
glColor3ub( rand()%255, rand()%255, rand()%255 );
//normalize the triangles first
triangles[j][0].normalize();
triangles[j][1].normalize();
triangles[j][2].normalize();
//call to draw vertices
glVertex3f( (GLfloat)triangles[j][0].getX(),(GLfloat)triangles[j][0].getY(),
(GLfloat)triangles[j][0].getZ());
glVertex3f( (GLfloat)triangles[j][1].getX(),(GLfloat)triangles[j][1].getY(),
(GLfloat)triangles[j][1].getZ());
glVertex3f( (GLfloat)triangles[j][2].getX(),(GLfloat)triangles[j][2].getY(),
(GLfloat)triangles[j][2].getZ());
}
glEnd();
EDIT: Generate, store, and render:
#include <GL/glut.h>
#include <vector>
using namespace std;
struct Vertex
{
Vertex( bool random = false )
{
x = y = z = 0;
r = g = b = a = 0;
if( random )
{
x = rand() % 20 - 10;
y = rand() % 20 - 10;
z = rand() % 20 - 10;
r = rand() % 255;
g = rand() % 255;
b = rand() % 255;
a = 1;
}
}
float x, y, z;
unsigned char r, g, b, a;
};
vector< Vertex > verts;
void init()
{
// fill verts array with random vertices
for( size_t i = 0; i < 100; ++i )
{
verts.push_back( Vertex(true) );
verts.push_back( Vertex(true) );
verts.push_back( Vertex(true) );
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-10, 10, -10, 10, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// enable vertex and color arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
// set vertex and color pointers
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &verts[0].x );
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &verts[0].r );
// draw verts array
glDrawArrays(GL_TRIANGLES, 0, verts.size() );
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glFlush();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(800,600);
glutCreateWindow("Demo");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
init();
glutMainLoop();
return 0;
}
I'd expect the colors to go from black to med red to med yellow to gray to lt blue grey with the way your if statement is setup (assuming you have at least 600 triangles.) How many tris are you rendering? Also, depending on how your other shaders are setup, textures could get in the way as could anything else if your vertex format is mismatched. Also not sure how glColor3ub() reacts when the blue field goes above 255, which it will in the above code rather quickly. If it truncates the bits, then you would see the colors repeat from yellow to blue grey every 256 triangles after the first 400 .

Getting smooth, big points in OpenGL

I started playing around with OpenGL and GLUT. I would like to draw some points, but the problem is that they turn out to be squares, and I would like them to be round dots (filled circles).
This is what I do:
void onInitialization( )
{
glEnable( GL_POINT_SMOOTH );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glPointSize( 6.0 );
}
void onDisplay()
{
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glBegin( GL_POINTS );
glColor3f( 0.95f, 0.207, 0.031f );
for ( int i = 0; i < g_numPoints; ++i )
{
glVertex2f( g_points[i].X, g_points[i].Y );
}
glEnd();
glFinish();
glutSwapBuffers();
}
This is the result:
The points show up where expected, only their shape is wrong.
Unlike what was said previously, this is possible with the fixed-function pipeline, even with the GL_POINTS primitive type, as long as you have support for OpenGL 1.4 or the GL_ARB_point_sprite extension. Consult this document, or the OpenGL core specification of your choice : http://www.opengl.org/registry/specs/ARB/point_sprite.txt
GL_ARB_point_sprite converts points into "quads", i.e a polygon with the form of a plane. The exact primitive type it gets converted to is not defined by the specification, though it is not important. What is important is that GL_COORD_REPLACE auto-generates texture coordinates for the surface when enabled, so you can texture-map them with a sphere-shaped RGBA-texture.
EDIT: It seems like you (the poster) is right. Anti-aliased points get rounded with respect to their radius. (I've used OpenGL since 2003, and I didn't know this. [/shame])
So enabling GL_POINT_SMOOTH while you have a multisample-able visual/pixelformat, you get rounded points. Still, multisampling can be slow, so I'd implement both. Textured quads are cheap.
To request a visual with multisampling with XLib, use these two attributes in the list to glXChooseFBConfig():
GLX_SAMPLE_BUFFERS - its value should be True. This is an on/off toggle.
GLX_SAMPLES - the number of samples.
To request a pixelformat with Win32, use these two attributes in the list to ChoosePixelFormat() or wglChoosePixelFormatARB():
WGL_SAMPLE_BUFFERS_ARB Same as above, a toggle.
WGL_SAMPLES_ARB Same as above, the number of samples.
It seem that you can OR in the flag GLUT_MULTISAMPLE to glutInitDisplayMode to get multisampling in GLUT, but you can't request the number of sample buffers.
Here is how alpha-blended quads could be implemented using your test case.
void onInitialization( )
{
glEnable( GL_POINT_SPRITE ); // GL_POINT_SPRITE_ARB if you're
// using the functionality as an extension.
glEnable( GL_POINT_SMOOTH );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glPointSize( 6.0 );
/* assuming you have setup a 32-bit RGBA texture with a legal name */
glActiveTexture(GL_TEXTURE0);
glEnable( GL_TEXTURE_2D );
glTexEnv(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
glTexEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, texture_name);
}
void onDisplay()
{
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glBegin( GL_POINTS );
glColor4f( 0.95f, 0.207, 0.031f, 1.0f );
for ( int i = 0; i < g_numPoints; ++i )
{
glVertex2f( g_points[i].X, g_points[i].Y );
}
glEnd();
glFinish();
glutSwapBuffers();
}
Image of rounded points using per-fragment alpha blending + textures:
(source: mechcore.net)
Image of rounded points by using GL_POINT_SMOOTH and multisampling:
(source: mechcore.net)
A little sample I made which shows both techniques. Requires libSDL and libGLEW to compile:
#include <iostream>
#include <exception>
#include <memory>
#include <SDL/SDL.h>
#include <cmath>
#include <GL/glew.h>
#include <GL/glu.h>
#define ENABLE_TEXTURE
#define ENABLE_MULTISAMPLE
int Width = 800;
int Height = 600;
void Draw(void);
void Init(void);
inline float maxf(float a, float b)
{
if(a < b)
return b;
return a;
}
inline float minf(float a, float b)
{
if(a > b)
return b;
return a;
}
GLuint texture_name;
int main(void)
{
try {
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
#ifdef ENABLE_MULTISAMPLE
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
#endif
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
SDL_SetVideoMode(Width, Height, 32, SDL_OPENGL);
glewInit();
Init();
SDL_Event event;
bool running = true;
while(running){
while(SDL_PollEvent(&event)){
switch(event.type)
{
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_ESCAPE)
running = false;
break;
case SDL_QUIT:
running = false;
break;
}
}
Draw();
SDL_GL_SwapBuffers();
}
SDL_Quit();
}
catch(std::bad_alloc& e)
{
std::cout << "Out of memory. " << e.what() << std::endl;
exit(-1);
}
catch(std::exception& e)
{
std::cout << "Runtime exception: " << e.what() << std::endl;
exit(-1);
}
catch(...)
{
std::cout << "Runtime exception of unknown type." << std::endl;
exit(-1);
}
return 0;
}
void Init(void)
{
const GLint texWidth = 256;
const GLint texHeight = 256;
const float texHalfWidth = 128.0f;
const float texHalfHeight = 128.0f;
printf("INIT: \n");
unsigned char* pData = new unsigned char[texWidth*texHeight*4];
for(int y=0; y<texHeight; ++y){
for(int x=0; x<texWidth; ++x){
int offs = (x + y*texWidth) * 4;
float xoffs = ((float)x - texHalfWidth) / texHalfWidth;
float yoffs = ((float)y - texHalfWidth) / texHalfHeight;
float alpha = 1.0f - std::sqrt(xoffs*xoffs + yoffs*yoffs);
if(alpha < 0.0f)
alpha = 0.0f;
pData[offs + 0] = 255; //r
pData[offs + 1] = 0; //g
pData[offs + 2] = 0; //b
pData[offs + 3] = 255.0f * alpha; // *
//printf("alpha: %f\n", pData[x + y*texWidth + 3]);
}
}
#ifdef ENABLE_TEXTURE
glGenTextures(1, &texture_name);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture_name);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData);
glEnable(GL_POINT_SPRITE);
glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif
glPointSize(32.0f);
glMatrixMode(GL_PROJECTION);
glOrtho(0, Width, 0, Height, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
#ifdef ENABLE_MULTISAMPLE
glEnable(GL_POINT_SMOOTH);
#endif
GLenum e;
do{
e = glGetError();
printf("%s\n",gluErrorString(e));
} while(e != GL_NO_ERROR);
delete [] pData;
}
void Draw(void)
{
const int gridWidth = 1024;
const int gridHeight = 1024;
float t1, t2;
t1 = t2 = (float)SDL_GetTicks() * 0.001f;
t1 = fmod(t1, 10.0f) / 10.0f;
t2 = fmod(t2, 4.0f) / 4.0f;
float scale = 0.5f + (-sin(t2 * 2.0 * M_PI) + 1.0f) * 1.2f;
//glColor4f(0.4f, 0.5f, 0.9f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef((Width>>1), (Height>>1), 0.0f);
glScalef(scale,scale,scale);
glRotatef(t1 * 360.0f, 0.0f, 0.0f, 1.0f);
glBegin(GL_POINTS);
for(int j=0; j<gridHeight; j+=64){
for(int i=0; i<gridWidth; i+=64){
glVertex2i(i-(gridWidth>>1),j-(gridHeight>>1));
}
}
glEnd();
}
Mads' answer provides everything you need if you go for the fixed function pipeline. However, if you have a system that does not provide the ARB_point_sprite extension or with a broken implementation (some ATI drivers), you can solve this part also with geometry shaders. The ARB_geometry_shader4
extension allows you to convert a point primitive to two triangles, which can be used as the quad created by the ARB_point_sprite extension. On OpenGL 3.2, geometry shaders are already supported in core, no extension needed. The OpenGL wiki has two examples.
Not possible with a fixed opengl function. Dots are always square :)
You have to draw your own circle (by building it up like a cake, piece by piece) or draw a GL_QUAD with a "circle" texture on.
best regards,
andre

Resources