Hola...
No se que estare haciendo mal pero hago una esfera de digamos 32 meridianos y 32 paralelos, pero me resulta muy muy lenta al momento de mostrarla...
¿como esta implementada la glutSolidSphere?
no me hace falta el codigo que genera los vertices sino el como fue hecha... con triangle_strip? o es acaso quad_strip?
se usan vertex array?
a la glutSolidSphere por mas meridianos y paralelos que le pongo se sigue viendo rapidisimo, en cambio mi esfera no.
por favor ayuda...
Podes hacer 3 cosas optimizar:
Una lista de comandos.
Un vertex buffer donde los vertes.
Y un triangle strip para los triangulos
Saludos
gracias
...una lista de comandos?
...no te entendi.
glList()
Lo normal es usar VBO, Vertex Buffer Object.
Busca directamente como hacer un vertex y un index buffer.
Saludos
CitarVBO
Esta y el triangle strip será lo que mas velocidad le den a la esfera
Cita de: "Pogacha"CitarVBO
Esta y el triangle strip será lo que mas velocidad le den a la esfera
posi! :)
Y no hacer glTranslate y glRotate por fixed pipelines xD
Evitar usar el fixed pipeline a toda costa, para una tetera no vas a saturar el BUS de datos por frame pero bueno :P
todos los consejos anteriores son buenos, aun así no me cuadra que una simple esfera te vaya tan lento. Puedes poner el codigo aquí?
Puede estar saturando el BUS de la tarjeta con algun bucle bestia que cambia datos.
Bottle Neck en CPU o GPU...
Usar gDebugger / VTune o hazte un profiler sencillo que mida tiempos :)
gracias a todos...ahora pongo el codigo para que me corrijan
Cuando hago la esfera lo hago de la sigiente forma:
- Cargo la textura para la esfera con cargarTGA().
- Genero la esfera, sus vertices, 4 por cada lado, y la normal asociada a cada lado. Todo lo anterior coordenadas de vertices y normales, lo guardo en un vector.
- LLamo a la funcion genera_lista que lo que hace es sacar del vector los vertices y normales, dibujar los lados y meterlos a un displaylist
- Luego mostrar la lista con la funcion dibuja.
-el numero de paralelos en la esfera es de 256
-el numero demeridianos en la esfera es de 256
-por lo tanto el numero de lados de la esfera es 65536
-La funcion cargaTGA es oviable...solo la puse.
//aqui cargo la texura de tipo tga
int cargarTGA( char *nombre, textura *imagen)
{
GLubyte cabezeraTGA[12]={0,0,2,0,0,0,0,0,0,0,0,0}; // Cabecera de un tga sin compresión
GLubyte compararTGA[12]; // Acá vamos a comprar la cabecera
GLubyte cabezera[6]; // Los 6 bytes importantes
GLuint bytesporpunto; // Cuantos bytes hay por punto
GLuint tamanoimagen; // Acá guardaremos el tamaño de la imagen
GLuint temp,i; // Variable temporal, y una para usar con el for
GLuint tipo=GL_RGBA; // Nuestro tipo por defecto, lo veremos mas abajo
FILE *archivo=fopen(nombre, "rb"); // Cargamos nuestro archivo en memoria
if( archivo == NULL ||// Existe nuestro archivo??
fread(compararTGA,1,sizeof(compararTGA),archivo)!=sizeof(compararTGA) || // Hay 12 bytes para leer??
memcmp(cabezeraTGA,compararTGA,sizeof(compararTGA))!=0 || // Son iguales??
fread(cabezera,1,sizeof(cabezera),archivo)!=sizeof(cabezera))
{
if(archivo==NULL)
return 0; // No se abrió el archivo
else
{
fclose(archivo);
return 0;
}
}
imagen->largo=256*cabezera[1]+ cabezera[0];
imagen->ancho=256*cabezera[3]+ cabezera[2];
/* Ahora vemos si hay datos no válidos, como largo o ancho iguales menores a 0 o iguales a 0 */
if( imagen->largo <= 0 || // Largo mayor que 0??
imagen->ancho <= 0 || // Ancho mayor que 0??
(cabezera[4]!=24 && cabezera[4]!=32)) { // bpp es 24 o 32?? (solo se cargan 24 y 32 bpp)
fclose(archivo);
return 0;
}
imagen->bpp=cabezera[4]; // Acá se guardan los bits por punto
bytesporpunto=cabezera[4]/8; // Acá los bytes por punto (1 byte = 8 bits)
tamanoimagen=imagen->largo * imagen->ancho * bytesporpunto;
// Esta es la memoria que necesitaremos para guardar los datos de la textura
/* Ahora reservamos espacio en memoria para nuestra textura, luego leemos la
textura del archivo */
imagen->dibujo = (GLubyte *)malloc(tamanoimagen); // Reservamos la memoria necesaria para nuestra textura
if(imagen->dibujo== NULL || // Se logró reservar la memoria???
fread(imagen->dibujo, 1, tamanoimagen, archivo) != tamanoimagen ) {
// Se lee, y se comprueba que lo leído es de la misma longitud que la asignada a a dibujo.
if(imagen->dibujo != NULL)
free(imagen->dibujo);
fclose(archivo);
return 0;
}
/* El formato tga guarda las imágenes en BGR, y opengl usa RGB,por lo cambiamos de lugares */
for(i=0; i < int(tamanoimagen); i+=bytesporpunto)
{
temp=imagen->dibujo[i]; // Guardamos el primer valor
imagen->dibujo[i] = imagen->dibujo[i + 2]; // Asignamos el nuevo primer valor
imagen->dibujo[i + 2] = temp; // Asignamos el ultimo valor
}
fclose (archivo); // Cerramos el archivo
/* Listo, terminamos con el código de carga, volvemos a opengl, ahora hay
que asignarle a la textura un ID, luego decirle a opengl cuales son el largo,
el ancho y los bpp */
glGenTextures(1,&imagen->ID); // Crea un ID para la textura, buscando un id que este vacío
glBindTexture(GL_TEXTURE_2D, imagen->ID); // Seleccionamos nuestra textura
if(imagen->bpp ==24) tipo= GL_RGB; // Si nuestra textura es de 24 bits, entonces
// se crea una textura rgb, sino una rgba
/* Ahora creamos nuestra textura, entrando el largo, ancho y tipo */
glTexImage2D(GL_TEXTURE_2D, 0, tipo, imagen->ancho, imagen->largo, 0, tipo, GL_UNSIGNED_BYTE, imagen->dibujo);
/* Ahora le decimos a opengl como queremos que se vea nuestra textura, MAG_FILTER
es cuando la textura es mas grande que el lugar donde la asignamos, y MIG_FILTER,
es cuando la textura es mas pequeña que el lugar donde la asignamos, GL_LINEAR es
para que se vea bien tanto cerca como lejos, pero ocupa bastante procesador.
Otra opción el GL_NEARES, que ocupa menos procesador */
//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_WRAP_S,GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // La m
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return 1; // Todo salió bien
}
//estructura en donde alojo la textura previamente cargada con cargarTGA()
typedef struct {
GLubyte *dibujo; // Un puntero los datos de la imagen
GLuint bpp; // bpp significa bits per pixel (bits por punto)
// es la calidad en palabras sencillas
GLuint largo; // Largo de la textura
GLuint ancho; // Ancho de la textura
GLuint ID; // ID de la textura, es como su nombre para opengl
} textura;
GLuint lista_esfera;//la lista para la esfera
int numero_de_lados_esfera=65536;
textura textura_esfera;
float *vector;//aki dejare la normal y 4 vertices por lado para la esfera
//aqui genero los vertices y la normal de cada lado de la esfera
void generar_esfera()
{
float radio=10;
int pa=256;
int me=256;
int nro_lados=pa*me;//65536 lados
vector = (float *) malloc (15*nro_lados*sizeof (float));// un vector en donde dejo los vertices y
//las normales de cada lado de la esfera
//el porque de 15*numero de lados es por:
// N(nx,ny,nz) N(nx,ny,nz)
// 1 coordenada x normal lado 1 v2(x2,y2,z2) _____________ v3(x3,y3,z3)
// 2 coordenada y normal lado 1 | |
// 3 coordenada z normal lado 1 | |
// 4 coordenada x vertice 1 lado 1 | LADO |
// 5 coordenada y vertice 1 lado 1 | ESFERA |
// 6 coordenada z vertice 1 lado 1 N(nx,ny,nz) | |N(nx,ny,nz)
// 7 coordenada x vertice 2 lado 1 v1(x1,y1,z1)|_____________|v4(x4,y4,z4)
// 8 coordenada y vertice 2 lado 1
// 9 coordenada z vertice 2 lado 1
//10 coordenada x vertice 3 lado 1
//11 coordenada y vertice 3 lado 1
//12 coordenada z vertice 3 lado 1
//13 coordenada x vertice 4 lado 1
//14 coordenada y vertice 4 lado 1
//15 coordenada z vertice 4 lado 1
float v1x,v1y,v1z,v2x,v2y,v2z,v3x,v3y,v3z,v4x,v4y,v4z,x1,x2,x3,x4,y1,y2,z1,z2,z3,z4;
for(int i=0;i<pa;++i)
for(int j=0;j<me;++j)
{
y1=2*radio/pa*i-radio;
y2=2*radio/pa*(i+1)-radio;
v1y=y1; v2y=y2; v3y=y2; v4y=y1;
x1=sin(360.0/me*j*3.14159265358979/180.0)*sqrt(radio*radio-y1*y1);
x2=sin(360.0/me*j*3.14159265358979/180.0)*sqrt(radio*radio-y2*y2);
x3=sin(360.0/me*(j+1)*3.14159265358979/180.0)*sqrt(radio*radio-y1*y1);
x4=sin(360.0/me*(j+1)*3.14159265358979/180.0)*sqrt(radio*radio-y2*y2);
v1x=x1; v2x=x2; v3x=x4; v4x=x3;
z1=cos(360.0/me*j*3.14159265358979/180.0)*sqrt(radio*radio-y1*y1);
z2=cos(360.0/me*j*3.14159265358979/180.0)*sqrt(radio*radio-y2*y2);
z3=cos(360.0/me*(j+1)*3.14159265358979/180.0)*sqrt(radio*radio-y1*y1);
z4=cos(360.0/me*(j+1)*3.14159265358979/180.0)*sqrt(radio*radio-y2*y2);
v1z=z1; v2z=z2; v3z=z4; v4z=z3;
a=v1x-v2x; b=v1y-v2y; c=v1z-v2z;
d=v3x-v2x; e=v3y-v2y; f=v3z-v2z;
float g= b*f-e*c ;
float h= -(a*f-d*c);
float ii= a*e-d*b ;
float nor= sqrt(g*g+h*h+ii*ii);
//arriba estoy generando los vertices( v1x,v1y,v1z - v2x,v2y,v2z - v3x,v3y,v3z - v4x,v4y,v4z) para cada lado de la esfera
//junto con las coordenadas de la normal para ese lado (nx = g/nor, ny = h/nor, nz = ii/nor )
vector[0 +15*(i*me+j)] =g/nor; vector[ 1+15*(i*me+j)] =h/nor; vector[ 2+15*(i*me+j)] =ii/nor;
vector[3 +15*(i*me+j)] =v1x; vector[ 4+15*(i*me+j)] =v1y; vector[ 5+15*(i*me+j)] =v1z;
vector[6 +15*(i*me+j)] =v2x; vector[ 7+15*(i*me+j)] =v2y; vector[ 8+15*(i*me+j)] =v2z;
vector[9 +15*(i*me+j)] =v3x; vector[10+15*(i*me+j)] =v3y; vector[11+15*(i*me+j)] =v3z;
vector[12+15*(i*me+j)] =v4x; vector[13+15*(i*me+j)] =v4y; vector[14+15*(i*me+j)] =v4z;
//ahora tengo todas las coordenadas de la esfera en el vector
}
}
void dibuja_lado_esfera(float nx,float ny,float nz,
float v1x,float v1y,float v1z,float v2x,float v2y,float v2z,
float v3x,float v3y,float v3z,float v4x,float v4y,float v4z)
{
glBegin(GL_QUADS);
glTexCoord2f(0.0,0.0); glNormal3f(nx,ny,nz); glVertex3f(v1x,v1y,v1z);
glTexCoord2f(0.0,1.0); glNormal3f(nx,ny,nz); glVertex3f(v2x,v2y,v2z);
glTexCoord2f(1.0,1.0); glNormal3f(nx,ny,nz); glVertex3f(v3x,v3y,v3z);
glTexCoord2f(1.0,0.0); glNormal3f(nx,ny,nz); glVertex3f(v4x,v4y,v4z);
glEnd();
}
void genera_lista()
{
list_esfera=glGenLists(1);
glNewList(lista_esfera,GL_COMPILE);
glBindTexture(GL_TEXTURE_2D,textura_esfera.ID);
for(int i=0;i<numero_de_lados_esfera*15;++i)
{
dibuja_lado_esfera( vector[ 0+i] , vector[ 1+i] , vector[ 2+i] ,//envio la coordenada x,y,z de la normal para el lado n
vector[ 3+i] , vector[ 4+i] , vector[ 5+i] ,//envio la coordenada x,y,z del vertice1 para el lado n
vector[ 6+i] , vector[ 7+i] , vector[ 8+i] ,//envio la coordenada x,y,z del vertice2 para el lado n
vector[ 9+i] , vector[10+i] , vector[11+i] ,//envio la coordenada x,y,z del vertice3 para el lado n
vector[12+i] , vector[13+i] , vector[14+i] );//envio la coordenada x,y,z del vertice4 para el lado n
i=i+14;
}
glEndList();
}
void dibuja()
{
glCallList(lista_esfera);
}
void main()
{
cargarTGA("esfera.tga", &textura_esfera);
generar_esfera();
genera_lista();
do
{
dibuja();
}while(key[KEY_ESC]);
}
Ok, ahi esta, si me pueden corregir...partiendo por no usar QUADS sino QUAD_STRIP....
muchas gracias y saludos a todos.
Jamás me acostumbrare a ver código en español y ver la palabra "arreglo"
Lo más wapo es ver:
vector ... = ... // Arreglo de... xD
ya me explicarás cuando necesites usar la ñ que vas a hacer :P (que en un momento determinado se puede poner en unicode y blahblablah)
Voy a intentar descifrar el código... a ver
Cita de: "xeex"
Ok, ahi esta, si me pueden corregir...partiendo por no usar QUADS sino QUAD_STRIP....
Tu problema aqui no son es QUAD_STRIP creeme. Que fps consigues? no se si lo dijiste
gracias por responder...trate de dejar el codigo lo mas simple...
mostrando la escena sin absolutamente nada en ella me da 120 FPS.
cuando muestro la esfera me da 20 FPS.
Esto es código de glut, tu haces cuadrados simulando la esfera, si no veo mal, vas cuadradito por cuadradito.
static GLUquadricObj *quadObj;
#define QUAD_OBJ_INIT() { if(!quadObj) initQuadObj(); }
static void
initQuadObj(void)
{
quadObj = gluNewQuadric();
if (!quadObj)
__glutFatalError("out of memory.");
}
/* CENTRY */
void APIENTRY
glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
{
QUAD_OBJ_INIT();
gluQuadricDrawStyle(quadObj, GLU_LINE);
gluQuadricNormals(quadObj, GLU_SMOOTH);
/* If we ever changed/used the texture or orientation state
of quadObj, we'd need to change it to the defaults here
with gluQuadricTexture and/or gluQuadricOrientation. */
gluSphere(quadObj, radius, slices, stacks);
}
void APIENTRY
glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
{
QUAD_OBJ_INIT();
[b]gluQuadricDrawStyle[/b](quadObj, GLU_FILL);
gluQuadricNormals(quadObj, GLU_SMOOTH);
/* If we ever changed/used the texture or orientation state
of quadObj, we'd need to change it to the defaults here
with gluQuadricTexture and/or gluQuadricOrientation. */
[b]gluSphere[/b](quadObj, radius, slices, stacks);
}
Esto va a ser una tochada...
Codigo de gluSphere
void GLAPIENTRY
gluSphere(GLUquadric *qobj, GLdouble radius, GLint slices, GLint stacks)
{
GLint i,j;
GLfloat sinCache1a[CACHE_SIZE];
GLfloat cosCache1a[CACHE_SIZE];
GLfloat sinCache2a[CACHE_SIZE];
GLfloat cosCache2a[CACHE_SIZE];
GLfloat sinCache3a[CACHE_SIZE];
GLfloat cosCache3a[CACHE_SIZE];
GLfloat sinCache1b[CACHE_SIZE];
GLfloat cosCache1b[CACHE_SIZE];
GLfloat sinCache2b[CACHE_SIZE];
GLfloat cosCache2b[CACHE_SIZE];
GLfloat sinCache3b[CACHE_SIZE];
GLfloat cosCache3b[CACHE_SIZE];
GLfloat angle;
GLfloat zLow, zHigh;
GLfloat sintemp1, sintemp2, sintemp3 = 0.0, sintemp4 = 0.0;
GLfloat costemp1, costemp2 = 0.0, costemp3 = 0.0, costemp4 = 0.0;
GLboolean needCache2, needCache3;
GLint start, finish;
if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
if (slices < 2 || stacks < 1 || radius < 0.0) {
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
}
/* Cache is the vertex locations cache */
/* Cache2 is the various normals at the vertices themselves */
/* Cache3 is the various normals for the faces */
needCache2 = needCache3 = GL_FALSE;
if (qobj->normals == GLU_SMOOTH) {
needCache2 = GL_TRUE;
}
if (qobj->normals == GLU_FLAT) {
if (qobj->drawStyle != GLU_POINT) {
needCache3 = GL_TRUE;
}
if (qobj->drawStyle == GLU_LINE) {
needCache2 = GL_TRUE;
}
}
for (i = 0; i < slices; i++) {
angle = 2 * PI * i / slices;
sinCache1a[i] = SIN(angle);
cosCache1a[i] = COS(angle);
if (needCache2) {
sinCache2a[i] = sinCache1a[i];
cosCache2a[i] = cosCache1a[i];
}
}
for (j = 0; j <= stacks; j++) {
angle = PI * j / stacks;
if (needCache2) {
if (qobj->orientation == GLU_OUTSIDE) {
sinCache2b[j] = SIN(angle);
cosCache2b[j] = COS(angle);
} else {
sinCache2b[j] = -SIN(angle);
cosCache2b[j] = -COS(angle);
}
}
sinCache1b[j] = radius * SIN(angle);
cosCache1b[j] = radius * COS(angle);
}
/* Make sure it comes to a point */
sinCache1b[0] = 0;
sinCache1b[stacks] = 0;
if (needCache3) {
for (i = 0; i < slices; i++) {
angle = 2 * PI * (i-0.5) / slices;
sinCache3a[i] = SIN(angle);
cosCache3a[i] = COS(angle);
}
for (j = 0; j <= stacks; j++) {
angle = PI * (j - 0.5) / stacks;
if (qobj->orientation == GLU_OUTSIDE) {
sinCache3b[j] = SIN(angle);
cosCache3b[j] = COS(angle);
} else {
sinCache3b[j] = -SIN(angle);
cosCache3b[j] = -COS(angle);
}
}
}
sinCache1a[slices] = sinCache1a[0];
cosCache1a[slices] = cosCache1a[0];
if (needCache2) {
sinCache2a[slices] = sinCache2a[0];
cosCache2a[slices] = cosCache2a[0];
}
if (needCache3) {
sinCache3a[slices] = sinCache3a[0];
cosCache3a[slices] = cosCache3a[0];
}
switch (qobj->drawStyle) {
case GLU_FILL:
/* Do ends of sphere as TRIANGLE_FAN's (if not texturing)
** We don't do it when texturing because we need to respecify the
** texture coordinates of the apex for every adjacent vertex (because
** it isn't a constant for that point)
*/
if (!(qobj->textureCoords)) {
start = 1;
finish = stacks - 1;
/* Low end first (j == 0 iteration) */
sintemp2 = sinCache1b[1];
zHigh = cosCache1b[1];
switch(qobj->normals) {
case GLU_FLAT:
sintemp3 = sinCache3b[1];
costemp3 = cosCache3b[1];
break;
case GLU_SMOOTH:
sintemp3 = sinCache2b[1];
costemp3 = cosCache2b[1];
glNormal3f(sinCache2a[0] * sinCache2b[0],
cosCache2a[0] * sinCache2b[0],
cosCache2b[0]);
break;
default:
break;
}
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, radius);
if (qobj->orientation == GLU_OUTSIDE) {
for (i = slices; i >= 0; i--) {
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
case GLU_FLAT:
if (i != slices) {
glNormal3f(sinCache3a[i+1] * sintemp3,
cosCache3a[i+1] * sintemp3,
costemp3);
}
break;
case GLU_NONE:
default:
break;
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
}
} else {
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
case GLU_FLAT:
glNormal3f(sinCache3a[i] * sintemp3,
cosCache3a[i] * sintemp3,
costemp3);
break;
case GLU_NONE:
default:
break;
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
}
}
glEnd();
/* High end next (j == stacks-1 iteration) */
sintemp2 = sinCache1b[stacks-1];
zHigh = cosCache1b[stacks-1];
switch(qobj->normals) {
case GLU_FLAT:
sintemp3 = sinCache3b[stacks];
costemp3 = cosCache3b[stacks];
break;
case GLU_SMOOTH:
sintemp3 = sinCache2b[stacks-1];
costemp3 = cosCache2b[stacks-1];
glNormal3f(sinCache2a[stacks] * sinCache2b[stacks],
cosCache2a[stacks] * sinCache2b[stacks],
cosCache2b[stacks]);
break;
default:
break;
}
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, -radius);
if (qobj->orientation == GLU_OUTSIDE) {
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
case GLU_FLAT:
glNormal3f(sinCache3a[i] * sintemp3,
cosCache3a[i] * sintemp3,
costemp3);
break;
case GLU_NONE:
default:
break;
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
}
} else {
for (i = slices; i >= 0; i--) {
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
case GLU_FLAT:
if (i != slices) {
glNormal3f(sinCache3a[i+1] * sintemp3,
cosCache3a[i+1] * sintemp3,
costemp3);
}
break;
case GLU_NONE:
default:
break;
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
}
}
glEnd();
} else {
start = 0;
finish = stacks;
}
for (j = start; j < finish; j++) {
zLow = cosCache1b[j];
zHigh = cosCache1b[j+1];
sintemp1 = sinCache1b[j];
sintemp2 = sinCache1b[j+1];
switch(qobj->normals) {
case GLU_FLAT:
sintemp4 = sinCache3b[j+1];
costemp4 = cosCache3b[j+1];
break;
case GLU_SMOOTH:
if (qobj->orientation == GLU_OUTSIDE) {
sintemp3 = sinCache2b[j+1];
costemp3 = cosCache2b[j+1];
sintemp4 = sinCache2b[j];
costemp4 = cosCache2b[j];
} else {
sintemp3 = sinCache2b[j];
costemp3 = cosCache2b[j];
sintemp4 = sinCache2b[j+1];
costemp4 = cosCache2b[j+1];
}
break;
default:
break;
}
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
case GLU_FLAT:
case GLU_NONE:
default:
break;
}
if (qobj->orientation == GLU_OUTSIDE) {
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) (j+1) / stacks);
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
} else {
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1a[i],
sintemp1 * cosCache1a[i], zLow);
}
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp4,
cosCache2a[i] * sintemp4,
costemp4);
break;
case GLU_FLAT:
glNormal3f(sinCache3a[i] * sintemp4,
cosCache3a[i] * sintemp4,
costemp4);
break;
case GLU_NONE:
default:
break;
}
if (qobj->orientation == GLU_OUTSIDE) {
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1a[i],
sintemp1 * cosCache1a[i], zLow);
} else {
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) (j+1) / stacks);
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
}
}
glEnd();
}
break;
case GLU_POINT:
glBegin(GL_POINTS);
for (j = 0; j <= stacks; j++) {
sintemp1 = sinCache1b[j];
costemp1 = cosCache1b[j];
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2 = sinCache2b[j];
costemp2 = cosCache2b[j];
break;
default:
break;
}
for (i = 0; i < slices; i++) {
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp2,
cosCache2a[i] * sintemp2,
costemp2);
break;
case GLU_NONE:
default:
break;
}
zLow = j * radius / stacks;
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1a[i],
sintemp1 * cosCache1a[i], costemp1);
}
}
glEnd();
break;
case GLU_LINE:
case GLU_SILHOUETTE:
for (j = 1; j < stacks; j++) {
sintemp1 = sinCache1b[j];
costemp1 = cosCache1b[j];
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2 = sinCache2b[j];
costemp2 = cosCache2b[j];
break;
default:
break;
}
glBegin(GL_LINE_STRIP);
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_FLAT:
glNormal3f(sinCache3a[i] * sintemp2,
cosCache3a[i] * sintemp2,
costemp2);
break;
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp2,
cosCache2a[i] * sintemp2,
costemp2);
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1a[i],
sintemp1 * cosCache1a[i], costemp1);
}
glEnd();
}
for (i = 0; i < slices; i++) {
sintemp1 = sinCache1a[i];
costemp1 = cosCache1a[i];
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2 = sinCache2a[i];
costemp2 = cosCache2a[i];
break;
default:
break;
}
glBegin(GL_LINE_STRIP);
for (j = 0; j <= stacks; j++) {
switch(qobj->normals) {
case GLU_FLAT:
glNormal3f(sintemp2 * sinCache3b[j],
costemp2 * sinCache3b[j],
cosCache3b[j]);
break;
case GLU_SMOOTH:
glNormal3f(sintemp2 * sinCache2b[j],
costemp2 * sinCache2b[j],
cosCache2b[j]);
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1b[j],
costemp1 * sinCache1b[j], cosCache1b[j]);
}
glEnd();
}
break;
default:
break;
}
}
Busca códigos en internet sobre esfereras en OpenGL usando listas y vertex buffers, seguro que hay. Trata de comparar.
No se exactamente que tratas de hacer... pero mira a ver si compilas en Debug o alguna razón externa.
Saludos (no tengo mas tiempo)
gracias.
...si voy cuadrado por cuadrado.
No dibujes cada quad por separado. Eso es equivalente a un batch por quad, lo cual es malo. Pon el glBegin (GL_QUADS)/glEnd mas arriba en la jerarquia (por ejemplo, fuera del bucle), con eso deberias ganar mas que suficiente para tus necesidades.
Cita de: shash en 08 de Agosto de 2008, 12:29:52 PM
No dibujes cada quad por separado. Eso es equivalente a un batch por quad, lo cual es malo. Pon el glBegin (GL_QUADS)/glEnd mas arriba en la jerarquia (por ejemplo, fuera del bucle), con eso deberias ganar mas que suficiente para tus necesidades.
Sip, se me adelantó shash. Piensa que en el momento que haces el glEnd es cuando se pone en marcha todo el proceso de pintado, y eso es costoso, cuantos menos Begin/End haya mejor, pero para eso tienes que organizar bien los datos, a poder ser en un Array y usar VertexArrays.
Ademas que estas enviando los mismos vertex una y otra vez a trabez del canal AGP practicamente 4 veces cada vertex
Usa triangle strips en vez y si es posible glDrawElements con glDrawArrays para subirlos mas eficientemente o bien dejarlos arriva en la placa de video.
hola y gracias por responder.
Bueno...si, estaba mandando vertices repetidos, cometiendo el error de no usar triangle_strip.
Bueno...corregi todo lo anterior.
Primero parto por decir que renderizando mi escena sin nada en ella obtengo 300fps, mi computador es un notebook toshiba A215 SP-4017
AMD Turion 64 X2 a 1.6 MHz, 1 GB de memoria RAM, ATI RADEON x1200 series.
Mi primera pregunta es:
1.-¿Esta bien que me de solo 300 FPS mostrando la escena sin nada en ella?
Bueno corregi los errores que tenia en el codigo, agrege triangle_strip, un displaylist para comparar con el VBO.
Ahora, cuando muestro mi esfera de 256 meridianos y 256 paralelos,
256x256=65536 lados,
(256+1)x(256)x2 vertices(de la forma que ordene los datos esa es la cantidad de vertices que obtuve, se entiende que un vertice esta formado por 3 coordenadas x,y,z)
con un displaylist obtengo de 75-80 FPS. Para mi sorpresa cuando uso vbo solo obtuve 52-58 FPS.
el codigo del render de la esfera con el displaylist es:
#include "allegro.h"
#include "alleggl.h"
#include <math.h>
#include <stdio.h>
float *vector;//vertex of the sphere
float *colors;//colors of the sphere
FONT *agl_font;
int fps_ant=0;
GLuint sphere_list;
int res_x=1280;
int pa=256;
int me=256;
void reshape(GLsizei w, GLsizei h);
void make_sphere();//generate sphere vertices and colors, fill "vector" with vertex and "colors" with colors
void show_fps(int a);//show FPS
void crea_displaylist_esfera()
{
sphere_list=glGenLists(1);
glNewList(sphere_list,GL_COMPILE);
glBegin(GL_TRIANGLE_STRIP);
for(int i=0;i<(pa+1)*2*me*3;++i)
{
glColor3f(colors[i+0],colors[i+1],colors[i+2]);glVertex3f(vector[i+0],vector[i+ 1],vector[i+ 2]);
i=i+2;
}
glEnd();
glEndList();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glColor3f(255.0,255.0,255.0);
glCallList(sphere_list);
show_fps(fps_ant);
glFlush();
allegro_gl_flip();
}
void main()
{
allegro_init();
install_allegro_gl();
install_keyboard();
allegro_gl_set( AGL_COLOR_DEPTH,desktop_color_depth() );
allegro_gl_set( AGL_Z_DEPTH, 0 );
allegro_gl_set( AGL_DOUBLEBUFFER, 1);
allegro_gl_set( AGL_RENDERMETHOD, 1);
allegro_gl_set( AGL_FULLSCREEN, 1);
allegro_gl_set( AGL_STENCIL_DEPTH,0);
allegro_gl_set( AGL_REQUIRE,AGL_COLOR_DEPTH );
allegro_gl_set( AGL_SUGGEST,AGL_Z_DEPTH);
allegro_gl_set( AGL_REQUIRE,AGL_DOUBLEBUFFER);
allegro_gl_set( AGL_REQUIRE,AGL_RENDERMETHOD);
allegro_gl_set( AGL_REQUIRE,AGL_FULLSCREEN);
set_gfx_mode(GFX_OPENGL_FULLSCREEN, 1280,800 , 0, 0);
agl_font = allegro_gl_load_system_font("C:\WINDOWS\Fonts\arial.ttf", AGL_FONT_TYPE_OUTLINE,1,1);
//fill vector with the vertex of the sphere
//fill colors of each vertex of the sphere
make_sphere();
reshape(SCREEN_W,SCREEN_H);
clock_t fps_t=clock();
bool fps=false;
int fps_f=0;
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
crea_displaylist_esfera();
do
{
if((clock()-fps_t)/(double)CLOCKS_PER_SEC>1)
{
fps_ant=fps_f;
fps_t=clock();
fps_f=0;
}
fps_f++;
display();
}while(!key[KEY_ESC]);
free(vector);
free(colors);
}END_OF_MAIN();
void reshape(GLsizei w, GLsizei h)
{
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5f, 10000.0f);
glMatrixMode (GL_MODELVIEW);
glViewport (0, 0, w, h);
}
void make_sphere()
{
float ratio=10;
int nro_lados=pa*me;//65536 faces
vector = (float *) malloc ((pa+1)*me*2*3*sizeof (float));
colors = (float *) malloc ((pa+1)*me*2*3*sizeof (float));
float v1x,v1y,v1z,v2x,v2y,v2z,v3x,v3y,v3z,v4x,v4y,v4z,x1,x2,x3,x4,y1,y2,z1,z2,z3,z4;
for(int i=0;i<me;++i)
for(int j=0;j<=pa;++j)
{
//generate sphere vertexs/////////////////////////////////////////////
y1=2*ratio/me*i-ratio;
y2=2*ratio/me*(i+1)-ratio;
v1y=y1; v2y=y2; v3y=y2; v4y=y1;
x1=sin(360.0/pa*j*3.14159265358979/180.0)*sqrt(ratio*ratio-y1*y1);
x2=sin(360.0/pa*j*3.14159265358979/180.0)*sqrt(ratio*ratio-y2*y2);
v1x=x1; v2x=x2;
z1=cos(360.0/pa*j*3.14159265358979/180.0)*sqrt(ratio*ratio-y1*y1);
z2=cos(360.0/pa*j*3.14159265358979/180.0)*sqrt(ratio*ratio-y2*y2);
v1z=z1; v2z=z2;
///////////////////////////////////////////////////////////////////////
//fill "vector" with sphere's vertexs
vector[0+6*(i*(pa+1)+j)] =v1x; vector[ 1+6*(i*(pa+1)+j)] =v1y; vector[ 2+6*(i*(pa+1)+j)] =v1z;
vector[3+6*(i*(pa+1)+j)] =v2x; vector[ 4+6*(i*(pa+1)+j)] =v2y; vector[ 5+6*(i*(pa+1)+j)] =v2z;
}
//fill "color" of each vertex of each face
for(int i=0;i<(pa+1)*me*2*3;++i)
{
colors[0+i]=1.f; colors[ 1+i]=0.f; colors[ 2+i]=0.f;
colors[3+i]=0.f; colors[ 4+i]=1.f; colors[ 5+i]=0.f;
colors[6+i]=0.f; colors[ 7+i]=0.f; colors[ 8+i]=1.f;
colors[9+i]=1.f; colors[10+i]=0.f; colors[11+i]=1.f;
i=i+11;
}
}
void show_fps(int a)
{
glPushMatrix();
glLoadIdentity();
glTranslatef(-1,.8,-1.5);
glScalef(.05,.05,1);
allegro_gl_printf(agl_font,0.0 , 0.0, 0.0, makecol( 255, 255, 000), "FPS=%d",a);
glPopMatrix();
}
el codigo del render de la esfera con vbo es:
#include "allegro.h"
#include "alleggl.h"
#include <math.h>
#include <stdio.h>
GLuint vertexBuffer = 0;
GLuint colourBuffer = 0;
float *vector;//vertex of the sphere
float *colors;//colors of the sphere
FONT *agl_font;
int fps_ant=0;
int res_x=1280;
int pa=256;
int me=256;
void reshape(GLsizei w, GLsizei h);
void make_sphere();//generate sphere vertices and colors, fill "vector" with vertex and "colors" with colors
void show_fps(int a);//show FPS
void vbo()
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colourBuffer);
glColorPointer (3, GL_FLOAT, 0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0,(pa+1)*2*me);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(255.0,255.0,255.0);
vbo();
show_fps(fps_ant);
glFlush();
allegro_gl_flip();
}
void main()
{
allegro_init();
install_allegro_gl();
install_keyboard();
allegro_gl_set( AGL_COLOR_DEPTH, desktop_color_depth() );
allegro_gl_set( AGL_Z_DEPTH, 16 );
allegro_gl_set( AGL_DOUBLEBUFFER, 1);
allegro_gl_set( AGL_RENDERMETHOD, 1);
allegro_gl_set( AGL_FULLSCREEN, 1);
allegro_gl_set( AGL_STENCIL_DEPTH,0);
allegro_gl_set( AGL_REQUIRE,AGL_COLOR_DEPTH );
allegro_gl_set( AGL_SUGGEST,AGL_Z_DEPTH);
allegro_gl_set( AGL_REQUIRE,AGL_DOUBLEBUFFER);
allegro_gl_set( AGL_REQUIRE,AGL_RENDERMETHOD);
allegro_gl_set( AGL_REQUIRE,AGL_FULLSCREEN);
set_gfx_mode(GFX_OPENGL_FULLSCREEN, 1280,800 , 0, 0);
agl_font = allegro_gl_load_system_font("C:\WINDOWS\Fonts\arial.ttf", AGL_FONT_TYPE_OUTLINE,1,1);
//fill vector with the vertex of the sphere( 4 vertex for each face of the sphere)
//fill colors of each vertex of the sphere
make_sphere();
reshape(SCREEN_W,SCREEN_H);
glGenBuffersARB(1, &vertexBuffer);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, (pa+1)*2*me*3*4, vector, GL_DYNAMIC_DRAW_ARB);
glGenBuffersARB(1, &colourBuffer);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colourBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, (pa+1)*2*me*3*4, colors, GL_DYNAMIC_DRAW_ARB);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
clock_t fps_t=clock();
bool fps=false;
int fps_f=0;
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
do
{
if((clock()-fps_t)/(double)CLOCKS_PER_SEC>1)
{
fps_ant=fps_f;
fps_t=clock();
fps_f=0;
}
fps_f++;
display();
}while(!key[KEY_ESC]);
free(vector);
free(colors);
}END_OF_MAIN();
void reshape(GLsizei w, GLsizei h)
{
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5f, 10000.0f);
glMatrixMode (GL_MODELVIEW);
glViewport (0, 0, w, h);
}
void make_sphere()
{
float ratio=10;
int nro_lados=pa*me;//65536 faces
vector = (float *) malloc ((pa+1)*me*2*3*sizeof (float));
colors = (float *) malloc ((pa+1)*me*2*3*sizeof (float));
float v1x,v1y,v1z,v2x,v2y,v2z,v3x,v3y,v3z,v4x,v4y,v4z,x1,x2,x3,x4,y1,y2,z1,z2,z3,z4;
for(int i=0;i<me;++i)
for(int j=0;j<=pa;++j)
{
//generate sphere vertexs/////////////////////////////////////////////
y1=2*ratio/me*i-ratio;
y2=2*ratio/me*(i+1)-ratio;
v1y=y1; v2y=y2; v3y=y2; v4y=y1;
x1=sin(360.0/pa*j*3.14159265358979/180.0)*sqrt(ratio*ratio-y1*y1);
x2=sin(360.0/pa*j*3.14159265358979/180.0)*sqrt(ratio*ratio-y2*y2);
v1x=x1; v2x=x2;
z1=cos(360.0/pa*j*3.14159265358979/180.0)*sqrt(ratio*ratio-y1*y1);
z2=cos(360.0/pa*j*3.14159265358979/180.0)*sqrt(ratio*ratio-y2*y2);
v1z=z1; v2z=z2;
///////////////////////////////////////////////////////////////////////
//fill "vector" with sphere's vertexs
vector[0+6*(i*(pa+1)+j)] =v1x; vector[ 1+6*(i*(pa+1)+j)] =v1y; vector[ 2+6*(i*(pa+1)+j)] =v1z-20;
vector[3+6*(i*(pa+1)+j)] =v2x; vector[ 4+6*(i*(pa+1)+j)] =v2y; vector[ 5+6*(i*(pa+1)+j)] =v2z-20;
}
//fill "color" of each vertex of each face
for(int i=0;i<(pa+1)*me*2*3;++i)
{
colors[0+i]=1.f; colors[ 1+i]=0.f; colors[ 2+i]=0.f;
colors[3+i]=0.f; colors[ 4+i]=1.f; colors[ 5+i]=0.f;
colors[6+i]=0.f; colors[ 7+i]=0.f; colors[ 8+i]=1.f;
colors[9+i]=1.f; colors[10+i]=0.f; colors[11+i]=1.f;
i=i+11;
}
}
void show_fps(int a)
{
glPushMatrix();
glLoadIdentity();
glTranslatef(-1,.8,-1.5);
glScalef(.05,.05,1);
allegro_gl_printf(agl_font,0.0 , 0.0, 0.0, makecol( 255, 255, 000), "FPS=%d",a);
glPopMatrix();
}
bueno mi segunda pregunta es:
2.-¿Como es posible que me de mas fps el displaylist que el vbo?...¿tengo algun error en el codigo del vbo?...¿que estoy haciendo mal?
gracias y saludos.