Почему при масштабировании полигонов меняется интенсивность света?

Мне нужно легко изменить масштаб полигона в проекте OpenGL, но по какой-то причине интенсивность света прямо пропорциональна размеру полигонов.

Я пытался перемещать направление света в разные места. Измените интенсивность света и разделите векторы нормалей на скейлере, но это не помогает.

В моем коде scaler означает сжатие полигонов => если scaler = 2 , poly становится 0,5 размера

Координаты вершин:

verticesMatrix[i][k] = new Vector3f((float) (i - cellCount / 2) / scaler, 
                      (float) 0, (float) (k - cellCount / 2) / scaler);

Расчетные нормали:

 public void calcNormal(Vector3f s1, Vector3f s2, Vector3f s3) {
        Vector3f a = new Vector3f(s2.x - s1.x, s2.y - s1.y, s2.z - s1.z);
        Vector3f b = new Vector3f(s3.x - s2.x, s3.y - s2.y, s3.z - s2.z);
        Vector3f normal = new Vector3f(a.y * b.z - a.z * b.y, a.z * b.x - a.x 
        * b.z, a.x * b.y - a.y * b.x);
        glNormal3f(normal.x, normal.y, normal.z);
    }

Настройка света:

private static float[] lightPosition = {-2.19f, 100.36f, 11.45f, 1f};

 private static void setUpLighting() {
        glShadeModel(GL_SMOOTH);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        glLightModel(GL_LIGHT_MODEL_AMBIENT, 
        BufferTools.asFlippedFloatBuffer(new float[]{0.0f, 0.0f, 0.0f, 1f}));
        glLight(GL_LIGHT0, GL_POSITION, 
        BufferTools.asFlippedFloatBuffer(lightPosition));
        glEnable(GL_CULL_FACE);
        glCullFace(GL_BACK);
        glEnable(GL_COLOR_MATERIAL);
        glColorMaterial(GL_FRONT, GL_DIFFUSE);
    }

Мне нужно иметь тот же свет, используя другой скейлер. Я не знаю, как это может повлиять на свет, потому что я проверил весь код, и я не использую скейлер со светом. Изображение результата: https://yadi.sk/i/kxQLvRSTP7LYVA


person Bogdan Madzhuga    schedule 03.05.2019    source источник
comment
scaler влияет на координаты вершин. Более близкий свет (lightPosition остается неизменным) к этим координатам изменяет интенсивность, потому что это «точечный свет», а не «направленный свет». См. Использование glLight   -  person Ripi2    schedule 03.05.2019
comment
@genpfault Почему ты удалил свой ответ? Возможно ты прав. Думаю, это был хороший улов.   -  person Rabbid76    schedule 03.05.2019
comment
Действительно ли calcNormal() испускает нормали единичной длины? Похоже, это просто перекрестный продукт, не видящий никаких попыток (повторной) нормализации. Входные данные всегда имеют единичную длину?   -  person genpfault    schedule 03.05.2019
comment
@Ripi2 Свет рассчитывается для каждой вершины (затенение Гуро). Диффузная часть — это скалярное произведение вектора нормали и вектора света. Таким образом, интенсивность света зависит от угла вектора нормали к вектору света, а не от расстояния координаты вершины до положения источника света. Для зависимости от расстояния параметры *ATTENUATION имеют установить (изменить).   -  person Rabbid76    schedule 03.05.2019
comment
@ Rabbid76 Rabbid76 Признаюсь, я довольно неуклюж с OGL 1.1. Но затухание учитывается при w != 0. как указано в документе glLight (спуститься в GL_POSITION)   -  person Ripi2    schedule 03.05.2019
comment
@Ripi2 Но параметры по умолчанию (1, 0, 0) отключают затухание. - коэффициент затухания равен 1, а коэффициенты, зависящие от расстояния, равны 0.   -  person Rabbid76    schedule 03.05.2019
comment
@ Rabbid76 Верно. Но это не относится к ОП, он определяет lightPosition.   -  person Ripi2    schedule 03.05.2019
comment
@Ripi2 Пожалуйста, прочитайте спецификацию ... Это не предположение, я это очень хорошо знаю.   -  person Rabbid76    schedule 03.05.2019
comment
Спасибо, я действительно забыл нормализовать свои нормали.   -  person Bogdan Madzhuga    schedule 04.05.2019


Ответы (1)


Мне нужно нормализовать норму следующим образом:

public void calcNormal(Vector3f s1, Vector3f s2, Vector3f s3) {
        Vector3f a = new Vector3f(s2.x - s1.x, s2.y - s1.y, s2.z - s1.z);
        Vector3f b = new Vector3f(s3.x - s2.x, s3.y - s2.y, s3.z - s2.z);
        Vector3f normal = new Vector3f(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
        float length = (float)Math.pow(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z, 0.5f); 
        glNormal3f(normal.x / length, normal.y / length, normal.z / length);
    }
person Bogdan Madzhuga    schedule 04.05.2019