Author Topic: [C++/OpenGL] using a texture that has a transparent color (A snowflake texture)  (Read 734 times)

0 Members and 1 Guest are viewing this topic.

Offline ViL

  • Avocado lover 🥑
  • C= 64
  • **
  • Posts: 52
  • Karma: 1
    • View Profile
Hii! i am almost about to release my first old-school intro with some friends! the only thing left is to know how to bind textures to a quad

i am working with opengl 1.1 as much as i can, for this intro to work on old windows/old integrated graphic chips, so i want to avoid libraries and do it as vanilla as posible also to learn from it! = p

i created a new opengl template in Code::Blocks to work in a cleaner environment, the code is as follow:
https://pastebin.com/raw/XpS0hRpj

which output this nice square on the screen:
https://i.imgur.com/e2FIrUI.png

BUT instead i want to use this nice snowflake:
https://i.imgur.com/HZsjYvW.png

and since afaik i can't use png files without a library, here is the 24 bits bmp version with #FF00FF ( glColor3f(1.0f, 0.0f, 1.0f); ) background instead:
https://i.imgur.com/T5vKjCH.png

i attached the project folder here, i use the Code::Blocks; and has it's project file in

i have read the opengl 1.1 red book and the 1.1 super bible respetive sections, even got through over 500 threads here https://i.imgur.com/34kbxio.png and can't find my solution

can someone help me with what to do to bind the snowflake texture to the quad, and it to show transparent?

thanks you so much before hand! the release of this oldschool intro is stuck by this, i apreciate any help! x3
« Last Edit: January 21, 2018 by ViLXDRYAD »

Offline Knurz

  • C= 64
  • **
  • Posts: 99
  • Karma: 24
    • View Profile
Hi!

Last question first, you can use PNGs without any libraries, there are many PNG decoders out there, like http://lodev.org/lodepng/picopng.cpp (which I prefer, because of it's size).

Let's assume you have the image in RGBA Format uncompressed in memory, first of all you'll have to tell GL to generate a texture:
Code: [Select]
glGenTextures (1, &myTexture);
You'll have to bind the texture for the operations to follow:
Code: [Select]
glBindTexture (GL_TEXTURE_2D, myTexture);
And you'll have to describe to GL what size and format your image has (please take a look at the API Manual, there are many options!):
Code: [Select]
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, myTexture_width, myTexture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE,  uncompressedMemoryTexture);
If you have done any errors in your previous steps, you will notice it when calling glTexImage2D =).
We can change the filtering of our texture:
Code: [Select]
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

After you've done all that, unbind any texture:
Code: [Select]
glBindTexture(GL_TEXTURE_2D, 0);
Somewhere in your code you have to enable the usage of textures:
Code: [Select]
glEnable(GL_TEXTURE_2D);
In your code where you do the rendering you'll have to pass a UV-Coordinate to every vertex you pass to the pipeline to tell GL how to map the image onto the vertex.
Imagine this:


and use glTexCoord2f(s,t) and pass the coordinates to gl.

Nehe has good examples for mapping: http://nehe.gamedev.net/tutorial/texture_mapping/12038/

Bye =).

Edit:

Transparency is very tricky to do right because you have to be very cautious to order your vertices from the most far to the closest one.
But a quick answer would be:
Code: [Select]
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
« Last Edit: January 21, 2018 by Knurz »
Remember what the dormouse said: Feed your head

Offline ViL

  • Avocado lover 🥑
  • C= 64
  • **
  • Posts: 52
  • Karma: 1
    • View Profile
hiii, Knurz! first of all i am mindblowed about the amount of detail you put on your help, massive K++ for that! :D

i started to test PicoLodePNG right after you posted it, unfortunately i couldn't compile any of the examples there in Code::Blocks with the GNU GCC Compiler either .cpp files with the g++ option nor .c files with the gcc option, so i couldn't make it run

i also seek for other examples around the web and couldn't figure them out; my intro has .c extension so i can't #include <iostream> since that's exclusive for the g++ compiler; and using it makes it throw thousands of warnings LOL so i must use a .c file for it aka compile it with the gcc option

i understood how everything else worked! :D i am just stuck in loading a image with PicoLodePNG in my main.c from the hdd and set it to "myTexture" for instance x3

any help is very appreciated! thanks a lot, beforehand!~ =' D

Offline Knurz

  • C= 64
  • **
  • Posts: 99
  • Karma: 24
    • View Profile
Hi!

You're very welcome =).

If you're using ANSI-C you could use https://github.com/elanthis/upng UPNG.

UPNG compiles without any prerequisites with gcc:
Code: [Select]
majortom@vdr:~/coding/c/upng/upng$ gcc -c upng.c -o upng.o
majortom@vdr:~/coding/c/upng/upng$ echo $?
0

