All materials render black on some mobile devices #69

Let's detect the wrong devices, and set precision to mediump only if needed.
This commit is contained in:
Viktor Kovacs 2021-06-05 09:01:24 +02:00
parent ff46ecc7d2
commit c7ef690933
11 changed files with 149 additions and 81 deletions

View File

@ -55,6 +55,7 @@
<script type="text/javascript" src="../source/export/exporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoimporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoexporter.js"></script>
<script type="text/javascript" src="../source/external/threeutils.js"></script>
<script type="text/javascript" src="../source/external/threeconverter.js"></script>
<script type="text/javascript" src="../source/external/threemodelloader.js"></script>
<script type="text/javascript" src="../source/parameters/parameterlist.js"></script>

View File

@ -56,6 +56,7 @@
<script type="text/javascript" src="../source/export/exporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoimporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoexporter.js"></script>
<script type="text/javascript" src="../source/external/threeutils.js"></script>
<script type="text/javascript" src="../source/external/threeconverter.js"></script>
<script type="text/javascript" src="../source/external/threemodelloader.js"></script>
<script type="text/javascript" src="../source/parameters/parameterlist.js"></script>

View File

@ -55,6 +55,7 @@
<script type="text/javascript" src="../source/export/exporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoimporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoexporter.js"></script>
<script type="text/javascript" src="../source/external/threeutils.js"></script>
<script type="text/javascript" src="../source/external/threeconverter.js"></script>
<script type="text/javascript" src="../source/external/threemodelloader.js"></script>
<script type="text/javascript" src="../source/parameters/parameterlist.js"></script>

View File

@ -55,6 +55,7 @@
<script type="text/javascript" src="../source/export/exporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoimporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoexporter.js"></script>
<script type="text/javascript" src="../source/external/threeutils.js"></script>
<script type="text/javascript" src="../source/external/threeconverter.js"></script>
<script type="text/javascript" src="../source/external/threemodelloader.js"></script>
<script type="text/javascript" src="../source/parameters/parameterlist.js"></script>

View File

