Open GL Lighting Трудности
Фон
В настоящее время я по сути делаю просмотрщик САПР, который будет использоваться в более крупной системе. Я читал тонну информации об изучении Open GL, и я довольно далеко продвинулся. Я могу импортировать файл, отображать его и перемещаться с помощью клавиш управления. Я стараюсь понять и настроить правильное освещение сейчас.
проблема
После некоторого обсуждения ниже, я понимаю, что у меня нет загруженного шейдера, поэтому у меня проблемы. Проводя некоторые исследования, я нашел несколько шейдерных файлов, фрагмента.glsl и vertex.glsl, которые написаны на C. Будет ли это проблемой, так как я пишу свой код на C#/ VB.net? Я так не думаю.
Теперь у меня проблема с компиляцией шейдинга и связыванием шейдеров с моим кодом. Я нашел удобный источник для компиляции:
http://pages.cpsc.ucalgary.ca/~brosz/wiki/pmwiki.php/CSharp/08022008
В этой статье создается функция для компиляции шейдера. Компилятору требуется поток, в который затем передается компилятору. У меня есть эта функция, которую я создал, чтобы читать шейдер в поток:
Public Function path_to_stream(ByVal path As String) As System.IO.Stream
Dim bData As Byte()
Dim br As System.IO.BinaryReader = New System.IO.BinaryReader(System.IO.File.OpenRead(path))
bData = br.ReadBytes(br.BaseStream.Length)
Dim ms As System.IO.MemoryStream = New System.IO.MemoryStream(bData, 0, bData.Length)
ms.Write(bData, 0, bData.Length)
Return ms
End Function
В конце своей функции рисования я пытаюсь загрузить, используя функцию шейдера:
vertexShader = path_to_stream(Application.StartupPath & "\default.frag")
fragmentShader = path_to_stream(Application.StartupPath & "\default.vert")
vs_object = Helpers.OpenGLUtilities.createAndCompileShader(vertexShader, Gl.GL_VERTEX_SHADER)
fs_object = Helpers.OpenGLUtilities.createAndCompileShader(fragmentShader, Gl.GL_FRAGMENT_SHADER)
program = Helpers.OpenGLUtilities.createAttachLinkShaderProgram(vs_object, fs_object)
Однако я получаю сообщение об ошибке, что шейдер не может быть скомпилирован. Любая идея, где я иду не так?
Вот как выглядит моя модель:
Выглядит достойно, но не отлично..
Выглядит ужасно..
Так же плохо..
Обновить
Так как это было задано ниже, это мой метод для рисования моих треугольников. Представление списка, из которого он получает информацию, в основном представляет собой файл STL, который содержит вектор нормали, а затем три точки, образующие треугольник.
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)
'Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_FILL)
Gl.glBegin(Gl.GL_TRIANGLES)
Gl.glColor3f(part_color.R, part_color.G, part_color.B)
Dim i As Integer = 0
Do Until i + 4 >= ListView1.Items.Count
Gl.glNormal3f(ListView1.Items.Item(i).SubItems(0).Text, ListView1.Items.Item(i).SubItems(1).Text, ListView1.Items.Item(i).SubItems(2).Text)
Gl.glVertex3f(ListView1.Items.Item(i + 1).SubItems(0).Text - avgx, ListView1.Items.Item(i + 1).SubItems(1).Text - avgy, ListView1.Items.Item(i + 1).SubItems(2).Text - avgz)
Gl.glVertex3f(ListView1.Items.Item(i + 2).SubItems(0).Text - avgx, ListView1.Items.Item(i + 2).SubItems(1).Text - avgy, ListView1.Items.Item(i + 2).SubItems(2).Text - avgz)
Gl.glVertex3f(ListView1.Items.Item(i + 3).SubItems(0).Text - avgx, ListView1.Items.Item(i + 3).SubItems(1).Text - avgy, ListView1.Items.Item(i + 3).SubItems(2).Text - avgz)
i = i + 4
Loop
Gl.glEnd()
Мой основной чертежный саб:
Private Sub display()
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT)
' Clear the Color Buffer
Gl.glPushMatrix()
' It is important to push
' the Matrix before calling
' glRotatef and glTranslatef
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)
' Translates the screen
' left or right, up or down
' or zoom in zoom out
' Draw the positive side of the lines x,y,z
Gl.glBegin(Gl.GL_LINES)
'Gl.glColor3f(0.0F, 1.0F, 0.0F)
Gl.glColor4f(0.0F, 1.0F, 0.0F, 1.0F)
' Green for x axis
Gl.glVertex3f(0.0F, 0.0F, 0.0F)
Gl.glVertex3f(10.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, 10.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, 10.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(-10.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, -10.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, -10.0F)
Gl.glEnd()
Gl.glDisable(Gl.GL_LINE_STIPPLE)
' Disable the line stipple
Gl.glPopMatrix()
' Don't forget to pop the Matrix
Gl.glEnable(Gl.GL_LIGHTING)
Light1Position = {0.0F, 0.0F, 100.0F, 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)
' Enable Lighting
Gl.glEnable(Gl.GL_LIGHT1)
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
Моя ветка draw_extra:
Public Sub draw_extras()
Dim texture As UInteger() = New UInteger(0) {}
If allowdraw = True Then
find_center_of_part()
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)
Gl.glBegin(Gl.GL_TRIANGLES)
Gl.glColor3f(part_color.R, part_color.G, part_color.B)
Dim i As Integer = 0
Do Until i + 4 >= ListView1.Items.Count
Gl.glNormal3f(ListView1.Items.Item(i).SubItems(0).Text, ListView1.Items.Item(i).SubItems(1).Text, ListView1.Items.Item(i).SubItems(2).Text)
Gl.glVertex3f(ListView1.Items.Item(i + 1).SubItems(0).Text - avgx, ListView1.Items.Item(i + 1).SubItems(1).Text - avgy, ListView1.Items.Item(i + 1).SubItems(2).Text - avgz)
Gl.glVertex3f(ListView1.Items.Item(i + 2).SubItems(0).Text - avgx, ListView1.Items.Item(i + 2).SubItems(1).Text - avgy, ListView1.Items.Item(i + 2).SubItems(2).Text - avgz)
Gl.glVertex3f(ListView1.Items.Item(i + 3).SubItems(0).Text - avgx, ListView1.Items.Item(i + 3).SubItems(1).Text - avgy, ListView1.Items.Item(i + 3).SubItems(2).Text - avgz)
i = i + 4
Loop
Gl.glEnd()
' Disable the line stipple
Gl.glPopMatrix()
End If
End Sub
Вот как выглядит файл STL:
Он начинается с вектора нормали, затем следуют три точки для треугольника, затем еще один вектор нормали и так далее. Это все, что делает мой цикл.
Следующее обновление
Я попытался изменить код для света, чтобы быть:
Gl.glEnable(Gl.GL_LIGHTING)
Light1Position = {X, Y, 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)
' Enable Lighting
Gl.glEnable(Gl.GL_LIGHT1)
Переменные X, Y, Z должны соответствовать камере, так как ранее в коде она переводит камеру:
Gl.glTranslatef(X, Y, Z)
Нет света, чтобы найти:
Любое руководство будет очень оценено. Я отметил это как C# и VB .NET, так как оба ответа будут работать для меня.
3 ответа
Вы также можете написать свой собственный шейдер для визуализации вашего реального объекта, который будет рассчитывать рассеянное освещение, возможно, даже зеркальное, если хотите. Оттуда вы также можете делать наложение текстур, тени, нормали и т. Д.
OpenGL предлагает отличное руководство по коду шейдера, и вы можете найти руководство по использованию GLSL с C# в Интернете.
Я не согласен с ответами здесь: если ваша цель - иметь простое освещение и вы только начинаете изучать OGL, вам не нужно писать свои собственные шейдеры. OpenGL имеет встроенную функциональность, чтобы справиться с этим для вас, как я уверен, вы видели во многих руководствах. Хотя эта функция больше не поддерживается, что побуждает многих людей осуждать ее, несмотря на ее очевидные преимущества, она значительно облегчит ваш учебный процесс.
Поскольку уже упоминалось, что вы включили освещение, я хотел бы знать, как вы в данный момент рисуете свою модель. Если вы используете немедленный режим (вызывая glVertex для каждой вершины), вызываете ли вы также glNormal для предоставления нормалей? Без нормалей OpenGL не имеет информации о том, как рассчитать освещение для вашей модели. Если вы не используете немедленный режим, пожалуйста, объясните, что именно вы делаете. Отправка вашего кода была бы большой помощью, так как я понятия не имею, чем вы сейчас занимаетесь, и у OpenGL есть миллион способов сделать ошибку.
Как дополнение: код шейдера в учебнике, который вы связали, кажется слишком сложным для начинающего, вы не должны его использовать.
Я хотел бы поместить это в комментарии вместо ответа, но моя репутация в настоящее время недостаточна.
Пожалуйста, задавайте любые вопросы в комментариях к моему ответу, чтобы можно было найти пошаговое решение вашей проблемы.
Я нигде не вижу, когда ты включил молнию. Это нормально, что вы включили 2 лампы с glEnable(GL_LIGHTn)
но весь материал не включен. Там есть статья, если вы запутались. Я говорю, что, поскольку ваши модели выглядят совсем не затененными, все они имеют одинаковый цвет, и этот цвет не зависит от того, как поверхность направлена на источник света, не зависит от нормального, если вы установите его. должен сказать. Я думаю, что двух источников света достаточно для этой цели, для демонстрационных проектов у меня обычно есть молния с одним рассеянным светом, я даже не устанавливаю рассеивающую или зеркальную часть. Вот так:
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, { 0.8f, 0.8f, 0.8f, 1.0f } );
Это довольно просто, но у вас есть все, что вы, вероятно, хотите, базовое затенение, а не только одно большое цветовое пятно на экране, формирующее границу вашей фигуры.