Published
Edited
Sep 30, 2020
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
regl = createRegl(canvas)
Insert cell
drawObj = regl({
frag: `
precision mediump float;
uniform vec4 color;
varying vec3 vtxNormal;
uniform vec3 lightDir;
uniform vec3 lightColor;
uniform vec3 objColor;
uniform float ambient;
uniform float emission;
uniform float diffuse;
uniform float specular;
uniform float shininess;

uniform vec3 lightPos;
uniform float cutoffAngle;
uniform float spotExponent;
varying vec3 worldPos;

void main () {
vec3 lightDir = -lightDir;
vec3 lightToObject = normalize(-worldPos + lightPos);
float direction = max(dot(lightDir, lightToObject), 0.0);
if (direction < cos(radians(cutoffAngle))){
gl_FragColor = vec4(0,0,0,0.9);
return;
}
vec3 lightColor = lightColor * pow(direction,spotExponent);
vec3 normal = normalize(vtxNormal);
float diffuseComp = max(0.0,diffuse * dot(normal,lightDir));
vec3 ref = 2.0*dot(lightDir,normal)*normal - lightDir;
float specularComp = specular*pow(max(0.0,dot(ref,vec3(0.0,0.0,1.0))),shininess);
gl_FragColor = vec4(emission*objColor +
(ambient+diffuseComp)*lightColor*objColor +
specularComp*lightColor, 1.0);
}`,

vert: `
attribute vec3 position;
attribute vec3 normal;
varying vec3 vtxNormal;
uniform mat4 modelview;
uniform mat4 projection;
varying vec3 worldPos;
void main () {
vec4 worldpos = modelview*vec4(position, 1.0);
gl_Position = projection*worldpos;
worldPos = worldpos.xyz;
vtxNormal = (modelview*vec4(normal,0.0)).xyz;
}`,

// These are the vertex attributes that will be passed
// on to the vertex shader
attributes: {
position: obj.pos,
normal: obj.normal
},

// These are the uniforms, i.e., global shader variables that are set
// from inside the host (CPU) program
uniforms: {
objColor: regl.prop('objColor'),
lightColor: regl.prop('lightColor'),
lightDir: regl.prop('lightDir'),
ambient: regl.prop('ambient'),
emission: regl.prop('emission'),
diffuse: regl.prop('diffuse'),
specular: regl.prop('specular'),
shininess : regl.prop ('shininess'),
modelview : regl.prop('modelview'),
projection : regl.prop ('projection'),
lightPos: regl.prop('lightPos'),
cutoffAngle: regl.prop('cutoffAngle'),
spotExponent: regl.prop('spotExponent'),
},
// The depth buffer
depth: {
enable: true,
func: '<',
mask: true,
},
// Number of triangles
elements: obj.faces
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//
// Draws one frame
//
draw = {
// First clear the frame buffer
regl.clear({
color: [0.8, 0.8, 1.0, 1],
depth: 1
})
// And then draw the triangle
drawObj(
{ objColor: colorToVec3(parameters.obj.color),
lightColor: colorToVec3(parameters.light.color),
lightDir: lightDir,
ambient: parameters.obj.coefficients.ambient,
emission: parameters.obj.coefficients.emission,
diffuse: parameters.obj.coefficients.diffuse,
specular: parameters.obj.coefficients.specular,
shininess : parameters.obj.coefficients.shininess,
modelview:mat4.mul([],view,model),
projection:projection,
lightPos: xyzToVec3(parameters.light.position),
cutoffAngle: parameters.light.cutoff,
spotExponent: parameters.light.exponent,
})
}
Insert cell
Insert cell
Insert cell
Insert cell
//
// Little utility to add a title to the left of an input, rather than to the top as in the elements
// produced by the Input bazzar.
//
addTitle = function (title,input) {
input.childNodes[0].style.display="inline-block";
input.prepend(html`<span style="font: 700 0.9rem sans-serif;display:inline-block;padding-right:1em;">${title}</span>`);
return input;
}
Insert cell
Insert cell
Insert cell
bunny = {
let obj = parseObj (await FileAttachment("bunny.obj").text());
obj.pos = obj.pos.map (([x,y,z])=>[x+0.4,y-1,z])
return obj
}
Insert cell
teapot = {
let obj = parseObj (await FileAttachment("teapot@1.obj").text());
obj.pos = obj.pos.map(([x,y,z])=>[x/10,y/10,z/10])
return obj
}
Insert cell
obj = parameters.obj.type == "bunny" ? bunny : (parameters.obj.type == "teapot" ? teapot : sphere)
Insert cell
Insert cell
createRegl = require('regl@1.4.2/dist/regl.js')
Insert cell
import {tabbed,paged,combo} from "@esperanc/aggregated-inputs"
Insert cell
import {number,slider,select,color} from "@jashkenas/inputs"
Insert cell
glmatrix = await require('https://bundle.run/gl-matrix@3.3.0')
Insert cell
Insert cell
Insert cell
Insert cell
import {sphere} from "@esperanc/modelview-demo"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more