-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
3,709 additions
and
362 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,314 @@ | ||
<!-- Licensed under a BSD license. See license.html for license --> | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> | ||
<title>Per Face Per Vertex vs Shared Normals Diagram</title> | ||
<style> | ||
:root { | ||
color-scheme: light dark; | ||
} | ||
html, body { | ||
margin: 0; | ||
height: 100%; | ||
} | ||
canvas { | ||
width: 100%; | ||
height: 100%; | ||
display: block; | ||
} | ||
@media (prefers-color-scheme: dark) { | ||
canvas { | ||
background: #444; | ||
} | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<canvas id="canvas"></canvas> | ||
</body> | ||
</html> | ||
<script id="vertexColorVertexShader" type="text/something-not-javascript"> | ||
attribute vec4 position; | ||
attribute vec4 color; | ||
uniform mat4 u_worldViewProjection; | ||
varying vec4 v_color; | ||
void main() { | ||
gl_Position = u_worldViewProjection * position; | ||
v_color = color; | ||
} | ||
|
||
</script> | ||
<script id="vertexColorFragmentShader" type="text/something-not-javascript"> | ||
precision mediump float; | ||
uniform vec4 u_color; | ||
varying vec4 v_color; | ||
void main() { | ||
gl_FragColor = u_color * v_color; | ||
} | ||
</script> | ||
<script id="vertexColorFakeLightVertexShader" type="text/something-not-javascript"> | ||
attribute vec4 position; | ||
attribute vec3 normal; | ||
uniform mat4 u_world; | ||
uniform mat4 u_worldViewProjection; | ||
uniform mat4 u_worldInverseTranspose; | ||
uniform mat4 u_viewInverse; | ||
uniform vec3 u_lightPosition; | ||
varying vec3 v_normal; | ||
varying vec3 v_surfaceToLight; | ||
varying vec3 v_surfaceToView; | ||
void main() { | ||
gl_Position = u_worldViewProjection * position; | ||
v_normal = (u_worldInverseTranspose * vec4(normal, 0)).xyz; | ||
v_surfaceToLight = u_lightPosition - (u_world * position).xyz; | ||
v_surfaceToView = (u_viewInverse[3] - (u_world * position)).xyz; | ||
} | ||
|
||
</script> | ||
<script id="vertexColorFakeLightFragmentShader" type="text/something-not-javascript"> | ||
precision mediump float; | ||
uniform vec4 u_color; | ||
uniform float u_specular; | ||
varying vec3 v_normal; | ||
varying vec3 v_surfaceToLight; | ||
varying vec3 v_surfaceToView; | ||
|
||
void main() { | ||
vec3 normal = normalize(v_normal); | ||
vec3 surfaceToLight = normalize(v_surfaceToLight); | ||
vec3 surfaceToView = normalize(v_surfaceToView); | ||
vec3 halfVector = normalize(surfaceToLight + surfaceToView); | ||
float lit = dot(normal, surfaceToLight) * .5 + .5; | ||
gl_FragColor = vec4(u_color.rgb * lit, u_color.a); | ||
} | ||
</script> | ||
<script type="module"> | ||
import * as twgl from '/3rdparty/twgl-full.module.js'; | ||
|
||
const { v3, m4 } = twgl; | ||
|
||
let eyePosition; | ||
let target; | ||
|
||
// globals | ||
let canvas; // the canvas | ||
|
||
function createNormalLines(vertices) { | ||
const scale = 10; | ||
const srcPositions = vertices.position; | ||
const srcNormals = vertices.normal; | ||
|
||
const normVertices = []; | ||
|
||
for (let ii = 0; ii < srcPositions.length; ii += 3) { | ||
const cube = twgl.primitives.createCubeVertices(1); | ||
delete cube.normal; | ||
delete cube.texcoord; | ||
cube.color = new Float32Array(cube.position.length / 3 * 4); | ||
cube.color.forEach((v, i) => { | ||
const ch = i % 4; | ||
cube.color[i] = ch === 3 | ||
? 1 | ||
: srcNormals[ii + ch] * 0.5 + 0.5; | ||
}); | ||
const target = srcNormals.slice(ii, ii + 3); | ||
const self = [0, 0, 0]; | ||
const up = Math.abs(target[1]) === 1 ? [1, 0, 0] : [0, 1, 0]; | ||
const lookAt = m4.lookAt(self, target, up); | ||
let mat = m4.identity(); | ||
mat = m4.translate(mat, srcPositions.slice(ii, ii + 3)); | ||
mat = m4.multiply(mat, lookAt); | ||
mat = m4.scale(mat, [1, 1, scale]); | ||
mat = m4.translate(mat, [0, 0, -0.5]); | ||
twgl.primitives.reorientVertices(cube, mat); | ||
normVertices.push(cube); | ||
} | ||
|
||
return twgl.primitives.concatVertices(normVertices); | ||
} | ||
|
||
function createApp(gl) { | ||
|
||
// Create Shader Programs | ||
const vertexColorProgramInfo = twgl.createProgramInfo(gl, [ | ||
'vertexColorVertexShader', | ||
'vertexColorFragmentShader', | ||
]); | ||
const litProgramInfo = twgl.createProgramInfo(gl, [ | ||
'vertexColorFakeLightVertexShader', | ||
'vertexColorFakeLightFragmentShader', | ||
]); | ||
|
||
const m = m4.identity(); | ||
m4.rotateX(m, Math.PI * 0.5, m); | ||
m4.translate(m, [0.5, 0, -0.5], m); | ||
const sphereVertices = { | ||
position: [ | ||
-35, -35, -35, // 0------1 | ||
35, -35, -35, // /| /| | ||
-35, 35, -35, // / | / | | ||
35, 35, -35, // 2------3 | | ||
-35, -35, 35, // | 4---|--5 | ||
35, -35, 35, // | / | / | ||
-35, 35, 35, // |/ |/ | ||
35, 35, 35, // 6------7 | ||
], | ||
normal: [ | ||
-0.333, -0.333, -0.333, | ||
0.333, -0.333, -0.333, | ||
-0.333, 0.333, -0.333, | ||
0.333, 0.333, -0.333, | ||
-0.333, -0.333, 0.333, | ||
0.333, -0.333, 0.333, | ||
-0.333, 0.333, 0.333, | ||
0.333, 0.333, 0.333, | ||
], | ||
indices: [ | ||
0, 1, 2, 1, 2, 3, | ||
4, 5, 6, 5, 6, 7, | ||
0, 2, 4, 4, 2, 6, | ||
3, 1, 7, 7, 1, 5, | ||
1, 0, 4, 4, 0, 5, | ||
2, 3, 6, 6, 3, 7, | ||
], | ||
}; | ||
const sphereBufferInfo = twgl.createBufferInfoFromArrays(gl, sphereVertices); | ||
const sphereNormalsBufferInfo = twgl.createBufferInfoFromArrays(gl, createNormalLines(sphereVertices)); | ||
const cubeVertices = twgl.primitives.createCubeVertices(70); | ||
const cubeBufferInfo = twgl.createBufferInfoFromArrays(gl, cubeVertices); | ||
const cubeNormalsBufferInfo = twgl.createBufferInfoFromArrays(gl, createNormalLines(cubeVertices)); | ||
|
||
// pre-allocate a bunch of arrays | ||
const projection = m4.identity(); | ||
const view = m4.identity(); | ||
const viewInverse = m4.identity(); | ||
const world = m4.identity(); | ||
const worldInverseTranspose = m4.identity(); | ||
const viewProjection = m4.identity(); | ||
const inverseViewProjection = m4.identity(); | ||
const worldViewProjection = m4.identity(); | ||
eyePosition = new Float32Array([150, 150, 150]); | ||
target = new Float32Array([0, 0, 0]); | ||
const up = new Float32Array([0, 1, 0]); | ||
const v3t0 = new Float32Array(3); | ||
|
||
// uniforms. | ||
const sharedUniforms = { | ||
u_world: world, | ||
u_worldViewProjection: worldViewProjection, | ||
u_worldInverseTranspose: worldInverseTranspose, | ||
u_viewInverse: viewInverse, | ||
u_lightPosition: [200, 500, -300], | ||
u_specular: 1000, | ||
}; | ||
|
||
|
||
const normalUniforms = { | ||
u_color: [1, 1, 1, 1], | ||
}; | ||
|
||
const sphereUniforms = { | ||
u_color: [1, 0, 0, 1], | ||
}; | ||
|
||
const cubeUniforms = { | ||
u_color: [0, 0, 1, 1], | ||
}; | ||
|
||
function drawModel(programInfo, bufferInfo, type, uniforms, world) { | ||
m4.multiply(viewProjection, world, worldViewProjection); | ||
m4.inverse(world, worldInverseTranspose); | ||
m4.transpose(worldInverseTranspose, worldInverseTranspose); | ||
gl.useProgram(programInfo.program); | ||
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo); | ||
twgl.setUniforms(programInfo, sharedUniforms, uniforms); | ||
twgl.drawBufferInfo(gl, bufferInfo, type); | ||
} | ||
|
||
function degToRad(deg) { | ||
return deg * Math.PI / 180; | ||
} | ||
|
||
let clock = 0; | ||
function render(elapsedTime) { | ||
clock += elapsedTime; | ||
|
||
// clear the screen. | ||
gl.enable(gl.DEPTH_TEST); | ||
// gl.colorMask(true, true, true, true); | ||
// gl.clearColor(1, 1, 1, 1); | ||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | ||
|
||
const aspect = canvas.clientWidth / canvas.clientHeight; | ||
m4.perspective( | ||
degToRad(40), | ||
aspect, | ||
1, | ||
5000, | ||
projection); | ||
|
||
const dist = v3.length(v3.subtract(target, eyePosition)); | ||
const a = Math.PI * -.5;//clock / 8; | ||
v3t0[0] = Math.cos(a) * dist + target[0]; | ||
v3t0[1] = eyePosition[1]; | ||
v3t0[2] = Math.sin(a) * dist + target[2]; | ||
m4.lookAt( | ||
v3t0, | ||
target, | ||
up, | ||
viewInverse); | ||
m4.inverse(viewInverse, view); | ||
m4.multiply(projection, view, viewProjection); | ||
m4.inverse(viewProjection, inverseViewProjection); | ||
|
||
m4.translation([-60, 0, 0], world); | ||
m4.rotateY(world, clock / 8, world); | ||
drawModel(litProgramInfo, sphereBufferInfo, gl.TRIANGLES, sphereUniforms, world); | ||
drawModel(vertexColorProgramInfo, sphereNormalsBufferInfo, gl.TRIANGLES, normalUniforms, world); | ||
m4.translation([ 60, 0, 0], world); | ||
m4.rotateY(world, clock / 8, world); | ||
drawModel(litProgramInfo, cubeBufferInfo, gl.TRIANGLES, cubeUniforms, world); | ||
drawModel(vertexColorProgramInfo, cubeNormalsBufferInfo, gl.TRIANGLES, normalUniforms, world); | ||
//m4.translation([0, -100, 0], world); | ||
//m4.scale(world, [100, 100, 100], world); | ||
//drawModel(vertexColorProgramInfo, gridBufferInfo, gl.LINES, gridUniforms, world); | ||
} | ||
|
||
return { | ||
render, | ||
}; | ||
} | ||
|
||
let app; | ||
function main() { | ||
canvas = document.querySelector('#canvas'); | ||
|
||
const gl = twgl.getWebGLContext(canvas, {alpha: true, preMultipliedAlpha: false}); | ||
if (!gl) { | ||
return; | ||
} | ||
|
||
twgl.resizeCanvasToDisplaySize(gl.canvas, window.devicePixelRatio); | ||
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); | ||
|
||
app = createApp(gl); | ||
|
||
let then = 0; | ||
function render(time) { | ||
const now = time * 0.001; | ||
const elapsedTime = now - then; | ||
then = now; | ||
app.render(elapsedTime); | ||
requestAnimationFrame(render); | ||
} | ||
requestAnimationFrame(render); | ||
} | ||
|
||
main(); | ||
</script> | ||
|
||
|
||
|
||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.