I'm seeing artifacts when I attempt to rotate an image - c++

This is the before:
http://img22.imageshack.us/img22/5310/beforedes.jpg
znd after:
http://img189.imageshack.us/img189/8890/afterr.jpg
EDIT:: Now that I look at imageshack's upload, the artifacts are diminished a great deal.. but trust me, they are more pronounced than that.
I don't understand why this is happening. Imageshack uploads them to jpg, but in my program they are in the image folder as .tif (The reason for .tif is because I couldn't get ANY other image to maintain their transparent parts).
But anyways, these artifacts follow the original top of the image as it rotates anywhere except the original.
Here's part of my code that loads the image
GLuint texture;
GLenum texture_format;
GLint nofcolors;
GLfloat spin;
bool Game::loadImage()
{
SDL_Surface * surface; // this surface will tell us the details of the image
if ( surface = SM.load_image("Images/tri2.tif") )
{
//get number of channels in the SDL surface
nofcolors = surface->format->BytesPerPixel;
//contains an alpha channel
if ( nofcolors == 4 )
{
if ( surface->format->Rmask == 0x000000ff )
texture_format = GL_RGBA;
else texture_format = GL_BGRA;
}
else if ( nofcolors == 3 ) //no alpha channel
{
if ( surface->format->Rmask == 0x000000ff )
texture_format = GL_RGB;
else texture_format = GL_BGR;
}
// 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 );
glTexImage2D( GL_TEXTURE_2D, 0, nofcolors, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels );
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
SDL_Quit();
return false;
}
// Free the SDL_Surface only if it was successfully created
if ( surface )
{
SDL_FreeSurface( surface );
return true;
}
else return false;
}
void Game::drawImage()
{
// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );
glTranslatef( float(S_WIDTH/2), float(S_HEIGHT/2), 0.0f );
glRotatef( spin, 0.0, 0.0, 1.0 );
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );
glBegin( GL_QUADS );
{
// Top-left vertex (corner)
glTexCoord2i( 0, 0 );
glVertex3f( -64, 0, 0 );
// Top-right vertex (corner)
glTexCoord2i( 1, 0 );
glVertex3f( 64, 0, 0 );
// Bottom-right vertex (corner)
glTexCoord2i( 1, 1 );
glVertex3f( 64, 128, 0 );
// Bottom-left vertex (corner)
glTexCoord2i( 0, 1 );
glVertex3f( -64, 128, 0 );
}
glEnd();
glLoadIdentity();
SDL_GL_SwapBuffers();
}

Looks like the texture is set to GL_WRAP. Try GL_CLAMP_TO_EDGE instead.

In Game::loadImage, after your glBindTexture call:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Your current setting is GL_REPEAT, which is the OpenGL default.

Related

Using single channel texture (OpenGL 2)?

