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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With