کاربر:Ebrahim/glsandbox2.js
ظاهر
کدهایی که در این صفحه قرار میدهید، ممکن است حاوی محتوای مخربی باشند که حساب کاربری شما را به خطر میاندازند. اگر با استفاده از دستور «importScript» یا الگوی «نصب اسکریپت کاربری» اسکریپتی را از صفحهای دیگر درونریزی میکنید، دقت داشتهباشید که این کار باعث میشود تا بهطور سیال اسکریپتی را بارگیری کنید که امکان تغییر آن توسط دیگران وجود دارد. اگر از امنیت کدهایی که به این صفحه میافزایید مطمئن نیستید، در قهوهخانهٔ فنی درخواست کمک کنید. هرگاه پیشنمایش تغییراتی که در این صفحه اعمال کردهاید را مشاهده کنید، کد اجرا خواهد شد. |
مستندات این اسکریپت کاربری را میتوان در کاربر:Ebrahim/glsandbox2 قرار داد. |
// Author: [[User:Ebrahim]]
document.getElementById('content').innerHTML = `<canvas id="canvas" width="640" height="480"></canvas>
<br>
<input type="checkbox" id="wireframe" onclick="onlyWireframe = this.checked"></option>
<label for="wireframe">Only wireframe?</label>
<br>
<input type="checkbox" id="rotation" onclick="gl.uniform1f(enableRotation, this.checked)"></option>
<label for="rotation">Rotation?</label>
<br>
Speed: <input id="number" type="number" value="0" onchange="gl.uniform1f(speed, this.value)">`;
var onlyWireframe = false;
var canvas = document.getElementById('canvas');
var gl = canvas.getContext('webgl');
// Build a vertex shader
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, `
precision mediump float;
attribute vec3 pos;
//varying vec3 colour;
uniform float time;
uniform bool enableRotation;
uniform float speed;
void main() {
gl_Position = vec4(
pos.x / 2.0 + sin(time * speed) / 2.0,
pos.y / 2.0 + sin(time * speed * 1.5) / 2.0,
pos.z / 2.0,
1.0
);
if (enableRotation) {
// https://www.cs.helsinki.fi/group/goa/mallinnus/3dtransf/3drot.html
gl_Position *= mat4(
1.0, 0.0, 0.0, 0.0,
0.0, cos(time), sin(time), 0.0,
0.0, -sin(time), cos(time), 0.0,
0.0, 0.0, 0.0, 1.0
);
gl_Position *= mat4(
cos(time), 0.0, -sin(time), 0.0,
0.0, 1.0, 0.0, 0.0,
sin(time), 0.0, cos(time), 0.0,
0.0, 0.0, 0.0, 1.0
);
gl_Position *= mat4(
cos(time), sin(time), 0.0, 0.0,
-sin(time), cos(time), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
);
}
}
`);
gl.compileShader(vertexShader);
// Build a fragment shader
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, `
// http://glslsandbox.com/e#43762.0
precision mediump float;
uniform float time;
uniform bool wireframe;
const float color_intensity = 0.45;
const float Pi = 3.14159;
void main() {
if (wireframe) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
return;
}
vec2 p = gl_FragCoord.xy / 100.0;
for (float i = 1.0; i < 9.0; i++) {
vec2 newp = p;
newp.x += 0.55 / i * sin(i * Pi * p.y + time * .01 + cos((time / (10. * i)) * i));
newp.y += 0.55 / i * cos(i * Pi * p.x + time * .01 + sin((time / (10. * i)) * i));
p = newp;
}
vec3 col = vec3(
cos(p.x + p.y + 3.) * .5 + .5,
sin(p.x + p.y + 6.) * .5 + .5,
(sin(p.x + p.y + 9.) + cos(p.x + p.y + 12.)) * .25 + .5
);
gl_FragColor = vec4(col * col, 0.5);
}
`);
gl.compileShader(fragmentShader);
// Link vertex and fragment shader to form a program, a.k.a. graphic pipeline
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
// Create a uniform, a shared variable between CPU and GPU
var time = gl.getUniformLocation(program, 'time');
var enableRotation = gl.getUniformLocation(program, 'enableRotation');
var speed = gl.getUniformLocation(program, 'speed');
var wireframe = gl.getUniformLocation(program, 'wireframe');
var vertexBufferAttribute = gl.getAttribLocation(program, 'pos');
// Create and send our model to GPU as a buffer
// http://antongerdelan.net/opengl/images/colour_buffer.png
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
var vertices = [
// Front
0.0, 1.0, 0.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
// Right
0.0, 1.0, 0.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
// Back
0.0, 1.0, 0.0,
1.0, -1.0, -1.0,
-1.0, -1.0, -1.0,
// Left
0.0, 1.0, 0.0,
-1.0,-1.0,-1.0,
-1.0,-1.0, 1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
// Our game loop, a game loop should be as light as possible
setInterval(function () {
// Clear our screen
gl.clearColor(0.3, 0.3, 0.3, 1); // R, G, B, A
gl.clear(gl.COLOR_BUFFER_BIT);
// Select a pipeline, we created only one but on a real application there could many
gl.useProgram(program);
// Select a sent buffer as a model
gl.enableVertexAttribArray(vertexBufferAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(vertexBufferAttribute, 3, gl.FLOAT, false, 0, 0);
// Set time on our pipeline so our GPU can have an understanding of time
gl.uniform1f(time, (Date.now() / 1000) % 10000);
// Now that everything is set, draw our shape
// What TRIANGLES or LINE_STRIP mean?
// See: http://antongerdelan.net/opengl/images/draw_modes.png
if (!onlyWireframe) {
gl.uniform1f(wireframe, false);
gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 3);
}
gl.uniform1f(wireframe, true);
gl.drawArrays(gl.LINE_STRIP, 0, vertices.length / 3);
}, 1000 / 60);
// "1000 / 60" means 60 times per second, 60 Frame Per Second (FPS)