【问题标题】:Undesirable shadows with Haskell OpenGLHaskell OpenGL 产生不受欢迎的阴影
【发布时间】:2018-11-16 08:11:16
【问题描述】:

我用 Haskell OpenGL 绘制了 Barth 六分仪,但出现了问题。我也在 R 中画了它(带有包rglmisc3d),没有问题。这两种算法(在 Haskell 和 R 中)非常相似。 Barth sextic 是一个隐式曲面,在 Haskell 中,我使用行进立方体算法计算该曲面的三角剖分,我通过将 misc3d 中的一个转换为 Haskell 和 C。我使用顶点法线,每个法线由梯度定义的隐式方程。

问题来了:

我不想要这些黑色阴影。当我看六分仪的背面时,旋转了 180°,没有这样的阴影:

完整代码可在this Github repo 中找到。以下是与颜色相关的代码部分:

fuchsia :: Color4 GLfloat
fuchsia = Color4 1.00 0.00 1.00 1
discord :: Color4 GLfloat
discord = Color4 0.21 0.22 0.25 1

  renderPrimitive Triangles $ mapM_ drawTriangle triangles
  swapBuffers
  where
    drawTriangle ((v1,v2,v3), (n1,n2,n3)) = do
      materialDiffuse FrontAndBack $= fuchsia
      normal n1
      vertex v1
      normal n2
      vertex v2
      normal n3
      vertex v3

  clearColor $= discord
  materialAmbient FrontAndBack $= black
  materialDiffuse FrontAndBack $= white
  materialEmission FrontAndBack $= black
  lighting $= Enabled
  lightModelTwoSide $= Enabled
  light (Light 0) $= Enabled
  position (Light 0) $= Vertex4 0 0 (-1000) 1
  ambient (Light 0) $= white
  diffuse (Light 0) $= white
  specular (Light 0) $= white

我已尝试更改最后一段代码中的颜色,但无法摆脱这些阴影。我对颜色做坏事了吗?我确信法线是正确的,因为这在 R 中有效。但是阴影出现在表面不光滑的地方,所以我想知道问题是否是由法线引起的。

R 渲染:

编辑

我已经设法摆脱了这些阴影:

我真的不知道怎么做的,我做了这么多尝试......但不管怎样,现在的问题是六分仪的背面太轻了:

【问题讨论】:

  • 对法线进行颜色调试
  • @Nadir 你是什么意思?
  • 不要绘制隐式表面的阴影颜色,而是将颜色输出设置为就好像法线向量是一种颜色一样。
  • 问题是表面的真实法线变化太快,粗三角无法重现它们。因此,您可以尝试的一件事是增加 Marching Cubes 分辨率。像这样的尖点对于每个顶点法线来说总是有问题的,因为您无法合理地对它们进行插值。第二种选择是将它们保留为角,并使用单独的法线复制顶点(您对面内的顶点进行一点评估)。
  • 这真的很奇怪。当只有一盏灯时,我观察到类似的行为,在 (0,0,0),这是对象的中心。

标签: haskell opengl marching-cubes


【解决方案1】:

现在渲染很好:-)

我不知道是什么导致了这个问题,因为我做了很多更改......以下是代码的相关部分:

resize :: Double -> Size -> IO ()
resize zoom s@(Size w h) = do
  viewport $= (Position 0 0, s)
  matrixMode $= Projection
  loadIdentity
  perspective 45.0 (w'/h') 1.0 100.0
  lookAt (Vertex3 0 0 (-6+zoom)) (Vertex3 0 0 0) (Vector3 0 1 0)
  matrixMode $= Modelview 0
  where
    w' = realToFrac w
    h' = realToFrac h