Here's an example (png = compressed PNG, pngsize=size in Bytes of png):
Code: [Select]
GLuint createTexturefromPNG (unsigned char *png, size_t pngsize, GLint filter) {
GLuint texture = 0;
upng_t *pngt;
unsigned int format = 0;

glGenTextures(1, &texture);

if (!texture) return (texture);

pngt = upng_new_from_bytes(png, pngsize);

upng_decode(pngt);

if ( (upng_get_error(pngt) != UPNG_EOK) || (!texture) || (!pngt) ) {
if (pngt) upng_free(pngt);
return (0);
}

format = upng_get_format(pngt);

glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, format == UPNG_RGB8 ? GL_RGB : GL_RGBA, upng_get_width(pngt), upng_get_height(pngt), \
0, format == UPNG_RGB8 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, upng_get_buffer(pngt));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glBindTexture(GL_TEXTURE_2D, 0);

upng_free(pngt);

return (texture);
}

This only supports RGB and RGBA Images - no other fancy stuff.

What I forgot to mention in my first reply is that you have to glBindTexture(GL_TEXTURE_2D, <your_texture_id>); before rendering your object.

Bye!
Remember what the dormouse said: Feed your head

Offline ViL

  • Avocado lover 🥑
  • C= 64
  • **
  • Posts: 52
  • Karma: 1
    • View Profile
OMG this works like a charm! :D you are amazing! +O+ thanks you so much! =' D K++ aren't enough, you deserve an spot on the intro greetings! x3

now it shows a nice snowflake on the screen! x3
https://i.imgur.com/Etbc5XE.png

made some modifications on the code BUT after some messing around trying to use a second snowflake texture, i couldn't find my way to use other texture than the first, this is the code:
https://pastebin.com/raw/GSc8fZvu

how can i set another texture id? =' 3 it is the only thing left to beat to actually have everything that is left on the intro! x3 and my bad for asking too much :c i effort on make my "homework" before asking anything, and really have a hard time figuring out this, i'll appreciate any idea!~ x3

Offline Knurz

  • C= 64
  • **
  • Posts: 99
  • Karma: 24
    • View Profile
I'm glad it worked! (greetings are always appreciated :D)

If you want to use different textures in your project, just load another file with UPNG and do the stuff you did with the first texture again(glgentextures, glbindtexture, glteximage2d...) but with the 2nd texture to upload it to your GPU.  After that, you can simply switch the current texture by using glBindTexture with the new texture-id again:

Code: [Select]
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
  glTexCoord2f(0.0, 0.0);   glVertex2f(-0.3f,   0.3f);
glTexCoord2f(1.0, 0.0);   glVertex2f(0.3f,  0.3f);
glTexCoord2f(1.0, 1.0);   glVertex2f(0.3f, -0.3f);
glTexCoord2f(0.0, 1.0);   glVertex2f(-0.3f, -0.3f);
glEnd();

glBindTexture(GL_TEXTURE_2D, texture_2);
glBegin(GL_QUADS);
  glTexCoord2f(0.0, 0.0);   glVertex2f(-0.3f,   0.3f);
glTexCoord2f(1.0, 0.0);   glVertex2f(0.3f,  0.3f);
glTexCoord2f(1.0, 1.0);   glVertex2f(0.3f, -0.3f);
glTexCoord2f(0.0, 1.0);   glVertex2f(-0.3f, -0.3f);
glEnd();

Just be sure that you don't mess around with texture within your glbegin...glend block, this would probably result in an error.

Something to consider in your project..because I saw it in your code.. you're calling glBindTexture(...) twice. First you do the preparations for the texture, then you bind it again. This isn't necessary, because GL is a "state machine", everything you set stays in it's state until you change it. You're calling glPushMatrix() and glPopMatrix() without doing any matrix operations within it's logical block.  (I'm just saying because GL calls are limited and expensive)

Happy coding! =)
Remember what the dormouse said: Feed your head

Offline ViL

  • Avocado lover 🥑
  • C= 64
  • **
  • Posts: 52
  • Karma: 1
    • View Profile
Hiii, Knurz! :D you are a wizard! +O+

everything works amazingly now, i never though i could get to this point; and it, as well as this intro would never be without all your kindness and help! =' D
https://i.imgur.com/ajA3hHG.png

now i got to implement it on the almost done intro, also a greetings is the least you deserve for being such a hero :)
all the K++! \o/

btw thanks about the glBindTexture hint! x3 and about the glPush and Pop Matrix it was a leftover since i though about using glTranslate on two quads! x3

also i'll link the intro + source code here once it's done!~ :D and once more; thanks a lot for everything, Knurz! =' D

Offline Knurz

  • C= 64
  • **
  • Posts: 99
  • Karma: 24
    • View Profile
Hi!

Oh no you're giving me too much attention =). Glad I could help and thanks that you will release the source!

Remember what the dormouse said: Feed your head