PBR progress

This commit is contained in:
JannisX11 2024-10-03 17:09:22 +02:00
parent 25ae6a5046
commit a2b55e826b
7 changed files with 151 additions and 72 deletions

View File

@ -7,6 +7,13 @@ function setupDragHandlers() {
loadImages(files, event)
}
)
Blockbench.addDragHandler(
'texture_set',
{extensions: ['texture_set.json'], propagate: true, readtype: 'image', condition: () => !Dialog.open},
function(files, event) {
importTextureSet(files[0]);
}
)
Blockbench.addDragHandler(
'reference_image',
{extensions: ReferenceImage.supported_extensions, propagate: true, readtype: 'image', condition: () => Project && !Dialog.open},

View File

@ -854,6 +854,10 @@ const Canvas = {
}
Blockbench.dispatchEvent('update_view', options);
},
updateViewMode() {
this.updateAllFaces();
this.updateShading();
},
//Main updaters
clear() {
var objects = []

View File

@ -2068,28 +2068,51 @@ function animate() {
function updateShading() {
Canvas.updateLayeredTextures();
scene.remove(lights)
Sun.intensity = settings.brightness.value/50;
if (settings.shading.value === true) {
Sun.intensity *= 0.5;
let parent = scene;
parent.add(lights);
lights.position.copy(parent.position).multiplyScalar(-1);
scene.remove(lights);
let settings_brightness = settings.brightness.value/50;
Sun.intensity = settings_brightness;
let view_mode = window.BarItems ? BarItems.view_mode.value : 'textured';
if (view_mode == 'material') {
let light = Canvas.material_light ?? new THREE.DirectionalLight(0xffffca, 0.7 * settings_brightness);
Canvas.material_light = light;
scene.add(light);
light.position.y = 100
light.position.x = 60
light.position.z = 2
scene.add(Sun);
Sun.intensity *= 0.3;
TextureGroup.all.forEach(tg => {
if (tg.is_material) tg.updateMaterial();
})
} else {
if (settings.shading.value === true) {
Sun.intensity *= 0.5;
let parent = scene;
parent.add(lights);
lights.position.copy(parent.position).multiplyScalar(-1);
}
lights.add(Sun);
Texture.all.forEach(tex => {
let material = tex.getMaterial();
if (!material.uniforms) return;
material.uniforms.SHADE.value = settings.shading.value;
material.uniforms.LIGHTCOLOR.value.copy(Canvas.global_light_color).multiplyScalar(settings.brightness.value / 50);
material.uniforms.LIGHTSIDE.value = Canvas.global_light_side;
})
Canvas.emptyMaterials.forEach(material => {
material.uniforms.SHADE.value = settings.shading.value;
material.uniforms.BRIGHTNESS.value = settings.brightness.value / 50;
})
Canvas.coloredSolidMaterials.forEach(material => {
material.uniforms.SHADE.value = settings.shading.value;
material.uniforms.BRIGHTNESS.value = settings.brightness.value / 50;
})
}
Texture.all.forEach(tex => {
let material = tex.getMaterial();
material.uniforms.SHADE.value = settings.shading.value;
material.uniforms.LIGHTCOLOR.value.copy(Canvas.global_light_color).multiplyScalar(settings.brightness.value / 50);
material.uniforms.LIGHTSIDE.value = Canvas.global_light_side;
})
Canvas.emptyMaterials.forEach(material => {
material.uniforms.SHADE.value = settings.shading.value;
material.uniforms.BRIGHTNESS.value = settings.brightness.value / 50;
})
Canvas.coloredSolidMaterials.forEach(material => {
material.uniforms.SHADE.value = settings.shading.value;
material.uniforms.BRIGHTNESS.value = settings.brightness.value / 50;
})
Canvas.monochromaticSolidMaterial.uniforms.SHADE.value = settings.shading.value;
Canvas.monochromaticSolidMaterial.uniforms.BRIGHTNESS.value = settings.brightness.value / 50;
Canvas.uvHelperMaterial.uniforms.SHADE.value = settings.shading.value;
@ -2118,10 +2141,11 @@ BARS.defineActions(function() {
wireframe: {name: true, icon: 'far.fa-square', condition: () => (!Toolbox.selected.allowed_view_modes || Toolbox.selected.allowed_view_modes.includes('wireframe'))},
uv: {name: true, icon: 'grid_guides', condition: () => (!Toolbox.selected.allowed_view_modes || Toolbox.selected.allowed_view_modes.includes('uv'))},
normal: {name: true, icon: 'fa-square-caret-up', condition: () => ((!Toolbox.selected.allowed_view_modes || Toolbox.selected.allowed_view_modes.includes('normal')) && Mesh.all.length)},
material: {name: true, icon: 'pages', condition: () => ((!Toolbox.selected.allowed_view_modes || Toolbox.selected.allowed_view_modes.includes('normal')) && TextureGroup.all.find(tg => tg.is_material))},
},
onChange() {
Project.view_mode = this.value;
Canvas.updateAllFaces();
Canvas.updateViewMode();
if (Modes.id === 'animate') {
Animator.preview();
}

View File

@ -23,6 +23,8 @@ const Painter = {
callback(canvas, Painter.current);
Blockbench.dispatchEvent('edit_texture', {texture, options, canvas, ctx, offset});
if (options.use_cache && options.no_update === true) {
return;
}
@ -2217,7 +2219,7 @@ BARS.defineActions(function() {
cursor: 'grab',
selectFace: false,
transformerMode: 'hidden',
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
modes: ['paint'],
condition: Blockbench.isMobile && {modes: ['paint']}
})
@ -2293,7 +2295,7 @@ BARS.defineActions(function() {
}
}
},
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
keybind: new Keybind({key: 'b'}),
modes: ['paint'],
side_menu: new Menu('brush_tool', () => {
@ -2443,7 +2445,7 @@ BARS.defineActions(function() {
return result_color;
}
},
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
modes: ['paint'],
onCanvasClick(data) {
Painter.startPaintToolCanvas(data, data.event);
@ -2472,7 +2474,7 @@ BARS.defineActions(function() {
selectFace: true,
transformerMode: 'hidden',
paintTool: true,
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
modes: ['paint'],
onCanvasClick: function(data) {
Painter.startPaintToolCanvas(data, data.event)
@ -2522,7 +2524,7 @@ BARS.defineActions(function() {
return pxcolor;
}
},
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
modes: ['paint'],
keybind: new Keybind({key: 'e'}),
onCanvasClick: function(data) {
@ -2544,7 +2546,7 @@ BARS.defineActions(function() {
selectFace: true,
transformerMode: 'hidden',
paintTool: true,
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
modes: ['paint'],
onCanvasClick(data) {
Painter.startPaintToolCanvas(data, data.event)
@ -2572,7 +2574,7 @@ BARS.defineActions(function() {
selectFace: true,
transformerMode: 'hidden',
paintTool: true,
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
modes: ['paint'],
condition: {modes: ['paint']},
keybind: new Keybind({key: 'u'}),
@ -2596,7 +2598,7 @@ BARS.defineActions(function() {
selectFace: true,
transformerMode: 'hidden',
paintTool: true,
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
modes: ['paint'],
condition: {modes: ['paint']},
//keybind: new Keybind({key: 'u'}),
@ -2620,7 +2622,7 @@ BARS.defineActions(function() {
selectFace: true,
transformerMode: 'hidden',
paintTool: true,
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
modes: ['paint'],
condition: {modes: ['paint']},
keybind: new Keybind({key: 'm'}),
@ -2650,7 +2652,7 @@ BARS.defineActions(function() {
selectFace: true,
transformerMode: 'hidden',
paintTool: true,
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
modes: ['paint'],
keybind: new Keybind({key: 'm'}, {
create: '',
@ -2725,7 +2727,7 @@ BARS.defineActions(function() {
selectFace: true,
transformerMode: 'hidden',
paintTool: true,
allowed_view_modes: ['textured'],
allowed_view_modes: ['textured', 'material'],
modes: ['paint'],
keybind: new Keybind({shift: true, key: 'v'}),
onCanvasClick(data) {

View File

@ -100,22 +100,44 @@ class TextureGroup {
} else if (height_tex) {
material.bumpMap = height_tex.getOwnMaterial().map;
material.bumpScale = 0.4;
material.normalMap = null;
// Bump map scale
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
canvas.width = height_tex.width * 8;
canvas.height = height_tex.height * 8;
ctx.imageSmoothingEnabled = false;
ctx.drawImage(height_tex.canvas, 0, 0, canvas.width, canvas.height);
material.bumpMap.image = canvas;
material.bumpMap.magFilter = THREE.LinearFilter;
material.bumpMap.needsUpdate = true;
}
if (mer_tex && mer_tex.img?.naturalWidth) {
let image_data = mer_tex.canvas.getContext('2d').getImageData(0, 0, mer_tex.width, mer_tex.height);
let image_data_albedo = color_tex.canvas.getContext('2d').getImageData(0, 0, color_tex.width, color_tex.height);
function generateMap(source_channel, target_channel, key) {
let canvas = material[key]?.image ?? document.createElement('canvas');
let ctx = canvas.getContext('2d');
canvas.width = mer_tex.width;
canvas.height = mer_tex.height;
ctx.fillStyle = 'red';
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, mer_tex.width, mer_tex.height);
document.body.append(canvas)
let image_data_new = ctx.getImageData(0, 0, mer_tex.width, mer_tex.height);
for (let i = 0; i < image_data.data.length; i += 4) {
image_data_new.data[i + target_channel] = image_data.data[i + source_channel];
if (target_channel == 0) {
let value = image_data.data[i + source_channel] / 255;
image_data_new.data[i + 0] = image_data_albedo.data[i + 0] * value;
image_data_new.data[i + 1] = image_data_albedo.data[i + 1] * value;
image_data_new.data[i + 2] = image_data_albedo.data[i + 2] * value;
} else {
image_data_new.data[i + target_channel] = image_data.data[i + source_channel];
if (source_channel == 2 && image_data_new.data[i + target_channel] == 0) {
//image_data_new.data[i + target_channel] = 255;
}
}
}
ctx.putImageData(image_data_new, 0, 0);
@ -123,10 +145,14 @@ class TextureGroup {
material[key] = new THREE.Texture(canvas, THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping, THREE.NearestFilter, THREE.NearestFilter);
material[key].needsUpdate = true;
}
//material.map = material[key];
}
generateMap(0, 2, 'metalnessMap');
generateMap(1, 0, 'emissiveMap');
generateMap(2, 1, 'roughnessMap');
material.emissive.set(0xffffff);
material.emissiveIntensity = 30;
material.metalness = 1;
}
material.needsUpdate = true;
}
@ -178,6 +204,52 @@ ToDo:
- Search
*/
Blockbench.on('edit_texture', ({texture}) => {
if (texture.pbr_channel == 'mer' && texture.getGroup()?.is_material && BarItems.view_mode.value == 'material') {
texture.getGroup().updateMaterial();
}
})
function importTextureSet(file) {
let new_textures = [], new_texture_groups = [];
Undo.initEdit({textures: new_textures, texture_groups: new_texture_groups});
if (file.name.endsWith('texture_set.json')) {
let texture_group = new TextureGroup({is_material: true});
texture_group.name = file.name.replace('.texture_set.json', '');
let content = fs.readFileSync(file.path, {encoding: 'utf-8'});
let content_json = autoParseJSON(content);
if (content_json && content_json['minecraft:texture_set']) {
let channels = {
color: 'color',
normal: 'normal',
heightmap: 'height',
metalness_emissive_roughness: 'mer',
};
for (let key in channels) {
let source = content_json['minecraft:texture_set'][key];
if (typeof source == 'string') {
let path = PathModule.resolve(file.path, '../' + source + '.png');
Blockbench.read([path], {
readtype: 'image',
}, ([file2]) => {
let t = new Texture({
name: file2.name,
pbr_channel: channels[key]
}).fromFile(file2).add(false, true).fillParticle();
new_textures.push(t);
t.group = texture_group.uuid;
})
}
}
}
new_texture_groups.push(texture_group);
texture_group.add(false);
}
Undo.finishEdit('Import texture set');
}
SharedActions.add('rename', {
condition: () => Prop.active_panel == 'textures' && TextureGroup.active_menu_group,
run() {

View File

@ -882,7 +882,7 @@ class Texture {
}
getMaterial() {
let group = this.getGroup();
if (group?.is_material) {
if (group?.is_material && BarItems.view_mode.value == 'material') {
return group.getMaterial();
}
return Project.materials[this.uuid];
@ -2271,52 +2271,21 @@ BARS.defineActions(function() {
multiple: true,
startpath: start_path
}, function(files) {
if (files[0].name.endsWith('texture_set.json')) {
importTextureSet(files[0]);
return;
}
let new_textures = [], new_texture_groups = [];
let texture_group = context instanceof TextureGroup ? context : Texture.selected?.getGroup();
Undo.initEdit({textures: new_textures, texture_groups: new_texture_groups});
files.forEach((f) => {
if (f.name.endsWith('texture_set.json')) {
let texture_group = new TextureGroup({is_material: true});
texture_group.name = f.name.replace('.texture_set.json', '');
let content = fs.readFileSync(f.path, {encoding: 'utf-8'});
let content_json = autoParseJSON(content);
if (content_json && content_json['minecraft:texture_set']) {
let channels = {
color: 'color',
normal: 'normal',
heightmap: 'height',
metalness_emissive_roughness: 'mer',
};
for (let key in channels) {
let source = content_json['minecraft:texture_set'][key];
if (typeof source == 'string') {
let path = PathModule.resolve(f.path, '../' + source + '.png');
Blockbench.read([path], {
readtype: 'image',
}, ([file2]) => {
let t = new Texture({
name: file2.name,
pbr_channel: channels[key]
}).fromFile(file2).add(false, true).fillParticle();
new_textures.push(t);
t.group = texture_group.uuid;
})
}
}
}
new_texture_groups.push(texture_group);
texture_group.add(false);
return;
}
let t = new Texture({name: f.name}).fromFile(f).add(false, true).fillParticle();
new_textures.push(t);
if (texture_group) {
t.group = texture_group.uuid;
}
})
Undo.finishEdit('Add texture')
Undo.finishEdit('Add texture');
})
}
})

View File

@ -1673,6 +1673,7 @@
"action.view_mode.wireframe": "Wireframe",
"action.view_mode.uv": "UV Preview",
"action.view_mode.normal": "Face Orientation",
"action.view_mode.material": "Material Preview",
"action.preview_scene": "Preview Scene",
"action.preview_scene.desc": "Change the model preview scene",
"action.screenshot_model": "Screenshot Model",