高级纹理知识

矩形纹理

纹理目标为GL_TEXTURE_RECTANGLE。

首选,矩形纹理不能进行Mip贴图;

然后,矩形纹理不是标准化的(实际上是对像素寻址)

最后,纹理坐标不能重复,并且不支持纹理压缩

加载矩形纹理

bool LoadTGATextureRect(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
    {
    GLbyte *pBits;
    int nWidth, nHeight, nComponents;
    GLenum eFormat;

    // 读入纹理位
    pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
    if(pBits == NULL)
        return false;

    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, wrapMode);
    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, wrapMode);

    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, minFilter);
    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, magFilter);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_RECTANGLE, 0, nComponents, nWidth, nHeight, 0,
                 eFormat, GL_UNSIGNED_BYTE, pBits);

    free(pBits);

    return true;
    }

使用矩形纹理

加载矩形纹理:

    glBindTexture(GL_TEXTURE_RECTANGLE, uiTextures[3]);
    LoadTGATextureRect("OpenGL-Logo.tga", GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE);

对矩形纹理投影矩阵的设置:

    M3DMatrix44f mScreenSpace;
m3dMakeOrthographicMatrix(mScreenSpace, 0.0f, 800.0f, 0.0f, 600.0f, -1.0f, 1.0f);

设置矩形纹理从0.0到标志宽度或者高度范围内的纹理坐标:

    int x = 500;    int y = 155;    int width = 300;    int height = 155;   logoBatch.Begin(GL_TRIANGLE_FAN, 4, 1);

        // Upper left hand corner
        logoBatch.MultiTexCoord2f(0, 0.0f, height);
        logoBatch.Vertex3f(x, y, 0.0);

        // Lower left hand corner
        logoBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
        logoBatch.Vertex3f(x, y - height, 0.0f);

        // Lower right hand corner
        logoBatch.MultiTexCoord2f(0, width, 0.0f);
        logoBatch.Vertex3f(x + width, y - height, 0.0f);

        // Upper righ hand corner
        logoBatch.MultiTexCoord2f(0, width, height);
        logoBatch.Vertex3f(x + width, y, 0.0f);

    logoBatch.End();

矩形纹理的贴图着色器需要将采样器从sampler2D改变成samplerRect类型:

// Rectangle Texture (replace) Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 140

out vec4 vFragColor;

uniform sampler2DRect  rectangleImage;

smooth in vec2 vVaryingTexCoord;

void main(void)
    {
    vFragColor = texture(rectangleImage, vVaryingTexCoord);
}

立方体贴图

立方体贴图是作为一个单独的由组成立方体6个面的6个正方形的2D图像组成的纹理对象看待。

加载立方体贴图

立方体贴图新增了以下6个值,这些值可以传递到glTexImage2D:

GL_TEXTURE_CUBE_MAP_POSITIVE_X,GL_TEXTURE_CUBE_MAP_NEGATIVE_X,

GL_TEXTURE_CUBE_MAP_POSITIVE_Y,GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,

GL_TEXTURE_CUBE_MAP_POSITIVE_Z,GL_TEXTURE_CUBE_MAP_NEGATIVE_Z.

例如,要加载x轴正方向的贴图:

glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,0,GL_RGBA,iWidth,iHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,pImage);

创建天空盒

例如,我们创建一个在每个方向到原点距离都为20个单位长度的立方体:

gltMakeCube(cubeBatch,20.0f);

然后使用如下着色器对从立方体的中心指向每个角的向量标准化:

立方体贴图顶点着色器

// Skybox Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130

// Incoming per vertex... just the position
in vec4 vVertex;

uniform mat4   mvpMatrix;  // Transformation matrix

// Texture Coordinate to fragment program
varying vec3 vVaryingTexCoord;

void main(void)
    {
    // Pass on the texture coordinates
    vVaryingTexCoord = normalize(vVertex.xyz);

    // Don‘t forget to transform the geometry!
    gl_Position = mvpMatrix * vVertex;
}

立方体贴图片段着色器

// Skybox Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130

out vec4 vFragColor;

uniform samplerCube  cubeMap;

varying vec3 vVaryingTexCoord;

void main(void)
    {
    vFragColor = texture(cubeMap, vVaryingTexCoord);
}

