Skip to content

Commit

Permalink
feat: rendering parameters controller, updated gui
Browse files Browse the repository at this point in the history
  • Loading branch information
polarr committed May 11, 2024
1 parent eaaecc9 commit 812f7e7
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 59 deletions.
13 changes: 13 additions & 0 deletions dat.gui.min.js

Large diffs are not rendered by default.

127 changes: 88 additions & 39 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,52 +13,97 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<!-- OG Meta Tags for Social Media Queries -->
<meta property="og:title" content="Graphics Showcase"/>
<!-- Thumbnail here <meta property="og:image" content="https://raw.githubusercontent.com/1e9end/minesweeper"/> -->
<meta property="og:description" content="1egend's Computer Graphics & Rendering showcase!" />
<meta property="og:url" content= "https://1e9end.github.io/graphics"/>
<meta property="og:title" content="CERXA Engine"/>
<!--
Thumbnail here <meta property="og:image" content="https://cerxa.polarity.sh"/>
-->
<meta property="og:description" content="WebGL-Powered Volumetric Raytracing Engine" />
<meta property="og:url" content= "https://cerxa.polarity.sh"/>
<meta property="og:type" content="website"/>
<script type="text/javascript" src="dat.gui.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/stats.js"></script>

<title>Raymarched fractals</title>
<title>CERXA Engine</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
font-family: "Trebuchet MS", sans-serif;
}
#canvas {
float: left;
.canvas-wrapper {
position: relative;
width: 100vw;
height: 100vh;
width: 100vh;
background-color: rgb(0, 0, 127.5);
display: flex;
justify-content: center;
}
.canvas-overlay {
position: absolute;
z-index: 100;
bottom: 0;
right: 0;
padding: .5rem 1rem;
color: #ffffff;
}
#ui{
word-wrap: normal;
#canvas {
height: 100vmin;
width: 100vmin;
}
.ui{
text-align: center;
float: left;
}
#title-wrapper{
font-family: "Trebuchet MS", sans-serif;
ul {
display: table;
margin: 0 auto;
text-align: left;
list-style-position: inside
}
.title-wrapper{
margin-top: 30px;
}
.footer {
width: 100vw;
display: flex;
justify-content: space-between;
padding: 1rem;
}
</style>
</head>
<body>
<canvas id = "canvas">
Your browser does not currently support HTML5. <br> Please try Chrome, Firefox, or Edge.
</canvas>
<div id = "ui">
<div id = "title-wrapper">
<h1>Raymarched Fractals Demo</h1>
<p>Collection of cool 3D fractals.</p>
<p>Rendered in WebGL, with boilerplate help from my own WebGL library <a href = "https://www.github.com/1e9end/Impact">Impact</a></p>
<p>Rendering algorithms all self written using Linear Algebra & light tracing techniques.</p>
<p>Includes: Ambient lighting, Specular lighting, Dynamic Camera & Scale, Hard shadows, (occlusion to come)</p>
<body>
<div class="canvas-wrapper">
<canvas id = "canvas">
Your browser does not currently support HTML5. <br> Please try Chrome, Firefox, or Edge.
</canvas>
<div class="canvas-overlay">
CERXA &#9660;
</div>
</div>
<div class = "ui">
<div class = "title-wrapper">
<h1>CERXA Engine</h1>
<p>WebGL Rasterization & Volumetric Raytracing Engine</p>
<p>From-scratch shaders and light-tracing algorithms written in GLSL with my WebGL boilerplate library <a href = "https://www.github.com/polarr/Impact">Impact</a>.</p>
<h3>Features:</h3>
<ul>
<li>Diffuse, Ambient, Specular Lighting</li>
<li>Dynamic Camera & Scale</li>
<li>Hard Shadows</li>
</ul>
<div>
<select name="fractals" id="fractals" onchange="updateFractal()">
<option value="0">Sierpenski Pyramid</option>
<option value="1">Mandelbox</option>
<option value="2">Mandelbulb</option>
<option value="3">Menger Sponge</option>
</select>
</div>
<div class = "footer">
<span>
&copy; 2020-present
</span>
<span>
~<a href = "https://polarity.sh">polarity</a>
</span>
</div>
</body>
<script id = "vts" type = "vertex-shader">
Expand All @@ -77,6 +122,8 @@ <h1>Raymarched Fractals Demo</h1>
uniform int fractal;
uniform float camZ;
uniform float THICC;
uniform float specularExp;
uniform float lightAngle;

