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 class="screen">
<canvas id="c"></canvas>
<canvas id="d"></canvas>
<canvas id="d" width="755" height="240"></canvas>
</div>
</div><!-- class="wrapper" -->
<script>
@ -218,16 +218,32 @@ void main() {
gl.drawArrays(primitiveType, offset, count);
// 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);
// });
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 sv = new screenEmu.ScreenView(canvas);
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();
sv.image = imageInfo;
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];
// Total number of CPU cycles per frame: 17030 for NTSC.
const frameCycleNum = HORIZ_TOTAL * vertTotal;
@ -228,6 +228,7 @@ void main(void)
const topLeft80Col = [imageLeft - CELL_WIDTH/2, vertStart - visibleRect[0][1]];
return {
fsc: fsc,
clockFrequency: clockFrequency,
displayRect: displayRect,
visibleRect: visibleRect,
@ -430,7 +431,7 @@ void main(void)
mul(val) {
const m = new Matrix3(0,0,0,0,0,0,0,0,0);
if (typeof val == "number") {
m.data = m.data.map(x => x * val);
m.data = this.data.map(x => x * val);
} else {
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
@ -472,8 +473,22 @@ void main(void)
context.fillStyle = 'rgba(0,0,0,1)';
context.fillRect(0, 0, width, height);
context.drawImage(image, details.topLeft80Col[0], details.topLeft80Col[1]);
// const myData = context.getImageData(0, 0, image.naturalWidth, image.naturalHeight);
return canvas;
const imageData = context.getImageData(0, 0, width, height);
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 = [
@ -566,17 +581,17 @@ void main(void)
this.videoHue = 0;
this.videoCenter = [0,0];
this.videoSize = [1,1];
this.videoBandwidth = 14318180;
this.videoLumaBandwidth = 600000;
this.videoChromaBandwidth = 2000000;
this.videoBandwidth = 6000000; // 14318180;
this.videoLumaBandwidth = 2000000; // 600000;
this.videoChromaBandwidth = 600000; // 2000000;
this.videoWhiteOnly = false;
this.displayResolution = [640, 480];
this.displayPixelDensity = 72;
this.displayBarrel = 0;
this.displayScanlineLevel = 0;
this.displayShadowMaskLevel = 0;
this.displayShadowMaskDotPitch = 1;
this.displayBarrel = 0.05; // 0;
this.displayScanlineLevel = 0.05; // 0;
this.displayShadowMaskLevel = 0.05; // 0;
this.displayShadowMaskDotPitch = 0.5; // 1;
this.displayShadowMask = "SHADOWMASK_TRIAD";
this.displayPersistence = 0;
this.displayCenterLighting = 1;
@ -786,20 +801,23 @@ void main(void)
gl.bindTexture(gl.TEXTURE_2D, texInfoImage.glTexture);
const format = gl.LUMINANCE;
const type = gl.UNSIGNED_BYTE;
const luminance = luminanceData(image.data);
gl.texSubImage2D(gl.TEXTURE_2D, 0,
0, 0, // xoffset, yoffset
format, type, image.data);
image.data.width,
image.data.height,
format, type, luminance);
// Update configuration
if ((image.sampleRate != this.imageSampleRate) ||
(image.blackLevel != this.imageBlackLevel) ||
(image.whiteLevel != this.imageWhiteLevel) ||
(image.subcarrier != this.imageSubcarrier))
(image.subCarrier != this.imageSubcarrier))
{
this.imageSampleRate = image.sampleRate;
this.imageBlackLevel = image.blackLevel;
this.imageWhiteLevel = image.whiteLevel;
this.imageSubcarrier = image.subcarrier;
this.imageSubcarrier = image.subCarrier;
this.configurationChanged = true;
}
@ -1204,7 +1222,7 @@ void main(void)
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.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0,
gl.LUMINANCE, gl.UNSIGNED_BYTE, dummy);
}
}
@ -1227,9 +1245,9 @@ void main(void)
NTSC_Q_CUTOFF: NTSC_Q_CUTOFF,
NTSC_IQ_DELTA: NTSC_IQ_DELTA,
NTSC_DETAILS: buildTiming(ntscClockFrequency, ntscDisplayRect,
ntscVisibleRect, ntscVertTotal),
ntscVisibleRect, ntscVertTotal, NTSC_FSC),
PAL_DETAILS: buildTiming(palClockFrequency, palDisplayRect,
palVisibleRect, palVertTotal),
palVisibleRect, palVertTotal, PAL_FSC),
},
loadImage: loadImage,
screenData: screenData,