Я следую учебнику по OpenGL ES 2.0 и комбинирую его с учебником по освещению GLSL , которое я нашел, используя удобный чайник из Юты из developer.apple.com.
После долгих потрясений и экспериментов у меня заварен чайник на экране в меру правильно, вращаясь вокруг всех трех осей с помощью «затенения мультфильмов» из учебного пособия по освещению. В геометрии есть несколько глюков из-за того, что я просто рисую весь список вершин в виде треугольных полос (если вы посмотрите в файл teapot.h, там будет встроен '-1', где я должен начать новые треугольные полоски, но это только данные испытаний и не имеют отношения к моей проблеме).
Что меня действительно смущает, так это то, как расположить источник света на сцене. В моем коде Objective-C у меня есть вектор с плавающей точкой 3 , который содержит {0,1,0}, и я передаю его в шейдер, чтобы затем рассчитать интенсивность света.
Почему свет появляется в сцене тоже? Я имею в виду, что свет действует так, как будто он прикреплен к чайнику невидимой палочкой, всегда указывая на одну и ту же сторону, независимо от того, в каком направлении смотрит чайник.
Это вершинный шейдер
attribute vec4 Position;
attribute vec4 SourceColor;
attribute vec3 Normal;
uniform mat4 Projection;
uniform mat4 Modelview;
varying vec3 normal;
void main(void) {
normal = Normal;
gl_Position = Projection * Modelview * Position;
}
«Положение» задается кодом Obj-C и является вершинами для объекта, «Норма» - это список нормалей как из массива вершин (VBO), так и «Проекция» и «Вид модели» рассчитываются следующим образом :
(CC3GLMatrix из библиотеки Cocos3D, упомянутой в учебном пособии GLES, связанном выше)
CC3GLMatrix *projection = [CC3GLMatrix matrix];
float h = 4.0f * self.frame.size.height / self.frame.size.width;
[projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:1 andFar:100];
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);
CC3GLMatrix *modelView = [CC3GLMatrix matrix];
[modelView populateFromTranslation:CC3VectorMake(0, 0, -7)];
[modelView scaleBy:CC3VectorMake(30, 30, 30)];
_currentRotation += displayLink.duration * 90;
[modelView rotateBy:CC3VectorMake(_currentRotation, _currentRotation, _currentRotation)];
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);
И я установил свет в сцене, выполнив
float lightDir[] = {1,0,1};
glUniform3fv(_lightDirUniform, 1, lightDir);
Фрагмент шейдера выглядит так
varying lowp vec4 DestinationColor; // 1
varying highp vec3 normal;
uniform highp vec3 LightDir;
void main(void) {
highp float intensity;
highp vec4 color;
intensity = dot(LightDir,normal);
if (intensity > 0.95)
color = vec4(1.0,0.5,0.5,1.0);
else if (intensity > 0.5)
color = vec4(0.6,0.3,0.3,1.0);
else if (intensity > 0.25)
color = vec4(0.4,0.2,0.2,1.0);
else
color = vec4(0.2,0.1,0.1,1.0);
gl_FragColor = color;
}
Пытаясь решить эту проблему, я сталкиваюсь с кодом, который ссылается на (несуществующий в GLES) gl_LightSource и gl_NormalMatrix, но не знает, что поместить в эквиваленты, которые я должен передать в шейдеры из своего кода. , Ссылки на «пространство глаза», «пространство камеры», «пространство мира» и т. Д. Сбивают с толку, я знаю, что, вероятно, мне следует конвертировать вещи между ними, но не понимаю, почему и как (и где - в коде или в шейдере ?)
В каждом кадре мне нужно изменить источник света? Код для настройки выглядит слишком упрощенно. На самом деле я не двигаю чайник, вместо этого я перемещаю всю сцену - свет и все вокруг?