博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Opengl绘制我们的小屋(三)纹理绘制
阅读量:6711 次
发布时间:2019-06-25

本文共 3590 字,大约阅读时间需要 11 分钟。

本准备先说光照相关实现,但是发现对那个模型实在看不下去了,于是先绘制纹理。

先看下基本纹理贴上去的显示效果。具体模型图请看上篇文章的实现,这篇只讲纹理实现。

我们常见的纹理绘制差不多如下,先写一个纹理坐标,然后是一个顶点坐标,GL.TexCoord2(1.0f,1.0f);GL.Vectex(1.f,1.f,1.f)。先说一下纹理坐标与顶点坐标的对应处理关系,为了好理解,我们只说二维纹理。先看下图。

我们设置一张16*8的纹理,如上图,我们设置GL.TexCoord2(1.0f,1.0f)就是在(16,8)位置,超出1的部分,会复制超出部分,如上图设置GL.TexCoord(2.0,2.0)就会在图上一共显示四张图,同理我们只要纹理的右下部分四分之一,那坐标应该分别是(1,0.5),(0.5,0.5),(0.5,0)(1,0).

在上个模型中,我们可以看到我们有很多的模型需要纹理贴图,如果采用一般的方法,需要在每个立方体的面上去计算我们相应的纹理坐标,这样花费时间太大,这样我们采用opengl里提供的自动生成纹理。首先要指定以什么样的模式(既什么样的算法)来生成纹理坐标。可以指定几种纹理坐标生成模式:GL_OBJECT_LINEAR, GL_EYE_LINEAR, GL_SPHERE_MAP等。

在这里我们只需要采用最容易理解的纹理生成模式。GL_OBJECT_LINEAR,在这种模式下,指定四个参数,p0,p1,p2,p3,对应顶点(x0,y0,z0,w0),生成的纹理坐标为p0*x0+p1*y0+p2*z0+p3*w0。

我们再来看我们的需求

1。要对立方体的各面自动生成纹理。

2。我们贴地面的,要像砖是一块一块的,而贴墙时,只需要贴一张。如最上图所绘,左下角与右上角分别对应的纹理坐标在贴砖是一块一块的应该是((0,0),(n,m))《m>0,n>0》,而贴墙时应该对应((0,0),(1,1))。

借用上篇的图。

第一点,根据我们的p0*x0+p1*y0+p2*z0+p3*w0算法来看,比如贴地面时,也就是垂直于Y轴时,用到的是图上的(4,5,1,0)这个面。

 想象一下对应关系,纹理的S轴坐标对应是1-0这条线,T轴坐标对应的是1-5这条线,那么对应s轴大致如下[x;0.;0.;0],T轴坐标大致如下[0;0.;y;0].各面按照这样得到对应的参数。相关代码如下。

1         member this.GenTexture(vector:Vector3,ball) =  2             GL.Enable(EnableCap.TextureGenS) 3             GL.Enable(EnableCap.TextureGenT) 4             GL.TexGen(TextureCoordName.S,TextureGenParameter.TextureGenMode,int TextureGenMode.ObjectLinear) 5             GL.TexGen(TextureCoordName.T,TextureGenParameter.TextureGenMode,int TextureGenMode.ObjectLinear) 6             let mutable xa = [|1.f;0.f;0.f;0.f|] 7             let mutable xy = [|0.f;1.f;0.f;0.f|] 8             let mutable x,y,z=1.f,1.f,0.f 9             if ball then z <-0.5f10             if vector = Vector3.UnitY || vector = -Vector3.UnitY then 11                 if ball then12                     x<-1.0f/Vector3.Subtract(v8.[0],v8.[1]).Length13                     y<-1.0f/Vector3.Subtract(v8.[0],v8.[4]).Length14                 xa <- [|x;0.f;0.f;z|]15                 xy <- [|0.f;0.f;y;z|]16             if vector = Vector3.UnitZ || vector = -Vector3.UnitZ then 17                 if ball then18                     x<-1.0f/Vector3.Subtract(v8.[0],v8.[1]).Length19                     y<-1.0f/Vector3.Subtract(v8.[0],v8.[3]).Length20                 xa <- [|x;0.f;0.f;z|]21                 xy <- [|0.f;y;0.f;z|]22             if vector = Vector3.UnitX || vector = -Vector3.UnitX then 23                 if ball then                24                     x<-1.0f/Vector3.Subtract(v8.[0],v8.[4]).Length25                     y<-1.0f/Vector3.Subtract(v8.[0],v8.[3]).Length26                 xa <- [|0.f;0.f;x;z|]27                 xy <- [|0.f;y;0.f;z|]28             GL.TexGen(TextureCoordName.S,TextureGenParameter.ObjectPlane,xa)29             GL.TexGen(TextureCoordName.T,TextureGenParameter.ObjectPlane,xy)
View Code

其中ball参数表示贴墙这种一面只帖一张纹理。在ball时,我们可以看到我们的p0,p1,p2,p3,p3=0.5,这是因为我的矩形的画法所导致的(前看上篇所叙),比如我要生成宽为8的立方体,其中我画顶点是x=-4,x=4这种画法,如果不加0.5,那么我的帖图就会是左下到右上是(-0,5,-0,5),(0.5,0.5)这种。

在opengl是状态机模式,记的每画一面打开相应的状态后,在画完后,需要关掉,不然会影响下一部分的贴图。绘制部分的代码如下。

1         member this.DrawTexTure(ts:int*int*bool,vector:Vector3,indexs:int []) = 2             let ind,txtId,ball = ts 3             if txtId <> 0  then  4                 GL.BindTexture(TextureTarget.Texture2D,txtId) 5                 this.GenTexture(vector,ball) 6             GL.Normal3(vector) 7             GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,indexs) 8             GL.Disable(EnableCap.TextureGenS) 9             GL.Disable(EnableCap.TextureGenT)10             GL.Disable(EnableCap.TextureGenR)11             GL.Disable(EnableCap.TextureGenQ)
View Code

最后附上源码与可执行文件。操作方式和网游一样,鼠标右键按下加鼠标上下左右移动是视角.EDSF行走。

下一章节会给大家讲到光照的运用。

 

转载地址:http://pmxlo.baihongyu.com/

你可能感兴趣的文章
linux磁盘批量分区格式化和挂载脚本
查看>>
LVM配置与管理
查看>>
RAC节点服务ora.rac2.gsd的offline问题解决方法
查看>>
SharedPreferences小细节
查看>>
Configuring Default-network for EIGRP
查看>>
【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记32 NSNotification
查看>>
【嵌入式】探究bootloader,分析u-boot源码
查看>>
Oracle数据库通过定义TYPE及Member对象来实现日志信息的分级管理
查看>>
pb之autocommit
查看>>
UDT拥塞控制算法
查看>>
Bsidesiowa 2015 Track2: Secure Process Isolation With Docker By Greg Rice
查看>>
解决开机 svchost.exe 进程占用居高不下的问题
查看>>
如何控制某个方法允许并发访问线程的个数?
查看>>
Android2.2 API 中文文档系列(2) —— EditText
查看>>
openstack iptables
查看>>
Matlab中的ans小结
查看>>
三行代码接入,社交软件打字时底下弹出的表情布局,自定义ViewPager+页面点标+各种功能的android小框架。...
查看>>
nginx学习总结二(nginx的启动停止以及版本平滑升级)
查看>>
linux网卡绑定
查看>>
fastjson报java.lang.ClassNotFoundError
查看>>