Created
February 28, 2013 20:39
-
-
Save tiagosr/5059922 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Exemplo 02: Primitivos básicos</title> | |
<script src="jquery-1.9.1.min.js"></script> | |
<script src="gl-matrix-min.js"></script> | |
<script type="text/x-glsl-vertex" id="simple-vertex"> | |
uniform mat4 projectionMtx, modelViewMtx; | |
attribute vec3 inPosition; | |
attribute vec4 inColor; | |
varying vec4 fragColor; | |
void main() { | |
// gl_Position é uma das saídas padrão de vertex shaders | |
gl_Position = projectionMtx * modelViewMtx * vec4(inPosition, 1.0); | |
// fragColor é uma das informações que a gente vai passar | |
// do vertex shader para o fragment shader | |
fragColor = inColor; | |
} | |
</script> | |
<script type="text/x-glsl-fragment" id="simple-fragment"> | |
precision mediump float; | |
varying vec4 fragColor; // entrada a ser linkada com o vertex shader | |
void main() { | |
gl_FragColor = fragColor; // gl_FragColor é uma das saídas padrão do GLSL, | |
// armazena o valor diretamente no buffer de cor | |
//gl_FragDepth = gl_FragCoord.z; | |
// profundidade pode ser alterada pelo shader, | |
// mas não no WebGL/OpenGLES. | |
} | |
</script> | |
<script type="text/javascript"> | |
window.requestAnimFrame = (function(){ | |
return window.requestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.mozRequestAnimationFrame || | |
window.oRequestAnimationFrame || | |
window.msRequestAnimationFrame || | |
function( callback ){ | |
window.setTimeout(callback, 1000 / 60); | |
}; | |
})(); | |
// função pra pegar código de shader de uma tag <script id=""> | |
var getShaderFromID = function(id) { | |
var source = document.getElementById(id); | |
if (!source) { | |
return null; | |
} | |
var srcstr = ""; | |
var child = source.firstChild; | |
while (child) { | |
if (child.nodeType == 3) { // se for nó de texto | |
srcstr += child.textContent; | |
} | |
child = child.nextSibling; | |
} | |
var shader; | |
if (source.type == "text/x-glsl-fragment") { | |
shader = gl.createShader(gl.FRAGMENT_SHADER); | |
} else if (source.type == "text/x-glsl-vertex"){ | |
shader = gl.createShader(gl.VERTEX_SHADER); | |
} else { | |
// não existe shader de tesselation | |
// ou geometry pra GLES/WebGL ainda. | |
return null; | |
} | |
// anexa a string com o source ao shader | |
gl.shaderSource(shader, srcstr); | |
// compila o shader | |
gl.compileShader(shader); | |
// testa se foi compilado corretamente | |
if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { | |
alert(gl.getShaderInfoLog(shader)); | |
return null; | |
} | |
return shader; | |
} | |
// matriz de projeção | |
var projectionMtx = mat4.create(); | |
// matriz de objetos/mundo | |
var modelViewMtx = mat4.create(); | |
// buffers de atributos | |
var vertexbuffer; | |
var colorsbuffer; | |
// programa do shader | |
var shaderpgm; | |
var setupGL = function(canvas) { | |
// não dá pra inicializar contexto 2D e 3D no mesmo canvas | |
gl = null; | |
try { | |
gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); | |
} catch (e) {} | |
if (!gl) { | |
alert("bzzzt! no support for webgl here."); | |
} | |
} | |
var setup = function() { | |
canvas = document.getElementById("gl"); | |
setupGL(canvas); | |
// seta infos básicas para as viewports | |
gl.clearColor(0.0,0.0,0.0,1.0); | |
gl.enable(gl.DEPTH_TEST); | |
gl.depthFunc(gl.LEQUAL); | |
gl.clearDepth(1.0); | |
// callback de redimensionamento da viewport | |
var resizefn = function(){ | |
if ((canvas.width != canvas.clientWitdh) || (canvas.height != canvas.clientHeight)) { | |
canvas.width = canvas.clientWidth; | |
canvas.height = canvas.clientHeight; | |
} | |
gl.viewportWidth = canvas.clientWidth; | |
gl.viewportHeight = canvas.clientHeight; | |
} | |
resizefn(); | |
$(window).resize(resizefn); | |
// criando o programa dos shaders | |
shaderpgm = gl.createProgram(); | |
var simple_vtx_shader = getShaderFromID("simple-vertex"); | |
var simple_fgmt_shader = getShaderFromID("simple-fragment"); | |
// anexando os shaders criados | |
gl.attachShader(shaderpgm, simple_vtx_shader); | |
gl.attachShader(shaderpgm, simple_fgmt_shader); | |
// linkando os shaders no programa | |
gl.linkProgram(shaderpgm); | |
// testa se tudo foi nos trinks | |
if(!gl.getProgramParameter(shaderpgm, gl.LINK_STATUS)) { | |
alert("Could not link shaders"); | |
} | |
gl.useProgram(shaderpgm); | |
// seta algumas variáveis pra ajudar na hora de renderizar. | |
// como todo objeto normal em javascript, dá pra adicionar | |
// propriedades extras aos programas e shaders ... | |
shaderpgm.simpleVtxShader = simple_vtx_shader; | |
shaderpgm.simpleFragShader = simple_fgmt_shader; | |
// ... o que é bastante útil pra levar as localizações | |
// dos atributos e uniforms dos shaders | |
shaderpgm.inPositionLoc = gl.getAttribLocation(shaderpgm, "inPosition"); | |
gl.enableVertexAttribArray(shaderpgm.inPositionLoc); | |
shaderpgm.inColorLoc = gl.getAttribLocation(shaderpgm, "inColor"); | |
gl.enableVertexAttribArray(shaderpgm.inColorLoc); | |
shaderpgm.projectionMtxLoc = gl.getUniformLocation(shaderpgm, "projectionMtx"); | |
shaderpgm.modelViewMtxLoc = gl.getUniformLocation(shaderpgm, "modelViewMtx"); | |
// declarando os buffers de atributos | |
var vertices = [ // x, y, z | |
0.0, 0.8, 0.0, | |
0.8, -0.8, 0.0, | |
-0.8, -0.8, 0.0 | |
]; | |
var colors = [ // r, g, b, a | |
1.0, 0.0, 0.0, 1.0, | |
0.0, 1.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, 1.0 | |
]; | |
// gerando o identificador do buffer de vértices | |
vertexbuffer = gl.createBuffer(); | |
// anexando o identificador ao estado do opengl, | |
// para fazer modificações ao buffer | |
gl.bindBuffer(gl.ARRAY_BUFFER, vertexbuffer); | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); | |
// setando algumas propriedades extras pra ajudar na renderização | |
vertexbuffer.itemSize = 3; | |
vertexbuffer.numItems = 3; | |
// agora o mesmo com o buffer de cores | |
colorsbuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, colorsbuffer); | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); | |
colorsbuffer.itemSize = 4; | |
colorsbuffer.numItems = 2; | |
} | |
var render = function() { | |
// window.requestAnimationFrame é um callback dos navegadores mais recentes, | |
// praticamente o evento ENTER_FRAME do flash, mas vc tem que requisitar | |
// novamente o frame seguinte para ter animação contínua. | |
// requestAnimFrame é o esquema de compatibilidade entre os vários browsers, | |
// veja a linha 37. | |
window.requestAnimFrame(render, canvas); | |
// não faz mal setar a viewport várias vezes por frame. | |
// um sistema split-screen setaria a viewport tantas vezes | |
// quantas telas houverem. | |
gl.viewport(0.0, 0.0, gl.viewportWidth, gl.viewportHeight); | |
// glClear limpa a região da viewport nos buffers | |
gl.clear(gl.DEPTH_BUFFER_BIT|gl.COLOR_BUFFER_BIT); | |
// seta a matriz de projeção para um FOV vertical de 45 graus, com aspect ratio correto, | |
// e distância do plano próximo pra 0.1 e do plano distante para 100.0 | |
mat4.perspective(projectionMtx, 45, gl.viewportWidth/gl.viewportHeight, 0.1, 100.0); | |
// seta transformação para identidade, depois faz translação pra posição correta | |
mat4.identity(modelViewMtx); | |
mat4.translate(modelViewMtx, modelViewMtx, [0.0, 0.0, -3.0]); | |
// manda essas matrizes pro shader de vértice | |
gl.uniformMatrix4fv(shaderpgm.projectionMtxLoc, false, projectionMtx); | |
gl.uniformMatrix4fv(shaderpgm.modelViewMtxLoc, false, modelViewMtx); | |
// bota os buffers de atributo pra funcionar. redundante especificar isso todo frame pra | |
// geometria que não muda, mas é exemplo de como fazer setup de um objeto | |
gl.bindBuffer(gl.ARRAY_BUFFER, vertexbuffer); | |
gl.vertexAttribPointer(shaderpgm.inPositionLoc, vertexbuffer.itemSize, gl.FLOAT, false, 0, 0); | |
gl.bindBuffer(gl.ARRAY_BUFFER, colorsbuffer); | |
gl.vertexAttribPointer(shaderpgm.inColorLoc, colorsbuffer.itemSize, gl.FLOAT, false, 0, 0); | |
// a chamada do desenho propriamente dito | |
gl.drawArrays(gl.TRIANGLES, 0, vertexbuffer.numItems); | |
} | |
$(function(){ | |
setup(); | |
render(); | |
}); | |
</script> | |
<style type="text/css"> | |
html, body { | |
margin: 0; | |
padding: 0; | |
height: 100%; | |
} | |
canvas#gl { | |
width: 100%; | |
height: 100%; | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="gl"></canvas> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment