webgl glsl 改变投影
webgl glsl change the projection
我正在使用 webgl 在屏幕上绘制二维平面图。我想稍微旋转一下平面图以给人一种 3d 印象。
当前的:
想要:
我的第一个方法是像透视画一样使用消失点,但我不知道如何改变y坐标,我没有走到尽头。有没有更简单的方法来旋转输出?
这是我的代码:
uniform float scale;
uniform vec2 ratio;
uniform vec2 center;
in vec3 fillColor;
in vec2 position;
out vec3 color;
void main() {
color = fillColor;
gl_Position = vec4((position - center) * ratio, 0.0, scale);
}
如果你想构建一个完整的游戏引擎或一个复杂的动画,你将需要深入研究透视投影矩阵。
但是如果你只是想实现这个小效果,并试图了解它是如何工作的,你可以直接使用gl_Position
的w
坐标。例如,此坐标对于告诉 GPU 如何以有效的 3D 方式插入 UV 纹理至关重要。并且会分为x
、y
和z
.
因此,假设您要显示一个矩形。你需要两个三角形。
如果使用 TRIANGLE_STRIP 模式,4 个顶点就足够了。我们可以只使用一个属性,但为了教程起见,我将使用两个:
Vertex #
attPos
attUV
0
-1, +1
0, 0
1
-1, +1
0, 1
2
+1, +1
1, 0
3
+1, -1
1, 1
所有逻辑都在顶点着色器:
uniform float uniScale;
uniform float uniAspectRatio;
attribute vec2 attPos;
attribute vec2 attUV;
varying vec2 varUV;
void main() {
varUV = attUV;
gl_Position = vec4(
attPos.x * uniScale,
attPos.y * uniAspectRatio,
1.0,
attUV.y < 0.5 ? uniScale : 1.0
);
}
行attUV.y < 0.5 ? uniScale : 1.0
表示
- 如果attUV.y为0,则使用
uniScale
- 否则使用
1.0
attUV
属性让您可以根据需要使用纹理。在这个例子中,
我只是用这个 片段着色器 :
模拟一个棋盘
precision mediump float;
const float MARGIN = 0.1;
const float CELLS = 8.0;
const vec3 ORANGE = vec3(1.0, 0.5, 0.0);
const vec3 BLUE = vec3(0.0, 0.6, 1.0);
varying vec2 varUV;
void main() {
float u = fract(varUV.x * CELLS);
float v = fract(varUV.y * CELLS);
if (u > MARGIN && v > MARGIN) gl_FragColor = vec4(BLUE, 1.0);
else gl_FragColor = vec4(ORANGE, 1.0);
}
您可以在这个 CopePen 中看到所有这些操作:
https://codepen.io/tolokoban/full/oNpBRyO
我正在使用 webgl 在屏幕上绘制二维平面图。我想稍微旋转一下平面图以给人一种 3d 印象。
当前的:
想要:
我的第一个方法是像透视画一样使用消失点,但我不知道如何改变y坐标,我没有走到尽头。有没有更简单的方法来旋转输出?
这是我的代码:
uniform float scale;
uniform vec2 ratio;
uniform vec2 center;
in vec3 fillColor;
in vec2 position;
out vec3 color;
void main() {
color = fillColor;
gl_Position = vec4((position - center) * ratio, 0.0, scale);
}
如果你想构建一个完整的游戏引擎或一个复杂的动画,你将需要深入研究透视投影矩阵。
但是如果你只是想实现这个小效果,并试图了解它是如何工作的,你可以直接使用gl_Position
的w
坐标。例如,此坐标对于告诉 GPU 如何以有效的 3D 方式插入 UV 纹理至关重要。并且会分为x
、y
和z
.
因此,假设您要显示一个矩形。你需要两个三角形。 如果使用 TRIANGLE_STRIP 模式,4 个顶点就足够了。我们可以只使用一个属性,但为了教程起见,我将使用两个:
Vertex # | attPos | attUV |
---|---|---|
0 | -1, +1 | 0, 0 |
1 | -1, +1 | 0, 1 |
2 | +1, +1 | 1, 0 |
3 | +1, -1 | 1, 1 |
所有逻辑都在顶点着色器:
uniform float uniScale;
uniform float uniAspectRatio;
attribute vec2 attPos;
attribute vec2 attUV;
varying vec2 varUV;
void main() {
varUV = attUV;
gl_Position = vec4(
attPos.x * uniScale,
attPos.y * uniAspectRatio,
1.0,
attUV.y < 0.5 ? uniScale : 1.0
);
}
行attUV.y < 0.5 ? uniScale : 1.0
表示
- 如果attUV.y为0,则使用
uniScale
- 否则使用
1.0
attUV
属性让您可以根据需要使用纹理。在这个例子中,
我只是用这个 片段着色器 :
precision mediump float;
const float MARGIN = 0.1;
const float CELLS = 8.0;
const vec3 ORANGE = vec3(1.0, 0.5, 0.0);
const vec3 BLUE = vec3(0.0, 0.6, 1.0);
varying vec2 varUV;
void main() {
float u = fract(varUV.x * CELLS);
float v = fract(varUV.y * CELLS);
if (u > MARGIN && v > MARGIN) gl_FragColor = vec4(BLUE, 1.0);
else gl_FragColor = vec4(ORANGE, 1.0);
}
您可以在这个 CopePen 中看到所有这些操作: https://codepen.io/tolokoban/full/oNpBRyO