forked from patriciogonzalezvivo/thebookofshaders
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 30dae04
Showing
179 changed files
with
28,968 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.DS_Store | ||
.dropbox | ||
*Icon* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# Introduction | ||
|
||
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas> | ||
|
||
The images above were made in different ways. The first one was made by Van Gogh's hand applying layer over layer of paint. It took him hours. The second was produced in seconds by the combination of four matrices of pixels: one for cyan, one for magenta, one for yellow and one for black. The key difference is that the second image is produced in a non-serial way (that means not step-by-step, but all at the same time). | ||
|
||
This book is about the revolutionary computational technique, *fragment shaders*, that is taking digitally generated images to the next level. You can think of it as the equivalent of Gutenberg's press for graphics. | ||
|
||
![Gutenberg's press](gutenpress.jpg) | ||
|
||
Fragment shaders give you total control over the pixels rendered on the screen at a super fast speed. This is why they're used in all sort of cases, from video filters on cellphones to incredible 3D video games. | ||
|
||
![Journey by The Game Company](journey.jpg) | ||
|
||
In the following chapters you will discover how incredibly fast and powerful this technique is and how to apply it to your professional and personal work. | ||
|
||
## Who is this book for? | ||
|
||
This book is written for creative coders, game developers and engineers who have coding experience, a basic knowledge of linear algebra and trigonometry, and who want to take their work to an exciting new level of graphical quality. (If you want to learn how to code, I highly recommend you start with [Processing](https://processing.org/) and come back later when you are comfortable with it.) | ||
|
||
This book will teach you how to use and integrate shaders into your projects, improving their performance and graphical quality. Because GLSL (OpenGL Shading Language) shaders compile and run on a variety of platforms, you will be able to apply what you learn here to any enviroment that uses OpenGL, OpenGL ES or WebGL. In other words, you will be able to apply and use your knowledge with [Processing](https://processing.org/) sketches, [openFrameworsk](http://openframeworks.cc/) applications, [Cinder](http://libcinder.org/) interactive installations, [Three.js](http://threejs.org/) websites or iOS/Android games. | ||
|
||
## What does this book cover? | ||
|
||
This book will focus on the use of GLSL pixel shaders. First we'll define what shaders are; then we'll learn how to make procedural shapes, patterns, textures and animations with them. You'll learn the foundations of shading language and apply it to more useful scenarios such as: image processing (image operations, matrix convolutions, blurs, color filters, lookup tables and other effects) and simulations (Conway's game of life, Gray-Scott's reaction-diffusion, water ripples, watercolor effects, Voronoi cells, etc.). Towards the end of the book we'll see a set of advanced techniques based on Ray Marching. | ||
|
||
*There are interactive examples for you to play with in every chapter.* When you change the code, you will see the changes immediately. The concepts can be abstract and confusing, so the interactive examples are essential to helping you learn the material. The faster you put the concepts into motion the easier the learning process will be. | ||
|
||
What this book doesn't cover: | ||
|
||
* This *is not* an openGL or webGL book. OpenGL/webGL is a bigger subject than GLSL or fragment shaders. To learn more about openGL/webGL I recommend taking a look at: [OpenGL Introduction](https://open.gl/introduction), [the 8th edition of the OpenGL Programming Guide](http://www.amazon.com/OpenGL-Programming-Guide-Official-Learning/dp/0321773039/ref=sr_1_1?s=books&ie=UTF8&qid=1424007417&sr=1-1&keywords=open+gl+programming+guide) (also known as the red book) or [WebGL: Up and Running](http://www.amazon.com/WebGL-Up-Running-Tony-Parisi/dp/144932357X/ref=sr_1_4?s=books&ie=UTF8&qid=1425147254&sr=1-4&keywords=webgl) | ||
|
||
* This *is not* a math book. Although we will cover a number of algorithms and techniques that rely on an understanding of algebra and trigonometry, we will not explain them in detail. For questions regarding the math I recommend keeping one of the following books nearby: [3rd Edition of Mathematics for 3D Game Programming and computer Graphics](http://www.amazon.com/Mathematics-Programming-Computer-Graphics-Third/dp/1435458869/ref=sr_1_1?ie=UTF8&qid=1424007839&sr=8-1&keywords=mathematics+for+games) or [2nd Edition of Essential Mathematics for Games and Interactive Applications](http://www.amazon.com/Essential-Mathematics-Games-Interactive-Applications/dp/0123742978/ref=sr_1_1?ie=UTF8&qid=1424007889&sr=8-1&keywords=essentials+mathematics+for+developers). | ||
|
||
## What do you need to start? | ||
|
||
Not much! If you have a modern browser that can do WebGL (like Chrome, Firefox or Safari) and a internet connection, click the “Next” Chapter button at the end of this page to get started. | ||
|
||
Alternatively, based on what you have or what you need from this book you can: | ||
|
||
- [Make a off-line version of this book](../90/) | ||
|
||
- [Run the examples on a RaspberryPi without a browser](../91/) | ||
|
||
- [Make a PDF of the book to print](../92/) | ||
|
||
- Use the [on-line repository](https://github.com/patriciogonzalezvivo/thebookofshaders) to help resolve issues and share code. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// Author: tsone | ||
// https://www.shadertoy.com/view/Mdf3Dn | ||
|
||
#ifdef GL_ES | ||
precision mediump float; | ||
#endif | ||
|
||
#define DOTSIZE 1.48 | ||
#define D2R(d) radians(d) | ||
#define MIN_S 07.5 | ||
#define MAX_S 15.0 | ||
#define SPEED 0.3 | ||
|
||
#define SST 0.888 | ||
#define SSQ 0.288 | ||
|
||
uniform sampler2D u_tex0; | ||
uniform vec2 u_resolution; | ||
uniform vec2 u_mouse; | ||
uniform float u_time; | ||
|
||
vec2 ORIGIN = 0.5*u_resolution.xy; | ||
float S = MIN_S+(MAX_S-MIN_S)*(0.5-0.5*cos(SPEED*u_time)); | ||
float R = SPEED*0.333*u_time; | ||
|
||
vec4 rgb2cmyki (in vec4 c) { | ||
float k = max(max(c.r,c.g),c.b); | ||
return min(vec4(c.rgb/k,k),1.0); | ||
} | ||
|
||
vec4 cmyki2rgb (in vec4 c) { | ||
return vec4(c.rgb*c.a,1.0); | ||
} | ||
|
||
vec2 px2uv (in vec2 px) { | ||
return vec2(px/(u_resolution.xy*vec2(1.0,2.0))-vec2(1.0,0.0) ); | ||
} | ||
|
||
vec2 grid (in vec2 px) { | ||
return px-mod(px,S); | ||
} | ||
|
||
vec4 ss(in vec4 v) { | ||
return smoothstep(SST-SSQ,SST+SSQ,v); | ||
} | ||
|
||
vec4 halftone (in vec2 fc,in mat2 m) { | ||
vec2 smp = (grid(m*fc)+0.5*S)*m; | ||
float s = min(length(fc-smp)/(DOTSIZE*0.5*S),1.0); | ||
vec4 c = rgb2cmyki(texture2D(u_tex0,px2uv(smp+ORIGIN))); | ||
return c+s; | ||
} | ||
|
||
mat2 rotm (in float r) { | ||
float cr = cos(r); | ||
float sr = sin(r); | ||
return mat2( | ||
cr,-sr, | ||
sr,cr | ||
); | ||
} | ||
|
||
void main() { | ||
vec2 st = gl_FragCoord.xy/u_resolution.xy; | ||
|
||
if (st.x > 0.5) { | ||
R = 3.14-(u_mouse.y/u_resolution.y)*(3.14/180.); | ||
S = 12.0-(u_mouse.x/u_resolution.x)*7.0; | ||
|
||
vec2 fc = gl_FragCoord.xy*2.0-ORIGIN; | ||
mat2 mc = rotm(R+D2R(15.0)); | ||
mat2 mm = rotm(R+D2R(75.0)); | ||
mat2 my = rotm(R); | ||
mat2 mk = rotm(R+D2R(45.0)); | ||
|
||
float k = halftone(fc,mk).a; | ||
vec4 c = cmyki2rgb(ss(vec4( | ||
halftone(fc,mc).r, | ||
halftone(fc,mm).g, | ||
halftone(fc,my).b, | ||
halftone(fc,mk).a | ||
))); | ||
|
||
gl_FragColor = c; | ||
} else { | ||
st = vec2(st.x,st.y*0.5)*2.0; | ||
gl_FragColor = texture2D(u_tex0,st); | ||
} | ||
|
||
|
||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#ifdef GL_ES | ||
precision mediump float; | ||
#endif | ||
|
||
uniform sampler2D u_tex0; | ||
uniform vec2 u_resolution; | ||
uniform vec2 u_mouse; | ||
|
||
float PI = 3.1415926535897932384626433832795; | ||
float PI180 = float(PI / 180.0); | ||
|
||
float sind (float a) { | ||
return sin(a * PI180); | ||
} | ||
|
||
float cosd (float a) { | ||
return cos(a * PI180); | ||
} | ||
|
||
float added (vec2 sh, float sa, float ca, vec2 c, float d) { | ||
return 0.5 + 0.25 * cos((sh.x * sa + sh.y * ca + c.x) * d) + 0.25 * cos((sh.x * ca - sh.y * sa + c.y) * d); | ||
} | ||
|
||
void main () { | ||
|
||
float threshold = clamp(0.5, 0.0, 1.0); | ||
|
||
vec2 st = gl_FragCoord.xy/u_resolution.xy; | ||
|
||
if (st.x > 0.5) { | ||
// Halftone dot matrix shader | ||
// @author Tomek Augustyn 2010 | ||
|
||
// Ported from my old PixelBender experiment | ||
// https://github.com/og2t/HiSlope/blob/master/src/hislope/pbk/fx/halftone/Halftone.pbk | ||
float ratio = u_resolution.y / u_resolution.x; | ||
|
||
vec2 dstCoord = vec2(st.x-0.5, st.y*0.5)*2.0; | ||
vec2 srcCoord = vec2(st.x-0.5, st.y*0.5)*2.0; | ||
vec2 rotationCenter = vec2(0.5); | ||
vec2 shift = dstCoord - rotationCenter; | ||
|
||
float dotSize = 5.0; | ||
float angle = 45.0; | ||
|
||
float rasterPattern = added(shift, sind(angle), cosd(angle), rotationCenter, PI / dotSize * 680.0); | ||
vec4 srcPixel = texture2D(u_tex0, srcCoord); | ||
|
||
float avg = 0.2125 * srcPixel.r + 0.7154 * srcPixel.g + 0.0721 * srcPixel.b; | ||
float gray = (rasterPattern * threshold + avg - threshold) / (1.0 - threshold); | ||
|
||
// uncomment to see how the raster pattern looks | ||
// gray = rasterPattern; | ||
|
||
gl_FragColor = vec4(gray, gray, gray, 1.0); | ||
} else { | ||
st = vec2(st.x,st.y*0.5)*2.0; | ||
gl_FragColor = texture2D(u_tex0, st); | ||
} | ||
|
||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<!-- Copyright 2015 Patricio Gonzalez Vivo (http://patriciogonzalezvivo.com) --> | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>About this Book</title> | ||
<meta name="keywords" content="shader,shaders,GLSL,book" /> | ||
<meta name="description" content="This is a gentle step-by-step guide through the abstract and complex universe of Fragment Shaders." /> | ||
|
||
<!-- CodeMirror --> | ||
<link type='text/css' rel='stylesheet' href="../src/codemirror/css/codemirror.css"> | ||
<link type='text/css' rel="stylesheet" href="../src/codemirror/addon/fold/foldgutter.css"> | ||
<link type='text/css' rel="stylesheet" href="../src/codemirror/addon/dialog/dialog.css"> | ||
<link type='text/css' rel="stylesheet" href="../src/codemirror/addon/hint/show-hint.css"> | ||
<link type='text/css' rel="stylesheet" href="../src/codemirror/theme/neo.css"> | ||
<script type="text/javascript" src="../src/codemirror.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/addon/search/searchcursor.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/addon/search/search.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/addon/dialog/dialog.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/addon/edit/matchbrackets.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/addon/edit/closebrackets.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/addon/comment/comment.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/addon/wrap/hardwrap.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/addon/fold/foldcode.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/addon/fold/brace-fold.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/keymap/sublime.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/addon/hint/show-hint.js"></script> | ||
<script type="text/javascript" src="../src/codemirror/mode/clike.js"></script> | ||
|
||
<!-- Highlight --> | ||
<link type='text/css' rel='stylesheet' href="../css/github.css"> | ||
<script type="text/javascript" src="../src/highlight.min.js"></script> | ||
|
||
<!-- Marked --> | ||
<script type="text/javascript" src="../src/marked.js"></script> | ||
|
||
<!-- My stuff --> | ||
<link type='text/css' rel='stylesheet' href="../css/style.css"> | ||
<script type="text/javascript" src="../src/glslCanvas.js"></script> | ||
|
||
</head> | ||
<body> | ||
|
||
<div class="header"><p><a href="http://patriciogonzalezvivo.com/2015/thebookofshaders/">The Book of Shaders</a> by <a href="http://patriciogonzalezvivo.com">Patricio Gonzalez Vivo</a></p></div> | ||
<hr> | ||
<div id="content"> </div> | ||
<hr> | ||
<ul class="navigationBar" > | ||
<li class="navigationBar" onclick="homePage()">< < Previous</li> | ||
<li class="navigationBar" onclick="homePage()"> Home </li> | ||
<li class="navigationBar" onclick="nextPage()">Next > ></li> | ||
</ul> | ||
<footer> | ||
<p> Copyright 2015 <a href="http://www.patriciogonzalezvivo.com" target="_blank">Patricio Gonzalez Vivo</a> </p> | ||
</footer> | ||
|
||
<script type="text/javascript" src="../src/main.js" defer></script> | ||
<script> | ||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ | ||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), | ||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) | ||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); | ||
|
||
ga('create', 'UA-18824436-2', 'auto'); | ||
ga('send', 'pageview'); | ||
|
||
</script> | ||
</body> | ||
</html> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# Getting started | ||
## What is a fragment shader? | ||
|
||
In the previous chapter we described shaders as the equivalent of the Gutenberg press for graphics. Why? And more importantly: what's a shader? | ||
|
||
![From Leter-by-Leter, Right: William Blades (1891). To Page-by-page, Left: Rolt-Wheeler (1920).](print.png) | ||
|
||
If you already have experience making drawings with computers, you know that in that process you draw a circle, then a rectangle, a line, some triangles until you compose the image you want. That process is very similar to writing a letter or a book by hand - it is a set of instructions that do one task after another. | ||
|
||
Shaders are also a set of instructions, but the instructions are excecuted all at once for every single pixel on the screen. That means the code you write has to behave differently depending on the position of the pixel on the screen. Like a type press, your program will work as a function that receives a position and returns a color, and when it's compiled it will run extraordinarily fast. | ||
|
||
![Chinese movable type](typepress.jpg) | ||
|
||
## Why are shaders fast? | ||
|
||
To answer this, I present the wonders of *parallel processing*. | ||
|
||
Imagine the CPU of your computer as a big industrial pipe, and every task as something that passes through it - like a factory line. Some tasks are bigger than others, which means they require more time and energy to deal with. We say they require more processing power. Because of the architecture of computers the jobs are forced to run in a series; each job has to be finished one at a time. Modern computers usually have groups of four processors that work like these pipes, completing tasks one after another to keeping things running smoothly. Each pipe is also known as *thread*. | ||
|
||
![CPU](00.jpeg) | ||
|
||
Video games and other graphic applications require a lot more processing power than other programs. Because of their graphic content they have to do huge numbers of pixel-by-pixel operations. Every single pixel on the screen needs to be computed, and in 3D games geometries and perspectives need to be calculated as well. | ||
|
||
Let's go back to our metaphor of the pipes and tasks. Each pixel on the screen represents a simple small task. Individually each pixel task isn't an issue for the CPU, but (and here is the problem) the tiny task has to be done to each pixel on the screen! That means in an old 800x600 screen, 480,000 pixels have to processed per frame which means 14,400,000 calculations per second! Yes! That’s a problem big enough to overload a microprocessor. In a modern 2880x1800 retina display running at 60 frames per second that calculation adds up to 311,040,000 calculations per second. How do graphics engineers solve this problem? | ||
|
||
![](03.jpeg) | ||
|
||
This is when parallel processing becomes a good solution. Instead of having a couple of big and powerful microprocessors, or *pipes*, it is smarter to have lots of tiny microprocessors running in parallel at the same time. That’s what a Graphic Processor Unit (GPU) is. | ||
|
||
![GPU](04.jpeg) | ||
|
||
Picture the tiny microprocessors as a table of pipes, and the data of each pixel as a ping pong ball. 14,400,000 ping pong balls a second can obstruct almost any pipe. But a table of 800x600 tiny pipes receiving 30 waves of 480,000 pixels a second can be handled smoothly. This works the same at higher resolutions - the more parallel hardware you have, the bigger the stream it can manage. | ||
|
||
Another “super power” of the GPU is special math functions accelerated via hardware, so complicated math operations are resolved directly by the microchips instead of by software. That means extra fast trigonometrical and matrix operations - as fast as electricity can go. | ||
|
||
## What is GLSL? | ||
|
||
GLSL stands for openGL Shading Language, which is the specific standard of shader programs you'll see in the following chapters. There are other types of shaders depending on hardware and Operating Systems. Here we will work with the openGL specs regulated by [Khronos Group](https://www.khronos.org/opengl/). Understanding the history of OpenGL can be helpful for understanding most of its weird conventions, for that I recommend taking a look at: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html) | ||
|
||
## Why are Shaders famously painful? | ||
|
||
As Uncle Ben said “with great power comes great responsibility,” and parallel computation follows this rule; the powerful architectural design of the GPU comes with its own constrains and restrictions. | ||
|
||
In order to run in parallel every pipe, or thread, has to be independent from every other thread. We say the threads are *blind* to what the rest of the threads are doing. This restriction implies that all data must flow in the same direction. So it’s impossible to check the result of another thread, modify the input data, or pass the outcome of a thread into another thread. Allowing thread-to-thread communications puts the integrity of the data at risk. | ||
|
||
Also the GPU keeps the parallel micro-processor (the pipes) constantly busy; as soon as they get free they receive new information to processes. It's impossible for a thread to know what it was doing in the previous moment. It could be drawing a button from the UI of the operating system, then rendering a portion of sky in a game, then displaying the text of an email. Each thread is not just **blind** but also **memoryless**. Besides the abstraction require to code a general function that changes the result pixel by pixel depending on its position, the blind and memoryless constraints make shaders not very popular among beginning programmers. | ||
|
||
Don't worry! In the following chapters, we will learn step-by-step how to go from simple to advanced shading computations. If you are reading this with a modern browser, you will appreciate playing with the interactive examples. So let's not delay the fun any longer and press *Next >>* to jump into the code! |
Oops, something went wrong.