2017-03-22 1 views
2

Sur mon 2ème projet, je travaille avec opengl et SDL2. Je veux rendre le texte à une surface avec SDL2, puis le convertir.Pourquoi la conversion d'une surface SDL fonctionne-t-elle lorsque la surface a été chargée à partir d'un fichier mais pas quand elle a été générée à partir d'un fichier de police?

Je charge déjà des textures à partir de fichiers avec SDL donc j'ai une fonction qui peut convertir des surfaces. Encore quand je fournis une surface générée par la fonction TTF_Render le résultat est le suivant: enter image description here

Maintenant je ne sais pas pourquoi cela se produit donc un soutien serait apprécié. J'utilise la librairie SDL_ttf pour charger le fichier. J'utilise visual studio 2015 comme ide.

Voici ma fonction de conversion:

GLuint JUMA_Texture::loadFromSurface(SDL_Surface *img, GLenum target, GLenum filtering) { 
    GLuint TextureID = 0; 
    glGenTextures(1, &TextureID); 
    glBindTexture(GL_TEXTURE_2D, TextureID); 
    std::cout << " got " << img; 
    if (target == GL_TEXTURE_2D) 
    { 
     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
    } 
    int Mode = GL_RGB; 
    if (img->format->BytesPerPixel == 4) { 
     glEnable(GL_BLEND); 
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
     transparent = true; 
     Mode = GL_RGBA; 
    } 

    glTexImage2D(GL_TEXTURE_2D, 0, Mode, img->w, img->h, 0, Mode, GL_UNSIGNED_BYTE, img->pixels); 
    glGenerateMipmap(target); 
    return TextureID; 
} 

J'imprime l'adresse des pointeurs de surface avant et après qu'il ait été envoyé à la fonction et ils semblent identiques.

Aussi j'écris la surface dans un fichier en utilisant SDL_SaveBmp et il semble bien aussi.

Edit:

En raison de la demande Je vais maintenant poster le code pour les fonctions d'utilisation, ainsi que les constructeurs de mes classes de shaders et de texture.

constructeur shader/chargeur

printf("Loading shader"); 
    // 1. Retrieve the vertex/fragment source code from filePath 
    std::string vertexCode; 
    std::string fragmentCode; 
    std::ifstream vShaderFile; 
    std::ifstream fShaderFile; 
    strcpy_s(Fragpath, fragmentPath); 
    strcpy_s(Vertexpath, vertexPath); 

    printf("."); 
    // ensures ifstream objects can throw exceptions: 
    vShaderFile.exceptions(std::ifstream::badbit); 
    fShaderFile.exceptions(std::ifstream::badbit); 
    try 
    { 
     // Open files 
     vShaderFile.open(vertexPath); 
     fShaderFile.open(fragmentPath); 
     std::stringstream vShaderStream, fShaderStream; 
     // Read file's buffer contents into streams 
     vShaderStream << vShaderFile.rdbuf(); 
     fShaderStream << fShaderFile.rdbuf(); 
     // close file handlers 
     vShaderFile.close(); 
     fShaderFile.close(); 
     // Convert stream into string 
     vertexCode = vShaderStream.str(); 
     fragmentCode = fShaderStream.str(); 
     printf("."); 
    } 
    catch (std::ifstream::failure e) 
    { 
     std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; 
    } 
    const GLchar* vShaderCode = vertexCode.c_str(); 
    const GLchar * fShaderCode = fragmentCode.c_str(); 
    // 2. Compile shaders 
    GLuint vertex, fragment; 
    GLint success; 
    GLchar infoLog[512]; 
    // Vertex Shader 
    vertex = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vertex, 1, &vShaderCode, NULL); 
    glCompileShader(vertex); 
    // Print compile errors if any 
    glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); 
    printf("."); 
    if (!success) 
    { 
     glGetShaderInfoLog(vertex, 512, NULL, infoLog); 
     std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; 
    } 
    // Fragment Shader 
    fragment = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(fragment, 1, &fShaderCode, NULL); 
    glCompileShader(fragment); 
    // Print compile errors if any 
    glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); 
    if (!success) 
    { 
     glGetShaderInfoLog(fragment, 512, NULL, infoLog); 
     std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; 
    } 
    printf("."); 
    // Shader Program 
    this->Program = glCreateProgram(); 
    glAttachShader(this->Program, vertex); 
    glAttachShader(this->Program, fragment); 
    glLinkProgram(this->Program); 
    // Print linking errors if any 
    glGetProgramiv(this->Program, GL_LINK_STATUS, &success); 
    if (!success) 
    { 
     glGetProgramInfoLog(this->Program, 512, NULL, infoLog); 
     std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; 
    } 
    printf("."); 
    // Delete the shaders as they're linked into our program now and no longer necessery 
    glDeleteShader(vertex); 
    glDeleteShader(fragment); 
    printf("done\n"); 

