SlideShare a Scribd company logo
The making of HexGL
• Thibaut Despoulain (@bkcore – bkcore.com)

• 22 year-old student in Computer Engineering

• University of Technology of Belfort-Montbéliard (France)

• Web dev and 3D enthousiast

• The guy behind the HexGL project
HTML5 game dev with three.js - HexGL
• Fast-paced, futuristic racing game

• Inspired by the F-Zero and Wipeout series

• HTML5, JavaScript, WebGL (via Three.js)

• Less than 2 months

• Just me.
HTML5 game dev with three.js - HexGL
HTML5 game dev with three.js - HexGL
HTML5 game dev with three.js - HexGL
HTML5 game dev with three.js - HexGL
• JavaScript API

• OpenGL ES 2.0

• Chrome, FireFox, (Opera, Safari)

• <Canvas> (HTML5)
HTML5 game dev with three.js - HexGL
• Rendering engine
• Maintained by Ricardo Cabello (MrDoob) and Altered Qualia
• R50/stable

• + : Active community, stable, updated frequently

• - : Documentation
HTML5 game dev with three.js - HexGL
HTML5 game dev with three.js - HexGL
HTML5 game dev with three.js - HexGL
• First « real » game

• 2 months to learn and code

• Little to no modeling and texturing skills

• Physics? Controls? Gameplay?
• Last time I could have 2 months free

• Visibility to get an internship

• Huge learning opportunity

• Explore Three.js for good
HTML5 game dev with three.js - HexGL
• Third-party physics engine (rejected)
   – Slow learning curve

   – Not really meant for racing games
• Ray casting (rejected)
   – Heavy perfomance-wise

   – Needs Octree-like structure

   – > too much time to learn and implement
• Home-made 2D approximation
  – Little to no learning curve

  – Easy to implement with 2D maps

  – Pretty fast

  – > But with some limitations
HTML5 game dev with three.js - HexGL
HTML5 game dev with three.js - HexGL
• Home-made 2D approximation
  – No track overlap

  – Limited track twist and gradient

  – Accuracy depends on map resolution

  – > Enough for what I had in mind
HTML5 game dev with three.js - HexGL
• No pixel getter on JS Image object/tag

• Canvas2D to the rescue
Load data                   Draw it on a             Get canvas


                            Drawing




                                                     Getting
Loading




          texture with JS             Canvas using             pixels using
          Image object                2D context               getImageData()
• ImageData (BKcore package)
  – Github.com/Bkcore/bkcore-js

var a = new bkcore.ImageData(path, callback);
//…
a.getPixel(x, y);
a.getPixelBilinear(xf, yf);
// -> {r, g, b, a};
Game loop:
  Convert world position to pixel indexes
  Get current pixel intensity (red)
  If pixel is not white:
      Collision
      Test pixels relatively (front, left, right)
:end
Front


Left            Right




Track             Void
Front


         Front
                                               Current
                                    Gradient
Left                Right    Left



                                                Right
       Height map                     Tilt
HTML5 game dev with three.js - HexGL
HTML5 game dev with three.js - HexGL
HTML5 game dev with three.js - HexGL
Model
  .OBJ               Python               Three.js
Materials           converter           JSON model
 .MTL

 $ python convert_obj_three.py -i mesh.obj -o mesh.js
var scene = new THREE.Scene();
var loader = new THREE.JSONLoader();

var createMesh = function(geometry)
{
   var mesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial());
   mesh.position.set(0, 0, 0);
   mesh.scale.set(3, 3, 3);
   scene.add(mesh);
};

loader.load("mesh.js", createMesh);
HTML5 game dev with three.js - HexGL
var renderer = new THREE.WebGLRenderer({
  antialias: false,
  clearColor: 0x000000
});


renderer.autoClear = false;
renderer.sortObjects = false;
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
renderer.gammaInput = true;

renderer.gammaOutput = true;



renderer.shadowMapEnabled = true;

