精华内容
下载资源
问答
  • 纹理映射

    2021-03-02 09:05:31
    纹理映射 纹理最初的目的就是使用一张图片来控制模型的外观。使用纹理映射(texture mapping)技术,我们可以把一张图“黏”在模型表面,逐纹素(texel)(纹素的名字是为了和像素进行区分)地控制模型的颜色。 在美术人员...

    纹理映射

    纹理最初的目的就是使用一张图片来控制模型的外观。使用纹理映射(texture mapping)技术,我们可以把一张图“黏”在模型表面,逐纹素(texel)(纹素的名字是为了和像素进行区分)地控制模型的颜色。
    在美术人员建模的时候,通常会在建模软件中利用纹理展开技术把纹理映射坐标(texture-mapping coordinates) 存储在每个顶点上。纹理映射坐标定义了该顶点在纹理中对应的2D 坐标。通常,这些坐标使用一个二维变量(u, v)来表示,其中u是横向坐标,而v是纵向坐标。因此,纹理映射坐标也被称为UV坐标。
    尽管纹理的大小可以是多种多样的,例如可以是256×256或者1028×1028,但顶点UV坐标的范围通常都被归一化到[0,1]范围内。需要注意的是,纹理采样时使用的纹理坐标不一定是在[0,1]范围内。实际上,这种不在[0,1]范围内的纹理坐标有时会非常有用。与之关系紧密的是纹理的平铺模式,它将决定渲染引擎在遇到不在[0,1]范围内的纹理坐标时如何进行纹理采样。
    纹理采样就是漫反射系数值设定为纹理

    普通纹理映射

    由像素的位置算出uv的值,得到对应的纹理值,纹理作为漫反射系数

    在这里插入图片描述

    纹理的像素为纹素

    在这里插入图片描述
    物体表面的每个点的k_d属性表示纹理颜色等等,是漫反射系数
    三维物体的表面是2d的,所以物体的纹理可以由图片来表示
    在这里插入图片描述
    空间的三角形映射到纹理的三角形关系由Artist实现,或者自动化,我们不需要管
    在这里插入图片描述
    纹理用uv表示坐标系
    在这里插入图片描述

    Unity 单张纹理采样的实现

    Shader "TurBoQShader/Chapter7/ST(单张纹理加BP模型)"
    {
        Properties
        {
           _Color("Color Tint",Color)=(1,1,1,1)//控制纹理的色调
           _MainTex("Main Tex",2D)="white" {}//2D是纹理属性的声明方式
           _Specular("Specular",Color)=(1,1,1,1)//高光反射的颜色
           _Gloss("Gloss",Range(8.0,256))=20//高光区域的大小
        }
        SubShader
        {
        Pass{
        //指定该Pass的光照模式,LightMode属于Pass标签
            Tags { "LightMode"="ForwardBase" }
           
            CGPROGRAM//包裹CG代码片
            //顶点着色器名称
          #pragma vertex vert
          //片元着色器名称
          #pragma fragment frag
          //为了使用Unity内置的变量,如_LightColor0,引入内置文件
          #include "Lighting.cginc"
          //CG代码中需要和Unity面板对应的属性
          fixed4 _Color;
          sampler2D _MainTex;
          float4 _MainTex_ST;//纹理的缩放和平移
          fixed4 _Specular;
          float _Gloss;
          //顶点着色器的输入结构体a2v,顶点着色器的输出结构体和片元着色器的输入结构体v2f
          struct a2v{
       float4 vertex :POSITION;
       float3 normal:NORMAL;
       float4 texcoord:TEXCOORD0;//顶点纹理坐标
       };
       struct v2f{
       float4 pos:SV_POSITION;
       float3 worldNormal:TEXCOORD0;
       float3 worldPos:TEXCOORD1;
       float2 uv:TEXCOORD2;
       };
       v2f vert(a2v v)//顶点着色器代码,计算世界法线和世界坐标和转换世界坐标到模型坐标
       {
       v2f o;
       o.pos=UnityObjectToClipPos(v.vertex);
      
       o.worldNormal=UnityObjectToWorldNormal(v.normal);
       o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
       // o.uv=v.texcoord.xy*_MainTex_ST.xy+_MainTex_ST.zw;
       //在顶点着色器中,我们使用纹理的属性值_MainTex_ST来对顶点纹理坐标进行变换,得到最终的纹理坐标。
       //计算过程是,首先使用缩放属性_MainTex_ST.xy对顶点纹理坐标进行缩放,然后再使用偏移属性_MainTex_ST.zw
       //对结果进行偏移。Unity 提供了一个内置宏TRANSFORM_TEX来帮我们计算上述过程。TRANSFORM_TEX是在 UnityCGcginc中定义的:
       //它接受两个参数,第一个参数是顶点纹理坐标,第二个参数是纹理名,在它的实现中,将利用纹理名_ST的方式来计算变换后的uv坐标。
        o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);//使用缩放和偏移计算纹理,v.texcoord是材质的顶点纹理坐标,_MainTex是2D图片的名称
       return o;
       }
    
        fixed4 frag(v2f i):SV_Target{//片元着色器代码,负责计算高光反射和漫反射,漫反射中加入纹理的uv坐标
        fixed3 worldNormal=normalize(i.worldNormal);//normalize归一化世界法线
        //fixed3 worldLigthDir=normalize(_WorldSpaceLightPos0.xyz);//normalize截取前三行三列光源方向
        fixed3 worldLigthDir=normalize(UnityWorldSpaceLightDir(i.worldPos));//世界光照方向
        //纹理进行采样。它的第一个参数是需要被采样的纹理,第二个参数是一个float2类型的纹理坐标,它将返回计算得到的纹素值。
        fixed3 albedo=tex2D(_MainTex,i.uv).rgb*_Color.rgb;//纹素计算
        fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;//世界光照乘纹素
    
       fixed3 diffuse=_LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLigthDir));//漫反射=入射光颜色强度*材质的漫反射系数*dot(光源方向,表面法线),乘世界光照和纹素
    
      // fixed3 reflectDir=normalize(reflect(-worldLigthDir,worldNormal));
       //fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
       fixed3 viewDir=normalize(UnityWorldSpaceViewDir(i.worldPos));//视角方向
       fixed3 halfDir=normalize(worldLigthDir+viewDir);//normalize归一化
       fixed3 specular=_LightColor0.rgb*_Specular.rgb*pow(max(0,dot(worldNormal,halfDir)),_Gloss);//高光反射=入射光颜色强度*材质的高光反射系数*dot(视角方向,
       //反射方向(由表面法线和光源方向求得))
       return fixed4(ambient+diffuse+specular,1.0);
       }
            ENDCG
            }
        }
        FallBack "Specular"
    }
    

    Unity中纹理的属性

    在这里插入图片描述

    纹理太小的解决方案

    Unity的处理方式(最近邻插值,双线性插值,双三次插值)

    在这里插入图片描述在内部实现上,Point模式使用了最近邻(nearest neighbor)滤波,在放大或缩小时,它的采样像素数目通常只有一个,因此图像会看起来有种像素风格的效果。而 Bilinear滤波则使用了线性滤波,对于每个目标像素,它会找到4个邻近像素,然后对它们进行线性插值混合后得到最终像素,因此图像看起来像被模糊了。而 Trilinear滤波几乎是和 Bilinear一样的,只是 Trilinear还会在多级渐远纹理之间进行混合。如果一张纹理没有使用多级渐远纹理技术,那么Trilinear得到的结果是和 Bilinear就一样的。通常,我们会选择Bilinear滤波模式。需要注意的是,有时我们不希望纹理看起来是模糊的,例如对于一些类似棋盘的纹理,我们希望它就是像素风的,这时我们可能会选择Point模式。

    图形学的处理方式

    在这里插入图片描述

    双线性插值

    纹理图太小,想要像素平滑过渡的解决方法

    在这里插入图片描述邻近四个点做插值
    在这里插入图片描述
    水平插值结束后竖直插值
    在这里插入图片描述

    Bicubic双三次插值

    函数f在点 (x,y) 的值可以通过矩形网格中最近的十六个采样点的[加权平均]得到,在这里需要使用两个多项式插值三次函数,每个方向使用一个。

    纹理太大的解决方案

    Unity的处理方式

    纹理缩小的过程比放大更加复杂一些,此时原纹理中的多个像素将会对应一个目标像素。纹理缩放更加复杂的原因在于我们往往需要处理抗锯齿问题,一个最常使用的方法就是使用多级渐远纹理(mipmapping)技术。其中“mip”是拉丁文“multum in parvo”的缩写,它的意思是“在一个小空间中有许多东西”。如同它的名字,多级渐远纹理技术将原纹理提前用滤波处理来得到很多更小的图像,形成了一个图像金字塔,每一层都是对上一层图像降采样的结果。这样在实时运行时,就可以快速得到结果像素,例如当物体远离摄像机时,可以直接使用较小的纹理。但缺点是需要使用一定的空间用于存储这些多级渐远纹理,通常会多占用33%的内存空间。这是一种典型的用空间换取时间的方法。在Unity中,我们可以在纹理导入面板中,首先将纹理类型(TextureType)选择成Advanced,再勾选Generate Mip Maps 即可开启多级渐远纹理技术。同时,我们还可以选择生成多级渐远纹理时是否使用线性空间(用于伽玛校正,详见18.4.2.节)以及采用的滤波器等,如图7.8所示。
    在这里插入图片描述

    图形学的处理方式

    离摄像机远的像素,像素里面覆盖(包含)的纹理太多,一个纹素代表不了纹理的结果

    在这里插入图片描述

    超采样(增加像素数量)

    在这里插入图片描述

    求范围的平均值,Mipmap

    需要原纹理图的三分之一空间存储
    在这里插入图片描述
    点的右边和上边投影到纹理空间,求对应的长度最大值,作为纹理空间的边长,边长决定去第几层mipmap找像素,立即找到区域的平均值。
    在这里插入图片描述不平滑用插值来解决,比如1.8层,在1和2层做双线性插值,再做插值,叫做三线性插值

    各项异性过滤

    解决三线性插值以及mipmap对于不是正方形的计算不准确的问题
    在这里插入图片描述
    mipmap是对角线
    在这里插入图片描述解决长条和矩形区域问题
    在这里插入图片描述

    重心坐标(三角形顶点属性知道,其他通过插值得到)

    三角形内的点三个系数都是非负的
    在这里插入图片描述A点重心坐标
    在这里插入图片描述重心坐标求法
    在这里插入图片描述重心的重心坐标(0.3,0.3,0.3)
    属性通过重心坐标插值
    在这里插入图片描述

    纹理模式

    在这里插入图片描述

    纹理应用

    凹凸映射

    纹理的另一种常见的应用就是凹凸映射(bump mapping)。凹凸映射的目的是使用一张纹理来修改模型表面的法线,以便为模型提供更多的细节。这种方法不会真的改变模型的顶点位置,只是让模型看起来好像是“凹凸不平”的,但可以从模型的轮廓处看出“破绽”。
    有两种主要的方法可以用来进行凹凸映射:一种方法是使用一张==高度纹理(height map)来模拟表面位移(displacement),然后得到一个修改后的法线值,这种方法也被称为高度映射(heightmapping);另一种方法则是使用一张法线纹理(normal map)==来直接存储表面法线,这种方法又被称为法线映射(normal mapping)。尽管我们常常将凹凸映射和法线映射当成是相同的技术,但读者需要知道它们之间的不同。

    高度图通常会和法线映射一起使用,用于给出表面凹凸的额外信息。也就是说,我们通常会使用法线映射来修改光照。

    纹理定义点相对于自己模型的相对高度,应用导致法线变换,最后导致光照结果出现变换

    橙色为凹凸贴图存的内容
    在这里插入图片描述先算切线再逆时针旋转90度
    在这里插入图片描述现代位移贴图,会按照橙色线变换三角形顶点的位置
    在这里插入图片描述

    纹理图记录其他计算结果

    在真实的游戏制作过程中,遮罩纹理已经不止限于保护某些区域使它们免于某些修改,而是可以存储任何我们希望逐像素控制的表面属性。通常,我们会充分利用一张纹理的RGBA四个通道,用于存储不同的属性。例如,我们可以把高光反射的强度存储在R通道,把边缘光照的强度存储在G通道,把高光反射的指数部分存储在B通道,最后把自发光强度存储在A通道。
    在游戏《DOTA2》的开发中,开发人员为每个模型使用了4张纹理:一张用于定义模型颜色,一张用于定义表面法线,另外两张则都是遮罩纹理。这样,两张遮罩纹理提供了共8种额外的表面属性,这使得游戏中的人物材质自由度很强,可以支持很多高级的模型属性。读者可以在他们的官网上找到关于《DOTA2》的更加详细的制作资料,包括游戏中的人物模型、纹理以及制作手册等。这是非常好的学习资料。

    光照纹理

    环境光照可以用纹理保存
    在这里插入图片描述

    遮罩纹理

    遮罩纹理(mask texture)是本章要介绍的最后一种纹理,它非常有用,在很多商业游戏中都可以见到它的身影。那么什么是遮罩呢?简单来讲,遮罩允许我们可以保护某些区域,使它们免于某些修改。例如,在之前的实现中,我们都是把高光反射应用到模型表面的所有地方,即所有的像素都使用同样大小的高光强度和高光指数。但有时,我们希望模型表面某些区域的反光强烈一些,而某些区域弱一些。为了得到更加细腻的效果,我们就可以使用一张遮罩纹理来控制光照。另一种常见的应用是在制作地形材质时需要混合多张图片,例如表现草地的纹理、表现石子的纹理、表现裸露土地的纹理等,使用遮罩纹理可以控制如何混合这些纹理。
    使用遮罩纹理的流程一般是:通过采样得到遮罩纹理的纹素值,然后使用其中某个(或某几个)通道的值(例如 texel.r)来与某种表面属性进行相乘,这样,当该通道的值为1时,可以保护表面不受该属性的影响。总而言之,使用遮罩纹理可以让美术人员更加精准(像素级别)地控制模型表面的各种性质。

    展开全文
  • 纹理映射

    千次阅读 2008-06-18 10:48:00
    这两天看纹理映射看的头大,我认为这是《Direct3D游戏入门教程》这本书写的不好的一个地方,解释的不清楚,或者说认为读者水平太高。看了第一遍没有什么感觉,又看了一遍,还是感觉不太清楚的样子。反正先写下来吧,...
    这两天看纹理映射看的头大,我认为这是《Direct3D游戏入门教程》这本书写的不好的一个地方,解释的不清楚,或者说认为读者水平太高。看了第一遍没有什么感觉,又看了一遍,还是感觉不太清楚的样子。反正先写下来吧,将来有了更多的理解再进行补充。
    -------------------
    1,要点
    首先我觉得D3D纹理映射的选项太多,给人一种眼花缭乱的感觉,而且刚看的时候并不容易分辩不同选项之间的差别,不知道如何使用这些选项,或者说不知道这些选项对应以前经验中的哪些效果。这些选现包括:
    • Dark mapping
    • Animated Dark mapping
    • Blending with Material Diffuse Color
    • Darkmap with Material Diffuse Color
    • Glow mapping
    • Detail mapping
    • Modulate mapping
    • Blending with Frame Buffer
    • Trillinear Filtering
    • Clamp Addressing Mode
    • Mirror Once
    • Border Color.
    使用的主要API就是:
    • HRESULT SetSampleState(
                     DWORD Sampler,//纹理阶段号
                     D3DSAMPLERSTATETYPE type,//采样器状态类型
                     DWORD value)//采样器状态值
    ,用于指定纹理的过滤方式,贴夹方式(tiling/clamping)和MIPLOD方式等等。
    • HRESULT SetTextureStageState(
                       DWORD Stage,//纹理阶段号
                       D3DSAMPLERSTATETYPE type,//采样器状态类型
                       DWORD value)//采样器状态值

    用于为使用固定功能的多纹理单元提供附加的操作功能。包括:不同的纹理坐标,颜色操作,alpha操作,凹凸映射/环境映射。 -------------------------------------------- 2,纹理坐标 对于一个顶点,最多允许使用八组纹理坐标(D3DFVF_TEX1到D3DFVF_TEX8),可以利用D3DTSS_TEXCOORDINDEX来选择某组特定的纹理坐标:

    m_pd3dDevice->SetTexture(0,m_pWallTexture); m_pd3dDevice->SetTextureStateState(0,D3DTSS_TEXCOORDINDEX,0); m_pd3dDevice->SetTexture(1,m_pWallTexture); m_pd3dDevice->SetTextureStateState(1,D3DTSS_TEXCOORDINDEX,1);
    上边第一张纹理使用了顶点的第一组纹理坐标,第二张纹理使用了顶点的第二组纹理坐标。当然也可以让第二张纹理也使用第一组纹理坐标,这要是情况而定。

    -------------------------------------------- 3,四种纹理寻址模式

    纹理寻址方式实在是我又查询了其他一些网站之后才知道的事情,因为以前用openGL的时候对纹理映射方式一点都没有接触过,因此这部分看起来就的确显得有点难度了。

    一般来说,分配的U、V纹理坐标值都在0.0到1.0范围内(包括它们)。但是,如果我们分配了超出这个范围的纹理坐标,可能会得到一些特别的纹理效果。通过设置纹理寻址模式,我们就可以在纹理坐标超出范围时进行控制,纹理寻址模式就是用来干这个的。

     包装(Wrapping)纹理寻址模式

    一次镜像寻址模式

    这个模式由D3DTEXTUREADDRESS枚举类型的D3DTADDRESS_MIRRORONCE成员确定,是从DirectX8才引入的新的纹理寻址模式,类似于镜像模式于夹持模式的组合。纹理再-1.0到1.0之间做镜像,而在该范围之外做夹持。

    -----------------------------------------
    4,纹理包装(Wrapping)
    简单来说,纹理Wrapping就是要改变Direct3D光栅使用纹理坐标对有纹理的多边形进行光栅操作的基本方式。我们对一个多边形进行光栅操作时,系统在每一个多边形顶点的纹理坐标之间进行内插运算,这样来决定在多边形的每个像素上所使用的纹理像素。通常,系统将纹理看作一个二维平面,在这个平面内A、B两点间的连线上进行内插。如果点A的U、V坐标为(0.8, 0.3),点B为(0.1,.9),那么进行内插的连线就如下图所示:

    pic85.gif (2608 bytes)   注意,上图中A、B两点的最短连线穿过了纹理的中间部分。U、V纹理Wrapping的使用会影响Direct3D在U、V方向上对纹理坐标间最短连线的选取。现在我们假定0.0与1.0重合,那么通过定义,纹理Wrapping就会导致光栅在纹理坐标设置之间来选择最短距离。我们可以认为一个方向上的纹理Wrapping就是让系统认为将一个纹理包裹在了一个圆筒上,就象下图中那样:

    pic86.gif (3890 bytes)

       上图中我们在U方向上进行了Wrapping,它影响了系统对纹理坐标进行的插值操作。我们使用同样的两个点A和B,可以看到,它们之间最短的连线不再通过纹理的中间部分;它现在穿越了0.0和1.0所在的交界线。沿V方向的Wrapping与它相似,只不过纹理所包裹的圆筒横躺在地上。U、V方向上同时进行Wrapping比较复杂,这时我们可以将纹理想象成一个园环面或者是面包圈的形状。    再具体说明一下,就是说如果按照U方向来包装就取U方向的最小距离线段,在该段上做插值;如果如果按照V方向来包装就取V方向的最小距离线段,然后做插值。那么设置了按U&V方式可以将纹理想象成一个环形。    需要注意的是,在启用纹理包装之后将使[0,1]之外的纹理坐标成为无效值,所以纹理包装不能于各种纹理寻址模式共用。 ----------------------------------------------

    5,纹理过滤和抗锯齿(反走样Anti-Aliasing)

    纹理过滤和反走样解决的是同一类问题,就是屏幕锯齿的问题,不同的是文理过滤解决的是纹理映射过程中的锯齿,而反走样解决的是几何体边沿的锯齿。

    • MipMap:是由一系列纹理组成的分辨率分级的特殊纹理形式。

    一个mipmap就是一系列的纹理,每一幅纹理都与前一幅是相同的图样,但是分辨率都要比前一幅有所降低。mipmap中的每一幅或者每一级图象的高和宽都比前一级小二分之一。Mipmap并不一定必须是正方形。 高分辨率的mipmap图象用于接近观察者的物体。当物体逐渐远离观察者时,使用低分辨率的图象。Mipmap可以提高场景渲染的质量,但是它的内存消耗却很大。   Direct3D将mipmap描绘成一系列相互联系的表面。高分辨率的纹理位于开始处,并与下一级纹理相互联系。以此类推,纹理相互联系,逐渐排列到分辨率最小的一级。  下面这套插图显示了这样的一个例子。这套纹理是一个三维场景中一个集装箱的标签。当我们创建了一个mipmap时,分辨率最高的一幅纹理就是这一套纹理的第一个。这套mipmap中的每一个纹理宽高都是前一个纹理宽高的二分之一。这样,最大分辨率的纹理是256x256,接下来的纹理就是128x128,最后一个纹理就是64x64。 我们有一个能看到这个标签的最大距离。如果观察者从远处向标签走近,那么场景中首先会显示最小的一幅纹理,它的大小是64x64的。

    pic84.gif (19673 bytes)pic83.gif (8944 bytes)pic82.gif (3304 bytes)

    当观察者走进标签时,我们就使用更高分辨率一幅纹理;当观察者走到允许的最近距离时,我们使用分辨率最高的那幅纹理.

      这是方法能够模拟纹理的透视效果并能够减少处理时的计算量。与将一幅纹理用于不同的分辨率相比,这种方法更加快速。   Direct3D能够访问mipmap中与我们想要输出的分辨率最接近的那个纹理设置,并将像素映射到它的纹理像素空间中。如果最终图象的分辨率在mipmap纹理的分辨率的中间,那么Direct3D会对两幅纹理中的纹理像素进行检查,并将它们的颜色值进行融合。
      提供给CreateTexture()正确的参数就可以自动创建MipMap纹理。
    • 纹理过滤方法:最近点采样,线性纹理过滤,各项异性过滤,混合过滤

       过滤是指通过给定的UV坐标从纹理贴图中获取图素的一种方法。一张64*64的纹理映射到400*400象素的多边形就会出现因放大而造成的锯齿,这称为放大问题;一张64*64的纹理映射到10*10象素的多边形的时候,一个屏幕象素对应多个纹理图素,就会因交替占有象素而出现抖动。那么为了解决这个问题,就要采用纹理过滤方法。在默认的显卡设置中,纹理过滤的方法是由驱动程序控制的。

       最近点采样是最简单的过滤方法,顾名思义,就是采用离象素最近的图素作为颜色。将纹理坐标对齐到最接近的整数,再将那个位于整数坐标的纹理图素作为最终的颜色。这种方法在处理图素边界的时候会发生一些错误。

       线性纹理过滤在Direct3D中采用的是双线性纹理过滤,它计算相对于采样点距离最近的4个图素的平均值。采用如下形式进行设置: m_pd3Device->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); m_pd3Device->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);

       三线性过滤:选择两张最接近的mipmap,将它们双线性过滤为两张理想大小的mipmap,然后根据理想的mip级组合这两张过滤厚的mipmap中的对应象素。采用如下形式进行设置: m_pd3Device->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); m_pd3Device->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); m_pd3Device->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);

    各向异性过滤:双线性过滤和三线性过滤的缺点是他们都使用正方形采样区域来采样图素,如果纹理是侧着朝向视点的化则会发生一种称之为“各向异性”的失真效果。那么各向异性过滤则会把因为透视投影拉伸的几何体大小映射回纹理空间中,使得纹理在投射时候被伸张,因此来获得更佳的深度细节和精确显示。使用各向异性过滤的代码如下: m_pd3Device->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC); m_pd3Device->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC); m_pd3Device->SetSamplerState(0,D3DSAMP_MAXD3DTEXF_ANISOTROOPY,16);

    • 反走样:现在反走样已经是DirectX中的一项默认特征。

    全屏反走样(FSAA):采用全屏多采样对每个象素进行对此采样,进行混合后进行输出,通过这种方式来调整图像中每条斜线周围的亮度来隐藏骑上的锯齿效果,它沿着这些边沿产生局部模糊的效果。一种更为高级的多采样成为“可屏蔽多采样(maskable multisampling)”。

    • alpha混合

    alpha混合不知道怎么搞到这一章来介绍,可能是为了利用这一个没有程序的篇章把该介绍的基本知识介绍完吧。我也姑且写到这里。

    alpha混合的原理很简单,就是利用混合因子把要绘制到帧缓存中的颜色和当前帧缓存中的颜色进行一个叠加,因此可以实现多次渲染,从而实现许多特效。对应的代码像下面这种形式: m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ZERO); m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCCOLOR); 原载:http://blog.sina.com.cn/u/40d00f17010001qe

      “Wrapping”纹理寻址模式由D3DTEXTUREADDRESS枚举类型的D3DTADDRESS_WRAP成员来确定,它使Direct3D在每一个整数结点(integer junction)对纹理进行重复。假设我们要创建一个正方形图元,并将纹理坐标声明为(0.0,0.0)、(0.0,3.0)、(3.0,3.0)和(3.0,0.0)。这时,如果我们设置了纹理寻址模式,就可以使纹理在U、V方向都重复三次。,如下图所示:

    pic76.gif (64086 bytes)

      这种纹理寻址模式的效果与“镜像”模式比较相似,但在本质上是不同的。

    镜像纹理寻址模式

      “镜像”纹理寻址模式由D3DTEXTUREADDRESS枚举类型的D3DTADDRESS_MIRROR成员来确定,它使Direct3D在每个整数边界处(integer boundary)对纹理进行镜像处理。想在我们创建一个正方形图元,为坐标为(0.0,0.0)、(0.0,3.0)、(3.0,3.0)和(3.0,0.0)。我们设置镜像纹理寻址模式,纹理在U、V方向都重复了三次,并且每一行、每一列都与相邻的行和列成镜像关系。如下图所示:

    pic77.gif (15582 bytes)

    钳位纹理寻址模式

      “钳位”纹理寻址模式由D3DTEXTUREADDRESS枚举类型的D3DTADDRESS_CLAMP成员确定,它使Direct3D将纹理坐标钳制在[0.0, 1.0]范围内。也就是说,它只使用一次纹理,然后将边缘像素的颜色抹去。我们创建一个正方形图元,纹理地址分配为(0.0,0.0)、(0.0,3.0)、(3.0,3.0)和(3.0,0.0)。这时,设置钳位纹理寻址模式,纹理将只使用一次,并且最顶一行和最后一列上的像素颜色会一直延伸到图元的最顶端和最右段,如下图所示:

    pic78.gif (5443 bytes)

     

    边界颜色纹理寻址模式

      “边缘颜色”纹理寻址模式由D3DTEXTUREADDRESS枚举类型的D3DTADDRESS_BORDER成员确定,它使Direct3D可以在纹理坐标超过范围的地方使用一个任意的颜色,也就是边界颜色。

      下图中展示了一个使用了纹理的图元,它使用了红色的边界色:

    pic79.gif (5657 bytes)

    展开全文
  • 用VS2013配置PCL后可以运行此程序,程序有PCL的属性列表,改一下就好,此程序为VTK的纹理映射体绘制_三维纹理映射,内含vtk文件
  • 【OpenCV】基本的纹理映射,实现纹理映射效果1.绘制目标2.核心代码3.运行结果 1.绘制目标 练习基本的纹理映射,请实现如下纹理映射效果。 2.核心代码 // 处理加载进来的图像 Mat LoadImage(const string& ...

    【OpenCV】基本的纹理映射,实现纹理映射效果

    1.绘制目标

    1. 练习基本的纹理映射,请实现如下纹理映射效果。
      在这里插入图片描述

    2.核心代码

    // 处理加载进来的图像
    Mat LoadImage(const string& fname, bool bAlpha = true) 
    {
    	if (bAlpha) 
    	{
    		Mat img_bgra = imread(fname, IMREAD_UNCHANGED);
    		if (img_bgra.empty()) 
    		{
    			cout << "Failed load the image!" << endl;
    			return img_bgra;
    		}
    		flip(img_bgra, img_bgra, 0);
    		Mat img_rgba;
    		cvtColor(img_bgra, img_rgba, COLOR_BGRA2RGBA);
    		return img_rgba;
    	}
    	else 
    	{
    		Mat img_bgr = imread(fname, IMREAD_COLOR);
    		if (img_bgr.empty()) 
    		{
    			cout << "Failed load the image!" << endl;
    			return img_bgr;
    		}
    		flip(img_bgr, img_bgr, 0);
    		Mat img_rgb;
    		cvtColor(img_bgr, img_rgb, COLOR_BGR2RGB);
    		return img_rgb;
    	}
    }
    
    // 加载外部的纹理图	
    void LoadExternalTexture() 
    {
    	// 加载纹理图
    	//Mat img_rgba = LoadImage("Brick.jpg", true);
    	//Mat img_rgba = LoadImage("smile.png", true);
    	Mat img_rgba = LoadImage("monkey.png", true);
    
    	// 绑定纹理图
    	glBindTexture(GL_TEXTURE_2D, TEXTURE_ID);
    	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img_rgba.size[1], img_rgba.size[0], 0, GL_RGBA, GL_UNSIGNED_BYTE, img_rgba.data);
    
    	// 设置纹理平铺属性
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    
    	// 设置纹理滤波属性
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    }
    
    void init() {
    	glClearColor(1.f, 1.f, 1.f, 0.f);
    
    	// 创建纹理图ID
    	glGenTextures(1, &TEXTURE_ID);
    
    	// 加载纹理图
    	LoadExternalTexture();
    
    	// 设置纹理环境
    	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    
    	// 开启纹理映射
    	glEnable(GL_TEXTURE_2D);
    }
    
    void NewFunction5_1()
    {
    	glBegin(GL_TRIANGLE_STRIP);
    	glTexCoord2f(0.f, 1.f); glVertex2f(-160.f, 150.f);
    	glTexCoord2f(0.f, 0.f); glVertex2f(-160.f, -150.f);
    	glTexCoord2f(0.5f, 1.f); glVertex2f(0.f, 150.f);
    	glTexCoord2f(1.0f, 0.f); glVertex2f(120.f, -150.f);
    	glTexCoord2f(1.f, 0.5f); glVertex2f(160.f, 0.f);
    	glEnd();
    }
    

    3.运行结果

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 1.三维纹理映射 目前市面上的能多先科都是支持三维纹理映射的。利用三维纹理映射,将体数据映射至一组与视图平面平行的多边形,避免了二维纹理映射方法中因为纹理图像的切换造成的瑕疵。VTK中三维纹理映射体绘制...

    1.三维纹理映射

    目前市面上的能多先科都是支持三维纹理映射的。利用三维纹理映射,将体数据映射至一组与视图平面平行的多边形,避免了二维纹理映射方法中因为纹理图像的切换造成的瑕疵。VTK中三维纹理映射体绘制方法由vtkVolumeTexture3D类实现,使用方法与二维纹理映射体绘制方法一致。(实时渲染效果真的是非常好)
    代码如下:
     

    #include <vtkAutoInit.h>
    VTK_MODULE_INIT(vtkRenderingOpenGL);
    VTK_MODULE_INIT(vtkRenderingVolumeOpenGL);
    VTK_MODULE_INIT(vtkRenderingFreeType);
    VTK_MODULE_INIT(vtkInteractionStyle);
     
    #include <vtkSmartPointer.h>
    #include <vtkStructuredPoints.h>
    #include <vtkStructuredPointsReader.h>
    //#include <vtkVolumeTextureMapper2D.h>
    #include <vtkVolumeTextureMapper3D.h>
    #include <vtkColorTransferFunction.h>
    #include <vtkPiecewiseFunction.h>
    #include <vtkRenderer.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>
    #include <vtkVolumeProperty.h>
    #include <vtkVolumeRayCastIsosurfaceFunction.h>
     
    int main(int argc, char *argv[])
    {
    	vtkSmartPointer<vtkStructuredPointsReader> reader =
    		vtkSmartPointer<vtkStructuredPointsReader>::New();
    	reader->SetFileName("mummy.128.vtk");
    	reader->Update();
     
     
    	/*vtkSmartPointer<vtkVolumeTextureMapper2D> volumeMapper =
    		vtkSmartPointer<vtkVolumeTextureMapper2D>::New();
    	volumeMapper->SetInputData(reader->GetOutput());;*/
    	
    	vtkSmartPointer<vtkVolumeTextureMapper3D> volumeMapper =
    		vtkSmartPointer<vtkVolumeTextureMapper3D>::New();
    	volumeMapper->SetInputData(reader->GetOutput());;
    	/*************************************************************************/
    	vtkSmartPointer<vtkVolumeProperty> volumeProperty =
    		vtkSmartPointer<vtkVolumeProperty>::New();
    	volumeProperty->SetInterpolationTypeToLinear();
    	volumeProperty->ShadeOn();  //打开或者关闭阴影测试
    	volumeProperty->SetAmbient(0.4);
    	volumeProperty->SetDiffuse(0.6);  //漫反射
    	volumeProperty->SetSpecular(0.2); //镜面反射
    	//设置不透明度
    	vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity =
    		vtkSmartPointer<vtkPiecewiseFunction>::New();
    	compositeOpacity->AddPoint(70, 0.00);
    	compositeOpacity->AddPoint(90, 0.40);
    	compositeOpacity->AddPoint(180, 0.60);
    	volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数
    	
    	//设置颜色属性
    	vtkSmartPointer<vtkColorTransferFunction> color =
    		vtkSmartPointer<vtkColorTransferFunction>::New();
    	color->AddRGBPoint(0.000, 0.00, 0.00, 0.00);
    	color->AddRGBPoint(64.00, 1.00, 0.52, 0.30);
    	color->AddRGBPoint(190.0, 1.00, 1.00, 1.00);
    	color->AddRGBPoint(220.0, 0.20, 0.20, 0.20);
    	volumeProperty->SetColor(color);
    	/********************************************************************************/
    	vtkSmartPointer<vtkVolume> volume =
    		vtkSmartPointer<vtkVolume>::New();
    	volume->SetMapper(volumeMapper);
    	volume->SetProperty(volumeProperty);
     
    	vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
    	ren->SetBackground(0, 1, 0);
    	ren->AddVolume(volume);
     
    	vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();
    	rw->AddRenderer(ren);
    	rw->SetSize(480, 480);
    	rw->Render();
    	rw->SetWindowName("VolumeRendering by Texture2D");
     
    	vtkSmartPointer<vtkRenderWindowInteractor> rwi =
    		vtkSmartPointer<vtkRenderWindowInteractor>::New();
    	rwi->SetRenderWindow(rw);
     
    	ren->ResetCamera();
    	rw->Render();
    	rwi->Start();
     
    	return 0;
    }

    输出图像如下:

     2.硬件上的限制

    受硬件纹理空间限制,当数据传递至vtkVolumeTextureMapper3D中后,在内部会进行重采样,以确保图像大小能过满足当前的纹理空间。默认情况下,对于单组分数据的纹理最大为256:256:128;四元非独立数据最大为256:128:128。三维纹理映射仅支持两种类型的显卡:NVIDIA和ATI。为了确保程序能够正确运行,其内部定义了核对函数:

    int ISRenderSupported(vtkVolumeProperty* , vtkRenderer* );

    用来判断是否支持当前的渲染,避免出现错误,使用方法如下:

    int valid = volumeMapper->IsRenderSupported(volumeProperty,ren);

    当软件程序检查到显卡类型满足时,就会返回TRUE。

    3.VTK中体绘制渲染总结

    VTK中不同的vtkVolumeMapper支持不同的数据类型。
    vtkVolumeRayCastMapper和vtkVolumeTextureMapper2D仅支持VTK_UNSIGNED_CHAR 和VTK_UNSIGNED_SHORT类型数据。当涉及到其他类型数据时,需要做数据强制转换,可以考虑使用vtkImageCast或vtkImageShiftScale类。
    vtkVolumeTextureMapper3D则支持任意类型数据,当然必须输单组分数据或者是多元独立数据。
    VTKFixedPointVolumeRayCastMapper灵活性最高,支持所有类型数据,最该可以支持四元数据。
     

    展开全文
  • OpenGL 纹理映射

    2018-07-16 08:51:05
    学习 texture map 纹理映射(贴图)有很多好处。比方说您想让一颗导弹飞过屏幕。根据前几课的知识,我们最可行的办法可能是很多个多边形来构建导弹的轮廓并加上有趣的颜色。使用纹理映射,您可以使用真实的导弹图像并...
  • 1.三维纹理映射 目前市面上的能多先科都是支持三维纹理映射的。利用三维纹理映射,将体数据映射至一组与视图平面平行的多边形,避免了二维纹理映射方法中因为纹理图像的切换造成的瑕疵。VTK中三维纹理映射体...
  • Directx11教程(43) 纹理映射(13)-动态纹理映射 原文:Directx11教程(43) 纹理映射(13)-动态纹理映射 本篇教程中,我们将在前面基于光照的地形与水面程序里面加上纹理映射,而且我们会基于时间动态改变...
  • 纹理映射概述

    2021-01-13 19:22:08
    纹理映射基本概念 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这 提示:文章写完后,目录可以自动生成,如何生成可参考右边...
  • 纹理映射算法

    2018-01-03 22:26:17
    使用OpenGL实现了针对简单3D物体的纹理映射算法,在VC++6.0中能够编译通过。
  • Qt_OpenGL纹理映射

    2019-05-03 15:55:54
    纹理映射基础知识 什么叫纹理映射,一开始我也不明白,感觉这个词好专业(毕竟没有学过图形学),后面经过网上查找资料和这次实验稍微理解了点。纹理映射简单的讲,就是把一个纹理(其实说白了,纹理可以理解为一幅图像...
  • 基于系数图和基本纹理图的纹理映射
  • cg纹理映射

    2015-07-31 10:34:29
    unity的shaderlab做的纹理映射shader
  • 1.纹理映射体绘制 基于软件实现的光线投影体绘制算法计算量非常大,不利于进行实时渲染。因此,目前体绘制经常使用图形硬件利用纹理映射来加速。 其主要原理是将三维体数据作为纹理装载入硬件缓存中,利用硬件来...
  • vtk纹理映射

    2020-11-03 14:37:11
    vtk 纹理映射 原理:渲染时把二维的图像"贴"到物体的表面上,根据二维图像渲染出丰富多彩的效果,所以也叫纹理贴图。纹理映射需要三个要素:待贴图的表面、纹理映射以及纹理坐标。 example code #include <...
  • 纹理映射基础

    2012-07-12 19:06:42
    纹理映射基础
  • MATLAB——纹理映射

    2018-08-27 16:39:46
    本代码主要利用MATLAB工具实现MATLAB——纹理映射,简单明了,易于理解

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,340
精华内容 1,336
关键字:

纹理映射