Hi all,
This is my first post here (so go easy on me . I have spent the better part of a week attempting to properly load a png image,bind it to a texture, set it to an object and have the transparent layer stay transparent while rendering the rest of the sprite(like a decal would appear, or a billboarded sprite). I've searched this forum rather thoroughly, but every solution I've found has seemed not to work for me. Any help would be genuinely and greatly appreciated As I'm uncertain where I'm going wrong, I'm uncertain what information you may need, but I'll try to include the essentials, an image of the semi-transparent sprite is included.
To the best of my knowledge, the png file(created in gimp) does contain the alpha layer and was saved correctly.
Am I failing to set the OpenGL Alpha layer correctly, or perhaps calling the BlendFunc in the wrong location? Perhaps I'm misunderstanding the BlendFunc. (I'm getting my information here:https://www.opengl.org/archives/resources/faq/technical/transparency.htm).
Things:
I'm using c++, codeblocks, Ubuntu 14.04, glfw3, freeImage (and a little loader found on this forum for png files, included in the code below), nvidia 560 ti,
When i set :
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
nothing is rendered at all. Though, if I set :
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
things actually appear to display correctly, however, while the transparent layer is completely transparent, the rest of the sprite appears semi-transparent as well.
I've attempted to display the sprite using GL_DECAL, as well as trying to set the alpha_state and have ended up with similar results. Either nothing is displayed at all, the transparent layer is displayed as completely black, or this state, where it is semi-transparent. I've tried calling the glEnable and glBlendFunc in various places. The one thing I can't seem to successfully code is having the sprite display without the background and not be semi-transparent itself.
I should note as well that if I change the Fragment shader color value to vec4 (it's currently set to a vec3) and include an alpha color (set to anything between 0.1 and 1) the glBLendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) will display the sprite, but (perhaps predictably) the entire sprite is semi-transparent, though the transparent layer of the sprite appears to be black(just slightly transparent) and, thus, not set correctly.
Here is (what i think would be) the relevant code:
Main:
#include "Main.h"
int main()
{
glEnable(GL_TEXTURE_2D);
if(!glfwInit())
{
fprintf( stderr, "Failed to initialize glfw\n");
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(1920, 1080, "OpenGL is an ******", NULL, NULL);
if(window == NULL)
{
fprintf(stderr, "Failed to open GLFW window.");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = true;
if(glewInit() != GLEW_OK)
{
fprintf(stderr, "Failled to initialize GLEW\n");
return -1;
}
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
Object Obj2("background.png","plane5.obj");
Object Obj1("tree.png","tree3.obj");
do
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(Obj1.programID);
Obj2.Render();
Obj1.Render();
glfwSwapBuffers(window);
glfwPollEvents();
}
while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
Obj1.CleanUp();
Obj2.CleanUp();
glfwTerminate();
return 0;
}
Object:
#include "Object.h"
Object::Object(const char* textureHere, const char* objHere) {
VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
programID = LoadShaders("StandardShading.vertexshader",
"StandardShading.fragmentshader");
MatrixID = glGetUniformLocation(programID, "MVP");
ViewMatrixID = glGetUniformLocation(programID, "V");
ModelMatrixID = glGetUniformLocation(programID, "M");
PlaneMatrixID = glGetUniformLocation(programID, "P");
Texture = LoadImage(textureHere);
res = loadOBJ(objHere, vertices, uvs, normals);
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);
glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);
glUseProgram(programID);
LightID = glGetUniformLocation(programID, "LightPosition_worldspace");
}
Object::Object(const Object& orig) {
}
Object::~Object() {
}
void Object::Render()
{
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
computeMatricesFromInputs();
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
glm::vec3 lightPos = glm::vec3(4,4,4);
glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
glUniform1i(TextureID, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, //attribute
3, //size
GL_FLOAT, //type
GL_FALSE, //normalized?
0, //stride...whateverthehell that is
(void*)0 //array buffer offset
);
// 2nd attribute buffer : uvs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1, // attribute.
2, // size : u + v = 2
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
//3rd attribute normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
2, //attribute
3, //size
GL_FLOAT, //type)
GL_FALSE, //normalized?
0, //stride
(void*)0 //array buffer offset
);
glDrawArrays(GL_TRIANGLES, 0, vertices.size() );
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
void Object::CleanUp()
{
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &uvbuffer);
glDeleteBuffers(2, &normalbuffer);
glDeleteProgram(programID);
glDeleteTextures(1, &TextureID);
glDeleteVertexArrays(1, &VertexArrayID);
}
GLuint Object::LoadImage(const char* imageName)
{
FREE_IMAGE_FORMAT formato =
FreeImage_GetFileType(imageName,0);
FIBITMAP* imagen = FreeImage_Load(formato, imageName);
FIBITMAP* temp = imagen;
imagen = FreeImage_ConvertTo32Bits(imagen);
FreeImage_Unload(temp);
int w = FreeImage_GetWidth(imagen);
int h = FreeImage_GetHeight(imagen);
GLubyte* textura = new GLubyte[4*w*h];
char* pixels = (char*)FreeImage_GetBits(imagen);
for(int j= 0; j<w*h; j++){
textura[j*4+0]= pixels[j*4+2];
textura[j*4+1]= pixels[j*4+1];
textura[j*4+2]= pixels[j*4+0];
textura[j*4+3]= pixels[j*4+3];
}
GLuint TextureID;
glGenTextures(1, &TextureID);
glBindTexture(GL_TEXTURE_2D, TextureID);
if(FreeImage_GetBPP(imagen) == 24)
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, w, h, 0,
GL_RGB,GL_UNSIGNED_BYTE,(GLvoid*)textura );
else if(FreeImage_GetBPP(imagen) == 32)
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, w, h, 0,
GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid*)textura );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return TextureID;
}
Let me know if you need any more relevant information. And, my apologies for posting yet another png transparency thread. I'm out of ideas, so create yet another thread on this out of simple desperation. The solution on almost every thread appears to be to simply set glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);, which results in nothing being displayed at all.
Thank you in advance for any assistance,