【问题标题】:Is there a way to reference a custom shader from within the json material format in three.js?有没有办法从 three.js 的 json 材质格式中引用自定义着色器?
【发布时间】:2016-11-30 12:52:29
【问题描述】:

Three.js 的 JSON 对象场景格式 4 在此处定义了材质规范:JSON Material Format 4

但目前尚不清楚,至少对我来说,从那里引用自定义着色器的方式或天气是可能的。任何想法如何做到这一点?

[更新]

我想我的问题不够清楚,我所说的是让 JSON 加载器能够解释由自定义着色器定义的材质。这是 JSON 对象场景格式 4 的摘录:

"materials": [
    {
        "uuid": "87D95D6C-6BB4-4B8F-8166-A3A6945BA5E3",
        "type": "MeshPhongMaterial",
        "color": 16777215,
        "ambient": 16777215,
        "emissive": 0,
        "specular": 1118481,
        "shininess": 30,
        "opacity": 1,
        "transparent": false,
        "wireframe": false
    }
],
"object": {
    "uuid": "89529CC6-CBAC-412F-AFD1-FEEAE785BA19",
    "type": "Scene",
    "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
    "children": [
        {
            "uuid": "33FA38D9-0AAC-4657-9BBE-5E5780DDFB2F",
            "name": "Box 1",
            "type": "Mesh",
            "geometry": "C3BF1E70-0BE7-4E6D-B184-C9F1E84A3423",
            "material": "87D95D6C-6BB4-4B8F-8166-A3A6945BA5E3",
            "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
        },

如您所见,网格可以通过其 UUID 引用材质。 JSON 加载器在加载此文件时将检查此材质的类型,并基于它使用提供的参数创建该材质的实例。我遇到的问题是材质类型是在 WebGLPrograms 函数中预定义的,我找不到使用自定义着色器扩展此列表的明确方法。

【问题讨论】:

  • 对我来说仍然很不清楚。您要 "extend" 什么列表? WebGLProgram 仅检查它是否正在处理 RawShaderMaterial 或 ShaderMaterial 如果您想将自定义着色器应用于几何图形,则使用这些材质类型。您应该添加代码以澄清问题。
  • 让我这样解释:当您使用 JSONLoader 加载场景时负责创建材质的 MaterialLoader 类能够创建所有标准材质的实例。但目前尚不清楚是否或如何告诉它创建自定义 ShaderMaterial 的实例。
  • 只是将类型指定为ShaderMaterial并传递uniforms、vertexShader和fragmentShader作为参数的问题吗?

标签: javascript three.js shader


【解决方案1】:

对于自定义着色器,您必须使用属性vertexShader、fragmentShader 实现ShaderMaterial 或RawShaderMaterial,这两个着色器的代码都必须包含在html/js 源中。

只要提供了两个着色器的源,您就可以使用 JSON 格式,ShaderMaterial 继承自基础 Material 对象。

如果没有参数 ShaderMaterial,您将在 JSON 输出中看到默认的顶点和片段着色器代码。

var shader = new THREE.ShaderMaterial();
console.log(shader.toJSON());
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r82/three.js" charset="utf-8"></script>

更新:

最后一次尝试。希望我能正确理解您的问题更新和 cmets。

但不清楚是否或如何告诉它创建自定义 ShaderMaterial 的实例。

是的,MaterialLoader 可以加载带有自定义顶点和片段着色器的ShaderMaterial,Material.toJSON 方法和MaterialLoader 是镜面反射的,因为它应该是,否则转换材质没有意义转为 JSON 格式。

// specular aspect of saving and loading
var loader = new THREE.MaterialLoader();

var shaderMaterial = new THREE.ShaderMaterial();
var shaderMaterialJSON = JSON.stringify(shaderMaterial.toJSON());

console.log('JSON ' + shaderMaterialJSON);

var loadedShaderMaterial = loader.parse(JSON.parse(shaderMaterialJSON));

console.log(loadedShaderMaterial);

// convert a phong material to a shader material
var phongMatJSON = '{"uuid": "87D95D6C-6BB4-4B8F-8166-A3A6945BA5E3", "type": "MeshPhongMaterial", "color": 16777215, "ambient": 16777215, "emissive": 0, "specular": 1118481, "shininess": 30, "opacity": 1, "transparent": false, "wireframe": false}';

var phongMatObj = JSON.parse(phongMatJSON);
phongMatObj.color = undefined; // not used in a shaderMaterial
phongMatObj.emissive = undefined; // not used in a shaderMaterial
phongMatObj.specular = undefined; // not used in a shaderMaterial
phongMatObj.name = '';
phongMatObj.type = 'ShaderMaterial';
phongMatObj.uniforms = {}
phongMatObj.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
phongMatObj.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 0.0, 0.0, 1.0, 1.0 );\n}';

var shaderMatObj = loader.parse(phongMatObj);

console.log(shaderMatObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r82/three.js" charset="utf-8"></script>

【讨论】:

  • 谢谢@Marcs,但这并不是我要问的。如果您有时间,请查看我在上面添加的说明。
猜你喜欢
  • 2020-08-28
  • 2017-04-14
  • 2012-09-28
  • 2012-10-12
  • 1970-01-01
  • 2017-01-17
  • 2022-01-20
  • 2013-03-16
  • 2021-09-20
相关资源
最近更新 更多