SharpGL学习笔记(十六) 多重纹理映射
多重纹理就把多张贴图隔和在一起.比如下面示例中,一个表现砖墙的纹理,配合一个表现聚光灯效果的灰度图,就形成了砖墙被一个聚光灯照亮的效果,这便是所谓的光照贴图技术.
多重纹理只在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/