Javascript 无法在沿轴旋转的WebGL中创建三维Koch 最近我已经拿起WebGL来将我的C++游戏移植到JS。我成功地创建并旋转了三维科赫曲线的基本四面体。同样,由于WebGL中的着色器,我无法翻译代码。我解决这个问题的方法和OpenGL一样,计算新的几何点,然后,一旦形成三角形,我就画它。这在WebGL中似乎不起作用。 这是密码。。。 这是我成功之前WebGL的代码。具体来说,我需要翻译功能方面的帮助

Javascript 无法在沿轴旋转的WebGL中创建三维Koch 最近我已经拿起WebGL来将我的C++游戏移植到JS。我成功地创建并旋转了三维科赫曲线的基本四面体。同样,由于WebGL中的着色器,我无法翻译代码。我解决这个问题的方法和OpenGL一样,计算新的几何点,然后,一旦形成三角形,我就画它。这在WebGL中似乎不起作用。 这是密码。。。 这是我成功之前WebGL的代码。具体来说,我需要翻译功能方面的帮助,javascript,c++,opengl-es,webgl,Javascript,C++,Opengl Es,Webgl,下面是index.html //桑托什汇编。标题:main.js var-gl; 函数initGLcanvas{ 试一试{ gl=canvas.getContextexperimental-webgl; gl.viewportWidth=canvas.width; gl.viewportHeight=canvas.height; }抓住e{ } 如果!德国劳埃德船级社{ 警报无法初始化WebGL,抱歉:-; } gl.enablegl.DEPTH_测试; gl.clearColor0.0,0.

下面是index.html