main :: IO ()
main = do
  _ <- getArgsAndInitialize
  _ <- createWindow "Barth Sextic"
  windowSize $= Size 500 500
  initialDisplayMode $= [RGBMode, DoubleBuffered, WithDepthBuffer]
  clearColor $= discord
  clientState ColorArray $= Disabled -- this is a default option, I think
  materialAmbient Front $= black
  materialDiffuse Front $= white
  materialEmission Front $= Color4 0 0 0 0
  materialSpecular Front $= white
  materialShininess Front $= 50
  lighting $= Enabled
  light (Light 0) $= Enabled
  position (Light 0) $= Vertex4 500 500 (-1000) 1
  diffuse (Light 0) $= white
  specular (Light 0) $= white
  lightModelAmbient $= Color4 0.35 0.35 0.35 1
  depthMask $= Enabled -- this is default option
  depthFunc $= Just Lequal
  shadeModel $= Smooth
  fog $= Disabled -- this is default option, I think
  polygonMode $= (Fill, Fill) -- this is default option
  polygonSmooth $= Enabled
  cullFace $= Just Front
  rescaleNormal $= Enabled
  ......

我也改变了每个三角形的顶点顺序:

drawTriangle ((v1,v2,v3), (n1,n2,n3)) = do
  materialDiffuse Front $= fuchsia
  normal n1
  vertex v1
  normal n3
  vertex v3
  normal n2
  vertex v2

这个答案有点为时过早。稍后我会进行更多调查,我会进行编辑以写下我的发现。

编辑

好吧,我做了进一步的调查,可悲的是,我的结论是我没有任何解释:我已经恢复了我的所有更改,并且无法重现该问题!

现在我使用这个更短的代码:

display :: ...... -> displayCallback
  ......
  renderPrimitive Triangles $
    mapM_ drawTriangle triangles
  swapBuffers
  where
    drawTriangle ((v1,v2,v3), (n1,n2,n3)) = do
      materialDiffuse Front $= fuchsia
      normal n1
      vertex v1
      normal n2
      vertex v2
      normal n3
      vertex v3

resize :: Double -> Size -> IO ()
resize zoom s@(Size w h) = do
  viewport $= (Position 0 0, s)
  matrixMode $= Projection
  loadIdentity
  perspective 45.0 (w'/h') 1.0 100.0
  lookAt (Vertex3 0 0 (-6+zoom)) (Vertex3 0 0 0) (Vector3 0 1 0)
  matrixMode $= Modelview 0
  where
    w' = realToFrac w
    h' = realToFrac h

这两个MatrixMode 很重要。

main :: IO ()
main = do
  _ <- getArgsAndInitialize
  _ <- createWindow "Barth Sextic"
  windowSize $= Size 500 500
  initialDisplayMode $= [RGBMode, DoubleBuffered, WithDepthBuffer]
  clearColor $= discord
  materialAmbient Front $= black
  materialDiffuse Front $= white
  materialEmission Front $= black
  lighting $= Enabled
  light (Light 0) $= Enabled
  position (Light 0) $= Vertex4 500 500 (-1000) 1
  ambient (Light 0) $= white
  diffuse (Light 0) $= white
  specular (Light 0) $= white
  depthFunc $= Just Less
  shadeModel $= Smooth
  cullFace $= Just Back
  ......

polygonSmoothrescaleNormal 没用。我也改变了灯的位置,但这不是导致问题的地方。 cullFace 不是必需的,但它很好,因为没有可见的背面。

【讨论】:

  • 这里有两点让我印象深刻:-rescaleNormal $= Enabled,它可能正确地“修复”了你的法线。 - 你的灯的位置在一个非常不同的位置。我的预感是,您最初的问题的可能原因是法线不正确。
  • 谢谢@Mokosha。稍后我将尝试逐个取消设置每个选项,以便找到确凿的证据。我还更改了每个三角形顶点的顺序,如果这是问题的根源,我不会感到惊讶。
  • @Mokosha 不。 rescaleNormal 没有效果,问题不是由于灯光的位置(见我的编辑)。我迷路了。我确信我已经复制了导致问题的代码,但现在它不会导致问题......我肯定忘记了一个微妙的点,或者这是一个错误。
猜你喜欢
  • 2021-02-20
  • 1970-01-01
  • 2022-11-12
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 2021-07-02
  • 1970-01-01
  • 2020-10-16
相关资源
最近更新 更多