2017-05-21 7 views
0

Ich versuche, WebGL zu lernen. Ich lese dieses Tutorial https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL Aber um besser zu lernen schreibe ich meinen eigenen Code und nicht kopieren-Vergangenheit-Code aus dem Tutorial. Ich habe meinen Code hier hochgeladen https://github.com/Azaravicius/GLCanvas Dateien glUtils.js und sylvester.js sind von Tutorial als Abhängige. Dateien glcanvas.js und run.js haben meinen Code.Fehler in meinem WebGL-Code nicht gefunden

Code sollte Quadrat in vier Farben wie im Tutorial zeichnen, aber ich bekomme rotes Quadrat in Firefox und schwarzes Quadrat in Chrom.

<script id="shader-vs" type="x-shader/x-vertex"> 
    attribute vec3 aVertexPosition; 
    attribute vec4 aVertexColor; 
    uniform mat4 uMVMatrix; 
    uniform mat4 uPMatrix; 
    varying lowp vec4 vColor; 

    void main(void) { 
     gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); 
     vColor = aVertexColor; 
    } 
</script> 

ich vertext Shader erraten bekommen keine Werte für aVertexColor, aber hier keine Fehler in der Konsole. Für den Test habe ich den Code in vColor = vec4 geändert (aVertexPosition, 1.0); und es hat funktioniert. Der Fragment-Shader erhält also Daten vom Fragment-Shader. Ich weiß nicht, wie man Fehler im Code findet.

class GLCanvas { 
 
    constructor(canvasID, clear = [1.0, 1.0, 1.0, 1.0], contextAttributes = {}) { 
 
    // WebGLRenderingContext 
 
    this.gl = null; 
 
    // Object to hold all created programs. {programName:program} 
 
    this.programs = {}; 
 
    // All variables of current program {variableName: variableLoction} 
 
    this.variables = {}; 
 
    // Buffers in use 
 
    this.buffers = {}; 
 
    // HTML5 canvas element 
 
    this.canvas = document.getElementById(canvasID); 
 

 
    if (!this.canvas) { 
 
     console.log("ERROR: Can't find canvas with id", canvasID); 
 
     return; 
 
    } 
 
    // contextAttributes = {alpha: true, depth: true, stencil: false, antialias: true, 
 
    //      premultipliedAlpha: true, preserveDrawingBuffer: false, 
 
    //      failIfMajorPerformanceCaveat: false } 
 
    this.gl = this.canvas.getContext('webgl', contextAttributes) || 
 
     this.canvas.getContext('experimental-webgl', contextAttributes); 
 
    if (!this.gl) { 
 
     console.log("ERROR: Unable to get WebGL context. Your browser may not support it."); 
 
     return; 
 
    } 
 
    this.gl.clearColor(clear[0], clear[1], clear[2], clear[3]); 
 
    this.gl.clear(this.gl.COLOR_BUFFER_BIT); 
 
    } 
 

 
    initProgram(vShader, fShader, program) { 
 
    var fragmentShader, vertexShader; 
 
    vertexShader = this.initShader(vShader, this.gl.VERTEX_SHADER); 
 
    if (!vertexShader) { 
 
     console.log('Vertex shader not loaded.'); 
 
     return; 
 
    } 
 
    fragmentShader = this.initShader(fShader, this.gl.FRAGMENT_SHADER); 
 
    if (!fragmentShader) { 
 
     console.log('Fragment shader not loaded.'); 
 
     return; 
 
    } 
 

 
    this.programs[program] = this.gl.createProgram(); 
 
    this.gl.attachShader(this.programs[program], vertexShader); 
 
    this.gl.attachShader(this.programs[program], fragmentShader); 
 
    this.gl.linkProgram(this.programs[program]); 
 
    if (!this.gl.getProgramParameter(this.programs[program], this.gl.LINK_STATUS)) { 
 
     console.log('Unable to initialize the shader program: ' + this.gl.getProgramInfoLog(this.programs[program])); 
 
     this.gl.deleteProgram(this.programs[program]); 
 
     delete this.programs[program]; 
 
     return; 
 
    } 
 
    } 
 

 
    initShader(shaderScript, type) { 
 
    var shader = this.gl.createShader(type); 
 
    this.gl.shaderSource(shader, shaderScript); 
 
    this.gl.compileShader(shader); 
 
    if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) { 
 
     console.log('An error occurred compiling the shaders: ' + this.gl.getShaderInfoLog(shader)); 
 
     this.gl.deleteShader(shader); 
 
     return null; 
 
    } 
 
