├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── Sandbox ├── README.md ├── ShaderKit.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── ShaderKit │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-1024.png │ │ ├── Icon-128.png │ │ ├── Icon-128@2x.png │ │ ├── Icon-16.png │ │ ├── Icon-16@2x.png │ │ ├── Icon-256.png │ │ ├── Icon-256@2x.png │ │ ├── Icon-32.png │ │ ├── Icon-32@2x.png │ │ ├── Icon-512.png │ │ └── Icon-512@2x.png │ ├── Background.colorset │ │ └── Contents.json │ ├── Contents.json │ ├── city.imageset │ │ ├── Contents.json │ │ ├── city.png │ │ ├── city@2x.png │ │ └── city@3x.png │ └── swift.imageset │ │ ├── Contents.json │ │ ├── swift@1x.png │ │ ├── swift@2x.png │ │ └── swift@3x.png │ ├── ContentView.swift │ ├── GameScene.swift │ ├── Helpers.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── ShaderKit.entitlements │ └── ShaderKitApp.swift ├── ShaderKitExtensions.swift └── Shaders ├── SHKCheckerboard.fsh ├── SHKCircleWave.fsh ├── SHKCircleWaveBlended.fsh ├── SHKCircleWaveRainbow.fsh ├── SHKCircleWaveRainbowBlended.fsh ├── SHKColorAlpha.fsh ├── SHKColorInvert.fsh ├── SHKColorNonAlpha.fsh ├── SHKColorize.fsh ├── SHKDesaturate.fsh ├── SHKDynamicGrayNoise.fsh ├── SHKDynamicRainbowNoise.fsh ├── SHKEmbossColor.fsh ├── SHKEmbossGray.fsh ├── SHKInfrared.fsh ├── SHKInterlace.fsh ├── SHKLightGrid.fsh ├── SHKLinearGradient.fsh ├── SHKPassthrough.fsh ├── SHKPixelate.fsh ├── SHKRadialGradient.fsh ├── SHKScanlines.fsh ├── SHKScreen.fsh ├── SHKStaticGrayNoise.fsh ├── SHKStaticRainbowNoise.fsh └── SHKWater.fsh /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | .DS_Store 22 | *.moved-aside 23 | *.xccheckout 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | *.dSYM.zip 30 | *.dSYM 31 | 32 | ## Playgrounds 33 | timeline.xctimeline 34 | playground.xcworkspace 35 | 36 | # Swift Package Manager 37 | # 38 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 39 | # Packages/ 40 | # Package.pins 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at paul@hackingwithswift.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 44 | 45 | [homepage]: https://www.contributor-covenant.org 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Paul Hudson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | ShaderKit logo 4 |

5 | 6 |

7 | 8 | 9 | 10 | 11 | 12 | Twitter: @twostraws 13 | 14 |

