我使用OpenGL ES 2.0 for Android制作地球模型。我绘制球体,每次在顶点着色器中,我想旋转它。每次绘制时,我都会设置一个表示旋转角度的制服。以下是我计算新点的方法:
Vertex Shader
:
uniform mat4 u_Matrix;
uniform vec3 u_VectorToLight;
uniform vec3 u_Center;
uniform float u_RotationAngle;
attribute vec4 a_Position;
attribute vec2 a_TextureCoordinates;
attribute vec3 a_Normal;
varying vec2 v_TextureCoordinates;
varying vec3 v_VectorToLight;
varying vec3 v_Normal;
vec2 rotate(vec2 c, vec2 p, float a);
void main() {
v_TextureCoordinates = a_TextureCoordinates;
v_VectorToLight = u_VectorToLight;
v_Normal = a_Normal;
vec2 point = rotate(u_Center.xz, a_Position.xz, radians(u_RotationAngle));
gl_Position = a_Position;
gl_Position *= u_Matrix;
gl_Position.x = point.x;
gl_Position.z = point.y;
}
vec2 rotate(vec2 c, vec2 p, float a) {
p.x -= c.x;
p.y -= c.y;
float x1 = p.x * cos(a) - p.y * sin(a);
float y1 = p.x * sin(a) + p.y * cos(a);
p.x = c.x + x1;
p.y = c.y + y1;
return p;
}
Fragment Shader
:
precision mediump float;
uniform sampler2D u_TextureUnit;
varying vec2 v_TextureCoordinates;
varying vec3 v_VectorToLight;
varying vec3 v_Normal;
void main() {
gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
vec4 color = gl_FragColor.rgba;
vec3 scaledNormal = v_Normal;
scaledNormal = normalize(scaledNormal);
float diffuse = max(dot(scaledNormal, v_VectorToLight), 0.0);
gl_FragColor.rgb *= diffuse;
float ambient = 0.2;
gl_FragColor.rgb += ambient * color;
}
我使用顶点着色器中的rotate()
方法围绕球体中心旋转每个单独的点,这只会导致扭曲的地球,在X和Z轴上变小,但不是Y (想象一下地球的一个非常薄的版本)。更令人困惑的是,即使我每次传递一个新的旋转角度值,我仍然得到相同的静止图像。即使它是扭曲的,每次都应该以某种方式看起来不同,因为我每次都使用不同的角度。这是我如何设置制服:
public void setUniforms(float[] matrix, Vector vectorToLight, int texture, Point center, float angle) {
glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(uTextureUnitLocation, 0);
glUniform3f(uRadiusLocation, center.x, center.y, center.z);
glUniform3f(uVectorToLightLocation, vectorToLight.x, vectorToLight.y, vectorToLight.z);
glUniform1f(uRotationAngleLocation, angle); // <-- I set the rotation angle
}
答案 0 :(得分:2)
我认为围绕轴的旋转与u_Matrix
中包含的全局旋转的组合方式存在问题:
vec2 point = rotate(u_Center.xz, a_Position.xz, radians(u_RotationAngle));
gl_Position = a_Position;
gl_Position *= u_Matrix;
gl_Position.x = point.x;
gl_Position.z = point.y;
由于point
仅包含围绕轴的轮播,并且您使用x
中的值替换z
的{{1}}和gl_Position
,因此生成{ {1}}和point
没有应用x
。
您需要首先应用轴旋转,然后将z
应用于此变换点:
u_Matrix
要完成此任务,在Java代码中计算一次旋转矩阵,将其设置为均匀,然后仅在顶点着色器中应用矩阵乘法通常会更有效。使用现在的代码,您将为着色器代码中的每个顶点计算u_Matrix
和vec2 point = rotate(u_Center.xz, a_Position.xz, radians(u_RotationAngle));
vec4 rotPoint = a_Position;
rotPoint.x = point.x;
rotPoint.z = point.y;
gl_Position = rotPoint;
gl_Position *= u_Matrix;
值,除非GLSL编译器真的很聪明。如果你不想传入一个完整的矩阵,我至少会将余弦和正弦值传递给着色器而不是角度。