Open GL Positioning Lighting на камеру всегда

Фон

Я пытаюсь создать программу просмотра САПР, в которую я могу внести файл STL и просто вращать, панорамировать и т. Д. Это не должно быть чем-то таким продвинутым, как игра.

У меня были проблемы с освещением, которое можно увидеть в предыдущем посте: Предыдущий пост

проблема

По сути, у меня сейчас есть свет, и мои матричные вызовы pop и push находятся в нужном месте. Все, что я сейчас пытаюсь сделать, - это оптимизировать освещение, чтобы оно походило на среду САПР. Поправьте меня, если я ошибаюсь, но я считаю, что лучшее освещение для просмотра детали - всегда направлять свет в камеру в направлении объекта. Если это не оптимальный способ освещения, во что бы то ни стало, не стесняйтесь предложить лучший способ.

Я думаю, что это в основном сводится к математике. Я не знаю, есть ли какие-то встроенные функции, чтобы просто определить, где находится камера, или вам нужно следить за ней.

Вот что у меня есть для моей функции отображения:

Private Sub display()

    Gl.glEnable(Gl.GL_DEPTH_TEST)
    Gl.glClear(Gl.GL_COLOR_BUFFER_BIT)
     Gl.glClear(Gl.GL_DEPTH_BUFFER_BIT)


    Gl.glPushMatrix()

    Gl.glRotatef(rotX, 1.0F, 0.0F, 0.0F)
    ' Rotate on x
    Gl.glRotatef(rotY, 0.0F, 1.0F, 0.0F)
    ' Rotate on y
    Gl.glRotatef(rotZ, 0.0F, 0.0F, 1.0F)
    ' Rotate on z
    Gl.glTranslatef(X, Y, Z)



    'Draw x,y,z axis 
    Gl.glBegin(Gl.GL_LINES)
    Gl.glColor4f(0.0F, 1.0F, 0.0F, 1.0F)

    ' Green for x axis
    Gl.glVertex3f(0.0F, 0.0F, 0.0F)
    Gl.glVertex3f(5000.0F, 0.0F, 0.0F)
    Gl.glColor3f(1.0F, 0.0F, 0.0F)
    ' Red for y axis
    Gl.glVertex3f(0.0F, 0.0F, 0.0F)
    Gl.glVertex3f(0.0F, 5000.0F, 0.0F)
    Gl.glColor3f(0.0F, 0.0F, 1.0F)
    ' Blue for z axis
    Gl.glVertex3f(0.0F, 0.0F, 0.0F)
    Gl.glVertex3f(0.0F, 0.0F, 15.0F)
    Gl.glEnd()

    ' Dotted lines for the negative sides of x,y,z
    Gl.glEnable(Gl.GL_LINE_STIPPLE)
    ' Enable line stipple to
    ' use a dotted pattern for
    ' the lines
    Gl.glLineStipple(1, &H101)
    ' Dotted stipple pattern for
    ' the lines
    Gl.glBegin(Gl.GL_LINES)
    Gl.glColor3f(0.0F, 1.0F, 0.0F)
    ' Green for x axis
    Gl.glVertex3f(-5000.0F, 0.0F, 0.0F)
    Gl.glVertex3f(0.0F, 0.0F, 0.0F)
    Gl.glColor3f(1.0F, 0.0F, 0.0F)
    ' Red for y axis
    Gl.glVertex3f(0.0F, 0.0F, 0.0F)
    Gl.glVertex3f(0.0F, -5000.0F, 0.0F)
    Gl.glColor3f(0.0F, 0.0F, 1.0F)
    ' Blue for z axis
    Gl.glVertex3f(0.0F, 0.0F, 0.0F)
    Gl.glVertex3f(0.0F, 0.0F, -5000.0F)
    Gl.glEnd()

    Gl.glDisable(Gl.GL_LINE_STIPPLE)

    ' Disable the line stipple

    Gl.glColor3f(1.0F, 1.0F, 1.0F)
    Glut.glutSolidTeapot(5)


    Gl.glEnable(Gl.GL_LIGHTING)

    Label1.Text = "X=" & lighting_x & ", Y=" & lighting_y & " Z=" & lighting_z
    Light1Position = {lighting_x, lighting_y, lighting_z, 0.0F}

    ' Enable Default Light
    Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_AMBIENT, Light1Ambient)
    Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_DIFFUSE, Light1Diffuse)
    Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION, Light1Position)
    Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_SPECULAR, Light1Specular)
    Gl.glEnable(Gl.GL_LIGHT1)

    Gl.glPopMatrix()

    draw_extras()

    Gl.glEnable(Gl.GL_COLOR_MATERIAL)
    Gl.glColorMaterial(Gl.GL_FRONT, Gl.GL_AMBIENT_AND_DIFFUSE)
    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SPECULAR, MaterialSpecular)
    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SHININESS, SurfaceShininess)

    Gl.glEnable(Gl.GL_COLOR_MATERIAL)
    Glut.glutSwapBuffers()