最后消除立方体边缘的缝隙:

glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);

创建反射

首先必须使用表面法线和指向顶点的向量在着色器中创建一个视觉坐标系中的反射向量。另外,为了获得一个真实的反射,还要考虑照相机的方向。从GLFrame类中提取照相机的旋转矩阵并进行转置。然后将其作为统一值,与另一个变换矩阵(用来与前述的反射向量进行旋转,这个反射实际上就是立方体贴图纹理坐标)一起提供给着色器。

// Reflection Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130

// Incoming per vertex... position and normal
in vec4 vVertex;
in vec3 vNormal;

uniform mat4   mvpMatrix;
uniform mat4   mvMatrix;
uniform mat3   normalMatrix;
uniform mat4   mInverseCamera;

// Texture coordinate to fragment program
smooth out vec3 vVaryingTexCoord;

void main(void)
    {
    // Normal in Eye Space
    vec3 vEyeNormal = normalMatrix * vNormal;

    // Vertex position in Eye Space
    vec4 vVert4 = mvMatrix * vVertex;
    vec3 vEyeVertex = normalize(vVert4.xyz / vVert4.w);

    // Get reflected vector
    vec4 vCoords = vec4(reflect(vEyeVertex, vEyeNormal), 1.0);

    // Rotate by flipped camera
    vCoords = mInverseCamera * vCoords;
    vVaryingTexCoord.xyz = normalize(vCoords.xyz);

    // Don‘t forget to transform the geometry!
    gl_Position = mvpMatrix * vVertex;
}

多重纹理

片段着色器中的单个统一值是我们将要绑定到的纹理单元的索引,我们可以对实现进行查询,来查看支持的纹理单元数量:

Glint iUnits;
glGetIntegerv(GL_MAX_TEXTURE_UNITS,&iUnits);

我们可以通过调用以纹理单元标识符为变量的glActiveTexture来改变当前纹理单元:

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,textureID);

多重纹理坐标

在调用以nTextureUnits为参数的Begin函数时,我们最多可以指定4组纹理坐标:

void GLBatch::Begin(GLenum primitive,GLuint nVerts,GLuint nTextureUnits=0);

CopyTexCoordData2f会一次复制整个一组纹理坐标:

void GLBatch::CopyTexCoordData2f(M3DVector2f *vTexCoords,GLuint uiTextureLayer);

而下面的方法则会每次提供纹理一个顶点的接口,速度较慢:

void GLBatch::MultiTexCoord2f(GLuint texture,GLclampf s,GLclampf t);
void GLBatch::MultiTexCoord2fv(GLuint texture,M3DVector2f vTexCoord);

点精灵(点块纹理)

使用点精灵,我们可以通过绘制一个3D点将一个2D纹理图像显示在屏幕的任意位置上。

店精灵允许我们通过发送单个3D顶点,渲染一个完美对其的纹理2D多边形,他所需要的带宽只有为四边形发送4个顶点所需带宽的四分之一,并且不需要客户端的矩阵逻辑来保持3D四边形与照相机的对其。

使用点

在客户端,我们需要做的指示简单地绑定一个2D纹理;

// SpaceFlight Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130

out vec4 vFragColor;

in vec4 vStarColor;

uniform sampler2D  starImage;

void main(void)
    {
    vFragColor = texture(starImage, gl_PointCoord) * vStarColor;
}

点大小

有两种方式可以设置点大小。第一种方式是glPointSize函数:

void glPointSize(GLfloat size);

我们也可以在顶点着色器中用程序设置点大小。首先启用点大小模式:

glEnable(GL_PROGRAM_POINT_SIZE);

然后,在我们的低昂点程序中,可以设置一个内建变量gl_PointSize,这个变量确定了点的最终光栅化大小。这通常用来根据点的距离来确定它的大小。

点参数

通过glPointParameter函数,我们可以对店精灵的几个特性进行微调。将GL_POINT_SPRITE_COORD_ORIGIN参数设置为GL_LOWER_LEFT,可以将纹理坐标系的原点放置在点的左下角,点精灵的默认方向为GL_UPPER_LEFT

glPointParameteri(GL_POINT_SPRITE_COORD_ORGIN,GL_LOWER_LEFT);

异形点

