Skip to main content

Featured

Build docker image from multiple build contexts

Build docker image from multiple build contexts Building a docker image requires specifying a source of truth to include in the image from a local directory or a remote git repository. In the previous version, the docker BuildKit allows users to specify the build context from a single source of truth only. However, the engineers may need to have the context from different locations based on the type of files. For instance, icons, images or other resources that are not included in the same package, including the resource from other docker images. Fortunately, the Docker Buildx toolkit supports multiple build context flag for Docker 1.4. Let's learn how to use this new feature. The following list is a shortcut for jumping into a specific topic handy. What version of Docker is this tutorial targeting? How to specify the version of Dockerfile frontend? Ho

[OpenGL]2D Texture Mapping

Reference:Nehe's OpenGL - Lesson 17

目前工作僅需要將BMP圖片顯示在GL Scene裡面,所以就僅擷取出貼圖片材質的部分。並附上原網頁的註解,已方便對照跟查詢。由於是原文貼上,所以有些用語會有有前後不接的狀況,所以想瞭解原始的意義,請至Hehe的網頁觀看。

0.在開始進行前,先建立存放Texture的全域變數。
 ....  
 GLuint m_glTextureList[DS_GL_MAX_TEXTURE];  
 ....  

1.建立讀取BMP檔的函式。由於此函式有用到auxDIBImageLoad,所以要在*.h引用gl\glaux.h。
CDSFileIO為自訂的類別,目的是要檢查檔案是否存在,不存在的話,讀了也沒有意義。原文有提到圖片大小的建議,目前因為要配合TreeList顯示的問題,所以是讀取16*16的大小的圖片,於Windows XP SP2測試是正常。
 //----------- L.6 ----------------  
 //Now immediately after the above code, and before ReSizeGLScene(), we want to add the following section of code.   
 //    The job of this code is to load in a bitmap file. If the file doesn't exist NULL is sent back meaning the texture couldn't be loaded.   
 //    Before I start explaining the code there are a few VERY important things you need to know about the images you plan to use as textures.   
 //    The image height and width MUST be a power of 2.   
 //    The width and height must be at least 64 pixels, and for compatability reasons, shouldn't be more than 256 pixels.   
 //    If the image you want to use is not 64, 128 or 256 pixels on the width or height, resize it in an art program.   
 //    There are ways around this limitation, but for now we'll just stick to standard texture sizes.   
 //First thing we do is create a file handle. A handle is a value used to identify a resource so that our program can access it.   
 //    We set the handle to NULL to start off.  
 //----------- L.6 ----------------  
 AUX_RGBImageRec *COpenGLDrawer::LoadBMP(const char *szFilePath)  
 {  
     if ( CDSFileIO::IsFileExisted(szFilePath) ) {  
         return auxDIBImageLoad(szFilePath);                // Load The Bitmap And Return A Pointer  
     }    //End of if ( CDSFileIO::IsFileExisted(szFilePath) )  
     return NULL;                                        // If Load Failed Return NULL  
 }  

