twgl.js/examples/webgl2-textures.html
Gregg Tavares 0f6f7060d7 lint
2017-10-25 22:25:24 +09:00

1169 lines
32 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<!--
@license twgl.js Copyright (c) 2015, Gregg Tavares All Rights Reserved.
Available via the MIT license.
see: http://github.com/greggman/twgl.js for details
-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<meta property="og:title" content="TWGL.js - webgl2 textures" />
<meta property="og:type" content="website" />
<meta property="og:image" content="http://twgljs.org/examples/screenshots/webgl2-textures.png" />
<meta property="og:description" content="TWGL.js - webgl2 textures" />
<meta property="og:url" content="http://twgljs.org" />
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@greggman">
<meta name="twitter:creator" content="@greggman">
<meta name="twitter:domain" content="twgljs.org">
<meta name="twitter:title" content="TWGL.js - webgl2 textures">
<meta name="twitter:url" content="http://twgljs.org/examples/webgl2-textures.html">
<meta name="twitter:description" content="TWGL.js - webgl2 textures">
<meta name="twitter:image:src" content="http://twgljs.org/examples/screenshots/webgl2-textures.png">
<link href="/resources/images/twgljs-icon.png" rel="shortcut icon" type="image/png">
<title>twgl.js - webgl2 textures</title>
<style>
body {
margin: 0;
font-family: monospace;
}
canvas {
display: block;
width: 100vw;
height: 100vh;
}
#b {
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 2;
}
#no-webgl2 {
position: absolute;
left: 0;
top: 0;
background: red;
color: white;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<canvas id="c"></canvas>
<div id="b"><a href="http://twgljs.org">twgl.js</a> - webgl2 textures</div>
<div id="no-webgl2" style="display: none;">
<div>Sorry but your browser doesn't appear to support WebGL2</div>
</div>
</body>
<script id="one-point-vs" type="notjs">
#version 300 es
uniform mat4 u_worldViewProjection;
uniform mat4 u_world;
in vec4 a_position;
in vec2 a_texcoord;
out vec4 v_position;
out vec2 v_texCoord;
void main() {
v_texCoord = a_texcoord;
gl_Position = u_worldViewProjection * a_position;
}
</script>
<script id="one-point-fs" type="notjs">
#version 300 es
precision mediump float;
in vec4 v_position;
in vec2 v_texCoord;
uniform vec4 u_diffuseMult;
uniform sampler2D u_diffuse;
out vec4 outColor;
void main() {
vec4 diffuseColor = texture(u_diffuse, v_texCoord) * u_diffuseMult;
if (diffuseColor.a < 0.1) {
discard;
}
outColor = diffuseColor;
outColor.rbg *= outColor.a;
}
</script>
<script id="int-one-point-fs" type="notjs">
#version 300 es
precision mediump float;
in vec4 v_position;
in vec2 v_texCoord;
uniform ivec4 u_diffuseOffset;
uniform ivec4 u_diffuseMult;
uniform mediump isampler2D u_diffuse;
out vec4 outColor;
void main() {
ivec4 diffuseColor = texture(u_diffuse, v_texCoord) * u_diffuseMult + u_diffuseOffset;
if (diffuseColor.a <= 0) {
discard;
}
outColor = vec4(diffuseColor) / 100. * .5 + .5;
outColor.rbg *= outColor.a;
}
</script>
<script id="uint-one-point-fs" type="notjs">
#version 300 es
precision mediump float;
in vec4 v_position;
in vec2 v_texCoord;
uniform uvec4 u_diffuseOffset;
uniform uvec4 u_diffuseMult;
uniform mediump usampler2D u_diffuse;
out vec4 outColor;
void main() {
uvec4 diffuseColor = texture(u_diffuse, v_texCoord) * u_diffuseMult + u_diffuseOffset;
if (diffuseColor.a == 0u) {
discard;
}
outColor = vec4(diffuseColor) / 200.;
outColor.rbg *= outColor.a;
}
</script>
<script id="norm-one-point-fs" type="notjs">
#version 300 es
precision mediump float;
in vec4 v_position;
in vec2 v_texCoord;
uniform vec4 u_diffuseMult;
uniform sampler2D u_diffuse;
out vec4 outColor;
void main() {
vec4 diffuseColor = (texture(u_diffuse, v_texCoord) * .5 + .5) * u_diffuseMult;
if (diffuseColor.a < 0.1) {
discard;
}
outColor = diffuseColor;
outColor.rbg *= outColor.a;
}
</script>
<script id="float-one-point-fs" type="notjs">
#version 300 es
precision mediump float;
in vec4 v_position;
in vec2 v_texCoord;
uniform vec4 u_diffuseMult;
uniform vec4 u_diffuseOffset;
uniform sampler2D u_diffuse;
out vec4 outColor;
void main() {
vec4 diffuseColor = texture(u_diffuse, v_texCoord) / 100. * u_diffuseMult + u_diffuseOffset;
if (diffuseColor.a < 0.1) {
discard;
}
outColor = diffuseColor;
outColor.rbg *= outColor.a;
}
</script>
<script src="../dist/4.x/twgl-full.min.js"></script>
<script src="../3rdparty/chroma.min.js"></script>
<script>
"use strict";
// adapted from http://stackoverflow.com/a/6162687/128511
const toHalf = (function() {
const floatView = new Float32Array(1);
const int32View = new Int32Array(floatView.buffer);
return function toHalf(fval) {
floatView[0] = fval;
const fbits = int32View[0];
const sign = (fbits >> 16) & 0x8000; // sign only
let val = (fbits & 0x7fffffff) + 0x1000; // rounded value
if (val >= 0x47800000) { // might be or become NaN/Inf
if ((fbits & 0x7fffffff) >= 0x47800000) {
// is or must become NaN/Inf
if (val < 0x7f800000) { // was value but too large
return sign | 0x7c00; // make it +/-Inf
}
return sign | 0x7c00 | // remains +/-Inf or NaN
(fbits & 0x007fffff) >> 13; // keep NaN (and Inf) bits
}
return sign | 0x7bff; // unrounded not quite Inf
}
if (val >= 0x38800000) { // remains normalized value
return sign | val - 0x38000000 >> 13; // exp - 127 + 15
}
if (val < 0x33000000) { // too small for subnormal
return sign; // becomes +/-0
}
val = (fbits & 0x7fffffff) >> 23; // tmp exp for subnormal calc
return sign | ((fbits & 0x7fffff | 0x800000) // add subnormal bit
+ (0x800000 >>> val - 102) // round depending on cut off
>> 126 - val); // div by 2^(1-(exp-127+15)) and >> 13 | exp=0
};
}());
// Adapted from http://gamedev.stackexchange.com/a/17329/79
const to11uf = (function() {
const F11_EXPONENT_BITS = 0x1F;
const F11_EXPONENT_SHIFT = 6;
const F11_EXPONENT_BIAS = 15;
const F11_MANTISSA_BITS = 0x3f;
const F11_MANTISSA_SHIFT = (23 - F11_EXPONENT_SHIFT);
const F11_MAX_EXPONENT = (F11_EXPONENT_BITS << F11_EXPONENT_SHIFT);
const floatView = new Float32Array(1);
const int32View = new Int32Array(floatView.buffer);
return function(val) {
floatView[0] = val;
const f32 = int32View[0];
let f11 = 0;
/* Decode IEEE 754 little-endian 32-bit floating-point value */
if (f32 & 0x80000000) {
// negative values go to 0
return 0;
}
/* Map exponent to the range [-127,128] */
let exponent = ((f32 >> 23) & 0xff) - 127;
let mantissa = f32 & 0x007fffff;
if (exponent === 128) {
/* Infinity or NaN */
f11 = F11_MAX_EXPONENT;
if (mantissa) {
f11 |= (mantissa & F11_MANTISSA_BITS);
}
} else if (exponent > 15) {
/* Overflow - flush to Infinity */
f11 = F11_MAX_EXPONENT;
} else if (exponent > -15) {
/* Representable value */
exponent += F11_EXPONENT_BIAS;
mantissa >>= F11_MANTISSA_SHIFT;
f11 = exponent << F11_EXPONENT_SHIFT | mantissa;
} else {
f11 = 0;
}
return f11;
};
}());
// Adapted from http://gamedev.stackexchange.com/a/17329/79
const to10uf = (function() {
const F10_EXPONENT_BITS = 0x1F;
const F10_EXPONENT_SHIFT = 5;
const F10_EXPONENT_BIAS = 15;
const F10_MANTISSA_BITS = 0x1f;
const F10_MANTISSA_SHIFT = (23 - F10_EXPONENT_SHIFT);
const F10_MAX_EXPONENT = (F10_EXPONENT_BITS << F10_EXPONENT_SHIFT);
const floatView = new Float32Array(1);
const int32View = new Int32Array(floatView.buffer);
return function(val) {
floatView[0] = val;
const f32 = int32View[0];
let f10 = 0;
/* Decode IEEE 754 little-endian 32-bit floating-point value */
if (f32 & 0x80000000) {
// negative values go to 0
return 0;
}
/* Map exponent to the range [-127,128] */
let exponent = ((f32 >> 23) & 0xff) - 127;
let mantissa = f32 & 0x007fffff;
if (exponent === 128) {
/* Infinity or NaN */
f10 = F10_MAX_EXPONENT;
if (mantissa) {
f10 |= (mantissa & F10_MANTISSA_BITS);
}
} else if (exponent > 15) {
/* Overflow - flush to Infinity */
f10 = F10_MAX_EXPONENT;
} else if (exponent > -15) {
/* Representable value */
exponent += F10_EXPONENT_BIAS;
mantissa >>= F10_MANTISSA_SHIFT;
f10 = exponent << F10_EXPONENT_SHIFT | mantissa;
} else {
f10 = 0;
}
return f10;
};
}());
function main() {
twgl.setDefaults({attribPrefix: "a_"});
const m4 = twgl.m4;
const gl = document.getElementById("c").getContext("webgl2");
if (!gl) {
document.querySelector("#no-webgl2").style.display = "";
return;
}
const onePointProgramInfo = twgl.createProgramInfo(gl, ["one-point-vs", "one-point-fs"], ["a_texcoord", "a_position"]);
const intProgramInfo = twgl.createProgramInfo(gl, ["one-point-vs", "int-one-point-fs"], ["a_texcoord", "a_position"]);
const uintProgramInfo = twgl.createProgramInfo(gl, ["one-point-vs", "uint-one-point-fs"], ["a_texcoord", "a_position"]);
const normProgramInfo = twgl.createProgramInfo(gl, ["one-point-vs", "norm-one-point-fs"], ["a_texcoord", "a_position"]);
const floatProgramInfo = twgl.createProgramInfo(gl, ["one-point-vs", "float-one-point-fs"], ["a_texcoord", "a_position"]);
const shapes = [
twgl.primitives.createCubeBufferInfo(gl, 2),
twgl.primitives.createSphereBufferInfo(gl, 1, 24, 12),
twgl.primitives.createPlaneBufferInfo(gl, 2, 2),
twgl.primitives.createTruncatedConeBufferInfo(gl, 1, 0, 2, 24, 1),
];
function rand(min, max) {
if (max === undefined) {
max = min;
min = 0;
}
return min + Math.random() * (max - min);
}
// Shared values
const camera = m4.identity();
const view = m4.identity();
const viewProjection = m4.identity();
function rgb565(r, g, b) {
return (((r * 31) | 0) << 11) |
(((g * 63) | 0) << 6) |
(((b * 31) | 0) << 0);
}
function rgba5551(r, g, b, a) {
return (((r * 31) | 0) << 11) |
(((g * 31) | 0) << 6) |
(((b * 31) | 0) << 1) |
(((a * 1) | 0) << 0);
}
function rgba1010102(r, g, b, a) {
return (((r * 1023) | 0) << 0) |
(((g * 1023) | 0) << 10) |
(((b * 1023) | 0) << 20) |
(((a * 3) | 0) << 30);
}
function rgb9e5(r, g, b) {
const e = 15;
return (((r * 511) | 0) << 0) |
(((g * 511) | 0) << 9) |
(((b * 511) | 0) << 18) |
(e << 27);
}
function rgb101111(r, g, b) {
return (to11uf(r) << 0) |
(to11uf(g) << 11) |
(to10uf(b) << 22);
}
const flatten = list => list.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
);
const texturesSettings = {
R8: { // 8 Y Y
internalFormat: gl.R8,
format: gl.RED,
type: gl.UNSIGNED_BYTE,
width: 4,
minMag: gl.NEAREST,
src: [ 64, 255, 128, 192 ],
},
R8_SNORM: { // s8 Y
internalFormat: gl.R8_SNORM,
format: gl.RED,
type: gl.BYTE,
minMag: gl.NEAREST,
src: [ 127, 64, 32, 96 ],
},
R16F: { // f16 Y
internalFormat: gl.R16F,
format: gl.RED,
type: gl.HALF_FLOAT,
src: new Uint16Array([toHalf(20), toHalf(40), toHalf(30), toHalf(100)]),
diffuseOffset: [ 0, 0, 0, 1 ],
},
R16Fb: { // f16 Y
internalFormat: gl.R16F,
format: gl.RED,
type: gl.FLOAT,
minMag: gl.NEAREST,
src: [ 20, 40, 30, 100 ],
diffuseOffset: [ 0, 0, 1, 1 ],
},
R32F: { // f32
internalFormat: gl.R32F,
format: gl.RED,
type: gl.FLOAT,
minMag: gl.NEAREST,
src: [ 100, 25, 50, 75 ],
diffuseOffset: [ 0, 1, 0, 1 ],
},
R8UI: { // ui8 Y
internalFormat: gl.R8UI,
format: gl.RED_INTEGER,
type: gl.UNSIGNED_BYTE,
src: [ 50, 25, 175, 100 ],
diffuseOffset: [ 0, 100, 0, 200 ],
},
R8I: { // i8 Y
internalFormat: gl.R8I,
format: gl.RED_INTEGER,
type: gl.BYTE,
src: [ 0x100 - 50, 25, 0x100 - 75, 100 ],
diffuseOffset: [ 0, 0, 0, 100 ],
},
R16UI: { // ui16 Y
internalFormat: gl.R16UI,
format: gl.RED_INTEGER,
type: gl.UNSIGNED_SHORT,
src: [ 50, 25, 175, 100 ],
diffuseOffset: [ 0, 100, 100, 200 ],
},
R16I: { // i16 Y
internalFormat: gl.R16I,
format: gl.RED_INTEGER,
type: gl.SHORT,
width: 1,
src: [ 0x100 - 50, 25, 0x100 - 75, 100 ],
diffuseOffset: [ 0, 50, 100, 100 ],
},
R32UI: { // ui32 Y
internalFormat: gl.R32UI,
format: gl.RED_INTEGER,
type: gl.UNSIGNED_INT,
height: 1,
src: [ 50, 25, 175, 100 ],
diffuseOffset: [ 0, 100, 200, 200 ],
},
R32I: { // i32 Y
internalFormat: gl.R32I,
format: gl.RED_INTEGER,
type: gl.INT,
src: [ 0x100 - 50, 25, 0x100 - 75, 100 ],
diffuseOffset: [ 0, 0, 50, 100 ],
},
RG8: { // 8 8 Y Y
internalFormat: gl.RG8,
format: gl.RG,
type: gl.UNSIGNED_BYTE,
minMag: gl.NEAREST,
src: [ 255, 0, 0, 255 ],
},
RG8_SNORM: { // s8 s8 Y
internalFormat: gl.RG8_SNORM,
format: gl.RG,
type: gl.BYTE,
minMag: gl.NEAREST,
src: [ 32, 16, 64, 127],
},
RG16F: { // f16 f16 Y
internalFormat: gl.RG16F,
format: gl.RG,
type: gl.HALF_FLOAT,
minMag: gl.NEAREST,
src: new Uint16Array([ toHalf(20), toHalf(40), toHalf(60), 0, 0, toHalf(100), 0, 0]),
diffuseOffset: [0, 0, 0, 1],
},
RG16Fb: { // f16 f16 Y
internalFormat: gl.RG16F,
format: gl.RG,
type: gl.FLOAT,
minMag: gl.NEAREST,
src: [ 100, 100, 100, 50, 50, 100, 50, 70 ],
diffuseOffset: [0, 0, 0, 1],
},
RG32F: { // f32 f32
internalFormat: gl.RG32F,
format: gl.RG,
type: gl.FLOAT,
minMag: gl.NEAREST,
src: [ 20, 40, 40, 66, 66, 88, 88, 100 ],
diffuseOffset: [0, 0, 0, 1],
},
RG8UI: { // ui8 ui8 Y
internalFormat: gl.RG8UI,
format: gl.RG_INTEGER,
type: gl.UNSIGNED_BYTE,
width: 1,
src: [ 50, 75, 75, 25, 200, 175, 100, 200 ],
diffuseOffset: [ 0, 0, 200, 200 ],
},
RG8I: { // i8 i8 Y
internalFormat: gl.RG8I,
format: gl.RG_INTEGER,
type: gl.BYTE,
width: 1,
src: [ 50, 75, 75, 25, 80, 0x100 - 75, 100, 100 ],
diffuseOffset: [ 0, 0, 80, 100 ],
},
RG16UI: { // ui16 ui16 Y
internalFormat: gl.RG16UI,
format: gl.RG_INTEGER,
type: gl.UNSIGNED_SHORT,
src: [ 75, 50, 75, 25, 200, 175, 100, 200 ],
diffuseOffset: [ 0, 0, 200, 200 ],
},
RG16I: { // i16 i16 Y
internalFormat: gl.RG16I,
format: gl.RG_INTEGER,
type: gl.SHORT,
src: [ 80, 0x100 - 75, 50, 75, 75, 25, 100, 100 ],
diffuseOffset: [ 0, 0, 60, 100 ],
},
RG32UI: { // ui32 ui32 Y
internalFormat: gl.RG32UI,
format: gl.RG_INTEGER,
type: gl.UNSIGNED_INT,
src: [ 75, 50, 75, 25, 200, 175, 100, 200 ],
diffuseOffset: [ 0, 0, 100, 200 ],
},
RG32I: { // i32 i32 Y
internalFormat: gl.RG32I,
format: gl.RG_INTEGER,
type: gl.INT,
src: [ 80, 0x100 - 75, 50, 75, 75, 25, 100, 100 ],
diffuseOffset: [ 0, 0, 20, 100 ],
},
RGB8: { // 8 8 8 Y Y
internalFormat: gl.RGB8,
format: gl.RGB,
type: gl.UNSIGNED_BYTE,
minMag: gl.NEAREST,
src: [ 0, 0, 255, 255, 0, 255, 0, 255, 255, 255, 255, 255],
},
SRGB8: { // 8 8 8 Y
internalFormat: gl.SRGB8,
format: gl.RGB,
type: gl.UNSIGNED_BYTE,
width: 1,
minMag: gl.NEAREST,
src: [
64, 0, 0,
0, 96, 0,
0, 0, 127,
],
},
RGB565: { // 5 6 5 Y Y
internalFormat: gl.RGB565,
format: gl.RGB,
type: gl.UNSIGNED_BYTE,
minMag: gl.NEAREST,
src: [ 0xFF, 0xFF, 0x55, 0x55, 0xFF, 0xFF ],
},
RGB565b: { // 5 6 5 Y Y
internalFormat: gl.RGB565,
format: gl.RGB,
type: gl.UNSIGNED_SHORT_5_6_5,
minMag: gl.NEAREST,
src: new Uint16Array([rgb565(0, 1, 0), rgb565(0, 1, 1)]),
},
RGB8_SNORM: { // s8 s8 s8 Y
internalFormat: gl.RGB8_SNORM,
format: gl.RGB,
type: gl.BYTE,
src: [
127, 117, 107,
0x100 - 64, 0x100 - 32, 0x100 - 16,
12, 32, 64,
],
},
R11F_G11F_B10F: { // f11 f11 f10 Y
internalFormat: gl.R11F_G11F_B10F,
format: gl.RGB,
type: gl.UNSIGNED_INT_10F_11F_11F_REV,
src: [
rgb101111(50, 60, 100),
rgb101111(0, 0, 0),
rgb101111(70, 100, 70),
rgb101111(100, 0, 0),
rgb101111(0, 100, 0),
rgb101111(0, 0, 100),
],
diffuseMult: [1, 1, 1, 100],
},
R11F_G11F_B10Fb: { // f11 f11 f10 Y
internalFormat: gl.R11F_G11F_B10F,
format: gl.RGB,
type: gl.HALF_FLOAT,
src: [
toHalf(50), toHalf( 60), toHalf(100),
toHalf( 0), toHalf( 0), toHalf( 0),
toHalf(70), toHalf(100), toHalf(100),
],
diffuseOffset: [0, 0, 0, 1],
},
R11F_G11F_B10Fc: { // f11 f11 f10 Y
internalFormat: gl.R11F_G11F_B10F,
format: gl.RGB,
type: gl.FLOAT,
src: [
50, 60, 100,
0, 0, 0,
70, 100, 70,
70, 30, 70,
],
diffuseOffset: [0, 0, 0, 1],
},
RGB9_E5: { // 9 9 9 5 Y
internalFormat: gl.RGB9_E5,
format: gl.RGB,
type: gl.UNSIGNED_INT_5_9_9_9_REV,
src: [
rgb9e5(0.5, 1, 1),
rgb9e5( 1, 0, 0),
rgb9e5(0.7, 1, 0.5),
],
},
RGB9_E5b: { // 9 9 9 5 Y
internalFormat: gl.RGB9_E5,
format: gl.RGB,
type: gl.HALF_FLOAT,
minMag: gl.NEAREST,
src: new Uint16Array([
toHalf(0.2), toHalf(0.1), toHalf(0.1),
toHalf(0.4), toHalf(0.8), toHalf(0.5),
toHalf(0.6), toHalf(0.6), toHalf(0.9),
toHalf(0.8), toHalf(0.4), toHalf(0.5),
toHalf(0.1), toHalf(0.2), toHalf(0.1),
]),
},
RGB9_E5c: { // 9 9 9 5 Y
internalFormat: gl.RGB9_E5,
format: gl.RGB,
type: gl.FLOAT,
width: 2,
src: [
0.1, 0.2, 1.1,
0.2, 0.1, 0.1,
0.4, 0.5, 0.8,
0.6, 0.9, 0.6,
0.8, 0.5, 0.4,
1.1, 0.1, 0.2,
],
},
RGB16F: { // f16 f16 f16 Y
internalFormat: gl.RGB16F,
format: gl.RGB,
type: gl.HALF_FLOAT,
minMag: gl.NEAREST,
src: [ toHalf(1), toHalf(40), toHalf(90), toHalf(20), toHalf(70), toHalf(50) ],
diffuseOffset: [ 0, 0, 0, 1 ],
},
RGB16Fb: { // f16 f16 f16 Y
internalFormat: gl.RGB16F,
format: gl.RGB,
type: gl.FLOAT,
src: [ 90, 100, 80, 70, 50, 50 ],
diffuseOffset: [ 0, 0, 0, 1 ],
},
RGB32F: { // f32 f32 f32
internalFormat: gl.RGB32F,
format: gl.RGB,
type: gl.FLOAT,
src: [
50, 100, 50,
50, 90, 50,
50, 80, 50,
50, 70, 50,
50, 60, 50,
50, 40, 50,
50, 30, 50,
50, 20, 50,
],
diffuseOffset: [ 0, 0, 0, 1 ],
},
RGB8UI: { // ui8 ui8 ui8
internalFormat: gl.RGB8UI,
format: gl.RGB_INTEGER,
type: gl.UNSIGNED_BYTE,
src: [
200, 150, 100,
180, 175, 90,
160, 187, 80,
],
diffuseOffset: [ 0, 0, 0, 200 ],
},
RGB8I: { // i8 i8 i8
internalFormat: gl.RGB8I,
format: gl.RGB_INTEGER,
type: gl.BYTE,
src: [
0x100 - 50, 25, 100,
0x100 - 75, 100, 20,
0x100 - 50, 25, 100,
0x100 - 75, 60, 40,
0x100 - 50, 25, 100,
0x100 - 75, 20, 60,
],
diffuseOffset: [ 0, 0, 0, 100 ],
},
RGB16UI: { // ui16 ui16 ui16
internalFormat: gl.RGB16UI,
format: gl.RGB_INTEGER,
type: gl.UNSIGNED_SHORT,
src: [
150, 100, 200,
175, 90, 180,
187, 80, 160,
],
diffuseOffset: [ 0, 0, 0, 200 ],
},
RGB16I: { // i16 i16 i16
internalFormat: gl.RGB16I,
format: gl.RGB_INTEGER,
type: gl.SHORT,
src: [
25, 100, 0x100 - 50,
100, 20, 0x100 - 75,
25, 100, 0x100 - 50,
60, 40, 0x100 - 75,
25, 100, 0x100 - 50,
20, 60, 0x100 - 75,
],
diffuseOffset: [ 0, 0, 0, 100 ],
},
RGB32UI: { // ui32 ui32 ui32
internalFormat: gl.RGB32UI,
format: gl.RGB_INTEGER,
type: gl.UNSIGNED_INT,
src: [
150, 100, 200,
175, 90, 180,
187, 80, 160,
],
diffuseOffset: [ 0, 0, 0, 200 ],
},
RGB32I: { // i32 i32 i32
internalFormat: gl.RGB32I,
format: gl.RGB_INTEGER,
type: gl.INT,
src: [
0x100 - 50, 100, 25,
0x100 - 75, 20, 100,
0x100 - 50, 100, 25,
0x100 - 75, 40, 60,
0x100 - 50, 100, 25,
0x100 - 75, 60, 20,
],
diffuseOffset: [ 0, 0, 0, 100 ],
},
RGBA8: { // 8 8 8 8 Y Y
internalFormat: gl.RGBA8,
format: gl.RGBA,
type: gl.UNSIGNED_BYTE,
width: 1,
src: [
0x80, 0x90, 0x80, 0x80,
0x80, 0xA0, 0x80, 0xA0,
0x80, 0xB0, 0x80, 0xC0,
0x80, 0xC0, 0x80, 0xFF,
],
},
SRGB8_ALPHA8: { // 8 8 8 8 Y Y
internalFormat: gl.SRGB8_ALPHA8,
format: gl.RGBA,
type: gl.UNSIGNED_BYTE,
src: [
0x80, 0x80, 0x90, 0x80,
0x80, 0x80, 0xA0, 0xA0,
0x80, 0x80, 0xB0, 0xC0,
0x80, 0x80, 0xC0, 0xFF,
],
},
RGBA8_SNORM: { // s8 s8 s8 s8 Y
internalFormat: gl.RGBA8_SNORM,
format: gl.RGBA,
type: gl.BYTE,
src: [
0x7F, 0x60, 0x40, 0x60,
0x7F, 0x60, 0x40, 0x65,
0x7F, 0x60, 0x40, 0x70,
0x7F, 0x60, 0x40, 0x7F,
],
},
RGB5_A1: { // 5 5 5 1 Y Y
internalFormat: gl.RGB5_A1,
format: gl.RGBA,
type: gl.UNSIGNED_BYTE,
minMag: gl.NEAREST,
src: [
0xFF, 0x80, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0x00,
0x80, 0xFF, 0x80, 0x00, 0x80, 0x80, 0xFF, 0xFF, 0x80, 0xFF, 0x80, 0x00, 0x80, 0x80, 0xFF, 0xFF,
0xFF, 0x80, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0x00,
0x80, 0xFF, 0x80, 0x00, 0x80, 0x80, 0xFF, 0xFF, 0x80, 0xFF, 0x80, 0x00, 0x80, 0x80, 0xFF, 0xFF,
],
},
RGB5_A1b: { // 5 5 5 1 Y Y
internalFormat: gl.RGB5_A1,
format: gl.RGBA,
type: gl.UNSIGNED_SHORT_5_5_5_1,
minMag: gl.NEAREST,
wrap: gl.CLAMP_TO_EDGE,
src: [
rgba5551(0.75, 0.75, 1, 1),
rgba5551(0.75, 0.75, 1, 1),
rgba5551(0.75, 0.75, 1, 0),
rgba5551(0.75, 0.75, .8, 1),
],
},
RGB5_A1c: { // 5 5 5 1 Y Y
internalFormat: gl.RGB5_A1,
format: gl.RGBA,
type: gl.UNSIGNED_INT_2_10_10_10_REV,
minMag: gl.NEAREST,
wrap: gl.CLAMP_TO_EDGE,
width: 1,
src: [
rgba1010102(0, .1, 1, 1),
rgba1010102(0, .2, 1, 1),
rgba1010102(0, .4, 1, 1),
],
},
RGBA4: { // 4 4 4 4 Y Y
internalFormat: gl.RGBA4,
format: gl.RGBA,
type: gl.UNSIGNED_BYTE,
src: [
0xFF, 200, 100, 0xFF,
100, 0xFF, 100, 0xFF,
200, 100, 0xFF, 0xFF,
0xFF, 0xCF, 0xFF, 0xFF,
],
},
RGBA4b: { // 4 4 4 4 Y Y
internalFormat: gl.RGBA4,
format: gl.RGBA,
type: gl.UNSIGNED_SHORT_4_4_4_4,
minMag: gl.NEAREST,
src: new Uint16Array([
0xF00F,
0xF008,
0xFF0F,
0xFF08,
0x0F0F,
0x0F08,
0x0FFF,
0x0FF8,
0x00FF,
0x00F8,
]),
},
// RGB10_A2: { // 10 10 10 2 Y Y
// internalFormat: gl.RGB10_A2,
// format: gl.RGBA,
// type: gl.UNSIGNED_INT_2_10_10_10_REV,
// src: ,
// },
RGBA16F: { // f16 f16 f16 f16 Y
internalFormat: gl.RGBA16F,
format: gl.RGBA,
type: gl.HALF_FLOAT,
src: new Uint16Array([
toHalf( 80), toHalf(100), toHalf( 50), toHalf(100),
toHalf( 70), toHalf( 50), toHalf(100), toHalf( 80),
toHalf( 50), toHalf(100), toHalf( 50), toHalf( 60),
toHalf( 40), toHalf( 50), toHalf(100), toHalf( 40),
toHalf( 30), toHalf(100), toHalf( 50), toHalf( 20),
]),
},
RGBA16Fb: { // f16 f16 f16 f16 Y
internalFormat: gl.RGBA16F,
format: gl.RGBA,
type: gl.FLOAT,
src: (function(w, h) {
const m = [];
for (let y = 0; y < w; ++y) {
for (let x = 0; x < h; ++x) {
m.push(chroma.hsv(Math.abs(Math.atan2(x / (w - 1) - 0.5, y / (h - 1) - 0.5)) / Math.PI * 180, .8, 1).gl().map(x => x * 100));
}
}
return flatten(m);
}(16, 16)),
},
RGBA32F: { // f32 f32 f32 f32
internalFormat: gl.RGBA32F,
format: gl.RGBA,
type: gl.FLOAT,
src: [
100, 90, 80, 100,
100, 90, 80, 50,
90, 80, 70, 100,
90, 80, 70, 50,
80, 70, 60, 100,
80, 70, 60, 50,
70, 60, 50, 100,
],
},
RGBA8UI: { // ui8 ui8 ui8 ui8 Y
internalFormat: gl.RGBA8UI,
format: gl.RGBA_INTEGER,
type: gl.UNSIGNED_BYTE,
width: 5,
src: [
180, 160, 200, 200,
180, 150, 200, 100,
180, 140, 200, 200,
180, 130, 200, 100,
180, 120, 200, 200,
180, 160, 200, 100,
180, 150, 200, 200,
180, 140, 200, 100,
180, 130, 200, 200,
180, 120, 200, 100,
],
},
RGBA8I: { // i8 i8 i8 i8 Y
internalFormat: gl.RGBA8I,
format: gl.RGBA_INTEGER,
type: gl.BYTE,
src: [
80, 100, 60, 20,
80, 100, 50, 100,
80, 100, 40, 20,
80, 100, 30, 100,
80, 100, 20, 20,
80, 100, 60, 100,
80, 100, 50, 20,
80, 100, 40, 100,
80, 100, 30, 20,
80, 100, 20, 100,
],
},
RGB10_A2UI: { // ui10 ui10 ui10 ui2 Y
internalFormat: gl.RGB10_A2UI,
format: gl.RGBA_INTEGER,
type: gl.UNSIGNED_INT_2_10_10_10_REV,
src: new Uint32Array([
rgba1010102(0.09, 0.06, 1, 1),
rgba1010102(0.08, 0.06, 1, 0.75),
rgba1010102(0.07, 0.06, 1, 0.5),
rgba1010102(0.06, 0.06, 1, 0.3),
]),
diffuseMult: [1, 1, 1, 50],
diffuseOffset: [0, 0, 0, 0],
},
RGBA16UI: { // ui16 ui16 ui16 ui16 Y
internalFormat: gl.RGBA16UI,
format: gl.RGBA_INTEGER,
type: gl.UNSIGNED_SHORT,
src: [
120, 160, 160, 160,
140, 80, 140, 140,
120, 120, 60, 120,
],
},
RGBA16I: { // i16 i16 i16 i16 Y
internalFormat: gl.RGBA16I,
format: gl.RGBA_INTEGER,
type: gl.SHORT,
src: [
20, 60, 60, 100,
40, 80, 40, 80,
20, 20, 60, 60,
],
},
RGBA32I: { // i32 i32 i32 i32 Y
internalFormat: gl.RGBA32I,
format: gl.RGBA_INTEGER,
type: gl.INT,
src: [
100, 90, 80, 80,
90, 90, 80, 80,
80, 90, 80, 80,
70, 90, 80, 80,
],
},
RGBA32UI: { // ui32 ui32 ui32 ui32 Y
internalFormat: gl.RGBA32UI,
format: gl.RGBA_INTEGER,
type: gl.UNSIGNED_INT,
src: [
200, 90, 80, 180,
190, 90, 80, 180,
180, 90, 80, 180,
170, 90, 80, 180,
],
},
// Sized Internal Format Format Type Depth Bits Stencil Bits
DEPTH_COMPONENT16: { // 16
internalFormat: gl.DEPTH_COMPONENT16,
format: gl.DEPTH_COMPONENT,
type: gl.UNSIGNED_SHORT,
src: [
0xFFFF, 0x7FFF, 0xCFFF,
],
},
DEPTH_COMPONENT16b: { // 16
internalFormat: gl.DEPTH_COMPONENT16,
format: gl.DEPTH_COMPONENT,
type: gl.UNSIGNED_INT,
src: [
0xFFFFFFFF, 0xCFFFFFFF, 0x7FFFFFFF,
],
},
DEPTH_COMPONENT24: { // 24
internalFormat: gl.DEPTH_COMPONENT24,
format: gl.DEPTH_COMPONENT,
type: gl.UNSIGNED_INT,
src: [
0xFFFFFFFF, 0x7FFFFFFF, 0x3FFFFFFF,
],
diffuseOffset: [ 0, 0, 0, 1, ],
},
DEPTH_COMPONENT32F: { // f32
internalFormat: gl.DEPTH_COMPONENT32F,
format: gl.DEPTH_COMPONENT,
type: gl.FLOAT,
src: [ 1, 0.7, 0.5, 0.3 ],
diffuseMult: [ 100, 100, 100, 1 ],
diffuseOffset: [ 0, 0, 0, 1 ],
},
DEPTH24_STENCIL8: { // 24 8
internalFormat: gl.DEPTH24_STENCIL8,
format: gl.DEPTH_STENCIL,
type: gl.UNSIGNED_INT_24_8,
src: [
0xFFFFFFFF, 0x7FFFFFFF, 0x3FFFFFFF,
0x5FFFFFFF, 0xAFFFFFFF, 0xCFFFFFFF,
],
},
//DEPTH32F_STENCIL8: { // f32 8
// internalFormat: gl.DEPTH32F_STENCIL8,
// format: gl.DEPTH_STENCIL,
// type: gl.FLOAT_32_UNSIGNED_INT_24_8_REV,
// src: ,
//},
};
const textures = twgl.createTextures(gl, texturesSettings);
// This is soley to make it easy to pick textures at random
const twoDTextureNames = Object.keys(textures);
const objects = [];
const drawObjects = [];
const numObjects = 200;
// total / across / aspect = down
// 200
for (let ii = 0; ii < numObjects; ++ii) {
const shape = shapes[ii % shapes.length];
const texName = twoDTextureNames[ii % twoDTextureNames.length];
const texture = textures[texName];
const texSettings = texturesSettings[texName];
let programInfo = onePointProgramInfo;
if (texName.endsWith("UI")) {
programInfo = uintProgramInfo;
} else if (texName.endsWith("I")) {
programInfo = intProgramInfo;
} else if (texName.indexOf("F") >= 0 ) {
programInfo = floatProgramInfo;
} else if (texName.indexOf("SNORM") >= 0) {
programInfo = normProgramInfo;
}
const uniforms = {
u_diffuseMult: texSettings.diffuseMult || [1, 1, 1, 1], //chroma.hsv((baseHue + rand(0, 60)) % 360, 0.4, 0.8).gl(),
u_diffuseOffset: texSettings.diffuseOffset || [0, 0, 0, 0],
u_diffuse: texture,
u_viewInverse: camera,
u_world: m4.identity(),
u_worldInverseTranspose: m4.identity(),
u_worldViewProjection: m4.identity(),
};
drawObjects.push({
programInfo: programInfo,
bufferInfo: shape,
uniforms: uniforms,
});
objects.push({
translation: [rand(-10, 10), rand(-10, 10), rand(-10, 10)],
ySpeed: rand(0.1, 0.3),
zSpeed: rand(0.1, 0.3),
uniforms: uniforms,
});
}
function render(time) {
time *= 0.001;
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
const radius = 20;
const orbitSpeed = time * 0.1;
const projection = m4.perspective(30 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.5, 100);
const eye = [Math.cos(orbitSpeed) * radius, 4, Math.sin(orbitSpeed) * radius];
const target = [0, 0, 0];
const up = [0, 1, 0];
m4.lookAt(eye, target, up, camera);
m4.inverse(camera, view);
m4.multiply(projection, view, viewProjection);
objects.forEach(function(obj) {
const uni = obj.uniforms;
const world = uni.u_world;
m4.identity(world);
m4.rotateY(world, time * obj.ySpeed, world);
m4.rotateZ(world, time * obj.zSpeed, world);
m4.translate(world, obj.translation, world);
m4.rotateX(world, time, world);
m4.transpose(m4.inverse(world, uni.u_worldInverseTranspose), uni.u_worldInverseTranspose);
m4.multiply(viewProjection, uni.u_world, uni.u_worldViewProjection);
});
twgl.drawObjectList(gl, drawObjects);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
</script>
</html>