April 8, 2025

Shader - Built-in Variables


GLSL 內置變數筆記

GLSL (OpenGL Shading Language) 中的內置變數是以 gl_ 開頭的特殊變數,它們提供與 OpenGL 渲染管線的交互。以下是常用的內置變數及其用途。

頂點著色器中的內置變數

變數名數據類型描述範例
gl_Positionvec4頂點的裁剪空間座標gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
gl_PointSizefloat點精靈的大小(像素)gl_PointSize = 10.0;
gl_VertexIDint當前頂點的索引if (gl_VertexID % 2 == 0) { color = vec3(1.0); }
gl_InstanceIDint當前實例的索引offset = instanceOffsets[gl_InstanceID];

片段著色器中的內置變數

變數名數據類型描述範例
gl_FragCoordvec4片段在窗口座標系中的位置 (x,y,z,1/w)vec2 texCoord = gl_FragCoord.xy / resolution;
gl_FrontFacingbool表示片段是否屬於正面if (gl_FrontFacing) { color = frontColor; } else { color = backColor; }
gl_FragDepthfloat允許修改片段的深度值gl_FragDepth = gl_FragCoord.z * 0.5;
gl_PointCoordvec2點精靈內的座標 (0,0 至 1,1)color = texture(pointSprite, gl_PointCoord);
gl_FragColorvec4片段的最終顏色 (舊版GLSL使用)gl_FragColor = vec4(1.0, 0.5, 0.2, 1.0);

幾何著色器中的內置變數

變數名數據類型描述範例
gl_in[]數組來自上一階段的頂點資料陣列vec4 position = gl_in[i].gl_Position;
gl_PrimitiveIDInint當前圖元的 IDif (gl_PrimitiveIDIn % 2 == 0) { EmitVertex(); }
gl_Layerint指定渲染的目標層gl_Layer = i % 6;

共享的內置常量

常量名數據類型描述
gl_MaxVertexAttribsint支持的最大頂點屬性數
gl_MaxTextureUnitsint支持的最大紋理單元數
gl_MaxDrawBuffersint支持的最大繪圖緩衝數
gl_MaxVaryingFloatsint支持的最大 varying 變數數量

使用範例

基本頂點和片段著色器

// 頂點著色器
#version 300 es
in vec3 position;
in vec3 normal;
in vec2 texCoord;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

out vec3 vNormal;
out vec2 vTexCoord;

void main() {
    // 計算並輸出裁剪空間座標
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
    
    // 傳遞法線和紋理座標到片段著色器
    vNormal = (modelMatrix * vec4(normal, 0.0)).xyz;
    vTexCoord = texCoord;
}

// 片段著色器
#version 300 es
precision highp float;

in vec3 vNormal;
in vec2 vTexCoord;

uniform sampler2D diffuseMap;
uniform vec3 lightDir;

out vec4 fragColor;

void main() {
    // 計算基本漫反射光照
    vec3 normal = normalize(vNormal);
    float diffuse = max(dot(normal, normalize(lightDir)), 0.0);
    
    // 基於片段是正面還是背面應用不同效果
    if (gl_FrontFacing) {
        // 正面:使用紋理和全光照
        vec4 texColor = texture(diffuseMap, vTexCoord);
        fragColor = texColor * vec4(vec3(0.2 + diffuse * 0.8), 1.0);
    } else {
        // 背面:使用紅色並降低光照強度
        fragColor = vec4(0.8, 0.2, 0.2, 1.0) * vec4(vec3(0.2 + diffuse * 0.4), 1.0);
    }
    
    // 根據片段深度調整透明度
    float depth = gl_FragCoord.z / gl_FragCoord.w;
    fragColor.a *= smoothstep(20.0, 10.0, depth);
}

使用 gl_PointCoord 創建自定義點精靈

// 頂點著色器
#version 300 es
in vec3 position;
in float size;

uniform mat4 mvpMatrix;

void main() {
    gl_Position = mvpMatrix * vec4(position, 1.0);
    gl_PointSize = size;
}

// 片段著色器
#version 300 es
precision highp float;

uniform vec4 color;

out vec4 fragColor;

void main() {
    // 創建圓形點精靈
    vec2 coord = gl_PointCoord * 2.0 - 1.0;
    float dist = length(coord);
    
    // 如果在圓外則丟棄片段
    if (dist > 1.0) {
        discard;
    }
    
    // 添加圓形漸變效果
    float alpha = smoothstep(1.0, 0.0, dist);
    fragColor = vec4(color.rgb, color.a * alpha);
}

版本差異注意事項

其他重要內置變數

變數名著色器類型描述
gl_ClipDistance[]頂點用戶定義的裁剪平面距離
gl_PrimitiveID片段當前處理的圖元 ID
gl_SamplePosition片段當前樣本在片段中的位置 (多重採樣)
gl_SampleID片段當前樣本的索引 (多重採樣)
gl_SampleMask片段指定樣本掩碼 (多重採樣)
gl_NumWorkGroups計算調度的工作組總數
gl_WorkGroupID計算當前工作組的 ID
gl_LocalInvocationID計算當前工作組內的本地 ID
gl_GlobalInvocationID計算全局工作項的 ID