2010-08-25 5 views
5

Мне просто интересно, как я могу преобразовать SDL_Surface (загруженный из png через IMG_Load) и вставлять его на квадранте. Вот то, что у меня есть (в основном, только что скопировано из учебника, который я нашел).SDL/OpenGL Texture Transparency

#include "SDL.h" 
#include "SDL_opengl.h" 
#include "SDL_image.h" 

#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
    SDL_Surface *screen; 

    // Slightly different SDL initialization 
    if (SDL_Init(SDL_INIT_VIDEO) != 0) { 
     printf("Unable to initialize SDL: %s\n", SDL_GetError()); 
     return 1; 
    } 

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // *new* 

    screen = SDL_SetVideoMode(640, 480, 16, SDL_OPENGL); // *changed* 
    if (!screen) { 
    printf("Unable to set video mode: %s\n", SDL_GetError()); 
    return 1; 
} 

    // Set the OpenGL state after creating the context with SDL_SetVideoMode 

glClearColor(0, 0, 0, 0); 

glEnable(GL_TEXTURE_2D); // Need this to display a texture 

    glViewport(0, 0, 640, 480); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 

    glOrtho(0, 640, 480, 0, -1, 1); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    // Load the OpenGL texture 

    GLuint texture; // Texture object handle 
    SDL_Surface *surface; // Gives us the information to make the texture 

    if ((surface = IMG_Load("img/star.png"))) { 

     // Check that the image's width is a power of 2 
     if ((surface->w & (surface->w - 1)) != 0) { 
      printf("warning: image.bmp's width is not a power of 2\n"); 
     } 

     // Also check if the height is a power of 2 
     if ((surface->h & (surface->h - 1)) != 0) { 
      printf("warning: image.bmp's height is not a power of 2\n"); 
     } 

     // Have OpenGL generate a texture object handle for us 
     glGenTextures(1, &texture); 

     // Bind the texture object 
     glBindTexture(GL_TEXTURE_2D, texture); 

     // Set the texture's stretching properties 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

     // Edit the texture object's image data using the information SDL_Surface gives us 
     glTexImage2D(GL_TEXTURE_2D, 0, 3, surface->w, surface->h, 0, 
        GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); 
    } 
    else { 
     printf("SDL could not load image.bmp: %s\n", SDL_GetError()); 
     SDL_Quit(); 
     return 1; 
    }  

    // Free the SDL_Surface only if it was successfully created 
    if (surface) { 
     SDL_FreeSurface(surface); 
    } 

    // Clear the screen before drawing 
glClear(GL_COLOR_BUFFER_BIT); 

    // Bind the texture to which subsequent calls refer to 
    glBindTexture(GL_TEXTURE_2D, texture); 

    glColor3f(1,0,0); 
    glDisable(GL_TEXTURE_2D); 
    glBegin(GL_QUADS); 
     // Top-left vertex (corner) 
     glTexCoord2i(0, 0); 
     glVertex3f(0, 0, 0); 

     // Bottom-left vertex (corner) 
     glTexCoord2i(1, 0); 
     glVertex3f(328, 0, 0); 

     // Bottom-right vertex (corner) 
     glTexCoord2i(1, 1); 
     glVertex3f(328, 328, 0); 

     // Top-right vertex (corner) 
     glTexCoord2i(0, 1); 
     glVertex3f(0, 328, 0); 
    glEnd(); 
    glColor3f(1,1,1); 
    glEnable(GL_TEXTURE_2D); 

    glBegin(GL_QUADS); 
     // Top-left vertex (corner) 
     glTexCoord2i(0, 0); 
     glVertex3f(100, 100, 0); 

     // Bottom-left vertex (corner) 
     glTexCoord2i(1, 0); 
     glVertex3f(228, 100, 0); 

     // Bottom-right vertex (corner) 
     glTexCoord2i(1, 1); 
     glVertex3f(228, 228, 0); 

     // Top-right vertex (corner) 
     glTexCoord2i(0, 1); 
     glVertex3f(100, 228, 0); 
    glEnd(); 

    SDL_GL_SwapBuffers(); 

    // Wait for 3 seconds to give us a chance to see the image 
    SDL_Delay(3000); 

    // Now we can delete the OpenGL texture and close down SDL 
    glDeleteTextures(1, &texture); 

    SDL_Quit(); 

return 0; 
} 

Текстура оказывает, но там, где должна быть прозрачность, есть только черный цвет.

+1

В следующий раз используйте кнопку «Пример кода» для больших блоков кода. – genpfault

ответ

1

Для ВГА прозрачности, вам нужен альфа-канал, на вашей структуре, но что более важно, в вашем фреймбуфером. Это делается с помощью SDL_GL_SetAttribute, например:

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); 

Это будет просить видеобуфер, по крайней мере, те размеры, и вы будете иметь возможность использовать смешивание. Не забудьте включить смешивание и установить функцию смешивания.

0

Посмотрите на ваш звонок glTexImage2D(GL_TEXTURE_2D, 0, 3, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);. Вы указываете 3 цветовых компонента для внутреннего формата. Попробуйте 4 (с альфа-каналом) или GL_RGBA (more about this).

+1

Я настоятельно рекомендую просто вызывать 'surface-> format-> BytesPerPixel' вместо того, чтобы вручную записывать значение' 4' в качестве значения. Это более гибко, и позже вы избежите странных проблем, если по какой-то причине изменится канал загруженного объекта SDL_Surface (тогда у нас будет ситуация с поиском одной цифры, возможно, в огромной куче кода - вообще не весело) , – rbaleksandar

0

Я проверил ваш код на своем компьютере, и он работает правильно. Установили ли вы «opengl32.lib» в своем компоновщике?

0

Будучи блестящим умом, которым я являюсь, моя проблема заключалась в том, что у меня был glEnable (GL_DEPTH_TEST). Удаление этой линии заставило все работать, и я беспокоюсь о более поздних проблемах. Повеселись!