GLSL纹理贴图 【转】

时间:2023-02-20 08:57:42
转载:http://blog.csdn.net/hgl868/article/details/7872466

简单的纹理贴图(Simple Texture)

为了在GLSL中应用纹理,我们需要访问每个顶点的纹理坐标。GLSL中提供了一些属性变量,每个纹理单元一个:

attribute vec4 gl_MultiTexCoord0;
attribute vec4 gl_MultiTexCoord1;
attribute vec4 gl_MultiTexCoord2;
attribute vec4 gl_MultiTexCoord3;
attribute vec4 gl_MultiTexCoord4;
attribute vec4 gl_MultiTexCoord5;
attribute vec4 gl_MultiTexCoord6;
attribute vec4 gl_MultiTexCoord7;

GLSL还为访问每个纹理的纹理矩阵提供了一个一致变量数组:

uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];

顶点shader可以通过上面所示的内容访问OpenGL程序中指定的纹理坐标。然后必须为每个顶点计算纹理坐标,并保存在预先定义的易变变量gl_TexCoord[i]中,i表示纹理单元号。

下面这条语句直接复制OpenGL程序中指定的纹理坐标,作为纹理单元0的顶点纹理坐标。

gl_TexCoord[0]  = gl_MultiTexCoord0;

下面是个简单的例子,在顶点shader中设置纹理单元0的纹理坐标。

void main()
{
   
gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position
= ftransform();
}

如果你想使用纹理矩阵,可以这样操作:

void main()
{
   
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
    gl_Position
= ftransform();
}

前面说过,gl_TexCoord是一个易变变量,所以在片断shder中可以访问经过插值的纹理坐标。
为了访问纹理的数值,在片断shader中有必要声明一个特殊的变量,对一个2D纹理可以可以这样写:

uniform sampler2D tex;

如果是1D或者3D的纹理,可以改成sampler1D和sampler3D。
这个用户定义的变量tex包含我们将会使用的纹理单元,通过texture2D函数我们可以得到一个纹素(texel),这是一个纹理图片中的像素。函数参数分别为simpler2D以及纹理坐标:

vec4 texture2D(sampler2D, vec2);

函数的返回值已经考虑了所有在OpenGL程序中定义的纹理设置,比如过滤、mipmap、clamp等。
我们的片断shader可以写成如下形式:

uniform sampler2D tex;

void main()
{
    vec4 color =
texture2D(tex,gl_TexCoord[0].st);
    gl_FragColor
= color;
}

注意访问gl_TexCoord时选择子st的使用。在本教程前面关于数据类型和变量的讨论中说过,访问纹理坐标时可以使用如下选择子:s、t、p、q。(r因为和rgb选择子冲突而没有使用)

GLSL纹理贴图 【转】

本节内容Shader Designer的工程下载地址:
http://www.lighthouse3d.com/wp-content/uploads/2011/03/textureSimple.zip

组合纹理与片断

OpenGL允许我们通过多种方式将纹理颜色和片断颜色联合到一起。下表显示了RGBA模式时可用的联合方式:

GL_REPLACE C =
Ct
A =
At
GL_MODULATE C =
Ct*Cf
A =
At*Af
GL_DECAL C =
Cf * (1 – At) + Ct * At
A =
Af

表中Ct和At表示纹理的颜色和alpha值,Cf和Af表示片断(fragment)的颜色和alpha值,C和A表示最终的颜色和alpha值。

上一节的例子就相当于使用了GL_REPLACE模式。下面我们我们准备在一个立方体上实现与GL_MODULATE等同的效果。两个shader只计算使用一个白色方向光的散射以及环境光成分,关于材质的完整定义请参照光照有关的章节。

因为使用了光照,所以顶点shader中必须处理法线信息。必须将法线变换到视图空间然后归一化,光线方向向量也必须归一化(光线方向向量已经由OpenGL变换到了视图空间)。现在新的顶点shader如下:

varying vec3 lightDir,normal;

void main()
{
    normal =
normalize(gl_NormalMatrix * gl_Normal);

lightDir =
normalize(vec3(gl_LightSource[0].position));
   
gl_TexCoord[0] = gl_MultiTexCoord0;

gl_Position
= ftransform();
}

在片断shader中,光照得到的片断的颜色和alpha值在cf和af中分别计算。shader中剩余代码按照GL_MODULATE的公式计算:

varying vec3 lightDir,normal;
uniform sampler2D tex;