2.建立設定Texture的函式。DS_GL_MAX_TEXTURE為自訂常數,用來定義讀取BMP的Texture buffer大小。所以就看需求定義即可。由於是非動態宣告buffer大小,所以要小心邊界的問題。
 //The follwing code has also changed very little from the code used in previous tutorials.   
 //    If you're not sure what each of the following lines do, go back and review.   
 //Note that TextureImage[ ] is going to hold 2 rgb image records.   
 //    It's very important to double check code that deals with loading or storing our textures.   
 //    One wrong number could result in a memory leak or crash!  
 // Load Bitmaps And Convert To Textures  
 int COpenGLDrawer::LoadGLTextures(std::vector<std::string> vstrFilePaths)                                  
 {  
     int Status = TRUE;  
     AUX_RGBImageRec *TextureImage[DS_GL_MAX_TEXTURE];        // Create Storage Space For The Textures  
           
 //The next line is the most important line to watch. If you were to replace the 2 with any other number, major problems will happen.   
 //    Double check! This number should match the number you used when you set up TextureImages[ ].   
 //The two textures we're going to load are font.bmp (our font), and bumps.bmp.   
 //    The second texture can be replaced with any texture you want.   
 //    I wasn't feeling very creative, so the texture I decided to use may be a little drab.              
 /*    memset(TextureImage,0,sizeof(void *)*2);                // Set The Pointer To NULL    */  
     memset(TextureImage,0,sizeof(void *)*DS_GL_MAX_TEXTURE);    // Set The Pointer To NULL  
   
     for ( unsigned int i = 0 ; i < vstrFilePaths.size() ; i++ )  
     {  
         if ( !(TextureImage[i] = this->LoadBMP(vstrFilePaths[i].c_str())) )        //有一個讀不到就不繼續執行,不然就是要改塞白色。  
         {  
             Status = FALSE;  
         }  
     }    //End of for ( unsigned int i = 0 ; i < vstrFilePaths.size() ; i++ )          
   
     if ( !Status ) {  
         return Status; };  
   
 //Another important line to double check.   
 //    I can't begin to tell you how many emails I've received from people asking "why am I only seeing one texture,   
 //        or why are my textures all white!?!".   
 //    Usually this line is the problem.   
 //    If you were to replace the 2 with a 1, only one texture would be created and the second texture would appear all white.   
 //    If you replaced the 2 with a 3 you're program may crash!   
 //You should only have to call glGenTextures() once. After glGenTextures() you should generate all your textures.   
 //    I've seen people put a glGenTextures() line before each texture they create.   
 //    Usually they causes the new texture to overwrite any textures you've already created.   
 //    It's a good idea to decide how many textures you need to build, call glGenTextures() once, and then build all the textures.   
 //    It's not wise to put glGenTextures() inside a loop unless you have a reason to.          
 //--------- L.6 ------------  
 //Now that we've loaded the image data into TextureImage[0], we will build a texture using this data.   
 //    The first line glGenTextures(1, &texture[0]) tells OpenGL we want to generate one texture name   
 //        (increase the number if you load more than one texture).   
 //    Remember at the very beginning of this tutorial we created room for one texture with the line GLuint texture[1].   
 //    Although you'd think the first texture would be stored at &texture[1] instead of &texture[0], it's not.   
 //    The first actual storage area is 0.   
 //    If we wanted two textures we would use GLuint texture[2] and the second texture would be stored at texture[1].   
 //The second line glBindTexture(GL_TEXTURE_2D, texture[0]) tells OpenGL to bind the named texture texture[0] to a texture target.   
 //    2D textures have both height (on the Y axes) and width (on the X axes).   
 //    The main function of glBindTexture is to assign a texture name to texture data.  
 //    In this case we're telling OpenGL there is memory available at &texture[0].   
 //    When we create the texture, it will be stored in the memory that &texture[0] references.  
 //--------- L.6 ------------  
     glGenTextures((GLsizei)DS_GL_MAX_TEXTURE, &this->m_glTextureList[0]);        //Create n Texture  
   
     for ( unsigned int i = 0 ; i < this->m_vstrTextureFilePath.size() ; i++ )    // Loop Through All The Textures  
     {  
         //Build All The Textures  
         glBindTexture(GL_TEXTURE_2D, this->m_glTextureList[i]);  
   
 //----------- L.6 ---------------  
 //The next two lines tell OpenGL what type of filtering to use when the image is larger (GL_TEXTURE_MAG_FILTER) or   
 //        stretched on the screen than the original texture, or when it's smaller (GL_TEXTURE_MIN_FILTER) on the screen than the actual texture.   
 //    I usually use GL_LINEAR for both. This makes the texture look smooth way in the distance, and when it's up close to the screen.   
 //    Using GL_LINEAR requires alot of work from the processor/video card, so if your system is slow, you might want to use GL_NEAREST.   
 //    A texture that's filtered with GL_NEAREST will appear blocky when it's stretched. You can also try a combination of both.   
 //    Make it filter things up close, but not things in the distance.  
 //----------- L.6 ---------------  
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  
   
 //----------- L.6 ---------------  
 //Next we create the actual texture. The following line tells OpenGL the texture will be a 2D texture (GL_TEXTURE_2D).   
 //    Zero represents the images level of detail, this is usually left at zero. Three is the number of data components.   
 //    Because the image is made up of red data, green data and blue data, there are three components.   
 //    TextureImage[0]->sizeX is the width of the texture. If you know the width, you can put it here,   
 //        but it's easier to let the computer figure it out for you.   
 //    TextureImage[0]->sizey is the height of the texture. zero is the border.   
 //    It's usually left at zero. GL_RGB tells OpenGL the image data we are using is made up of red, green and blue data in that order.   
 //    GL_UNSIGNED_BYTE means the data that makes up the image is made up of unsigned bytes, and finally...   
 //        TextureImage[0]->data tells OpenGL where to get the texture data from.   
 //    In this case it points to the data stored in the TextureImage[0] record.  
 //----------- L.6 ---------------  
         glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[i]->sizeX, TextureImage[i]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[i]->data);  
     }    //End of for ( int i = 0 ; i < DS_GL_MAX_TEXTURE ; i++ )  
   
 /*        }    */  
   
 //The following lines of code check to see if the bitmap data we loaded to build our textures is using up ram.   
 //    If it is, the ram is freed. Notice we check and free both rgb image records.   
 //    If we used 3 different images to build our textures, we'd check and free 3 rgb image records.  
 //---------- L.6 ---------------  
 //Now we free up any ram that we may have used to store the bitmap data. We check to see if the bitmap data was stored in TextureImage[0].   
 //    If it was we check to see if the data has been stored. If data was stored, we erase it.   
 //    Then we free the image structure making sure any used memory is freed up.  
 //---------- L.6 ---------------  
     for ( int i = 0 ; i < this->m_vstrTextureFilePath.size() ; i++ )  
     {  
         if ( TextureImage[i] )                            // If Texture Exists  
         {  
             if ( TextureImage[i]->data ) {                //If Texture Image Exists  
                 free(TextureImage[i]->data); };            //Free the Texture Image Memory  
   
             free(TextureImage[i]);                        //Free The Image Structure  
         }    //End of if ( TextureImage[i] )  
     }    //End of for ( int i = 0 ; i < DS_GL_MAX_TEXTURE ; i++ )  
   
     return Status;                                // Return The Status  
 }  

