diff options
-rw-r--r-- | Final.hs | 1 | ||||
-rw-r--r-- | Graphics/Glyph/Util.hs | 13 | ||||
-rw-r--r-- | Resources.hs | 43 | ||||
-rw-r--r-- | shaders/snow.frag | 13 | ||||
-rw-r--r-- | shaders/snow.geom | 26 | ||||
-rw-r--r-- | shaders/snow.vert | 20 |
6 files changed, 113 insertions, 3 deletions
@@ -122,6 +122,7 @@ colorArray marr = do - 2 things: - A map of water bodies ids to elevations (to detect if you are under water - A builder that will generate all of the quads for the water. -} + getWaterQuads :: Array (Int,Int) Tile -> IOArray (Int,Int) Int -> IO ( Map.Map Int GLfloat, BuilderM GLfloat () ) getWaterQuads marr arr = do let (_,(w,h)) = bounds marr diff --git a/Graphics/Glyph/Util.hs b/Graphics/Glyph/Util.hs index 21e219a..2a3e060 100644 --- a/Graphics/Glyph/Util.hs +++ b/Graphics/Glyph/Util.hs @@ -322,3 +322,16 @@ fpart x = x - (fromIntegral (floor x::Int)) ifNaN :: (RealFloat a) => a -> a -> a ifNaN reg def = if' (isNaN reg) def reg + +everyN :: Int -> [a] -> [a] +everyN _ [] = [] +everyN n (x : xs) = x : (everyN n $ drop n xs) + +chunkList :: [a] -> [(a,a)] +chunkList l = zip [x | x <- everyN 1 l] [x | x <- everyN 1 (tail l)] + +chunkList3 :: [a] -> [(a,a,a)] +chunkList3 l = zip3 + [x | x <- everyN 2 l] + [x | x <- everyN 2 (tail l)] + [x | x <- everyN 2 (tail $ tail l)] diff --git a/Resources.hs b/Resources.hs index c0a947c..a04afa7 100644 --- a/Resources.hs +++ b/Resources.hs @@ -43,6 +43,7 @@ import Data.Time.Clock.POSIX import Control.Concurrent import Text.Printf import System.IO +import System.Random {- Types of terrain which are possible -} data TileType = Forest | Beach | Water | Grass | Jungle | Mountains | @@ -282,7 +283,6 @@ eventHandle event res = do return $ setSpeedMultiplier 1 res _ -> return res - where oracle = if (mode res == FirstPerson) then 1 else 3 {- Callback for the display -} displayHandle :: Resources -> IO Resources @@ -448,6 +448,41 @@ buildTerrainObject builder = do -- uniform lightposU $= rcLightPos rc -- setupTexturing3D density densityU 0 +buildSnowVal :: Array (Int,Int) Tile -> StdGen -> BuilderM GLfloat () +buildSnowVal arr gen = + let (_,(w,h)) = bounds arr + run :: [Int] -> (Int,Int) -> BuilderM GLfloat [Int] + run rs (x,y) = do + let (seed:npart:t) = rs + nStdGen = mkStdGen seed + height = elevation (arr ! (x,y)) + when (tileType (arr ! (x,y)) == Tundra) $ + forM_ (take (npart`mod`50) $ chunkList3 $ randomRs (0::GLfloat,1) nStdGen ) $ \(a,b,c) -> do + let (x',y') = (int x + a, int y + b) + bVertex3 (x',c*100,y') + bColor4 (int $ height `div` 10,1, 0, 0) + + return t + in + + foldM_ run (randoms gen) [(x,y) | x <- [1..w], y <- [1..h]] + +buildSnowObject :: Array (Int,Int) Tile -> StdGen -> IO (ResourcesClosure -> IO ()) +buildSnowObject arr gen = do + snowProgram <- loadProgramSafe' "shaders/snow.vert" "shaders/snow.frag" (Just "shaders/snow.geom") + obj <- + liftM (setPrimitiveMode Ex.Points) $ + newDefaultGlyphObjectWithClosure (buildSnowVal arr gen) () $ \_ -> do + currentProgram $= Just snowProgram + + [globalAmbientU,pjMatrixU,mvMatrixU,timeU] <- + getUniformsSafe snowProgram ["globalAmbient","pjMatrix","mvMatrix","time"] + return $ \rc -> do + draw $ (prepare obj) $ \_ -> do + uniform mvMatrixU $= rcMVMatrix rc + uniform pjMatrixU $= rcPMatrix rc + uniform timeU $= (Index1 $ (rcTime rc/75)) + uniform globalAmbientU $= rcGlobalAmbient rc buildForestObject :: Seq.Seq GLfloat -> String -> String -> IO (ResourcesClosure -> IO ()) buildForestObject a_seq obj tex = @@ -532,7 +567,7 @@ buildWaterObject builder = do uniform (UniformLocation 5) $= rcMVMatrix rc uniform (UniformLocation 7) $= rcNormalMatrix rc uniform (UniformLocation 8) $= rcLightPos rc - uniform (UniformLocation 9) $= Index1 (rcTime rc / 20.0) + uniform (UniformLocation 9) $= Index1 (rcTime rc / 20.0); uniform (UniformLocation 10) $= rcGlobalAmbient rc bool <- (resourcesUnderWater $ rcResources rc) if bool then @@ -548,6 +583,7 @@ makeResources surf builder forestB jungleB water arr waterarr = do hSetBuffering stdout NoBuffering let pMatrix' = perspectiveMatrix 50 1.8 0.1 100 + stdgen <- newStdGen let l_routines = sequence [ skyboxObject, (return $ \_ -> do @@ -560,7 +596,8 @@ makeResources surf builder forestB jungleB water arr waterarr = do blendFunc $= (GL.SrcAlpha,OneMinusSrcAlpha)), buildWaterObject water, buildForestObject forestB "tree.obj" "textures/wood_low.png", - buildForestObject jungleB "jungletree.obj" "textures/jungle_tree.png" + buildForestObject jungleB "jungletree.obj" "textures/jungle_tree.png", + buildSnowObject arr stdgen -- cloudProgram ] Resources diff --git a/shaders/snow.frag b/shaders/snow.frag new file mode 100644 index 0000000..d494633 --- /dev/null +++ b/shaders/snow.frag @@ -0,0 +1,13 @@ +#version 150 +#extension GL_ARB_explicit_attrib_location : enable +#extension GL_ARB_explicit_uniform_location : enable + +layout(location = 0) out vec4 frag_color ; + +in float rad ; + +uniform vec4 globalAmbient ; + +void main() { + frag_color = vec4( 1.0,1.0,1.0,(9 - rad*rad)/9) * vec4(normalize(globalAmbient.xyz),globalAmbient.a) ; +} diff --git a/shaders/snow.geom b/shaders/snow.geom new file mode 100644 index 0000000..116a59d --- /dev/null +++ b/shaders/snow.geom @@ -0,0 +1,26 @@ +#version 150 +layout(points) in; +layout(triangle_strip, max_vertices=28) out; + +out float rad ; + +void vertex( vec3 pos ) { + gl_Position = gl_in[0].gl_Position + vec4(pos,0.0) ; + EmitVertex() ; +} + +void main( ) { + float r = 0.008 ; + float th = 0.00 ; + for( ; th < 6.3 ; th += 0.5 ) { + rad = 3 ; + vertex( vec3(r*sin(th),r*cos(th),0.0) ) ; + rad = 0.0 ; + vertex( vec3(0.0,0.0,0.0) ) ; + } + th = 0 ; + rad = 3 ; + vertex( vec3(r*sin(th),r*cos(th),0.0) ) ; + // vertex( vector[0] ) ; + EndPrimitive(); +} diff --git a/shaders/snow.vert b/shaders/snow.vert new file mode 100644 index 0000000..535c26a --- /dev/null +++ b/shaders/snow.vert @@ -0,0 +1,20 @@ +#version 150 +#extension GL_ARB_explicit_attrib_location : enable +#extension GL_ARB_explicit_uniform_location : enable + +layout(location = 0) in vec3 in_position ; +layout(location = 2) in vec3 in_range ; + +uniform mat4 pjMatrix ; +uniform mat4 mvMatrix ; + +uniform float time ; + +void main() { + float tmp = in_position.y + time ; + float ipart ; + float fpart = modf( tmp, ipart ) ; + float newy = in_range.y - (int(ipart) % int(in_range.y) + fpart) + in_range.x ; + vec3 newp = vec3( in_position.x, newy, in_position.z ) ; + gl_Position = pjMatrix * (mvMatrix * vec4(newp,1.0)) ; +} |