    return shader; 
 
    } 
 

 
    useProgram(program, variables) { 
 
    var attr; 
 
    this.gl.useProgram(this.programs[program]); 
 
    for (attr in variables["attributes"]) { 
 
     this.variables[variables["attributes"][attr]] = this.gl.getAttribLocation(this.programs[program], variables["attributes"][attr]); 
 
     if (this.variables[variables["attributes"][attr]] == -1) { 
 
     console.log(variables["attributes"][attr], " vertex position attribut not found."); 
 
     continue; 
 
     } 
 
     this.gl.enableVertexAttribArray(this.variables[attr]); 
 
    } 
 
    for (attr in variables["uniforms"]) { 
 
     this.variables[variables["uniforms"][attr]] = this.gl.getUniformLocation(this.programs[program], variables["uniforms"][attr]); 
 
     if (!this.variables[variables["uniforms"][attr]]) { 
 
     console.log(variables["uniforms"][attr], " uniform attribut not found."); 
 
     continue; 
 
     } 
 
    } 
 
    } 
 

 
    // Create and bind buffer and initializes and creates the buffer object's data store. 
 
    // Parameters: 
 
    // name - buffer name 
 
    // data - An ArrayBuffer that will be copied into the data store. 
 
    // target - A GLenum specifying the binding point (target). Default ARRAY_BUFFER. 
 
    // usage - A GLenum specifying the usage pattern of the data store. Default STATIC_DRAW 
 
    initBuffer(name, data, target = this.gl.ARRAY_BUFFER, usage = this.gl.STATIC_DRAW) { 
 
    this.buffers[name] = this.gl.createBuffer(); 
 
    this.gl.bindBuffer(target, this.buffers[name]); 
 
    this.gl.bufferData(target, new Float32Array(data), usage); 
 
    } 
 

 
    //resize canvas and viewport. 
 
    // Parameters: 
 
    // width - width to resize. Default window.innerWidth. 
 
    // height - height to resize. Default window.innerHeight. 
 
    // return value - None. 
 
    resize(width = window.innerWidth, height = window.innerHeight) { 
 
    this.canvas.width = width; 
 
    this.canvas.height = height; 
 
    this.gl.viewport(0, 0, width, height); 
 
    } 
 

 
    // Clear COLOR_BUFFER_BIT and DEPTH_BUFFER_BIT. 
 
    // return value - None. 
 
    clear() { 
 
    // COLOR_BUFFER_BIT; STENCIL_BUFFER_BIT; DEPTH_BUFFER_BIT 
 
    this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); 
 
    } 
 

 
    // Parameters: 
 
    // name - buffer name 
 
    // location - string, name of the vertex attribute that is to be modified. 
 
    // size - A GLint specifying the number of components per vertex attribute. Default 3. 
 
    // type - A GLenum specifying the data type of each component in the array. Default FLOAT. 
 
    // normalized - A GLboolean specifying whether integer data values should be normalized when being casted to a float. Default false. 
 
    // stride - A GLsizei specifying the offset in bytes between the beginning of consecutive vertex attributes. Cannot be larger than 255. Default 0. 
 
    // offset - A GLintptr specifying an offset in bytes of the first component in the vertex attribute array. Must be a multiple of type. Default 0. 
 
    // return value - None. 
 
    useBuffer(location, size = 3, target = this.gl.ARRAY_BUFFER, type = this.gl.FLOAT, normalized = false, stride = 0, offset = 0) { 
 
    this.gl.bindBuffer(target, this.buffers[location]); 
 
    this.gl.vertexAttribPointer(this.variables[location], size, type, normalized, stride, offset); 
 
    } 
 

 
    // Parameters: 
 
    // location - string, name of the uniform attribute to modify. 
 
    // value - A Float32Array of float values. 
 
    // transpose - A GLboolean specifying whether to transpose the matrix. Default false. 
 
    // return value - None. 
 
    uniformMatrix4fv(location, value, transpose = false) { 
 
    this.gl.uniformMatrix4fv(this.variables[location], transpose, new Float32Array(value)); 
 
    } 
 

 
    // Returns canvas aspect ratio of width and height. 
 
    aspect() { 
 
    return this.canvas.width/this.canvas.height; 
 
    } 
 

 
} 
 

 
var canvas; 
 