3.上述兩個步驟完成後,則在GL做初始化的時候,載入並設定Texture。這邊所需的圖檔路徑皆在物件產生時就先指定好。
 void COpenGLDrawer::glInitialize(void)  
 {  
 ....  
     if ( !this->LoadGLTextures(this->m_vstrTextureFilePath) ) {  
         return;    };  
 ....  
 }  

4.於GL Scene繪製方式如下,關鍵的部分為,要進行Texture Mapping時,要先開啟GL_TEXTURE。繪製完成後,可設定關閉,以釋放記憶體。
 void CDSGLDrawer::glDrawScene(void)  
 {  
 //Show Texture  
 //The next line of code selects which texture we want to use.   
 //    If there was more than one texture you wanted to use in your scene,   
 //        you would select the texture using glBindTexture(GL_TEXTURE_2D, texture[number of texture to use]).   
 //    If you wanted to change textures, you would bind to the new texture.   
 //    One thing to note is that you can NOT bind a texture inside glBegin() and glEnd(), you have to do it before or after glBegin().   
 //    Notice how we use glBindTextures to specify which texture to create and to select a specific texture.      
     glBindTexture(GL_TEXTURE_2D, this->m_glTextureList[0]);                // Select Our Texture  
           
 //To properly map a texture onto a quad, you have to make sure the top right of the texture is mapped to the top right of the quad.   
 //    The top left of the texture is mapped to the top left of the quad,   
 //        the bottom right of the texture is mapped to the bottom right of the quad, and finally,   
 //        the bottom left of the texture is mapped to the bottom left of the quad.   
 //    If the corners of the texture do not match the same corners of the quad, the image may appear upside down, sideways, or not at all.   
 //The first value of glTexCoord2f is the X coordinate.   
 //    0.0f is the left side of the texture. 0.5f is the middle of the texture, and 1.0f is the right side of the texture.   
 //    The second value of glTexCoord2f is the Y coordinate. 0.0f is the bottom of the texture.   
 //    0.5f is the middle of the texture, and 1.0f is the top of the texture.   
 //So now we know the top left coordinate of a texture is 0.0f on X and 1.0f on Y, and the top left vertex of a quad is -1.0f on X,   
 //        and 1.0f on Y.   
 //    Now all you have to do is match the other three texture coordinates up with the remaining three corners of the quad.  
 //Try playing around with the x and y values of glTexCoord2f.   
 //    Changing 1.0f to 0.5f will only draw the left half of a texture from 0.0f (left) to 0.5f (middle of the texture).   
 //    Changing 0.0f to 0.5f will only draw the right half of a texture from 0.5f (middle) to 1.0f (right).          
 //--------------- L.6 -------------------  
 //If everything went OK, and the texture was created, we enable 2D texture mapping.   
 //    If you forget to enable texture mapping your object will usually appear solid white, which is definitely not good.  
 //--------------- L.6 -------------------  
     glEnable(GL_TEXTURE_2D);                            // Enable Texture Mapping  
     glPolygonMode(GL_FRONT, GL_FILL);                    //Set polygon rasterization mode  
     glColor3f(1.0f, 1.0f, 1.0f);                        //用來重設顏色,如果前面這個位置有被繪製圖形,就必須做此動作。反之則無所謂。  
     glBegin(GL_QUADS);  
         glTexCoord2f(0.0f, 0.0f);  
         glVertex2f(this->m_vcdsGrid[0].LB.x, this->m_vcdsGrid[0].LB.y);    // Bottom Left Of The Texture and Quad  
         glTexCoord2f(1.0f, 0.0f);  
         glVertex2f(this->m_vcdsGrid[0].RB.x, this->m_vcdsGrid[0].RB.y);    // Bottom Right Of The Texture and Quad  
         glTexCoord2f(1.0f, 1.0f);  
         glVertex2f(this->m_vcdsGrid[0].RT.x, this->m_vcdsGrid[0].RT.y);    // Top Right Of The Texture and Quad  
         glTexCoord2f(0.0f, 1.0f);  
         glVertex2f(this->m_vcdsGrid[0].LT.x, this->m_vcdsGrid[0].LT.y);    // Top Left Of The Texture and Quad  
     glEnd();  
     glDisable(GL_TEXTURE_2D);                            //Disable texture mapping  
 }  

這樣就可以把讀進來的圖,貼到GL Scene裡面了。

Comments

Popular Posts