一. 逻辑部分
缩放和平移一样简单。
让我们将位置乘以期望的缩放值,这是前例中的变化部分。
// 这是一段关于缩放区域的一段的代码;<script id="vertex-shader-2d" type="x-shader/x-vertex">attribute vec2 a_position;uniform vec2 u_resolution;uniform vec2 u_translation;uniform vec2 u_rotation;uniform vec2 u_scale;void main() {// 缩放vec2 scaledPosition = a_position * u_scale;// 旋转vec2 rotatedPosition = vec2(scaledPosition.x * u_rotation.y + scaledPosition.y * u_rotation.x,scaledPosition.y * u_rotation.y - scaledPosition.x * u_rotation.x);// 平移vec2 position = rotatedPosition + u_translation;// 然后需要在JavaScript中绘制的地方设置缩放量。...var scaleLocation = gl.getUniformLocation(program, "u_scale");...var scale = [1, 1];...// 绘制场景function drawScene() {...// 设置平移gl.uniform2fv(translationLocation, translation);// 设置旋转gl.uniform2fv(rotationLocation, rotation);// 设置缩放gl.uniform2fv(scaleLocation, scale);// 绘制几何体var primitiveType = gl.TRIANGLES;var offset = 0;var count = 18; // 6 个三角形组成 'F', 每个三角形 3 个点gl.drawArrays(primitiveType, offset, count);}
二. 全部代码
"use strict";function main() {// Get A WebGL context/** @type {HTMLCanvasElement} */var canvas = document.querySelector("#canvas");var gl = canvas.getContext("webgl");if (!gl) {return;}// setup GLSL programvar program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-2d", "fragment-shader-2d"]);// look up where the vertex data needs to go.var positionLocation = gl.getAttribLocation(program, "a_position");// lookup uniformsvar resolutionLocation = gl.getUniformLocation(program, "u_resolution");var colorLocation = gl.getUniformLocation(program, "u_color");var translationLocation = gl.getUniformLocation(program, "u_translation");var rotationLocation = gl.getUniformLocation(program, "u_rotation");var scaleLocation = gl.getUniformLocation(program, "u_scale");// Create a buffer to put positions invar positionBuffer = gl.createBuffer();// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);// Put geometry data into buffersetGeometry(gl);var translation = [100, 150];var rotation = [0, 1];var scale = [1, 1];var color = [Math.random(), Math.random(), Math.random(), 1];drawScene();// Setup a ui.webglLessonsUI.setupSlider("#x", {value: translation[0], slide: updatePosition(0), max: gl.canvas.width });webglLessonsUI.setupSlider("#y", {value: translation[1], slide: updatePosition(1), max: gl.canvas.height});webglLessonsUI.setupSlider("#angle", {slide: updateAngle, max: 360});webglLessonsUI.setupSlider("#scaleX", {value: scale[0], slide: updateScale(0), min: -5, max: 5, step: 0.01, precision: 2});webglLessonsUI.setupSlider("#scaleY", {value: scale[1], slide: updateScale(1), min: -5, max: 5, step: 0.01, precision: 2});function updatePosition(index) {return function(event, ui) {translation[index] = ui.value;drawScene();};}function updateAngle(event, ui) {var angleInDegrees = 360 - ui.value;var angleInRadians = angleInDegrees * Math.PI / 180;rotation[0] = Math.sin(angleInRadians);rotation[1] = Math.cos(angleInRadians);drawScene();}function updateScale(index) {return function(event, ui) {scale[index] = ui.value;drawScene();};}// Draw the scene.function drawScene() {webglUtils.resizeCanvasToDisplaySize(gl.canvas);// Tell WebGL how to convert from clip space to pixelsgl.viewport(0, 0, gl.canvas.width, gl.canvas.height);// Clear the canvas.gl.clear(gl.COLOR_BUFFER_BIT);// Tell it to use our program (pair of shaders)gl.useProgram(program);// Turn on the attributegl.enableVertexAttribArray(positionLocation);// Bind the position buffer.gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)var size = 2; // 2 components per iterationvar type = gl.FLOAT; // the data is 32bit floatsvar normalize = false; // don't normalize the datavar stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next positionvar offset = 0; // start at the beginning of the buffergl.vertexAttribPointer(positionLocation, size, type, normalize, stride, offset);// set the resolutiongl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height);// set the colorgl.uniform4fv(colorLocation, color);// Set the translation.gl.uniform2fv(translationLocation, translation);// Set the rotation.gl.uniform2fv(rotationLocation, rotation);// Set the scale.gl.uniform2fv(scaleLocation, scale);// Draw the geometry.var primitiveType = gl.TRIANGLES;var offset = 0;var count = 18; // 6 triangles in the 'F', 3 points per trianglegl.drawArrays(primitiveType, offset, count);}}// Fill the buffer with the values that define a letter 'F'.function setGeometry(gl) {gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([// left column0, 0,30, 0,0, 150,0, 150,30, 0,30, 150,// top rung30, 0,100, 0,30, 30,30, 30,100, 0,100, 30,// middle rung30, 60,67, 60,30, 90,30, 90,67, 60,67, 90,]),gl.STATIC_DRAW);}main();// html<canvas id="canvas"></canvas><div id="uiContainer"><div id="ui"><div id="x"></div><div id="y"></div><div id="angle"></div><div id="scaleX"></div><div id="scaleY"></div></div></div><!-- vertex shader --><script id="vertex-shader-2d" type="x-shader/x-vertex">attribute vec2 a_position;uniform vec2 u_resolution;uniform vec2 u_translation;uniform vec2 u_rotation;uniform vec2 u_scale;void main() {// Scale the positionvec2 scaledPosition = a_position * u_scale;// Rotate the positionvec2 rotatedPosition = vec2(scaledPosition.x * u_rotation.y + scaledPosition.y * u_rotation.x,scaledPosition.y * u_rotation.y - scaledPosition.x * u_rotation.x);// Add in the translation.vec2 position = rotatedPosition + u_translation;// convert the position from pixels to 0.0 to 1.0vec2 zeroToOne = position / u_resolution;// convert from 0->1 to 0->2vec2 zeroToTwo = zeroToOne * 2.0;// convert from 0->2 to -1->+1 (clipspace)vec2 clipSpace = zeroToTwo - 1.0;gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);}</script><!-- fragment shader --><script id="fragment-shader-2d" type="x-shader/x-fragment">precision mediump float;uniform vec4 u_color;void main() {gl_FragColor = u_color;}</script>https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script><script src="https://webglfundamentals.org/webgl/resources/webgl-lessons-ui.js"></script>
