【问题标题】:Shaders & structs着色器和结构
【发布时间】:2020-07-17 16:25:40
【问题描述】:

2016 年 8 月 16 日编辑

我终于设法让它抛出一个可能暴露正在发生的事情的错误。在我最新的代码编辑中,我添加了在片段着色器之间进行热交换的功能。这适用于具有单例制服的着色器,但切换到具有结构的着色器会引发以下错误:

未捕获的类型错误:无法读取未定义的属性“x”

调用栈:

setValue3fv @ three.js:31915
THREE.WebGLUniforms.StructuredUniform.setValue @ three.js:32148
THREE.WebGLUniforms.WebGLUniforms.upload @ three.js:32285
setProgram @ three.js:26733 renderBufferDirect @ three.js:25492
renderObjects @ three.js:26303
render @ three.js:26044
draw @ VM160:191doStructs @ VM86:148

看起来它构建的结​​构制服不正确(它试图引用属性value 来获取只有rg 和,bTHREE.Color)。我正在继续挖掘,但也许这个新信息会为某人触发一个灯泡。

原始帖子和代码

根据here 的对话,Three.js 能够使用structs 作为着色器制服。我现在正在尝试使用具有结构的着色器,将其简化到最低限度,但仍然无法将它们识别为结构。

在下面的小提琴中,只需将WITH_STRUCTS 的值更改为true/false 并重新运行以查看差异。

我也尝试过这样定义制服,但没有任何区别。

uniforms: {
    "colorValues": {
        "color": { type: "c", value: new THREE.Color(0x00ff00) }
    },
    "opacityValues": {
        "opacity": { type: "f", value: 1.0 }
    }
}

我错过了一些属性,还是我完全错误地处理了这个?

jsFiddle: http://jsfiddle.net/TheJim01/546syLur/

HTML:

<script src="http://threejs.org/build/three.js"></script>
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>
<div id="host"></div>

<script>
// INITIALIZE
var WIDTH = window.innerWidth,
    HEIGHT = window.innerHeight,
    FOV = 35,
    NEAR = 1,
    FAR = 1000;

var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
document.getElementById('host').appendChild(renderer.domElement);

var camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 250;

var trackballControl = new THREE.TrackballControls(camera, renderer.domElement);
trackballControl.rotateSpeed = 5.0; // need to speed it up a little

var scene = new THREE.Scene();

var light = new THREE.PointLight(0xffffff, 1, Infinity);
light.position.copy(camera.position);

scene.add(light);

function draw(){
    light.position.copy(camera.position);
    renderer.render(scene, camera);
}
trackballControl.addEventListener('change', draw);

function navStartHandler(e) {
  renderer.domElement.addEventListener('mousemove', navMoveHandler);
  renderer.domElement.addEventListener('mouseup', navEndHandler);
}
function navMoveHandler(e) {
  trackballControl.update();
}
function navEndHandler(e) {
  renderer.domElement.removeEventListener('mousemove', navMoveHandler);
  renderer.domElement.removeEventListener('mouseup', navEndHandler);
}

renderer.domElement.addEventListener('mousedown', navStartHandler);
renderer.domElement.addEventListener('mousewheel', navMoveHandler);
</script>

<fieldset id="controls">
  <legend>Controls</legend>
  <input id="drawButton" type="button" value="DRAW" />
  <input id="useStructsCheck" type="checkbox" /><label for="useStructsCheck">Use Structs</label>
</fieldset>

CSS:

html, body{
    padding: 0;
    margin: 0;
    width: 100%;
    overflow: hidden;
}

#controls {
    position: absolute;
    top: 20px;
    left: 20px;
    z-index: 99;
    color: white;
    border-radius: 10px;
}

#host {
    width: 100%;
    height: 100%;
}

JavaScript:

// NOTE: To run this demo, you MUST use the HTTP protocol, not HTTPS!

var WITH_STRUCTS = false;

var vShaderCode = [
    "precision highp float;",
    "precision highp int;",

    "uniform mat4 modelViewMatrix;",
    "uniform mat4 projectionMatrix;",

    "attribute vec3 position;",

    "void main() {",
        "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
        "gl_Position = projectionMatrix * mvPosition;",
    "}"
].join("\n");