var programs = ["first"]; 
 
var para = { 
 
    "first": { 
 
    "var": { 
 
     "attributes": ["aVertexPosition", "aVertexColor"], 
 
     "uniforms": ["uPMatrix", "uMVMatrix"] 
 
    }, 
 
    "shaders": { 
 
     "vs": "shader-vs", 
 
     "fs": "shader-fs" 
 
    } 
 
    } 
 
}; 
 
var vertices = [ 
 
    0.9, 0.9, 0.0, -0.9, 0.9, 0.0, 
 
    0.9, -0.9, 0.0, -0.9, -0.9, 0.0 
 
]; 
 
var colors = [ 
 
    1.0, 1.0, 1.0, 1.0, // white 
 
    1.0, 0.0, 0.0, 1.0, // red 
 
    0.0, 1.0, 0.0, 1.0, // green 
 
    0.0, 0.0, 1.0, 1.0 // blue 
 
]; 
 

 

 
function start() { 
 
    canvas = new GLCanvas("canvasGL"); 
 
    if (canvas.gl) { 
 
    canvas.initProgram(getShader(para[programs[0]]["shaders"]["vs"]), getShader(para[programs[0]]["shaders"]["fs"]), programs[0]); 
 
    canvas.useProgram(programs[0], para[programs[0]]["var"]); 
 
    canvas.initBuffer(para[programs[0]]["var"]["attributes"][0], vertices); 
 
    canvas.initBuffer(para[programs[0]]["var"]["attributes"][1], colors); 
 

 
    window.addEventListener('resize', draw, false); 
 
    draw(); 
 
    } 
 
} 
 

 
function getShader(id) { 
 
    var shaderScript = document.getElementById(id); 
 
    if (!shaderScript) { 
 
    console.log('ERROR: Shader not loaded.'); 
 
    return null; 
 
    } 
 
    return shaderScript.text; 
 
} 
 

 
function draw() { 
 
    canvas.resize(); 
 
    var perspective = makePerspective(30, canvas.aspect(), 0.1, 100); 
 
    canvas.clear(); 
 
    loadIdentity(); 
 
    mvTranslate([0.0, 0.0, -3.5]); 
 

 
    canvas.useBuffer(para[programs[0]]["var"]["attributes"][0]); 
 
    canvas.useBuffer(para[programs[0]]["var"]["attributes"][1], 4); 
 

 
    canvas.uniformMatrix4fv(para[programs[0]]["var"]["uniforms"][0], perspective.flatten()); 
 
    canvas.uniformMatrix4fv(para[programs[0]]["var"]["uniforms"][1], mvMatrix.flatten()); 
 

 
    canvas.gl.drawArrays(canvas.gl.TRIANGLE_STRIP, 0, 4); 
 
} 
 

 
// augment Sylvester some 
 
