raymarch_sphere_shaded.fsh
4.41 KB
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
/*
* Fragment shader for textured quad
*/
varying mediump vec2 vTexCoord;
varying mediump vec2 vRayCastCoord;
uniform mediump float uRadius;
uniform mediump float uAdjuster;
#define CAMERA_Z_POSITION 1.0 // gives us a FOV of 90 degrees if Plane of projection is at Z = 0 with size 2x2
#define SPHERE_Z_POSITION -1.0 // Sphere placed behind Plane of projection
#define SPHERE_RADIUS 0.5
// signed distance function
// returns
// < 0 if inside sphere
// 0 == on sphere surface
// > 1 if outside sphere
mediump float distanceToSphere( mediump vec3 point, mediump vec3 sphereCenter, mediump float radius )
{
return distance( point, sphereCenter ) - radius;
}
// Simulate a simple spot light ( there's no ambient light in this example)
mediump vec4 lightSphere( mediump vec3 point, mediump vec3 sphereCenter )
{
// the normal = direction of the vector from the sphere center to the point on the surface of the sphere
mediump vec3 normal = normalize( point - sphereCenter );
// Animate the light around the sphere in a circular motion
mediump vec3 lightDirection = vec3( sin(uAdjuster)+uRadius, cos ( uAdjuster )+uRadius, CAMERA_Z_POSITION );
// calculate the dot product to give us the intensity of the light bouncing off the surface
mediump float value = dot( normal , lightDirection);
// add a purple tint to the final color by adjust green channel by 0.84
return vec4( value, value * 0.843, value , 1.0);
}
void main()
{
// The fragment shader is called for every pixel that is to be drawn for our
// quad geometry ( 2 triangles ). The size and number of pixels drawn is
// determined by the size / position of the quad and the DALi camera position.
//
// For this example the vRayCastCoord is currently set to the range -1 to 1 by the Vertex Shader
//
// (-1,-1)
// |--------------|
// | | |
// | | |
// |_____(0,0)____|
// | | |
// | | |
// |_______|______|(1,1)
mediump vec3 pixelPosition = vec3( vRayCastCoord, 0.0 );
// uncomment line below to see red / green colors only visible when x > 0, or y > 0
// gl_FragColor = vec4( pixelPosition, 1.0 ); return;
// We are going to assume there is a virtual camera infront of the plane of projection
// Side view:
// projection
// plane (2x2)
// /|
// / |
// / | /----\
// Camera---->| (SPHERE)
// \ | \----/
// \ |
// \|
// z=1 z=0 z = -1
//
//
// Why z=1 for camera? Our projection plane is at z = 0, with plane size 2x2 which gives a 90 degree FOV
// from the camera to the projection plane
//
mediump vec3 cameraPos = vec3( 0.0, 0.0, CAMERA_Z_POSITION );
// calculate the ray direction from the camera to the pixel on the quad
mediump vec3 rayDirection = normalize( pixelPosition - cameraPos );
// uncomment to visualize the normalized ray direction vector
// gl_FragColor = vec4( rayDirection, 1.0 ); return;
// Setup the position on radius of our virtual sphere
mediump vec3 spherePosition = vec3( 0.0, 0.0, SPHERE_Z_POSITION );
mediump float sphereRadius = SPHERE_RADIUS + uRadius ; // use uRadius to animate radius from small to large
// We have the direction of the ray from the camera, now see if it
// hits our sphere using ray marching
// starting at a pixel position 0 on our projection plane, step in the direction
// of ray from the camera to see if it hits our sphere
// The concept of ray marching is the step size = minimum distance to an object
mediump vec3 hitPoint = pixelPosition;
int steps = 5;
for( int i = 0; i < steps ; ++i )
{
// calculate the shortest distance between our hitPoint and the sphere
mediump float distance = distanceToSphere( hitPoint, spherePosition, sphereRadius );
// if the distance < 0 then were inside the sphere
// if the distance > 0 then were outside the sphere
// if we're close to the edge of the sphere, then draw it
if( distance < 0.01 )
{
gl_FragColor = lightSphere( hitPoint, spherePosition );
return;
}
// move the hit point along by the distance to the spin the direction of the ray
hitPoint += rayDirection * distance;
}
// no hit, color the pixel based on it's x,y position
gl_FragColor = vec4(pixelPosition.x,pixelPosition.y,0.5,1);
}