renderer.shadowMapSoft = true;
HTML5 game dev with three.js - HexGL
• Blinn-phong
   – Diffuse + Specular + Normal + Environment maps

• THREE.ShaderLib.normal
   – > Per vertex point lights

• Custom shader with per-pixel point lights for the road
   – > Booster light
HTML5 game dev with three.js - HexGL
var boosterSprite = new THREE.Sprite(
{
  map: spriteTexture,
  blending: THREE.AdditiveBlending,
  useScreenCoordinates: false,
  color: 0xffffff
});

boosterSprite.mergeWith3D = false;
boosterMesh.add(boosterSprite);
HTML5 game dev with three.js - HexGL
var material = new THREE.ParticleBasicMaterial({
  color: 0xffffff,
  map: THREE.ImageUtils.loadTexture(“tex.png”),
  size: 4,
  blending: THREE.AdditiveBlending,
  depthTest: false,
  transparent: true,
  vertexColors: true,
  sizeAttenuation: true
});
var pool = [];
var geometry = new THREE.Geometry();
geometry.dynamic = true;

for(var i = 0; i < 1000; ++i)
{
   var p = new bkcore.Particle();
   pool.push(p);
   geometry.vertices.push(p.position);
   geometry.colors.push(p.color);
}
bkcore.Particle = function()
{
  this.position = new THREE.Vector3();
  this.velocity = new THREE.Vector3();
  this.force = new THREE.Vector3();
  this.color = new THREE.Color(0x000000);
  this.basecolor = new THREE.Color(0x000000);
  this.life = 0.0;
  this.available = true;
}
var system = new THREE.ParticleSystem(
   geometry,
   material
);
system.sort = false;

system.position.set(x, y, z);
system.rotation.set(a, b, c);

scene.add(system);
// Particle physics
var p = pool[i];
p.position.addSelf(p.velocity);
//…
geometry.verticesNeedUpdate = true;
geometry.colorsNeedUpdate = true;
• Particles (BKcore package)
   – Github.com/BKcore/Three-extensions
var clouds = new bkcore.Particles({
  opacity: 0.8,
  tint: 0xffffff, color: 0x666666, color2: 0xa4f1ff,
  texture: THREE.ImageUtils.loadTexture(“cloud.png”),
  blending: THREE.NormalBlending,
  size: 6, life: 60,      max: 500,
  spawn: new THREE.Vector3(3, 3, 0),
  spawnRadius: new THREE.Vector3(1, 1, 2),
  velocity: new THREE.Vector3(0, 0, 4),
  randomness: new THREE.Vector3(5, 5, 1)
});
scene.add(clouds);

// Game loop
clouds.emit(10);
clouds.update(dt);
HTML5 game dev with three.js - HexGL
• Built-in support for off-screen passes

• Already has some pre-made post effects
   – Bloom

   – FXAA

• Easy to use and Extend

• Custom shaders
var renderTargetParameters = {
   minFilter: THREE.LinearFilter,
   magFilter: THREE.LinearFilter,
   format: THREE.RGBFormat,
   stencilBuffer: false
};
var renderTarget = new THREE.WebGLRenderTarget(
   width, height,
   renderTargetParameters
);
var composer = new THREE.EffectComposer(
   renderer,
   renderTarget
);

composer.addPass( … );

composer.render();
• Generic passes
   –   RenderPass
   –   ShaderPass
   –   SavePass
   –   MaskPass

• Pre-made passes
   – BloomPass
   – FilmPass
   – Etc.
var renderModel = new THREE.RenderPass(
   scene,
   camera
);

renderModel.clear = false;

composer.addPass(renderModel);
var effectBloom = new THREE.BloomPass(
   0.8, // Strengh
   25, // Kernel size
   4, // Sigma
   256 // Resolution
);