void main()
{
    vec3
ct,cf;
    vec4
texel;
    float
intensity,at,af;

intensity =
max(dot(lightDir,normalize(normal)),0.0);
    cf =
intensity * (gl_FrontMaterial.diffuse).rgb +
                 
gl_FrontMaterial.ambient.rgb;
    af =
gl_FrontMaterial.diffuse.a;

texel =
texture2D(tex,gl_TexCoord[0].st);
    ct =
texel.rgb;
    at =
texel.a;

gl_FragColor
= vec4(ct * cf, at * af);
}

GLSL纹理贴图 【转】

Shader Designer的工程下载地址:
http://www.lighthouse3d.com/wp-content/uploads/2011/03/textureComb.zip

多重纹理
在GLSL中实现多重纹理十分容易,我们只需要访问所有纹理即可。因为我们打算给每个纹理使用相同的纹理坐标,所以顶点shader不需要改动。片断shader中只需要进行些许改动,加上多个纹理的颜色值。

varying vec3 lightDir,normal;
uniform sampler2D tex;

void main()
{
    vec3
ct,cf;
    vec4
texel;
    float
intensity,at,af;

intensity =
max(dot(lightDir,normalize(normal)),0.0);
    cf =
intensity * (gl_FrontMaterial.diffuse).rgb +
                 
gl_FrontMaterial.ambient.rgb;
    af =
gl_FrontMaterial.diffuse.a;

texel =
texture2D(tex,gl_TexCoord[0].st) +
         
texture2D(l3d,gl_TexCoord[0].st);
    ct =
texel.rgb;
    at =
texel.a;

gl_FragColor
= vec4(ct * cf, at * af);
}

效果如下:

GLSL纹理贴图 【转】

下面添加点不同的效果:在黑暗中发光。我们希望第二个纹理能在黑暗中发光,在没有光照时达到最亮,在有光照时变暗。

GLSL纹理贴图 【转】

我们通过两步计算最终的颜色:首先将第一个纹理与片断颜色进行modulate计算,然后根据光照强度(indensity)加上第二个纹理单元。

如果indensity是0,第二个纹理单元取最大值,如果indensity为1,只取第二个纹理单元颜色的10%,当indensity在0和1之间时按这两个大小进行插值。可以使用smoothstep函数实现这个要求:

genType smoothStep(genType edge0, genType edge1, genType x);

如果x <= edge0结果是0,如果x >= edge1结果为1,如果edge0 < x <
edge1结果在0和1之间进行Hermite插值。在本例中我们按如下方式调用:
coef = smoothStep(1.0, 0.2, intensity);
下面的片断shader实现了需要的效果:

varying vec3 lightDir,normal;
uniform sampler2D tex,l3d;

void main()
{
    vec3
ct,cf,c;
    vec4
texel;
    float
intensity,at,af,a;

intensity =
max(dot(lightDir,normalize(normal)),0.0);

cf =
intensity * (gl_FrontMaterial.diffuse).rgb +
                     
gl_FrontMaterial.ambient.rgb;
    af =
gl_FrontMaterial.diffuse.a;

texel =
texture2D(tex,gl_TexCoord[0].st);

ct =
texel.rgb;
    at =
texel.a;

c = cf *
ct;
    a = af *
at;

float coef =
smoothstep(1.0,0.2,intensity);
    c += coef
*  vec3(texture2D(l3d,gl_TexCoord[0].st));

gl_FragColor
= vec4(c, a);
}

Shader Designer的工程下载地址:
http://www.lighthouse3d.com/wp-content/uploads/2011/03/textureGlow.zip

