Недавно я взял WebGL для переноса моей игры на C++ в JS. Мне удалось создать и повернуть базовый тетраэдр для кривой 3D Коха. Опять же, из-за Shaders в WebGL, я не могу перевести код. Мой подход к проблеме был таким же, как и в OpenGL, вычислять новые точки геометрии, а затем, как только образуется треугольник, я рисую его. Это не работает в WebGL. Вот код ... https://github.com/Horopter/koch-snowflake/blob/master/koch/koch3d.cpp и вот код для WebGL, пока я не преуспел. В частности мне нужна помощь с переводом функций ...Невозможно создать 3D Koch в WebGL с вращением вдоль оси
Так вот для index.html
//compiled by Santosh. Title : main.js
var gl;
function initGL(canvas) {
try {
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch (e) {
}
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
}
gl.enable(gl.DEPTH_TEST);
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.viewport(0, 0, canvas.width, canvas.height);
}
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
var shaderProgram;
function initShaders() {
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}
var mvMatrix = mat4.create();
var mvMatrixStack = [];
var pMatrix = mat4.create();
function mvPushMatrix() {
var copy = mat4.create();
mat4.set(mvMatrix, copy);
mvMatrixStack.push(copy);
}
function mvPopMatrix() {
if (mvMatrixStack.length == 0) {
throw "Invalid popMatrix!";
}
mvMatrix = mvMatrixStack.pop();
}
function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}
function degToRad(degrees) {
return degrees * Math.PI/180;
}
var pyramidVertexPositionBuffer;
var pyramidVertexColorBuffer;
function initBuffers() {
pyramidVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexPositionBuffer);
var vertices = [
// Front face
1.0, 1.0, 1.0,//a
1.0, -1.0, -1.0,//b
-1.0, 1.0, -1.0,//c
// Right face
1.0, -1.0, -1.0,//b
-1.0, 1.0, -1.0,//c
-1.0, -1.0, 1.0,//d
// Left face
1.0, 1.0, 1.0,//a
-1.0, -1.0, 1.0,//d
1.0, -1.0, -1.0,//b
// Back face
-1.0, 1.0, -1.0,//c
-1.0, -1.0, 1.0,//d
1.0, 1.0, 1.0//a
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
pyramidVertexPositionBuffer.itemSize = 3;
pyramidVertexPositionBuffer.numItems = 12;
pyramidVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexColorBuffer);
var colors = [
// Front face
1.0, 0.0, 0.0, 1.0,//a
0.0, 1.0, 0.0, 1.0,//b
0.0, 0.0, 1.0, 1.0,//c
// Right face
0.0, 1.0, 0.0, 1.0,//b
0.0, 0.0, 1.0, 1.0,//c
1.0, 1.0, 1.0, 1.0,//d
// Left face
1.0, 0.0, 0.0, 1.0,//a
1.0, 1.0, 1.0, 1.0,//d
0.0, 1.0, 0.0, 1.0,//b
// Back face
0.0, 0.0, 1.0, 1.0,//c
1.0, 1.0, 1.0, 1.0,//d
1.0, 0.0, 0.0, 1.0,//a
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
pyramidVertexColorBuffer.itemSize = 4;
pyramidVertexColorBuffer.numItems = 12;
}
var rPyramid = 0;
function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45, gl.viewportWidth/gl.viewportHeight, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [0.0, 2.0, -8.0]);
mat4.scale(mvMatrix,[0.7,0.7,0.7]);
mvPushMatrix();
mat4.rotate(mvMatrix, degToRad(rPyramid), [0, 1, 0]);
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, pyramidVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, pyramidVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES, 0, pyramidVertexPositionBuffer.numItems);
mvPopMatrix();
}
var lastTime = 0;
function animate() {
var timeNow = new Date().getTime();
if (lastTime != 0) {
var elapsed = timeNow - lastTime;
rPyramid += (90 * elapsed)/1000.0;
}
lastTime = timeNow;
}
function tick() {
requestAnimationFrame(tick);
drawScene();
animate();
}
function webGLStart() {
var canvas = document.getElementById("gameCanvas");
initGL(canvas);
initShaders()
initBuffers();
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.enable(gl.DEPTH_TEST);
tick();
}
webGLStart();
<script src="http://learningwebgl.com/lessons/lesson01/glMatrix-0.9.5.min.js"></script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec4 vColor;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
</script>
<canvas id="gameCanvas" style="border: none;" width="800" height="500"> </canvas>
Любопытный и любопытный ... Фракталы, такие как кривая koch поверхности Коха, требуют от нас динамического создания точек. По сути, это предложенный алгоритм. создание точек может быть сделано статически, но затем снова, собирание таких точек, присутствующих в массиве буфера, и построение графика является жестким. Кроме того, мне нужно разработать постоянно развивающуюся поверхность. Есть ли способ, которым это можно было бы сделать?
Другой подход, предложенный в то время, когда пирамида статична, заключается в добавлении к нему объектов в определенных местах. Могу ли я создать объект, а затем создать несколько его экземпляров? –
Однако в новом подходе мне нужно выровнять новый экземпляр вдоль нормального присутствия в центре тяжести поверхности старого экземпляра. Итак, любое предложение, в котором я могу создать новые пирамиды с использованием модели, создать несколько экземпляров, а затем TSR разместить в новой позиции? –
Если все пирамиды - это в основном одно и то же, только что перегруппированное, переориентированное и масштабированное, вы можете просто сделать один набор точек пирамиды во время init, в момент рисования установите шейдер (useProgram), установите все буферы/атрибуты, затем для каждая пирамида установила какую-то униформу, куда ее поместить, и назовем ничью. Если пирамиды не перемещаются относительно друг друга, тогда вы можете создать одну модель, содержащую все комбинации пирамид. Это будет работать быстрее всего. – gman