多重紋理就把多張貼圖隔和在一起.比如下面示例中,一個表現磚牆的紋理,配合一個表現聚光燈效果的灰度圖,就形成了磚牆被一個聚光燈照亮的效果,這便是所謂的光照貼圖技術.
多重紋理只在OpenGL擴展庫中才提供的.OpenGL和D3D比較起來,最大的一個優點是有擴展機制.
顯卡硬件廠商開發出一項新功能,就可以針對新功能開發OpenGL擴展,軟件開發人員通過這個擴展就可以使用新的硬件功能,而不用等新的OpenGL版來公布才能使用這個新功能.而D3D則必須等到新版本的DirectX發布后才能支持硬件的新功能.
下面的代碼演示了如何使用擴展函數 GL_ARB_multitexture();
示例源代碼:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using SharpGL; 10 11 namespace SharpGLWinformsApplication1 12 { 13 //原創文章,出自"博客園, 豬悟能'S博客" : http://www.cnblogs.com/hackpig/ 14 public partial class SharpGLForm : Form 15 { 16 static float wrap = 0; // 用於霧的流動 17 SharpGL.SceneGraph.Assets.Texture[] textureAry = new SharpGL.SceneGraph.Assets.Texture[4]; 18 float[] fLightPosition = new float[4] { 0.0f, 0.0f, 8.0f, 1.0f}; // 光源位置 19 float[] fLightAmbient = new float[4] { 1f,1f, 1f, 1f }; // 環境光參數 20 float[] fLightDiffuse = new float[4] { 1f,1f, 1f, 1f }; // 漫射光參數 21 22 bool multitexturing = true; 23 public SharpGLForm() 24 { 25 InitializeComponent(); 26 } 27 28 private void openGLControl_OpenGLDraw(object sender, PaintEventArgs e) 29 { 30 OpenGL gl = openGLControl.OpenGL; 31 gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); 32 gl.LoadIdentity(); 33 draw(gl); 34 } 35 36 37 private void openGLControl_OpenGLInitialized(object sender, EventArgs e) 38 { 39 OpenGL gl = openGLControl.OpenGL; 40 String[] fileName = new String[4] { "wall.bmp", "lightmap.bmp", "bitmap.bmp", "fog.bmp" }; 41 for (int i = 0; i < fileName.Length; i++) 42 { 43 textureAry[i] = new SharpGL.SceneGraph.Assets.Texture(); 44 if (textureAry[i].Create(gl, fileName[i])) 45 { 46 textureAry[i].Id = i; 47 textureAry[i].Name = fileName[i]; 48 49 } 50 } 51 52 gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_AMBIENT, fLightAmbient);//環境光源 53 gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, fLightDiffuse);//漫射光源 54 gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, fLightPosition);//光源位置 55 gl.Enable(OpenGL.GL_LIGHTING);//開啟光照 56 gl.Enable(OpenGL.GL_LIGHT0); 57 58 gl.ClearColor(0.0f, 0.0f, 0.0f, 0.5f); 59 gl.ClearDepth(1.0f); 60 gl.DepthFunc(OpenGL.GL_LEQUAL); 61 gl.Enable(OpenGL.GL_DEPTH_TEST); 62 gl.ShadeModel(OpenGL.GL_SMOOTH); 63 64 gl.Hint(OpenGL.GL_PERSPECTIVE_CORRECTION_HINT, OpenGL.GL_NICEST); 65 gl.Enable(OpenGL.GL_NORMALIZE); 66 67 if (!initMultiTexture(gl)) 68 { 69 MessageBox.Show("您的硬件和驅動不支持多重紋理"); 70 return; 71 } 72 } 73 74 private void openGLControl_Resized(object sender, EventArgs e) 75 { 76 OpenGL gl = openGLControl.OpenGL; 77 gl.MatrixMode(OpenGL.GL_PROJECTION); 78 gl.LoadIdentity(); 79 gl.Perspective(45f, (double)Width / (double)Height, 1, 100.0); 80 gl.MatrixMode(OpenGL.GL_MODELVIEW); 81 draw(gl); 82 } 83 84 private void draw(OpenGL Gl) 85 { 86 Gl.LoadIdentity(); 87 Gl.Translate(0.0f, 0.0f, -10.0f); 88 89 //激活紋理0,並綁定紋理 90 Gl.ActiveTextureARB(OpenGL.GL_TEXTURE0_ARB); 91 Gl.Enable(OpenGL.GL_TEXTURE_2D); 92 textureAry[0].Bind(Gl); 93 94 Gl.ActiveTextureARB(OpenGL.GL_TEXTURE1_ARB); 95 //如果多重紋理啟用,則啟用該紋理 96 if (multitexturing) 97 Gl.Enable(OpenGL.GL_TEXTURE_2D); 98 else 99 Gl.Disable(OpenGL.GL_TEXTURE_2D); 100 textureAry[1].Bind(Gl); 101 102 // 繪制一個四方形牆面 103 Gl.PushMatrix(); 104 { 105 Gl.Translate(-2.5f, 0f, 0f); 106 Gl.Scale(2.0f, 2.0f, 2.0f); 107 Gl.Begin(OpenGL.GL_QUADS); 108 { 109 //左上點 110 111 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE0_ARB, 0.0f, 1.0f); 112 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE1_ARB, 0.0f + wrap, 1.0f); 113 Gl.Vertex(-1, 1, 0); 114 115 // 左下點 116 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE0_ARB, 0.0f, 0.0f); 117 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE1_ARB, 0.0f + wrap, 0.0f); 118 Gl.Vertex(-1, -1, 0); 119 120 // 右下點 121 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE0_ARB, 1.0f, 0.0f); 122 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE1_ARB, 1.0f + wrap, 0.0f); 123 Gl.Vertex(1, -1, 0); 124 125 // 右上點 126 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE0_ARB, 1.0f, 1.0f); 127 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE1_ARB, 1.0f + wrap, 1.0f); 128 Gl.Vertex(1, 1, 0); 129 } 130 Gl.End(); 131 } 132 Gl.PopMatrix(); 133 134 135 136 Gl.ActiveTextureARB(OpenGL.GL_TEXTURE0_ARB); 137 Gl.Enable(OpenGL.GL_TEXTURE_2D); 138 textureAry[2].Bind(Gl); 139 140 Gl.ActiveTextureARB(OpenGL.GL_TEXTURE1_ARB); 141 if (multitexturing) 142 Gl.Enable(OpenGL.GL_TEXTURE_2D); 143 else 144 Gl.Disable(OpenGL.GL_TEXTURE_2D); 145 textureAry[3].Bind(Gl); 146 147 148 Gl.PushMatrix(); 149 { 150 Gl.Translate(2.5f, 0, 0); 151 Gl.Scale(2.0f, 2.0f, 2.0f); 152 Gl.Begin(OpenGL.GL_QUADS); 153 { 154 // 左上點 155 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE0_ARB, 0.0f, 1.0f); 156 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE1_ARB, 0.0f - wrap, 1.0f); 157 Gl.Vertex(-1, 1, 0); 158 159 // 左下點 160 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE0_ARB, 0.0f, 0.0f); 161 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE1_ARB, 0.0f - wrap, 0.0f); 162 Gl.Vertex(-1, -1, 0); 163 164 // 右下點 165 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE0_ARB, 1.0f, 0.0f); 166 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE1_ARB, 1.0f - wrap, 0.0f); 167 Gl.Vertex(1, -1, 0); 168 169 // 右上點 170 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE0_ARB, 1.0f, 1.0f); 171 Gl.MultiTexCoord2ARB(OpenGL.GL_TEXTURE1_ARB, 1.0f - wrap, 1.0f); 172 Gl.Vertex(1, 1, 0); 173 } 174 Gl.End(); 175 wrap += 0.01f; 176 } 177 Gl.PopMatrix(); 178 179 Gl.Flush(); 180 } 181 182 /// <summary> 183 /// 檢查多重紋理支持 184 /// </summary> 185 /// <param name="input"></param> 186 /// <returns></returns> 187 bool isExtensionSupported(OpenGL gl, string input) 188 {
//GetSting獲取顯卡所支持的全部擴展的信息 189 string extension = gl.GetString(OpenGL.GL_EXTENSIONS); 190 return extension.IndexOf(input) >= 0; 191 } 192 193 bool initMultiTexture(OpenGL gl) 194 { 195 //檢查是否支持擴展 196 if (isExtensionSupported(gl,"GL_ARB_multitexture")) 197 { 198 return true; 199 } 200 else 201 return false; 202 } 203 204 } 205 }
效果如下:
左邊的四邊形貼上了地磚和燈光效果的兩張貼圖.
右邊的四邊形貼上了風景和霧效果的兩張貼圖.
通過移動多重紋理X坐標實現了水平移動的效果.

代碼基本和和普通的紋理映射沒有非常大的區別,我沒有什么好解析的.
原創文章,出自"博客園, 豬悟能'S博客" : http://www.cnblogs.com/hackpig/
