Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                .three
              
            
!

CSS

              
                body, html
  overflow: hidden
              
            
!

JS

              
                #/////////////////////////////////#
# VARS

webgl = null
gui   = null

cubeMap = null
mouseX = 0
mouseY = -150
windowHalfX = window.innerWidth / 2
windowHalfY = window.innerHeight / 2

# is mobile?
isMobile = ->
	/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test navigator.userAgent
  
console.log isMobile

# cors bypass for codepen
THREE.ImageUtils.crossOrigin = ''

# universal metal texture
metalTexture = THREE.ImageUtils.loadTexture("https://s3-us-west-2.amazonaws.com/s.cdpn.io/21693/metalblared-136.jpg")
metalTexture.minFilter = THREE.NearestFilter
metalTexture.wrapT = THREE.RepeatWrapping
metalTexture.wrapS = THREE.RepeatWrapping
metalTexture.repeat.set(5, 5)

#/////////////////////////////////#
# MAIN + INIT

init = ->
  webgl = new Webgl(window.innerWidth, window.innerHeight)
  $('.three').append webgl.renderer.domElement
  $(window).on 'resize', resizeHandler
  $(window).on 'mousemove', mouseMoveHandler
  animate()

resizeHandler = ->
  webgl.resize window.innerWidth, window.innerHeight

mouseMoveHandler = (e) ->
  mouseX = e.clientX - windowHalfX
  mouseY = e.clientY - windowHalfY
  
animate = ->
  requestAnimationFrame animate
  webgl.render()

$(document).ready init


#/////////////////////////////////
# Three.js Scene Basics

Webgl = do ->

  Webgl = (width, height) ->
    # Basic three.js setup
    @scene = new (THREE.Scene)
    @scene.fog = new THREE.FogExp2( 0x010101, 0.00025 )
    @renderer = new (THREE.WebGLRenderer)(antialias: true)
    @renderer.setSize width, height
    @renderer.setPixelRatio(window.devicePixelRatio)
    @renderer.setClearColor 0x000000
    
    # main cam
    @camera = new (THREE.PerspectiveCamera)(25, width / height, 1, 10000)
    @camera.position.set 0, 1500, 3500
    @camera.lookAt new THREE.Vector3(0, 0, 1000)
    @scene.add @camera
    
    # cam helper so I can see where this is pointed
    @camHelper = new THREE.CameraHelper @camera
    #@scene.add @camHelper
    
    # test cam so I can position shit
    @testCam = new (THREE.PerspectiveCamera)(50, width / height, 1, 100000)
    @testCam.position.set 3000, 2000, 5000
    @testCam.lookAt new THREE.Vector3(0, 0, 0)
    
    # device orientation controls - view on mobile!
    if isMobile()
      @controls = new THREE.DeviceOrientationControls(@camera)
    
    # Lighting
    @lighting = new Lights
    @scene.add @lighting
    
    # Skybox
    @skybox = new Skybox
    #@scene.add @skybox

    # Ground Plane
    @plane = new Plane
    @plane.position.set 0, 0, 0
    @scene.add @plane
    
    # Terrain
    @terrain = new Terrain
    @scene.add @terrain
    
    # Cube Grid
    @grid = new Grid
    @grid.position.set 0, 0, -6000
    @scene.add @grid
    
    # setup post-processing
    @composer = new THREE.EffectComposer(@renderer)
    @composer.addPass new THREE.RenderPass(@scene, @camera)
    
    # add a bleach pass
    @shaderEffect = new THREE.ShaderPass(THREE.BleachBypassShader)
    @shaderEffect.uniforms["opacity"].value = 0.95
    @composer.addPass @shaderEffect
    
    # add a bloom pass
    @bloomEffect = new THREE.BloomPass(5.5)
    #@composer.addPass @bloomEffect
    
    # add a film pass
    @filmPass = new THREE.FilmPass(0.8, 0.25, 256, false)
    
    # render to screen so we can see something
    @filmPass.renderToScreen = true
    @composer.addPass @filmPass
    
    # exit init
    return
  
  

  Webgl::resize = (width, height) ->
    @camera.aspect = width / height
    @camera.updateProjectionMatrix()
    @renderer.setSize width, height
    return

  Webgl::render = ->
    
    # cam controls
    @camera.position.x += ( (mouseX * 2) - @camera.position.x ) * 0.05
    camY = @camera.position.y += ( - (mouseY * 6) - @camera.position.y ) * 0.05
    @camera.position.y = Math.max camY, 135
    @camera.lookAt @scene.position
    
    # device orientation controls only on mobile
    if isMobile()
      @controls.update()
  
    # post processing render
    #if @composer
    #  @composer.render()

    # update things
    @plane.update()
    @lighting.update()
    @terrain.update()
    @grid.update()
    
    # render the scene
    @renderer.render @scene, @camera
    
    return

  Webgl


  
