three.js - Shaders & structs -


edit 16 august, 2016

i managed throw error might expose what's going on. in latest code edit, adding ability hot-swap between fragment shaders. works fine shaders singleton uniforms, swapping shader structure throws following error:

uncaught typeerror: cannot read property 'x' of undefined

call stack:

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 

it looks it's building structure uniforms incorrectly (it's trying reference property value three.color has r, g, , ,b). i'm continuing dig, maybe new info trigger lightbulb someone.

original post & code

according conversation here, three.js has ability use structs shader uniforms. i'm trying use shader has structs, simplified bare minimum, , still can't recognize them structs.

in fiddle below, change with_structs value true/false , re-run see difference.

i've tried defining uniforms this, didn't make difference.

uniforms: {     "colorvalues": {         "color": { type: "c", value: new three.color(0x00ff00) }     },     "opacityvalues": {         "opacity": { type: "f", value: 1.0 }     } } 

did miss properties, or approaching entirely incorrectly?

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 speed 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: run demo, must use 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 external function rather referencing draw directly, in case want update draw 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); 

this lesson in how couple small , stupid mistakes can make whole thing crash , burn.

i had named singleton uniforms same thing structured uniforms. when uniform parser trying assign values, tried assign singleton value onto structure object. didn't work, naturally, , whole thing fell apart.

it seems "alternate" uniform definition way go. i'm not sure why din't work originally, have feeling due naming mismatch, above.

here's working code chunks, , i've update fiddle linked in original post.

new fragment shader (only 1 structs)

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"); 

new material definition

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     }); 

Comments