Snippets
Created by
Joseph Chow
last modified
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | // time is a global variable. Re-defining so it's a little less to type
#define time iGlobalTime
// define the maximum number of times we raymarch.
#define MAX_STEPS 100
// defines how close we can get before we've hit the scene
#define HOW_CLOSE 0.001
// defines how far the ray can go
#define FURTHEST_OUR_RAY_CAN_REACH 10.0
/**
* Defines a basic template for doing ray marching based on articles from
* @cabibbo,@iq and @nicoptere
*
* The variables defined and functions are for ShaderToy / OpenGL ES 2 but should be fairly
* portable to another context.
*
* This particular template starts off by drawing a yellow-orange sphere
*
* http://barradeau.com/blog/?p=575
* https://www.shadertoy.com/view/Xds3zN
* https://www.shadertoy.com/view/Xl2XWt
*/
/////////// UTILITY FUNCTIONS ///////////////
// This calculation basically gets a way for us to
// transform the rays coming out of our eyes and going through the window.
// aka - creating a camera
mat3 calculateEyeRayTransformationMatrix( in vec3 ro, in vec3 ta, in float roll )
{
vec3 ww = normalize( ta - ro );
vec3 uu = normalize( cross(ww,vec3(sin(roll),cos(roll),0.0) ) );
vec3 vv = normalize( cross(uu,ww));
return mat3( uu, vv, ww );
}
/////////// SHAPE FUNCTIONS ///////////////
//the signed-distance function to build a sphere
float sdSphere( vec3 p, float s )
{
return length(p)-s;
}
vec2 sdfBalloon( vec3 currentRayPosition ){
// First we define our balloon position
vec3 balloonPosition = vec3( 0.0 , 0.0 , -0.4 );
// than we define our balloon radius
float balloonRadius = 0.5;
// Here we get the distance to the surface of the balloon
float distanceToBalloon = length( currentRayPosition - balloonPosition );
// finally we get the distance to the balloon surface
// by substacting the balloon radius. This means that if
// the distance to the balloon is less than the balloon radius
// the value we get will be negative! giving us the 'Signed' in
// Signed Distance Field!
float distanceToBalloonSurface = distanceToBalloon - balloonRadius;
// Finally we build the full balloon information, by giving it an ID
float balloonID = 1.;
// And there we have it! A fully described balloon!
vec2 balloon = vec2( distanceToBalloonSurface, balloonID );
return balloon;
}
/////////// MAP ALL THE THINGS ///////////////
vec2 map(vec3 currentPos){
vec2 result;
vec2 balloon = sdfBalloon( currentPos );
result = balloon;
return result;
}
vec3 march(in vec3 ro, in vec3 rd ){
vec3 result = vec3(0.);
float min = HOW_CLOSE;
float max = FURTHEST_OUR_RAY_CAN_REACH;
float finalDistanceTraveledByRay = min;
float finalID = -1.0;
for( int i = 0; i < MAX_STEPS; i++ ){
//march something!
vec2 res = map( ro + rd * finalDistanceTraveledByRay );
//if we're less than 0, thats too far, so break
if(res.x < min || finalDistanceTraveledByRay > max){
break;
}
finalDistanceTraveledByRay += res.x;
finalID = res.y;
}
if(finalDistanceTraveledByRay > max){
finalID = -1.0;
}
result.x = finalDistanceTraveledByRay;
result.y = finalID;
return result;
}
// Calculates the normal direction so that we ca
vec3 getNormalOfSurface( in vec3 positionOfHit ){
vec3 tinyChangeX = vec3( 0.001, 0.0, 0.0 );
vec3 tinyChangeY = vec3( 0.0 , 0.001 , 0.0 );
vec3 tinyChangeZ = vec3( 0.0 , 0.0 , 0.001 );
float upTinyChangeInX = map( positionOfHit + tinyChangeX ).x;
float downTinyChangeInX = map( positionOfHit - tinyChangeX ).x;
float tinyChangeInX = upTinyChangeInX - downTinyChangeInX;
float upTinyChangeInY = map( positionOfHit + tinyChangeY ).x;
float downTinyChangeInY = map( positionOfHit - tinyChangeY ).x;
float tinyChangeInY = upTinyChangeInY - downTinyChangeInY;
float upTinyChangeInZ = map( positionOfHit + tinyChangeZ ).x;
float downTinyChangeInZ = map( positionOfHit - tinyChangeZ ).x;
float tinyChangeInZ = upTinyChangeInZ - downTinyChangeInZ;
vec3 normal = vec3(
tinyChangeInX,
tinyChangeInY,
tinyChangeInZ
);
return normalize(normal);
}
// Color some objects
vec3 colorTheWorld( in vec2 rayHitInfo , in vec3 eyePosition , in vec3 rayDirection ){
vec3 color = vec3(0.);
if(rayHitInfo.y < 0.0){
color = vec3(0.0,0.0,0.0);
}else {
vec3 positionOfHit = eyePosition + rayHitInfo.x * rayDirection;
vec3 normalOfSurface = getNormalOfSurface( positionOfHit );
if(rayHitInfo.y == 1.0){
vec3 sunPosition = vec3( 1. , 4. , 3. );
// the direction of the light goes from the sun
// to the position of the hit
vec3 lightDirection = sunPosition - positionOfHit;
// Here we are 'normalizing' the light direction
// because we don't care how long it is, we
// only care what direction it is!
lightDirection = normalize( lightDirection );
// getting the value of how much the surface
// faces the light direction
float faceValue = dot( lightDirection , normalOfSurface );
// if the face value is negative, just make it 0.
// so it doesn't give back negative light values
// cuz that doesn't really make sense...
faceValue = max( 0. , faceValue );
vec3 balloonColor = vec3( 1. , 1. , 0. );
// our final color is the balloon color multiplied
// by how much the surface faces the light
color = balloonColor * faceValue;
// add in a bit of ambient color
// just so we don't get any pure black
color += vec3( .3 , .1, .2 );
}
}
return color;
}
/////////// RUN ALL THE THINGS ///////////////
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 currentPixel = ( -iResolution.xy + 2.0 * fragCoord.xy ) / iResolution.y;
// We use the eye position to tell use where the viewer is
vec3 eyePosition = vec3( 0., 0., 2.);
// This is the point the view is looking at.
// The window will be placed between the eye, and the
// position the eye is looking at!
vec3 pointWeAreLookingAt = vec3( 0. , 0. , 0. );
//build the camera
mat3 cam = calculateEyeRayTransformationMatrix(eyePosition,pointWeAreLookingAt,0.0);
vec3 rayComingOutOfEyeDirection = normalize( cam * vec3( currentPixel.xy , 2. ) );
vec3 rayHitInfo = march( eyePosition , rayComingOutOfEyeDirection );
vec3 t = colorTheWorld(rayHitInfo.xy,eyePosition,rayComingOutOfEyeDirection);
fragColor = vec4(t,1.0);
//fragColor = vec4(currentPixel,0.5+0.5*sin(iGlobalTime),1.0);
}
|
Comments (0)
You can clone a snippet to your computer for local editing. Learn more.