#fragmentShader
repost @yannickgregoire on IG
Dithering for days. 🖤

#realtime #shader #fragmentshader
September 13, 2025 at 9:01 AM
February 3, 2026 at 5:59 PM
Kodelife screen shot, running fragment shaders on OpenGL over WebGL is so much crisper / cleaner of an image. #kodelife #fragmentshader #shader #opengl #glsl #hexagon #geometry
November 23, 2024 at 10:40 AM
Testing text reveal effect ✨

[portfolio wip]

#WebGL #creativecode #fragmentShader #bandStretch
June 3, 2025 at 3:06 PM
January 14, 2025 at 8:41 AM
what if we add a bit of physics in this intro section...🍃

[portfolio wip]

#WebGL #creativecode #3dphysics #fragmentShader
June 6, 2025 at 2:55 PM
ok now let's see if we add rgb shift + tweak the values 🖌️

[portfolio wip]

#WebGL #creativecode #fragmentShader #bandStretch
June 4, 2025 at 12:31 PM
The more I learn about this the more powerful it feels. The `fragmentShader` is going through each pixel each frame and is using the variables passed in to determine the final render. And we can pass in anything, it appears, via the `uniforms` member of the `shaderMaterial`.
November 15, 2024 at 6:03 AM
I'm using `react + vite` with `react-three/fiber` and `react-three/drei`.
The image itself is turned into a `texture` via `useTexture` . It looks like the `fragmentShader` then does the work on altering the pixels of the `texture`.
November 15, 2024 at 5:40 AM
Justement dans ton screenshot, premier ligne, Vert c'est pas pour VertexShader ?
Vu que juste en dessous Frag ne semble être pour FragmentShader...
May 30, 2026 at 12:04 AM
Shader Pipeline: PrimShader and Random Face Colours
It took all bloody day but I’ve finally done it. `mapAccumL` is an AWESOME function. It is annoying to have to unwrap tuples tho but oh well. objShaderPipeline s@(Shader vertexShader primShader _ fragmentShader _) modelTransform projection camera obj (Face p1 p2 p3 pn) = let faceInfoList = p1 : p2 : p3 : pn vs = objVertices obj out@(endShad, points) = (\(projSpace, shad) -> fragShaderHandler shad projSpace) . (\(coords, newShad) -> (fmap (toProjection projection) coords, newShad)) . Debug.traceShowWith (fmap (getVertexColour . getViewSpace). fst) . primShaderHandling vertShaderOut $ faceVertices (vertShaderOut,faceVertices) = mapAccumL vertInvoker s . fmap ( toViewSpace camera . toModelView modelTransform . (vs V.!) . subtract 1 . objFaceVertexIndex ) $ faceInfoList in (endShad, points) where vertInvoker shad vert = (newShader, transformed) where (transformed, newShader) = invokeVertShader shad (getShaderStdGen shad) vert primShaderHandling shadState faceVerts = invokePrimShader shadState (getShaderStdGen shadState) faceVerts fragShaderHandler shadState projVerts = mapAccumL fragger shadState projVerts fragger shad pix = let (newShad, newPix) = invokeFragmentShader shad (getShaderStdGen shad) pix in (newPix, newShad) getObjFaces dims modelTransform projection camera shader obj = let allFaces = snd <$> Map.elems (objFaces obj) allVerts = snd . builder shader $ (concatMap V.toList allFaces) builder oldShad faces = mapAccumL buildHelper oldShad faces buildHelper shad face = objShaderPipeline shad modelTransform projection camera obj face in [toScreenSpace dims <$> verts | verts <- allVerts, all pointIsVisible verts] and Shaders look something like this: type VertexShader = StdGen -> ViewSpace -> ViewSpace type PrimShader = forall f. Functor f => StdGen -> f ViewSpace -> f ViewSpace type MeshShader = forall t f. (Traversable t, Functor f) => StdGen -> t (f ViewSpace) -> t (f ViewSpace) type FragmentShader = StdGen -> ProjectionSpace -> ProjectionSpace data Shader = Shader { getVertexShader :: VertexShader, getPrimShader :: PrimShader, getMeshShader :: MeshShader, getFragmentShader :: FragmentShader, getShaderStdGen :: StdGen } baseShader :: StdGen -> Shader baseShader gen = Shader (const id) (const id) (const id) (const id) gen invokeVertShader :: Shader -> StdGen -> ViewSpace -> (ViewSpace, Shader) invokeVertShader s gen v = (getVertexShader s gen v, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokePrimShader :: Functor f => Shader -> StdGen -> f ViewSpace -> (f ViewSpace, Shader) invokePrimShader s gen vs = (getPrimShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeMeshShader :: (Traversable t, Functor f) => Shader -> StdGen -> t (f ViewSpace) -> (t (f ViewSpace), Shader) invokeMeshShader s gen vs = (getMeshShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeFragmentShader :: Shader -> StdGen -> ProjectionSpace -> (ProjectionSpace, Shader) invokeFragmentShader s gen vs = (getFragmentShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) -- genCol :: IO VertexColour -- genCol :: RandomGen p => p -> VertexColour genCol gen = (g2, VertexColour r g b 255) where (r, g0) = randomR (0, 255) gen (g, g1) = randomR (0, 255) g0 (b, g2) = randomR (0, 255) g1 randomFaceColourShader gen = colourFaces where colourFaces vs = fmap (toGeneratedColour newCol) vs (newGen, newCol) = genCol gen toGeneratedColour col (ViewSpace (Vertex pos _ vnorm)) = ViewSpace (Vertex pos (Just col) vnorm) I will obviously clean this up and make it more manageable, maybe even give myself a nice little wrapper type to keep track of things better but I’m just happy it works.
discourse.haskell.org
April 8, 2026 at 10:41 AM
Shader Pipeline: PrimShader and Random Face Colours
It took all bloody day but I’ve finally done it. `mapAccumL` is an AWESOME function. It is annoying to have to unwrap tuples tho but oh well. objShaderPipeline s@(Shader vertexShader primShader _ fragmentShader _) modelTransform projection camera obj (Face p1 p2 p3 pn) = let faceInfoList = p1 : p2 : p3 : pn vs = objVertices obj out@(endShad, points) = (\(projSpace, shad) -> fragShaderHandler shad projSpace) . (\(coords, newShad) -> (fmap (toProjection projection) coords, newShad)) . Debug.traceShowWith (fmap (getVertexColour . getViewSpace). fst) . primShaderHandling vertShaderOut $ faceVertices (vertShaderOut,faceVertices) = mapAccumL vertInvoker s . fmap ( toViewSpace camera . toModelView modelTransform . (vs V.!) . subtract 1 . objFaceVertexIndex ) $ faceInfoList in (endShad, points) where vertInvoker shad vert = (newShader, transformed) where (transformed, newShader) = invokeVertShader shad (getShaderStdGen shad) vert primShaderHandling shadState faceVerts = invokePrimShader shadState (getShaderStdGen shadState) faceVerts fragShaderHandler shadState projVerts = mapAccumL fragger shadState projVerts fragger shad pix = let (newShad, newPix) = invokeFragmentShader shad (getShaderStdGen shad) pix in (newPix, newShad) getObjFaces dims modelTransform projection camera shader obj = let allFaces = snd <$> Map.elems (objFaces obj) allVerts = snd . builder shader $ (concatMap V.toList allFaces) builder oldShad faces = mapAccumL buildHelper oldShad faces buildHelper shad face = objShaderPipeline shad modelTransform projection camera obj face in [toScreenSpace dims <$> verts | verts <- allVerts, all pointIsVisible verts] and Shaders look something like this: type VertexShader = StdGen -> ViewSpace -> ViewSpace type PrimShader = forall f. Functor f => StdGen -> f ViewSpace -> f ViewSpace type MeshShader = forall t f. (Traversable t, Functor f) => StdGen -> t (f ViewSpace) -> t (f ViewSpace) type FragmentShader = StdGen -> ProjectionSpace -> ProjectionSpace data Shader = Shader { getVertexShader :: VertexShader, getPrimShader :: PrimShader, getMeshShader :: MeshShader, getFragmentShader :: FragmentShader, getShaderStdGen :: StdGen } baseShader :: StdGen -> Shader baseShader gen = Shader (const id) (const id) (const id) (const id) gen invokeVertShader :: Shader -> StdGen -> ViewSpace -> (ViewSpace, Shader) invokeVertShader s gen v = (getVertexShader s gen v, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokePrimShader :: Functor f => Shader -> StdGen -> f ViewSpace -> (f ViewSpace, Shader) invokePrimShader s gen vs = (getPrimShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeMeshShader :: (Traversable t, Functor f) => Shader -> StdGen -> t (f ViewSpace) -> (t (f ViewSpace), Shader) invokeMeshShader s gen vs = (getMeshShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeFragmentShader :: Shader -> StdGen -> ProjectionSpace -> (ProjectionSpace, Shader) invokeFragmentShader s gen vs = (getFragmentShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) -- genCol :: IO VertexColour -- genCol :: RandomGen p => p -> VertexColour genCol gen = (g2, VertexColour r g b 255) where (r, g0) = randomR (0, 255) gen (g, g1) = randomR (0, 255) g0 (b, g2) = randomR (0, 255) g1 randomFaceColourShader gen = colourFaces where colourFaces vs = fmap (toGeneratedColour newCol) vs (newGen, newCol) = genCol gen toGeneratedColour col (ViewSpace (Vertex pos _ vnorm)) = ViewSpace (Vertex pos (Just col) vnorm) I will obviously clean this up and make it more manageable, maybe even give myself a nice little wrapper type to keep track of things better but I’m just happy it works.
discourse.haskell.org
April 8, 2026 at 8:40 AM
Shader Pipeline: PrimShader and Random Face Colours
It took all bloody day but I’ve finally done it. `mapAccumL` is an AWESOME function. It is annoying to have to unwrap tuples tho but oh well. objShaderPipeline s@(Shader vertexShader primShader _ fragmentShader _) modelTransform projection camera obj (Face p1 p2 p3 pn) = let faceInfoList = p1 : p2 : p3 : pn vs = objVertices obj out@(endShad, points) = (\(projSpace, shad) -> fragShaderHandler shad projSpace) . (\(coords, newShad) -> (fmap (toProjection projection) coords, newShad)) . Debug.traceShowWith (fmap (getVertexColour . getViewSpace). fst) . primShaderHandling vertShaderOut $ faceVertices (vertShaderOut,faceVertices) = mapAccumL vertInvoker s . fmap ( toViewSpace camera . toModelView modelTransform . (vs V.!) . subtract 1 . objFaceVertexIndex ) $ faceInfoList in (endShad, points) where vertInvoker shad vert = (newShader, transformed) where (transformed, newShader) = invokeVertShader shad (getShaderStdGen shad) vert primShaderHandling shadState faceVerts = invokePrimShader shadState (getShaderStdGen shadState) faceVerts fragShaderHandler shadState projVerts = mapAccumL fragger shadState projVerts fragger shad pix = let (newShad, newPix) = invokeFragmentShader shad (getShaderStdGen shad) pix in (newPix, newShad) getObjFaces dims modelTransform projection camera shader obj = let allFaces = snd <$> Map.elems (objFaces obj) allVerts = snd . builder shader $ (concatMap V.toList allFaces) builder oldShad faces = mapAccumL buildHelper oldShad faces buildHelper shad face = objShaderPipeline shad modelTransform projection camera obj face in [toScreenSpace dims <$> verts | verts <- allVerts, all pointIsVisible verts] and Shaders look something like this: type VertexShader = StdGen -> ViewSpace -> ViewSpace type PrimShader = forall f. Functor f => StdGen -> f ViewSpace -> f ViewSpace type MeshShader = forall t f. (Traversable t, Functor f) => StdGen -> t (f ViewSpace) -> t (f ViewSpace) type FragmentShader = StdGen -> ProjectionSpace -> ProjectionSpace data Shader = Shader { getVertexShader :: VertexShader, getPrimShader :: PrimShader, getMeshShader :: MeshShader, getFragmentShader :: FragmentShader, getShaderStdGen :: StdGen } baseShader :: StdGen -> Shader baseShader gen = Shader (const id) (const id) (const id) (const id) gen invokeVertShader :: Shader -> StdGen -> ViewSpace -> (ViewSpace, Shader) invokeVertShader s gen v = (getVertexShader s gen v, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokePrimShader :: Functor f => Shader -> StdGen -> f ViewSpace -> (f ViewSpace, Shader) invokePrimShader s gen vs = (getPrimShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeMeshShader :: (Traversable t, Functor f) => Shader -> StdGen -> t (f ViewSpace) -> (t (f ViewSpace), Shader) invokeMeshShader s gen vs = (getMeshShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeFragmentShader :: Shader -> StdGen -> ProjectionSpace -> (ProjectionSpace, Shader) invokeFragmentShader s gen vs = (getFragmentShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) -- genCol :: IO VertexColour -- genCol :: RandomGen p => p -> VertexColour genCol gen = (g2, VertexColour r g b 255) where (r, g0) = randomR (0, 255) gen (g, g1) = randomR (0, 255) g0 (b, g2) = randomR (0, 255) g1 randomFaceColourShader gen = colourFaces where colourFaces vs = fmap (toGeneratedColour newCol) vs (newGen, newCol) = genCol gen toGeneratedColour col (ViewSpace (Vertex pos _ vnorm)) = ViewSpace (Vertex pos (Just col) vnorm) I will obviously clean this up and make it more manageable, maybe even give myself a nice little wrapper type to keep track of things better but I’m just happy it works.
discourse.haskell.org
April 8, 2026 at 6:39 AM
Shader Pipeline: PrimShader and Random Face Colours
It took all bloody day but I’ve finally done it. `mapAccumL` is an AWESOME function. It is annoying to have to unwrap tuples tho but oh well. objShaderPipeline s@(Shader vertexShader primShader _ fragmentShader _) modelTransform projection camera obj (Face p1 p2 p3 pn) = let faceInfoList = p1 : p2 : p3 : pn vs = objVertices obj out@(endShad, points) = (\(projSpace, shad) -> fragShaderHandler shad projSpace) . (\(coords, newShad) -> (fmap (toProjection projection) coords, newShad)) . Debug.traceShowWith (fmap (getVertexColour . getViewSpace). fst) . primShaderHandling vertShaderOut $ faceVertices (vertShaderOut,faceVertices) = mapAccumL vertInvoker s . fmap ( toViewSpace camera . toModelView modelTransform . (vs V.!) . subtract 1 . objFaceVertexIndex ) $ faceInfoList in (endShad, points) where vertInvoker shad vert = (newShader, transformed) where (transformed, newShader) = invokeVertShader shad (getShaderStdGen shad) vert primShaderHandling shadState faceVerts = invokePrimShader shadState (getShaderStdGen shadState) faceVerts fragShaderHandler shadState projVerts = mapAccumL fragger shadState projVerts fragger shad pix = let (newShad, newPix) = invokeFragmentShader shad (getShaderStdGen shad) pix in (newPix, newShad) getObjFaces dims modelTransform projection camera shader obj = let allFaces = snd <$> Map.elems (objFaces obj) allVerts = snd . builder shader $ (concatMap V.toList allFaces) builder oldShad faces = mapAccumL buildHelper oldShad faces buildHelper shad face = objShaderPipeline shad modelTransform projection camera obj face in [toScreenSpace dims <$> verts | verts <- allVerts, all pointIsVisible verts] and Shaders look something like this: type VertexShader = StdGen -> ViewSpace -> ViewSpace type PrimShader = forall f. Functor f => StdGen -> f ViewSpace -> f ViewSpace type MeshShader = forall t f. (Traversable t, Functor f) => StdGen -> t (f ViewSpace) -> t (f ViewSpace) type FragmentShader = StdGen -> ProjectionSpace -> ProjectionSpace data Shader = Shader { getVertexShader :: VertexShader, getPrimShader :: PrimShader, getMeshShader :: MeshShader, getFragmentShader :: FragmentShader, getShaderStdGen :: StdGen } baseShader :: StdGen -> Shader baseShader gen = Shader (const id) (const id) (const id) (const id) gen invokeVertShader :: Shader -> StdGen -> ViewSpace -> (ViewSpace, Shader) invokeVertShader s gen v = (getVertexShader s gen v, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokePrimShader :: Functor f => Shader -> StdGen -> f ViewSpace -> (f ViewSpace, Shader) invokePrimShader s gen vs = (getPrimShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeMeshShader :: (Traversable t, Functor f) => Shader -> StdGen -> t (f ViewSpace) -> (t (f ViewSpace), Shader) invokeMeshShader s gen vs = (getMeshShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeFragmentShader :: Shader -> StdGen -> ProjectionSpace -> (ProjectionSpace, Shader) invokeFragmentShader s gen vs = (getFragmentShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) -- genCol :: IO VertexColour -- genCol :: RandomGen p => p -> VertexColour genCol gen = (g2, VertexColour r g b 255) where (r, g0) = randomR (0, 255) gen (g, g1) = randomR (0, 255) g0 (b, g2) = randomR (0, 255) g1 randomFaceColourShader gen = colourFaces where colourFaces vs = fmap (toGeneratedColour newCol) vs (newGen, newCol) = genCol gen toGeneratedColour col (ViewSpace (Vertex pos _ vnorm)) = ViewSpace (Vertex pos (Just col) vnorm) I will obviously clean this up and make it more manageable, maybe even give myself a nice little wrapper type to keep track of things better but I’m just happy it works.
discourse.haskell.org
April 8, 2026 at 4:39 AM
Shader Pipeline: PrimShader and Random Face Colours
It took all bloody day but I’ve finally done it. `mapAccumL` is an AWESOME function. It is annoying to have to unwrap tuples tho but oh well. objShaderPipeline s@(Shader vertexShader primShader _ fragmentShader _) modelTransform projection camera obj (Face p1 p2 p3 pn) = let faceInfoList = p1 : p2 : p3 : pn vs = objVertices obj out@(endShad, points) = (\(projSpace, shad) -> fragShaderHandler shad projSpace) . (\(coords, newShad) -> (fmap (toProjection projection) coords, newShad)) . Debug.traceShowWith (fmap (getVertexColour . getViewSpace). fst) . primShaderHandling vertShaderOut $ faceVertices (vertShaderOut,faceVertices) = mapAccumL vertInvoker s . fmap ( toViewSpace camera . toModelView modelTransform . (vs V.!) . subtract 1 . objFaceVertexIndex ) $ faceInfoList in (endShad, points) where vertInvoker shad vert = (newShader, transformed) where (transformed, newShader) = invokeVertShader shad (getShaderStdGen shad) vert primShaderHandling shadState faceVerts = invokePrimShader shadState (getShaderStdGen shadState) faceVerts fragShaderHandler shadState projVerts = mapAccumL fragger shadState projVerts fragger shad pix = let (newShad, newPix) = invokeFragmentShader shad (getShaderStdGen shad) pix in (newPix, newShad) getObjFaces dims modelTransform projection camera shader obj = let allFaces = snd <$> Map.elems (objFaces obj) allVerts = snd . builder shader $ (concatMap V.toList allFaces) builder oldShad faces = mapAccumL buildHelper oldShad faces buildHelper shad face = objShaderPipeline shad modelTransform projection camera obj face in [toScreenSpace dims <$> verts | verts <- allVerts, all pointIsVisible verts] and Shaders look something like this: type VertexShader = StdGen -> ViewSpace -> ViewSpace type PrimShader = forall f. Functor f => StdGen -> f ViewSpace -> f ViewSpace type MeshShader = forall t f. (Traversable t, Functor f) => StdGen -> t (f ViewSpace) -> t (f ViewSpace) type FragmentShader = StdGen -> ProjectionSpace -> ProjectionSpace data Shader = Shader { getVertexShader :: VertexShader, getPrimShader :: PrimShader, getMeshShader :: MeshShader, getFragmentShader :: FragmentShader, getShaderStdGen :: StdGen } baseShader :: StdGen -> Shader baseShader gen = Shader (const id) (const id) (const id) (const id) gen invokeVertShader :: Shader -> StdGen -> ViewSpace -> (ViewSpace, Shader) invokeVertShader s gen v = (getVertexShader s gen v, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokePrimShader :: Functor f => Shader -> StdGen -> f ViewSpace -> (f ViewSpace, Shader) invokePrimShader s gen vs = (getPrimShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeMeshShader :: (Traversable t, Functor f) => Shader -> StdGen -> t (f ViewSpace) -> (t (f ViewSpace), Shader) invokeMeshShader s gen vs = (getMeshShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeFragmentShader :: Shader -> StdGen -> ProjectionSpace -> (ProjectionSpace, Shader) invokeFragmentShader s gen vs = (getFragmentShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) -- genCol :: IO VertexColour -- genCol :: RandomGen p => p -> VertexColour genCol gen = (g2, VertexColour r g b 255) where (r, g0) = randomR (0, 255) gen (g, g1) = randomR (0, 255) g0 (b, g2) = randomR (0, 255) g1 randomFaceColourShader gen = colourFaces where colourFaces vs = fmap (toGeneratedColour newCol) vs (newGen, newCol) = genCol gen toGeneratedColour col (ViewSpace (Vertex pos _ vnorm)) = ViewSpace (Vertex pos (Just col) vnorm) I will obviously clean this up and make it more manageable, maybe even give myself a nice little wrapper type to keep track of things better but I’m just happy it works.
discourse.haskell.org
April 8, 2026 at 2:39 AM
Shader Pipeline: PrimShader and Random Face Colours
It took all bloody day but I’ve finally done it. `mapAccumL` is an AWESOME function. It is annoying to have to unwrap tuples tho but oh well. objShaderPipeline s@(Shader vertexShader primShader _ fragmentShader _) modelTransform projection camera obj (Face p1 p2 p3 pn) = let faceInfoList = p1 : p2 : p3 : pn vs = objVertices obj out@(endShad, points) = (\(projSpace, shad) -> fragShaderHandler shad projSpace) . (\(coords, newShad) -> (fmap (toProjection projection) coords, newShad)) . Debug.traceShowWith (fmap (getVertexColour . getViewSpace). fst) . primShaderHandling vertShaderOut $ faceVertices (vertShaderOut,faceVertices) = mapAccumL vertInvoker s . fmap ( toViewSpace camera . toModelView modelTransform . (vs V.!) . subtract 1 . objFaceVertexIndex ) $ faceInfoList in (endShad, points) where vertInvoker shad vert = (newShader, transformed) where (transformed, newShader) = invokeVertShader shad (getShaderStdGen shad) vert primShaderHandling shadState faceVerts = invokePrimShader shadState (getShaderStdGen shadState) faceVerts fragShaderHandler shadState projVerts = mapAccumL fragger shadState projVerts fragger shad pix = let (newShad, newPix) = invokeFragmentShader shad (getShaderStdGen shad) pix in (newPix, newShad) getObjFaces dims modelTransform projection camera shader obj = let allFaces = snd <$> Map.elems (objFaces obj) allVerts = snd . builder shader $ (concatMap V.toList allFaces) builder oldShad faces = mapAccumL buildHelper oldShad faces buildHelper shad face = objShaderPipeline shad modelTransform projection camera obj face in [toScreenSpace dims <$> verts | verts <- allVerts, all pointIsVisible verts] and Shaders look something like this: type VertexShader = StdGen -> ViewSpace -> ViewSpace type PrimShader = forall f. Functor f => StdGen -> f ViewSpace -> f ViewSpace type MeshShader = forall t f. (Traversable t, Functor f) => StdGen -> t (f ViewSpace) -> t (f ViewSpace) type FragmentShader = StdGen -> ProjectionSpace -> ProjectionSpace data Shader = Shader { getVertexShader :: VertexShader, getPrimShader :: PrimShader, getMeshShader :: MeshShader, getFragmentShader :: FragmentShader, getShaderStdGen :: StdGen } baseShader :: StdGen -> Shader baseShader gen = Shader (const id) (const id) (const id) (const id) gen invokeVertShader :: Shader -> StdGen -> ViewSpace -> (ViewSpace, Shader) invokeVertShader s gen v = (getVertexShader s gen v, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokePrimShader :: Functor f => Shader -> StdGen -> f ViewSpace -> (f ViewSpace, Shader) invokePrimShader s gen vs = (getPrimShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeMeshShader :: (Traversable t, Functor f) => Shader -> StdGen -> t (f ViewSpace) -> (t (f ViewSpace), Shader) invokeMeshShader s gen vs = (getMeshShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) invokeFragmentShader :: Shader -> StdGen -> ProjectionSpace -> (ProjectionSpace, Shader) invokeFragmentShader s gen vs = (getFragmentShader s gen vs, s {getShaderStdGen = newGen}) where (_, newGen) = random gen :: (Int, StdGen) -- genCol :: IO VertexColour -- genCol :: RandomGen p => p -> VertexColour genCol gen = (g2, VertexColour r g b 255) where (r, g0) = randomR (0, 255) gen (g, g1) = randomR (0, 255) g0 (b, g2) = randomR (0, 255) g1 randomFaceColourShader gen = colourFaces where colourFaces vs = fmap (toGeneratedColour newCol) vs (newGen, newCol) = genCol gen toGeneratedColour col (ViewSpace (Vertex pos _ vnorm)) = ViewSpace (Vertex pos (Just col) vnorm) I will obviously clean this up and make it more manageable, maybe even give myself a nice little wrapper type to keep track of things better but I’m just happy it works.
discourse.haskell.org
April 8, 2026 at 12:39 AM
Shader Pipeline: PrimShader and Random Face Colours
While building my toy rasterizer I was thinking that I could implement various stages like so: type VertexShader = ViewSpace -> ViewSpace type PrimShader = forall f. Functor f => f ViewSpace -> f ViewSpace type MeshShader = forall t f. (Traversable t, Functor f) => t (f ViewSpace) -> t (f ViewSpace) type FragmentShader = ProjectionSpace -> ProjectionSpace data Shader = Shader { getVertexShader :: VertexShader, getPrimShader :: PrimShader, getMeshShader :: MeshShader, getFragmentShader :: FragmentShader } noShaders :: Shader noShaders = Shader id id id id addShader :: Shader -> Shader -> Shader addShader (Shader v0 p0 m0 f0) (Shader v1 p1 m1 f1) = Shader (v0 . v1) (p0 . p1) (m0 . m1) (f0 . f1) And use them in a pipeline like so: getObjFaces :: Dimensions -> ModelSpaceTransform -> Projection a -> CameraTransform -> Shader -> ObjFile -> [[ScreenSpace]] getObjFaces dims modelTransform projection camera shader obj = let allFaces = snd <$> Map.elems (objFaces obj) allVerts = fmap someFunc allFaces someFunc faceVec = concatMap (objShaderPipeline shader modelTransform projection camera obj) (V.toList faceVec) in [toScreenSpace dims <$> verts | verts <- allVerts, all pointIsVisible verts] objShaderPipeline :: Shader -> ModelSpaceTransform -> Projection a -> CameraTransform -> ObjFile -> Face ObjFaceInfo -> [ProjectionSpace] objShaderPipeline (Shader vertexShader primShader _ fragmentShader) modelTransform projection camera obj (Face p1 p2 p3 pn) = let faceInfoList = p1 : p2 : p3 : pn vs = objVertices obj points = fmap (fragmentShader . toProjection projection) faceVertices faceVertices = Debug.traceShowWith (fmap (getVertexColour . getViewSpace)) . primShader . fmap ( vertexShader . toViewSpace camera . toModelView modelTransform . (vs V.!) . subtract 1 . objFaceVertexIndex ) $ faceInfoList in points The problem I’m having is implementing a `PrimShader` that randomly sets all the vertices on one face to one specfic `VertexColour `using `unsafePerformIO`. This colour would ideally be generated every time the shader is called: genCol :: IO VertexColour genCol = VertexColour <$> randomRIO (0, 255) <*> randomRIO (0, 255) <*> randomRIO (0, 255) <*> pure 255 randomFaceColourShader :: IO VertexColour -> Shader randomFaceColourShader colGenerator = Shader id colourFaces id id where colourFaces vs = fmap (toGeneratedColour colGenerator) vs toGeneratedColour col (ViewSpace (Vertex pos _ vnorm)) = ViewSpace (Vertex pos (Just (unsafePerformIO col)) vnorm) I later execute the whole pipeline as part of getting the `pixelsToRender` in the `canvasLoop` function. canvasLoop = do SDL.initializeAll -- model <- testParse let -- Initialisation stuff shader = randomFaceColourShader genCol -- The shader of interest. -- shader = noShaders -- projection = projectFrustrum (-right * aspect ) (right * aspect) (-top) (top) near far -- projection = projectPerspective 53 aspect 1 20 -- depthBufferPix = getObjFaceDepth dims modelOpts projection camera model pixelsToRender = getObjFaces dims modelOpts projection camera shader model -- Shaders executed in here via getObjFaces -- ... (newZ, newCanv) = addPointsToBuffer (fromIntegral w) pixelsToRender 1 zBuf canv -- rest of program In `cabal repl`and `cabal run` I get all the verts being correctly set according to my `Debug.Trace` output but a dithered and incorrectly coloured output face colours. EDIT: Or maybe not: this output is inconsistent. Sometimes all three verts are same colour and other times, I get this lol. Even still, the dithering should not be happening as far as I can tell! ghci> canvasLoop [Just (VertexColour {r = 131, g = 191, b = 83, a = 255}),Just (VertexColour {r = 204, g = 226, b = 140, a = 255}),Just (VertexColour {r = 114, g = 205, b = 169, a = 255})] [Just (VertexColour {r = 223, g = 67, b = 147, a = 255}),Just (VertexColour {r = 49, g = 228, b = 23, a = 255}),Just (VertexColour {r = 9, g = 62, b = 174, a = 255})] [Just (VertexColour {r = 161, g = 94, b = 184, a = 255}),Just (VertexColour {r = 227, g = 206, b = 146, a = 255}),Just (VertexColour {r = 138, g = 6, b = 29, a = 255})] [Just (VertexColour {r = 255, g = 187, b = 217, a = 255}),Just (VertexColour {r = 140, g = 55, b = 221, a = 255}),Just (VertexColour {r = 182, g = 113, b = 167, a = 255})] [Just (VertexColour {r = 44, g = 213, b = 17, a = 255}),Just (VertexColour {r = 180, g = 135, b = 37, a = 255}),Just (VertexColour {r = 25, g = 189, b = 69, a = 255})] [Just (VertexColour {r = 39, g = 6, b = 180, a = 255}),Just (VertexColour {r = 11, g = 1, b = 24, a = 255}),Just (VertexColour {r = 69, g = 88, b = 6, a = 255})] [Just (VertexColour {r = 92, g = 64, b = 121, a = 255}),Just (VertexColour {r = 64, g = 160, b = 76, a = 255}),Just (VertexColour {r = 239, g = 17, b = 85, a = 255})] [Just (VertexColour {r = 28, g = 156, b = 188, a = 255}),Just (VertexColour {r = 28, g = 200, b = 218, a = 255}),Just (VertexColour {r = 30, g = 232, b = 153, a = 255})] If I `cabal install` followed by executing the binary, all vertices on every face get set to the same colour: $ game-engine +RTS -s -N8 [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] The only thing I can think of doing at this point is lifting all of the `Shader` types to be in `IO` and everything that interacts with the shader pipeline to also be in `IO`but I’m wondering if there is any other approach that could be worth trying.
discourse.haskell.org
April 7, 2026 at 12:38 PM
Shader Pipeline: PrimShader and Random Face Colours
While building my toy rasterizer I was thinking that I could implement various stages like so: type VertexShader = ViewSpace -> ViewSpace type PrimShader = forall f. Functor f => f ViewSpace -> f ViewSpace type MeshShader = forall t f. (Traversable t, Functor f) => t (f ViewSpace) -> t (f ViewSpace) type FragmentShader = ProjectionSpace -> ProjectionSpace data Shader = Shader { getVertexShader :: VertexShader, getPrimShader :: PrimShader, getMeshShader :: MeshShader, getFragmentShader :: FragmentShader } noShaders :: Shader noShaders = Shader id id id id addShader :: Shader -> Shader -> Shader addShader (Shader v0 p0 m0 f0) (Shader v1 p1 m1 f1) = Shader (v0 . v1) (p0 . p1) (m0 . m1) (f0 . f1) And use them in a pipeline like so: getObjFaces :: Dimensions -> ModelSpaceTransform -> Projection a -> CameraTransform -> Shader -> ObjFile -> [[ScreenSpace]] getObjFaces dims modelTransform projection camera shader obj = let allFaces = snd <$> Map.elems (objFaces obj) allVerts = fmap someFunc allFaces someFunc faceVec = concatMap (objShaderPipeline shader modelTransform projection camera obj) (V.toList faceVec) in [toScreenSpace dims <$> verts | verts <- allVerts, all pointIsVisible verts] objShaderPipeline :: Shader -> ModelSpaceTransform -> Projection a -> CameraTransform -> ObjFile -> Face ObjFaceInfo -> [ProjectionSpace] objShaderPipeline (Shader vertexShader primShader _ fragmentShader) modelTransform projection camera obj (Face p1 p2 p3 pn) = let faceInfoList = p1 : p2 : p3 : pn vs = objVertices obj points = fmap (fragmentShader . toProjection projection) faceVertices faceVertices = Debug.traceShowWith (fmap (getVertexColour . getViewSpace)) . primShader . fmap ( vertexShader . toViewSpace camera . toModelView modelTransform . (vs V.!) . subtract 1 . objFaceVertexIndex ) $ faceInfoList in points The problem I’m having is implementing a `PrimShader` that randomly sets all the vertices on one face to one specfic `VertexColour `using `unsafePerformIO`. This colour would ideally be generated every time the shader is called: genCol :: IO VertexColour genCol = VertexColour <$> randomRIO (0, 255) <*> randomRIO (0, 255) <*> randomRIO (0, 255) <*> pure 255 randomFaceColourShader :: IO VertexColour -> Shader randomFaceColourShader colGenerator = Shader id colourFaces id id where colourFaces vs = fmap (toGeneratedColour colGenerator) vs toGeneratedColour col (ViewSpace (Vertex pos _ vnorm)) = ViewSpace (Vertex pos (Just (unsafePerformIO col)) vnorm) I later execute the whole pipeline as part of getting the `pixelsToRender` in the `canvasLoop` function. canvasLoop = do SDL.initializeAll -- model <- testParse let -- Initialisation stuff shader = randomFaceColourShader genCol -- The shader of interest. -- shader = noShaders -- projection = projectFrustrum (-right * aspect ) (right * aspect) (-top) (top) near far -- projection = projectPerspective 53 aspect 1 20 -- depthBufferPix = getObjFaceDepth dims modelOpts projection camera model pixelsToRender = getObjFaces dims modelOpts projection camera shader model -- Shaders executed in here via getObjFaces -- ... (newZ, newCanv) = addPointsToBuffer (fromIntegral w) pixelsToRender 1 zBuf canv -- rest of program In `cabal repl`and `cabal run` I get all the verts being correctly set according to my `Debug.Trace` output but a dithered and incorrectly coloured output face colours. EDIT: Or maybe not: this output is inconsistent. Sometimes all three verts are same colour and other times, I get this lol. ghci> canvasLoop [Just (VertexColour {r = 131, g = 191, b = 83, a = 255}),Just (VertexColour {r = 204, g = 226, b = 140, a = 255}),Just (VertexColour {r = 114, g = 205, b = 169, a = 255})] [Just (VertexColour {r = 223, g = 67, b = 147, a = 255}),Just (VertexColour {r = 49, g = 228, b = 23, a = 255}),Just (VertexColour {r = 9, g = 62, b = 174, a = 255})] [Just (VertexColour {r = 161, g = 94, b = 184, a = 255}),Just (VertexColour {r = 227, g = 206, b = 146, a = 255}),Just (VertexColour {r = 138, g = 6, b = 29, a = 255})] [Just (VertexColour {r = 255, g = 187, b = 217, a = 255}),Just (VertexColour {r = 140, g = 55, b = 221, a = 255}),Just (VertexColour {r = 182, g = 113, b = 167, a = 255})] [Just (VertexColour {r = 44, g = 213, b = 17, a = 255}),Just (VertexColour {r = 180, g = 135, b = 37, a = 255}),Just (VertexColour {r = 25, g = 189, b = 69, a = 255})] [Just (VertexColour {r = 39, g = 6, b = 180, a = 255}),Just (VertexColour {r = 11, g = 1, b = 24, a = 255}),Just (VertexColour {r = 69, g = 88, b = 6, a = 255})] [Just (VertexColour {r = 92, g = 64, b = 121, a = 255}),Just (VertexColour {r = 64, g = 160, b = 76, a = 255}),Just (VertexColour {r = 239, g = 17, b = 85, a = 255})] [Just (VertexColour {r = 28, g = 156, b = 188, a = 255}),Just (VertexColour {r = 28, g = 200, b = 218, a = 255}),Just (VertexColour {r = 30, g = 232, b = 153, a = 255})] If I `cabal install` followed by executing the binary, all vertices on every face get set to the same colour: $ game-engine +RTS -s -N8 [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] [Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255}),Just (VertexColour {r = 136, g = 243, b = 159, a = 255})] The only thing I can think of doing at this point is lifting all of the `Shader` types to be in `IO` and everything that interacts with the shader pipeline to also be in `IO`but I’m wondering if there is any other approach that could be worth trying.
discourse.haskell.org
April 7, 2026 at 10:37 AM
Playing with shaders in Mocku.me/nt

🅼 tty.wtf#%23+THREE.js...
January 10, 2025 at 11:25 PM
looking at psm it looks like it actually is vertexShader / fragmentShader as seperate files, except that vertexShader is always set and fragmentShader is always null :D

look its even like that in Sce.PlayStation.Core ... uuuuhgh

maybe its possible in some old version i dont know
June 19, 2026 at 4:31 AM
Manually Calculating the Depth value in a compute shader
OK I found one Error in my code after taking a break from it, but its still weird. It wasnt in anything I posted here though. I just wrote my result into an ivec3 and because all my results were between 0 - 1 it all got rounded down to zero. So now I can finally send values to my fragmentshader properly and the results are mixed. My effect works on some Faces of my cube but not others: I’ve highlighted the areas where the effect should be vidible but sometimes is’nt with my glorious Paint Skills. This is just the best visible case but it happens all over the cube. From testing I know the depth Values I calculate in my compute shader are not correct. They deviate from the ones I calculate in my shader the closer I am to the Mesh I just used these lines of code to check that vec4 clip_pos = PROJECTION_MATRIX * vec4(VERTEX,1.0); clip_pos.xzy / clip_pos.w ; vec4 tex = texture(exclusionmask,SCREEN_UV); ALBEDO = vec3(abs(tex.g - clip_pos.z)); without that test my Fragment shader currently looks like this ALPHA_HASH_SCALE = 1.0; vec4 clip_pos = PROJECTION_MATRIX * vec4(VERTEX,1.0); clip_pos.xzy / clip_pos.w ; vec4 tex = texture(exclusionmask,SCREEN_UV); vec3 color = vec3(0.5,0.5,0.5); if(tex.r == 1.0) { if(abs(tex.b - clip_pos.z) > abs(tex.g - clip_pos.z) ) { DEPTH = tex.b ; }else { DEPTH = tex.g; } }else { DEPTH = clip_pos.z; } ALBEDO = color; I have made some changes to my projection function and to my calculation of the depth values. The Projection Code: Vector3 projectVertex(Vector3 inVertex) { Projection invViewMatrix = new Projection (cam.GetTransform().AffineInverse()); Projection projectionMatrix = cam.GetCameraProjection(); Rect2 res = cam.GetViewport().GetVisibleRect(); Vector4 vertex = new Vector4(inVertex.X,inVertex.Y,inVertex.Z,1); vertex = projectionMatrix * invViewMatrix * vertex ; vertex.X = vertex.X / vertex.W; vertex.Y = vertex.Y / vertex.W; vertex.Z = vertex.Z / vertex.W; return new Vector3((float)((vertex.X + 1.0) / 2.0) * res.Size.X ,(float)(1-((vertex.Y + 1.0) / 2.0)) * res.Size.Y,vertex.Z); } And the depth Calculation: float calcZ(vec2 ScreenUV, vec3 V1, vec3 V2, vec3 V3) { float upper = ((V2.y - V3.y) * (ScreenUV.x - V3.x)) + ((V3.x - V2.x) * (ScreenUV.y - V3.y)); float lower = ((V2.y - V3.y) * (V1.x - V3.x)) + ((V3.x - V2.x) * (V1.y - V3.y)); float W_v1 = upper / lower ; float upper2 = ((V3.y - V1.y) * (ScreenUV.x - V3.x)) + ((V1.x - V3.x) * (ScreenUV.y - V3.y)); float lower2 = ((V2.y - V3.y) * (V1.x - V3.x)) + ((V3.x-V2.x) * (V1.y - V3.y)); float W_v2 = upper2 / lower2 ; float W_v3 = 1.0 - W_v1 - W_v2; if(W_v1 < 0 || W_v2 < 0 || W_v3 < 0) { return -1; } float z1 = V1.z ; float z2 = V2.z ; float z3 = V3.z ; float z = (W_v1 * z1 + W_v2 * z2 + W_v3 * z3) ; return 1 - z ; } Right now I am unsure where the problem lies. I think my calculations are the same in my c# script and my fragment shader but apparently not. Any help is appreciated Thank you
forum.godotengine.org
February 18, 2025 at 2:05 PM