float PI = 3.14;
float EPSILON = 0.001;
Expand Down Expand Up @@ -225,19 +272,20 @@ <h1>Raymarched Fractals Demo</h1>
}
}

float NORM_EPSILON = 0.001;
vec3 approxNormal(vec3 p)
{
return normalize(vec3(
DE(p + vec3(EPSILON, 0, 0)) - DE(p - vec3(EPSILON, 0, 0)),
DE(p + vec3(0, EPSILON, 0)) - DE(p - vec3(0, EPSILON, 0)),
DE(p + vec3(0, 0, EPSILON)) - DE(p - vec3(0, 0, EPSILON))));
DE(p + vec3(NORM_EPSILON, 0, 0)) - DE(p - vec3(NORM_EPSILON, 0, 0)),
DE(p + vec3(0, NORM_EPSILON, 0)) - DE(p - vec3(0, NORM_EPSILON, 0)),
DE(p + vec3(0, 0, NORM_EPSILON)) - DE(p - vec3(0, 0, NORM_EPSILON))));
}

float hardshadow (vec3 origin, vec3 direction, float smoothness){
float distance = EPSILON;
float light = 1.0;
float eps = 0.1;
for (float iters = 0.0; iters < 100.0; ++iters){
for (float iters = 0.0; iters < 200.0; ++iters){
vec3 pos = origin + distance * direction;
float nextDistance = DE(pos);
distance += nextDistance;
Expand All @@ -261,11 +309,11 @@ <h1>Raymarched Fractals Demo</h1>
float diffuse = max(0.0, dot(normal, light));
// https://learnopengl.com/Lighting/Basic-Lighting
vec3 reflected = reflect(direction, normal);
float specular = pow(max(dot(reflected, light), 0.0), 16.0);
float specular = pow(max(dot(reflected, light), 0.0), specularExp);
float shade = diffuse * 0.7 + specular * 0.3;
float occlusion = 1.0;
vec3 ambient = vec3(1.0, 1.0, 1.0);
return shade * ambient * occlusion * hardshadow(pos, light, .1);
return shade * ambient * occlusion * hardshadow(pos, light, 0.1);
}
if (distance > 100.0){
break;
Expand All @@ -279,15 +327,16 @@ <h1>Raymarched Fractals Demo</h1>
// window relative -> clip space
vec2 uv = gl_FragCoord.xy * res - 1.0;
// directional light
vec3 light = normalize(vec3(-1.0, 0.8, -1.0));
vec3 rot_axis = vec3(0.707107, 0, -0.707107);
vec3 rot = vec3(1.0, 0.8, 1.0);
vec3 light = normalize(rot * cos(lightAngle) + cross(rot_axis, rot) * sin(lightAngle) + rot_axis * dot(rot_axis, rot) * (1.0 - cos(lightAngle)));

//camera
vec3 rotation = vec3(0.0, mod(time, 360.0) * 30.0 + 45.0, 55.0);
vec3 cameraPosition = vec3(0.0, 0.0, camZ);

gl_FragColor = vec4(raymarch(rotate(cameraPosition, rotation), rotate(normalize(vec3(uv, 1.0)), rotation), light), 1.0);
}

</script>
<script src = "https://cdn.jsdelivr.net/gh/1e9end/Impact/main.js"></script><!-- My WebGL library -->
<script src = "main.js"></script>
Expand Down
106 changes: 86 additions & 20 deletions main.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
var gl;
gl = initGL("canvas");
var program = createProgram("vts", "fts");

let program = createProgram("vts", "fts");
gl.useProgram(program);

var posL = gl.getAttribLocation(program, "position");
var posBuffer = gl.createBuffer();
let posL = gl.getAttribLocation(program, "position");
let posBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);

var positions = [
let positions = [
-1, -1,
+1, -1,
-1, +1,
Expand All @@ -19,23 +19,31 @@ var positions = [
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

resize(gl.canvas, false, false, true);
document.getElementById("ui").style.width = window.innerWidth - window.innerHeight + "px";
clearColor();

gl.enableVertexAttribArray(posL);
gl.vertexAttribPointer(posL, 2, gl.FLOAT, false, 0, 0);

var resL = gl.getUniformLocation(program, "res");
let config = {
fractal: 3,
specular_exp: 16,
light_angle: 0.0,
fps: 60,
};

let resL = gl.getUniformLocation(program, "res");
gl.uniform2f(resL, 2.0/gl.drawingBufferWidth, 2.0/gl.drawingBufferHeight);
var timeL = gl.getUniformLocation(program, "time");
var fractalL = gl.getUniformLocation(program, "fractal");
var camZL = gl.getUniformLocation(program, "camZ");
var THICCL = gl.getUniformLocation(program, "THICC");
let timeL = gl.getUniformLocation(program, "time");
let fractalL = gl.getUniformLocation(program, "fractal");
let camZL = gl.getUniformLocation(program, "camZ");
let THICCL = gl.getUniformLocation(program, "THICC");
let specularExpL = gl.getUniformLocation(program, "specularExp");
let lightAngleL = gl.getUniformLocation(program, "lightAngle");

function updateFractal(){
var fractalN = document.getElementById("fractals").value;
var camZ, THICC;
switch(+fractalN){
// let fractalN = document.getElementById("fractals").value;
let camZ, THICC;
switch(+config.fractal){
case 3:
camZ = -3.0;
THICC = 0.001;
Expand All @@ -52,26 +60,84 @@ function updateFractal(){
camZ = -6.0;
THICC = 0.001;
}
gl.uniform1i(fractalL, fractalN);
gl.uniform1i(fractalL, config.fractal);
gl.uniform1f(camZL, camZ);
gl.uniform1f(THICCL, THICC);
gl.uniform1f(specularExpL, config.specular_exp);
gl.uniform1f(lightAngleL, config.light_angle);
}

updateFractal();

let gui = new dat.GUI({ width: 300 });

gui.add(config, 'fractal', {
'Menger Sponge': 3,
'Sierpenski Pyramid': 0,
'Mandelbox': 1,
'Mandelbulb': 2,
}).name('Fractal').onFinishChange(updateFractal);

gui.add(config, 'specular_exp', 0.5, 16, 0.5).name('Specular Exponent').onFinishChange(updateFractal);

gui.add(config, 'light_angle', 0.0, 1, 0.1).name('Lighting Angle').onFinishChange(updateFractal);

//let perfFolder = gui.addFolder("Performance");
//perfFolder.add(config, 'fps', 0, 120).name('Target FPS').step(1);

// Choose best requestAnimationFrame
window.reqAnimationFrame = (function(callback){
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
window.setTimeout(callback, 1000 / config.fps);
};
})();
var startTime = (new Date()).getTime();

let stats = new Stats();
stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild(stats.dom);

let startTime = performance.now();

function draw(){
var time = (new Date()).getTime();
let time = performance.now();

stats.begin();

gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.uniform1f(timeL, (time - startTime)/2000);

window.reqAnimationFrame(draw, 1000/60);

stats.end();

window.reqAnimationFrame(draw, 1000/ config.fps);
}

/**
function animate(newtime) {
// request another frame
window.reqAnimationFrame(animate);
// elapsed time since last loop
now = newtime;
elapsed = now - then;
// if enough time has elapsed, draw the next frame
if (elapsed > fpsInterval) {
// Get ready for next frame by setting then=now, but...
// Also, adjust for fpsInterval not being multiple of 16.67
then = now - (elapsed % fpsInterval);
// draw stuff here
// TESTING...Report #seconds since start and achieved fps.
var sinceStart = now - startTime;
var currentFps = Math.round(1000 / (sinceStart / ++frameCount) * 100) / 100;
$results.text("Elapsed time= " + Math.round(sinceStart / 1000 * 100) / 100 + " secs @ " + currentFps + " fps.");
}
}**/

window.addEventListener("load", draw, false);

0 comments on commit 812f7e7

Please sign in to comment.