fonction shader utilisation

void JUMA_Shader::Use() 
{ 
    glUseProgram(this->Program); 
} 

constructeur de texture

printf("loading Texture"); 
    int pos; 
    pos = filePath.find("."); 
    if (filePath.substr(pos) == ".png") { 

     IMG_Init(IMG_INIT_PNG); 
    } 
    else if (filePath.substr(pos) == ".jpg") 
     IMG_Init(IMG_INIT_JPG); 

    SDL_Surface *img = IMG_Load(filePath.c_str()); 
    id = loadFromSurface(img,target,filtering); 

Texture :: loadFromSurface (NOTE:. J'AI PAS ENCORE DISPONIBLE POUR VÉRIFIER GL_BGR ET GL_BGRA Toutefois, j'ai MANUELLEMENT TENTATIVE DE CES DEUX MODES SANS EFFET DIFFERENT ACTUELLEMENT)

GLuint JUMA_Texture::loadFromSurface(SDL_Surface *img, GLenum target, GLenum filtering) { 
    GLuint TextureID = 0; 
    glGenTextures(1, &TextureID); 
    glBindTexture(GL_TEXTURE_2D, TextureID); 
    std::cout << " got " << img; 
    if (target == GL_TEXTURE_2D) 
    { 
     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
    } 
    int Mode = GL_RGB; 
    if (img->format->BytesPerPixel == 4) { 
     glEnable(GL_BLEND); 
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
     transparent = true; 
     Mode = GL_RGBA; 
    } 

    glTexImage2D(GL_TEXTURE_2D, 0, Mode, img->w, img->h, 0, Mode, GL_UNSIGNED_BYTE, img->pixels); 
    glGenerateMipmap(target); 
    return TextureID; 
} 

Texture :: UTILISATION

int JUMA_Texture::use(GLenum Channel) { 
    glActiveTexture(Channel); // Activate the texture unit first before binding texture 
    glBindTexture(GL_TEXTURE_2D, id); 

    if (transparent) 
    { 
     glEnable(GL_BLEND); 
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

    } 
    return 1; 
} 

aussi voici ce que je vois en ce moment (Notez que j'ai vérifié à nouveau et ce n'est pas la couleur que je mets ma police comme je l'ai déjà dit. Je ne sais pas d'où vient cette couleur bleue.Je suis actuellement en train de comprendre cela) enter image description here

Enfin voici mon vertex shader:

#version 330 core 
layout (location = 0) in vec3 position; 
layout (location = 1) in vec3 texcoords; 
out vec2 texCoords; 
uniform mat4 model; 
uniform mat4 view; 
uniform mat4 projection; 
out vec4 pos; 
void main() 
{ 
    pos=gl_Position = projection*view*model*vec4(position,1.0f); 
    texCoords=vec2(texcoords.xy); 
}; 

Et mon fragment shader:

#version 330 core 
out vec4 color; 
in vec2 texCoords; 
in vec4 pos; 
uniform sampler2D ourTexture; 
uniform vec4 mixCol; 