composer.addPass(effectBloom);
HTML5 game dev with three.js - HexGL
var hexvignette: {
    uniforms: {
          tDiffuse: { type: "t", value: 0, texture: null },
          tHex: { type: "t", value: 1, texture: null},
          size: { type: "f", value: 512.0},
          color: { type: "c", value: new THREE.Color(0x458ab1) }
    },
    fragmentShader: [
          "uniform float size;",
          "uniform vec3 color;",
          "uniform sampler2D tDiffuse;",
          "uniform sampler2D tHex;",

          "varying vec2 vUv;",

          "void main() { ... }"

     ].join("n")
};
var effectHex = new THREE.ShaderPass(hexvignette);

effectHex.uniforms['size'].value = 512.0;
effectHex.uniforms['tHex'].texture = hexTexture;

composer.addPass(effectHex);

//…
effectHex.renderToScreen = true;
HTML5 game dev with three.js - HexGL
HTML5 game dev with three.js - HexGL
HTML5 game dev with three.js - HexGL
Ad

Recommended

WebGL and three.js - Web 3D Graphics
WebGL and three.js - Web 3D Graphics
PSTechSerbia
 
WebGL and three.js
WebGL and three.js
Anton Narusberg
 
From Hello World to the Interactive Web with Three.js: Workshop at FutureJS 2014
From Hello World to the Interactive Web with Three.js: Workshop at FutureJS 2014
Verold
 
Introduction to three.js
Introduction to three.js
yuxiang21
 
Intro to Three.js
Intro to Three.js
Kentucky JavaScript Users Group
 
Creating Applications with WebGL and Three.js
Creating Applications with WebGL and Three.js
Future Insights
 
[JS EXPERIENCE 2018] Jogos em JavaScript com WebGL - Juliana Negreiros, Codem...
[JS EXPERIENCE 2018] Jogos em JavaScript com WebGL - Juliana Negreiros, Codem...
iMasters
 
Introduction to threejs
Introduction to threejs
Gareth Marland
 
Introduction to three.js & Leap Motion
Introduction to three.js & Leap Motion
Lee Trout
 
ENEI16 - WebGL with Three.js
ENEI16 - WebGL with Three.js
José Ferrão
 
Three.js basics
Three.js basics
Vasilika Klimova
 
Портируем существующее Web-приложение в виртуальную реальность / Денис Радин ...
Портируем существующее Web-приложение в виртуальную реальность / Денис Радин ...
Ontico
 
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
JavaScript Meetup HCMC
 
Bs webgl소모임004
Bs webgl소모임004
Seonki Paik
 
CUDA Raytracing을 이용한 Voxel오브젝트 가시성 테스트
CUDA Raytracing을 이용한 Voxel오브젝트 가시성 테스트
YEONG-CHEON YOU
 
HTML5 Canvas - Let's Draw!
HTML5 Canvas - Let's Draw!
Phil Reither
 
HTML5 Canvas
HTML5 Canvas
Robyn Overstreet
 
Cocos2dを使ったゲーム作成の事例
Cocos2dを使ったゲーム作成の事例
Yuichi Higuchi
 
3D everywhere
3D everywhere
Vasilika Klimova
 
How to Hack a Road Trip with a Webcam, a GSP and Some Fun with Node
How to Hack a Road Trip with a Webcam, a GSP and Some Fun with Node
pdeschen
 
Html5 canvas
Html5 canvas
Gary Yeh
 
The State of JavaScript
The State of JavaScript
Domenic Denicola
 
Having fun with graphs, a short introduction to D3.js
Having fun with graphs, a short introduction to D3.js
Michael Hackstein
 
Making Games in JavaScript
Making Games in JavaScript
Sam Cartwright
 
Begin three.js.key
Begin three.js.key
Yi-Fan Liao
 
A Novice's Guide to WebGL
A Novice's Guide to WebGL
Krzysztof Kula
 
HTML 5 Canvas & SVG
HTML 5 Canvas & SVG
Ofir's Fridman
 
nunuStudio Geometrix 2017
nunuStudio Geometrix 2017
José Ferrão
 
