Kepler is a open source deferred, pbr based render engine written in Javascript. Current features are: #### Surface Normal ![Surface Normal](https://code.kajdijkstra.com/kaj/Kepler/src/branch/main/media/normal.png) #### Positions ![Positions](/images/kepler/position.png) #### Diffuse Maps ![Diffuse Maps](/images/kepler/diffuse.png) --- ### Screen Space Ambient Occlusion (SSAO) ![SSAO](/images/kepler/ssao.png) --- In the final render pass, all G-buffer data is combined and PBR lighting calculations are performed in parallel on the GPU, producing a photorealistic real-time image. Real-time PBR enables interactive applications such as games and simulations to deliver high-fidelity visuals by leveraging modern GPU computational power. ![PBR lights without Diffuse](/images/kepler/lightOnly.png) --- ## **Rendering Multiple Lights** Deferred lighting efficiently renders many lights by processing geometry once into G-buffers, then computing lighting per light in screen space. This avoids redundant geometry rendering and limits lighting calculations to affected screen regions, significantly improving performance. ![Multiple Lights 1](/images/kepler/4.png) ![Multiple Lights 2](/images/kepler/3.png) --- ## **PBR Roughness Parameter** **Roughness** controls the microsurface texture of a material, affecting reflection sharpness. It governs the spread and intensity of specular highlights, crucial for realistic PBR materials. ![PBR Roughness](/images/kepler/roughness_blue.png) --- # Load models: ```javascript import keplerEngine from './engine/kepler.js'; import sampler2D from './engine/sampler2D.js'; import viewport from './engine/viewport.js'; // Create raprtor engine instance kepler = new keplerEngine(); // Create viewport to dom element width id keplerEngine var ViewPort = new viewport("keplerEngine"); // Load 3d model kepler.assimpLoader.load( "demo.json", ViewPort.scene ); // Add viewport kepler.addViewport( ViewPort ); // Start application kepler.application(); ``` # Create primitives (Entity's, Materials, textures, samplers): ```javascript import keplerEngine from './engine/kepler.js'; import entity from './engine/entity.js'; import material from './engine/material.js'; import sampler2D from './engine/sampler2D.js'; import mesh from './engine/mesh.js'; import viewport from './engine/viewport.js'; kepler = new keplerEngine(); // Viewport var ViewPort = new viewport("keplerEngine"); // Material var groundMaterial = new material(); // Create Normal Texture and Sampler var normalTexture = kepler.resources.getTexture("floorTiles_normal.png"); var normalSampler = new sampler2D(); normalSampler.addTexture(normalTexture); // Create Diffuse Texture and Sampler var diffuseTexture = kepler.resources.getTexture("floorTiles_diff.png"); var diffuseSampler = new sampler2D(); diffuseSampler.addTexture(diffuseTexture); // Add Samplers to Material groundMaterial.addTexture(diffuseSampler); groundMaterial.addNormal(normalSampler); // Properties groundMaterial.diffuseColor = [179.0 / 256.0, 199.0 / 256.0, 217.0 / 256.0]; groundMaterial.alpha = 1.0; groundMaterial.reflection = 0.2; groundMaterial.roughness = 0.3; groundMaterial.metalic = 0.1; groundMaterial.uvMultiplier = 6.0; // Create cube mesh var cubeMesh = ViewPort.primitives.createCube(10); cubeMesh.addMaterial(groundMaterial); // Create cube Entity var cubeEntity = new entity( ); cubeEntity.addMesh( cubeMesh ); cubeEntity.name = "Cube"; cubeEntity.transform.position = [0, 10, 0]; cubeEntity.transform.update(); // Add cube entity to scene ViewPort.scene.addEntity( cubeEntity ); // Start application kepler.application(); ``` # Renderpass: ```javascript import defaultRenderPass from '../defaultRenderPass.js'; import sampler2D from '../sampler2D.js'; import shader from '../shader.js'; class tonemap extends defaultRenderPass { prepare() { var randomTexure = kepler.resources.getTexture("random.png"); var randomSampler = new sampler2D(); randomSampler.addTexture(randomTexure); this.shader = new shader(); this.shader.createFromFile("shaders/tonemap.shader"); // set uniforms like this this.shader.setUniform("exposure", 1.1 ); this.shader.setUniform("exampleVector2", [1,1] ); this.shader.setUniform("exampleVector3", [1,1,1] ); this.shader.setUniform("randomSampler", randomSampler ); } } export {tonemap as default}; ``` In rendersytem.js in the method createRenderPasses add: ```javascript import tonemap from './renderPasses/tonemap.js'; var tonemapPass = new tonemap(); this.deferredRenderPipeline.addRenderpass( tonemapPass, "uber" ); //tonemapPass.renderToViewport = true; tonemapPass.shader.setUniform("colorSampler", uberPass.framebuffer.getSampler() ); ``` ## tonemap.shader ```glsl attribute vec3 position; attribute vec2 uv; uniform mat4 viewProjection; varying vec2 v_textureCoord; void main(void) { v_textureCoord = uv; gl_Position = viewProjection * vec4(position, 1.0); } // #keplerEngine - Split precision highp float; uniform sampler2D colorSampler; varying vec2 v_textureCoord; void main() { vec3 color = texture2D( colorSampler, v_textureCoord ).rgb; gl_FragColor = vec4( tonemap(color), 1.0 ); } ```