OpenGL 개발 셋팅 할때 헤드(.h)파일 Lib파일 모두 적용해보고
아래 프로그램 OpenGL Extensions Viewer 가 잘 잘동되는지 확인해 보자
OpenGL Extensions Viewer 설치 링크
http://realtech-vr.com/admin/glview
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FreeImage 를 OpenGL에서 이미지 로드하기 전에 알아두어야 할것
각각 OS 의 바이트 순서에 따라 칼라값을 읽는 순서가 다르다!
(윈도우, 애플(OSX), 리눅스 등등)
little-endian -> BGR
big-endian -> RGB
test(...)
{
...
FREE_IMAGE_FORMAT format = FreeImage_GetFileType(filename.c_str(), 0);
FIBITMAP *bitmap = FreeImage_Load(format, filename.c_str());
m_w = FreeImage_GetWidth(pBitmap);
m_h = FreeImage_GetHeight(pBitmap);
bit = FreeImage_GetBPP(m_pBitmap);
...
...
//아래와 같은 식으로 두었다면 특정 OS에 따라 색깔이 맞게 않나올수도 있다.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_w, m_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)FreeImage_GetBits(m_pBitmap));
//아래와 같은 식으로 두었다면 특정 OS에 맞게 바꾸어준다.
unsigned int glBit = GL_RGBA;
if (FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR)
{
if( bit == 24) //24비트
{
//24비트 BGR 알파값X
glBit = GL_BGR;
}
else if( bit == 32) //32비트
{
//32비트 BGR 알파값포함 값
glBit = GL_BGRA;
}
}
else if (FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB)
{
if( bit == 24) //24비트
{
//24비트 RGB 알파값X
glBit = GL_RGB;
}
else if( bit == 32) //32비트
{
//32비트 RGB 알파값포함 값
glBit = GL_RGBA;
}
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_w, m_h, 0, glBit , GL_UNSIGNED_BYTE, (GLvoid*)FreeImage_GetBits(m_pBitmap));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: https://stackoverflow.com/questions/31103121/why-freeimage-loads-image-in-bgr-format
I write game using Android NDK and FreeImage library to load images into my game. It loads images in BGR format. It is possible to load in RGB format? Or I need to swap R and B components manualy? Edited My device is Samsung Galaxy S4(armv7 archtecture). Here is code` FIMEMORY* fiStream = FreeImage_OpenMemory((BYTE*)data, size);
FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(fiStream);
if (FreeImage_FIFSupportsReading(fif))
{
dib = FreeImage_LoadFromMemory(fif, fiStream, 0);
}
if (!dib)
return;
data_ = FreeImage_GetBits(dib);
width_ = FreeImage_GetWidth(dib);
height_ = FreeImage_GetHeight(dib);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width_, height_, 0, GL_RGB, GL_UNSIGNED_BYTE, data_ );
| | asked Jun 28 '15 at 18:12 |
|
| |
| FreeImage actually doesn't neccessarily use BGR(A) ordering. Section "Pixel access functions" in the FreeImage documentation contains the following statement (emphasis mine): However, the pixel layout used by this model is OS dependant. Using a byte by byte memory order to label the pixel layout, then FreeImage uses a BGR[A] pixel layout under a Little Endian processor (Windows, Linux) and uses a RGB[A] pixel layout under a Big Endian processor (Mac OS X or any Big Endian Linux / Unix). This choice was made to ease the use of FreeImage with graphics API. This subtle difference is however transparent to the user. In order to make pixel access OS independent, FreeImage defines a set of macros used to set or get individual color components in a 24- or 32-bit DIB.
However, these macros will not help you when you want to use FreeImage's raw pixel data as source for OpenGL. But I don't know what your issue with this is. OpenGL will accept BGR(A) as well as RGB(A) as image data. And actually, FreeImage's choice is not bad, as BGR(A) is most likely the native data format on such platforms, so that using this format represents the most efficient way to transfer image data. | answered Jun 29 '15 at 19:40 |
|
| |
| FreeImage can be built to always load in RGB order independent of the architecture. Use #define FREEIMAGE_COLORORDER=FREEIMAGE_COLORORDER_RGB. If you're using Android.mk to build FreeImage, add the following line to it: LOCAL_CPPFLAGS += -DFREEIMAGE_COLORORDER=FREEIMAGE_COLORORDER_RGB
Documentation for this can be found in Source/FreeImage.h if you search for FREEIMAGE_COLORORDER: Color-Order: The specified order of color components red, green and blue affects 24- and 32-bit images of type FIT_BITMAP as well as the colors that are part of a color palette. All other images always use RGB order. By default, color order is coupled to endianness: little-endian -> BGR big-endian -> RGB However, you can always define FREEIMAGE_COLORORDER to any of the known orders FREEIMAGE_COLORORDER_BGR (0) and FREEIMAGE_COLORORDER_RGB (1) to specify your preferred color order.
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32비트 알파채널 추가 이미지 투명 설정하기
/////////////////////////////////////////////////////////
//{alpha Blend 알파가 추가된 32비트 이미지, 투명처리 반영
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//}
////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
//{위의 옵션이 추가된 상황에서 이미지가 겹칠때 뚫린 부분에 서로 이미지가 마스크되어 보일려면 아래와 같이 필요하다
glTexEnvf(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDepthMask(GL_FALSE);
//}
////////////////////////////////////////////////////////
//즉 아래와 같이 옵션을 해주면 32비트 알파이미지가 겹쳐도 뚫린곳으로 서로 보이게끔 설정이 된다.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDepthMask(GL_FALSE);
이렇게 추가된 부분을 보면 된다.
아래 스크롤되는 코드를 보면 위와같이 코드부분추가한 부분을 보면 이해가 될 것이다.
출처: https://www.opengl.org/discussion_boards/showthread.php/165638-Texture-transparency-problems
Texture transparency problems
No matter what I try, I can't get the transparent pixels to actually be transparent.
I'm initializing with these:
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
glEnable(GL_TEXTURE_2D)
glEnable(GL_ALPHA_TEST)
glAlphaFunc(GL_GREATER,0.4)
glEnable(GL_BLEND)
glColor4f(1.0,1.0,1.0,1.0)
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
And initializing textures with this:
glBindTexture(GL_TEXTURE_2D, each.index)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, each.w, each.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, each.image)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
But no matter what the alpha values are, the output screen is the same.
----------------------------------------------------------------------------------------------------------------------------------------------------------------
xture transparency problems
Ok, I have replaced the texture env mode from decal mode to modulate. So the transparency is not defined only by the image of the texture but also defined by the color of the quad just for testing purpose.
Here is my test code:
Code :
#include <iostream>
#include <vector>
#include <GL/glut.h>
void display(void);
void init(void);
void reshape(int w,int h);
GLuint texture_id;
int main(int argc,char **argv)
{
glutInit(&argc,argv);
glutInitWindowSize(512,512);
glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGBA);
glutCreateWindow("Transparency test");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
init();
glutMainLoop();
return(EXIT_SUCCESS);
}
/*---------------------------------------------------*/
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0,0.0,2.0,0.0,0.0,0.0,0.0,1.0,0.0);
glPushMatrix();
glDisable(GL_TEXTURE_2D);
glColor4f(1.0,1.0,1.0,1.0);
glTranslatef(-1.5,-1.5,-0.25);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-5.0,-5.0,0.0);
glVertex3f(5.0,-5.0,0.0);
glVertex3f(-5.0,5.0,0.0);
glVertex3f(5.0,5.0,0.0);
glEnd();
glPopMatrix();
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,texture_id);
/////////////////////////////////////////////////////////
//{위의 옵션이 추가된 상황에서 이미지가 겹칠때 뚫린 부분에 서로 이미지가
// 마스크되어 보일려면 아래와 같이 필요하다
glTexEnvf(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glDepthMask(GL_FALSE);
//}
////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
//{alpha Blend 알파가 추가된 32비트 이미지, 투명처리 반영
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//}
////////////////////////////////////////////////////////
glColor4f(1.0,1.0,1.0,0.5);//Replace this alpha for transparency
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0,0.0);
glVertex3f(-5.0,-5.0,0.0);
glTexCoord2f(1.0,0.0);
glVertex3f(5.0,-5.0,0.0);
glTexCoord2f(0.0,1.0);
glVertex3f(-5.0,5.0,0.0);
glTexCoord2f(1.0,1.0);
glVertex3f(5.0,5.0,0.0);
glEnd();
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
glPopMatrix();
glutSwapBuffers();
}
/*------------------------------------------------------*/
void init(void)
{
glEnable(GL_DEPTH_TEST);
std::vector<GLubyte> texel;
texel.push_back(255); texel.push_back(0); texel.push_back(0);texel.push_back(255);
texel.push_back(0); texel.push_back(255); texel.push_back(0);texel.push_back(255);
texel.push_back(0); texel.push_back(0);texel.push_back(255);texel.push_back(255);
texel.push_back(0); texel.push_back(255);texel.push_back(255);texel.push_back(255);
glEnable(GL_TEXTURE_2D);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glGenTextures(1,&texture_id);
glBindTexture(GL_TEXTURE_2D,texture_id);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
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,2,2,0,GL_RGBA,GL_UNSIGNED_BYTE,&texel[0]);
glDisable(GL_TEXTURE_2D);
}
/*-------------------------------------------------------*/
void reshape(int w,int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-5.0,5.0,-5.0,5.0,1.0,100.0);
glMatrixMode(GL_MODELVIEW);
}
This code work for me. But if it does not work for you, can you post a screen shot to see what happen.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://collagefactory.blogspot.kr/2009/10/opengl.html
OpenGL의 투명 효과
OpenGL은 translucent 또는 partially opaque primite들을 rendering하기 위한 직접적인 interface를 제공하지 않는다. 그러나 blend feature와 primitive data들의 조심스러운 순서 조작과 함께 transparency effect를 구현 할 수 있다. 또한 screen door transparency를 고려 할 수도 있을 것이다.
OpenGL application을 전형적으로 다음과 같은 방법으로 blending을 enable한다.
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
Blending이 enable된 후, 처리되는 primitive color는 framebuffer에 이미 저장되어 있는 color와 blending된다. glBlendFunc()은 어떻게 blending할 것인가를 결정한다. 위의 전형적인 예제는 현재 입력된 color를 그것의 alpha value와 1 - 입력되는 alpha value로 최종 color를 수정한다. 이 두 color의 합은 다시 framebuffer에 쓰여진다.
Primitive의 opaicty는 glColor4*()를 사용하여 설정한다. RGB는 color를 설정하고, alpha parameter는 opacity를 결정한다.
Depth buffering을 사용할 경우, primitives를 rendering하는 순서에 주의를 기울일 필요가 있다. 완벽한 opaque primitives는 가장 먼저 rendering 될 필요가 있으며, 다음은 부분적으로 opaque한 primiteves들이 뒤에서 앞으로 rendering될 필요가 있다. 만약 이런 순서로 rendering하지 않는다면, 부분적으로 opaque한 primitive를 통해 보여지는 primitive들은 그들이 depth test를 모두 잃을 수 있다.
For more information:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://stackoverflow.com/questions/4153055/how-to-load-jpg-png-textures-in-an-sdl-opengl-app-under-osx
Take a look at freeimage. It supports all major formats and is easily built with macports. Nice to work with as well. Auto-detects image format etc.
GLuint m_mpTextures;
FREE_IMAGE_FORMAT format = FreeImage_GetFileType(filename.c_str(), 0);
FIBITMAP *bitmap = FreeImage_Load(format, filename.c_str());
if (!bitmap)
{
LOG_ERROR("Unable to load texture: " + filename);
return false;
}
mlWidth = FreeImage_GetWidth(bitmap);
mlHeight = FreeImage_GetHeight(bitmap);
glGenTextures(1, &m_mpTextures);
glBindTexture(GL_TEXTURE_2D, m_mpTextures);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
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, GL_RGBA, mlWidth, mlHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE,
(GLvoid*)FreeImage_GetBits(bitmap));
FreeImage_Unload(bitmap);
출처: http://202psj.tistory.com/1031 [알레폰드의 IT 이모저모]
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://m.blog.naver.com/jungwan82/20108510997
텍스쳐를 렌더링 하기 위해서는 다양한 포맷의 이미지를 프로그램 내에서 다룰 수 있어야 하는데요 이 일을 해주는 좋은 라이브러리가 있습니다. 라이브러리 이름은 FreeImage Library입니다. 아래의 주소에서 다운 받으실 수 있습니다.
http://freeimage.sourceforge.net/
.lib파일은 Visual C++ 디렉토리에 추가해주시면 되고요, .dll파일은 .vcproj가 존재하는 프로젝트 디렉토리로 옮기시거나 windows\system32 디렉토리에 카피해 넣으셔도 됩니다.
이제, 이미지 파일을 다루는 것은 FreeImage가 담당해 줄테고, 우리는 그 이미지를 Geometry에 그려넣는 방법만 살펴보면 되겠습니다. FreeImage 라이브러리의 OpenGL 예제 코드에 보면 TextureManager라는 클래스가 있습니다. 이 파일을 프로젝트 폴더로 옮깁니다. 이제 이 클래스의 도움을 받아서 텍스쳐를 아래와 같은 방법으로 만듭니다.
TextureManager::Inst()->LoadTexture("glories_tudorica_big.jpg", 0);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
LoadTexture()는 명시된 파일을 읽어드려서 그래픽 카드에 등록시켜줍니다. 이미지가 만들어 진 후에는 반드시 필터링 방법을 설정해 주어야 합니다. 만약 이 과정을 생략하면 절대 렌더링 되지 않습니다. 아마도 OpenGL에 디폴트 처리가 되어 있지 않은 것 같습니다.
Direct3D에 UV를 OpenGL에서는 ST라고 부릅니다. 아래와 같이 ST 데이타를 정의합니다.
float fSTs[] = {0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f};
이제, 버퍼의 수를 하나 늘립니다. ST 값을 저장하기 위함이죠.
다음으로 ST 데이타를 새로 만들어진 버퍼로 보냅니다.
glBindBuffer(GL_ARRAY_BUFFER, m_BOs[2]);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), fSTs, GL_STATIC_DRAW);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(2);
이제, 셰이더 코드를 고칠 차레인데요. 먼저 정점 셰이더를 아래와 같이 수정합니다.
#version 150
in vec2 in_Position;
in vec3 in_Color;
in vec2 in_ST;
out vec3 ex_Color;
out vec2 ex_ST;
void main(void)
{
gl_Position = vec4(in_Position, 0.0f, 1.0f);
ex_Color = in_Color;
ex_ST = in_ST;
}
in_ST 가 입력 값으로 추가 된 것을 보실 수 있으실 겁니다. ex_ST역시 출력값으로 추가되었습니다. 다른 변화는 inPosition 변수의 타입이 vec3에서 vec2로 변경되었습니다. 왜냐하면 이 예제에서는 Z값을 사용할 필요하지 않았기 때문입니다. in_Position을 vec2로 변경하였기 때문에 vertex attribute pointer함수의 인자도 이에 따라서 변경해 주어야합니다. 아래 처럼요.
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2번째 인자가 3에서 2로 변경되었습니다.
이제, 프라그먼트 셰이더를 수정합니다.
#version 150
uniform sampler2D myTexture;
in vec3 ex_Color;
in vec2 ex_ST;
out vec4 out_Color;
void main(void)
{
vec4 texcolor = texture(myTexture, ex_ST);
out_Color = texcolor + vec4(ex_Color,1.0);
}
sampler2D for our texture텍스쳐 샘플러 sampler2D가 선언되었고 ex_ST가 추가 입력값으로 추가되었습니다. 가장 중요한 부분이 outColor의 값을 결정하는 부분인데요, 텍스쳐 값과 정점의 색상을 더한 값을 출력 값으로 하고 있습니다.
이제 셰이더는 제쳐두고, 프로그램내의 그리기 코드를 살펴보겠습니다.
void CTriangle::Draw()
{
glUseProgram(m_Program);
glBindVertexArray(m_VAO);
TextureManager::Inst()->BindTexture(0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
한 가지가 변했는데요 그리기 전에 BindTexture함수를 호출해 준 것입니다.
결과는 아래 그림과 같습니다.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: https://r3dux.org/2014/10/how-to-load-an-opengl-texture-using-the-freeimage-library-or-freeimageplus-technically/
The loadTexture Method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | // Method to load an image into a texture using the freeimageplus library. Returns the texture ID or dies trying. GLuint loadTexture(string filenameString, GLenum minificationFilter = GL_LINEAR, GLenum magnificationFilter = GL_LINEAR) { // Get the filename as a pointer to a const char array to play nice with FreeImage const char* filename = filenameString.c_str(); // Determine the format of the image. // Note: The second paramter ('size') is currently unused, and we should use 0 for it. FREE_IMAGE_FORMAT format = FreeImage_GetFileType(filename , 0); // Image not found? Abort! Without this section we get a 0 by 0 image with 0 bits-per-pixel but we don't abort, which // you might find preferable to dumping the user back to the desktop. if (format == -1) { cout << "Could not find image: " << filenameString << " - Aborting." << endl; exit(-1); } // Found image, but couldn't determine the file format? Try again... if (format == FIF_UNKNOWN) { cout << "Couldn't determine file format - attempting to get from file extension..." << endl; // ...by getting the filetype from the filename extension (i.e. .PNG, .GIF etc.) // Note: This is slower and more error-prone that getting it from the file itself, // also, we can't use the 'U' (unicode) variant of this method as that's Windows only. format = FreeImage_GetFIFFromFilename(filename); // Check that the plugin has reading capabilities for this format (if it's FIF_UNKNOWN, // for example, then it won't have) - if we can't read the file, then we bail out =( if ( !FreeImage_FIFSupportsReading(format) ) { cout << "Detected image format cannot be read!" << endl; exit(-1); } } // If we're here we have a known image format, so load the image into a bitap FIBITMAP* bitmap = FreeImage_Load(format, filename); // How many bits-per-pixel is the source image? int bitsPerPixel = FreeImage_GetBPP(bitmap); // Convert our image up to 32 bits (8 bits per channel, Red/Green/Blue/Alpha) - // but only if the image is not already 32 bits (i.e. 8 bits per channel). // Note: ConvertTo32Bits returns a CLONE of the image data - so if we // allocate this back to itself without using our bitmap32 intermediate // we will LEAK the original bitmap data, and valgrind will show things like this: // // LEAK SUMMARY: // definitely lost: 24 bytes in 2 blocks // indirectly lost: 1,024,874 bytes in 14 blocks <--- Ouch. // // Using our intermediate and cleaning up the initial bitmap data we get: // // LEAK SUMMARY: // definitely lost: 16 bytes in 1 blocks // indirectly lost: 176 bytes in 4 blocks // // All above leaks (192 bytes) are caused by XGetDefault (in /usr/lib/libX11.so.6.3.0) - we have no control over this. // FIBITMAP* bitmap32; if (bitsPerPixel == 32) { cout << "Source image has " << bitsPerPixel << " bits per pixel. Skipping conversion." << endl; bitmap32 = bitmap; } else { cout << "Source image has " << bitsPerPixel << " bits per pixel. Converting to 32-bit colour." << endl; bitmap32 = FreeImage_ConvertTo32Bits(bitmap); } // Some basic image info - strip it out if you don't care int imageWidth = FreeImage_GetWidth(bitmap32); int imageHeight = FreeImage_GetHeight(bitmap32); cout << "Image: " << filenameString << " is size: " << imageWidth << "x" << imageHeight << "." << endl; // Get a pointer to the texture data as an array of unsigned bytes. // Note: At this point bitmap32 ALWAYS holds a 32-bit colour version of our image - so we get our data from that. // Also, we don't need to delete or delete[] this textureData because it's not on the heap (so attempting to do // so will cause a crash) - just let it go out of scope and the memory will be returned to the stack. GLubyte* textureData = FreeImage_GetBits(bitmap32); // Generate a texture ID and bind to it GLuint tempTextureID; glGenTextures(1, &tempTextureID); glBindTexture(GL_TEXTURE_2D, tempTextureID); // Construct the texture. // Note: The 'Data format' is the format of the image data as provided by the image library. FreeImage decodes images into // BGR/BGRA format, but we want to work with it in the more common RGBA format, so we specify the 'Internal format' as such. glTexImage2D(GL_TEXTURE_2D, // Type of texture 0, // Mipmap level (0 being the top level i.e. full size) GL_RGBA, // Internal format imageWidth, // Width of the texture imageHeight, // Height of the texture, 0, // Border in pixels GL_BGRA, // Data format GL_UNSIGNED_BYTE, // Type of texture data textureData); // The image data to use for this texture // Specify our minification and magnification filters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minificationFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magnificationFilter); // If we're using MipMaps, then we'll generate them here. // Note: The glGenerateMipmap call requires OpenGL 3.0 as a minimum. if (minificationFilter == GL_LINEAR_MIPMAP_LINEAR || minificationFilter == GL_LINEAR_MIPMAP_NEAREST || minificationFilter == GL_NEAREST_MIPMAP_LINEAR || minificationFilter == GL_NEAREST_MIPMAP_NEAREST) { glGenerateMipmap(GL_TEXTURE_2D); } // Check for OpenGL texture creation errors GLenum glError = glGetError(); if(glError) { cout << "There was an error loading the texture: "<< filenameString << endl; switch (glError) { case GL_INVALID_ENUM: cout << "Invalid enum." << endl; break; case GL_INVALID_VALUE: cout << "Invalid value." << endl; break; case GL_INVALID_OPERATION: cout << "Invalid operation." << endl; default: cout << "Unrecognised GLenum." << endl; break; } cout << "See https://www.opengl.org/sdk/docs/man/html/glTexImage2D.xhtml for further details." << endl; } // Unload the 32-bit colour bitmap FreeImage_Unload(bitmap32); // If we had to do a conversion to 32-bit colour, then unload the original // non-32-bit-colour version of the image data too. Otherwise, bitmap32 and // bitmap point at the same data, and that data's already been free'd, so // don't attempt to free it again! (or we'll crash). if (bitsPerPixel != 32) { FreeImage_Unload(bitmap); } // Finally, return the texture ID return tempTextureID; } |
Usage
To use the method, just set up your code something like this – in your main .cpp file at the top have:
| #include <iostream> #include <cstdlib> // OpenGL/GLEW/GLFW/SDL/Whatever headers // Include the FreeImagePlus library (don't forget to link your project to the .so/.a or to the lib/dll on Windows) #include <FreeImagePlus.h> using std::string; using std::cout; using std::endl; // Create a handle for our texture GLuint textureID; |
In your initialisation/setup method add something like this:
| // ----- Initialise the FreeImage library ----- // Note: Flag is whether we should load ONLY local (built-in) libraries, so // false means 'no, use external libraries also', and 'true' means - use built // in libs only, so it's like using the library as a static version of itself. FreeImage_Initialise(true); |
In your main method, once you’ve create an OpenGL context (i.e. window) and called your initialise/setup method, then you can load a texture to use like this:
| // Load an image and bind it to a texture textureID = loadTexture("TestImage.png"); // Or load an image using trilinear filtering via mipmaps for minification and GL_LINEAR (the method's default) for magnification textureID = loadTexture("TestImage.png", GL_LINEAR_MIPMAP_LINEAR); // Or load an image using low quality mipmaps for minification and GL_NEAREST for magnification. // The point is that you can set the minification and magnification parameters separately, not necessarily that you'd choose these interpolation options. textureID = loadTexture("TestImage.png", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST); |
Finally, on shutdown you may (optionally, as long as you’re not using the Linux/Mac .a version of the library) like to add the following:
| // As we're using a .so version of the freeimageplus library on Linux we // don't need to call DeInitialise (we would only really HAVE to do so on Linux // or Mac [not Windows!] when using the .a version) - but it doesn't hurt to do it anyway. FreeImage_DeInitialise(); |
Wrap-up
Not a great deal to say – it works, it should be relatively robust, it doesn’t leak memory (or at least none that we control), and the code is commented to the hilt and explains why it’s doing things instead of just what it’s doing (some people don’t like verbose code like this – but I teach a lot of programming so I just try to explain everything as clearly as possible as I go – and find I prefer it to ‘terse’ code that I have no idea WTF it’s up to or why it’s bothering).
Many thanks to the FreeImage devs for the library – it’s rather feature-packed and I quite like it (some good example code wouldn’t go amiss though!) =D
Hope you find the code useful! (Bugs? Comments? Suggestions? Feedback always welcome!).
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: https://www.opengl.org/discussion_boards/showthread.php/164502-freeImage-example-code
freeImage example code
Anyone know where I can find a good example of how to use FreeImage with OpenGL? I want to use FreeImage to load any image file it supports to an OpenGL texture.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Re: freeImage example code
I've post before about that, look at the end of this thread:
http://www.opengl.org/discussion_boards/...3307#Post233307
It's good to make a search in this forums before make a question, just use the right side panel.
Good luck, bye
http://www.raul-art.blogspot.com
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Certainly not ! why would you want to _always_ swizzle your texture accesses just because of a small hypothetical performance hit for the texture creation...
Moreover you can tell OpenGL that your data is in BGRA format ::
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, w, h, 0, GL_BGRA,GL_UNSIGNED_BYTE,(GLvoid*)textura )
Cheers
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
I tried using your code RGHP for loading a texture using freeImage. It only work with standard opengl image size. I am trying to load an image that is 39x35. Is there a way I can copy that image to a standard opengl image size with transparency for the new image.
Code :
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <SDL\SDL.h>
#include <fmod.hpp>
#include <FreeImage.h>
//The attributes of the screen
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
//The surfaces that will be used
SDL_Surface *screen = NULL;
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glViewport(0, 0, Width, Height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
}
/* The main drawing function. */
int main( int argc, char* args[] )
{
//Initialize all SDL subsystems
if( SDL_Init(SDL_INIT_VIDEO) != 0 )
{
return 1;
}
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
//Set up the screen
screen = SDL_SetVideoMode( 640, 480, 32, SDL_OPENGL);
//If there was an error in setting up the screen
if( screen == NULL )
{
return 1;
}
//Set the window caption
SDL_WM_SetCaption( "Hello World", NULL );
/*
FMOD::System *system;
FMOD::System_Create(&system);
system->init(100, FMOD_INIT_NORMAL, 0);
FMOD::Sound *sound;
system->createStream("music.mp3", FMOD_DEFAULT, 0, &sound);
FMOD::Channel *channel;
system->playSound(FMOD_CHANNEL_FREE, sound, false, &channel);
*/
InitGL(640, 480);
FREE_IMAGE_FORMAT formato = FreeImage_GetFileType("image.png",0);//Automatocally detects the format(from over 20 formats!)
FIBITMAP* imagen = FreeImage_Load(formato, "image.png");
FIBITMAP* temp = imagen;
imagen = FreeImage_ConvertTo32Bits(imagen);
FreeImage_Unload(temp);
int w = FreeImage_GetWidth(imagen);
int h = FreeImage_GetHeight(imagen);
//cout<<"The size of the image is: "<<textureFile<<" es "<<w<<"*"<<h<<endl; //Some debugging code
GLubyte* textura = new GLubyte[4*w*h];
char* pixeles = (char*)FreeImage_GetBits(imagen);
//FreeImage loads in BGR format, so you need to swap some bytes(Or use GL_BGR).
for(int j= 0; j<w*h; j++){
textura[j*4+0]= pixeles[j*4+2];
textura[j*4+1]= pixeles[j*4+1];
textura[j*4+2]= pixeles[j*4+0];
textura[j*4+3]= pixeles[j*4+3];
//cout<<j<<": "<<textura[j*4+0]<<"**"<<textura[j*4+1]<<"**"<<textura[j*4+2]<<"**"<<textura[j*4+3]<<endl;
}
//Now generate the OpenGL texture object
GLuint texturaID;
glGenTextures(1, &texturaID);
glBindTexture(GL_TEXTURE_2D, texturaID);
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_NEAREST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-3.0f,0.0f,-6.0f);
glBegin (GL_QUADS);
glTexCoord2f (0.0, 0.0);
glVertex3f (0.0, 0.0, 0.0);
glTexCoord2f (1.0, 0.0);
glVertex3f (1.0, 0.0, 0.0);
glTexCoord2f (1.0, 1.0);
glVertex3f (1.0, 1.0, 0.0);
glTexCoord2f (0.0, 1.0);
glVertex3f (0.0, 1.0, 0.0);
glEnd ();
SDL_GL_SwapBuffers();
int done = 0;
while ( ! done ) {
/* This could go in a separate function */
{ SDL_Event event;
while ( SDL_PollEvent(&event) ) {
if ( event.type == SDL_QUIT ) {
done = 1;
}
if ( event.type == SDL_KEYDOWN ) {
if ( event.key.keysym.sym == SDLK_ESCAPE ) {
done = 1;
}
}
}
}
}
//Quit SDL
SDL_Quit();
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://stackoverflow.com/questions/4153055/how-to-load-jpg-png-textures-in-an-sdl-opengl-app-under-osx
i am writing an SDL / OpenGL application that runs under OSX. I have to use existing code which uses the DevIL library for loading JPG and PNG textures. Unfortunately, this works very bad under OS X, so i decided not to use DevIL at all, and rewrite the respective parts of the application using another library. I want to keep it flexible (DevIL can handle a lot of image formats) and easy to use. Is there a good replacement for DevIL that you can recommend? The application is entirely written in C++.
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Take a look at freeimage. It supports all major formats and is easily built with macports. Nice to work with as well. Auto-detects image format etc.
GLuint m_mpTextures;
FREE_IMAGE_FORMAT format = FreeImage_GetFileType(filename.c_str(), 0);
FIBITMAP *bitmap = FreeImage_Load(format, filename.c_str());
if (!bitmap)
{
LOG_ERROR("Unable to load texture: " + filename);
return false;
}
mlWidth = FreeImage_GetWidth(bitmap);
mlHeight = FreeImage_GetHeight(bitmap);
glGenTextures(1, &m_mpTextures);
glBindTexture(GL_TEXTURE_2D, m_mpTextures);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
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, GL_RGBA, mlWidth, mlHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE,
(GLvoid*)FreeImage_GetBits(bitmap));
FreeImage_Unload(bitmap);
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
If you're on Mac OS anyway, why not just use CGImageSource to do the loading? OS X natively supports loading many file formats including PNG and JPEG.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Runnable SDL 2 example
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
int main(void) {
SDL_Event event;
SDL_Renderer *renderer = NULL;
SDL_Texture *texture = NULL;
SDL_Window *window = NULL;
SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(
COMMON_WINDOW_WIDTH, COMMON_WINDOW_WIDTH,
0, &window, &renderer
);
IMG_Init(IMG_INIT_PNG);
texture = IMG_LoadTexture(renderer, "flower.png");
common_fps_init();
while (1) {
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
common_fps_update_and_print();
if (SDL_PollEvent(&event) && event.type == SDL_QUIT)
break;
}
SDL_DestroyTexture(texture);
IMG_Quit();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
Compiled with:
sudo apt-get install libsdl2-dev libsdl2-image-dev
gcc -std=c99 main.c -lSDL2 -lSDL2_image
on Ubuntu 16.10, SDL 2.0.4.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: https://solarianprogrammer.com/2013/05/17/opengl-101-textures/
The code for this post is on GitHub: https://github.com/sol-prog/OpenGL-101.
This is the third article from my OpenGL 101 series. In the first two articles we’ve seen how we can open a window and draw OpenGL primitives: points, lines and triangles. We’ve also seen how we can assign a particular color to a vertex and use this to paint a two-dimensional surface with a smooth color.
Suppose now that we want to draw something more complex like the ruins of an ancient building, think a bit about how we can draw something as close as possible to what we can see in the real world. Theoretically, we can model everything with triangles and calculate the colors corresponding to each vertex, but this quickly gets out of hand - we are limited by the memory of our graphics card and by the speed of our graphics processor. A much practical approach to create the illusion of reality is to use textures that can be glued on the geometrical representation of our computer world.
In this article, we will concern ourselves only with two-dimensional textures, OpenGL can use other type of textures: 1D, 3D, cube textures etc … Technically a texture is just a container for data, you can store any numerical values in a texture, usually color values, and process this data in your shaders, usually in the fragment shader.
Let’s start with something simple like reading an image from a file in a 2D texture and using the color information from this to paint a simple 2D surface - the square from ex_9, see the last article if you need to refresh your memory:
We say that a texture is composed of texels, for a 2D texture the texel space can be represented like in the next figure:
If we have an image data in our texture, the lower left corner of the image will be at (0, 0) and the upper right corner at (1, 1) in the (s, t) space. It is important to note that the image data, the pixel values, is layered in memory starting from the upper left corner to the right, and from the top to the bottom, using the C convention for storing an array in memory.
When we work with textures in OpenGL, we need to specify the texture coordinates, the position of the texture in the (s, t) space. If we want to map an image to a rectangle, we can use the next texture coordinates:
1 ...
2 // 1 square (made by 2 triangles) to be rendered
3 GLfloat vertices_position[8] = {
4 -0.5, -0.5,
5 0.5, -0.5,
6 0.5, 0.5,
7 -0.5, 0.5,
8 };
9
10 GLfloat texture_coord[8] = {
11 0.0, 0.0,
12 1.0, 0.0,
13 1.0, 1.0,
14 0.0, 1.0,
15 };
16
17 GLuint indices[6] = {
18 0, 1, 2,
19 2, 3, 0
20 };
21 ...
If you want to follow along, copy ex_9 from the previous article to ex_10 and add the texture_coord array in the intialize function, we’ll also need to remove/comment any code that uses the colors array.
We could store the texture_coord in the same VBO that stores the vertex_position array:
1 glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices_position), sizeof(texture_coord), texture_coord);
In order to create a texture, we follow the same recipe as in the case of a buffer object. We start by asking OpenGL for a unique identifier for our texture:
1 GLuint texture;
2 glGenTextures(1, &texture);
Next step is to specify that we will work with a 2D texture:
1 glBindTexture(GL_TEXTURE_2D, texture);
Now, we need to actually load an image from a file and initialize the texture with the the color data from the image, we can abstract this by calling a, to be discussed, function load_image, that takes as a parameter the path to the image file:
1 load_image("squirrel.jpg");
At the end of the initialize function let’s enable the texture_coord attribute, we’ll need this as an entry point to the vertex shader:
1 GLint texture_coord_attribute = glGetAttribLocation(shaderProgram, "texture_coord");
2 glVertexAttribPointer(texture_coord_attribute, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid *)sizeof(vertices_position));
3 glEnableVertexAttribArray(texture_coord_attribute);
Now, we need to modify the vertex shader in order to accept as input the texture_coord data and send it, through the OpenGL pipeline, to the fragment shader:
1 #version 150
2
3 in vec4 position;
4 in vec2 texture_coord;
5 out vec2 texture_coord_from_vshader;
6
7 void main() {
8 gl_Position = position;
9 texture_coord_from_vshader = texture_coord;
10 }
The fragment shader needs more modifications:
1 #version 150
2
3 in vec2 texture_coord_from_vshader;
4 out vec4 out_color;
5
6 uniform sampler2D texture_sampler;
7
8 void main() {
9 out_color = texture(texture_sampler, texture_coord_from_vshader);
10 }
Line 6 from the above shader defines a uniform shader variable, a 2D texture sampler - this is used internally by OpenGL to sample, or map, values from the continuous (s, t) space to the discrete color data stored in our texture. A uniform is a read-only variable for a shader and it is constant for all shaders, in other words it is a global variable for all shaders.
Line 9 will extract the color information for the current fragment based on the texture sampler and on the texture coordinates.
Now, we can discuss the load_image function. As mentioned in the first article from this series, OpenGL doesn’t include functionality for reading/writing image files. We could use the FreeImage library to read/write images. There are a number of other image processing libraries available, some free and open source like FreeImage, feel free to test other libraries if you don’t like FreeImage. I prefer to use FreeImage because it is a relatively small library, open source and portable on all major operating systems.
You can find the complete source code for load_image on the Github repository for this article, in ex_10. In the next chunk of code we omit the boilerplate code used to initialize FreeImage and other cleaning operations:
1 FIBITMAP *bitmap;
2 // Get the format of the image file
3 FREE_IMAGE_FORMAT fif =FreeImage_GetFileType(fname, 0);
4
5 // If the format can't be determined, try to guess the format from the file name
6 if(fif == FIF_UNKNOWN) {
7 fif = FreeImage_GetFIFFromFilename(fname);
8 }
9
10 // Load the data in bitmap if possible
11 if(fif != FIF_UNKNOWN && FreeImage_FIFSupportsReading(fif)) {
12 bitmap = FreeImage_Load(fif, fname);
13 }
14 else {
15 bitmap = NULL;
16 }
17
18 // PROCESS IMAGE if bitmap was successfully initialized
19 if(bitmap) {
20 unsigned int w = FreeImage_GetWidth(bitmap);
21 unsigned int h = FreeImage_GetHeight(bitmap);
22 unsigned pixel_size = FreeImage_GetBPP(bitmap);
23
24 // Get a pointer to the pixel data
25 BYTE *data = (BYTE*)FreeImage_GetBits(bitmap);
26
27 // Process only RGB and RGBA images
28 if(pixel_size == 24) {
29 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, (GLvoid*)data);
30 }
31 else if (pixel_size == 32) {
32 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)data);
33 }
34 else {
35 std::cerr << "pixel size = " << pixel_size << " don't know how to process this case. I'm out!" << std::endl;
36 exit(-1);
37 }
38
39 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
40 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
41 }
42 else {
43 ...
44 }
45 ...
Line 29, or 32 for RGBA images, allocates the necessary memory for storing the image data and fills the texture with the color data from the original image. glTexImage2D creates a mutable storage for our texture, this is useful if you plan to later resize the texture storage, perhaps to accommodate a larger or a smaller image. On the other hand, if you know that your texture storage will remain constant it is more efficient to use glTexStorage2D to allocate space and glTexSubImage2D to add data to the texture. glTexStorage2D will create an immutable storage for our texture. In both cases, mutable or immutable storage, we can modify the data stored in a texture.
Next two highlighted lines instructs OpenGL how to interpolate the image data when we scale up or down the original image, in this case we will use linear interpolation.
If you’ve installed FreeImage on OS X using my modified Makefile, as suggested in the first article, you will need to add an extra parameter stdlib=libc++ when you use FreeImage, specifically:
1 clang++ -Wall -stdlib=libc++ your_program_name.cpp -lglfw -framework Cocoa -framework OpenGL -framework IOKit -lGLEW -lfreeimage
If you run ex_10, this what you should see:
Please note that I’ve commented the line that sets the clear color to red, the default clear color for OpenGL is black.
If you want to completely fill the available window surface you can change the vertices_position accordingly:
1 GLfloat vertices_position[8] = {
2 -1.0, -1.0,
3 1.0, -1.0,
4 1.0, 1.0,
5 -1.0, 1.0,
6 };
Say that you want to use tones of grey for the texture and not the original RGB colors, we can modify the fragment shader to average the red, green, blue from the original image and use this average color as the output color from the shader:
1 #version 150
2
3 in vec2 texture_coord_from_vshader;
4 out vec4 out_color;
5
6 uniform sampler2D texture_sampler;
7
8 void main() {
9 out_color = texture(texture_sampler, texture_coord_from_vshader);
10 float average_color = (out_color.r + out_color.g + out_color.b)/3.0;
11 out_color = vec4(average_color, average_color, average_color, 1.0);
12 }
If you run ex_11, this is what you should see:
We can get more interesting effects if we extend the texture coordinates outside the (s, t) space, which is defined as the unit square [0, 1] x [0, 1], the image will be wrapped on the missing values. We can control the wrapping mode with glTexParameteri.
First, let’s change the texture_coord array:
1 GLfloat texture_coord[8] = {
2 -1.0, -1.0,
3 2.0, -1.0,
4 2.0, 2.0,
5 -1.0, 2.0,
6 };
If you run ex_12, this is what you should see:
By default, OpenGL will repeat the image in both s and t directions for values outside of the unit square. Same effect can be obtained if we set (this is the default wrap mode):
1 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
2 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
Other possible value for the third parameter in the above function: GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_MIRRORED_REPEAT, if you press W while running ex_12 you can test all these wrap options:
In the next article, we are going to talk about geometrical transformations - translation, scaling, rotation, projection matrix and the camera model. If you don’t know what matrix multiplication means, or the inverse of a matrix is, you are going to have a hard time working with more complex models. Take your time and read a bit about basic matrix operations: addition, multiplication, inverse of a matrix, a simple Google search will do. You don’t need to be an expert, but you need to know what these operations means.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////