├── README.md ├── Setup.hs ├── app ├── Main ├── referans.png ├── main.py └── Main.hs ├── ChangeLog.md ├── test └── Spec.hs ├── src ├── Lib.hs ├── Ray.hs ├── RandomFn.hs ├── Color.hs ├── Vec3.hs └── Primitives.hs ├── .gitignore ├── stack.yaml.lock ├── package.yaml ├── LICENSE ├── raytracing-hs.cabal └── stack.yaml /README.md: -------------------------------------------------------------------------------- 1 | # raytracing-hs 2 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /app/Main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/D-K-E/raytracing-hs/master/app/Main -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Changelog for raytracing-hs 2 | 3 | ## Unreleased changes 4 | -------------------------------------------------------------------------------- /test/Spec.hs: -------------------------------------------------------------------------------- 1 | main :: IO () 2 | main = putStrLn "Test suite not yet implemented" 3 | -------------------------------------------------------------------------------- /app/referans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/D-K-E/raytracing-hs/master/app/referans.png -------------------------------------------------------------------------------- /src/Lib.hs: -------------------------------------------------------------------------------- 1 | module Lib 2 | ( someFunc 3 | ) where 4 | 5 | someFunc :: IO () 6 | someFunc = putStrLn "someFunc" 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .stack-work/ 2 | *~ 3 | dist 4 | dist-* 5 | cabal-dev 6 | *.o 7 | *.hi 8 | *.hie 9 | *.chi 10 | *.chs.h 11 | *.dyn_o 12 | *.dyn_hi 13 | .hpc 14 | .hsenv 15 | .cabal-sandbox/ 16 | cabal.sandbox.config 17 | *.prof 18 | *.aux 19 | *.hp 20 | *.eventlog 21 | *.ppm 22 | .stack-work/ 23 | cabal.project.local 24 | cabal.project.local~ 25 | .HTF/ 26 | .ghc.environment.* 27 | -------------------------------------------------------------------------------- /src/Ray.hs: -------------------------------------------------------------------------------- 1 | -- Ray object 2 | 3 | module Ray where 4 | 5 | import Vec3 6 | 7 | data Ray = Ray Point3 Vec3 deriving (Eq, Show) 8 | 9 | origin :: Ray -> Point3 10 | 11 | origin (Ray orig dir) = orig 12 | 13 | direction :: Ray -> Vec3 14 | direction (Ray orig dir) = dir 15 | 16 | at :: Ray -> Double -> Point3 17 | at (Ray orig dir) t = vplus orig (Left (vmultip dir (Right t))) 18 | -------------------------------------------------------------------------------- /src/RandomFn.hs: -------------------------------------------------------------------------------- 1 | -- license, see LICENSE 2 | -- author: Kaan ERASLAN 3 | module RandomFn where 4 | {- 5 | import System.Random 6 | 7 | 8 | random_double :: Maybe Float -> Maybe Float -> Float 9 | 10 | random_double mi ma = fst (randomR mi ma) 11 | random_double Nothing Nothing = fst (randomR 0.0 1.0) 12 | 13 | random_int :: Maybe Int -> Maybe Int -> Int 14 | 15 | random_int mi ma = fst (randomR mi ma) 16 | -} 17 | -------------------------------------------------------------------------------- /app/main.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | im = 256 3 | ih = 256 4 | print("P3\n",im," ",ih,"\n255\n") 5 | for j in range(ih, 0, -1): 6 | for i in range(im): 7 | r = i / (im-1) 8 | g = j / (ih -1) 9 | b = 0.25 10 | 11 | ir = int(255.999 * r) 12 | ig = int(255.999 * g) 13 | ib = int(255.999 * b) 14 | 15 | print(ir, " ", ig, " ", ib) 16 | -------------------------------------------------------------------------------- /stack.yaml.lock: -------------------------------------------------------------------------------- 1 | # This file was autogenerated by Stack. 2 | # You should not edit this file by hand. 3 | # For more information, please see the documentation at: 4 | # https://docs.haskellstack.org/en/stable/lock_files 5 | 6 | packages: [] 7 | snapshots: 8 | - completed: 9 | size: 496112 10 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/15/15.yaml 11 | sha256: 86169722ad0056ffc9eacc157ef80ee21d7024f92c0d2961c89ccf432db230a3 12 | original: lts-15.15 13 | -------------------------------------------------------------------------------- /src/Color.hs: -------------------------------------------------------------------------------- 1 | -- license, see LICENSE 2 | module Color(printColor, pixDiv) where 3 | 4 | import Vec3 5 | 6 | pixDiv :: Int -> Int -> Double 7 | pixDiv a b = (fromIntegral a) / (fromIntegral b) 8 | 9 | pixMul :: Double -> Double -> Int 10 | pixMul a b = floor (a * b) 11 | 12 | printColor :: Color -> IO() 13 | 14 | printColor (Vec3 x y z) = do 15 | let r = pixMul 255.999 x 16 | g = pixMul 255.999 y 17 | b = pixMul 255.999 z 18 | putStrLn ((show r) ++ " " ++ (show g) ++ " " ++ (show b)) 19 | -------------------------------------------------------------------------------- /package.yaml: -------------------------------------------------------------------------------- 1 | name: raytracing-hs 2 | version: 0.1.0.0 3 | github: "githubuser/raytracing-hs" 4 | license: BSD3 5 | author: "Author name here" 6 | maintainer: "example@example.com" 7 | copyright: "2020 Author name here" 8 | 9 | extra-source-files: 10 | - README.md 11 | - ChangeLog.md 12 | 13 | # Metadata used when publishing your package 14 | # synopsis: Short description of your package 15 | # category: Web 16 | 17 | # To avoid duplicated efforts in documentation and dealing with the 18 | # complications of embedding Haddock markup inside cabal files, it is 19 | # common to point users to the README.md file. 20 | description: Please see the README on GitHub at 21 | 22 | dependencies: 23 | - base >= 4.7 && < 5 24 | 25 | library: 26 | source-dirs: src 27 | 28 | executables: 29 | raytracing-hs-exe: 30 | main: Main.hs 31 | source-dirs: app 32 | ghc-options: 33 | - -threaded 34 | - -rtsopts 35 | - -with-rtsopts=-N 36 | dependencies: 37 | - raytracing-hs 38 | 39 | tests: 40 | raytracing-hs-test: 41 | main: Spec.hs 42 | source-dirs: test 43 | ghc-options: 44 | - -threaded 45 | - -rtsopts 46 | - -with-rtsopts=-N 47 | dependencies: 48 | - raytracing-hs 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Author name here (c) 2020 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Author name here nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /raytracing-hs.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 1.12 2 | 3 | -- This file has been generated from package.yaml by hpack version 0.31.2. 4 | -- 5 | -- see: https://github.com/sol/hpack 6 | -- 7 | -- hash: 9c7bf384ea86c025849816c1a201b0b6585d1f46cac23bda888f884bce2038a3 8 | 9 | name: raytracing-hs 10 | version: 0.1.0.0 11 | description: Please see the README on GitHub at 12 | homepage: https://github.com/githubuser/raytracing-hs#readme 13 | bug-reports: https://github.com/githubuser/raytracing-hs/issues 14 | author: Author name here 15 | maintainer: example@example.com 16 | copyright: 2020 Author name here 17 | license: BSD3 18 | license-file: LICENSE 19 | build-type: Simple 20 | extra-source-files: 21 | README.md 22 | ChangeLog.md 23 | 24 | source-repository head 25 | type: git 26 | location: https://github.com/githubuser/raytracing-hs 27 | 28 | library 29 | exposed-modules: 30 | Color 31 | Lib 32 | Primitives 33 | RandomFn 34 | Ray 35 | Vec3 36 | other-modules: 37 | Paths_raytracing_hs 38 | hs-source-dirs: 39 | src 40 | build-depends: 41 | base >=4.7 && <5 42 | default-language: Haskell2010 43 | 44 | executable raytracing-hs-exe 45 | main-is: Main.hs 46 | other-modules: 47 | Paths_raytracing_hs 48 | hs-source-dirs: 49 | app 50 | ghc-options: -threaded -rtsopts -with-rtsopts=-N 51 | build-depends: 52 | base >=4.7 && <5 53 | , raytracing-hs 54 | default-language: Haskell2010 55 | 56 | test-suite raytracing-hs-test 57 | type: exitcode-stdio-1.0 58 | main-is: Spec.hs 59 | other-modules: 60 | Paths_raytracing_hs 61 | hs-source-dirs: 62 | test 63 | ghc-options: -threaded -rtsopts -with-rtsopts=-N 64 | build-depends: 65 | base >=4.7 && <5 66 | , raytracing-hs 67 | default-language: Haskell2010 68 | -------------------------------------------------------------------------------- /src/Vec3.hs: -------------------------------------------------------------------------------- 1 | -- Small vec3 lib 2 | -- see LICENSE 3 | module Vec3 where 4 | 5 | data Vec3 = Vec3 Double Double Double deriving (Eq, Show) 6 | 7 | makeVec :: Double -> Vec3 8 | makeVec t = Vec3 t t t 9 | 10 | makeVec3 :: (Double, Double, Double) -> Vec3 11 | makeVec3 (v1, v2, v3) = Vec3 v1 v2 v3 12 | 13 | vlookup :: Int -> Vec3 -> Double 14 | vlookup a (Vec3 x1 y1 z1) 15 | | a == 0 = x1 16 | | a == 1 = y1 17 | | a == 2 = z1 18 | | otherwise = error "Value error integer should not be bigger than 2" 19 | 20 | vecx :: Vec3 -> Double 21 | vecx v = vlookup 0 v 22 | 23 | vecy :: Vec3 -> Double 24 | vecy v = vlookup 1 v 25 | 26 | vecz :: Vec3 -> Double 27 | vecz v = vlookup 2 v 28 | 29 | type VOp = Either Vec3 Double -- data Either a b - Left a - Right b 30 | 31 | vneg :: Vec3 -> Vec3 32 | vplus :: Vec3 -> VOp -> Vec3 33 | vminus :: Vec3 -> VOp -> Vec3 34 | vmultip :: Vec3 -> VOp -> Vec3 35 | vdiv :: Vec3 -> VOp -> Vec3 36 | 37 | vplus (Vec3 x y z) (Left (Vec3 a b c)) = Vec3 (x+a) (y+b) (c+z) 38 | vplus (Vec3 x y z) (Right a) = Vec3 (x+a) (y+a) (z+a) 39 | 40 | vminus (Vec3 x y z) (Left (Vec3 a b c)) = Vec3 (x-a) (y-b) (c-z) 41 | vminus (Vec3 x y z) (Right a) = Vec3 (x-a) (y-a) (z-a) 42 | 43 | vmultip (Vec3 x y z) (Left (Vec3 a b c)) = Vec3 (x*a) (y*b) (c*z) 44 | vmultip (Vec3 x y z) (Right a) = Vec3 (x*a) (y*a) (z*a) 45 | 46 | vdiv (Vec3 x y z) (Left (Vec3 a b c)) 47 | | a == 0 = error "first component is equal to 0" 48 | | b == 0 = error "second component is equal to 0" 49 | | c == 0 = error "third component is equal to 0" 50 | | otherwise = Vec3 (x/a) (y/b) (z/c) 51 | 52 | vdiv (Vec3 x y z) (Right a) 53 | | a == 0 = error "division term is zero" 54 | | otherwise = Vec3 (x/a) (y/a) (z/a) 55 | 56 | vneg (Vec3 x y z) = Vec3 (-x) (-y) (-z) 57 | 58 | dot :: Vec3 -> Vec3 -> Double 59 | dot (Vec3 x y z) (Vec3 a b c) = (x*a) + (y*b)+(z*c) 60 | 61 | length_squared :: Vec3 -> Double 62 | length_squared v = dot v v 63 | 64 | vlength :: Vec3 -> Double 65 | vlength v = (length_squared v) ** (1/2::Double) 66 | 67 | cross :: Vec3 -> Vec3 -> Vec3 68 | cross (Vec3 p1x p1y p1z) (Vec3 p2x p2y p2z) = Vec3 (p1y * p2z - p1z * p2y) (p1z * p2x - p1x * p2z) (p1x * p2y - p1y * p2x) 69 | 70 | unit_vector :: Vec3 -> Vec3 71 | unit_vector v = v `vdiv` (Right (vlength v)) 72 | 73 | type Point3 = Vec3 74 | type Color = Vec3 75 | -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by 'stack init' 2 | # 3 | # Some commonly used options have been documented as comments in this file. 4 | # For advanced use and comprehensive documentation of the format, please see: 5 | # https://docs.haskellstack.org/en/stable/yaml_configuration/ 6 | 7 | # Resolver to choose a 'specific' stackage snapshot or a compiler version. 8 | # A snapshot resolver dictates the compiler version and the set of packages 9 | # to be used for project dependencies. For example: 10 | # 11 | # resolver: lts-3.5 12 | # resolver: nightly-2015-09-21 13 | # resolver: ghc-7.10.2 14 | # 15 | # The location of a snapshot can be provided as a file or url. Stack assumes 16 | # a snapshot provided as a file might change, whereas a url resource does not. 17 | # 18 | # resolver: ./custom-snapshot.yaml 19 | # resolver: https://example.com/snapshots/2018-01-01.yaml 20 | resolver: lts-15.15 21 | 22 | # User packages to be built. 23 | # Various formats can be used as shown in the example below. 24 | # 25 | # packages: 26 | # - some-directory 27 | # - https://example.com/foo/bar/baz-0.0.2.tar.gz 28 | # subdirs: 29 | # - auto-update 30 | # - wai 31 | packages: 32 | - . 33 | # Dependency packages to be pulled from upstream that are not in the resolver. 34 | # These entries can reference officially published versions as well as 35 | # forks / in-progress versions pinned to a git hash. For example: 36 | # 37 | # extra-deps: 38 | # - acme-missiles-0.3 39 | # - git: https://github.com/commercialhaskell/stack.git 40 | # commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a 41 | # 42 | # extra-deps: [] 43 | 44 | # Override default flag values for local packages and extra-deps 45 | # flags: {} 46 | 47 | # Extra package databases containing global packages 48 | # extra-package-dbs: [] 49 | 50 | # Control whether we use the GHC we find on the path 51 | # system-ghc: true 52 | # 53 | # Require a specific version of stack, using version ranges 54 | # require-stack-version: -any # Default 55 | # require-stack-version: ">=2.1" 56 | # 57 | # Override the architecture used by stack, especially useful on Windows 58 | # arch: i386 59 | # arch: x86_64 60 | # 61 | # Extra directories used by stack for building 62 | # extra-include-dirs: [/path/to/dir] 63 | # extra-lib-dirs: [/path/to/dir] 64 | # 65 | # Allow a newer minor version of GHC than the snapshot specifies 66 | # compiler-check: newer-minor 67 | -------------------------------------------------------------------------------- /app/Main.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Color ( pixDiv, printColor ) 4 | import Ray 5 | import Vec3 6 | 7 | hitSphere :: Vec3 -> Double -> Ray -> Bool 8 | 9 | hitSphere p radius (Ray rorig rdir) = let oc = rorig `vminus` (Left p) 10 | a = dot rdir rdir 11 | b = 2.0 * (dot oc rdir) 12 | c = (dot oc oc) - (radius * radius) 13 | d = (b*b) - (4*a*c) 14 | in d > 0 15 | 16 | rayOrColor :: Bool -> Vec3 -> VOp -> Vec3 17 | rayOrColor b v1 v2 18 | | b == True = Vec3 0.5 0.5 0 19 | | otherwise = v1 `vplus` v2 20 | 21 | 22 | ray_color :: Ray -> Color 23 | ray_color r = let unit = unit_vector (direction r) 24 | t = 0.5 * ((vecy unit) + 1) 25 | alpha = Right (1 - t) 26 | sorig = makeVec3 (0.0, 0.0, -1.0) 27 | radius = 0.5 28 | isHit = hitSphere sorig radius r 29 | first = vmultip (makeVec 1.0) (Right t) 30 | second = Left (vmultip (Vec3 0.5 0.7 1.0) alpha) 31 | in rayOrColor isHit first second 32 | 33 | 34 | aspect_ratio :: Double 35 | aspect_ratio = 16.0 / 9.0 36 | 37 | image_width :: Int 38 | image_width = 354 39 | 40 | image_height :: Int 41 | image_height = floor ((fromIntegral image_width) / aspect_ratio) 42 | 43 | viewport_height :: Double 44 | viewport_height = 2.0 45 | 46 | viewport_width :: Double 47 | viewport_width = aspect_ratio * viewport_height 48 | 49 | focal_length :: Double 50 | focal_length = 1.0 51 | camera_origin :: Point3 52 | camera_origin = makeVec 0.0 53 | camera_horizontal = Vec3 viewport_width 0 0 54 | camera_vertical = Vec3 viewport_height 0 0 55 | camera_lower_left :: Vec3 56 | camera_lower_left = let hhalf = Left (vdiv camera_horizontal (Right 2.0)) 57 | vhalf = Left (vdiv camera_vertical (Right 2.0)) 58 | origin_hdiff = camera_origin `vminus` hhalf 59 | origin_vdiff = origin_hdiff `vminus` vhalf 60 | in origin_vdiff `vminus` (Left (Vec3 0.0 0.0 focal_length)) 61 | 62 | zipMerge :: [a] -> [b] -> [(a, b)] 63 | zipMerge [] _ = [] 64 | zipMerge _ [] = error "zipMerge second list cannot be empty" 65 | zipMerge (a : as) bs = (zip (replicate (length bs) a) bs) ++ (zipMerge as bs) 66 | 67 | makeColor :: (Int, Int) -> Color 68 | makeColor (i, j) = let u = Right ( pixDiv i (image_width - 1)) 69 | v = Right (pixDiv j (image_height - 1)) 70 | uh = Left (camera_horizontal `vmultip` u) 71 | vv = Left (camera_vertical `vmultip` v) 72 | dir = camera_lower_left `vplus` uh `vplus` vv `vminus` (Left camera_origin) 73 | r = Ray camera_origin dir 74 | in ray_color(r) 75 | 76 | -- foldl :: (a -> b -> a) -> a -> [b] -> a 77 | printPixel :: (Int, Int) -> IO () 78 | printPixel pixCoord = printColor (makeColor pixCoord) 79 | 80 | printPixels :: [(Int, Int)] -> IO () 81 | printPixels colors = mapM_ printPixel colors 82 | 83 | printGradient :: IO () 84 | printGradient = do 85 | putStrLn "P3" 86 | putStrLn ((show image_width) ++ " " ++ (show image_height)) 87 | putStrLn "255" 88 | let is = [0 .. image_width] 89 | js = image_height:[254, 253 .. 0] 90 | printPixels (zipMerge is js) 91 | 92 | 93 | main :: IO () 94 | main = printGradient 95 | -------------------------------------------------------------------------------- /src/Primitives.hs: -------------------------------------------------------------------------------- 1 | -- Primitives for the general 2 | module Primitives where 3 | {- 4 | // start constants 5 | // constants.hpp 6 | float PI = 3.1415926535; 7 | float INFINITY = 1.0 / 0.0; 8 | // end constants 9 | // 10 | // --------------------- utility functions ------------------------------ 11 | float degree_to_radian(float degree) { 12 | // 13 | return degree * PI / 180.0; 14 | } 15 | float rand(vec2 co) { 16 | // random gen 17 | float a = 12.9898; 18 | float b = 78.233; 19 | float c = 43758.5453; 20 | float dt = dot(co.xy, vec2(a, b)); 21 | float sn = mod(dt, PI); 22 | return fract(sin(sn) * c); 23 | } 24 | float random_double() { 25 | // random double 26 | return rand(vec2(0.0, 1.0)); 27 | } 28 | float random_double(float mi, float mx) { 29 | // random double 30 | return rand(vec2(mi, mx)); 31 | } 32 | int random_int(int mi, int mx) { return int(random_double(mi, mx)); } 33 | vec3 random_vec() { 34 | // random vector 35 | return vec3(random_double(), random_double(), random_double()); 36 | } 37 | vec3 random_vec(float mi, float ma) { 38 | // random vector in given seed 39 | return vec3(random_double(mi, ma), random_double(mi, ma), 40 | random_double(mi, ma)); 41 | } 42 | vec3 random_in_unit_sphere() { 43 | // random in unit sphere 44 | while (true) { 45 | // 46 | vec3 v = random_vec(-1.0, 1.0); 47 | if (dot(v, v) >= 1.0) { 48 | continue; 49 | } 50 | return v; 51 | } 52 | } 53 | vec3 random_unit_vector() { 54 | // unit vector 55 | float a = random_double(0, 2 * PI); 56 | float z = random_double(-1, 1); 57 | float r = sqrt(1 - z * z); 58 | return vec3(r * cos(a), r * sin(a), z); 59 | } 60 | vec3 random_in_hemisphere(vec3 normal) { 61 | // normal ekseninde dagilan yon 62 | vec3 unit_sphere_dir = random_in_unit_sphere(); 63 | if (dot(unit_sphere_dir, normal) > 0.0) { 64 | return unit_sphere_dir; 65 | } else { 66 | return -1 * unit_sphere_dir; 67 | } 68 | } 69 | vec3 random_in_unit_disk() { 70 | // lens yakinsamasi için gerekli 71 | while (true) { 72 | vec3 point = vec3(random_double(-1, 1), random_double(-1, 1), 0); 73 | if (dot(point, point) >= 1) { 74 | continue; 75 | } 76 | return point; 77 | } 78 | } 79 | vec3 refract_vec(vec3 uv, vec3 normal, float eta_over) { 80 | // 81 | float cos_theta = dot(-uv, normal); 82 | vec3 outpar = eta_over * (uv + (cos_theta * normal)); 83 | vec3 out_prep = -sqrt(1.0 - dot(outpar, outpar)) * normal; 84 | return outpar + out_prep; 85 | } 86 | 87 | vec3 mixv(float mi, float ma, vec3 val) { 88 | // 89 | return vec3(mix(mi, ma, val.x), mix(mi, ma, val.y), mix(mi, ma, val.z)); 90 | } 91 | 92 | vec3 fix_color(vec3 pcolor, int samples_per_pixel) { 93 | // scale sample 94 | pcolor /= samples_per_pixel; 95 | return clamp(sqrt(pcolor), 0.0, 0.999); 96 | // return mixv(0.0, 0.999, sqrt(pcolor)); 97 | } 98 | 99 | // --------------------- utility functions end -------------------------- 100 | 101 | // 102 | struct Ray { 103 | vec3 origin; 104 | vec3 direction; 105 | }; 106 | Ray makeRay(vec3 orig, vec3 dir) { 107 | Ray r; 108 | r.origin = orig; 109 | r.direction = dir; 110 | return r; 111 | } 112 | 113 | vec3 at(Ray r, float dist) { return r.direction * dist + r.origin; } 114 | 115 | struct HitRecord { 116 | vec3 point; 117 | vec3 normal; 118 | float dist; 119 | bool front_face; 120 | }; 121 | 122 | HitRecord makeRecord(vec3 p, vec3 n, float d, bool ff) { 123 | HitRecord rec; 124 | rec.point = p; 125 | rec.normal = n; 126 | rec.dist = d; 127 | rec.front_face = ff; 128 | return rec; 129 | } 130 | 131 | void set_face_normal(inout HitRecord rec, in Ray r, in vec3 out_normal) { 132 | // set face normal to hit record did we hit front or back 133 | rec.front_face = dot(r.direction, out_normal) < 0; 134 | rec.normal = (rec.front_face) ? out_normal : -1 * out_normal; 135 | } 136 | struct Camera { 137 | vec3 lower_left_corner; 138 | vec3 origin; 139 | vec3 vertical; 140 | vec3 horizontal; 141 | }; 142 | 143 | Camera makeCamera(float aspect_ratio, float focus_dist) { 144 | // make camera struct 145 | Camera cam; 146 | cam.origin = vec3(0.0, 0.0, 0.0); 147 | cam.horizontal = vec3(4, 0, 0); 148 | cam.vertical = vec3(0, 2, 0); 149 | cam.lower_left_corner = vec3(-2, -1, -1); 150 | 151 | return cam; 152 | } 153 | 154 | Ray get_ray(Camera ca, float u, float v) { 155 | // get camera ray 156 | vec3 r_origin = ca.origin; 157 | vec3 r_dir = 158 | ca.lower_left_corner + (u * ca.horizontal) + (v * ca.vertical) - r_origin; 159 | return makeRay(r_origin, r_dir); 160 | } 161 | 162 | struct Sphere { 163 | vec3 center; 164 | float radius; 165 | }; 166 | 167 | Sphere makeSphere(vec3 cent, float r) { 168 | Sphere sp; 169 | sp.center = cent; 170 | sp.radius = r; 171 | return sp; 172 | } 173 | 174 | bool hitSphere(in Sphere s, in Ray r, float dist_min, float dist_max, 175 | inout HitRecord record) { 176 | // kureye isin vurdu mu onu test eden fonksiyon 177 | vec3 origin_to_center = r.origin - s.center; 178 | float a = dot(r.direction, r.direction); 179 | float half_b = dot(origin_to_center, r.direction); 180 | float c = dot(origin_to_center, origin_to_center) - s.radius * s.radius; 181 | float isHit = half_b * half_b - a * c; 182 | float margin; 183 | if (isHit > 0) { 184 | float root = sqrt(isHit); 185 | margin = (-1 * half_b - root) / a; 186 | if (margin < dist_max && margin > dist_min) { 187 | record.dist = margin; 188 | record.point = at(r, record.dist); 189 | vec3 out_normal = (record.point - s.center) / s.radius; 190 | set_face_normal(record, r, out_normal); 191 | return true; 192 | } 193 | margin = (-1 * half_b + root) / a; 194 | if (margin < dist_max && margin > dist_min) { 195 | record.dist = margin; 196 | record.point = at(r, record.dist); 197 | vec3 out_normal = (record.point - s.center) / s.radius; 198 | set_face_normal(record, r, out_normal); 199 | return true; 200 | } 201 | } 202 | return false; 203 | } 204 | 205 | struct SceneObj { 206 | int type; // 0 sphere, 1, other 207 | Sphere sp; 208 | }; 209 | 210 | struct Scene { 211 | SceneObj ss[SCENE_OBJECT_NB]; 212 | bool isEmpty; 213 | }; 214 | 215 | Scene sliceScene(in Scene scn, int s, int e) { 216 | // slice scene 217 | Scene sout; 218 | if ((s < 0) || (e > SCENE_OBJECT_NB)) { 219 | sout.isEmpty = true; 220 | return sout; 221 | } 222 | int k = 0; 223 | for (int i = s; i < e; i++) { 224 | sout.ss[k] = scn.ss[i]; 225 | k += 1; 226 | } 227 | sout.isEmpty = false; 228 | return sout; 229 | } 230 | 231 | bool hit_scene(in Scene scene, in Ray r, float dmin, float dmax, 232 | inout HitRecord record) { 233 | // check if sphere is hit 234 | HitRecord temp; 235 | bool hit_ = false; 236 | float current_closest = dmax; 237 | for (int i = 0; i < SCENE_OBJECT_NB; i++) { 238 | SceneObj sobj = scene.ss[i]; 239 | if (sobj.type == 0) { 240 | if (hitSphere(sobj.sp, r, dmin, current_closest, temp)) { 241 | hit_ = true; 242 | current_closest = temp.dist; 243 | record = temp; 244 | } 245 | } 246 | } 247 | return hit_; 248 | } 249 | /* 250 | *color ray_color(const ray& r, const hittable& world, int depth) { 251 | hit_record rec; 252 | 253 | // If we've exceeded the ray bounce limit, no more light is gathered. 254 | if (depth <= 0) 255 | return color(0,0,0); 256 | 257 | if (world.hit(r, 0.001, infinity, rec)) { 258 | point3 target = rec.p + rec.normal + random_unit_vector(); 259 | return 0.5 * ray_color(ray(rec.p, target - rec.p), world, depth-1); 260 | } 261 | 262 | vec3 unit_direction = unit_vector(r.direction()); 263 | auto t = 0.5*(unit_direction.y() + 1.0); 264 | return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); 265 | } 266 | * 267 | * */ 268 | 269 | vec3 no_hit_color(in Ray r) { 270 | vec3 dir = normalize(r.direction); 271 | float temp = 0.5 * (dir.y + 1.0); 272 | vec3 cval = vec3(1.0 - temp) + temp * vec3(0.5, 0.7, 1.0); 273 | return cval; 274 | } 275 | 276 | vec3 ray_color(in Ray r, in Scene scene, int depth) { 277 | // 278 | Ray r_in; 279 | r_in.origin = r.origin; 280 | r_in.direction = r.direction; 281 | vec3 bcolor = vec3(1); 282 | 283 | while (true) { 284 | if (depth <= 0) { 285 | // 286 | return vec3(0); 287 | // return bcolor; 288 | } 289 | HitRecord rec; 290 | if (hit_scene(scene, r_in, 0.001, INFINITY, rec)) { 291 | vec3 target = rec.point + random_in_hemisphere(rec.normal); 292 | r_in = makeRay(rec.point, target - rec.point); 293 | depth--; 294 | bcolor *= 0.5; 295 | } else { 296 | vec3 dir = normalize(r_in.direction); 297 | float temp = 0.5 * (dir.y + 1.0); 298 | bcolor *= vec3(1.0 - temp) + temp * vec3(0.5, 0.7, 1.0); 299 | return bcolor; 300 | } 301 | } 302 | } 303 | /* 304 | vec3 ray_color(in Ray r, in Scene scene, int depth) { 305 | // 306 | HitRecord rec; 307 | Ray r_in; 308 | r_in.origin = r.origin; 309 | r_in.direction = r.direction; 310 | vec3 bcolor = vec3(1); 311 | for (int i = depth; i >= 0; i--) { 312 | if (hit_scene(scene, r_in, 0.001, INFINITY, rec)) { 313 | vec3 target = rec.point + random_in_hemisphere(rec.normal); 314 | r_in = makeRay(rec.point, target - rec.point); 315 | bcolor *= 0.5; 316 | } 317 | vec3 dir = normalize(r.direction); 318 | float temp = 0.5 * (dir.y + 1.0); 319 | bcolor *= (1.0 - temp) * vec3(1.0) + temp * vec3(0.5, 0.7, 1.0); 320 | break; // important else gpu chokes 321 | } 322 | return bcolor; 323 | } 324 | */ 325 | 326 | void main() { 327 | // index of global work group 328 | vec4 pixel = vec4(0.0, 0.0, 0.0, 1.0); 329 | ivec2 pixel_index = ivec2(gl_GlobalInvocationID.xy); 330 | ivec2 img_dims = imageSize(img_output); // image dimensions 331 | int imwidth = img_dims.x; 332 | int imheight = img_dims.y; 333 | float aspect_ratio = float(imwidth) / imheight; 334 | int i = pixel_index.x; 335 | int j = pixel_index.y; 336 | int mdepth = 45; // 5 337 | int psample = 50; // 10 338 | 339 | // -------------- declare objects --------------- 340 | 341 | Scene scene; 342 | 343 | SceneObj s10, s20; 344 | s10.type = 0; 345 | s20.type = 0; 346 | Sphere s1 = makeSphere(vec3(0, -100.5, -1), 100); 347 | Sphere s2 = makeSphere(vec3(0, 0, -1), 0.5); 348 | s10.sp = s1; 349 | s20.sp = s2; 350 | scene.ss[0] = s10; 351 | scene.ss[1] = s20; 352 | 353 | float focus_dist = 1.0; 354 | Camera cam = makeCamera(aspect_ratio, focus_dist); 355 | 356 | vec3 rcolor = vec3(0); 357 | 358 | for (int k = 0; k < psample; k++) { 359 | 360 | float u = float(i + random_double()) / (imwidth - 1); 361 | float v = float(j + random_double()) / (imheight - 1); 362 | Ray r = get_ray(cam, u, v); 363 | rcolor += ray_color(r, scene, mdepth); 364 | } 365 | 366 | rcolor = fix_color(rcolor, psample); 367 | // no one ends with 0 in fix color 368 | // 369 | 370 | // output specific pixel in the image 371 | imageStore(img_output, pixel_index, vec4(rcolor, 1.0)); 372 | } 373 | 374 | -} 375 | 376 | infinity = read "Infinity":: Double 377 | 378 | 379 | degree_to_radian :: Float -> Float 380 | 381 | degree_to_radian deg = deg * pi / 180.0 382 | --------------------------------------------------------------------------------