Play around with vertex Shader (4) rotationCopy the code
Last time we dealt with stretching and shifting, but this time we’ve dealt with the other and last important operation: rotation.
Rotation:
I’m going to go around each pointThe origin (0, 0)
That isThe center of the canvas
.counterclockwise
Turn aThe Angle
.
Explanation: Point 1: Still do the same operation for each point. Point 2: it must be going around the origin (0,0), remember that, this will keep you from getting dizzy. As for rotating around other points, that's another matter. Point 3: Why must be counterclockwise, because the definition needs to be accurate. You can do this by rotating counterclockwise by a negative Angle.Copy the code
For stretching and translation, it’s easy to get the math right, but rotation is not so obvious. There are many ways for the specific derivation process. Instead of elaborating, the results are given as follows:
A planar point (x, y), around the origin (0, 0) counterclockwise alpha (arc), the point coordinates are: (x, y ') : x = x * cos' (alpha) - y * sin (alpha) y 'sin (alpha) + y = x * * cos (alpha)Copy the code
According to the above formula, and then put all the stretching and shifting in the last lesson together, the overall code is as follows:
<! doctype html> <html> <head> <style> canvas { border: 1px solid #000000; } < / style > < / head > < body > < p > < b > scale value: < / b > < input id = "scalex" type = "range" Max min = "1" = "1" value = "1" step = "0.1" oninput="updatefunc()" /> <b id="scalevaluex">0</b> <input id="scaley" type="range" min="-1" max="1" value="1" Step = "0.1" the oninput = "updatefunc ()" / > < b id = "scalevaluey" > 0 < / b > < / p > < p > < b > offset value: < / b > < input id = "offsetx" Type ="range" min="-1" Max ="1" value="0" step="0.1" onINPUT =" updateFunc ()" /> < id=" offsetValuex ">0</b> <input Id ="offsety" type="range" min="-1" Max ="1" value="0" step="0.1" onINPUT =" updateFunc ()" /> <b id=" offsetValuey "> < / p > < p > < b > rotate value: < / b > < input id = "rotate" type = "range" min = "0" Max = "6.28" value = "0" step = "0.01" oninput="updatefunc()" /> <b id="rotatevalue">0</b> </p> <canvas id="point" style="width:300px; height:300px"> </canvas> <script id="vertex_shader" type="myshader"> // Vertex Shader precision mediump int; precision mediump float; uniform float u_x_scale; uniform float u_x_offset; uniform float u_y_scale; uniform float u_y_offset; uniform float u_rotate; attribute vec2 a_PointVertex; Void main() {gl_Position = vec4(a_PointVertex, 0.0, 1.0); gl_Position.x *= u_x_scale; gl_Position.y *= u_y_scale; float rx = gl_Position.x * cos(u_rotate) - gl_Position.y * sin(u_rotate); float ry = gl_Position.x * sin(u_rotate) + gl_Position.y * cos(u_rotate); gl_Position.x = rx + u_x_offset; gl_Position.y = ry + u_y_offset; Gl_PointSize = 3.0; } </script> <script id="fragment_shader" type="myshader"> // Fragment shader precision mediump int; precision mediump float; Void main() {gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); } </script> <script type="text/javascript"> var pointCanvas = document.getElementById('point'); Var gl = pointCanvas. GetContext ('webgl', {preserveDrawingBuffer: true}); Var pointCount = 0; var pointData = []; for (var idx = 0; idx <= 15; idx++) { for (var idy = 0; idy <= 15 - idx; idy++) { pointCount++; pointData.push(idx / 15); pointData.push(idy / 15); } } // var pointArray = new Float32Array(pointData); var buffer_id; buffer_id = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer_id); gl.bufferData(gl.ARRAY_BUFFER, pointArray, gl.STATIC_DRAW); // var vertex_shader_code = document.getElementById('vertex_shader').textContent; console.log(vertex_shader_code); var vertex_shader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertex_shader, vertex_shader_code); gl.compileShader(vertex_shader); // var fragment_shader_code = document.getElementById('fragment_shader').textContent; var fragment_shader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragment_shader, fragment_shader_code); gl.compileShader(fragment_shader); // var program = gl.createProgram(); gl.attachShader(program, vertex_shader); gl.attachShader(program, fragment_shader); gl.linkProgram(program); gl.useProgram(program); // var a_PointVertex = gl.getAttribLocation(program, 'a_PointVertex'); gl.vertexAttribPointer(a_PointVertex, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(a_PointVertex); // </script> <script> var u_x_offset_loc = gl.getUniformLocation(program, "u_x_offset"); var u_x_scale_loc = gl.getUniformLocation(program, "u_x_scale"); var u_y_offset_loc = gl.getUniformLocation(program, "u_y_offset"); var u_y_scale_loc = gl.getUniformLocation(program, "u_y_scale"); var u_rotate_loc = gl.getUniformLocation(program, "u_rotate"); var scaleDomX = document.getElementById("scalex"); var scaleValueDomX = document.getElementById("scalevaluex"); var scaleDomY = document.getElementById("scaley"); var scaleValueDomY = document.getElementById("scalevaluey"); var offsetDomX = document.getElementById("offsetx"); var offsetValueDomX = document.getElementById("offsetvaluex"); var offsetDomY = document.getElementById("offsety"); var offsetValueDomY = document.getElementById("offsetvaluey"); var rotateDom = document.getElementById("rotate"); var rotateValueDom = document.getElementById("rotatevalue"); function updatefunc() { gl.uniform1f(u_x_scale_loc, parseFloat(scaleDomX.value)); gl.uniform1f(u_y_scale_loc, parseFloat(scaleDomY.value)); gl.uniform1f(u_x_offset_loc, parseFloat(offsetDomX.value)); gl.uniform1f(u_y_offset_loc, parseFloat(offsetDomY.value)); gl.uniform1f(u_rotate_loc, parseFloat(rotateDom.value)); scaleValueDomX.innerText = scaleDomX.value; offsetValueDomX.innerText = offsetDomX.value; scaleValueDomY.innerText = scaleDomY.value; offsetValueDomY.innerText = offsetDomY.value; rotateValueDom.innerText = rotateDom.value; gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.POINTS, 0, pointCount); } updatefunc(); </script> </script> </body> </html>Copy the code
Open the page directly in your browser and it looks like this:
The updated code turns the original data into a triangle. This is for observation purposes.
And then you add oneuniform
variableu_rotate
Is used to receive rotation values. Note that this value is in radians, in the range [0-2*3.14]. Exactly one circle, 360 degrees.
Then look at the Vertex shader as follows:
<script id="vertex_shader" type="myshader"> // Vertex Shader precision mediump int; precision mediump float; uniform float u_x_scale; uniform float u_x_offset; uniform float u_y_scale; uniform float u_y_offset; uniform float u_rotate; attribute vec2 a_PointVertex; Void main() {gl_Position = vec4(a_PointVertex, 0.0, 1.0); gl_Position.x *= u_x_scale; gl_Position.y *= u_y_scale; float rx = gl_Position.x * cos(u_rotate) - gl_Position.y * sin(u_rotate); float ry = gl_Position.x * sin(u_rotate) + gl_Position.y * cos(u_rotate); gl_Position.x = rx + u_x_offset; gl_Position.y = ry + u_y_offset; Gl_PointSize = 3.0; } </script>Copy the code
Notice the order of stretching, rotation, and translation.
- The tensile
- rotating
- translation
This sequence, again for business purposes, is explained in a plain sentence: because we want to stretch, then rotate, then translate.
When I pan it somewhere, and then I rotate it, the rotation doesn’t seem to work as defined
See below:
And obviously, as we slide rotate, all of the points are not going around the origin which is the center of the canvas, they’re going around the right Angle vertex of this triangle.
Why is that?
It’s actually very simple. Stick to the order of these three operations and you will understand everything.
- So the first thing I’m going to do is
scale
Operation, we display the result after this step operation:
As we expected, the coordinates in both directions become0.5 times
.
- Rotate and then give the effect:
At this point, it becomes obvious that it is indeed moving around the center of the canvas.
-
And when you’re done, you’re going to shift it. So it gives you the illusion that when you’re done translating, the center of the rotation becomes some other point.
-
And the truth is: first around the center of rotation, rotation, and then translation!!
With the end of the text, here is the q&ACopy the code
Little Melon melon said: When can we draw something complete, I don’t want to see dots, I want to draw something else.
-
A: The dots are the core. Everything else, like triangles, is actually interpolated. You can interpolate the dots in your mind for a while.
Small melon melon said: next time can still draw point?
- Answer: next class anyway won’t draw triangle, you believe me, 🙃.
Small ya ya said: other people’s courses inside, are so bright ah, colorful.
- Answer: multicolored, see flower eye all……
-