Причина в том, что вы ставите раздел стиля в конце.Вещи выполняются по порядку, поэтому сначала выполняется скрипт.В то время нет стиля, поэтому по умолчанию используется холст 300x150.Сценарий рисует.Затем появляется раздел <style>
, который сообщает браузеру, что текстура 300x150 должна отображать полный размер окна.Переместите секцию стиля перед сценарием или, в идеале, вверх.
Тем не менее, пример воспроизводится только один раз.Если вы измените размер страницы, она не будет повторно отображаться, поэтому даже если вы переместите <style>
над <script>
, если окно начнется с малого и вы увеличите размер окна, вы все равно получите размытие.
Длясправиться с изменением размера, вам нужно будет снова сделать прямоугольники.Чтобы нарисовать те же прямоугольники, вам нужно сохранить позиции, размеры и используемые цвета.Вам решать, должны ли они оставаться одинакового размера относительно окна или нет, того же аспекта или нет.
Вы можете найти эту статью полезной.
Приведенный ниже код выбирает 50 случайных прямоугольников и цветов
// pick 50 random rectangles and their colors
const rectangles = [];
for (let ii = 0; ii < 50; ++ii) {
rectangles.push({
rect: [randomInt(300), randomInt(300), randomInt(300), randomInt(300)],
color: [Math.random(), Math.random(), Math.random(), 1],
});
}
Затем он рисует ранее выбранные прямоугольники в функции рендеринга
function render() {
...
for (const rectangle of rectangles) {
// This will write to positionBuffer because
// its the last thing we bound on the ARRAY_BUFFER
// bind point
setRectangle(
gl, ...rectangle.rect);
// Set the color.
gl.uniform4f(colorUniformLocation, ...rectangle.color);
// Draw the rectangle.
var primitiveType = gl.TRIANGLES;
var offset = 0;
var count = 6;
gl.drawArrays(primitiveType, offset, count);
}
}
и, наконец, вызывает render
, когда страницаизменяет размер
window.addEventListener('resize', render);
"use strict";
function main() {
// Get A WebGL context
/** @type {HTMLCanvasElement} */
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl");
if (!gl) {
return;
}
// setup GLSL program
var program = webglUtils.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
// look up where the vertex data needs to go.
var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
// look up uniform locations
var resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution");
var colorUniformLocation = gl.getUniformLocation(program, "u_color");
// Create a buffer to put three 2d clip space points in
var positionBuffer = gl.createBuffer();
// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// pick 50 random rectangles and their colors
const rectangles = [];
for (let ii = 0; ii < 50; ++ii) {
rectangles.push({
rect: [randomInt(300), randomInt(300), randomInt(300), randomInt(300)],
color: [Math.random(), Math.random(), Math.random(), 1],
});
}
function render() {
webglUtils.resizeCanvasToDisplaySize(gl.canvas);
// Tell WebGL how to convert from clip space to pixels
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
// Clear the canvas
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
// Tell it to use our program (pair of shaders)
gl.useProgram(program);
// Turn on the attribute
gl.enableVertexAttribArray(positionAttributeLocation);
// 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 iteration
var type = gl.FLOAT; // the data is 32bit floats
var normalize = false; // don't normalize the data
var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
var offset = 0; // start at the beginning of the buffer
gl.vertexAttribPointer(
positionAttributeLocation, size, type, normalize, stride, offset);
// set the resolution
gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height);
for (const rectangle of rectangles) {
// This will write to positionBuffer because
// its the last thing we bound on the ARRAY_BUFFER
// bind point
setRectangle(
gl, ...rectangle.rect);
// Set the color.
gl.uniform4f(colorUniformLocation, ...rectangle.color);
// Draw the rectangle.
var primitiveType = gl.TRIANGLES;
var offset = 0;
var count = 6;
gl.drawArrays(primitiveType, offset, count);
}
}
render();
window.addEventListener('resize', render);
}
// Returns a random integer from 0 to range - 1.
function randomInt(range) {
return Math.floor(Math.random() * range);
}
// Fill the buffer with the values that define a rectangle.
function setRectangle(gl, x, y, width, height) {
var x1 = x;
var x2 = x + width;
var y1 = y;
var y2 = y + height;
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
x1, y1,
x2, y1,
x1, y2,
x1, y2,
x2, y1,
x2, y2,
]), gl.STATIC_DRAW);
}
main();
body {
margin: 0;
}
canvas {
width: 100vw;
height: 100vh;
display: block;
}
<canvas id="canvas"></canvas>
<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
uniform vec2 u_resolution;
void main() {
// convert the rectangle from pixels to 0.0 to 1.0
vec2 zeroToOne = a_position / u_resolution;
// convert from 0->1 to 0->2
vec2 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="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 u_color;
void main() {
gl_FragColor = u_color;
}
</script>
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>