背景
目前,我正在制作一个将在更大的系统中使用的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)
我收到错误消息,但无法编译着色器。知道我哪里错了吗?
以下是我的模型:
看起来不错但不是很好..
看起来很糟糕..
同样糟糕......
更新
由于下面有人问过,这是我实际绘制三角形的方法。它获取信息的列表视图基本上是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文件的样子:
它从法线向量开始,然后是三角形的三个点,然后是另一个法线向量,依此类推。这就是我的循环所做的一切。
下次更新
我尝试将灯光的代码更改为:
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,因为任何一个答案都适用于我。
答案 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 } );
这很简单,但是你有你想要的所有,基本的阴影,而不只是你屏幕上的一个大颜色的斑点形成你的形状的边界。