var fShaderCode_structs = [
    "precision highp float;",
    "precision highp int;",

    "struct ColorStruct{",
        "vec3 value;",
    "};",
    "struct OpacityStruct{",
        "float value;",
    "};",
    "uniform ColorStruct color;",
    "uniform OpacityStruct opacity;",

    "void main() {",
        "gl_FragColor = vec4(color.value, opacity.value);",
    "}"
].join("\n");

var fShaderCode_nostructs = [
    "precision highp float;",
    "precision highp int;",

    "uniform vec3 color;",
    "uniform float opacity;",

    "void main() {",
        "gl_FragColor = vec4(color, opacity);",
    "}"
].join("\n");

var geo = new THREE.BoxBufferGeometry(30, 30, 30);

var mat = new THREE.RawShaderMaterial({
        uniforms: {
        "color": { type: "c", value: new THREE.Color(0xff0000) },
            "opacity": { type: "1f", value: 1.0 },
            "color.value": { type: "c", value: new THREE.Color(0x00ff00) },
            "opacity.value": { type: "1f", value: 1.0 }
        },
        vertexShader: vShaderCode,
        fragmentShader: (WITH_STRUCTS) ? fShaderCode_structs : fShaderCode_nostructs
    });

var msh = new THREE.Mesh(geo, mat);
scene.add(msh);

draw();

// Draw button
// Making this an external function rather than referencing draw directly, in case we want to update draw with parameters.
function doDraw() {
  draw();
}
document.getElementById("drawButton").addEventListener("click", doDraw);

// Use Structs checkbox
function doStructs() {
  WITH_STRUCTS = !WITH_STRUCTS;
  if (WITH_STRUCTS) {
    mat.fragmentShader = fShaderCode_structs;
  }
  else {
    mat.fragmentShader = fShaderCode_nostructs;
  }
  mat.needsUpdate = true;
  draw();
}
document.getElementById("useStructsCheck").addEventListener("click", doStructs);

【问题讨论】:

  • 我更新了我的代码,使片段着色器不再那么模糊(两个单独的着色器代码块,而不是使用预处理器逻辑)。我还将事情追溯到渲染器,可以看到它正在调用gl.getUniformLocation(program, "color.value");(和opacity.value),所以据我所知,这些制服应该设置正确。

标签: three.js


【解决方案1】:

这是关于几个小而愚蠢的错误如何使整个事情崩溃和燃烧的教训。

我将单身制服命名为与结构化制服相同的名称。当统一解析器尝试分配值时,它尝试将单例值分配给结构对象。自然而然,这不起作用,整个事情都崩溃了。

“替代”制服定义似乎也是要走的路。我不确定为什么它最初不起作用,但我感觉这是由于命名不匹配,就像上面一样。

这是工作代码块,我已经更新了原始帖子中链接的小提琴。

新的片段着色器(只有一个 WITH 结构)

var fShaderCode_structs = [
    "precision highp float;",
    "precision highp int;",

    "struct ColorStruct{",
        "vec3 cvalue;",
    "};",
    "struct OpacityStruct{",
        "float ovalue;",
    "};",
    "uniform ColorStruct colorS;",
    "uniform OpacityStruct opacityS;",

    "void main() {",
        "gl_FragColor = vec4(colorS.cvalue, opacityS.ovalue);",
    "}"
].join("\n");

新材料定义

var mat = new THREE.RawShaderMaterial({
    uniforms: {
        "color": { type: "c", value: new THREE.Color(0xff0000) },
        "opacity": { type: "1f", value: 1.0 },
        "colorS": {
            value: { type: "c", cvalue: new THREE.Color(0x00ff00) },
        },
        "opacityS": {
            value: { type: "1f", ovalue: 1.0 }
        }
    },
    vertexShader: vShaderCode,
    fragmentShader: (WITH_STRUCTS) ? fShaderCode_structs : fShaderCode_nostructs
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 2018-11-14
    • 1970-01-01
    • 2013-09-17
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多