我对计算机图形学很感兴趣,想参加一些比赛。
我想了解新的(对我自己而言)方法来生成从相当简单的公式获得的各种分形或其他图像。
也就是说,比赛的标准是——使用简单的基本公式来获得有趣的图片。
比如有这样一个循环遍历图片中所有像素的实现:
let c = canvas.getContext('2d'), w = canvas.width, h = canvas.height
let formula = (x, y, cx, cy, m) => {
return [x/w+cx/w, y/h+cy/h, 0]
}
canvas.onmousemove = e => {
var img = c.getImageData(0, 0, w, h)
for(var x = 0; x<w; x++) {
for(var y = 0; y<h; y++) {
let value = formula(x, y, e.x, e.y)
let offset = (y*w + x)*4
img.data[offset] = value[0]*255
img.data[offset + 1] = value[1]*255
img.data[offset + 2] = value[2]*255
img.data[offset + 3] = 255
}
}
c.putImageData(img, 0, 0)
}
canvas.onmousemove({x: 456, y: 123})
<canvas width="600" height="175" id="canvas"/>
有必要实现一个函数formula
来获得一个“有趣”的图像,鼠标坐标是额外的参数
语言 - 任何,但最好js
是,因为在线可视化的可能性。
PS:递归方法对我来说不太有趣,特别是如果递归不是尾,因为将其移植到 glsl 将很困难,如果不是不可能的话。
PPS,为了吸引更多的观众,我选择了cpu,我为它写了图片的循环代码,但是如果你喜欢,我更喜欢webgl,所以下面是我绘制时显卡循环遍历所有像素的片段一个关闭整个屏幕的三角形和公式函数是片段着色器:)
let gl = canvas.getContext('webgl');
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, 3, -1, -1, 3, -1]), gl.STATIC_DRAW);
let pid = gl.createProgram();
shader('vertex', gl.VERTEX_SHADER);
shader('fragment', gl.FRAGMENT_SHADER);
gl.linkProgram(pid);
gl.useProgram(pid);
let coords = gl.getAttribLocation(pid, "coords");
gl.vertexAttribPointer(coords, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(coords);
let mouse = gl.getUniformLocation(pid, 'mouse');
let resolution = gl.getUniformLocation(pid, 'resolution');
gl.uniform2f(resolution, gl.drawingBufferWidth, gl.drawingBufferHeight);
let changeCenter = e => {
e = e.touches ? e.touches[0] : e;
gl.uniform2f(mouse, e.pageX - canvas.offsetLeft, e.pageY - canvas.offsetTop);
draw();
}
window.addEventListener('mousemove', changeCenter);
window.addEventListener('touchmove', changeCenter);
draw();
function draw() {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(0, 0, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
function shader(src, type) {
let sid = gl.createShader(type);
gl.shaderSource(sid, document.querySelector(`script[type="glsl/${src}"]`).textContent);
gl.compileShader(sid);
var message = gl.getShaderInfoLog(sid);
gl.attachShader(pid, sid);
if (message.length > 0) {
console.log(src.split('\n').map(function (str, i) {
return ("" + (1 + i)).padStart(4, "0") + ": " + str
}).join('\n'));
throw message;
}
}
<canvas width="600" height="175" id="canvas"/>
<script type="glsl/vertex">
attribute vec2 coords;
void main(void) {
gl_Position = vec4(coords.xy, 0.0, 1.0);
}
</script>
<script type="glsl/fragment">
precision highp float;
uniform vec2 mouse;
uniform vec2 resolution;
void main(void) {
vec2 m = mouse/resolution;
vec2 p = gl_FragCoord.xy/resolution - 0.5;
gl_FragColor = vec4(p, m);
}
</script>