Open GL Lighting Adiculties

时间:2015-07-17 18:46:33

标签: c# vb.net opengl tao-framework

背景

目前,我正在制作一个将在更大的系统中使用的CAD查看器。我一直在阅读有关学习Open GL的大量信息,而且我还有很长的路要走。我可以导入文件,显示它,并使用键盘控件进行导航。我现在正在努力理解并建立适当的照明。

问题

经过一些讨论后,我意识到我没有加载着色器,这就是我遇到问题的原因。在做一些研究时,我发现了一些用C编写的着色器文件,fragment.glsl和vertex.glsl。这是一个问题,因为我在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)

我收到错误消息,但无法编译着色器。知道我哪里错了吗?

以下是我的模型:

http://i.imgur.com/UvN4Tj8.png

看起来不错但不是很好..

http://i.imgur.com/G2TJt12.png

看起来很糟糕..

http://i.imgur.com/SXZ7C5S.png

同样糟糕......

更新

由于下面有人问过,这是我实际绘制三角形的方法。它获取信息的列表视图基本上是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 sub:

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文件的样子:

enter image description here

它从法线向量开始,然后是三角形的三个点,然后是另一个法线向量,依此类推。这就是我的循环所做的一切。

下次更新

我尝试将灯光的代码更改为:

 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)

找不到光明:

enter image description here

任何指导都会受到极大的关注。我将其标记为C#和VB .NET,因为任何一个答案都适用于我。

3 个答案:

答案 0 :(得分:2)

您还可以编写自己的着色器来渲染实际对象,这将计算漫反射光照,如果需要,甚至可能是镜面反射。从那里,你还可以做纹理贴图,阴影,法线等。

OpenGL在着色器代码here上有一个很好的教程,你可以在互联网上找到一个关于在C#上使用GLSL的教程。

答案 1 :(得分:1)

我不同意这里的答案,如果你的目标是拥有简单的灯光而你刚开始学习OGL,那么你就不必编写自己的着色器。 OpenGL具有内置功能来为您处理这个问题,因为我相信您已经在许多教程中看到过。尽管不再支持此功能,但这会促使许多人谴责它,尽管它有明显的好处,它会使您的学习过程更加轻松。

由于已经提到您已启用照明,我想知道您当前如何绘制模型。如果你使用立即模式(为每个顶点调用glVertex),你还调用glNormal来提供法线吗?没有法线,OpenGL没有关于如何计算模型光照的信息。如果您不使用立即模式,请准确说明您的操作。提交您的代码将是一个很大的帮助,因为我不知道您目前正在做什么,并且OpenGL有一百万种方法可以让您犯错误。

作为补充:您链接的教程中的着色器代码对于初学者来说似乎过于复杂,您不应该使用它。

我想把它放在评论中而不是答案中,但我的声誉目前还不够。

请在我的回答评论中提出任何问题,以便逐步解决您的问题。

答案 2 :(得分:-1)

当你打开闪电时我无处可见。你可以用glEnable(GL_LIGHTn)打开2个灯,但是没有启用。如果你感到困惑,那就有一个article。我是这么说的,因为你的模特看起来都没有阴影,它们都有相同的颜色,颜色不取决于表面如何指向光源,如果你设置它不依赖于法线我应该说。我认为两个光线足够用于此目的,对于演示项目,我通常使用一个漫射光进行闪电,我甚至没有设置环境光或镜面反射部分。像这样:

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, { 0.8f, 0.8f, 0.8f, 1.0f } );

这很简单,但是你有你想要的所有,基本的阴影,而不只是你屏幕上的一个大颜色的斑点形成你的形状的边界。