webgl: renderImage now correct except for final copy; untabify all

This commit is contained in:
Zellyn Hunter 2018-05-09 22:35:14 -04:00
parent dba6c94236
commit 1881b62f3a
2 changed files with 262 additions and 228 deletions

View File

@ -153,7 +153,7 @@ void main() {
</div> </div>
<div class="screen"> <div class="screen">
<canvas id="c"></canvas> <canvas id="c"></canvas>
<canvas id="d"></canvas> <canvas id="d" width="755" height="240"></canvas>
</div> </div>
</div><!-- class="wrapper" --> </div><!-- class="wrapper" -->
<script> <script>
@ -218,16 +218,32 @@ void main() {
gl.drawArrays(primitiveType, offset, count); gl.drawArrays(primitiveType, offset, count);
// screenEmu.loadImage("images/airheart-560x192.png").then(image => { // screenEmu.loadImage("images/airheart-560x192.png").then(image => {
// let c = screenEmu.screenData(image, screenEmu.C.NTSC_DETAILS); // let [c, data] = screenEmu.screenData(image, screenEmu.C.NTSC_DETAILS);
// document.body.appendChild(c); // document.body.appendChild(c);
// }); // });
async function tryScreenView() { async function tryScreenView() {
const image = await screenEmu.loadImage("images/airheart-560x192.png");
const [imageCanvas, imageData] = screenEmu.screenData(image, screenEmu.C.NTSC_DETAILS);
let canvas = document.getElementById("d"); let canvas = document.getElementById("d");
let sv = new screenEmu.ScreenView(canvas); let sv = new screenEmu.ScreenView(canvas);
await sv.initOpenGL(); await sv.initOpenGL();
let imageInfo = new screenEmu.ImageInfo(0, 0, 0, 0, 0, 0, new ImageData(10, 10)); const sampleRate = 4 * screenEmu.C.NTSC_DETAILS.fsc;
const blackLevel = 0;
const whiteLevel = 1;
const subCarrier = screenEmu.C.NTSC_DETAILS.fsc;
const colorBurst = screenEmu.C.NTSC_DETAILS.colorBurst;
const phaseAlternation = [false];
let imageInfo = new screenEmu.ImageInfo(
sampleRate,
blackLevel,
whiteLevel,
subCarrier,
colorBurst,
phaseAlternation,
imageData);
let displayConfig = new screenEmu.DisplayConfiguration(); let displayConfig = new screenEmu.DisplayConfiguration();
sv.image = imageInfo; sv.image = imageInfo;
sv.displayConfiguration = displayConfig; sv.displayConfiguration = displayConfig;

View File

@ -208,7 +208,7 @@ void main(void)
} }
`; `;
function buildTiming(clockFrequency, displayRect, visibleRect, vertTotal) { function buildTiming(clockFrequency, displayRect, visibleRect, vertTotal, fsc) {
const vertStart = displayRect[0][1]; const vertStart = displayRect[0][1];
// Total number of CPU cycles per frame: 17030 for NTSC. // Total number of CPU cycles per frame: 17030 for NTSC.
const frameCycleNum = HORIZ_TOTAL * vertTotal; const frameCycleNum = HORIZ_TOTAL * vertTotal;
@ -228,6 +228,7 @@ void main(void)
const topLeft80Col = [imageLeft - CELL_WIDTH/2, vertStart - visibleRect[0][1]]; const topLeft80Col = [imageLeft - CELL_WIDTH/2, vertStart - visibleRect[0][1]];
return { return {
fsc: fsc,
clockFrequency: clockFrequency, clockFrequency: clockFrequency,
displayRect: displayRect, displayRect: displayRect,
visibleRect: visibleRect, visibleRect: visibleRect,
@ -430,7 +431,7 @@ void main(void)
mul(val) { mul(val) {
const m = new Matrix3(0,0,0,0,0,0,0,0,0); const m = new Matrix3(0,0,0,0,0,0,0,0,0);
if (typeof val == "number") { if (typeof val == "number") {
m.data = m.data.map(x => x * val); m.data = this.data.map(x => x * val);
} else { } else {
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) { for (let j = 0; j < 3; j++) {
@ -472,8 +473,22 @@ void main(void)
context.fillStyle = 'rgba(0,0,0,1)'; context.fillStyle = 'rgba(0,0,0,1)';
context.fillRect(0, 0, width, height); context.fillRect(0, 0, width, height);
context.drawImage(image, details.topLeft80Col[0], details.topLeft80Col[1]); context.drawImage(image, details.topLeft80Col[0], details.topLeft80Col[1]);
// const myData = context.getImageData(0, 0, image.naturalWidth, image.naturalHeight); const imageData = context.getImageData(0, 0, width, height);
return canvas; return [canvas, imageData];
};
// Given an ImageData (RGBA), convert to luminance by taking the max
// of (R,G,B) for each pixel. Return a Uint8Array.
const luminanceData = (imageData) => {
const width = imageData.width;
const height = imageData.height;
const data = imageData.data;
const size = width * height;
const ary = new Uint8Array(size);
for (let i = 0; i < size; i++) {
ary[i] = Math.max(data[i*4], data[i*4+1], data[i*4+2]);
}
return ary;
}; };
const TEXTURE_NAMES = [ const TEXTURE_NAMES = [
@ -566,17 +581,17 @@ void main(void)
this.videoHue = 0; this.videoHue = 0;
this.videoCenter = [0,0]; this.videoCenter = [0,0];
this.videoSize = [1,1]; this.videoSize = [1,1];
this.videoBandwidth = 14318180; this.videoBandwidth = 6000000; // 14318180;
this.videoLumaBandwidth = 600000; this.videoLumaBandwidth = 2000000; // 600000;
this.videoChromaBandwidth = 2000000; this.videoChromaBandwidth = 600000; // 2000000;
this.videoWhiteOnly = false; this.videoWhiteOnly = false;
this.displayResolution = [640, 480]; this.displayResolution = [640, 480];
this.displayPixelDensity = 72; this.displayPixelDensity = 72;
this.displayBarrel = 0; this.displayBarrel = 0.05; // 0;
this.displayScanlineLevel = 0; this.displayScanlineLevel = 0.05; // 0;
this.displayShadowMaskLevel = 0; this.displayShadowMaskLevel = 0.05; // 0;
this.displayShadowMaskDotPitch = 1; this.displayShadowMaskDotPitch = 0.5; // 1;
this.displayShadowMask = "SHADOWMASK_TRIAD"; this.displayShadowMask = "SHADOWMASK_TRIAD";
this.displayPersistence = 0; this.displayPersistence = 0;
this.displayCenterLighting = 1; this.displayCenterLighting = 1;
@ -786,20 +801,23 @@ void main(void)
gl.bindTexture(gl.TEXTURE_2D, texInfoImage.glTexture); gl.bindTexture(gl.TEXTURE_2D, texInfoImage.glTexture);
const format = gl.LUMINANCE; const format = gl.LUMINANCE;
const type = gl.UNSIGNED_BYTE; const type = gl.UNSIGNED_BYTE;
const luminance = luminanceData(image.data);
gl.texSubImage2D(gl.TEXTURE_2D, 0, gl.texSubImage2D(gl.TEXTURE_2D, 0,
0, 0, // xoffset, yoffset 0, 0, // xoffset, yoffset
format, type, image.data); image.data.width,
image.data.height,
format, type, luminance);
// Update configuration // Update configuration
if ((image.sampleRate != this.imageSampleRate) || if ((image.sampleRate != this.imageSampleRate) ||
(image.blackLevel != this.imageBlackLevel) || (image.blackLevel != this.imageBlackLevel) ||
(image.whiteLevel != this.imageWhiteLevel) || (image.whiteLevel != this.imageWhiteLevel) ||
(image.subcarrier != this.imageSubcarrier)) (image.subCarrier != this.imageSubcarrier))
{ {
this.imageSampleRate = image.sampleRate; this.imageSampleRate = image.sampleRate;
this.imageBlackLevel = image.blackLevel; this.imageBlackLevel = image.blackLevel;
this.imageWhiteLevel = image.whiteLevel; this.imageWhiteLevel = image.whiteLevel;
this.imageSubcarrier = image.subcarrier; this.imageSubcarrier = image.subCarrier;
this.configurationChanged = true; this.configurationChanged = true;
} }
@ -1204,7 +1222,7 @@ void main(void)
texInfo.height = height; texInfo.height = height;
gl.bindTexture(gl.TEXTURE_2D, texInfo.glTexture); gl.bindTexture(gl.TEXTURE_2D, texInfo.glTexture);
const dummy = new Uint8Array(width * height); const dummy = new Uint8Array(width * height);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, width, height, 0, gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0,
gl.LUMINANCE, gl.UNSIGNED_BYTE, dummy); gl.LUMINANCE, gl.UNSIGNED_BYTE, dummy);
} }
} }
@ -1227,9 +1245,9 @@ void main(void)
NTSC_Q_CUTOFF: NTSC_Q_CUTOFF, NTSC_Q_CUTOFF: NTSC_Q_CUTOFF,
NTSC_IQ_DELTA: NTSC_IQ_DELTA, NTSC_IQ_DELTA: NTSC_IQ_DELTA,
NTSC_DETAILS: buildTiming(ntscClockFrequency, ntscDisplayRect, NTSC_DETAILS: buildTiming(ntscClockFrequency, ntscDisplayRect,
ntscVisibleRect, ntscVertTotal), ntscVisibleRect, ntscVertTotal, NTSC_FSC),
PAL_DETAILS: buildTiming(palClockFrequency, palDisplayRect, PAL_DETAILS: buildTiming(palClockFrequency, palDisplayRect,
palVisibleRect, palVertTotal), palVisibleRect, palVertTotal, PAL_FSC),
}, },
loadImage: loadImage, loadImage: loadImage,
screenData: screenData, screenData: screenData,