End Sub

По сути, у меня есть light_x, lighting_y и lighting_z в качестве переменных для перемещения моего света. У меня есть переменные X, Y и Z, которые устанавливают панорамирование (Gl.glTranslatef(X, Y, Z)). Переменные rotx, roty и rotz устанавливают вращение в основной функции с помощью Gl.glRotatef(rotX, 1.0F, 0.0F, 0.0F).

Эти переменные применяются ко всей сцене, что имеет смысл в среде САПР, так что моя ось также перемещается.

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

Private Sub zoom_fit()
    rotX = 0
    rotY = 0
    rotZ = 0
    rotLx = 0
    rotLy = 0
    rotLz = 0


    Dim i As Integer = 1
    Dim maxz As Decimal = -10000

    Do Until i >= ListView1.Items.Count
        If Convert.ToDecimal(ListView1.Items.Item(i).SubItems(2).Text) > maxz Then
            maxz = Convert.ToDecimal(ListView1.Items.Item(i).SubItems(2).Text)
        End If
        If Convert.ToDecimal(ListView1.Items.Item(i + 1).SubItems(2).Text) > maxz Then
            maxz = Convert.ToDecimal(ListView1.Items.Item(i).SubItems(2).Text)
        End If
        If Convert.ToDecimal(ListView1.Items.Item(i + 2).SubItems(2).Text) > maxz Then
            maxz = Convert.ToDecimal(ListView1.Items.Item(i).SubItems(2).Text)
        End If
        i = i + 4
    Loop




    rotLz = Convert.ToSingle((maxz - avgz) * 10)

    Gl.glMatrixMode(Gl.GL_MODELVIEW)
    Gl.glLoadIdentity()
    Glu.gluLookAt(rotLx, rotLy, 15.0 + rotLz, 0.0, 0.0, 0.0, _
        0.0, 1.0, 0.0)


    Glut.glutPostRedisplay()
End Sub

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

Что я могу видеть до сих пор:

Светлая сторона чайника:

введите описание изображения здесь

Темная сторона луны (чайник):

введите описание изображения здесь

Весь код написан на VB.NET, но ответы на C# тоже будут работать.

1 ответ

Код выглядит немного грубым, и я не буду комментировать каждую деталь, которую вам, возможно, придется исправить. Но вот некоторые важные аспекты, которые, мы надеемся, помогут вам начать работу:

  • Все состояния должны быть установлены до вызова розыгрыша. Другими словами, каждый вызов отрисовки использует точное состояние, которое было на момент вызова. Например, вы устанавливаете некоторые свойства материала в конце display() функция, после того, как все вызовы отрисовки уже были сделаны. Эти изменения состояния не повлияют ни на что до следующего вызова.

  • Вы должны быть осторожны с текущим преобразованием, когда вы указываете легкие позиции. Из спецификации:

    Текущая матрица вида модели применяется к параметру положения, указанному с помощью Light для конкретного источника света, когда указана эта позиция.

    Поэтому, если вы хотите, чтобы источник света был неподвижен относительно камеры, вам нужно сделать glLightfv(.., GL_POSITION, ..) вызовите, пока в стеке матриц нет преобразований модели.

Я не думаю, что размещение света точно в положении камеры очень распространено. Для систем типа CAD, что я видел больше всего, это источник света, расположенный в левом верхнем углу. Или, другими словами, источник света размещается с отрицательным смещением по оси x и положительным смещением по оси y относительно положения камеры. Для лучших результатов может быть полезно использовать более одного источника света. Например, размещение (возможно, более слабого) источника света в противоположном направлении позади объектов может выглядеть очень хорошо. Но вам придется поиграть с ним, чтобы увидеть, что работает лучше для вас.

Кроме того, даже если вы, вероятно, уже знаете это, но мне придется добавить (почти) обязательное: большинство используемых вами функций OpenGL устарели и устарели. Если вы изучаете, я настоятельно рекомендую изучить "современный OpenGL", то есть версию, которая больше не использует фиксированный конвейер и основана на программируемых шейдерах.

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