Затенение полигонов – это фундаментальный аспект компьютерной графики, который повышает реалистичность и визуальную привлекательность 3D-моделей. Одним из важнейших факторов достижения реалистичного затенения является расчет нормалей поверхности. В этой статье мы рассмотрим различные методы затенения полигонов с использованием обычных методов, сопровождаемые разговорными пояснениями и примерами кода.
- Плоское затенение.
Плоское затенение — это самый простой метод, при котором каждый многоугольник отображается одним цветом. Нормаль поверхности каждого многоугольника рассчитывается как среднее значение нормалей его вершин. Вот фрагмент кода в OpenGL:
// Calculate surface normal
vec3 normal = normalize(cross(vertex1 - vertex0, vertex2 - vertex0));
// Use the same normal for all vertices of the triangle
glNormal3f(normal.x, normal.y, normal.z);
// Render the triangle
glBegin(GL_TRIANGLES);
glVertex3f(vertex0.x, vertex0.y, vertex0.z);
glVertex3f(vertex1.x, vertex1.y, vertex1.z);
glVertex3f(vertex2.x, vertex2.y, vertex2.z);
glEnd();
- Затенение по Гуро.
Затенение по Гуро улучшает плоское затенение за счет назначения нормали каждой вершине многоугольника. Затем цвет каждого пикселя интерполируется по поверхности многоугольника на основе нормалей вершин. Вот пример в WebGL:
// Calculate vertex normals
let normal0 = calculateNormal(vertex0);
let normal1 = calculateNormal(vertex1);
let normal2 = calculateNormal(vertex2);
// Render the triangle with interpolated vertex normals
ctx.beginPath();
ctx.moveTo(vertex0.x, vertex0.y);
ctx.lineTo(vertex1.x, vertex1.y);
ctx.lineTo(vertex2.x, vertex2.y);
ctx.closePath();
// Interpolate vertex normals across the triangle
let grad = ctx.createLinearGradient(vertex0.x, vertex0.y, vertex2.x, vertex2.y);
grad.addColorStop(0, colorForNormal(normal0));
grad.addColorStop(0.5, colorForNormal(normal1));
grad.addColorStop(1, colorForNormal(normal2));
ctx.fillStyle = grad;
ctx.fill();
- Затенение Фонга.
Затенение Фонга вычисляет нормаль к поверхности для каждого пикселя в многоугольнике. Это приводит к более плавному эффекту затенения по сравнению с затенением по Гуро. Вот пример кода в Unity ShaderLab:
// Calculate interpolated normal
fixed3 interpolatedNormal = normalize(v.vertexNormal);
// Calculate the final color using interpolated normal
fixed3 lightDir = normalize(lightPosition - v.vertexPosition);
fixed3 diffuseColor = max(dot(lightDir, interpolatedNormal), 0) * lightIntensity * surfaceColor;
fixed3 finalColor = ambientColor + diffuseColor;
// Assign the final color to the fragment
fragColor = finalColor;
В этой статье мы рассмотрели различные методы затенения полигонов с использованием обычных методов. Мы обсудили плоское затенение, затенение Гуро и затенение Фонга, каждое из которых обеспечивает разные уровни реализма и вычислительной сложности. Поняв эти методы и выбрав соответствующий метод в соответствии с вашими требованиями, вы сможете добиться потрясающих визуальных результатов в своих проектах 3D-рендеринга.
Применив эти методы затенения полигонов, вы сможете оживить свои 3D-модели и создать визуально захватывающий опыт для своей аудитории.