我是webgl的新手,正在尝试绘制圆形,但是不知何故,它看起来像椭圆形但不是我想要的形状。我在哪里犯了错误(或代码中的其他问题)?
index.html文件仅包含width = 900 height = 600的canvas元素。所以我没有在这里添加它。
var vertexShader=['precision mediump float;','attribute vec2 vPosition;','attribute vec3 vColor;','varying vec3 fragColor;','void main()','{','fragColor=vColor;','gl_Position=vec4(vPosition,0.0,1.0);','}'].join('\n');
var fragmentShader=['precision mediump float;','varying vec3 fragColor;','void main(){','gl_FragColor=vec4(fragColor,1.0);','}'].join('\n');
function init(){
console.log('running');
var canvas=document.getElementById('canvas');
var gl=canvas.getContext('webgl');
//CLEAR
gl.clearColor(1.0,0.0,0.0,1.0);//R,G,B,Alfa
gl.clear(gl.COLOR_BUFFER_BIT);//gl.DEPTH_BUFFER_BIT
//SHADERS
var vertShader=gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader,vertexShader);
var fragShader=gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader,fragmentShader);
gl.compileShader(vertShader);
gl.compileShader(fragShader);
//PROGRAM
var program=gl.createProgram();
gl.attachShader(program,vertShader);
gl.attachShader(program,fragShader);
gl.linkProgram(program);
gl.useProgram(program);
var numberofsides=360;
var triangleVertices=yuvarlakCiz(-0.19,0,0,0.35,numberofsides);
var triangleVertices2=yuvarlakCiz(-0.1,0,0,0.29,numberofsides);
triangleVertices=renkAyarla(1.0,1.0,1.0,triangleVertices);
triangleVertices2=renkAyarla(1.0,0.0,0.0,triangleVertices2);
console.log(triangleVertices);
//BUFFER
var triangleBuffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,triangleBuffer);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(triangleVertices),gl.STATIC_DRAW);
//LOCATION ALMA
var attloc=gl.getAttribLocation(program,'vPosition');
var attcolor=gl.getAttribLocation(program,'vColor');
//ATTRIBUTE AYARLAMA
gl.vertexAttribPointer(
attloc,
2,
gl.FLOAT,
gl.FALSE,
5*Float32Array.BYTES_PER_ELEMENT,
0
);
gl.vertexAttribPointer(
attcolor,
3,
gl.FLOAT,
gl.FALSE,
5*Float32Array.BYTES_PER_ELEMENT,
2*Float32Array.BYTES_PER_ELEMENT
);
//İLK CIRCLE ÇİZME
gl.enableVertexAttribArray(attloc);
gl.enableVertexAttribArray(attcolor);
gl.drawArrays(gl.TRIANGLE_FAN, 0,numberofsides+2);
//2.CIRCLE BUFFER
var circle2=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,circle2);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(triangleVertices2),gl.STATIC_DRAW);
var attloc1=gl.getAttribLocation(program,'vPosition');
var attcolor1=gl.getAttribLocation(program,'vColor');
gl.vertexAttribPointer(
attloc1,
2,
gl.FLOAT,
gl.FALSE,
5*Float32Array.BYTES_PER_ELEMENT,
0
);
gl.vertexAttribPointer(
attcolor1,
3,
gl.FLOAT,
gl.FALSE,
5*Float32Array.BYTES_PER_ELEMENT,
2*Float32Array.BYTES_PER_ELEMENT
);
gl.enableVertexAttribArray(attloc1);
gl.enableVertexAttribArray(attcolor1);
//gl.drawArrays(gl.TRIANGLE_FAN, 0,numberofsides+2);
}
function yuvarlakCiz(x,y,z,radius,numberofsides){
var numberofVertices=numberofsides+2;
var doublepi=2*Math.PI;
var verticesX=[];
var verticesY=[];
var verticesZ=[];
verticesX[0]=x;
verticesY[0]=y;
verticesZ[0]=z;
for (var i = 1 ;i<numberofVertices; i++) {
verticesX[i]=x+(radius * Math.cos(i*doublepi/numberofsides));
verticesY[i]=y+(radius * Math.sin(i*doublepi/numberofsides));
verticesZ[i]=z;
}
var mergeVertices=[];
for (var i = 0 ;i<numberofVertices; i++) {
mergeVertices[i*5]=verticesX[i];
mergeVertices[i*5+1]=verticesY[i];
mergeVertices[i*5+2]=0.0;
mergeVertices[i*5+3]=0.0;
mergeVertices[i*5+4]=0.0;
// mergeVertices[i*3+2]=verticesZ[i];
}
return mergeVertices;
}
function renkAyarla(r,g,b,dizi){ //SETTING COLORS
for (var i =0; i <dizi.length/5; i++) {
dizi[i*5+2]=r;
dizi[i*5+3]=g;
dizi[i*5+4]=b;
}
return dizi;
}
答案 0 :(得分:2)
缺少的是WebGL始终在画布上采用从-1到+1的剪辑空间坐标,而与尺寸无关,因此,如果画布不是正方形,则需要寻找一些数学运算来补偿。
由于只是数学,所以有1000种更改代码的方法。
一种方法是将您的位置乘以画布的纵横比。
您当前有这个
gl_Position=vec4(vPosition,0.0,1.0);
您可以将其更改为此
gl_Position=vec4(vPosition * vec2(600.0/900.0, 1),0.0,1.0);
您可以对其进行更改以使其按比例通过
uniform vec2 scale;
...
gl_Position=vec4(vPosition * scale,0.0,1.0);
然后通过查找其位置并将其设置,将scale
设置为600.0 / 900.0, 1
一种更常见的方法是使用一个或多个矩阵
uniform mat4 matrix;
...
gl_Position = matrix * vec4(vPosition, 0.0, 1.0);
在这种情况下,您可以应用与上述相同的比例,但是您也可以做大量其他事情。
This series of articles涵盖了所有这些解决方案以及更多
答案 1 :(得分:1)
缺少的是补偿视口不是正方形的事实。如果要通过以下操作将其变成正方形:
gl.viewport(0, 0, 600, 600);
您会得到正确的圆圈。
要支持任何视口大小,必须使用诸如投影变换之类的方法。您可以查找orthographic projection。基本上,您将所有座标乘以这样的东西:
( 600 / gl.drawingBufferWidth, 600 / gl.drawingBufferHeight )