Added texture-based coloured voxels, fixed UVs

This commit is contained in:
Lucas Dower 2021-07-27 16:29:41 +01:00
parent 9cd2c496c4
commit f7d1487838
7 changed files with 127 additions and 12 deletions

View File

@ -5,6 +5,7 @@ uniform sampler2D u_texture;
varying float v_lighting;
varying vec4 v_occlusion;
varying vec2 v_texcoord;
varying vec3 v_colour;
void main() {
@ -18,7 +19,8 @@ void main() {
float g = v*(u*b + (1.0-u)*d) + (1.0-v)*(u*a + (1.0-u)*c);
vec3 diffuse = texture2D(u_texture, v_texcoord).rgb;
//vec3 diffuse = texture2D(u_texture, v_texcoord).rgb;
vec3 diffuse = v_colour;
gl_FragColor = vec4(diffuse * (v_lighting * g), 1.0);
//gl_FragColor = vec4(vec3(v_lighting * g), 1.0);
//gl_FragColor = vec4(v_colour.xyz * g, 1.0);

View File

@ -6,10 +6,12 @@ attribute vec4 position;
attribute vec3 normal;
attribute vec4 occlusion;
attribute vec2 texcoord;
attribute vec3 colour;
varying float v_lighting;
varying vec4 v_occlusion;
varying vec2 v_texcoord;
varying vec3 v_colour;
vec3 light = vec3(0.78, 0.98, 0.59);
@ -17,6 +19,7 @@ vec3 light = vec3(0.78, 0.98, 0.59);
void main() {
v_texcoord = texcoord;
v_occlusion = occlusion;
v_colour = colour;
//float lighting = dot(light, abs(normal)) * (1.0 - occlusion * 0.2);
//float lighting = 0.2 * occlusion;
//v_colour = vec4(abs(normal), 1.0);

View File

@ -15,7 +15,9 @@ const canvas = document.querySelector("#c");
let loadedMesh = null;
const mesh = new Mesh(renderer._gl, "./resources/mix.obj");
renderer.registerMesh(mesh);
//renderer.registerMesh(mesh);
voxelManager.voxeliseMesh(mesh);
renderer.registerVoxelMesh(voxelManager);
//console.log(renderer._materialBuffers);
function showToastWithText(text, style) {

View File

@ -43,7 +43,7 @@ class Renderer {
this._registerData(data);
}
_registerVoxel(centre, voxelManager) {
_registerVoxel(centre, voxelManager, colour) {
let occlusions = new Array(6);
// For each face
for (let f = 0; f < 6; ++f) {
@ -67,11 +67,15 @@ class Renderer {
// Each vertex of a face needs the occlusion data for the other 3 vertices
// in it's face, not just itself. Also flatten occlusion data.
data.occlusion = new Array(96);
data.colour = [];
for (let j = 0; j < 6; ++j) {
for (let k = 0; k < 16; ++k) {
data.occlusion[j * 16 + k] = occlusions[j][k % 4];
}
}
}
const l = data.position.length / 3;
for (let i = 0; i < l; ++i)
data.colour.push(colour[0], colour[1], colour[2]);
this._registerVoxels.add(data);
}
@ -91,7 +95,7 @@ class Renderer {
mesh.materialTriangles[material].forEach((triangle) => {
const data = GeometryTemplates.getTriangleBufferData(triangle, false);
console.log(data);
//console.log(data);
materialBuffer.add(data);
});
this._materialBuffers.push({
@ -114,9 +118,16 @@ class Renderer {
} else {
this._setupOcclusions(voxelSize); // Setup arrays for calculating voxel ambient occlusion
for (let i = 0; i < voxelManager.voxels.length; ++i) {
const voxel = voxelManager.voxels[i];
const colour = voxelManager.voxelColours[i];
this._registerVoxel(voxel, voxelManager, colour);
}
/*
voxelManager.voxels.forEach((voxel) => {
this._registerVoxel(voxel, voxelManager);
});
*/
}
/*
@ -297,7 +308,8 @@ class Renderer {
{name: 'position', numComponents: 3},
{name: 'normal', numComponents: 3},
{name: 'occlusion', numComponents: 4},
{name: 'texcoord', numComponents: 2}
{name: 'texcoord', numComponents: 2},
{name: 'colour', numComponents: 3},
]);
this._registerDefault = new SegmentedBuffer(bufferSize, [
{name: 'position', numComponents: 3},

27
src/texture.js Normal file
View File

@ -0,0 +1,27 @@
const fs = require("fs");
const png = require("pngjs").PNG;
class Texture {
constructor(filename) {
const file = fs.readFileSync(filename);
this._image = png.sync.read(file);
}
getRGBA(u, v) {
//u = 1 - u;
v = 1 - v;
let x = Math.floor(this._image.width * u);
let y = Math.floor(this._image.height * v);
x = Math.max(0, Math.min(x, this._image.width - 1));
y = Math.max(0, Math.min(y, this._image.height - 1));
const index = this._image.bpp * (this._image.width * y + x);
return this._image.data.slice(index, index + this._image.bpp);
}
}
module.exports.Texture = Texture;

View File

@ -109,12 +109,12 @@ class Vector3 {
return this.x == vec.x && this.y == vec.y && this.z == vec.z;
}
_magnitude() {
magnitude() {
return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2) + Math.pow(this.z, 2));
}
normalise() {
const mag = this._magnitude();
const mag = this.magnitude();
this.x /= mag;
this.y /= mag;
this.z /= mag;

View File

@ -1,12 +1,14 @@
const { AABB, CubeAABB } = require("./aabb.js");
const { Vector3 } = require("./vector.js");
const { HashSet, HashMap } = require('./hash_map.js');
const { Texture } = require("./texture.js");
class VoxelManager {
constructor(voxelSize) {
this._voxelSize = voxelSize;
this.voxels = [];
this.voxelColours = [];
this.triangleAABBs = [];
this.failedAABBs = [];
@ -25,6 +27,7 @@ class VoxelManager {
_clearVoxels() {
this.voxels = [];
this.voxelColours = [];
this.failedAABBs = [];
this.minX = Infinity; // JavaScript crack
@ -81,7 +84,7 @@ class VoxelManager {
return this.voxelsHash.contains(pos);
}
addVoxel(vec) {
addVoxel(vec, colour) {
// (0.5, 0.5, 0.5) -> (0, 0, 0);
vec = Vector3.subScalar(vec, this._voxelSize / 2);
@ -100,6 +103,7 @@ class VoxelManager {
return;
}
this.voxels.push(pos);
this.voxelColours.push(colour);
this.voxelsHash.add(pos);
this.minX = Math.min(this.minX, vec.x);
@ -243,6 +247,67 @@ class VoxelManager {
this.triangleAABBs = newTriangleAABBs;
}
_getVoxelColour(triangle, centre) {
const a = triangle.v0;
const b = triangle.v1;
const c = triangle.v2;
const p = centre;
const uv0 = triangle.uv0;
const uv1 = triangle.uv1;
const uv2 = triangle.uv2;
const delta = 0.5 * Vector3.sub(a, b).magnitude() * Vector3.sub(a, c).magnitude();
const da = 0.5 * Vector3.sub(p, b).magnitude() * Vector3.sub(p, c).magnitude();
const db = 0.5 * Vector3.sub(p, a).magnitude() * Vector3.sub(p, c).magnitude();
const dc = 0.5 * Vector3.sub(p, a).magnitude() * Vector3.sub(p, b).magnitude();
const ka = da / delta;
const kb = db / delta;
const kc = dc / delta;
const u = uv0[0] * ka + uv1[0] * kb + uv2[0] * kc;
const v = uv0[1] * ka + uv1[1] * kb + uv2[1] * kc;
//const rgba = triangle.material.texture.getRGBA(u, v);
const rgba = this._currentTexture.getRGBA(u, v);
if (rgba.length == 0) {
return [1.0, 0.0, 0.0];
}
//return [0.0, 0.0, 0.0];
return [rgba[0]/255, rgba[1]/255, rgba[2]/255];
}
_getVoxelColour2(triangle, centre) {
const p1 = triangle.v0;
const p2 = triangle.v1;
const p3 = triangle.v2;
const uv1 = triangle.uv0;
const uv2 = triangle.uv1;
const uv3 = triangle.uv2;
const f1 = Vector3.sub(p1, centre);
const f2 = Vector3.sub(p2, centre);
const f3 = Vector3.sub(p3, centre);
const a = Vector3.cross(Vector3.sub(p1, p2), Vector3.sub(p1, p3)).magnitude();
const a1 = Vector3.cross(f2, f3).magnitude() / a;
const a2 = Vector3.cross(f3, f1).magnitude() / a;
const a3 = Vector3.cross(f1, f2).magnitude() / a;
const u = uv1[0] * a1 + uv2[0] * a2 + uv3[0] * a3;
const v = uv1[1] * a1 + uv2[1] * a2 + uv3[1] * a3;
//const rgba = triangle.material.texture.getRGBA(u, v);
const rgba = this._currentTexture.getRGBA(u, v);
if (rgba.length == 0) {
return [1.0, 0.0, 0.0];
}
//return [0.0, 0.0, 0.0];
return [rgba[0]/255, rgba[1]/255, rgba[2]/255];
}
voxeliseTriangle(triangle) {
const cubeAABB = this._getTriangleCubeAABB(triangle);
@ -257,7 +322,7 @@ class VoxelManager {
queue.push(...aabb.subdivide());
} else {
// We've reached the voxel level, stop
this.addVoxel(aabb.centre);
this.addVoxel(aabb.centre, this._getVoxelColour2(triangle, aabb.centre));
triangleAABBs.push(aabb);
}
} else {
@ -269,8 +334,12 @@ class VoxelManager {
}
voxeliseMesh(mesh) {
for (const triangle of mesh.triangles) {
this.voxeliseTriangle(triangle);
for (const material in mesh.materialTriangles) {
this._currentTexture = new Texture(mesh._materials[material].diffuseTexturePath);
console.log(this._currentTexture);
for (const triangle of mesh.materialTriangles[material]) {
this.voxeliseTriangle(triangle);
}
}
}