javascript - 如何修复3D谢尔宾斯基三 Angular 形的透明边

标签 javascript webgl

我有一个用 Javascript 和 WebGL 编写的 3D Serpinski 三 Angular 形,使用位于以下位置的 Common 文件夹:https://github.com/esangel/WebGL/tree/master/Common

每一面都应该有不同的颜色。三 Angular 形会按应有的方式渲染和旋转,但问题是背面是透明的。

我尝试过在三 Angular 形函数内更改 baseColors 中的 vec3,我什至尝试将另一种颜色插入颜色数组。我在另一篇文章中读到,当某些多边形被绘制时可能会发生这种情况。我唯一的猜测是有几行代码需要重新排列。

"use strict";

 var canvas;
 var gl;

 var theta = 0.0;
 var dtheta = 0.1;
 var thetaLoc;
 var speed = 50;
 var bufferId;
 var vertices;
 var dir = 1;

var points = [];
var colors = [];

var NumTimesToSubdivide = 3;

window.onload = function init()
{
 canvas = document.getElementById( "gl-canvas" );

 gl = WebGLUtils.setupWebGL( canvas );
 if (!gl) { alert("WebGL isn't available"); }

 //
 //  Initialize our data for the Sierpinski Gasket
 //

 // First, initialize the vertices of our 3D gasket
 // Four vertices on unit circle
 // Intial tetrahedron with equal length sides

 var vertices = [
     vec3(  0.0000,  0.0000, -1.0000 ),
     vec3(  0.0000,  0.9428,  0.3333 ),
     vec3( -0.8165, -0.4714,  0.3333 ),
     vec3(  0.8165, -0.4714,  0.3333 )
 ];

 divideTetra( vertices[0], vertices[1], vertices[2], vertices[3],
              NumTimesToSubdivide);

 //
 //  Configure WebGL
 //
 gl.viewport( 0, 0, canvas.width, canvas.height );
 gl.clearColor( 1.0, 1.0, 1.0, 1.0 );

 // enable hidden-surface removal

 gl.enable(gl.DEPTH_TEST);

 //  Load shaders and initialize attribute buffers

 var program = initShaders( gl, "vertex-shader", "fragment-shader" );
 gl.useProgram( program );

 // Create a buffer object, initialize it, and associate it with the
 //  associated attribute variable in our vertex shader

 var cBuffer = gl.createBuffer();
 gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );
 gl.bufferData( gl.ARRAY_BUFFER, flatten(colors), gl.STATIC_DRAW );

 var vColor = gl.getAttribLocation( program, "vColor" );
 gl.vertexAttribPointer( vColor, 3, gl.FLOAT, false, 0, 0 );
 gl.enableVertexAttribArray( vColor );

 var vBuffer = gl.createBuffer();
 gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer );
 gl.bufferData( gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW );

 var vPosition = gl.getAttribLocation( program, "vPosition" );
 gl.vertexAttribPointer( vPosition, 3, gl.FLOAT, false, 0, 0 );
 gl.enableVertexAttribArray(vPosition);

 thetaLoc = gl.getUniformLocation(program, "theta");
 gl.uniform1f(thetaLoc, theta);

 render();
};

function triangle( a, b, c, color )
{

 // add colors and vertices for one triangle

 var baseColors = [
     vec3(1.0, 0.0, 0.0),
     vec3(0.0, 1.0, 0.0),
     vec3(0.0, 0.0, 1.0),
     vec3(1.0, 1.0, 0.0)
 ];

 colors.push( baseColors[color] );
 points.push( a );
 colors.push( baseColors[color] );
 points.push( b );
 colors.push( baseColors[color] );
 points.push(c);

 //colors.push(baseColors[color]);
// points.push(a);


}

function tetra( a, b, c, d )
{
 // tetrahedron with each side using
 // a different color

 triangle( a, c, b, 0 );
 triangle( a, c, d, 1 );
 triangle( a, b, d, 2 );
 triangle( b, c, d, 3 ); //bcd
}

function divideTetra( a, b, c, d, count )
{
 // check for end of recursion

 if ( count === 0 ) {
     tetra( a, b, c, d );
 }

 // find midpoints of sides
 // divide four smaller tetrahedra

 else {
     var ab = mix( a, b, 0.5 );
     var ac = mix( a, c, 0.5 );
     var ad = mix( a, d, 0.5 );
     var bc = mix( b, c, 0.5 );
     var bd = mix( b, d, 0.5 );
     var cd = mix( c, d, 0.5 );

     --count;

     divideTetra(  a, ab, ac, ad, count );
     divideTetra( ab,  b, bc, bd, count );
     divideTetra( ac, bc,  c, cd, count );
     divideTetra( ad, bd, cd,  d, count );
 }
}


function render()
{


 gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 //gl.drawArrays(gl.TRIANGLES, 0, points.length);

 theta += dir * dtheta * (speed / 100);
 gl.uniform1f(thetaLoc, theta);

 gl.drawArrays(gl.TRIANGLES, 0, points.length);
 requestAnimFrame(render);
}

这是 HTML:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>3D Sierpinski Gasket</title>


<script id="vertex-shader" type="x-shader/x-vertex">
    attribute vec3 vPosition;
    attribute vec3 vColor;
    varying vec4 color;
    uniform float theta;

    void
    main()
    {
    gl_Position = vec4(vPosition, 1.0);
    color = vec4(vColor, 1.0);

    float s = sin( theta );
    float c = cos( theta );

    gl_Position.x = -s * vPosition.z + c * vPosition.x;
    gl_Position.z =  s * vPosition.x + c * vPosition.z;
    gl_Position.z = 0.0;
    gl_Position.w = 1.0;
    }
</script>

<script id="fragment-shader" type="x-shader/x-fragment">
    precision mediump float;

    varying vec4 color;

    void
    main()
    {

    gl_FragColor = color;
    }
</script>

<script type="text/javascript" src="Common/webgl-utils.js"></script>
<script type="text/javascript" src="Common/initShaders.js"></script>
<script type="text/javascript" src="Common/MV.js"></script>
<script type="text/javascript" src="3DSierpinskiTriangle.js"></script>
</head>   

<body>
<canvas id="gl-canvas" width="512" height="512">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
</body>
</html>

三 Angular 形的背面是透明的,但如果您查看 baseColors 数组,您会发现背面有一个额外的颜色。

最佳答案

我不是 WebGL 专家,但看起来您在顶点着色器中覆盖了 gl_Position.z 的值。

gl_Position.x = -s * vPosition.z + c * vPosition.x;
gl_Position.z =  s * vPosition.x + c * vPosition.z;
gl_Position.z = 0.0; // <--- REMOVE THIS LINE
gl_Position.w = 1.0;

删除该线会正确呈现具有所有 4 个边的四面体。

关于javascript - 如何修复3D谢尔宾斯基三 Angular 形的透明边,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54301381/

相关文章:

Three.js 中数千行的性能问题

MediaWiki 中的 3D 对象查看器?

javascript - 从多个选择中用逗号分隔每个值

javascript - 我可以向从代码触发的事件添加新属性吗

javascript - 在 li 内缩放背景图像

javascript - 使用 webgl 和 meatballs.js 的响应式 Canvas

javascript - MMO 3D 游戏在 HTML5/WebGL 上的可行性

webgl - 获取 webGL2 片段着色器上的当前像素位置

javascript - jquery 使用复选框禁用文本框(带复选框的多个文本框)

javascript - 如何仅通过 html 代码禁用特定页面的保存书签功能?