zoukankan      html  css  js  c++  java
  • Opengl绘制我们的小屋(三)纹理绘制

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

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

    我们常见的纹理绘制差不多如下,先写一个纹理坐标,然后是一个顶点坐标,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.5f
    10             if vector = Vector3.UnitY || vector = -Vector3.UnitY then 
    11                 if ball then
    12                     x<-1.0f/Vector3.Subtract(v8.[0],v8.[1]).Length
    13                     y<-1.0f/Vector3.Subtract(v8.[0],v8.[4]).Length
    14                 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 then
    18                     x<-1.0f/Vector3.Subtract(v8.[0],v8.[1]).Length
    19                     y<-1.0f/Vector3.Subtract(v8.[0],v8.[3]).Length
    20                 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]).Length
    25                     y<-1.0f/Vector3.Subtract(v8.[0],v8.[3]).Length
    26                 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行走。

     纹理小室版

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

  • 相关阅读:
    玩游戏(dfs)
    Find them, Catch them(并查集)
    Shredding Company(dfs)
    Sudoku(dfs)
    Network Saboteur(dfs)
    棋盘问题(dfs)
    Curling 2.0(dfs)
    A Knight's Journey(dfs)
    15. 3Sum
    12. Integer to Roman
  • 原文地址:https://www.cnblogs.com/zhouxin/p/3424562.html
Copyright © 2011-2022 走看看