//桑托什汇编。标题:main.js var-gl; 函数initGLcanvas{ 试一试{ gl=canvas.getContextexperimental-webgl; gl.viewportWidth=canvas.width; gl.viewportHeight=canvas.height; }抓住e{ } 如果!德国劳埃德船级社{ 警报无法初始化WebGL,抱歉:-; } gl.enablegl.DEPTH_测试; gl.clearColor0.0,0.0,0.0,0.0; gl.viewport0,0,canvas.width,canvas.height; } 函数getShadergl,id{ var shaderScript=document.getElementByIdid; 如果!着色器脚本{ 返回null; } var-str=; var k=shaderScript.firstChild; 而k{ 如果k.nodeType==3{ str+=k.textContent; } k=k.nextSibling; } var着色器; 如果shaderScript.type==x-shader/x-fragment{ 着色器=gl.createShadergl.FRAGMENT\u着色器; }如果shaderScript.type==x-shader/x-vertex,则为else{ 着色器=gl.createShadergl.VERTEX_着色器; }否则{ 返回null; } shaderSourceshader街gl号; gl.compileShadershader; 如果!gl.getShaderParametershader,gl.COMPILE\u状态{ alertgl.getShaderInfoLogshader; 返回null; } 返回着色器; } var着色器程序; 函数初始化着色器{ var fragmentShader=getShadergl,着色器fs; var vertexShader=getShadergl,shader vs; shaderProgram=gl.createProgram; gl.AttachShaderShader程序,vertexShader; gl.AttachShaderShader程序,碎片着色器; gl.linkProgramshaderProgram; 如果!gl.getProgramParametershaderProgram,gl.LINK\u状态{ 警报无法初始化着色器; } gl.useProgramshaderProgram; shaderProgram.vertexPositionAttribute=gl.GetAttributeLocationShaderProgram,aVertexPosition; gl.EnableVertexAttribute数组ShaderProgramm.vertexPositionAttribute; shaderProgram.vertexcoloratAttribute=gl.getAttributesShaderprogram,aVertexColor; gl.EnableVertexAttribute数组ShaderProgram.vertexColorAttribute; shaderProgram.pMatrixUniform=gl.getUniformLocationsShaderprogram,uPMatrix; shaderProgram.mvMatrixUniform=gl.getUniformLocationsShaderprogram,uMVMatrix; } var mvMatrix=mat4.create; var mvMatrixStack=[]; var pMatrix=mat4.create; 函数矩阵{ var copy=mat4.create; mat4.setmvMatrix,副本; mvMatrixStack.pushcopy; } 函数矩阵{ 如果mvMatrixStack.length==0{ 抛出无效的popMatrix!; } mvMatrix=mvMatrixStack.pop; } 函数集矩阵形式{ gl.uniformMatrix4fvshaderProgram.pMatrixUniform,false,pMatrix; gl.uniformMatrix4fvshaderProgram.mvMatrixUniform,false,mvMatrix; } 函数去余度{ 返回度*Math.PI/180; } var暴露缓冲区; 变分光器; 函数初始化缓冲区{ PyraminVertExpositionBuffer=gl.createBuffer; gl.bindBuffergl.ARRAY_BUFFER,PyraminVertExpositionBuffer; 变量顶点=[ //正面 1.0,1.0,1.0,//a 1.0,-1.0,-1.0,//b -1.0,1.0,-1.0,//c //右脸 1.0,-1.0,-1.0,//b -1.0,1.0,-1.0,//c -1.0,-1.0,1.0,//d //左脸 1.0,1.0,1.0,//a -1.0,-1.0,1.0,//d 1.0,-1.0,-1.0,//b //背面 -1.0,1.0,-1.0,//c -1.0,-1.0,1.0,//d 1.0,1.0,1.0//a ]; gl.bufferDatagl.ARRAY\u BUFFER,新float32arrayvities,gl.STATIC\u DRAW; PyraminVertExpositionBuffer.itemSize=3; PyraminVertExpositionBuffer.numItems=12; PyraminVertexColorBuffer=gl.createBuffer; gl.bindBuffergl.ARRAY_缓冲区,金字塔顶点颜色缓冲区; 变量颜色=[ //正面 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 //右脸 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 //左脸 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 //背面 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.bufferDatagl.ARRAY\u BUFFER,新float32arrayColor,gl.STATIC\u DRAW; pyramidVertexColorBuffer.itemSize=4; 金字塔顶点颜色缓冲区.numItems=12; } var rPyramid=0; 功能绘图场景{ gl.viewport0,0,gl.viewportWidth,gl.viewportHeight; 德国劳埃德船级社 .cleargl.COLOR_BUFFER|gl.DEPTH_BUFFER|位; mat4.perspective45,gl.viewportWidth/gl.viewportHeight,0.1100.0,pMatrix; mat4.识别矩阵; mat4.translatemvMatrix[0.0,2.0,-8.0]; mat4.标度矩阵[0.7,0.7,0.7]; MVP矩阵; mat4.rotatemvMatrix,degtoradr金字塔[0,1,0]; gl.bindBuffergl.ARRAY_BUFFER,PyraminVertExpositionBuffer; gl.VertexAttributesPointerShaderProgram.vertexPositionAttribute,pyramidVertexPositionBuffer.itemSize,gl.FLOAT,false,0,0; gl.bindBuffergl.ARRAY_缓冲区,金字塔顶点颜色缓冲区; gl.VertexAttributePointerShaderProgram.vertexColorAttribute,金字塔VertexColorBuffer.itemSize,gl.FLOAT,false,0,0; 刚毛状体; gl.drawArraysgl.TRIANGLES,0,金字塔顶点ExpositionBuffer.numItems; MVPOP矩阵; } var lastTime=0; 函数动画{ var timeNow=new Date.getTime; 如果上次!=0{ var Expased=timeNow-lastTime; rPyramid+=90*经过/1000.0; } lastTime=timeNow; } 功能记号{ requestAnimationFrametick; 绘画场景; 使有生气 } 函数webGLStart{ var canvas=document.getElementByIdgameCanvas; 初始化画布; 初始化着色器 初始化缓冲区; gl.clearColor0.0,0.0,0.0,0.0; gl.enablegl.DEPTH_测试; 打上钩 } webGLStart; 精密中泵浮子; 可变vec4颜色; 无效主无效{ gl_FragColor=vColor; } 属性向量3; 属性向量4;颜色; 均匀mat4-uMVMatrix; 一致mat4上矩阵; 可变vec4颜色; 无效主无效{ gl_位置=上矩阵*UMV矩阵*VEC4,1.0; vColor=excolor; }
像OpenGLES2.0及以上版本的WebGL不再有固定的功能管道。换句话说,它不支持一次指定一个顶点的glVertex、glColor等。原因是在现代GPU上效率极低且速度很慢。当然,在你的PC上,速度足够快,可以让东西正常工作,但它甚至远没有接近GPU的工作方式,因此设计OpenGL的人Khronos聪明地决定删除这些东西,特别是对于OpenGL ES,其中ES=嵌入式系统=智能手机,因为超低效的方法消耗了用户的电池,而且由于它实际上不是GPU工作,这也意味着用代码填充驱动程序以支持旧的低效方法

现在的方法是创建缓冲区,就像上面的示例中那样,并将数据放入缓冲区中。通常,数据只需要创建一次。例如,如果您正在绘制一个棱锥体,为什么要在每一帧指定每个顶点,而您可以只指定它们一次,然后每次重复使用它们。效率更高

<> P>所以,基本上需要将旧的OpenGL C++代码重新构造成新的现代OpenGL ES代码。一种简单的方法可能是制作一些缓冲区创建者助手。范例

