Skip to content

Instantly share code, notes, and snippets.

@mathdoodle
Last active July 28, 2017 03:37
Show Gist options
  • Save mathdoodle/39390d95450ff9159b8e to your computer and use it in GitHub Desktop.
Save mathdoodle/39390d95450ff9159b8e to your computer and use it in GitHub Desktop.
Julia Set
<!doctype html>
<html>
<head>
<base href='/'>
<style>
/* STYLE-MARKER */
</style>
<!-- SHADERS-MARKER -->
<!-- SCRIPTS-MARKER -->
<!-- SYSTEM-SHIM-MARKER -->
</head>
<body>
<canvas id='doodle-canvas' width='600' height='600'>
Your browser does not support the HTML5 canvas element.
</canvas>
<script>
// CODE-MARKER
</script>
<script>
System.defaultJSExtensions = true
System.import('./script')
</script>
</body>
</html>
{
"dependencies": {
"DomReady": "1.0.0"
},
"name": "webgl-010-julia-set",
"version": "0.1.0",
"author": "David Geo Holmes",
"keywords": [
"Fractals",
"WebGL",
"GLSL",
"shaders"
],
"description": "Julia Set",
"hideConfigFiles": true,
"linting": true
}
DomReady.ready(function() {
try {
main()
}
catch (e) {
alert(e)
}
})
/**
* The export is not required, but does force the file to be a module.
*/
export function main() {
const canvas = <HTMLCanvasElement> document.getElementById('doodle-canvas')
const gl: WebGLRenderingContext = initWebGL(canvas)
const vs_source = (<HTMLScriptElement> document.getElementById('shader-vs')).innerText
const fs_source = (<HTMLScriptElement> document.getElementById('shader-fs')).innerText
const program = makeProgram(gl, vs_source, fs_source)
gl.useProgram(program)
const size = 2.0
const vertices: number[] = [
0.0, 0.0, 0.0, // 0 center
-size / 2, -size / 2, 0.0, // 1 lower left
+size / 2, -size / 2, 0.0, // 2 lower right
+size / 2, +size / 2, 0.0, // 3 upper right
-size / 2, +size / 2, 0.0 // 4 upper left
]
const vbo = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, vbo)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW)
const indices = [0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1]
const ibo = gl.createBuffer()
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STREAM_DRAW)
gl.clearColor(0.5, 0.5, 0.6, 1.0)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.viewport(0, 0, canvas.width, canvas.height)
const aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition')
gl.enableVertexAttribArray(aVertexPosition)
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0)
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0)
}
function initWebGL(canvas: HTMLCanvasElement): WebGLRenderingContext {
// Try to grab the standard context. If it fails, fallback to experimental.
const context = canvas.getContext('webgl') || canvas.getContext('experimental-webgl')
if (context) {
return context
}
else {
throw new Error("Unable to initialize WebGL. Your browser may not support it.")
}
}
/**
* Creates a WebGLProgram with compiled and linked shaders.
*/
function makeProgram(gl: WebGLRenderingContext, vertexShader: string, fragmentShader: string): WebGLProgram {
// TODO: Proper cleanup if we throw an error at any point.
const vs = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vs, vertexShader)
gl.compileShader(vs)
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
const text = gl.getShaderInfoLog(vs)
if (text) {
throw new Error(text)
}
}
const fs = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fs, fragmentShader)
gl.compileShader(fs)
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
const text = gl.getShaderInfoLog(fs)
if (text) {
throw new Error(text)
}
}
const program = gl.createProgram()
if (program) {
gl.attachShader(program, vs)
gl.attachShader(program, fs)
gl.linkProgram(program)
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
const text = gl.getProgramInfoLog(program)
if (text) {
throw new Error(text)
}
}
return program
}
else {
throw new Error("Unable to create WebGLProgram")
}
}
varying highp vec2 position;
const int MAX_ITERATIONS = 250;
const highp float LIGHTNESS_FACTOR = 10.0;
void main(void) {
highp vec2 z = vec2(position.x, position.y);
highp vec2 c = vec2(-0.8, -0.2);
highp vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
for (int i=0; i < MAX_ITERATIONS; i++) {
z = vec2(z.x * z.x -z.y * z.y, 2.0 * z.x * z.y) + c;
if (dot(z, z) > 4.0) {
highp float f = LIGHTNESS_FACTOR * float(i) / float(MAX_ITERATIONS);
color = vec4(vec3(0.4 * z.x, 0.4 * z.y, 0.4) * f, 1.0);
break;
}
}
gl_FragColor = color;
}
attribute vec3 aVertexPosition;
varying vec2 position;
void main(void) {
position = vec2(aVertexPosition);
gl_Position = vec4(position, 0.0, 1.0);
}
body {
background-color: white;
margin: 0px;
overflow: hidden;
}
canvas {
background-color: blue;
position: absolute;
left: 10px;
top: 10px;
}
{
"allowJs": false,
"declaration": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"jsx": "react",
"module": "system",
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"preserveConstEnums": true,
"removeComments": false,
"sourceMap": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es5",
"traceResolution": true
}
{
"rules": {
"array-type": [
true,
"array"
],
"curly": false,
"comment-format": [
true,
"check-space"
],
"eofline": true,
"forin": true,
"jsdoc-format": true,
"new-parens": true,
"no-conditional-assignment": false,
"no-consecutive-blank-lines": true,
"no-construct": true,
"no-for-in-array": true,
"no-inferrable-types": [
true
],
"no-magic-numbers": false,
"no-shadowed-variable": true,
"no-string-throw": true,
"no-trailing-whitespace": [
true,
"ignore-jsdoc"
],
"no-var-keyword": true,
"one-variable-per-declaration": [
true,
"ignore-for-loop"
],
"prefer-const": true,
"prefer-for-of": true,
"prefer-function-over-method": false,
"prefer-method-signature": true,
"radix": true,
"semicolon": [
true,
"never"
],
"trailing-comma": [
true,
{
"multiline": "never",
"singleline": "never"
}
],
"triple-equals": true,
"use-isnan": true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment