mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-04-12 17:41:57 +08:00
PBR preview (wip)
bedrock texture set import
This commit is contained in:
parent
85577d38aa
commit
25ae6a5046
@ -214,7 +214,7 @@ function buildSkinnedMesh(root_group, scale) {
|
||||
if (face.texture === null) continue;
|
||||
let tex = face.getTexture();
|
||||
if (tex && tex.uuid) {
|
||||
materials.push(Project.materials[tex.uuid])
|
||||
materials.push(tex.getMaterial())
|
||||
} else {
|
||||
materials.push(Canvas.emptyMaterials[child.color])
|
||||
}
|
||||
|
@ -1172,7 +1172,7 @@ new NodePreviewController(Cube, {
|
||||
if (element.faces[face].texture !== null) {
|
||||
let tex = element.faces[face].getTexture();
|
||||
if (tex && tex.uuid) {
|
||||
materials.push(Project.materials[tex.uuid])
|
||||
materials.push(tex.getMaterial())
|
||||
} else {
|
||||
materials.push(Canvas.emptyMaterials[element.color % Canvas.emptyMaterials.length])
|
||||
}
|
||||
|
@ -1118,7 +1118,7 @@ new NodePreviewController(Mesh, {
|
||||
if (faces[key].vertices.length < 3) continue;
|
||||
var tex = faces[key].getTexture()
|
||||
if (tex && tex.uuid) {
|
||||
materials.push(Project.materials[tex.uuid])
|
||||
materials.push(tex.getMaterial())
|
||||
} else {
|
||||
materials.push(Canvas.emptyMaterials[element.color])
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ new NodePreviewController(TextureMesh, {
|
||||
} else {
|
||||
var tex = Texture.getDefault();
|
||||
if (tex && tex.uuid) {
|
||||
mesh.material = Project.materials[tex.uuid]
|
||||
mesh.material = tex.getMaterial()
|
||||
} else {
|
||||
mesh.material = Canvas.emptyMaterials[0]
|
||||
}
|
||||
|
@ -949,7 +949,7 @@ const Canvas = {
|
||||
let side = Canvas.getRenderSide();
|
||||
ModelProject.all.forEach(project => {
|
||||
project.textures.forEach((tex) => {
|
||||
var mat = project.materials[tex.uuid];
|
||||
var mat = tex.getMaterial();
|
||||
if (!mat) return;
|
||||
mat.side = Canvas.getRenderSide(tex);
|
||||
})
|
||||
@ -1216,7 +1216,7 @@ const Canvas = {
|
||||
if (layers instanceof Array == false) layers = Texture.all;
|
||||
layers.forEachReverse(texture => {
|
||||
if (texture.visible && i < 3) {
|
||||
uniforms[`t${i}`].value = texture.getMaterial().map;
|
||||
uniforms[`t${i}`].value = texture.getOwnMaterial().map;
|
||||
i++;
|
||||
}
|
||||
})
|
||||
@ -1269,7 +1269,7 @@ const Canvas = {
|
||||
} else {
|
||||
var tex = cube.faces[face].getTexture()
|
||||
if (tex && tex.uuid) {
|
||||
materials.push(Project.materials[tex.uuid])
|
||||
materials.push(tex.getMaterial())
|
||||
} else {
|
||||
materials.push(Canvas.emptyMaterials[cube.color])
|
||||
}
|
||||
|
@ -104,8 +104,13 @@ class PreviewScene {
|
||||
|
||||
Canvas.global_light_color.copy(this.light_color);
|
||||
Canvas.global_light_side = this.light_side;
|
||||
scene.background = this.cubemap;
|
||||
scene.fog = this.fog;
|
||||
Canvas.scene.background = this.cubemap;
|
||||
Canvas.scene.fog = this.fog;
|
||||
|
||||
|
||||
let pmremGenerator = new THREE.PMREMGenerator( Preview.selected.renderer );
|
||||
Canvas.scene.environment = pmremGenerator.fromCubemap(this.cubemap).texture;
|
||||
|
||||
if (this.fov) {
|
||||
Preview.selected.setFOV(this.fov);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ const Painter = {
|
||||
|
||||
if (options.no_undo && options.use_cache) {
|
||||
texture.updateLayerChanges();
|
||||
let map = texture.getMaterial().map;
|
||||
let map = texture.getOwnMaterial().map;
|
||||
map.needsUpdate = true;
|
||||
UVEditor.vue.updateTextureCanvas();
|
||||
} else {
|
||||
|
@ -7,6 +7,12 @@ class TextureGroup {
|
||||
TextureGroup.properties[key].reset(this);
|
||||
}
|
||||
if (data) this.extend(data);
|
||||
|
||||
this._static = Object.freeze({
|
||||
properties: {
|
||||
material: null
|
||||
}
|
||||
})
|
||||
}
|
||||
extend(data) {
|
||||
for (let key in TextureGroup.properties) {
|
||||
@ -16,6 +22,9 @@ class TextureGroup {
|
||||
}
|
||||
add() {
|
||||
TextureGroup.all.push(this);
|
||||
if (this.is_material) {
|
||||
this.updateMaterial();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
select() {
|
||||
@ -66,6 +75,67 @@ class TextureGroup {
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
updateMaterial() {
|
||||
let material = this._static.properties.material;
|
||||
if (!material) {
|
||||
//let g = new THREE.PMREMGenerator(Preview.selected.renderer);
|
||||
//let pmrem_render_target = g.fromScene(Canvas.scene);
|
||||
// https://threejs.org/docs/index.html#api/en/materials/MeshStandardMaterial
|
||||
material = this._static.properties.material = new THREE.MeshStandardMaterial({
|
||||
//envMap: pmrem_render_target
|
||||
});
|
||||
}
|
||||
let textures = this.getTextures();
|
||||
let color_tex = textures.find(t => t.pbr_channel == 'color');
|
||||
let normal_tex = textures.find(t => t.pbr_channel == 'normal');
|
||||
let height_tex = textures.find(t => t.pbr_channel == 'height');
|
||||
let mer_tex = textures.find(t => t.pbr_channel == 'mer');
|
||||
if (color_tex) {
|
||||
material.map = color_tex.getOwnMaterial().map;
|
||||
}
|
||||
if (normal_tex) {
|
||||
material.normalMap = normal_tex.getOwnMaterial().map;
|
||||
material.bumpMap = null;
|
||||
|
||||
} else if (height_tex) {
|
||||
material.bumpMap = height_tex.getOwnMaterial().map;
|
||||
material.normalMap = null;
|
||||
}
|
||||
if (mer_tex && mer_tex.img?.naturalWidth) {
|
||||
let image_data = mer_tex.canvas.getContext('2d').getImageData(0, 0, mer_tex.width, mer_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.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];
|
||||
}
|
||||
ctx.putImageData(image_data_new, 0, 0);
|
||||
|
||||
if (!material[key] || true) {
|
||||
material[key] = new THREE.Texture(canvas, THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping, THREE.NearestFilter, THREE.NearestFilter);
|
||||
material[key].needsUpdate = true;
|
||||
}
|
||||
}
|
||||
generateMap(0, 2, 'metalnessMap');
|
||||
generateMap(1, 0, 'emissiveMap');
|
||||
generateMap(2, 1, 'roughnessMap');
|
||||
}
|
||||
material.needsUpdate = true;
|
||||
}
|
||||
getMaterial() {
|
||||
if (!this._static.properties.material) {
|
||||
this.updateMaterial();
|
||||
}
|
||||
return this._static.properties.material;
|
||||
}
|
||||
}
|
||||
Object.defineProperty(TextureGroup, 'all', {
|
||||
get() {
|
||||
|
@ -725,7 +725,7 @@ class Texture {
|
||||
}
|
||||
updateMaterial() {
|
||||
if (Format.image_editor) return this;
|
||||
let mat = this.getMaterial();
|
||||
let mat = this.getOwnMaterial();
|
||||
|
||||
mat.name = this.name;
|
||||
mat.uniforms.EMISSIVE.value = this.render_mode == 'emissive';
|
||||
@ -881,7 +881,14 @@ class Texture {
|
||||
return this;
|
||||
}
|
||||
getMaterial() {
|
||||
return Project.materials[this.uuid]
|
||||
let group = this.getGroup();
|
||||
if (group?.is_material) {
|
||||
return group.getMaterial();
|
||||
}
|
||||
return Project.materials[this.uuid];
|
||||
}
|
||||
getOwnMaterial() {
|
||||
return Project.materials[this.uuid];
|
||||
}
|
||||
//Management
|
||||
select(event) {
|
||||
@ -1741,7 +1748,7 @@ class Texture {
|
||||
this.ctx.globalCompositeOperation = 'source-over';
|
||||
|
||||
if (!Format.image_editor && this.getMaterial()) {
|
||||
this.getMaterial().map.needsUpdate = true;
|
||||
this.getOwnMaterial().map.needsUpdate = true;
|
||||
}
|
||||
if (update_data_url) {
|
||||
this.internal = true;
|
||||
@ -1756,7 +1763,7 @@ class Texture {
|
||||
} else {
|
||||
if (!this.internal) this.convertToInternal();
|
||||
if (!Format.image_editor) {
|
||||
this.getMaterial().map.needsUpdate = true;
|
||||
this.getOwnMaterial().map.needsUpdate = true;
|
||||
}
|
||||
this.source = this.canvas.toDataURL('image/png', 1);
|
||||
this.updateImageFromCanvas();
|
||||
@ -1849,7 +1856,7 @@ class Texture {
|
||||
name: 'menu.texture.pbr_channel',
|
||||
condition: (texture) => texture.getGroup()?.is_material,
|
||||
children(texture) {
|
||||
function setViewMode(channel) {
|
||||
function applyChannel(channel) {
|
||||
let group = texture.getGroup();
|
||||
let changed_textures = group.getTextures();
|
||||
|
||||
@ -1858,13 +1865,14 @@ class Texture {
|
||||
changed_textures.forEach(t => {
|
||||
t.updateMaterial();
|
||||
});
|
||||
if (group) group.updateMaterial();
|
||||
Undo.finishEdit('Change texture PBR channel');
|
||||
}
|
||||
return [
|
||||
{name: 'menu.texture.pbr_channel.color', icon: texture.pbr_channel == 'color' ? 'far.fa-dot-circle' : 'far.fa-circle', click() {setViewMode('color')}},
|
||||
{name: 'menu.texture.pbr_channel.normal', icon: texture.pbr_channel == 'normal' ? 'far.fa-dot-circle' : 'far.fa-circle', click() {setViewMode('normal')}},
|
||||
{name: 'menu.texture.pbr_channel.height', icon: texture.pbr_channel == 'height' ? 'far.fa-dot-circle' : 'far.fa-circle', click() {setViewMode('height')}},
|
||||
{name: 'menu.texture.pbr_channel.mer', icon: texture.pbr_channel == 'mer' ? 'far.fa-dot-circle' : 'far.fa-circle', click() {setViewMode('mer')}},
|
||||
{name: 'menu.texture.pbr_channel.color', icon: texture.pbr_channel == 'color' ? 'far.fa-dot-circle' : 'far.fa-circle', click() {applyChannel('color')}},
|
||||
{name: 'menu.texture.pbr_channel.normal', icon: texture.pbr_channel == 'normal' ? 'far.fa-dot-circle' : 'far.fa-circle', click() {applyChannel('normal')}},
|
||||
{name: 'menu.texture.pbr_channel.height', icon: texture.pbr_channel == 'height' ? 'far.fa-dot-circle' : 'far.fa-circle', click() {applyChannel('height')}},
|
||||
{name: 'menu.texture.pbr_channel.mer', icon: texture.pbr_channel == 'mer' ? 'far.fa-dot-circle' : 'far.fa-circle', click() {applyChannel('mer')}},
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -2251,18 +2259,57 @@ BARS.defineActions(function() {
|
||||
arr.push('textures')
|
||||
start_path = arr.join(osfs)
|
||||
}
|
||||
let extensions = ['png', 'tga'];
|
||||
if (isApp) {
|
||||
extensions.push('texture_set.json');
|
||||
}
|
||||
Blockbench.import({
|
||||
resource_id: 'texture',
|
||||
readtype: 'image',
|
||||
type: 'PNG Texture',
|
||||
extensions: ['png', 'tga'],
|
||||
extensions,
|
||||
multiple: true,
|
||||
startpath: start_path
|
||||
}, function(results) {
|
||||
let new_textures = [];
|
||||
}, function(files) {
|
||||
let new_textures = [], new_texture_groups = [];
|
||||
let texture_group = context instanceof TextureGroup ? context : Texture.selected?.getGroup();
|
||||
Undo.initEdit({textures: new_textures});
|
||||
results.forEach(function(f) {
|
||||
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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user