Formula Not Working as Expected when inside GPU.js kernel
sojs-coder opened this issue · comments
No meme sorry
What is wrong?
I have made a lighting shader using GPU.js. After taking the exact same code and modifying it to work with variables passed to a GPU.js kernel, it stops working.
This is a photo of it working...
The exact same formula put into GPU.js kernel (I am away that the kernel's height is inverted from normal canvas.js... this is not the problem
Where does it happen?
Firefox, chrome browsers.
How do we replicate the issue?
Copied and pasted no worky code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Directional Lighting Scene</title>
<style>
canvas { border: 1px solid #000; }
</style>
</head>
<body>
<script src = "matter.js"></script>
<script src = "gpu.js"></script>
<script src = "anvil.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Define colored triangles in the scene
const triangles = [
{ vertices: [[50, 50], [150, 50], [100, 150]], color: [255, 0, 0, 255] }, // Red triangle
{ vertices: [[200, 50], [300, 50], [250, 150]], color: [0, 255, 0, 255] }, // Green triangle
{ vertices: [[100, 200], [200, 200], [150, 300]], color: [0, 0, 255, 255] } // Blue triangle
];
function drawScene() {
ctx.fillStyle = "white";
ctx.fillRect(0,0,canvas.width,canvas.height);
for (const triangle of triangles) {
const path = new Path2D();
const [startX, startY] = triangle.vertices[0];
path.moveTo(startX, startY);
for (let i = 1; i < triangle.vertices.length; i++) {
const [x, y] = triangle.vertices[i];
path.lineTo(x, y);
}
path.closePath();
const [r, g, b, a] = triangle.color;
ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${a / 255})`;
ctx.fill(path);
}
}
const directionalLights = [
[Math.PI / 4, 100, 100, 1, 400, Math.PI / 3],
[Math.PI, 300, 300, 0.8, 500, Math.PI / 4]
];
var gpu = new GPU()
var diffuseKernel = gpu.createKernel(function(pix, width, height, dlights, numdlights, ambient){
var pixNum = ((width * height-this.thread.y) +this.thread.x) * 4;
var red = pix[pixNum];
var green = pix[pixNum+1];
var blue = pix[pixNum+2];
var brightness = ambient;
var dlight = dlights[0];
var lightDir = dlights[0][0];
var lightX = dlights[0][1];
var lightY = dlights[0][2];
var intensity = dlights[0][3];
var diffuse = dlights[0][4];
var spread = dlights[0][5];
const dirX = this.thread.x - lightX;
const dirY = this.thread.y - lightY;
const distance = Math.sqrt(dirX * dirX + dirY * dirY);
const angleToLight = Math.atan2(dirY, dirX);
const angleDiff = Math.abs(angleToLight - lightDir);
if (angleDiff <= spread / 2) {
// Calculate diffuse lighting
const diffuseFactor = Math.max(0, Math.cos(angleDiff) * (1 - (distance / diffuse)));
brightness += intensity * diffuseFactor;
}
this.color((red/255)*brightness, (green/255)*brightness, (blue/255)*brightness,pix[pixNum+2]/255)
},{
output: [canvas.width,canvas.height],
graphical: true
})
function applyDirectionalLights(x, y, currentColor) {
let ambient = 0.05;
let finalColor = [0,0,0,255]; // Initialize with ambient color
let pixelLit = false;
brightness = ambient;
for (const light of directionalLights) {
const [lightDir, lightX, lightY, intensity, diffuse, spread] = light;
// Calculate direction from light to pixel
const dirX = x - lightX;
const dirY = y - lightY;
const distance = Math.sqrt(dirX * dirX + dirY * dirY);
// Check if pixel is within the light spread angle
const angleToLight = Math.atan2(dirY, dirX);
const angleDiff = Math.abs(angleToLight - lightDir);
if (angleDiff <= spread / 2) {
// Calculate diffuse lighting
const diffuseFactor = Math.max(0, Math.cos(angleDiff) * (1 - (distance / diffuse)));
brightness += intensity * diffuseFactor;
}
}
finalColor = currentColor.map((channel, index) => Math.min(255, channel * brightness));
return finalColor
}
// Draw the initial scene
drawScene();
function diffuse(){
const width = canvas.width;
const height = canvas.height;
const pix = ctx.getImageData(0, 0, width, height).data;
diffuseKernel(pix, width, height, directionalLights, directionalLights.length, 0.05);
const pixels = this.diffuseKernel.getPixels();
ctx.putImageData(new ImageData(pixels, width, height), 0, 0);
}
var mouseX, mouseY = [-1,-1]
document.addEventListener("mousemove",(e)=>{
mouseX = event.clientX - canvas.getBoundingClientRect().left;
mouseY = event.clientY - canvas.getBoundingClientRect().top;
})
// Call the diffuse function to apply directional lighting
diffuse();
setInterval(()=>{
ctx.clearRect(0,0,canvas.width,canvas.height);
directionalLights[0][0] = Math.atan2(mouseY - directionalLights[0][1], mouseX - directionalLights[0][2]);
drawScene();
diffuse();
},1000/0.5);
</script>
</body>
</html>
Copied and pasted worky code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Directional Lighting Scene</title>
<style>
canvas { border: 1px solid #000; }
</style>
</head>
<body>
<script src = "matter.js"></script>
<script src = "gpu.js"></script>
<script src = "anvil.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Define colored triangles in the scene
const triangles = [
{ vertices: [[50, 50], [150, 50], [100, 150]], color: [255, 0, 0, 255] }, // Red triangle
{ vertices: [[200, 50], [300, 50], [250, 150]], color: [0, 255, 0, 255] }, // Green triangle
{ vertices: [[100, 200], [200, 200], [150, 300]], color: [0, 0, 255, 255] } // Blue triangle
];
function drawScene() {
ctx.fillStyle = "white";
ctx.fillRect(0,0,canvas.width,canvas.height);
for (const triangle of triangles) {
const path = new Path2D();
const [startX, startY] = triangle.vertices[0];
path.moveTo(startX, startY);
for (let i = 1; i < triangle.vertices.length; i++) {
const [x, y] = triangle.vertices[i];
path.lineTo(x, y);
}
path.closePath();
const [r, g, b, a] = triangle.color;
ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${a / 255})`;
ctx.fill(path);
}
}
const directionalLights = [
[Math.PI / 4, 100, 100, 1, 400, Math.PI / 3],
[Math.PI, 300, 300, 0.8, 500, Math.PI / 4]
];
function applyDirectionalLights(x, y, currentColor) {
let ambient = 0.05;
let finalColor = [0,0,0,255]; // Initialize with ambient color
let pixelLit = false;
brightness = ambient;
for (const light of directionalLights) {
const [lightDir, lightX, lightY, intensity, diffuse, spread] = light;
// Calculate direction from light to pixel
const dirX = x - lightX;
const dirY = y - lightY;
const distance = Math.sqrt(dirX * dirX + dirY * dirY);
// Check if pixel is within the light spread angle
const angleToLight = Math.atan2(dirY, dirX);
const angleDiff = Math.abs(angleToLight - lightDir);
if (angleDiff <= spread / 2) {
// Calculate diffuse lighting
const diffuseFactor = Math.max(0, Math.cos(angleDiff) * (1 - (distance / diffuse)));
brightness += intensity * diffuseFactor;
}
}
finalColor = currentColor.map((channel, index) => Math.min(255, channel * brightness));
return finalColor
}
// Draw the initial scene
drawScene();
function diffuse(){
const width = canvas.width;
const height = canvas.height;
const pix = ctx.getImageData(0, 0, width, height).data;
// Loop through each pixel
for(var x = 0; x < width; x++){
for(var y = 0; y < height; y++){
// Calculate the color of the pixel
const pixelColor = [pix[(x + y * width) * 4 + 0], pix[(x + y * width) * 4 + 1], pix[(x + y * width) * 4 + 2], pix[(x + y * width) * 4 + 3]];
var [r,g,b,a] = applyDirectionalLights(x,y,pixelColor);
ctx.fillStyle = `rgba(${r},${g},${b},${a})`
ctx.fillRect(x,y,1,1);
}
}
}
var mouseX, mouseY = [-1,-1]
document.addEventListener("mousemove",(e)=>{
mouseX = event.clientX - canvas.getBoundingClientRect().left;
mouseY = event.clientY - canvas.getBoundingClientRect().top;
})
// Call the diffuse function to apply directional lighting
diffuse();
setInterval(()=>{
ctx.clearRect(0,0,canvas.width,canvas.height);
directionalLights[0][0] = Math.atan2(mouseY - directionalLights[0][1], mouseX - directionalLights[0][2]);
drawScene();
diffuse();
},1000/10);
</script>
</body>
</html>
How important is this (1-5)?
I have to delay the directional lighting system in my game as long as this is not resolved
4 ( I can work on other things in the meantime, but still important)
Expected behavior (i.e. solution)
Provided image
Other Comments
If it is a bug in my own code.... I'm sorry but I can't find it, ChatGPT can't find it, Bard can't find it, and my math teacher can't find it.