GLSL纹理贴图 【转】的更多相关文章

  1. GLSL 纹理贴图

    #include <ork/render/FrameBuffer.h> #include <ork/scenegraph/SceneManager.h> #include &l ...

  2. 【GLSL教程】(八)纹理贴图 【转】

    http://blog.csdn.net/racehorse/article/details/6664717 简单的纹理贴图(Simple Texture) 为了在GLSL中应用纹理,我们需要访问每个 ...

  3. 关于OpenGL&plus;GLSL深度贴图采样

    作者:Nin+.Lee 邮箱:lilei9110@gmail.com * 本文属原创,转载请注明出处. 在GLSL中,存在着sampler2D和sampler2DShadow两种2D贴图采样器.在对一 ...

  4. Android OpenGL ES 开发(九)&colon; OpenGL ES 纹理贴图

    一.概念 一般说来,纹理是表示物体表面的一幅或几幅二维图形,也称纹理贴图(texture).当把纹理按照特定的方式映射到物体表面上的时候,能使物体看上去更加真实.当前流行的图形系统中,纹理绘制已经成为 ...

  5. (转)使用OpenGL显示图像(七)Android OpenGLES2&period;0——纹理贴图之显示图片

    转:http://blog.csdn.net/junzia/article/details/52842816 前面几篇博客,我们将了Android中利用OpenGL ES 2.0绘制各种形体,并在上一 ...

  6. &lbrack;Unity&rsqb; Shader&lpar;着色器)之纹理贴图

    在Shader中,我们除了可以设定各种光线处理外,还可以增加纹理贴图. 使用 settexture 命令可以为着色器指定纹理. 示例代码: Shader "Sbin/ff2" { ...

  7. IOS 中openGL使用教程3(openGL ES 入门篇 &vert; 纹理贴图(texture)使用)

    在这篇文章中,我们将学习如何在openGL中使用纹理贴图. penGL中纹理可以分为1D,2D和3D纹理,我们在绑定纹理对象的时候需要指定纹理的种类.由于本文将以一张图片为例,因此我们为我们的纹理对象 ...

  8. Unity3D ShaderLab压缩混合纹理贴图

    Unity3D ShaderLab压缩混合纹理贴图 纹理可以用于存储大量的数据,我们可以把多个图像打包存储在单一的RGBA纹理上,然后通过着色器代码提取这些元素, 我们就可以使用每个图片的RGBA通道 ...

  9. OpenGL 纹理贴图

    前一节实例代码中有个贴图操作. 今天就简单说明一下纹理贴图... 为了使用纹理贴图.我们首先需要启用纹理贴图功能. 我们可以在Renderer实现的onSurfaceCreated中定义启用: // ...

随机推荐

  1. em与px换算关系以及常用列表

    1.任意浏览器的默认字体大小都是16px.2.所有未经调整的浏览器都符合: 1em=16px 12px=0.75em 10px=0.625em3.为了简化font-size的换算,在body选择器中声 ...

  2. git介绍

    简介:Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目.Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件.Git ...

  3. 一款可以下拉搜索html下拉框控件

    直接上图,组件不错,支持静态和动态搜索,这个只是在原控件上自己修改样式后的,这里主要记录一下,在修改别人控件时,应该如何去封装代码: 原控件:http://ivaynberg.github.com/s ...

  4. jvm分析&lpar;MD语法&rpar;

    #是什么**jps**  查看所有的jvm进程,包括进程ID,进程启动的路径等等. **jstack**  观察jvm中当前所有线程的运行情况和线程当前状态.系统崩溃了?如果java程序崩溃生成cor ...

  5. 【工具】openwrt安装记录

    步骤: 1  从以太网引导启动.由于我们实验室在服务器上放了一个openwrt镜像,安装时先从以太网启动,将服务器上的镜像载入到RAM中启动系统. 2  用SCP将在PC上编译好的openwrt-XX ...

  6. windows xp 安装mysql5&period;6&period;17-ERROR 1045 &lpar;28000&rpar;&colon; Access denied for user &&num;39&semi;root&&num;39&semi;&commat;&&num;39&semi;localhost&&num;39&semi; &lpar;using password

    .zip解压后没有setup 没有my.ini 1.安装方法 bin目录下执行以下: E:\mysql-5.6.17-win32\bin>mysqld install MySQL --defau ...

  7. 【汉字乱码】IE下GET形式传递汉字。

    js:encodeURI(); php:urlencode(); 举例: 本来打算这样使用 <a href="list.php?plate=辖区动态" charset=&qu ...

  8. Android 签名&lpar;4&rpar;验证是否签名

    判断Apk是否签名 用命令:jarsigner -verify  XXX.apk 增加 -verbose -certs 两个选项可显示更多信息. 如果有Android Debug字樣就是debug 如 ...

  9. oracle中的function的简单语法定义

    1. create or replace 函数名 (参数名 in 类型) return 返回值类型 as 定义变量 begin 函数体 end;

  10. SpringMVC&lpar;二七&rpar; 自定义视图

    可以参考博客http://www.cnblogs.com/parryyang/p/5683600.html,举例很清晰. 对自定义的视图名称匹配不同的解析器进行解析. 作用:自己定义视图,视图继承vi ...