使用Haskell Opengl实现光泽度
我用Haskell OpenGL做了很多图形。它们在我这里的回购协议中:(画廊并非详尽无遗)。然而,我有一个问题:当我使用使用Haskell Opengl实现光泽度,haskell,opengl,Haskell,Opengl,我用Haskell OpenGL做了很多图形。它们在我这里的回购协议中:(画廊并非详尽无遗)。然而,我有一个问题:当我使用材料时,透明度什么都没有发生。有什么东西可以让你拥有光泽吗 下面是我的一个程序示例。它还不完整,但我希望它足以确定问题所在 module CompoundFiveTetrahedra2 where import CompoundFiveTetrahedra.Data import Control.Monad
材料时,透明度什么都没有发生。有什么东西可以让你拥有光泽吗
下面是我的一个程序示例。它还不完整,但我希望它足以确定问题所在
module CompoundFiveTetrahedra2
where
import CompoundFiveTetrahedra.Data
import Control.Monad (when)
import qualified Data.ByteString as B
import Data.IORef
import Graphics.Rendering.OpenGL.Capture (capturePPM)
import Graphics.Rendering.OpenGL.GL
import Graphics.UI.GLUT
import Text.Printf
import Utils.ConvertPPM
import Utils.OpenGL (negateNormal)
import Utils.Prism
blue,red,green,yellow,purple,white,black :: Color4 GLfloat
blue = Color4 0 0 1 1
red = Color4 1 0 0 1
green = Color4 0 1 0 1
yellow = Color4 1 1 0 1
white = Color4 1 1 1 1
black = Color4 0 0 0 1
purple = Color4 0.5 0 0.5 1
display :: IORef GLfloat -> IORef GLfloat -> IORef GLfloat -> IORef GLdouble
-> IORef GLint -> IORef GLfloat -> DisplayCallback
display rot1 rot2 rot3 zoom capture angle = do
clear [ColorBuffer, DepthBuffer]
r1 <- get rot1
r2 <- get rot2
r3 <- get rot3
z <- get zoom
a <- get angle
i <- get capture
loadIdentity
(_, size) <- get viewport
resize z size
rotate a $ Vector3 1 1 1
rotate r1 $ Vector3 1 0 0
rotate r2 $ Vector3 0 1 0
rotate r3 $ Vector3 0 0 1
mapM_ (drawEdge blue) (edges!!0)
mapM_ (drawEdge red) (edges!!1)
mapM_ (drawEdge green) (edges!!2)
mapM_ (drawEdge yellow) (edges!!3)
mapM_ (drawEdge purple) (edges!!4)
mapM_ (drawVertex blue) vertices1
mapM_ (drawVertex red) vertices2
mapM_ (drawVertex green) vertices3
mapM_ (drawVertex yellow) vertices4
mapM_ (drawVertex purple) vertices5
when (i > 0) $ do
let ppm = printf "tetrahedra%04d.ppm" i
png = printf "tetrahedra%04d.png" i
(>>=) capturePPM (B.writeFile ppm)
convert ppm png True
capture $~! (+1)
swapBuffers
drawVertex :: Color4 GLfloat -> Vertex3 GLfloat -> IO ()
drawVertex col v =
preservingMatrix $ do
translate $ toVector v
materialDiffuse Front $= col
renderObject Solid $ Sphere' 0.03 30 30
where
toVector (Vertex3 x y z) = Vector3 x y z
drawEdge :: Color4 GLfloat -> (Vertex3 GLfloat, Vertex3 GLfloat) -> IO ()
drawEdge col (v1,v2) = do
let cylinder = prism v1 v2 30 0.03
renderPrimitive Quads $ do
materialDiffuse Front $= col
mapM_ drawQuad cylinder
where
drawQuad ((w1,w2,w3,w4),n) = do
normal $ negateNormal n
vertex w1
vertex w2
vertex w3
vertex w4
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 (-3 + zoom)) (Vertex3 0 0 0) (Vector3 0 1 0)
matrixMode $= Modelview 0
where
w' = realToFrac w
h' = realToFrac h
keyboard :: IORef GLfloat -> IORef GLfloat -> IORef GLfloat -> IORef GLint
-> KeyboardCallback
keyboard rot1 rot2 rot3 capture c _ =
case c of
'r' -> rot1 $~! subtract 1
't' -> rot1 $~! (+1)
'f' -> rot2 $~! subtract 1
'g' -> rot2 $~! (+1)
'v' -> rot3 $~! subtract 1
'b' -> rot3 $~! (+1)
'c' -> capture $~! (+1)
'q' -> leaveMainLoop
_ -> return ()
mouse :: IORef GLdouble -> MouseCallback
mouse zoom button keyState _ =
case (button, keyState) of
(LeftButton, Down) -> zoom $~! (+0.1)
(RightButton, Down) -> zoom $~! subtract 0.1
_ -> return ()
idle :: IORef GLfloat -> IdleCallback
idle angle = do
angle $~! (+ 2)
postRedisplay Nothing
main :: IO ()
main = do
_ <- getArgsAndInitialize
_ <- createWindow "Five tetrahedra"
initialDisplayMode $= [RGBAMode, DoubleBuffered, WithDepthBuffer]
clearColor $= black
materialAmbient Front $= black
materialShininess Front $= 80 -- THIS DOES NOT WORK
lighting $= Enabled
light (Light 0) $= Enabled
position (Light 0) $= Vertex4 0 0 (-100) 1
ambient (Light 0) $= white
diffuse (Light 0) $= white
specular (Light 0) $= white
depthFunc $= Just Lequal
depthMask $= Enabled
shadeModel $= Smooth
rot1 <- newIORef 0.0
rot2 <- newIORef 0.0
rot3 <- newIORef 0.0
zoom <- newIORef 0.0
capture <- newIORef 0
angle <- newIORef 0.0
displayCallback $= display rot1 rot2 rot3 zoom capture angle
reshapeCallback $= Just (resize 0)
keyboardCallback $= Just (keyboard rot1 rot2 rot3 capture)
mouseCallback $= Just (mouse zoom)
idleCallback $= Just (idle angle)
mainLoop
模块组件五层四面体A2
哪里
导入CompoundFiveTetrahedra.Data
导入控制.Monad(何时)
将限定数据.ByteString作为B导入
导入数据.IORef
导入Graphics.Rendering.OpenGL.Capture(capturePPM)
导入Graphics.Rendering.OpenGL.GL
导入Graphics.UI.GLUT
导入文本.Printf
导入Utils.convertpm
导入Utils.OpenGL(默认值)
导入Utils.Prism
蓝色、红色、绿色、黄色、紫色、白色、黑色::彩色4 GLfloat
蓝色=彩色4 0 1 1 1
红色=颜色41 0 0 1
绿色=彩色4 0 1 0 1
黄色=颜色4 1 0 1
白色=彩色4 1
黑色=彩色4 0 0 1
紫色=颜色40.50 0.51
显示::IORef GLfloat->IORef GLfloat->IORef GLfloat->IORef GLdouble
->IORef闪烁->IORef GLfloat->显示回调
显示rot1 rot2 rot3缩放捕捉角度=do
清除[颜色缓冲区,深度缓冲区]
r1更新:尝试1.0的反光度,以在低分辨率下更清楚地看到差异
“光泽度”参数会影响镜面反射照明的锐度,因此需要为材质启用这种类型的照明,方法是为材质指定镜面反射颜色。(默认情况下,镜面反射颜色为黑色,因此“光泽度”参数的效果将不可见。)您还需要减小此场景的“光泽度”值,因为该值太高,无法非常可见
尝试:
您将开始看到白色高光,尤其是沿着形状的弯曲边缘。平面也会反射一些白光,但只有当它们几乎垂直于观察者和光源之间夹角的直线时——这有点复杂
请注意,大多数材质的镜面反射颜色都是白色的“倍数”(即,对于完全暗淡的材质,黑色与对于场景中最亮的材质,白色之间的某个位置)。唯一具有有色镜面反射颜色的材料是有色金属,如金或青铜
一些补充说明:
- 您使用的是旧式OpenGL 2.1着色,而不是“现代OpenGL”,因此您不必太担心@user2297560所说的“着色器”。OpenGL 2.1自带了内置的着色器来进行基本着色;使用现代OpenGL,您必须从头开始构建所有内容
- 正如@luqui所提到的,如果你在寻找能够真实反映场景其他部分的材质,这种反光对你没有帮助
这就是区别。您的原始代码在左侧,上面的设置在右侧,在您的“compoundfivetetrahedra”示例中。如果你加大窗户的尺寸,看起来会更好
请注意,它在曲面上效果更好。以下是圆柱体示例,使用:
materialShininess Front $= 5
materialSpecular Front $= white
你可以在更近的球体上看到光亮
非常酷的例子。我不是OpenGL专家,但我以前玩过它。iirc,您需要创建一个着色器,该着色器需要用一种特殊的着色器语言编译一些代码。请参见Graphics.Rendering.OpenGL.GL.Shaders.Thank you@user2297560。我也不是专家,但我不知道着色器是什么。它可能会起作用,但不会达到您的预期,并且可能不会在您创建的示例场景中产生任何效果。光泽度只是照明中镜面反射点的大小,它不会产生反射或任何东西。谢谢@luqui。不幸的是,我不容易理解这样的讨论。顺便说一句,我也在使用R包rgl,它也是OpenGL的包装,我想知道作者是如何处理反光的。不幸的是,代码很难。回到你的评论,我应该说我对所有与照明有关的东西都有点迷茫。我经常随机尝试,直到我达到我想要的。@Stéphanelant我不认为这一定是一个坏方法——你可以阅读有关照明的数学知识,但我不确定它是否给出了实践中的直觉。虽然了解不同的术语的含义会有所帮助。也许值得读一本专门关于照明的教程(我并没有读过,只是略读了一下),以获得不同组件的结构化感觉。谢谢。我试得很快,但没有发现任何区别。稍后我将在球体上进行尝试。我不知道“模型OpenGL”。很抱歉,我没有获得白度。我编辑了我的文章,加入了一个例子来说明我的意思。我从你的代码中添加了几个例子来展示效果。非常感谢!我稍后再试。太好了。嗯,对不起,我还没来得及。我试过马鞍,它很弯。你到底把代码放在哪里了?把它放在主功能中可以吗?或者我应该把它放在我做的renderPrimitive
的地方吗?
materialShininess Front $= 5
materialSpecular Front $= white