Maps
Maps
boybuon205
 
Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.
UA Mobile
 

More Related Content

What's hot (20)

Introduction to three.js & Leap Motion
Introduction to three.js & Leap Motion
Lee Trout
 
ENEI16 - WebGL with Three.js
ENEI16 - WebGL with Three.js
José Ferrão
 
Three.js basics
Three.js basics
Vasilika Klimova
 
Портируем существующее Web-приложение в виртуальную реальность / Денис Радин ...
Портируем существующее Web-приложение в виртуальную реальность / Денис Радин ...
Ontico
 
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
JavaScript Meetup HCMC
 
Bs webgl소모임004
Bs webgl소모임004
Seonki Paik
 
CUDA Raytracing을 이용한 Voxel오브젝트 가시성 테스트
CUDA Raytracing을 이용한 Voxel오브젝트 가시성 테스트
YEONG-CHEON YOU
 
HTML5 Canvas - Let's Draw!
HTML5 Canvas - Let's Draw!
Phil Reither
 
HTML5 Canvas
HTML5 Canvas
Robyn Overstreet
 
Cocos2dを使ったゲーム作成の事例
Cocos2dを使ったゲーム作成の事例
Yuichi Higuchi
 
3D everywhere
3D everywhere
Vasilika Klimova
 
How to Hack a Road Trip with a Webcam, a GSP and Some Fun with Node
How to Hack a Road Trip with a Webcam, a GSP and Some Fun with Node
pdeschen
 
Html5 canvas
Html5 canvas
Gary Yeh
 
The State of JavaScript
The State of JavaScript
Domenic Denicola
 
Having fun with graphs, a short introduction to D3.js
Having fun with graphs, a short introduction to D3.js
Michael Hackstein
 
Making Games in JavaScript
Making Games in JavaScript
Sam Cartwright
 
Begin three.js.key
Begin three.js.key
Yi-Fan Liao
 
A Novice's Guide to WebGL
A Novice's Guide to WebGL
Krzysztof Kula
 
HTML 5 Canvas & SVG
HTML 5 Canvas & SVG
Ofir's Fridman
 
nunuStudio Geometrix 2017
nunuStudio Geometrix 2017
José Ferrão
 
Introduction to three.js & Leap Motion
Introduction to three.js & Leap Motion
Lee Trout
 
ENEI16 - WebGL with Three.js
ENEI16 - WebGL with Three.js
José Ferrão
 
Портируем существующее Web-приложение в виртуальную реальность / Денис Радин ...
Портируем существующее Web-приложение в виртуальную реальность / Денис Радин ...
Ontico
 
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
3D Web Programming [Thanh Loc Vo , CTO Epsilon Mobile ]
JavaScript Meetup HCMC
 
Bs webgl소모임004
Bs webgl소모임004
Seonki Paik
 
CUDA Raytracing을 이용한 Voxel오브젝트 가시성 테스트
CUDA Raytracing을 이용한 Voxel오브젝트 가시성 테스트
YEONG-CHEON YOU
 
HTML5 Canvas - Let's Draw!
HTML5 Canvas - Let's Draw!
Phil Reither
 
Cocos2dを使ったゲーム作成の事例
Cocos2dを使ったゲーム作成の事例
Yuichi Higuchi
 
How to Hack a Road Trip with a Webcam, a GSP and Some Fun with Node
How to Hack a Road Trip with a Webcam, a GSP and Some Fun with Node
pdeschen
 
Html5 canvas
Html5 canvas
Gary Yeh
 
Having fun with graphs, a short introduction to D3.js
Having fun with graphs, a short introduction to D3.js
Michael Hackstein
 
Making Games in JavaScript
Making Games in JavaScript
Sam Cartwright
 
Begin three.js.key
Begin three.js.key
Yi-Fan Liao
 
A Novice's Guide to WebGL
A Novice's Guide to WebGL
Krzysztof Kula
 
nunuStudio Geometrix 2017
nunuStudio Geometrix 2017
José Ferrão
 

