OpenGL ES球体上的照明不流畅

时间:2014-11-28 19:18:29

标签: android opengl-es

在Android的OpenGL ES 2.0中,我正在绘制一个球体。球体在屏幕上显示为圆形,因此我需要添加光照。当我添加灯光时,而不是像现实生活中那样光滑,它是明暗之间的细线,如下所示:
enter image description here
但是,我希望它看起来像这样,阴影更平滑和混合:

这是我的顶点着色器代码:

uniform mat4 u_Matrix;
uniform vec3 u_VectorToLight;

attribute vec4 a_Position;
attribute vec3 a_Color;
attribute vec3 a_Normal;

varying vec3 v_Color;

void main() {
  v_Color = a_Color;
  vec3 scaledNormal = a_Normal;
  scaledNormal = normalize(scaledNormal);
  float diffuse = max(dot(scaledNormal, u_VectorToLight), 0.0);
  v_Color *= diffuse;
  float ambient = 0.1;
  v_Color += ambient;
  gl_Position = u_Matrix * a_Position;
}

我的片段着色器:

precision mediump float;

varying vec3 v_Color;

void main() {
  gl_FragColor = vec4(v_Color, 1.0);
}

通过从球体中心到球体上的点获取矢量,然后将其标准化(给它的长度为1)来计算法线

以下是我设置颜色的方法:

vertices[offset++] = Color.red(color);
vertices[offset++] = Color.green(color);
vertices[offset++] = Color.blue(color);

颜色为0xffea00。

1 个答案:

答案 0 :(得分:1)

问题在于您使用的颜色值范围。 OpenGL使用[0.0,1.0]范围内的颜色分量值进行操作。但是您要在Java代码中指定[0,255]范围内的颜色。

您有两种方法可以解决此问题:

  • 将您从Color类获得的颜色值除以255.0f。
  • 指定类型为GL_UNSIGNED_BYTE的颜色。为此,将值存储在元素类型为byte的数组/缓冲区中,将这些值存储在VBO中,然后使用以下命令设置顶点属性:

    glVertexAttribPointer(attrLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, stride, 0);
    

    注意第四个参数的值。虽然GL_FLOAT属性无关紧要,但在这种情况下使用GL_TRUE至关重要,因为字节值需要规范化。