Matrix.Translation = function(v) { 
 
    if (v.elements.length == 2) { 
 
    var r = Matrix.I(3); 
 
    r.elements[2][0] = v.elements[0]; 
 
    r.elements[2][1] = v.elements[1]; 
 
    return r; 
 
    } 
 

 
    if (v.elements.length == 3) { 
 
    var r = Matrix.I(4); 
 
    r.elements[0][3] = v.elements[0]; 
 
    r.elements[1][3] = v.elements[1]; 
 
    r.elements[2][3] = v.elements[2]; 
 
    return r; 
 
    } 
 

 
    throw "Invalid length for Translation"; 
 
} 
 

 
Matrix.prototype.flatten = function() { 
 
    var result = []; 
 
    if (this.elements.length == 0) 
 
    return []; 
 

 

 
    for (var j = 0; j < this.elements[0].length; j++) 
 
    for (var i = 0; i < this.elements.length; i++) 
 
     result.push(this.elements[i][j]); 
 
    return result; 
 
} 
 

 
Matrix.prototype.ensure4x4 = function() { 
 
    if (this.elements.length == 4 && 
 
    this.elements[0].length == 4) 
 
    return this; 
 

 
    if (this.elements.length > 4 || 
 
    this.elements[0].length > 4) 
 
    return null; 
 

 
    for (var i = 0; i < this.elements.length; i++) { 
 
    for (var j = this.elements[i].length; j < 4; j++) { 
 
     if (i == j) 
 
     this.elements[i].push(1); 
 
     else 
 
     this.elements[i].push(0); 
 
    } 
 
    } 
 

 
    for (var i = this.elements.length; i < 4; i++) { 
 
    if (i == 0) 
 
     this.elements.push([1, 0, 0, 0]); 
 
    else if (i == 1) 
 
     this.elements.push([0, 1, 0, 0]); 
 
    else if (i == 2) 
 
     this.elements.push([0, 0, 1, 0]); 
 
    else if (i == 3) 
 
     this.elements.push([0, 0, 0, 1]); 
 
    } 
 

 
    return this; 
 
}; 
 

 
Matrix.prototype.make3x3 = function() { 
 
    if (this.elements.length != 4 || 
 
    this.elements[0].length != 4) 
 
    return null; 
 

 
    return Matrix.create([ 
 
    [this.elements[0][0], this.elements[0][1], this.elements[0][2]], 
 
    [this.elements[1][0], this.elements[1][1], this.elements[1][2]], 
 
    [this.elements[2][0], this.elements[2][1], this.elements[2][2]] 
 
    ]); 
 
}; 
 

 
Vector.prototype.flatten = function() { 
 
    return this.elements; 
 
}; 
 

 
function mht(m) { 
 
    var s = ""; 
 
    if (m.length == 16) { 
 
    for (var i = 0; i < 4; i++) { 
 
     s += "<span style='font-family: monospace'>[" + m[i * 4 + 0].toFixed(4) + "," + m[i * 4 + 1].toFixed(4) + "," + m[i * 4 + 2].toFixed(4) + "," + m[i * 4 + 3].toFixed(4) + "]</span><br>"; 
 
    } 
 
    } else if (m.length == 9) { 
 
    for (var i = 0; i < 3; i++) { 
 
     s += "<span style='font-family: monospace'>[" + m[i * 3 + 0].toFixed(4) + "," + m[i * 3 + 1].toFixed(4) + "," + m[i * 3 + 2].toFixed(4) + "]</font><br>"; 
 
    } 
 
    } else { 
 
    return m.toString(); 
 
    } 
 
    return s; 
 
} 
 

 
// 
 
// gluLookAt 
 
// 
 
function makeLookAt(ex, ey, ez, 
 
    cx, cy, cz, 
 
    ux, uy, uz) { 
 
    var eye = $V([ex, ey, ez]); 
 
    var center = $V([cx, cy, cz]); 
 
    var up = $V([ux, uy, uz]); 
 

 
    var mag; 
 

 
    var z = eye.subtract(center).toUnitVector(); 
 
    var x = up.cross(z).toUnitVector(); 
 
    var y = z.cross(x).toUnitVector(); 
 

 
    var m = $M([ 
 
    [x.e(1), x.e(2), x.e(3), 0], 
 
    [y.e(1), y.e(2), y.e(3), 0], 
 
    [z.e(1), z.e(2), z.e(3), 0], 
 
    [0, 0, 0, 1] 
 
    ]); 
 

 
    var t = $M([ 
 
    [1, 0, 0, -ex], 
 
    [0, 1, 0, -ey], 
 
    [0, 0, 1, -ez], 
 
    [0, 0, 0, 1] 
 
    ]); 
 
    return m.x(t); 
 
} 
 

 
// 
 
// glOrtho 
 
// 
 
function makeOrtho(left, right, 
 
    bottom, top, 
 
    znear, zfar) { 
 
    var tx = -(right + left)/(right - left); 
 
    var ty = -(top + bottom)/(top - bottom); 
 
    var tz = -(zfar + znear)/(zfar - znear); 
 

 
    return $M([ 
 
    [2/(right - left), 0, 0, tx], 
 
    [0, 2/(top - bottom), 0, ty], 
 
    [0, 0, -2/(zfar - znear), tz], 
 
    [0, 0, 0, 1] 
 
    ]); 
 
} 
 

 
// 
 
