テクスチャはポリゴンに貼るが、そのポリゴンの色が何色かで張り付けた結果に違いが出る。
以下は、テクスチャを一枚用意し、それをglColor3dでポリゴンの色を指定した上に張り付けた結果。
//描画関数 void disp(void) { glViewport(0, 0, winwidth, winheight); glClearColor(0.2, 0.2, 0.2, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_CULL_FACE); double v = 0.95;
//下地の色を設定 glColor3d(1, 0, 0);
//テクスチャを有効化 glBindTexture(GL_TEXTURE_2D, texname); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2d(0, 1); glVertex2d(-v, -v); glTexCoord2d(1, 1); glVertex2d(v, -v); glTexCoord2d(1, 0); glVertex2d(v, v); glTexCoord2d(0, 0); glVertex2d(-v, v); glEnd(); glFlush(); }
glActiveTextureを使うと、下地の色用のテクスチャと、張り付けたい画像のテクスチャを同時に指定できる。「同時に指定できる」とはつまり、普通glBindTextureを一度実行したらほかのテクスチャは無効になるが、glActiveTextureを使えば二つのglBindTextureを有効にできるという意味。
OpenGLにはテクスチャスロットのような概念がある。
glActiveTexture(GL_TEXTURE0);
で、「これからスロット名"GL_TEXTURE0"の設定をする」という意味になる。
そして、一つのスロットで一度に使えるテクスチャは一枚だけで、これは「最後にglBindTextureで指定したテクスチャ」だが、一度に複数のスロットを使えるので、各スロットで glEnable(GL_TEXTURE_2D)でそのスロットを有効にしてやれば、テクスチャを複数使うことができる。
#include <iostream> #include <Windows.h> #include <gl/glew.h>// glActiveTextureに必要 #include <gl/GL.h> #include <gl/GLU.h> #include <gl/freeglut.h> #pragma comment(lib,"glew32.lib") #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" // freeglut: // http://freeglut.sourceforge.net/ //ウィンドウの幅と高さ int winwidth, winheight; GLuint texname_img; GLuint texname_block;
//下地用のテクスチャ void init_tex_block() { unsigned char pixels[] = { 255, 0, 0, 0,255, 0, 0, 0,255, 255,255,255 }; glGenTextures(1, &texname_block); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texname_block); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); }
//画像読み込み,テクスチャとしてロード //pngの読み込みに STBライブラリを使用 //https://suzulang.com/stb-library-image-read/ //https://github.com/nothings/stb void init_tex_img() { unsigned char* pixels; int bpp; int imgwidth; int imgheight; // ファイルを読み込み、画像データを取り出す // 最後の引数でピクセルあたりのバイト数を強制できる pixels = stbi_load(R"(C:\Users\szl\Desktop\bird-1232416_640.png)", &imgwidth, &imgheight, &bpp, 0); glGenTextures(1, &texname_img); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texname_img); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, imgwidth, imgheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels ); // メモリ上の画像データを破棄 stbi_image_free(pixels); }
//描画関数 void disp(void) { glViewport(0, 0, winwidth, winheight); glClearColor(0.2, 0.2, 0.2, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_CULL_FACE); double v = 0.95;
glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,texname_block);
glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texname_img);
glBegin(GL_QUADS); glMultiTexCoord2f(GL_TEXTURE0, 0, 1); glMultiTexCoord2f(GL_TEXTURE1, 0, 1); glVertex2d(-v, -v); glMultiTexCoord2f(GL_TEXTURE0, 1, 1); glMultiTexCoord2f(GL_TEXTURE1, 1, 1); glVertex2d(v, -v); glMultiTexCoord2f(GL_TEXTURE0, 1, 0); glMultiTexCoord2f(GL_TEXTURE1, 1, 0); glVertex2d(v, v); glMultiTexCoord2f(GL_TEXTURE0, 0, 0); glMultiTexCoord2f(GL_TEXTURE1, 0, 0); glVertex2d(-v, v); glEnd(); glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); glFlush(); } //ウィンドウサイズの変化時に呼び出される void reshape(int w, int h) { winwidth = w; winheight = h; disp(); } //エントリポイント int main(int argc, char** argv) { glutInit(&argc, argv); glutInitWindowPosition(100, 50); glutInitWindowSize(640, 480); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutCreateWindow("sample"); glutDisplayFunc(disp); glutReshapeFunc(reshape); glewInit(); init_tex_img(); init_tex_block(); glutMainLoop(); return 0; }