编辑2016年8月16日
我终于设法让它抛出一个错误,可能会暴露正在发生的事情。在我最新的代码编辑中,我添加了在片段着色器之间进行热交换的功能。这适用于具有单件制服的着色器,但是交换到具有结构的着色器会引发以下错误:
未捕获的TypeError:无法读取未定义的属性“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
的属性THREE.Color
,r
只有g
,b
和{{1} }})。我正在继续挖掘,但也许这个新信息会为某人触发灯泡。
Original Post&代码
根据对话here,Three.js可以使用struct
s作为着色器制服。我现在正在尝试使用具有结构的着色器,简化到最低限度,但仍然无法将其识别为结构。
在下面的小提琴中,只需将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);
答案 0 :(得分:0)
这是一个关于一些小而愚蠢的错误如何使整个事情崩溃和燃烧的教训。
我将我的单身制服命名为与我的结构制服相同。当统一解析器尝试分配值时,它尝试将单例值分配给结构对象。当然,这不起作用,整个事情就崩溃了。
似乎“替代”统一定义是要走的路。我不确定为什么它最初不起作用,但我感觉这是由于命名不匹配,如上所述。
这是工作代码块,我更新了原始帖子中链接的小提琴。
新片段着色器(只有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
});