我们可以在片段着色器中使用discard关键字来丢弃位域我们想要的点形状范围之外的片段,从而创建出非正方形的点。

vec2 p=gl_PointCoord*2.0-vec2(1.0);
if(dot(p,p)>1.0)
    discard;

点的旋转

要让点旋转,我们只需在片段着色器中创建一个2D旋转矩阵,并用它乘以gl_PointCoord使它围绕z轴进行旋转。旋转的角度可以从顶点着色器或者集合着色器中作为一个插值变量传递到片段着色器。

纹理数组

在纹理数组中,我们可以将整个数组的纹理图县绑定到一个纹理对象上,然后阻碍着色器中对它们进行检索,这样就大大增加了着色器可用的文礼书局的数量。

加载2D纹理数组

纹理数组添加了两个新的纹理对象作为大多数文理管理函数的有效参数,他们是GL_TEXTURE_1D_ARRAY和GL_TEXTURE_2D_ARRAY。

GLuint  moonTexture;
……
    glGenTextures(1, &moonTexture);
    glBindTexture(GL_TEXTURE_2D_ARRAY, moonTexture);

纹理参数、环绕模式和过滤器的情况也是如此:

    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

对于2D纹理数组来说,我们使用管理TexImageD函数来加载纹理数据:

void glTexImage3D(GLenum target,Glint level,Glint internalformat,GLsizei width,GLsizei height,GLsizei depth,Glint border,GLenum format,GLenum type,void *data);

然后,我们使用glTexSubImageXD函数族来更新纹理。例如要保留29个64X64的RGBA图像,代码应如下所示:

glTexImage3D(GL_TEXTURE_2D_ARRAY,0,GL_RGBA,64,64,29,0,GL_BGRA,GL_UNSIGNED_BYTE,NULL);

纹理数组索引

在进行渲染前,下面的代码会在顶点着色器中设置恰当的统一值:

    float fTime = timer.GetElapsedSeconds();
    fTime = fmod(fTime, 28.0f);
    glUniform1f(locTimeStamp, fTime);

moonBatch.Draw();

在顶点着色器中,我们将包含经过实践的统一值放在vec3的p变量中在随后的片段着色器中使用:

// MoonShader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130

in vec4 vVertex;
in vec4 vTexCoords;

uniform mat4 mvpMatrix;
uniform float fTime;

smooth out vec3 vMoonCoords;

void main(void)
    {
    vMoonCoords.st = vTexCoords.st;
    vMoonCoords.p = fTime;

    gl_Position = mvpMatrix * vVertex;
}

访问纹理数组

// MoonShader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130

out vec4 vFragColor;

uniform sampler2DArray moonImage;

smooth in vec3 vMoonCoords;

void main(void)
   {
   vFragColor = texture2DArray(moonImage, vMoonCoords);
   }

纹理代理

下面方法可以获得一个一维或二维纹理贴图(或者也可以用特定纹理类型如GL_MAX_3D_TEXTURE_SIZE和GL_MAX_CUBE_MAP_TEXTURE_SIZE)最大宽度或者最大高度的下限:

Glint maxSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxSize);

要弄清是否支持某种特定的纹理大小和格式,我们可以使用一个纹理代理。纹理代理不占用内存空间也无法应用到几何图形上,仅仅用来尝试。

例如,为了查明是否能够整整加载一个2048X4096的BGRA纹理,我们可以创建类似下面这样的代理:

glTexImage2D(GL_PROXY_TEXTURE_2D,0,GL_RGBA,2048,4096,0,GL_BGRA,GL_UNSIGNED_BYTE,NULL);

然后查看是否支持相应的高度4096:

void glGetTexLevelParameter(GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height);

转载请注明出处:http://blog.csdn.net/ylbs110/article/details/51926110

说明

由于超级宝典版本太老了,决定本周开始改学习编程指南第8版。

时间: 2024-08-04 22:37:10

高级纹理知识的相关文章

【Unity Shader】(九) ------ 高级纹理之渲染纹理及镜子与玻璃效果的实现

笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Shader](三) ------ 光照模型原理及漫反射和高光反射的实现 [Unity Shader](四) ------ 纹理之法线纹理.单张纹理及遮罩纹理的实现 [Unity Shader](五) ------ 透明效果之半透明效果的实现及原理 [Unity Shader](六) ------ 复杂的光照(上) [Unity

Unity_二维纹理 Texture 2D_2_高级纹理

The Advanced Texture Importer Settings dialog 高级纹理导入器设置对话框 Non Power of 2 不是2的幂:如果纹理大小不是2的幂,这将定义在导入时的缩放行为(更多信息请参阅下文纹理尺寸部分): None 无:纹理将被填充到下一个较大的2的幂大小以便与GUI纹理组件使用.(真别扭!) To nearest 到最近的:纹理在导入时将被缩放到最近的幂大小.例如257x511纹理将成为256x512.请注意,PVRTC格式要求纹理是正方形(宽度与高度

整理JavaScript高级基础知识

整理JavaScript高级基础知识 因为空余时间很多..所以博客更新频率得相对频繁些.. 原型以及原型链 考察原型以及原型链: var object = {} object.__proto__ === Object.prototype // 为 true var fn = function(){} fn.__proto__ === Function.prototype // 为 true fn.__proto__.__proto__ === Object.prototype // 为 true

[HTTP] 高级基础知识整理

HTTP 高级基础知识 整理 HTTP 高级基础知识,包括 Cookie / Session / localStorage / sessionStorage / Cache-Control / Expires / Etag 等 Cookie cookie :wiki Cookie(复数形态Cookies),又称为"小甜饼".中文名称为"小型文本文件",指某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密) -wiki coo

全基因组重测序基础及高级分析知识汇总

全基因组重测序基础及高级分析知识汇总 oddxix 已关注 2018.09.20 17:04 字数 11355 阅读 212评论 0喜欢 6 转自:http://www.360doc.com/content/18/0208/11/19913717_728563847.shtml 全基因组重测序是通过对已有参考序列(Reference Sequence)的物种的不同个体进行基因组测序,并以此为基础进行个体或群体水平的遗传差异性分析.通过全基因组重测序,研究者可以找到大量的单核苷酸多态性位点(SNP

【Unity Shader】(八) ------ 高级纹理(上)

笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题.    [Unity Shader](三) ------ 光照模型原理及漫反射和高光反射的实现    [Unity Shader](四) ------ 纹理之法线纹理.单张纹理及遮罩纹理的实现    [Unity Shader](五) ------ 透明效果之半透明效果的实现及原理    [Unity Shader](六) ------ 复杂的光

Android高级开发知识总结

第1篇 基础篇 第1章 Android触摸事件传递机制 1.1 触摸事件的类型 1.2 事件传递的三个阶段 1.3 View的事件传递机制 1.4 ViewGroup的事件传递机制 第2章 Android View的绘制流程 2.1 绘制的整体流程 2.2 MeasureSpec 2.3 Measure 2.4 Layout 2.5 Draw 第3章 Android 动画机制 3.1 逐帧动画(Frame Animation) 3.1.1 XML 资源文件方式 3.1.2 代码方式 3.2 补间

Core Animation高级理论知识汇总

一. 基本概念 Core Animation其实是一个令人误解的命名.你可能认为它只是用来做动画的,但实际上它是从一个叫做Layer Kit这么一个不怎么和动画有关的名字演变而来,所以做动画这只是Core Animation特性的冰山一角.Core Animation是一个复合引擎,它的职责就是尽可能快地组合屏幕上不同的可视内容,这个内容是被分解成独立的图层,存储在一个叫做图层树的体系之中.于是这个树形成了UIKit以及在iOS应用程序当中你所能在屏幕上看见的一切的基础.和UIView最大的不同

2016峰会:项目管理与高级项目管理(广州站)

1.    高端峰会:项目管理与高级项目管理 项目管理及公司管理中遇到的各类问题: 疲于应对需求变更,客户过于"强势"而无法控制: 项目成员的"闷骚".各种沟通障碍和各种技能不足: 进度压力大,加班和牺牲软件质量,反而导致更多项目延期: 项目成本严重超支: 加班再加班,问题还是持续滚雪球: 没有风险意识,不会危机处理: 项目没有积累,如:没有资产库,人员不稳定等等: -- 公司需要给力的项目经理, 你就是这位项目经理!公司需要项目管理水平的整体提升!这次高端峰会,为