@ -53,11 +53,6 @@
pixels
);
// TODO: remove
let resultDiv = document.createElement ('div');
document.body.appendChild (resultDiv);
resultDiv.innerHTML = pixels;
document.body.removeChild (canvas);
if (pixels[0] < 50 && pixels[1] < 50 && pixels[2] < 50) {
return true;

View File

@ -1,4 +1,12 @@
OV.ConvertModelToThreeMeshes = function (model, callbacks)
OV.ModelToThreeConversionParams = class
{
constructor ()
{
this.forceMediumpForMaterials = false;
}
};
OV.ConvertModelToThreeMeshes = function (model, params, callbacks)
{
function CreateThreeMaterial (model, materialIndex)
{
@ -35,7 +43,7 @@ OV.ConvertModelToThreeMeshes = function (model, callbacks)
specularColor.setRGB (0.0, 0.0, 0.0);
}
let threeMaterial = new THREE.MeshPhongMaterial ({
let materialParams = {
color : diffuseColor,
specular : specularColor,
emissive : emissiveColor,
@ -44,8 +52,12 @@ OV.ConvertModelToThreeMeshes = function (model, callbacks)
transparent : material.transparent,
alphaTest : material.alphaTest,
side : THREE.DoubleSide
});
};
if (params.forceMediumpForMaterials) {
materialParams.precision = 'mediump';
}
let threeMaterial = new THREE.MeshPhongMaterial (materialParams);
LoadTexture (threeMaterial, material.diffuseMap, function (threeTexture) {
if (!material.multiplyDiffuseMap) {
threeMaterial.color.setRGB (1.0, 1.0, 1.0);

View File

@ -3,9 +3,10 @@ OV.ThreeModelLoader = class
constructor ()
{
this.importer = new OV.Importer ();
this.importer.AddImporter (new OV.Importer3dm ());
this.importer.AddImporter (new OV.Importer3dm ());
this.callbacks = null;
this.inProgress = false;
this.inProgress = false;
this.hasHighpDriverIssue = OV.HasHighpDriverIssue ();
}
Init (callbacks)
@ -13,79 +14,82 @@ OV.ThreeModelLoader = class
this.callbacks = callbacks;
}
LoadFromUrlList (urls, settings)
{
if (this.inProgress) {
return;
}
LoadFromUrlList (urls, settings)
{
if (this.inProgress) {
return;
}
let obj = this;
this.inProgress = true;
let obj = this;
this.inProgress = true;
this.callbacks.onLoadStart ();
this.importer.LoadFilesFromUrls (urls, function () {
obj.OnFilesLoaded (settings);
});
}
LoadFromFileList (files, settings)
{
if (this.inProgress) {
return;
}
let obj = this;
this.inProgress = true;
this.callbacks.onLoadStart ();
this.importer.LoadFilesFromFileObjects (files, function () {
obj.OnFilesLoaded (settings);
});
}
ReloadFiles (settings)
{
if (this.inProgress) {
return;
}
this.inProgress = true;
this.callbacks.onLoadStart ();
this.OnFilesLoaded (settings);
}
this.importer.LoadFilesFromUrls (urls, function () {
obj.OnFilesLoaded (settings);
});
}
OnFilesLoaded (settings)
{
let obj = this;
this.callbacks.onImportStart ();
OV.RunTaskAsync (function () {
obj.importer.Import (settings, {
onSuccess : function (importResult) {
obj.OnModelImported (importResult);
},
onError : function (importError) {
obj.callbacks.onLoadError (importError);
obj.inProgress = false;
}
});
});
}
LoadFromFileList (files, settings)
{
if (this.inProgress) {
return;
}
OnModelImported (importResult)
{
let obj = this;
this.callbacks.onVisualizationStart ();
OV.ConvertModelToThreeMeshes (importResult.model, {
onTextureLoaded : function () {
obj.callbacks.onTextureLoaded ();
},
onModelLoaded : function (meshes) {
obj.callbacks.onModelFinished (importResult, meshes);
obj.inProgress = false;
}
});
}
let obj = this;
this.inProgress = true;
this.callbacks.onLoadStart ();
this.importer.LoadFilesFromFileObjects (files, function () {
obj.OnFilesLoaded (settings);
});
}
GetImporter ()
{
return this.importer;
}
ReloadFiles (settings)
{
if (this.inProgress) {
return;
}
this.inProgress = true;
this.callbacks.onLoadStart ();
this.OnFilesLoaded (settings);
}
OnFilesLoaded (settings)
{
let obj = this;
this.callbacks.onImportStart ();
OV.RunTaskAsync (function () {
obj.importer.Import (settings, {
onSuccess : function (importResult) {
obj.OnModelImported (importResult);
},
onError : function (importError) {
obj.callbacks.onLoadError (importError);
obj.inProgress = false;
}
});
});
}
OnModelImported (importResult)
{
let obj = this;
this.callbacks.onVisualizationStart ();
let params = new OV.ModelToThreeConversionParams ();
// https://github.com/kovacsv/Online3DViewer/issues/69
params.forceMediumpForMaterials = this.hasHighpDriverIssue;
OV.ConvertModelToThreeMeshes (importResult.model, params, {
onTextureLoaded : function () {
obj.callbacks.onTextureLoaded ();
},
onModelLoaded : function (meshes) {
obj.callbacks.onModelFinished (importResult, meshes);
obj.inProgress = false;
}
});
}
GetImporter ()
{
return this.importer;
}
};

50
source/external/threeutils.js vendored Normal file
View File

@ -0,0 +1,50 @@
OV.HasHighpDriverIssue = function ()
{
let canvas = document.createElement ('canvas');
document.body.appendChild (canvas);
let parameters = {
canvas : canvas,
antialias : true
};
let renderer = new THREE.WebGLRenderer (parameters);
renderer.setClearColor ('#ffffff', 1);
renderer.setSize (10, 10);
let scene = new THREE.Scene ();
let ambientLight = new THREE.AmbientLight (0x888888);
scene.add (ambientLight);
let light = new THREE.DirectionalLight (0x888888);
light.position.set (0.0, 0.0, 1.0);
scene.add (light);
let camera = new THREE.PerspectiveCamera (45.0, 1.0, 0.1, 1000.0);
camera.position.set (0.0, 0.0, 1.0);
camera.up.set (0.0, 1.0, 0.0);
camera.lookAt (new THREE.Vector3 (0.0, 0.0, 0.0));
scene.add (camera);
let plane = new THREE.PlaneGeometry (1.0, 1.0);
let mesh = new THREE.Mesh (plane, new THREE.MeshPhongMaterial ({
color : 0xcc0000
}));
scene.add (mesh);
renderer.render (scene, camera);
let context = renderer.getContext ();
let pixels = new Uint8Array (4);
context.readPixels(
5, 5, 1, 1,
context.RGBA,
context.UNSIGNED_BYTE,
pixels
);
document.body.removeChild (canvas);
if (pixels[0] < 50 && pixels[1] < 50 && pixels[2] < 50) {
return true;
}
return false;
};

View File

@ -51,6 +51,7 @@
"source/export/exporter.js",
"source/external/rhinoimporter.js",
"source/external/rhinoexporter.js",
"source/external/threeutils.js",
"source/external/threeconverter.js",
"source/external/threemodelloader.js",
"source/parameters/parameterlist.js",

View File

@ -64,6 +64,7 @@
<script type="text/javascript" src="../source/export/exporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoimporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoexporter.js"></script>
<script type="text/javascript" src="../source/external/threeutils.js"></script>
<script type="text/javascript" src="../source/external/threeconverter.js"></script>
<script type="text/javascript" src="../source/external/threemodelloader.js"></script>
<script type="text/javascript" src="../source/parameters/parameterlist.js"></script>

View File

@ -64,6 +64,7 @@
<script type="text/javascript" src="../source/export/exporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoimporter.js"></script>
<script type="text/javascript" src="../source/external/rhinoexporter.js"></script>
<script type="text/javascript" src="../source/external/threeutils.js"></script>
<script type="text/javascript" src="../source/external/threeconverter.js"></script>
<script type="text/javascript" src="../source/external/threemodelloader.js"></script>
<script type="text/javascript" src="../source/parameters/parameterlist.js"></script>