Как создать дешевые тени в OpenGL?

У меня две модели: A и B и один свет, L. Я бы хотел, чтобы модель A бросила тень на модель B. Я не хочу беспокоиться о теневых томах или правильных тенях на данный момент, просто достаточно простой тени круга. Эффект заключается в том, что модель A рассматривается как сфера для целей теневого литья.

Вот как я представляю алгоритм:

Для каждого треугольника в модели B нарисуйте треугольник. Проецируйте круг на треугольник вдоль линии от L до A, увеличивая размер круга в зависимости от того, как далеко находится треугольник. Убедитесь, что круг обрезается до границ треугольника (я полагаю, используя буфер трафарета каким-то образом).

Я работаю с OpenGL и простой C.

Любые указатели на некоторую справочную документацию, которую я могу прочитать? Или идеи внедрения?

Ответы

Ответ 1

Я думаю, что на самом деле проще реализовать правильные тени, потому что OpenGL может сделать для вас работу.

Я нашел рабочий теневой код с большим количеством документации здесь: http://www.opengl.org/resources/code/samples/mjktips/TexShadowReflectLight.html

Код выше отображает объект дважды: сначала обычно с помощью специальной матрицы. Он делает много несвязанных вещей, таких как управление мышью и размышлениями. Итак, вот интересные части.

Это вычисляет матрицу тени:

/* Create a matrix that will project the desired shadow. */
void
shadowMatrix(GLfloat shadowMat[4][4],
  GLfloat groundplane[4],
  GLfloat lightpos[4])
{
  GLfloat dot;

  /* Find dot product between light position vector and ground plane normal. */
  dot = groundplane[X] * lightpos[X] +
    groundplane[Y] * lightpos[Y] +
    groundplane[Z] * lightpos[Z] +
    groundplane[W] * lightpos[W];

  shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
  shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
  shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
  shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];

  shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
  shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
  shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
  shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];

  shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
  shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
  shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
  shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];

  shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
  shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
  shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
  shadowMat[3][3] = dot - lightpos[W] * groundplane[W];

}

Я не претендую на полное понимание этого. lightpos - это положение источника света. Первые 3 координаты наземной плоскости являются нормальным вектором поверхности земли. Четвертый - смещение (насколько это далеко от 0,0,0).

И эта часть фактически отображает тень:

glPushMatrix();
/* Project the shadow. */
glMultMatrixf((GLfloat *) floorShadow);
drawDinosaur();
glPopMatrix();

Перед тем, как это сделать, вам нужно сначала glEnable/glDisable, чтобы посмотреть на ссылку.

Ответ 2

Этот документ, по-видимому, отвечает вашим требованиям, используя OpenGL и аппаратное ускорение для создания подробной теневой карты.

Если бы я пытался это сделать, у меня возникло бы желание использовать лучевое кастинг. Для каждого треугольника в B создайте вектор от треугольника к свету. Если он что-то бьет по пути, он находится в тени. Это было бы медленным, если бы вы не использовали приличную структуру ускорения и быстрый тест на треугольник. Мне нравится иерархии ограничивающих томов; многие программы используют их для обнаружения столкновений.