SFML community forums
Help => Graphics => Topic started by: Richy19 on November 18, 2011, 03:38:10 am
-
trying to use SFML to load images and to use with OpenGL textures, but when I draw the quad its just black.
I know the UV is right so im pretty sure its the texture its self.
The main problem is im not sure how I should be using sf::Texture in an openGL way
#include "./3dSprite.hpp"
#include "./Engine.hpp"
d3Sprite::d3Sprite(Engine *mEngine)
{
engine = mEngine;
shader = new Shader("./Data/vert.vert" ,"./Data/frag.frag");
UVList[0] = 1.0f;
UVList[1] = 1.0f;
UVList[2] = 0.0f;
UVList[3] = 1.0f;
UVList[4] = 0.0f;
UVList[5] = 0.0f;
UVList[6] = 1.0f;
UVList[7] = 1.0f;
UVList[8] = 0.0f;
UVList[9] = 0.0f;
UVList[10] = 1.0f;
UVList[11] = 0.0f;
vertexList[0] = 0.5f;
vertexList[1] = 1.0f;
vertexList[2] = 0.0f;
vertexList[3] = -0.5f;
vertexList[4] = 1.0f;
vertexList[5] = 0.0f;
vertexList[6] = -0.5f;
vertexList[7] = 0.0f;
vertexList[8] = 0.0f;
vertexList[9] = 0.5f;
vertexList[10] = 1.0f;
vertexList[11] = 0.0f;
vertexList[12] = -0.5f;
vertexList[13] = 0.0f;
vertexList[14] = 0.0f;
vertexList[15] = 0.5f;
vertexList[16] = 0.0f;
vertexList[17] = 0.0f;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &vertexbuffer);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexList), vertexList, GL_STATIC_DRAW);
MatrixID = glGetUniformLocation(shader->shaderID, "MVP");
positionID = glGetAttribLocation(shader->shaderID, "Position");
TextureID = glGetUniformLocation(shader->shaderID, "myTexture");
UVID = glGetAttribLocation(shader->shaderID, "UV");
//std::cout << MatrixID << ":" << positionID << ":" << TextureID << ":" << UVID << std::endl;
//TextureID prints out 65526 for some reason
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(UVList), UVList, GL_STATIC_DRAW);
glGenTextures(1, &texturebuffer);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, texturebuffer);
// Give the image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, TextureResourceManager::textureResourceManager.getFile("./Data/Pedro.png").GetWidth(), TextureResourceManager::textureResourceManager.getFile("./Data/Pedro.png").GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,TextureResourceManager::textureResourceManager.getFile("./Data/Pedro.png").CopyToImage().GetPixelsPtr() );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
d3Sprite::~d3Sprite()
{
// Cleanup VBO and shader
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &uvbuffer);
glDeleteTextures(1, &texturebuffer);
delete shader;
}
void d3Sprite::Initiate(glm::mat4 *persMat, glm::mat4 *camMat)
{
*camMat = glm::lookAt(
glm::vec3( 0, 0, 5 ), // Camera is here glm::vec3( 0, 0, 5 );
glm::vec3( 0, 0, 0 ), // and looks here : at the same position, plus "direction"
glm::vec3( 0, 1, 0 ) // Head is up (set to 0,-1,0 to look upside-down)
);
Drawable::Initiate(persMat, camMat);
}
void d3Sprite::Update(float deltaTime)
{
Drawable::Update();
}
void d3Sprite::Draw()
{
glUseProgram(shader->shaderID);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texturebuffer);
glUniform1i(TextureID, 0);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(positionID);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
positionID, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(UVID);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
UVID, // attribute. No particular reason for 1, but must match the layout in the shader.
2, // size : U+V => 2
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
// For each model you render, since the MVP will be different (at least the M part)
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 6); // Starting from vertex 0; 3 vertices total -> 1 triangle
glDisableVertexAttribArray(UVID);
glDisableVertexAttribArray(positionID);
}
-
Texture::CopyToImage binds the internal texture, so your glTexImage2D call is not applied to your own texture.
You obviously need a sf::Image there, not a sf::Texture.
-
Ahh that fixed it, however the image is upside down.
Is there a reason for this do you know?
-
Don't forget that texture coordinate (0, 0) is the top-left corner.
-
Ohhh, thats the problem.
I was usig this as a reference which states the bottom left as 0,0
Thanks :)
(http://www.opengl-tutorial.org/wp-content/uploads/2011/04/UVintro.png)
-
Also just wondering but does this mean I cant render stuff to a rendertarget via SFML functions and then draw the rendertarget onto an openGL quad?
-
Also just wondering but does this mean I cant render stuff to a rendertarget via SFML functions and then draw the rendertarget onto an openGL quad?
Why not?
-
I thought that calling copytoimage would make it unavailable for openGL textures
-
Can't you use the sf::Texture directly? It's quite expensive to copy pixels from one texture to another every frame.
And CopyToImage doesn't make it unavailable for OpenGL textures, it's just that it binds the texture so if you previously bound your own texture it will have no effect. But if you call CopyToImage before glBindTexture, it's ok.
-
Don't forget that texture coordinate (0, 0) is the top-left corner.
Is this correct? I am having the same problem with textures being upside down and all documentation and books I have looked at say 0, 0 is the bottom-left for tex coord.
I looked at the texture using gDebugger and it displays it upside down, as well.
-
I don't know. I think it's up to you, OpenGL doesn't impose anything.
If you open an image file with any image editor, (0, 0) will be the top-left corner. So I don't know why all OpenGL-based stuff assume the opposite.
-
Grr, yes, tell me about it. I think it comes down to a fundamental misuse of cartesian coordinates for convenience. Image applications technically display (+, -), while GL uses (+, +).
An image that is 32x32 when displayed in an image app, or similar, the last pixel is being displayed at (+31, -31). Looking at it like this would confuse people so they just translate it to say both are positive and now many people are comfortable with a misrepresented cartesian system.
GL follows the "rules" and the last pixel is at (+31, +31), but I agree this gets confusing considering how much the former has been beaten into our heads.
At least this is my understanding, I won't pretend to be an expert on the matter. Image for clarity.
(http://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Cartesian-coordinate-system.svg/250px-Cartesian-coordinate-system.svg.png)
-
I don't think that OpenGL follows any rule. It depends on many things:
- the projection matrix
- the viewport
- the texture coordinates
- and finally the way you load the upload image pixels to the texture
Any of these things are able to choose their own coordinates system. So it's really up to the programmer to choose its preferred one.
I don't know where this "convention" comes from.
-
Just wondering but does SFML mess up the openGL calls of other contexts?
I.e. can I render to a renderTarget without worrying about other openGL contexts such as the window?
-
Just wondering but does SFML mess up the openGL calls of other contexts?
No.
-
Do you know how you would use a sf::Texture with openGL?
The only way I can think of is converting it to a sf::Image and then
// Give the image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, TextureResourceManager::textureResourceManager.getFile("./Data/Pedro.png").GetWidth(), TextureResourceManager::textureResourceManager.getFile("./Data/Pedro.png").GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,TextureResourceManager::textureResourceManager.getFile("./Data/Pedro.png").CopyToImage().GetPixelsPtr() );
-
Isn't it what we talked about in the previous page? :roll:
-
Yea but you mentioned that it wasnt good to call sf::Texture.getImage() each frame as it takes quite a bit of resources to swap from GPU to CPU, so I was wondering how you use the sf::Texture straight away
-
But why do you start with a texture? If all you want is to use the pixel data of an image file, load it directly as a sf::Image. And why does it have to happen each frame? The source is an image file, it doesn't change every frame, does it?
-
no, but if I used renderTextures then they would
-
If you used sf::RenderTexture it would be another problem, with another solution.
-
Hate to resurrect a dead thread, but I don't think anyone ever explicitly said this: The OpenGL coordinate system, if no transformations are applied besides the identity matrix, puts the origin at the bottom left of the screen, when dealing with vertices, and at the bottom left of an image when dealing with textures. The positive Y axis points up in the plane of the screen/image, and the Z axis points out of the screen toward the viewer, meaning openGL is a right handed coordinate system. Of course, one can reverse any of these with a transformation matrix which simply negates the desired axis.