function OldOpenGLVertexHelper() {
  var colors = [];
  var vertices = [];
  var normals = [];

  var currentColor = [1, 1, 1, 1];
  var currentNormal = [0, 0, 0];
  var mode;

  this.color3f = function(r, g, b) {
    currentColor = [r, g, b, 1];
  }

  this.color4f = function(r, g, b, a) {
    currentColor = [r, g, b, a];
  }

  this.color3fv = function(rgb) {
    currentColor = rgb.concat(1);
  }

  this.color4fv = function(rgba) {
    currentColor = rgba.slice();
  }

  this.normal3f = function(x, y, z) {
    currentNormal = [x, y, z];
  }

  this.normal3fv = function(xyz) {
    currentNormal = xyz.slice();
  }

  var vertex3f = function(x, y, z) {
    colors.push(currentColor[0], 
                currentColor[1], 
                currentColor[2], 
                currentColor[3]);
    normals.push(currentNormal[0],
                 currentNormal[1],
                 currentNormal[2]);
    vertices.push(x, y, z);
  }

  this.vertex3f = vertex3f;

  this.vertex3fv = function(xyz) {
    vertex3f(xyz[0], xyz[1], xyz[2]);
  };

  this.end = function() {
    return {
      vertices: new Float32Array(vertices),
      normals: new Float32Array(normals),
      colors: new Float32Array(colors),
      mode: mode,
    };
  });

  this.begin = function(m) {
     mode = m;
     colors = [];
     normals = [];
     vertices = [];,
  };
}
现在你可以这样做了

var oldGL = new OldOpenGLVertexHelper();

oldGL.color3f(0.0,0.0,0.0); 
oldGL.begin(gl.LINES);
    oldGL.vertex3fv(a);
    oldGL.vertex3fv(b);
    oldGL.vertex3fv(b);
    oldGL.vertex3fv(c);
    oldGL.vertex3fv(c);
    oldGL.vertex3fv(d);
    oldGL.vertex3fv(d);
    oldGL.vertex3fv(a);
    oldGL.vertex3fv(a);
    oldGL.vertex3fv(c);
    oldGL.vertex3fv(b);
    oldGL.vertex3fv(d);
var buffers = oldGL.end();
现在,您可以使用buffers.vertices、buffers.colors、buffers.normals等访问创建的缓冲区

如何使用这些缓冲区取决于您。理想情况下,如果它们不改变每一帧,您应该在初始化时创建它们并重用它们。请参阅上面发布的代码,该代码为金字塔创建了一组缓冲区

否则,如果您想做旧的OpenGL所做的事情,您可以立即在该点上绘制

 gl.bindBuffer(gl.ARRAY_BUFFER, somebufferForPositions);
 gl.bufferData(gl.ARRAY_BUFFER, buffers.vertices, gl.DYNAMIC_DRAW);
 gl.bindBuffer(gl.ARRAY_BUFFER, somebufferForColors);
 gl.bindBuffer(gl.ARRAY_BUFFER, buffers.colors, gl.DYNAMIC_DRAW);

 // set your attributes
 ...
 gl.drawArrays(buffers.mode, 0, buffers.vertices.length / 3); 
 // NOTE: you'll need to change that divided by 3 if buffers.mode
 // is lines (2) or points (1)
这基本上就是旧的OpenGL驱动程序为您所做的


我不知道这是否足以帮助你。由于您是WebGL新手,我建议您多阅读一些教程

好奇者和好奇者。。。像科赫曲面的科赫曲线这样的分形要求我们动态地创建点。本质上,这就是建议的算法。创建点可以静态完成,但同样地,拾取arraybuffer中的这些点并进行打印是很困难的。此外,我需要设计一个不断演变的表面。有没有办法做到这一点?当金字塔是静态的时,建议的另一种方法是在特定位置向其添加对象。我可以创建一个对象,然后创建它的多个实例吗?但是,在新方法中,我需要沿着旧实例曲面质心处的法线对齐新实例。有没有任何建议,我可以使用一个模型创建新的棱锥体,创建几个实例,然后TSR放置在新位置?如果所有棱锥体基本上都是相同的,只需重新定位、重新定向和缩放,那么您可以在初始时间创建一组棱锥体点,在绘制时间设置着色器使用程序,设置所有缓冲区/属性,然后为每个金字塔设置一些统一的放置位置,并调用draw。如果棱锥体彼此不相对移动,则可以生成一个包含所有棱锥体的模型。那会跑得最快。我知道问这个问题很有意思,但我能找到关于这个的教程吗?非常感谢你的意见。同时,也要回答上述问题。我会接受的。