Reputation: 47
I've just started to learn webgl I've been trying to generate triangles with random size and positions just like in this picture using javascript.
I know that I need to use a for loop inside the function initScene() but I am not sure how to put the new positions into the array. Please help.
// Application info.
var app = app || {};
var nbTriangles=20;
function getContextGL(canvasElement)
{
var can = document.getElementById(canvasElement);
if(can == null)
{
return [null, null];
}
var gl = can.getContext("webgl");
return [can, gl];
}
function createShaderFromElement(gl, id)
{
// Grab the script element.
var scriptElt = document.getElementById(id);
if (!scriptElt)
{
return null;
}
// Retrieve the source.
var scriptSource = scriptElt.textContent;
// Identify shader type based on element type.
var shaderObj;
if (scriptElt.type == "x-shader/x-fragment")
{
shaderObj = gl.createShader(gl.FRAGMENT_SHADER);
}
else if (scriptElt.type == "x-shader/x-vertex")
{
shaderObj = gl.createShader(gl.VERTEX_SHADER);
}
else
{
return null;
}
// Compile and check status.
gl.shaderSource(shaderObj, scriptSource);
gl.compileShader(shaderObj);
var ok = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
if (!ok)
{
var msgError = gl.getShaderInfoLog(shaderObj);
alert(msgError);
gl.deleteShader(shader);
return null;
}
return shaderObj;
}
function buildProgram(gl, vertexShader, fragmentShader)
{
if (!vertexShader || !fragmentShader)
{
return null;
}
var progObject = gl.createProgram();
if(!progObject)
{
alert("Can't create program object.");
return ;
}
gl.attachShader(progObject, vertexShader);
gl.attachShader(progObject, fragmentShader);
gl.linkProgram(progObject);
var ok = gl.getProgramParameter(progObject, gl.LINK_STATUS);
if(!ok)
{
var msgError = gl.getProgramInfoLog(progObject);
alert(msgError);
gl.deleteProgram(progObject);
return null;
}
return progObject;
}
function initGL()
{
app.gl.viewport(0,0,app.can.width, app.can.height);
app.gl.clearColor(0.,0.,0., 1.0);
app.gl.clear(app.gl.COLOR_BUFFER_BIT);
var vs = createShaderFromElement(app.gl, "vs");
var fs = createShaderFromElement(app.gl, "fs");
app.progObject = buildProgram(app.gl, vs, fs);
app.gl.useProgram(app.progObject);
}
function initScene()
{
var gl = app.gl;
// Creer le buffer de geometrie (vertex)
//
/* Drawing one triangle:
var positions = [
// coordonnees normalisees.
0.0, 0.1, 0.1, -0.1,-0.1, -0.1
];*/
for (var i=0; i<nbTriangles;++i)
{
var orig = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6, Math.random * 1.6];
P0 = orig[0] * scale + Trans[0];
P1 = orig[1] * scale + Trans[1];
P2 = orig[2] * scale + Trans[2];
var positions= new Positions (P0,P1,P2)
TRIANGLES.push(newPositions);
}
// Creer un nouveau buffer vide.
var posBuffer = gl.createBuffer();
// Ref sur l'attribut "pos" dans le vertex shader.
var posLocation = gl.getAttribLocation(app.progObject, "pos");
// Activer le buffer. Toute operation sur buffer
// sera appliquer a posBuffer (il est actif!).
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
gl.enableVertexAttribArray(posLocation);
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false /*no normalization*/, 0 /*stride*/, 0 /*offset*/);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
}
function render()
{
var gl = app.gl;
gl.clear( gl.COLOR_BUFFER_BIT)
// Dessiner le buffer.
gl.drawArrays(gl.TRIANGLES, 0, 3* nbTriangles);
}
function init()
{
[app.can, app.gl] = getContextGL('can');
if (app.can == null || app.gl == null)
{
alert("Can't init canvas or context");
return;
}
app.can.width = app.can.height * (app.can.clientWidth / app.can.clientHeight);
var rect = app.can.getBoundingClientRect();
app.scaleX = app.can.width / rect.width;
app.scaleY = app.can.height / rect.height;
initGL();
initScene();
render();
}
div
{
}
#main-div
{
display:inline-block;
}
#viewport, #manager
{
float: left;
margin: auto;
}
.color
{
width:100px;
height:50px;
}
.blue{
background:#0f0;
}
#viewport
{
width: 600px;
height:700px;
}
#can
{
width: 600px;
height: 500px;
border:1px solid orange;
}
#manager
{
width: 200px;
height:300px;
padding: 0 0 0 5px;
}
#obj-list
{
width: 200px;
}
<!DOCTYPE html>
<html>
<head>
<title>Colored Quad</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="colored_quad.js"></script>
<script id="vs" type="x-shader/x-vertex">
precision mediump float;
attribute vec2 pos;
void main()
{
vec4 pt = vec4(pos, 0.0, 1.0);
gl_Position = pt;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
void main()
{
gl_FragColor = vec4(1,0,0,1);
}
</script>
</head>
<body onload="init();">
<div id="main-div">
<div id="viewport">
<canvas id="can" >Your browser doesn't seem to support canvas!</canvas>
</div>
</div>
</body>
</html>
Upvotes: 1
Views: 698
Reputation:
When I run your code I get an error "positions is undefined"
Maybe you should try to fix those errors before posting your question? If you're just learning JavaScript maybe these lessons would help
In any case, this code
// Creer le buffer de geometrie (vertex)
//
/* Drawing one triangle:
var positions = [
// coordonnees normalisees.
0.0, 0.1, 0.1, -0.1,-0.1, -0.1
];*/
for (var i=0; i<nbTriangles;++i)
{
var orig = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6, Math.random * 1.6];
P0 = orig[0] * scale + Trans[0];
P1 = orig[1] * scale + Trans[1];
P2 = orig[2] * scale + Trans[2];
var positions= new Positions (P0,P1,P2)
TRIANGLES.push(newPositions);
}
has a lot of basic javascript issues.
Positions
is not defined (the first error when running it). Just looking at the code I can also see a reference to TRIANGLES
that is not defined, newPositions
that is not defined. Also I see P0
, P1
, and P2
I'm assuming were supposed to be points but they are referencing only a single value in orig
each instead of 2 values (x and y). And P2
is referencing Trans[2]
which doesn't exist.
Here is one fix
var positions = [];
for (var i = 0; i < nbTriangles; ++i) {
var orig = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6, Math.random() * 1.6];
var P0 = [
orig[0] * scale + Trans[0],
orig[1] * scale + Trans[1],
];
var P1 = [
orig[2] * scale + Trans[0],
orig[3] * scale + Trans[1],
];
var P2 = [
orig[4] * scale + Trans[0],
orig[5] * scale + Trans[1],
];
positions.push(...P0, ...P1, ...P2);
}
Another fix would be to loop over the points in orig
for (var i = 0; i < nbTriangles; ++i) {
var orig = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6, Math.random() * 1.6];
for (var j = 0; j < orig.length; j += 2) {
positions.push(
orig[j ] * scale + Trans[0],
orig[j + 1] * scale + Trans[1],
);
}
}
another would be to write functions to scale and add vectors
const addV = (v1, v2) => v1.map((v1Elem, i) => v1Elem + v2[i]);
const scaleV = (v, scale) => v.map((elem) => elem * scale);
for (var i = 0; i < nbTriangles; ++i) {
var orig = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6, Math.random() * 1.6];
for (var j = 0; j < orig.length; j += 2) {
// pull out 2 values from orig
let p = orig.slice(j, j + 2);
p = scaleV(p, scale);
p = addV(p, Trans);
positions.push(...p);
}
}
As for adding a different color to each triangle I'd suggest you go read some other articles on WebGL
// Application info.
var app = app || {};
var nbTriangles = 20;
function getContextGL(canvasElement) {
var can = document.getElementById(canvasElement);
if (can == null) {
return [null, null];
}
var gl = can.getContext("webgl");
return [can, gl];
}
function createShaderFromElement(gl, id) {
// Grab the script element.
var scriptElt = document.getElementById(id);
if (!scriptElt) {
return null;
}
// Retrieve the source.
var scriptSource = scriptElt.textContent;
// Identify shader type based on element type.
var shaderObj;
if (scriptElt.type == "x-shader/x-fragment") {
shaderObj = gl.createShader(gl.FRAGMENT_SHADER);
} else if (scriptElt.type == "x-shader/x-vertex") {
shaderObj = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
// Compile and check status.
gl.shaderSource(shaderObj, scriptSource);
gl.compileShader(shaderObj);
var ok = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
if (!ok) {
var msgError = gl.getShaderInfoLog(shaderObj);
alert(msgError);
gl.deleteShader(shader);
return null;
}
return shaderObj;
}
function buildProgram(gl, vertexShader, fragmentShader) {
if (!vertexShader || !fragmentShader) {
return null;
}
var progObject = gl.createProgram();
if (!progObject) {
alert("Can't create program object.");
return;
}
gl.attachShader(progObject, vertexShader);
gl.attachShader(progObject, fragmentShader);
gl.linkProgram(progObject);
var ok = gl.getProgramParameter(progObject, gl.LINK_STATUS);
if (!ok) {
var msgError = gl.getProgramInfoLog(progObject);
alert(msgError);
gl.deleteProgram(progObject);
return null;
}
return progObject;
}
function initGL() {
app.gl.viewport(0, 0, app.can.width, app.can.height);
app.gl.clearColor(0., 0., 0., 1.0);
app.gl.clear(app.gl.COLOR_BUFFER_BIT);
var vs = createShaderFromElement(app.gl, "vs");
var fs = createShaderFromElement(app.gl, "fs");
app.progObject = buildProgram(app.gl, vs, fs);
app.gl.useProgram(app.progObject);
}
function initScene() {
var gl = app.gl;
// Creer le buffer de geometrie (vertex)
//
var positions = [];
for (var i = 0; i < nbTriangles; ++i) {
var orig = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
var scale = Math.random() * 0.2;
var Trans = [Math.random() * 1.6, Math.random() * 1.6];
var P0 = [
orig[0] * scale + Trans[0],
orig[1] * scale + Trans[1],
];
var P1 = [
orig[2] * scale + Trans[0],
orig[3] * scale + Trans[1],
];
var P2 = [
orig[4] * scale + Trans[0],
orig[5] * scale + Trans[1],
];
positions.push(...P0, ...P1, ...P2);
}
// Creer un nouveau buffer vide.
var posBuffer = gl.createBuffer();
// Ref sur l'attribut "pos" dans le vertex shader.
var posLocation = gl.getAttribLocation(app.progObject, "pos");
// Activer le buffer. Toute operation sur buffer
// sera appliquer a posBuffer (il est actif!).
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
gl.enableVertexAttribArray(posLocation);
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false /*no normalization*/ , 0 /*stride*/ , 0 /*offset*/ );
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
}
function render() {
var gl = app.gl;
gl.clear(gl.COLOR_BUFFER_BIT)
// Dessiner le buffer.
gl.drawArrays(gl.TRIANGLES, 0, 3 * nbTriangles);
}
function init() {
[app.can, app.gl] = getContextGL('can');
if (app.can == null || app.gl == null) {
alert("Can't init canvas or context");
return;
}
app.can.width = app.can.height * (app.can.clientWidth / app.can.clientHeight);
var rect = app.can.getBoundingClientRect();
app.scaleX = app.can.width / rect.width;
app.scaleY = app.can.height / rect.height;
initGL();
initScene();
render();
}
init();
#main-div {
display: inline-block;
}
#viewport,
#manager {
float: left;
margin: auto;
}
.color {
width: 100px;
height: 50px;
}
.blue {
background: #0f0;
}
#viewport {
width: 600px;
height: 700px;
}
#can {
width: 600px;
height: 500px;
border: 1px solid orange;
}
#manager {
width: 200px;
height: 300px;
padding: 0 0 0 5px;
}
#obj-list {
width: 200px;
}
<div id="main-div">
<div id="viewport">
<canvas id="can" >Your browser doesn't seem to support canvas!</canvas>
</div>
</div>
<script id="vs" type="x-shader/x-vertex">
precision mediump float;
attribute vec2 pos;
void main()
{
vec4 pt = vec4(pos, 0.0, 1.0);
gl_Position = pt;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
void main()
{
gl_FragColor = vec4(1,0,0,1);
}
</script>
Upvotes: 1