Similar to HTML5 game dev with three.js - HexGL (20)

Maps
Maps
boybuon205
 
Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.
UA Mobile
 
Learning Predictive Modeling with TSA and Kaggle
Learning Predictive Modeling with TSA and Kaggle
Yvonne K. Matos
 
Real life XNA
Real life XNA
Johan Lindfors
 
Exploring Canvas
Exploring Canvas
Kevin Hoyt
 
Intro to HTML5 Canvas
Intro to HTML5 Canvas
Juho Vepsäläinen
 
The Ring programming language version 1.5.3 book - Part 48 of 184
The Ring programming language version 1.5.3 book - Part 48 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 58 of 184
The Ring programming language version 1.5.3 book - Part 58 of 184
Mahmoud Samir Fayed
 
Pointer Events in Canvas
Pointer Events in Canvas
deanhudson
 
Need an detailed analysis of what this code-model is doing- Thanks #St.pdf
Need an detailed analysis of what this code-model is doing- Thanks #St.pdf
actexerode
 
Deep dive into deeplearn.js
Deep dive into deeplearn.js
Kai Sasaki
 
Stupid Canvas Tricks
Stupid Canvas Tricks
deanhudson
 
Html5 game programming overview
Html5 game programming overview
민태 김
 
The Ring programming language version 1.3 book - Part 38 of 88
The Ring programming language version 1.3 book - Part 38 of 88
Mahmoud Samir Fayed
 
Bindings: the zen of montage
Bindings: the zen of montage
Kris Kowal
 
Presentation: Plotting Systems in R
Presentation: Plotting Systems in R
Ilya Zhbannikov
 
Can someone please explain what the code below is doing and comment on.pdf
Can someone please explain what the code below is doing and comment on.pdf
kuldeepkumarapgsi
 
A More Flash Like Web?
A More Flash Like Web?
Murat Can ALPAY
 
COMPUTER GRAPHICS LAB MANUAL
COMPUTER GRAPHICS LAB MANUAL
Vivek Kumar Sinha
 
How to make a video game
How to make a video game
dandylion13
 
Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.
UA Mobile
 
Learning Predictive Modeling with TSA and Kaggle
Learning Predictive Modeling with TSA and Kaggle
Yvonne K. Matos
 
Exploring Canvas
Exploring Canvas
Kevin Hoyt
 
The Ring programming language version 1.5.3 book - Part 48 of 184
The Ring programming language version 1.5.3 book - Part 48 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 58 of 184
The Ring programming language version 1.5.3 book - Part 58 of 184
Mahmoud Samir Fayed
 
Pointer Events in Canvas
Pointer Events in Canvas
deanhudson
 
Need an detailed analysis of what this code-model is doing- Thanks #St.pdf
Need an detailed analysis of what this code-model is doing- Thanks #St.pdf
actexerode
 
Deep dive into deeplearn.js
Deep dive into deeplearn.js
Kai Sasaki
 
Stupid Canvas Tricks
Stupid Canvas Tricks
deanhudson
 
Html5 game programming overview
Html5 game programming overview
민태 김
 
The Ring programming language version 1.3 book - Part 38 of 88
The Ring programming language version 1.3 book - Part 38 of 88
Mahmoud Samir Fayed
 
Bindings: the zen of montage
Bindings: the zen of montage
Kris Kowal
 
Presentation: Plotting Systems in R
Presentation: Plotting Systems in R
Ilya Zhbannikov
 
Can someone please explain what the code below is doing and comment on.pdf
Can someone please explain what the code below is doing and comment on.pdf
kuldeepkumarapgsi
 
COMPUTER GRAPHICS LAB MANUAL
COMPUTER GRAPHICS LAB MANUAL
Vivek Kumar Sinha
 
How to make a video game
How to make a video game
dandylion13
 
Ad

Recently uploaded (20)

Coordinated Disclosure for ML - What's Different and What's the Same.pdf
Coordinated Disclosure for ML - What's Different and What's the Same.pdf
Priyanka Aash
 
