mirror of
https://github.com/zellyn/apple2shader.git
synced 2025-01-14 10:29:51 +00:00
webgl: ongoing impl
This commit is contained in:
parent
e25b3bae1c
commit
3e9246fae6
52
index.html
52
index.html
@ -31,7 +31,6 @@ attribute vec4 a_position;
|
|||||||
|
|
||||||
// all shaders have a main function
|
// all shaders have a main function
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
// gl_Position is a special variable a vertex shader
|
// gl_Position is a special variable a vertex shader
|
||||||
// is responsible for setting
|
// is responsible for setting
|
||||||
gl_Position = a_position;
|
gl_Position = a_position;
|
||||||
@ -160,47 +159,6 @@ void main() {
|
|||||||
<script>
|
<script>
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// Code from:
|
|
||||||
// https://webglfundamentals.org/webgl/lessons/webgl-fundamentals.html
|
|
||||||
|
|
||||||
function createShader(gl, type, source) {
|
|
||||||
let shader = gl.createShader(type);
|
|
||||||
gl.shaderSource(shader, source);
|
|
||||||
gl.compileShader(shader);
|
|
||||||
let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
|
||||||
if (success) {
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
console.log(gl.getShaderInfoLog(shader));
|
|
||||||
gl.deleteShader(shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createProgram(gl, vertexShader, fragmentShader) {
|
|
||||||
let program = gl.createProgram();
|
|
||||||
gl.attachShader(program, vertexShader);
|
|
||||||
gl.attachShader(program, fragmentShader);
|
|
||||||
gl.linkProgram(program);
|
|
||||||
let success = gl.getProgramParameter(program, gl.LINK_STATUS);
|
|
||||||
if (success) {
|
|
||||||
return program;
|
|
||||||
}
|
|
||||||
console.log(gl.getProgramInfoLog(program));
|
|
||||||
gl.deleteProgram(program);
|
|
||||||
}
|
|
||||||
|
|
||||||
function resizeCanvas(canvas) {
|
|
||||||
// Lookup the size the browser is displaying the canvas.
|
|
||||||
let displayWidth = canvas.clientWidth;
|
|
||||||
let displayHeight = canvas.clientHeight;
|
|
||||||
|
|
||||||
// Check if the canvas is not the same size.
|
|
||||||
if (canvas.width != displayWidth ||
|
|
||||||
canvas.height != displayHeight) {
|
|
||||||
canvas.width = displayWidth;
|
|
||||||
canvas.height = displayHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
|
|
||||||
let canvas = document.getElementById("c");
|
let canvas = document.getElementById("c");
|
||||||
@ -208,10 +166,10 @@ void main() {
|
|||||||
|
|
||||||
let vertexShaderSource = document.getElementById("vertexShader").text;
|
let vertexShaderSource = document.getElementById("vertexShader").text;
|
||||||
let fragmentShaderSource = document.getElementById("fragmentShader").text;
|
let fragmentShaderSource = document.getElementById("fragmentShader").text;
|
||||||
let vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
|
let vertexShader = screenEmu.createShader(gl, 'vertexShader', gl.VERTEX_SHADER, vertexShaderSource);
|
||||||
let fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
|
let fragmentShader = screenEmu.createShader(gl, 'fragmentShader', gl.FRAGMENT_SHADER, fragmentShaderSource);
|
||||||
|
|
||||||
let program = createProgram(gl, vertexShader, fragmentShader);
|
let program = screenEmu.createProgram(gl, 'program', vertexShader, fragmentShader);
|
||||||
|
|
||||||
let positionAttributeLocation = gl.getAttribLocation(program, "a_position");
|
let positionAttributeLocation = gl.getAttribLocation(program, "a_position");
|
||||||
let positionBuffer = gl.createBuffer();
|
let positionBuffer = gl.createBuffer();
|
||||||
@ -226,7 +184,7 @@ void main() {
|
|||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
|
|
||||||
resizeCanvas(gl.canvas);
|
screenEmu.resizeCanvas(gl.canvas);
|
||||||
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
|
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
|
||||||
|
|
||||||
// Clear the canvas.
|
// Clear the canvas.
|
||||||
@ -273,7 +231,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tryScreenView().then(() => console.log('tryScreenView: success'))
|
tryScreenView().then(() => console.log('tryScreenView: success'))
|
||||||
.catch(() => console.log('tryScreenView: error'));
|
.catch((e) => console.log(`tryScreenView: error: ${e}`));
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
261
screenEmu.js
261
screenEmu.js
@ -59,21 +59,39 @@ let screenEmu = (function () {
|
|||||||
[HORIZ_DISPLAY, VERT_DISPLAY]];
|
[HORIZ_DISPLAY, VERT_DISPLAY]];
|
||||||
let palVertTotal = PAL_VTOTAL;
|
let palVertTotal = PAL_VTOTAL;
|
||||||
|
|
||||||
|
const VERTEX_SHADER =`
|
||||||
|
// an attribute will receive data from a buffer
|
||||||
|
attribute vec4 a_position;
|
||||||
|
attribute vec2 a_texCoord;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
|
||||||
|
// all shaders have a main function
|
||||||
|
void main() {
|
||||||
|
// gl_Position is a special variable a vertex shader
|
||||||
|
// is responsible for setting
|
||||||
|
gl_Position = a_position;
|
||||||
|
v_texCoord = a_texCoord;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const COMPOSITE_SHADER = `
|
const COMPOSITE_SHADER = `
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
uniform sampler2D texture;
|
uniform sampler2D texture;
|
||||||
uniform vec2 textureSize;
|
uniform vec2 textureSize;
|
||||||
uniform float subcarrier;
|
uniform float subcarrier;
|
||||||
uniform sampler1D phaseInfo;
|
uniform sampler2D phaseInfo;
|
||||||
uniform vec3 c0, c1, c2, c3, c4, c5, c6, c7, c8;
|
uniform vec3 c0, c1, c2, c3, c4, c5, c6, c7, c8;
|
||||||
uniform mat3 decoderMatrix;
|
uniform mat3 decoderMatrix;
|
||||||
uniform vec3 decoderOffset;
|
uniform vec3 decoderOffset;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
|
||||||
float PI = 3.14159265358979323846264;
|
float PI = 3.14159265358979323846264;
|
||||||
|
|
||||||
vec3 pixel(in vec2 q)
|
vec3 pixel(in vec2 q)
|
||||||
{
|
{
|
||||||
vec3 c = texture2D(texture, q).rgb;
|
vec3 c = texture2D(texture, q).rgb;
|
||||||
vec2 p = texture1D(phaseInfo, q.y).rg;
|
vec2 p = texture2D(phaseInfo, vec2(0, q.y)).rg;
|
||||||
float phase = 2.0 * PI * (subcarrier * textureSize.x * q.x + p.x);
|
float phase = 2.0 * PI * (subcarrier * textureSize.x * q.x + p.x);
|
||||||
return c * vec3(1.0, sin(phase), (1.0 - 2.0 * p.y) * cos(phase));
|
return c * vec3(1.0, sin(phase), (1.0 - 2.0 * p.y) * cos(phase));
|
||||||
}
|
}
|
||||||
@ -85,7 +103,7 @@ vec3 pixels(vec2 q, float i)
|
|||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
vec2 q = gl_TexCoord[0].st;
|
vec2 q = v_texCoord;
|
||||||
vec3 c = pixel(q) * c0;
|
vec3 c = pixel(q) * c0;
|
||||||
c += pixels(q, 1.0 / textureSize.x) * c1;
|
c += pixels(q, 1.0 / textureSize.x) * c1;
|
||||||
c += pixels(q, 2.0 / textureSize.x) * c2;
|
c += pixels(q, 2.0 / textureSize.x) * c2;
|
||||||
@ -100,6 +118,8 @@ void main(void)
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const DISPLAY_SHADER = `
|
const DISPLAY_SHADER = `
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
uniform sampler2D texture;
|
uniform sampler2D texture;
|
||||||
uniform vec2 textureSize;
|
uniform vec2 textureSize;
|
||||||
uniform float barrel;
|
uniform float barrel;
|
||||||
@ -114,21 +134,22 @@ uniform vec2 persistenceSize;
|
|||||||
uniform vec2 persistenceOrigin;
|
uniform vec2 persistenceOrigin;
|
||||||
uniform float persistenceLevel;
|
uniform float persistenceLevel;
|
||||||
uniform float luminanceGain;
|
uniform float luminanceGain;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
|
||||||
float PI = 3.14159265358979323846264;
|
float PI = 3.14159265358979323846264;
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
vec2 qc = (gl_TexCoord[1].st - vec2(0.5, 0.5)) * barrelSize;
|
vec2 qc = (v_texCoord - vec2(0.5, 0.5)) * barrelSize;
|
||||||
vec2 qb = barrel * qc * dot(qc, qc);
|
vec2 qb = barrel * qc * dot(qc, qc);
|
||||||
vec2 q = gl_TexCoord[0].st + qb;
|
vec2 q = v_texCoord + qb;
|
||||||
|
|
||||||
vec3 c = texture2D(texture, q).rgb;
|
vec3 c = texture2D(texture, q).rgb;
|
||||||
|
|
||||||
float scanline = sin(PI * textureSize.y * q.y);
|
float scanline = sin(PI * textureSize.y * q.y);
|
||||||
c *= mix(1.0, scanline * scanline, scanlineLevel);
|
c *= mix(1.0, scanline * scanline, scanlineLevel);
|
||||||
|
|
||||||
vec3 mask = texture2D(shadowMask, (gl_TexCoord[1].st + qb) * shadowMaskSize).rgb;
|
vec3 mask = texture2D(shadowMask, (v_texCoord + qb) * shadowMaskSize).rgb;
|
||||||
c *= mix(vec3(1.0, 1.0, 1.0), mask, shadowMaskLevel);
|
c *= mix(vec3(1.0, 1.0, 1.0), mask, shadowMaskLevel);
|
||||||
|
|
||||||
vec2 lighting = qc * centerLighting;
|
vec2 lighting = qc * centerLighting;
|
||||||
@ -136,7 +157,7 @@ void main(void)
|
|||||||
|
|
||||||
c *= luminanceGain;
|
c *= luminanceGain;
|
||||||
|
|
||||||
vec2 qp = gl_TexCoord[1].st * persistenceSize + persistenceOrigin;
|
vec2 qp = v_texCoord * persistenceSize + persistenceOrigin;
|
||||||
c = max(c, texture2D(persistence, qp).rgb * persistenceLevel - 0.5 / 256.0);
|
c = max(c, texture2D(persistence, qp).rgb * persistenceLevel - 0.5 / 256.0);
|
||||||
|
|
||||||
gl_FragColor = vec4(c, 1.0);
|
gl_FragColor = vec4(c, 1.0);
|
||||||
@ -227,6 +248,52 @@ void main(void)
|
|||||||
"DISPLAY",
|
"DISPLAY",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const resizeCanvas = (canvas) => {
|
||||||
|
// Lookup the size the browser is displaying the canvas.
|
||||||
|
let displayWidth = canvas.clientWidth;
|
||||||
|
let displayHeight = canvas.clientHeight;
|
||||||
|
|
||||||
|
// Check if the canvas is not the same size.
|
||||||
|
if (canvas.width != displayWidth ||
|
||||||
|
canvas.height != displayHeight) {
|
||||||
|
canvas.width = displayWidth;
|
||||||
|
canvas.height = displayHeight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Code from:
|
||||||
|
// https://webglfundamentals.org/webgl/lessons/webgl-fundamentals.html
|
||||||
|
const createShader = (gl, name, type, source) => {
|
||||||
|
let shader = gl.createShader(type);
|
||||||
|
gl.shaderSource(shader, source);
|
||||||
|
gl.compileShader(shader);
|
||||||
|
let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
||||||
|
if (success) {
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
let log = gl.getShaderInfoLog(shader);
|
||||||
|
gl.deleteShader(shader);
|
||||||
|
throw `unable to compile shader ${name}: \n${log}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Code from:
|
||||||
|
// https://webglfundamentals.org/webgl/lessons/webgl-fundamentals.html
|
||||||
|
const createProgram = (gl, name, ...shaders) => {
|
||||||
|
let program = gl.createProgram();
|
||||||
|
for (let shader of shaders) {
|
||||||
|
gl.attachShader(program, shader);
|
||||||
|
}
|
||||||
|
gl.linkProgram(program);
|
||||||
|
let success = gl.getProgramParameter(program, gl.LINK_STATUS);
|
||||||
|
if (success) {
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
let log = gl.getProgramInfoLog(program);
|
||||||
|
gl.deleteProgram(program);
|
||||||
|
throw `unable to compile program ${name}: \n${log}`;
|
||||||
|
};
|
||||||
|
|
||||||
const TextureInfo = class {
|
const TextureInfo = class {
|
||||||
constructor(width, height, glTexture) {
|
constructor(width, height, glTexture) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
@ -235,11 +302,40 @@ void main(void)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ImageInfo = class {
|
||||||
|
constructor(sampleRate, blackLevel, whiteLevel, subCarrier, colorBurst,
|
||||||
|
phaseAlternation, data) {
|
||||||
|
this.sampleRate = sampleRate;
|
||||||
|
this.blackLevel = blackLevel;
|
||||||
|
this.whiteLevel = whiteLevel;
|
||||||
|
this.subCarrier = subCarrier;
|
||||||
|
this.colorBurst = colorBurst;
|
||||||
|
this.phaseAlternation = phaseAlternation;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
get width() {
|
||||||
|
// TODO(zellyn): implement
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
get height() {
|
||||||
|
// TODO(zellyn): implement
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const ScreenView = class {
|
const ScreenView = class {
|
||||||
constructor(gl) {
|
constructor(gl) {
|
||||||
this.gl = gl;
|
this.gl = gl;
|
||||||
this.textures = {};
|
this.textures = {};
|
||||||
this.shaders = {};
|
this.shaders = {};
|
||||||
|
this.image = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
set image(imageInfo) {
|
||||||
|
this.imageInfo = imageInfo;
|
||||||
|
this.imageChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async initOpenGL() {
|
async initOpenGL() {
|
||||||
@ -284,74 +380,52 @@ void main(void)
|
|||||||
|
|
||||||
async loadTexture(path, isMipMap, name) {
|
async loadTexture(path, isMipMap, name) {
|
||||||
let gl = this.gl;
|
let gl = this.gl;
|
||||||
let textureInfo = this.textures[name];
|
let texInfo = this.textures[name];
|
||||||
let image = await loadImage(path);
|
let image = await loadImage(path);
|
||||||
gl.bindTexture(gl.TEXTURE_2D, textureInfo.glTexture);
|
gl.bindTexture(gl.TEXTURE_2D, texInfo.glTexture);
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,
|
||||||
// TODO(zellyn): implement
|
gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||||
if (isMipMap) {
|
if (isMipMap) {
|
||||||
// gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8,
|
gl.generateMipmap(gl.TEXTURE_2D);
|
||||||
// image.getSize().width, image.getSize().height,
|
|
||||||
// getGLFormat(image.getFormat()),
|
|
||||||
// GL_UNSIGNED_BYTE, image.getPixels());
|
|
||||||
} else {
|
|
||||||
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
|
||||||
// image.getSize().width, image.getSize().height,
|
|
||||||
// 0,
|
|
||||||
// getGLFormat(image.getFormat()), GL_UNSIGNED_BYTE, image.getPixels());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textureInfo.width = image.naturalWidth;
|
texInfo.width = image.naturalWidth;
|
||||||
textureInfo.height = image.naturalHeight;
|
texInfo.height = image.naturalHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(zellyn): implement
|
|
||||||
loadShaders() {
|
loadShaders() {
|
||||||
this.loadShader("COMPOSITE", COMPOSITE_SHADER);
|
this.loadShader("COMPOSITE", COMPOSITE_SHADER);
|
||||||
this.loadShader("DISPLAY", DISPLAY_SHADER);
|
this.loadShader("DISPLAY", DISPLAY_SHADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(zellyn): implement
|
|
||||||
loadShader(name, source) {
|
loadShader(name, source) {
|
||||||
console.log(`ScreenView.loadShader(${name}): not implemented yet`);
|
console.log(`ScreenView.loadShader(${name}): not implemented yet`);
|
||||||
|
|
||||||
|
let glVertexShader = createShader(this.gl, name, this.gl.VERTEX_SHADER, VERTEX_SHADER);
|
||||||
|
let glFragmentShader = createShader(this.gl, name, this.gl.FRAGMENT_SHADER, source);
|
||||||
|
let glProgram = createProgram(this.gl, name, glVertexShader, glFragmentShader);
|
||||||
|
this.gl.deleteShader(glVertexShader);
|
||||||
|
this.gl.deleteShader(glFragmentShader);
|
||||||
|
this.shaders[name] = glProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(zellyn): implement
|
|
||||||
deleteShaders() {
|
deleteShaders() {
|
||||||
for (let name of SHADER_NAMES) {
|
for (let name of SHADER_NAMES) {
|
||||||
if (this.shaders[name]) {
|
if (this.shaders[name]) {
|
||||||
gl.deleteProgram(this.shaders[name]);
|
this.gl.deleteProgram(this.shaders[name]);
|
||||||
this.shaders[name] = false;
|
this.shaders[name] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Resize the texture with the given name to the next
|
// TODO(zellyn): implement
|
||||||
// highest power of two width and height. Wouldn't be
|
vsync() {
|
||||||
// necessary with webgl2.
|
|
||||||
const resizeTexture = (gl, textures, name, width, height) => {
|
|
||||||
let textureInfo = textures[name];
|
|
||||||
if (!!textureInfo) {
|
|
||||||
throw `Cannot find texture named ${name}`;
|
|
||||||
}
|
|
||||||
if (width < 4) width = 4;
|
|
||||||
if (height < 4) height = 4;
|
|
||||||
width = 2**Math.ceil(Math.log2(width));
|
|
||||||
height = 2**Math.ceil(Math.log2(height));
|
|
||||||
textureInfo.width = width;
|
|
||||||
textureInfo.height = height;
|
|
||||||
gl.bindTexture(gl.TEXTURE_2D, textureInfo.glTexture);
|
|
||||||
const dummy = new Uint8Array(width * height);
|
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, dummy);
|
|
||||||
};
|
|
||||||
|
|
||||||
const vsync = (gl) => {
|
|
||||||
// if viewport size has changed:
|
// if viewport size has changed:
|
||||||
// glViewPort(0, 0, new_width, new_height);
|
// glViewPort(0, 0, new_width, new_height);
|
||||||
|
|
||||||
// if image updated:
|
if (this.imageChanged) {
|
||||||
// uploadImage();
|
this.uploadImage();
|
||||||
|
}
|
||||||
|
|
||||||
// if configuration updated:
|
// if configuration updated:
|
||||||
// configureShaders();
|
// configureShaders();
|
||||||
@ -361,23 +435,88 @@ void main(void)
|
|||||||
|
|
||||||
// if anything updated, or displayPersistence != 0.0
|
// if anything updated, or displayPersistence != 0.0
|
||||||
// drawDisplayCanvas();
|
// drawDisplayCanvas();
|
||||||
};
|
}
|
||||||
|
|
||||||
|
uploadImage() {
|
||||||
|
let image = this.imageInfo;
|
||||||
|
|
||||||
|
this.resizeTexture("IMAGE_IN", image.width, image.height);
|
||||||
|
let texInfo = this.textures["IMAGE_IN"];
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texInfo.glTexture);
|
||||||
|
let format = gl.XYZZY;
|
||||||
|
gl.texSubImage(gl.TEXTURE_2D, 0,
|
||||||
|
0, 0,
|
||||||
|
image.width, image.height,
|
||||||
|
format, gl.UNSIGNED_BYTE, image.pixels);
|
||||||
|
|
||||||
|
// Update configuration
|
||||||
|
if ((image.sampleRate != this.imageSampleRate) ||
|
||||||
|
(image.blackLevel != this.imageBlackLevel) ||
|
||||||
|
(image.whiteLevel != this.imageWhiteLevel) ||
|
||||||
|
(image.subcarrier != this.imageSubcarrier))
|
||||||
|
{
|
||||||
|
this.imageSampleRate = image.sampleRate;
|
||||||
|
this.imageBlackLevel = image.blackLevel;
|
||||||
|
this.imageWhiteLevel = image.whiteLevel;
|
||||||
|
this.imageSubcarrier = image.subcarrier;
|
||||||
|
|
||||||
|
this.isConfigurationUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload phase info
|
||||||
|
let texHeight = 2**Math.ceil(Math.log2(image.height));
|
||||||
|
let colorBurst = image.colorBurst
|
||||||
|
let phaseAlternation = image.phaseAlternation;
|
||||||
|
|
||||||
|
let phaseInfo = new Float32Array(3 * texHeight);
|
||||||
|
|
||||||
|
for (let x = 0; x < image.height; x++) {
|
||||||
|
let c = colorBurst[x % colorBurst.length] / 2 / Math.PI;
|
||||||
|
phaseInfo[3 * x + 0] = c - Math.floor(c);
|
||||||
|
phaseInfo[3 * x + 1] = phaseAlternation[x % phaseAlternation.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
texInfo = this.textures("IMAGE_PHASEINFO");
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texInfo.glTexture);
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, texHeight, 0,
|
||||||
|
gl.RGB, gl.FLOAT, phaseInfo);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(zellyn): implement
|
// TODO(zellyn): implement
|
||||||
const uploadImage = (gl) => {
|
configureShaders() {
|
||||||
};
|
}
|
||||||
|
|
||||||
// TODO(zellyn): implement
|
// TODO(zellyn): implement
|
||||||
const configureShaders = (gl) => {
|
renderImage() {
|
||||||
};
|
}
|
||||||
|
|
||||||
// TODO(zellyn): implement
|
// TODO(zellyn): implement
|
||||||
const renderImage = (gl) => {
|
drawDisplayCanvas() {
|
||||||
};
|
}
|
||||||
|
|
||||||
// TODO(zellyn): implement
|
// Resize the texture with the given name to the next
|
||||||
const drawDisplayCanvas = (gl) => {
|
// highest power of two width and height. Wouldn't be
|
||||||
};
|
// necessary with webgl2.
|
||||||
|
resizeTexture(name, width, height) {
|
||||||
|
let gl = this.gl;
|
||||||
|
let texInfo = this.textures[name];
|
||||||
|
if (!!texInfo) {
|
||||||
|
throw `Cannot find texture named ${name}`;
|
||||||
|
}
|
||||||
|
if (width < 4) width = 4;
|
||||||
|
if (height < 4) height = 4;
|
||||||
|
width = 2**Math.ceil(Math.log2(width));
|
||||||
|
height = 2**Math.ceil(Math.log2(height));
|
||||||
|
if (texInfo.width != width || texInfo.height != height) {
|
||||||
|
texInfo.width = width;
|
||||||
|
texInfo.height = height;
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texInfo.glTexture);
|
||||||
|
const dummy = new Uint8Array(width * height);
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, width, height, 0,
|
||||||
|
gl.LUMINANCE, gl.UNSIGNED_BYTE, dummy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
C: {
|
C: {
|
||||||
@ -399,7 +538,9 @@ void main(void)
|
|||||||
},
|
},
|
||||||
loadImage: loadImage,
|
loadImage: loadImage,
|
||||||
screenData: screenData,
|
screenData: screenData,
|
||||||
resizeTexture: resizeTexture,
|
|
||||||
getScreenView: (gl) => new ScreenView(gl),
|
getScreenView: (gl) => new ScreenView(gl),
|
||||||
|
resizeCanvas: resizeCanvas,
|
||||||
|
createShader: createShader,
|
||||||
|
createProgram: createProgram,
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user