@@ -1144,6 +1144,128 @@ visualSuite('WebGL', function() {
11441144 screenshot ( ) ;
11451145 } ) ;
11461146 } ) ;
1147+
1148+ visualTest ( 'Strands tutorial' , function ( p5 , screenshot ) {
1149+ // From Luke Plowden's Intro to Strands tutorial
1150+ // https://beta.p5js.org/tutorials/intro-to-p5-strands/
1151+
1152+ function starShaderCallback ( { p5 } ) {
1153+ const time = p5 . uniformFloat ( ( ) => p5 . millis ( ) ) ;
1154+ const skyRadius = p5 . uniformFloat ( 90 ) ;
1155+
1156+ function rand2 ( st ) {
1157+ return p5 . sin ( ( st . x + st . y ) * 123.456 ) ;
1158+ }
1159+
1160+ function semiSphere ( ) {
1161+ let id = p5 . instanceID ( ) ;
1162+ let theta = rand2 ( [ id , 0.1234 ] ) * p5 . TWO_PI + time / 100000 ;
1163+ let phi = rand2 ( [ id , 3.321 ] ) * p5 . PI + time / 50000 ;
1164+
1165+ let r = skyRadius ;
1166+ r *= p5 . sin ( phi ) ;
1167+ let x = r * p5 . sin ( phi ) * p5 . cos ( theta ) ;
1168+ let y = r * 1.5 * p5 . cos ( phi ) ;
1169+ let z = r * p5 . sin ( phi ) * p5 . sin ( theta ) ;
1170+ return [ x , y , z ] ;
1171+ }
1172+
1173+ p5 . getWorldInputs ( ( inputs ) => {
1174+ inputs . position += semiSphere ( ) ;
1175+ return inputs ;
1176+ } ) ;
1177+
1178+ p5 . getObjectInputs ( ( inputs ) => {
1179+ let size = 1 + 0.5 * p5 . sin ( time * 0.002 + p5 . instanceID ( ) ) ;
1180+ inputs . position *= size ;
1181+ return inputs ;
1182+ } ) ;
1183+ }
1184+
1185+ function pixelateShaderCallback ( { p5 } ) {
1186+ const pixelCountX = p5 . uniformFloat ( ( ) => 100 ) ;
1187+
1188+ p5 . getColor ( ( inputs , canvasContent ) => {
1189+ const aspectRatio = inputs . canvasSize . x / inputs . canvasSize . y ;
1190+ const pixelSize = [ pixelCountX , pixelCountX / aspectRatio ] ;
1191+
1192+ let coord = inputs . texCoord ;
1193+ coord = p5 . floor ( coord * pixelSize ) / pixelSize ;
1194+
1195+ let col = p5 . getTexture ( canvasContent , coord ) ;
1196+ return col //[coord, 0, 1];
1197+ } ) ;
1198+ }
1199+
1200+ function bloomShaderCallback ( { p5, originalImage } ) {
1201+ const preBlur = p5 . uniformTexture ( ( ) => originalImage ) ;
1202+
1203+ getColor ( ( input , canvasContent ) => {
1204+ const blurredCol = p5 . getTexture ( canvasContent , input . texCoord ) ;
1205+ const originalCol = p5 . getTexture ( preBlur , input . texCoord ) ;
1206+
1207+ const intensity = p5 . max ( originalCol , 0.1 ) * 12.2 ;
1208+
1209+ const bloom = originalCol + blurredCol * intensity ;
1210+ return [ bloom . rgb , 1 ] ;
1211+ } ) ;
1212+ }
1213+
1214+ p5 . createCanvas ( 200 , 200 , p5 . WEBGL ) ;
1215+ const stars = p5 . buildGeometry ( ( ) => p5 . sphere ( 4 , 4 , 2 ) )
1216+ const originalImage = p5 . createFramebuffer ( ) ;
1217+
1218+ function fresnelShaderCallback ( { p5 } ) {
1219+ const fresnelPower = p5 . uniformFloat ( 2 ) ;
1220+ const fresnelBias = p5 . uniformFloat ( - 0.1 ) ;
1221+ const fresnelScale = p5 . uniformFloat ( 2 ) ;
1222+
1223+ p5 . getCameraInputs ( ( inputs ) => {
1224+ let n = p5 . normalize ( inputs . normal ) ;
1225+ let v = p5 . normalize ( - inputs . position ) ;
1226+ let base = 1.0 - p5 . dot ( n , v ) ;
1227+ let fresnel = fresnelScale * p5 . pow ( base , fresnelPower ) + fresnelBias ;
1228+ let col = p5 . mix ( [ 0 , 0 , 0 ] , [ 1 , .5 , .7 ] , fresnel ) ;
1229+ inputs . color = [ col , 1 ] ;
1230+ return inputs ;
1231+ } ) ;
1232+ }
1233+
1234+ const starShader = p5 . baseMaterialShader ( ) . modify ( starShaderCallback , { p5 } ) ;
1235+ const starStrokeShader = p5 . baseStrokeShader ( ) . modify ( starShaderCallback , { p5 } )
1236+ const fresnelShader = p5 . baseColorShader ( ) . modify ( fresnelShaderCallback , { p5 } ) ;
1237+ const bloomShader = p5 . baseFilterShader ( ) . modify ( bloomShaderCallback , { p5, originalImage } ) ;
1238+ const pixelateShader = p5 . baseFilterShader ( ) . modify ( pixelateShaderCallback , { p5 } ) ;
1239+
1240+ originalImage . begin ( ) ;
1241+ p5 . background ( 0 ) ;
1242+
1243+ p5 . push ( )
1244+ p5 . strokeWeight ( 2 )
1245+ p5 . stroke ( 255 , 0 , 0 )
1246+ p5 . fill ( 255 , 100 , 150 )
1247+ p5 . strokeShader ( starStrokeShader )
1248+ p5 . shader ( starShader ) ;
1249+ p5 . model ( stars , 100 ) ;
1250+ p5 . pop ( )
1251+
1252+ p5 . push ( )
1253+ p5 . shader ( fresnelShader )
1254+ p5 . noStroke ( )
1255+ p5 . sphere ( 30 ) ;
1256+ p5 . filter ( pixelateShader ) ;
1257+ p5 . pop ( )
1258+
1259+ originalImage . end ( ) ;
1260+
1261+ p5 . imageMode ( p5 . CENTER )
1262+ p5 . image ( originalImage , 0 , 0 )
1263+
1264+ p5 . filter ( p5 . BLUR , 5 )
1265+ p5 . filter ( bloomShader ) ;
1266+
1267+ screenshot ( ) ;
1268+ } ) ;
11471269 } ) ;
11481270
11491271 visualSuite ( 'background()' , function ( ) {
@@ -1316,7 +1438,7 @@ visualSuite('WebGL', function() {
13161438 visualSuite ( 'Tessellation' , function ( ) {
13171439 visualTest ( 'Handles nearly identical consecutive vertices' , function ( p5 , screenshot ) {
13181440 p5 . createCanvas ( 400 , 400 , p5 . WEBGL ) ;
1319-
1441+
13201442 const contours = [
13211443 [
13221444 [ - 3.8642425537109375 , - 6.120738636363637 , 0 ] ,
@@ -1355,7 +1477,7 @@ visualSuite('WebGL', function() {
13551477 [ - 1.8045834628018462 , 4.177556818181818 , 0 ]
13561478 ]
13571479 ] ;
1358-
1480+
13591481 p5 . background ( 'red' ) ;
13601482 p5 . push ( ) ;
13611483 p5 . stroke ( 0 ) ;
0 commit comments