Public
Edited
Aug 15, 2023
Insert cell
Insert cell
Insert cell
gl = {
const myCanvas = DOM.canvas(900, 600);
const gl = myCanvas.getContext("webgl2");
return gl;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
modelExtents = computeModelExtent(modelObject)
Insert cell
Insert cell
Insert cell
## Camera Matrices
Insert cell
Insert cell
Insert cell
Insert cell
## Buffers
Insert cell
bufferInfoArray = vertexAttributes.map((d)=>twgl.createBufferInfoFromArrays(gl, d));
Insert cell
## Light Computation
Insert cell
lightPosition = {
const D = (lightParameters.distanceFactor) / 2;
return v3.add(target, v3.mulScalar(lightDirection, D));
}
Insert cell
lightDirection = m4.transformDirection(
m4.rotationZ(toRadian(lightParameters.orientation)),
[0, 1, 0]
)
Insert cell
Insert cell
shaders = {
const vs = `#version 300 es
in vec3 position; // Attribute
in vec3 normal; // Attribute

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projMatrix;
uniform float aspect;

out vec3 fragPosition;
out vec3 fragNormal;

uniform vec3 offsets[3];

void main(){
vec4 newPos = modelMatrix*vec4(position,1);
fragPosition = newPos.xyz;
gl_Position = projMatrix*viewMatrix*newPos;

mat4 normalMatrix = transpose(inverse(modelMatrix));
fragNormal = (normalMatrix * vec4(normal, 0.0) ).xyz;

}`;
const fs = `#version 300 es
precision mediump float;

out vec4 outColor;

in vec3 fragPosition;
in vec3 fragNormal;

uniform vec4 lightPosOrDir;
uniform vec3 eyePosition;

uniform float ambientIntensity;
uniform float K_s;

uniform vec3 materialColor;
uniform vec3 material;
uniform float roughness;
uniform float anisotropy;
uniform bool enableAnisotropy;

float PI = 3.14f;

float square(float x)
{
return pow(x, 2.0);
}

vec3 fresnelTerm(vec3 N, vec3 L)
{
vec3 F0 = material;
float NdotL = dot(N,L);
NdotL = clamp(NdotL, 0.0, 1.0);
vec3 F = F0 + (1.0 - F0) * pow(1.0 - NdotL , 5.0);
return F;
}

float distributionTerm(vec3 N, vec3 H)
{
float r = pow(roughness, 2.0);
float NdotH = clamp(dot(N,H), 0.0, 1.0);
float D = r/( PI * square( square(NdotH)*(r-1.0) + 1.0 ) );
return D;
}

float geometryTerm(vec3 N, vec3 V, vec3 L)
{
float r = square(roughness);
float NdotV = dot(N,V);
float NdotL = dot(N,L);

NdotV = clamp(NdotV, 0.0, 1.0);
NdotL = clamp(NdotL, 0.0, 1.0);

float Gv = NdotV / (NdotV*(1.0-r*0.5) + r);
float Gl = NdotL / (NdotL*(1.0-r*0.5) + r);
float G = Gv * Gl;

return G;
}

float anisotropicDistribution(vec3 N, vec3 H)
{
vec3 A = normalize(cross(N, N-vec3(1,0,0)));
vec3 B = normalize(cross(N, A));
vec3 T = normalize(cross(B, N));
float at = max(roughness * (1.0 + anisotropy), 0.001);
float ab = max(roughness * (1.0 - anisotropy), 0.001);

float a2 = at*ab;

float NdotH = dot(N,H);
float TdotH = dot(T,H);
float BdotH = dot(B,H);

float Dani = (square(at*ab))/ ( PI * (square(at*TdotH) + square(ab*BdotH) + square(a2*square(NdotH)) ));
return Dani;
}

void main(){
vec3 N = normalize(fragNormal);
vec3 L;
if (lightPosOrDir.w==0.0){
L = normalize(lightPosOrDir.xyz);
}
else{
L = normalize(lightPosOrDir.xyz-fragPosition);
}
vec3 V = normalize(eyePosition-fragPosition);
vec3 H = normalize(L+V);
vec3 ambient = ambientIntensity*materialColor;
vec3 diffuse = materialColor * clamp(dot(L,N), 0.0, 1.0);


// compute F : fresnel term
vec3 F = fresnelTerm(N, L);

// compute G: Geometry term
float G = geometryTerm(N, V, L);

// compute D: Distribution term
float D;
if (enableAnisotropy==true)
D = anisotropicDistribution(N, H);
else
D = distributionTerm(N, H);

vec3 microfacet = F*G*D;

vec3 color = ambient + (1.0-K_s)*diffuse + K_s*microfacet;
outColor = vec4(color, 1.0);
}`;
return [vs, fs];
}
Insert cell
errorBlock = html`<textarea style="height : 20px; width : ${width}px; font-size: 0.8em; display: block"></textarea>`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
gl.useProgram(programInfo.program);

gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.clearColor(...hex2rgb(sceneParameters.color),1.0);

render(modelMatrix);
return gl.canvas;
}
Insert cell
function render(modelMatrix){
const uniforms = {
modelMatrix: modelMatrix,
viewMatrix: viewMatrix,
projMatrix: projMatrix,
lightPosOrDir: lightParameters.lightType == "point"? [...lightPosition, 1] : [...lightDirection, 0],
//lightPosOrDir: [1,1,1,0],
eyePosition: m4.inverse(viewMatrix).slice(12, 15),

//materialColor: hex2rgb(misc.materialColor),
materialColor: materialProperty.material,
ambientIntensity: misc.ambient,
K_s: misc.K_s,
material: materialProperty.material,
roughness: materialProperty.roughness,
anisotropy: anisotropyDist.anisotropy,
enableAnisotropy: anisotropyDist.enable
};
twgl.setUniforms(programInfo, uniforms);
bufferInfoArray.forEach((bufferInfo)=> {
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.drawBufferInfo(gl, bufferInfo, gl.TRIANGLES, bufferInfo.numElements);
}
);

}
Insert cell
Insert cell
toRadian = glMatrix.glMatrix.toRadian
Insert cell
Insert cell
twgl = require("twgl.js")
Insert cell
m4 = twgl.m4
Insert cell
v3 = twgl.v3
Insert cell
require.resolve("twgl.js")
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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