9-1-1 Addressing: End-to-End Automation Using FME
9-1-1 Addressing: End-to-End Automation Using FME
Safe Software
 
Oh, the Possibilities - Balancing Innovation and Risk with Generative AI.pdf
Oh, the Possibilities - Balancing Innovation and Risk with Generative AI.pdf
Priyanka Aash
 
"Scaling in space and time with Temporal", Andriy Lupa.pdf
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
Mastering AI Workflows with FME by Mark Döring
Mastering AI Workflows with FME by Mark Döring
Safe Software
 
The Growing Value and Application of FME & GenAI
The Growing Value and Application of FME & GenAI
Safe Software
 
“MPU+: A Transformative Solution for Next-Gen AI at the Edge,” a Presentation...
“MPU+: A Transformative Solution for Next-Gen AI at the Edge,” a Presentation...
Edge AI and Vision Alliance
 
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Safe Software
 
Connecting Data and Intelligence: The Role of FME in Machine Learning
Connecting Data and Intelligence: The Role of FME in Machine Learning
Safe Software
 
" How to survive with 1 billion vectors and not sell a kidney: our low-cost c...
" How to survive with 1 billion vectors and not sell a kidney: our low-cost c...
Fwdays
 
Enhance GitHub Copilot using MCP - Enterprise version.pdf
Enhance GitHub Copilot using MCP - Enterprise version.pdf
Nilesh Gule
 
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
Tech-ASan: Two-stage check for Address Sanitizer - Yixuan Cao.pdf
Tech-ASan: Two-stage check for Address Sanitizer - Yixuan Cao.pdf
caoyixuan2019
 
Agentic AI for Developers and Data Scientists Build an AI Agent in 10 Lines o...
Agentic AI for Developers and Data Scientists Build an AI Agent in 10 Lines o...
All Things Open
 
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
pcprocore
 
Security Tips for Enterprise Azure Solutions
Security Tips for Enterprise Azure Solutions
Michele Leroux Bustamante
 
2025_06_18 - OpenMetadata Community Meeting.pdf
2025_06_18 - OpenMetadata Community Meeting.pdf
OpenMetadata
 
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Safe Software
 
Python Conference Singapore - 19 Jun 2025
Python Conference Singapore - 19 Jun 2025
ninefyi
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
Coordinated Disclosure for ML - What's Different and What's the Same.pdf
Coordinated Disclosure for ML - What's Different and What's the Same.pdf
Priyanka Aash
 
9-1-1 Addressing: End-to-End Automation Using FME
9-1-1 Addressing: End-to-End Automation Using FME
Safe Software
 
Oh, the Possibilities - Balancing Innovation and Risk with Generative AI.pdf
Oh, the Possibilities - Balancing Innovation and Risk with Generative AI.pdf
Priyanka Aash
 
"Scaling in space and time with Temporal", Andriy Lupa.pdf
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
Mastering AI Workflows with FME by Mark Döring
Mastering AI Workflows with FME by Mark Döring
Safe Software
 
The Growing Value and Application of FME & GenAI
The Growing Value and Application of FME & GenAI
Safe Software
 
“MPU+: A Transformative Solution for Next-Gen AI at the Edge,” a Presentation...
“MPU+: A Transformative Solution for Next-Gen AI at the Edge,” a Presentation...
Edge AI and Vision Alliance
 
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Safe Software
 
Connecting Data and Intelligence: The Role of FME in Machine Learning
Connecting Data and Intelligence: The Role of FME in Machine Learning
Safe Software
 
" How to survive with 1 billion vectors and not sell a kidney: our low-cost c...
" How to survive with 1 billion vectors and not sell a kidney: our low-cost c...
Fwdays
 
