Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Problema de memoria con OpenGL

Iniciado por Kherom, 31 de Diciembre de 2011, 04:07:59 AM

« anterior - próximo »

Kherom

Saludos a todos, tengo un problema con OpenGL que no logro solucionar:

Cuando comencé con OpenGL utilizaba una librería en c++ que no puedo usar en c, por lo que he decidido cargar las imágenes yo mismo. Pero al intentarlo me he encontrado con un error de  "Memoria insuficiente" al intentar cargar una imagen compuesta por un simple array de 16 bytes. La cosa es que tras comerme mucho el tarro probé la función en un programa anterior y no da problemas, me permite cargar imágenes con normalidad, pero en todos los que hago después me da el mismo error y no encuentro la diferencia.

Aquí dejo una versión resumida del código que da problemas (concretamente en la función "gluBuild2DMipmaps()"):

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

int main(void)
{
GLuint textura;
/*int biSizeImage, bfOffbits, biWidth, biHeight;
FILE * bmp;

bmp=fopen(imagen, "r");

//Busco el desfase y lo guardo
fseek (bmp, 10, 0);
fread(&bfOffbits, 4, 1, bmp);

//Busco el ancho y lo guardo
fseek (bmp, 18, 0);
fread(&biWidth, 4, 1, bmp);

//Busco el alto y lo guardo
fseek (bmp, 22, 0);
fread(&biHeight, 4, 1, bmp);

printf("%i\n", biWidth);
printf("%i\n", biHeight);
//Busco la posición en la que se almacena el tamaño de la imagen y la guardo
fseek (bmp, 34, 0);
fread(&biSizeImage, 4, 1, bmp);

imagend = malloc (biSizeImage);
fseek (bmp, bfOffbits, 0);
fread(imagend, biSizeImage, 1, bmp);
fclose(bmp);*/

  glGenTextures(1, &textura);
  glBindTexture(GL_TEXTURE_2D, textura);
 
unsigned char imagenprueba[16]={255,0,0,255,0,255,0,255,0,0,0,0,0,128,255,128};

int err;
  //FILE * ERR;
  //ERR=fopen("ERR.txt", "a");
err=gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2,
    2, GL_RGBA, GL_UNSIGNED_BYTE, imagenprueba);
  if (err)
  {
char c;
char error[100];
const GLubyte * rrr=gluErrorString(err);
int i=0;
do{
c=*rrr;
error[i]=c;
rrr++;
i++;
}while(c!=0);
MessageBox(NULL, error, "gluBuild2DMipmaps()", MB_OK | MB_ICONERROR);
    //fwrite(error,1,100, ERR);
    //fputc(10,ERR);
}
  //fclose(ERR);
}


Aquí más resumido (sin las partes comentadas):

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

int main(void)
{
GLuint textura;
  glGenTextures(1, &textura);
  glBindTexture(GL_TEXTURE_2D, textura);
 
unsigned char imagenprueba[16]={255,0,0,255,0,255,0,255,0,0,0,0,0,128,255,128};

int err;
err=gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2,
    2, GL_RGBA, GL_UNSIGNED_BYTE, imagenprueba);
  if (err)
  {
char c;
char error[100];
const GLubyte * rrr=gluErrorString(err);
int i=0;
do{
c=*rrr;
error[i]=c;
rrr++;
i++;
}while(c!=0);
MessageBox(NULL, error, "gluBuild2DMipmaps()", MB_OK | MB_ICONERROR);
}
}

nostromo

Pero... ¿No Inicializas OpenGL y creas un context para llamar a funciones OpenGL?

Kherom

#2
Si claro, si no no me habría dado cuenta del error, lo que pasa es que está con la API de Windows y no con Glu y está un poco caótico de los cambios que he hecho, limpiando la basura quedaría algo así:

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

HWND hWndPrincipal, hWndConsola;

MSG Mensaje;

RECT med, rect;

HDC hDC;

HGLRC OGLrc;

GLuint portada;

LRESULT CALLBACK PrincipalProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
GLuint cargaBMP(const char * ruta);
void iniciaOGL(void);
void pinta(void);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX principal;

principal.cbSize = sizeof(WNDCLASSEX);
principal.style = CS_HREDRAW | CS_VREDRAW;
principal.lpfnWndProc = PrincipalProc;
principal.cbClsExtra = 0;
principal.cbWndExtra = 0;
principal.hInstance = hInstance;
principal.hIcon = NULL;
principal.hCursor = LoadCursor(0, IDC_ARROW);
principal.hbrBackground= (HBRUSH)(COLOR_WINDOW);
principal.lpszMenuName = NULL;
principal.lpszClassName = "principal";
principal.hIconSm = NULL;

RegisterClassEx (&principal);

hWndPrincipal = CreateWindow("principal", "Casino",
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
100, 100, 512, 512, 0, 0, hInstance, 0);

ShowWindow(hWndPrincipal, nCmdShow);

UpdateWindow(hWndPrincipal);

portada=cargaBMP("Principal.bmp");

iniciaOGL();

while(1)
{
if (PeekMessage(&Mensaje, NULL, 0, 0, PM_NOREMOVE))
{
if(!GetMessage(&Mensaje, NULL, 0, 0))
return (int)Mensaje.wParam;
TranslateMessage(&Mensaje);
DispatchMessage(&Mensaje);
}
pinta();
}
}

LRESULT CALLBACK PrincipalProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}