#/////////////////////////////////
# 3 Point Lighting

Lights = do ->
  
  Lights = ->
    THREE.Object3D.call this
    
    # helper geo, for test positioning only
    #sphere = new THREE.SphereGeometry( 20, 16, 8 )
        
    # lighting colors
    blue = 0x00FFED
    yellow = 0xEB3742

    # blue light
    @light1 = new THREE.PointLight( blue, 10 )
    @light1.position.set -400, 600, 0
    #@light1.add new (THREE.Mesh)(sphere, new (THREE.MeshBasicMaterial)(color: blue))
    @add @light1

    # yellow light
    @light2 = new THREE.PointLight( yellow, 15 )
    @light2.position.set 400, 600, 0
    #@light2.add new (THREE.Mesh)(sphere, new (THREE.MeshBasicMaterial)(color: yellow))
    @add @light2
    
    # white light
    @light3 = new THREE.SpotLight( 0xEBAC9F, 25 )
    @light3.position.set 500, 1000, 3500
    #@light3.add new (THREE.Mesh)(sphere, new (THREE.MeshBasicMaterial)(color: 0xF7FFE6))
    @add @light3
    
  Lights.prototype = new (THREE.Object3D)
  Lights::constructor = Lights
  
  Lights::update = ->
    time = Date.now() * 0.0005
    @light1.position.x = Math.sin( time * 0.7 ) * 1000
    @light1.position.z = Math.cos( time * 0.3 ) * 500

    @light2.position.x = Math.cos( time * 0.5 ) * 1000
    @light2.position.z = Math.sin( time * 0.7 ) * 500
  
  Lights
  

#/////////////////////////////////
# Skybox

Skybox = do ->

  Skybox = ->
    THREE.Object3D.call this
    
    urls = [
      'https://s3-us-west-2.amazonaws.com/s.cdpn.io/21693/disco-0001.jpg'
      'https://s3-us-west-2.amazonaws.com/s.cdpn.io/21693/disco-0002.jpg'
      'https://s3-us-west-2.amazonaws.com/s.cdpn.io/21693/disco-0003.jpg'
      'https://s3-us-west-2.amazonaws.com/s.cdpn.io/21693/disco-0004.jpg'
      'https://s3-us-west-2.amazonaws.com/s.cdpn.io/21693/disco-0005.jpg'
      'https://s3-us-west-2.amazonaws.com/s.cdpn.io/21693/disco-0006.jpg'
    ]
    cubeMap = THREE.ImageUtils.loadTextureCube(urls)
    # load textures
    cubeMap.format = THREE.RGBFormat
    shader = THREE.ShaderLib['cube']
    # init cube shader from built-in lib
    shader.uniforms['tCube'].value = cubeMap
    # apply textures to shader
    # create shader material
    skyBoxMaterial = new (THREE.ShaderMaterial)(
      fragmentShader: shader.fragmentShader
      vertexShader: shader.vertexShader
      uniforms: shader.uniforms
      depthWrite: false
      side: THREE.BackSide)
    # create skybox mesh
    @mesh = new (THREE.Mesh)(
      new (THREE.BoxGeometry)(1500, 1500, 1500)
      skyBoxMaterial)
    @add @mesh

  Skybox.prototype = new (THREE.Object3D)
  Skybox::constructor = Skybox

  Skybox
 