Enhance GitHub Copilot using MCP - Enterprise version.pdf
Enhance GitHub Copilot using MCP - Enterprise version.pdf
Nilesh Gule
 
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
Tech-ASan: Two-stage check for Address Sanitizer - Yixuan Cao.pdf
Tech-ASan: Two-stage check for Address Sanitizer - Yixuan Cao.pdf
caoyixuan2019
 
Agentic AI for Developers and Data Scientists Build an AI Agent in 10 Lines o...
Agentic AI for Developers and Data Scientists Build an AI Agent in 10 Lines o...
All Things Open
 
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
pcprocore
 
Security Tips for Enterprise Azure Solutions
Security Tips for Enterprise Azure Solutions
Michele Leroux Bustamante
 
2025_06_18 - OpenMetadata Community Meeting.pdf
2025_06_18 - OpenMetadata Community Meeting.pdf
OpenMetadata
 
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Safe Software
 
Python Conference Singapore - 19 Jun 2025
Python Conference Singapore - 19 Jun 2025
ninefyi
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
Ad

HTML5 game dev with three.js - HexGL

  • 2. • Thibaut Despoulain (@bkcore – bkcore.com) • 22 year-old student in Computer Engineering • University of Technology of Belfort-Montbéliard (France) • Web dev and 3D enthousiast • The guy behind the HexGL project
  • 4. • Fast-paced, futuristic racing game • Inspired by the F-Zero and Wipeout series • HTML5, JavaScript, WebGL (via Three.js) • Less than 2 months • Just me.
  • 9. • JavaScript API • OpenGL ES 2.0 • Chrome, FireFox, (Opera, Safari) • <Canvas> (HTML5)
  • 11. • Rendering engine • Maintained by Ricardo Cabello (MrDoob) and Altered Qualia • R50/stable • + : Active community, stable, updated frequently • - : Documentation
  • 15. • First « real » game • 2 months to learn and code • Little to no modeling and texturing skills • Physics? Controls? Gameplay?
  • 16. • Last time I could have 2 months free • Visibility to get an internship • Huge learning opportunity • Explore Three.js for good
  • 18. • Third-party physics engine (rejected) – Slow learning curve – Not really meant for racing games
  • 19. • Ray casting (rejected) – Heavy perfomance-wise – Needs Octree-like structure – > too much time to learn and implement
  • 20. • Home-made 2D approximation – Little to no learning curve – Easy to implement with 2D maps – Pretty fast – > But with some limitations
  • 23. • Home-made 2D approximation – No track overlap – Limited track twist and gradient – Accuracy depends on map resolution – > Enough for what I had in mind
  • 25. • No pixel getter on JS Image object/tag • Canvas2D to the rescue
  • 26. Load data Draw it on a Get canvas Drawing Getting Loading texture with JS Canvas using pixels using Image object 2D context getImageData()
  • 27. • ImageData (BKcore package) – Github.com/Bkcore/bkcore-js var a = new bkcore.ImageData(path, callback); //… a.getPixel(x, y); a.getPixelBilinear(xf, yf); // -> {r, g, b, a};
  • 28. Game loop: Convert world position to pixel indexes Get current pixel intensity (red) If pixel is not white: Collision Test pixels relatively (front, left, right) :end
  • 29. Front Left Right Track Void
  • 30. Front Front Current Gradient Left Right Left Right Height map Tilt
  • 34. Model .OBJ Python Three.js Materials converter JSON model .MTL $ python convert_obj_three.py -i mesh.obj -o mesh.js
  • 35. var scene = new THREE.Scene(); var loader = new THREE.JSONLoader(); var createMesh = function(geometry) { var mesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial()); mesh.position.set(0, 0, 0); mesh.scale.set(3, 3, 3); scene.add(mesh); }; loader.load("mesh.js", createMesh);
  • 37. var renderer = new THREE.WebGLRenderer({ antialias: false, clearColor: 0x000000 }); renderer.autoClear = false; renderer.sortObjects = false; renderer.setSize(width, height); document.body.appendChild(renderer.domElement);
  • 38. renderer.gammaInput = true; renderer.gammaOutput = true; renderer.shadowMapEnabled = true; renderer.shadowMapSoft = true;
  • 40. • Blinn-phong – Diffuse + Specular + Normal + Environment maps • THREE.ShaderLib.normal – > Per vertex point lights • Custom shader with per-pixel point lights for the road – > Booster light
  • 42. var boosterSprite = new THREE.Sprite( { map: spriteTexture, blending: THREE.AdditiveBlending, useScreenCoordinates: false, color: 0xffffff }); boosterSprite.mergeWith3D = false; boosterMesh.add(boosterSprite);
  • 44. var material = new THREE.ParticleBasicMaterial({ color: 0xffffff, map: THREE.ImageUtils.loadTexture(“tex.png”), size: 4, blending: THREE.AdditiveBlending, depthTest: false, transparent: true, vertexColors: true, sizeAttenuation: true });
  • 45. var pool = []; var geometry = new THREE.Geometry(); geometry.dynamic = true; for(var i = 0; i < 1000; ++i) { var p = new bkcore.Particle(); pool.push(p); geometry.vertices.push(p.position); geometry.colors.push(p.color); }
  • 46. bkcore.Particle = function() { this.position = new THREE.Vector3(); this.velocity = new THREE.Vector3(); this.force = new THREE.Vector3(); this.color = new THREE.Color(0x000000); this.basecolor = new THREE.Color(0x000000); this.life = 0.0; this.available = true; }
  • 47. var system = new THREE.ParticleSystem( geometry, material ); system.sort = false; system.position.set(x, y, z); system.rotation.set(a, b, c); scene.add(system);
  • 48. // Particle physics var p = pool[i]; p.position.addSelf(p.velocity); //… geometry.verticesNeedUpdate = true; geometry.colorsNeedUpdate = true;
  • 49. • Particles (BKcore package) – Github.com/BKcore/Three-extensions
  • 50. var clouds = new bkcore.Particles({ opacity: 0.8, tint: 0xffffff, color: 0x666666, color2: 0xa4f1ff, texture: THREE.ImageUtils.loadTexture(“cloud.png”), blending: THREE.NormalBlending, size: 6, life: 60, max: 500, spawn: new THREE.Vector3(3, 3, 0), spawnRadius: new THREE.Vector3(1, 1, 2), velocity: new THREE.Vector3(0, 0, 4), randomness: new THREE.Vector3(5, 5, 1) });
  • 53. • Built-in support for off-screen passes • Already has some pre-made post effects – Bloom – FXAA • Easy to use and Extend • Custom shaders
  • 54. var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false }; var renderTarget = new THREE.WebGLRenderTarget( width, height, renderTargetParameters );
  • 55. var composer = new THREE.EffectComposer( renderer, renderTarget ); composer.addPass( … ); composer.render();
  • 56. • Generic passes – RenderPass – ShaderPass – SavePass – MaskPass • Pre-made passes – BloomPass – FilmPass – Etc.
  • 57. var renderModel = new THREE.RenderPass( scene, camera ); renderModel.clear = false; composer.addPass(renderModel);
  • 58. var effectBloom = new THREE.BloomPass( 0.8, // Strengh 25, // Kernel size 4, // Sigma 256 // Resolution ); composer.addPass(effectBloom);
  • 60. var hexvignette: { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, tHex: { type: "t", value: 1, texture: null}, size: { type: "f", value: 512.0}, color: { type: "c", value: new THREE.Color(0x458ab1) } }, fragmentShader: [ "uniform float size;", "uniform vec3 color;", "uniform sampler2D tDiffuse;", "uniform sampler2D tHex;", "varying vec2 vUv;", "void main() { ... }" ].join("n") };
  • 61. var effectHex = new THREE.ShaderPass(hexvignette); effectHex.uniforms['size'].value = 512.0; effectHex.uniforms['tHex'].texture = hexTexture; composer.addPass(effectHex); //… effectHex.renderToScreen = true;