在 Javascript/WebGL 中的 for 循环中创建随机形状对象
Creating random shape objects in a for loop in Javascript / WebGL
我目前正在尝试弄清楚如何创建多个随机三角形对象(大小不同)并同时将它们全部平移到屏幕右侧。当它们离开屏幕时,我打算创建新对象来替换它们。
我不确定如何正确渲染这些,也不确定我缺少什么来解决这个问题。目前看来我正在绘制某种随机多边形,它正在屏幕上平移。尽管创建了对象,但它肯定不会生成多个对象。
HTML 相关代码:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Rotating Square</title>
<script type="x-shader/x-vertex" id="vertex-shader">
attribute vec4 myPosition;
uniform float theta;
uniform vec2 mouseCoordinates;
void main() {
gl_PointSize=10.0;
gl_Position.x=myPosition.x *cos(theta)+myPosition.y *sin(theta)+ mouseCoordinates.x;
gl_Position.y=-myPosition.x *sin(theta)+myPosition.y *cos(theta)+mouseCoordinates.y;
gl_Position.z=0.0;
gl_Position.w=1.0;
}
</script>
<script type ="x-shader/x-fragment" id="fragment-shader">
void main(){
gl_FragColor =vec4(0.0,1.0,0.0,1.0);
}
</script>
<script type="text/javascript" src="Common/webgl-utils.js"></script>
<script type="text/javascript" src="Common/initShaders.js"></script>
<script type="text/javascript" src="Common/MV.js"></script>
<script type="text/javascript" src="project1.js"></script>
</head>
**相关 JS/WEBGL 代码:**
var canvas;
var gl;
var myShaderProgram;
var theta;
var stopStartFlag;
var mouseCoordinatesUniform;
var clipX;
var clipY;
var stepX;
var stepY;
var speed;
var triangleAmount = 25;
var triangles = [];
function init() {
theta =.0;
speed=0.0025;
stopStartFlag=0;
clipX =.0;
clipY =.0;
stepX=1.0;
stepY=0.0;
randomX_X = 0.0;
randomX_Y = 0.0;
randomY_X = 0.0;
randomY_Y = 0.0;
randomZ_X = 0.0;
randomZ_Y = 0.0;
randomTheta = 0.0;
randomSpeed = 0.0;
for ( var i = 0; i < triangleAmount; i++ ){
randomX_X = (Math.random() * 1) - 1;
randomX_Y = (Math.random() * 1);
randomY_X = (Math.random() * 1) - 1; // get it off the screen x-wise
randomY_Y = (Math.random() * 1);
randomZ_X = (Math.random() * 1) - 1;
randomZ_Y = (Math.random() * 1);
var triangle = new Triangle(vec2(randomX_X,randomX_Y),
vec2(randomY_X,randomY_Y),
vec2(randomZ_X,randomZ_Y),
randomTheta,
randomSpeed)
triangles.push(triangle);
}
canvas = document.getElementById("gl-canvas");
gl= WebGLUtils.setupWebGL(canvas);
if(!gl){ alert("WebGL is not working");}
gl.viewport(0,0,512,512);
gl.clearColor(0.0,0.0,1.0,1.0);
myShaderProgram=initShaders(gl,"vertex-shader","fragment-shader");
gl.useProgram(myShaderProgram);
mouseCoordinatesUniform = gl.getUniformLocation( myShaderProgram,"mouseCoordinates");
gl.uniform2f( mouseCoordinatesUniform,.0,.0);
setupSquare();
render();
}
// vec2 points for args
function Triangle(x, y, z, thetaInc, spd) {
this.onScreen = true;
this.x = x;
this.y = y;
this.z = z;
this.spawnY = y[1]; // y value of the y vertex
// decides where on the y axis the triangle appears offscreen
this.theta = 0;
this.rotationSpeed = thetaInc;
this.speed = spd;
this.counter = 0;
}
function setupSquare() {
var point0 = vec2(-.2,-.2);
var point1 = vec2(-.2,.2);
var point2 = vec2(.2,.2);
var point3 = vec2(.2,-.2);
var point4 = vec2(0,.75)
var pointa = vec2(-0.5, .4);
var pointb = vec2( -0.25, .4);
var pointc = vec2(-0.35, .8);
var arrayOfpointsForSquare=[point0,point1,point2,point3,point4];
var arrayOfPointsForTriangle=[pointa,pointb,pointc];
var bufferId =gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,bufferId);
gl.bufferData(gl.ARRAY_BUFFER,flatten(arrayOfpointsForSquare),gl.STATIC_DRAW );
var myPosition = gl.getAttribLocation(myShaderProgram,"myPosition");
gl.vertexAttribPointer(myPosition,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(myPosition);
}
function drawTriangles(){
arrayOfPointsForTriangle = [];
var arrayOfPointsForTriangle=[];
for (var i = 0; i < triangleAmount; i++){
arrayOfPointsForTriangle.push(triangles[i].x, triangles[i].y, triangles[i].z);
console.log(triangles[i].x);
}
var bufferId =gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,bufferId);
gl.bufferData(gl.ARRAY_BUFFER,flatten(arrayOfPointsForTriangle),gl.STATIC_DRAW );
var myPosition = gl.getAttribLocation(myShaderProgram,"myPosition");
gl.vertexAttribPointer(myPosition,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(myPosition);
}
function render() {
var thetaUniform = gl.getUniformLocation(myShaderProgram,"theta" );
gl.uniform1f(thetaUniform,theta);
gl.clear(gl.COLOR_BUFFER_BIT );
gl.drawArrays(gl.TRIANGLE_FAN,0,5);
drawTriangles();
gl.drawArrays(gl.TRIANGLE_FAN,0,3);
theta+=.01*stopStartFlag;
clipX=clipX+stepX*speed;
clipY=clipY+stepY*speed;
gl.uniform2f(mouseCoordinatesUniform,clipX,clipY);
requestAnimFrame(render);
}
可以在 http://www.aceverything.com/cskelly/project1/project1.html
查看当前状态的示例
You are using this for drawing triangles:
gl.drawArrays(gl.TRIANGLE_FAN,0,3);
这意味着 "draw fan using 3 vertices"。用gl.drawArrays(gl.TRIANGLES,0,3);
比较合适,不过风扇应该也可以。
顺便说一句,这是三角扇:
但是 在我在您附加的网站上找到的代码中,我看到了 gl.drawArrays( gl.TRIANGLE_FAN, 0, 6 );
和 gl.drawArrays( gl.TRIANGLE_FAN, 0, 4 );
。这导致多边形 ofc。
Vertex attribute pointer size does not match prepared array and does not match vertex shader
另一个问题在这里:
arrayOfPointsForTriangle.push(triangles[i].x, triangles[i].y, triangles[i].z);
...
gl.vertexAttribPointer(myPosition,2,gl.FLOAT,false,0,0);
...可能在顶点着色器中:
<script type="x-shader/x-vertex" id="vertex-shader">
attribute vec4 myPosition;
我解释一下,首先你说,你的三角形的每个顶点都有x,y z坐标,但是你的demo好像是二维的,所以你应该只有x,y?
然后这里gl.vertexAttribPointer(myPosition, 2 ...
这意味着您的 gl.drawArrays
将为每个顶点使用 2 个项目。但是带有数据的数组包含 3 个组件,所以这是一团糟。
最后一件事,在顶点着色器中你定义了attribute vec4 myPosition
,但是因为你使用了gl.vertexAttribPointer(myPosition, 2 ...
,所以它应该是attribute vec2 myPosition
。但是你没有在着色器中使用 z 和 w 属性,所以至少它看起来是 "working"。
我目前正在尝试弄清楚如何创建多个随机三角形对象(大小不同)并同时将它们全部平移到屏幕右侧。当它们离开屏幕时,我打算创建新对象来替换它们。
我不确定如何正确渲染这些,也不确定我缺少什么来解决这个问题。目前看来我正在绘制某种随机多边形,它正在屏幕上平移。尽管创建了对象,但它肯定不会生成多个对象。
HTML 相关代码:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Rotating Square</title>
<script type="x-shader/x-vertex" id="vertex-shader">
attribute vec4 myPosition;
uniform float theta;
uniform vec2 mouseCoordinates;
void main() {
gl_PointSize=10.0;
gl_Position.x=myPosition.x *cos(theta)+myPosition.y *sin(theta)+ mouseCoordinates.x;
gl_Position.y=-myPosition.x *sin(theta)+myPosition.y *cos(theta)+mouseCoordinates.y;
gl_Position.z=0.0;
gl_Position.w=1.0;
}
</script>
<script type ="x-shader/x-fragment" id="fragment-shader">
void main(){
gl_FragColor =vec4(0.0,1.0,0.0,1.0);
}
</script>
<script type="text/javascript" src="Common/webgl-utils.js"></script>
<script type="text/javascript" src="Common/initShaders.js"></script>
<script type="text/javascript" src="Common/MV.js"></script>
<script type="text/javascript" src="project1.js"></script>
</head>
**相关 JS/WEBGL 代码:**
var canvas;
var gl;
var myShaderProgram;
var theta;
var stopStartFlag;
var mouseCoordinatesUniform;
var clipX;
var clipY;
var stepX;
var stepY;
var speed;
var triangleAmount = 25;
var triangles = [];
function init() {
theta =.0;
speed=0.0025;
stopStartFlag=0;
clipX =.0;
clipY =.0;
stepX=1.0;
stepY=0.0;
randomX_X = 0.0;
randomX_Y = 0.0;
randomY_X = 0.0;
randomY_Y = 0.0;
randomZ_X = 0.0;
randomZ_Y = 0.0;
randomTheta = 0.0;
randomSpeed = 0.0;
for ( var i = 0; i < triangleAmount; i++ ){
randomX_X = (Math.random() * 1) - 1;
randomX_Y = (Math.random() * 1);
randomY_X = (Math.random() * 1) - 1; // get it off the screen x-wise
randomY_Y = (Math.random() * 1);
randomZ_X = (Math.random() * 1) - 1;
randomZ_Y = (Math.random() * 1);
var triangle = new Triangle(vec2(randomX_X,randomX_Y),
vec2(randomY_X,randomY_Y),
vec2(randomZ_X,randomZ_Y),
randomTheta,
randomSpeed)
triangles.push(triangle);
}
canvas = document.getElementById("gl-canvas");
gl= WebGLUtils.setupWebGL(canvas);
if(!gl){ alert("WebGL is not working");}
gl.viewport(0,0,512,512);
gl.clearColor(0.0,0.0,1.0,1.0);
myShaderProgram=initShaders(gl,"vertex-shader","fragment-shader");
gl.useProgram(myShaderProgram);
mouseCoordinatesUniform = gl.getUniformLocation( myShaderProgram,"mouseCoordinates");
gl.uniform2f( mouseCoordinatesUniform,.0,.0);
setupSquare();
render();
}
// vec2 points for args
function Triangle(x, y, z, thetaInc, spd) {
this.onScreen = true;
this.x = x;
this.y = y;
this.z = z;
this.spawnY = y[1]; // y value of the y vertex
// decides where on the y axis the triangle appears offscreen
this.theta = 0;
this.rotationSpeed = thetaInc;
this.speed = spd;
this.counter = 0;
}
function setupSquare() {
var point0 = vec2(-.2,-.2);
var point1 = vec2(-.2,.2);
var point2 = vec2(.2,.2);
var point3 = vec2(.2,-.2);
var point4 = vec2(0,.75)
var pointa = vec2(-0.5, .4);
var pointb = vec2( -0.25, .4);
var pointc = vec2(-0.35, .8);
var arrayOfpointsForSquare=[point0,point1,point2,point3,point4];
var arrayOfPointsForTriangle=[pointa,pointb,pointc];
var bufferId =gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,bufferId);
gl.bufferData(gl.ARRAY_BUFFER,flatten(arrayOfpointsForSquare),gl.STATIC_DRAW );
var myPosition = gl.getAttribLocation(myShaderProgram,"myPosition");
gl.vertexAttribPointer(myPosition,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(myPosition);
}
function drawTriangles(){
arrayOfPointsForTriangle = [];
var arrayOfPointsForTriangle=[];
for (var i = 0; i < triangleAmount; i++){
arrayOfPointsForTriangle.push(triangles[i].x, triangles[i].y, triangles[i].z);
console.log(triangles[i].x);
}
var bufferId =gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,bufferId);
gl.bufferData(gl.ARRAY_BUFFER,flatten(arrayOfPointsForTriangle),gl.STATIC_DRAW );
var myPosition = gl.getAttribLocation(myShaderProgram,"myPosition");
gl.vertexAttribPointer(myPosition,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(myPosition);
}
function render() {
var thetaUniform = gl.getUniformLocation(myShaderProgram,"theta" );
gl.uniform1f(thetaUniform,theta);
gl.clear(gl.COLOR_BUFFER_BIT );
gl.drawArrays(gl.TRIANGLE_FAN,0,5);
drawTriangles();
gl.drawArrays(gl.TRIANGLE_FAN,0,3);
theta+=.01*stopStartFlag;
clipX=clipX+stepX*speed;
clipY=clipY+stepY*speed;
gl.uniform2f(mouseCoordinatesUniform,clipX,clipY);
requestAnimFrame(render);
}
可以在 http://www.aceverything.com/cskelly/project1/project1.html
查看当前状态的示例You are using this for drawing triangles:
gl.drawArrays(gl.TRIANGLE_FAN,0,3);
这意味着 "draw fan using 3 vertices"。用gl.drawArrays(gl.TRIANGLES,0,3);
比较合适,不过风扇应该也可以。
顺便说一句,这是三角扇:
但是 在我在您附加的网站上找到的代码中,我看到了 gl.drawArrays( gl.TRIANGLE_FAN, 0, 6 );
和 gl.drawArrays( gl.TRIANGLE_FAN, 0, 4 );
。这导致多边形 ofc。
Vertex attribute pointer size does not match prepared array and does not match vertex shader
另一个问题在这里:
arrayOfPointsForTriangle.push(triangles[i].x, triangles[i].y, triangles[i].z);
...
gl.vertexAttribPointer(myPosition,2,gl.FLOAT,false,0,0);
...可能在顶点着色器中:
<script type="x-shader/x-vertex" id="vertex-shader">
attribute vec4 myPosition;
我解释一下,首先你说,你的三角形的每个顶点都有x,y z坐标,但是你的demo好像是二维的,所以你应该只有x,y?
然后这里gl.vertexAttribPointer(myPosition, 2 ...
这意味着您的 gl.drawArrays
将为每个顶点使用 2 个项目。但是带有数据的数组包含 3 个组件,所以这是一团糟。
最后一件事,在顶点着色器中你定义了attribute vec4 myPosition
,但是因为你使用了gl.vertexAttribPointer(myPosition, 2 ...
,所以它应该是attribute vec2 myPosition
。但是你没有在着色器中使用 z 和 w 属性,所以至少它看起来是 "working"。