packages feed

h-raylib-5.5.0.0: examples/basic-shaders/src/Main.hs

{-# LANGUAGE PatternSynonyms #-}

module Main where

import Paths_h_raylib (getDataFileName)
import Control.Monad (when)
import Numeric (showFFloat)
import Raylib.Core
  ( beginDrawing,
    beginMode3D,
    clearBackground,
    closeWindow,
    disableCursor,
    endDrawing,
    endMode3D,
    getFrameTime,
    initWindow,
    isKeyDown,
    loadShader,
    setShaderValue,
    setTargetFPS,
  )
import Raylib.Core.Camera (updateCamera)
import Raylib.Core.Models (drawModel, drawSphereWires, genMeshCube, genMeshPlane, genMeshSphere, loadModelFromMesh)
import Raylib.Core.Text (drawText)
import Raylib.Types
  ( Camera3D (Camera3D, camera3D'position),
    CameraMode (CameraModeFirstPerson),
    CameraProjection (CameraPerspective),
    KeyboardKey (KeyH, KeyJ, KeyU, KeyY),
    ShaderUniformData
      ( ShaderUniformFloat,
        ShaderUniformVec3,
        ShaderUniformVec4
      ),
    vector4'w,
    vectorToColor,
    pattern Vector3,
    pattern Vector4,
  )
import Raylib.Util (setMaterialShader, whileWindowOpen_, managed)
import Raylib.Util.Colors (black, blue, lightGray, orange, white)

assetsPath :: String
assetsPath = "examples/basic-shaders/assets/"

main :: IO ()
main = do
  window <- initWindow 1300 800 "raylib [shaders] example - basic shaders"
  setTargetFPS 60
  disableCursor

  let camera = Camera3D (Vector3 1 3 3) (Vector3 1 0 1) (Vector3 0 1 0) 45 CameraPerspective

  vert <- getDataFileName (assetsPath ++ "lighting.vert")
  frag <- getDataFileName (assetsPath ++ "lighting.frag")
  shader <- managed window $ loadShader (Just vert) (Just frag)

  let pointLightPosition = Vector3 0 3 2
  let pointLightColor = Vector4 1 1 1 1
  let pointLightStrength = 1.0
  let specularStrength = 0.5
  let ambientLightColor = Vector4 1 1 0 1
  let ambientStrength = 0.1

  setShaderValue shader "pointLightPosition" (ShaderUniformVec3 pointLightPosition) window
  setShaderValue shader "pointLightColor" (ShaderUniformVec4 pointLightColor) window
  setShaderValue shader "pointLightStrength" (ShaderUniformFloat pointLightStrength) window
  setShaderValue shader "specularStrength" (ShaderUniformFloat specularStrength) window
  setShaderValue shader "ambientLightColor" (ShaderUniformVec4 ambientLightColor) window
  setShaderValue shader "ambientStrength" (ShaderUniformFloat ambientStrength) window

  cubeMesh <- managed window $ genMeshCube 2 2 2
  cubeModel' <- managed window $ loadModelFromMesh cubeMesh
  let cubeModel = setMaterialShader cubeModel' 0 shader

  sphereMesh <- managed window $ genMeshSphere 0.5 32 32
  sphereModel' <- managed window $ loadModelFromMesh sphereMesh
  let sphereModel = setMaterialShader sphereModel' 0 shader

  planeMesh <- managed window $ genMeshPlane 100 100 20 20
  planeModel' <- managed window $ loadModelFromMesh planeMesh
  let planeModel = setMaterialShader planeModel' 0 shader

  whileWindowOpen_
    ( \(c, ls, ss) -> do
        beginDrawing
        clearBackground black

        beginMode3D c

        drawModel cubeModel (Vector3 0 1 0) 1 orange
        drawModel sphereModel (Vector3 2 0.5 2) 1 blue
        drawModel planeModel (Vector3 0 0 0) 1 lightGray
        drawSphereWires pointLightPosition 0.25 12 12 $ vectorToColor (pointLightColor {vector4'w = ls / 3})

        endMode3D

        yDown <- isKeyDown KeyY
        hDown <- isKeyDown KeyH
        uDown <- isKeyDown KeyU
        jDown <- isKeyDown KeyJ
        frameTime <- getFrameTime

        let newLightStrength = clamp (ls + change * frameTime) 0 3
              where
                change
                  | yDown = 1
                  | hDown = -1
                  | otherwise = 0

        let newSpecularStrength = clamp (ss + change * frameTime) 0 2
              where
                change
                  | uDown = 1
                  | jDown = -1
                  | otherwise = 0

        when (yDown || hDown) $ setShaderValue shader "pointLightStrength" (ShaderUniformFloat newLightStrength) window
        when (uDown || jDown) $ setShaderValue shader "specularStrength" (ShaderUniformFloat newSpecularStrength) window

        drawText "Press the Y and H keys to increase and decrease the diffuse strength." 10 10 20 white
        drawText ("Current diffuse strength: " ++ showFFloat (Just 2) newLightStrength "") 10 40 20 white

        drawText "Press the U and J keys to increase and decrease the specular strength." 10 80 20 white
        drawText ("Current specular strength: " ++ showFFloat (Just 2) newSpecularStrength "") 10 110 20 white

        endDrawing

        newCam <- updateCamera c CameraModeFirstPerson
        setShaderValue shader "viewPos" (ShaderUniformVec3 $ camera3D'position newCam) window

        return (newCam, newLightStrength, newSpecularStrength)
    )
    (camera, pointLightStrength, specularStrength)

  closeWindow (Just window)

clamp :: Float -> Float -> Float -> Float
clamp x l h = min h (max x l)