void main() 
{ 
    vec4 texColor = texture(ourTexture, texCoords); 
    if(texColor.a < 0.1f) 
     discard; 

    color = texColor; 
}; 

Mon constructeur de police

JUMA_Font::JUMA_Font(char *path, int size, SDL_Color color, char* text, char *uniform) { 
    TTF_Init(); 
    font = TTF_OpenFont(path, 40); 
    sourceSurface = TTF_RenderText_Blended(font, text, color); 
    printf("%d %d %d %d", color.r, color.g, color.b, color.a); 
}; 

police convertir texturer

JUMA_Texture convertToTexture() { 
     JUMA_Texture _this; 
     SDL_SaveBMP(sourceSurface, "out.bmp"); //outputs font correctly 
     std::cout << "Expected " << sourceSurface; 
     _this.id = _this.loadFromSurface(sourceSurface,GL_TEXTURE_2D,GL_NEAREST); 

     return _this; 
    } 
+0

Je suis un peu confus. Le code que vous avez ajouté charge la texture à partir d'un fichier (constructeur de texture), ce que vous avez indiqué fonctionne correctement. Est-ce toujours le cas? C'est à dire. Lorsque vous chargez une image à partir d'un fichier et envoyez la surface à 'loadFromSurface()', tout fonctionne-t-il correctement? Dans ce cas, la partie intéressante du code est la création de la surface à partir d'une police ('TTF_Render *'), qui est toujours manquante. – Meyer

+0

Très bien, j'ajoute la classe complète de polices ... S'il vous plaît maintenez – MoustacheSpy

+0

@Meyer J'ai ajouté tout ce que vous vouliez. Aussi les images sont encore chargées correctement – MoustacheSpy

Répondre

1

Cela ressemble à la surface que vous avez généré avec TTF_Render*_Solid() ou TTF_Render*_Shaded(). Cependant, ces fonctions return an 8-bit palettized surface, que OpenGL ne comprend pas. Ceci n'est pas détecté dans votre fonction, où vous définissez le format de la source (Mode) sur GL_RGB ou GL_RGBA, les deux étant incorrects dans ce cas. En guise de solution, assurez-vous de restituer le texte en mode mixte en utilisant l'une des fonctions TTF_Render*_Blended(). Cela crée une surface BGRA complète, qui peut ensuite être utilisée avec glTexImage2D().

Notez également que it is recommended à utiliser un format interne spécifique avec glTexImage2D(), de sorte que l'appel de fonction devrait ressembler à ceci:

glTexImage2D(GL_TEXTURE_2D, 0, 
    GL_RGBA8, 
    img->w, img->h, 0, 
    GL_BGRA, 
    GL_UNSIGNED_BYTE, img->pixels); 
+0

J'ai changé la fonction en TTF_Render_Blended comme vous l'avez dit mais maintenant le quad entier est coloré dans le SDL_Color que j'ai spécifié. Je me suis assuré que ce n'est pas un problème de shader. – MoustacheSpy

+0

Je peux penser à quelques causes. Assurez-vous que les coordonnées UV sont correctes et en effet mapper la texture sur le quad. Assurez-vous de bien échantillonner les bons canaux de couleur. Last but not least, assurez-vous que l'alpha blending est vraiment activé. Comme un simple test, utilisez quelque chose comme ça dans le fragment shader: 'if (sampledColor.a <0.5) rejeter;'. Si le texte est rendu (sans antialiasing), alors l'alpha-blending est en effet le problème. Sinon, il serait utile que vous ajoutiez le code de chargement complet de la texture, ainsi que le code shader correspondant, à votre question, pour un examen plus approfondi. – Meyer

+0

J'ai ajouté toutes les fonctions que vous vouliez. Le mélange devrait être bon. S'il y a autre chose que je devrais fournir s'il vous plaît demander immédiatement. Aussi, je suis désolé pour la confusion, mais la couleur que le quad est colorée n'est en fait pas la couleur que j'avais à l'origine ma police. Je me trompais. – MoustacheSpy