// gluPerspective 
 
// 
 
function makePerspective(fovy, aspect, znear, zfar) { 
 
    var ymax = znear * Math.tan(fovy * Math.PI/360.0); 
 
    var ymin = -ymax; 
 
    var xmin = ymin * aspect; 
 
    var xmax = ymax * aspect; 
 

 
    return makeFrustum(xmin, xmax, ymin, ymax, znear, zfar); 
 
} 
 

 
// 
 
// glFrustum 
 
// 
 
function makeFrustum(left, right, 
 
    bottom, top, 
 
    znear, zfar) { 
 
    var X = 2 * znear/(right - left); 
 
    var Y = 2 * znear/(top - bottom); 
 
    var A = (right + left)/(right - left); 
 
    var B = (top + bottom)/(top - bottom); 
 
    var C = -(zfar + znear)/(zfar - znear); 
 
    var D = -2 * zfar * znear/(zfar - znear); 
 

 
    return $M([ 
 
    [X, 0, A, 0], 
 
    [0, Y, B, 0], 
 
    [0, 0, C, D], 
 
    [0, 0, -1, 0] 
 
    ]); 
 
} 
 

 
// 
 
// glOrtho 
 
// 
 
function makeOrtho(left, right, bottom, top, znear, zfar) { 
 
    var tx = -(right + left)/(right - left); 
 
    var ty = -(top + bottom)/(top - bottom); 
 
    var tz = -(zfar + znear)/(zfar - znear); 
 

 
    return $M([ 
 
    [2/(right - left), 0, 0, tx], 
 
    [0, 2/(top - bottom), 0, ty], 
 
    [0, 0, -2/(zfar - znear), tz], 
 
    [0, 0, 0, 1] 
 
    ]); 
 
} 
 

 
function loadIdentity() { 
 
    mvMatrix = Matrix.I(4); 
 
} 
 

 
function multMatrix(m) { 
 
    mvMatrix = mvMatrix.x(m); 
 
} 
 

 
function mvTranslate(v) { 
 
    multMatrix(Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4()); 
 
}
body { 
 
    height: 100%; 
 
    width: 100%; 
 
    margin: 0px; 
 
    padding: 0px; 
 
    overflow: hidden; 
 
    /* Disable scrollbars */ 
 
    display: block; 
 
    /* No floating content on sides */ 
 
    border: 0; 
 
} 
 

 
* { 
 
    box-sizing: border-box; 
 
} 
 

 
canvas { 
 
    position: absolute; 
 
    left: 0px; 
 
    top: 0px; 
 
}
<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <title>Geo</title> 
 
    <meta http-equiv="content-type" content="text/html; charset=utf-8" /> 
 
    <link rel="stylesheet" type="text/css" href="style.css" /> 
 
</head> 
 

 
<body onload="start()"> 
 
    <canvas id="canvasGL"> 
 
      Your browser does not support the HTML5 canvas tag. 
 
     </canvas> 
 
    <script id="shader-vs" type="x-shader/x-vertex"> 
 
    attribute vec3 aVertexPosition; attribute vec4 aVertexColor; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying lowp vec4 vColor; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vColor = aVertexColor; } 
 
    </script> 
 
    <script id="shader-fs" type="x-shader/x-fragment"> 
 
    varying lowp vec4 vColor; void main(void) { gl_FragColor = vColor; } 
 
    </script> 
 
    <script src="https://mdn.github.io/webgl-examples/tutorial/sylvester.js"></script> 
 
</body> 
 

 
</html>

+0

Try [diese Tutorials] (http://webglfundamentals.org) – gman

Antwort

0

Sie verwenden einen falschen Index Ihr Attribut Ortsbezug in useProgram Funktion zu erhalten.

useProgram(program, variables) { 
    // ... 

    for (attr in variables["attributes"]) { 
     // ... 
     // correct code 
     this.gl.enableVertexAttribArray(this.variables[variables["attributes"][attr]]); 
    } 
    // ... 
} 

Vorsicht ...

+0

Vielen Dank für diesen Fehler zu finden. – Donatas