mirror of
https://github.com/overte-org/community-apps.git
synced 2025-06-24 07:38:48 +02:00
659 lines
No EOL
36 KiB
HTML
659 lines
No EOL
36 KiB
HTML
<!doctype html>
|
|
<!--
|
|
// materialDataCreator.html
|
|
//
|
|
// Created by Alezia Kurdis, April 12th, 2020.
|
|
// Copyright 2020 Vircadia and contributors.
|
|
// Copyright 2022 Overte e.V.
|
|
//
|
|
// A tool to generate materialData.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
-->
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Material Data Creator</title>
|
|
<link href="color-picker.min.css" rel="stylesheet">
|
|
<style>
|
|
.color-picker.no-alpha .color-picker\:a {
|
|
display: none;
|
|
}
|
|
textarea.output {
|
|
width: 98%;
|
|
max-height: 100%;
|
|
}
|
|
div.info{
|
|
background-color: #AAAAAA;
|
|
padding: 5px;
|
|
margin: 0px 0px 6px 0px;
|
|
font-family: arial,sans-serif, helvetica;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
font-size: 13px;
|
|
color:#000000;
|
|
}
|
|
div.group{
|
|
background-color: #2e3745;
|
|
border: 2px solid #aaaaaa;
|
|
padding: 5px;
|
|
margin: 0px 0px 6px 0px;
|
|
font-family: arial,sans-serif, helvetica;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
font-size: 13px;
|
|
color:#ffffff;
|
|
}
|
|
font.Explain{
|
|
font-family: arial,sans-serif, helvetica;
|
|
font-weight: 500;
|
|
text-decoration: Italic;
|
|
font-size: 10px;
|
|
color:#8ad5ff;
|
|
}
|
|
font.label{
|
|
font-family: arial,sans-serif, helvetica;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
font-size: 12px;
|
|
color:#fff2d0;
|
|
}
|
|
body{
|
|
background-color: #4c4d5c;
|
|
font-family: arial,sans-serif, helvetica;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
font-size: 12px;
|
|
color:#000000;
|
|
margin: 0px;
|
|
border-collapse: collapse;
|
|
}
|
|
img.demo{
|
|
background-color: #AAAAAA;
|
|
}
|
|
img.save{
|
|
background-color: #dfd093;
|
|
}
|
|
img.reset{
|
|
background-color: #d16c64;
|
|
}
|
|
img.studio{
|
|
background-color: #c6dcb6;
|
|
}
|
|
td.title {
|
|
text-align: center;
|
|
font-family: arial,sans-serif, helvetica;
|
|
font-weight: 700;
|
|
text-decoration: none;
|
|
font-size: 20px;
|
|
color:#ffffff;
|
|
}
|
|
input.copybtn {
|
|
font-family: arial,sans-serif, helvetica;
|
|
font-weight: 800;
|
|
text-decoration: none;
|
|
font-size: 11px;
|
|
padding: 2px;
|
|
}
|
|
#helpOverlay {
|
|
position: fixed;
|
|
display: none;
|
|
width: 100%;
|
|
height: 100%;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: #4c4d5c;
|
|
color: #ffffff;
|
|
padding: 10px;
|
|
z-index: 2;
|
|
cursor: pointer;
|
|
}
|
|
</style>
|
|
<script src='jquery.min.js'></script>
|
|
<script src="color-picker.min.js"></script>
|
|
<script>
|
|
var material = {
|
|
"name": "untitled",
|
|
"albedo": "#ffffff",
|
|
"metallic": 0.001,
|
|
"roughness": 1.0,
|
|
"opacity": 1,
|
|
"emissive": "#000000",
|
|
"bloom": 1,
|
|
"scattering": 0,
|
|
"unlit": false,
|
|
"albedoMap": "",
|
|
"metallicMap": "",
|
|
"roughnessMap": "",
|
|
"normalMap": "",
|
|
"opacityMap": "DO NOT USE",
|
|
"opacityCutoff": 0.5,
|
|
"emissiveMap": "",
|
|
"scatteringMap": "",
|
|
"occlusionMap": "",
|
|
"cullFaceMode": "CULL_BACK",
|
|
"defaultFallthrough": false
|
|
};
|
|
|
|
|
|
function resetMaterial() {
|
|
material = {
|
|
"name": "untitled",
|
|
"albedo": "#ffffff",
|
|
"metallic": 0.001,
|
|
"roughness": 1.0,
|
|
"opacity": 1,
|
|
"emissive": "#000000",
|
|
"bloom": 1,
|
|
"scattering": 0,
|
|
"unlit": false,
|
|
"albedoMap": "",
|
|
"metallicMap": "",
|
|
"roughnessMap": "",
|
|
"normalMap": "",
|
|
"opacityMap": "DO NOT USE",
|
|
"opacityCutoff": 0.5,
|
|
"emissiveMap": "",
|
|
"scatteringMap": "",
|
|
"occlusionMap": "",
|
|
"cullFaceMode": "CULL_BACK",
|
|
"defaultFallthrough": false
|
|
};
|
|
|
|
document.materialEditor.reset();
|
|
document.materialEditor.name.value = "untitled";
|
|
document.materialEditor.albedo.value = "#ffffff";
|
|
document.materialEditor.metallic.value = 1;
|
|
document.materialEditor.metallic_value.value = 0.001;
|
|
document.materialEditor.roughness.value = 500;
|
|
document.materialEditor.roughness_value.value = 1.0;
|
|
document.materialEditor.opacity.value = 1000;
|
|
document.materialEditor.opacity_value.value = 1;
|
|
document.materialEditor.emissive.value = "#000000";
|
|
document.materialEditor.bloom.value = 100;
|
|
document.materialEditor.bloom_value.value = 1;
|
|
document.materialEditor.scattering.value = 0;
|
|
document.materialEditor.scattering_value.value = 0;
|
|
document.materialEditor.unlit.checked = false;
|
|
document.materialEditor.albedoMap.value = "";
|
|
document.materialEditor.metallicMap.value = "";
|
|
document.materialEditor.roughnessMap.value = "";
|
|
document.materialEditor.normalMap.value = "";
|
|
document.materialEditor.opacityMap.value = "DO NOT USE";
|
|
document.materialEditor.opacityCutoff.value = 0.5;
|
|
document.materialEditor.emissiveMap.value = "";
|
|
document.materialEditor.scatteringMap.value = "";
|
|
document.materialEditor.occlusionMap.value = "";
|
|
document.materialEditor.cullFaceMode.value = "CULL_BACK";
|
|
document.materialEditor.defaultFallthrough.checked = false;
|
|
generateMaterialJSON();
|
|
}
|
|
|
|
|
|
function loadMaterial() {
|
|
document.materialEditor.name.value = material.name;
|
|
document.materialEditor.albedo.value = material.albedo;
|
|
document.materialEditor.albedo.style.backgroundColor = material.albedo;
|
|
document.materialEditor.albedo.style.color = material.albedo;
|
|
document.materialEditor.metallic.value = material.metallic * 1000;
|
|
document.materialEditor.metallic_value.value = material.metallic;
|
|
document.materialEditor.roughness.value = material.roughness * 1000;
|
|
document.materialEditor.roughness_value.value = material.roughness;
|
|
document.materialEditor.opacity.value = material.opacity * 1000;
|
|
document.materialEditor.opacity_value.value = material.opacity;
|
|
document.materialEditor.emissive.value = material.emissive;
|
|
document.materialEditor.emissive.style.backgroundColor = material.emissive;
|
|
document.materialEditor.emissive.style.color = material.emissive;
|
|
document.materialEditor.bloom.value = material.bloom * 100;
|
|
document.materialEditor.bloom_value.value = material.bloom;
|
|
document.materialEditor.scattering.value = material.scattering * 1000;
|
|
document.materialEditor.scattering_value.value = material.scattering;
|
|
document.materialEditor.unlit.checked = material.unlit;
|
|
document.materialEditor.albedoMap.value = material.albedoMap;
|
|
document.materialEditor.metallicMap.value = material.metallicMap;
|
|
document.materialEditor.roughnessMap.value = material.roughnessMap;
|
|
document.materialEditor.normalMap.value = material.normalMap;
|
|
document.materialEditor.opacityMap.value = material.opacityMap;
|
|
document.materialEditor.opacityCutoff.value = material.opacityCutoff * 1000;
|
|
document.materialEditor.opacityCutoff_value.value = material.opacityCutoff;
|
|
document.materialEditor.emissiveMap.value = material.emissiveMap;
|
|
document.materialEditor.scatteringMap.value = material.scatteringMap;
|
|
document.materialEditor.occlusionMap.value = material.occlusionMap;
|
|
document.materialEditor.cullFaceMode.value = material.cullFaceMode;
|
|
document.materialEditor.defaultFallthrough.value = material.defaultFallthrough;
|
|
|
|
}
|
|
|
|
function save( attribute, valueContainer) {
|
|
if (attribute === "metallic" || attribute === "roughness" || attribute === "opacity" || attribute === "opacityCutoff" || attribute === "scattering" ) {
|
|
material[attribute] = valueContainer.value/1000;
|
|
} else {
|
|
if (attribute === "bloom") {
|
|
material[attribute] = valueContainer.value/100;
|
|
} else {
|
|
if (attribute === "unlit") {
|
|
material[attribute] = valueContainer.checked;
|
|
} else {
|
|
if (attribute === "defaultFallthrough") {
|
|
material[attribute] = valueContainer.checked;
|
|
} else {
|
|
material[attribute] = valueContainer.value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
document.materialEditor.metallic_value.value = (document.materialEditor.metallic.value/1000);
|
|
document.materialEditor.roughness_value.value = (document.materialEditor.roughness.value/1000);
|
|
document.materialEditor.opacity_value.value = (document.materialEditor.opacity.value/1000);
|
|
document.materialEditor.opacityCutoff_value.value = (document.materialEditor.opacityCutoff.value/1000);
|
|
document.materialEditor.bloom_value.value = (document.materialEditor.bloom.value/100);
|
|
document.materialEditor.scattering_value.value = (document.materialEditor.scattering.value/1000);
|
|
|
|
generateMaterialJSON();
|
|
|
|
}
|
|
|
|
function hexToRgb(str, factor) {
|
|
// Note to user, for normal color, used a factor of 1.
|
|
|
|
if ( /^#([0-9a-f]{3}|[0-9a-f]{6})$/ig.test(str) ) {
|
|
var hex = str.substr(1);
|
|
hex = hex.length == 3 ? hex.replace(/(.)/g, '$1$1') : hex;
|
|
var rgb = parseInt(hex, 16);
|
|
var r = (rgb >> 16) & 255;
|
|
var g = (rgb >> 8) & 255;
|
|
var b = rgb & 255;
|
|
|
|
return "[" + (r/255*factor) + ", " + (g/255*factor) +", " + (b/255*factor) + "]";
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function generateMaterialJSON() {
|
|
|
|
var materialData = "";
|
|
var fstMaterialData = "";
|
|
|
|
|
|
materialData += '{' + "\n";
|
|
materialData += ' "materialVersion": 1,' + "\n";
|
|
materialData += ' "materials": [' + "\n";
|
|
materialData += ' {' + "\n";
|
|
|
|
fstMaterialData += '{"mat::' + material.name.escapeJSON() + '": {"materials":[{ "name": "' + material.name.escapeJSON() + '"';
|
|
|
|
if (material.name !== "") {
|
|
materialData += ' "name": "' + material.name.escapeJSON() + '",' + "\n";
|
|
}
|
|
|
|
|
|
materialData += ' "albedo": ' + hexToRgb(material.albedo, 1) + ',' + "\n";
|
|
fstMaterialData += ', "albedo": ' + hexToRgb(material.albedo, 1);
|
|
|
|
if (material.metallicMap === "") {
|
|
materialData += ' "metallic": ' + material.metallic + ',' + "\n";
|
|
fstMaterialData += ', "metallic": ' + material.metallic;
|
|
}
|
|
if (material.roughnessMap === "" && material.roughness !== 1.0) {
|
|
materialData += ' "roughness": ' + material.roughness + ',' + "\n";
|
|
fstMaterialData += ', "roughness": ' + material.roughness;
|
|
}
|
|
if (material.opacityMap === "DO NOT USE" && material.opacity !== 1.0) {
|
|
materialData += ' "opacity": ' + material.opacity + ',' + "\n";
|
|
fstMaterialData += ', "opacity": ' + material.opacity;
|
|
}
|
|
if (material.emissive !== "#000000") {
|
|
materialData += ' "emissive": ' + hexToRgb(material.emissive, material.bloom) + ',' + "\n";
|
|
fstMaterialData += ', "emissive": ' + hexToRgb(material.emissive, material.bloom);
|
|
}
|
|
if (material.scatteringMap === "" && material.scattering !== 0) {
|
|
materialData += ' "scattering": ' + material.scattering + ',' + "\n";
|
|
fstMaterialData += ', "scattering": ' + material.scattering;
|
|
}
|
|
if (material.unlit === true) {
|
|
materialData += ' "unlit": ' + material.unlit + ',' + "\n";
|
|
fstMaterialData += ', "unlit": ' + material.unlit;
|
|
}
|
|
if (material.normalMap !== "") {
|
|
materialData += ' "normalMap": "' + material.normalMap.escapeJSON() + '",' + "\n";
|
|
fstMaterialData += ', "normalMap": "' + material.normalMap.escapeJSON() + '"';
|
|
}
|
|
if (material.albedoMap !== "") {
|
|
materialData += ' "albedoMap": "' + material.albedoMap.escapeJSON() + '",' + "\n";
|
|
fstMaterialData += ', "albedoMap": "' + material.albedoMap.escapeJSON() + '"';
|
|
}
|
|
if (material.metallicMap !== "") {
|
|
materialData += ' "metallicMap": "' + material.metallicMap.escapeJSON() + '",' + "\n";
|
|
fstMaterialData += ', "metallicMap": "' + material.metallicMap.escapeJSON() + '"';
|
|
}
|
|
if (material.roughnessMap !== "") {
|
|
materialData += ' "roughnessMap": "' + material.roughnessMap.escapeJSON() + '",' + "\n";
|
|
fstMaterialData += ', "roughnessMap": "' + material.roughnessMap.escapeJSON() + '"';
|
|
}
|
|
if (material.opacityMap === "OPACITY_MAP_MASK" || material.opacityMap === "OPACITY_MAP_BLEND") {
|
|
materialData += ' "opacityMap": "' + material.albedoMap.escapeJSON() + '",' + "\n";
|
|
fstMaterialData += ', "opacityMap": "' + material.albedoMap.escapeJSON() + '"';
|
|
materialData += ' "opacityMapMode": "' + material.opacityMap + '",' + "\n";
|
|
fstMaterialData += ', "opacityMapMode": "' + material.opacityMap + '"';
|
|
if (material.opacityMap === "OPACITY_MAP_MASK") {
|
|
materialData += ' "opacityCutoff": ' + material.opacityCutoff + ',' + "\n";
|
|
fstMaterialData += ', "opacityCutoff": ' + material.opacityCutoff;
|
|
}
|
|
}
|
|
if (material.emissiveMap !== "") {
|
|
materialData += ' "emissiveMap": "' + material.emissiveMap.escapeJSON() + '",' + "\n";
|
|
fstMaterialData += ', "emissiveMap": "' + material.emissiveMap.escapeJSON() + '"';
|
|
}
|
|
if (material.scatteringMap !== "") {
|
|
materialData += ' "scatteringMap": "' + material.scatteringMap.escapeJSON() + '",' + "\n";
|
|
fstMaterialData += ', "scatteringMap": "' + material.scatteringMap.escapeJSON() + '"';
|
|
}
|
|
if (material.occlusionMap !== "") {
|
|
materialData += ' "occlusionMap": "' + material.occlusionMap.escapeJSON() + '",' + "\n";
|
|
fstMaterialData += ', "occlusionMap": "' + material.occlusionMap.escapeJSON() + '"';
|
|
}
|
|
materialData += ' "cullFaceMode": "' + material.cullFaceMode + '",' + "\n";
|
|
fstMaterialData += ', "cullFaceMode": "' + material.cullFaceMode + '"';
|
|
if (material.defaultFallthrough === true) {
|
|
materialData += ' "defaultFallthrough": ' + material.defaultFallthrough + ',' + "\n";
|
|
fstMaterialData += ', "defaultFallthrough": ' + material.defaultFallthrough;
|
|
}
|
|
materialData += ' "model": "hifi_pbr"' + "\n";
|
|
fstMaterialData += ', "model": "hifi_pbr"';
|
|
materialData += ' }' + "\n";
|
|
materialData += ' ]' + "\n";
|
|
materialData += '}';
|
|
|
|
|
|
fstMaterialData += '}]}}';
|
|
|
|
document.materialEditor.output.value = materialData;
|
|
document.materialEditor.fstoutput.value = fstMaterialData;
|
|
|
|
var message = {
|
|
"channel": channel,
|
|
"action": "updateMaterialData",
|
|
"materialData": materialData,
|
|
"materialRecord": material
|
|
};
|
|
|
|
EventBridge.emitWebEvent(JSON.stringify(message));
|
|
|
|
}
|
|
|
|
String.prototype.escapeJSON = function() {
|
|
var result = "";
|
|
for (var i = 0; i < this.length; i++) {
|
|
var ch = this[i];
|
|
switch (ch)
|
|
{
|
|
case "\\": ch = "\\\\"; break;
|
|
//case "\'": ch = "\\'"; break;
|
|
case "\"": ch = '\\"'; break;
|
|
//case "\&": ch = "\\&"; break;
|
|
case "\t": ch = "\\t"; break;
|
|
case "\n": ch = "\\n"; break;
|
|
case "\r": ch = "\\r"; break;
|
|
case "\b": ch = "\\b"; break;
|
|
case "\f": ch = "\\f"; break;
|
|
case "\v": ch = "\\v"; break;
|
|
default: break;
|
|
}
|
|
|
|
result += ch;
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
var channel = "materialDataCreator.ak.overte";
|
|
|
|
|
|
function copyToClipboard(data) {
|
|
var $temp = $("<input>");
|
|
$("body").append($temp);
|
|
$temp.val(data).select();
|
|
document.execCommand("copy");
|
|
$temp.remove();
|
|
}
|
|
|
|
function demo(shape) {
|
|
var message = {
|
|
"channel": channel,
|
|
"action": "changeDemoShape",
|
|
"shape": shape
|
|
};
|
|
|
|
EventBridge.emitWebEvent(JSON.stringify(message));
|
|
|
|
}
|
|
|
|
function exportAsJson() {
|
|
var message = {
|
|
"channel": channel,
|
|
"action": "exportMaterialAsJson"
|
|
};
|
|
|
|
EventBridge.emitWebEvent(JSON.stringify(message));
|
|
|
|
}
|
|
|
|
function createMaterialEntity() {
|
|
var message = {
|
|
"channel": channel,
|
|
"action": "createMaterialEntity"
|
|
};
|
|
|
|
EventBridge.emitWebEvent(JSON.stringify(message));
|
|
|
|
}
|
|
|
|
function teleportToServerless() {
|
|
var message = {
|
|
"channel": channel,
|
|
"action": "teleportToServerless"
|
|
};
|
|
|
|
EventBridge.emitWebEvent(JSON.stringify(message));
|
|
}
|
|
|
|
function toggleDayNight() {
|
|
var message = {
|
|
"channel": channel,
|
|
"action": "toggleDayNight"
|
|
};
|
|
|
|
EventBridge.emitWebEvent(JSON.stringify(message));
|
|
}
|
|
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<form name='materialEditor' id='materialEditor'>
|
|
|
|
<table style= 'width: 100%;'><tr><td style= 'width: 90%;'>
|
|
|
|
<div class='header'>
|
|
<table style= 'width: 100%;'><tr>
|
|
<td class='title' colspan='10'>MATERIAL DATA CREATOR<br> </td>
|
|
<td style= 'width: 10%; vertical-align: top;'><a href='#' onclick='helpOn();'><img src="images/help.png"></a></td>
|
|
</tr><tr>
|
|
<td style= 'width: 10%;'><a href='#' onclick='demo("cube");'><img class='demo' src="images/demo_cube.png"></a></td>
|
|
<td style= 'width: 10%;'><a href='#' onclick='demo("sphere");'><img class='demo' src="images/demo_sphere.png"></a></td>
|
|
<td style= 'width: 10%;'><a href='#' onclick='demo("teapot");'><img class='demo' src="images/demo_teapot.png"></a></td>
|
|
<td style= 'width: 10%;'><a href='#' onclick='demo("brand");'><img class='demo' src="images/demo_brand.png"></a></td>
|
|
<td style= 'width: 5%;'> </td>
|
|
<td style= 'width: 10%;'><a href='#' onclick='teleportToServerless();'><img class='studio' src="images/studio.png"></a></td>
|
|
<td style= 'width: 10%;'><a href='#' onclick='toggleDayNight();'><img class='studio' src="images/toggle_day_night.png"></a></td>
|
|
<td style= 'width: 5%;'> </td>
|
|
<td style= 'width: 10%;'><a href='#' onclick='resetMaterial();'><img class='reset' src="images/reset.png"></a></td>
|
|
<td style= 'width: 10%;'><a href='#' onclick='exportAsJson();'><img class='save' src="images/save_as_json.png"></a></td>
|
|
<td style= 'width: 10%;'><a href='#' onclick='createMaterialEntity();'><img class='save' src="images/create_material_entity.png"></a></td>
|
|
</tr></table>
|
|
|
|
</div>
|
|
|
|
<div class='info'>
|
|
<table style= 'width: 100%;'><tr><td>Name:</td><td style= 'width: 100%;'><input name = 'name' type = 'text' style= 'width: 100%;' oninput="save('name', this);"></td></tr></table>
|
|
</div>
|
|
|
|
<div class='group'>
|
|
<font class='label'>Albedo (Color):</font> <input name = 'albedo' type = 'text' value="#ffffff"><br>
|
|
<font class='label'>Albedo Map (RGB) URL:</font> <input name = 'albedoMap' type = 'text' style= 'width:100%;' oninput="save('albedoMap', this);"><br>
|
|
<font class = 'Explain'>The Albedo (Color) can be used to tint the texture of the Albedo Map.</font>
|
|
</div>
|
|
|
|
<div class='group'>
|
|
<font class='label'>Metallic:</font> <input name = 'metallic_value' readonly type = 'text' size = '5'><br>
|
|
<input type="range" style="width:100%;" min="1" max="1000" value="1" class="slider" name = 'metallic' id = 'metallic' oninput="save('metallic', this); document.materialEditor.metallic_value.value = (this.value/1000);"><br>
|
|
<table style='width:100%'><tr><td style='width: 15%; text-align: left;'><font class = 'Explain'>|< Nonmetal</font></td><td style='width: 15%; text-align: left;'><font class = 'Explain'>| Hair</font></td><td style='width: 60%; text-align: left;'><font class = 'Explain'>| Chitin</font></td><td style='width: 10%; text-align: right;'><font class = 'Explain'>Metal >|</font></td></tr></table>
|
|
<font class='label'>Metallic Map (Grayscale) URL:</font> <input name = 'metallicMap' type = 'text' style= 'width:100%;' oninput="save('metallicMap', this);">
|
|
</div>
|
|
|
|
<div class='group'>
|
|
<font class='label'>Roughness:</font> <input name = 'roughness_value' readonly type = 'text' size = '5'><br>
|
|
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="slider" name = 'roughness' id = 'roughness' oninput="save('roughness', this); document.materialEditor.roughness_value.value = (this.value/1000);"><br>
|
|
<table style='width:100%'><tr><td style='width: 50%; text-align: left;'><font class = 'Explain'>|< Glossy, polished, lustrous</font></td><td style='width: 50%; text-align: right;'><font class = 'Explain'>Unpolished, mat, rough >|</font></td></tr></table>
|
|
<font class='label'>Roughness Map (Grayscale) URL:</font> <input name = 'roughnessMap' type = 'text' style= 'width:100%;' oninput="save('roughnessMap', this);">
|
|
</div>
|
|
|
|
<div class='group'>
|
|
<font class='label'>Normal Map URL:</font> <input name = 'normalMap' type = 'text' style= 'width:100%;' oninput="save('normalMap', this);">
|
|
</div>
|
|
|
|
<div class='group'>
|
|
<font class='label'>Opacity:</font> <input name = 'opacity_value' readonly type = 'text' size = '5'><br>
|
|
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="slider" name = 'opacity' id = 'opacity' oninput="save('opacity', this); document.materialEditor.opacity_value.value = (document.materialEditor.opacity.value/1000);"><br>
|
|
<table style='width:100%'><tr><td style='width: 50%; text-align: left;'><font class = 'Explain'>|< Transparent</font></td><td style='width: 50%; text-align: right;'><font class = 'Explain'>Opaque >|</font></td></tr></table>
|
|
<br>
|
|
<font class='label'>Opacity Map Mode:</font><br>
|
|
<input type="radio" checked name = 'opacityMap' value = 'DO NOT USE' oninput="save('opacityMap', this);">Do not used
|
|
<input type="radio" name = 'opacityMap' value = 'OPACITY_MAP_MASK' oninput="save('opacityMap', this);">Cut off mask
|
|
<input type="radio" name = 'opacityMap' value = 'OPACITY_MAP_BLEND' oninput="save('opacityMap', this);">Blend<br>
|
|
<font class='Explain'>Note: For an opacity map, the alpha layer of the Albedo Map will be used. 'Blend' mode will used the alpha value to determine the opacity of a pixel. 'Cut off mask' mode will use the 'Cut off threshold' to determine if a pixel will be opaque or transparent, based on the alpha value from the map.</font><br><br>
|
|
<font class='label'>Cut Off Threshold:</font> <input name = 'opacityCutoff_value' readonly type = 'text' size = '5'><br>
|
|
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="slider" name = 'opacityCutoff' id = 'opacityCutoff' oninput="save('opacityCutoff', this); document.materialEditor.opacityCutoff_value.value = (document.materialEditor.opacityCutoff.value/1000);"><br>
|
|
<table style='width:100%'><tr><td style='width: 50%; text-align: left;'><font class = 'Explain'>|< Transparent</font></td><td style='width: 50%; text-align: right;'><font class = 'Explain'>Opaque >|</font></td></tr></table>
|
|
|
|
</div>
|
|
|
|
<div class='group'>
|
|
<table style="width:100%;"><tr><td><font class='label'>Emissive:</font> <input name = 'emissive' type = 'text' value = '#000000'>
|
|
</td><td>
|
|
<font class='label'>Unlit:</font> <input type="checkbox" name = 'unlit' oninput="save('unlit', this);">
|
|
</td></tr></table>
|
|
<font class='label'>Bloom Factor:</font> <input name = 'bloom_value' readonly type = 'text' size = '5'><br>
|
|
<input type="range" style="width:100%;" min="100" max="900" value="100" class="slider" name = 'bloom' id = 'bloom' oninput="save('bloom', this); document.materialEditor.bloom_value.value = (this.value/100);"><br>
|
|
<font class='label'>Emissive Map (RGB) URL:</font> <input name = 'emissiveMap' type = 'text' style= 'width:100%;' oninput="save('emissiveMap', this);">
|
|
</div>
|
|
|
|
<div class='group'>
|
|
<font class='label'>Scattering:</font> <input name = 'scattering_value' readonly type = 'text' size = '5'><br>
|
|
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="slider" name = 'scattering' id = 'scattering' oninput="save('scattering', this); document.materialEditor.scattering_value.value = (this.value/1000);"><br>
|
|
<font class='label'>Scattering Map (Grayscale) URL:</font> <input name = 'scatteringMap' type = 'text' style= 'width:100%;' oninput="save('scatteringMap', this);">
|
|
</div>
|
|
|
|
<div class='group'>
|
|
<font class='label'>Occlusion Map (Grayscale) URL:</font> <input name = 'occlusionMap' type = 'text' style= 'width:100%;' oninput="save('occlusionMap', this);">
|
|
</div>
|
|
|
|
<div class='group'>
|
|
<font class='label'>Material displayed on surface: </font><br>
|
|
<input type="radio" checked name = 'cullFaceMode' value = 'CULL_BACK' oninput="save('cullFaceMode', this);">Outside
|
|
<input type="radio" name = 'cullFaceMode' value = 'CULL_FRONT' oninput="save('cullFaceMode', this);">Inside
|
|
<input type="radio" name = 'cullFaceMode' value = 'CULL_NONE' oninput="save('cullFaceMode', this);">Both<br>
|
|
</div>
|
|
|
|
<div class='group'>
|
|
<font class='label'>Keep other existing material's properties: </font><br>
|
|
<font class='label'>defaultFallthrough:</font> <input type="checkbox" name = 'defaultFallthrough' oninput="save('defaultFallthrough', this);">
|
|
</div>
|
|
|
|
<input type='button' class = 'copybtn' name='copy' value = 'Copy' onclick='copyToClipboard(document.materialEditor.output.value);'><br>
|
|
<textarea name='output' id='output' rows = '21' class='output'></textarea>
|
|
<br><br>
|
|
<input type='button' class = 'copybtn' name='copy-fst' value = 'Copy for .fst materialMap array' onclick='copyToClipboard(document.materialEditor.fstoutput.value);'><br>
|
|
<textarea name='fstoutput' id='fstoutput' rows = '6' class='output'></textarea>
|
|
|
|
</td><td style=' background-image: url("images/trottoire.png"); background-repeat: repeat;'> </td></tr></table>
|
|
|
|
</form>
|
|
<script>
|
|
//Color Pickers functions
|
|
var picker = new CP(document.materialEditor.albedo);
|
|
|
|
picker.self.classList.add('no-alpha');
|
|
|
|
picker.on('change', function(r, g, b) {
|
|
this.source.value = this.color(r, g, b, 1);
|
|
this.source.style.backgroundColor = this.color(r, g, b, 1);
|
|
this.source.style.color = this.color(r, g, b, 1);
|
|
material.albedo = this.color(r, g, b, 1);
|
|
generateMaterialJSON();
|
|
});
|
|
|
|
|
|
var pickerEmissive = new CP(document.materialEditor.emissive);
|
|
|
|
pickerEmissive.self.classList.add('no-alpha');
|
|
|
|
pickerEmissive.on('change', function(r, g, b) {
|
|
this.source.value = this.color(r, g, b, 1);
|
|
this.source.style.backgroundColor = this.color(r, g, b, 1);
|
|
this.source.style.color = this.color(r, g, b, 1);
|
|
material.emissive = this.color(r, g, b, 1);
|
|
generateMaterialJSON();
|
|
});
|
|
|
|
EventBridge.scriptEventReceived.connect(function (message) {
|
|
var messageObj = JSON.parse(message);
|
|
if (messageObj.channel === channel) {
|
|
if (messageObj.action === "initializeMaterial") {
|
|
if (messageObj.material !== undefined) {
|
|
material = messageObj.material;
|
|
}
|
|
loadMaterial();
|
|
generateMaterialJSON();
|
|
}
|
|
}
|
|
});
|
|
|
|
function helpOn() {
|
|
document.getElementById("helpOverlay").style.display = "block";
|
|
}
|
|
|
|
function helpOff() {
|
|
document.getElementById("helpOverlay").style.display = "none";
|
|
}
|
|
</script>
|
|
<div id="helpOverlay" onclick="helpOff();">
|
|
<div style='text-align:right; font-size:14px; color:#999999; width:95%;'>✖</div><br><br>
|
|
<div style='width:95%;'>
|
|
<img class='demo' src="images/demo_cube.png"> <img class='demo' src="images/demo_sphere.png">
|
|
<img class='demo' src="images/demo_teapot.png"> <img class='demo' src="images/demo_brand.png"><br>
|
|
You can use these buttons to change the shape of the demonstration entity.
|
|
<br><hr>
|
|
<img class='studio' src="images/studio.png"><br>
|
|
You can use this button to teleport yourself to a serverless environment preconfigured with a consistent "ambientLight".
|
|
<br><hr>
|
|
<img class='studio' src="images/toggle_day_night.png"><br>
|
|
You can use this button to toggle between day and night in the serverless preconfigured environment.
|
|
<br><hr>
|
|
<img class='reset' src="images/reset.png"><br>
|
|
This button resets the material data to a new blank material.
|
|
<br><hr>
|
|
<img class='save' src="images/save_as_json.png"><br>
|
|
You can use this button to export the material data as a .json file. Such a .json file can be used in a material entity. It's mainly useful when you plan to reuse the same material for many entities. Using a .json file can simplify the update of a material used on many entities.
|
|
<br><hr>
|
|
<img class='save' src="images/create_material_entity.png"><br>
|
|
This button generates a Material entity from the specified material data. (Ready to be used.)
|
|
<br><hr>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html> |