GLuint cargaBMP(const char * ruta)
{
GLuint gluint;
unsigned char c, d;
unsigned int n, i, biSizeImage, bfOffbits, biWidth, biHeight;
float  p;
short u;
void *imagen;

FILE *bmp;
bmp=fopen(ruta, "rb");

//Busco el desfase y lo guardo
fseek (bmp, 10, 0);
fread(&bfOffbits, 4, 1, bmp);

//Busco el ancho y lo guardo
fseek (bmp, 18, 0);
fread(&biWidth, 4, 1, bmp);

//Busco el alto y lo guardo
fseek (bmp, 22, 0);
fread(&biHeight, 4, 1, bmp);
//Busco la posición en la que se almacena el tamaño de la imagen y la guardo
fseek (bmp, 34, 0);
fread(&biSizeImage, 4, 1, bmp);

imagen = malloc (biSizeImage);
fseek (bmp, bfOffbits, 0);
fread(imagen, biSizeImage, 1, bmp);

fclose(bmp);

  glGenTextures(1, &gluint);
  glBindTexture(GL_TEXTURE_2D, gluint);
 
  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                   GL_LINEAR_MIPMAP_NEAREST );
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

  int err;
  FILE * ERR;
  ERR=fopen("ERR.txt", "a");
err=gluBuild2DMipmaps(GL_TEXTURE_2D, 3, biWidth,
    biHeight, GL_RGBA, GL_UNSIGNED_BYTE, imagen);
  if (err)
  {
char c;
char error[100];
const GLubyte * rrr=gluErrorString(err);
int i=0;
do{
c=*rrr;
error[i]=c;
rrr++;
i++;
}while(c!=0);
MessageBox(NULL, error, "gluBuild2DMipmaps()", MB_OK | MB_ICONERROR);
}
  return gluint;
}

void iniciaOGL(void)
{
static PIXELFORMATDESCRIPTOR pfd =
{
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW |
        PFD_SUPPORT_OPENGL |
        PFD_DOUBLEBUFFER |
        PFD_TYPE_RGBA,
        32,
        0,0,0,0,0,0, // ignorados
        0, // Sin buffer alpha
        0, // Shift bit ignorado
        0, // Buffer de acumulación ignorado
        0,0,0,0, // Bits de acumulación ignorados
        32, // Z-Buffer
        0, // Sin buffer de pincel (Stencil)
        0, // Sin buffer auxiliar
        PFD_MAIN_PLANE, // Layer de dibujo principal
        0, // Reservado
        0,0,0, // Layers de máscara ignorados
};

hDC=GetDC(hWndPrincipal);
int PixF=ChoosePixelFormat(hDC,&pfd);
SetPixelFormat(hDC,PixF,&pfd);
OGLrc=wglCreateContext(hDC);
wglMakeCurrent(hDC,OGLrc);

SwapBuffers(hDC);
}

void pinta(void)
{
static int bloq=0;

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
  glClear( GL_COLOR_BUFFER_BIT );

  glEnable(GL_TEXTURE_2D);
 
glBindTexture(GL_TEXTURE_2D, portada);

glColor3f(0.9,0.5,0.3);

glBegin(GL_QUADS);
    glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0);
    glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0);
    glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);
    glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);
glEnd();

Sleep(33);

SwapBuffers(hDC);
}


Para compilarlo modo GUI y --opengl32 -lglu32 en el linker.

Supuesta mente debería tener textura y no generar el error, o al menos es lo que me pasa en otros programas, como un buscaminas que hice hace unas semanas, pero ahora no hay manera.

nostromo

Ok.

En el código, lo que veo es que primero cargas el BMP y esto hace llamadas a OpenGL, y despues inicializas el contexto de OpenGL.
Deberias inicializar OpenGL antes de cargar el BMP.
Puedes probar a intercambiar las dos llamadas que están juntas.

Otra cosa...¿Glut necesita iniciarse? No lo recuerdo.

Suerte!


Kherom

#4
Joooder era eso, gracias, ya me carga la textura, aunque con el color invertido, pero es un comienzo :D Tanto mover las cosas de sitio...

Para glu yo nunca he inicializado nada y no he tenido problemas. Aunque sólo he usado gluPerspective y poco más. Que yo sepa son más funciones sobre la misma base.

La que sí que me sigue sin funcionar es

glTexImage2D(GL_TEXTURE_2D, 0, 3, biWidth, biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, imagen);

Que era la función que iba a usar al principio, pero de ésta no se cómo sacar los errores que produce, sabes cómo? Sólo la he conseguido usar con la librería corona, aquí sustituyéndola no hace nada, y como no tiene valor de retorno no se sacar los errores.

Gallo

Glut, acabado en t, si ke necesita inicializarse. Glu no necesita inicializar nada.

nostromo

Cita de: Kherom en 31 de Diciembre de 2011, 06:48:00 PM
Joooder era eso, gracias, ya me carga la textura, aunque con el color invertido, pero es un comienzo :D Tanto mover las cosas de sitio...

Para glu yo nunca he inicializado nada y no he tenido problemas. Aunque sólo he usado gluPerspective y poco más. Que yo sepa son más funciones sobre la misma base.

La que sí que me sigue sin funcionar es

glTexImage2D(GL_TEXTURE_2D, 0, 3, biWidth, biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, imagen);

Que era la función que iba a usar al principio, pero de ésta no se cómo sacar los errores que produce, sabes cómo? Sólo la he conseguido usar con la librería corona, aquí sustituyéndola no hace nada, y como no tiene valor de retorno no se sacar los errores.

El error lo puedes ver con la función glGetError(). 






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.