Освещение blinn phong создает странные результаты
Я создаю raycaster и пытаюсь использовать глобальное освещение в качестве метода затенения. Я рассчитал пересечение сферы и куба, а также их нормалей.
создание каждого отдельного окружающего, рассеянного и зеркального результата приводит к затенению объекта, как и ожидалось, но в целом после сложения их вместе, как показано в коде ниже
glm::vec3 n = surfaceNormal(position, intersect);
glm::vec3 lightStart = glm::vec3(-10, 1, 10);//light points in 3d space
glm::vec3 lightDir = glm::normalize(lightStart - intersect); // direction towards light source
glm::vec3 viewDir = glm::normalize(cam.pos - intersect); // direction towards camera
glm::vec3 midDir = glm::normalize(lightDir + viewDir);//mid point between light and view
glm::vec3 lightColor = glm::vec3(1, 1, 1);//color of light
glm::vec3 objectColor = color ;
float shinyness = 10.0f;
float ambientStr = 0.1f;
///ambient
glm::vec3 ambient = lightColor * ambientStr;
///diffuse
glm::vec3 diffuse = lightColor * glm::max(glm::dot(n,lightDir), 0.0f);
///specular
//ks * light color * facing * (max(n dot h))
glm::vec3 specular = lightColor * facing(n, lightDir) *
std::pow(glm::max(glm::dot(n, midDir), 0.0f), shinyness);
glm::vec3 outColor = ambient + diffuse + specular;
return outColor * objectColor * 255.0f;
метод face возвращает 1, если перекрестное произведение (n,lightDir) > 0, иначе он возвращает 0, чтобы избежать освещения граней, направленных в неправильном направлении
это результат:
1 ответ
*255f
было уже подозрительно (типичное использование OpenGL работает с цветными компонентами в диапазоне [0...1]), и вы добавили комментарий
выходные данные являются плавающими значениями для цвета, рисуемого прямо на экране.
Это простая проблема переполнения тогда. Ваш вес представляет собой сумму 0,1+[0...1]+[0...1] (окружающий, рассеянный и зеркальный), которая попадает в [0,1 ... 2,1], и когда вы умножаете его на цвет Компонент больше 0,5 (приблизительно, 1/2,1 является точным пределом), их произведение превышает 1. Затем это число умножается на 255, и результат будет выше 255, а при сокращении до байта он "начинается заново" с черный, по компонентам.
Основываясь на коде, который вы показываете, вы можете попробовать что-то вроде
return glm::min(outColor * objectColor * 255.0f, glm::vec3(255f, 255f, 255f));
но для этого может быть лучшая функция.