Trying to pass an array of vec3s to the shader, Firefox gives me this warning:
WebGL warning: uniform setter: (uniform u_colors[0]) 'values' length
(4) must be a positive integer multiple of size of <enum 0x8b51>.
Also, it only renders black, not the given color.
const colrs = [
[239, 71, 111],
[255, 209, 102],
[6, 214, 160],
[17, 138, 178]
],
dmnsn = [1200, 300],
glCtx = (() => twgl.getContext(document.createElement("canvas")))(
twgl.setDefaults({ attribPrefix: "a_" })
);
var bfInf = twgl.primitives.createXYQuadBufferInfo(glCtx),
pgInf = twgl.createProgramInfo(glCtx, ["vs", "fs"]);
function rendr(fbi, pi, u) {
twgl.bindFramebufferInfo(glCtx, fbi);
twgl.drawObjectList(glCtx, [
{
programInfo: pi,
bufferInfo: bfInf,
uniforms: u
}
]);
}
function prepr() {
glCtx.canvas.width = dmnsn[0];
glCtx.canvas.height = dmnsn[1];
document.body.append(glCtx.canvas);
rendr(null, pgInf, { u_colors: colrs });
}
prepr();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script id="vs" type="x-shader/x-vertex">
attribute vec4 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
void main() {
v_texcoord = a_texcoord;
gl_Position = a_position;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision highp float;
uniform vec3 u_colors[4];
void main() {
gl_FragColor= vec4(u_colors[0], 1.0);
}
</script>
WebGL does not want an array of arrays.
const someArrayWith4ArraysOf3Values = [
[11, 22, 33],
[44, 55, 66],
[77, 88, 99],
[10, 11, 12],
];
gl.uniform3fv(some4ElementVec3Uniform, someArrayWith4ArraysOf3Values); // bad
It wants a flat array.
const someArrayWith12Values = [
11, 22, 33,
44, 55, 66,
77, 88, 99,
10, 11, 12,
];
gl.uniform3fv(some4ElementVec3Uniform, someArrayWith12Values); // good
Also, colors in shaders are float values that go from 0 to 1 so you probably want to set your colors to values from 0 to 1 or divide by 255 in your shader
const colrs = [
[1, 0.7, 0.5],
[255, 209, 102],
[6, 214, 160],
[17, 138, 178]
].flat(),
dmnsn = [1200, 300],
glCtx = (() => twgl.getContext(document.createElement("canvas")))(
twgl.setDefaults({ attribPrefix: "a_" })
);
var bfInf = twgl.primitives.createXYQuadBufferInfo(glCtx),
pgInf = twgl.createProgramInfo(glCtx, ["vs", "fs"]);
function rendr(fbi, pi, u) {
twgl.bindFramebufferInfo(glCtx, fbi);
twgl.drawObjectList(glCtx, [
{
programInfo: pi,
bufferInfo: bfInf,
uniforms: u
}
]);
}
function prepr() {
glCtx.canvas.width = dmnsn[0];
glCtx.canvas.height = dmnsn[1];
document.body.append(glCtx.canvas);
rendr(null, pgInf, { u_colors: colrs });
}
prepr();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script id="vs" type="x-shader/x-vertex">
attribute vec4 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
void main() {
v_texcoord = a_texcoord;
gl_Position = a_position;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision highp float;
uniform vec3 u_colors[4];
void main() {
gl_FragColor=vec4(u_colors[0], 1.0);
}
</script>
Related
I have an XY Charts in amCharts 4 and I can't set the correct parameter to insert in the tooltip. This is the code that design the chart:
Is possible to show the parameter "desc" in the tooltip?
var chart = am4core.create("chartdiv", am4charts.XYChart);
// Add data
chart.data = [ {
"x": -6,
"y": 0,
"diam": 4,
"desc": "test"
}, {
"x": 0,
"y": -10,
"diam": 4,
"desc": "test"
}, {
"x": 12,
"y": 10,
"diam": 8,
"desc": "special"
} ];
// Create axes
var xAxis = chart.xAxes.push(new am4charts.ValueAxis());
var yAxis = chart.yAxes.push(new am4charts.ValueAxis());
// Create series
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueX = "x";
series.dataFields.valueY = "y";
series.strokeWidth = 2;
series.fillOpacity = 0;
series.stroke = "red";
// Create bullet and tooltip
seriesBullet = series.bullets.push(new am4charts.CircleBullet());
seriesBullet.circle.fill = am4core.color("#fff");
seriesBullet.circle.strokeWidth = 3;
seriesBullet.circle.propertyFields.radius = "diam";
seriesBullet.tooltipText = "desc";
#chartdiv {
width: 100%;
height: 200px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<div id="chartdiv"></div>
You need to wrap the desc in curly braces: {desc}
seriesBullet.tooltipText = "{desc}";
Here is your updated working example:
var chart = am4core.create("chartdiv", am4charts.XYChart);
// Add data
chart.data = [ {
"x": -6,
"y": 0,
"diam": 4,
"desc": "test"
}, {
"x": 0,
"y": -10,
"diam": 4,
"desc": "test"
}, {
"x": 12,
"y": 10,
"diam": 8,
"desc": "special"
} ];
// Create axes
var xAxis = chart.xAxes.push(new am4charts.ValueAxis());
var yAxis = chart.yAxes.push(new am4charts.ValueAxis());
// Create series
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueX = "x";
series.dataFields.valueY = "y";
series.strokeWidth = 2;
series.fillOpacity = 0;
series.stroke = "red";
series.tooltipText = "{desc}";
// Create bullet and tooltip
seriesBullet = series.bullets.push(new am4charts.CircleBullet());
seriesBullet.circle.fill = am4core.color("#fff");
seriesBullet.circle.strokeWidth = 3;
seriesBullet.circle.propertyFields.radius = "diam";
seriesBullet.tooltipText = "{desc}";
#chartdiv {
width: 100%;
height: 200px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<div id="chartdiv"></div>
You need to put your parameter inside a {} curly braces.
E.g :
seriesBullet.tooltipText = "{desc}";
I am using google charts and here is my piechart code...I want to use background repeating image instead of colors. Is that possible with google charts?
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 1],
['Eat', 1],
['Commute', 1],
['Watch TV', 1],
['Sleep', 1]
]);
var options = {
pieSliceBorderColor : 'none',
chartArea:{left:5,top:5,width:390,height:390},
enableInteractivity:false,
pieStartAngle:30,
pieHole: 0.6,
slices: {
0: { color: 'brown', offset: 0.01 },
1: { color: 'brown', offset: 0.01 },
2: { color: 'brown', offset: 0.01 },
3: { color: 'brown', offset: 0.01 },
4: { color: 'brown', offset: 0.01 },
}
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
options.slices[sliceCount].color = 'transparent';
chart.draw(data, options);
}
there are no standard options to fill slices with repeating image
however, you can modify the chart's svg after it finishes drawing
on the 'ready' event,
create an image pattern and add to svg defs
then replace the 'fill' attribute on the chart elements that should have the image
pie chart slices are typically drawn with <path> elements
when there is only one slice (100%), a <rect> element is used
the legend is drawn with <circle>
keep in mind, if you need to create an image of the chart,
custom modifications such as these will not work when using method --> getImageURI
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages: ['corechart']
});
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 1],
['Eat', 1],
['Commute', 1],
['Watch TV', 1],
['Sleep', 1]
]);
var options = {
pieSliceBorderColor: 'none',
pieSliceText: 'none',
chartArea: {
bottom: 12,
left: 12,
top: 12,
width: 390,
height:390
},
enableInteractivity: false,
pieStartAngle: 30,
pieHole: 0.6,
slices: {
0: { color: 'brown', offset: 0.1 },
1: { color: 'brown', offset: 0.1 },
2: { color: 'brown', offset: 0.1 },
3: { color: 'brown', offset: 0.1 },
4: { color: 'brown', offset: 0.1 },
}
};
var container = $('#piechart')[0];
var chart = new google.visualization.PieChart(container);
google.visualization.events.addListener(chart, 'ready', function () {
// create image pattern
var svgNS = $('svg')[0].namespaceURI;
var pattern = document.createElementNS(svgNS, 'pattern');
pattern.setAttribute('id', 'whiteHat');
pattern.setAttribute('patternUnits', 'userSpaceOnUse');
pattern.setAttribute('width', 16);
pattern.setAttribute('height', 16);
var image = document.createElementNS(svgNS, 'image');
image.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'http://findicons.com/files/icons/512/star_wars/16/clone_old.png');
image.setAttribute('x', 0);
image.setAttribute('y', 0);
image.setAttribute('width', 16);
image.setAttribute('height', 16);
pattern.appendChild(image);
$('#defs')[0].appendChild(pattern);
// add image to pie slices
$('svg path').attr('fill', 'url(#whiteHat)');
// add image to legend circles
$('svg circle').attr('fill', 'url(#whiteHat)');
// test chart image
$(container.parentNode).append('<img alt="Chart" src="' + chart.getImageURI() + '">');
});
chart.draw(data, options);
}
div {
padding: 6px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div>piechart</div>
<div id="piechart"></div>
<div>image</div>
When coding a fade transition, what does the following code mean? I'm looking to achieve the same effect as http://jsfiddle.net/DW9q4/85/ but I have 2 scenes with 2 different map cubes rendered through a PerspectiveCamera.
I'm having trouble understanding what is going on, what is code doing?
uniforms: {
tDiffuse1: {
type: "t",
value: rtTexture1
},
tDiffuse2: {
type: "t",
value: rtTexture2
},
mixRatio: {
type: "f",
value: 0.5
},
opacity: {
type: "f",
value: 1.0
}
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = vec2( uv.x, 1.0 - uv.y );",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"uniform float opacity;",
"uniform float mixRatio;",
"uniform sampler2D tDiffuse1;",
"uniform sampler2D tDiffuse2;",
"varying vec2 vUv;",
"void main() {",
"vec4 texel1 = texture2D( tDiffuse1, vUv );",
"vec4 texel2 = texture2D( tDiffuse2, vUv );",
"gl_FragColor = opacity * mix( texel1, texel2, mixRatio );",
"}"
].join("\n")
All help is greatly appreciated!
If you googled 'vertexShader' or 'fragmentShader' you'd get tons of hits. These shaders are core to WebGL. If you want to understand shaders and WebGl there are many online resources. Three.js generates the shader calls for you. For most normal work you can ignore shaders and work entirely with three.js.
I've used Three.js quite a bit, but I'm just starting to learn how shaders work.
I have a green cube which is one-half transparent, as defined in a THREE.ShaderMaterial (based on the "phong" ShaderLib). I put a simple red cube inside the ShaderMaterial cube so I could tell the transparency was working (it is). The remaining problem is that the green cube's backfaces don't seem to be rendering, despite setting it to double-sided geometry.
Here's my fiddle: http://jsfiddle.net/TheJim01/kgkhvbtL/113/
// partial glass box
var hostDiv, scene, renderer, camera, root, controls, light, shape;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 0.1,
FAR = 100;
function init() {
hostDiv = document.createElement('div');
document.body.appendChild(hostDiv);
renderer = new THREE.WebGLRenderer({ antialias: true, preserverDrawingBuffer: true });
renderer.setSize(WIDTH, HEIGHT);
hostDiv.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 75;
controls = new THREE.TrackballControls(camera, renderer.domElement);
light = new THREE.PointLight(0xffffff, 2, Infinity);
light.position.copy(camera.position);
scene = new THREE.Scene();
scene.add(camera);
scene.add(light);
var geo = new THREE.BoxGeometry(10, 10, 10);
var shader = {
uniforms: THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "common" ],
THREE.UniformsLib[ "bump" ],
THREE.UniformsLib[ "normalmap" ],
THREE.UniformsLib[ "fog" ],
THREE.UniformsLib[ "lights" ],
THREE.UniformsLib[ "shadowmap" ],
{
"ambient" : { type: "c", value: new THREE.Color( 0xffffff ) },
"emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
"specular" : { type: "c", value: new THREE.Color( 0x111111 ) },
"shininess": { type: "f", value: 30 },
"wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
}
] ),
vertexShader: [
"#define PHONG",
"varying vec3 vViewPosition;",
"varying vec3 vNormal;",
THREE.ShaderChunk[ "map_pars_vertex" ],
THREE.ShaderChunk[ "lightmap_pars_vertex" ],
THREE.ShaderChunk[ "envmap_pars_vertex" ],
THREE.ShaderChunk[ "lights_phong_pars_vertex" ],
THREE.ShaderChunk[ "color_pars_vertex" ],
THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
THREE.ShaderChunk[ "skinning_pars_vertex" ],
THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
"varying vec3 glassPos;", // <!-- I added this -->
"void main() {",
THREE.ShaderChunk[ "map_vertex" ],
THREE.ShaderChunk[ "lightmap_vertex" ],
THREE.ShaderChunk[ "color_vertex" ],
THREE.ShaderChunk[ "morphnormal_vertex" ],
THREE.ShaderChunk[ "skinbase_vertex" ],
THREE.ShaderChunk[ "skinnormal_vertex" ],
THREE.ShaderChunk[ "defaultnormal_vertex" ],
" vNormal = normalize( transformedNormal );",
THREE.ShaderChunk[ "morphtarget_vertex" ],
THREE.ShaderChunk[ "skinning_vertex" ],
THREE.ShaderChunk[ "default_vertex" ],
THREE.ShaderChunk[ "logdepthbuf_vertex" ],
" vViewPosition = -mvPosition.xyz;",
THREE.ShaderChunk[ "worldpos_vertex" ],
THREE.ShaderChunk[ "envmap_vertex" ],
THREE.ShaderChunk[ "lights_phong_vertex" ],
THREE.ShaderChunk[ "shadowmap_vertex" ],
" glassPos = worldPosition.xyz / worldPosition.w;", // <!-- I added this -->
"}"
].join("\n"),
fragmentShader: [
"uniform vec3 diffuse;",
"uniform float opacity;",
"uniform vec3 ambient;",
"uniform vec3 emissive;",
"uniform vec3 specular;",
"uniform float shininess;",
THREE.ShaderChunk[ "color_pars_fragment" ],
THREE.ShaderChunk[ "map_pars_fragment" ],
THREE.ShaderChunk[ "alphamap_pars_fragment" ],
THREE.ShaderChunk[ "lightmap_pars_fragment" ],
THREE.ShaderChunk[ "envmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
THREE.ShaderChunk[ "lights_phong_pars_fragment" ],
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
THREE.ShaderChunk[ "normalmap_pars_fragment" ],
THREE.ShaderChunk[ "specularmap_pars_fragment" ],
THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
"varying vec3 glassPos;", // <!-- I added this -->
"void main() {",
" gl_FragColor = vec4( vec3( 1.0 ), opacity );",
// <!-- I added this
" if(glassPos.x < 0.0) {",
" gl_FragColor = gl_FragColor * vec4( vec3( 1.0 ), 0.5 );//discard;",
" }",
// end -->
THREE.ShaderChunk[ "logdepthbuf_fragment" ],
THREE.ShaderChunk[ "map_fragment" ],
THREE.ShaderChunk[ "alphamap_fragment" ],
THREE.ShaderChunk[ "alphatest_fragment" ],
THREE.ShaderChunk[ "specularmap_fragment" ],
THREE.ShaderChunk[ "lights_phong_fragment" ],
THREE.ShaderChunk[ "lightmap_fragment" ],
THREE.ShaderChunk[ "color_fragment" ],
THREE.ShaderChunk[ "envmap_fragment" ],
THREE.ShaderChunk[ "shadowmap_fragment" ],
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
THREE.ShaderChunk[ "fog_fragment" ],
"}"
].join("\n")
};
//console.log(shader.vertexShader);
//console.log(shader.fragmentShader);
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
uniforms['diffuse'].value.setHex(0x00ff00);
uniforms['ambient'].value.setHex(0x002200);
uniforms['emissive'].value.setHex(0x000000);
uniforms['specular'].value.setHex(0x007f00);
uniforms['ambient'].value.convertGammaToLinear();
var parameters = {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: uniforms,
lights: true,
fog: false,
doubleSided: true,
blending: THREE.NormalBlending,
transparent: true,
depthTest: true
};
var shaderMaterial = new THREE.ShaderMaterial( parameters );
var msh = new THREE.Mesh(geo, shaderMaterial);
scene.add(msh);
var m = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({
color: 0xff0000,
ambient: 0x22000,
emissive: 0x000000,
specular: 0x7f0000
}));
m.scale.set(0.75, 0.75, 0.75);
scene.add(m);
animate();
}
function animate() {
light.position.copy(camera.position);
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
}
init();
Did I do something wrong? Did I miss something? Or is this just not possible?
Thanks!
It is side: THREE.DoubleSide not doubleSided: true.
three.js r.68
I've tried to create an multipleline chart with tag for each node.
Every things ok. But some time the tags are showed not good when the values are nearly.
Any one have solution for this problem. Thank!
http://www.flickr.com/photos/96516997#N02/8973858413/
This is my
Graphael Line Chart
<script src="js/raphael-min.js"></script>
<script src="js/g.raphael-min.js"></script>
<script src="js/g.line-min.js"></script>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<style type="text/css">
.block {
text-align: center;
background: #c0c0c0;
}
.block:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.centered1{
display: inline-block;
vertical-align: middle;
width: 97%;
background: #f5f5f5;
}
.centered2{
text-align: left;
display: inline-block;
vertical-align: middle;
width: 97%;
background: #f5f5f5;
}
</style>
<script type="text/javascript">
var hidedChart = [ false, false, false, false];
var paper;
var chart;
var xData = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];
var yData = [ [ 31, 62, 3, 4, 5, 60, 47, 8, 9, 10, 51, 72 ],
[ 31, 33, 44, 11, 55, 60, 71, 82, 19, 141, 23, 34 ],
[ 3, 2, 49, 64, 51, 26, 43, 14, 39, 10, 41, 32 ],
[ 10, 330, 50, 34, 53, 12, 67, 84, 32, 171, 239, 36 ]];
var colory = [ "#9e1316", "#007fff", "#104421", "#734f96", "#b43f26" ];
var xAxis = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec" ];
var direcTag = [ 'right', 'up', 'left', 'down' ];
var angle = [0,45,90,135,180,225,270,315];
var options = {
symbol : "circle",
nostroke : false,
smooth : false,
colors : colory,
shade : true,
fill : "transparent",
axis : "0 0 1 1",
axisxstep : xAxis.length - 1,
axisystep : 5
};
window.onload = function() {
paper = Raphael("no", "800", "550");
//line chart object
chart = drawLineChart(34, 35, 600, 450, xData, yData, options);
addCheckBox(yData.length);
}
$(window).load(function(){
});
function drawLineChart(x, y, w, h, xdata, ydata, options) {
var lines = paper.linechart(x, y, w, h, xdata, ydata, options);
lines.hoverColumn(hoverColumn, unhoverColumn);
//set x Axis label
$.each(lines.axis[0].text.items, function(index, label) {
this.attr("text", xAxis[index]);
});
for ( var i = 0; i < ydata.length; i++) {
lines.shades[i].attr({
fill : "transparent"
});
}
lines.symbols.attr({
r : 4
});
return lines
}
function hoverColumn() {
this.tags = paper.set();
for ( var i = 0, ii = this.y.length; i < ii; i++) {
if (hidedChart[i] == false) {
var nTag;
nTag = paper.drop(this.x, this.y[i], this.values[i],
angle[i]);
this.tags.push(nTag.insertBefore(this).attr([ {
fill : colory[i]
}, {
fill : "#ffffff"
} ]));
}
}
}
function unhoverColumn() {
this.tags && this.tags.remove();
}
function showHideLine(num) {
if((!$("#LINE"+num).is(':checked')) != hidedChart[num]){
hidedChart[num] = !hidedChart[num];
if (hidedChart[num] == true) {
chart.lines[num].attr({
opacity : 0
});
chart.symbols[num].attr({
opacity : 0
});
} else {
chart.lines[num].attr({
opacity : 100
});
chart.symbols[num].attr({
opacity : 100
});
}
}
}
function addCheckBox(num) {
$("#lineCheck").empty();
for ( var i = 0; i < num; i++) {
//CHECK BOX
var checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.id = "LINE" + i;
checkbox.style.margin = "7px";
checkbox.checked = "checked";
$(checkbox).click(function() {
for ( var j = 0; j < num; j++) {
showHideLine(j);
}
});
//LABEL
var label = document.createElement("label");
label.htmlFor = "LINE" + i;
label.appendChild(document.createTextNode("Line " + (i + 1)));
//BREAK LINE
var br = document.createElement("br");
$("#lineCheck").append(checkbox);
$("#lineCheck").append(label);
$("#lineCheck").append(br);
}
}
</script>
</head>
<body>
<div id="padLeft" class="block" style="float: left; width: 84%; height: 100%;">
<div id="no" class="centered1"></div>
</div>
<div id="padRight" class="block" style="float: right; height: 100%; width: 15%;" align="left">
<div id="lineCheck" class="centered2"></div>
</div>
</body>
</html>