diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/web/api/webgl_api | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip |
initial commit
Diffstat (limited to 'files/zh-cn/web/api/webgl_api')
29 files changed, 8983 insertions, 0 deletions
diff --git a/files/zh-cn/web/api/webgl_api/basic_2d_animation_example/index.html b/files/zh-cn/web/api/webgl_api/basic_2d_animation_example/index.html new file mode 100644 index 0000000000..0b0f4f4193 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/basic_2d_animation_example/index.html @@ -0,0 +1,318 @@ +--- +title: 一个 2D WebGL 动画的基础示例 +slug: Web/API/WebGL_API/Basic_2D_animation_example +tags: + - 测试翻译 +translation_of: Web/API/WebGL_API/Basic_2D_animation_example +--- +<div>{{WebGLSidebar}}</div> + +<div id="live-sample"> +<p>在这个WebGL示例中,我们创建一个画布,并在其中使用WebGL渲染旋转正方形。我们用来表示场景的坐标系与画布的坐标系相同。也就是说,(0, 0)这个坐标在左上角,右下角是坐标在(600, 460)。</p> + +<h2 id="Vertex_shader">Vertex shader</h2> + +<p>首先,让我们看一下顶点着色器。它的工作如同以往,是将我们用于场景的坐标转换为剪贴空间的坐标(即系统中的(0,0)位于上下文的中心,每个轴从-1.0扩展到1.0,而不管上下文的实际大小)。</p> + +<pre class="brush: html"><script id="vertex-shader" type="x-shader/x-vertex"> + attribute vec2 aVertexPosition; + + uniform vec2 uScalingFactor; + uniform vec2 uRotationVector; + + void main() { + vec2 rotatedPosition = vec2( + aVertexPosition.x * uRotationVector.y + + aVertexPosition.y * uRotationVector.x, + aVertexPosition.y * uRotationVector.y - + aVertexPosition.x * uRotationVector.x + ); + + gl_Position = vec4(rotatedPosition * uScalingFactor, 0.0, 1.0); + } +</script></pre> + +<p dir="ltr" id="tw-target-text">主程序与我们共享属性aVertexPosition,它是顶点在其使用的任何坐标系中的位置。我们需要转换这些值,以便位置的两个组件都在-1.0到1.0的范围内。通过乘以基于上下文宽高比的缩放因子,可以很容易地完成此操作。我们很快就会看到这个计算。</p> + +<p>我们也可以通过一次变换来旋转这个图形。 The rotated position of the vertex is computed by applying the rotation vector, found in the uniform <code>uRotationVector</code>, that's been computed by the JavaScript code.</p> + +<p>Then the final position is computed by multiplying the rotated position by the scaling vector provided by the JavaScript code in <code>uScalingFactor</code>. The values of <code>z</code> and <code>w</code> are fixed at 0.0 and 1.0, respectively, since we're drawing in 2D.</p> + +<p>The standard WebGL global <code>gl_Position</code> is then set to the transformed and rotated vertex's position.</p> + +<h2 id="Fragment_shader">Fragment shader</h2> + +<p>Next comes the fragment shader. Its role is to return the color of each pixel in the shape being rendered. Since we're drawing a solid, untextured object with no lighting applied, this is exceptionally simple:</p> + +<pre class="brush: html"><script id="fragment-shader" type="x-shader/x-fragment"> + #ifdef GL_ES + precision highp float; + #endif + + uniform vec4 uGlobalColor; + + void main() { + gl_FragColor = uGlobalColor; + } +</script></pre> + +<p>This starts by specifying the precision of the <code>float</code> type, as required. Then we set the global <code>gl_FragColor</code> to the value of the uniform <code>uGlobalColor</code>, which is set by the JavaScript code to the color being used to draw the square.</p> + +<h2 id="HTML">HTML</h2> + +<p>The HTML consists solely of the {{HTMLElement("canvas")}} that we'll obtain a WebGL context on.</p> + +<pre class="brush: html"><canvas id="glcanvas" width="600" height="460"> + Oh no! Your browser doesn't support canvas! +</canvas></pre> + +<h2 id="JavaScript">JavaScript</h2> + +<h3 id="Globals_and_initialization">Globals and initialization</h3> + +<p>First, the global variables. We won't discuss these here; instead, we'll talk about them as they're used in the code to come.</p> + +<pre class="brush: js">let gl = null; +let glCanvas = null; + +// Aspect ratio and coordinate system +// details + +let aspectRatio; +let currentRotation = [0, 1]; +let currentScale = [1.0, 1.0]; + +// Vertex information + +let vertexArray; +let vertexBuffer; +let vertexNumComponents; +let vertexCount; + +// Rendering data shared with the +// scalers. + +let uScalingFactor; +let uGlobalColor; +let uRotationVector; +let aVertexPosition; + +// Animation timing + +let previousTime = 0.0; +let degreesPerSecond = 90.0; +</pre> + +<p>Initializing the program is handled through a {{event("load")}} event handler called <code>startup()</code>:</p> + +<pre class="brush: js">window.addEventListener("load", startup, false); + +function startup() { + glCanvas = document.getElementById("glcanvas"); + gl = glCanvas.getContext("webgl"); + + const shaderSet = [ + { + type: gl.VERTEX_SHADER, + id: "vertex-shader" + }, + { + type: gl.FRAGMENT_SHADER, + id: "fragment-shader" + } + ]; + + shaderProgram = buildShaderProgram(shaderSet); + + aspectRatio = glCanvas.width/glCanvas.height; + currentRotation = [0, 1]; + currentScale = [1.0, aspectRatio]; + + vertexArray = new Float32Array([ + -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, + -0.5, 0.5, 0.5, -0.5, -0.5, -0.5 + ]); + + vertexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, vertexArray, gl.STATIC_DRAW); + + vertexNumComponents = 2; + vertexCount = vertexArray.length/vertexNumComponents; + + currentAngle = 0.0; + rotationRate = 6; + + animateScene(); +}</pre> + +<p>After getting the WebGL context, <code>gl</code>, we need to begin by building the shader program. Here, we're using code designed to let us add multiple shaders to our program quite easily. The array <code>shaderSet</code> contains a list of objects, each describing one shader function to be compiled into the program. Each function has a type (one of <code>gl.VERTEX_SHADER</code> or <code>gl.FRAGMENT_SHADER</code>) and an ID (the ID of the {{HTMLElement("script")}} element containing the shader's code).</p> + +<p>The shader set is passed into the function <code>buildShaderProgram()</code>, which returns the compiled and linked shader program. We'll look at how this works next.</p> + +<p>Once the shader program is built, we compute the aspect ratio of our context by dividing its width by its height. Then we set the current rotation vector for the animation to <code>[0, 1]</code>, and the scaling vector to <code>[1.0, aspectRatio]</code>. The scaling vector, as we saw in the vertex shader, is used to scale the coordinates to fit the -1.0 to 1.0 range.</p> + +<p>The array of vertices is created next, as a {{jsxref("Float32Array")}} with six coordinates (three 2D vertices) per triangle to be drawn, for a total of 12 values.</p> + +<p>As you can see, we're using a coordinate system of -1.0 to 1.0 for each axis. Why, you may ask, do we need to do any adjustments at all? This is simply because our context is not square. We're using a context that's 600 pixels wide and 460 tall. Each of those dimensions is mapped to the range -1.0 to 1.0. Since the two axes aren't the same length, if we don't adjust the values of one of the two axes, the square will get stretched out in one direction or the other. So we need to normalize these values.</p> + +<p>Once the vertex array has been created, we create a new GL buffer to contain them by calling {{domxref("WebGLRenderingContext.createBuffer", "gl.createBuffer()")}}. We bind the standard WebGL array buffer reference to that by calling {{domxref("WebGLRenderingContext.bindBuffer", "gl.bindBuffer()")}} and then copy the vertex data into the buffer using {{domxref("WebGLRenderingContext.bufferData", "gl.bufferData()")}}. The usage hint <code>gl.STATIC_DRAW</code> is specified, telling WebGL that the data will be set only one time and never modified, but will be used repeatedly. This lets WebGL consider any optimizations it can apply that may improve performance based on that information.</p> + +<p>With the vertex data now provided to WebGL, we set <code>vertexNumComponents</code> to the number of components in each vertex (2, since they're 2D vertexes) and <code>vertexCount</code> to the number of vertexes in the vertex list.</p> + +<p>Then the current rotation angle (in degrees) is set to 0.0, since we haven't performed any rotation yet, and the rotation speed (in degrees per screen refresh period, typically 60 FPS) is set to 6.</p> + +<p>Finally, <code>animateScene()</code> is called to render the first frame and schedule the rendering of the next frame of the animation.</p> + +<h3 id="Compiling_and_linking_the_shader_program">Compiling and linking the shader program</h3> + +<h4 id="Constructing_and_linking_the_program">Constructing and linking the program</h4> + +<p>The <code>buildShaderProgram()</code> function accepts as input an array of objects describing a set of shader functions to be compiled and linked into the shader program and returns the shader program after it's been built and linked.</p> + +<pre class="brush: js">function buildShaderProgram(shaderInfo) { + let program = gl.createProgram(); + + shaderInfo.forEach(function(desc) { + let shader = compileShader(desc.id, desc.type); + + if (shader) { + gl.attachShader(program, shader); + } + }); + + gl.linkProgram(program) + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + console.log("Error linking shader program:"); + console.log(gl.getProgramInfoLog(program)); + } + + return program; +}</pre> + +<p>First, {{domxref("WebGLRenderingContext.createProgram", "gl.createProgram()")}} is called to create a new, empty, GLSL program.</p> + +<p>Then, for each shader in the specified list of shaders, we call a <code>compileShader()</code> function to compile it, passing into it the ID and type of the shader function to build. Each of those objects includes, as mentioned before, the ID of the <code><script></code> element the shader code is found in and the type of shader it is. The compiled shader is attached to the shader program by passing it into {{domxref("WebGLRenderingContext.attachShader", "gl.attachShader()")}}.</p> + +<div class="note"> +<p>We could go a step farther here, actually, and look at the value of the <code><script></code> element's <code>type</code> attribute to determine the shader type.</p> +</div> + +<p>Once all of the shaders are compiled, the program is linked using {{domxref("WebGLRenderingContext.linkProgram", "gl.linkProgram()")}}.</p> + +<p>If an error occurrs while linking the program, the error message is logged to console.</p> + +<p>Finally, the compiled program is returned to the caller.</p> + +<h4 id="Compiling_an_individual_shader">Compiling an individual shader</h4> + +<p>The <code>compileShader()</code> function, below, is called by <code>buildShaderProgram()</code> to compile a single shader.</p> + +<pre class="brush: js">function compileShader(id, type) { + let code = document.getElementById(id).firstChild.nodeValue; + let shader = gl.createShader(type); + + gl.shaderSource(shader, code); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + console.log(`Error compiling ${type === gl.VERTEX_SHADER ? "vertex" : "fragment"} shader:`); + console.log(gl.getShaderInfoLog(shader)); + } + return shader; +}</pre> + +<p>The code is fetched from the HTML document by obtaining the value of the text node contained within the {{HTMLElement("script")}} element with the specified ID. Then a new shader of the specified type is created using {{domxref("WebGLRenderingContext.createShader", "gl.createShader()")}}.</p> + +<p>The source code is sent into the new shader by passing it into {{domxref("WebGLRenderingContext.shaderSource", "gl.shaderSource()")}}, and then the shader is compiled using {{domxref("WebGLRenderingContext.compileShader", "gl.compileShader()")}}</p> + +<p>Compile errors are logged to the console. Note the use of a <a href="/en-US/docs/Web/JavaScript/Reference/Template_literals">template literal</a> string to insert the correct shader type string into the message that gets generated. The actual error details are obtained by calling {{domxref("WebGLRenderingContext.getShaderInfoLog", "gl.getShaderInfoLog()")}}.</p> + +<p>Finally, the compiled shader is returned to the caller (which is the <code>buildShaderProgram()</code> function.</p> + +<h3 id="Drawing_and_animating_the_scene">Drawing and animating the scene</h3> + +<p>The <code>animateScene()</code> function is called to render each animation frame.</p> + +<pre class="brush: js">function animateScene() { + gl.viewport(0, 0, glCanvas.width, glCanvas.height); + gl.clearColor(0.8, 0.9, 1.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + + let radians = currentAngle * Math.PI / 180.0; + currentRotation[0] = Math.sin(radians); + currentRotation[1] = Math.cos(radians); + + gl.useProgram(shaderProgram); + + uScalingFactor = + gl.getUniformLocation(shaderProgram, "uScalingFactor"); + uGlobalColor = + gl.getUniformLocation(shaderProgram, "uGlobalColor"); + uRotationVector = + gl.getUniformLocation(shaderProgram, "uRotationVector"); + + gl.uniform2fv(uScalingFactor, currentScale); + gl.uniform2fv(uRotationVector, currentRotation); + gl.uniform4fv(uGlobalColor, [0.1, 0.7, 0.2, 1.0]); + + gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); + + aVertexPosition = + gl.getAttribLocation(shaderProgram, "aVertexPosition"); + + gl.enableVertexAttribArray(aVertexPosition); + gl.vertexAttribPointer(aVertexPosition, vertexNumComponents, + gl.FLOAT, false, 0, 0); + + gl.drawArrays(gl.TRIANGLES, 0, vertexCount); + + window.requestAnimationFrame(function(currentTime) { + let deltaAngle = ((currentTime - previousTime) / 1000.0) + * degreesPerSecond; + + currentAngle = (currentAngle + deltaAngle) % 360; + + previousTime = currentTime; + animateScene(); + }); +}</pre> + +<p>The first thing that needs to be done in order to draw a frame of the animation is to clear the background to the desired color. In this case, we set the viewport based on the size of the {{HTMLElement("canvas")}}, call {{domxref("WebGLRenderingContext.clearColor", "clearColor()")}} to set the color to use when clearing content, then we clear the buffer with {{domxref("WebGLRenderingContext.clear", "clear()")}}.</p> + +<p>Next, the current rotation vector is computed by converting the current rotation in degrees (<code>currentAngle</code>) into {{interwiki("wikipedia", "radians")}}, then setting the first component of the rotation vector to the {{interwiki("wikipedia", "sine")}} of that value and the second component to the {{interwiki("wikipedia", "cosine")}}. The <code>currentRotation</code> vector is now the location of the point on the {{interwiki("wikipedia", "unit circle")}} located at the angle <code>currentAngle</code>.</p> + +<p>{{domxref("WebGLRenderingContext.useProgram", "useProgram()")}} is called to activate the GLSL shading program we established previously. Then we obtain the locations of each of the uniforms used to share information between the JavaScript code and the shaders (with {{domxref("WebGLRenderingContext.getUniformLocation", "getUniformLocation()")}}).</p> + +<p>The uniform named <code>uScalingFactor</code> is set to the <code>currentScale</code> value previously computed; this, as you may recall, is the value used to adjust the coordinate system based on the aspect ratio of the context. This is done using {{domxref("WebGLRenderingContext.uniform2fv", "uniform2fv()")}} (since this is a 2-value floating-point vector).</p> + +<p><code>uRotationVector</code> is set to the current rotation vector (<code>currentRotation)</code>, also using <code>uniform2fv()</code>.</p> + +<p><code>uGlobalColor</code> is set using {{domxref("WebGLRenderingContext.uniform4fv", "uniform4fv()")}} to the color we wish to use when drawing the square. This is a 4-component floating-point vector (one component each for red, green, blue, and alpha).</p> + +<p>Now that that's all out of the way, we can set up the vertex buffer and draw our shape, first, the buffer of vertexes that will be used to draw the triangles of the shape is set by calling {{domxref("WebGLRenderingContext.bindBuffer", "bindBuffer()")}}. Then the vertex position attribute's index is obtained from the shader program by calling {{domxref("WebGLRenderingContext.getAttribLocation", "getAttribLocation()")}}.</p> + +<p>With the index of the vertex position attribute now available in <code>aVertexPosition</code>, we call <code>enableVertexAttribArray()</code> to enable the position attribute so it can be used by the shader program (in particular, by the vertex shader).</p> + +<p>Then the vertex buffer is bound to the <code>aVertexPosition</code> attribute by calling {{domxref("WebGLRenderingContext.vertexAttribPointer", "vertexAttribPointer()")}}. This step is not obvious, since this binding is almost a side effect. But as a result, accessing <code>aVertexPosition</code> now obtains data from the vertex buffer.</p> + +<p>With the association in place between the vertex buffer for our shape and the <code>aVertexPosition</code> attribute used to deliver vertexes one by one into the vertex shader, we're ready to draw the shape by calling {{domxref("WebGLRenderingContext.drawArrays", "drawArrays()")}}.</p> + +<p>At this point, the frame has been drawn. All that's left to do is to schedule to draw the next one. That's done here by calling {{domxref("Window.requestAnimationFrame", "requestAnimationFrame()")}}, which asks that a callback function be executed the next time the browser is ready to update the screen.</p> + +<p>Our <code>requestAnimationFrame()</code> callback receives as input a single parameter, <code>currentTime</code>, which specifies the time at which the frame drawing began. We use that and the saved time at which the last frame was drawn, <code>previousTime</code>, along with the number of degrees per second the square should rotate (<code>degreesPerSecond</code>) to calculate the new value of <code>currentAngle</code>. Then the value of <code>previousTime</code> is updated and we call <code>animateScene()</code> to draw the next frame (and in turn schedule the next frame to be drawn, ad infinitum).</p> +</div> + +<h2 id="Result">Result</h2> + +<p>This is a pretty simple example, since it's just drawing one simple object, but the concepts used here extend to much more complex animations.</p> + +<p>{{EmbedLiveSample("live-sample", 660, 500)}}</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/WebGL_API">WebGL API</a></li> + <li><a href="/en-US/docs/Web/API/WebGL_API/Tutorial">WebGL tutorial</a></li> +</ul> diff --git a/files/zh-cn/web/api/webgl_api/by_example/basic_scissoring/index.html b/files/zh-cn/web/api/webgl_api/by_example/basic_scissoring/index.html new file mode 100644 index 0000000000..4a21b9265e --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/basic_scissoring/index.html @@ -0,0 +1,90 @@ +--- +title: Basic scissoring +slug: Web/API/WebGL_API/By_example/Basic_scissoring +translation_of: Web/API/WebGL_API/By_example/Basic_scissoring +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Color_masking","Learn/WebGL/By_example/Canvas_size_and_WebGL")}}</p> + +<div id="basic-scissoring"> +<div class="summary"> +<p>在本例中,我们将学会如何使用WebGL (scissoring operations)剪切操作来绘制简单的矩形和正方形。Scissoring建立了一个剪切区域,在此区域内不会发生绘图。</p> +</div> + +<p>{{EmbedLiveSample("basic-scissoring-source",660,425)}}</p> + +<div id="basic-scissoring-intro"> +<h3 id="Clearing_the_drawing_buffer_when_scissoring_applies">Clearing the drawing buffer when scissoring applies</h3> + +<p>This is a simple demonstration of a rendering with {{domxref("WebGLRenderingContext.scissor","scissor()")}}.</p> + +<p>Although the {{domxref("WebGLRenderingContext.clear","clear()")}} drawing command writes the clear color (set by {{domxref("WebGLRenderingContext.clearColor","clearColor()")}}) to all pixels in the drawing buffer, {{domxref("WebGLRenderingContext.scissor","scissor()")}} defines a mask that only allows pixels inside the specified rectangular area to be updated.</p> + +<p>This is a good opportunity to talk about the difference between pixels and <em>fragments</em>. A pixel is a picture element (in practice, a point) on the screen, or a single element of the drawing buffer, that area in memory that holds your pixel data (such as {{Glossary("RGBA")}} color components). A <em>fragment</em> refers to the pixel while it is being handled by the {{Glossary("WebGL")}} pipeline.</p> + +<p>The reason for this distinction is that fragment color (and other fragment values, such as depth) may be manipulated and changed several times during graphics operations before finally being written to the screen. We have already seen how fragment color changes during graphics operations, by applying {{domxref("WebGLRenderingContext.colorMask()","color masking", "", 1)}}. In other cases, the fragments may be discarded altogether (so the pixel value is not updated), or it may interact with the already existing pixel value (such as when doing color blending for non-opaque elements in the scene).</p> + +<p>Here we see another example of the distinction between fragments and pixels. Scissoring is a distinct stage in the {{Glossary("WebGL")}}/{{Glossary("OpenGL")}} graphics pipeline (it occurs after color clearing, but before color masking). Before the actual pixels are updated, fragments must go through the scissor test. If the fragments pass the scissor test, they continue down the graphics pipeline, and the corresponding pixels are updated on the screen. If they fail the test, they are immediately discarded, no further processing occurs, and pixels are not updated. Because only fragments within the specified rectangular area successfully pass the scissor test, only pixels inside that area are updated, and we get a rectangle on the screen.</p> + +<p>The scissoring stage of the pipeline is disabled by default. We enable it here using the {{domxref("WebGLRenderingContext.enable","enable()")}} method (you will also use <code>enable()</code> to activate many other features of WebGL; hence, the use of the<code> SCISSOR_TEST</code> constant as an argument in this case). This again demonstrates the typical order of commands in {{Glossary("WebGL")}}. We first tweak WebGL state. In this case, enabling the scissor test and establishing a rectangular mask. Only when the WebGL state has been satisfactorily tweaked, we execute the drawing command (in this case, <code>clear()</code>) that starts the processing of fragments down the graphics pipeline.</p> +</div> + +<div id="basic-scissoring-source"> +<pre class="brush: html"><p>Result of of scissoring.</p> +<canvas>Your browser does not seem to support + HTML5 canvas.</canvas> +</pre> + +<pre class="brush: css">body { + text-align : center; +} +canvas { + display : block; + width : 280px; + height : 210px; + margin : auto; + padding : 0; + border : none; + background-color : black; +} +</pre> + +<pre class="brush: js" id="livesample-js">window.addEventListener("load", function setupWebGL (evt) { + "use strict" + window.removeEventListener(evt.type, setupWebGL, false); + var paragraph = document.querySelector("p"); + var canvas = document.querySelector("canvas"); + + // The following two lines set the size (in CSS pixels) of + // the drawing buffer to be identical to the size of the + // canvas HTML element, as determined by CSS. + canvas.width = canvas.clientWidth; + canvas.height = canvas.clientHeight; + + var gl = canvas.getContext("webgl") + || canvas.getContext("experimental-webgl"); + if (!gl) { + paragraph.innerHTML = "Failed to get WebGL context. " + + "Your browser or device may not support WebGL."; + return; + } + gl.viewport(0, 0, + gl.drawingBufferWidth, gl.drawingBufferHeight); + + // Enable scissoring operation and define the position and + // size of the scissoring area. + gl.enable(gl.SCISSOR_TEST); + gl.scissor(40, 20, 60, 130); + + // Clear the drawing buffer solid yellow. + gl.clearColor(1.0, 1.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); +}, false); +</pre> + +<p>The source code of this example is also available on <a href="https://github.com/idofilin/webgl-by-example/tree/master/basic-scissoring">GitHub</a>.</p> +</div> +</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Color_masking","Learn/WebGL/By_example/Canvas_size_and_WebGL")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/by_example/boilerplate_1/index.html b/files/zh-cn/web/api/webgl_api/by_example/boilerplate_1/index.html new file mode 100644 index 0000000000..6abaf4b033 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/boilerplate_1/index.html @@ -0,0 +1,86 @@ +--- +title: Boilerplate 1 +slug: Web/API/WebGL_API/By_example/Boilerplate_1 +translation_of: Web/API/WebGL_API/By_example/Boilerplate_1 +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Canvas_size_and_WebGL","Learn/WebGL/By_example/Scissor_animation")}}</p> + +<div id="boilerplate-1"> +<div class="summary"> +<p>这个例子描述了从现在开始将要隐藏重复的代码片断,以及定义一个JavaScript函数复用以简化WebGL初始化。</p> +</div> + +<p>{{EmbedLiveSample("boilerplate-1-source",660,400)}}</p> + +<div id="boilerplate-1-intro"> +<h3 id="用于设置WebGL呈现上下文的复用代码">用于设置WebGL呈现上下文的复用代码</h3> + +<p>现在你很习惯看到相同的{{Glossary("HTML")}}, {{Glossary("CSS")}}和{{Glossary("JavaScript")}}重复一遍又一遍。所以我们从现在起要隐藏他们。这将使我们能够专注于代码最有趣的部分相关学习{{Glossary("WebGL")}}。</p> + +<p>特别是,在HTML的{{HTMLElement("p")}}元素包含一些描述性的文本页面也可以是错误消息;一个{{HTMLElement("canvas")}} 元素;和一个可选的{{HTMLElement("button")}}。CSS规则包含<code>body</code>, <code>canvas</code>, 和<code>button</code>。任何额外的冗余的CSS和HTML将不会显示在页面的具体的例子。</p> + +<p>在以下示例中,我们将使用一个JavaScript函数功能,<code>getRenderingContext()</code> ,来初始化{{domxref("WebGLRenderingContext","WebGL rendering context", "", 1)}}。现在,您应该能够了解什么功能。基本上,它得到了WebGL从画布元素,渲染上下文初始化绘图缓冲区,清除它黑色,并返回初始化上下文。在错误的情况下,它会显示一个错误消息,并返回 {{jsxref("null")}}。</p> + +<p>最后,所有JavaScript代码将运行在一个直接的函数,这是一种常见的JavaScript技术(see {{Glossary("Function")}})。函数声明和调用也将被隐藏。</p> +</div> + +<div id="boilerplate-1-source"> +<h3 id="HTML">HTML</h3> + +<pre class="brush: html"><p>[ Some descriptive text about the example. ]</p> +<button>[ Optional button element. ]</button> +<canvas>Your browser does not seem to support + HTML5 canvas.</canvas> +</pre> + +<h3 id="CSS">CSS</h3> + +<pre class="brush: css">body { + text-align : center; +} +canvas { + display : block; + width : 280px; + height : 210px; + margin : auto; + padding : 0; + border : none; + background-color : black; +} +button { + display : block; + font-size : inherit; + margin : auto; + padding : 0.6em; +} +</pre> + +<h3 id="JavaScript">JavaScript</h3> + +<pre class="brush: js">function getRenderingContext() { + var canvas = document.querySelector("canvas"); + canvas.width = canvas.clientWidth; + canvas.height = canvas.clientHeight; + var gl = canvas.getContext("webgl") + || canvas.getContext("experimental-webgl"); + if (!gl) { + var paragraph = document.querySelector("p"); + paragraph.innerHTML = "Failed to get WebGL context." + + "Your browser or device may not support WebGL."; + return null; + } + gl.viewport(0, 0, + gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.clearColor(0.0, 0.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + return gl; +} +</pre> + +<p>The source code of this example is also available on <a href="https://github.com/idofilin/webgl-by-example/tree/master/boilerplate-1">GitHub</a>.</p> +</div> +</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Canvas_size_and_WebGL","Learn/WebGL/By_example/Scissor_animation")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/by_example/canvas_size_and_webgl/index.html b/files/zh-cn/web/api/webgl_api/by_example/canvas_size_and_webgl/index.html new file mode 100644 index 0000000000..518571028d --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/canvas_size_and_webgl/index.html @@ -0,0 +1,80 @@ +--- +title: Canvas size and WebGL +slug: Web/API/WebGL_API/By_example/Canvas_size_and_WebGL +translation_of: Web/API/WebGL_API/By_example/Canvas_size_and_WebGL +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Basic_scissoring","Learn/WebGL/By_example/Boilerplate_1")}}</p> + +<div class="summary"> +<p><span class="seoSummary">此WebGL案例将探究设置(或不设置)Canvas属性的宽高值在浏览器中显示的影响。</span></p> +</div> + +<div id="canvas-size-and-webgl"> +<p>{{EmbedLiveSample("canvas-size-and-webgl-source",660,180)}}</p> + +<div id="canvas-size-and-webgl-intro"> +<h3 id="canvas属性值大小对WebGL渲染的作用">canvas属性值大小对WebGL渲染的作用</h3> + +<p>使用 {{domxref("WebGLRenderingContext.scissor()","scissor()")}} 和 {{domxref("WebGLRenderingContext.clear()","clear()")}} 我们可以观察到canvas属性大小是如何影响WebGL绘图展示的。</p> + +<p>第一个canvas元素通过css样式定义了元素的大小,之后通过javascript获取该元素的 {{domxref("Element.clientWidth","clientWidth")}} 和{{domxref("Element.clientHeight","clientHeight")}} 值,并分别赋值给元素的 {{domxref("HTMLCanvasElement.width","width")}} 和{{domxref("HTMLCanvasElement.height","height")}}。</p> + +<p>相反的,第二个canvas元素并没有这样做,canvas内部对象的{{domxref("HTMLCanvasElement.width","width")}} 和 {{domxref("HTMLCanvasElement.height","height")}} 属性值仍然是默认值,这样导致在浏览器中实际画布大小是不同的。</p> + +<p>使用 {{domxref("WebGLRenderingContext.scissor()","scissor()")}} 和{{domxref("WebGLRenderingContext.clear()","clear()")}}在canvas中绘制矩形的效果是清晰可见的,在第一个canvas中,通过指定位置和像素大小,可以得到我们想要的效果,但是在第二个canvas中,这个矩形的位置、大小都是错误展示的。</p> +</div> + +<div id="canvas-size-and-webgl-source"> +<pre class="brush: html"><p>Compare the two canvases.</p> +<canvas>Your browser does not seem to support + HTML5 canvas.</canvas> +<canvas>Your browser does not seem to support + HTML5 canvas.</canvas> +</pre> + +<pre class="brush: css">body { + text-align : center; +} +canvas { + display : inline-block; + width : 120px; + height : 80px; + margin : auto; + padding : 0; + border : none; + background-color : black; +} +</pre> + +<pre class="brush: js">window.addEventListener("load", function() { + "use strict" + var firstCanvas = document.getElementsByTagName("canvas")[0], + secondCanvas = document.getElementsByTagName("canvas")[1]; + firstCanvas.width = firstCanvas.clientWidth; + firstCanvas.height = firstCanvas.clientHeight; + [firstCanvas, secondCanvas].forEach(function(canvas) { + var gl = canvas.getContext("webgl") + || canvas.getContext("experimental-webgl"); + if (!gl) { + document.querySelector("p").innerHTML = + "Failed to get WebGL context. " + + "Your browser or device may not support WebGL."; + return; + } + gl.viewport(0, 0, + gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.enable(gl.SCISSOR_TEST); + gl.scissor(30, 10, 60, 60); + gl.clearColor(1.0, 1.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + }); +}, false); +</pre> + +<p>The source code of this example is also available on <a href="https://github.com/idofilin/webgl-by-example/tree/master/canvas-size-and-webgl">GitHub</a>.</p> +</div> +</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Basic_scissoring","Learn/WebGL/By_example/Boilerplate_1")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/by_example/clearing_by_clicking/index.html b/files/zh-cn/web/api/webgl_api/by_example/clearing_by_clicking/index.html new file mode 100644 index 0000000000..c484f63439 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/clearing_by_clicking/index.html @@ -0,0 +1,109 @@ +--- +title: Clearing by clicking +slug: Web/API/WebGL_API/By_example/Clearing_by_clicking +translation_of: Web/API/WebGL_API/By_example/Clearing_by_clicking +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Clearing_with_colors","Learn/WebGL/By_example/Simple_color_animation")}}</p> + +<div id="clearing-by-clicking"> +<div class="summary"> +<p><span class="seoSummary">此示例演示了如何通过用户单击时用随机颜色渲染上下文来将用户交互与WebGL图形操作结合起来。</span></p> +</div> + +<p>{{EmbedLiveSample("clearing-by-clicking-source",660,425)}}</p> + +<div id="clearing-by-clicking-intro"> +<h3 id="用随机颜色渲染上下文">用随机颜色渲染上下文</h3> + +<p>这个例子提供了一个简单的例子,说明如何结合 {{Glossary("WebGL")}} 和用户交互。每次用户点击画布或按钮时,画布都会使用一种新的随机色。</p> + +<p>注意我们如何在事件处理函数中嵌入 {{Glossary("WebGL")}} 函数调用。</p> +</div> + +<div id="clearing-by-clicking-source"> +<pre class="brush: html"><p>A very simple WebGL program that still shows some color and + user interaction.</p> +<p>You can repeatedly click the empty canvas or the button below + to change color.</p> +<canvas id="canvas-view">Your browser does not seem to support + HTML5 canvas.</canvas> +<button id="color-switcher">Press here to switch color</button> +</pre> + +<pre class="brush: css">body { + text-align : center; +} +canvas { + display : block; + width : 280px; + height : 210px; + margin : auto; + padding : 0; + border : none; + background-color : black; +} +button { + display : inline-block; + font-size : inherit; + margin : auto; + padding : 0.6em; +} +</pre> + +<pre class="brush: js">window.addEventListener("load", function setupWebGL (evt) { + "use strict" + + // Cleaning after ourselves. The event handler removes + // itself, because it only needs to run once. + window.removeEventListener(evt.type, setupWebGL, false); + + // 给 canvas 和 button 添加相同的时间处理器 + var canvas = document.querySelector("#canvas-view"); + var button = document.querySelector("#color-switcher"); + canvas.addEventListener("click", switchColor, false); + button.addEventListener("click", switchColor, false); + + // 存放 WebGLRenderingContext 的变量 + var gl; + + // 点击事件处理器 + function switchColor () { + // Referring to the externally defined gl variable. + // If undefined, try to obtain the WebGLRenderingContext. + // If failed, alert user of failure. + // Otherwise, initialize the drawing buffer (the viewport). + if (!gl) { + gl = canvas.getContext("webgl") + || canvas.getContext("experimental-webgl"); + if (!gl) { + alert("Failed to get WebGL context.\n" + + "Your browser or device may not support WebGL."); + return; + } + gl.viewport(0, 0, + gl.drawingBufferWidth, gl.drawingBufferHeight); + } + // 使用辅助函数获取一种随机色 + var color = getRandomColor(); + // 用随机色设置底色 + gl.clearColor(color[0], color[1], color[2], 1.0); + // Clear the context with the newly set color. This is + // the function call that actually does the drawing. + gl.clear(gl.COLOR_BUFFER_BIT); + } + + // 随机颜色辅助函数 + function getRandomColor() { + return [Math.random(), Math.random(), Math.random()]; + } + +}, false); +</pre> + +<p>这个例子的代码可以在 <a href="https://github.com/idofilin/webgl-by-example/tree/master/clearing-by-clicking">GitHub</a> 上下载。</p> +</div> +</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Clearing_with_colors","Learn/WebGL/By_example/Simple_color_animation")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/by_example/clearing_with_colors/index.html b/files/zh-cn/web/api/webgl_api/by_example/clearing_with_colors/index.html new file mode 100644 index 0000000000..3872526cb8 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/clearing_with_colors/index.html @@ -0,0 +1,99 @@ +--- +title: 清除画布 +slug: Web/API/WebGL_API/By_example/Clearing_with_colors +translation_of: Web/API/WebGL_API/By_example/Clearing_with_colors +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Detect_WebGL","Learn/WebGL/By_example/Clearing_by_clicking")}}</p> + +<div id="clearing-with-colors"> +<div class="summary"> +<p>这个例子将展示如何用一个单色清除画布</p> +</div> + +<p>{{EmbedLiveSample("clearing-with-colors-source",660,425)}}</p> + +<div id="clearing-with-colors-intro"> +<h3 id="清除画布(使用单一颜色清除WebGl区域)">清除画布(使用单一颜色清除WebGl区域)</h3> + +<p>这是一个最简单的WebGL代码。通过{{domxref("WebGLRenderingContext","rendering context", "", 1)}}设置好状态后,直接将整个区域清除为绿色。要注意css 已经将canvas画布设置为黑色了,所以当画布变为绿色时,我们就知道神奇的WebGL魔法起作用了!</p> + +<p>此外,你需要注意用单色绘制图像是两个步骤:首先,通过使用{{domxref("WebGLRenderingContext.clearColor()","clearColor()")}}设置清除色为绿色。这只会改变Webgl 内部的一个状态,但并不会绘制任何东西。接下来,我们就真的开始绘制了,使用{{domxref("WebGLRenderingContext.clear()","clear()")}}方法,这是一个典型的用webgl绘制的方法,webgl 实际上只有少数的几个绘制方法(clear() 就是其中之一)。其他方法大多都是类似设置或改变WebGl状态和变量的(例如设置clearcolor)。</p> + +<p>这里有许多属性和方法作用于Webgl,清除方法只是你第一个掌握的,这也就是为什么WebGL/OpenGl经常被叫做状态机,通过调整这些属性和方法可以修改WebGL内部的状态,从而进行输出(例如先设置好绿色,在清除画布的时候像素点都变成了绿色)</p> + +<p>最后,我们知道在WebGl中颜色格式是由RGBA(红,绿,蓝,透明度)组成的,因此clearColor()方法接受四个参数</p> + +<p> </p> +</div> + +<div id="clearing-with-colors-source"> +<pre class="brush: html"><p>A very simple WebGL program that shows some color.</p> +<!-- Text within a canvas element is displayed + only if canvas is not supported. --> +<canvas>Your browser does not seem to support + HTML5 canvas.</canvas> +</pre> + +<pre class="brush: css">body { + text-align : center; +} +canvas { + display : block; + width : 280px; + height : 210px; + margin : auto; + padding : 0; + border : none; + background-color : black; +} +</pre> + +<pre class="brush: js">// Run everything inside window load event handler, to make sure +// DOM is fully loaded and styled before trying to manipulate it, +// and to not mess up the global scope. We are giving the event +// handler a name (setupWebGL) so that we can refer to the +// function object within the function itself. +window.addEventListener("load", function setupWebGL (evt) { + "use strict" + + // Cleaning after ourselves. The event handler removes + // itself, because it only needs to run once. + window.removeEventListener(evt.type, setupWebGL, false); + + // References to the document elements. + var paragraph = document.querySelector("p"), + canvas = document.querySelector("canvas"); + + // Getting the WebGL rendering context. + var gl = canvas.getContext("webgl") + || canvas.getContext("experimental-webgl"); + + // If failed, inform user of failure. Otherwise, initialize + // the drawing buffer (the viewport) and clear the context + // with a solid color. + if (!gl) { + paragraph.innerHTML = "Failed to get WebGL context. " + + "Your browser or device may not support WebGL."; + return; + } + paragraph.innerHTML = + "Congratulations! Your browser supports WebGL. "; + gl.viewport(0, 0, + gl.drawingBufferWidth, gl.drawingBufferHeight); + // Set the clear color to darkish green. + gl.clearColor(0.0, 0.5, 0.0, 1.0); + // Clear the context with the newly set color. This is + // the function call that actually does the drawing. + gl.clear(gl.COLOR_BUFFER_BIT); + +}, false); + +</pre> + +<p>这个例子的代码可以在 <a href="https://github.com/idofilin/webgl-by-example/tree/master/clearing-with-colors">GitHub</a> 上下载。</p> +</div> +</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Detect_WebGL","Learn/WebGL/By_example/Clearing_by_clicking")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/by_example/color_masking/index.html b/files/zh-cn/web/api/webgl_api/by_example/color_masking/index.html new file mode 100644 index 0000000000..7fac11d398 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/color_masking/index.html @@ -0,0 +1,128 @@ +--- +title: Color masking +slug: Web/API/WebGL_API/By_example/Color_masking +translation_of: Web/API/WebGL_API/By_example/Color_masking +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Simple_color_animation","Learn/WebGL/By_example/Basic_scissoring")}}</p> + +<div id="color-masking"> +<div class="summary"> +<p><span class="seoSummary">这个 WebGL 示例 通过随机的颜色(random colors)应用到colorMask,从而将显示的颜色范围限制在特定的颜色通道(red/green/blue);</span></p> +</div> + +<p>{{EmbedLiveSample("color-masking-source",660,425)}}</p> + +<div id="color-masking-intro"> +<h3 id="Masking_random_colors">Masking random colors</h3> + +<p>This example modifies the random color animation by applying color masking with {{domxref("WebGLRenderingContext.colorMask()","colorMask()")}}. You can think of the color masking operation as if looking at the colored canvas through some tinted glass or color filter. So, by masking off the blue and green channels, you are only allowing the red component of pixels to be updated, and therefore it is as if you were looking through a red tinted glass.</p> + +<p>Color masking allows us to demonstrate some basics of <a href="https://en.wikipedia.org/wiki/Color_theory">color theory</a>. By masking off some channel(s), we are in fact biasing the displayed colors towards the complementary color. So, clearly masking both blue and red, would give us shades of green. Masking only the blue channel would give us shades of yellow (including shades of orange, brown, olive and yellow-green), the complementary of blue. Similarly, masking only green would give us shades of magenta (also purples, crimsons, and so on), and masking only red would give shades of cyan (also sea greens, blues, and so on).</p> + +<p>Note that the calls to <code>colorMask()</code> only occur when the user clicks on one of the toggle buttons. But rendering is done every second, using the timer. The color mask state of {{Glossary("WebGL")}} is preserved, so we do not need to call <code>colorMask()</code> every frame to set up the color mask. This is an important aspect of the WebGL state machine. It allows us to setup WebGL in a single initialization phase, and then just execute drawing commands for each frame.</p> + +<p>Color masking gives you fine control of updating pixel values on the screen. By limiting the color channels that are written by each drawing command, you can use each channel, for example, to store a different grayscale image. Alternatively, you may use the {{Glossary("RGB")}} components for color, but the alpha component for some custom pixel data of your invention.</p> + +<p>Finally, color masking teaches us that {{Glossary("WebGL")}} is not only a state machine, it is also a <em>graphics pipeline</em>. This means that graphics operations in WebGL are done in a certain order, where the output of each operation serves as the input of the next. So, for example, clearing operation sets the value of each pixel to the chosen clear color. Masking occurs later in the pipeline, and modifies the pixel color value, so the final result on the screen is that of the clear color, tinted by the color mask.</p> +</div> + +<div id="color-masking-source"> +<pre class="brush: html"><p>Tinting the displayed colors with color masking.</p> +<canvas>Your browser does not seem to support + HTML5 canvas.</canvas> +<button id="red-toggle">On</button> +<button id="green-toggle">On</button> +<button id="blue-toggle">On</button> +</pre> + +<pre class="brush: css">body { + text-align : center; +} +canvas { + display : block; + width : 280px; + height : 210px; + margin : auto; + padding : 0; + border : none; + background-color : black; +} +button { + display : inline-block; + font-family : serif; + font-size : inherit; + font-weight : 900; + color : white; + margin : auto; + padding : 0.6em 1.2em; +} +#red-toggle { + background-color : red; +} +#green-toggle { + background-color : green; +} +#blue-toggle { + background-color : blue; +} +</pre> + +<pre class="brush: js" id="livesample-js">window.addEventListener("load", function setupAnimation (evt) { + "use strict" + window.removeEventListener(evt.type, setupAnimation, false); + + var canvas = document.querySelector("canvas"); + var gl = canvas.getContext("webgl") + || canvas.getContext("experimental-webgl"); + if (!gl) { + document.querySelector("p").innerHTML = + "Failed to get WebGL context." + + "Your browser or device may not support WebGL."; + return; + } + gl.viewport(0, 0, + gl.drawingBufferWidth, gl.drawingBufferHeight); + + var timer = setInterval(drawAnimation, 1000); + + var mask = [true, true, true]; + var redtoggle = document.querySelector("#red-toggle"), + greentoggle = document.querySelector("#green-toggle"), + bluetoggle = document.querySelector("#blue-toggle"); + redtoggle.addEventListener("click", setColorMask, false); + greentoggle.addEventListener("click", setColorMask, false); + bluetoggle.addEventListener("click", setColorMask, false); + + function setColorMask(evt) { + var index = + evt.target === greentoggle && 1 + || evt.target === bluetoggle && 2 + || 0; + mask[index] = !mask[index]; + if (mask[index] === true) + evt.target.innerHTML="On"; + else + evt.target.innerHTML="Off"; + gl.colorMask(mask[0], mask[1], mask[2], true); + drawAnimation(); + }; + + function drawAnimation () { + var color = getRandomColor(); + gl.clearColor(color[0], color[1], color[2], 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + } + + function getRandomColor() { + return [Math.random(), Math.random(), Math.random()]; + } +}, false); +</pre> + +<p>The source code of this example is also available on <a href="https://github.com/idofilin/webgl-by-example/tree/master/color-masking">GitHub</a>.</p> +</div> +</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Simple_color_animation","Learn/WebGL/By_example/Basic_scissoring")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/by_example/detect_webgl/index.html b/files/zh-cn/web/api/webgl_api/by_example/detect_webgl/index.html new file mode 100644 index 0000000000..0836880bbf --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/detect_webgl/index.html @@ -0,0 +1,73 @@ +--- +title: 检测WebGL +slug: Web/API/WebGL_API/By_example/Detect_WebGL +translation_of: Web/API/WebGL_API/By_example/Detect_WebGL +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{PreviousNext("Learn/WebGL/By_example","Learn/WebGL/By_example/Clearing_with_colors")}}</p> + +<div id="detect-webgl"> +<div class="summary"> +<p>这个例子演示了如何通过渲染上下文来检测{{Glossary("WebGL")}},并将结果报告给用户。</p> +</div> + +<p>{{EmbedLiveSample("detect-webgl-source",660,150)}}</p> + +<div id="detect-webgl-intro"> +<h3 id="WebGL特性检测">WebGL特性检测</h3> + +<p>在第一个例子中,我们将检查浏览器是否支持{{Glossary("WebGL")}}。为此,我们将尝试从{{domxref("HTMLCanvasElement","canvas")}}元素获取{{domxref("WebGLRenderingContext","WebGL渲染的上下文","",1)}} 。{{domxref("WebGLRenderingContext","WebGL渲染的上下文", "", 1)}}是一个接口,通过它你可以设置和查询绘图器的状态,发送数据到WebGL,执行绘制命令。</p> + +<p>在单个上下文接口中保存绘图器的状态并不是{{Glossary("WebGL")}}独有的。这在其他绘图技术里也是存在的{{Glossary("API")}},比如{{domxref("CanvasRenderingContext2D","2D渲染上下文的canvas", "", 1)}}。然而,您可以调整的属性和变量对于每个{{Glossary("API")}}来说都是不同的。</p> +</div> + +<div id="detect-webgl-source"> +<pre class="brush: html"><p>[ Here would go the result of WebGL feature detection ]</p> +<button>Press here to detect WebGLRenderingContext</button> +</pre> + +<pre class="brush: css">body { + text-align : center; +} +button { + display : block; + font-size : inherit; + margin : auto; + padding : 0.6em; +} +</pre> + +<pre class="brush: js">// Run everything inside window load event handler, to make sure +// DOM is fully loaded and styled before trying to manipulate it. +window.addEventListener("load", function() { + var paragraph = document.querySelector("p"), + button = document.querySelector("button"); + // Adding click event handler to button. + button.addEventListener("click", detectWebGLContext, false); + function detectWebGLContext () { + // Create canvas element. The canvas is not added to the + // document itself, so it is never displayed in the + // browser window. + var canvas = document.createElement("canvas"); + // Get WebGLRenderingContext from canvas element. + var gl = canvas.getContext("webgl") + || canvas.getContext("experimental-webgl"); + // Report the result. + if (gl && gl instanceof WebGLRenderingContext) { + paragraph.innerHTML = + "Congratulations! Your browser supports WebGL."; + } else { + paragraph.innerHTML = "Failed to get WebGL context. " + + "Your browser or device may not support WebGL."; + } + } +}, false); + +</pre> + +<p>这个例子的源代码可以在<a href="https://github.com/idofilin/webgl-by-example/tree/master/detect-webgl">GitHub</a>上获取。</p> +</div> +</div> + +<p>{{PreviousNext("Learn/WebGL/By_example","Learn/WebGL/By_example/Clearing_with_colors")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/by_example/hello_glsl/index.html b/files/zh-cn/web/api/webgl_api/by_example/hello_glsl/index.html new file mode 100644 index 0000000000..cb1034bcdb --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/hello_glsl/index.html @@ -0,0 +1,168 @@ +--- +title: Hello GLSL +slug: Web/API/WebGL_API/By_example/Hello_GLSL +translation_of: Web/API/WebGL_API/By_example/Hello_GLSL +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Raining_rectangles","Learn/WebGL/By_example/Hello_vertex_attributes")}}</p> + +<div id="hello-glsl"> +<div class="summary"> +<p id="hello-glsl-summary"><span class="seoSummary">该例子将演示一个绘制固态颜色的矩形的简单着色器程序。</span></p> +</div> + +<div class="note"> +<p><strong>注意:</strong>本例子能在大多数现代桌面版浏览器上运行。但或许不能在移动端或者古老的浏览器上运行。如果canvas显示一片空白,你可以试着用下一个例子检查一下输出是否绘制的是同样的图形。 但要记住在前往下一个例子之前,要仔细阅读本页并动手写代码。</p> +</div> + +<p>{{EmbedLiveSample("hello-glsl-source",660,425)}}</p> + +<div id="hello-glsl-intro"> +<h3 id="用GLSL语言写Hello_World_程序">用GLSL语言写Hello World 程序</h3> + +<p>第一个非常简单的着色器程序。</p> +</div> + +<div id="hello-glsl-source"> +<div class="hidden"> +<pre class="brush: html"><p>Hello World! Hello GLSL!</p> +</pre> + +<pre class="brush: html"><canvas>Your browser does not seem to support + HTML5 canvas.</canvas> +</pre> + +<pre class="brush: css">body { + text-align : center; +} +canvas { + width : 280px; + height : 210px; + margin : auto; + padding : 0; + border : none; + background-color : black; +} +button { + display : block; + font-size : inherit; + margin : auto; + padding : 0.6em; +} +</pre> +</div> + +<pre class="brush: html"><script type="x-shader/x-vertex" id="vertex-shader"> +#version 100 +void main() { + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); + gl_PointSize = 64.0; +} +</script> +</pre> + +<pre class="brush: html"><script type="x-shader/x-fragment" id="fragment-shader"> +#version 100 +void main() { + gl_FragColor = vec4(0.18, 0.54, 0.34, 1.0); +} +</script> +</pre> + +<div class="hidden"> +<pre class="brush: js">;(function(){ +</pre> +</div> + +<pre class="brush: js" id="livesample-js">"use strict" +window.addEventListener("load", setupWebGL, false); +var gl, + program; +function setupWebGL (evt) { + window.removeEventListener(evt.type, setupWebGL, false); + if (!(gl = getRenderingContext())) + return; + + var source = document.querySelector("#vertex-shader").innerHTML; + var vertexShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertexShader,source); + gl.compileShader(vertexShader); + source = document.querySelector("#fragment-shader").innerHTML + var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragmentShader,source); + gl.compileShader(fragmentShader); + program = gl.createProgram(); + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + gl.linkProgram(program); + gl.detachShader(program, vertexShader); + gl.detachShader(program, fragmentShader); + gl.deleteShader(vertexShader); + gl.deleteShader(fragmentShader); + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + var linkErrLog = gl.getProgramInfoLog(program); + cleanup(); + document.querySelector("p").innerHTML = + "Shader program did not link successfully. " + + "Error log: " + linkErrLog; + return; + } + + initializeAttributes(); + + gl.useProgram(program); + gl.drawArrays(gl.POINTS, 0, 1); + + cleanup(); +} + +var buffer; +function initializeAttributes() { + gl.enableVertexAttribArray(0); + buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0); +} + +function cleanup() { +gl.useProgram(null); +if (buffer) + gl.deleteBuffer(buffer); +if (program) + gl.deleteProgram(program); +} +</pre> + +<div class="hidden"> +<pre class="brush: js">function getRenderingContext() { + var canvas = document.querySelector("canvas"); + canvas.width = canvas.clientWidth; + canvas.height = canvas.clientHeight; + var gl = canvas.getContext("webgl") + || canvas.getContext("experimental-webgl"); + if (!gl) { + var paragraph = document.querySelector("p"); + paragraph.innerHTML = "Failed to get WebGL context." + + "Your browser or device may not support WebGL."; + return null; + } + gl.viewport(0, 0, + gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.clearColor(0.0, 0.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + return gl; +} +</pre> +</div> + +<div class="hidden"> +<pre class="brush: js">})(); +</pre> +</div> + +<p>该例子的源代码能在 <a href="https://github.com/idofilin/webgl-by-example/tree/master/hello-glsl">GitHub</a>获得。</p> +</div> +</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Raining_rectangles","Learn/WebGL/By_example/Hello_vertex_attributes")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/by_example/index.html b/files/zh-cn/web/api/webgl_api/by_example/index.html new file mode 100644 index 0000000000..3ff18aed61 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/index.html @@ -0,0 +1,75 @@ +--- +title: WebGL 的例子 +slug: Web/API/WebGL_API/By_example +translation_of: Web/API/WebGL_API/By_example +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{Next("Learn/WebGL/By_example/Detect_WebGL")}}</p> + +<div id="webgl-by-example"> +<div class="summary"> +<p>WebGL <em>例子</em>是一系列附有简短的解释的样本用来展示WebGL的概念和功能。这些示例根据主题和难度级别进行排序,涵盖WebGL渲染上下文,着色器编程,纹理,几何图形,用户交互等。</p> +</div> + +<div id="webgl-by-example-big-list"> +<h2 id="主题例子">主题例子</h2> + +<p>这些范例是有浅到深的,它们除了是一个个可以让你实现的例子外,还和主题高度重合,当我们需要在中级和高级阶段实现这个例子时有时我们会重复此例子的基础内容。</p> + +<p>在第一个程序中,并没有尝试着色着色器,几何图形和使用{{Glossary("GPU")}} 内存,这里的示例以渐进的方式探索WebGL。我们相信它会带来更有效的学习体验,并最终更深入地理解底层概念。</p> + +<p>有关这些例子的解释可以在代码的正文和注释中找到。您应该阅读所有注释,因为更高级的示例不会重复注释以前的代码。</p> + +<div> +<h3 id="开始了解渲染上下文">开始了解渲染上下文</h3> + +<dl> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Detect_WebGL">检测 WebGL</a></dt> + <dd>这个例子演示如何检测 {{Glossary("WebGL")}} 渲染上下文并且反馈给用户。</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Clearing_with_colors">Clearing with colors</a></dt> + <dd>How to clear the rendering context with a solid color.</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Clearing_by_clicking">Clearing by clicking</a></dt> + <dd>How to combine user interaction with graphics operations. Clearing the rendering context with a random color when the user clicks.</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Simple_color_animation">Simple color animation</a></dt> + <dd>A very basic color animation, done by clearing the {{Glossary("WebGL")}} drawing buffer with a different random color every second.</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Color_masking">Color masking</a></dt> + <dd>Modifying random colors by applying color masking and thus limiting the range of displayed colors to specific shades.</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Basic_scissoring">Basic scissoring</a></dt> + <dd>How to draw simple rectangles and squares with scissoring operations.</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Canvas_size_and_WebGL">Canvas size and WebGL</a></dt> + <dd>The example explores the effect of setting (or not setting) the canvas size to its element size in {{Glossary("CSS")}} pixels, as it appears in the browser window.</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Boilerplate_1">Boilerplate 1</a></dt> + <dd>The example describes repeated pieces of code that will be hidden from now on, as well as defining a JavaScript utility function to make WebGL initialization easier.</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Scissor_animation">Scissor animation</a></dt> + <dd>Some animation fun with scissoring and clearing operations.</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Raining_rectangles">Raining rectangles</a></dt> + <dd>A simple game that demonstrates clearing with solid colors, scissoring, animation, and user interaction.</dd> +</dl> +</div> + +<div> +<h3 id="Shader_programming_basics">Shader programming basics</h3> + +<dl> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Hello_GLSL">Hello GLSL</a></dt> + <dd>A very basic shader program that draws a solid color square.</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Hello_vertex_attributes">Hello vertex attributes</a></dt> + <dd>Combining shader programming and user interaction through vertex attributes.</dd> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Textures_from_code">Textures from code</a></dt> + <dd>A simple demonstration of procedural texturing with fragment shaders.</dd> +</dl> +</div> + +<div> +<h3 id="Miscellaneous_advanced_examples">Miscellaneous advanced examples</h3> + +<dl> + <dt><a href="/en-US/docs/Learn/WebGL/By_example/Video_textures">Video textures</a></dt> + <dd>This example demonstrates how to use video files as textures.</dd> +</dl> +</div> +</div> +</div> + +<p>{{Next("Learn/WebGL/By_example/Detect_WebGL")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/by_example/scissor_animation/index.html b/files/zh-cn/web/api/webgl_api/by_example/scissor_animation/index.html new file mode 100644 index 0000000000..1acfafd28a --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/scissor_animation/index.html @@ -0,0 +1,166 @@ +--- +title: Scissor animation +slug: Web/API/WebGL_API/By_example/Scissor_animation +translation_of: Web/API/WebGL_API/By_example/Scissor_animation +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Boilerplate_1","Learn/WebGL/By_example/Raining_rectangles")}}</p> + +<div id="scissor-animation"> +<div class="summary"> +<p>使用剪切和清除操作实现一些动画的简单WebGL的例子。</p> +</div> + +<p>{{EmbedLiveSample("scissor-animation-source",660,425)}}</p> + +<div> +<h3 id="剪切动画">剪切动画</h3> + +<p>本例中,我们使用{{domxref("WebGLRenderingContext.scissor()","scissor()")}} 和 {{domxref("WebGLRenderingContext.clear()","clear()")}}。我们再次建立一个动画循环使用计时器。注意,这次是方块的位置(剪切区)更新每一帧(我们设置帧率大约每17毫秒,约60 fps -帧每秒)</p> + +<p>相比之下,方块的颜色(用{{domxref("WebGLRenderingContext.clearColor()","clearColor")}})仅创建一个新的方块。这是一个很好的演示{{Glossary("WebGL")}}是一个状态机。对于每一个方块,我们设置它的颜色,然后只更新它的位置每一帧。WebGL的清晰的颜色状态维持在设定值,直到我们再次改变它创建一个新的方块。</p> +</div> + +<div id="scissor-animation-source"> +<div class="hidden"> +<pre class="brush: html"><p>WebGL animation by clearing the drawing buffer with solid +color and applying scissor test.</p> +<button id="animation-onoff"> + Press here to +<strong>[verb goes here]</strong> + the animation</button> +</pre> + +<pre class="brush: html"><canvas>Your browser does not seem to support + HTML5 canvas.</canvas> +</pre> + +<pre class="brush: css">body { + text-align : center; +} +canvas { + display : block; + width : 280px; + height : 210px; + margin : auto; + padding : 0; + border : none; + background-color : black; +} +button { + display : block; + font-size : inherit; + margin : auto; + padding : 0.6em; +} +</pre> +</div> + +<div class="hidden"> +<pre class="brush: js">;(function(){ +</pre> +</div> + +<pre class="brush: js" id="livesample-js">"use strict" +window.addEventListener("load", setupAnimation, false); +// Variables to hold the WebGL context, and the color and +// position of animated squares. +var gl, + color = getRandomColor(), + position; + +function setupAnimation (evt) { + window.removeEventListener(evt.type, setupAnimation, false); + if (!(gl = getRenderingContext())) + return; + + gl.enable(gl.SCISSOR_TEST); + gl.clearColor(color[0], color[1], color[2], 1.0); + // Unlike the browser window, vertical position in WebGL is + // measured from bottom to top. In here we set the initial + // position of the square to be at the top left corner of the + // drawing buffer. + position = [0, gl.drawingBufferHeight]; + + var button = document.querySelector("button"); + var timer; + function startAnimation(evt) { + button.removeEventListener(evt.type, startAnimation, false); + button.addEventListener("click", stopAnimation, false); + document.querySelector("strong").innerHTML = "stop"; + timer = setInterval(drawAnimation, 17); + drawAnimation(); + } + function stopAnimation(evt) { + button.removeEventListener(evt.type, stopAnimation, false); + button.addEventListener("click", startAnimation, false); + document.querySelector("strong").innerHTML = "start"; + clearInterval(timer); + } + stopAnimation({type: "click"}); +} + +// Variables to hold the size and velocity of the square. +var size = [60, 60], + velocity = 3.0; +function drawAnimation () { + gl.scissor(position[0], position[1], size[0] , size[1]); + gl.clear(gl.COLOR_BUFFER_BIT); + // Every frame the vertical position of the square is + // decreased, to create the illusion of movement. + position[1] -= velocity; + // When the sqaure hits the bottom of the drawing buffer, + // we override it with new square of different color and + // velocity. + if (position[1] < 0) { + // Horizontal position chosen randomly, and vertical + // position at the top of the drawing buffer. + position = [ + Math.random()*(gl.drawingBufferWidth - size[0]), + gl.drawingBufferHeight + ]; + // Random velocity between 1.0 and 7.0 + velocity = 1.0 + 6.0*Math.random(); + color = getRandomColor(); + gl.clearColor(color[0], color[1], color[2], 1.0); + } +} + +function getRandomColor() { + return [Math.random(), Math.random(), Math.random()]; +} +</pre> + +<div class="hidden"> +<pre class="brush: js">function getRenderingContext() { + var canvas = document.querySelector("canvas"); + canvas.width = canvas.clientWidth; + canvas.height = canvas.clientHeight; + var gl = canvas.getContext("webgl") + || canvas.getContext("experimental-webgl"); + if (!gl) { + var paragraph = document.querySelector("p"); + paragraph.innerHTML = "Failed to get WebGL context." + + "Your browser or device may not support WebGL."; + return null; + } + gl.viewport(0, 0, + gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.clearColor(0.0, 0.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + return gl; +} +</pre> +</div> + +<div class="hidden"> +<pre class="brush: js">})(); +</pre> +</div> + +<p>The source code of this example is also available on <a href="https://github.com/idofilin/webgl-by-example/tree/master/scissor-animation">GitHub</a>.</p> +</div> +</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Boilerplate_1","Learn/WebGL/By_example/Raining_rectangles")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/by_example/simple_color_animation/index.html b/files/zh-cn/web/api/webgl_api/by_example/simple_color_animation/index.html new file mode 100644 index 0000000000..e4dbc5eb09 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/by_example/simple_color_animation/index.html @@ -0,0 +1,120 @@ +--- +title: Simple color animation +slug: Web/API/WebGL_API/By_example/Simple_color_animation +translation_of: Web/API/WebGL_API/By_example/Simple_color_animation +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Clearing_by_clicking","Learn/WebGL/By_example/Color_masking")}}</p> + +<div id="simple-color-animation"> +<div class="summary"> +<p><span class="seoSummary">这是一个非常基础的{{Glossary("WebGL")}}色彩动画案例, 通过定时器来逐秒填充不同的颜色来实现.</span></p> +</div> + +<p>{{EmbedLiveSample("simple-color-animation-source",660,425)}}</p> + +<div id="simple-color-animation-intro"> +<h3 id="通过填充实现色彩动画">通过填充实现色彩动画</h3> + +<p>本案例使用{{Glossary("WebGL")}}来实现简单的色彩动画和用户交互效果, 用户可以通过按按钮来开始/暂停/重新开始动画.</p> + +<p>我们把 {{Glossary("WebGL")}}函数放在一个定时循环器里(<code>setInterval</code>) .通过监听点击事件来让用户开始/暂停动画.并通过定时器来循环执行绘制指令(通常是逐帧动画,这次我们设置为逐秒动画) </p> +</div> + +<div id="simple-color-animation-source"> +<pre class="brush: html"><p>一个色彩动画的简单WebGl程序</p> +<p>点击下面的按钮来开/关动画</p> +<canvas id="canvas-view">你的浏览器不支持Html5 canvas</canvas> +<button id="animation-onoff"> + 点我来 +<strong>[verb goes here]</strong> + 动画 +</button> +</pre> + +<pre class="brush: css">body { + text-align : center; +} +canvas { + display : block; + width : 280px; + height : 210px; + margin : auto; + padding : 0; + border : none; + background-color : black; +} +button { + display : inline-block; + font-size : inherit; + margin : auto; + padding : 0.6em; +} +</pre> + +<pre class="brush: js" id="livesample-js">window.addEventListener("load", function setupAnimation (evt) { + "use strict" + window.removeEventListener(evt.type, setupAnimation, false); + + // 定义一个变量来保存定时器,以播放动画 + var timer; + + // 点击事件处理器 + var button = document.querySelector("#animation-onoff"); + var verb = document.querySelector("strong"); + function startAnimation(evt) { + button.removeEventListener(evt.type, startAnimation, false); + button.addEventListener("click", stopAnimation, false); + verb.innerHTML="暂停"; + //设置一个循环来逐秒渲染动画 + timer = setInterval(drawAnimation, 1000); + // 在用户点击完以后立即执行一次动画 + drawAnimation(); + } + function stopAnimation(evt) { + button.removeEventListener(evt.type, stopAnimation, false); + button.addEventListener("click", startAnimation, false); + verb.innerHTML="开始"; + // 通过清除定时器来停止动画 + clearInterval(timer); + } + // 调用stopAnimation() 来初始化按钮的事件处理器 + stopAnimation({type: "click"}); + + var gl; + function drawAnimation () { + if (!gl) { + var canvas = document.getElementById("canvas-view"); + gl = canvas.getContext("webgl") + ||canvas.getContext("experimental-webgl"); + if (!gl) { + clearInterval(timer); + alert("Failed to get WebGL context.\n" + + "Your browser or device may not support WebGL."); + return; + } + gl.viewport(0, 0, + gl.drawingBufferWidth, gl.drawingBufferHeight); + } + + // 使用辅助函数 得到随机颜色 + var color = getRandomColor(); + // 将随机颜色设置到WebGL渲染上下文的填充颜色上去 + gl.clearColor(color[0], color[1], color[2], 1.0); + // 使用新设置的颜色来清除上下文 + gl.clear(gl.COLOR_BUFFER_BIT); + } + + //获取随机颜色的辅助函数 + function getRandomColor() { + return [Math.random(), Math.random(), Math.random()]; + } +}, false); +</pre> + +<p>在 <a href="https://github.com/idofilin/webgl-by-example/tree/master/simple-color-animation">GitHub</a>.上查看源码</p> +</div> +</div> + +<p>{{PreviousNext("Learn/WebGL/By_example/Clearing_by_clicking","Learn/WebGL/By_example/Color_masking")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/constants/index.html b/files/zh-cn/web/api/webgl_api/constants/index.html new file mode 100644 index 0000000000..fc023cbbc9 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/constants/index.html @@ -0,0 +1,4039 @@ +--- +title: WebGL 相关常量 +slug: Web/API/WebGL_API/Constants +translation_of: Web/API/WebGL_API/Constants +--- +<div>{{WebGLSidebar}}</div> + +<p><a href="/en-US/docs/Web/API/WebGL_API">WebGL API</a> 提供了一些常量,这些常量常作为参数传入函数调用,或常作为函数的返回值。所有这些常量都是 {{domxref("GLenum")}} 类型。</p> + +<p>标准WebGL常量挂载在WebGL的两个渲染上下文环境({{domxref("WebGLRenderingContext")}} 和{{domxref("WebGL2RenderingContext")}})中,因此,以形如<code>gl.CONSTANT_NAME</code>的形式使用WebGL常量:</p> + +<pre class="brush: js">var canvas = document.getElementById('myCanvas'); +var gl = canvas.getContext('webgl'); + +gl.getParameter(gl.LINE_WIDTH); +</pre> + +<p>其中一些常量也由 <a href="/en-US/docs/Web/API/WebGL_API/Using_Extensions">WebGL 扩展</a> 提供,如下方提供的 <a href="#Constants_defined_in_WebGL_extensions">清单</a>:</p> + +<pre class="brush: js">var debugInfo = gl.getExtension('WEBGL_debug_renderer_info'); +var vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);</pre> + +<p><a href="/en-US/docs/Web/API/WebGL_API/Tutorial" title="WebGL tutorial">WebGL tutorial</a> 中有更多关于WebGL的信息,示例和如何开始WebGL编程的其它资源。</p> + +<h2 id="常量表">常量表</h2> + +<ul> + <li><a href="#Standard_WebGL_1_constants">标准 WebGL 1 常量</a></li> + <li><a href="#Additional_constants_defined_WebGL_2">标准 WebGL 2 常量</a></li> + <li><a href="#Constants_defined_in_WebGL_extensions">WebGL 扩展常量</a></li> +</ul> + +<h2 id="标准_WebGL_1_常量">标准 WebGL 1 常量</h2> + +<p>这些常量定义在 {{domxref("WebGLRenderingContext")}} 接口中。</p> + +<h3 id="清除缓存">清除缓存</h3> + +<p>常量传入 {{domxref("WebGLRenderingContext.clear()")}} 作为清除缓冲区掩码(buffer masks)。</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>DEPTH_BUFFER_BIT</code></td> + <td>0x00000100</td> + <td>传递给 <code>clear</code> 来清除深度缓冲区。</td> + </tr> + <tr> + <td><code>STENCIL_BUFFER_BIT</code></td> + <td>0x00000400</td> + <td>传递给 <code>clear</code> 来清除当前模板缓冲区。</td> + </tr> + <tr> + <td><code>COLOR_BUFFER_BIT</code></td> + <td>0x00004000</td> + <td>传递给 <code>clear</code> 来清除颜色缓冲区。</td> + </tr> + </tbody> +</table> + +<h3 id="指定渲染图元_Rendering_primitives">指定渲染图元 Rendering primitives</h3> + +<p>传递给 {{domxref("WebGLRenderingContext.drawElements()")}} 或{{domxref("WebGLRenderingContext.drawArrays()")}} 的常量来指定要以何种原始类型渲染。</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>POINTS</code></td> + <td>0x0000</td> + <td>传递给 <code>drawElements</code> 或<code>drawArrays</code> 画点。</td> + </tr> + <tr> + <td><code>LINES</code></td> + <td>0x0001</td> + <td>传递给 <code>drawElements</code> 或<code>drawArrays</code> 画线段。 每个顶点链接到它的下一个顶点。每两点画一条线段。</td> + </tr> + <tr> + <td><code>LINE_LOOP</code></td> + <td>0x0002</td> + <td>传递给 <code>drawElements</code> 或<code>drawArrays</code> 画回路。 每两个点被当作是一条独立的线段。线段首尾相连。</td> + </tr> + <tr> + <td><code>LINE_STRIP</code></td> + <td>0x0003</td> + <td>传递给 <code>drawElements</code> 或<code>drawArrays</code> 画一个从第一个顶点到最后一个顶点绘制一组相连的线段。</td> + </tr> + <tr> + <td><code>TRIANGLES</code></td> + <td>0x0004</td> + <td>传递给<code>drawElements</code> 或<code>drawArrays</code>画三角形。 每三个点创建一个独立的三角形。</td> + </tr> + <tr> + <td><code>TRIANGLE_STRIP</code></td> + <td>0x0005</td> + <td>传递给<code>drawElements<font face="Open Sans, arial, x-locale-body, sans-serif"><span style="background-color: rgba(212, 221, 228, 0.15);">或</span></font></code><code>drawArrays</code> 画一组相连的三角形带。</td> + </tr> + <tr> + <td><code>TRIANGLE_FAN</code></td> + <td>0x0006</td> + <td> + <p>传递给 <code>drawElements</code> 或<code>drawArrays</code> 画一组连接的三角形。以第一个点做原点,每个顶点都连着它的前一个点和第一个顶点(类似风扇)。</p> + </td> + </tr> + </tbody> +</table> + +<h3 id="混合模式">混合模式</h3> + +<p>传递给 {{domxref("WebGLRenderingContext.blendFunc()")}} 或{{domxref("WebGLRenderingContext.blendFuncSeparate()")}} 的常量来指定混合模式 (同时用于或分别用于RBG和alpha).</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>ZERO</code></td> + <td>0</td> + <td>传递给<code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以关闭分量。</td> + </tr> + <tr> + <td><code>ONE</code></td> + <td>1</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以打开分量。</td> + </tr> + <tr> + <td><code>SRC_COLOR</code></td> + <td>0x0300</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以将分量乘以源元素颜色分量。</td> + </tr> + <tr> + <td><code>ONE_MINUS_SRC_COLOR</code></td> + <td>0x0301</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以将分量乘以1 减去源颜色分量。</td> + </tr> + <tr> + <td><code>SRC_ALPHA</code></td> + <td>0x0302</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以将分量乘以源颜色的 alpha值。</td> + </tr> + <tr> + <td><code>ONE_MINUS_SRC_ALPHA</code></td> + <td>0x0303</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以将分量乘以一个源颜色的 alpha值。</td> + </tr> + <tr> + <td><code>DST_ALPHA</code></td> + <td>0x0304</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以将分量乘以目标颜色的alpha值。</td> + </tr> + <tr> + <td><code>ONE_MINUS_DST_ALPHA</code></td> + <td>0x0305</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以将分量乘以1减去目标颜色的alpha值。</td> + </tr> + <tr> + <td><code>DST_COLOR</code></td> + <td>0x0306</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以将分量乘以目标颜色分量。</td> + </tr> + <tr> + <td><code>ONE_MINUS_DST_COLOR</code></td> + <td>0x0307</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以将分量乘以1减去目标颜色分量。</td> + </tr> + <tr> + <td><code>SRC_ALPHA_SATURATE</code></td> + <td>0x0308</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以将分量乘以源颜色alpha与目标颜色alpha中的最小值。</td> + </tr> + <tr> + <td><code>CONSTANT_COLOR</code></td> + <td>0x8001</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以指定常量颜色的混合函数。</td> + </tr> + <tr> + <td><code>ONE_MINUS_CONSTANT_COLOR</code></td> + <td>0x8002</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以指定1减去常量颜色的混合函数。</td> + </tr> + <tr> + <td><code>CONSTANT_ALPHA</code></td> + <td>0x8003</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以指定常量alpha混合函数。</td> + </tr> + <tr> + <td><code>ONE_MINUS_CONSTANT_ALPHA</code></td> + <td>0x8004</td> + <td>传递给 <code>blendFunc</code> 或 <code>blendFuncSeparate</code> 以指定1减去一个常量alpha的混合函数。</td> + </tr> + </tbody> +</table> + +<h3 id="混合方程">混合方程</h3> + +<p>传递给 {{domxref("WebGLRenderingContext.blendEquation()")}} 或 {{domxref("WebGLRenderingContext.blendEquationSeparate()")}} 的常量,以控制混合的计算方式(同时用于或分别用于RBG和alpha)。</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>FUNC_ADD</code></td> + <td>0x8006</td> + <td>传递给 <code>blendEquation</code> 或 <code>blendEquationSeparate</code> 来设置加法混合函数。</td> + </tr> + <tr> + <td><code>FUNC_SUBSTRACT</code></td> + <td>0x800A</td> + <td>传递给 <code>blendEquation</code> 或 <code>blendEquationSeparate</code> 来指定减法混合函数(源 - 目标)</td> + </tr> + <tr> + <td><code>FUNC_REVERSE_SUBTRACT</code></td> + <td>0x800B</td> + <td>传递给 <code>blendEquation</code> 或 <code>blendEquationSeparate</code> 指定反向减法函数(目标 - 源)</td> + </tr> + </tbody> +</table> + +<h3 id="获取_GL_参数信息">获取 GL 参数信息</h3> + +<p>传递给 {{domxref("WebGLRenderingContext.getParameter()")}} 的常量,用以指定要返回的信息。 </p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>BLEND_EQUATION</code></td> + <td>0x8009</td> + <td>传递给 <code>getParameter</code> 以获取当前的RGB混合函数。</td> + </tr> + <tr> + <td><code>BLEND_EQUATION_RGB</code></td> + <td>0x8009</td> + <td>传递给 <code>getParameter</code> 以获取当前的RGB混合函数。与 BLEND_EQUATION 相同。</td> + </tr> + <tr> + <td><code>BLEND_EQUATION_ALPHA</code></td> + <td>0x883D</td> + <td>传递给 <code>getParameter</code> 以获取当前的alpha函数。与 BLEND_EQUATION 相同。</td> + </tr> + <tr> + <td><code>BLEND_DST_RGB</code></td> + <td>0x80C8</td> + <td>传递给 <code>getParameter</code> 以获取当前的目标RGB混合函数。</td> + </tr> + <tr> + <td><code>BLEND_SRC_RGB</code></td> + <td>0x80C9</td> + <td>传递给 <code>getParameter</code> 以获取当前的源RGB混合函数。</td> + </tr> + <tr> + <td><code>BLEND_DST_ALPHA</code></td> + <td>0x80CA</td> + <td>传递给 <code>getParameter</code> 以获取当前目标的alpha混合函数。</td> + </tr> + <tr> + <td><code>BLEND_SRC_ALPHA</code></td> + <td>0x80CB</td> + <td>传递给 <code>getParameter</code> 以获取当前的源alpha混合函数。</td> + </tr> + <tr> + <td><code>BLEND_COLOR</code></td> + <td>0x8005</td> + <td>传递给 <code>getParameter</code> 以返回当前的混合颜色。</td> + </tr> + <tr> + <td><code>ARRAY_BUFFER_BINDING</code></td> + <td>0x8894</td> + <td>传递给 <code>getParameter</code> 获取数组缓冲区绑定。</td> + </tr> + <tr> + <td><code>ELEMENT_ARRAY_BUFFER_BINDING</code></td> + <td>0x8895</td> + <td>传递给 <code>getParameter</code> 获取当前元素数组缓冲区。</td> + </tr> + <tr> + <td><code>LINE_WIDTH</code></td> + <td>0x0B21</td> + <td>传递给 <code>getParameter</code> 获取当前的 <code>lineWidth</code> (由 <code>lineWidth</code> 方法设置)。</td> + </tr> + <tr> + <td><code>ALIASED_POINT_SIZE_RANGE</code></td> + <td>0x846D</td> + <td>传递给 <code>getParameter</code> 获取使用 <code>gl.POINTS</code> 绘制的点的大小。</td> + </tr> + <tr> + <td><code>ALIASED_LINE_WIDTH_RANGE</code></td> + <td>0x846E</td> + <td>传递给 <code>getParameter</code> 得到一条线的可用宽度范围。返回一个长度为2的数组。其中低值为0,高值为1。</td> + </tr> + <tr> + <td><code>CULL_FACE_MODE</code></td> + <td>0x0B45</td> + <td>传递给 <code>getParameter</code> 获取当前的<code>cullFace</code> 值。 应该返回 <code>FRONT</code>, <code>BACK</code>, 或 <code>FRONT_AND_BACK</code>。</td> + </tr> + <tr> + <td><code>FRONT_FACE</code></td> + <td>0x0B46</td> + <td>传递给 <code>getParameter</code> 以确定当前的 <code>frontFace</code> 值。应该 <code>CW</code> 或 <code>CCW</code>。</td> + </tr> + <tr> + <td><code>DEPTH_RANGE</code></td> + <td>0x0B70</td> + <td>传递给 <code>getParameter</code> 返回长度为2的浮点数数组,以表示当前深度范围。</td> + </tr> + <tr> + <td><code>DEPTH_WRITEMASK</code></td> + <td>0x0B72</td> + <td>传递给 <code>getParameter</code> 确定是否启用深度缓冲区写入操作。</td> + </tr> + <tr> + <td><code>DEPTH_CLEAR_VALUE</code></td> + <td>0x0B73</td> + <td>传递给 <code>getParameter</code> 确定当前的深度清除值。</td> + </tr> + <tr> + <td><code>DEPTH_FUNC</code></td> + <td>0x0B74</td> + <td>传递给 <code>getParameter</code> 获取当前的深度函数。返回 <code>NEVER</code>, <code>ALWAYS</code>, <code>LESS</code>, <code>EQUAL</code>, <code>LEQUAL</code>, <code>GREATER</code>, <code>GEQUAL</code>, 或 <code>NOTEQUAL</code>。</td> + </tr> + <tr> + <td><code>STENCIL_CLEAR_VALUE</code></td> + <td>0x0B91</td> + <td>传递给 <code>getParameter</code> 获取将消除的模板值。</td> + </tr> + <tr> + <td><code>STENCIL_FUNC</code></td> + <td>0x0B92</td> + <td>传递给 <code>getParameter</code> 获取当前的模板函数。返回 <code>NEVER</code>, <code>ALWAYS</code>, <code>LESS</code>, <code>EQUAL</code>, <code>LEQUAL</code>, <code>GREATER</code>, <code>GEQUAL</code>, 或 <code>NOTEQUAL</code>。</td> + </tr> + <tr> + <td><code>STENCIL_FAIL</code></td> + <td>0x0B94</td> + <td>传递给 <code>getParameter</code> 获取当前模板的失效函数。应该返回 <code>KEEP</code>, <code>REPLACE</code>, <code>INCR</code>, <code>DECR</code>, <code>INVERT</code>, <code>INCR_WRAP</code>, 或 <code>DECR_WRAP</code>。</td> + </tr> + <tr> + <td><code>STENCIL_PASS_DEPTH_FAIL</code></td> + <td>0x0B95</td> + <td>如果深度缓冲区测试失败,则传递给 <code>getParameter</code> 以获取当前模板失败函数。应该返回 <code>KEEP</code>, <code>REPLACE</code>, <code>INCR</code>, <code>DECR</code>, <code>INVERT</code>, <code>INCR_WRAP</code>, 或 <code>DECR_WRAP</code>。</td> + </tr> + <tr> + <td><code>STENCIL_PASS_DEPTH_PASS</code></td> + <td>0x0B96</td> + <td>如果深度缓冲区测试通过,则传递给 <code>getParameter</code> 以获取当前模板失败函数。应该返回 <code>KEEP</code>, <code>REPLACE</code>, <code>INCR</code>, <code>DECR</code>, <code>INVERT</code>, <code>INCR_WRAP</code>, 或 <code>DECR_WRAP</code>。</td> + </tr> + <tr> + <td><code>STENCIL_REF</code></td> + <td>0x0B97</td> + <td>传递给 <code>getParameter</code> 获取用于模板测试的参考值。</td> + </tr> + <tr> + <td><code>STENCIL_VALUE_MASK</code></td> + <td>0x0B93</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_WRITEMASK</code></td> + <td>0x0B98</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_BACK_FUNC</code></td> + <td>0x8800</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_BACK_FAIL</code></td> + <td>0x8801</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_BACK_PASS_DEPTH_FAIL</code></td> + <td>0x8802</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_BACK_PASS_DEPTH_PASS</code></td> + <td>0x8803</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_BACK_REF</code></td> + <td>0x8CA3</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_BACK_VALUE_MASK</code></td> + <td>0x8CA4</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_BACK_WRITEMASK</code></td> + <td>0x8CA5</td> + <td></td> + </tr> + <tr> + <td><code>VIEWPORT</code></td> + <td>0x0BA2</td> + <td>返回带有当前视口尺寸的四个元素的 {{jsxref("Int32Array")}} </td> + </tr> + <tr> + <td><code>SCISSOR_BOX</code></td> + <td>0x0C10</td> + <td>返回带有当前裁剪盒子尺寸的四个元素的 {{jsxref("Int32Array")}} 。</td> + </tr> + <tr> + <td><code>COLOR_CLEAR_VALUE</code></td> + <td>0x0C22</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_WRITEMASK</code></td> + <td>0x0C23</td> + <td></td> + </tr> + <tr> + <td><code>UNPACK_ALIGNMENT</code></td> + <td>0x0CF5</td> + <td></td> + </tr> + <tr> + <td><code>PACK_ALIGNMENT</code></td> + <td>0x0D05</td> + <td></td> + </tr> + <tr> + <td><code>MAX_TEXTURE_SIZE</code></td> + <td>0x0D33</td> + <td></td> + </tr> + <tr> + <td><code>MAX_VIEWPORT_DIMS</code></td> + <td>0x0D3A</td> + <td></td> + </tr> + <tr> + <td><code>SUBPIXEL_BITS</code></td> + <td>0x0D50</td> + <td></td> + </tr> + <tr> + <td><code>RED_BITS</code></td> + <td>0x0D52</td> + <td></td> + </tr> + <tr> + <td><code>GREEN_BITS</code></td> + <td>0x0D53</td> + <td></td> + </tr> + <tr> + <td><code>BLUE_BITS</code></td> + <td>0x0D54</td> + <td></td> + </tr> + <tr> + <td><code>ALPHA_BITS</code></td> + <td>0x0D55</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH_BITS</code></td> + <td>0x0D56</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_BITS</code></td> + <td>0x0D57</td> + <td></td> + </tr> + <tr> + <td><code>POLYGON_OFFSET_UNITS</code></td> + <td>0x2A00</td> + <td></td> + </tr> + <tr> + <td><code>POLYGON_OFFSET_FACTOR</code></td> + <td>0x8038</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_BINDING_2D</code></td> + <td>0x8069</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLE_BUFFERS</code></td> + <td>0x80A8</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLES</code></td> + <td>0x80A9</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLE_COVERAGE_VALUE</code></td> + <td>0x80AA</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLE_COVERAGE_INVERT</code></td> + <td>0x80AB</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_TEXTURE_FORMATS</code></td> + <td>0x86A3</td> + <td></td> + </tr> + <tr> + <td><code>VENDOR</code></td> + <td>0x1F00</td> + <td></td> + </tr> + <tr> + <td><code>RENDERER</code></td> + <td>0x1F01</td> + <td></td> + </tr> + <tr> + <td><code>VERSION</code></td> + <td>0x1F02</td> + <td></td> + </tr> + <tr> + <td><code>IMPLEMENTATION_COLOR_READ_TYPE</code></td> + <td>0x8B9A</td> + <td></td> + </tr> + <tr> + <td><code>IMPLEMENTATION_COLOR_READ_FORMAT</code></td> + <td>0x8B9B</td> + <td></td> + </tr> + <tr> + <td><code>BROWSER_DEFAULT_WEBGL</code></td> + <td>0x9244</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Buffers">Buffers</h3> + +<p>传递给{{domxref("WebGLRenderingContext.bufferData()")}}, {{domxref("WebGLRenderingContext.bufferSubData()")}}, {{domxref("WebGLRenderingContext.bindBuffer()")}}, or {{domxref("WebGLRenderingContext.getBufferParameter()")}} 的变量。</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>STATIC_DRAW</code></td> + <td>0x88E4</td> + <td>Passed to <code>bufferData</code> as a hint about whether the contents of the buffer are likely to be used often and not change often.</td> + </tr> + <tr> + <td><code>STREAM_DRAW</code></td> + <td>0x88E0</td> + <td>Passed to <code>bufferData</code> as a hint about whether the contents of the buffer are likely to not be used often.</td> + </tr> + <tr> + <td><code>DYNAMIC_DRAW</code></td> + <td>0x88E8</td> + <td>Passed to <code>bufferData</code> as a hint about whether the contents of the buffer are likely to be used often and change often.</td> + </tr> + <tr> + <td><code>ARRAY_BUFFER</code></td> + <td>0x8892</td> + <td>Passed to <code>bindBuffer</code> or <code>bufferData</code> to specify the type of buffer being used.</td> + </tr> + <tr> + <td><code>ELEMENT_ARRAY_BUFFER</code></td> + <td>0x8893</td> + <td>Passed to <code>bindBuffer</code> or <code>bufferData</code> to specify the type of buffer being used.</td> + </tr> + <tr> + <td><code>BUFFER_SIZE</code></td> + <td>0x8764</td> + <td>Passed to <code>getBufferParameter</code> to get a buffer's size.</td> + </tr> + <tr> + <td><code>BUFFER_USAGE</code></td> + <td>0x8765</td> + <td>Passed to <code>getBufferParameter</code> to get the hint for the buffer passed in when it was created.</td> + </tr> + </tbody> +</table> + +<h3 id="Vertex_attributes">Vertex attributes</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.getVertexAttrib()")}}.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>CURRENT_VERTEX_ATTRIB</code></td> + <td>0x8626</td> + <td>Passed to <code>getVertexAttrib</code> to read back the current vertex attribute.</td> + </tr> + <tr> + <td><code>VERTEX_ATTRIB_ARRAY_ENABLED</code></td> + <td>0x8622</td> + <td></td> + </tr> + <tr> + <td><code>VERTEX_ATTRIB_ARRAY_SIZE</code></td> + <td>0x8623</td> + <td></td> + </tr> + <tr> + <td><code>VERTEX_ATTRIB_ARRAY_STRIDE</code></td> + <td>0x8624</td> + <td></td> + </tr> + <tr> + <td><code>VERTEX_ATTRIB_ARRAY_TYPE</code></td> + <td>0x8625</td> + <td></td> + </tr> + <tr> + <td><code>VERTEX_ATTRIB_ARRAY_NORMALIZED</code></td> + <td>0x886A</td> + <td></td> + </tr> + <tr> + <td><code>VERTEX_ATTRIB_ARRAY_POINTER</code></td> + <td>0x8645</td> + <td></td> + </tr> + <tr> + <td><code>VERTEX_ATTRIB_ARRAY_BUFFER_BINDING</code></td> + <td>0x889F</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Culling">Culling</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.cullFace()")}}.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>CULL_FACE</code></td> + <td>0x0B44</td> + <td>Passed to <code>enable</code>/<code>disable</code> to turn on/off culling. Can also be used with <code>getParameter</code> to find the current culling method.</td> + </tr> + <tr> + <td><code>FRONT</code></td> + <td>0x0404</td> + <td>Passed to <code>cullFace</code> to specify that only front faces should be drawn.</td> + </tr> + <tr> + <td><code>BACK</code></td> + <td>0x0405</td> + <td>Passed to <code>cullFace</code> to specify that only back faces should be drawn.</td> + </tr> + <tr> + <td><code>FRONT_AND_BACK</code></td> + <td>0x0408</td> + <td>Passed to <code>cullFace</code> to specify that front and back faces should be drawn.</td> + </tr> + </tbody> +</table> + +<h3 id="Enabling_and_disabling">Enabling and disabling</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.enable()")}} or {{domxref("WebGLRenderingContext.disable()")}}.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>BLEND</code></td> + <td>0x0BE2</td> + <td>Passed to <code>enable</code>/<code>disable</code> to turn on/off blending. Can also be used with <code>getParameter</code> to find the current blending method.</td> + </tr> + <tr> + <td><code>DEPTH_TEST</code></td> + <td>0x0B71</td> + <td>通过 <code>enable</code>/<code>disable</code> 来打开/关闭深度测试。 也可以使用 <code>getParameter</code> 来查询深度测试。LEQUAL</td> + </tr> + <tr> + <td><code>DITHER</code></td> + <td>0x0BD0</td> + <td>Passed to <code>enable</code>/<code>disable</code> to turn on/off dithering. Can also be used with <code>getParameter</code> to find the current dithering method.</td> + </tr> + <tr> + <td><code>POLYGON_OFFSET_FILL</code></td> + <td>0x8037</td> + <td>Passed to <code>enable</code>/<code>disable</code> to turn on/off the polygon offset. Useful for rendering hidden-line images, decals, and or solids with highlighted edges. Can also be used with <code>getParameter</code> to query the scissor test.</td> + </tr> + <tr> + <td><code>SAMPLE_ALPHA_TO_COVERAGE</code></td> + <td>0x809E</td> + <td>Passed to <code>enable</code>/<code>disable</code> to turn on/off the alpha to coverage. Used in multi-sampling alpha channels.</td> + </tr> + <tr> + <td><code>SAMPLE_COVERAGE</code></td> + <td>0x80A0</td> + <td>Passed to <code>enable</code>/<code>disable</code> to turn on/off the sample coverage. Used in multi-sampling.</td> + </tr> + <tr> + <td><code>SCISSOR_TEST</code></td> + <td>0x0C11</td> + <td>Passed to <code>enable</code>/<code>disable</code> to turn on/off the scissor test. Can also be used with <code>getParameter</code> to query the scissor test.</td> + </tr> + <tr> + <td><code>STENCIL_TEST</code></td> + <td>0x0B90</td> + <td>Passed to <code>enable</code>/<code>disable</code> to turn on/off the stencil test. Can also be used with <code>getParameter</code> to query the stencil test.</td> + </tr> + <tr> + </tr> + </tbody> +</table> + +<h3 id="Errors">Errors</h3> + +<p>Constants returned from {{domxref("WebGLRenderingContext.getError()")}}.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>NO_ERROR</code></td> + <td>0</td> + <td>Returned from <code>getError</code>.</td> + </tr> + <tr> + <td><code>INVALID_ENUM</code></td> + <td>0x0500</td> + <td>Returned from <code>getError</code>.</td> + </tr> + <tr> + <td><code>INVALID_VALUE</code></td> + <td>0x0501</td> + <td>Returned from <code>getError</code>.</td> + </tr> + <tr> + <td><code>INVALID_OPERATION</code></td> + <td>0x0502</td> + <td>Returned from <code>getError</code>.</td> + </tr> + <tr> + <td><code>OUT_OF_MEMORY</code></td> + <td>0x0505</td> + <td>Returned from <code>getError</code>.</td> + </tr> + <tr> + <td><code>CONTEXT_LOST_WEBGL</code></td> + <td>0x9242</td> + <td>Returned from <code>getError</code>.</td> + </tr> + </tbody> +</table> + +<h3 id="Front_face_directions">Front face directions</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.frontFace()")}}.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>CW</code></td> + <td>0x0900</td> + <td>Passed to <code>frontFace</code> to specify the front face of a polygon is drawn in the clockwise direction</td> + </tr> + <tr> + <td><code>CCW</code></td> + <td>0x0901</td> + <td>Passed to <code>frontFace</code> to specify the front face of a polygon is drawn in the counter clockwise direction</td> + </tr> + </tbody> +</table> + +<h3 id="Hints">Hints</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.hint()")}}</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>DONT_CARE</code></td> + <td>0x1100</td> + <td>There is no preference for this behavior.</td> + </tr> + <tr> + <td><code>FASTEST</code></td> + <td>0x1101</td> + <td>The most efficient behavior should be used.</td> + </tr> + <tr> + <td><code>NICEST</code></td> + <td>0x1102</td> + <td>The most correct or the highest quality option should be used.</td> + </tr> + <tr> + <td><code>GENERATE_MIPMAP_HINT</code></td> + <td>0x8192</td> + <td>Hint for the quality of filtering when generating mipmap images with {{domxref("WebGLRenderingContext.generateMipmap()")}}.</td> + </tr> + </tbody> +</table> + +<h3 id="Data_types">Data types</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>BYTE</code></td> + <td>0x1400</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_BYTE</code></td> + <td>0x1401</td> + <td></td> + </tr> + <tr> + <td><code>SHORT</code></td> + <td>0x1402</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_SHORT</code></td> + <td>0x1403</td> + <td></td> + </tr> + <tr> + <td><code>INT</code></td> + <td>0x1404</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_INT</code></td> + <td>0x1405</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT</code></td> + <td>0x1406</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Pixel_formats">Pixel formats</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>DEPTH_COMPONENT</code></td> + <td>0x1902</td> + <td></td> + </tr> + <tr> + <td><code>ALPHA</code></td> + <td>0x1906</td> + <td></td> + </tr> + <tr> + <td><code>RGB</code></td> + <td>0x1907</td> + <td></td> + </tr> + <tr> + <td><code>RGBA</code></td> + <td>0x1908</td> + <td></td> + </tr> + <tr> + <td><code>LUMINANCE</code></td> + <td>0x1909</td> + <td></td> + </tr> + <tr> + <td><code>LUMINANCE_ALPHA</code></td> + <td>0x190A</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Pixel_types">Pixel types</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>UNSIGNED_BYTE</code></td> + <td>0x1401</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_SHORT_4_4_4_4</code></td> + <td>0x8033</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_SHORT_5_5_5_1</code></td> + <td>0x8034</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_SHORT_5_6_5</code></td> + <td>0x8363</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Shaders">Shaders</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.createShader()")}} or {{domxref("WebGLRenderingContext.getShaderParameter()")}}</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">常量名称</th> + <th scope="col">值</th> + <th scope="col">说明</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>FRAGMENT_SHADER</code></td> + <td>0x8B30</td> + <td>Passed to <code>createShader</code> to define a fragment shader.</td> + </tr> + <tr> + <td><code>VERTEX_SHADER</code></td> + <td>0x8B31</td> + <td>Passed to <code>createShader</code> to define a vertex shader</td> + </tr> + <tr> + <td><code>COMPILE_STATUS</code></td> + <td>0x8B81</td> + <td>Passed to <code>getShaderParamter</code> to get the status of the compilation. Returns false if the shader was not compiled. You can then query <code>getShaderInfoLog</code> to find the exact error</td> + </tr> + <tr> + <td><code>DELETE_STATUS</code></td> + <td>0x8B80</td> + <td>Passed to <code>getShaderParamter</code> to determine if a shader was deleted via <code>deleteShader</code>. Returns true if it was, false otherwise.</td> + </tr> + <tr> + <td><code>LINK_STATUS</code></td> + <td>0x8B82</td> + <td>Passed to <code>getProgramParameter</code> after calling <code>linkProgram</code> to determine if a program was linked correctly. Returns false if there were errors. Use <code>getProgramInfoLog</code> to find the exact error.</td> + </tr> + <tr> + <td><code>VALIDATE_STATUS</code></td> + <td>0x8B83</td> + <td>Passed to <code>getProgramParameter</code> after calling <code>validateProgram</code> to determine if it is valid. Returns false if errors were found.</td> + </tr> + <tr> + <td><code>ATTACHED_SHADERS</code></td> + <td>0x8B85</td> + <td>Passed to <code>getProgramParameter</code> after calling <code>attachShader</code> to determine if the shader was attached correctly. Returns false if errors occurred.</td> + </tr> + <tr> + <td><code>ACTIVE_ATTRIBUTES</code></td> + <td>0x8B89</td> + <td>Passed to <code>getProgramParameter</code> to get the number of attributes active in a program.</td> + </tr> + <tr> + <td><code>ACTIVE_UNIFORMS</code></td> + <td>0x8B86</td> + <td>Passed to <code>getProgramParamter</code> to get the number of uniforms active in a program.</td> + </tr> + <tr> + <td><code>MAX_VERTEX_ATTRIBS</code></td> + <td>0x8869</td> + <td></td> + </tr> + <tr> + <td><code>MAX_VERTEX_UNIFORM_VECTORS</code></td> + <td>0x8DFB</td> + <td></td> + </tr> + <tr> + <td><code>MAX_VARYING_VECTORS</code></td> + <td>0x8DFC</td> + <td></td> + </tr> + <tr> + <td><code>MAX_COMBINED_TEXTURE_IMAGE_UNITS</code></td> + <td>0x8B4D</td> + <td></td> + </tr> + <tr> + <td><code>MAX_VERTEX_TEXTURE_IMAGE_UNITS</code></td> + <td>0x8B4C</td> + <td></td> + </tr> + <tr> + <td><code>MAX_TEXTURE_IMAGE_UNITS</code></td> + <td>0x8872</td> + <td>Implementation dependent number of maximum texture units. At least 8.</td> + </tr> + <tr> + <td><code>MAX_FRAGMENT_UNIFORM_VECTORS</code></td> + <td>0x8DFD</td> + <td></td> + </tr> + <tr> + <td><code>SHADER_TYPE</code></td> + <td>0x8B4F</td> + <td></td> + </tr> + <tr> + <td><code>SHADING_LANGUAGE_VERSION</code></td> + <td>0x8B8C</td> + <td></td> + </tr> + <tr> + <td><code>CURRENT_PROGRAM</code></td> + <td>0x8B8D</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Depth_or_stencil_tests">Depth or stencil tests</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.depthFunc()")}} or {{domxref("WebGLRenderingContext.stencilFunc()")}}.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>NEVER</code></td> + <td>0x0200</td> + <td>Passed to <code>depthFunction</code> or <code>stencilFunction</code> to specify depth or stencil tests will never pass. i.e. Nothing will be drawn.</td> + </tr> + <tr> + <td><code>ALWAYS</code></td> + <td>0x0207</td> + <td>Passed to <code>depthFunction</code> or <code>stencilFunction</code> to specify depth or stencil tests will always pass. i.e. Pixels will be drawn in the order they are drawn.</td> + </tr> + <tr> + <td><code>LESS</code></td> + <td>0x0201</td> + <td>Passed to <code>depthFunction</code> or <code>stencilFunction</code> to specify depth or stencil tests will pass if the new depth value is less than the stored value.</td> + </tr> + <tr> + <td><code>EQUAL</code></td> + <td>0x0202</td> + <td>Passed to <code>depthFunction</code> or <code>stencilFunction</code> to specify depth or stencil tests will pass if the new depth value is equals to the stored value.</td> + </tr> + <tr> + <td><code>LEQUAL</code></td> + <td>0x0203</td> + <td>如果新深度值小于或等于存储值,则通过 <code>depthFunction</code> 或 <code>stencilFunction</code> 指定深度或模板测试。</td> + </tr> + <tr> + <td><code>GREATER</code></td> + <td>0x0204</td> + <td>Passed to <code>depthFunction</code> or <code>stencilFunction</code> to specify depth or stencil tests will pass if the new depth value is greater than the stored value.</td> + </tr> + <tr> + <td><code>GEQUAL</code></td> + <td>0x0206</td> + <td>Passed to <code>depthFunction</code> or <code>stencilFunction</code> to specify depth or stencil tests will pass if the new depth value is greater than or equal to the stored value.</td> + </tr> + <tr> + <td><code>NOTEQUAL</code></td> + <td>0x0205</td> + <td>Passed to <code>depthFunction</code> or <code>stencilFunction</code> to specify depth or stencil tests will pass if the new depth value is not equal to the stored value.</td> + </tr> + </tbody> +</table> + +<h3 id="Stencil_actions">Stencil actions</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.stencilOp()")}}.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>KEEP</code></td> + <td>0x1E00</td> + <td></td> + </tr> + <tr> + <td><code>REPLACE</code></td> + <td>0x1E01</td> + <td></td> + </tr> + <tr> + <td><code>INCR</code></td> + <td>0x1E02</td> + <td></td> + </tr> + <tr> + <td><code>DECR</code></td> + <td>0x1E03</td> + <td></td> + </tr> + <tr> + <td><code>INVERT</code></td> + <td>0x150A</td> + <td></td> + </tr> + <tr> + <td><code>INCR_WRAP</code></td> + <td>0x8507</td> + <td></td> + </tr> + <tr> + <td><code>DECR_WRAP</code></td> + <td>0x8508</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Textures">Textures</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.texParameteri()")}}, {{domxref("WebGLRenderingContext.texParameterf()")}}, {{domxref("WebGLRenderingContext.bindTexture()")}}, {{domxref("WebGLRenderingContext.texImage2D()")}}, and others.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>NEAREST</code></td> + <td>0x2600</td> + <td></td> + </tr> + <tr> + <td><code>LINEAR</code></td> + <td>0x2601</td> + <td></td> + </tr> + <tr> + <td><code>NEAREST_MIPMAP_NEAREST</code></td> + <td>0x2700</td> + <td></td> + </tr> + <tr> + <td><code>LINEAR_MIPMAP_NEAREST</code></td> + <td>0x2701</td> + <td></td> + </tr> + <tr> + <td><code>NEAREST_MIPMAP_LINEAR</code></td> + <td>0x2702</td> + <td></td> + </tr> + <tr> + <td><code>LINEAR_MIPMAP_LINEAR</code></td> + <td>0x2703</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_MAG_FILTER</code></td> + <td>0x2800</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_MIN_FILTER</code></td> + <td>0x2801</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_WRAP_S</code></td> + <td>0x2802</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_WRAP_T</code></td> + <td>0x2803</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_2D</code></td> + <td>0x0DE1</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE</code></td> + <td>0x1702</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_CUBE_MAP</code></td> + <td>0x8513</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_BINDING_CUBE_MAP</code></td> + <td>0x8514</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_CUBE_MAP_POSITIVE_X</code></td> + <td>0x8515</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_CUBE_MAP_NEGATIVE_X</code></td> + <td>0x8516</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_CUBE_MAP_POSITIVE_Y</code></td> + <td>0x8517</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_CUBE_MAP_NEGATIVE_Y</code></td> + <td>0x8518</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_CUBE_MAP_POSITIVE_Z</code></td> + <td>0x8519</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_CUBE_MAP_NEGATIVE_Z</code></td> + <td>0x851A</td> + <td></td> + </tr> + <tr> + <td><code>MAX_CUBE_MAP_TEXTURE_SIZE</code></td> + <td>0x851C</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE0 - 31</code></td> + <td>0x84C0 - 0x84DF</td> + <td>A texture unit.</td> + </tr> + <tr> + <td><code>ACTIVE_TEXTURE</code></td> + <td>0x84E0</td> + <td>The current active texture unit.</td> + </tr> + <tr> + <td><code>REPEAT</code></td> + <td>0x2901</td> + <td></td> + </tr> + <tr> + <td><code>CLAMP_TO_EDGE</code></td> + <td>0x812F</td> + <td></td> + </tr> + <tr> + <td><code>MIRRORED_REPEAT</code></td> + <td>0x8370</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Uniform_types">Uniform types</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>FLOAT_VEC2</code></td> + <td>0x8B50</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_VEC3</code></td> + <td>0x8B51</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_VEC4</code></td> + <td>0x8B52</td> + <td></td> + </tr> + <tr> + <td><code>INT_VEC2</code></td> + <td>0x8B53</td> + <td></td> + </tr> + <tr> + <td><code>INT_VEC3</code></td> + <td>0x8B54</td> + <td></td> + </tr> + <tr> + <td><code>INT_VEC4</code></td> + <td>0x8B55</td> + <td></td> + </tr> + <tr> + <td><code>BOOL</code></td> + <td>0x8B56</td> + <td></td> + </tr> + <tr> + <td><code>BOOL_VEC2</code></td> + <td>0x8B57</td> + <td></td> + </tr> + <tr> + <td><code>BOOL_VEC3</code></td> + <td>0x8B58</td> + <td></td> + </tr> + <tr> + <td><code>BOOL_VEC4</code></td> + <td>0x8B59</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_MAT2</code></td> + <td>0x8B5A</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_MAT3</code></td> + <td>0x8B5B</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_MAT4</code></td> + <td>0x8B5C</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLER_2D</code></td> + <td>0x8B5E</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLER_CUBE</code></td> + <td>0x8B60</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Shader_precision-specified_types">Shader precision-specified types</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>LOW_FLOAT</code></td> + <td>0x8DF0</td> + <td></td> + </tr> + <tr> + <td><code>MEDIUM_FLOAT</code></td> + <td>0x8DF1</td> + <td></td> + </tr> + <tr> + <td><code>HIGH_FLOAT</code></td> + <td>0x8DF2</td> + <td></td> + </tr> + <tr> + <td><code>LOW_INT</code></td> + <td>0x8DF3</td> + <td></td> + </tr> + <tr> + <td><code>MEDIUM_INT</code></td> + <td>0x8DF4</td> + <td></td> + </tr> + <tr> + <td><code>HIGH_INT</code></td> + <td>0x8DF5</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Framebuffers_and_renderbuffers">Framebuffers and renderbuffers</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>FRAMEBUFFER</code></td> + <td>0x8D40</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER</code></td> + <td>0x8D41</td> + <td></td> + </tr> + <tr> + <td><code>RGBA4</code></td> + <td>0x8056</td> + <td></td> + </tr> + <tr> + <td><code>RGB5_A1</code></td> + <td>0x8057</td> + <td></td> + </tr> + <tr> + <td><code>RGB565</code></td> + <td>0x8D62</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH_COMPONENT16</code></td> + <td>0x81A5</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_INDEX</code></td> + <td>0x1901</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_INDEX8</code></td> + <td>0x8D48</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH_STENCIL</code></td> + <td>0x84F9</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_WIDTH</code></td> + <td>0x8D42</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_HEIGHT</code></td> + <td>0x8D43</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_INTERNAL_FORMAT</code></td> + <td>0x8D44</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_RED_SIZE</code></td> + <td>0x8D50</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_GREEN_SIZE</code></td> + <td>0x8D51</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_BLUE_SIZE</code></td> + <td>0x8D52</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_ALPHA_SIZE</code></td> + <td>0x8D53</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_DEPTH_SIZE</code></td> + <td>0x8D54</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_STENCIL_SIZE</code></td> + <td>0x8D55</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE</code></td> + <td>0x8CD0</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_OBJECT_NAME</code></td> + <td>0x8CD1</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL</code></td> + <td>0x8CD2</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE</code></td> + <td>0x8CD3</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT0</code></td> + <td>0x8CE0</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH_ATTACHMENT</code></td> + <td>0x8D00</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL_ATTACHMENT</code></td> + <td>0x8D20</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH_STENCIL_ATTACHMENT</code></td> + <td>0x821A</td> + <td></td> + </tr> + <tr> + <td><code>NONE</code></td> + <td>0</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_COMPLETE</code></td> + <td>0x8CD5</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_INCOMPLETE_ATTACHMENT</code></td> + <td>0x8CD6</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT</code></td> + <td>0x8CD7</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_INCOMPLETE_DIMENSIONS</code></td> + <td>0x8CD9</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_UNSUPPORTED</code></td> + <td>0x8CDD</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_BINDING</code></td> + <td>0x8CA6</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_BINDING</code></td> + <td>0x8CA7</td> + <td></td> + </tr> + <tr> + <td><code>MAX_RENDERBUFFER_SIZE</code></td> + <td>0x84E8</td> + <td></td> + </tr> + <tr> + <td><code>INVALID_FRAMEBUFFER_OPERATION</code></td> + <td>0x0506</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Pixel_storage_modes">Pixel storage modes</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.pixelStorei()")}}.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>UNPACK_FLIP_Y_WEBGL</code></td> + <td>0x9240</td> + <td></td> + </tr> + <tr> + <td><code>UNPACK_PREMULTIPLY_ALPHA_WEBGL</code></td> + <td>0x9241</td> + <td></td> + </tr> + <tr> + <td><code>UNPACK_COLORSPACE_CONVERSION_WEBGL</code></td> + <td>0x9243</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="Additional_constants_defined_WebGL_2">Additional constants defined WebGL 2</h2> + +<p>These constants are defined on the {{domxref("WebGL2RenderingContext")}} interface. All WebGL 1 constants are also available in a WebGL 2 context.</p> + +<h3 id="Getting_GL_parameter_information">Getting GL parameter information</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.getParameter()")}} to specify what information to return.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>READ_BUFFER</code></td> + <td>0x0C02</td> + <td></td> + </tr> + <tr> + <td><code>UNPACK_ROW_LENGTH</code></td> + <td>0x0CF2</td> + <td></td> + </tr> + <tr> + <td><code>UNPACK_SKIP_ROWS</code></td> + <td>0x0CF3</td> + <td></td> + </tr> + <tr> + <td><code>UNPACK_SKIP_PIXELS</code></td> + <td>0x0CF4</td> + <td></td> + </tr> + <tr> + <td><code>PACK_ROW_LENGTH</code></td> + <td>0x0D02</td> + <td></td> + </tr> + <tr> + <td><code>PACK_SKIP_ROWS</code></td> + <td>0x0D03</td> + <td></td> + </tr> + <tr> + <td><code>PACK_SKIP_PIXELS</code></td> + <td>0x0D04</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_BINDING_3D</code></td> + <td>0x806A</td> + <td></td> + </tr> + <tr> + <td><code>UNPACK_SKIP_IMAGES</code></td> + <td>0x806D</td> + <td></td> + </tr> + <tr> + <td><code>UNPACK_IMAGE_HEIGHT</code></td> + <td>0x806E</td> + <td></td> + </tr> + <tr> + <td><code>MAX_3D_TEXTURE_SIZE</code></td> + <td>0x8073</td> + <td></td> + </tr> + <tr> + <td><code>MAX_ELEMENTS_VERTICES</code></td> + <td>0x80E8</td> + <td></td> + </tr> + <tr> + <td><code>MAX_ELEMENTS_INDICES</code></td> + <td>0x80E9</td> + <td></td> + </tr> + <tr> + <td><code>MAX_TEXTURE_LOD_BIAS</code></td> + <td>0x84FD</td> + <td></td> + </tr> + <tr> + <td><code>MAX_FRAGMENT_UNIFORM_COMPONENTS</code></td> + <td>0x8B49</td> + <td></td> + </tr> + <tr> + <td><code>MAX_VERTEX_UNIFORM_COMPONENTS</code></td> + <td>0x8B4A</td> + <td></td> + </tr> + <tr> + <td><code>MAX_ARRAY_TEXTURE_LAYERS</code></td> + <td>0x88FF</td> + <td></td> + </tr> + <tr> + <td><code>MIN_PROGRAM_TEXEL_OFFSET</code></td> + <td>0x8904</td> + <td></td> + </tr> + <tr> + <td><code>MAX_PROGRAM_TEXEL_OFFSET</code></td> + <td>0x8905</td> + <td></td> + </tr> + <tr> + <td><code>MAX_VARYING_COMPONENTS</code></td> + <td>0x8B4B</td> + <td></td> + </tr> + <tr> + <td><code>FRAGMENT_SHADER_DERIVATIVE_HINT</code></td> + <td>0x8B8B</td> + <td></td> + </tr> + <tr> + <td><code>RASTERIZER_DISCARD</code></td> + <td>0x8C89</td> + <td></td> + </tr> + <tr> + <td><code>VERTEX_ARRAY_BINDING</code></td> + <td>0x85B5</td> + <td></td> + </tr> + <tr> + <td><code>MAX_VERTEX_OUTPUT_COMPONENTS</code></td> + <td>0x9122</td> + <td></td> + </tr> + <tr> + <td><code>MAX_FRAGMENT_INPUT_COMPONENTS</code></td> + <td>0x9125</td> + <td></td> + </tr> + <tr> + <td><code>MAX_SERVER_WAIT_TIMEOUT</code></td> + <td>0x9111</td> + <td></td> + </tr> + <tr> + <td><code>MAX_ELEMENT_INDEX</code></td> + <td>0x8D6B</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Textures_2">Textures</h3> + +<p>Constants passed to {{domxref("WebGLRenderingContext.texParameteri()")}}, {{domxref("WebGLRenderingContext.texParameterf()")}}, {{domxref("WebGLRenderingContext.bindTexture()")}}, {{domxref("WebGLRenderingContext.texImage2D()")}}, and others.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>RED</code></td> + <td>0x1903</td> + <td></td> + </tr> + <tr> + <td><code>RGB8</code></td> + <td>0x8051</td> + <td></td> + </tr> + <tr> + <td><code>RGBA8</code></td> + <td>0x8058</td> + <td></td> + </tr> + <tr> + <td><code>RGB10_A2</code></td> + <td>0x8059</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURES_3D</code></td> + <td>0x806F</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_WRAP_R</code></td> + <td>0x8072</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_MIN_LOD</code></td> + <td>0x813A</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_MAX_LOD</code></td> + <td>0x813B</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_BASE_LEVEL</code></td> + <td>0x813C</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_MAX_LEVEL</code></td> + <td>0x813D</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_COMPARE_MODE</code></td> + <td>0x884C</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_COMPARE_FUNC</code></td> + <td>0x884D</td> + <td></td> + </tr> + <tr> + <td><code>SRGB</code></td> + <td>0x8C40</td> + <td></td> + </tr> + <tr> + <td><code>SRGB8</code></td> + <td>0x8C41</td> + <td></td> + </tr> + <tr> + <td><code>SRGB8_ALPHA8</code></td> + <td>0x8C43</td> + <td></td> + </tr> + <tr> + <td><code>COMPARE_REF_TO_TEXTURE</code></td> + <td>0x884E</td> + <td></td> + </tr> + <tr> + <td><code>RGBA32F</code></td> + <td>0x8814</td> + <td></td> + </tr> + <tr> + <td><code>RGB32F</code></td> + <td>0x8815</td> + <td></td> + </tr> + <tr> + <td><code>RGBA16F</code></td> + <td>0x881A</td> + <td></td> + </tr> + <tr> + <td><code>RGB16F</code></td> + <td>0x881B</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_2D_ARRAY</code></td> + <td>0x8C1A</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_BINDING_2D_ARRAY</code></td> + <td>0x8C1D</td> + <td></td> + </tr> + <tr> + <td><code>R11F_G11F_B10F</code></td> + <td>0x8C3A</td> + <td></td> + </tr> + <tr> + <td><code>RGB9_E5</code></td> + <td>0x8C3D</td> + <td></td> + </tr> + <tr> + <td><code>RGBA32UI</code></td> + <td>0x8D70</td> + <td></td> + </tr> + <tr> + <td><code>RGB32UI</code></td> + <td>0x8D71</td> + <td></td> + </tr> + <tr> + <td><code>RGBA16UI</code></td> + <td>0x8D76</td> + <td></td> + </tr> + <tr> + <td><code>RGB16UI</code></td> + <td>0x8D77</td> + <td></td> + </tr> + <tr> + <td><code>RGBA8UI</code></td> + <td>0x8D7C</td> + <td></td> + </tr> + <tr> + <td><code>RGB8UI</code></td> + <td>0x8D7D</td> + <td></td> + </tr> + <tr> + <td><code>RGBA32I</code></td> + <td>0x8D82</td> + <td></td> + </tr> + <tr> + <td><code>RGB32I</code></td> + <td>0x8D83</td> + <td></td> + </tr> + <tr> + <td><code>RGBA16I</code></td> + <td>0x8D88</td> + <td></td> + </tr> + <tr> + <td><code>RGB16I</code></td> + <td>0x8D89</td> + <td></td> + </tr> + <tr> + <td><code>RGBA8I</code></td> + <td>0x8D8E</td> + <td></td> + </tr> + <tr> + <td><code>RGB8I</code></td> + <td>0x8D8F</td> + <td></td> + </tr> + <tr> + <td><code>RED_INTEGER</code></td> + <td>0x8D94</td> + <td></td> + </tr> + <tr> + <td><code>RGB_INTEGER</code></td> + <td>0x8D98</td> + <td></td> + </tr> + <tr> + <td><code>RGBA_INTEGER</code></td> + <td>0x8D99</td> + <td></td> + </tr> + <tr> + <td><code>R8</code></td> + <td>0x8229</td> + <td></td> + </tr> + <tr> + <td><code>RG8</code></td> + <td>0x822B</td> + <td></td> + </tr> + <tr> + <td>R16F</td> + <td>0x822D</td> + <td></td> + </tr> + <tr> + <td>R32F</td> + <td>0x822E</td> + <td></td> + </tr> + <tr> + <td>RG16F</td> + <td>0x822F</td> + <td></td> + </tr> + <tr> + <td>RG32F</td> + <td>0x8230</td> + <td></td> + </tr> + <tr> + <td>R8I</td> + <td>0x8231</td> + <td></td> + </tr> + <tr> + <td>R8UI</td> + <td>0x8232</td> + <td></td> + </tr> + <tr> + <td>R16I</td> + <td>0x8233</td> + <td></td> + </tr> + <tr> + <td>R16UI</td> + <td>0x8234</td> + <td></td> + </tr> + <tr> + <td>R32I</td> + <td>0x8235</td> + <td></td> + </tr> + <tr> + <td>R32UI</td> + <td>0x8236</td> + <td></td> + </tr> + <tr> + <td>RG8I</td> + <td>0x8237</td> + <td></td> + </tr> + <tr> + <td>RG8UI</td> + <td>0x8238</td> + <td></td> + </tr> + <tr> + <td>RG16I</td> + <td>0x8239</td> + <td></td> + </tr> + <tr> + <td>RG16UI</td> + <td>0x823A</td> + <td></td> + </tr> + <tr> + <td>RG32I</td> + <td>0x823B</td> + <td></td> + </tr> + <tr> + <td>RG32UI</td> + <td>0x823C</td> + <td></td> + </tr> + <tr> + <td>R8_SNORM</td> + <td>0x8F94</td> + <td></td> + </tr> + <tr> + <td>RG8_SNORM</td> + <td>0x8F95</td> + <td></td> + </tr> + <tr> + <td>RGB8_SNORM</td> + <td>0x8F96</td> + <td></td> + </tr> + <tr> + <td>RGBA8_SNORM</td> + <td>0x8F97</td> + <td></td> + </tr> + <tr> + <td><code>RGB10_A2UI</code></td> + <td>0x906F</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_R11_EAC</code></td> + <td>0x9270</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_SIGNED_R11_EAC</code></td> + <td>0x9271</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_RG11_EAC</code></td> + <td>0x9272</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_SIGNED_RG11_EAC</code></td> + <td>0x9273</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_RGB8_ETC2</code></td> + <td>0x9274</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_SRGB8_ETC2</code></td> + <td>0x9275</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2</code></td> + <td>0x9276</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC</code></td> + <td>0x9277</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_RGBA8_ETC2_EAC</code></td> + <td>0x9278</td> + <td></td> + </tr> + <tr> + <td><code>COMPRESSED_SRGB8_ALPHA8_ETC2_EAC</code></td> + <td>0x9279</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_IMMUTABLE_FORMAT </code></td> + <td>0x912F</td> + <td></td> + </tr> + <tr> + <td><code>TEXTURE_IMMUTABLE_LEVELS</code></td> + <td>0x82DF</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Pixel_types_2">Pixel types</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>UNSIGNED_INT_2_10_10_10_REV</code></td> + <td>0x8368</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_INT_10F_11F_11F_REV</code></td> + <td>0x8C3B</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_INT_5_9_9_9_REV</code></td> + <td>0x8C3E</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_32_UNSIGNED_INT_24_8_REV</code></td> + <td>0x8DAD</td> + <td></td> + </tr> + <tr> + <td>UNSIGNED_INT_24_8</td> + <td>0x84FA</td> + <td></td> + </tr> + <tr> + <td><code>HALF_FLOAT</code></td> + <td>0x140B</td> + <td></td> + </tr> + <tr> + <td><code>RG</code></td> + <td>0x8227</td> + <td></td> + </tr> + <tr> + <td><code>RG_INTEGER</code></td> + <td>0x8228</td> + <td></td> + </tr> + <tr> + <td><code>INT_2_10_10_10_REV</code></td> + <td>0x8D9F</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Queries">Queries</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>CURRENT_QUERY</code></td> + <td>0x8865</td> + <td></td> + </tr> + <tr> + <td><code>QUERY_RESULT </code></td> + <td>0x8866</td> + <td></td> + </tr> + <tr> + <td><code>QUERY_RESULT_AVAILABLE</code></td> + <td>0x8867</td> + <td></td> + </tr> + <tr> + <td><code>ANY_SAMPLES_PASSED</code></td> + <td>0x8C2F</td> + <td></td> + </tr> + <tr> + <td><code>ANY_SAMPLES_PASSED_CONSERVATIVE</code></td> + <td>0x8D6A</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Draw_buffers">Draw buffers</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>MAX_DRAW_BUFFERS</code></td> + <td>0x8824</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER0</code></td> + <td>0x8825</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER1</code></td> + <td>0x8826</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER2</code></td> + <td>0x8827</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER3</code></td> + <td>0x8828</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER4</code></td> + <td>0x8829</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER5</code></td> + <td>0x882A</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER6</code></td> + <td>0x882B</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER7</code></td> + <td>0x882C</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER8</code></td> + <td>0x882D</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER9</code></td> + <td>0x882E</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER10</code></td> + <td>0x882F</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER11</code></td> + <td>0x8830</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER12</code></td> + <td>0x8831</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER13</code></td> + <td>0x8832</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER14</code></td> + <td>0x8833</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_BUFFER15</code></td> + <td>0x8834</td> + <td></td> + </tr> + <tr> + <td><code>MAX_COLOR_ATTACHMENTS</code></td> + <td>0x8CDF</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT1</code></td> + <td>0x8CE1</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT2</code></td> + <td>0x8CE2</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT3</code></td> + <td>0x8CE3</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT4</code></td> + <td>0x8CE4</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT5</code></td> + <td>0x8CE5</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT6</code></td> + <td>0x8CE6</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT7</code></td> + <td>0x8CE7</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT8</code></td> + <td>0x8CE8</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT9</code></td> + <td>0x8CE9</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT10</code></td> + <td>0x8CEA</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT11</code></td> + <td>0x8CEB</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT12</code></td> + <td>0x8CEC</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT13</code></td> + <td>0x8CED</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT14</code></td> + <td>0x8CEE</td> + <td></td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT15</code></td> + <td>0x8CEF</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Samplers">Samplers</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>SAMPLER_3D</code></td> + <td>0x8B5F</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLER_2D_SHADOW</code></td> + <td>0x8B62</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLER_2D_ARRAY</code></td> + <td>0x8DC1</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLER_2D_ARRAY_SHADOW</code></td> + <td>0x8DC4</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLER_CUBE_SHADOW</code></td> + <td>0x8DC5</td> + <td></td> + </tr> + <tr> + <td><code>INT_SAMPLER_2D</code></td> + <td>0x8DCA</td> + <td></td> + </tr> + <tr> + <td><code>INT_SAMPLER_3D</code></td> + <td>0x8DCB</td> + <td></td> + </tr> + <tr> + <td><code>INT_SAMPLER_CUBE</code></td> + <td>0x8DCC</td> + <td></td> + </tr> + <tr> + <td><code>INT_SAMPLER_2D_ARRAY</code></td> + <td>0x8DCF</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_INT_SAMPLER_2D</code></td> + <td>0x8DD2</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_INT_SAMPLER_3D</code></td> + <td>0x8DD3</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_INT_SAMPLER_CUBE</code></td> + <td>0x8DD4</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_INT_SAMPLER_2D_ARRAY</code></td> + <td>0x8DD7</td> + <td></td> + </tr> + <tr> + <td><code>MAX_SAMPLES</code></td> + <td>0x8D57</td> + <td></td> + </tr> + <tr> + <td><code>SAMPLER_BINDING</code></td> + <td>0x8919</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Buffers_2">Buffers</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>PIXEL_PACK_BUFFER</code></td> + <td>0x88EB</td> + <td></td> + </tr> + <tr> + <td><code>PIXEL_UNPACK_BUFFER</code></td> + <td>0x88EC</td> + <td></td> + </tr> + <tr> + <td><code>PIXEL_PACK_BUFFER_BINDING</code></td> + <td>0x88ED</td> + <td></td> + </tr> + <tr> + <td><code>PIXEL_UNPACK_BUFFER_BINDING </code></td> + <td>0x88EF</td> + <td></td> + </tr> + <tr> + <td><code>COPY_READ_BUFFER</code></td> + <td>0x8F36</td> + <td></td> + </tr> + <tr> + <td><code>COPY_WRITE_BUFFER</code></td> + <td>0x8F37</td> + <td></td> + </tr> + <tr> + <td><code>COPY_READ_BUFFER_BINDING</code></td> + <td>0x8F36</td> + <td></td> + </tr> + <tr> + <td><code>COPY_WRITE_BUFFER_BINDING</code></td> + <td>0x8F37</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Data_types_2">Data types</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>FLOAT_MAT2x3</code></td> + <td>0x8B65</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_MAT2x4</code></td> + <td>0x8B66</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_MAT3x2</code></td> + <td>0x8B67</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_MAT3x4 </code></td> + <td>0x8B68</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_MAT4x2</code></td> + <td>0x8B69</td> + <td></td> + </tr> + <tr> + <td><code>FLOAT_MAT4x3</code></td> + <td>0x8B6A</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_INT_VEC2</code></td> + <td>0x8DC6</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_INT_VEC3</code></td> + <td>0x8DC7</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_INT_VEC4</code></td> + <td>0x8DC8</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_NORMALIZED</code></td> + <td>0x8C17</td> + <td></td> + </tr> + <tr> + <td><code>SIGNED_NORMALIZED</code></td> + <td>0x8F9C</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Vertex_attributes_2">Vertex attributes</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>VERTEX_ATTRIB_ARRAY_INTEGER </code></td> + <td>0x88FD</td> + <td></td> + </tr> + <tr> + <td><code>VERTEX_ATTRIB_ARRAY_DIVISOR</code></td> + <td>0x88FE</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Transform_feedback">Transform feedback</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>TRANSFORM_FEEDBACK_BUFFER_MODE</code></td> + <td>0x8C7F</td> + <td></td> + </tr> + <tr> + <td><code>MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS</code></td> + <td>0x8C80</td> + <td></td> + </tr> + <tr> + <td><code>TRANSFORM_FEEDBACK_VARYINGS</code></td> + <td>0x8C83</td> + <td></td> + </tr> + <tr> + <td><code>TRANSFORM_FEEDBACK_BUFFER_START</code></td> + <td>0x8C84</td> + <td></td> + </tr> + <tr> + <td><code>TRANSFORM_FEEDBACK_BUFFER_SIZE</code></td> + <td>0x8C85</td> + <td></td> + </tr> + <tr> + <td><code>TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN</code></td> + <td>0x8C88</td> + <td></td> + </tr> + <tr> + <td><code>MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS</code></td> + <td>0x8C8A</td> + <td></td> + </tr> + <tr> + <td><code>MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS</code></td> + <td>0x8C8B</td> + <td></td> + </tr> + <tr> + <td><code>INTERLEAVED_ATTRIBS</code></td> + <td>0x8C8C</td> + <td></td> + </tr> + <tr> + <td><code>SEPARATE_ATTRIBS</code></td> + <td>0x8C8D</td> + <td></td> + </tr> + <tr> + <td><code>TRANSFORM_FEEDBACK_BUFFER</code></td> + <td>0x8C8E</td> + <td></td> + </tr> + <tr> + <td><code>TRANSFORM_FEEDBACK_BUFFER_BINDING</code></td> + <td>0x8C8F</td> + <td></td> + </tr> + <tr> + <td><code>TRANSFORM_FEEDBACK</code></td> + <td>0x8E22</td> + <td></td> + </tr> + <tr> + <td><code>TRANSFORM_FEEDBACK_PAUSED</code></td> + <td>0x8E23</td> + <td></td> + </tr> + <tr> + <td><code>TRANSFORM_FEEDBACK_ACTIVE</code></td> + <td>0x8E24</td> + <td></td> + </tr> + <tr> + <td><code>TRANSFORM_FEEDBACK_BINDING</code></td> + <td>0x8E25</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Framebuffers_and_renderbuffers_2">Framebuffers and renderbuffers</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING</code></td> + <td>0x8210</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE</code></td> + <td>0x8211</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_RED_SIZE</code></td> + <td>0x8212</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_GREEN_SIZE</code></td> + <td>0x8213</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_BLUE_SIZE</code></td> + <td>0x8214</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE</code></td> + <td>0x8215</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE</code></td> + <td>0x8216</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE</code></td> + <td>0x8217</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_DEFAULT</code></td> + <td>0x8218</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH_STENCIL_ATTACHMENT</code></td> + <td>0x821A</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH_STENCIL</code></td> + <td>0x84F9</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH24_STENCIL8</code></td> + <td>0x88F0</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_FRAMEBUFFER_BINDING</code></td> + <td>0x8CA6</td> + <td></td> + </tr> + <tr> + <td><code>READ_FRAMEBUFFER</code></td> + <td>0x8CA8</td> + <td></td> + </tr> + <tr> + <td><code>DRAW_FRAMEBUFFER</code></td> + <td>0x8CA9</td> + <td></td> + </tr> + <tr> + <td><code>READ_FRAMEBUFFER_BINDING</code></td> + <td>0x8CAA</td> + <td></td> + </tr> + <tr> + <td><code>RENDERBUFFER_SAMPLES</code></td> + <td>0x8CAB</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER</code></td> + <td>0x8CD4</td> + <td></td> + </tr> + <tr> + <td><code>FRAMEBUFFER_INCOMPLETE_MULTISAMPLE</code></td> + <td>0x8D56</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Uniforms">Uniforms</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>UNIFORM_BUFFER</code></td> + <td>0x8A11</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BUFFER_BINDING</code></td> + <td>0x8A28</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BUFFER_START</code></td> + <td>0x8A29</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BUFFER_SIZE</code></td> + <td>0x8A2A</td> + <td></td> + </tr> + <tr> + <td><code>MAX_VERTEX_UNIFORM_BLOCKS</code></td> + <td>0x8A2B</td> + <td></td> + </tr> + <tr> + <td><code>MAX_FRAGMENT_UNIFORM_BLOCKS</code></td> + <td>0x8A2D</td> + <td></td> + </tr> + <tr> + <td><code>MAX_COMBINED_UNIFORM_BLOCKS</code></td> + <td>0x8A2E</td> + <td></td> + </tr> + <tr> + <td><code>MAX_UNIFORM_BUFFER_BINDINGS</code></td> + <td>0x8A2F</td> + <td></td> + </tr> + <tr> + <td><code>MAX_UNIFORM_BLOCK_SIZE</code></td> + <td>0x8A30</td> + <td></td> + </tr> + <tr> + <td><code>MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS</code></td> + <td>0x8A31</td> + <td></td> + </tr> + <tr> + <td><code>MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS</code></td> + <td>0x8A33</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BUFFER_OFFSET_ALIGNMENT</code></td> + <td>0x8A34</td> + <td></td> + </tr> + <tr> + <td><code>ACTIVE_UNIFORM_BLOCKS</code></td> + <td>0x8A36</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_TYPE </code></td> + <td>0x8A37</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_SIZE</code></td> + <td>0x8A38</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BLOCK_INDEX</code></td> + <td>0x8A3A</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_OFFSET</code></td> + <td>0x8A3B</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_ARRAY_STRIDE</code></td> + <td>0x8A3C</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_MATRIX_STRIDE</code></td> + <td>0x8A3D</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_IS_ROW_MAJOR</code></td> + <td>0x8A3E</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BLOCK_BINDING</code></td> + <td>0x8A3F</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BLOCK_DATA_SIZE</code></td> + <td>0x8A40</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BLOCK_ACTIVE_UNIFORMS</code></td> + <td>0x8A42</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES</code></td> + <td>0x8A43</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER</code></td> + <td>0x8A44</td> + <td></td> + </tr> + <tr> + <td><code>UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER</code></td> + <td>0x8A46</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Sync_objects">Sync objects</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>OBJECT_TYPE</code></td> + <td>0x9112</td> + <td></td> + </tr> + <tr> + <td><code>SYNC_CONDITION</code></td> + <td>0x9113</td> + <td></td> + </tr> + <tr> + <td><code>SYNC_STATUS</code></td> + <td>0x9114</td> + <td></td> + </tr> + <tr> + <td><code>SYNC_FLAGS</code></td> + <td>0x9115</td> + <td></td> + </tr> + <tr> + <td><code>SYNC_FENCE</code></td> + <td>0x9116</td> + <td></td> + </tr> + <tr> + <td><code>SYNC_GPU_COMMANDS_COMPLETE</code></td> + <td>0x9117</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNALED</code></td> + <td>0x9118</td> + <td></td> + </tr> + <tr> + <td><code>SIGNALED</code></td> + <td>0x9119</td> + <td></td> + </tr> + <tr> + <td><code>ALREADY_SIGNALED</code></td> + <td>0x911A</td> + <td></td> + </tr> + <tr> + <td><code>TIMEOUT_EXPIRED</code></td> + <td>0x911B</td> + <td></td> + </tr> + <tr> + <td><code>CONDITION_SATISFIED</code></td> + <td>0x911C</td> + <td></td> + </tr> + <tr> + <td><code>WAIT_FAILED</code></td> + <td>0x911D</td> + <td></td> + </tr> + <tr> + <td><code>SYNC_FLUSH_COMMANDS_BIT</code></td> + <td>0x00000001</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Miscellaneous_constants">Miscellaneous constants</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>COLOR</code></td> + <td>0x1800</td> + <td></td> + </tr> + <tr> + <td>DEPTH</td> + <td>0x1801</td> + <td></td> + </tr> + <tr> + <td><code>STENCIL</code></td> + <td>0x1802</td> + <td></td> + </tr> + <tr> + <td><code>MIN</code></td> + <td>0x8007</td> + <td></td> + </tr> + <tr> + <td>MAX</td> + <td>0x8008</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH_COMPONENT24</code></td> + <td>0x81A6</td> + <td></td> + </tr> + <tr> + <td><code>STREAM_READ</code></td> + <td>0x88E1</td> + <td></td> + </tr> + <tr> + <td><code>STREAM_COPY</code></td> + <td>0x88E2</td> + <td></td> + </tr> + <tr> + <td><code>STATIC_READ</code></td> + <td>0x88E5</td> + <td></td> + </tr> + <tr> + <td><code>STATIC_COPY</code></td> + <td>0x88E6</td> + <td></td> + </tr> + <tr> + <td><code>DYNAMIC_READ</code></td> + <td>0x88E9</td> + <td></td> + </tr> + <tr> + <td><code>DYNAMIC_COPY</code></td> + <td>0x88EA</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH_COMPONENT32F</code></td> + <td>0x8CAC</td> + <td></td> + </tr> + <tr> + <td><code>DEPTH32F_STENCIL8</code></td> + <td>0x8CAD</td> + <td></td> + </tr> + <tr> + <td><code>INVALID_INDEX</code></td> + <td>0xFFFFFFFF</td> + <td></td> + </tr> + <tr> + <td><code>TIMEOUT_IGNORED</code></td> + <td>-1</td> + <td></td> + </tr> + <tr> + <td><code>MAX_CLIENT_WAIT_TIMEOUT_WEBGL</code></td> + <td>0x9247</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="Constants_defined_in_WebGL_extensions">Constants defined in WebGL extensions</h2> + +<h3 id="domxrefANGLE_instanced_arrays">{{domxref("ANGLE_instanced_arrays")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE</code></td> + <td>0x88FE</td> + <td>Describes the frequency divisor used for instanced rendering.</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefWEBGL_debug_renderer_info">{{domxref("WEBGL_debug_renderer_info")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>UNMASKED_VENDOR_WEBGL</code></td> + <td>0x9245</td> + <td>Passed to <code>getParameter</code> to get the vendor string of the graphics driver.</td> + </tr> + <tr> + <td><code>UNMASKED_RENDERER_WEBGL</code></td> + <td>0x9246</td> + <td>Passed to <code>getParameter</code> to get the renderer string of the graphics driver.</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefEXT_texture_filter_anisotropic">{{domxref("EXT_texture_filter_anisotropic")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>MAX_TEXTURE_MAX_ANISOTROPY_EXT</code></td> + <td>0x84FF</td> + <td>Returns the maximum available anisotropy.</td> + </tr> + <tr> + <td><code>TEXTURE_MAX_ANISOTROPY_EXT</code></td> + <td>0x84FE</td> + <td>Passed to <code>texParameter</code> to set the desired maximum anisotropy for a texture.</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefWEBGL_compressed_texture_s3tc">{{domxref("WEBGL_compressed_texture_s3tc")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>COMPRESSED_RGB_S3TC_DXT1_EXT</code></td> + <td>0x83F0</td> + <td>A DXT1-compressed image in an RGB image format.</td> + </tr> + <tr> + <td><code>COMPRESSED_RGBA_S3TC_DXT1_EXT</code></td> + <td>0x83F1</td> + <td>A DXT1-compressed image in an RGB image format with a simple on/off alpha value.</td> + </tr> + <tr> + <td><code>COMPRESSED_RGBA_S3TC_DXT3_EXT</code></td> + <td>0x83F2</td> + <td>A DXT3-compressed image in an RGBA image format. Compared to a 32-bit RGBA texture, it offers 4:1 compression.</td> + </tr> + <tr> + <td><code>COMPRESSED_RGBA_S3TC_DXT5_EXT</code></td> + <td>0x83F3</td> + <td>A DXT5-compressed image in an RGBA image format. It also provides a 4:1 compression, but differs to the DXT3 compression in how the alpha compression is done.</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefWEBGL_compressed_texture_es3">{{domxref("WEBGL_compressed_texture_es3")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>COMPRESSED_R11_EAC</code></td> + <td>0x9270</td> + <td>One-channel (red) unsigned format compression.</td> + </tr> + <tr> + <td><code>COMPRESSED_SIGNED_R11_EAC</code></td> + <td>0x9271</td> + <td>One-channel (red) signed format compression.</td> + </tr> + <tr> + <td><code>COMPRESSED_RG11_EAC</code></td> + <td>0x9272</td> + <td>Two-channel (red and green) unsigned format compression.</td> + </tr> + <tr> + <td><code>COMPRESSED_SIGNED_RG11_EAC</code></td> + <td>0x9273</td> + <td>Two-channel (red and green) signed format compression.</td> + </tr> + <tr> + <td><code>COMPRESSED_RGB8_ETC2</code></td> + <td>0x9274</td> + <td>Compresses RBG8 data with no alpha channel.</td> + </tr> + <tr> + <td><code>COMPRESSED_RGBA8_ETC2_EAC</code></td> + <td>0x9275</td> + <td>Compresses RGBA8 data. The RGB part is encoded the same as <code>RGB_ETC2</code>, but the alpha part is encoded separately.</td> + </tr> + <tr> + <td><code>COMPRESSED_SRGB8_ETC2</code></td> + <td>0x9276</td> + <td>Compresses sRBG8 data with no alpha channel.</td> + </tr> + <tr> + <td><code>COMPRESSED_SRGB8_ALPHA8_ETC2_EAC</code></td> + <td>0x9277</td> + <td>Compresses sRGBA8 data. The sRGB part is encoded the same as <code>SRGB_ETC2</code>, but the alpha part is encoded separately.</td> + </tr> + <tr> + <td><code>COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2</code></td> + <td>0x9278</td> + <td>Similar to <code>RGB8_ETC</code>, but with ability to punch through the alpha channel, which means to make it completely opaque or transparent.</td> + </tr> + <tr> + <td><code>COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2</code></td> + <td>0x9279</td> + <td>Similar to <code>SRGB8_ETC</code>, but with ability to punch through the alpha channel, which means to make it completely opaque or transparent.</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefWEBGL_compressed_texture_pvrtc">{{domxref("WEBGL_compressed_texture_pvrtc")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>COMPRESSED_RGB_PVRTC_4BPPV1_IMG</code></td> + <td>0x8C00</td> + <td>RGB compression in 4-bit mode. One block for each 4×4 pixels.</td> + </tr> + <tr> + <td><code>COMPRESSED_RGBA_PVRTC_4BPPV1_IMG</code></td> + <td>0x8C02</td> + <td>RGBA compression in 4-bit mode. One block for each 4×4 pixels.</td> + </tr> + <tr> + <td><code>COMPRESSED_RGB_PVRTC_2BPPV1_IMG</code></td> + <td>0x8C01</td> + <td>RGB compression in 2-bit mode. One block for each 8×4 pixels.</td> + </tr> + <tr> + <td><code>COMPRESSED_RGBA_PVRTC_2BPPV1_IMG</code></td> + <td>0x8C03</td> + <td>RGBA compression in 2-bit mode. One block for each 8×4 pixe</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefWEBGL_compressed_texture_etc1">{{domxref("WEBGL_compressed_texture_etc1")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>COMPRESSED_RGB_ETC1_WEBGL</code></td> + <td>0x8D64</td> + <td>Compresses 24-bit RGB data with no alpha channel.</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefWEBGL_compressed_texture_atc">{{domxref("WEBGL_compressed_texture_atc")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>COMPRESSED_RGB_ATC_WEBGL</code></td> + <td>0x8C92</td> + <td>Compresses RGB textures with no alpha channel.</td> + </tr> + <tr> + <td><code>COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL</code></td> + <td>0x8C92</td> + <td>Compresses RGBA textures using explicit alpha encoding (useful when alpha transitions are sharp).</td> + </tr> + <tr> + <td><code>COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL</code></td> + <td>0x87EE</td> + <td>Compresses RGBA textures using interpolated alpha encoding (useful when alpha transitions are gradient).</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefWEBGL_depth_texture">{{domxref("WEBGL_depth_texture")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>UNSIGNED_INT_24_8_WEBGL</code></td> + <td>0x84FA</td> + <td>Unsigned integer type for 24-bit depth texture data.</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefOES_texture_half_float">{{domxref("OES_texture_half_float")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>HALF_FLOAT_OES</code></td> + <td>0x8D61</td> + <td>Half floating-point type (16-bit).</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefWEBGL_color_buffer_float">{{domxref("WEBGL_color_buffer_float")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>RGBA32F_EXT</code></td> + <td>0x8814</td> + <td>RGBA 32-bit floating-point color-renderable format.</td> + </tr> + <tr> + <td><code>RGB32F_EXT</code></td> + <td>0x8815</td> + <td>RGB 32-bit floating-point color-renderable format.</td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT</code></td> + <td>0x8211</td> + <td></td> + </tr> + <tr> + <td><code>UNSIGNED_NORMALIZED_EXT</code></td> + <td>0x8C17</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="domxrefEXT_blend_minmax">{{domxref("EXT_blend_minmax")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>MIN_EXT</code></td> + <td>0x8007</td> + <td>Produces the minimum color components of the source and destination colors.</td> + </tr> + <tr> + <td><code>MAX_EXT</code></td> + <td>0x8008</td> + <td>Produces the maximum color components of the source and destination colors.</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefEXT_sRGB">{{domxref("EXT_sRGB")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>SRGB_EXT</code></td> + <td>0x8C40</td> + <td>Unsized sRGB format that leaves the precision up to the driver.</td> + </tr> + <tr> + <td><code>SRGB_ALPHA_EXT</code></td> + <td>0x8C42</td> + <td>Unsized sRGB format with unsized alpha component.</td> + </tr> + <tr> + <td><code>SRGB8_ALPHA8_EXT</code></td> + <td>0x8C43</td> + <td>Sized (8-bit) sRGB and alpha formats.</td> + </tr> + <tr> + <td><code>FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT</code></td> + <td>0x8210</td> + <td>Returns the framebuffer color encoding.</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefOES_standard_derivatives">{{domxref("OES_standard_derivatives")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>FRAGMENT_SHADER_DERIVATIVE_HINT_OES</code></td> + <td>0x8B8B</td> + <td>Indicates the accuracy of the derivative calculation for the GLSL built-in functions: <code>dFdx</code>, <code>dFdy</code>, and <code>fwidth</code>.</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefWEBGL_draw_buffers">{{domxref("WEBGL_draw_buffers")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>COLOR_ATTACHMENT0_WEBGL</code></td> + <td>0x8CE0</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT1_WEBGL</code></td> + <td>0x8CE1</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT2_WEBGL</code></td> + <td>0x8CE2</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT3_WEBGL</code></td> + <td>0x8CE3</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT4_WEBGL</code></td> + <td>0x8CE4</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT5_WEBGL</code></td> + <td>0x8CE5</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT6_WEBGL</code></td> + <td>0x8CE6</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT7_WEBGL</code></td> + <td>0x8CE7</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT8_WEBGL</code></td> + <td>0x8CE8</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT9_WEBGL</code></td> + <td>0x8CE9</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT10_WEBGL</code></td> + <td>0x8CEA</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT11_WEBGL</code></td> + <td>0x8CEB</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT12_WEBGL</code></td> + <td>0x8CEC</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT13_WEBGL</code></td> + <td>0x8CED</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT14_WEBGL</code></td> + <td>0x8CEE</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>COLOR_ATTACHMENT15_WEBGL</code></td> + <td>0x8CEF</td> + <td>Framebuffer color attachment point</td> + </tr> + <tr> + <td><code>DRAW_BUFFER0_WEBGL</code></td> + <td>0x8825</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER1_WEBGL</code></td> + <td>0x8826</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER2_WEBGL</code></td> + <td>0x8827</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER3_WEBGL</code></td> + <td>0x8828</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER4_WEBGL</code></td> + <td>0x8829</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER5_WEBGL</code></td> + <td>0x882A</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER6_WEBGL</code></td> + <td>0x882B</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER7_WEBGL</code></td> + <td>0x882C</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER8_WEBGL</code></td> + <td>0x882D</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER9_WEBGL</code></td> + <td>0x882E</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER10_WEBGL</code></td> + <td>0x882F</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER11_WEBGL</code></td> + <td>0x8830</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER12_WEBGL</code></td> + <td>0x8831</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER13_WEBGL</code></td> + <td>0x8832</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER14_WEBGL</code></td> + <td>0x8833</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>DRAW_BUFFER15_WEBGL</code></td> + <td>0x8834</td> + <td>Draw buffer</td> + </tr> + <tr> + <td><code>MAX_COLOR_ATTACHMENTS_WEBGL</code></td> + <td>0x8CDF</td> + <td>Maximum number of framebuffer color attachment points</td> + </tr> + <tr> + <td><code>MAX_DRAW_BUFFERS_WEBGL</code></td> + <td>0x8824</td> + <td>Maximum number of draw buffers</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefOES_vertex_array_object">{{domxref("OES_vertex_array_object")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>VERTEX_ARRAY_BINDING_OES</code></td> + <td>0x85B5</td> + <td>The bound vertex array object (VAO).</td> + </tr> + </tbody> +</table> + +<h3 id="domxrefEXT_disjoint_timer_query">{{domxref("EXT_disjoint_timer_query")}}</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Constant name</th> + <th scope="col">Value</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>QUERY_COUNTER_BITS_EXT</code></td> + <td>0x8864</td> + <td>The number of bits used to hold the query result for the given target.</td> + </tr> + <tr> + <td><code>CURRENT_QUERY_EXT</code></td> + <td>0x8865</td> + <td>The currently active query.</td> + </tr> + <tr> + <td><code>QUERY_RESULT_EXT</code></td> + <td>0x8866</td> + <td>The query result.</td> + </tr> + <tr> + <td><code>QUERY_RESULT_AVAILABLE_EXT</code></td> + <td>0x8867</td> + <td>A Boolean indicating whether or not a query result is available.</td> + </tr> + <tr> + <td><code>TIME_ELAPSED_EXT</code></td> + <td>0x88BF</td> + <td>Elapsed time (in nanoseconds).</td> + </tr> + <tr> + <td><code>TIMESTAMP_EXT</code></td> + <td>0x8E28</td> + <td>The current time.</td> + </tr> + <tr> + <td><code>GPU_DISJOINT_EXT</code></td> + <td>0x8FBB</td> + <td>A Boolean indicating whether or not the GPU performed any disjoint operation.</td> + </tr> + </tbody> +</table> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('WebGL', "#5.14", "WebGLRenderingContext")}}</td> + <td>{{Spec2('WebGL')}}</td> + <td>Initial definition</td> + </tr> + <tr> + <td>{{SpecName('WebGL2', "#3.7", "WebGL2RenderingContext")}}</td> + <td>{{Spec2('WebGL2')}}</td> + <td>Defines additional constants.</td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatChrome("9")}}</td> + <td>{{CompatGeckoDesktop("2.0")}}</td> + <td>{{CompatIE("11")}}</td> + <td>{{CompatOpera("12")}}</td> + <td>{{CompatSafari("5.1")}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>25</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>12</td> + <td>8.1</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{domxref("WebGLRenderingContext")}}</li> +</ul> diff --git a/files/zh-cn/web/api/webgl_api/data/index.html b/files/zh-cn/web/api/webgl_api/data/index.html new file mode 100644 index 0000000000..ded07d6e36 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/data/index.html @@ -0,0 +1,89 @@ +--- +title: Data in WebGL +slug: Web/API/WebGL_API/Data +tags: + - 3D + - 3D 图像 + - WebGL + - WebGL API + - 中间件 + - 变体 + - 图形 + - 属性 + - 指南 + - 绘图 + - 统一的 + - 需要内容 + - 需要示例 +translation_of: Web/API/WebGL_API/Data +--- +<div>{{WebGLSidebar}}{{draft}}</div> + +<p>GLSL 为 Shader 提供了三种不同作用的数据存储,每种都有一个特定的用例。每种数据依作用不同可以被一种或者全部shader访问(取决于数据存储类型),也可能通过站点的Javascript代码进行访问,这取决于变量的特定类型。</p> + +<h2 id="GLSL_数据类型">GLSL 数据类型</h2> + +<p><<关于 基本数据类型, 向量等,参见Khronos WebGL Wiki的文档:<a href="https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)">Data Type (GLSL)</a> >></p> + +<h2 id="GLSL_变量">GLSL 变量</h2> + +<p>GLSL中有三种类型的“变量”或者说数据存储类型。每一种类型都有特定的目标和使用方法:: <strong>{{anch("Attributes", "attributes")}}</strong>、<strong>{{anch("Varyings", "varyings")}}</strong>和<strong>{{anch("Uniforms", "uniforms")}}</strong>.</p> + +<h3 id="Attributes">Attributes</h3> + +<p><strong>Attributes</strong> 可以被JavaScript代码操作,也可以在 vertex shader 中被作为变量访问。Attributes 通常被用于存储颜色、纹理坐标以及其他需要在JavaScript代码和 vertex shader 之间互相传递的数据。</p> + +<pre class="brush: js notranslate">//init colors + var vertexColors = [ + vec4( 0.0, 0.0, 0.0, 1.0 ), // black + vec4( 1.0, 0.0, 0.0, 1.0 ), // red + vec4( 1.0, 1.0, 0.0, 1.0 ), // yellow + vec4( 0.0, 1.0, 0.0, 1.0 ), // green + vec4( 0.0, 0.0, 0.0, 1.0 ), // black + vec4( 1.0, 0.0, 0.0, 1.0 ), // red + vec4( 1.0, 1.0, 0.0, 1.0 ), // yellow + vec4( 0.0, 1.0, 0.0, 1.0 ), // green + ]; + var cBuffer = gl.createBuffer(); +</pre> + +<pre class="brush: js notranslate">//continued +//create buffer to store colors and reference it to "vColor" which is in GLSL + gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer ); + gl.bufferData( gl.ARRAY_BUFFER, flatten(vertexColors), gl.STATIC_DRAW ); + + var vColor = gl.getAttribLocation( program, "vColor" ); + gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 ); + gl.enableVertexAttribArray( vColor ); +</pre> + +<pre class="brush: cpp notranslate">//glsl +attribute vec4 vColor; + +void main() +{ + +fColor = vColor; +} + +</pre> + +<h3 id="Varyings">Varyings</h3> + +<p><strong>Varyings</strong> 在 vertex shader 中定义,用于从 vertex shader 向 fragment shader 传递数据。通常传递 {{interwiki("wikipedia", "Normal_(geometry)", "normal vector")}} 等在 vertex shader 中计算生成的数据会使用varying。</p> + +<p><<how to use>></p> + +<h3 id="Uniforms">Uniforms</h3> + +<p><strong>Uniform</strong> 通常是由 JavaScript 代码设置并且在 vertex shader 和 fragment shader 中都能够访问。 使用uniform设定在一帧的所有绘制中相同的数据,例如光源颜色、亮度、全局变换以及透视数据等等。</p> + +<p><<添加细节>></p> + +<h2 id="Buffers">Buffers</h2> + +<p><<添加信息>></p> + +<h2 id="Textures">Textures</h2> + +<p><<添加信息>></p> diff --git a/files/zh-cn/web/api/webgl_api/index.html b/files/zh-cn/web/api/webgl_api/index.html new file mode 100644 index 0000000000..ed1f1dede2 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/index.html @@ -0,0 +1,267 @@ +--- +title: WebGL +slug: Web/API/WebGL_API +tags: + - 3D图形 + - WebGL + - WebGL API + - 图像 + - 媒体 + - 高级 +translation_of: Web/API/WebGL_API +--- +<div class="boxed translate-rendered"> +<div>{{WebGLSidebar}}</div> + +<div class="summary"> +<p>WebGL(Web图形库)是一个JavaScript API,可在任何兼容的Web浏览器中渲染高性能的交互式3D和2D图形,而无需使用插件。WebGL通过引入一个与OpenGL ES 2.0非常一致的API来做到这一点,该API可以在HTML5 {{HTMLElement("canvas")}}元素中使用。 这种一致性使API可以利用用户设备提供的硬件图形加速。</p> +</div> + +<p>目前支持 WebGL 的浏览器有:<a href="https://developer.mozilla.org/zh-CN/Firefox" title="Firefox 4 for developers">Firefox</a> 4+, <a href="http://www.google.com/chrome/" title="http://www.google.com/chrome/">Google Chrome</a> 9+, <a href="http://www.opera.com/" title="http://www.opera.com/">Opera</a> 12+, <a href="http://www.apple.com/safari/" title="http://www.apple.com/fr/safari/">Safari </a>5.1+, <a href="http://windows.microsoft.com/en-us/internet-explorer/browser-ie" title="http://windows.microsoft.com/en-us/internet-explorer/download-ie">Internet Explorer</a> 11+和<a href="https://www.microsoft.com/en-us/edge">Microsoft Edge</a> build 10240+;然而, WebGL一些特性也需要用户的硬件设备支持。</p> + +<p>{{anch("WebGL 2")}}<font><font> API引入了对大部分的OpenGL ES 3.0功能集的支持; </font><font>它是通过</font></font>{{domxref("WebGL2RenderingContext")}}<font><font>界面</font><font>提供的</font><font>。</font></font></p> + +<p> {{HTMLElement("canvas")}} 元素也被 <a href="https://wiki.developer.mozilla.org/en-US/docs/Web/API/Canvas_API">Canvas API</a> 用于在网页上进行2D图形处理。</p> + +<h2 id="参考">参考</h2> + +<h3 id="标准接口">标准接口</h3> + +<div class="index"> +<ul> + <li>{{domxref("WebGLRenderingContext")}}</li> + <li>{{domxref("WebGL2RenderingContext")}}</li> + <li>{{domxref("WebGLActiveInfo")}}</li> + <li>{{domxref("WebGLBuffer")}}</li> + <li>{{domxref("WebGLContextEvent")}}</li> + <li>{{domxref("WebGLFramebuffer")}}</li> + <li>{{domxref("WebGLProgram")}}</li> + <li>{{domxref("WebGLQuery")}}</li> + <li>{{domxref("WebGLRenderbuffer")}}</li> + <li>{{domxref("WebGLSampler")}}</li> + <li>{{domxref("WebGLShader")}}</li> + <li>{{domxref("WebGLShaderPrecisionFormat")}}</li> + <li>{{domxref("WebGLSync")}}</li> + <li>{{domxref("WebGLTexture")}}</li> + <li>{{domxref("WebGLTransformFeedback")}}</li> + <li>{{domxref("WebGLUniformLocation")}}</li> + <li>{{domxref("WebGLVertexArrayObject")}}</li> +</ul> +</div> + +<h3 id="扩展">扩展</h3> + +<div class="index"> +<ul> + <li>{{domxref("ANGLE_instanced_arrays")}}</li> + <li>{{domxref("EXT_blend_minmax")}}</li> + <li>{{domxref("EXT_color_buffer_float")}}</li> + <li>{{domxref("EXT_color_buffer_half_float")}}</li> + <li>{{domxref("EXT_disjoint_timer_query")}}</li> + <li>{{domxref("EXT_float_blend")}} {{experimental_inline}}</li> + <li>{{domxref("EXT_frag_depth")}}</li> + <li>{{domxref("EXT_sRGB")}}</li> + <li>{{domxref("EXT_shader_texture_lod")}}</li> + <li>{{domxref("EXT_texture_compression_bptc")}}</li> + <li>{{domxref("EXT_texture_compression_rgtc")}}</li> + <li>{{domxref("EXT_texture_filter_anisotropic")}}</li> + <li>{{domxref("OES_element_index_uint")}}</li> + <li>{{domxref("OES_fbo_render_mipmap")}}</li> + <li>{{domxref("OES_standard_derivatives")}}</li> + <li>{{domxref("OES_texture_float")}}</li> + <li>{{domxref("OES_texture_float_linear")}}</li> + <li>{{domxref("OES_texture_half_float")}}</li> + <li>{{domxref("OES_texture_half_float_linear")}}</li> + <li>{{domxref("OES_vertex_array_object")}}</li> + <li>{{domxref("OVR_multiview2")}}</li> + <li>{{domxref("WEBGL_color_buffer_float")}}</li> + <li>{{domxref("WEBGL_compressed_texture_astc")}}</li> + <li>{{domxref("WEBGL_compressed_texture_atc")}}</li> + <li>{{domxref("WEBGL_compressed_texture_etc")}}</li> + <li>{{domxref("WEBGL_compressed_texture_etc1")}}</li> + <li>{{domxref("WEBGL_compressed_texture_pvrtc")}}</li> + <li>{{domxref("WEBGL_compressed_texture_s3tc")}}</li> + <li>{{domxref("WEBGL_compressed_texture_s3tc_srgb")}}</li> + <li>{{domxref("WEBGL_debug_renderer_info")}}</li> + <li>{{domxref("WEBGL_debug_shaders")}}</li> + <li>{{domxref("WEBGL_depth_texture")}}</li> + <li>{{domxref("WEBGL_draw_buffers")}}</li> + <li>{{domxref("WEBGL_lose_context")}}</li> +</ul> +</div> + +<h3 id="事件">事件</h3> + +<ul> + <li>{{domxref("HTMLCanvasElement/webglcontextlost_event", "webglcontextlost")}}</li> + <li>{{domxref("HTMLCanvasElement/webglcontextrestored_event", "webglcontextrestored")}}</li> + <li>{{domxref("HTMLCanvasElement/webglcontextcreationerror_event", "webglcontextcreationerror")}}<br> + </li> +</ul> + +<h3 id="常量和类型">常量和类型</h3> + +<ul> + <li><a href="/zh-CN/docs/Web/API/WebGL_API/Constants">WebGL常量</a></li> + <li><a href="/zh-CN/docs/Web/API/WebGL_API/Types">WebGL类型</a></li> +</ul> + +<h3 id="WebGL_2">WebGL 2</h3> + +<p>WebGL 2 是WebGL的一个主要更新,它通过{{domxref("WebGL2RenderingContext")}} 接口提供。它基于OpenGL ES 3.0,新功能包括:</p> + +<ul> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL2RenderingContext/texImage3D">3D textures</a>,</li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLSampler">Sampler objects</a>,</li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL2RenderingContext#Uniform_buffer_objects">Uniform Buffer objects</a>,</li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLSync">Sync objects</a>,</li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLQuery">Query objects</a>,</li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLTransformFeedback">Tranform Feedback objects</a>,</li> + <li>部分扩展被纳入了 WebGL 2 核心 : <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLVertexArrayObject">Vertex Array objects</a>, <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL2RenderingContext/drawArraysInstanced">instancing</a>, <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL2RenderingContext/drawBuffers">multiple render targets</a>, <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/EXT_frag_depth">fragment depth</a>.</li> +</ul> + +<p>另请参见博客文章 <a href="https://hacks.mozilla.org/2017/01/webgl-2-lands-in-firefox/">"WebGL 2 lands in Firefox"</a> 和 <a href="http://webglsamples.org/WebGL2Samples/">webglsamples.org/WebGL2Samples</a> 几个演示。</p> + +<h2 id="指南和教程">指南和教程</h2> + +<p>下面,您将找到各种指南,以帮助您学习WebGL概念和教程,提供分步课程和示例。</p> + +<h3 id="指南">指南 </h3> + +<dl> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/Data">WebGL 中的数据</a></dt> + <dd>编写WebGL代码时使用的变量,缓冲区和其他类型数据的指南。</dd> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/WebGL_best_practices">WebGL 最佳实践</a></dt> + <dd>提示和建议,以帮助您提高WebGL内容的质量,性能和可靠性。</dd> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/Using_Extensions">使用扩展</a></dt> + <dd>WebGL 扩展的使用指南。</dd> +</dl> + +<h3 id="教程">教程</h3> + +<dl> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/Tutorial">WebGL 教程</a></dt> + <dd>WebGL 核心概念的初学者指南。如果您以前没有 WebGL 的经验,那么这是一个很好的起点。</dd> +</dl> + +<h3 id="示例">示例</h3> + +<dl> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/Basic_2D_animation_example">一个基础的 WebGL 的 2D 动画示例</a></dt> + <dd>此示例演示了单色形状的简单动画。检查的主题是适应宽高比差异,从多个着色器集合构建着色器程序的功能,以及 WebGL 绘图的基础知识。</dd> + <dt><a href="https://wiki.developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/By_example"><font><font>WebGL示例</font></font></a></dt> + <dd><font><font>一系列带有简短说明的实时示例展示了WebGL的概念和功能。</font><font>根据主题和难易程度对示例进行了排序,涵盖了WebGL渲染上下文,着色器编程,纹理,几何图形,用户交互等。</font></font></dd> +</dl> + +<h3 id="高级教程">高级教程</h3> + +<dl> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/WebGL_model_view_projection">WebGL 模型视图投影</a></dt> + <dd>详述了常用于显示3D物体视图的三种核心矩阵:模型,视图和投影矩阵。</dd> + <dt><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/Matrix_math_for_the_web">Web 中的矩阵运算</a></dt> + <dd>讲述 3D 变换矩阵工作原理的指南 —— 这也能在WebGL计算和CSS3变换中派上用场。</dd> +</dl> + +<h2 id="资源">资源</h2> + +<ul> + <li><a href="https://www.youtube.com/embed/H4c8t6myAWU/?feature=player_detailpage">Raw WebGL: WebGL入门</a> Nick Desaulniers 主讲的WebGL 基础知识。如果你从未接触过底层的图形编程,这是一个开始学习初级图形编程的好地方。</li> + <li><a href="http://www.khronos.org/webgl/" title="http://www.khronos.org/webgl/">WebGL官网</a> Khronos Group 的WebGL官方站点。</li> + <li><a href="http://learningwebgl.com/blog/?page_id=1217" title="http://learningwebgl.com/blog/">学习WebGL</a> 一个关于如何使用WebGL的教程站点。</li> + <li><a href="http://www.html5rocks.com/en/tutorials/webgl/webgl_fundamentals/" title="http://www.html5rocks.com/en/tutorials/webgl/webgl_fundamentals/">WebGL基础</a> 一个关于WebGL的基础教程。</li> + <li><a href="http://webglplayground.net" title="http://webglplayground.net">WebGL试炼</a> 一个在线创建和分享WebGL的工具站点,非常适合快速创建一个原型或者体验一个成品。</li> + <li><a href="http://www.webglacademy.com" title="http://www.webglacademy.com">WebGL Academy</a> 通过一个 HTML/JavaScript 编辑器来学习一个基础的WebGl基础知识。</li> + <li><a href="http://webglstats.com/">WebGL Stats</a> 一个统计WebGL在不同平台上能力表现的网站。</li> +</ul> + +<h3 id="库">库</h3> + +<ul> + <li><a class="link-https" href="https://github.com/toji/gl-matrix" title="https://github.com/toji/gl-matrix">glMatrix</a> 创建高性能WebGL应用的JavaScript矩阵矢量库。</li> + <li><a href="/zh-CN/docs/">PhiloGL</a> 一个用于数据可视化、创意编程和游戏开发的WebGL库。</li> + <li><a href="http://www.pixijs.com/" rel="noopener"><font><font>Pixi.js</font></font></a><font><font>是一种快速的开源2D WebGL渲染器。</font></font></li> + <li><a href="https://playcanvas.com/" rel="noopener"><font><font>PlayCanvas</font></font></a><font><font>是一个开源游戏引擎。</font></font></li> + <li><a href="http://sylvester.jcoglan.com/" rel="noopener" title="http://sylvester.jcoglan.com/"><font><font>Sylvester</font></font></a><font><font>是一个用于处理向量和矩阵的开源库。</font><font>尚未针对WebGL进行优化,但功能极其强大。</font></font></li> + <li><a href="https://threejs.org/" rel="noopener"><font><font>three.js</font></font></a><font><font>是一个开源的,功能齐全的3D WebGL库。</font></font></li> + <li><a href="https://phaser.io/" rel="noopener"><font><font>Phaser</font></font></a><font><font>是一个适用于Canvas和WebGL的浏览器游戏的快速,免费和有趣的开源框架。</font></font></li> + <li><a href="https://github.com/redcamel/RedGL2" rel="noopener"><font><font>RedGL</font></font></a><font><font> 是一个开源3D WebGL库。</font></font></li> + <li><a href="https://kitware.github.io/vtk-js/" rel="noopener"><font><font>vtk.js</font></font></a><font><font> 是一个JavaScript库,用于在浏览器中进行科学可视化。</font></font></li> +</ul> + +<h2 id="规范">规范</h2> + + +<table> + <thead> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('WebGL')}}</td> + <td>{{Spec2('WebGL')}}</td> + <td>初始定义。基于 OpenGL ES 2.0</td> + </tr> + <tr> + <td>{{SpecName('WebGL2')}}</td> + <td>{{Spec2('WebGL2')}}</td> + <td>在 WebGL 1 基础上构建。基于 OpenGL ES 3.0</td> + </tr> + <tr> + <td>{{SpecName('OpenGL ES 2.0')}}</td> + <td>{{Spec2('OpenGL ES 2.0')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('OpenGL ES 3.0')}}</td> + <td>{{Spec2('OpenGL ES 3.0')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<h3 id="WebGL_1">WebGL 1</h3> + +<div class="hidden"> +<p>此页面上的兼容性表是根据结构化数据生成的。 如果您想提供数据,请查看<a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a>并向我们发送拉取请求。</p> +</div> + +<p>{{Compat("api.WebGLRenderingContext", 0)}}</p> + +<h3 id="WebGL_2_2">WebGL 2</h3> + +<div class="hidden"> +<p>此页面上的兼容性表是根据结构化数据生成的。 如果您想提供数据,请查看<a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a>并向我们发送拉取请求。</p> +</div> + +<p>{{Compat("api.WebGL2RenderingContext", 0)}}</p> + +<h3 id="兼容性说明">兼容性说明</h3> + +<p>不仅是浏览器,GPU本身也需要支持该特性。比如 S3 纹理压缩 (S3TC) 只在基于图睿的GPU的设备上可用。大多数浏览器可以通过 <code>webgl</code> 这一上下文名称来使用 WebGL,但是旧的浏览器需要使用 <code>experimental-webgl</code>。另外,将来的 <a href="/zh-CN/docs/Web/API/WebGL2RenderingContext">WebGL 2</a> 只会向后兼容,其使用的上下文名称为 <code>webgl2</code> 。</p> + +<h3 id="Gecko备忘">Gecko备忘</h3> + +<h4 id="WebGL调试与检测">WebGL调试与检测</h4> + +<p>开始使用Gecko 10.0 {{geckoRelease("10.0")}}, 在测试中,这里有两个参数可以让你来控制WebGL性能:</p> + +<dl> + <dt><code>webgl.min_capability_mode</code></dt> + <dd>一个以布尔值存储的属性。当它的值为<code>True</code>时,将会启用最小性能模式。当这个模式启用时,WebGL将会仅提供由其标准指定的最基本的功能集和性能支持。这样可以确保您的WebGL代码能够在性能的设备和浏览器上正确运行。它的默认值是<code>False</code>。</dd> + <dt><code>webgl.disable_extensions</code></dt> + <dd>一个以布尔值存储的属性。当它的值为<code>True</code>时,会禁用所有的WebGL拓展。它的默认值是<code>False</code>。</dd> +</dl> + +<h2 id="参见">参见</h2> + +<ul> + <li><a href="/zh-CN/docs/Web/API/Canvas_API">Canvas(画布)</a></li> + <li><a href="/zh-CN/docs/Web/API/WebGLRenderingContext/getSupportedExtensions#Browser_compatibility">兼容性信息关于WebGL的扩展</a></li> +</ul> +</div> diff --git a/files/zh-cn/web/api/webgl_api/matrix_math_for_the_web/index.html b/files/zh-cn/web/api/webgl_api/matrix_math_for_the_web/index.html new file mode 100644 index 0000000000..26472a5c15 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/matrix_math_for_the_web/index.html @@ -0,0 +1,326 @@ +--- +title: Matrix math for the web +slug: Web/API/WebGL_API/Matrix_math_for_the_web +tags: + - WebGL + - matrix + - 三维 + - 矩阵数学 +translation_of: Web/API/WebGL_API/Matrix_math_for_the_web +--- +<p>{{WebGLSidebar}}</p> + +<p class="summary">矩阵可以用于表示空间中的对象的变换,并且是Web页面可视化的重要工具。本文探索如何创建并配合<a href="/zh-CN/docs/Web/Guide/CSS/Using_CSS_transforms">CSS3变换</a>和matrix3d变换类型使用矩阵。</p> + +<p>虽然本文为了便于解释而使用了CSS3, 矩阵却是许多技术中的核心概念, 包括WebGL和着色器。本文也是<a href="https://github.com/TatumCreative/mdn-matrix-math">MDN content kit</a>的一部分。示例使用了一组全局对象MDN下的<a href="https://github.com/TatumCreative/mdn-webgl">工具函数</a>。</p> + +<h2 id="什么是变换矩阵?">什么是变换矩阵?</h2> + +<p>虽然存在许多类型的矩阵,但我们感兴趣的是三维变换矩阵。这种矩阵由一个4x4方阵,共16个值组成。在JavaScript中,可以很方便的用数组表示矩阵。比如典型的单位矩阵。单位阵乘上一个点或者矩阵, 其结果保持不变。</p> + +<pre class="brush: js">var identityMatrix = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +]; +</pre> + +<p>说到乘法,这种运算用于矩阵是什么样的呢?最简单的例子是矩阵乘一个点。你可能注意到,三维空间中的点和一个4x4矩阵并不匹配,为此我们加上了额外的第四维W。一般来说,把W设为1就可以了。W维度还有一些额外的用途超出本文的讨论范围。查看<a href="/en-US/docs/Web/API/WebGL_API/WebGL_model_view_projection">WebGL model view projection</a>看它有哪些用途。</p> + +<p>注意矩阵和点的对齐方式:</p> + +<pre class="brush: js">[1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1] + +[4, 3, 2, 1] +</pre> + +<h3 id="定义相乘函数">定义相乘函数</h3> + +<p>我们在示例代码中定义了一个乘法函数 — <code>multiplyMatrixAndPoint()</code>:</p> + +<pre class="brush: js">function multiplyMatrixAndPoint(matrix, point) { + + // 给矩阵的每一部分一个简单的变量名, 列数(c)与行数(r) + var c0r0 = matrix[ 0], c1r0 = matrix[ 1], c2r0 = matrix[ 2], c3r0 = matrix[ 3]; + var c0r1 = matrix[ 4], c1r1 = matrix[ 5], c2r1 = matrix[ 6], c3r1 = matrix[ 7]; + var c0r2 = matrix[ 8], c1r2 = matrix[ 9], c2r2 = matrix[10], c3r2 = matrix[11]; + var c0r3 = matrix[12], c1r3 = matrix[13], c2r3 = matrix[14], c3r3 = matrix[15]; + + // 定义点坐标 + var x = point[0]; + var y = point[1]; + var z = point[2]; + var w = point[3]; + + // 点坐标和第一列对应相乘, 再求和 + var resultX = (x * c0r0) + (y * c0r1) + (z * c0r2) + (w * c0r3); + + // 点坐标和第二列对应相乘, 再求和 + var resultY = (x * c1r0) + (y * c1r1) + (z * c1r2) + (w * c1r3); + + // 点坐标和第三列对应相乘, 再求和 + var resultZ = (x * c2r0) + (y * c2r1) + (z * c2r2) + (w * c2r3); + + // 点坐标和第四列对应相乘, 再求和 + var resultW = (x * c3r0) + (y * c3r1) + (z * c3r2) + (w * c3r3); + + return [resultX, resultY, resultZ, resultW] +} +</pre> + +<p>现在我们可以使用上面的函数将一个点乘上一个矩阵。乘以单位阵将会返回原值:</p> + +<pre class="brush: js">// identityResult等于[4,3,2,1] +var identityResult = multiplyMatrixAndPoint(identityMatrix, [4,3,2,1]); +</pre> + +<p>返回同一个点并没有什么用处, 但还有一些其它的矩阵可以作用于点,返回有用的结果。接下来我们将演示其中一些矩阵。</p> + +<h3 id="两个矩阵相乘">两个矩阵相乘</h3> + +<p>除了把矩阵和点相乘,你也可以把两个矩阵相乘。之前的函数可以帮助我们简化这个过程:</p> + +<pre class="brush: js">function multiplyMatrices(matrixA, matrixB) { + + // 将第二个矩阵按列切片 + var column0 = [matrixB[0], matrixB[4], matrixB[8], matrixB[12]]; + var column1 = [matrixB[1], matrixB[5], matrixB[9], matrixB[13]]; + var column2 = [matrixB[2], matrixB[6], matrixB[10], matrixB[14]]; + var column3 = [matrixB[3], matrixB[7], matrixB[11], matrixB[15]]; + + // 将每列分别和矩阵相乘 + var result0 = multiplyMatrixAndPoint( matrixA, column0 ); + var result1 = multiplyMatrixAndPoint( matrixA, column1 ); + var result2 = multiplyMatrixAndPoint( matrixA, column2 ); + var result3 = multiplyMatrixAndPoint( matrixA, column3 ); + + // 把结果重新组合成矩阵 + return [ + result0[0], result1[0], result2[0], result3[0], + result0[1], result1[1], result2[1], result3[1], + result0[2], result1[2], result2[2], result3[2], + result0[3], result1[3], result2[3], result3[3] + ] +} +</pre> + +<h3 id="用法">用法</h3> + +<p>让我们看一看实际使用:</p> + +<pre class="brush: js">var someMatrix = [ + 4, 0, 0, 0, + 0, 3, 0, 0, + 0, 0, 5, 0, + 4, 8, 4, 1 +] + +var identityMatrix = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +]; + +// 返回someMatrix的数组表示 +var someMatrixResult = multiplyMatrices(identityMatrix, someMatrix); +</pre> + +<div class="warning"> +<p><strong>重要:</strong> 这些函数是为了解释的清晰而编写,而不是为了速度或者内存管理。这些函数新建了大量数组, 可能在实时运算时导致垃圾回收的巨大开销。在实际产品中最好使用优化过的函数。比如<a href="http://glmatrix.net/">glMatrix</a>就是一个注重速度和性能的库。</p> +</div> + +<h2 id="平移矩阵">平移矩阵</h2> + +<p>平移矩阵基于单位矩阵。它将一个对象沿x,y,z其中一个方向进行移动。最简单的想象平移的方式是设想拿起一个咖啡杯。咖啡杯必须保持直立和朝向以免咖啡洒出来。它可以离开桌子在空间中移动。</p> + +<p>现在我们还喝不到这个杯子里的咖啡,因为在平移矩阵的单独作用下杯子并不能倾斜。在之后的部分,我们会讨论新的矩阵,来解决这个问题。</p> + +<pre class="brush: js">var x = 50; +var y = 100; +var z = 0; + +var translationMatrix = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, y, z, 1 +]; +</pre> + +<h2 id="用矩阵操作DOM">用矩阵操作DOM</h2> + +<p>一个非常简单的开始使用矩阵的方法是使用CSS3里的<code>matrix3d<a href="/zh-CN/docs/Web/CSS/transform">变换</a>。首先,</code> 我们新建一个简单的{{htmlelement("div")}}并加上一些内容。这里样式没有展示出来,但我们将其设置成了页面居中且固定宽度与高度。我们同样为变换设定了动画以便清晰的观察发生的变化。</p> + +<pre class="brush: html"><div id='move-me' class='transformable'> + <h2>Move me with a matrix</h2> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit...</p> +</div> +</pre> + +<p>最后,我们会为每一个例子生成一个4x4矩阵,然后更新<div>的样式,对其应用一个matrix3d变换。要记住即使矩阵有四行四列,也要将其写成单行16个值。</p> + +<pre class="brush: js">// 从矩阵数组创建matrix3d样式属性 +function matrixArrayToCssMatrix(array) { + return "matrix3d(" + array.join(',') + ")"; +} + +// 获取DOM元素 +var moveMe = document.getElementById('move-me'); + +// 返回结果如:"matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 50, 100, 0, 1);" +var matrix3dRule = matrixArrayToCssMatrix( translationMatrix ); + +// 设置变换 +moveMe.style.transform = matrix3dRule; +</pre> + +<p><a href="https://jsfiddle.net/g24mgw6y">在JSFiddle中查看</a></p> + +<p><img alt="An example of matrix translation" src="https://mdn.mozillademos.org/files/11409/matrix-translation.jpg" style="height: 385px; width: 339px;"></p> + +<h2 id="缩放矩阵">缩放矩阵</h2> + +<p>缩放矩阵使对象的高度、宽度和深度三个维度的其中之一变大或变小。在典型(笛卡尔)坐标系中, 这将使得x,y,z坐标拉伸或收缩。</p> + +<pre class="brush: js">var w = 1.5; // width (x) +var h = 0.7; // height (y) +var d = 1; // depth (z) + +var scaleMatrix = [ + w, 0, 0, 0, + 0, h, 0, 0, + 0, 0, d, 0, + 0, 0, 0, 1 +]; +</pre> + +<p><a href="https://jsfiddle.net/fndd6e1b">在JSFiddle中查看</a></p> + +<p><img alt="An example of matrix scaling" src="https://mdn.mozillademos.org/files/11407/matrix-scale.jpg" style="height: 291px; width: 398px;"></p> + +<h2 id="旋转矩阵">旋转矩阵</h2> + +<p>旋转矩阵比平移和缩放矩阵要稍复杂一些。其中用到了三角函数来完成旋转。尽管这部分不会把步骤讲得过于详细,但是下例有简单的说明。</p> + +<pre class="brush: js">// 不借助矩阵将点绕原点旋转 +var point = [10,2]; + +// 计算到原点的距离 +var distance = Math.sqrt(point[0] * point[0] + point[1] * point[1]); + +// 60度 +var rotationInRadians = Math.PI / 3; + +var transformedPoint = [ + Math.cos( rotationInRadians ) * distance, + Math.sin( rotationInRadians ) * distance +]; +</pre> + +<p>我们可以将上述步骤表示为一个矩阵,并且单独应用到x, y,和z坐标。下面是绕Z轴旋转的表示:</p> + +<pre class="brush: js">var sin = Math.sin; +var cos = Math.cos; + +<code>// NOTE: There is no perspective in these transformations, so a rotation +// at this point will only appear to only shrink the div</code> + +var a = Math.PI * 0.3; // 转角 + +// 绕Z轴旋转 +var rotateZMatrix = [ + cos(a), -sin(a), 0, 0, + sin(a), cos(a), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +]; +</pre> + +<p><a href="https://jsfiddle.net/9vr2dorz">在JSFiddle中查看</a></p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/11405/matrix-rotation.jpg" style="height: 363px; width: 417px;"></p> + +<p>这里是一组返回旋转矩阵的函数。要注意的是由于没有加入透视,所以旋转看起来没有那么3D。这就好像摄像机在极近距离拍摄一个物体——透视的感觉消失了。</p> + +<pre class="brush: js">function rotateAroundXAxis(a) { + + return [ + 1, 0, 0, 0, + 0, cos(a), -sin(a), 0, + 0, sin(a), cos(a), 0, + 0, 0, 0, 1 + ]; +} + +function rotateAroundYAxis(a) { + + return [ + cos(a), 0, sin(a), 0, + 0, 1, 0, 0, + -sin(a), 0, cos(a), 0, + 0, 0, 0, 1 + ]; +} + +function rotateAroundZAxis(a) { + + return [ + cos(a), -sin(a), 0, 0, + sin(a), cos(a), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ]; +} +</pre> + +<p><a href="https://jsfiddle.net/tk072doc">在JSFiddle中查看</a></p> + +<h2 id="矩阵组合">矩阵组合</h2> + +<p>矩阵的真正厉害之处在于矩阵的组合。当一组特定类型的矩阵连乘起来,它们保留了变换的经过并且是可逆的。这意味着如果平移、旋转和缩放矩阵组合在一起,当我们使用逆变换并颠倒应用的顺序,可以得到原来的点。</p> + +<p>矩阵相乘的结果与顺序有关。两个数相乘时,a * b = c, 和 b * a = c 都是正确的。例如,3 * 4 = 12, 和 4 * 3 = 12。在数学上这些数被称为<strong>可交换</strong>。矩阵不能保证交换顺序后的运算结果,所以矩阵是<strong>不可交换</strong>的。</p> + +<p>另一个需要记住的点是在WebGL和CSS3中的矩阵相乘需要和变换发生的顺序相反。例如,缩放对象到80%,向下移动200像素,然后绕原点旋转90度在伪代码中应该像下面这样。</p> + +<pre> transformation = rotate * translate * scale +</pre> + +<h3 id="组合多种变换">组合多种变换</h3> + +<p>我们将使用的函数是<a href="https://github.com/TatumCreative/mdn-webgl">工具函数</a>的一部分。其接受矩阵的数组并把它们乘起来。在WebGL着色器代码里,这内建在语言里,并且我们可以使用 * 运算符。除此之外,本例使用了一个缩放函数,一个平移函数,它们返回之前定义的矩阵。</p> + +<pre class="brush: js">var transformMatrix = MDN.multiplyArrayOfMatrices([ + rotateAroundZAxis(Math.PI * 0.5), // 第3步:旋转90度 + translate(0, 200, 0), // 第2步:下移100像素 + scale(0.8, 0.8, 0.8), // 第1步:缩小 +]); + +</pre> + +<p><a href="https://jsfiddle.net/qxxg3yvc">在JSFiddle中查看</a></p> + +<p><img alt="An example of matrix composition" src="https://mdn.mozillademos.org/files/11403/matrix-composition.jpg" style="height: 292px; width: 488px;"></p> + +<p>最后是展示矩阵用途的有趣的一步,看看怎样颠倒这些步骤并得到最开始的单位矩阵。</p> + +<pre class="brush: js">var transformMatrix = MDN.multiplyArrayOfMatrices([ + scale(1.25, 1.25, 1.25), // 第6步:放大 + translate(0, -200, 0), // 第5步:上移 + rotateAroundZAxis(-Math.PI * 0.5), // 第4步:倒转 + rotateAroundZAxis(Math.PI * 0.5), // 第3步:旋转90度 + translate(0, 200, 0), // 第2步:下移100像素 + scale(0.8, 0.8, 0.8), // 第1步:缩小 +]); +</pre> + +<h2 id="为什么矩阵这么重要?">为什么矩阵这么重要?</h2> + +<p>矩阵之所以重要,是因为它可以用少量的数字描述大量的空间中的变换,并且能轻易地在程序间共享。矩阵可以不同的坐标空间,甚至一些矩阵乘法可以将一组数据从一个坐标空间映射到另一个坐标空间。矩阵能够高效率地保存生成它们的每一步变换。</p> + +<p>对于在WebGL中使用,显卡尤其擅长大量的点乘矩阵运算。各种各样的运算,如点定位、光线运算、动态角色,都依赖这个基础工具。</p> diff --git a/files/zh-cn/web/api/webgl_api/tutorial/adding_2d_content_to_a_webgl_context/index.html b/files/zh-cn/web/api/webgl_api/tutorial/adding_2d_content_to_a_webgl_context/index.html new file mode 100644 index 0000000000..460d6debee --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/tutorial/adding_2d_content_to_a_webgl_context/index.html @@ -0,0 +1,284 @@ +--- +title: 使用 WebGL 创建 2D 内容 +slug: Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context +tags: + - Tutorial + - WebGL + - 着色器 +translation_of: Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL", "Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL")}}</p> + +<p>一旦创建WebGL上下文创建成功,你就可以在这个上下文里渲染画图了。而对我们而言最简单的事,莫过于绘制一个没有纹理的2D图形了。那就让我们从画出一个正方形开始吧。</p> + +<h2 id="渲染场景">渲染场景</h2> + +<p>在开始前,我们首先需要明确最重要的一点,虽然我们的例子只是画一个二维物体,但我们仍然是在把它画在一个三维空间里。所以,我们依然需要创建着色器,通过它来渲染我们的简单场景并画出我们的物体。往下,我们将展示正方形是怎样一步步被画出来的。</p> + +<h3 id="着色器">着色器</h3> + +<p><strong>着色器是</strong>使用 <a href="http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf" title="http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf">OpenGL ES 着色语言</a>(<strong>GLSL</strong>)编写的程序,它携带着绘制形状的顶点信息以及构造绘制在屏幕上像素的所需数据,换句话说,它负责记录着像素点的位置和颜色。</p> + +<p>绘制WebGL时候有两种不同的着色器函数,<strong>顶点着色器和片段着色器。</strong>你需要通过用GLSL 编写这些着色器,并将代码文本传递给WebGL , 使之在GPU执行时编译。顺便一提,顶点着色器和片段着色器的集合我们通常称之为<strong>着色器程序。</strong></p> + +<p>下面我们通过在WebGL 环境绘制一个2D图像的例子快速介绍这两种着色器。</p> + +<h4 id="顶点着色器">顶点着色器</h4> + +<p>每次渲染一个形状时,顶点着色器会在形状中的每个顶点运行。 它的工作是将输入顶点从原始坐标系转换到WebGL使用的缩放空间(<strong>clipspace</strong>)坐标系,其中每个轴的坐标范围从-1.0到1.0,并且不考虑纵横比,实际尺寸或任何其他因素。</p> + +<p>顶点着色器需要对顶点坐标进行必要的转换,在每个顶点基础上进行其他调整或计算,然后通过将其保存在由GLSL提供的特殊变量(我们称为gl_Position)中来返回变换后的顶点</p> + +<p>顶点着色器根据需要, 也可以完成其他工作。例如,决定哪个包含 {{interwiki("wikipedia", "texel_(graphics)", "texel")}}面部纹理的坐标,可以应用于顶点;通过法线来确定应用到顶点的光照因子等。然后将这些信息存储在<a href="/zh-CN/docs/XUL_%E7%A8%8B%E5%BA%8F%E6%89%93%E5%8C%85">变量(varyings)</a>或<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Data#Attributes">属性(attributes)</a>属性中,以便与片段着色器共享</p> + +<p>以下的顶点着色器接收一个我们定义的属性(aVertexPosition)的顶点位置值。之后这个值与两个4x4的矩阵(uProjectionMatrix和uModelMatrix)相乘; 乘积赋值给gl_Position。有关投影和其他矩阵的更多信息,<a href="https://webglfundamentals.org/webgl/lessons/webgl-3d-perspective.html">在这里您可能可以找到有帮助的文章</a>.。</p> + +<pre class="brush: js notranslate">// Vertex shader program + + const vsSource = ` + attribute vec4 aVertexPosition; + + uniform mat4 uModelViewMatrix; + uniform mat4 uProjectionMatrix; + + void main() { + gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition; + } + `;</pre> + +<p>这个例子中,我们没有计算任何光照效果,因为我们还没有应用到场景,它将后面的 <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Lighting_in_WebGL">WebGL光照</a>章节介绍。同样我们也还没应用任何纹理,这将在<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL">WebGL添加纹理</a>章节补充。</p> + +<h4 id="片段着色器">片段着色器</h4> + +<p><strong>片段着色器</strong>在顶点着色器处理完图形的顶点后,会被要绘制的每个图形的每个像素点调用一次。它的职责是确定像素的颜色,通过指定应用到像素的纹理元素(也就是图形纹理中的像素),获取纹理元素的颜色,然后将适当的光照应用于颜色。之后颜色存储在特殊变量gl_FragColor中,返回到WebGL层。该颜色将最终绘制到屏幕上图形对应像素的对应位置。</p> + +<pre class="brush: js notranslate">const fsSource = ` + void main() { + gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); + } + `;</pre> + +<h3 id="初始化着色器">初始化着色器</h3> + +<p>现在我们已经定义了两个着色器,我们需要将它们传递给WebGL,编译并将它们连接在一起。下面的代码通过调用loadShader(),为着色器传递类型和来源,创建了两个着色器。然后创建一个附加着色器的程序,将它们连接在一起。如果编译或链接失败,代码将弹出alert。</p> + +<pre class="brush: js notranslate">// +// 初始化着色器程序,让WebGL知道如何绘制我们的数据 +function initShaderProgram(gl, vsSource, fsSource) { + const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource); + const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource); + + // 创建着色器程序 + + const shaderProgram = gl.createProgram(); + gl.attachShader(shaderProgram, vertexShader); + gl.attachShader(shaderProgram, fragmentShader); + gl.linkProgram(shaderProgram); + + // 创建失败, alert + if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { + alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram)); + return null; + } + + return shaderProgram; +} + +// +// 创建指定类型的着色器,上传source源码并编译 +// +function loadShader(gl, type, source) { + const shader = gl.createShader(type); + + // Send the source to the shader object + + gl.shaderSource(shader, source); + + // Compile the shader program + + gl.compileShader(shader); + + // See if it compiled successfully + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); + gl.deleteShader(shader); + return null; + } + + return shader; +} +</pre> + +<p>loadShader函数将WebGL上下文,着色器类型和<code>源码</code>作为参数输入,然后按如下步骤创建和编译着色器:</p> + +<p>1. 调用{{domxref("WebGLRenderingContext.createShader", "gl.createShader()")}}.创建一个新的着色器。</p> + +<p>2. 调用{{domxref("WebGLRenderingContext.shaderSource", "gl.shaderSource()")}}.将源代码发送到着色器。</p> + +<p>3. 一旦着色器获取到源代码,就使用{{domxref("WebGLRenderingContext.compileShader", "gl.compileShader()")}}.进行编译。</p> + +<p>4. 为了检查是否成功编译了着色器,将检查着色器参数gl.COMPILE_STATUS状态。通过调用{{domxref("WebGLRenderingContext.getShaderParameter", "gl.getShaderParameter()")}}获得它的值,并指定着色器和我们想要检查的参数的名字(gl.COMPILE_STATUS)。如果返回错误,则着色器无法编译,因此通过{{domxref("WebGLRenderingContext.getShaderInfoLog", "gl.getShaderInfoLog()")}}从编译器中获取日志信息并alert,然后删除着色器返回null,表明加载着色器失败。</p> + +<p>5. 如果着色器被加载并成功编译,则返回编译的着色器。</p> + +<p>我们可以像这样调用这段代码</p> + +<pre class="brush: js notranslate"> const shaderProgram = initShaderProgram(gl, vsSource, fsSource);</pre> + +<p>在创建着色器程序之后,我们需要查找WebGL返回分配的输入位置。在上述情况下,我们有一个属性和两个uniforms。属性从缓冲区接收值。顶点着色器的每次迭代都从分配给该属性的缓冲区接收下一个值。uniforms类似于JavaScript全局变量。它们在着色器的所有迭代中保持相同的值。由于属性和统一的位置是特定于单个着色器程序的,因此我们将它们存储在一起以使它们易于传递</p> + +<pre class="brush: js notranslate">const programInfo = { + program: shaderProgram, + attribLocations: { + vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'), + }, + uniformLocations: { + projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'), + modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'), + }, + };</pre> + +<h2 id="创建对象">创建对象</h2> + +<p>在画正方形前,我们需要创建一个缓冲器来存储它的顶点。我们会用到名字为 initBuffers() 的函数。当我们了解到更多WebGL 的高级概念时,这段代码会将有更多参数,变得更加复杂,并且用来创建更多的三维物体。</p> + +<pre class="brush: js notranslate">function initBuffers(gl) { + const positionBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); + + var 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); + + return { + position: positionBuffer, + }; +} +</pre> + +<p>这段代码简单给出了绘画场景的本质。首先,它调用 gl 的成员函数 {{domxref("WebGLRenderingContext.createBuffer()", "createBuffer()")}} 得到了缓冲对象并存储在顶点缓冲器。然后调用 {{domxref("WebGLRenderingContext.bindBuffer()", "bindBuffer()")}} 函数绑定上下文。</p> + +<p><span style="line-height: 1.5;">当上一步完成,我们创建一个Javascript 数组去记录每一个正方体的每一个顶点。然后将其转化为 WebGL 浮点型类型的数组,并将其传到 gl 对象的 </span> {{domxref("WebGLRenderingContext.bufferData()", "bufferData()")}}<span style="line-height: 1.5;"> 方法来建立对象的顶点。</span></p> + +<p><strong style="">绘制场景</strong></p> + +<p>当着色器和物体都创建好后,我们可以开始渲染这个场景了。因为我们这个例子不会产生动画,所以 drawScene() 方法非常简单。它还使用了几个工具函数,稍后我们会介绍。</p> + +<div class="blockIndicator note"> +<p><strong>注意</strong>: 你可能会得到这样一段错误报告:“ mat4 is not defined”,意思是说你缺少<code>glmatrix</code>库。该库的js文件<a href="https://mdn.github.io/webgl-examples/tutorial/gl-matrix.js">gl-matrix.js</a>可以从<a href="https://github.com/mdn/webgl-examples/issues/20">这里</a>获得.</p> +</div> + +<pre class="brush: js notranslate">function drawScene(gl, programInfo, buffers) { + gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear to black, fully opaque + gl.clearDepth(1.0); // Clear everything + gl.enable(gl.DEPTH_TEST); // Enable depth testing + gl.depthFunc(gl.LEQUAL); // Near things obscure far things + + // Clear the canvas before we start drawing on it. + + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + // Create a perspective matrix, a special matrix that is + // used to simulate the distortion of perspective in a camera. + // Our field of view is 45 degrees, with a width/height + // ratio that matches the display size of the canvas + // and we only want to see objects between 0.1 units + // and 100 units away from the camera. + + const fieldOfView = 45 * Math.PI / 180; // in radians + const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight; + const zNear = 0.1; + const zFar = 100.0; + const projectionMatrix = mat4.create(); + + // note: glmatrix.js always has the first argument + // as the destination to receive the result. + mat4.perspective(projectionMatrix, + fieldOfView, + aspect, + zNear, + zFar); + + // Set the drawing position to the "identity" point, which is + // the center of the scene. + const modelViewMatrix = mat4.create(); + + // Now move the drawing position a bit to where we want to + // start drawing the square. + + mat4.translate(modelViewMatrix, // destination matrix + modelViewMatrix, // matrix to translate + [-0.0, 0.0, -6.0]); // amount to translate + + // Tell WebGL how to pull out the positions from the position + // buffer into the vertexPosition attribute. + { + const numComponents = 3; // pull out 3 values per iteration + const type = gl.FLOAT; // the data in the buffer is 32bit floats + const normalize = false; // don't normalize + const stride = 0; // how many bytes to get from one set of values to the next + // 0 = use type and numComponents above + const offset = 0; // how many bytes inside the buffer to start from + gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position); + gl.vertexAttribPointer( + programInfo.attribLocations.vertexPosition, + numComponents, + type, + normalize, + stride, + offset); + gl.enableVertexAttribArray( + programInfo.attribLocations.vertexPosition); + } + + // Tell WebGL to use our program when drawing + + gl.useProgram(programInfo.program); + + // Set the shader uniforms + + gl.uniformMatrix4fv( + programInfo.uniformLocations.projectionMatrix, + false, + projectionMatrix); + gl.uniformMatrix4fv( + programInfo.uniformLocations.modelViewMatrix, + false, + modelViewMatrix); + + { + const offset = 0; + const vertexCount = 4; + gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount); + } +} +</pre> + +<p>第一步,用背景色擦除画布,接着建立摄像机透视矩阵。设置45度的视图角度,并且设置一个适合实际图像的宽高比。 指定在摄像机距离0.1到100单位长度的范围内的物体可见。</p> + +<p>接着加载特定位置,并把正方形放在距离摄像机6个单位的的位置。然后,我们绑定正方形的顶点缓冲到上下文,并配置好,再通过调用 {{domxref("WebGLRenderingContext.drawArrays()", "drawArrays()")}} 方法来画出对象。 </p> + +<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample2/index.html', 670, 510) }}</p> + +<p>如果你的浏览器支持WebGL的话,<a href="/samples/webgl/sample2">可以点击这里看看DEMO</a>。完整的源代码从<a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample2">这里</a>获得</p> + +<h2 id="矩阵通用计算">矩阵通用计算</h2> + +<p>矩阵计算是一个很复杂的运算。 没人会想去自己写完所有代码来处理这些运算。通常人们使用一个矩阵运算库,而不会自己实现矩阵运算。在这个例子中我们使用的是<a href="http://glmatrix.net/">glMatrix library</a>.</p> + +<h2 id="相关资料">相关资料</h2> + +<ul> + <li><a class="external" href="http://mathworld.wolfram.com/Matrix.html" title="http://mathworld.wolfram.com/Matrix.html">Matrices</a> 线上数学百科全书</li> + <li><a class="external" href="http://en.wikipedia.org/wiki/Matrix_(mathematics)" title="http://en.wikipedia.org/wiki/Matrix_(mathematics)">Matrix</a> 维基百科</li> +</ul> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL", "Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/tutorial/animating_objects_with_webgl/index.html b/files/zh-cn/web/api/webgl_api/tutorial/animating_objects_with_webgl/index.html new file mode 100644 index 0000000000..6cfeee1284 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/tutorial/animating_objects_with_webgl/index.html @@ -0,0 +1,55 @@ +--- +title: 用WebGL让目标动起来 +slug: Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL +tags: + - WebGL + - 教程 +translation_of: Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL", "Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL") }}</p> + +<p>在此示例中,我们实际上将旋转正方形平面。</p> + +<h2 id="使正方形旋转"><font><font>使正方形旋转</font></font></h2> + +<p><font>让我们开始旋转正方形。</font><font>我们需要的第一件事是创建一个变量,用于跟踪正方形的当前旋转:</font></p> + +<pre class="brush: js">var squareRotation = 0.0; +</pre> + +<p><font><font>现在我们需要更新</font></font><code>drawScene()</code><font><font>函数以在绘制正方形时将当前旋转应用于正方形。</font><font>转换为正方形的初始绘图位置后,我们像这样应用旋转:</font></font></p> + +<pre class="brush: js"> mat4.rotate(modelViewMatrix, // destination matrix + modelViewMatrix, // matrix to rotate + squareRotation, // amount to rotate in radians + [0, 0, 1]); // axis to rotate around</pre> + +<p><font><font>这会将modelViewMatrix的当前值</font></font><code>squareRotation</code><font><font>绕Z轴旋转。</font></font></p> + +<p><font><font>要进行动画制作,我们需要添加</font></font><code>squareRotation</code><font><font>随时间</font><font>更改值的代码</font><font>。</font><font>为此,我们可以创建一个新变量来跟踪上次动画播放的时间(我们称之为</font></font><code>then</code><font><font>),然后将以下代码添加到主函数的末尾</font></font></p> + +<pre class="brush: js"> var then = 0; + + // Draw the scene repeatedly + function render(now) { + now *= 0.001; // convert to seconds + const deltaTime = now - then; + then = now; + + drawScene(gl, programInfo, buffers, deltaTime); + + requestAnimationFrame(render); + } + requestAnimationFrame(render);</pre> + +<p><font><font>该代码用于 </font></font><code>requestAnimationFrame</code><font><font> 要求浏览器</font></font><font><font>在每一帧上</font><font>调用函数“</font></font><code>render</code><font><font>”。</font></font><code>requestAnimationFrame</code><font><font> 自页面加载以来经过的时间(以毫秒为单位)。</font><font>我们将其转换为秒,然后从中减去,以计算</font></font><code>deltaTime</code><font><font> 自渲染最后一帧以来的</font><font>秒数 </font><font>。</font><font>在drawscene的结尾,我们添加了要更新的代码 </font></font><code>squareRotation.</code></p> + +<pre class="brush: js"><code> squareRotation += deltaTime;</code></pre> + +<p><font><font>该代码使用自上次我们更新值以来所经过的时间</font></font><code>squareRotation</code><font><font>来确定旋转正方形的距离。</font></font></p> + +<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample4/index.html', 670, 510) }}</p> + +<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample4">查看完整代码</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample4/">在新页面中打开示例</a></p> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL", "Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL") }}</p> diff --git a/files/zh-cn/web/api/webgl_api/tutorial/animating_textures_in_webgl/index.html b/files/zh-cn/web/api/webgl_api/tutorial/animating_textures_in_webgl/index.html new file mode 100644 index 0000000000..763e9ae60d --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/tutorial/animating_textures_in_webgl/index.html @@ -0,0 +1,144 @@ +--- +title: 动画纹理 +slug: Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL +tags: + - WebGL +translation_of: Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL +--- +<p>{{WebGLSidebar("Tutorial") }} {{Previous("Web/API/WebGL_API/Tutorial/Lighting_in_WebGL")}}</p> + +<p><font><font>在本演示中,我们以上一个示例为基础,将静态纹理替换为正在播放的mp4视频文件的帧。</font><font>实际上,这很容易做到,而且观看起来很有趣,所以让我们开始吧。</font><font>您可以使用类似的代码来使用任何类型的数据(例如</font></font>{{ HTMLElement("canvas") }}) <font><font>作为纹理的源。</font></font></p> + +<h2 id="获取视频">获取视频</h2> + +<p><font><font>第一步是创建</font></font>{{ HTMLElement("video") }}<font><font>将用于检索视频帧</font><font>的</font><font>元素:</font></font></p> + +<pre class="brush: js">// will set to true when video can be copied to texture +var copyVideo = false; + +function setupVideo(url) { + const video = document.createElement('video'); + + var playing = false; + var timeupdate = false; + + video.autoplay = true; + video.muted = true; + video.loop = true; + + // Waiting for these 2 events ensures + // there is data in the video + + video.addEventListener('playing', function() { + playing = true; + checkReady(); + }, true); + + video.addEventListener('timeupdate', function() { + timeupdate = true; + checkReady(); + }, true); + + video.src = url; + video.play(); + + function checkReady() { + if (playing && timeupdate) { + copyVideo = true; + } + } + + return video; +} +</pre> + +<p><font><font>首先,我们创建一个视频元素。</font><font>我们将其设置为自动播放,静音和循环播放视频。</font><font>然后,我们设置了两个事件以确保视频正在播放并且时间轴已更新。</font><font>我们需要进行这两项检查,因为如果将视频上传到WebGL尚无可用数据,它将产生错误。</font><font>检查这两个事件可确保有可用数据,并且可以安全地开始将视频上传到WebGL纹理。</font><font>在上面的代码中,我们确认是否同时发生了这两个事件。</font><font>如果是这样,我们将全局变量设置 </font></font><code>copyVideo</code><font><font>为true,以表示可以安全地开始将视频复制到纹理。</font></font></p> + +<p><font><font>最后,我们将</font></font><code>src</code><font><font>属性</font><font>设置</font><font>为start并调用</font></font><code>play</code><font><font> 以开始加载和播放视频。</font></font></p> + +<h2 id="用视频帧作为纹理">用视频帧作为纹理 </h2> + +<p><font><font>接下来的更改是</font></font><code>initTexture()</code><font><font>,它变得更加简单,因为它不再需要加载图像文件。</font><font>相反,它所做的只是创建一个空的纹理对象,在其中放置一个像素,然后设置其过滤条件供以后使用:</font></font></p> + +<pre class="brush: js">function initTexture(gl) { + const texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + + // Because video has to be download over the internet + // they might take a moment until it's ready so + // put a single pixel in the texture so we can + // use it immediately. + const level = 0; + const internalFormat = gl.RGBA; + const width = 1; + const height = 1; + const border = 0; + const srcFormat = gl.RGBA; + const srcType = gl.UNSIGNED_BYTE; + const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue + gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, + width, height, border, srcFormat, srcType, + pixel); + + // Turn off mips and set wrapping to clamp to edge so it + // will work regardless of the dimensions of the video. + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + + return texture; +}</pre> + +<div><font><font>这里是</font></font><code>updateTexture()</code><font><font> 方法; </font><font>这是完成实际工作的地方:</font></font></div> + +<pre class="brush: js">function updateTexture(gl, texture, video) { + const level = 0; + const internalFormat = gl.RGBA; + const srcFormat = gl.RGBA; + const srcType = gl.UNSIGNED_BYTE; + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, + srcFormat, srcType, video); +}</pre> + +<p><font><font>您之前已经看过此代码。</font><font>它与上一个示例中的image onload函数几乎相同-除非我们调用</font></font><code>texImage2D()</code><font><font>,而不是传递</font></font><code>Image</code><font><font>对象,而是传递</font></font>{{ HTMLElement("video") }}<font><font>元素。</font><font>WebGL知道如何拉出当前帧并将其用作纹理。</font></font></p> + +<p><font><font>然后,在</font></font><code>main()</code><font><font> 代替通话,以</font></font><code>loadTexture()</code><font><font>在前面的例子中,我们调用 </font></font><code>initTexture</code><code>()</code><font><font>之后</font></font><code>setupVideo()</code><font><font>。</font></font></p> + +<p><font><font>在</font></font><code>render()</code><font><font>if是否</font></font><code>copyVideo</code><font><font>为真的</font><font>定义中</font><font>,则 </font></font><code>updateTexture()</code><font><font>每次调用</font></font><code>drawScene()</code><font><font> 函数</font><font>之前都会调用一次 </font><font>。</font></font></p> + +<pre class="brush: js"> const texture = initTexture(gl); + + const video = setupVideo('Firefox.mp4'); + + var then = 0; + + // Draw the scene repeatedly + function render(now) { + now *= 0.001; // convert to seconds + const deltaTime = now - then; + then = now; + + if (copyVideo) { + updateTexture(gl, texture, video); + } + + drawScene(gl, programInfo, buffers, texture, deltaTime); + + requestAnimationFrame(render); + } + requestAnimationFrame(render);</pre> + +<p>下面是结果:</p> + +<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample8/index.html', 670, 510) }}</p> + +<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample8">查看完整的代码</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample8/">在新页中打开这个demo</a></p> + +<h2 id="参考">参考</h2> + +<ul> + <li><a href="/en/Using_HTML5_audio_and_video" title="En/Using audio and video in Firefox">Using audio and video in Firefox</a></li> +</ul> + +<p>{{Previous("Web/API/WebGL_API/Tutorial/Lighting_in_WebGL")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/tutorial/creating_3d_objects_using_webgl/index.html b/files/zh-cn/web/api/webgl_api/tutorial/creating_3d_objects_using_webgl/index.html new file mode 100644 index 0000000000..88e1bf75e7 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/tutorial/creating_3d_objects_using_webgl/index.html @@ -0,0 +1,128 @@ +--- +title: Creating 3D objects using WebGL +slug: Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL +translation_of: Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL", "Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL")}}</p> + +<p>现在让我们给之前的正方形添加五个面从而可以创建一个三维的立方体。最简单的方式就是通过调用方法 {{domxref("WebGLRenderingContext.drawElements()", "gl.drawElements()")}} 使用顶点数组列表来替换之前的通过方法{{domxref("WebGLRenderingContext.drawArrays()", "gl.drawArrays()")}} 直接使用顶点数组。而顶点数组列表里保存着将会被引用到一个个独立的顶点。</p> + +<p>其实现在会存在这样一个问题:每个面需要4个顶点,而每个顶点会被3个面共享。我们会创建一个包含24个顶点的数组列表,通过使用数组下标来索引顶点,然后把这些用于索引的下标传递给渲染程序而不是直接把整个顶点数据传递过去,这样来减少数据传递。那么也许你就会问:那么使用8个顶点就好了,为什么要使用24个顶点呢?这是因为每个顶点虽然被3个面共享但是它在每个面上需要使用不同的颜色信息。24个顶点中的每一个都会有独立的颜色信息,这就会造成每个顶点位置都会有3份副本。</p> + +<h2 id="定义立方体顶点位置">定义立方体顶点位置</h2> + +<p>首先,更新 <code>initBuffers() 函数代码</code>创建顶点位置数据缓存。现在的代码看起来和渲染正方形时的代码很相似,只是比之前的代码更长因为现在有了24个顶点(每个面使用4个顶点):</p> + +<pre class="brush: js">var 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 +]; +</pre> + +<h2 id="定义顶点颜色">定义顶点颜色</h2> + +<p>然后我们还要为每个顶点定义颜色。下面的代码首先为每个面定义颜色,然后用一个循环语句为每个顶点定义颜色信息。</p> + +<pre class="brush: js">var colors = [ + [1.0, 1.0, 1.0, 1.0], // Front face: white + [1.0, 0.0, 0.0, 1.0], // Back face: red + [0.0, 1.0, 0.0, 1.0], // Top face: green + [0.0, 0.0, 1.0, 1.0], // Bottom face: blue + [1.0, 1.0, 0.0, 1.0], // Right face: yellow + [1.0, 0.0, 1.0, 1.0] // Left face: purple +]; + +var generatedColors = []; + +for (j=0; j<6; j++) { + var c = colors[j]; + + for (var i=0; i<4; i++) { + generatedColors = generatedColors.concat(c); + } +} + +var cubeVerticesColorBuffer = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesColorBuffer); +gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(generatedColors), gl.STATIC_DRAW); +</pre> + +<h2 id="定义元素(三角形)数组">定义元素(三角形)数组</h2> + +<p>既然已经创建好了顶点数组,接下来就要创建元素(三角形)数组了。</p> + +<pre class="brush: js">var cubeVerticesIndexBuffer = gl.createBuffer(); +gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer); + +// This array defines each face as two triangles, using the +// indices into the vertex array to specify each triangle's +// position. + +var cubeVertexIndices = [ + 0, 1, 2, 0, 2, 3, // front + 4, 5, 6, 4, 6, 7, // back + 8, 9, 10, 8, 10, 11, // top + 12, 13, 14, 12, 14, 15, // bottom + 16, 17, 18, 16, 18, 19, // right + 20, 21, 22, 20, 22, 23 // left +]; + +// Now send the element array to GL + +gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, + new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW); +</pre> + +<p><code><font face="Open Sans, Arial, sans-serif">代码中的 </font>cubeVertexIndices</code> 数组声明每一个面都使用两个三角形来渲染。通过立方体顶点数组的索引指定每个三角形的顶点。那么这个立方体就是由12个三角形组成的了。</p> + +<h2 id="渲染立方体">渲染立方体</h2> + +<p>接下来就需要在 <code>drawScene()</code> 函数里添加代码使用立方体顶点索引数据来渲染这个立方体了。代码里添加了对 {{domxref("WebGLRenderingContext.bindBuffer()", "gl.bindBuffer()")}} 和 {{domxref("WebGLRenderingContext.drawElements()", "gl.drawElements()")}}的调用:</p> + +<pre class="brush: js">gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer); +setMatrixUniforms(); +gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0); +</pre> + +<p>立方体的每个面都由2个三角形组成,那就是每个面需要6个顶点,或者说总共36个顶点,尽管有许多重复的。然而,因为索引数组的每个元素都是简单的整数类型,所以每一帧动画需要传递给渲染程序的数据也不是很多。</p> + +<p>到现在为止,我们已经创建了一个颜色生动的并且会在场景中移动和旋转的立方体,这一定很酷吧。</p> + +<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample5/index.html', 670, 510) }}</p> + +<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample5">查看全部源代码</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample5/">在新页面打开示例</a></p> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL", "Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/tutorial/getting_started_with_webgl/index.html b/files/zh-cn/web/api/webgl_api/tutorial/getting_started_with_webgl/index.html new file mode 100644 index 0000000000..efbdc9fd7f --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/tutorial/getting_started_with_webgl/index.html @@ -0,0 +1,70 @@ +--- +title: 初识 WebGL +slug: Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL +tags: + - WebGL + - 教程 +translation_of: Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{Next("Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context")}}</p> + +<p><a class="external" href="http://www.khronos.org/webgl/" title="http://www.khronos.org/webgl/">WebGL</a> 使得在支持HTML 的 <a class="internal" href="/zh-CN/HTML/Canvas" title="zh-CN/HTML/Canvas"><code>canvas</code></a> 标签的浏览器中,不需要安装任何插件,便可以使用基于 <a class="external" href="http://www.khronos.org/opengles/" title="http://www.khronos.org/opengles/">OpenGL ES</a> 2.0 的 API 在 canvas 中进行2D和3D渲染。WebGL程序包括用 JavaScript 写的控制代码,以及在图形处理单元(GPU, Graphics Processing Unit)中执行的着色代码(GLSL,注:GLSL为OpenGL着色语言)。WebGL 元素可以和其他 HTML 元素混合使用,并且可以和网页其他部分或者网页背景结合起来。</p> + +<p>本文将向您介绍 WebGL 的基本用法。此处假定您对三维图形方面的数学知识已经有一定的理解,本文也不会试图向您教授 3D图像概念本身。</p> + +<p>本文的代码也可以在这里下载 <a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial">webgl-examples GitHub repository</a> 。</p> + +<p><a href="https://threejs.org/">THREE.js</a>和<a href="https://www.babylonjs.com/">BABYLON.js</a>等很多框架封装了WebGL,提供了各个平台之间的兼容性。使用这些框架而非原生的WebGL可以更容易地开发3D应用和游戏。</p> + +<h2 id="准备_3D_渲染">准备 3D 渲染</h2> + +<p>为了使用 WebGL 进行 3D 渲染,你首先需要一个 canvas 元素。下面的 HTML 片段用来建立一个 canvas 元素并设置一个 onload 事件处理程序来初始化我们的 WebGL 上下文 。</p> + +<pre class="brush: html notranslate"><body onload="main()"> + <canvas id="glcanvas" width="640" height="480"> + 你的浏览器似乎不支持或者禁用了HTML5 <code>&lt;canvas&gt;</code> 元素. + </canvas> +</body> +</pre> + +<h3 id="准备_WebGL_上下文">准备 WebGL 上下文</h3> + +<p>我们的 JavaScript 代码中的 <code>main()</code> 函数将会在文档加载完成之后被调用。它的任务是设置 WebGL 上下文并开始渲染内容。<code class="language-js"> </code></p> + +<pre class="brush: js line-numbers language-js notranslate"><code class="language-js">// 从这里开始 +function main() { + const canvas = document.querySelector("#glcanvas"); + // 初始化WebGL上下文 + const gl = canvas.getContext("webgl"); + + // 确认WebGL支持性 + if (!gl) { + alert("无法初始化WebGL,你的浏览器、操作系统或硬件等可能不支持WebGL。"); + return; + } + + // 使用完全不透明的黑色清除所有图像 + gl.clearColor(0.0, 0.0, 0.0, 1.0); + // 用上面指定的颜色清除缓冲区 + gl.clear(gl.COLOR_BUFFER_BIT); +}</code></pre> + +<p>我们所要做的第一件事就是是获取 canvas 的引用,把它保存在 ‘canvas’ 变量里。</p> + +<p>当我们获取到 canvas之后,我们会调用<a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext">getContext</a> 函数并向它传递<code>"webgl"</code>参数,来尝试获取<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext">WebGLRenderingContext</a>。如果浏览器不支持webgl,<code>getContext</code>将会返回<code>null</code>,我们就可以显示一条消息给用户然后退出。</p> + +<p>如果WebGL上下文成功初始化,变量 ‘gl’ 会用来引用该上下文。在这个例子里,我们用黑色清除上下文内已有的元素。(用背景颜色重绘canvas)。</p> + +<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample1/index.html', 670, 510) }}</p> + +<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample1">看源码</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample1/">看DEMO</a></p> + +<h2 id="参见">参见</h2> + +<ul> + <li><a href="https://dev.opera.com/articles/introduction-to-webgl-part-1/">WebGL介绍</a>: 由Luz Caballero所著, 发布在dev.opera.com。 这篇文章说明WebGL是什么, 解释了WebGL是如何工作的 (介绍了渲染管线的概念),并且介绍了一些WebGL库。</li> + <li><a href="http://webglfundamentals.org/">WebGL基础</a></li> + <li><a href="http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Table-of-Contents.html">现代OpenGL介绍:</a> 由Joe Groff写的一系列关于OpenGL的不错的文章,提供了一个清晰的介绍,从OpenGL的历史到图形管线概念,也包括一些说明OpenGL如何工作的例子,如果你对OpenGL没有任何概念的话,这是不错的出发点。</li> +</ul> + +<p>{{Next("Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/tutorial/index.html b/files/zh-cn/web/api/webgl_api/tutorial/index.html new file mode 100644 index 0000000000..b73235a3d6 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/tutorial/index.html @@ -0,0 +1,41 @@ +--- +title: WebGL 教程 +slug: Web/API/WebGL_API/Tutorial +tags: + - WebGL + - 教程 + - 概览 +translation_of: Web/API/WebGL_API/Tutorial +--- +<div>{{WebGLSidebar}}</div> + +<div class="summary"> +<p><a class="external" href="http://www.khronos.org/webgl/" title="http://www.khronos.org/webgl/">WebGL</a> 使得网页在支持HTML {{HTMLElement("canvas")}} 标签的浏览器中,不需要使用任何插件,便可以使用基于 <a href="http://www.khronos.org/opengles/" title="http://www.khronos.org/opengles/">OpenGL ES</a> 2.0 的 API 在 canvas 中进行3D渲染. WebGL 程序由javascript的控制代码,和在计算机的图形处理单元(GPU, Graphics Processing Unit)中执行的特效代码(shader code,渲染代码) 组成. WebGL 元素可以和其他HTML元素混合, 并且会和页面的其他部分或页面背景相合成.</p> +</div> + +<p><span class="seoSummary">此教程从基础开始讲解如何使用<code><canvas></code> 元素来画WebGL 图形. 提供的例子会让你对WebGL有更清晰的认识, 并且会提供代码片段方便你构建自己的内容.</span></p> + +<h2 id="开始之前">开始之前</h2> + +<p>使用 <code><canvas></code> 元素并不困难,但你需要基本的 <a href="/en-US/docs/Web/HTML" title="HTML">HTML</a> 和 <a href="/en-US/docs/Web/JavaScript" title="JavaScript">JavaScript</a> 知识。一些老浏览器不支持<code><canvas></code> 元素和 WebGL,但所有最近的主流浏览器都支持它们.。为了能在canvas中绘制图形,我们使用Javascript的上下文环境(context)对象,此对象可以动态创建图形。</p> + +<h2 id="在本教程中">在本教程中</h2> + +<dl> + <dt><a href="/zh-CN/docs/Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL">开始WebGL</a></dt> + <dd>如何设置WebGL上下文环境.</dd> + <dt><a href="/zh-CN/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context">给WebGL的上下文环境添加2D内容</a></dt> + <dd>如何用WebGl渲染简单的平面化图形.</dd> + <dt><a href="/zh-CN/docs/Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL">在WebGL中使用着色器(shader)去赋予颜色</a></dt> + <dd>演示如何使用着色器给图形添加颜色.</dd> + <dt><a href="/zh-CN/docs/Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL">用WebGL让对象动起来</a></dt> + <dd>展示如何旋转移动物体来实现简单动画效果.</dd> + <dt><a href="/zh-CN/docs/Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL">使用WebGL创建3D物体</a></dt> + <dd>展示如何创建并设置一个3D物体动画 (这里使用立方体).</dd> + <dt><a href="/zh-CN/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL">在WebGL中使用纹理贴图(texture)</a></dt> + <dd>展示如何投射纹理贴图到物体的各个面.</dd> + <dt><a href="/zh-CN/docs/Web/API/WebGL_API/Tutorial/Lighting_in_WebGL">WebGL中的灯光</a></dt> + <dd>如何在WebGL上下文环境中模拟灯光效果.</dd> + <dt><a href="/zh-CN/docs/Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL">WebGL中的动画纹理贴图</a></dt> + <dd>展示如何让纹理贴图动起来; 在此例中, 会投射一个Ogg格式的视频在一个旋转立方体的各个面上.</dd> +</dl> diff --git a/files/zh-cn/web/api/webgl_api/tutorial/lighting_in_webgl/index.html b/files/zh-cn/web/api/webgl_api/tutorial/lighting_in_webgl/index.html new file mode 100644 index 0000000000..fcb6b665a1 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/tutorial/lighting_in_webgl/index.html @@ -0,0 +1,175 @@ +--- +title: Lighting in WebGL +slug: Web/API/WebGL_API/Tutorial/Lighting_in_WebGL +translation_of: Web/API/WebGL_API/Tutorial/Lighting_in_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL", "Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL")}}</p> + +<p>在使用灯光之前,首先我们需要了解,与定义更广泛的OpenGL不同,WebGL并没有继承OpenGL中灯光的支持。所以你只能由自己完全得控制灯光。幸运得是,这也并不是很难,本文接下来就会介绍完成灯光的基础。</p> + +<h2 id="在3D空间中模拟现实灯光">在3D空间中模拟现实灯光</h2> + +<p>在3D空间中模拟现实世界的灯光的具体原理和细节绝非本篇文章能够描述清楚的,但是对灯光模型有一定的了解对我们的学习还是很有帮助的。虽然这里没办法深入讲解,但是维基百科中的<a href="https://zh.wikipedia.org/wiki/Phong%E8%91%97%E8%89%B2%E6%B3%95">Phong着色法</a>给出了一个不错的概要介绍,其中包含了最常用的几种光照模型。</p> + +<p>光源类型可以概括成如下三种:</p> + +<p><strong>环境光 </strong>是一种可以渗透到场景的每一个角落的光。它是非方向光并且会均匀地照射物体的每一个面,无论这个面是朝向哪个方向的。</p> + +<p><strong>方向光</strong> 是一束从一个固定的方向照射过来的光。这种光的特点可以理解为好像是从一个很遥远的地方照射过来的,然后光线中的每一个光子与其它光子都是平行运动的。举个例子来说,阳光就可以认为是方向光。</p> + +<p><strong>点光源光</strong> 是指光线是从一个点发射出来的,是向着四面八方发射的。这种光在我们的现实生活中是最常被用到的。举个例子来说,电灯泡就是向各个方向发射光线的。</p> + +<p>以我们的需要来看,我们会简化光照模型,只考虑简单的方向光和环境光,不会考虑任何镜面反射和点光源。这样的话,我们只需要在我们使用的环境光上加上照射到旋转立方体的方向光就可以了。在这里可以看到之前的<a href="/zh-CN/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL">旋转立方体的例子</a>。</p> + +<p>虽然可以抛开了点光源和镜面反射,但是关于方向光还是有两点需要注意一下:</p> + +<ol> + <li>需要在每个顶点信息中加入面的<strong>朝向法线</strong>。这个法线是一个垂直于这个顶点所在平面的向量。</li> + <li>需要明确方向光的传播方向,可以使用一个<strong>方向向量</strong>来定义。</li> +</ol> + +<p>接着,我们会更新顶点着色器,考虑到环境光,再考虑到方向光(方向光的作用会因为光线方向与面的夹角关系而不同),计算每一个顶点的颜色。实现这一目标的代码如下。</p> + +<h2 id="建立顶点法线">建立顶点法线</h2> + +<p>首先我们需要做的是建立一个数组来存放立方体所有顶点的法线。由于立方体是一个很简单的物体,所以很容易实现;显然如果是对复杂物体,则法线的计算方法需要更深入的研究。(注:译者调试后发现此处new WebGLFloatArray(...) 可能应该使用new Float32Array())</p> + +<pre class="brush: js">cubeVerticesNormalBuffer = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesNormalBuffer); + +var vertexNormals = [ + // Front + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + + // Back + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + + // Top + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + + // Bottom + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + + // Right + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + + // Left + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0 +]; + +gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(vertexNormals), gl.STATIC_DRAW); +</pre> + +<p>现在我们应该对此非常熟悉了;创建新的buffer,将它和gl.ARRAR_BUFFER绑定在一起,然后通过调用bufferData()把我们的顶点法线数组一起传入。</p> + +<p>然后我们在drawScene()中添加代码,将法线数组和着色器的attribute绑定起来以便着色器能够获取到法线数组的信息。</p> + +<p>(此处变量 vertexNormalAttribute 应该在initShader()函数中声明, 并赋值: vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal"); gl.enableVertexAttribArray(vertexNormalAttribute);)</p> + +<pre class="brush: js">gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesNormalBuffer); +gl.vertexAttribPointer(vertexNormalAttribute, 3, gl.FLOAT, false, 0, 0); +</pre> + +<p>最后,我们(为了读者便于理解, 此处代码应该在setMatrixUniforms() 函数中添加)需要更新下代码,在着色器中建立和传递法线向量矩阵,用这个矩阵来处理当前立方体相对于光源位置法线向量的转换(注:译者调试后发现此处new WebGLFloatArray(...) 应该使用new Float32Array()):</p> + +<pre class="brush: js">var normalMatrix = mvMatrix.inverse(); +normalMatrix = normalMatrix.transpose(); +var nUniform = gl.getUniformLocation(shaderProgram, "uNormalMatrix"); +gl.uniformMatrix4fv(nUniform, false, new WebGLFloatArray(normalMatrix.flatten())); +</pre> + +<h2 id="更新着色器">更新着色器</h2> + +<p>现在着色器需要的所有数据已经全部可以获取到了(或者说全部准备好了),我们需要更新下着色器本身的代码。</p> + +<h3 id="顶点着色器">顶点着色器</h3> + +<p>首先更新顶点着色器,让它给每一个基于环境光和方向光的顶点一个着色器值。让我们看下代码:</p> + +<pre class="brush: html"><script id="shader-vs" type="x-shader/x-vertex"> + attribute highp vec3 aVertexNormal; + attribute highp vec3 aVertexPosition; + attribute highp vec2 aTextureCoord; + + uniform highp mat4 uNormalMatrix; + uniform highp mat4 uMVMatrix; + uniform highp mat4 uPMatrix; + + varying highp vec2 vTextureCoord; + varying highp vec3 vLighting; + + void main(void) { + gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); + vTextureCoord = aTextureCoord; + + // Apply lighting effect + + highp vec3 ambientLight = vec3(0.6, 0.6, 0.6); + highp vec3 directionalLightColor = vec3(0.5, 0.5, 0.75); + highp vec3 directionalVector = vec3(0.85, 0.8, 0.75); + + highp vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0); + + highp float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0); + vLighting = ambientLight + (directionalLightColor * directional); + } +</script> +</pre> + +<p>一旦顶点位置计算完毕,我们就可以获得纹理对应于顶点的坐标,从而计算出顶点的阴影。</p> + +<p>我们先根据立方体位置和朝向,通过顶点法线乘以法线矩阵来转换法线。接着我们可以通过计算转换过后的法线与方向向量(即,光来自的方向)的点积来计算得出顶点反射方向光的量。如果计算出的这个值小于0,则我们把值固定设为0,因为你不会有小于0的光。</p> + +<p>当方向光的量计算完,我们可以通过获取环境光并且添加方向光的颜色和要提供的定向光的量来生成光照值(lighting value)。最终结果我们会得到一个RGB值,用于片段着色器调整我们渲染的每一个像素的颜色。</p> + +<h3 id="片段着色器">片段着色器</h3> + +<p>片段着色器现在需要根据顶点着色器计算出的光照值来更新:</p> + +<pre class="brush: js"><script id="shader-fs" type="x-shader/x-fragment"> + varying highp vec2 vTextureCoord; + varying highp vec3 vLighting; + + uniform sampler2D uSampler; + + void main(void) { + mediump vec4 texelColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); + + gl_FragColor = vec4(texelColor.rgb * vLighting, texelColor.a); + } +</script> +</pre> + +<p>和先前我们做的例子一样,我们获取纹理的颜色(原文“color of the texel”? 此处个人觉得应该就是指纹理的颜色),不同的是在设置片段颜色之前,我们将纹理的颜色乘以光照值来调整纹理以达到我们光源的效果。</p> + +<p>效果就是这样!</p> + +<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample7/index.html', 670, 510) }}</p> + +<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample7">View the complete code</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample7/">Open this demo on a new page</a></p> + +<h2 id="读者练习">读者练习</h2> + +<p>显然这是一个很简单的例子,实现了基本的每个顶点的照明。对于更高级的图形,你将可能需要实现每个像素(或者说更多像素)的照明,但这会帮助你朝着正确的方向前行。</p> + +<p>你也可以尝试光源方向颜色等等。</p> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL", "Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/tutorial/using_shaders_to_apply_color_in_webgl/index.html b/files/zh-cn/web/api/webgl_api/tutorial/using_shaders_to_apply_color_in_webgl/index.html new file mode 100644 index 0000000000..4f2c37046c --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/tutorial/using_shaders_to_apply_color_in_webgl/index.html @@ -0,0 +1,117 @@ +--- +title: 使用着色器将颜色应用于WebGL +slug: Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL +tags: + - WebGL + - 教程 +translation_of: Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context", "Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL")}}</p> + +<p>在<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context">之前的展示</a>中我们已经创建好了一个正方形,接下来我们要做的就是给它添加一抹色彩。添加颜色可以通过修改着色器来实现。</p> + +<h2 id="给顶点着色">给顶点着色</h2> + +<p>在GL中,物体是由一系列顶点组成的,每一个顶点都有位置和颜色信息。在默认情况下,所有像素的颜色(以及它所有的属性,包括位置)都由线性插值计算得来,自动形成平滑的渐变。我们以前的顶点着色器没有给顶点添加任何特定的颜色——在顶点着色器与片段着色器之间给每个像素着白色,于是整个正方形被渲染成纯白。</p> + +<p>现在我们假设正方形的每个顶点使用不同的颜色:红,黄,绿,白,以此渲染一个渐变的色彩。第一步,要给这些顶点建立相应的颜色。首先我们要创建一个顶点颜色数组,然后将它们存在WebGL的缓冲区中。为实现这一功能,我们在 initBuffers() 函数中加入如下代码:</p> + +<pre><code>initBuffers() { + const positionBuffer = gl.createBuffer(); + const positions = [ + 1.0, 1.0, + -1.0, 1.0, + 1.0, -1.0, + -1.0, -1.0, + ];</code> +<code> gl.bindBuffer(</code>WebGLRenderingContext<code>.ARRAY_BUFFER, positionBuffer); + gl.bufferData(</code>WebGLRenderingContext<code>.ARRAY_BUFFER, + new Float32Array(positions), + </code>WebGLRenderingContext<code>.STATIC_DRAW + ); + + const colorBuffer = gl.createBuffer(); + const colors = [ + 1.0, 1.0, 1.0, 1.0, // 白 + 1.0, 0.0, 0.0, 1.0, // 红 + 0.0, 1.0, 0.0, 1.0, // 绿 + 0.0, 0.0, 1.0, 1.0, // 蓝 + ]; + + gl.bindBuffer(</code>WebGLRenderingContext<code>.ARRAY_BUFFER, colorBuffer); + gl.bufferData(</code>WebGLRenderingContext<code>.ARRAY_BUFFER, + new Float32Array(colors), + </code>WebGLRenderingContext<code>.STATIC_DRAW + ); + + return { + position: positionBuffer, + color: colorBuffer, + }; +}</code></pre> + +<p>这段代码首先建立了一个JavaScript的数组,此数组中包含四组四值向量,每一组向量代表一个顶点的颜色。然后,创建一个WebGL缓冲区用来存储这些颜色——将数组中的值转换成WebGL所规定的浮点型后,存储在该缓冲区中。</p> + +<p>为了实际使用这些颜色,我们继续修改顶点着色器,使得着色器可以从颜色缓冲区中正确取出颜色:</p> + +<pre class="brush: html"> <script id="shader-vs" type="x-shader/x-vertex"> + attribute vec3 aVertexPosition; + attribute vec4 aVertexColor; + + uniform mat4 uModelViewMatrix; + uniform mat4 uProjectionMatrix; + + varying lowp vec4 vColor; + + void main(void) { + gl_Position = uProjectionMatrix* uModelViewMatrix * vec4(aVertexPosition, 1.0); + vColor = aVertexColor; + } + </script> +</pre> + +<p>与之前相比,这段代码的关键不同点在于:每个顶点都与一个颜色数组中的数值相连接。</p> + +<h2 id="给片段着色">给片段着色</h2> + +<p>我们先来复习一下之前构造的片段着色器:</p> + +<pre class="brush: html"> <script id="shader-fs" type="x-shader/x-fragment"> + void main(void) { + gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); + } + </script> +</pre> + +<p>为使每个像素都得到插值后的颜色,我们只需要在此从 <code>vColor </code>变量中获取这个颜色的值:</p> + +<pre class="brush: html"> <script id="shader-fs" type="x-shader/x-fragment"> + varying lowp vec4 vColor; + + void main(void) { + gl_FragColor = vColor; + } + </script> +</pre> + +<p>这是一个非常简单的改变,每个片段只是根据其相对于顶点的位置得到一个插值过的颜色,而不是一个指定的颜色值。</p> + +<h2 id="带颜色的绘制">带颜色的绘制</h2> + +<p>接下来,我们要在 <code>initShader()</code> 中初始化颜色属性,以便着色器程序使用</p> + +<pre class="brush: js"> vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor"); + gl.enableVertexAttribArray(vertexColorAttribute); +</pre> + +<p>然后,我们便可以修改 <code>drawScene()</code> 使之在绘制正方形时使用这些颜色:</p> + +<pre class="brush: js"> gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer); + gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0); +</pre> + +<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample3/index.html', 670, 510) }}</p> + +<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample3">查看完整代码</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample3/">在新页面中打开示例</a></p> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context", "Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/tutorial/using_textures_in_webgl/index.html b/files/zh-cn/web/api/webgl_api/tutorial/using_textures_in_webgl/index.html new file mode 100644 index 0000000000..07b3eb2042 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/tutorial/using_textures_in_webgl/index.html @@ -0,0 +1,205 @@ +--- +title: Using textures in WebGL +slug: Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL +translation_of: Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL", "Web/API/WebGL_API/Tutorial/Lighting_in_WebGL")}}</p> + +<p>现在我们已经创建好了一个可以旋转的3D的立方体,接下来是时候使用贴图来代替每个面的单一的颜色了。</p> + +<h2 id="加载纹理">加载纹理</h2> + +<p>首先加入加载纹理的代码。现在我们只使用一张单一的纹理贴到立方体的6个面上,但是同样的方法可以用来加载任意数量的纹理贴图。</p> + +<div class="note"><strong>注意:</strong> 值得注意的一点是对纹理的加载同样需要遵循<a href="zh-CN/docs/Web/HTTP/Access_control_CORS">跨域访问规则</a>;也就是说你只能从允许跨域访问的网址加载你需要的纹理。下面的例子就是支持跨域访问的。</div> + +<p>加载纹理的代码如下:</p> + +<pre class="brush: js">function initTextures() { + cubeTexture = gl.createTexture(); + cubeImage = new Image(); + cubeImage.onload = function() { handleTextureLoaded(cubeImage, cubeTexture); } + cubeImage.src = "cubetexture.png"; +} + +function handleTextureLoaded(image, texture) { + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + gl.generateMipmap(gl.TEXTURE_2D); + gl.bindTexture(gl.TEXTURE_2D, null); +} +</pre> + +<p>函数 <code>initTextures()</code> 首先调用 GL {{domxref("WebGLRenderingContext.createTexture()", "createTexture()")}} 函数来创建一个GL纹理对象 cubeTexture 。为了把图片文件加载到纹理,代码首先创建了一个 <code>Image</code> 对象然后把需要当作纹理使用的图形文件加载了进来。当图片加载完成后回调函数 <code>handleTextureLoaded()</code> 就会执行。</p> + +<p>接下来为了真正地形成纹理,我们通过把新创建的纹理对象绑定到 <code>gl.TEXTURE_2D 来让它成为当前操作纹理。然后通过调用</code> {{domxref("WebGLRenderingContext.texImage2D()", "texImage2D()")}} 把已经加载的图片图形数据写到纹理。</p> + +<div class="note"><strong>注意:</strong> 在多数情况下,纹理的宽和高都必须是2的幂(如:1,2,4,8,16等等)。如果有什么特殊情况请参考下面的“<a href="/zh-CN/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL#非2的幂纹理">非2的幂纹理</a>”小节。</div> + +<p>代码的接下来两行设置了纹理过滤器,过滤器用来控制当图片缩放时像素如何生成如何插值。在这个例子里,我们对图片放大使用的是线性过滤,而对图片缩小使用的是多级渐进纹理过滤。接下来我们通过调用 {{domxref("WebGLRenderingContext.generateMipMap()", "generateMipMap()")}} 来生成多级渐进纹理,接着通过给 <code>gl.TEXTURE_2D 绑定值 null 来告诉 WebGL 我们对当前纹理的操作已经结束了。</code></p> + +<h3 id="非2的幂纹理">非2的幂纹理</h3> + +<p>一般来说,宽和高都是2的幂的纹理使用是最理想的。2的幂纹理在渲染内存里的存储更高效,而且对它们的使用限制也更少。由美术工作人员生成的纹理最终在用来渲染前都应该使用放大或缩小的方式把它生成为2的幂纹理,其实事实上来说,在创作纹理之初就应该直接使用大小是2的幂的宽和高。纹理的每一边都应该是像1,2,4,8,16,32,64,128,256,512,1024或2048这样的值。当然也要注意尺寸的大小,因为虽说现在的大部分设置都已经可以支持4096像素的图片,但也不是全部;而有一些设备甚至可以支持8192或更高像素呢。</p> + +<p>有的时候从你的特定情况出发,使用2的幂纹理会比较困难。当使用到第三方的资源时,一般来说最好的方式就是先使用HTML5的画布把图片修正成2的幂然后再放到WebGL中进行渲染使用,这样一来,如果图片拉伸比较明显的话纹理坐标的值可需要适当地进行修正。</p> + +<p>但是,如果你一定要使用非2的幂纹理的话,WebGL也有原生支持,不过这些支持是受限的。当然在某些情况下使用非2的幂纹理也是很有用的,比如这张纹理刚好与你的显示器的分辨率相匹配,或者使用画布重新生成纹理的方式并不值得时。但是要特别注意的是:这种非2的幂纹理不能用来生成多级渐进纹理,而且不能使用纹理重复(重复纹理寻址等)。</p> + +<p>使用重复纹理寻址的一个例子就是使用一张砖块的纹理来平铺满一面墙壁。</p> + +<p>多级渐进纹理和纹理坐标重复可以通过调用 {{domxref("WebGLRenderingContext.texParameter()", "texParameteri()")}} 来禁用,当然首先你已经通过调用 {{domxref("WebGLRenderingContext.bindTexture()", "bindTexture()")}} 绑定过纹理了。这样虽然已经可以使用非2的幂纹理了,但是你将无法使用多级渐进纹理,纹理坐标包装,纹理坐标重复,而且无法控制设备如何处理你的纹理。</p> + +<pre class="brush: js">// gl.NEAREST is also allowed, instead of gl.LINEAR, as neither mipmap. +gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); +// Prevents s-coordinate wrapping (repeating). +gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); +// Prevents t-coordinate wrapping (repeating). +gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);</pre> + +<p>现在,当使用以上参数时,兼容WebGL的设备就会自动变得可以使用任何分辨率的纹理(当然还要考虑像素上限)。如果不使用上面这些参数的话,任何非2的幂纹理使用都会失败然后返回一张纯黑图片。</p> + +<h2 id="映射纹理到面">映射纹理到面</h2> + +<p>现在,纹理已经加载好了,而且已经可以使用了。但是在使用之前我们还要创建好纹理坐标到立方体各个面的顶点的映射关系。下面的代码通过替换之前的设置每个面颜色的代码,当然还是在 <code>initBuffers() 函数里。</code></p> + +<pre class="brush: js">cubeVerticesTextureCoordBuffer = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesTextureCoordBuffer); + +var textureCoordinates = [ + // Front + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + // Back + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + // Top + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + // Bottom + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + // Right + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + // Left + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 +]; + +gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), + gl.STATIC_DRAW); +</pre> + +<p>首先,代码创建了一个GL缓存区,用来保存每个面的纹理坐标信息,然后把这个缓存区绑定到GL以方便我们写入数据。</p> + +<p><code>数组变量 textureCoordinates</code> 中定义好了与每个面上的每个顶点一一对应的纹理坐标。请注意,纹理坐标的取值范围只能从0.0到1.0,所以不论纹理贴图的实际大小是多少,为了实现纹理映射,我们要使用的纹理坐标只能规范化到0.0到1.0的范围内。</p> + +<p>纹理坐标信息给定了之后,把这个数组里的数据都写到GL缓存区,这样GL就能使用这个坐标数据了。</p> + +<h2 id="更新着色器">更新着色器</h2> + +<p>为了使用纹理来代替单一的颜色,着色器程序和着色器程序的初始化代码都需要进行修改。</p> + +<p>先让我们看一看需要加入函数 initShaders() 里的非常简单的改变:</p> + +<pre class="brush: js">textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); +gl.enableVertexAttribArray(textureCoordAttribute); +gl.vertexAttribPointer(texCoordAttribute, 2, gl.FLOAT, false, 0, 0); +</pre> + +<p>这段代码中我们使用包含纹理坐标信息的属性替换之前使用的顶点颜色属性。</p> + +<h3 id="顶点着色器">顶点着色器</h3> + +<p>接下来我们会修改顶点着色器代码,现在不再需要获取顶点颜色数据,而是获取纹理坐标数据。</p> + +<pre class="brush: html"><script id="shader-vs" type="x-shader/x-vertex"> + attribute vec3 aVertexPosition; + attribute vec2 aTextureCoord; + + uniform mat4 uMVMatrix; + uniform mat4 uPMatrix; + + varying highp vec2 vTextureCoord; + + void main(void) { + gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); + vTextureCoord = aTextureCoord; + } +</script> +</pre> + +<p>代码的关键更改在于不再获取顶点颜色数据转而获取和设置纹理坐标数据;这样就能把顶点与其对应的纹理联系在一起了。</p> + +<h3 id="片段着色器">片段着色器</h3> + +<p>那么片段着色器也要相应地进行更改:</p> + +<pre class="brush: html"><script id="shader-fs" type="x-shader/x-fragment"> + varying highp vec2 vTextureCoord; + + uniform sampler2D uSampler; + + void main(void) { + gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); + } +</script> +</pre> + +<p>现在的代码不会再使用一个简单的颜色值填充片段颜色,片段的颜色是通过采样器使用最好的映射方式从纹理中的每一个像素计算出来的。</p> + +<h2 id="绘制具体纹理贴图的立方体">绘制具体纹理贴图的立方体</h2> + +<p>接下来是对 <code>drawScene()</code> 函数的更改,为了使整体的代码看起来更简洁,我们去掉了让立方体位置变化的代码,现在它只会随着时间的变化进行旋转,而为了使用纹理,所要进行的代码更改确是很少的。</p> + +<p>使用下面的代码代替映射颜色到纹理的代码:</p> + +<pre class="brush: js">gl.activeTexture(gl.TEXTURE0); +gl.bindTexture(gl.TEXTURE_2D, cubeTexture); +gl.uniform1i(gl.getUniformLocation(shaderProgram, "uSampler"), 0); +</pre> + +<p>GL 最多可同时注册32张纹理;<code>gl.TEXTURE0 是第一张。我们把我们之前加载的纹理绑定到了第一个寄存器,然后着色器程序里的采样器 uSampler</code> 就会完成它的功能:使用纹理。</p> + +<p>好,现在我们的立方体就会像这样旋转起来了。</p> + +<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample6/index.html', 670, 510) }}</p> + +<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample6">查看完整示例代码</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample6/">在新窗口里打开示例</a></p> + +<h2 id="关于跨域纹理">关于跨域纹理</h2> + +<p>加载WebGL纹理应该也可以说是跨域访问控制里的一个话题。为了在我们的显示内容里使用其它域名里的纹理图片,允许跨域访问也是要考虑的。可以通过查看<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS">HTTP访问控制</a>来获取到更多的相关细节。</p> + +<p><a href="http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/">这篇文章</a>也对跨域加载纹理到WebGL做出了解释。而且文章里面还包含了一个使用的<a href="http://people.mozilla.org/~bjacob/webgltexture-cors-js.html">例子</a>。</p> + +<div class="note"> +<p><strong>注意:</strong>对跨域加载WebGL纹理的支持和对 image 元素的 <code>crossOrigin</code> 的属性的支持都是在 {{Gecko("8.0")}} 版本中实现的。</p> +</div> + +<p>被污染过的(只写)画布是不能拿来当作WebGL纹理来使用的。举个例子来说,当把一张跨域的图片画到一个2D的 {{ HTMLElement("canvas") }} 中时,这个画布就是“被污染过的”。</p> + +<div class="note"> +<p><strong>注意:</strong> 对 Canvas 2D 的 <code>drawImage 的跨域支持已经在 </code>{{Gecko("9.0")}} 版本实现的。这就意味着使用支持跨域的图片来污染一个2D的画布,这张画布也已经可以作为WebGL的纹理来使用了。</p> +</div> + +<div class="note"> +<p><strong>注意:</strong> 视频对跨域的支持以及 {{ HTMLElement("video") }} 元素的 <code>crossorigin</code> 属性的支持是在 {{Gecko("12.0")}} 版本中实现的。</p> +</div> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL", "Web/API/WebGL_API/Tutorial/Lighting_in_WebGL")}}</p> diff --git a/files/zh-cn/web/api/webgl_api/types/index.html b/files/zh-cn/web/api/webgl_api/types/index.html new file mode 100644 index 0000000000..2ce6fac2bc --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/types/index.html @@ -0,0 +1,215 @@ +--- +title: WebGL types +slug: Web/API/WebGL_API/Types +translation_of: Web/API/WebGL_API/Types +--- +<div>{{WebGLSidebar}}</div> + +<p>以下是<a href="/en-US/docs/Web/API/WebGL_API">WebGL</a>提供的接口中用到的变量类型。</p> + +<h2 id="WebGL_1">WebGL 1</h2> + +<p>以下类型的变量属于{{domxref("WebGLRenderingContext")}}对象。</p> + +<table class="standard-table"> + <tbody> + <tr> + <td class="header">类型</td> + <td class="header">Web接口类型</td> + <td class="header">描述</td> + </tr> + <tr> + <td><code>GLenum</code></td> + <td><code>unsigned long</code></td> + <td>用于枚举。另见 <a href="/zh-CN/docs/Web/API/WebGL_API/Constants">constants</a>。</td> + </tr> + <tr> + <td><code>GLboolean</code></td> + <td><code>boolean</code></td> + <td>{{jsxref("Boolean")}}型。</td> + </tr> + <tr> + <td><code>GLbitfield</code></td> + <td><code>unsigned long</code></td> + <td>一个位字段(bit field),用于存储逻辑位(bit)。例如,在 {{domxref("WebGLRenderingContext.clear()")}}的使用。</td> + </tr> + <tr> + <td><code>GLbyte</code></td> + <td><code>byte</code></td> + <td>八位(一个字节),2的补码表示的有符号整数。</td> + </tr> + <tr> + <td><code>GLshort</code></td> + <td><code>short</code></td> + <td>十六位2的补码表示的有符号整数。</td> + </tr> + <tr> + <td><code>GLint</code></td> + <td><code>long</code></td> + <td>三十二位2的补码表示的有符号整数。</td> + </tr> + <tr> + <td><code>GLsizei</code></td> + <td><code>long</code></td> + <td>用来描述尺寸(例如:绘画缓冲drawing buffer的宽和高)。</td> + </tr> + <tr> + <td><code>GLintptr</code></td> + <td><code>long long</code></td> + <td>用来表示指针的特殊类型。</td> + </tr> + <tr> + <td><code>GLsizeiptr</code></td> + <td><code>long long</code></td> + <td>用来表示指针的特殊类型。</td> + </tr> + <tr> + <td><code>GLubyte</code></td> + <td><code>octet</code></td> + <td>八位(一个字节),2的补码表示的无符号整数。</td> + </tr> + <tr> + <td><code>GLushort</code></td> + <td><code>unsigned short</code></td> + <td>十六位2的补码表示的无符号整数。</td> + </tr> + <tr> + <td><code>GLuint</code></td> + <td><code>unsigned long</code></td> + <td>三十二位2的补码表示的有符号整数。</td> + </tr> + <tr> + <td><code>GLfloat</code></td> + <td><code>unrestricted float</code></td> + <td>三十二位的IEEE标准的浮点数。</td> + </tr> + <tr> + <td><code>GLclampf</code></td> + <td><code>unrestricted float</code></td> + <td>限值32位IEEE浮点数。</td> + </tr> + </tbody> +</table> + +<h2 id="WebGL_2">WebGL 2</h2> + +<p>以下类型的变量属于 {{domxref("WebGL2RenderingContext")}}. 所有WebGL 1中的类型也有使用。</p> + +<table class="standard-table"> + <tbody> + <tr> + <td class="header">类型</td> + <td class="header">Web接口类型</td> + <td class="header">描述</td> + </tr> + <tr> + <td><code>GLint64</code></td> + <td><code>long long</code></td> + <td>六十四位有符号整数。</td> + </tr> + </tbody> +</table> + +<h2 id="WebGL_扩展">WebGL 扩展</h2> + +<p>以下类型用在 <a href="/en-US/docs/Web/API/WebGL_API/Using_Extensions">WebGL extensions</a>中。</p> + +<table class="standard-table"> + <tbody> + <tr> + <td class="header">类型</td> + <td class="header">Web接口类型</td> + <td class="header">描述</td> + </tr> + <tr> + <td><code>GLuint64EXT</code></td> + <td><code>long long</code></td> + <td>六十四位无符号整数</td> + </tr> + </tbody> +</table> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('WebGL', "#5.1", "Types")}}</td> + <td>{{Spec2('WebGL')}}</td> + <td>初始定义</td> + </tr> + <tr> + <td>{{SpecName('WebGL2', "#3.1", "Types")}}</td> + <td>{{Spec2('WebGL2')}}</td> + <td>定义额外的类型.</td> + </tr> + <tr> + <td>{{SpecName('EXT_disjoint_timer_query', "", "GLuint64EXT")}}</td> + <td>{{Spec2('EXT_disjoint_timer_query')}}</td> + <td>添加<code>GLuint64EXT</code></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatChrome("9")}}</td> + <td>{{CompatGeckoDesktop("2.0")}}</td> + <td>{{CompatIE("11")}}</td> + <td>{{CompatOpera("12")}}</td> + <td>{{CompatSafari("5.1")}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>25</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>12</td> + <td>8.1</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="另见">另见</h2> + +<ul> + <li>{{domxref("WebGLRenderingContext")}}</li> +</ul> diff --git a/files/zh-cn/web/api/webgl_api/using_extensions/index.html b/files/zh-cn/web/api/webgl_api/using_extensions/index.html new file mode 100644 index 0000000000..bb2c0add23 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/using_extensions/index.html @@ -0,0 +1,578 @@ +--- +title: Using WebGL extensions +slug: Web/API/WebGL_API/Using_Extensions +tags: + - WebGL extensions +translation_of: Web/API/WebGL_API/Using_Extensions +--- +<div>{{WebGLSidebar}}</div> + +<p>WebGL,像它的姐妹API (OpenGL and OpenGL ES),支持使用扩展(extensions)。一份完整的扩展列表可在 <a class="external" href="http://www.khronos.org/registry/webgl/extensions/">khronos webgl extension registry</a>。</p> + +<div class="note"><strong>Note:</strong> 不像别的 GL APIs, 在webGL中 , 扩展只有在明确需要的情况下才会加载。</div> + +<h2 id="规范扩展名,供应商前缀和首选项">规范扩展名,供应商前缀和首选项</h2> + +<p>扩展(extensions)在未被官方正式制定为标准前,某些浏览器厂商可能会支持WebGL扩展 (but only when they are in draft stage)。这样的话,扩展的名字应该加上相应的厂商前缀 (<code>MOZ_</code>, <code>WEBKIT_</code>, etc.),否则这个扩展只能在浏览器切换了偏好设置的前提下生效。</p> + +<p>If you wish to work with the bleeding edge of extensions, and want to keep working on upon ratification (assuming, of course, that the extension doesn't change in incompatible ways), that you query the canonical extension name as well as the vendor extension name. For instance:</p> + +<pre class="brush:js">var ext = ( + gl.getExtension('OES_vertex_array_object') || + gl.getExtension('MOZ_OES_vertex_array_object') || + gl.getExtension('WEBKIT_OES_vertex_array_object') +); +</pre> + +<p>Note that, vendor prefix have been discouraged more and more and thus most browser implement experimental extensions behind a feature flag rather than vendor prefix.</p> + +<p>The feature flags are:</p> + +<ul> + <li><code>webgl.enable-draft-extensions</code> in Firefox</li> + <li><code>chrome://flags/#enable-webgl-draft-extensions</code> in Chromium based browsers (Chrome, Opera).</li> +</ul> + +<h2 id="命名约定">命名约定</h2> + +<p>WebGL extensions are prefixed with "ANGLE", "OES", "EXT" or "WEBGL". These prefixes reflect origin and intent:</p> + +<ul> + <li>ANGLE_: Extensions that are written by the <a href="https://en.wikipedia.org/wiki/ANGLE_%28software%29">ANGLE library</a> authors.</li> + <li>OES_: Extensions that mirror functionality from OpenGL ES or OpenGL API extensions approved by the respective architecture review boards.</li> + <li>EXT_: Extensions that mirror other OpenGL ES or OpenGL API extensions.</li> + <li>WEBGL_: Extensions that are WebGL-specific and intended to be compatible with multiple web browsers. It should also be used for extensions which originated with the OpenGL ES or OpenGL APIs, but whose behavior has been significantly altered.</li> +</ul> + +<h2 id="查询可用的扩展程序">查询可用的扩展程序</h2> + +<p>The WebGL context supports querying what extensions are available.</p> + +<pre class="brush:js">var available_extensions = gl.getSupportedExtensions();</pre> + +<p>The {{domxref("WebGLRenderingContext.getSupportedExtensions()")}} method returns an array of strings, one for each supported extension.</p> + +<h2 id="扩展列表">扩展列表</h2> + +<p>The current extensions are:</p> + +<p>{{page("en-US/docs/Web/API/WebGL_API", "Extensions")}}</p> + +<h2 id="启用一个扩展">启用一个扩展</h2> + +<p>Before an extension can be used it has to be enabled using {{domxref("WebGLRenderingContext.getExtension()")}}. For example:</p> + +<pre class="brush:js">var float_texture_ext = gl.getExtension('OES_texture_float');</pre> + +<p>The return value is <code>null</code> if the extension is not supported, or an extension object otherwise.</p> + +<h2 id="扩展对象">扩展对象</h2> + +<p>If an extension defines specific symbols or functions that are not available in the core specification of WebGL, they will be available on the extension object returned by the call to <code>gl.getExtension()</code>.</p> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<p>{{CompatibilityTable}}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>9</td> + <td>{{CompatGeckoDesktop("2.0")}}</td> + <td>11</td> + <td>12</td> + <td>5.1</td> + </tr> + <tr> + <td><code>ANGLE_instanced_arrays</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("33.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_blend_minmax</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("33.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_color_buffer_half_float</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("30.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_disjoint_timer_query</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("41.0")}} [1]</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_frag_depth</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("30.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_sRGB</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("28.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_shader_texture_lod</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("34.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_texture_filter_anisotropic</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("17.0")}} [2]</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_element_index_uint</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("24.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_standard_derivatives</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("10.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_texture_float</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("6.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_texture_float_linear</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("24.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_texture_half_float</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("29.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_texture_half_float_linear</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("30.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_vertex_array_object</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("25.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_color_buffer_float</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("30.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_compressed_texture_atc</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("18.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_compressed_texture_es3</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("46.0")}} [1]</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_compressed_texture_etc1</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("30.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_compressed_texture_pvrtc</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("18.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_compressed_texture_s3tc</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("22.0")}} [2]</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_debug_renderer_info</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("19.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_debug_shaders</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("30.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_depth_texture</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("22.0")}} [2]</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_draw_buffers</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("28.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_lose_context</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("22.0")}} [2]</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>25</td> + <td>{{CompatGeckoMobile("2.0")}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>12</td> + <td>8.0</td> + </tr> + <tr> + <td><code>ANGLE_instanced_arrays</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_blend_minmax</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_color_buffer_half_float</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_disjoint_timer_query</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_frag_depth</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_sRGB</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_shader_texture_lod</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>EXT_texture_filter_anisotropic</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_element_index_uint</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_standard_derivatives</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_texture_float</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_texture_float_linear</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_texture_half_float</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_texture_half_float_linear</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>OES_vertex_array_object</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_color_buffer_float</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_compressed_texture_atc</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_compressed_texture_etc1</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_compressed_texture_s3tc</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_compressed_texture_pvrtc</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_compressed_texture_s3tc</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_debug_renderer_info</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_debug_shaders</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_depth_texture</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_draw_buffers</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td><code>WEBGL_lose_context</code></td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<p>[1] Toggling the <code>webgl.enable-draft-extensions</code> preference in about:config is required.</p> + +<p>[2] This extension was prefixed with <code>MOZ_</code> in prior versions.</p> + +<h2 id="也可以看看">也可以看看</h2> + +<ul> + <li>{{domxref("WebGLRenderingContext.getSupportedExtensions()")}}</li> + <li>{{domxref("WebGLRenderingContext.getExtension()")}}</li> + <li><a class="external external-icon" href="http://webglreport.com">webglreport.com</a></li> + <li><a href="http://webglstats.com">webglstats.com</a></li> +</ul> diff --git a/files/zh-cn/web/api/webgl_api/webgl_best_practices/index.html b/files/zh-cn/web/api/webgl_api/webgl_best_practices/index.html new file mode 100644 index 0000000000..65072d91a0 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/webgl_best_practices/index.html @@ -0,0 +1,48 @@ +--- +title: WebGL best practices +slug: Web/API/WebGL_API/WebGL_best_practices +tags: + - WebGL best practices +translation_of: Web/API/WebGL_API/WebGL_best_practices +--- +<p>{{WebGLSidebar}}</p> + +<p>WebGL是一个复杂的API,通常我们不能明显的知道它的推荐使用方式。该页面涵盖了各种专业知识的建议,不仅仅是列举出什么该做,什么不该做,还有详细的解释为什么要这样做。你可以将本文档作为指导你选择的方法,确保你无论在何种浏览器以及硬件上都使用了正确的技巧。</p> + +<h2 id="需要避免的事情">需要避免的事情</h2> + +<ul> + <li>确保应用程序运行时不会产生任何WebGL错误(如getError()返回的). In Firefox, every WebGL error (until a certain limit), and some other WebGL issues, are reported as a JavaScript warning with a descriptive message. 在 Firefox 中,所有 WebGL 错误(直至超出数量限制)以及其它一些 WebGL 问题,都会以一段提供描述的 JavaScript 警告报告出来。你不想自己的应用在用户的控制台打印出一堆东西对吧?你当然不想了。</li> + <li>你应该永远不去触碰 WebGL shader 里的 <code>#ifdef GL_ES </code>;虽然前边的一些例子使用了这个,这并无必要,因为这个条件判断在 WebGL shader 中始终为 true。</li> + <li>在 fragment shader 中使用 <code>highp</code> 精度将阻碍你的内容在某些旧的移动设备上正确运行。这里,你可以使用 <code>mediump</code>;但是,你需要知道,由于在大多移动设备上的精度丢失,这经常导致渲染失败,这在典型的 PC 机型上没有问题。通常来说,在vertex 和 fragment shader 中仅使用 <code>highp</code> ,除非 shaders 通过了各大平台的测试。从 Firefox 11 开始,WebGL 的 <code>getShaderPrecisionFormat()</code> 函数的实现,允许你判断 <code>highp</code> 是否得到支持,进而允许你可以查询到实际的精度。</li> +</ul> + +<h2 id="需要记住的事情">需要记住的事情</h2> + +<ul> + <li>Some WebGL capabilities depend on the client. Before relying on them, you should use the WebGL <code>getParameter()</code> function to determine what values are supported on the client. For example, the maximum size of a 2D texture is given by <code>webgl.getParameter(webgl.MAX_TEXTURE_SIZE)</code>. Starting in Firefox 10, the <code>webgl.min_capability_mode</code> preference allows simulating minimal values for these capabilities, to test portability.</li> + <li>In particular, note that usage of textures in vertex shaders is only possible if <code>webgl.getParameter(webgl.MAX_VERTEX_TEXTURE_IMAGE_UNITS)</code> is greater than zero. Typically, this fails on current mobile hardware.</li> + <li>The availability of most WebGL extensions depends on the client. When using WebGL extensions, if possible, try to make them optional by gracefully adapting to the case there they are not supported. Starting in Firefox 10, the <code>webgl.disable-extensions</code> preference allows simulating the absence of all extensions, to test portability.</li> + <li>Rendering to a floating-point texture may not be supported, even if the <code>OES_texture_float</code> extension is supported. Typically, this fails on current mobile hardware. To check if this is supported, you have to call the WebGL <code>checkFramebufferStatus()</code> function.</li> + <li>Rendering to a canvas can be done at a different resolution than the style sheet will eventually force the canvas to appear at. If struggling with performance you should consider rendering to a low resolution WebGL context and using CSS to upscale its canvas to the size you intend.</li> +</ul> + +<h2 id="一般性能提示">一般性能提示</h2> + +<ul> + <li>Anything that requires syncing the CPU and GPU sides is potentially very slow, so if possible you should try to avoid doing that in your main rendering loops. This includes the following WebGL calls: <code>getError()</code>, <code>readPixels()</code>, and <code>finish()</code>. WebGL getter calls such as <code>getParameter()</code> and <code>getUniformLocation()</code> should be considered slow too, so try to cache their results in a JavaScript variable.</li> + <li>Fewer, larger draw operations will improve performance. If you have 1000 sprites to paint, try to do it as a single <code>drawArrays()</code> or <code>drawElements()</code> call. You can draw degenerate (flat) triangles if you need to draw discontinuous objects as a single <code>drawArrays()</code> call.</li> + <li>Fewer state changes will also improve performance. In particular, if you can pack multiple images into a single texture and select them by using the appropriate texture coordinates, that can help you do fewer texture binding changes, which improves performance. + <ul> + <li>In some rare cases, packing greyscale textures which belong together into the color channels of a single texture might help.</li> + </ul> + </li> + <li>Smaller textures perform better than larger ones. For this reason, mipmapping can be a performance win.</li> + <li>Simpler shaders perform better than complex ones. In particular, if you can remove an <code>if</code> statement from a shader, that will make it run faster. Division and math functions like <code>log()</code> should be considered expensive too. + <ul> + <li>However, nowadays even mobile devices possess powerful GPUs that are capable of running even relatively complex shader programs. Moreover, because shaders are compiled, the eventual machine code that actually runs on the hardware may be highly optimized. What may seem like an expensive function call may in fact compile into only few (or even a single) machine instructions. This is particularly true for {{Glossary("GLSL")}} functions that typically operate on vectors, such as <code>normalize()</code>, <code>dot()</code> and <code>mix()</code>. The best advice in that regard is to use the built-in functions, rather than try to implement, for example, one's own version of a dot-product or linear interpolation, which may in fact compile to larger and less optimized machine code. Finally, it is important to keep in mind that GPUs are constructed to do complex mathematical calculations in hardware, and therefore, may support math functions, such as <code>sin()</code>, <code>cos()</code> and other, through dedicated machine instructions.</li> + </ul> + </li> + <li>Do as much as you can in the vertex shader, rather than in the fragment shader. Because, per rendering pass, fragment shaders run many more times than vertex shaders, any calculation that can be done on the vertices and then just interpolated among fragments is a performance boon (this interpolation is done "automagically" for you, through the fixed functionality rasterization phase of the OpenGL pipeline). For example, a simple animation of a textured surface can be achieved through a time-dependent transformation of texture coordinates (simplest case is to add a uniform vector to the texture coordinates attribute vector). If visually acceptable, one can transform the texture coordinates in the vertex shader rather than in the fragment shader, to get better performance.</li> + <li>Always have vertex attrib 0 array enabled. If you draw with vertex attrib 0 array disabled, you will force the browser to do complicated emulation when running on desktop OpenGL (e.g. on Mac OSX). This is because in desktop OpenGL, nothing gets drawn if vertex attrib 0 is not array-enabled. You can use <code>bindAttribLocation()</code> to force a vertex attribute to use location <code>0</code>, and use <code>enableVertexAttribArray()</code> to make it array-enabled.</li> +</ul> diff --git a/files/zh-cn/web/api/webgl_api/webgl_model_view_projection/index.html b/files/zh-cn/web/api/webgl_api/webgl_model_view_projection/index.html new file mode 100644 index 0000000000..20804af827 --- /dev/null +++ b/files/zh-cn/web/api/webgl_api/webgl_model_view_projection/index.html @@ -0,0 +1,690 @@ +--- +title: WebGL model view projection +slug: Web/API/WebGL_API/WebGL_model_view_projection +translation_of: Web/API/WebGL_API/WebGL_model_view_projection +--- +<p>{{WebGLSidebar}}</p> + +<p class="summary">本文探讨如何在WebGL项目中获取数据,并将其投影到适当的空间以在屏幕上显示。 它假定了你具备用于平移,缩放和旋转的基本矩阵数学知识。它解释了组成3D场景时通常使用的三个核心矩阵:模型,视图和投影矩阵。</p> + +<div class="note"> +<p><strong>注意: </strong>本文还可作为 <a href="https://github.com/TatumCreative/mdn-model-view-projection">MDN 内容套件</a> 提供。它还使用 <code>MDN</code>全局对象下可用的 <a href="https://github.com/TatumCreative/mdn-webgl">实用函数</a> 集合。</p> +</div> + +<h2 id="模型、视图、投影矩阵">模型、视图、投影矩阵</h2> + +<p>WebGL空间中的点和多边形的个体转化由基本的转换矩阵(例如平移,缩放和旋转)处理。可以将这些矩阵组合在一起并以特殊方式分组,以使其用于渲染复杂的3D场景。这些组合成的矩阵最终将原始数据类型移动到一个称为裁剪空间的特殊坐标空间中。这是一个中心点位于(0, 0, 0),角落范围在 (-1, -1, -1) 到 (1, 1, 1) 之间,2个单位宽的立方体。该剪裁空间被压缩到一个二维空间并栅格化为图像。</p> + +<p>下面讨论的第一个矩阵是<strong>模型矩阵</strong>,它定义了如何获取原始模型数据并将其在3D世界空间中移动。<strong>投影矩阵</strong>用于将世界空间坐标转换为剪裁空间坐标。常用的投影矩阵(<strong>透视矩阵</strong>)用于模拟充当3D虚拟世界中观看者的替身的典型相机的效果。<strong>视图矩阵</strong>负责移动场景中的对象以模拟相机位置的变化,改变观察者当前能够看到的内容。</p> + +<p>以下的几个部分提供了对模型,视图和投影矩阵背后的思想及实现的深入理解。这些矩阵是在屏幕上移动数据的核心,是胜过各个框架和引擎的概念。</p> + +<h2 id="裁剪空间">裁剪空间</h2> + +<p>在WebGL程序中,数据通常上传到具有自己的坐标系统的GPU上,然后顶点着色器将这些点转换到一个称为<strong>裁剪空间</strong>的特殊坐标系上。延展到裁剪空间之外的任何数据都会被剪裁并且不会被渲染。如果一个三角形超出了该空间的边界,则将其裁切成新的三角形,并且仅保留新三角形在裁剪空间中的部分。</p> + +<p><img alt="A 3d graph showing clip space in WebGL." src="https://mdn.mozillademos.org/files/11371/clip-space-graph.svg" style="height: 432px; width: 500px;"></p> + +<p>上面的图像裁剪空间的可视化,所有点都必须被包含在其中。它是一个角在(-1, -1, -1),对角在 (1, 1, 1),中心点在 (0, 0, 0) 的每边2个单位的立方体。裁剪空间使用的这个两个立方米坐标系称为归一化设备坐标(NDC)。在研究和使用WebGL代码时,你可能时不时的会使用这个术语。</p> + +<p>在本节中,我们将直接将数据放入裁剪空间坐标系中。通常使用位于任意坐标系中的模型数据,然后使用矩阵进行转换,将模型坐标转换为裁剪空间系下的坐标。这个例子,通过简单地使用从 (-1,-1,-1) 到 (1,1,1) 的模型坐标值来说明剪辑空间的工作方式是最简单的。下面的代码将创建2个三角形,这些三角形将在屏幕上绘制一个正方形。正方形中的Z深度确定当前正方形共享同一个空间时在顶部绘制的内容,较小的Z值将呈现在较大的Z值之上。</p> + +<h3 id="WebGLBox_例子">WebGLBox 例子</h3> + +<p>本示例将创建一个自定义WebGL对象,该对象将在屏幕上绘制一个2D框。</p> + +<div class="note"> +<p><strong>注意</strong>: 每一个WebGL示例代码在此 <a href="https://github.com/TatumCreative/mdn-model-view-projection/tree/master/lessons">github repo</a> 中可找到,并按章节组织。此外,每个章节底部都有一个 JSFiddle 链接。</p> +</div> + +<h4 id="WebGLBox_Constructor">WebGLBox Constructor</h4> + +<p>构造函数看起来像这样:</p> + +<pre class="brush: js">function WebGLBox() { + + // 设置 canvas 和 WebGL 上下文 + this.canvas = document.getElementById('canvas'); + this.canvas.width = window.innerWidth; + this.canvas.height = window.innerHeight; + this.gl = MDN.createContext(canvas); + + var gl = this.gl; + + // 设置一个WebGL程序,任何MDN对象相关的部分在本文之外定义 + this.webglProgram = MDN.createWebGLProgramFromIds(gl, 'vertex-shader', 'fragment-shader'); + gl.useProgram(this.webglProgram); + + // 保存 attribute 和 uniform 位置 + this.positionLocation = gl.getAttribLocation(this.webglProgram, 'position'); + this.colorLocation = gl.getUniformLocation(this.webglProgram, 'color'); + + // 告诉WebGL在绘制时测试深度,所以如果一个正方形后面有另一个正方形 + // 另一个正方形不会被绘制 + gl.enable(gl.DEPTH_TEST); + +} +</pre> + +<h4 id="WebGLBox_绘制">WebGLBox 绘制</h4> + +<p>现在,我们将创建一个在屏幕上绘制框的方法。</p> + +<pre class="brush: js">WebGLBox.prototype.draw = function(settings) { + + // 创建一下 attribute 数据; 这些是最终绘制到屏幕上的三角形 + // 有两个形成一个正方形 + + var data = new Float32Array([ + + //Triangle 1 + settings.left, settings.bottom, settings.depth, + settings.right, settings.bottom, settings.depth, + settings.left, settings.top, settings.depth, + + //Triangle 2 + settings.left, settings.top, settings.depth, + settings.right, settings.bottom, settings.depth, + settings.right, settings.top, settings.depth + ]); + + // 使用 WebGL 将其绘制到屏幕上 + + // 性能要点:为每个绘制创建新的缓冲器很慢 + // 这个方法仅用于说明 + + var gl = this.gl; + + // 创建一个缓冲区并绑定数据 + var buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW); + + // 设置指向 attribute 数据的指针(三角形) + gl.enableVertexAttribArray(this.positionLocation); + gl.vertexAttribPointer(this.positionLocation, 3, gl.FLOAT, false, 0, 0); + + // 设置将在所有三角形之间共享的 color uniform + gl.uniform4fv(this.colorLocation, settings.color); + + // 在屏幕上绘制该三角形 + gl.drawArrays(gl.TRIANGLES, 0, 6); +} +</pre> + +<p>着色器是用GLSL编写的代码片段,它接收我们的点数据并最终将它们渲染到屏幕上。为了方便起见,这些着色器存储在 {{htmlelement("script")}} 元素之中,该元素通过自定义函数 <code>MDN.createWebGLProgramFromIds()</code> 引入程序中。这个方法是为这些教程编写的 <a href="https://github.com/TatumCreative/mdn-webgl">实用函数</a> 集合的一部分,此处不再赘述。此函数用于处理获取一些GLSL源代码并将其编译为WebGL程序的基础操作。该函数具有三个参数-用于渲染程序的上下文,包含顶点着色器的 {{htmlelement("script")}} 元素的ID和包含片段着色器的 {{htmlelement("script")}} 元素的ID。顶点着色器放置顶点,片段着色器为每个像素着色。</p> + +<p>首先看一下将在屏幕上移动顶点的顶点着色器:</p> + +<pre class="brush: glsl">// 一个顶点位置 +attribute vec3 position; + +void main() { + + // gl_Position 是顶点着色器对其修改后在裁剪空间的最终位置 + gl_Position = vec4(position, 1.0); +} +</pre> + +<p>接下来,要实际将数据栅格化为像素,片段着色器将在每个像素的基础上计算评估一切,设置一个单一颜色。GPU为需要渲染的每个像素调用着色器方法。着色器的工作是返回要用于该像素的颜色。</p> + +<pre class="brush: glsl">precision mediump float; +uniform vec4 color; + +void main() { + gl_FragColor = color; +} +</pre> + +<p>有了这些设置,是时候使用裁剪空间坐标直接绘制到屏幕了。</p> + +<pre class="brush: js">var box = new WebGLBox(); +</pre> + +<p>首先在中间画一个红色框。</p> + +<pre class="brush: js">box.draw({ + + top : 0.5, // x + bottom : -0.5, // x + left : -0.5, // y + right : 0.5, // y + + depth : 0, // z + color : [1, 0.4, 0.4, 1] // red +}); +</pre> + +<p>接下来,在上面的红色框的后面绘制一个绿色框。</p> + +<pre class="brush: js">box.draw({ + + top : 0.9, // x + bottom : 0, // x + left : -0.9, // y + right : 0.9, // y + + depth : 0.5, // z + color : [0.4, 1, 0.4, 1] // green +}); +</pre> + +<p>最后,为了演示裁剪实际上发生了,这个框没有被绘制,因为它完全在裁剪空间之外,深度超出 -1.0 到 1.0 的范围。</p> + +<pre class="brush: js">box.draw({ + + top : 1, // x + bottom : -1, // x + left : -1, // y + right : 1, // y + + depth : -1.5, // z + color : [0.4, 0.4, 1, 1] // blue +}); +</pre> + +<h4 id="结果">结果</h4> + +<p><a href="https://jsfiddle.net/2x03hdc8">在JSFiddle中查看</a></p> + +<p><img alt="The results of drawing to clip space using WebGL." src="https://mdn.mozillademos.org/files/11373/part1.png" style="height: 530px; width: 800px;"></p> + +<h4 id="练习">练习</h4> + +<p>在这一点上一个有用的练习是通过更改代码来使框在裁剪空间中移动,感受点是如何在裁剪空间中被剪切和移动的。尝试画一张有背景的方形笑脸。</p> + +<h2 id="齐次坐标">齐次坐标</h2> + +<p>之前的裁剪空间顶点着色器主要包含以下代码:</p> + +<pre class="brush: js">gl_Position = vec4(position, 1.0); +</pre> + +<p>位置变量是在 <code>draw()</code> 方法中定义的,并作为 attribute 传递给着色器。这是一个三维点,但最终通过管线传递的 <code>gl_Position</code> 变量实际上是四维的 - 是 <code>(x,y,z,w)</code> 而不是 <code>(x,y,z)</code> 。 <code>z</code> 后面没有字母了,因此习惯上将第四维标记为 <code>w</code>。在上面的示例中, <code>w</code> 坐标设置为1.0。</p> + +<p>显而易见的问题是:“为什么要增加维度?”。事实证明,这种增加允许使用许多不错的技术来处理3D数据。这个增加的维度将透视的概念引入坐标系中。将其放置在适当的位置后,我们可以将3D坐标映射到2D空间中,从而允许两条平行线当它们延伸到远方时相交。 <code>w</code> 的值被用作该坐标的其他分量放除数,因此 <code>x</code>, <code>y</code> 和 <code>z</code> 的真实值被计算为 <code>x/w</code> , <code>y/w</code> 和 <code>z/w</code>(然后 <code>w</code> 也 <code>w/w</code> , 变成1)。</p> + +<p>三维点定义在典型的笛卡尔坐标系中。增加的第四维将这一点变为 {{interwiki("wikipedia", "homogeneous coordinates", "齐次坐标")}} 。它仍然代表3D空间中的一个点,并且可以通过一对简单的函数轻松地演示如何构造这种类型的坐标。</p> + +<pre class="brush: js">function cartesianToHomogeneous(point) { + + var x = point[0]; + var y = point[1]; + var z = point[2]; + + return [x, y, z, 1]; +} + +function homogeneousToCartesian(point) { + + var x = point[0]; + var y = point[1]; + var z = point[2]; + var w = point[3]; + + return [x/w, y/w, z/w]; +} +</pre> + +<p>正如前面提到的和上面展示的函数,w 分量将和 x, y 和z相除。当 w 分量为非零实数时,齐次坐标很容易转换回笛卡尔空间中。现在,如果 w 分量为零会发生什么?在JavaScript 中,返回值如下:</p> + +<pre class="brush: js">homogeneousToCartesian([10, 4, 5, 0]); +</pre> + +<p>计算结果为: <code>[Infinity, Infinity, Infinity]</code>.</p> + +<p>该齐次坐标表示无穷大的某个点。这是一种方便的方式表示从原点向特定方向发射的射线。除了射线,还可以将其视为方向矢量的表示。如果将此齐次坐标和带有平移的矩阵相乘,则该平移将被有效地消去了。</p> + +<p>当计算机上的数字非常大(或非常小)时,它们的精确度将越来越低,因为仅用这么多的“1”和“0”来表示它们。对较大的数字执行的操作越多,结果中就会积累越来越多的错误。当除以 w 时,这可以通过两个可能更小,更不易出错的数字进行运算来有效地提高非常大的数字的精度。</p> + +<p>使用齐次坐标的最终好处是,它们非常适合与4x4矩阵相乘。一个顶点必须至少与矩阵的一个维数(行/列)匹配,才能与其相乘。4x4矩阵可用于编码各种转换。实际上,典型的透视矩阵使用 w 分量除法来实现其变换。</p> + +<p>实际上,在将齐次坐标转换回笛卡尔坐标之后(通过除以w),会发生从裁剪空间中裁剪点和多边形的情况。该最终空间称为<strong>归一化设备坐标</strong>或NDC。</p> + +<p>为了开始使用这个思想,可以修改前面的示例,以允许使用 <code>w</code> 分量。</p> + +<pre class="brush: js">// 重新定义三角形以使用 W 分量 +var data = new Float32Array([ + + //Triangle 1 + settings.left, settings.bottom, settings.depth, settings.w, + settings.right, settings.bottom, settings.depth, settings.w, + settings.left, settings.top, settings.depth, settings.w, + + //Triangle 2 + settings.left, settings.top, settings.depth, settings.w, + settings.right, settings.bottom, settings.depth, settings.w, + settings.right, settings.top, settings.depth, settings.w +]); +</pre> + +<p>然后,顶点着色器使用传入的4维点。</p> + +<pre class="brush: js">attribute vec4 position; + +void main() { + gl_Position = position; +} +</pre> + +<p>首先,我们在中间绘制一个红色框,但将 W 设置为 0.7。但坐标除以0.7时,它们全部会被放大。</p> + +<pre class="brush: js">box.draw({ + + top : 0.5, // x + bottom : -0.5, // x + left : -0.5, // y + right : 0.5, // y + w : 0.7, // w - 放大这个盒子 + + depth : 0, // z + color : [1, 0.4, 0.4, 1] // red +}); +</pre> + +<p>现在,我们在上面绘制一个绿色框,但是通过将 w 分量设置为 1.1 来缩小它。</p> + +<pre class="brush: js">box.draw({ + + top : 0.9, // x + bottom : 0, // x + left : -0.9, // y + right : 0.9, // y + w : 1.1, // w - 缩小这个盒子 + + depth : 0.5, // z + color : [0.4, 1, 0.4, 1] // green +}); +</pre> + +<p>最后一个框未被绘制,因为它在裁剪空间之外。深度超出 -1.0 到 1.0 范围。</p> + +<pre class="brush: js">box.draw({ + + top : 1, // x + bottom : -1, // x + left : -1, // y + right : 1, // y + w : 1.5, // w - 把这个盒子带回范围内 + + depth : -1.5, // z + color : [0.4, 0.4, 1, 1] // blue +}); +</pre> + +<h3 id="结果_2">结果</h3> + +<p><a href="https://jsfiddle.net/mff99yu">在JSFiddle中查看</a></p> + +<h3 id="sect1"><img alt="The results of using homogeneous coordinates to move the boxes around in WebGL." src="https://mdn.mozillademos.org/files/11375/part2.png" style="height: 530px; width: 800px;"></h3> + +<h3 id="练习_2">练习</h3> + +<ul> + <li>尝试使用这些值,看看它们如何影响屏幕上渲染的内容。请注意如何通过设置其 w 分量将先前裁剪的蓝色框带回带范围内。</li> + <li>尝试创建一个在裁剪空间之外的新框,然后将其除以 w,将其返回裁剪空间。</li> +</ul> + +<h2 id="模型转换">模型转换</h2> + +<p>将点直接放入裁剪空间的用途有限。在现实世界的应用程序中,你拥有的源坐标不全部在裁剪空间中。因此大多数时候,你需要将模型数据和其他坐标转换到裁剪空间中。简单的立方体就是一个如何执行此操作的简单示例。立方体数据由顶点位置,立方体表面颜色和构成单个多边形的顶点位置的顺序组成(以3个顶点为一组,以构成立方体表面的三角形)。这些位置和颜色存储在GL缓冲区中,作为属性发到着色器,然后分别进行操作。</p> + +<p>最后,计算并设置单个模型矩阵。该矩阵表示要在组成模型的每个点上执行的转换,以将其移到正确的空间,并在模型中的每个点上执行任何其他所需的转换。这不仅适用于每一个顶点,而且还适用于模型每个表面的每个点。</p> + +<p>在这种情况下,对于动画的每一帧,一系列缩放,旋转和平移矩阵会将数据移动到裁剪空间中所需的位置。这个立方体是裁剪空间(-1, -1, -1) 到 (1, 1, 1)的大小,因此需要缩小以不填满整个裁剪空间。该矩阵事先已经在JavaScript中进行了乘法运算,直接发到着色器。</p> + +<p>以下代码示例在 <code>CubeDemo</code> 对象上定义了一个创建模型矩阵的方法。它使用了自定义函数来创建和乘以 <a href="https://github.com/TatumCreative/mdn-webgl">MDN WebGL</a> 共享代码中定义的矩阵。新的函数如下:</p> + +<pre class="brush: js">CubeDemo.prototype.computeModelMatrix = function(now) { + + // 缩小50% + var scale = MDN.scaleMatrix(0.5, 0.5, 0.5); + + // 轻微旋转 + var rotateX = MDN.rotateXMatrix(now * 0.0003); + + // 根据时间旋转 + var rotateY = MDN.rotateYMatrix(now * 0.0005); + + // 稍微向下移动 + var position = MDN.translateMatrix(0, -0.1, 0); + + // 相乘,确定以相反的顺序读取它们 + this.transforms.model = MDN.multiplyArrayOfMatrices([ + position, // step 4 + rotateY, // step 3 + rotateX, // step 2 + scale // step 1 + ]); +}; +</pre> + +<p>为了在着色器中使用它,必须将其设置在 uniforms 的位置。uniforms 的位置保存在 <code>locations</code> 对象中,如下所示:</p> + +<pre class="brush: js">this.locations.model = gl.getUniformLocation(webglProgram, 'model'); +</pre> + +<p>最后,将 uniforms 设置在那个位置,这就把矩阵交给了GPU。</p> + +<pre class="brush: js">gl.uniformMatrix4fv(this.locations.model, false, new Float32Array(this.transforms.model)); +</pre> + +<p>在着色器中,每个位置顶点首先被转换为齐次坐标(vec4对象),然后与模型矩阵相乘。</p> + +<pre class="brush: glsl">gl_Position = model * vec4(position, 1.0); +</pre> + +<div class="note"> +<p><strong>注意</strong>: 在 JavaScript 中,矩阵乘法需要自定义函数,而在着色器中,它使用了内置在语言中的简单的 * 运算。</p> +</div> + +<h3 id="结果_3">结果</h3> + +<p><a href="https://jsfiddle.net/5jofzgsh">在JSFiddle中查看</a></p> + +<p><img alt="Using a model matrix" src="https://mdn.mozillademos.org/files/11377/part3.png" style="height: 530px; width: 800px;"></p> + +<p>此时,变换点的w值仍为1.0。立方体仍然没有什么角度。下一节将进行此设置并修改w值以提供一些透视效果。</p> + +<h3 id="练习_3">练习</h3> + +<ul> + <li>使用缩放矩阵缩小立方体,并将其放置在裁剪空间中不同位置。</li> + <li>尝试将其移到裁剪空间之外。</li> + <li>调整窗口大小,然后观察盒子的变形情况。</li> + <li>添加一个 <code>rotateZ</code> 。</li> +</ul> + +<h2 id="除以_W">除以 W</h2> + +<p>一个开始了解立方体模型透视的简单方法是获取Z坐标并将其复制到w坐标。通常,将笛卡尔点转换为齐次坐标时,它变为 <code>(x,y,z,1)</code> ,但我们将其设置为 <code>(x,y,z,z)</code> 。实际上,我们希望确保视图中的点的z值大于0,因此我们将其值改为 <code>((1.0 + z) * scaleFactor)</code> 对其进行轻微的修改。这将需要一个通常位于裁剪空间(-1到1)中的点,并将其移到更像(0到1)的空间中,具体取决于比例因子设置为什么。比例因子将最终w值更改为总体上更高或更低。</p> + +<p>着色器代码如下:</p> + +<pre class="brush: js">// 首先转换点 +vec4 transformedPosition = model * vec4(position, 1.0); + +// 透视有多大的影响? +float scaleFactor = 0.5; + +// 通过采用介于-1到1之间的z值来设置w +// 然后进行缩放为0到某个数,在这种情况下为0到1 +float w = (1.0 + transformedPosition.z) * scaleFactor; + +// 使用自定义w分量保存新的 gl_Position +gl_Position = vec4(transformedPosition.xyz, w); +</pre> + +<h3 id="结果_4">结果</h3> + +<p><a href="https://jsfiddle.net/vk9r8h2c">在JSFiddle中查看</a></p> + +<p><img alt="Filling the W component and creating some projection." src="https://mdn.mozillademos.org/files/11379/part4.png" style="height: 531px; width: 800px;"></p> + +<p>看到那个深蓝色的小三角形吗?那是添加到对象上的另一个面,因为形状的旋转导致了该角延伸到裁剪空间之外,从而导致该角被裁剪掉。有关如何使用更复杂的矩阵来帮助控制和防止裁剪的介绍,请参照下面的 {{anch("Perspective matrix")}}。</p> + +<h3 id="练习_4">练习</h3> + +<p>如果这听起来有点抽象,请打开顶点着色器,然后使用比例因子,观察其如何将顶点向表面进一步收缩。完全更改w分量的值,以表示真实空间。</p> + +<p>在下一节中,我们将执行把Z值复制到w插槽并将其转换为矩阵的步骤。</p> + +<h2 id="简单投影">简单投影</h2> + +<p>填充w分量的最后一步实际上可以用一个简单的矩阵完成。从 identity 矩阵开始:</p> + +<pre class="brush: js">var identity = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, +]; + +MDN.multiplyPoint(identity, [2, 3, 4, 1]); +//> [2, 3, 4, 1] +</pre> + +<p>然后将最后一列的 1 向上移动一个空格。</p> + +<pre class="brush: js">var copyZ = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 1, + 0, 0, 0, 0, +]; + +MDN.multiplyPoint(copyZ, [2, 3, 4, 1]); +//> [2, 3, 4, 4] +</pre> + +<p>但是,在最后一个示例中,我们执行了 <code>(z + 1) * scaleFactor</code>:</p> + +<pre>var scaleFactor = 0.5; + +var simpleProjection = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, scaleFactor, + 0, 0, 0, scaleFactor, +]; + +MDN.multiplyPoint(simpleProjection, [2, 3, 4, 1]); +//> [2, 3, 4, 2.5] +</pre> + +<p>进一步展开我们可以看到它是如何工作的:</p> + +<pre class="brush: js">var x = (2 * 1) + (3 * 0) + (4 * 0) + (1 * 0) +var y = (2 * 0) + (3 * 1) + (4 * 0) + (1 * 0) +var z = (2 * 0) + (3 * 0) + (4 * 1) + (1 * 0) +var w = (2 * 0) + (3 * 0) + (4 * scaleFactor) + (1 * scaleFactor) +</pre> + +<p>最后一行可以简化为:</p> + +<pre class="brush: js">w = (4 * scaleFactor) + (1 * scaleFactor) +</pre> + +<p>然后将 scaleFactor 提取出来,我们得到:</p> + +<pre class="brush: js">w = (4 + 1) * scaleFactor +</pre> + +<p>这与我们在前面示例中使用的 <code>(z + 1) * scaleFactor</code> 完全相同。</p> + +<p>在 box demo中,添加了一个额外的 <code>.computeSimpleProjectionMatrix()</code> 方法。在 <code>.draw()</code> 方法中调用,并将比例因子传递给它。结果应该与上一个示例相同:</p> + +<pre class="brush: js">CubeDemo.prototype.computeSimpleProjectionMatrix = function(scaleFactor) { + + this.transforms.projection = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, scaleFactor, + 0, 0, 0, scaleFactor + ]; + +}; +</pre> + +<p>尽管结果相同,但重要的步骤还是在顶点着色器中。与其直接修改顶点,不如将其乘以一个附加的 <strong>{{anch("Projection matrix", "projection matrix")}}</strong>,该矩阵将3D点投影到2D绘图表面上:</p> + +<pre class="brush: glsl">// 确保以相反的顺序读取转换矩阵 +gl_Position = projection * model * vec4(position, 1.0); +</pre> + +<h3 id="结果_5">结果</h3> + +<p><a href="https://jsfiddle.net/zwyLLcbw">在JSFiddle中查看</a></p> + +<p><img alt="A simple projection matrix" src="https://mdn.mozillademos.org/files/11381/part5.png" style="height: 531px; width: 800px;"></p> + +<h2 id="透视矩阵">透视矩阵</h2> + +<p>至此,我们逐步构建了自己的3D渲染设置。但是,我们当前构建的代码存在一些问题。首先,每当我们调整窗口大小时,它就会倾斜。另外是我们的简单投影无法处理场景数据的大范围值。大多数场景在裁剪空间中不起作用。定义与场景相关的距离是很有帮助的,这样在转换数字时不会损失精度。最后,对哪些点放在裁剪空间的内部和外部进行精度控制非常有帮助。在前面的例子中,立方体的角偶尔会被裁剪。</p> + +<p>透视矩阵是一种可以满足这些要求的投影矩阵。也开始涉及数学更多的内容,这些示例中将不做充分解释。简而言之,它结合了除以w(与前面的例子相同)和基于 <a href="https://en.wikipedia.org/wiki/Similarity_%28geometry%29">相似三角形</a> 相似三角形的一些巧妙操作。如果你想阅读有关其背后数学的完整说明,请查看以下一些链接:</p> + +<ul> + <li><a href="http://www.songho.ca/opengl/gl_projectionmatrix.html">OpenGL投影矩阵</a></li> + <li><a href="http://ogldev.atspace.co.uk/www/tutorial12/tutorial12.html">透视投影</a></li> + <li><a href="http://stackoverflow.com/questions/28286057/trying-to-understand-the-math-behind-the-perspective-matrix-in-webgl/28301213#28301213">尝试了解WebGL中透视矩阵背后的数学</a></li> +</ul> + +<p>关于下面使用的透视矩阵,需要注意的一件重要的事是它会翻转z轴。在裁剪空间中,z+原理观察者,而使用此矩阵,它朝向观察者。</p> + +<p>翻转z轴的原因是,裁剪空间坐标系是左手坐标系(z轴指向远离观察者并指入屏幕的位置),而数学,物理学和3D建模中的惯例与OpenGL中视图/眼睛坐标系一样,是使用右手坐标系(z轴指向屏幕,朝向观察者)。有关的Wikipedia文章的更多信息:<a href="https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness">直角坐标系</a>, <a href="https://en.wikipedia.org/wiki/Right-hand_rule">右手法则</a>。</p> + +<p>让我们看一下 <code>perspectiveMatrix()</code> 函数,该函数计算了透视矩阵。</p> + +<pre class="brush:js">MDN.perspectiveMatrix = function(fieldOfViewInRadians, aspectRatio, near, far) { + + var f = 1.0 / Math.tan(fieldOfViewInRadians / 2); + var rangeInv = 1 / (near - far); + + return [ + f / aspectRatio, 0, 0, 0, + 0, f, 0, 0, + 0, 0, (near + far) * rangeInv, -1, + 0, 0, near * far * rangeInv * 2, 0 + ]; +} +</pre> + +<p>此函数的四个参数是:</p> + +<dl> + <dt><code>fieldOfviewInRadians</code></dt> + <dd>一个以弧度表示的角度,指示观看者一层可以看多少场景。数字越大,摄像机可见的越多。边缘的几何形状变得越来越失真,等同于广角镜。当视野更大时,物体通常会变小。当视野较小时,摄像机在场景中的看到的东西会越来越少。物体因透视而变形的程度要小得多,并且物体似乎更靠近相机。</dd> + <dt><code>aspectRatio</code></dt> + <dd>场景的宽高比,等于其宽度除以其高度。在本示例中,就是窗口的宽度除以窗口的高度。此参数的引入最终解决了当画布调整大小和形状时模型的变形问题。</dd> + <dt><code>nearClippingPlaneDistance</code></dt> + <dd>一个正数,表示到屏幕的距离是垂直于地板的平面的距离,该距离比将所有内容都裁剪的距离更近。它在裁剪空间中映射为-1,并且不应设置为0。</dd> + <dt><code>farClippingPlaneDistance</code></dt> + <dd>一个正数,表示与平面之间的距离,超出该距离将裁剪几何体。它在裁剪空间中映射为1.该值应保持合理的距离以接近几何图形的距离,以免在渲染时出现精度误差。</dd> + <dd>在最新版本的盒子demo中, <code>computeSimpleProjectionMatrix()</code> 函数已替换为 <code>computePerspectiveMatrix()</code> 函数。</dd> +</dl> + +<pre class="brush: js">CubeDemo.prototype.computePerspectiveMatrix = function() { + + var fieldOfViewInRadians = Math.PI * 0.5; + var aspectRatio = window.innerWidth / window.innerHeight; + var nearClippingPlaneDistance = 1; + var farClippingPlaneDistance = 50; + + this.transforms.projection = MDN.perspectiveMatrix( + fieldOfViewInRadians, + aspectRatio, + nearClippingPlaneDistance, + farClippingPlaneDistance + ); +}; +</pre> + +<p>着色器代码与前面的示例相同:</p> + +<pre class="brush: js">gl_Position = projection * model * vec4(position, 1.0); +</pre> + +<p>此外(未显示),更改了模型的位置和缩放矩阵,以使其脱离裁剪空间并进入更大的坐标系。</p> + +<h3 id="结果_6">结果</h3> + +<p><a href="https://jsfiddle.net/Lzxw7e1q">在JSFiddle中查看</a></p> + +<p><img alt="A true perspective matrix" src="https://mdn.mozillademos.org/files/11383/part6.png" style="height: 531px; width: 800px;"></p> + +<h3 id="练习_5">练习</h3> + +<ul> + <li>使用透视矩阵和模型矩阵的参数进行体验。</li> + <li>将透视矩阵替换为 {{interwiki("wikipedia", "正交矩阵")}}。在MDN WebGL共享代码中可以找到 <code>MDN.orthographicMatrix()</code> 替换 <code>CubeDemo.prototype.computePerspectiveMatrix()</code> 中的 <code>MDN.perspectiveMatrix()</code> 函数。</li> +</ul> + +<h2 id="视图矩阵">视图矩阵</h2> + +<p>尽管某些图形库提供的虚拟相机可以在构成场景时可以定位和指向,但OpenGL(以及扩展的WebGL)却没有。这是视图矩阵的用处。它的作用是平移,旋转和缩放场景中的物体,以使根据观察者的位置和方向将它们放置到正确的位置。</p> + +<h3 id="模拟相机">模拟相机</h3> + +<p>这利用了爱因斯坦狭义相对论的基本理论之一:参考系和相对运动的原理说,从观察者的角度来看,你可以通过将相反的变化应用于场景中的物体来模拟改变观察者的位置和方向。无论哪种方式,结果似乎对于观察者是一样的。</p> + +<p>假设一个位于桌子上的盒子和一个放在一米外的桌子上的相机,它指向盒子,盒子的正面指向相机。然后考虑将相机从盒子中移开,直到2米远(通过在相机的Z值增加1米),然后将其向左滑动10厘米。盒子与相机的距离缩小了一定量,并向右稍微滑动,从而在相机中看起来较小,左侧的一小部分也暴露在相机前。</p> + +<p>现在,让我们重置场景,将盒子放回它的起始点,使相机距离盒子2米,并正对着盒子。但这一次,相机被锁定在桌子上无法移动或旋转。这就是在WebGL中运作的样子。那,我们如何模拟在空间中移动的相机?</p> + +<p>我们没有向后和向左移动相机,而是对盒子应用了逆变换:我们将盒子向后移动1米,然后向右移动10厘米。从两个物体的角度来看,结果是一样的。</p> + +<p><strong><<< insert image(s) here >>></strong></p> + +<p>最后一步是创建<strong>视图矩阵</strong>,该矩阵将转换场景中的对象,以便对它们进行定位以模拟相机当前位置与方向。目前的代码可以在世界空间中移动立方体并投影所有内容以获得透视图,但我们仍然无法移动相机。</p> + +<p>想象一下使用物理摄像机拍摄电影。你可以自由地将相机放到任何你想放置的位置,并对准任何你选择的方向。为了在3D图形中对此进行仿真,我们使用视图矩阵来模拟物理相机的位置和旋转。</p> + +<p>与直接转换模型顶点的模型矩阵不同,视图矩阵会移动一个抽象的相机。实际上,顶点着色器仍然移动的是模型,而“相机”保持在原位。为了使此计算正确,必须使用变换矩阵的逆。逆矩阵实质上是逆转了变换,因此,如果我们向前移动相机,则逆矩阵会导致场景中的物体向后移动。</p> + +<p>以下的 <code>computeViewMatrix()</code> 函数通过向内和向外,向左和向右移动的视图矩阵来激活视图矩阵。</p> + +<pre class="brush: js">CubeDemo.prototype.computeViewMatrix = function(now) { + + var moveInAndOut = 20 * Math.sin(now * 0.002); + var moveLeftAndRight = 15 * Math.sin(now * 0.0017); + + // 各个方向移动相机 + var position = MDN.translateMatrix(moveLeftAndRight, 0, 50 + moveInAndOut ); + + // 相乘,确保以相反的顺序读取它们 + var matrix = MDN.multiplyArrayOfMatrices([ + + // 练习: 旋转相机的视角 + position + ]); + + // 翻转相机的运动操作,因为我们实际上是 + // 移动场景中的几何图形,而不是相机本身 + this.transforms.view = MDN.invertMatrix(matrix); +}; +</pre> + +<p>着色器现在使用三个矩阵。</p> + +<pre class="brush: glsl">gl_Position = projection * view * model * vec4(position, 1.0); +</pre> + +<p>此步骤后,GPU管线将裁剪超出范围的顶点,并将模型向下发送到片段着色器以进行栅格化。</p> + +<h3 id="结果_7">结果</h3> + +<p><a href="https://jsfiddle.net/86fd797g">在JSFiddle中查看</a></p> + +<p><img alt="The view matrix" src="https://mdn.mozillademos.org/files/11385/part7.png" style="height: 531px; width: 800px;"></p> + +<h3 id="相关坐标系">相关坐标系</h3> + +<p>此时,回顾并标记我们使用的各种坐标系是很有用的。首先,在<strong>模型空间</strong>中定义了立方体的顶点。在场景中移动模型。这些顶点需要通过应用模型矩阵转换到<strong>世界空间</strong>。</p> + +<p>模型空间 → 模型矩阵 → 世界空间</p> + +<p>相机尚未执行任何操作,需要再次移动这些点。目前它们在世界空间中,但需要将它们移动到<strong>视图空间</strong>(使用视图矩阵)以表示相机的位置。</p> + +<p>世界空间 → 视图矩阵 → 视图空间</p> + +<p>最后,需要添加<strong>投影</strong>(在我们的示例中是<strong>透视矩阵</strong>),以便将世界坐标映射到裁剪空间。</p> + +<p>视图空间 → 投影矩阵 → 裁剪空间</p> + +<h3 id="练习_6">练习</h3> + +<ul> + <li>在场景中移动相机。</li> + <li>向视图矩阵中添加一些旋转矩阵以四处看看。</li> + <li>最后,跟踪鼠标的位置。使用2个旋转矩阵可以根据用户鼠标在屏幕上的位置上下移动相机。</li> +</ul> + +<p><font face="x-locale-heading-primary, zillaslab, Palatino, Palatino Linotype, x-locale-heading-secondary, serif"><span style="font-size: 37.33327865600586px;"><strong>参见</strong></span></font></p> + + + +<ul> + <li><a href="/en-US/docs/Web/API/WebGL_API">WebGL</a></li> + <li>{{interwiki("wikipedia", "3D projection")}}</li> +</ul> |