#/////////////////////////////////
# Ground Plane  

Plane = do ->

  Plane = ->
    THREE.Object3D.call this
    geometry = new (THREE.PlaneBufferGeometry)(5000, 6000, 8, 8)
    
    wireframeTexture = THREE.ImageUtils.loadTexture("https://s3-us-west-2.amazonaws.com/s.cdpn.io/21693/wireframe-mesh.png")
    wireframeTexture.minFilter = THREE.NearestFilter
    wireframeTexture.wrapT = THREE.RepeatWrapping
    wireframeTexture.wrapS = THREE.RepeatWrapping
    wireframeTexture.repeat.set(4, 4)
    
    material = new (THREE.MeshLambertMaterial)(
      map: wireframeTexture
      color: 0x232323)
    
    @mesh = new (THREE.Mesh)(geometry, material)
    @mesh.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) )
    @add @mesh

  Plane.prototype = new (THREE.Object3D)
  Plane::constructor = Plane

  Plane::update = ->
    @mesh.material.map.offset.y += 0.00675

  Plane
  
#/////////////////////////////////
# Terrain

Terrain = do ->

  Terrain = ->
    THREE.Object3D.call this

    xS = 15
    yS = 15
    @xSize = 1750
    @ySize = 4000
    @yOffset = 1.4
    @speed = 10
    
    @terrainOpts =
      heightmap: THREE.Terrain.PerlinDiamond
      easing: THREE.Terrain.Linear
      #frequency: 1.5
      turbulent: true
      material:
        new (THREE.MeshPhongMaterial)(
          shading: THREE.FlatShading
          color: 0x232323
          specular: 0x2C6855
          shininess: 0
          map: metalTexture
          bumpMap: metalTexture
          bumpScale: 0.35
          envMap: cubeMap)
      maxHeight: 650
      minHeight: -150
      useBufferGeometry: true
      xSegments: xS
      xSize: @xSize
      ySegments: yS
      ySize: @ySize
      after: (vertices, options) ->
        THREE.Terrain.Edges vertices, options, false, 256, THREE.Terrain.Linear
    
    @mesh = THREE.Terrain(@terrainOpts)
    @add @mesh
    

    
  Terrain.prototype = new (THREE.Object3D)
  Terrain::constructor = Terrain

  Terrain::update = ->
    @mesh.position.z += @speed
    if @mesh.position.z > @ySize * @yOffset
      @remove @mesh
      @mesh = THREE.Terrain(@terrainOpts)
      @add @mesh
      @mesh.position.z = -@ySize * @yOffset
    
  Terrain
  
  
#/////////////////////////////////
# Grid  

Grid = do ->

  Grid = ->
    THREE.Object3D.call this
    
    # cuuuube
    @cube = new (THREE.Mesh)(
      new (THREE.BoxGeometry)(15, 15, 15)
      new (THREE.MeshLambertMaterial)(
        shading: THREE.FlatShading
        color: 0x222222)
    )
    
    @grid = new THREE.Object3D()
    
    # make a grid
    @gridPart = @cube
    i = 0
    gridMaxX = 750
    gridMaxZ = 1500
    while i < gridMaxX
      j = 0
      while j < gridMaxZ
        cube = @gridPart.clone()
        randScale = Math.floor(Math.random() * 5) + 0.75
        cube.scale.set(1, randScale, 1)
        cube.position.set i, 0, j
        @grid.add cube
        j += 100
      i += 100
    @add @grid
    
  Grid.prototype = new (THREE.Object3D)
  Grid::constructor = Grid

  Grid::update = ->
    xRange = 2000
    @grid.position.z += 10
    if @grid.position.z > 9250
      @grid.position.x = Math.floor(Math.random() * xRange) + -xRange  
      @grid.position.z = -1500

  Grid
              
            
!
999px

Console