15 | 16 | ShaderKit is an open-source collection of fragment shaders designed for use in SpriteKit games. The shaders are designed to be easy to read and understand, even for relative beginners, so you’ll find each line of code is rephrased in plain English as well as an overall explanation of the algorithm used at the top of each file. 17 | 18 | If you’re already comfortable with shaders then please download one or more that interest you and get going. If not, most of the the remainder of this README acts as a primer for using shaders in SpriteKit. 19 | 20 | 21 | ## See it in action 22 | 23 | This repository contains a cross-platform sample project demonstrating all the shaders in action. Although the shaders themselves work back to iOS 10 and macOS 10.12, the sample project is built using SwiftUI and requires iOS 16 and macOS 13. 24 | 25 | [![Show a video of the shaders in action](https://www.hackingwithswift.com/files/shaderkit/shaderkit-play.png)](https://www.hackingwithswift.com/files/shaderkit/shaderkit-example.mp4) 26 | 27 | 28 | ## TL;DR 29 | 30 | If you use SpriteKit, you can add special effects from ShaderKit to add water ripples, spinning black holes, flashing lights, embossing, noise, gradients, and more – all done on the GPU for maximum speed. 31 | 32 | 33 | ## Credits 34 | 35 | ShaderKit was made by [Paul Hudson](https://twitter.com/twostraws), who writes [free Swift tutorials over at Hacking with Swift](https://www.hackingwithswift.com). It’s available under the MIT license, which permits commercial use, modification, distribution, and private use. 36 | 37 | 38 | ## What are shaders? 39 | 40 | Fragment shaders are tiny programs that operate on individual elements of a sprite’s texture. They are sometimes called “pixel shaders” – it’s not a wholly accurate name, but it does make them easier to understand. 41 | 42 | Effectively, a fragment shader gets run on every pixel in a texture, and can transform that pixel however it wants. That might sound slow, but it isn’t – all the fragment shaders here run at 60fps on iPhone 6 and newer, and 120fps on iPad Pro. 43 | 44 | The transformation process can recolor the pixel however it wants. Users can customize the process by passing fixed values in to the shader (known as “uniforms”) and by assigning values to nodes that use the shader (known as “attributes”). SpriteKit also provides a few built-in values for us to work with, such as the texture co-ordinate for the pixel being modified and the current time. 45 | 46 | 47 | ## How are they written? 48 | 49 | Shaders are written in OpenGL ES 2.0 shading language (GLSL), which is a simple, fast, and extremely efficient C-like language that is optimized for high-performance GPU operations. When you activate a shader in your app, it gets loaded and compiled at runtime, and in doing so should be optimized for whatever device the user has. 50 | 51 | In each shader you’ll find a `main()` function, which is run when the shader activates. This must at some point assign a value to the pre-defined variable `gl_FragColor`, which represents the final color that will be used to draw the pixel. 52 | 53 | GLSL comes with a wide variety of built-in data types and functions, many of which operate on more than one data types. The data types are nice and simple: 54 | 55 | - `bool`: a boolean, i.e. true or false. 56 | - `float`: a floating-point number. GLSL lets you request various precisions, but this isn’t used in ShaderKit. `float` numbers must be written using a decimal place – 1 is considered an integer, whereas `1.` or `1.0` will be considered a `float`. 57 | - `vec2`: a two-component floating-point array. It’s used to hold things like X and Y co-ordinates or width and height. 58 | - `vec3`: a three-component floating-point array. It’s used to hold things like RGB values. 59 | - `vec4`: a four-component floating-point array. It’s used to hold things like RGBA values. 60 | - `void` is used to mark the `main()` function as not returning a value. 61 | 62 | Shaders commonly move fluidly between `float`, `vec2`, `vec3`, and `vec4` as needed. For example, if you create a `vec4` from a `float` then the number will just get repeated for each component in the vector. You’ll also frequently see code to create a `vec4` by using a `vec3` for the first three values (usually RGB) and specifying a fourth value as a `float`. 63 | 64 | Here are the functions used in ShaderKit: 65 | 66 | - `cos()` calculates the cosine of a value in radians. The cosine will always fall between -1 and 1. If you provide `cos()` with a vector (e.g. `vec3`) it will calculate the cosine of each component in the vector and return a vector of the same size containing the results. 67 | - `distance()` calculates the distance between two values. For example, if you provide it with a pair `vec2` you’ll get the length of the vector created by subtracting one from the other. This always returns a single number no matter what data type you give it. 68 | - `dot()` calculates the dot product of two values. This means multiplying each component of the first value by the respective component in the second value, then adding the result. 69 | - `floor()` rounds a number down to its nearest integer. If you pass it a vector this will be done for each component. 70 | - `fract()` returns the fractional component of a value. For example, `fract(12.5)` is 0.5. If you pass this a vector then the operation will be performed component-wise, and a new vector will be returning containing the results. 71 | - `min()` is used to find the lower of two values. If you pass vectors this is done component-wise, meaning that the resulting vector will evaluate each component in the vector and place the lowest in the resulting vector. 72 | - `max()` is used to find the higher of two values. If you pass vectors this is done component-wise, meaning that the resulting vector will evaluate each component in the vector and place the highest in the resulting vector. 73 | - `mix()` smooth interpolates between two values based on a third value that’s specified between 0 and 1, providing a linear curve. 74 | - `mod()` is the modulus function, and calculates remainder after integer division. For example, 10 divides into 3 a total of three times, with remainder 1, so 10 modulo 3 is 1. 75 | - `pow()` calculates one value raised to the power of another, for example `pow(2.0, 3.0)` evaluates to 2.0 * 2.0 * 2.0, giving 8.0. As well as operating on a `float`, `pow()` can also calculate component-wise exponents – it raises the first item in the first vector to the power of the first item in the second vector, and so on. 76 | - `sin()` calculates the sine of a value in radians. The sine will always fall between -1 and 1. If you provide `sin()` with a vector (e.g. `vec3`) it will calculate the sine of each component in the vector and return a vector of the same size containing the results. 77 | - `smoothstep()` interpolates between two values based on a third value that’s specified between 0 and 1, providing an S-curve shape. That is, the interpolation starts slow (values near 0.0), picks up speed (values near 0.5), then slows down towards the end (values near 1.0). 78 | - `texture2D()` provides the color value of a texture at a specific location. This is most commonly used to read the current pixel’s color. (Technically this reads *texels*, but it’s easier to think about pixels while you’re learning.) 79 | 80 | There is one further special function worth mentioning, which is `SKDefaultShading()`. This provides the default color SpriteKit was planning to render for the current fragment. 81 | 82 | 83 | ## Attributes and uniforms 84 | 85 | Many shaders can operate without any special input from the user – it can manipulate the color data it was sent by SpriteKit, then send back new data. 86 | 87 | However, often you’ll want to customize the way shaders work, a bit like passing in parameters to a function. Shaders are a little more complicated because these values need to be uploaded to the GPU, but the principle is the same. 88 | 89 | ShaderKit uses two approaches for customizing shader behavior: uniforms and attributes. They are very similar, but the difference is that uniforms are attached to shaders and attributes are attached to nodes. 90 | 91 | Almost everything is declared as a uniform in ShaderKit. So, if you want to customize the colors for your gradient, the strength of your water rippling, or the size of your interlacing lines, these are all specified as uniforms. 92 | 93 | However, one thing is consistently specified as an attribute, which is *node size*. Some shaders (see below) require the size of the node they are operating on, and although this *could* be specified as a uniform it would stop you from using the same shader on multiple nodes. So, instead it’s specified as an attribute: each sprite tells the shader how big it is, and that value combines with the uniforms inside the shader to produce the final result. 94 | 95 | By convention, uniform names start with “u” and attribute names start with “a”. So, when you see “u_strength” you know it’s a uniform, and when you see “a_size” you know it’s an attribute. 96 | 97 | **Please note note:** there is a performance cost to uploading uniform and attribute data to the GPU. As a result, you should only specify values that are actually used inside the shader. 98 | 99 | This repository also contains ShaderKitExtensions.swift. This adds a handful of convenience initializers for setting uniforms and attributes from common types: `CGSize`, `CGPoint`, and `SKColor`. (NB: `SKColor` is either `UIColor` or `NSColor` depending on whether you’re using iOS/tvOS/watchOS or macOS.) 100 | 101 | Although these extensions aren’t required, they will make it significantly easier to use the shaders provided here – you should add ShaderKitExtensions.swift to your own project alongside whichever shaders you want. 102 | 103 | One of these extensions adds a new initializer for `SKShader` that loads a shader file into a string then creates an `SKShader` from that string, and assigns any uniforms or attribute settings. This is helpful while debugging, because shaders loaded from strings get debug information printed inside Xcode, so if you modify a shader incorrectly Xcode will help you understand the problem. 104 | 105 | **All Swift code examples below use this initializer.** 106 | 107 | As stated above, the only attribute you need to specify in any of the ShaderKit shaders is the sprite’s size. This is only required in some shaders (see below), and with ShaderKitExtension.swift is done like this: 108 | 109 | ```swift 110 | yourSprite.setValue(SKAttributeValue(size: yourSprite.size), forAttribute: "a_size") 111 | ``` 112 | 113 | 114 | ## Built-in values 115 | 116 | SpriteKit provides several built-in values that are useful when building shaders: 117 | 118 | - `u_texture`: the texture that is being rendered. You can read individual color values from this. 119 | - `u_time`: how much time has elapsed in the game. 120 | - `v_tex_coord`: the position of the current pixel in the texture. These are normalized to the bottom-left corner, meaning that (0.0, 0.0) is the bottom-left corner and (1.0, 1.0) is the top-right corner. 121 | - `v_color_mix`: the color of the node being rendered. 122 | 123 | 124 | ## Reading the shaders 125 | 126 | All the shaders in ShaderKit were specifically written for readability. Specifically, they: 127 | 128 | 1. All start with a brief comment outlining what each shader does. 129 | 2. List all input attributes and uniforms (where they are used), along with ranges and a suggested starting point. 130 | 3. An explanation of the algorithm used. 131 | 4. Detailed line-by-line English translations of what the code means. 132 | 133 | The combination of what the code *does* (the interlinear comments) and what the code *means* (the algorithm introduction) should hopefully make these shaders comprehensible to everyone. 134 | 135 | One small note: you will commonly see the final fragment color multiplied both by the original color’s alpha and the alpha value of `v_color_mix`. The former ensures the new color takes into account the alpha value of the original, which keeps edges smooth; the latter ensures the new color takes into account the alpha of the whole node, so that it can be faded in or out smoothly. 136 | 137 | 138 | ## Shaders included in ShaderKit 139 | ShaderKit provides a selection of shaders, most of which allow some customization using uniforms. Some shaders are merely variations of others, provided separately to avoid too much of a performance hit. 140 | 141 | 142 | ### Checkerboard 143 | Renders a checkerboard with user-defined row/column count and colors. 144 | 145 | **Parameters:** 146 | 147 | - Uniform: `u_rows`, how many rows to generate. Should be at least 1. 148 | - Uniform: `u_cols`, how many columns to generate. Should be at least 1. 149 | - Uniform: `u_first_color`, an `SKColor` to use for half of the squares. 150 | - Uniform: `u_second_color`, an `SKColor` to use for the other half of the squares. 151 | 152 | Example code: 153 | 154 | ```swift 155 | func createCheckerboard() -> SKShader { 156 | let uniforms: [SKUniform] = [ 157 | SKUniform(name: "u_rows", float: 12), 158 | SKUniform(name: "u_cols", float: 12), 159 | SKUniform(name: "u_first_color", color: .white), 160 | SKUniform(name: "u_second_color", color: .black), 161 | ] 162 | 163 | return SKShader(fromFile: "SHKCheckerboard", uniforms: uniforms) 164 | } 165 | ``` 166 | 167 | ### Circle Wave 168 | Renders a circular pulsating wave effect. This comes in four variants: 169 | 170 | 1. Circle Wave generates a fixed-color wave while ignoring existing pixel colors. 171 | 2. Circle Wave (Blended) generates a fixed-color wave while blending with existing pixel colors. 172 | 3. Circle Wave Rainbow generates a fluctuating-color wave while ignoring existing pixel colors. 173 | 4. Circle Wave Rainbow (Blended) generates a fluctuating-color wave while blending with existing pixel colors. 174 | 175 | **Parameters for Circle Wave and Circle Wave Blended:** 176 | 177 | - Uniform: `u_speed`, how fast the wave should travel. Ranges from -2 to 2 work best, where negative numbers cause waves to come inwards; try starting with 1. 178 | - Uniform: `u_brightness`, how bright the colors should be. Ranges from 0 to 5 work best; try starting with 0.5 and experiment. 179 | - Uniform: `u_strength`, how intense the waves should be. Ranges from 0.02 to 5 work best; try starting with 2. 180 | - Uniform: `u_density`, how large each wave should be. Ranges from 20 to 500 work best; try starting with 100. 181 | - Uniform: `u_center`, a `CGPoint` representing the center of the gradient, where 0.5/0.5 is dead center 182 | - Uniform: `u_color`, the SKColor to use. Use darker colors to create a less intense core. 183 | 184 | **Parameters for Circle Wave Rainbow and Circle Wave Rainbow Blended:** 185 | 186 | - Uniform: `u_speed`, how fast the wave should travel. Ranges from -2 to 2 work best, where negative numbers cause waves to come inwards; try starting with 1. 187 | - Uniform: `u_brightness`, how bright the colors should be. Ranges from 0 to 5 work best; try starting with 0.5 and experiment. 188 | - Uniform: `u_strength`, how intense the waves should be. Ranges from 0.02 to 5 work best; try starting with 2. 189 | - Uniform: `u_density`, how large each wave should be. Ranges from 20 to 500 work best; try starting with 100. 190 | - Uniform: `u_center`, a `CGPoint` representing the center of the gradient, where 0.5/0.5 is dead center 191 | - Uniform: `u_red`, how much red to apply to the colors. Specify 0 to 1 to apply that amount of red, or use any negative number (e.g. -1) to have the amount of red fluctuate. 192 | 193 | 194 | Example code: 195 | 196 | ```swift 197 | func createCircleWave() -> SKShader { 198 | let uniforms: [SKUniform] = [ 199 | SKUniform(name: "u_speed", float: 1), 200 | SKUniform(name: "u_brightness", float: 0.5), 201 | SKUniform(name: "u_strength", float: 2), 202 | SKUniform(name: "u_density", float: 100), 203 | SKUniform(name: "u_center", point: CGPoint(x: 0.68, y: 0.33)), 204 | SKUniform(name: "u_color", color: UIColor(red: 0, green: 0.5, blue: 0, alpha: 1)) 205 | ] 206 | 207 | return SKShader(fromFile: "SHKCircleWave", uniforms: uniforms) 208 | } 209 | 210 | func createCircleWaveRainbowBlended() -> SKShader { 211 | let uniforms: [SKUniform] = [ 212 | SKUniform(name: "u_speed", float: 1), 213 | SKUniform(name: "u_brightness", float: 0.5), 214 | SKUniform(name: "u_strength", float: 2), 215 | SKUniform(name: "u_density", float: 100), 216 | SKUniform(name: "u_center", point: CGPoint(x: 0.68, y: 0.33)), 217 | SKUniform(name: "u_red", float: -1) 218 | ] 219 | 220 | return SKShader(fromFile: "SHKCircleWaveRainbowBlended", uniforms: uniforms) 221 | } 222 | ``` 223 | 224 | 225 | ### Color Alpha 226 | Colors all clear pixels in the node. 227 | 228 | **Parameters:** 229 | 230 | - Uniform: `u_color`, the `SKColor` to use. 231 | 232 | Example code: 233 | 234 | ```swift 235 | func createColorAlpha() -> SKShader { 236 | let uniforms: [SKUniform] = [ 237 | SKUniform(name: "u_color", color: .green) 238 | ] 239 | 240 | return SKShader(fromFile: "SHKColorAlpha", uniforms: uniforms) 241 | } 242 | ``` 243 | 244 | 245 | ### Color Non-Alpha 246 | Colors all clear pixels in the node. 247 | 248 | **Parameters:** 249 | 250 | - Uniform: u_color, the SKColor to use. 251 | 252 | Example code: 253 | 254 | ```swift 255 | func createColorNonAlpha() -> SKShader { 256 | let uniforms: [SKUniform] = [ 257 | SKUniform(name: "u_color", color: .yellow) 258 | ] 259 | 260 | return SKShader(fromFile: "SHKColorNonAlpha", uniforms: uniforms) 261 | } 262 | ``` 263 | 264 | 265 | ### Color Invert 266 | Inverts all colors in a node while retaining transparency. 267 | 268 | **Parameters:** 269 | 270 | - None. 271 | 272 | Example code: 273 | 274 | ```swift 275 | func createColorInvert() -> SKShader { 276 | return SKShader(fromFile: "SHKColorInvert") 277 | } 278 | ``` 279 | 280 | 281 | ### Colorize 282 | Recolors a texture to a user color based on a strength value. 283 | 284 | **Parameters:** 285 | 286 | - Uniform: `u_color`, the `SKColor` to use. This is multiplied with the original, meaning that blacks remain black. 287 | - Uniform: `u_strength`, how much of the replacement color to apply. Specify a value between 0 (use original color) and 1 (use replacement color fully). 288 | 289 | Example code: 290 | 291 | ```swift 292 | func createColorize() -> SKShader { 293 | let uniforms: [SKUniform] = [ 294 | SKUniform(name: "u_color", color: .green), 295 | SKUniform(name: "u_strength", float: 1) 296 | ] 297 | 298 | return SKShader(fromFile: "SHKColorize", uniforms: uniforms) 299 | } 300 | ``` 301 | 302 | 303 | ### Desaturate 304 | Desaturates the colors in a texture. 305 | 306 | **Parameters:** 307 | 308 | - Uniform: `u_strength`, the amount to desaturate. Specify 0 (no desaturation) to 1 (full desaturation). 309 | 310 | Example code: 311 | 312 | ```swift 313 | func createDesaturate() -> SKShader { 314 | let uniforms: [SKUniform] = [ 315 | SKUniform(name: "u_strength", float: 0.5), 316 | ] 317 | 318 | return SKShader(fromFile: "SHKDesaturate", uniforms: uniforms) 319 | } 320 | ``` 321 | 322 | 323 | ### Emboss 324 | Creates a 3D embossing effect. This comes in two variants: 325 | 326 | - Emboss Color retains the original color values while adding 3D highlights and shadows. 327 | - Emboss Gray uses a middle gray (RGB: 0.5) then adds 3D highlights and shadows on top. 328 | 329 | **Parameters:** 330 | 331 | - Attribute: `a_size`, the size of the node. 332 | - Uniform: `u_strength`, how much embossing to apply (ranges from 0 to 1 work best) 333 | 334 | Example code: 335 | 336 | ```swift 337 | func createColorEmboss() -> SKShader { 338 | let uniforms: [SKUniform] = [ 339 | SKUniform(name: "u_strength", float: 1) 340 | ] 341 | 342 | let attributes = [ 343 | SKAttribute(name: "a_size", type: .vectorFloat2) 344 | ] 345 | 346 | return SKShader(fromFile: "SHKEmbossColor", uniforms: uniforms, attributes: attributes) 347 | } 348 | 349 | func createGrayEmboss() -> SKShader { 350 | let uniforms: [SKUniform] = [ 351 | SKUniform(name: "u_strength", float: 1) 352 | ] 353 | 354 | let attributes = [ 355 | SKAttribute(name: "a_size", type: .vectorFloat2) 356 | ] 357 | 358 | return SKShader(fromFile: "SHKEmbossGray", uniforms: uniforms, attributes: attributes) 359 | } 360 | ``` 361 | 362 | 363 | ### Infrared 364 | Simulates an infrared camera by coloring brighter objects red and darker objects blue. 365 | 366 | **Parameters:** 367 | 368 | - None. 369 | 370 | Example code: 371 | 372 | ```swift 373 | func createInfrared() -> SKShader { 374 | return SKShader(fromFile: "SHKInfrared") 375 | } 376 | ``` 377 | 378 | 379 | ### Interlace 380 | Applies an interlacing effect where horizontal lines of original color are separated by lines of another color. 381 | 382 | **Parameters:** 383 | 384 | - Attribute: `a_size`, the size of the node. 385 | - Uniform: `u_width`, the width of the interlacing lines. Ranges of 1 to 4 work best; try starting with 1. 386 | - Uniform: `u_color`, the `SKColor` to use for interlacing lines. Try starting with black. 387 | - Uniform: `u_strength`, how much to blend interlaced lines with `u_color`. Specify 0 (not at all) up to 1 (fully). 388 | 389 | Example code: 390 | 391 | ```swift 392 | func createInterlace() -> SKShader { 393 | let uniforms: [SKUniform] = [ 394 | SKUniform(name: "u_width", float: 2), 395 | SKUniform(name: "u_color", color: .black), 396 | SKUniform(name: "u_strength", float: 0.35), 397 | ] 398 | 399 | let attributes = [ 400 | SKAttribute(name: "a_size", type: .vectorFloat2) 401 | ] 402 | 403 | return SKShader(fromFile: "SHKInterlace", uniforms: uniforms, attributes: attributes) 404 | } 405 | ``` 406 | 407 | 408 | ### Light grid 409 | Creates a grid of multi-colored flashing lights. 410 | 411 | **Parameters:** 412 | 413 | - Uniform: `u_density`, how many rows and columns to create. A range of 1 to 50 works well; try starting with 8. 414 | - Uniform: `u_speed`, how fast to make the lights vary their color. Higher values cause lights to flash faster and vary in color more. A range of 1 to 20 works well; try starting with 3. 415 | - Uniform: `u_group_size`, how many lights to place in each group. A range of 1 to 8 works well depending on your density; starting with 1. 416 | - Uniform: `u_brightness`, how bright to make the lights. A range of 0.2 to 10 works well; try starting with 3. 417 | 418 | Example code: 419 | 420 | ```swift 421 | func createLightGrid() -> SKShader { 422 | let uniforms: [SKUniform] = [ 423 | SKUniform(name: "u_density", float: 8), 424 | SKUniform(name: "u_speed", float: 3), 425 | SKUniform(name: "u_group_size", float: 2), 426 | SKUniform(name: "u_brightness", float: 3), 427 | ] 428 | 429 | return SKShader(fromFile: "SHKLightGrid", uniforms: uniforms) 430 | } 431 | ``` 432 | 433 | 434 | ### Linear gradient 435 | Creates a linear gradient over the node. Either the start or the end color can be translucent to let original pixel colors come through. 436 | 437 | **Parameters:** 438 | 439 | - Uniform: `u_first_color`, the `SKColor` to use at the top of the gradient 440 | - Uniform: `u_second_color`, the `SKColor` to use at the bottom of the gradient 441 | 442 | Example code: 443 | 444 | ```swift 445 | func createLinearGradient() -> SKShader { 446 | let uniforms: [SKUniform] = [ 447 | SKUniform(name: "u_first_color", color: .blue), 448 | SKUniform(name: "u_second_color", color: .clear) 449 | ] 450 | 451 | return SKShader(fromFile: "SHKLinearGradient", uniforms: uniforms) 452 | } 453 | ``` 454 | 455 | 456 | ### Noise 457 | Generates random pixels of different colors to simulate noise. This comes in four variants: 458 | 459 | 1. Static Gray Noise generates grayscale noise that doesn’t move. 460 | 2. Static Rainbow Noise generates multicolor noise that doesn’t move. 461 | 3. Dynamic Gray Noise generates grayscale noise that is constantly changing. 462 | 4. Dynamic Rainbow Noise generates multicolor noise that is constantly changing. 463 | 464 | **Parameters:** 465 | 466 | - None. 467 | 468 | Example code: 469 | 470 | ```swift 471 | func createStaticGrayNoise() -> SKShader { 472 | return SKShader(fromFile: "SHKStaticGrayNoise") 473 | } 474 | 475 | func createDynamicRainbowNoise() -> SKShader { 476 | return SKShader(fromFile: "SHKDynamicRainbowNoise") 477 | } 478 | ``` 479 | 480 | 481 | ### Pixelate 482 | Pixelates an image based on a strength provided by the user. 483 | 484 | **Parameters:** 485 | 486 | - Attribute: `a_size`, the size of the node. 487 | - Uniform: `u_strength`, how large each pixel block should be. Ranges from 2 to 50 work best; try starting with 5. 488 | 489 | Example code: 490 | 491 | ```swift 492 | func createPixelate() -> SKShader { 493 | let uniforms: [SKUniform] = [ 494 | SKUniform(name: "u_strength", float: 8), 495 | ] 496 | 497 | let attributes = [ 498 | SKAttribute(name: "a_size", type: .vectorFloat2) 499 | ] 500 | 501 | return SKShader(fromFile: "SHKPixelate", uniforms: uniforms, attributes: attributes) 502 | } 503 | ``` 504 | 505 | 506 | ### Radial gradient 507 | Creates a radial gradient over the node. Either the start or the end color can be translucent to let original pixel colors come through. 508 | 509 | **Parameters:** 510 | 511 | - Uniform: `u_first_color`, the SKColor to use at the center of the gradient 512 | - Uniform: `u_second_color`, the SKColor to use at the edge of the gradient 513 | - Uniform: `u_center`, a `CGPoint` representing the center of the gradient, where 0.5/0.5 is dead center. 514 | 515 | Example code: 516 | 517 | ```swift 518 | func createRadialGradient() -> SKShader { 519 | let uniforms: [SKUniform] = [ 520 | SKUniform(name: "u_first_color", color: .blue), 521 | SKUniform(name: "u_second_color", color: .clear), 522 | SKUniform(name: "u_center", point: CGPoint(x: 0.75, y: 0.25)) 523 | ] 524 | 525 | return SKShader(fromFile: "SHKRadialGradient", uniforms: uniforms) 526 | } 527 | ``` 528 | 529 | 530 | ### Scanlines 531 | Applies scanlines and pixelation to the node, giving a retro television effect. 532 | 533 | **Parameters:** 534 | 535 | - Uniform: `u_width`, vertical width of scanlines and width of pixelation. 536 | - Uniform: `u_brightness`, brightness of scanlines, between 0 and 1.0. Higher values introduce overexposure. 537 | - Uniform: `u_color`, blend color of scanlines. 538 | 539 | Example code: 540 | 541 | ```swift 542 | func createScanlines() -> SKShader { 543 | let uniforms: [SKUniform] = [ 544 | SKUniform(name: "u_width", float: 4.0), 545 | SKUniform(name: "u_brightness", float: 0.75), 546 | SKUniform(name: "u_color", color: .white), 547 | ] 548 | 549 | let attributes = [ 550 | SKAttribute(name: "a_size", type: .vectorFloat2) 551 | ] 552 | 553 | return SKShader(fromFile: "SHKScanlines", uniforms: uniforms, attributes: attributes) 554 | } 555 | ``` 556 | 557 | 558 | ### Screen 559 | Applies an interlacing effect where horizontal and vertical lines of original color are separated by lines of another color 560 | 561 | **Parameters:** 562 | 563 | - Attribute: `a_size`, the size of the node. 564 | - Uniform: `u_width`, the width of the interlacing lines. Ranges from 2 upwards work well. 565 | - Uniform: `u_color`, the `SKColor` to use for interlacing lines. Try starting with black. 566 | - Uniform: `u_strength`, how much to blend interlaced lines with `u_color`. Specify 0 (not at all) up to 1 (fully). 567 | 568 | Example code: 569 | 570 | ```swift 571 | func createScreen() -> SKShader { 572 | let uniforms: [SKUniform] = [ 573 | SKUniform(name: "u_width", float: 2), 574 | SKUniform(name: "u_color", color: .clear), 575 | SKUniform(name: "u_strength", float: 1), 576 | ] 577 | 578 | let attributes = [ 579 | SKAttribute(name: "a_size", type: .vectorFloat2) 580 | ] 581 | 582 | return SKShader(fromFile: "SHKScreen", uniforms: uniforms, attributes: attributes) 583 | } 584 | ``` 585 | 586 | 587 | ### Water 588 | Warps a textured node to create a water rippling effect. Note: this must be applied to something that has a texture. 589 | 590 | **Parameters:** 591 | 592 | - Uniform: `u_speed`, how many fast to make the water ripple. Ranges from 0.5 to 10 work best; try starting with 3. 593 | - Uniform: `u_strength`, how pronounced the rippling effect should be. Ranges from 1 to 5 work best; try starting with 3. 594 | - Uniform: `u_frequency`, how often ripples should be created. Ranges from 5 to 25 work best; try starting with 10. 595 | 596 | Example code: 597 | 598 | ```swift 599 | func createWater() -> SKShader { 600 | let uniforms: [SKUniform] = [ 601 | SKUniform(name: "u_speed", float: 3), 602 | SKUniform(name: "u_strength", float: 2.5), 603 | SKUniform(name: "u_frequency", float: 10) 604 | ] 605 | 606 | return SKShader(fromFile: "SHKWater", uniforms: uniforms) 607 | } 608 | ``` 609 | 610 | 611 | ## ShaderKit Sandbox 612 | 613 | Inside this repository are example SpriteKit projects for iOS and macOS that demonstrate each of the shaders with some example values – try running them if you’re curious how each of the shaders look or perform on your device. 614 | 615 | If you’ve modified one of the shaders and want to see how it looks, the sandbox is the best place. If you tap or click the screen the test nodes will alternate between alpha 0 and alpha 1 so you can make sure your modifications blend correctly. 616 | 617 | The iOS sandbox has been tested on iPhone 6, 6s, 7, and X, as well as iPad Pro. The macOS sandbox has been tested on a retina MacBook Pro using macOS 10.13. 618 | 619 | Note: although each of these filters could be ported to any shader-supporting platform with little work, I’ve tested them specifically on iOS/macOS and SpriteKit. 620 | 621 | 622 | ## Contributing 623 | 624 | I made ShaderKit because not enough people know that shaders are powerful, easy ways to add special effects to your games. If you’d like to contribute your own shaders or modifications to existing shaders, that’s great! But first please read the following: 625 | 626 | - ShaderKit has a strong emphasis on readability. Beginners should be able to read most of these shaders and have a good idea of how they work. If you want to make one of the shaders faster, please don’t do so at the expensive of readability. 627 | - You must comment your code thoroughly. Shaders are often extremely terse, so please write in English above every line what the code does – a transliteration, if you will – and also provide a description of how it all works to produce the final result. 628 | - All code must be licensed under the MIT license so it can benefit the most people. 629 | 630 | 631 | ## License 632 | 633 | MIT License. 634 | 635 | Copyright (c) 2017 Paul Hudson 636 | 637 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 638 | 639 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 640 | 641 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 642 | -------------------------------------------------------------------------------- /Sandbox/README.md: -------------------------------------------------------------------------------- 1 | This is a trivial cross-platform project that demonstrates each of the shaders being applied with some example settings. 2 | 3 | Note: to avoid duplicating code, this references ShaderKitExtensions.swift and all its shaders from the parent directory. 4 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 51DCEFDD2A0BD9AA00561C9B /* ShaderKitApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51DCEFDC2A0BD9AA00561C9B /* ShaderKitApp.swift */; }; 11 | 51DCEFDF2A0BD9AA00561C9B /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51DCEFDE2A0BD9AA00561C9B /* ContentView.swift */; }; 12 | 51DCEFE12A0BD9AB00561C9B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 51DCEFE02A0BD9AB00561C9B /* Assets.xcassets */; }; 13 | 51DCEFE52A0BD9AB00561C9B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 51DCEFE42A0BD9AB00561C9B /* Preview Assets.xcassets */; }; 14 | 51DCEFED2A0BD9F000561C9B /* GameScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51DCEFEC2A0BD9F000561C9B /* GameScene.swift */; }; 15 | 51DCF0412A0BE05400561C9B /* SHKCircleWaveRainbowBlended.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0272A0BE05400561C9B /* SHKCircleWaveRainbowBlended.fsh */; }; 16 | 51DCF0422A0BE05400561C9B /* SHKInfrared.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0282A0BE05400561C9B /* SHKInfrared.fsh */; }; 17 | 51DCF0432A0BE05400561C9B /* SHKWater.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0292A0BE05400561C9B /* SHKWater.fsh */; }; 18 | 51DCF0442A0BE05400561C9B /* SHKStaticGrayNoise.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF02A2A0BE05400561C9B /* SHKStaticGrayNoise.fsh */; }; 19 | 51DCF0452A0BE05400561C9B /* SHKCircleWave.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF02B2A0BE05400561C9B /* SHKCircleWave.fsh */; }; 20 | 51DCF0462A0BE05400561C9B /* SHKColorInvert.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF02C2A0BE05400561C9B /* SHKColorInvert.fsh */; }; 21 | 51DCF0472A0BE05400561C9B /* SHKEmbossColor.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF02D2A0BE05400561C9B /* SHKEmbossColor.fsh */; }; 22 | 51DCF0482A0BE05400561C9B /* SHKRadialGradient.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF02E2A0BE05400561C9B /* SHKRadialGradient.fsh */; }; 23 | 51DCF0492A0BE05400561C9B /* SHKLightGrid.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF02F2A0BE05400561C9B /* SHKLightGrid.fsh */; }; 24 | 51DCF04A2A0BE05400561C9B /* SHKLinearGradient.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0302A0BE05400561C9B /* SHKLinearGradient.fsh */; }; 25 | 51DCF04B2A0BE05400561C9B /* SHKColorAlpha.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0312A0BE05400561C9B /* SHKColorAlpha.fsh */; }; 26 | 51DCF04C2A0BE05400561C9B /* SHKCircleWaveBlended.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0322A0BE05400561C9B /* SHKCircleWaveBlended.fsh */; }; 27 | 51DCF04D2A0BE05400561C9B /* SHKEmbossGray.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0332A0BE05400561C9B /* SHKEmbossGray.fsh */; }; 28 | 51DCF04E2A0BE05400561C9B /* SHKInterlace.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0342A0BE05400561C9B /* SHKInterlace.fsh */; }; 29 | 51DCF04F2A0BE05400561C9B /* SHKPixelate.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0352A0BE05400561C9B /* SHKPixelate.fsh */; }; 30 | 51DCF0502A0BE05400561C9B /* SHKStaticRainbowNoise.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0362A0BE05400561C9B /* SHKStaticRainbowNoise.fsh */; }; 31 | 51DCF0512A0BE05400561C9B /* SHKColorize.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0372A0BE05400561C9B /* SHKColorize.fsh */; }; 32 | 51DCF0522A0BE05400561C9B /* SHKPassthrough.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0382A0BE05400561C9B /* SHKPassthrough.fsh */; }; 33 | 51DCF0532A0BE05400561C9B /* SHKDynamicGrayNoise.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0392A0BE05400561C9B /* SHKDynamicGrayNoise.fsh */; }; 34 | 51DCF0542A0BE05400561C9B /* SHKCircleWaveRainbow.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF03A2A0BE05400561C9B /* SHKCircleWaveRainbow.fsh */; }; 35 | 51DCF0552A0BE05400561C9B /* SHKScreen.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF03B2A0BE05400561C9B /* SHKScreen.fsh */; }; 36 | 51DCF0562A0BE05400561C9B /* SHKDynamicRainbowNoise.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF03C2A0BE05400561C9B /* SHKDynamicRainbowNoise.fsh */; }; 37 | 51DCF0572A0BE05400561C9B /* SHKDesaturate.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF03D2A0BE05400561C9B /* SHKDesaturate.fsh */; }; 38 | 51DCF0582A0BE05400561C9B /* SHKColorNonAlpha.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF03E2A0BE05400561C9B /* SHKColorNonAlpha.fsh */; }; 39 | 51DCF0592A0BE05400561C9B /* SHKScanlines.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF03F2A0BE05400561C9B /* SHKScanlines.fsh */; }; 40 | 51DCF05A2A0BE05400561C9B /* SHKCheckerboard.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 51DCF0402A0BE05400561C9B /* SHKCheckerboard.fsh */; }; 41 | 51DCF05C2A0BE0DF00561C9B /* ShaderKitExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51DCF05B2A0BE0DF00561C9B /* ShaderKitExtensions.swift */; }; 42 | 51DCF0952A0C012F00561C9B /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51DCF0942A0C012F00561C9B /* Helpers.swift */; }; 43 | /* End PBXBuildFile section */ 44 | 45 | /* Begin PBXFileReference section */ 46 | 51DCEFD92A0BD9AA00561C9B /* ShaderKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShaderKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 51DCEFDC2A0BD9AA00561C9B /* ShaderKitApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShaderKitApp.swift; sourceTree = ""; }; 48 | 51DCEFDE2A0BD9AA00561C9B /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 49 | 51DCEFE02A0BD9AB00561C9B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 50 | 51DCEFE22A0BD9AB00561C9B /* ShaderKit.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShaderKit.entitlements; sourceTree = ""; }; 51 | 51DCEFE42A0BD9AB00561C9B /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 52 | 51DCEFEC2A0BD9F000561C9B /* GameScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScene.swift; sourceTree = ""; }; 53 | 51DCF0272A0BE05400561C9B /* SHKCircleWaveRainbowBlended.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKCircleWaveRainbowBlended.fsh; sourceTree = ""; }; 54 | 51DCF0282A0BE05400561C9B /* SHKInfrared.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKInfrared.fsh; sourceTree = ""; }; 55 | 51DCF0292A0BE05400561C9B /* SHKWater.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKWater.fsh; sourceTree = ""; }; 56 | 51DCF02A2A0BE05400561C9B /* SHKStaticGrayNoise.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKStaticGrayNoise.fsh; sourceTree = ""; }; 57 | 51DCF02B2A0BE05400561C9B /* SHKCircleWave.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKCircleWave.fsh; sourceTree = ""; }; 58 | 51DCF02C2A0BE05400561C9B /* SHKColorInvert.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKColorInvert.fsh; sourceTree = ""; }; 59 | 51DCF02D2A0BE05400561C9B /* SHKEmbossColor.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKEmbossColor.fsh; sourceTree = ""; }; 60 | 51DCF02E2A0BE05400561C9B /* SHKRadialGradient.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKRadialGradient.fsh; sourceTree = ""; }; 61 | 51DCF02F2A0BE05400561C9B /* SHKLightGrid.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKLightGrid.fsh; sourceTree = ""; }; 62 | 51DCF0302A0BE05400561C9B /* SHKLinearGradient.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKLinearGradient.fsh; sourceTree = ""; }; 63 | 51DCF0312A0BE05400561C9B /* SHKColorAlpha.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKColorAlpha.fsh; sourceTree = ""; }; 64 | 51DCF0322A0BE05400561C9B /* SHKCircleWaveBlended.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKCircleWaveBlended.fsh; sourceTree = ""; }; 65 | 51DCF0332A0BE05400561C9B /* SHKEmbossGray.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKEmbossGray.fsh; sourceTree = ""; }; 66 | 51DCF0342A0BE05400561C9B /* SHKInterlace.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKInterlace.fsh; sourceTree = ""; }; 67 | 51DCF0352A0BE05400561C9B /* SHKPixelate.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKPixelate.fsh; sourceTree = ""; }; 68 | 51DCF0362A0BE05400561C9B /* SHKStaticRainbowNoise.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKStaticRainbowNoise.fsh; sourceTree = ""; }; 69 | 51DCF0372A0BE05400561C9B /* SHKColorize.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKColorize.fsh; sourceTree = ""; }; 70 | 51DCF0382A0BE05400561C9B /* SHKPassthrough.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKPassthrough.fsh; sourceTree = ""; }; 71 | 51DCF0392A0BE05400561C9B /* SHKDynamicGrayNoise.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKDynamicGrayNoise.fsh; sourceTree = ""; }; 72 | 51DCF03A2A0BE05400561C9B /* SHKCircleWaveRainbow.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKCircleWaveRainbow.fsh; sourceTree = ""; }; 73 | 51DCF03B2A0BE05400561C9B /* SHKScreen.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKScreen.fsh; sourceTree = ""; }; 74 | 51DCF03C2A0BE05400561C9B /* SHKDynamicRainbowNoise.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKDynamicRainbowNoise.fsh; sourceTree = ""; }; 75 | 51DCF03D2A0BE05400561C9B /* SHKDesaturate.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKDesaturate.fsh; sourceTree = ""; }; 76 | 51DCF03E2A0BE05400561C9B /* SHKColorNonAlpha.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKColorNonAlpha.fsh; sourceTree = ""; }; 77 | 51DCF03F2A0BE05400561C9B /* SHKScanlines.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKScanlines.fsh; sourceTree = ""; }; 78 | 51DCF0402A0BE05400561C9B /* SHKCheckerboard.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SHKCheckerboard.fsh; sourceTree = ""; }; 79 | 51DCF05B2A0BE0DF00561C9B /* ShaderKitExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShaderKitExtensions.swift; path = ../../ShaderKitExtensions.swift; sourceTree = ""; }; 80 | 51DCF0942A0C012F00561C9B /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; 81 | /* End PBXFileReference section */ 82 | 83 | /* Begin PBXFrameworksBuildPhase section */ 84 | 51DCEFD62A0BD9AA00561C9B /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXFrameworksBuildPhase section */ 92 | 93 | /* Begin PBXGroup section */ 94 | 51DCEFD02A0BD9AA00561C9B = { 95 | isa = PBXGroup; 96 | children = ( 97 | 51DCEFDB2A0BD9AA00561C9B /* ShaderKit */, 98 | 51DCEFDA2A0BD9AA00561C9B /* Products */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | 51DCEFDA2A0BD9AA00561C9B /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 51DCEFD92A0BD9AA00561C9B /* ShaderKit.app */, 106 | ); 107 | name = Products; 108 | sourceTree = ""; 109 | }; 110 | 51DCEFDB2A0BD9AA00561C9B /* ShaderKit */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 51DCEFDC2A0BD9AA00561C9B /* ShaderKitApp.swift */, 114 | 51DCEFDE2A0BD9AA00561C9B /* ContentView.swift */, 115 | 51DCEFEC2A0BD9F000561C9B /* GameScene.swift */, 116 | 51DCF0942A0C012F00561C9B /* Helpers.swift */, 117 | 51DCF05B2A0BE0DF00561C9B /* ShaderKitExtensions.swift */, 118 | 51DCF0262A0BE05400561C9B /* Shaders */, 119 | 51DCEFE02A0BD9AB00561C9B /* Assets.xcassets */, 120 | 51DCEFE22A0BD9AB00561C9B /* ShaderKit.entitlements */, 121 | 51DCEFE32A0BD9AB00561C9B /* Preview Content */, 122 | ); 123 | path = ShaderKit; 124 | sourceTree = ""; 125 | }; 126 | 51DCEFE32A0BD9AB00561C9B /* Preview Content */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 51DCEFE42A0BD9AB00561C9B /* Preview Assets.xcassets */, 130 | ); 131 | path = "Preview Content"; 132 | sourceTree = ""; 133 | }; 134 | 51DCF0262A0BE05400561C9B /* Shaders */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 51DCF0272A0BE05400561C9B /* SHKCircleWaveRainbowBlended.fsh */, 138 | 51DCF0282A0BE05400561C9B /* SHKInfrared.fsh */, 139 | 51DCF0292A0BE05400561C9B /* SHKWater.fsh */, 140 | 51DCF02A2A0BE05400561C9B /* SHKStaticGrayNoise.fsh */, 141 | 51DCF02B2A0BE05400561C9B /* SHKCircleWave.fsh */, 142 | 51DCF02C2A0BE05400561C9B /* SHKColorInvert.fsh */, 143 | 51DCF02D2A0BE05400561C9B /* SHKEmbossColor.fsh */, 144 | 51DCF02E2A0BE05400561C9B /* SHKRadialGradient.fsh */, 145 | 51DCF02F2A0BE05400561C9B /* SHKLightGrid.fsh */, 146 | 51DCF0302A0BE05400561C9B /* SHKLinearGradient.fsh */, 147 | 51DCF0312A0BE05400561C9B /* SHKColorAlpha.fsh */, 148 | 51DCF0322A0BE05400561C9B /* SHKCircleWaveBlended.fsh */, 149 | 51DCF0332A0BE05400561C9B /* SHKEmbossGray.fsh */, 150 | 51DCF0342A0BE05400561C9B /* SHKInterlace.fsh */, 151 | 51DCF0352A0BE05400561C9B /* SHKPixelate.fsh */, 152 | 51DCF0362A0BE05400561C9B /* SHKStaticRainbowNoise.fsh */, 153 | 51DCF0372A0BE05400561C9B /* SHKColorize.fsh */, 154 | 51DCF0382A0BE05400561C9B /* SHKPassthrough.fsh */, 155 | 51DCF0392A0BE05400561C9B /* SHKDynamicGrayNoise.fsh */, 156 | 51DCF03A2A0BE05400561C9B /* SHKCircleWaveRainbow.fsh */, 157 | 51DCF03B2A0BE05400561C9B /* SHKScreen.fsh */, 158 | 51DCF03C2A0BE05400561C9B /* SHKDynamicRainbowNoise.fsh */, 159 | 51DCF03D2A0BE05400561C9B /* SHKDesaturate.fsh */, 160 | 51DCF03E2A0BE05400561C9B /* SHKColorNonAlpha.fsh */, 161 | 51DCF03F2A0BE05400561C9B /* SHKScanlines.fsh */, 162 | 51DCF0402A0BE05400561C9B /* SHKCheckerboard.fsh */, 163 | ); 164 | name = Shaders; 165 | path = ../../Shaders; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXGroup section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | 51DCEFD82A0BD9AA00561C9B /* ShaderKit */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 51DCEFE82A0BD9AB00561C9B /* Build configuration list for PBXNativeTarget "ShaderKit" */; 174 | buildPhases = ( 175 | 51DCEFD52A0BD9AA00561C9B /* Sources */, 176 | 51DCEFD62A0BD9AA00561C9B /* Frameworks */, 177 | 51DCEFD72A0BD9AA00561C9B /* Resources */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | ); 183 | name = ShaderKit; 184 | productName = ShaderKit; 185 | productReference = 51DCEFD92A0BD9AA00561C9B /* ShaderKit.app */; 186 | productType = "com.apple.product-type.application"; 187 | }; 188 | /* End PBXNativeTarget section */ 189 | 190 | /* Begin PBXProject section */ 191 | 51DCEFD12A0BD9AA00561C9B /* Project object */ = { 192 | isa = PBXProject; 193 | attributes = { 194 | BuildIndependentTargetsInParallel = 1; 195 | LastSwiftUpdateCheck = 1430; 196 | LastUpgradeCheck = 1430; 197 | TargetAttributes = { 198 | 51DCEFD82A0BD9AA00561C9B = { 199 | CreatedOnToolsVersion = 14.3; 200 | }; 201 | }; 202 | }; 203 | buildConfigurationList = 51DCEFD42A0BD9AA00561C9B /* Build configuration list for PBXProject "ShaderKit" */; 204 | compatibilityVersion = "Xcode 14.0"; 205 | developmentRegion = en; 206 | hasScannedForEncodings = 0; 207 | knownRegions = ( 208 | en, 209 | Base, 210 | ); 211 | mainGroup = 51DCEFD02A0BD9AA00561C9B; 212 | productRefGroup = 51DCEFDA2A0BD9AA00561C9B /* Products */; 213 | projectDirPath = ""; 214 | projectRoot = ""; 215 | targets = ( 216 | 51DCEFD82A0BD9AA00561C9B /* ShaderKit */, 217 | ); 218 | }; 219 | /* End PBXProject section */ 220 | 221 | /* Begin PBXResourcesBuildPhase section */ 222 | 51DCEFD72A0BD9AA00561C9B /* Resources */ = { 223 | isa = PBXResourcesBuildPhase; 224 | buildActionMask = 2147483647; 225 | files = ( 226 | 51DCEFE52A0BD9AB00561C9B /* Preview Assets.xcassets in Resources */, 227 | 51DCF0542A0BE05400561C9B /* SHKCircleWaveRainbow.fsh in Resources */, 228 | 51DCF04B2A0BE05400561C9B /* SHKColorAlpha.fsh in Resources */, 229 | 51DCF04D2A0BE05400561C9B /* SHKEmbossGray.fsh in Resources */, 230 | 51DCF0572A0BE05400561C9B /* SHKDesaturate.fsh in Resources */, 231 | 51DCF0412A0BE05400561C9B /* SHKCircleWaveRainbowBlended.fsh in Resources */, 232 | 51DCF0462A0BE05400561C9B /* SHKColorInvert.fsh in Resources */, 233 | 51DCF0492A0BE05400561C9B /* SHKLightGrid.fsh in Resources */, 234 | 51DCF0472A0BE05400561C9B /* SHKEmbossColor.fsh in Resources */, 235 | 51DCF0422A0BE05400561C9B /* SHKInfrared.fsh in Resources */, 236 | 51DCF0452A0BE05400561C9B /* SHKCircleWave.fsh in Resources */, 237 | 51DCF04C2A0BE05400561C9B /* SHKCircleWaveBlended.fsh in Resources */, 238 | 51DCF04A2A0BE05400561C9B /* SHKLinearGradient.fsh in Resources */, 239 | 51DCF0512A0BE05400561C9B /* SHKColorize.fsh in Resources */, 240 | 51DCF0482A0BE05400561C9B /* SHKRadialGradient.fsh in Resources */, 241 | 51DCF04F2A0BE05400561C9B /* SHKPixelate.fsh in Resources */, 242 | 51DCF0502A0BE05400561C9B /* SHKStaticRainbowNoise.fsh in Resources */, 243 | 51DCF0442A0BE05400561C9B /* SHKStaticGrayNoise.fsh in Resources */, 244 | 51DCF04E2A0BE05400561C9B /* SHKInterlace.fsh in Resources */, 245 | 51DCF0552A0BE05400561C9B /* SHKScreen.fsh in Resources */, 246 | 51DCEFE12A0BD9AB00561C9B /* Assets.xcassets in Resources */, 247 | 51DCF0532A0BE05400561C9B /* SHKDynamicGrayNoise.fsh in Resources */, 248 | 51DCF0432A0BE05400561C9B /* SHKWater.fsh in Resources */, 249 | 51DCF0562A0BE05400561C9B /* SHKDynamicRainbowNoise.fsh in Resources */, 250 | 51DCF0522A0BE05400561C9B /* SHKPassthrough.fsh in Resources */, 251 | 51DCF0592A0BE05400561C9B /* SHKScanlines.fsh in Resources */, 252 | 51DCF0582A0BE05400561C9B /* SHKColorNonAlpha.fsh in Resources */, 253 | 51DCF05A2A0BE05400561C9B /* SHKCheckerboard.fsh in Resources */, 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | /* End PBXResourcesBuildPhase section */ 258 | 259 | /* Begin PBXSourcesBuildPhase section */ 260 | 51DCEFD52A0BD9AA00561C9B /* Sources */ = { 261 | isa = PBXSourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | 51DCEFED2A0BD9F000561C9B /* GameScene.swift in Sources */, 265 | 51DCEFDF2A0BD9AA00561C9B /* ContentView.swift in Sources */, 266 | 51DCF0952A0C012F00561C9B /* Helpers.swift in Sources */, 267 | 51DCEFDD2A0BD9AA00561C9B /* ShaderKitApp.swift in Sources */, 268 | 51DCF05C2A0BE0DF00561C9B /* ShaderKitExtensions.swift in Sources */, 269 | ); 270 | runOnlyForDeploymentPostprocessing = 0; 271 | }; 272 | /* End PBXSourcesBuildPhase section */ 273 | 274 | /* Begin XCBuildConfiguration section */ 275 | 51DCEFE62A0BD9AB00561C9B /* Debug */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ALWAYS_SEARCH_USER_PATHS = NO; 279 | CLANG_ANALYZER_NONNULL = YES; 280 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 281 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 282 | CLANG_ENABLE_MODULES = YES; 283 | CLANG_ENABLE_OBJC_ARC = YES; 284 | CLANG_ENABLE_OBJC_WEAK = YES; 285 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 286 | CLANG_WARN_BOOL_CONVERSION = YES; 287 | CLANG_WARN_COMMA = YES; 288 | CLANG_WARN_CONSTANT_CONVERSION = YES; 289 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 290 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 291 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 292 | CLANG_WARN_EMPTY_BODY = YES; 293 | CLANG_WARN_ENUM_CONVERSION = YES; 294 | CLANG_WARN_INFINITE_RECURSION = YES; 295 | CLANG_WARN_INT_CONVERSION = YES; 296 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 297 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 298 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 299 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 300 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 301 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 302 | CLANG_WARN_STRICT_PROTOTYPES = YES; 303 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 304 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 305 | CLANG_WARN_UNREACHABLE_CODE = YES; 306 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 307 | COPY_PHASE_STRIP = NO; 308 | DEBUG_INFORMATION_FORMAT = dwarf; 309 | ENABLE_STRICT_OBJC_MSGSEND = YES; 310 | ENABLE_TESTABILITY = YES; 311 | GCC_C_LANGUAGE_STANDARD = gnu11; 312 | GCC_DYNAMIC_NO_PIC = NO; 313 | GCC_NO_COMMON_BLOCKS = YES; 314 | GCC_OPTIMIZATION_LEVEL = 0; 315 | GCC_PREPROCESSOR_DEFINITIONS = ( 316 | "DEBUG=1", 317 | "$(inherited)", 318 | ); 319 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 320 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 321 | GCC_WARN_UNDECLARED_SELECTOR = YES; 322 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 323 | GCC_WARN_UNUSED_FUNCTION = YES; 324 | GCC_WARN_UNUSED_VARIABLE = YES; 325 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 326 | MTL_FAST_MATH = YES; 327 | ONLY_ACTIVE_ARCH = YES; 328 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 329 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 330 | }; 331 | name = Debug; 332 | }; 333 | 51DCEFE72A0BD9AB00561C9B /* Release */ = { 334 | isa = XCBuildConfiguration; 335 | buildSettings = { 336 | ALWAYS_SEARCH_USER_PATHS = NO; 337 | CLANG_ANALYZER_NONNULL = YES; 338 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 339 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 340 | CLANG_ENABLE_MODULES = YES; 341 | CLANG_ENABLE_OBJC_ARC = YES; 342 | CLANG_ENABLE_OBJC_WEAK = YES; 343 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 344 | CLANG_WARN_BOOL_CONVERSION = YES; 345 | CLANG_WARN_COMMA = YES; 346 | CLANG_WARN_CONSTANT_CONVERSION = YES; 347 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 348 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 349 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 350 | CLANG_WARN_EMPTY_BODY = YES; 351 | CLANG_WARN_ENUM_CONVERSION = YES; 352 | CLANG_WARN_INFINITE_RECURSION = YES; 353 | CLANG_WARN_INT_CONVERSION = YES; 354 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 355 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 356 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 357 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 358 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 359 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 360 | CLANG_WARN_STRICT_PROTOTYPES = YES; 361 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 362 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 363 | CLANG_WARN_UNREACHABLE_CODE = YES; 364 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 365 | COPY_PHASE_STRIP = NO; 366 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 367 | ENABLE_NS_ASSERTIONS = NO; 368 | ENABLE_STRICT_OBJC_MSGSEND = YES; 369 | GCC_C_LANGUAGE_STANDARD = gnu11; 370 | GCC_NO_COMMON_BLOCKS = YES; 371 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 372 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 373 | GCC_WARN_UNDECLARED_SELECTOR = YES; 374 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 375 | GCC_WARN_UNUSED_FUNCTION = YES; 376 | GCC_WARN_UNUSED_VARIABLE = YES; 377 | MTL_ENABLE_DEBUG_INFO = NO; 378 | MTL_FAST_MATH = YES; 379 | SWIFT_COMPILATION_MODE = wholemodule; 380 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 381 | }; 382 | name = Release; 383 | }; 384 | 51DCEFE92A0BD9AB00561C9B /* Debug */ = { 385 | isa = XCBuildConfiguration; 386 | buildSettings = { 387 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 388 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 389 | CODE_SIGN_ENTITLEMENTS = ShaderKit/ShaderKit.entitlements; 390 | CODE_SIGN_STYLE = Automatic; 391 | CURRENT_PROJECT_VERSION = 1; 392 | DEVELOPMENT_ASSET_PATHS = "\"ShaderKit/Preview Content\""; 393 | DEVELOPMENT_TEAM = B5C26XE59E; 394 | ENABLE_HARDENED_RUNTIME = YES; 395 | ENABLE_PREVIEWS = YES; 396 | GENERATE_INFOPLIST_FILE = YES; 397 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; 398 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; 399 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; 400 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; 401 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; 402 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; 403 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; 404 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; 405 | INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 406 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; 407 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 408 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; 409 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; 410 | MACOSX_DEPLOYMENT_TARGET = 13.0; 411 | MARKETING_VERSION = 1.0; 412 | PRODUCT_BUNDLE_IDENTIFIER = com.hackingwithswift.ShaderKit; 413 | PRODUCT_NAME = "$(TARGET_NAME)"; 414 | SDKROOT = auto; 415 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 416 | SWIFT_EMIT_LOC_STRINGS = YES; 417 | SWIFT_VERSION = 5.0; 418 | TARGETED_DEVICE_FAMILY = "1,2"; 419 | }; 420 | name = Debug; 421 | }; 422 | 51DCEFEA2A0BD9AB00561C9B /* Release */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 426 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 427 | CODE_SIGN_ENTITLEMENTS = ShaderKit/ShaderKit.entitlements; 428 | CODE_SIGN_STYLE = Automatic; 429 | CURRENT_PROJECT_VERSION = 1; 430 | DEVELOPMENT_ASSET_PATHS = "\"ShaderKit/Preview Content\""; 431 | DEVELOPMENT_TEAM = B5C26XE59E; 432 | ENABLE_HARDENED_RUNTIME = YES; 433 | ENABLE_PREVIEWS = YES; 434 | GENERATE_INFOPLIST_FILE = YES; 435 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; 436 | "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; 437 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; 438 | "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; 439 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; 440 | "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; 441 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; 442 | "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; 443 | INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 444 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; 445 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 446 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; 447 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; 448 | MACOSX_DEPLOYMENT_TARGET = 13.0; 449 | MARKETING_VERSION = 1.0; 450 | PRODUCT_BUNDLE_IDENTIFIER = com.hackingwithswift.ShaderKit; 451 | PRODUCT_NAME = "$(TARGET_NAME)"; 452 | SDKROOT = auto; 453 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 454 | SWIFT_EMIT_LOC_STRINGS = YES; 455 | SWIFT_VERSION = 5.0; 456 | TARGETED_DEVICE_FAMILY = "1,2"; 457 | }; 458 | name = Release; 459 | }; 460 | /* End XCBuildConfiguration section */ 461 | 462 | /* Begin XCConfigurationList section */ 463 | 51DCEFD42A0BD9AA00561C9B /* Build configuration list for PBXProject "ShaderKit" */ = { 464 | isa = XCConfigurationList; 465 | buildConfigurations = ( 466 | 51DCEFE62A0BD9AB00561C9B /* Debug */, 467 | 51DCEFE72A0BD9AB00561C9B /* Release */, 468 | ); 469 | defaultConfigurationIsVisible = 0; 470 | defaultConfigurationName = Release; 471 | }; 472 | 51DCEFE82A0BD9AB00561C9B /* Build configuration list for PBXNativeTarget "ShaderKit" */ = { 473 | isa = XCConfigurationList; 474 | buildConfigurations = ( 475 | 51DCEFE92A0BD9AB00561C9B /* Debug */, 476 | 51DCEFEA2A0BD9AB00561C9B /* Release */, 477 | ); 478 | defaultConfigurationIsVisible = 0; 479 | defaultConfigurationName = Release; 480 | }; 481 | /* End XCConfigurationList section */ 482 | }; 483 | rootObject = 51DCEFD12A0BD9AA00561C9B /* Project object */; 484 | } 485 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | }, 9 | { 10 | "filename" : "Icon-16.png", 11 | "idiom" : "mac", 12 | "scale" : "1x", 13 | "size" : "16x16" 14 | }, 15 | { 16 | "filename" : "Icon-16@2x.png", 17 | "idiom" : "mac", 18 | "scale" : "2x", 19 | "size" : "16x16" 20 | }, 21 | { 22 | "filename" : "Icon-32.png", 23 | "idiom" : "mac", 24 | "scale" : "1x", 25 | "size" : "32x32" 26 | }, 27 | { 28 | "filename" : "Icon-32@2x.png", 29 | "idiom" : "mac", 30 | "scale" : "2x", 31 | "size" : "32x32" 32 | }, 33 | { 34 | "filename" : "Icon-128.png", 35 | "idiom" : "mac", 36 | "scale" : "1x", 37 | "size" : "128x128" 38 | }, 39 | { 40 | "filename" : "Icon-128@2x.png", 41 | "idiom" : "mac", 42 | "scale" : "2x", 43 | "size" : "128x128" 44 | }, 45 | { 46 | "filename" : "Icon-256.png", 47 | "idiom" : "mac", 48 | "scale" : "1x", 49 | "size" : "256x256" 50 | }, 51 | { 52 | "filename" : "Icon-256@2x.png", 53 | "idiom" : "mac", 54 | "scale" : "2x", 55 | "size" : "256x256" 56 | }, 57 | { 58 | "filename" : "Icon-512.png", 59 | "idiom" : "mac", 60 | "scale" : "1x", 61 | "size" : "512x512" 62 | }, 63 | { 64 | "filename" : "Icon-512@2x.png", 65 | "idiom" : "mac", 66 | "scale" : "2x", 67 | "size" : "512x512" 68 | } 69 | ], 70 | "info" : { 71 | "author" : "xcode", 72 | "version" : 1 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-1024.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-128.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-128@2x.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-16.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-16@2x.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-256.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-256@2x.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-32.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-32@2x.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-512.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/AppIcon.appiconset/Icon-512@2x.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/Background.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.250", 9 | "green" : "0.250", 10 | "red" : "0.250" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/city.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "city.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "city@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "city@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/city.imageset/city.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/city.imageset/city.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/city.imageset/city@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/city.imageset/city@2x.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/city.imageset/city@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/city.imageset/city@3x.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/swift.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "swift@1x.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "swift@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "swift@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/swift.imageset/swift@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/swift.imageset/swift@1x.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/swift.imageset/swift@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/swift.imageset/swift@2x.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Assets.xcassets/swift.imageset/swift@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twostraws/ShaderKit/07c974dc0cb48a935e0f131e12c0453e6082fa68/Sandbox/ShaderKit/Assets.xcassets/swift.imageset/swift@3x.png -------------------------------------------------------------------------------- /Sandbox/ShaderKit/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ShaderKit 4 | // 5 | // Created by Paul Hudson on 10/05/2023. 6 | // 7 | 8 | import SpriteKit 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | @State private var scene: GameScene = { 13 | let newScene = GameScene() 14 | newScene.size = CGSize(width: 1024, height: 768) 15 | newScene.anchorPoint = CGPoint(x: 0.5, y: 0.5) 16 | newScene.scaleMode = .resizeFill 17 | return newScene 18 | }() 19 | 20 | @ToolbarContentBuilder var platformToolbar: some ToolbarContent { 21 | ToolbarItem(placement: .platformOptimizedLeading) { 22 | Button(action: scene.previousShader) { 23 | Label("Previous Shader", systemImage: "chevron.backward") 24 | .labelStyle(.imageOnLeft) 25 | } 26 | } 27 | 28 | ToolbarItem(placement: .platformOptimizedTrailing) { 29 | Button(action: scene.nextShader) { 30 | Label("Next Shader", systemImage: "chevron.forward") 31 | .labelStyle(.imageOnRight) 32 | } 33 | } 34 | } 35 | 36 | var body: some View { 37 | NavigationStack { 38 | SpriteView(scene: scene, preferredFramesPerSecond: 120, debugOptions: [.showsFPS, .showsNodeCount]) 39 | .navigationTitle("ShaderKit Sandbox") 40 | .frame(minWidth: 550, minHeight: 350) 41 | .background(Color("Background")) 42 | .toolbar { platformToolbar } 43 | .tint(.white) 44 | #if os(iOS) 45 | // Force dark appearance so the light nav title always stands 46 | // out against the dark background 47 | .preferredColorScheme(.dark) 48 | #endif 49 | } 50 | } 51 | } 52 | 53 | struct ContentView_Previews: PreviewProvider { 54 | static var previews: some View { 55 | ContentView() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/GameScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MIT License 3 | // 4 | // Copyright (c) 2017 Paul Hudson 5 | // https://www.github.com/twostraws/ShaderKit 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | 26 | import GameplayKit 27 | import SpriteKit 28 | 29 | class GameScene: SKScene { 30 | typealias ShaderExample = (title: String, shader: SKShader) 31 | var shaders = [ShaderExample]() 32 | var currentShader = 0 33 | 34 | let title = SKLabelNode(fontNamed: "HelveticaNeue") 35 | let tapToToggleAlpha = SKLabelNode(fontNamed: "HelveticaNeue") 36 | let testNode1 = SKSpriteNode(imageNamed: "swift") 37 | let testNode2 = SKSpriteNode(imageNamed: "city") 38 | 39 | var nodesVisible = true 40 | 41 | override func didMove(to view: SKView) { 42 | backgroundColor = SKColor(named: "Background")! 43 | 44 | title.position.y = 120 45 | title.text = "Shader Name Here" 46 | addChild(title) 47 | 48 | tapToToggleAlpha.fontSize = 18 49 | tapToToggleAlpha.position.y = 90 50 | tapToToggleAlpha.text = "Tap to toggle alpha" 51 | addChild(tapToToggleAlpha) 52 | 53 | testNode1.position = CGPoint(x: -150, y: -30) 54 | addChild(testNode1) 55 | 56 | testNode2.position = CGPoint(x: 150, y: -30) 57 | addChild(testNode2) 58 | shaders.append(("No Shader", createPassthrough())) 59 | shaders.append(("Checkerboard", createCheckerboard())) 60 | shaders.append(("Circle Wave", createCircleWave())) 61 | shaders.append(("Circle Wave (Blended)", createCircleWaveBlended())) 62 | shaders.append(("Circle Wave Rainbow", createCircleWaveRainbow())) 63 | shaders.append(("Circle Wave Rainbow (Blended)", createCircleWaveRainbowBlended())) 64 | shaders.append(("Color Alpha", createColorAlpha())) 65 | shaders.append(("Color Non-Alpha", createColorNonAlpha())) 66 | shaders.append(("Color Invert", createColorInvert())) 67 | shaders.append(("Colorize", createColorize())) 68 | shaders.append(("Desaturate", createDesaturate())) 69 | shaders.append(("Emboss (Color)", createColorEmboss())) 70 | shaders.append(("Emboss (Gray)", createGrayEmboss())) 71 | shaders.append(("Infrared", createInfrared())) 72 | shaders.append(("Interlace", createInterlace())) 73 | shaders.append(("Light Grid", createLightGrid())) 74 | shaders.append(("Linear Gradient", createLinearGradient())) 75 | shaders.append(("Pixelate", createPixelate())) 76 | shaders.append(("Scanlines", createScanlines())) 77 | shaders.append(("Static Gray Noise", createStaticGrayNoise())) 78 | shaders.append(("Static Rainbow Noise", createStaticRainbowNoise())) 79 | shaders.append(("Dynamic Gray Noise", createDynamicGrayNoise())) 80 | shaders.append(("Dynamic Rainbow Noise", createDynamicRainbowNoise())) 81 | shaders.append(("Radial Gradient", createRadialGradient())) 82 | shaders.append(("Screen", createScreen())) 83 | shaders.append(("Water", createWater())) 84 | loadShader() 85 | 86 | testNode1.setValue(SKAttributeValue(size: testNode1.size), forAttribute: "a_size") 87 | testNode2.setValue(SKAttributeValue(size: testNode2.size), forAttribute: "a_size") 88 | } 89 | 90 | func loadShader() { 91 | let example = shaders[currentShader] 92 | title.text = example.title 93 | 94 | testNode1.shader = example.shader 95 | testNode2.shader = example.shader 96 | } 97 | 98 | func createCheckerboard() -> SKShader { 99 | let uniforms: [SKUniform] = [ 100 | SKUniform(name: "u_rows", float: 12), 101 | SKUniform(name: "u_cols", float: 12), 102 | SKUniform(name: "u_first_color", color: .white), 103 | SKUniform(name: "u_second_color", color: .black) 104 | ] 105 | 106 | return SKShader(fromFile: "SHKCheckerboard", uniforms: uniforms) 107 | } 108 | 109 | func createCircleWave() -> SKShader { 110 | let uniforms: [SKUniform] = [ 111 | SKUniform(name: "u_speed", float: 1), 112 | SKUniform(name: "u_brightness", float: 0.5), 113 | SKUniform(name: "u_strength", float: 2), 114 | SKUniform(name: "u_density", float: 100), 115 | SKUniform(name: "u_center", point: CGPoint(x: 0.68, y: 0.33)), 116 | SKUniform(name: "u_color", color: SKColor(red: 0, green: 0.5, blue: 0, alpha: 1)) 117 | ] 118 | 119 | return SKShader(fromFile: "SHKCircleWave", uniforms: uniforms) 120 | } 121 | 122 | func createCircleWaveBlended() -> SKShader { 123 | let uniforms: [SKUniform] = [ 124 | SKUniform(name: "u_speed", float: 1), 125 | SKUniform(name: "u_brightness", float: 0.5), 126 | SKUniform(name: "u_strength", float: 2), 127 | SKUniform(name: "u_density", float: 100), 128 | SKUniform(name: "u_center", point: CGPoint(x: 0.68, y: 0.33)), 129 | SKUniform(name: "u_color", color: SKColor(red: 0, green: 0.5, blue: 0, alpha: 1)) 130 | ] 131 | 132 | return SKShader(fromFile: "SHKCircleWaveBlended", uniforms: uniforms) 133 | } 134 | 135 | func createCircleWaveRainbow() -> SKShader { 136 | let uniforms: [SKUniform] = [ 137 | SKUniform(name: "u_speed", float: 1), 138 | SKUniform(name: "u_brightness", float: 0.5), 139 | SKUniform(name: "u_strength", float: 2), 140 | SKUniform(name: "u_density", float: 100), 141 | SKUniform(name: "u_center", point: CGPoint(x: 0.68, y: 0.33)), 142 | SKUniform(name: "u_red", float: -1) 143 | ] 144 | 145 | return SKShader(fromFile: "SHKCircleWaveRainbow", uniforms: uniforms) 146 | } 147 | 148 | func createCircleWaveRainbowBlended() -> SKShader { 149 | let uniforms: [SKUniform] = [ 150 | SKUniform(name: "u_speed", float: 1), 151 | SKUniform(name: "u_brightness", float: 0.5), 152 | SKUniform(name: "u_strength", float: 2), 153 | SKUniform(name: "u_density", float: 100), 154 | SKUniform(name: "u_center", point: CGPoint(x: 0.68, y: 0.33)), 155 | SKUniform(name: "u_red", float: -1) 156 | ] 157 | 158 | return SKShader(fromFile: "SHKCircleWaveRainbowBlended", uniforms: uniforms) 159 | } 160 | 161 | func createColorAlpha() -> SKShader { 162 | let uniforms: [SKUniform] = [ 163 | SKUniform(name: "u_color", color: .green) 164 | ] 165 | 166 | return SKShader(fromFile: "SHKColorAlpha", uniforms: uniforms) 167 | } 168 | 169 | func createColorEmboss() -> SKShader { 170 | let uniforms: [SKUniform] = [ 171 | SKUniform(name: "u_strength", float: 1) 172 | ] 173 | 174 | let attributes = [ 175 | SKAttribute(name: "a_size", type: .vectorFloat2) 176 | ] 177 | 178 | return SKShader(fromFile: "SHKEmbossColor", uniforms: uniforms, attributes: attributes) 179 | } 180 | 181 | func createColorInvert() -> SKShader { 182 | return SKShader(fromFile: "SHKColorInvert") 183 | } 184 | 185 | func createColorNonAlpha() -> SKShader { 186 | let uniforms: [SKUniform] = [ 187 | SKUniform(name: "u_color", color: .yellow) 188 | ] 189 | 190 | return SKShader(fromFile: "SHKColorNonAlpha", uniforms: uniforms) 191 | } 192 | 193 | func createColorize() -> SKShader { 194 | let uniforms: [SKUniform] = [ 195 | SKUniform(name: "u_color", color: .green), 196 | SKUniform(name: "u_strength", float: 1) 197 | ] 198 | 199 | return SKShader(fromFile: "SHKColorize", uniforms: uniforms) 200 | } 201 | 202 | func createDesaturate() -> SKShader { 203 | let uniforms: [SKUniform] = [ 204 | SKUniform(name: "u_strength", float: 0.5) 205 | ] 206 | 207 | return SKShader(fromFile: "SHKDesaturate", uniforms: uniforms) 208 | } 209 | 210 | func createDynamicGrayNoise() -> SKShader { 211 | return SKShader(fromFile: "SHKDynamicGrayNoise") 212 | } 213 | 214 | func createDynamicRainbowNoise() -> SKShader { 215 | return SKShader(fromFile: "SHKDynamicRainbowNoise") 216 | } 217 | 218 | func createGrayEmboss() -> SKShader { 219 | let uniforms: [SKUniform] = [ 220 | SKUniform(name: "u_strength", float: 1) 221 | ] 222 | 223 | let attributes = [ 224 | SKAttribute(name: "a_size", type: .vectorFloat2) 225 | ] 226 | 227 | return SKShader(fromFile: "SHKEmbossGray", uniforms: uniforms, attributes: attributes) 228 | } 229 | 230 | func createInfrared() -> SKShader { 231 | return SKShader(fromFile: "SHKInfrared") 232 | } 233 | 234 | func createInterlace() -> SKShader { 235 | let uniforms: [SKUniform] = [ 236 | SKUniform(name: "u_width", float: 2), 237 | SKUniform(name: "u_color", color: .black), 238 | SKUniform(name: "u_strength", float: 0.35), 239 | ] 240 | 241 | let attributes = [ 242 | SKAttribute(name: "a_size", type: .vectorFloat2) 243 | ] 244 | 245 | return SKShader(fromFile: "SHKInterlace", uniforms: uniforms, attributes: attributes) 246 | } 247 | 248 | func createLightGrid() -> SKShader { 249 | let uniforms: [SKUniform] = [ 250 | SKUniform(name: "u_density", float: 8), 251 | SKUniform(name: "u_speed", float: 3), 252 | SKUniform(name: "u_group_size", float: 2), 253 | SKUniform(name: "u_brightness", float: 3), 254 | ] 255 | 256 | return SKShader(fromFile: "SHKLightGrid", uniforms: uniforms) 257 | } 258 | 259 | func createLinearGradient() -> SKShader { 260 | let uniforms: [SKUniform] = [ 261 | SKUniform(name: "u_first_color", color: .blue), 262 | SKUniform(name: "u_second_color", color: .clear) 263 | ] 264 | 265 | return SKShader(fromFile: "SHKLinearGradient", uniforms: uniforms) 266 | } 267 | 268 | func createPassthrough() -> SKShader { 269 | return SKShader(fromFile: "SHKPassthrough") 270 | } 271 | 272 | func createPixelate() -> SKShader { 273 | let uniforms: [SKUniform] = [ 274 | SKUniform(name: "u_strength", float: 8), 275 | ] 276 | 277 | let attributes = [ 278 | SKAttribute(name: "a_size", type: .vectorFloat2) 279 | ] 280 | 281 | return SKShader(fromFile: "SHKPixelate", uniforms: uniforms, attributes: attributes) 282 | } 283 | 284 | func createRadialGradient() -> SKShader { 285 | let uniforms: [SKUniform] = [ 286 | SKUniform(name: "u_first_color", color: .clear), 287 | SKUniform(name: "u_second_color", color: .darkGray), 288 | SKUniform(name: "u_center", point: CGPoint(x: 0.75, y: 0.25)) 289 | ] 290 | 291 | return SKShader(fromFile: "SHKRadialGradient", uniforms: uniforms) 292 | } 293 | 294 | func createScanlines() -> SKShader { 295 | let uniforms: [SKUniform] = [ 296 | SKUniform(name: "u_width", float: 4.0), 297 | SKUniform(name: "u_brightness", float: 0.75), 298 | SKUniform(name: "u_color", color: .white), 299 | ] 300 | 301 | let attributes = [ 302 | SKAttribute(name: "a_size", type: .vectorFloat2) 303 | ] 304 | 305 | return SKShader(fromFile: "SHKScanlines", uniforms: uniforms, attributes: attributes) 306 | } 307 | 308 | func createScreen() -> SKShader { 309 | let uniforms: [SKUniform] = [ 310 | SKUniform(name: "u_width", float: 2), 311 | SKUniform(name: "u_color", color: .clear), 312 | SKUniform(name: "u_strength", float: 1), 313 | ] 314 | 315 | let attributes = [ 316 | SKAttribute(name: "a_size", type: .vectorFloat2) 317 | ] 318 | 319 | return SKShader(fromFile: "SHKScreen", uniforms: uniforms, attributes: attributes) 320 | } 321 | 322 | func createStaticGrayNoise() -> SKShader { 323 | return SKShader(fromFile: "SHKStaticGrayNoise") 324 | } 325 | 326 | func createStaticRainbowNoise() -> SKShader { 327 | return SKShader(fromFile: "SHKStaticRainbowNoise") 328 | } 329 | 330 | func createWater() -> SKShader { 331 | let uniforms: [SKUniform] = [ 332 | SKUniform(name: "u_speed", float: 3), 333 | SKUniform(name: "u_strength", float: 2.5), 334 | SKUniform(name: "u_frequency", float: 10) 335 | ] 336 | 337 | return SKShader(fromFile: "SHKWater", uniforms: uniforms) 338 | } 339 | 340 | func previousShader() { 341 | currentShader -= 1 342 | 343 | if currentShader == -1 { 344 | currentShader = shaders.count - 1 345 | } 346 | 347 | loadShader() 348 | } 349 | 350 | func nextShader() { 351 | currentShader += 1 352 | 353 | if currentShader == shaders.count { 354 | currentShader = 0 355 | } 356 | 357 | loadShader() 358 | } 359 | 360 | func toggleAlpha() { 361 | let action: SKAction 362 | nodesVisible.toggle() 363 | 364 | if nodesVisible { 365 | action = SKAction.fadeIn(withDuration: 2) 366 | } else { 367 | action = SKAction.fadeOut(withDuration: 2) 368 | } 369 | 370 | testNode1.removeAllActions() 371 | testNode2.removeAllActions() 372 | 373 | testNode1.run(action) 374 | testNode2.run(action) 375 | } 376 | 377 | #if os(iOS) 378 | override func touchesBegan(_ touches: Set, with event: UIEvent?) { 379 | toggleAlpha() 380 | } 381 | #endif 382 | 383 | #if os(macOS) 384 | override func mouseDown(with event: NSEvent) { 385 | toggleAlpha() 386 | } 387 | #endif 388 | } 389 | 390 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Helpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Helpers.swift 3 | // ShaderKit 4 | // 5 | // Created by Paul Hudson on 10/05/2023. 6 | // 7 | // Note: This file contains helper code specifically for this 8 | // sample project, and is *not* needed to use ShaderKit in 9 | // your own projects. 10 | // 11 | 12 | import SwiftUI 13 | 14 | extension ToolbarItemPlacement { 15 | #if os(iOS) 16 | // Forcing leading and trailing looks great on iOS… 17 | static var platformOptimizedLeading = Self.navigationBarLeading 18 | static var platformOptimizedTrailing = Self.navigationBarTrailing 19 | #else 20 | // …but automatic placement looks much better on macOS. 21 | static var platformOptimizedLeading = Self.automatic 22 | static var platformOptimizedTrailing = Self.automatic 23 | #endif 24 | } 25 | 26 | struct FlippableLabelStyle: LabelStyle { 27 | var iconOnRight: Bool = false 28 | 29 | func makeBody(configuration: Configuration) -> some View { 30 | HStack { 31 | if iconOnRight { 32 | configuration.title 33 | configuration.icon 34 | } else { 35 | configuration.icon 36 | configuration.title 37 | } 38 | } 39 | } 40 | } 41 | 42 | extension LabelStyle where Self == FlippableLabelStyle { 43 | static var imageOnLeft: FlippableLabelStyle { .init(iconOnRight: false) } 44 | static var imageOnRight: FlippableLabelStyle { .init(iconOnRight: true) } 45 | } 46 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/ShaderKit.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Sandbox/ShaderKit/ShaderKitApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShaderKitApp.swift 3 | // ShaderKit 4 | // 5 | // Created by Paul Hudson on 10/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ShaderKitApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ShaderKitExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MIT License 3 | // 4 | // Copyright (c) 2019 Paul Hudson 5 | // https://www.github.com/twostraws/ShaderKit 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | 26 | import Foundation 27 | import SpriteKit 28 | 29 | extension SKAttributeValue { 30 | 31 | /** 32 | Convenience initializer to create an attribute value from a CGSize. 33 | - Parameter size: The input size; this is usually your node's size. 34 | */ 35 | public convenience init(size: CGSize) { 36 | let size = vector_float2(Float(size.width), Float(size.height)) 37 | self.init(vectorFloat2: size) 38 | } 39 | } 40 | 41 | extension SKShader { 42 | /** 43 | Convience initializer to create a shader from a filename by way of a string. 44 | Although this approach is less efficient than loading directly from disk, it enables 45 | shader errors to be printed in the Xcode console. 46 | 47 | - Parameter filename: A filename in your bundle, including extension. 48 | - Parameter uniforms: An array of SKUniforms to apply to the shader. Defaults to nil. 49 | - Parameter attributes: An array of SKAttributes to apply to the shader. Defaults to nil. 50 | */ 51 | convenience init(fromFile filename: String, uniforms: [SKUniform]? = nil, attributes: [SKAttribute]? = nil) { 52 | // it is a fatal error to attempt to load a missing or corrupted shader 53 | guard let path = Bundle.main.path(forResource: filename, ofType: "fsh") else { 54 | fatalError("Unable to find shader \(filename).fsh in bundle") 55 | } 56 | 57 | guard let source = try? String(contentsOfFile: path) else { 58 | fatalError("Unable to load shader \(filename).fsh") 59 | } 60 | 61 | // if we were sent any uniforms then apply them immediately 62 | if let uniforms = uniforms { 63 | self.init(source: source as String, uniforms: uniforms) 64 | } else { 65 | self.init(source: source as String) 66 | } 67 | 68 | // if we were sent any attributes then apply those too 69 | if let attributes = attributes { 70 | self.attributes = attributes 71 | } 72 | } 73 | } 74 | 75 | extension SKUniform { 76 | /** 77 | Convenience initializer to create an SKUniform from an SKColor. 78 | - Parameter name: The name of the uniform inside the shader, e.g. u_color. 79 | - Parameter color: The SKColor to set. 80 | */ 81 | public convenience init(name: String, color: SKColor) { 82 | #if os(macOS) 83 | guard let converted = color.usingColorSpace(.deviceRGB) else { 84 | fatalError("Attempted to use a color that is not expressible in RGB.") 85 | } 86 | 87 | let colors = vector_float4([Float(converted.redComponent), Float(converted.greenComponent), Float(converted.blueComponent), Float(converted.alphaComponent)]) 88 | #else 89 | var r: CGFloat = 0 90 | var g: CGFloat = 0 91 | var b: CGFloat = 0 92 | var a: CGFloat = 0 93 | 94 | color.getRed(&r, green: &g, blue: &b, alpha: &a) 95 | let colors = vector_float4([Float(r), Float(g), Float(b), Float(a)]) 96 | #endif 97 | 98 | self.init(name: name, vectorFloat4: colors) 99 | } 100 | 101 | /** 102 | Convenience initializer to create an SKUniform from a CGSize. 103 | - Parameter name: The name of the uniform inside the shader, e.g. u_size. 104 | - Parameter color: The CGSize to set. 105 | */ 106 | public convenience init(name: String, size: CGSize) { 107 | let size = vector_float2(Float(size.width), Float(size.height)) 108 | self.init(name: name, vectorFloat2: size) 109 | } 110 | 111 | /** 112 | Convenience initializer to create an SKUniform from a CGPoint. 113 | - Parameter name: The name of the uniform inside the shader, e.g. u_center. 114 | - Parameter color: The CGPoint to set. 115 | */ 116 | public convenience init(name: String, point: CGPoint) { 117 | let point = vector_float2(Float(point.x), Float(point.y)) 118 | self.init(name: name, vectorFloat2: point) 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Shaders/SHKCheckerboard.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Renders a checkerboard with user-defined row/column count and colors 3 | // Uniform: u_rows, how many rows to generate. Should be at least 1. 4 | // Uniform: u_cols, how many columns to generate. Should be at least 1. 5 | // Uniform: u_first_color, an SKColor to use for half of the squares. 6 | // Uniform: u_second_color, an SKColor to use for the other half of the squares. 7 | // 8 | // This works using modulus to calculate whether each pixel is in an odd or even 9 | // row/column, and if one of those is true (but only one) then we draw the first color, 10 | // otherwise we draw the second. 11 | // 12 | // MIT License 13 | // 14 | // Copyright (c) 2017 Paul Hudson 15 | // https://www.github.com/twostraws/ShaderKit 16 | // 17 | // Permission is hereby granted, free of charge, to any person obtaining a copy 18 | // of this software and associated documentation files (the "Software"), to deal 19 | // in the Software without restriction, including without limitation the rights 20 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 21 | // copies of the Software, and to permit persons to whom the Software is 22 | // furnished to do so, subject to the following conditions: 23 | // 24 | // The above copyright notice and this permission notice shall be included in all 25 | // copies or substantial portions of the Software. 26 | // 27 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 30 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | // SOFTWARE. 34 | // 35 | 36 | void main() { 37 | // find the current pixel color 38 | vec4 current_color = SKDefaultShading(); 39 | 40 | if (current_color.a > 0.0) { 41 | // figure out whether we are an even column 42 | bool x = mod(u_cols * v_tex_coord.x, 2.0) < 1.0; 43 | 44 | // figure out whether we are an even row 45 | bool y = mod(u_rows * v_tex_coord.y, 2.0) < 1.0; 46 | 47 | // iff one of these is true 48 | if ((x == true && y == false) || (x == false && y == true)) { 49 | // use the first color 50 | gl_FragColor = u_first_color * current_color.a * v_color_mix.a; 51 | } else { 52 | // use the second color 53 | gl_FragColor = u_second_color * current_color.a * v_color_mix.a; 54 | } 55 | } else { 56 | // use the current (transparent) color 57 | gl_FragColor = current_color * v_color_mix.a; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Shaders/SHKCircleWave.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Renders a circular pulsating wave effect with a fixed color based on user input, ignoring any current pixel colors 3 | // Uniform: u_speed, how fast the wave should travel. Ranges from -2 to 2 work best, where negative numbers cause waves to come inwards; try starting with 1. 4 | // Uniform: u_brightness, how bright the colors should be. Ranges from 0 to 5 work best; try starting with 0.5 and experiment. 5 | // Uniform: u_strength, how intense the waves should be. Ranges from 0.02 to 5 work best; try starting with 2. 6 | // Uniform: u_density, how large each wave should be. Ranges from 20 to 500 work best; try starting with 100. 7 | // Uniform: u_center, a CGPoint representing the center of the gradient, where 0.5/0.5 is dead center 8 | // Uniform: u_color, the SKColor to use. Use darker colors to create a less intense core. 9 | // 10 | // This works by calculating what a color gradient would look like over the space of the node 11 | // then calculating the pixel's distance from the center of the wave. From there we can calculate 12 | // the brightness of the pixel by taking the cosine the wave density and speed to create a nice and 13 | // smooth effect. 14 | // 15 | // MIT License 16 | // 17 | // Copyright (c) 2017 Paul Hudson 18 | // https://www.github.com/twostraws/ShaderKit 19 | // 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy 21 | // of this software and associated documentation files (the "Software"), to deal 22 | // in the Software without restriction, including without limitation the rights 23 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | // copies of the Software, and to permit persons to whom the Software is 25 | // furnished to do so, subject to the following conditions: 26 | // 27 | // The above copyright notice and this permission notice shall be included in all 28 | // copies or substantial portions of the Software. 29 | // 30 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | // SOFTWARE. 37 | // 38 | 39 | void main() { 40 | // find the current pixel color 41 | vec4 current_color = SKDefaultShading(); 42 | 43 | // if it's not transparent 44 | if (current_color.a > 0.0) { 45 | // calculate how fast to make the waves move; this is negative so the waves move outwards 46 | float wave_speed = -(u_time * u_speed * 10.0); 47 | 48 | // create RGB colors from the provided brightness 49 | vec3 brightness = vec3(u_brightness); 50 | 51 | // how far our pixel is from the center of the circle 52 | float pixel_distance = distance(v_tex_coord, u_center); 53 | 54 | // create a gradient by combining our R color with G and B values calculated using our texture coordinate, then multiply the result by the provided brightness 55 | vec3 gradient_color = vec3(u_color.r, u_color.g, u_color.b) * brightness; 56 | 57 | // calculate how much color to apply to this pixel by cubing its distance from the center 58 | float color_strength = pow(1.0 - pixel_distance, 3.0); 59 | 60 | // multiply by the user's input strength 61 | color_strength *= u_strength; 62 | 63 | // calculate the size of our wave by multiplying provided density with our distance from the center 64 | float wave_density = u_density * pixel_distance; 65 | 66 | // decide how dark this pixel should be as a range from -1 to 1 by adding the speed of the overall wave by the density of the current pixel 67 | float cosine = cos(wave_speed + wave_density); 68 | 69 | // halve that cosine and add 0.5, which will give a range of 0 to 1 70 | // this is our wave fluctuation, which causes waves to vary between colored and dark 71 | float cosine_adjustment = (0.5 * cosine) + 0.5; 72 | 73 | // calculate the brightness for this pixel by multiplying its color strength with the sum of the user's requested strength and our cosine adjustment 74 | float luma = color_strength * (u_strength + cosine_adjustment); 75 | 76 | // force the brightness to decay rapidly so we don't hit the edges of our sprite 77 | luma *= 1.0 - (pixel_distance * 2.0); 78 | luma = max(0.0, luma); 79 | 80 | // multiply our gradient color by brightness for RGB, and the brightness itself for A 81 | vec4 final_color = vec4(gradient_color * luma, luma); 82 | 83 | // multiply the final color by the actual alpha of this node, so users can make it fade in/out as needed 84 | gl_FragColor = final_color * current_color.a * v_color_mix.a; 85 | } else { 86 | // use the current (transparent) color 87 | gl_FragColor = current_color; 88 | } 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /Shaders/SHKCircleWaveBlended.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Renders a circular pulsating wave effect with a fixed color based on user input, blending with existing pixels 3 | // Uniform: u_speed, how fast the wave should travel. Ranges from -2 to 2 work best, where negative numbers cause waves to come inwards; try starting with 1. 4 | // Uniform: u_brightness, how bright the colors should be. Ranges from 0 to 5 work best; try starting with 0.5 and experiment. 5 | // Uniform: u_strength, how intense the waves should be. Ranges from 0.02 to 5 work best; try starting with 2. 6 | // Uniform: u_density, how large each wave should be. Ranges from 20 to 500 work best; try starting with 100. 7 | // Uniform: u_center, a CGPoint representing the center of the gradient, where 0.5/0.5 is dead center 8 | // Uniform: u_color, the SKColor to use. Use darker colors to create a less intense core. 9 | // 10 | // This works by calculating what a color gradient would look like over the space of the node 11 | // then calculating the pixel's distance from the center of the wave. From there we can calculate 12 | // the brightness of the pixel by taking the cosine the wave density and speed to create a nice and 13 | // smooth effect. 14 | // 15 | // MIT License 16 | // 17 | // Copyright (c) 2017 Paul Hudson 18 | // https://www.github.com/twostraws/ShaderKit 19 | // 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy 21 | // of this software and associated documentation files (the "Software"), to deal 22 | // in the Software without restriction, including without limitation the rights 23 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | // copies of the Software, and to permit persons to whom the Software is 25 | // furnished to do so, subject to the following conditions: 26 | // 27 | // The above copyright notice and this permission notice shall be included in all 28 | // copies or substantial portions of the Software. 29 | // 30 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | // SOFTWARE. 37 | // 38 | 39 | void main() { 40 | // find the current pixel color 41 | vec4 current_color = SKDefaultShading(); 42 | 43 | // if it's not transparent 44 | if (current_color.a > 0.0) { 45 | // calculate how fast to make the waves move; this is negative so the waves move outwards 46 | float wave_speed = -(u_time * u_speed * 10.0); 47 | 48 | // create RGB colors from the provided brightness 49 | vec3 brightness = vec3(u_brightness); 50 | 51 | // how far our pixel is from the center of the circle 52 | float pixel_distance = distance(v_tex_coord, u_center); 53 | 54 | // create a gradient by combining our R color with G and B values calculated using our texture coordinate, then multiply the result by the provided brightness 55 | vec3 gradient_color = vec3(u_color.r, u_color.g, u_color.b) * brightness; 56 | 57 | // calculate how much color to apply to this pixel by cubing its distance from the center 58 | float color_strength = pow(1.0 - pixel_distance, 3.0); 59 | 60 | // multiply by the user's input strength 61 | color_strength *= u_strength; 62 | 63 | // calculate the size of our wave by multiplying provided density with our distance from the center 64 | float wave_density = u_density * pixel_distance; 65 | 66 | // decide how dark this pixel should be as a range from -1 to 1 by adding the speed of the overall wave by the density of the current pixel 67 | float cosine = cos(wave_speed + wave_density); 68 | 69 | // halve that cosine and add 0.5, which will give a range of 0 to 1 70 | // this is our wave fluctuation, which causes waves to vary between colored and dark 71 | float cosine_adjustment = (0.5 * cosine) + 0.5; 72 | 73 | // calculate the brightness for this pixel by multiplying its color strength with the sum of the user's requested strength and our cosine adjustment 74 | float luma = color_strength * (u_strength + cosine_adjustment); 75 | 76 | // force the brightness to decay rapidly so we don't hit the edges of our sprite 77 | luma *= 1.0 - (pixel_distance * 2.0); 78 | luma = max(0.0, luma); 79 | 80 | // multiply our gradient color by brightness for RGB, and the brightness itself for A 81 | vec4 final_color = vec4(gradient_color * luma, luma); 82 | 83 | // multiply the final color by the actual alpha of this node, so users can make it fade in/out as needed 84 | gl_FragColor = mix(current_color, final_color, final_color.a) * current_color.a * v_color_mix.a; 85 | } else { 86 | // use the current (transparent) color 87 | gl_FragColor = current_color; 88 | } 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /Shaders/SHKCircleWaveRainbow.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Renders a circular pulsating wave effect with fluctuating colors, ignoring any current pixel colors 3 | // Uniform: u_speed, how fast the wave should travel. Ranges from -2 to 2 work best, where negative numbers cause waves to come inwards; try starting with 1. 4 | // Uniform: u_brightness, how bright the colors should be. Ranges from 0 to 5 work best; try starting with 0.5 and experiment. 5 | // Uniform: u_strength, how intense the waves should be. Ranges from 0.02 to 5 work best; try starting with 2. 6 | // Uniform: u_density, how large each wave should be. Ranges from 20 to 500 work best; try starting with 100. 7 | // Uniform: u_center, a CGPoint representing the center of the gradient, where 0.5/0.5 is dead center 8 | // Uniform: u_red, how much red to apply to the colors. Specify 0 to 1 to apply that amount of red, or use any negative number (e.g. -1) to have the amount of red fluctuate. 9 | // 10 | // This works by calculating what a color gradient would look like over the space of the node 11 | // then calculating the pixel's distance from the center of the wave. From there we can calculate 12 | // the brightness of the pixel by taking the cosine the wave density and speed to create a nice and 13 | // smooth effect. 14 | // 15 | // MIT License 16 | // 17 | // Copyright (c) 2017 Paul Hudson 18 | // https://www.github.com/twostraws/ShaderKit 19 | // 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy 21 | // of this software and associated documentation files (the "Software"), to deal 22 | // in the Software without restriction, including without limitation the rights 23 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | // copies of the Software, and to permit persons to whom the Software is 25 | // furnished to do so, subject to the following conditions: 26 | // 27 | // The above copyright notice and this permission notice shall be included in all 28 | // copies or substantial portions of the Software. 29 | // 30 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | // SOFTWARE. 37 | // 38 | 39 | void main() { 40 | // find the current pixel color 41 | vec4 current_color = SKDefaultShading(); 42 | 43 | // if it's not transparent 44 | if (current_color.a > 0.0) { 45 | // calculate how fast to change colors based on how much time has elapsed for this wave relative to its input speed 46 | float color_speed = u_time * u_speed; 47 | 48 | // calculate how fast to make the waves move significantly faster than the color changing; this is negative so the waves move outwards 49 | float wave_speed = -(color_speed * 10.0); 50 | 51 | // create RGB colors from the provided brightness 52 | vec3 brightness = vec3(u_brightness); 53 | 54 | // how far our pixel is from the center of the circle 55 | float pixel_distance = distance(v_tex_coord, u_center); 56 | 57 | // use the provided red color, or prepare to make it fluctuate 58 | float red_adjustment = u_red; 59 | 60 | // if they provided a negative red color then make it fluctuate instead 61 | if (u_red < 0.0) { 62 | // calculate the sine of the current time, which will give a value between -1 and 1 63 | float sine = sin(color_speed); 64 | 65 | // halve that sine and add 0.5, which will give a range of 0 to 1; this will be our R color 66 | red_adjustment = (0.5 * sine) + 0.5; 67 | } 68 | 69 | // create a gradient by combining our R color with G and B values calculated using our texture coordinate, then multiply the result by the provided brightness 70 | vec3 gradient_color = vec3(red_adjustment, v_tex_coord) * brightness; 71 | 72 | // calculate how much color to apply to this pixel by cubing its distance from the center 73 | float color_strength = pow(1.0 - pixel_distance, 3.0); 74 | 75 | // multiply by the user's input strength 76 | color_strength *= u_strength; 77 | 78 | // calculate the size of our wave by multiplying provided density with our distance from the center 79 | float wave_density = u_density * pixel_distance; 80 | 81 | // decide how dark this pixel should be as a range from -1 to 1 by adding the speed of the overall wave by the density of the current pixel 82 | float cosine = cos(wave_speed + wave_density); 83 | 84 | // halve that cosine and add 0.5, which will give a range of 0 to 1 85 | // this is our wave fluctuation, which causes waves to vary between colored and dark 86 | float cosine_adjustment = (0.5 * cosine) + 0.5; 87 | 88 | // calculate the brightness for this pixel by multiplying its color strength with the sum of the user's requested strength and our cosine adjustment 89 | float luma = color_strength * (u_strength + cosine_adjustment); 90 | 91 | // force the brightness to decay rapidly so we don't hit the edges of our sprite 92 | luma *= 1.0 - (pixel_distance * 2.0); 93 | luma = max(0.0, luma); 94 | 95 | // multiply our gradient color by brightness for RGB, and the brightness itself for A 96 | vec4 final_color = vec4(gradient_color * luma, luma); 97 | 98 | // multiply the final color by the actual alpha of this node, so users can make it fade in/out as needed 99 | gl_FragColor = final_color * current_color.a * v_color_mix.a; 100 | } else { 101 | // use the current (transparent) color 102 | gl_FragColor = current_color; 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /Shaders/SHKCircleWaveRainbowBlended.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Renders a circular pulsating wave effect with fluctuating colors, blending with existing pixels 3 | // Uniform: u_speed, how fast the wave should travel. Ranges from -2 to 2 work best, where negative numbers cause waves to come inwards; try starting with 1. 4 | // Uniform: u_brightness, how bright the colors should be. Ranges from 0 to 5 work best; try starting with 0.5 and experiment. 5 | // Uniform: u_strength, how intense the waves should be. Ranges from 0.02 to 5 work best; try starting with 2. 6 | // Uniform: u_density, how large each wave should be. Ranges from 20 to 500 work best; try starting with 100. 7 | // Uniform: u_center, a CGPoint representing the center of the gradient, where 0.5/0.5 is dead center 8 | // Uniform: u_red, how much red to apply to the colors. Specify 0 to 1 to apply that amount of red, or use any negative number (e.g. -1) to have the amount of red fluctuate. 9 | // 10 | // This works by calculating what a color gradient would look like over the space of the node 11 | // then calculating the pixel's distance from the center of the wave. From there we can calculate 12 | // the brightness of the pixel by taking the cosine the wave density and speed to create a nice and 13 | // smooth effect. 14 | // 15 | // MIT License 16 | // 17 | // Copyright (c) 2017 Paul Hudson 18 | // https://www.github.com/twostraws/ShaderKit 19 | // 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy 21 | // of this software and associated documentation files (the "Software"), to deal 22 | // in the Software without restriction, including without limitation the rights 23 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | // copies of the Software, and to permit persons to whom the Software is 25 | // furnished to do so, subject to the following conditions: 26 | // 27 | // The above copyright notice and this permission notice shall be included in all 28 | // copies or substantial portions of the Software. 29 | // 30 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | // SOFTWARE. 37 | // 38 | 39 | void main() { 40 | // find the current pixel color 41 | vec4 current_color = SKDefaultShading(); 42 | 43 | // if it's not transparent 44 | if (current_color.a > 0.0) { 45 | // calculate how fast to change colors based on how much time has elapsed for this wave relative to its input speed 46 | float color_speed = u_time * u_speed; 47 | 48 | // calculate how fast to make the waves move significantly faster than the color changing; this is negative so the waves move outwards 49 | float wave_speed = -(color_speed * 10.0); 50 | 51 | // create RGB colors from the provided brightness 52 | vec3 brightness = vec3(u_brightness); 53 | 54 | // how far our pixel is from the center of the circle 55 | float pixel_distance = distance(v_tex_coord, u_center); 56 | 57 | // use the provided red color, or prepare to make it fluctuate 58 | float red_adjustment = u_red; 59 | 60 | // if they provided a negative red color then make it fluctuate instead 61 | if (u_red < 0.0) { 62 | // calculate the sine of the current time, which will give a value between -1 and 1 63 | float sine = sin(color_speed); 64 | 65 | // halve that sine and add 0.5, which will give a range of 0 to 1; this will be our R color 66 | red_adjustment = (0.5 * sine) + 0.5; 67 | } 68 | 69 | // create a gradient by combining our R color with G and B values calculated using our texture coordinate, then multiply the result by the provided brightness 70 | vec3 gradient_color = vec3(red_adjustment, v_tex_coord) * brightness; 71 | 72 | // calculate how much color to apply to this pixel by cubing its distance from the center 73 | float color_strength = pow(1.0 - pixel_distance, 3.0); 74 | 75 | // multiply by the user's input strength 76 | color_strength *= u_strength; 77 | 78 | // calculate the size of our wave by multiplying provided density with our distance from the center 79 | float wave_density = u_density * pixel_distance; 80 | 81 | // decide how dark this pixel should be as a range from -1 to 1 by adding the speed of the overall wave by the density of the current pixel 82 | float cosine = cos(wave_speed + wave_density); 83 | 84 | // halve that cosine and add 0.5, which will give a range of 0 to 1 85 | // this is our wave fluctuation, which causes waves to vary between colored and dark 86 | float cosine_adjustment = (0.5 * cosine) + 0.5; 87 | 88 | // calculate the brightness for this pixel by multiplying its color strength with the sum of the user's requested strength and our cosine adjustment 89 | float luma = color_strength * (u_strength + cosine_adjustment); 90 | 91 | // force the brightness to decay rapidly so we don't hit the edges of our sprite 92 | luma *= 1.0 - (pixel_distance * 2.0); 93 | luma = max(0.0, luma); 94 | 95 | // multiply our gradient color by brightness for RGB, and the brightness itself for A 96 | vec4 final_color = vec4(gradient_color * luma, luma); 97 | 98 | // multiply the final color by the actual alpha of this node, so users can make it fade in/out as needed 99 | gl_FragColor = mix(current_color, final_color, final_color.a) * current_color.a * v_color_mix.a; 100 | } else { 101 | // use the current (transparent) color 102 | gl_FragColor = current_color; 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /Shaders/SHKColorAlpha.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Colors all clear pixels in the node. 3 | // Uniform: u_color, the SKColor to use. 4 | // 5 | // This works by scanning the alpha value of the current pixel. If it's transparent then 6 | // we color it using whatever was passed in by the user. If it's not transparent then 7 | // we blend it using the source color and user's color based on how transparent the 8 | // pixel is. This gives us a nice soft edge where existing pixels become translucent. 9 | // 10 | // MIT License 11 | // 12 | // Copyright (c) 2017 Paul Hudson 13 | // https://www.github.com/twostraws/ShaderKit 14 | // 15 | // Permission is hereby granted, free of charge, to any person obtaining a copy 16 | // of this software and associated documentation files (the "Software"), to deal 17 | // in the Software without restriction, including without limitation the rights 18 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | // copies of the Software, and to permit persons to whom the Software is 20 | // furnished to do so, subject to the following conditions: 21 | // 22 | // The above copyright notice and this permission notice shall be included in all 23 | // copies or substantial portions of the Software. 24 | // 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | // SOFTWARE. 32 | // 33 | 34 | void main() { 35 | // find the current pixel color 36 | vec4 current_color = SKDefaultShading(); 37 | 38 | // if it's transparent 39 | if (current_color.a == 0.0) { 40 | // use the input color, multiplying by the node alpha so we can fade in or out 41 | gl_FragColor = u_color * v_color_mix.a; 42 | } else { 43 | // make a blended color based on the input and current pixel color, using as much as is needed 44 | // based on the alpha value of the current pixel 45 | gl_FragColor = mix(u_color, current_color, current_color.a) * v_color_mix.a; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Shaders/SHKColorInvert.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Inverts all colors in a node while retaining transparency. 3 | // 4 | // This works by scanning the alpha value of the current pixel. If it's transparent 5 | // then we just send it back as-is. Otherwise we subtract the current RGB from 1 6 | // values to create their inverse. 7 | // 8 | // MIT License 9 | // 10 | // Copyright (c) 2017 Paul Hudson 11 | // https://www.github.com/twostraws/ShaderKit 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in all 21 | // copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | // SOFTWARE. 30 | // 31 | 32 | void main() { 33 | // find the current pixel color 34 | vec4 current_color = texture2D(u_texture, v_tex_coord); 35 | 36 | // if it's not transparent 37 | if (current_color.a > 0.0) { 38 | // subtract its current RGB values from 1 and use its current alpha; multiply by the node alpha so we can fade in or out 39 | gl_FragColor = vec4(1.0 - current_color.rgb, current_color.a) * current_color.a * v_color_mix.a; 40 | } else { 41 | // use the current (transparent) color 42 | gl_FragColor = current_color; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Shaders/SHKColorNonAlpha.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Colors all clear pixels in the node. 3 | // Uniform: u_color, the SKColor to use. 4 | // 5 | // This works by scanning the alpha value of the current pixel. If it's not transparent 6 | // then we color it using whatever was passed in by the user, otherwise we just pass 7 | // back the original color. 8 | // 9 | // MIT License 10 | // 11 | // Copyright (c) 2017 Paul Hudson 12 | // https://www.github.com/twostraws/ShaderKit 13 | // 14 | // Permission is hereby granted, free of charge, to any person obtaining a copy 15 | // of this software and associated documentation files (the "Software"), to deal 16 | // in the Software without restriction, including without limitation the rights 17 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | // copies of the Software, and to permit persons to whom the Software is 19 | // furnished to do so, subject to the following conditions: 20 | // 21 | // The above copyright notice and this permission notice shall be included in all 22 | // copies or substantial portions of the Software. 23 | // 24 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | // SOFTWARE. 31 | // 32 | 33 | void main() { 34 | // find the current pixel color 35 | vec4 current_color = SKDefaultShading(); 36 | 37 | // if it's not transparent 38 | if (current_color.a > 0.0) { 39 | // use the input color, multiplying by this pixel's alpha (to avoid a hard edge) and also 40 | // multiplying by the node alpha so we can fade in or out 41 | gl_FragColor = u_color * current_color.a * v_color_mix.a; 42 | } else { 43 | // use the current (non-transparent) color 44 | gl_FragColor = current_color; 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /Shaders/SHKColorize.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Recolors a texture to a user color based on a strength value. 3 | // Uniform: u_color, the SKColor to use. This is multiplied with the original, meaning that blacks remain black 4 | // Uniform: u_strength, how much of the replacement color to apply. Specify a value between 0 (use original color) and 1 (use replacement color fully) 5 | // 6 | // This works by calculating the grayscale value for each texel then multiplying that 7 | // by a color provided by the user. That is then blended with the original pixel color 8 | // based on a strength provided by the user to provide variable recoloring. 9 | // 10 | // MIT License 11 | // 12 | // Copyright (c) 2017 Paul Hudson 13 | // https://www.github.com/twostraws/ShaderKit 14 | // 15 | // Permission is hereby granted, free of charge, to any person obtaining a copy 16 | // of this software and associated documentation files (the "Software"), to deal 17 | // in the Software without restriction, including without limitation the rights 18 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | // copies of the Software, and to permit persons to whom the Software is 20 | // furnished to do so, subject to the following conditions: 21 | // 22 | // The above copyright notice and this permission notice shall be included in all 23 | // copies or substantial portions of the Software. 24 | // 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | // SOFTWARE. 32 | // 33 | 34 | void main( void ) { 35 | // find the current pixel color 36 | vec4 current_color = texture2D(u_texture, v_tex_coord); 37 | 38 | // if it's not transparent 39 | if (current_color.a > 0.0) { 40 | // these values correspond to how important each color is to the overall brightness 41 | vec3 gray_values = vec3(0.2125, 0.7154, 0.0721); 42 | 43 | // the dot() function multiples all the colors in our source color with all the values in 44 | // our gray_values conversion then sums them 45 | float gray = dot(current_color.rgb, gray_values); 46 | 47 | // calculate the new color by blending gray with the user's input color 48 | vec4 new_color = vec4(gray * u_color.rgb, current_color.a); 49 | 50 | // now blend that with the original color based on the strength uniform 51 | gl_FragColor = mix(current_color, new_color, u_strength) * v_color_mix.a; 52 | } else { 53 | // use the current (transparent) color 54 | gl_FragColor = current_color; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Shaders/SHKDesaturate.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Desaturates the colors in a texture. 3 | // Uniform: u_strength, the amount to desaturate. Specify 0 (no desaturation) to 1 (full desaturation). 4 | // 5 | // This works by calculating the grayscale color for a given pixel, then mixing that 6 | // with the original color based on the strength provided by the user. 7 | // 8 | // Calculating the relative luminance of a color – i.e., how bright it is – isn't as simple 9 | // as adding its RGB values and dividing by three, because human eyes are more sensitive to 10 | // green and red than they are to blue. That is, a fully green color appears brighter 11 | // than a fully blue color. 12 | // 13 | // So, to calculate the correct luminance for each pixel we use a precise weighting: 14 | // R is weighted at 0.2125, G at 0.7154, and B at 0.0721. This totals 1. 15 | // 16 | // MIT License 17 | // 18 | // Copyright (c) 2017 Paul Hudson 19 | // https://www.github.com/twostraws/ShaderKit 20 | // 21 | // Permission is hereby granted, free of charge, to any person obtaining a copy 22 | // of this software and associated documentation files (the "Software"), to deal 23 | // in the Software without restriction, including without limitation the rights 24 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | // copies of the Software, and to permit persons to whom the Software is 26 | // furnished to do so, subject to the following conditions: 27 | // 28 | // The above copyright notice and this permission notice shall be included in all 29 | // copies or substantial portions of the Software. 30 | // 31 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | // SOFTWARE. 38 | // 39 | 40 | void main() { 41 | float strength = clamp(u_strength, 0.0, 1.0); 42 | 43 | // find the current pixel color 44 | vec4 current_color = SKDefaultShading(); 45 | 46 | // these values correspond to how important each color is to the overall brightness 47 | vec3 gray_values = vec3(0.2125, 0.7154, 0.0721); 48 | 49 | // the dot() function multiples all the colors in our source color with all the values in our 50 | // gray_values conversion then sums them; this then gets put into a new vec3 color as its RGB values 51 | vec3 desaturated = vec3(dot(current_color.rgb, gray_values)); 52 | 53 | // if the user requested full desaturation 54 | if (strength == 1.0) { 55 | // just show the desaturated version 56 | gl_FragColor = vec4(desaturated, current_color.a) * v_color_mix.a; 57 | } else { 58 | // blend the original and desaturated by whatever 1 - strength was passed in 59 | gl_FragColor = vec4(mix(current_color.rgb, desaturated, strength), current_color.a) * v_color_mix.a; 60 | } 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /Shaders/SHKDynamicGrayNoise.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Creates moving grayscale noise. 3 | // 4 | // This works using a simple (but brilliant!) and well-known trick: if you 5 | // calculate the dot product of a texture coordinate with a vec2 containing 6 | // two numbers that are unlikely to repeat, then calculate the sine of that 7 | // and multiply it by a large number, you'll end up with what looks more or 8 | // less like random numbers in the fraction digits – i.e., everything after 9 | // the decimal place. 10 | // 11 | // This is perfect for our needs: those numbers will already range from 0 to 12 | // 0.99999... so we can use that for our color value by repeating it for each 13 | // of the RGB components. 14 | // 15 | // MIT License 16 | // 17 | // Copyright (c) 2017 Paul Hudson 18 | // https://www.github.com/twostraws/ShaderKit 19 | // 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy 21 | // of this software and associated documentation files (the "Software"), to deal 22 | // in the Software without restriction, including without limitation the rights 23 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | // copies of the Software, and to permit persons to whom the Software is 25 | // furnished to do so, subject to the following conditions: 26 | // 27 | // The above copyright notice and this permission notice shall be included in all 28 | // copies or substantial portions of the Software. 29 | // 30 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | // SOFTWARE. 37 | // 38 | 39 | float random(float offset, vec2 tex_coord, float time) { 40 | // pick two numbers that are unlikely to repeat 41 | vec2 non_repeating = vec2(12.9898 * time, 78.233 * time); 42 | 43 | // multiply our texture coordinates by the non-repeating numbers, then add them together 44 | float sum = dot(tex_coord, non_repeating); 45 | 46 | // calculate the sine of our sum to get a range between -1 and 1 47 | float sine = sin(sum); 48 | 49 | // multiply the sine by a big, non-repeating number so that even a small change will result in a big color jump 50 | float huge_number = sine * 43758.5453 * offset; 51 | 52 | // get just the numbers after the decimal point 53 | float fraction = fract(huge_number); 54 | 55 | // send the result back to the caller 56 | return fraction; 57 | } 58 | 59 | void main() { 60 | // find the current pixel color 61 | vec4 current_color = SKDefaultShading(); 62 | 63 | // if it's not transparent 64 | if (current_color.a > 0.0) { 65 | // make a color where the RGB values are the same random number and A is 1; multiply by the node alpha so we can fade in or out 66 | gl_FragColor = vec4(vec3(random(1.0, v_tex_coord, u_time)), 1) * current_color.a * v_color_mix.a; 67 | } else { 68 | // use the (transparent) color 69 | gl_FragColor = current_color; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Shaders/SHKDynamicRainbowNoise.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Creates moving multi-colored noise. 3 | // 4 | // This works using a simple (but brilliant!) and well-known trick: if you 5 | // calculate the dot product of a texture coordinate with a vec2 containing 6 | // two numbers that are unlikely to repeat, then calculate the sine of that 7 | // and multiply it by a large number, you'll end up with what looks more or 8 | // less like random numbers in the fraction digits – i.e., everything after 9 | // the decimal place. 10 | // 11 | // This is perfect for our needs: those numbers will already range from 0 to 12 | // 0.99999... so we can use that for our color value by calling it once for each 13 | // of the RGB components. 14 | // 15 | // MIT License 16 | // 17 | // Copyright (c) 2017 Paul Hudson 18 | // https://www.github.com/twostraws/ShaderKit 19 | // 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy 21 | // of this software and associated documentation files (the "Software"), to deal 22 | // in the Software without restriction, including without limitation the rights 23 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | // copies of the Software, and to permit persons to whom the Software is 25 | // furnished to do so, subject to the following conditions: 26 | // 27 | // The above copyright notice and this permission notice shall be included in all 28 | // copies or substantial portions of the Software. 29 | // 30 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | // SOFTWARE. 37 | // 38 | 39 | float random(float offset, vec2 tex_coord, float time) { 40 | // pick two numbers that are unlikely to repeat 41 | vec2 non_repeating = vec2(12.9898 * time, 78.233 * time); 42 | 43 | // multiply our texture coordinates by the non-repeating numbers, then add them together 44 | float sum = dot(tex_coord, non_repeating); 45 | 46 | // calculate the sine of our sum to get a range between -1 and 1 47 | float sine = sin(sum); 48 | 49 | // multiply the sine by a big, non-repeating number so that even a small change will result in a big color jump 50 | float huge_number = sine * 43758.5453 * offset; 51 | 52 | // get just the numbers after the decimal point 53 | float fraction = fract(huge_number); 54 | 55 | // send the result back to the caller 56 | return fraction; 57 | } 58 | 59 | void main() { 60 | // find the current pixel color 61 | vec4 current_color = SKDefaultShading(); 62 | 63 | // if it's not transparent 64 | if (current_color.a > 0.0) { 65 | // make a color where the RGB values are different random numbers and our fraction and A is 1; multiply by the node alpha so we can fade in or out 66 | gl_FragColor = vec4(random(1.23, v_tex_coord, u_time), random(5.67, v_tex_coord, u_time), random(8.90, v_tex_coord, u_time), 1) * current_color.a * v_color_mix.a; 67 | } else { 68 | // use the (transparent) color 69 | gl_FragColor = current_color; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Shaders/SHKEmbossColor.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Creates a color emboss effect for the node. 3 | // Attribute: a_size, the size of the node. 4 | // Uniform: u_strength, how much embossing to apply (ranges from 0 to 1 work best) 5 | // 6 | // This works in several steps. First, we need to find the size of one pixel in the image, 7 | // so we are able to read other nearby pixels. 8 | // 9 | // Second, we create our base new color using the pixel's existing color 10 | // 11 | // Third, we read values diagonally up and to the right, then down and to the left, to see 12 | // what's nearby, and add or subtract them from our color. How far we move diagonally 13 | // depends on the strength the user provided. 14 | // 15 | // If you're not sure how this works, imagine a pixel on the top edge of a sprite. Above it has nothing, 16 | // so nothing gets added to the base color. Below it has a pixel of the same color, so that color 17 | // gets subtracted from the base color to make it black. The same is true in reverse of pixels on 18 | // the bottom edge: they have nothing below so nothing is subtracted, but they have a pixel above so 19 | // that gets added, making it a bright color. 20 | // 21 | // As for pixels in the middle, they'll get embossed based on the pixels either side of them. If a red pixel 22 | // is surrounded by a sea of other red pixels, then red will get added from above then subtracted in equal 23 | // measure from below, so the final color will be the original. 24 | // 25 | // MIT License 26 | // 27 | // Copyright (c) 2017 Paul Hudson 28 | // https://www.github.com/twostraws/ShaderKit 29 | // 30 | // Permission is hereby granted, free of charge, to any person obtaining a copy 31 | // of this software and associated documentation files (the "Software"), to deal 32 | // in the Software without restriction, including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in all 38 | // copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 46 | // SOFTWARE. 47 | // 48 | 49 | void main() { 50 | // find the current pixel color 51 | vec4 current_color = SKDefaultShading(); 52 | 53 | // if it's not transparent 54 | if (current_color.a > 0.0) { 55 | // find the size of one pixel by reading the input size 56 | vec2 pixel_size = 1.0 / a_size; 57 | 58 | // copy our current color so we can modify it 59 | vec4 new_color = current_color; 60 | 61 | // move up one pixel diagonally and read the current color, multiply it by the input strength, then add it to our pixel color 62 | new_color += texture2D(u_texture, v_tex_coord + pixel_size) * u_strength; 63 | 64 | // move down one pixel diagonally and read the current color, multiply it by the input strength, then subtract it to our pixel color 65 | new_color -= texture2D(u_texture, v_tex_coord - pixel_size) * u_strength; 66 | 67 | // use that new color, with an alpha of 1, for our pixel color, multiplying by this pixel's alpha 68 | // (to avoid a hard edge) and also multiplying by the alpha for this node 69 | gl_FragColor = vec4(new_color.rgb, 1) * current_color.a * v_color_mix.a; 70 | } else { 71 | // use the current (transparent) color 72 | gl_FragColor = current_color; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Shaders/SHKEmbossGray.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Creates a grayscale emboss effect for the node. 3 | // Attribute: a_size, the size of the node. 4 | // Uniform: u_strength, how much embossing to apply. Ranges from 0 to 1 work best; try starting with 1. 5 | // 6 | // This works in several steps. First, we need to find the size of one pixel in the image, 7 | // so we are able to read other nearby pixels. 8 | // 9 | // Second, we create our base new color as a middle gray: RGB 0.5, with A 1.0. 10 | // 11 | // Third, we read values diagonally up and to the right, then down and to the left, to see 12 | // what's nearby, and add or subtract them from our gray color. How far we move diagonally 13 | // depends on the strength the user provided. 14 | // 15 | // Fourth, we average the new color's RGB values to create a flat gray color ignoring luminescence, 16 | // then use that average for the RGB value of our pixel. 17 | // 18 | // If you're not sure how this works, imagine a pixel on the top edge of a sprite. Above it has nothing, 19 | // so nothing gets added to the base gray color. Below it has a pixel of the same color, so that color 20 | // gets subtracted from the base gray color to make it black. The same is true in reverse of pixels on 21 | // the bottom edge: they have nothing below so nothing is subtracted, but they have a pixel above so 22 | // that gets added, making it a bright color. 23 | // 24 | // As for pixels in the middle, they'll get embossed based on the pixels either side of them. If a red pixel 25 | // is surrounded by a sea of other red pixels, then red will get added from above then subtracted in equal 26 | // measure from below, so the final color will be the original mid-gray. 27 | // 28 | // MIT License 29 | // 30 | // Copyright (c) 2017 Paul Hudson 31 | // https://www.github.com/twostraws/ShaderKit 32 | // 33 | // Permission is hereby granted, free of charge, to any person obtaining a copy 34 | // of this software and associated documentation files (the "Software"), to deal 35 | // in the Software without restriction, including without limitation the rights 36 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 37 | // copies of the Software, and to permit persons to whom the Software is 38 | // furnished to do so, subject to the following conditions: 39 | // 40 | // The above copyright notice and this permission notice shall be included in all 41 | // copies or substantial portions of the Software. 42 | // 43 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 46 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 47 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 48 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 49 | // SOFTWARE. 50 | // 51 | 52 | void main() { 53 | // find the current pixel color 54 | vec4 current_color = SKDefaultShading(); 55 | 56 | // if it's not transparent 57 | if (current_color.a > 0.0) { 58 | // find the size of one pixel by reading the input size 59 | vec2 pixel_size = 1.0 / a_size; 60 | 61 | // assume our new color is middle gray (R: 0.5, G: 0.5, B: 0.5, A: 1) 62 | vec4 new_color = vec4(vec3(0.5), 1); 63 | 64 | // move up one pixel diagonally and read the current color, multiply it by the input strength, then add it to our pixel color 65 | new_color += texture2D(u_texture, v_tex_coord + pixel_size) * u_strength; 66 | 67 | // move down one pixel diagonally and read the current color, multiply it by the input strength, then subtract it to our pixel color 68 | new_color -= texture2D(u_texture, v_tex_coord - pixel_size) * u_strength; 69 | 70 | // sum the RGB values for our new color 71 | float combined = new_color.r + new_color.g + new_color.b; 72 | 73 | // divide that sum by 3 to give us an average, and use that for the RGB values of our color 74 | new_color.rgb = vec3(combined / 3.0); 75 | 76 | // use that new color, with an alpha of 1, for our pixel color, multiplying by this pixel's alpha 77 | // (to avoid a hard edge) and also multiplying by the alpha for this node 78 | gl_FragColor = vec4(new_color.rgb, 1) * current_color.a * v_color_mix.a; 79 | } else { 80 | // use the current (transparent) color 81 | gl_FragColor = current_color; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Shaders/SHKInfrared.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Simulates an infrared camera by coloring brighter objects red and darker objects blue. 3 | // 4 | // This works by calculating the brightness of the current color, then creating a new 5 | // a new color based on that brightness. If the brightness is lower than 0.5 on a scale of 6 | // 0 to 1, the new color is a mix of blue and yellow based; if the brightness is 0.5 or 7 | // higher, the new color is a mix of yellow and red. 8 | // 9 | // MIT License 10 | // 11 | // Copyright (c) 2017 Paul Hudson 12 | // https://www.github.com/twostraws/ShaderKit 13 | // 14 | // Permission is hereby granted, free of charge, to any person obtaining a copy 15 | // of this software and associated documentation files (the "Software"), to deal 16 | // in the Software without restriction, including without limitation the rights 17 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | // copies of the Software, and to permit persons to whom the Software is 19 | // furnished to do so, subject to the following conditions: 20 | // 21 | // The above copyright notice and this permission notice shall be included in all 22 | // copies or substantial portions of the Software. 23 | // 24 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | // SOFTWARE. 31 | // 32 | 33 | void main() { 34 | // find the current pixel color 35 | vec4 current_color = texture2D(u_texture, v_tex_coord); 36 | 37 | // if it's not transparent 38 | if (current_color.a > 0.0) { 39 | // create three colors: blue (cold), yellow (medium), and hot (red) 40 | vec3 cold = vec3(0.0, 0.0, 1.0); 41 | vec3 medium = vec3(1.0, 1.0, 0.0); 42 | vec3 hot = vec3(1.0, 0.0, 0.0); 43 | 44 | // these values correspond to how important each color is to the overall brightness 45 | vec3 gray_values = vec3(0.2125, 0.7154, 0.0721); 46 | 47 | // the dot() function multiples all the colors in our source color with all the values in our gray_values conversion 48 | // then sums them; this then gets put into a new vec3 color as its RGB values 49 | float luma = dot(current_color.rgb, gray_values); 50 | 51 | // declare the color we're going to use 52 | vec3 new_color; 53 | 54 | // if we have brightness of lower than 0.5 55 | if (luma < 0.5) { 56 | // create a mix of blue and yellow; luma / 0.5 means this will be a range from 0 to 1 57 | new_color = mix(cold, medium, luma / 0.5); 58 | } else { 59 | // create a mix of yellow and red; (luma - 0.5) / 0.5 means this will be a range of 0 to 1 60 | new_color = mix(medium, hot, (luma - 0.5) / 0.5); 61 | } 62 | 63 | // create the final color, multiplying by this pixel's alpha (to avoid a hard edge) and also 64 | // multiplying by the node alpha so we can fade in or out 65 | gl_FragColor = vec4(new_color, current_color.a) * current_color.a * v_color_mix.a; 66 | } else { 67 | // use the current (transparent) color 68 | gl_FragColor = current_color; 69 | } 70 | } 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Shaders/SHKInterlace.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Applies an interlacing effect where horizontal lines of original color are separated by lines of another color 3 | // Attribute: a_size, the size of the node. 4 | // Uniform: u_width, the width of the interlacing lines. Ranges of 1 to 4 work best; try starting with 1. 5 | // Uniform: u_color, the SKColor to use for interlacing lines. Try starting with black. 6 | // Uniform: u_strength, how much to blend interlaced lines with u_color. Specify 0 (not at all) up to 1 (fully). 7 | // 8 | // This works using modulus: if the current pixel's position modulo twice the line width is less than the line 9 | // width then draw the original color. Otherwise blend the original color with the interlacing color based on 10 | // the user's provided strength. 11 | // 12 | // MIT License 13 | // 14 | // Copyright (c) 2017 Paul Hudson 15 | // https://www.github.com/twostraws/ShaderKit 16 | // 17 | // Permission is hereby granted, free of charge, to any person obtaining a copy 18 | // of this software and associated documentation files (the "Software"), to deal 19 | // in the Software without restriction, including without limitation the rights 20 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 21 | // copies of the Software, and to permit persons to whom the Software is 22 | // furnished to do so, subject to the following conditions: 23 | // 24 | // The above copyright notice and this permission notice shall be included in all 25 | // copies or substantial portions of the Software. 26 | // 27 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 30 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | // SOFTWARE. 34 | // 35 | 36 | void main() { 37 | // find the current pixel color 38 | vec4 current_color = SKDefaultShading(); 39 | 40 | // if the current color is not transparent 41 | if (current_color.a > 0.0) { 42 | // find this pixel's position in the texture 43 | float this_pixel = a_size[1] * v_tex_coord.y; 44 | 45 | // if we are an alternating line (horizontally) 46 | if (mod(this_pixel, u_width * 2.0) <= u_width) { 47 | // render the original color, taking into account node transparency 48 | gl_FragColor = SKDefaultShading() * v_color_mix.a; 49 | } else { 50 | // blend the original color with the provided color at whatever strength was requested, 51 | // multiplying by this pixel's alpha (to avoid a hard edge) and also multiplying by 52 | // the alpha for this node 53 | gl_FragColor = vec4(mix(current_color, u_color, u_strength)) * current_color.a * v_color_mix.a; 54 | } 55 | } else { 56 | // use the current (transparent) color 57 | gl_FragColor = vec4(0, 0, 0, 0); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Shaders/SHKLightGrid.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Creates a grid of multi-colored flashing lights. 3 | // Uniform: u_density, how many rows and columns to create. A range of 1 to 50 works well; try starting with 8. 4 | // Uniform: u_speed, how fast to make the lights vary their color. Higher values cause lights to flash faster and vary in color more. A range of 1 to 20 works well; try starting with 3. 5 | // Uniform: u_group_size, how many lights to place in each group. A range of 1 to 8 works well depending on your density; starting with 1. 6 | // Uniform: u_brightness, how bright to make the lights. A range of 0.2 to 10 works well; try starting with 3. 7 | // 8 | // This works by creating a grid of colors by chunking the texture according to the density from the user. 9 | // Each chunk is then assigned a random color variance using the same sine trick documented in 10 | // SHKStaticGrayNoise, which makes it fluctuate differently from other chunks around it. 11 | // 12 | // We then calculate the color for each chunk by taking a base color and adjusting it based on the 13 | // random color variance we just calculated, so that each chunk displays a different color. This is done 14 | // using sin() so we get a smooth color modulation. 15 | // 16 | // Finally, we pulsate each chunk so that it glows up and down, with black space between each chunk to create 17 | // delineated a light effect. The black space is created using another call to sin() so that the color 18 | // ramps from 0 to 1 then back down again. 19 | // 20 | // MIT License 21 | // 22 | // Copyright (c) 2017 Paul Hudson 23 | // https://www.github.com/twostraws/ShaderKit 24 | // 25 | // Permission is hereby granted, free of charge, to any person obtaining a copy 26 | // of this software and associated documentation files (the "Software"), to deal 27 | // in the Software without restriction, including without limitation the rights 28 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 29 | // copies of the Software, and to permit persons to whom the Software is 30 | // furnished to do so, subject to the following conditions: 31 | // 32 | // The above copyright notice and this permission notice shall be included in all 33 | // copies or substantial portions of the Software. 34 | // 35 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 36 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 37 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 38 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 39 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 40 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 41 | // SOFTWARE. 42 | // 43 | 44 | #define M_PI 3.1415926535897932384626433832795 45 | 46 | void main() { 47 | // get the color of the current pixel 48 | vec4 current_color = SKDefaultShading(); 49 | 50 | // if it's not transparent 51 | if (current_color.a > 0.0) { 52 | // STEP 1: split the grid up into groups based on user input 53 | vec2 point = v_tex_coord * u_density; 54 | 55 | // STEP 2: Calculate the color variance for each group 56 | // pick two numbers that are unlikely to repeat 57 | vec2 non_repeating = vec2(12.9898, 78.233); 58 | 59 | // assign this pixel to a group number 60 | vec2 group_number = floor(point); 61 | 62 | // multiply our group number by the non-repeating numbers, then add them together 63 | float sum = dot(group_number, non_repeating); 64 | 65 | // calculate the sine of our sum to get a range between -1 and 1 66 | float sine = sin(sum); 67 | 68 | // multiply the sine by a big, non-repeating number so that even a small change will result in a big color jump 69 | float huge_number = sine * 43758.5453; 70 | 71 | // calculate the sine of our time and our huge number and map it to the range 0-1 72 | float variance = (0.5 * sin(u_time + huge_number)) + 0.5; 73 | 74 | // adust the color variance by the provided speed 75 | float accelerated_variance = u_speed * variance; 76 | 77 | 78 | // STEP 3: Calculate the final color for this group 79 | // select a base color to work from 80 | vec3 base_color = vec3(3.0, 1.5, 0.0); 81 | 82 | // apply our variation to the base color, factoring in time 83 | vec3 varied_color = base_color + accelerated_variance + u_time; 84 | 85 | // calculate the sine of our varied color so it has the range -1 to 1 86 | vec3 varied_color_sine = sin(varied_color); 87 | 88 | // adjust the sine to lie in the range 0 to 1 89 | vec3 color = (0.5 * varied_color_sine) + 0.5; 90 | 91 | 92 | // STEP 4: Now we know the color, calculate the color pulse 93 | // Start by moving down and left a little to create black lines at insersection points 94 | vec2 group_size = M_PI * 2.0 * u_group_size * (point - (0.25 / u_group_size)); 95 | 96 | // calculate the sine of our group size, then adjust it to lie in the range 0 to 1 97 | vec2 group_sine = (0.5 * sin(group_size)) + 0.5; 98 | 99 | // use the sine to calculate a pulsating value between 0 and 1, making our group fluctuate together 100 | vec2 pulse = smoothstep(0.0, 1.0, group_sine); 101 | 102 | // calculate the final color by combining the pulse strength and user brightness with the color for this square 103 | gl_FragColor = vec4(color * (pulse.x * pulse.y * u_brightness), 1.0) * v_color_mix.a; 104 | } else { 105 | gl_FragColor = current_color; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Shaders/SHKLinearGradient.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Creates a linear gradient over the node. Either the start or the end color can be translucent to let original pixel colors come through. 3 | // Uniform: u_first_color, the SKColor to use at the top of the gradient 4 | // Uniform: u_second_color, the SKColor to use at the bottom of the gradient 5 | // 6 | // This works by blending the first color with the second based on how far up the pixel is from 7 | // the bottom of the texture. That's then blended with the original pixel color based on how 8 | // opaque the replacement color is, so that we can fade out to clear if needed. 9 | // 10 | // MIT License 11 | // 12 | // Copyright (c) 2017 Paul Hudson 13 | // https://www.github.com/twostraws/ShaderKit 14 | // 15 | // Permission is hereby granted, free of charge, to any person obtaining a copy 16 | // of this software and associated documentation files (the "Software"), to deal 17 | // in the Software without restriction, including without limitation the rights 18 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | // copies of the Software, and to permit persons to whom the Software is 20 | // furnished to do so, subject to the following conditions: 21 | // 22 | // The above copyright notice and this permission notice shall be included in all 23 | // copies or substantial portions of the Software. 24 | // 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | // SOFTWARE. 32 | // 33 | 34 | void main() { 35 | // get the color of the current pixel 36 | vec4 current_color = texture2D(u_texture, v_tex_coord); 37 | 38 | // if the current color is not transparent 39 | if (current_color.a > 0.0) { 40 | // mix the first color with the second color by however far we are from the bottom, 41 | // multiplying by this pixel's alpha (to avoid a hard edge) and also 42 | // multiplying by the node alpha so we can fade in or out 43 | vec4 new_color = mix(u_second_color, u_first_color, v_tex_coord.y); 44 | gl_FragColor = vec4(mix(current_color, new_color, new_color.a)) * current_color.a * v_color_mix.a; 45 | } else { 46 | // use the current (transparent) color 47 | gl_FragColor = current_color; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Shaders/SHKPassthrough.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // An empty shader that simply returns the default color for debugging purposes. 3 | // 4 | // This does nothing; it literally just sends back the original color. This is helpful 5 | // in the ShaderKit sandbox because it lets us start with no shader. 6 | // 7 | // MIT License 8 | // 9 | // Copyright (c) 2017 Paul Hudson 10 | // https://www.github.com/twostraws/ShaderKit 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | // 30 | 31 | void main() { 32 | // just use the default color for this fragment 33 | gl_FragColor = SKDefaultShading(); 34 | } 35 | -------------------------------------------------------------------------------- /Shaders/SHKPixelate.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Pixelates an image based on a strength provided by the user. 3 | // Attribute: a_size, the size of the node. 4 | // Uniform: u_strength, how large each pixel block should be. Ranges from 2 to 50 work best; try starting with 5. 5 | // 6 | // This works by dividing the image into groups based on the strength 7 | // parameter passed in by the user, then reading a single pixel from that 8 | // group and using it for the entire group. 9 | // 10 | // We get passed in the size of the node being transformed, e.g. 100x100. 11 | // Our texture coordinates are specified as a range from 0 to 1, so if we 12 | // divide 1 by our size we get 0.01x0.01 – the size of one pixel inside 13 | // the texture. We can then multiply that by the user's strength parameter, 14 | // e.g. 5, to get 0.05x0.05, which is the size of our pixelated effect. 15 | // 16 | // Once we have one pixelated size we can divide our texture coordinate by 17 | // that number. For example, if we're reading (0.12, 0.12) we divide that by 18 | // 0.05 to get 2.4. Now for the important part: we pass that number into floor() 19 | // to round it down so that it always uses the pixel in the bottom-left corner 20 | // for the entire group – that gives us 2.0. Finally, we multiply that back 21 | // by our original pixelated size (0.05) to get (0.1, 0.1), and that's the 22 | // texel we read from our texture rather than the original (0.12, 0.12). 23 | // 24 | // NOTE: Really this should algorithm should use round() rather than floor(), 25 | // but GLSL does not have a round() function. A simple replacement is to use 26 | // floor(some_number + 0.5) instead, which has the same effect as round(). 27 | // This is used in the code below. 28 | // 29 | // MIT License 30 | // 31 | // Copyright (c) 2017 Paul Hudson 32 | // https://www.github.com/twostraws/ShaderKit 33 | // 34 | // Permission is hereby granted, free of charge, to any person obtaining a copy 35 | // of this software and associated documentation files (the "Software"), to deal 36 | // in the Software without restriction, including without limitation the rights 37 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 38 | // copies of the Software, and to permit persons to whom the Software is 39 | // furnished to do so, subject to the following conditions: 40 | // 41 | // The above copyright notice and this permission notice shall be included in all 42 | // copies or substantial portions of the Software. 43 | // 44 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 46 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 47 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 48 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 49 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 50 | // SOFTWARE. 51 | // 52 | 53 | void main() { 54 | // figure out how big individual pixels are in texture space 55 | vec2 one_over_size = 1.0 / a_size; 56 | 57 | // now calculate the width of our pixelated effect by multiplying the provided density 58 | float pixel_x = u_strength * one_over_size.x; 59 | 60 | // and do the same for the pixel height 61 | float pixel_y = u_strength * one_over_size.y; 62 | 63 | // calculate the X pixel coordinate to read by dividing our original coordinate by the size 64 | // of one pixel, adding 0.5, then multiplying by the size of a pixel. 65 | float coord_x = pixel_x * floor(v_tex_coord.x / pixel_x + 0.5); 66 | 67 | // repeat for the Y pixel coordinate 68 | float coord_y = pixel_y * floor(v_tex_coord.y / pixel_y + 0.5); 69 | 70 | // read the new coordinate from our texture and send it back, , taking into 71 | // account node transparency 72 | gl_FragColor = texture2D(u_texture, vec2(coord_x, coord_y)) * v_color_mix.a; 73 | } 74 | -------------------------------------------------------------------------------- /Shaders/SHKRadialGradient.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Creates a radial gradient over the node. Either the start or the end color can be translucent to let original pixel colors come through. 3 | // Uniform: u_first_color, the SKColor to use at the center of the gradient 4 | // Uniform: u_second_color, the SKColor to use at the edge of the gradient 5 | // Uniform: u_center, a CGPoint representing the center of the gradient, where 0.5/0.5 is dead center 6 | // 7 | // This works by blending the first color with the second based on how far the pixel is from 8 | // the center of the circle. That's then blended with the original pixel color based on how 9 | // opaque the replacement color is, so that we can fade out to clear if needed. 10 | // 11 | // MIT License 12 | // 13 | // Copyright (c) 2017 Paul Hudson 14 | // https://www.github.com/twostraws/ShaderKit 15 | // 16 | // Permission is hereby granted, free of charge, to any person obtaining a copy 17 | // of this software and associated documentation files (the "Software"), to deal 18 | // in the Software without restriction, including without limitation the rights 19 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | // copies of the Software, and to permit persons to whom the Software is 21 | // furnished to do so, subject to the following conditions: 22 | // 23 | // The above copyright notice and this permission notice shall be included in all 24 | // copies or substantial portions of the Software. 25 | // 26 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | // SOFTWARE. 33 | // 34 | 35 | void main() { 36 | // get the color of the current pixel 37 | vec4 current_color = texture2D(u_texture, v_tex_coord); 38 | 39 | // the center of our circle 40 | vec2 circle_center = u_center; 41 | 42 | // how far our pixel is from the center of the circle, doubled and clamped so the range is 0.0 to 1.0 43 | float pixel_distance = min(1.0, distance(v_tex_coord, circle_center) * 2.0); 44 | 45 | // if the current color is not transparent 46 | if (current_color.a > 0.0) { 47 | // mix the first color with the second color by however far away we are, 48 | // multiplying by this pixel's alpha (to avoid a hard edge) and also 49 | // multiplying by the node alpha so we can fade in or out 50 | vec4 new_color = mix(u_first_color, u_second_color, pixel_distance); 51 | gl_FragColor = vec4(mix(current_color, new_color, new_color.a)) * current_color.a * v_color_mix.a; 52 | } else { 53 | // use the current (transparent) color 54 | gl_FragColor = current_color; 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /Shaders/SHKScanlines.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Applies an interlacing effect where horizontal lines of original color are separated by lines of another color 3 | // Attribute: a_size, the size of the node. 4 | // Uniform: u_width, the vertical width of the scanlines in pixels. float (e.g. 4). 5 | // Uniform: u_brightness, brightness of scanlines effect. Specify 0 (black) up to 1 (bright & saturated). float (e.g. 0.75) 6 | // Uniform: u_color, blend color of scanlines. color (e.g. .white) 7 | // 8 | // MIT License 9 | // 10 | // Copyright (c) 2017 Paul Hudson 11 | // https://www.github.com/twostraws/ShaderKit 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in all 21 | // copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | // SOFTWARE. 30 | // 31 | 32 | void main() { 33 | 34 | // 1. Pixelate vertically 35 | 36 | // figure out how big individual pixels are in texture space 37 | vec2 one_over_size = 1.0 / a_size; 38 | 39 | // and do the same for the pixel height 40 | float pixel_y = u_width * one_over_size.y; 41 | 42 | // calculate the Y pixel coordinate to read by dividing our original coordinate by the size 43 | // of one scanline, then multiplying by the size of a pixel. 44 | float coord_y = pixel_y * floor(v_tex_coord.y / pixel_y); 45 | 46 | // read the new coordinate from our texture and send it back, , taking into 47 | // account node transparency 48 | vec4 pixel_color = texture2D(u_texture, vec2(v_tex_coord.x, coord_y)) * v_color_mix.a; 49 | 50 | // 2. Now add scanlines 51 | 52 | // if the current color is not transparent 53 | if (pixel_color.a > 0.0) { 54 | // find this pixel's position in the texture 55 | float this_pixel = a_size[1] * v_tex_coord.y; 56 | 57 | // calculate the force of the scanline at this point 58 | // modulo of the pixel position against the scanline size dictates strength of line 59 | float scanlineForce = (mod(this_pixel, u_width) / u_width); 60 | float scanlineBrightness = (u_brightness * 2.0) - 1.0; 61 | 62 | // factor in brightness level and a little saturation (clamp output level between 0.3 and 1.0) 63 | scanlineForce = min(max(scanlineForce + scanlineBrightness, 0.3), 1.0); 64 | 65 | // interpolate the pixel color from black to input color using brightness factor 66 | vec4 scanlineColor = pixel_color * u_color; 67 | gl_FragColor = vec4(mix(vec4(0, 0, 0, v_color_mix.a), scanlineColor, scanlineForce)); 68 | } else { 69 | // use the current (transparent) color 70 | gl_FragColor = vec4(0, 0, 0, 0); 71 | } 72 | 73 | } 74 | 75 | -------------------------------------------------------------------------------- /Shaders/SHKScreen.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Applies an interlacing effect where horizontal and vertical lines of original color are separated by lines of another color 3 | // Attribute: a_size, the size of the node. 4 | // Uniform: u_width, the width of the interlacing lines. Ranges from 2 upwards work well. 5 | // Uniform: u_color, the SKColor to use for interlacing lines. Try starting with black. 6 | // Uniform: u_strength, how much to blend interlaced lines with u_color. Specify 0 (not at all) up to 1 (fully). 7 | // 8 | // This works using modulus: if the current pixel's position modulo twice the line width is less than the line 9 | // width then draw the original color. Otherwise blend the original color with the interlacing color based on 10 | // the user's provided strength. This is identical to the interlacing effect, except the modulus applies to 11 | // both X and Y coordinate. 12 | // 13 | // MIT License 14 | // 15 | // Copyright (c) 2017 Paul Hudson 16 | // https://www.github.com/twostraws/ShaderKit 17 | // 18 | // Permission is hereby granted, free of charge, to any person obtaining a copy 19 | // of this software and associated documentation files (the "Software"), to deal 20 | // in the Software without restriction, including without limitation the rights 21 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | // copies of the Software, and to permit persons to whom the Software is 23 | // furnished to do so, subject to the following conditions: 24 | // 25 | // The above copyright notice and this permission notice shall be included in all 26 | // copies or substantial portions of the Software. 27 | // 28 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 | // SOFTWARE. 35 | // 36 | 37 | void main() { 38 | // find the current pixel color 39 | vec4 current_color = SKDefaultShading(); 40 | 41 | // if the current color is not transparent 42 | if (current_color.a > 0.0) { 43 | // find this pixel's position in the texture 44 | vec2 this_pixel = a_size * v_tex_coord; 45 | 46 | // if we are an alternating line (vertically or horizontally) 47 | if (mod(this_pixel.x, u_width * 2.0) <= u_width || mod(this_pixel.y, u_width * 2.0) <= u_width) { 48 | // blend the original color with the provided color at whatever strength was requested, 49 | // multiplying by this pixel's alpha (to avoid a hard edge) and also multiplying by 50 | // the alpha for this node 51 | gl_FragColor = vec4(mix(current_color, u_color, u_strength)) * current_color.a * v_color_mix.a; 52 | } else { 53 | // render the original color, taking into account node transparency 54 | gl_FragColor = SKDefaultShading() * current_color.a * v_color_mix.a; 55 | } 56 | } else { 57 | // use the current (transparent) color 58 | gl_FragColor = current_color; 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /Shaders/SHKStaticGrayNoise.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Creates fixed grayscale noise. 3 | // 4 | // This works using a simple (but brilliant!) and well-known trick: if you 5 | // calculate the dot product of a texture coordinate with a vec2 containing 6 | // two numbers that are unlikely to repeat, then calculate the sine of that 7 | // and multiply it by a large number, you'll end up with what looks more or 8 | // less like random numbers in the fraction digits – i.e., everything after 9 | // the decimal place. 10 | // 11 | // This is perfect for our needs: those numbers will already range from 0 to 12 | // 0.99999... so we can use that for our color value by repeating it for each 13 | // of the RGB components. 14 | // 15 | // MIT License 16 | // 17 | // Copyright (c) 2017 Paul Hudson 18 | // https://www.github.com/twostraws/ShaderKit 19 | // 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy 21 | // of this software and associated documentation files (the "Software"), to deal 22 | // in the Software without restriction, including without limitation the rights 23 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | // copies of the Software, and to permit persons to whom the Software is 25 | // furnished to do so, subject to the following conditions: 26 | // 27 | // The above copyright notice and this permission notice shall be included in all 28 | // copies or substantial portions of the Software. 29 | // 30 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | // SOFTWARE. 37 | // 38 | 39 | float random(float offset, vec2 tex_coord) { 40 | // pick two numbers that are unlikely to repeat 41 | vec2 non_repeating = vec2(12.9898, 78.233); 42 | 43 | // multiply our texture coordinates by the non-repeating numbers, then add them together 44 | float sum = dot(tex_coord, non_repeating); 45 | 46 | // calculate the sine of our sum to get a range between -1 and 1 47 | float sine = sin(sum); 48 | 49 | // multiply the sine by a big, non-repeating number so that even a small change will result in a big color jump 50 | float huge_number = sine * 43758.5453 * offset; 51 | 52 | // get just the numbers after the decimal point 53 | float fraction = fract(huge_number); 54 | 55 | // send the result back to the caller 56 | return fraction; 57 | } 58 | 59 | void main() { 60 | // find the current pixel color 61 | vec4 current_color = SKDefaultShading(); 62 | 63 | // if it's not transparent 64 | if (current_color.a > 0.0) { 65 | // make a color where the RGB values are the same random number and A is 1; multiply by the node alpha so we can fade in or out 66 | gl_FragColor = vec4(vec3(random(1.0, v_tex_coord)), 1) * current_color.a * v_color_mix.a; 67 | } else { 68 | // use the (transparent) color 69 | gl_FragColor = current_color; 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /Shaders/SHKStaticRainbowNoise.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Creates fixed multi-colored noise. 3 | // 4 | // This works using a simple (but brilliant!) and well-known trick: if you 5 | // calculate the dot product of a texture coordinate with a vec2 containing 6 | // two numbers that are unlikely to repeat, then calculate the sine of that 7 | // and multiply it by a large number, you'll end up with what looks more or 8 | // less like random numbers in the fraction digits – i.e., everything after 9 | // the decimal place. 10 | // 11 | // This is perfect for our needs: those numbers will already range from 0 to 12 | // 0.99999... so we can use that for our color value by calling it once for each 13 | // of the RGB components. 14 | // 15 | // MIT License 16 | // 17 | // Copyright (c) 2017 Paul Hudson 18 | // https://www.github.com/twostraws/ShaderKit 19 | // 20 | // Permission is hereby granted, free of charge, to any person obtaining a copy 21 | // of this software and associated documentation files (the "Software"), to deal 22 | // in the Software without restriction, including without limitation the rights 23 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | // copies of the Software, and to permit persons to whom the Software is 25 | // furnished to do so, subject to the following conditions: 26 | // 27 | // The above copyright notice and this permission notice shall be included in all 28 | // copies or substantial portions of the Software. 29 | // 30 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | // SOFTWARE. 37 | // 38 | 39 | float random(float offset, vec2 tex_coord) { 40 | // pick two numbers that are unlikely to repeat 41 | vec2 non_repeating = vec2(12.9898, 78.233); 42 | 43 | // multiply our texture coordinates by the non-repeating numbers, then add them together 44 | float sum = dot(tex_coord, non_repeating); 45 | 46 | // calculate the sine of our sum to get a range between -1 and 1 47 | float sine = sin(sum); 48 | 49 | // multiply the sine by a big, non-repeating number so that even a small change will result in a big color jump 50 | float huge_number = sine * 43758.5453 * offset; 51 | 52 | // get just the numbers after the decimal point 53 | float fraction = fract(huge_number); 54 | 55 | // send the result back to the caller 56 | return fraction; 57 | } 58 | 59 | void main() { 60 | // find the current pixel color 61 | vec4 current_color = SKDefaultShading(); 62 | 63 | // if it's not transparent 64 | if (current_color.a > 0.0) { 65 | // make a color where the RGB values are different random numbers and A is 1; multiply by the node alpha so we can fade in or out 66 | gl_FragColor = vec4(random(1.23, v_tex_coord), random(5.67, v_tex_coord), random(8.90, v_tex_coord), 1) * current_color.a * v_color_mix.a; 67 | } else { 68 | // use the (transparent) color 69 | gl_FragColor = current_color; 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /Shaders/SHKWater.fsh: -------------------------------------------------------------------------------- 1 | // 2 | // Warps a textured node to create a water rippling effect. 3 | // NOTE: This must be applied to something that has a texture. 4 | // Uniform: u_speed, how many fast to make the water ripple. Ranges from 0.5 to 10 work best; try starting with 3. 5 | // Uniform: u_strength, how pronounced the rippling effect should be. Ranges from 1 to 5 work best; try starting with 3. 6 | // Uniform: u_frequency, how often ripples should be created. Ranges from 5 to 25 work best; try starting with 10. 7 | // 8 | // This works by using a nearby pixel color rather than the original pixel color. Which neighbour is 9 | // chosen depends on the algorithm: we pass the original coordinate, speed, and frequency 10 | // into the sin() and cos() functions to get different numbers between -1 and 1, then multiply 11 | // that by the user's strength parameter to see how far the neighbour pixel should be. 12 | // 13 | // MIT License 14 | // 15 | // Copyright (c) 2017 Paul Hudson 16 | // https://www.github.com/twostraws/ShaderKit 17 | // 18 | // Permission is hereby granted, free of charge, to any person obtaining a copy 19 | // of this software and associated documentation files (the "Software"), to deal 20 | // in the Software without restriction, including without limitation the rights 21 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | // copies of the Software, and to permit persons to whom the Software is 23 | // furnished to do so, subject to the following conditions: 24 | // 25 | // The above copyright notice and this permission notice shall be included in all 26 | // copies or substantial portions of the Software. 27 | // 28 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 | // SOFTWARE. 35 | // 36 | 37 | void main() { 38 | // bring both speed and strength into the kinds of ranges we need for this effect 39 | float speed = u_time * u_speed * 0.05; 40 | float strength = u_strength / 100.0; 41 | 42 | // take a copy of the current texture coordinate so we can modify it 43 | vec2 coord = v_tex_coord; 44 | 45 | // offset the coordinate by a small amount in each direction, based on wave frequency and wave strength 46 | coord.x += sin((coord.x + speed) * u_frequency) * strength; 47 | coord.y += cos((coord.y + speed) * u_frequency) * strength; 48 | 49 | // use the color at the offset location for our new pixel color 50 | gl_FragColor = texture2D(u_texture, coord) * v_color_mix.a; 51 | } 52 | --------------------------------------------------------------------------------