[英]Shaders & structs
編輯 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
看起來它正在錯誤地構建結構制服(它試圖引用只有r
、 g
和 、 b
的THREE.Color
屬性value
)。 我正在繼續挖掘,但也許這個新信息會觸發某人的燈泡。
原始郵政編碼
根據此處的對話,Three.js 能夠將struct
用作着色器制服。 我現在正在嘗試使用具有結構的着色器,簡化到最低限度,但仍然無法將它們識別為結構。
在下面的小提琴中,只需將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);
這是關於幾個小而愚蠢的錯誤如何使整個事情崩潰和燃燒的教訓。
我給我的單身制服命名和我的結構化制服一樣。 當統一解析器嘗試分配值時,它嘗試將單例值分配給結構對象。 那自然行不通,整個事情就崩潰了。
似乎“替代”統一定義也是要走的路。 我不確定為什么它最初不起作用,但我感覺這是由於命名不匹配,就像上面一樣。
這是工作代碼塊,我已經更新了原始帖子中鏈接的小提琴。
新的片段着色器(只有一個 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
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.