Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix transparent side of 3D Serpinski Triangle

I have a 3D Serpinski Triangle written in Javascript and WebGL, using a Common folder located at: https://github.com/esangel/WebGL/tree/master/Common

Each side is supposed to have a different color. The triangle renders and spins as it should, but the problem is that the back side is transparent.

I've tried altering the vec3's in baseColors inside the triangle function and I even tried pushing another color onto the colors array. I've read in another post that this could happen when certain polygons are being drawn over. My only guess is that there are a few lines of code that need to be rearranged.

"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);
}

Here is the 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>

The back side of the triangle is transparent, but if you look in the baseColors array, you'll see there is an extra color for the back.

like image 693
nullnode Avatar asked Oct 17 '22 07:10

nullnode


1 Answers

I'm no WebGL expert, but it looks like you're overwriting the value of gl_Position.z in your vertex shader.

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;

Removing that line correctly renders the tetrahedrons with all 4 sides.

like image 88
John Ellmore Avatar answered Oct 21 '22 06:10

John Ellmore