Я изучаю интересную проблему, с которой я сталкиваюсь при освещении OpenGL на Android.Я работаю над 3D Viewer, где вы можете добавлять и управлять 3D-объектами.Вы также можете установить свет с различными атрибутами.Проблема, с которой я столкнулся при работе со своим средством просмотра, заключалась в том, что выделение на трехмерных объектах от источника света (это точечный источник света) вели себя странно.Если источник света находится точно в той же точке, что и камера, выделение будет двигаться в направлении, противоположном ожидаемому.(Таким образом, если вы переместите объект влево, выделение переместится и на левую сторону объекта, а не вправо, что я и ожидал.)
Чтобы еще больше сузить проблему, я создал небольшое приложение-образец, которое визуализирует только квадрат, а затем поворачиваю этот квадрат вокруг положения камеры (начала координат), где также размещается свет.Это должно привести к тому, что все квадраты будут обращены непосредственно к камере, чтобы они были полностью выделены.Хотя результат выглядел так:
Может ли быть, что эти артефакты появляются из-за искажения, которое вы получаете на границе из-за проекции?
ВНа первом изображении расстояние между сферой и камерой составляет около 20 единиц, а размер сферы составляет около 2. Если я подведу свет ближе к объекту, то подсветка будет выглядеть намного лучше, чем я ожидаю.На втором изображении радиус, в котором расположены квадраты, составляет 25 единиц.Я использую OpenGL ES 1.1 (так как я изо всех сил пытался заставить его работать с шейдерами в ES 2.0) на Android 3.1
Вот часть кода, который я использую:
public void onDrawFrame(GL10 gl) {
// Setting the camera
GLU.gluLookAt(gl, 0, 0, 0, 0f, 0f, -1f, 0f, 1.0f, 0.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
for (int i = 0; i < 72; i++) {
gl.glPushMatrix();
gl.glRotatef(5f * i, 0, 1, 0);
gl.glTranslatef(0, 0, -25);
draw(gl);
gl.glPopMatrix();
}
}
public void draw(GL10 gl) {
setMaterial(gl);
gl.glEnable(GL10.GL_NORMALIZE);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glFrontFace(GL10.GL_CCW);
// Enable the vertex and normal state
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
gl.glNormalPointer(GL10.GL_FLOAT, 0, mNormalBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, mIndexBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
// Setting the light
private void drawLights(GL10 gl) {
// Point Light
float[] position = { 0, 0, 0, 1 };
float[] diffuse = { .6f, .6f, .6f, 1f };
float[] specular = { 1, 1, 1, 1 };
float[] ambient = { .2f, .2f, .2f, 1 };
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glLightfv(GL10.GL_LIGHT0, GL_POSITION, position, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL_DIFFUSE, diffuse, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL_AMBIENT, ambient, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL_SPECULAR, specular, 0);
}
private void setMaterial(GL10 gl) {
float shininess = 30;
float[] ambient = { 0, 0, .3f, 1 };
float[] diffuse = { 0, 0, .7f, 1 };
float[] specular = { 1, 1, 1, 1 };
gl.glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse, 0);
gl.glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient, 0);
gl.glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular, 0);
gl.glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
}
Я устанавливаю источник света в начале, когда начинается действие (в onSurfaceCreated) и материал каждый раз, когда я рисую квадрат.