Освещение 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));

но для этого может быть лучшая функция.

Другие вопросы по тегам