Com o código abaixo você pode desenhar cubo,triângulo,quadrado e pirâmides…
Porém a cada desenho ao se distanciar do centro do canvas o desenho geometrico diminui,
E eu quero saber porque isso acontece,
E como resolver este problema.
Pois o meu desenho no OpenGL2.0 não distorce a imagem geométrica, porém o meu código WebGL distorce, então se alguém poder me ajudar…me ajude por favor eu não sei o que fazer pra resolver isso.
<html>
<head>
<meta charset="utf-8"/>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uMMatrix;
uniform mat4 uVMatrix;
uniform mat4 uPMatrix;
varying vec4 vColor;
void main(void)
{
gl_Position = uPMatrix * uVMatrix * uMMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
void main(void)
{
gl_FragColor=vColor;
}
</script>
<!--Funções-->
<script type="text/javascript" src="glMatrix-0.9.5.min.js"></script>
<script type="text/javascript" src="jquery-2.1.0.min.js"></script>
<script type="text/javascript" src="webgl-utils.js"></script>
<script type="text/javascript">
var gl;
var shaderProgram;
var triangleVertexPositionBuffer;
var squareVertexPositionBuffer;
var triangleVertexColorBuffer;
var squareVertexColorBuffer;
var piramideVertexPositionBuffer;
var piramideVertexColorBuffer;
var cuboVertexPositionBuffer;
var cuboVertexColorBuffer;
var mMatrix = mat4.create();
var mMatrixPilha = [];
var pMatrix = mat4.create();
var vMatrix = mat4.create();
var rTri = 0;
var rQuad = 0;
var rPiramide = 0;
var rCubo = 0;
var ultimo = 0;
// Iniciar o ambiente quando a página for carregada
$(function()
{
iniciaWebGL();
});
// Iniciar o ambiente
function iniciaWebGL()
{
var canvas = $('#licao01-canvas')[0];
iniciarGL(canvas); // Definir como um canvas 3D
iniciarShaders(); // Obter e processar os Shaders
iniciarAmbiente(); // Definir background e cor do objeto
tick();
}
function tick()
{
requestAnimFrame(tick);
desenharCena();
animar();
}
function iniciarGL(canvas)
{
try
{
gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
}
catch(e)
{
if(!gl)
{
alert("Não pode inicializar WebGL, desculpe");
}
}
}
function iniciarShaders()
{
var vertexShader = getShader(gl, "#shader-vs");
var fragmentShader = getShader(gl, "#shader-fs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
{
alert("Não pode inicializar shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
shaderProgram.vertexTextureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.vertexTextureCoordAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.vMatrixUniform = gl.getUniformLocation(shaderProgram, "uVMatrix");
shaderProgram.mMatrixUniform = gl.getUniformLocation(shaderProgram, "uMMatrix");
}
function getShader(gl, id)
{
var shaderScript = $(id)[0];
if(!shaderScript)
{
return null;
}
var str = "";
var k = shaderScript.firstChild;
while(k)
{
if(k.nodeType == 3)
str += k.textContent;
k = k.nextSibling;
}
var shader;
if(shaderScript.type == "x-shader/x-fragment")
{
shader = gl.createShader(gl.FRAGMENT_SHADER);
}
else if(shaderScript.type == "x-shader/x-vertex")
{
shader = gl.createShader(gl.VERTEX_SHADER);
}
else
{
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
{
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
function iniciarAmbiente()
{
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
}
function desenharCena()
{
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45,gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
mat4.identity(mMatrix);
mat4.identity(vMatrix);
drawQuad(0.0,0,-24,1,1,1,60,0,0,1,0,1,0);//parede atraz
drawQuad(4,0,-24,1,1,1,60,0,0,1,1,0,0);//parede atraz
}
function drawPiramede(tx,ty,tz,sx,sy,sz,rPiramideX,rPiramideY,rPiramideZ,A,R,G,B){
piramideVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, piramideVertexPositionBuffer);
var vertices = [
// Frente
0.0, 1.0, 0.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
// Direita
0.0, 1.0, 0.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
// Trás
0.0, 1.0, 0.0,
1.0, -1.0, -1.0,
-1.0, -1.0, -1.0,
// Esquerda
0.0, 1.0, 0.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
piramideVertexPositionBuffer.itemSize = 3;
piramideVertexPositionBuffer.numItems = 12;
piramideVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, piramideVertexColorBuffer);
var cores = [
// Frente
R,G,B,A,
R,G,B,A,
R,G,B,A,
// Direita
R,G,B,A,
R,G,B,A,
R,G,B,A,
// Trás
R,G,B,A,
R,G,B,A,
R,G,B,A,
// Esquerda
R,G,B,A,
R,G,B,A,
R,G,B,A
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cores), gl.STATIC_DRAW);
piramideVertexColorBuffer.itemSize = 4;
piramideVertexColorBuffer.numItems = 12;
// Desenhando Pirâmide
mat4.translate(mMatrix,[tx,ty,tz]);
mPushMatrix();
mat4.rotate(mMatrix, degToRad(rPiramideX),[1,0,0]);
mat4.rotate(mMatrix, degToRad(rPiramideY),[0,1,0]);
mat4.rotate(mMatrix, degToRad(rPiramideZ),[0,0,1]);
mat4.scale(mMatrix,[sx,sy,sz]);
gl.bindBuffer(gl.ARRAY_BUFFER, piramideVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, piramideVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, piramideVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, piramideVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES, 0, piramideVertexPositionBuffer.numItems);
mPopMatrix();
}
function drawCube(tx,ty,tz,sx,sy,sz,rPiramideX,rPiramideY,rPiramideZ,A,R,G,B){
cuboVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cuboVertexPositionBuffer);
vertices = [
// Front face
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// Back face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// Top face
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// Bottom face
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// Right face
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// Left face
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
cuboVertexPositionBuffer.itemSize = 3;
cuboVertexPositionBuffer.numItems = 4;
cuboVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cuboVertexColorBuffer);
cores = [
[R,G,B,A], // Frente
[R,G,B,A], // Trás
[R,G,B,A], // Topo
[R,G,B,A], // Base
[R,G,B,A], // Direita
[R,G,B,A] // Esquerda
];
var coresReplicadas = [];
for (var i in cores) {
var cor = cores[i];
for (var j=0; j < 4; j++) {
coresReplicadas = coresReplicadas.concat(cor);
}
}
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coresReplicadas), gl.STATIC_DRAW);
cuboVertexColorBuffer.itemSize = 4;
cuboVertexColorBuffer.numItems = 24;
cuboVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cuboVertexIndexBuffer);
var indices = [
0, 1, 2, 0, 2, 3, // Frente
4, 5, 6, 4, 6, 7, // Trás
8, 9, 10, 8, 10, 11, // Topo
12, 13, 14, 12, 14, 15, // Base
16, 17, 18, 16, 18, 19, // Direita
20, 21, 22, 20, 22, 23 // Esquerda
]
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
cuboVertexIndexBuffer.itemSize = 1;
cuboVertexIndexBuffer.numItems = 36;
// Desenhando o Quadrado
mat4.translate(mMatrix,[tx,ty,tz]);
mPushMatrix();
mat4.rotate(mMatrix, degToRad(rPiramideX),[1,0,0]);
mat4.rotate(mMatrix, degToRad(rPiramideY),[0,1,0]);
mat4.rotate(mMatrix, degToRad(rPiramideZ),[0,0,1]);
mat4.scale(mMatrix,[sx,sy,sz]);
gl.bindBuffer(gl.ARRAY_BUFFER, cuboVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cuboVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, cuboVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, cuboVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cuboVertexIndexBuffer);
setMatrixUniforms();
gl.drawElements(gl.TRIANGLES, cuboVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT,0);
mPopMatrix();
}
function drawTriangle(tx,ty,tz,sx,sy,sz,rPiramideX,rPiramideY,rPiramideZ,A,R,G,B){
triangleVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
var vertices = [
0.0, 1.0, 0.0,
-1.0,-1.0, 0.0,
1.0,-1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
triangleVertexPositionBuffer.itemSize = 3;
triangleVertexPositionBuffer.numItems = 3;
triangleVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
var cores = [
R,G,B,A,
R,G,B,A,
R,G,B,A
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cores), gl.STATIC_DRAW);
triangleVertexColorBuffer.itemSize = 4;
triangleVertexColorBuffer.numItems = 3;
// Desenhando Triângulo
mat4.translate(mMatrix,[tx,ty,tz]);
mPushMatrix();
mat4.rotate(mMatrix, degToRad(rPiramideX),[1,0,0]);
mat4.rotate(mMatrix, degToRad(rPiramideY),[0,1,0]);
mat4.rotate(mMatrix, degToRad(rPiramideZ),[0,0,1]);
mat4.scale(mMatrix,[sx,sy,sz]);
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, triangleVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
mPopMatrix();
}
function drawQuad(tx,ty,tz,sx,sy,sz,rPiramideX,rPiramideY,rPiramideZ,A,R,G,B){
squareVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
vertices = [
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
1.0,-1.0, 0.0,
-1.0,-1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
squareVertexPositionBuffer.itemSize = 3;
squareVertexPositionBuffer.numItems = 4;
squareVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
cores = [];
for(var i =0; i < 4; i++)
{
cores = cores.concat([R,G,B,A]);
}
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cores), gl.STATIC_DRAW);
squareVertexColorBuffer.itemSize = 4;
squareVertexColorBuffer.numItems = 4;
// Desenhando o Quadrado
mat4.translate(mMatrix,[tx,ty,tz]);
mPushMatrix();
mat4.rotate(mMatrix, degToRad(rPiramideX),[1,0,0]);
mat4.rotate(mMatrix, degToRad(rPiramideY),[0,1,0]);
mat4.rotate(mMatrix, degToRad(rPiramideZ),[0,0,1]);
mat4.scale(mMatrix,[sx,sy,sz]);
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, squareVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
mPopMatrix();
}
function setMatrixUniforms()
{
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.vMatrixUniform, false, vMatrix);
gl.uniformMatrix4fv(shaderProgram.mMatrixUniform, false, mMatrix);
}
// o 'var ultimo = 0' está no topo (todos as vars globais estão juntas)
function animar()
{
var agora = new Date().getTime();
if(ultimo != 0)
{
var diferenca = agora-ultimo;
rTri += ((90*diferenca)/1000.0) % 360.0;
rQuad += ((75*diferenca)/1000.0) % 360.0;
rPiramide += ((90*diferenca)/1000.0) % 360.0;
rCubo += ((75*diferenca)/1000.0) % 360.0;
}
ultimo = agora;
}
function mPushMatrix()
{
var copy = mat4.create();
mat4.set(mMatrix, copy);
mMatrixPilha.push(copy);
}
function mPopMatrix()
{
if(mMatrixPilha.length == 0)
{
throw "inválido popMatrix!";
}
mMatrix = mMatrixPilha.pop();
}
function degToRad(graus)
{
return graus * Math.PI / 180;
}
</script>
<!--Aparência da página (canvas, background...)-->
<style>
canvas
{
border:none;
width:500px;
height:500px;
}
</style>
</head>
<body>
<canvas id="licao01-canvas" width="500" height="500"></canvas>
</body>
</html>