使用Haskell OpenGL产生不良阴影

Sté*_*ent 6 opengl haskell marching-cubes

我用Haskell OpenGL绘制了Barth sextic并且存在问题.我也用R(用包rglmisc3d)绘制它,没有问题.这两种算法(在Haskell和R中)非常相似.Barth sextic是一个隐式曲面,在Haskell中我使用行进立方体算法计算这个曲面的三角剖分,我通过将其中一个转换misc3d为Haskell和C.我使用顶点法线,每个由隐式渐变定义方程.

这是问题所在:

在此输入图像描述

我不想要这些黑色阴影.当我看到sextic的背面,通过180°旋转,没有这样的阴影:

在此输入图像描述

这个Github仓库中提供了完整的代码.以下是与颜色相关的代码部分:

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
Run Code Online (Sandbox Code Playgroud)

我试图改变最后一段代码中的颜色,但无法摆脱这些阴影.我做的颜色不好吗?我确定法线是正确的,因为这在R中起作用.但是阴影出现在表面不平滑的地方,所以我想知道问题是否是由法线引起的.

R渲染:

gfycat

编辑

我设法摆脱了这些阴影:

在此输入图像描述

我真的不知道怎么做,我做了很多尝试......但无论如何,现在问题是sextic的背面太轻了:

在此输入图像描述

Sté*_*ent 2

现在渲染效果很好:-)

在此输入图像描述

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

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
Run Code Online (Sandbox Code Playgroud)
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
  ......
Run Code Online (Sandbox Code Playgroud)

我还更改了每个三角形顶点的顺序:

drawTriangle ((v1,v2,v3), (n1,n2,n3)) = do
  materialDiffuse Front $= fuchsia
  normal n1
  vertex v1
  normal n3
  vertex v3
  normal n2
  vertex v2
Run Code Online (Sandbox Code Playgroud)

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

编辑

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

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

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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

两者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
  ......
Run Code Online (Sandbox Code Playgroud)

polygonSmooth并且rescaleNormal毫无用处。我还改变了灯光的位置,但这不是引起问题的点。这cullFace不是必需的,但它很好,因为没有可见的背面。