#version 320 es precision highp float; // 全局 UBO (binding = 0) - 每帧更新一次 layout(std140, binding = 0) uniform GlobalUBO { mat4 uViewProjection; vec4 uCameraPosition; float uTime; float uDeltaTime; vec2 uScreenSize; }; // 材质 UBO (binding = 1) - 每批次更新 layout(std140, binding = 1) uniform MaterialUBO { vec4 uColor; vec4 uTintColor; float uOpacity; float uPadding[3]; // std140 对齐填充 }; // 顶点属性 (每个顶点) layout(location = 0) in vec2 aPosition; layout(location = 1) in vec2 aTexCoord; layout(location = 2) in vec4 aColor; // 实例属性 (每个实例) - 使用 location 3-6 layout(location = 3) in vec2 iPosition; // 实例位置 layout(location = 4) in float iRotation; // 实例旋转 layout(location = 5) in vec2 iScale; // 实例缩放 layout(location = 6) in vec4 iColor; // 实例颜色 // 输出到片段着色器 out vec2 vTexCoord; out vec4 vColor; out vec4 vTintColor; out float vOpacity; /** * @brief 从旋转角度构建2D变换矩阵 * @param angle 旋转角度(弧度) * @return 2x2旋转矩阵 */ mat2 rotate2D(float angle) { float c = cos(angle); float s = sin(angle); return mat2(c, -s, s, c); } /** * @brief 顶点着色器入口 * * 计算顶点在裁剪空间中的位置, * 应用实例的变换(位置、旋转、缩放), * 并传递纹理坐标和颜色到片段着色器 */ void main() { // 应用实例缩放和旋转 vec2 localPos = rotate2D(iRotation) * (aPosition * iScale); // 应用实例位置偏移 vec2 worldPos = localPos + iPosition; // 变换到裁剪空间 gl_Position = uViewProjection * vec4(worldPos, 0.0, 1.0); vTexCoord = aTexCoord; // 混合顶点颜色、实例颜色和材质颜色 vColor = aColor * iColor * uColor; vTintColor = uTintColor; vOpacity = uOpacity; }