Рисование круга в webgl выглядит как эллипс - PullRequest
0 голосов
/ 26 марта 2019

Я новичок в webgl и пытаюсь нарисовать круг, но как-то это похоже на эллипс, а не на ту форму, которую я хочу. Где я допустил ошибку (или другую проблему в коде)?

index.html файлы просто содержат элемент canvas с шириной = 900, высотой = 600. Поэтому я не добавил его сюда.

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

Пример круга

Ответы [ 2 ]

2 голосов
/ 26 марта 2019

Чего не хватает, так это того, что 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);

В этом случае вы можете применять ту же шкалу, что и выше, но вы также можете делать множество других вещей.

Эта серия статей охватывает все эти решения и многое другое

1 голос
/ 26 марта 2019

Чего не хватает, так это того, что ваш видовой экран не квадратный.Если бы вы сделали квадрат таким образом:

gl.viewport(0, 0, 600, 600);

, вы бы получили правильные круги.

Чтобы поддерживать любой размер области просмотра, вы должны использовать что-то вроде проекциипреобразование.Вы можете посмотреть ортографическая проекция .Вы бы просто умножили все свои координаты на что-то вроде этого:

 ( 600 / gl.drawingBufferWidth, 600 / gl.drawingBufferHeight )
...