summaryrefslogtreecommitdiffhomepage
path: root/osl.html.markdown
blob: a412ba00e05d698641c6dfe91bbb6f750cca8c52 (plain)
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
---
language: osl
filename: learnosl.osl
contributors:
  - ["Preetham Pemmasani", "https://github.com/Preetham-ai"]
---

OSL (Open Shading Language) is a programming language designed by Sony for Arnold Renderer used for creating shaders.

[Read more here.](https://raw.githubusercontent.com/imageworks/OpenShadingLanguage/master/src/doc/osl-languagespec.pdf)

```c
// Single-line comments start with //

/* Multi line comments are preserved. */

// Statements can be terminated by ;
divide(1,2);

///////////////
// 1. Basics //
///////////////

// Declating variables
color Blue; // Initializing a variable
int _num = 3;
float Num = 3.00;
float c[3] = {0.1, 0.2, 3.14}; // Array

// Math works as you would expect
3 + 1;   // 4
74 - 3;   // 71
20 * 2; // 40
75/3;  // 25.0

// And modulo division only works with integers
10 % 2; // 0
31 % 4; // 1

// Bitwise operations only works with integers
- 0 // 1 (Unary Negation)
~ 00100011 // 11011100 (bitwise Compliment)
1 << 2; // 4 (shift Left)
12 >> 1; // 3 (shift Right)
1 & 0; // 0 (bitwise AND)
1 | 0; // 1 (bitwise OR)
1 ^ 1; // 0 (bitwise XOR)

// We also have booleans
true;
false;

// Booleans can't be compared to integers
true == 1 // Error
false == 0 // Error

// Negation uses the ! symbol
!0; // 1
!1; // 0
!2; // 0
//... and so on

// Relation Operators are defined like:
0 == 0 // true (equal to)
0 != 1 // true (not equal to)
5 < 3 // false (less then)
3 <= 3 // true (less than or equal to)
69 > 69 // false (greater than)
99 >= 52 // true (greater than or equal)


// Functions are same as C and C++
float sum(float a, float b){
	return a+b;
}

int subtract(int a, int b){
	return a-b;
}

sum(2,3); // 5

////////////////
// 2. Shaders //
////////////////

// Shaders explain the custom behavior of materials and light
// Shader's syntax is similar to the main function in C
// The inputs and the outputs should be initialized to default types
shader multiply(float a = 0.0,
				float b = 0.0, 
				output float c = 0.0){
    c = a*b;
}

// Double brackets[[ ]] is used to classify metadata of a shader
surface plastic
	[[ string help = "Realistic wood shader" ]]
(
	color Plastic = color (0.7, 0.5, 0.3) [[ string help = "Base color" ]],
	float Reflectivity = 0.5 [[ float min = 0, float max = 1 ]],
){...}

///////////////////////////////////////
// Metadata Types
///////////////////////////////////////

[[ string label = "IOR" ]] // Display-name in UI of the parameter
[[ string help = "Change Refractive Index" ]] // Info about the parameter
[[ string help = "widget" // Gives widgets to input the parameter
	string widget = "number" ]] // input float or int
	string widget = "string" ]] // String input
	string widget = "boolean" ]] // yes/no (or) 1/0
	string widget = "popup", options = "smooth|rough" ]] // Drop-down list
	// enum Drop-down list can also be made
	string widget = "mapper", options = "smooth:0|rough:1" ]]
	string widget = "filename" ]] // Input files externally
	string widget = "null" ]] // null input

[[ float min = 0.0 ]] // Minimum value of parameter
[[ float max = 0.5 ]] // Maximum value of parameter
[[ int slider = 3.0   // Adds a slider as an input
	int slidermin = -1]] // minimum value of the slider
	int slidermax = 3]] // maximum value of the slider
	int slidercenter = 2]] // origin value of the slider

[[ float sensitivity = 0.5 ]] // step size for incrementing the parameter
[[ string URL = www.example.com/ ]] // URL of shader's documentation 

	

// There are different types of shaders

/* Surface shaders determine the basic material properties of a surface and
how it reacts to light */
// Light shaders are a type of SURFACE shaders used for emissive objects.
// Displacement shaders alter the geometry using position and normals.
// Volume shaders adds a medium like air/smoke/dust into the scene.

volume multiply(float a = 0.0, float b = 0.0, output float c = 0.0){
    c = 2*a+b; 
}

////////////////////////////////////////
// 3. Data Types and Global Variables //
////////////////////////////////////////

// Data Types

// 1. The void type indicates a function that doesn't return any value

// 2. int (Integer)
	int x = -12; // Minimum size of 32-bits
	int new2 = 0x01cf; // Hexadecimal can also be specified

	///////////////////////////////////////
	// Order of Evaluation
	///////////////////////////////////////

	// From top to bottom, top has higher precedence
	//--------------------------//
	//        Operators         //
	//--------------------------//
	// int++, int--             //
	// ++ int --int - ~ !       //
	// * / %                    //
	// + -                      //
	// << >>                    //
	// < <= > >=                //
	// == !=                    //
	// &                        //
	// ^                        //
	// |                        //
	// &&                       //
	// ||                       //
	// ?:                       //
	// = += -= *= /=            //
	//--------------------------//

// 3. float (Floating-point number)
	float A = 2.3; // minimum  IEEE 32-bit float
	float Z = -4.1e2; // Z = -4.1 * 10^2

	// Order of evaluation is similar to int.
	// Operations like ( ~ ! % << >> ^ | & && || ) aren't available in float

// 4. string
	// The syntax is similar to C
	string new = "Hello World";
	// some Special characters:
	/*
	'\"'; // double quote
	'\n'; // newline character
	'\t'; // tab character (left justifies text)
	'\v'; // vertical tab
	'\\'; // back slash
	'\r'; // carriage return
	'\b'; // backspace character
	*/

	// Strings are concatenated with whitespace
	"Hello " "world!"; // "Hello world!"
	// concat function can also be used
	string concat ("Hello ","World!"); // "Hello world!"

	// printf function is same as C
	int i = 18;
	printf("I am %d years old",i); // I am 18 years old

	// String functions can alse be used
	int strlen (string s); // gives the length of the string
	int len = strlen("Hello, World!"); // len = 13

	// startswith returns 1 if string starts with prefix, else returns 0
	int starts = startswith("The quick brown fox", "The"); // starts = 1

	// endswith returns 1 if string starts with suffix, else returns 0
	int ends = endswith("The quick brown fox", "fox"); // ends will be 1

// 5. color (Red, Green, Blue)
	color p = color(0,1,2); // black
	color q = color(1); // white ( same as color(1,1,1) )
	color r = color("rgb", 0.23, 0.1, 0.8); // explicitly specify in RGB
	color s = color("hsv", 0.23, 0.1, 0.8); // specify in HSV
	// HSV stands for (Hue, Saturation, Luminance)
	// HSL stands for (Hue, Saturation, Lightness)
	// YIQ, XYZ and xyY formats can also be used
	// We can also access the indivudual values of (R,G,B)
	float Red = p[0]; // 0 (access the red component)
	float Green = p[1]; // 1 (access the green component)
	float Blue = p[2]; // 2 (access the blue component)

	// They can also be accessed like this
	float Red = p.r; // 0 (access the red component)  
	float Green = p.g; // 1 (access the green component) 
	float Blue = p.b; // 2 (access the blue component)

	// Math operators work like this with decreasing precedence
	color C = (3,2,3) * (1,0,0); // (3, 0, 0)
	color D = (1,1,1) * 255; // (255, 255, 255)
	color E = (25,5,125) / 5; // (5, 1, 25)
	color F = (30,40,50) / (3,4,5); // (10, 10, 10)
	color A = (1,2,3) + (1,0,0); // (2, 2, 3)
	color B = (1,2,3) - (1,0,0); // (0, 2, 3)
	// Operators like ( - == != ) are also used

	// Color Functions
	color blackbody (1500) // Gives color based on temperature (in Kelvin)
	float luminance (0.5, 0.3, 0.8) // 0.37 gives luminance cd/m^2
	// Luminance is calculated by 0.2126R+0.7152G+0.0722B
	color wavelength color (700) // (1, 0, 0) Gives color based on wavelength
	color transformc ("hsl", "rgb") // converts one system to another

// 6. point (x,y,z) is position of a point in the 3D space
// 7. vector (x,y,z) has length and direction but no position
// 8. normal (x,y,z) is a special vector perpendicular to a surface
	// These Operators are the same as color and have the same precedence
	L = point(0.5, 0.6, 0.7);
	M = vector(30, 100, 70);
	N = normal(0, 0, 1);

	// These 3 types can be assigned to a coordinate system
	L = point("object", 0.5, 0.6, 0.7); // relative to local space
	M = vector("common", 30, 100, 70); // relative to world space
	// There's also ("shader", "world", "camera", "screen", "raster", "NDC")

	float x = L[0]; // 0.5 (access the x-component)  
	float y = L[1]; // 0.6 (access the y-component)  
	float z = L[2]; // 0.7 (access the z-component)

	// They can also be accessed like this
	float x = M.x; // 30 (access the x-component)
	float y = M.y; // 100 (access the y-component)
	float z = M.z; // 70 (access the z-component)

	float a = dot ((1,2,3), (1,2,3)); // 14 (Dot Product)
	vector b = cross ((1,2,3), (1,2,3)); // (0,0,0) (Cross Product)
	float l = length(L); // 1.085 (length of vector)
	vector normalize (vector L); // (0.460, 0.552, 0.644) Normalizes the vector

	point p0 = point(1, 2, 3);
	point p1 = point(4, 5, 6);
	point Q = point(0, 0, 0);

	// Finding distance between two points
	float len = distance(point(1, 2, 3), point(4, 5, 6)); // 5.196
	// Perpendicular distance from Q to line joining P0 and P1
	float distance (point P0, point P1, point Q); // 2.45


// 9. matrix
	// Used for transforming vectors between different coordinate systems.
	// They are usually 4x4 (or) 16 floats
	matrix zero = 0; // makes a 4x4 zero matrix
	/* 0.0, 0.0, 0.0, 0.0,
       0.0, 0.0, 0.0, 0.0,
       0.0, 0.0, 0.0, 0.0,
       0.0, 0.0, 0.0, 0.0 */
	
	matrix ident = 1; // makes a 4x4 identity matrix
	/* 1.0, 0.0, 0.0, 0.0,
	   0.0, 1.0, 0.0, 0.0,
	   0.0, 0.0, 1.0, 0.0,
	   0.0, 0.0, 0.0, 1.0 */
		
	matrix m = 7; // Maked a 4x4 scalar matrix with scaling factor of 7
	/* 7.0, 0.0, 0.0, 0.0,
	   0.0, 7.0, 0.0, 0.0,
	   0.0, 0.0, 7.0, 0.0,
	   0.0, 0.0, 0.0, 7.0 */
	
	float x = m[1][1]; // 7
	
	// matrices can be constructed using floats in row-major order
	// matrices are usually 4x4 with 16 elements
	matrix myMatrix = matrix(1.0, 0.0, 0.0, 0.0,    // Row 1
                             0.0, 2.0, 0.0, 0.0,    // Row 2
                             0.0, 0.0, 3.0, 0.0,    // Row 3
                             0.0, 0.0, 0.0, 4.0);	// Row 4

	// matrix transformations are easy to implement
	matrix a = matrix ("shader", 1); // converted shader to common
	matrix m = matrix ("object", "world"); // converted object to world

	// Operations that can be used with decreasing precedence are:
	// ( - * / == !=)

	float determinant (matrix M) // 24 (returns the determinant of the matrix)
	float transpose (matrix M) // returns the transpose of the matrix
	/* 1.0, 0.0, 0.0, 0.0,
       0.0, 2.0, 0.0, 0.0,
       0.0, 0.0, 3.0, 0.0,
       0.0, 0.0, 0.0, 4.0 */

// 10. array 
	// Arrays in OSL are similar to C
	float a[5]; // initialize array a with size 5
	int b[3] = {90,80,70}; // declare array with size 3
	int len = arraylength(b); // 3
	int f = b[1]; // 80
	float anotherarray[3] = b; // arrays can be copied if same type

// 11. struct (Structures)
	// Structures in OSL are similar to C and C++.
	struct RGBA { // Defining a structure
		color rgb;
		float alpha;
	};

	
	RGBA col; // Declaring a structure
	RGBA b = { color(0.1, 0.2, 0.3), 1 }; // Can also be declared like this

	r.rgb = color (1, 0, 0); // Assign to one field
	color c = r.rgb; // Read from a structure field

// 12. closure
	// Closure is used to store data that aren't considered when it executes.
	// It cannot be manipulated or read.
	// A null closure can always be assigned.
	// OSL currently only supports color as their closure.

	// A few examples of closures are:

	// Diffuse BSDF closures:
	closure color oren_nayar_diffuse_bsdf(normal N, color alb, float roughness)
	closure color burley_diffuse_bsdf(normal N, color alb, float roughness);

	// Dielectric BSDF closure:
	closure color dielectric_bsdf(normal N, vector U, color reflection_tint,
	    color transmission_tint, float roughness_x, float roughness_y,
	    float ior, string distribution);

	// Conductor BSDF closure:
	closure color conductor_bsdf(normal N, vector U, float roughness_x,
	    float roughness_y, color ior, color extinction, string distribution);

	// Generalized Schlick BSDF closure:
	closure color generalized_schlick_bsdf(normal N, vector U,
	    color reflection_tint, color transmission_tint,
	    float roughness_x, float roughness_y, color f0, color f90,
	    float exponent, string distribution);

	// Translucent BSDF closure:
	closure color translucent_bsdf(normal N, color albedo);

	// Transparent BSDF closure:
	closure color transparent_bsdf();

	// Subsurface BSSRDF closure:
	closure color subsurface_bssrdf();

	// Sheen BSDF closure:
	closure color sheen_bsdf(normal N, color albedo, float roughness);

	// Anisotropic VDF closure: (Volumetric)
	closure color anisotropic_vdf(color albedo, color extinction,
	    float anisotropy);

	// Medium VDF closure: (Volumetric)
	closure color medium_vdf(color albedo, float transmission_depth,
	    color transmission_color, float anisotropy, float ior, int priority);

	closure color uniform edf(color emittance); // Emission closure
	closure color holdout(); // Holdout Hides objects beneath it

	// BSDFs can be layered using this closure
	closure color layer (closure color top, closure color base);



// Global Variables
// Contains info that the renderer knows
// These variables need not be declared

point P // Position of the point you are shading
vector I // Incident ray direction from viewing position to shading position
normal N // Normal of the surface at P
normal Ng // Normal of the surface at P irrespective of bump mapping
float u // UV 2D x - parametric coordinate of geometry
float v // UV 2D y - parametric coordinate of geometry
vector dPdu // change of P with respect to u tangent to the surface
vector dPdv // change of P with respect to v tangent to the surface
float time // Current time
float dtime // Time covered
vector dPdtime // change of P with respect to time

/////////////////////
// 4. Control flow //
/////////////////////

// Conditionals in OSL are just like in C or C++.

// If/Else
if (5>2){
	int x = s;
	int l = x;
}
else{
	int x = s + l; 
}

// 'while' loop
int i = 0;
while (i < 5) {
    i += 1;
    printf("Current value of i: %d\n", i);
}

// 'do-while' loop is where test happens after the body of the loop
int i = 0;
do {
    printf("Current value of i: %d\n", i);
    i += 1;
} while (i < 5);

// 'for' loop
for (int i = 0; i < 5; i += 1) {
    printf("Current value of i: %d\n", i);
}

/////////////////////
// 5. Functions //
/////////////////////

// Math Constants
	M_PI // π
	M_PI_35 // π/35
	m_E // e
	M_LN2 // ln 2
	M_SQRT2 // √2
	M_SQRT1_2 // √(1/2)

// Geometry Functions
	vector N = vector(0.1, 1, 0.2); // Normal vector
	vector I = vector(-0.5, 0.2, 0.8); // Incident vector

	// Faceforward tells the direction of vector
	vector facing_dir = faceforward(N, I); // facing_dir = (-0.5, 0.2, 0.8)

	// faceforward with three arguments
	vector ref = vector(0.3, -0.7, 0.6); // Reference normal
	facing_dir = faceforward(N, I, ref); // facing_dir = (0.5, -0.2, -0.8)

	// reflect gives the reflected vector along normal
	vector refl = reflect(I, N); // refl = (-0.7, -0.4, 1.4)\

	// refract gives the refracted vector along normal
	float ior = 1.5; // Index of refraction
	vector refr = refract(I, N, ior); // refr = (-0.25861, 0.32814, 0.96143)

	/* Fresnel computes the Reflection (R) and Transmission (T) vectors, along
	with the scaling factors for reflected (Kr) and transmitted (Kt) light. */
	float Kr, Kt;
	vector R, T;
	fresnel(I, N, ior, Kr, Kt, R, T);
/* Kr = 0.03958, Kt = 0.96042
	R = (-0.19278, -0.07711, 0.33854)
	T = (-0.25861, 0.32814, 0.96143) */

	// Rotating a point along a given axis
	point Q = point(1, 0, 0);
	float angle = radians(90); // 90 degrees
	vector axis = vector(0, 0, 1);
	point rotated_point = rotate(Q, angle, axis);
	// rotated_point = point(0, 1, 0)

	// Rotating a point along a line made by 2 points
	point P0 = point(0, 0, 0);
	point P1 = point(1, 1, 0);
	angle = radians(45); // 45 degrees
	Q = point(1, 0, 0);
	rotated_point = rotate(Q, angle, P0, P1);
	// rotated_point = point(0.707107, 0.707107, 0)

	// Calculating normal of surface at point p
	point p1 = point(1, 0, 0); // Point on the sphere of radius 1
	vector normal1 = calculatenormal(p1);
	// normal1 = vector(1, 0, 0)

	// Transforming units is easy
	float transformu ("cm", float x) // converts to cm
	float transformu ("cm", "m", float y) // converts cm to m

// Displacement Functions
	void displace (float 5); // Displace by 5 amp units
	void bump (float 10); // Bump by 10 amp units


// Noise Generation

	type noise (type noise (string noisetype, float u, float v, ...)); // noise
	type noise (string noisetype, point p,...); // point instead of coordinates
	/* some noises are ("perlin", "snoise", "uperlin", "noise", "cell", "hash"
	"simplex", "usimplex", "gabor", etc) */
	
	// Noise Names

	// 1. Perlin Noise (perlin, snoise):
	// Creates smooth, swirling noise often used for textures.
	// Range: [-1, 1] (signed)
	color cloud_texture = noise("perlin", P);

	// 2. Simplex Noise (simplex, usimplex):
	// Similar to Perlin noise but faster.
	// Range: [-1, 1] (signed) for simplex, [0, 1] (unsigned) for usimplex
	float bump_amount = 0.2 * noise("simplex", P * 5.0);

	// 3. UPerlin Noise (uperlin, noise):
	// Similar to peril
	// Range: [0, 1] (unsigned)
	color new_texture = noise("uperlin", P);
	
	// 4. Cell Noise (cell):
	// Creates a blocky, cellular and constant values within each unit block
	// Range: [0, 1] (unsigned)
	color new_texture = noise("cell", P);

	// 5. Hash Noise (hash):
	// Generates random, uncorrelated values at each point.
	// Range: [0, 1] (unsigned)
	color new_texture = noise("hash", P);

	// Gabor Noise (gabor) 
	// Gabor Noise is advanced version of Perin noies and gives more control
	// Range: [-1, 1] (signed)
	// Gabor Noise Parameters

	// Anisotropic (default: 0)
	// Controls anisotropy:
	// 0: Isotropic (equal frequency in all directions)
	// 1: Anisotropic with user-defined direction vector (defaults to (1,0,0))
	/* 2: Hybrid mode,anisotropic along direction vector but radially isotropic
	perpendicularly. */

	// Direction (default: (1,0,0))
	// Specifies the direction of anisotropy (used only if anisotropic is 1).

	// bandwidth (default: 1.0)
	// Controls the frequency range of the noise.

	// impulses (default: 16)
	// Controls the number of impulses used per cell, affecting detail level.

	// do_filter (default: 1)
	// Enables/disables antialiasing (filtering).

	result = noise(
        "gabor",
        P,
        "anisotropic", anisotropic,
        "direction", direction,
        "bandwidth", bandwidth,
        "impulses", impulses,
        "do_filter", do_filter
    );

	// Specific noises can also be used instead of passing them as types
	// pnoise is periodic noise
	float n1 = pnoise("perlin", 0.5, 1.0);
	// 2D periodic noise with Gabor type
	float n2 = pnoise("gabor", 0.2, 0.3, 2.0, 3.0);
	// 2D non-periodic simplex noise
	float n3 = snoise(0.1, 0.7);
	// 2D periodic simplex noise
	type psnoise (float u, float v, float uperiod, float vperiod);
	float n4 = psnoise(0.4, 0.6, 0.5, 0.25);
	// 2D cellular noise
	float n5 = cellnoise(0.2, 0.8);
	// 2D hash noise
	int n6 = hash(0.7, 0.3);

// Step Function
	// Step Functions are used to compare input and threshold

	// The type may be of float, color, point, vector, or normal.
	type step (type edge, type x); // Returns 1 if x ≥ edge, else 0
	color checker = step(0.5, P);  // P is a point on the surface
	/* Pixels with P values below 0.5 will be black, those above or equal will
	be white */
	float visibility = step(10, distance(P, light_position));
	// Light is fully visible within 10 units, completely invisible beyond

	type linearstep (type edge0, type edge1, type x); /* Linearstep Returns 0
	if x ≤ edge0, and 1 if x ≥ edge1, with linear interpolation */
	color gradient = linearstep(0, 1, P);
	// P is a point on the surface between 0 and 1
	// Color will graduate smoothly from black to white as P moves from 0 to 1
	float fade = linearstep(0.85, 1, N.z);  // N.z is the z-component
	// Object edges with normals close to vertical (N.z near 1) will fade out
	
	type smoothstep (type edge0, type edge1, type x); /* smoothstep Returns 0
	if x ≤ edge0, and 1 if x ≥ edge1, with Hermite interpolation */
	float soft_mask = smoothstep(0.2, 0.8, noise(P));  /* noise(P) is a noisy
	value between 0 and 1. soft_mask will vary smoothly between 0 and 1 based
	on noise(P), with a smoother curve than linearstep */

// Splines
	// Splines are smooth curves based on a set of control points

	/* The type of interpolation ranges from "catmull-rom", "bezier",
	"bspline", "hermite", "linear", or "constant" */

	// Spline with knot vector
	float[] knots = {0, 0, 0, 0.25, 0.5, 0.75, 1, 1, 1};
	point[] controls = {point(0),point(1, 2, 1),point(2, 1, 2),point(3, 3, 1)};
	spline curve1 = spline("bezier", 0.5, len(knots), controls);
	// curve1 is a Bezier spline evaluated at u = 0.5

	// Spline with control points
	spline curve2 = spline("catmull-rom", 0.25, point(0, 0, 0), point(1, 2, 1),
	                       point(2, 1, 2), point(3, 3, 1));
	// curve2 is a Catmull-Rom spline evaluated at u = 0.25

	// Constant spline with a single float value
	float value = 10;
	u = 0.1;
	spline curve5 = spline("constant", u, value);
	// curve5 is a constant spline with value 10 evaluated at u = 0.1

	// Hermite spline with point and vector controls
	point q0 = point(0, 0, 0), q1 = point(3, 3, 3);
	vector t0 = vector(1, 0, 0), t1 = vector(-1, 1, 1);
	u = 0.75;
	spline curve3 = spline("hermite", u, q0, t0, q1, t1);
	// curve3 is a Hermite spline evaluated at u = 0.75

	// Linear spline with float controls
	float f0 = 0, f1 = 1, f2 = 2, f3 = 3;
	u = 0.4;
	spline curve4 = spline("linear", u, f0, f1, f2, f3);
	// curve4 is a linear spline evaluated at u = 0.4
	
	// InverseSplines also exist
	
	// Inverse spline with control values
	float y0 = 0, y1 = 1, y2 = 2, y3 = 3;
	float v = 1.5;
	float u1 = splineinverse("linear", v, y0, y1, y2, y3);
	// u1 = 0.5 (linear interpolation between y1 and y2)

	// Inverse spline with knot vector
	float[] knots = {0, 0, 0, 0.25, 0.5, 0.75, 1, 1, 1};
	float[] values = {0, 1, 4, 9};
	v = 6;
	float u2 = splineinverse("bezier", v, len(knots), values);
	// u2 = 0.75 (Bezier spline inverse evaluated at v = 6)

	// Inverse spline with constant value
	v = 10;
	float u3 = splineinverse("constant", v, 10);
	// u3 = 0 (since the constant spline always returns 10)

	// Inverse spline with periodic values
	float y4 = 0, y5 = 1, y6 = 0;
	v = 0.5;
	float u4 = splineinverse("periodic", v, y4, y5, y6);
	// u4 = 0.75 (periodic spline inverse evaluated at v = 0.5)



// Calculus Operators
	// Partial derivative of f with respect to x, y and z using Dx, Dy, Dz
	float a = 3.14;
	float dx = Dx(a); // partial derivative of a with respect to x

	point p = point(1.0, 2.0, 3.0);
	vector dp_dx = Dx(p); // partial derivative of p with respect to x

	vector dv_dy = Dy(N); // partial derivative of normal with respect to y

	color c = color(0.5, 0.2, 0.8);
	color dc_dz = Dz(c); // partial derivative of c with respect to z
	

	float area (point p) // gives the surface area at the position p 

	float filterwidth (float x) // gives the changes of x in adjacent samples

// Texture Functions
	// lookup for a texture at coordinates (x,y)
	color col1 = texture("texture.png", 0.5, 0.2);
	// Lookup color at (0.5, 0.2) in texture.png

	// 3D lookup for a texture at coordinates (x,y)
	color col3 = texture3d("texture3d.vdb", point(0.25, 0.5, 0.75));

	// parameters are ("blur","width","wrap","fill","alpha","interp", ...)
	color col2 = texture("texture.png",1.0,0.75,"blur",0.1,"wrap", "periodic");
	// Lookup color at (1.0, 0.75) with blur 0.1 and periodic wrap mode
	
// Light Functions

	float surfacearea (); // Returns the surface area of area light covers
	int backfacing (); // Outputs 1 if the normals are backfaced, else 0
	int raytype (string name); // returns 1 if the ray is a particular raytype

	// Tracing a ray from a position in a direction
	point pos = point(0, 0, 0); // Starting position of the ray
	vector dir = vector(0, 0, 1); // Direction of the ray
	int hit = trace(pos, dir); // returns 1 if it hits, else 0
```

### Further reading

* [Blender Docs for OSL](https://docs.blender.org/manual/en/latest/render/shader_nodes/osl.html)
* [C4D Docs for OSL](https://docs.otoy.com/cinema4d//OpenShadingLanguageOSL.html)
* Open Shading Language on [GitHub](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage)
* [Official OSL Documentation](https://open-shading-language.readthedocs.io/en/main/)