OpenGL ES -> GLSL数据类型详解

GLSL数据类型详解

GLSL(OpenGL Shading Language)中的数据类型主要分为七种类型:标量、向量、矩阵、采样器、结构体、数组和空类型。下面将详细介绍每种类型的特点和用法。

1. 标量类型

标量表示只有大小没有方向的量,GLSL中包含以下标量类型:

  • bool:布尔值,可以是truefalse
  • int:整型,32位整数
  • float:浮点型,32位浮点数
    整型数值可以用不同进制表示:
// 不同进制表示同一个值(16)
int decimal = 16;      // 十进制
int octal = 020;       // 八进制
int hexadecimal = 0x10; // 十六进制

注意事项:

  • 在进行标量运算时,需要注意精度问题,防止溢出
    float类型数据建议始终加小数点,如1.0而不是1

2. 向量类型

向量可以看作是数组,在GLSL中通常用于存储颜色、坐标等数据。向量类型根据维数和存储的标量类型分类:

  • 浮点向量
vec2:二维浮点向量
vec3:三维浮点向量
vec4:四维浮点向量
  • 整型向量
ivec2:二维整型向量
ivec3:三维整型向量
ivec4:四维整型向量
  • 布尔向量
bvec2:二维布尔向量
bvec3:三维布尔向量
bvec4:四维布尔向量
  • 向量分量访问方式:
vec4 color = vec4(1.0, 0.5, 0.3, 1.0);
// 以下四种访问方式等价
float red1 = color[0];
float red2 = color.r;
float red3 = color.x;
float red4 = color.s;
  • 向量分量可以通过不同的命名约定访问:
颜色访问:使用r, g, b, a分量
vec4 color;
color.r; // 红色分量
color.g; // 绿色分量
color.b; // 蓝色分量
color.a; // 透明度分量
位置访问:使用x, y, z, w分量
vec4 position;
position.x; // x坐标
position.y; // y坐标
position.z; // z坐标
position.w; // 齐次坐标
纹理访问:使用s, t, p, q分量
vec4 texCoord;
texCoord.s; // 水平纹理坐标
texCoord.t; // 垂直纹理坐标
texCoord.p; // 深度纹理坐标
texCoord.q; // 第四个纹理坐标
向量还支持分量重组(swizzling):
vec4 color = vec4(1.0, 0.5, 0.3, 1.0);
vec3 rgb = color.rgb;  // 提取rgb分量
vec3 bgr = color.bgr;  // 反转rgb分量
vec2 rr = color.rr;    // 创建只有红色分量的向量

注意:GLSL中的向量是列向量,与矩阵相乘时,矩阵在前,向量在后

3. 矩阵类型

  • GLSL提供三种基本矩阵类型:
mat2:2×2浮点矩阵
mat3:3×3浮点矩阵
mat4:4×4浮点矩阵
  • 矩阵的声明和使用:
矩阵声明
mat4 transform;
单位矩阵初始化
mat4 identity = mat4(
    1.0, 0.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,
    0.0, 0.0, 0.0, 1.0
);
// 访问矩阵元素 - 列优先存储
float element = transform[1][2]; // 第2列第3行的元素
矩阵可以与向量或其他矩阵进行乘法运算:

mat4 modelMatrix;
vec4 position;
vec4 transformedPosition = modelMatrix * position;

4. 采样器类型

采样器类型用于访问纹理数据,主要包括:
sampler2D:2D纹理采样器
samplerCube:立方体纹理采样器
sampler3D:3D纹理采样器
sampler2DShadow:2D阴影纹理采样器
采样器使用示例:
uniform sampler2D diffuseTexture;

void main() {
    // 使用texture函数从纹理中采样颜色
    vec4 texColor = texture(diffuseTexture, vec2(0.5, 0.5));
}

采样器变量通常声明为uniform,表示一副或一套纹理贴图,可以理解为物体表面的"皮肤"

5. 结构体类型

GLSL中的结构体与C语言类似,用struct关键字定义:

struct Light {
    vec3 position;
    vec3 color;
    float intensity;
};

// 使用结构体
Light mainLight;
mainLight.position = vec3(0.0, 10.0, 0.0);
mainLight.color = vec3(1.0, 1.0, 1.0);
mainLight.intensity = 0.8;

结构体可以包含任何基本类型、数组或其他结构体

6. 数组类型

GLSL支持一维数组,声明方式与C语言类似:

// 固定大小数组
float values[4];
vec3 positions[10];

// 数组初始化
float factors[3] = float[3](1.0, 0.5, 0.2);

// 访问数组元素
float factor = factors[1];

注意事项:
GLSL中数组下标从0开始
在某些GLSL版本中,数组声明可以不指定大小,但建议总是指定大小以提高可读性和兼容性
数组索引必须是常量表达式或均匀循环索引,不支持动态索引(在某些较新版本中有所放宽)

7. 空类型

空类型用void表示,主要用于声明不返回任何值的函数:

void main() {
    // 函数体
}

void setColor(vec4 color) {
    // 没有返回值的函数
}

Demo代码

以下是一个综合使用多种数据类型的片段着色器示例:

#version 300 es
precision mediump float;

// 结构体定义
struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};

// 采样器
uniform sampler2D diffuseMap;
uniform sampler2D normalMap;

// 矩阵
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;

// 向量数组
uniform vec3 lightPositions[4];
uniform vec3 lightColors[4];

// 结构体
uniform Material material;

// 输入和输出
in vec2 texCoord;
in vec3 normal;
in vec3 fragPos;
out vec4 fragColor;

void main() {
    // 标量
    float ambientStrength = 0.1;
    
    // 向量
    vec3 norm = normalize(normal);
    vec3 viewDir = normalize(vec3(0.0, 0.0, 1.0) - fragPos);
    
    // 纹理采样
    vec4 texColor = texture(diffuseMap, texCoord);
    
    // 颜色计算(使用向量运算)
    vec3 result = material.ambient * ambientStrength;
    
    // 循环和数组访问
    for(int i = 0; i < 4; i++) {
        vec3 lightDir = normalize(lightPositions[i] - fragPos);
        float diff = max(dot(norm, lightDir), 0.0);
        vec3 diffuse = diff * material.diffuse * lightColors[i];
        result += diffuse;
    }
    
    // 最终输出
    fragColor = vec4(result, 1.0) * texColor;
}

这个示例展示了GLSL中各种数据类型的使用方式,包括标量、向量、矩阵、采样器、结构体和数组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值