Short storry:
when I render anything using texture loaded like this
glTexImage2D ( GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, pixels );
I get only black
Long storry:
I can get RGBA texture with alpha channel (e.g. text with transparent backgorund using this code):
This code works:
// === load
#define GL_ABGR 0x8000
SDL_Surface * surf = SDL_LoadBMP( "common_resources/dejvu_sans_mono_RGBA.bmp" );
glGenTextures ( 1, &itex );
glBindTexture ( GL_TEXTURE_2D, itex );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_ABGR, GL_UNSIGNED_BYTE, surf->pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// ....
// === render
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, itex );
glColor3f(1.0f,1.0f,1.0f);
glEnable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
drawString ( caption, xmin, ymin+12, 6 );
renders like
But I'm trying to use just one channel (8-bit; grayscale) images / textures instead of RGBA. These I cannot get to render neither with nor without transparancy. Whatever I do I get only black image.
This doesn't
// === load
#define GL_ABGR 0x8000
SDL_Surface * surf = SDL_LoadBMP( "common_resources/dejvu_sans_mono_Alpha.bmp" );
glGenTextures ( 1, &itex );
glBindTexture ( GL_TEXTURE_2D, itex );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_R8, surf->w, surf->h, 0, GL_RED, GL_UNSIGNED_BYTE, surf->pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// ....
// === render
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, itex );
glColor3f(1.0f,1.0f,1.0f);
//glEnable(GL_BLEND);
//glEnable(GL_ALPHA_TEST);
//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
drawString ( caption, xmin, ymin+12, 6 );
renders like
Notes:
I know that I should somehow use glTexEnv according to e.g. here but my main problem is that apparently the monochrome texture does not render at all
I tried also other GL_LUMINANCE and GL_INTENSITY instead of GL_RED in glTexImage2D with no difference
there are other questions like here and here but mostly with OpenGL>3.0 and fragment shaders
Also, is it possible that my graphics card or driver does not support this ? I'm on ubuntu 16.04
GL_VENDOR: Intel Open Source Technology Center
GL_RENDERER: Mesa DRI Intel(R) HD Graphics 530 (Skylake GT2)
GL_VERSION: 3.0 Mesa 11.2.0
for completeness - although it is not importaint the drawString looks like this:
drawString ( caption, xmin, ymin+12, 6 ){
const int nchars = 95;
float persprite = 1.0f/nchars;
glBegin(GL_QUADS);
for(int i=0; i<65536; i++){
if( str[i] == 0 ) break; // 0-terminated string
int isprite = str[i] - 33; // 33 is offset of meaningfull ASCII characters
float offset = isprite*persprite+(persprite*0.57);
float xi = i*sz + x;
glTexCoord2f( offset , 1.0f ); glVertex3f( xi, y, 3.0f );
glTexCoord2f( offset+persprite, 1.0f ); glVertex3f( xi+sz, y, 3.0f );
glTexCoord2f( offset+persprite, 0.0f ); glVertex3f( xi+sz, y+sz*2, 3.0f );
glTexCoord2f( offset , 0.0f ); glVertex3f( xi, y+sz*2, 3.0f );
}
glEnd();
}
I want to try to help you. In my projects I am using this arguments for generating textures from grayscale source images:
glTexImage2D(GL_TEXTURE_2D, 0, 1, width, height, 0, GL_RED,
GL_UNSIGNED_BYTE, pixels);
As written in documentation, third argument - number of color components (1 in our case). Need to check integer value of GL_R8 or replace it explicitly.
GL_RED means that you place luminances in red channel (not in each red, green, blue channels as for grayscale image).

OpenGL - FBO black screen when rendering to texture on NVIDIA card

I've followed some tutorials on how to setup and render an FBO. At first it worked and the scene rendered fine, but it turns out the program was using the integrated GPU. (I'm using my laptop)
Then, out of curiosity, I ran it with the "higher-performance" GPU (an Nvidia GeForce GT540M) and the screen was all black. At this point I tried saving the FBO's color texture into a file and the scene was actually being drawn there.
But eventually I found a solution. Previously I would only clear the FBO (color and depth buffers), but now I clear both the FBO and the default framebuffer and the scene is rendered again.
So the question is, is it bad that I have to call glClear twice? Do I really have to call glClear twice? Why would the one clear work on the integrated card?
I can show some code if it helps.
Framebuffer initialization
bool FrameBufferObject::initializeFBO( int width, int height ) {
glActiveTexture( GL_TEXTURE0 );
if ( !_colorTexture.createEmptyTexture( width, height ) ) {
return false;
}
_textureId = _colorTexture.getTextureId();
if ( !_depthTexture.createDepthTexture( width, height ) ) {
return false;
}
_depthTextureId = _depthTexture.getTextureId();
glGenFramebuffers( 1, &_frameBufferID );
glBindFramebuffer( GL_FRAMEBUFFER, _frameBufferID );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureId, 0 );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTextureId, 0 );
if ( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE ) {
return false;
}
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
_width = width;
_height = height;
_isInitialized = true;
return true;
}
Color Texture
bool Texture::createEmptyTexture( int width, int height ) {
if ( isLoaded() ) {
closeTexture();
}
GLuint textureId = 0;
glGenTextures( 1, &textureId );
if ( getOpenGLError( "Unable to generate TextureID." ) ) {
return false;
}
glBindTexture( GL_TEXTURE_2D, textureId );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glBindTexture( GL_TEXTURE_2D, 0 );
if ( getOpenGLError( "Error creating empty texture." ) ) {
glDeleteTextures( 1, &textureId );
return false;
}
_isLoaded = true;
_textureWidth = _imageWidth = width;
_textureHeight = _imageHeight = height;
_textureId = textureId;
return true;
}
The Depth Texture is the same, except it uses the GL_DEPTH_COMPONENT format,
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
Post Processing Shader
Vertex shader
#version 330 core
in vec2 inVertex;
in vec2 inTexture;
out vec2 texCoords;
void main() {
texCoords = inTexture;
gl_Position = vec4( inVertex.x, inVertex.y, 0, 1 );
}
Fragment shader
#version 330 core
in vec2 texCoords;
uniform sampler2D texture0;
layout(location = 0) out vec4 outColor;
void main() {
vec4 color = texture( texture0, texCoords );
outColor = color;
}
The rendering code looks like this,
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
fbo.bindFBO();
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// .. render scene ..
fbo.unbindFBO();
// This is a namespace
PostProcShader::shader.useShader();
PostProcShader::render( fbo.getColorTexture() );
PostProcShader::shader.disableShader();
SDL_GL_SwapWindow( window );
Where the post processing shader simply renders the texture on a screen-sized quad. The scene uses 3 shaders: one for 3D objects, the second for the skybox and last one for fonts.
I'm using C++, SDL2 and (of course) OpenGL/Glew in VS 2015.
Edit:
Depth Test initialization
glEnable( GL_DEPTH_TEST );
glDepthMask( GL_TRUE );
glDepthFunc( GL_LEQUAL );
glDepthRange( 0.0f, 1.0f );
glClearDepth( 1.0f );
I got a similar problem when I went from Intel HUD to Nvidia. However my solution was simple. I had to ensure I called glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) before rendering to the new framebuffer (on Nvidia) otherwise I would see nothing rendered. I suspect that on Nvidia the depth buffer is not set to the same defaults as on Intel so clearing it sets it to the opengl default clear value.

