├── .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 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
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 | [](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 |
--------------------------------------------------------------------------------