How can i use a texture .jpg image for an openGL background window in mac?

I want to set a background for an openGL window for mac. background will take a jpg or png file.
Here is my code..
GLuint texture; //the array for our texture
GLfloat angle = 0.0;
GLuint LoadTexture (const char * filename, int width, int height ){
// GLuint texture;
unsigned char * data;
FILE * file;
//The following code will read in our RAW file
file = fopen( filename, "rb" );
if ( file == NULL ) return 0;
data = (unsigned char *)malloc( width * height * 3 );
fread( data, width * height * 3, 1, file );
fclose( file );
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// // when texture area is small, bilinear filter the closest mipmap
// glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
// GL_LINEAR_MIPMAP_NEAREST );
// // when texture area is large, bilinear filter the original
// glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
//
// // the texture wraps over at the edges (repeat)
// glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
// glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
//
// //Generate the texture
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,GL_RGB, GL_UNSIGNED_BYTE, data);
// select modulate to mix texture with color for shading
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// when texture area is small, bilinear filter the closest mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST );
// when texture area is large, bilinear filter the first mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// // the texture wraps over at the edges (repeat)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
// build our texture mipmaps
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height,
GL_RGB, GL_UNSIGNED_BYTE, data );
free(data);
return texture; //return whether it was successful
}
void FreeTexture( GLuint texture ){
glDeleteTextures( 1, &texture );
}
void cube () {
glEnable(GL_TEXTURE_2D);
glBindTexture( GL_TEXTURE_2D, texture ); //bind the texture
glPushMatrix();
glRotatef( angle, 0.0f, 0.0f, 1.0f );
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();
glPopMatrix();
glutSwapBuffers();
//glutSolidCube(2);
}
void display () {
glClearColor (0.0,0.0,0.0,1.0);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
texture = LoadTexture( "/Users/macbook/MatrixEngineClientSample/Fighters/Sunset03.jpg", 256, 256 ); //load the texture
glEnable( GL_TEXTURE_2D ); //enable 2D texturing
// glEnable(GL_TEXTURE_GEN_S); //enable texture coordinate generation
// glEnable(GL_TEXTURE_GEN_T);
cube();
FreeTexture( texture );
//glutSwapBuffers();
//angle ++;
}
void reshape (int w, int h) {
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
//glLoadIdentity ();
gluPerspective (50, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode (GL_MODELVIEW);
}
int main (int argc, char **argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow ("A basic OpenGL Window");
glutDisplayFunc (display);
glutIdleFunc (display);
glutReshapeFunc (reshape);
glutMainLoop ();
return 0;
}
EDIT
I want to see this image as a background of the openGL window...image is below..
but it showing this...
I consulted this Apple guide.
The problem is that the file is compressed AND has a header, and with your code you are even using part of the file header as an image source.
I would replace this code:
// GLuint texture;
unsigned char * data;
FILE * file;
//The following code will read in our RAW file
file = fopen( filename, "rb" );
if ( file == NULL ) return 0;
data = (unsigned char *)malloc( width * height * 3 );
fread( data, width * height * 3, 1, file );
fclose( file );
With something more similar to this:
CFURLRef urlRef = (CFURLRef)[NSURL fileURLWithPath:#"/Users/macbook/MatrixEngineClientSample/Fighters/Sunset03.jpg"];
CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(url, NULL);
CGImageRef myImageRef = CGImageSourceCreateImageAtIndex(myImageSourceRef, 0, NULL);
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(myImageRef));
unsigned char *data = CFDataGetBytePtr(data);
You may need to add Core Graphics and Core Foundation to the list of your linked frameworks.
PNG and JPG images (as with most other image formats) require some form of decompression/decoding, so loading them raw from a file wont produce expected results. It should work with bmp or uncompressed tga images after reading the file header though :/ . Anyway, here are a few image loading libraries that should make loading images easy:
SOIL
DevIL
FreeImage
GLI

How can I load a .png image with transparency in it, using SDL, OpenGL and C++?

I am trying to load and display a .png image that has transparency in it. The whole image is not transparent, it's just a picture of a bag I have cropped in Photoshop, with transparency around it. I need to load it to my program that uses SDL and OpenGL on C++, but when I try it, instead of it displaying correctly, the space around the bag in the image is "fuzzy" (I can only put it that way). What I'm saying is, the transparency does not work.
This is my code so far:
The init() method:
SDL_Surface *surface;
GLenum texture_format;
GLint nOfColors;
if ( (surface = IMG_Load("bag.png")) ) {
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: bag.png'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: bag.png's height is not a power of 2\n");
}
// get the number of channels in the SDL surface
nOfColors = surface->format->BytesPerPixel;
if (nOfColors == 4) // contains an alpha channel
{
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGBA;
//else
//texture_format = GL_BGRA;
} else if (nOfColors == 3) // no alpha channel
{
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGB;
//else
//texture_format = GL_BGR;
} else {
printf("warning: the image is not truecolor.. this will probably break\n");
// this error should not go unhandled
}
// 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, nOfColors, surface->w, surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, surface->pixels );
}
else {
printf("SDL could not load bag.png: %s\n", SDL_GetError());
SDL_Quit();
//return 1;
}
// Free the SDL_Surface only if it was successfully created
if ( surface ) {
SDL_FreeSurface( surface );
}
The drawScene() method:
float xMin, xMax, yMin, yMax;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -6.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Use nice (linear) scaling
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Use nice (linear) scaling
glBegin (GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
if (texturesOn) glTexCoord2f(0.0f, 1.0f);
glVertex3f(4.3f, -3.5f, 0.0f); //bottom left
if (texturesOn) glTexCoord2f(1.0f, 1.0f);
glVertex3f(5.3f, -3.5f, 0.0f); //bottom right
if (texturesOn) glTexCoord2f(1.0f, 0.0f);
glVertex3f(5.3f, -4.5f, 0.0f); //top right
if (texturesOn) glTexCoord2f(0.0f, 0.0f);
glVertex3f(4.3f, -4.5f, 0.0f); //top left
glEnd();
glDisable(GL_TEXTURE_2D);
glutSwapBuffers();
You need to enable blending for transparency to work:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Also, you should check that the loaded PNG file contains an alpha channel.

SDL/OpenGL Texture Transparency

I'm just wondering how I can convert an SDL_Surface (loaded from a png via IMG_Load) and stick it on a quad. Here is what I have (mostly just copy pasted from a tutorial I found).
#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;
}
The texture renders, but where there should be transparency, there is just black.
I don't see you enabling blending anywhere. You'll need some variation of:
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
See here: http://www.opengl.org/resources/faq/technical/transparency.htm
To hav transparency, you need an alpha channel, on your texture, but more important, in your framebuffer. This is done with SDL_GL_SetAttribute, for example:
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 );
This will request a framebuffer with at least those sizes, and you'll be able to use blending. Remember to enable blending and set a blending function.
Have a look at your call glTexImage2D( GL_TEXTURE_2D, 0, 3, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );. You specify 3 color components for the internal format. Try 4 (with alpha channel), or GL_RGBA (more about this).
i've been check your code in my computer and thats run correctly. Have you set 'opengl32.lib' in your linker?
Being the brilliant mind that I am, my issue was that i had glEnable(GL_DEPTH_TEST) on. Removing that line made everything work and me worry about later issues. Have fun!