Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save 525c1e21-bd67-4735-ac99-b4b0e5262290/875750 to your computer and use it in GitHub Desktop.
Save 525c1e21-bd67-4735-ac99-b4b0e5262290/875750 to your computer and use it in GitHub Desktop.
THREE.WebGLRenderer = (parameters) ->
_canvas = document.createElement 'canvas'
_gl = null
_oldProgram = null
_oldFramebuffer = null
_this = this
# gl state cache
_oldDoubleSided = null
_oldFlipSided = null
_oldBlending = null
_oldDepth = null
_viewportX = 0
_viewportY = 0
_viewportWidth = 0
_viewportHeight = 0
# camera matrices caches
_frustum = [
new THREE.Vector4
new THREE.Vector4
new THREE.Vector4
new THREE.Vector4
new THREE.Vector4
new THREE.Vector4
]
_projScreenMatrix = new THREE.Matrix4
_projectionMatrixArray = new Float32Array 16
_viewMatrixArray = new Float32Array 16
_vector3 = new THREE.Vector4
# light arrays cache
_lights =
ambient: [0, 0, 0]
directional: {length: 0, colors: new Array, positions: new Array}
point: {length: 0, colors: new Array, positions: new Array}
# parameters defaults
antialias = true
clearColor = new THREE.Color 0x000000
clearAlpha = 0
if parameters
if parameters.antialias? then antialias = parameters.antialias
if parameters.clearColor? then clearColor.setHex parameters.clearColor
if parameters.clearAlpha? then clearAlpha = parameters.clearAlpha
@maxMorphTargets = 8
@domElement = _canvas
@autoClear = true
@sortObjects = true
do -> # init
try
if !(_gl = _canvas.getContext('experimental-webgl', {antialias: antialias}))
throw 'Error creating WebGL context.'
catch e
console.error e
_gl.clearColor 0, 0, 0, 1
_gl.clearDepth 1
_gl.enable _gl.DEPTH_TEST
_gl.depthFunc _gl.LEQUAL
_gl.frontFace _gl.CCW
_gl.cullFace _gl.BACK
_gl.enable _gl.CULL_FACE
_gl.enable _gl.BLEND
_gl.blendFunc _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA
_gl.clearColor clearColor.r, clearColor.g, clearColor.b, clearAlpha
_cullEnabled = true
@context = _gl
@setSize = (width, height) ->
_canvas.width = width
_canvas.height = height
@setViewport 0, 0, _canvas.width, _canvas.height
@setViewport = (x, y, width, height) ->
_viewportX = x
_viewportY = y
_viewportWidth = width
_viewportHeight = height
_gl.viewport _viewportX, _viewportY, _viewportWidth, _viewportHeight
@setScissor = (x, y, width, height) -> _gl.scissor x, y, width, height
@enableScissorTest = (enable) -> if enable then _gl.enable _gl.SCISSOR_TEST else _gl.disable _gl.SCISSOR_TEST
@enableDepthBufferWrite = (enable) -> _gl.depthMask enable
@setClearColorHex = (hex, alpha) ->
color = new THREE.Color hex
_gl.clearColor color.r, color.g, color.b, alpha
@setClearColor = (color, alpha) -> _gl.clearColor color.r, color.g, color.b, alpha
@clear = -> _gl.clear _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT
setupLights = (program, lights) ->
l = null
ll = null
light = null
r = 0
g = 0
b = 0
color = null
position = null
intensity = null
zlights = _lights
dcolors = zlights.directional.colors
dpositions = zlights.directional.positions
pcolors = zlights.point.colors
ppositions = zlights.point.positions
dlength = 0
plength = 0
doffset = 0
poffset = 0
for light in lights
color = light.color
position = light.position
intensity = light.intensity
if light instanceof THREE.AmbientLight
r += color.r
g += color.g
b += color.b
else if light instanceof THREE.DirectionalLight
doffset = dlength * 3
dcolors[doffset] = color.r * intensity
dcolors[doffset + 1] = color.g * intensity
dcolors[doffset + 2] = color.b * intensity
dpositions[doffset] = position.x
dpositions[doffset + 1] = position.y
dpositions[doffset + 2] = position.z
dlength += 1
else if light instanceof THREE.PointLight
poffset = plength * 3
pcolors[poffset] = color.r * intensity
pcolors[poffset + 1] = color.g * intensity
pcolors[poffset + 2] = color.b * intensity
ppositions[poffset] = position.x
ppositions[poffset + 1] = position.y
ppositions[poffset + 2] = position.z
plength += 1
for l in [(dlength * 3)...dcolors.length] then dcolors[l] = 0.0
for l in [(plength * 3)...pcolors.length] then pcolors[l] = 0.0
zlights.point.length = plength
zlights.directional.length = dlength
zlights.ambient[0] = r
zlights.ambient[1] = g
zlights.ambient[2] = b
createParticleBuffers = (geometry) ->
geometry.__webGLVertexBuffer = _gl.createBuffer()
geometry.__webGLColorBuffer = _gl.createBuffer()
createLineBuffers = (geometry) ->
geometry.__webGLVertexBuffer = _gl.createBuffer()
geometry.__webGLColorBuffer = _gl.createBuffer()
createRibbonBuffers = (geometry) ->
geometry.__webGLVertexBuffer = _gl.createBuffer()
geometry.__webGLColorBuffer = _gl.createBuffer()
createMeshBuffers = (geometryGroup) ->
geometryGroup.__webGLVertexBuffer = _gl.createBuffer()
geometryGroup.__webGLNormalBuffer = _gl.createBuffer()
geometryGroup.__webGLTangentBuffer = _gl.createBuffer()
geometryGroup.__webGLColorBuffer = _gl.createBuffer()
geometryGroup.__webGLUVBuffer = _gl.createBuffer()
geometryGroup.__webGLUV2Buffer = _gl.createBuffer()
geometryGroup.__webGLSkinVertexABuffer = _gl.createBuffer()
geometryGroup.__webGLSkinVertexBBuffer = _gl.createBuffer()
geometryGroup.__webGLSkinIndicesBuffer = _gl.createBuffer()
geometryGroup.__webGLSkinWeightsBuffer = _gl.createBuffer()
geometryGroup.__webGLFaceBuffer = _gl.createBuffer()
geometryGroup.__webGLLineBuffer = _gl.createBuffer()
if geometryGroup.numMorphTargets
geometryGroup.__webGLMorphTargetsBuffers = new Array
for m in [0...geometryGroup.numMorphTargets] then geometryGroup.__webGLMorphTargetsBuffers.push _gl.createBuffer()
initLineBuffers = (geometry) ->
nvertices = geometry.vertices.length
geometry.__vertexArray = new Float32Array nvertices * 3
geometry.__colorArray = new Float32Array nvertices * 3
geometry.__webGLLineCount = nvertices
initRibbonBuffers = (geometry) ->
nvertices = geometry.vertices.length
geometry.__vertexArray = new Float32Array nvertices * 3
geometry.__colorArray = new Float32Array nvertices * 3
geometry.__webGLVertexCount = nvertices
initParticleBuffers = (geometry) ->
nvertices = geometry.vertices.length
geometry.__vertexArray = new Float32Array nvertices * 3
geometry.__colorArray = new Float32Array nvertices * 3
geometry.__sortArray = new Array
geometry.__webGLParticleCount = nvertices
initMeshBuffers = (geometryGroup, object) ->
f = null
fl = null
nvertices = 0
ntris = 0
nlines = 0
obj_faces = object.geometry.faces
chunk_faces = geometryGroup.faces
for f in [0...chunk_faces.length]
face = obj_faces[chunk_faces[f]]
if face instanceof THREE.Face3
nvertices += 3
ntris += 1
nlines += 3
else if face instanceof THREE.Face4
nvertices += 4
ntris += 2
nlines += 4
# TODO: only create arrays for attributes existing in the object
geometryGroup.__vertexArray = new Float32Array nvertices * 3
geometryGroup.__normalArray = new Float32Array nvertices * 3
geometryGroup.__tangentArray = new Float32Array nvertices * 4
geometryGroup.__colorArray = new Float32Array nvertices * 3
geometryGroup.__uvArray = new Float32Array nvertices * 2
geometryGroup.__uv2Array = new Float32Array nvertices * 2
geometryGroup.__skinVertexAArray = new Float32Array nvertices * 4
geometryGroup.__skinVertexBArray = new Float32Array nvertices * 4
geometryGroup.__skinIndexArray = new Float32Array nvertices * 4
geometryGroup.__skinWeightArray = new Float32Array nvertices * 4
geometryGroup.__faceArray = new Uint16Array ntris * 3
geometryGroup.__lineArray = new Uint16Array nlines * 2
geometryGroup.__needsSmoothNormals = bufferNeedsSmoothNormals geometryGroup, object
geometryGroup.__webGLFaceCount = ntris * 3
geometryGroup.__webGLLineCount = nlines * 2
if geometryGroup.numMorphTargets
geometryGroup.__morphTargetsArrays = new Array
for m in [0...geometryGroup.numMorphTargets]
geometryGroup.__morphTargetsArrays.push new Float32Array(nvertices * 3)
setMeshBuffers = (geometryGroup, object, hint) ->
f = null
fl = null
fi = null
face = null
vertexNormals = null
faceNormal = null
normal = null
uv = uv2 = null
v1 = v2 = v3 = v4 = null
t1 = t2 = t3 = t4 = null
c1 = c2 = c3 = c4 = null
sw1 = sw2 = sw3 = sw4 = null
si1 = si2 = si3 = si4 = null
sa1 = sa2 = sa3 = sa4 = null
sb1 = sb2 = sb3 = sb4 = null
m = ml = i = null
vn = uvi = uv2i = null
vk = vkl = vka = null
vertexIndex = 0
offset = 0
offset_uv = 0
offset_uv2 = 0
offset_face = 0
offset_normal = 0
offset_tangent = 0
offset_line = 0
offset_color = 0
offset_skin = 0
offset_morphTarget = 0
vertexArray = geometryGroup.__vertexArray
uvArray = geometryGroup.__uvArray
uv2Array = geometryGroup.__uv2Array
normalArray = geometryGroup.__normalArray
tangentArray = geometryGroup.__tangentArray
colorArray = geometryGroup.__colorArray
skinVertexAArray = geometryGroup.__skinVertexAArray
skinVertexBArray = geometryGroup.__skinVertexBArray
skinIndexArray = geometryGroup.__skinIndexArray
skinWeightArray = geometryGroup.__skinWeightArray
morphTargetsArrays = geometryGroup.__morphTargetsArrays
faceArray = geometryGroup.__faceArray
lineArray = geometryGroup.__lineArray
needsSmoothNormals = geometryGroup.__needsSmoothNormals
geometry = object.geometry
dirtyVertices = geometry.__dirtyVertices
dirtyElements = geometry.__dirtyElements
dirtyUvs = geometry.__dirtyUvs
dirtyNormals = geometry.__dirtyNormals
dirtyTangents = geometry.__dirtyTangents
dirtyColors = geometry.__dirtyColors
dirtyMorphTargets = geometry.__dirtyMorphTargets
vertices = geometry.vertices
chunk_faces = geometryGroup.faces
obj_faces = geometry.faces
obj_uvs = geometry.uvs
obj_uvs2 = geometry.uvs2
obj_colors = geometry.colors
obj_skinVerticesA = geometry.skinVerticesA
obj_skinVerticesB = geometry.skinVerticesB
obj_skinIndices = geometry.skinIndices
obj_skinWeights = geometry.skinWeights
morphTargets = geometry.morphTargets
for f in [0...chunk_faces.length]
fi = chunk_faces[f]
face = obj_faces[fi]
uv = obj_uvs[fi]
uv2 = obj_uvs2[fi]
vertexNormals = face.vertexNormals
faceNormal = face.normal
if face instanceof THREE.Face3
if dirtyVertices
v1 = vertices[face.a].position
v2 = vertices[face.b].position
v3 = vertices[face.c].position
vertexArray[offset] = v1.x
vertexArray[offset + 1] = v1.y
vertexArray[offset + 2] = v1.z
vertexArray[offset + 3] = v2.x
vertexArray[offset + 4] = v2.y
vertexArray[offset + 5] = v2.z
vertexArray[offset + 6] = v3.x
vertexArray[offset + 7] = v3.y
vertexArray[offset + 8] = v3.z
offset += 9
if dirtyMorphTargets
for vk in [0...morphTargets.length]
v1 = morphTargets[vk].vertices[face.a].position
v2 = morphTargets[vk].vertices[face.b].position
v3 = morphTargets[vk].vertices[face.c].position
vka = morphTargetsArrays[vk]
vka[offset_morphTarget + 0] = v1.x
vka[offset_morphTarget + 1] = v1.y
vka[offset_morphTarget + 2] = v1.z
vka[offset_morphTarget + 3] = v2.x
vka[offset_morphTarget + 4] = v2.y
vka[offset_morphTarget + 5] = v2.z
vka[offset_morphTarget + 6] = v3.x
vka[offset_morphTarget + 7] = v3.y
vka[offset_morphTarget + 8] = v3.z
offset_morphTarget += 9
if obj_skinWeights.length
sw1 = obj_skinWeights[face.a]
sw2 = obj_skinWeights[face.b]
sw3 = obj_skinWeights[face.c]
skinWeightArray[offset_skin] = sw1.x
skinWeightArray[offset_skin + 1] = sw1.y
skinWeightArray[offset_skin + 2] = sw1.z
skinWeightArray[offset_skin + 3] = sw1.w
skinWeightArray[offset_skin + 4] = sw2.x
skinWeightArray[offset_skin + 5] = sw2.y
skinWeightArray[offset_skin + 6] = sw2.z
skinWeightArray[offset_skin + 7] = sw2.w
skinWeightArray[offset_skin + 8] = sw3.x
skinWeightArray[offset_skin + 9] = sw3.y
skinWeightArray[offset_skin + 10] = sw3.z
skinWeightArray[offset_skin + 11] = sw3.w
# indices
si1 = obj_skinIndices[face.a]
si2 = obj_skinIndices[face.b]
si3 = obj_skinIndices[face.c]
skinIndexArray[offset_skin] = si1.x
skinIndexArray[offset_skin + 1] = si1.y
skinIndexArray[offset_skin + 2] = si1.z
skinIndexArray[offset_skin + 3] = si1.w
skinIndexArray[offset_skin + 4] = si2.x
skinIndexArray[offset_skin + 5] = si2.y
skinIndexArray[offset_skin + 6] = si2.z
skinIndexArray[offset_skin + 7] = si2.w
skinIndexArray[offset_skin + 8] = si3.x
skinIndexArray[offset_skin + 9] = si3.y
skinIndexArray[offset_skin + 10] = si3.z
skinIndexArray[offset_skin + 11] = si3.w
# vertices A
sa1 = obj_skinVerticesA[face.a]
sa2 = obj_skinVerticesA[face.b]
sa3 = obj_skinVerticesA[face.c]
skinVertexAArray[offset_skin] = sa1.x
skinVertexAArray[offset_skin + 1] = sa1.y
skinVertexAArray[offset_skin + 2] = sa1.z
skinVertexAArray[offset_skin + 3] = 1
skinVertexAArray[offset_skin + 4] = sa2.x
skinVertexAArray[offset_skin + 5] = sa2.y
skinVertexAArray[offset_skin + 6] = sa2.z
skinVertexAArray[offset_skin + 7] = 1
skinVertexAArray[offset_skin + 8] = sa3.x
skinVertexAArray[offset_skin + 9] = sa3.y
skinVertexAArray[offset_skin + 10] = sa3.z
skinVertexAArray[offset_skin + 11] = 1
# vertices B
sb1 = obj_skinVerticesB[face.a]
sb2 = obj_skinVerticesB[face.b]
sb3 = obj_skinVerticesB[face.c]
skinVertexBArray[offset_skin] = sb1.x
skinVertexBArray[offset_skin + 1] = sb1.y
skinVertexBArray[offset_skin + 2] = sb1.z
skinVertexBArray[offset_skin + 3] = 1
skinVertexBArray[offset_skin + 4] = sb2.x
skinVertexBArray[offset_skin + 5] = sb2.y
skinVertexBArray[offset_skin + 6] = sb2.z
skinVertexBArray[offset_skin + 7] = 1
skinVertexBArray[offset_skin + 8] = sb3.x
skinVertexBArray[offset_skin + 9] = sb3.y
skinVertexBArray[offset_skin + 10] = sb3.z
skinVertexBArray[offset_skin + 11] = 1
offset_skin += 12
if dirtyColors && obj_colors.length
c1 = obj_colors[face.a]
c2 = obj_colors[face.b]
c3 = obj_colors[face.c]
colorArray[offset_color] = c1.r
colorArray[offset_color + 1] = c1.g
colorArray[offset_color + 2] = c1.b
colorArray[offset_color + 3] = c2.r
colorArray[offset_color + 4] = c2.g
colorArray[offset_color + 5] = c2.b
colorArray[offset_color + 6] = c3.r
colorArray[offset_color + 7] = c3.g
colorArray[offset_color + 8] = c3.b
offset_color += 9
if dirtyTangents && geometry.hasTangents
t1 = vertices[face.a].tangent
t2 = vertices[face.b].tangent
t3 = vertices[face.c].tangent
tangentArray[offset_tangent] = t1.x
tangentArray[offset_tangent + 1] = t1.y
tangentArray[offset_tangent + 2] = t1.z
tangentArray[offset_tangent + 3] = t1.w
tangentArray[offset_tangent + 4] = t2.x
tangentArray[offset_tangent + 5] = t2.y
tangentArray[offset_tangent + 6] = t2.z
tangentArray[offset_tangent + 7] = t2.w
tangentArray[offset_tangent + 8] = t3.x
tangentArray[offset_tangent + 9] = t3.y
tangentArray[offset_tangent + 10] = t3.z
tangentArray[offset_tangent + 11] = t3.w
offset_tangent += 12
if dirtyNormals
if vertexNormals.length is 3 && needsSmoothNormals
for vn in vertexNormals
normalArray[offset_normal] = vn.x
normalArray[offset_normal + 1] = vn.y
normalArray[offset_normal + 2] = vn.z
offset_normal += 3
else
for i in [0...3]
normalArray[offset_normal] = faceNormal.x
normalArray[offset_normal + 1] = faceNormal.y
normalArray[offset_normal + 2] = faceNormal.z
offset_normal += 3
if dirtyUvs && uv
for uvi in uv
uvArray[offset_uv] = uvi.u
uvArray[offset_uv + 1] = uvi.v
offset_uv += 2
if dirtyUvs && uv2
for uv2i in uv2
uv2Array[offset_uv2] = uv2i.u
uv2Array[offset_uv2 + 1] = uv2i.v
offset_uv2 += 2
if dirtyElements
faceArray[offset_face] = vertexIndex
faceArray[offset_face + 1] = vertexIndex + 1
faceArray[offset_face + 2] = vertexIndex + 2
offset_face += 3
lineArray[offset_line] = vertexIndex
lineArray[offset_line + 1] = vertexIndex + 1
lineArray[offset_line + 2] = vertexIndex
lineArray[offset_line + 3] = vertexIndex + 2
lineArray[offset_line + 4] = vertexIndex + 1
lineArray[offset_line + 5] = vertexIndex + 2
offset_line += 6
vertexIndex += 3
else if face instanceof THREE.Face4
if dirtyVertices
v1 = vertices[face.a].position
v2 = vertices[face.b].position
v3 = vertices[face.c].position
v4 = vertices[face.d].position
vertexArray[offset] = v1.x
vertexArray[offset + 1] = v1.y
vertexArray[offset + 2] = v1.z
vertexArray[offset + 3] = v2.x
vertexArray[offset + 4] = v2.y
vertexArray[offset + 5] = v2.z
vertexArray[offset + 6] = v3.x
vertexArray[offset + 7] = v3.y
vertexArray[offset + 8] = v3.z
vertexArray[offset + 9] = v4.x
vertexArray[offset + 10] = v4.y
vertexArray[offset + 11] = v4.z
offset += 12
if dirtyMorphTargets
for vk in [0...morphTargets.length]
v1 = morphTargets[vk].vertices[face.a].position
v2 = morphTargets[vk].vertices[face.b].position
v3 = morphTargets[vk].vertices[face.c].position
v4 = morphTargets[vk].vertices[face.d].position
vka = morphTargetsArrays[vk]
vka[offset_morphTarget + 0] = v1.x
vka[offset_morphTarget + 1] = v1.y
vka[offset_morphTarget + 2] = v1.z
vka[offset_morphTarget + 3] = v2.x
vka[offset_morphTarget + 4] = v2.y
vka[offset_morphTarget + 5] = v2.z
vka[offset_morphTarget + 6] = v3.x
vka[offset_morphTarget + 7] = v3.y
vka[offset_morphTarget + 8] = v3.z
vka[offset_morphTarget + 9] = v4.x
vka[offset_morphTarget + 10] = v4.y
vka[offset_morphTarget + 11] = v4.z
offset_morphTarget += 12
if obj_skinWeights.length
# weights
sw1 = obj_skinWeights[face.a]
sw2 = obj_skinWeights[face.b]
sw3 = obj_skinWeights[face.c]
sw4 = obj_skinWeights[face.d]
skinWeightArray[offset_skin] = sw1.x
skinWeightArray[offset_skin + 1] = sw1.y
skinWeightArray[offset_skin + 2] = sw1.z
skinWeightArray[offset_skin + 3] = sw1.w
skinWeightArray[offset_skin + 4] = sw2.x
skinWeightArray[offset_skin + 5] = sw2.y
skinWeightArray[offset_skin + 6] = sw2.z
skinWeightArray[offset_skin + 7] = sw2.w
skinWeightArray[offset_skin + 8] = sw3.x
skinWeightArray[offset_skin + 9] = sw3.y
skinWeightArray[offset_skin + 10] = sw3.z
skinWeightArray[offset_skin + 11] = sw3.w
skinWeightArray[offset_skin + 12] = sw4.x
skinWeightArray[offset_skin + 13] = sw4.y
skinWeightArray[offset_skin + 14] = sw4.z
skinWeightArray[offset_skin + 15] = sw4.w
# indices
si1 = obj_skinIndices[face.a]
si2 = obj_skinIndices[face.b]
si3 = obj_skinIndices[face.c]
si4 = obj_skinIndices[face.d]
skinIndexArray[offset_skin] = si1.x
skinIndexArray[offset_skin + 1] = si1.y
skinIndexArray[offset_skin + 2] = si1.z
skinIndexArray[offset_skin + 3] = si1.w
skinIndexArray[offset_skin + 4] = si2.x
skinIndexArray[offset_skin + 5] = si2.y
skinIndexArray[offset_skin + 6] = si2.z
skinIndexArray[offset_skin + 7] = si2.w
skinIndexArray[offset_skin + 8] = si3.x
skinIndexArray[offset_skin + 9] = si3.y
skinIndexArray[offset_skin + 10] = si3.z
skinIndexArray[offset_skin + 11] = si3.w
skinIndexArray[offset_skin + 12] = si4.x
skinIndexArray[offset_skin + 13] = si4.y
skinIndexArray[offset_skin + 14] = si4.z
skinIndexArray[offset_skin + 15] = si4.w
# vertices A
sa1 = obj_skinVerticesA[face.a]
sa2 = obj_skinVerticesA[face.b]
sa3 = obj_skinVerticesA[face.c]
sa4 = obj_skinVerticesA[face.d]
skinVertexAArray[offset_skin] = sa1.x
skinVertexAArray[offset_skin + 1] = sa1.y
skinVertexAArray[offset_skin + 2] = sa1.z
skinVertexAArray[offset_skin + 3] = 1
skinVertexAArray[offset_skin + 4] = sa2.x
skinVertexAArray[offset_skin + 5] = sa2.y
skinVertexAArray[offset_skin + 6] = sa2.z
skinVertexAArray[offset_skin + 7] = 1
skinVertexAArray[offset_skin + 8] = sa3.x
skinVertexAArray[offset_skin + 9] = sa3.y
skinVertexAArray[offset_skin + 10] = sa3.z
skinVertexAArray[offset_skin + 11] = 1
skinVertexAArray[offset_skin + 12] = sa4.x
skinVertexAArray[offset_skin + 13] = sa4.y
skinVertexAArray[offset_skin + 14] = sa4.z
skinVertexAArray[offset_skin + 15] = 1
# vertices B
sb1 = obj_skinVerticesB[face.a]
sb2 = obj_skinVerticesB[face.b]
sb3 = obj_skinVerticesB[face.c]
sb4 = obj_skinVerticesB[face.d]
skinVertexBArray[offset_skin] = sb1.x
skinVertexBArray[offset_skin + 1] = sb1.y
skinVertexBArray[offset_skin + 2] = sb1.z
skinVertexBArray[offset_skin + 3] = 1
skinVertexBArray[offset_skin + 4] = sb2.x
skinVertexBArray[offset_skin + 5] = sb2.y
skinVertexBArray[offset_skin + 6] = sb2.z
skinVertexBArray[offset_skin + 7] = 1
skinVertexBArray[offset_skin + 8] = sb3.x
skinVertexBArray[offset_skin + 9] = sb3.y
skinVertexBArray[offset_skin + 10] = sb3.z
skinVertexBArray[offset_skin + 11] = 1
skinVertexBArray[offset_skin + 12] = sb4.x
skinVertexBArray[offset_skin + 13] = sb4.y
skinVertexBArray[offset_skin + 14] = sb4.z
skinVertexBArray[offset_skin + 15] = 1
offset_skin += 16
if dirtyColors && obj_colors.length
c1 = obj_colors[face.a]
c2 = obj_colors[face.b]
c3 = obj_colors[face.c]
c4 = obj_colors[face.d]
colorArray[offset_color] = c1.r
colorArray[offset_color + 1] = c1.g
colorArray[offset_color + 2] = c1.b
colorArray[offset_color + 3] = c2.r
colorArray[offset_color + 4] = c2.g
colorArray[offset_color + 5] = c2.b
colorArray[offset_color + 6] = c3.r
colorArray[offset_color + 7] = c3.g
colorArray[offset_color + 8] = c3.b
colorArray[offset_color + 9] = c4.r
colorArray[offset_color + 10] = c4.g
colorArray[offset_color + 11] = c4.b
offset_color += 12
if dirtyTangents && geometry.hasTangents
t1 = vertices[face.a].tangent
t2 = vertices[face.b].tangent
t3 = vertices[face.c].tangent
t4 = vertices[face.d].tangent
tangentArray[offset_tangent] = t1.x
tangentArray[offset_tangent + 1] = t1.y
tangentArray[offset_tangent + 2] = t1.z
tangentArray[offset_tangent + 3] = t1.w
tangentArray[offset_tangent + 4] = t2.x
tangentArray[offset_tangent + 5] = t2.y
tangentArray[offset_tangent + 6] = t2.z
tangentArray[offset_tangent + 7] = t2.w
tangentArray[offset_tangent + 8] = t3.x
tangentArray[offset_tangent + 9] = t3.y
tangentArray[offset_tangent + 10] = t3.z
tangentArray[offset_tangent + 11] = t3.w
tangentArray[offset_tangent + 12] = t4.x
tangentArray[offset_tangent + 13] = t4.y
tangentArray[offset_tangent + 14] = t4.z
tangentArray[offset_tangent + 15] = t4.w
offset_tangent += 16
if dirtyNormals
if vertexNormals.length is 4 && needsSmoothNormals
for vn in vertexNormals
vn = vertexNormals[i]
normalArray[offset_normal] = vn.x
normalArray[offset_normal + 1] = vn.y
normalArray[offset_normal + 2] = vn.z
offset_normal += 3
else
for i in [0...4]
normalArray[offset_normal] = faceNormal.x
normalArray[offset_normal + 1] = faceNormal.y
normalArray[offset_normal + 2] = faceNormal.z
offset_normal += 3
if dirtyUvs && uv
for uvi in uv
uvArray[offset_uv] = uvi.u
uvArray[offset_uv + 1] = uvi.v
offset_uv += 2
if dirtyUvs && uv2
for uv2i in uv2
uv2i = uv2[i]
uv2Array[offset_uv2] = uv2i.u
uv2Array[offset_uv2 + 1] = uv2i.v
offset_uv2 += 2
if dirtyElements
faceArray[offset_face] = vertexIndex
faceArray[offset_face + 1] = vertexIndex + 1
faceArray[offset_face + 2] = vertexIndex + 2
faceArray[offset_face + 3] = vertexIndex
faceArray[offset_face + 4] = vertexIndex + 2
faceArray[offset_face + 5] = vertexIndex + 3
offset_face += 6
lineArray[offset_line] = vertexIndex
lineArray[offset_line + 1] = vertexIndex + 1
lineArray[offset_line + 2] = vertexIndex
lineArray[offset_line + 3] = vertexIndex + 3
lineArray[offset_line + 4] = vertexIndex + 1
lineArray[offset_line + 5] = vertexIndex + 2
lineArray[offset_line + 6] = vertexIndex + 2
lineArray[offset_line + 7] = vertexIndex + 3
offset_line += 8
vertexIndex += 4
if dirtyVertices
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLVertexBuffer
_gl.bufferData _gl.ARRAY_BUFFER, vertexArray, hint
if dirtyMorphTargets
for vk in [0...morphTargets.length]
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLMorphTargetsBuffers[vk]
_gl.bufferData _gl.ARRAY_BUFFER, morphTargetsArrays[vk], hint
if dirtyColors && obj_colors.length
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLColorBuffer
_gl.bufferData _gl.ARRAY_BUFFER, colorArray, hint
if dirtyNormals
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLNormalBuffer
_gl.bufferData _gl.ARRAY_BUFFER, normalArray, hint
if dirtyTangents && geometry.hasTangents
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLTangentBuffer
_gl.bufferData _gl.ARRAY_BUFFER, tangentArray, hint
if dirtyUvs && offset_uv > 0
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLUVBuffer
_gl.bufferData _gl.ARRAY_BUFFER, uvArray, hint
if dirtyUvs && offset_uv2 > 0
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLUV2Buffer
_gl.bufferData _gl.ARRAY_BUFFER, uv2Array, hint
if dirtyElements
_gl.bindBuffer _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webGLFaceBuffer
_gl.bufferData _gl.ELEMENT_ARRAY_BUFFER, faceArray, hint
_gl.bindBuffer _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webGLLineBuffer
_gl.bufferData _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint
if offset_skin > 0
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLSkinVertexABuffer
_gl.bufferData _gl.ARRAY_BUFFER, skinVertexAArray, hint
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLSkinVertexBBuffer
_gl.bufferData _gl.ARRAY_BUFFER, skinVertexBArray, hint
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLSkinIndicesBuffer
_gl.bufferData _gl.ARRAY_BUFFER, skinIndexArray, hint
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLSkinWeightsBuffer
_gl.bufferData _gl.ARRAY_BUFFER, skinWeightArray, hint
setLineBuffers = (geometry, hint) ->
v = null
c = null
vertex = null
offset = null
vertices = geometry.vertices
colors = geometry.colors
vl = vertices.length
cl = colors.length
vertexArray = geometry.__vertexArray
colorArray = geometry.__colorArray
dirtyVertices = geometry.__dirtyVertices
dirtyColors = geometry.__dirtyColors
if dirtyVertices
for v in [0...vl]
vertex = vertices[v].position
offset = v * 3
vertexArray[offset] = vertex.x
vertexArray[offset + 1] = vertex.y
vertexArray[offset + 2] = vertex.z
_gl.bindBuffer _gl.ARRAY_BUFFER, geometry.__webGLVertexBuffer
_gl.bufferData _gl.ARRAY_BUFFER, vertexArray, hint
if dirtyColors
for c in [0...cl]
color = colors[c]
offset = c * 3
colorArray[offset] = color.r
colorArray[offset + 1] = color.g
colorArray[offset + 2] = color.b
_gl.bindBuffer _gl.ARRAY_BUFFER, geometry.__webGLColorBuffer
_gl.bufferData _gl.ARRAY_BUFFER, colorArray, hint
setRibbonBuffers = (geometry, hint) ->
v = null
c = null
vertex = null
offset = null
vertices = geometry.vertices
colors = geometry.colors
vl = vertices.length
cl = colors.length
vertexArray = geometry.__vertexArray
colorArray = geometry.__colorArray
dirtyVertices = geometry.__dirtyVertices
dirtyColors = geometry.__dirtyColors
if dirtyVertices
for v in [0...vl]
vertex = vertices[v].position
offset = v * 3
vertexArray[offset] = vertex.x
vertexArray[offset + 1] = vertex.y
vertexArray[offset + 2] = vertex.z
_gl.bindBuffer _gl.ARRAY_BUFFER, geometry.__webGLVertexBuffer
_gl.bufferData _gl.ARRAY_BUFFER, vertexArray, hint
if dirtyColors
for c in [0...cl]
color = colors[c]
offset = c * 3
colorArray[offset] = color.r
colorArray[offset + 1] = color.g
colorArray[offset + 2] = color.b
_gl.bindBuffer _gl.ARRAY_BUFFER, geometry.__webGLColorBuffer
_gl.bufferData _gl.ARRAY_BUFFER, colorArray, hint
setParticleBuffers = (geometry, hint, object) ->
v = null
c = null
vertex = null
offset = null
vertices = geometry.vertices
vl = vertices.length
colors = geometry.colors
cl = colors.length
vertexArray = geometry.__vertexArray
colorArray = geometry.__colorArray
sortArray = geometry.__sortArray
dirtyVertices = geometry.__dirtyVertices
dirtyElements = geometry.__dirtyElements
dirtyColors = geometry.__dirtyColors
if object.sortParticles
_projScreenMatrix.multiplySelf object.matrixWorld
for v in [0...vl]
vertex = vertices[v].position
_vector3.copy vertex
_projScreenMatrix.multiplyVector3 _vector3
sortArray[v] = [_vector3.z, v]
sortArray.sort (a, b) -> b[0] - a[0]
for v in [0...vl]
vertex = vertices[sortArray[v][1]].position
offset = v * 3
vertexArray[offset] = vertex.x
vertexArray[offset + 1] = vertex.y
vertexArray[offset + 2] = vertex.z
for c in [0...cl]
offset = c * 3
color = colors[sortArray[c][1]]
colorArray[offset] = color.r
colorArray[offset + 1] = color.g
colorArray[offset + 2] = color.b
else
if dirtyVertices
for v in [0...vl]
vertex = vertices[v].position
offset = v * 3
vertexArray[offset] = vertex.x
vertexArray[offset + 1] = vertex.y
vertexArray[offset + 2] = vertex.z
if dirtyColors
for c in [0...cl]
color = colors[c]
offset = c * 3
colorArray[offset] = color.r
colorArray[offset + 1] = color.g
colorArray[offset + 2] = color.b
if dirtyVertices || object.sortParticles
_gl.bindBuffer _gl.ARRAY_BUFFER, geometry.__webGLVertexBuffer
_gl.bufferData _gl.ARRAY_BUFFER, vertexArray, hint
if dirtyColors || object.sortParticles
_gl.bindBuffer _gl.ARRAY_BUFFER, geometry.__webGLColorBuffer
_gl.bufferData _gl.ARRAY_BUFFER, colorArray, hint
setMaterialShaders = (material, shaders) ->
material.fragmentShader = shaders.fragmentShader
material.vertexShader = shaders.vertexShader
material.uniforms = Uniforms.clone shaders.uniforms
refreshUniformsCommon = (uniforms, material) ->
# premultiply alpha
uniforms.diffuse.value.setRGB material.color.r * material.opacity, material.color.g * material.opacity, material.color.b * material.opacity
# pure color
#uniforms.color.value.setHex material.color.hex
uniforms.opacity.value = material.opacity
uniforms.map.texture = material.map
uniforms.lightMap.texture = material.lightMap
uniforms.envMap.texture = material.envMap
uniforms.reflectivity.value = material.reflectivity
uniforms.refractionRatio.value = material.refractionRatio
uniforms.combine.value = material.combine
uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping
refreshUniformsLine = (uniforms, material) ->
uniforms.diffuse.value.setRGB material.color.r * material.opacity, material.color.g * material.opacity, material.color.b * material.opacity
uniforms.opacity.value = material.opacity
refreshUniformsParticle = (uniforms, material) ->
uniforms.psColor.value.setRGB material.color.r * material.opacity, material.color.g * material.opacity, material.color.b * material.opacity
uniforms.opacity.value = material.opacity
uniforms.size.value = material.size
uniforms.scale.value = _canvas.height / 2.0 # TODO: Cache this
uniforms.map.texture = material.map
refreshUniformsFog = (uniforms, fog) ->
uniforms.fogColor.value.setHex fog.color.hex
if fog instanceof THREE.Fog
uniforms.fogNear.value = fog.near
uniforms.fogFar.value = fog.far
else if fog instanceof THREE.FogExp2 then uniforms.fogDensity.value = fog.density
refreshUniformsPhong = (uniforms, material) ->
# uniforms.ambient.value.setHex material.ambient.hex
# uniforms.specular.value.setHex material.specular.hex
uniforms.ambient.value.setRGB material.ambient.r, material.ambient.g, material.ambient.b
uniforms.specular.value.setRGB material.specular.r, material.specular.g, material.specular.b
uniforms.shininess.value = material.shininess
refreshUniformsLights = (uniforms, lights) ->
uniforms.enableLighting.value = lights.directional.length + lights.point.length
uniforms.ambientLightColor.value = lights.ambient
uniforms.directionalLightColor.value = lights.directional.colors
uniforms.directionalLightDirection.value = lights.directional.positions
uniforms.pointLightColor.value = lights.point.colors
uniforms.pointLightPosition.value = lights.point.positions
this.initMaterial = (material, lights, fog, object) ->
u = a = identifiers = i = parameters = maxLightCount = maxBones = null
if material instanceof THREE.MeshDepthMaterial then setMaterialShaders material, THREE.ShaderLib['depth']
else if material instanceof THREE.MeshNormalMaterial then setMaterialShaders material, THREE.ShaderLib['normal']
else if material instanceof THREE.MeshBasicMaterial then setMaterialShaders material, THREE.ShaderLib['basic']
else if material instanceof THREE.MeshLambertMaterial then setMaterialShaders material, THREE.ShaderLib['lambert']
else if material instanceof THREE.MeshPhongMaterial then setMaterialShaders material, THREE.ShaderLib['phong']
else if material instanceof THREE.LineBasicMaterial then setMaterialShaders material, THREE.ShaderLib['basic']
else if material instanceof THREE.ParticleBasicMaterial then setMaterialShaders material, THREE.ShaderLib['particle_basic']
# heuristics to create shader parameters according to lights in the scene
# (not to blow over maxLights budget)
maxLightCount = allocateLights lights, 4
maxBones = allocateBones object
parameters =
fog: fog
map: material.map
envMap: material.envMap
lightMap: material.lightMap
vertexColors: material.vertexColors
sizeAttenuation: material.sizeAttenuation
skinning: material.skinning
morphTargets: material.morphTargets
maxDirLights: maxLightCount.directional
maxPointLights: maxLightCount.point
maxBones: maxBones
material.program = buildProgram material.fragmentShader, material.vertexShader, parameters
# load uniforms
identifiers = ['viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition', 'cameraInverseMatrix', 'boneGlobalMatrices', 'morphTargetInfluences']
for k, v of material.uniforms then identifiers.push k
cacheUniformLocations material.program, identifiers
# load attributes
identifiers = ['position', 'normal', 'uv', 'uv2', 'tangent', 'color', 'skinVertexA', 'skinVertexB', 'skinIndex', 'skinWeight']
for i in [0...@maxMorphTargets] then identifiers.push "morphTarget#{i}"
for k, v of material.attributes then identifiers.push k
cacheAttributeLocations material.program, identifiers
attributes = material.program.attributes
_gl.enableVertexAttribArray attributes.position
if attributes.color >= 0 then _gl.enableVertexAttribArray attributes.color
if attributes.normal >= 0 then _gl.enableVertexAttribArray attributes.normal
if attributes.tangent >= 0 then _gl.enableVertexAttribArray attributes.tangent
if material.skinning && attributes.skinVertexA >=0 && attributes.skinVertexB >= 0 && attributes.skinIndex >= 0 && attributes.skinWeight >= 0
_gl.enableVertexAttribArray attributes.skinVertexA
_gl.enableVertexAttribArray attributes.skinVertexB
_gl.enableVertexAttribArray attributes.skinIndex
_gl.enableVertexAttribArray attributes.skinWeight
if material.morphTargets
material.numSupportedMorphTargets = 0
if attributes.morphTarget0 >= 0
_gl.enableVertexAttribArray attributes.morphTarget0
material.numSupportedMorphTargets++
if attributes.morphTarget1 >= 0
_gl.enableVertexAttribArray attributes.morphTarget1
material.numSupportedMorphTargets++
if attributes.morphTarget2 >= 0
_gl.enableVertexAttribArray attributes.morphTarget2
material.numSupportedMorphTargets++
if attributes.morphTarget3 >= 0
_gl.enableVertexAttribArray attributes.morphTarget3
material.numSupportedMorphTargets++
if attributes.morphTarget4 >= 0
_gl.enableVertexAttribArray attributes.morphTarget4
material.numSupportedMorphTargets++
if attributes.morphTarget5 >= 0
_gl.enableVertexAttribArray attributes.morphTarget5
material.numSupportedMorphTargets++
if attributes.morphTarget6 >= 0
_gl.enableVertexAttribArray attributes.morphTarget6
material.numSupportedMorphTargets++
if attributes.morphTarget7 >= 0
_gl.enableVertexAttribArray attributes.morphTarget7
material.numSupportedMorphTargets++
object.__webGLMorphTargetInfluences = new Float32Array @maxMorphTargets
for i in [0...@maxMorphTargets] then object.__webGLMorphTargetInfluences[i] = 0
setProgram = (camera, lights, fog, material, object) ->
if not material.program then _this.initMaterial material, lights, fog, object
program = material.program
p_uniforms = program.uniforms
m_uniforms = material.uniforms
if program isnt _oldProgram
_gl.useProgram program
_oldProgram = program
_gl.uniformMatrix4fv p_uniforms.projectionMatrix, false, _projectionMatrixArray
# refresh uniforms common to several materials
if fog && (material instanceof THREE.MeshBasicMaterial || material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial || material instanceof THREE.LineBasicMaterial || material instanceof THREE.ParticleBasicMaterial)
refreshUniformsFog m_uniforms, fog
if material instanceof THREE.MeshPhongMaterial || material instanceof THREE.MeshLambertMaterial || material.lights
setupLights program, lights
refreshUniformsLights m_uniforms, _lights
if material instanceof THREE.MeshBasicMaterial || material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial
refreshUniformsCommon m_uniforms, material
#refresh single material specific uniforms
if material instanceof THREE.LineBasicMaterial then refreshUniformsLine m_uniforms, material
else if material instanceof THREE.ParticleBasicMaterial then refreshUniformsParticle m_uniforms, material
else if material instanceof THREE.MeshPhongMaterial then refreshUniformsPhong m_uniforms, material
else if material instanceof THREE.MeshNormalMaterial then m_uniforms.opacity.value = material.opacity
else if material instanceof THREE.MeshDepthMaterial
m_uniforms.mNear.value = camera.near
m_uniforms.mFar.value = camera.far
m_uniforms.opacity.value = material.opacity
# load common uniforms
loadUniformsGeneric program, m_uniforms
loadUniformsMatrices p_uniforms, object
# load material specific uniforms
# (shader material also gets them for the sake of genericity)
if material instanceof THREE.MeshShaderMaterial || material instanceof THREE.MeshPhongMaterial || material.envMap
_gl.uniform3f p_uniforms.cameraPosition, camera.position.x, camera.position.y, camera.position.z
if material instanceof THREE.MeshShaderMaterial || material.envMap || material.skinning
_gl.uniformMatrix4fv p_uniforms.objectMatrix, false, object._objectMatrixArray
if material instanceof THREE.MeshPhongMaterial || material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshShaderMaterial || material.skinning
_gl.uniformMatrix4fv p_uniforms.viewMatrix, false, _viewMatrixArray
if material.skinning then loadUniformsSkinning p_uniforms, object
return program
renderBuffer = (camera, lights, fog, material, geometryGroup, object) ->
if material.opacity is 0 then return
program = attributes = linewidth = primitives = null
program = setProgram camera, lights, fog, material, object
attributes = program.attributes
# vertices
if not material.morphTargets
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLVertexBuffer
_gl.vertexAttribPointer attributes.position, 3, _gl.FLOAT, false, 0, 0
else
setupMorphTargets material, geometryGroup, object
# colors
if attributes.color >= 0
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLColorBuffer
_gl.vertexAttribPointer attributes.color, 3, _gl.FLOAT, false, 0, 0
# normals
if attributes.normal >= 0
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLNormalBuffer
_gl.vertexAttribPointer attributes.normal, 3, _gl.FLOAT, false, 0, 0
# tangents
if attributes.tangent >= 0
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLTangentBuffer
_gl.vertexAttribPointer attributes.tangent, 4, _gl.FLOAT, false, 0, 0
# uvs
if attributes.uv >= 0
if geometryGroup.__webGLUVBuffer
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLUVBuffer
_gl.vertexAttribPointer attributes.uv, 2, _gl.FLOAT, false, 0, 0
_gl.enableVertexAttribArray attributes.uv
else
_gl.disableVertexAttribArray attributes.uv
if attributes.uv2 >= 0
if geometryGroup.__webGLUV2Buffer
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLUV2Buffer
_gl.vertexAttribPointer attributes.uv2, 2, _gl.FLOAT, false, 0, 0
_gl.enableVertexAttribArray attributes.uv2
else
_gl.disableVertexAttribArray attributes.uv2
if material.skinning && attributes.skinVertexA >= 0 && attributes.skinVertexB >= 0 && attributes.skinIndex >= 0 && attributes.skinWeight >= 0
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLSkinVertexABuffer
_gl.vertexAttribPointer attributes.skinVertexA, 4, _gl.FLOAT, false, 0, 0
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLSkinVertexBBuffer
_gl.vertexAttribPointer attributes.skinVertexB, 4, _gl.FLOAT, false, 0, 0
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLSkinIndicesBuffer
_gl.vertexAttribPointer attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLSkinWeightsBuffer
_gl.vertexAttribPointer attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0
# render mesh
if object instanceof THREE.Mesh
# wireframe
if material.wireframe
_gl.lineWidth material.wireframeLinewidth
_gl.bindBuffer _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webGLLineBuffer
_gl.drawElements _gl.LINES, geometryGroup.__webGLLineCount, _gl.UNSIGNED_SHORT, 0
# triangles
else
_gl.bindBuffer _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webGLFaceBuffer
_gl.drawElements _gl.TRIANGLES, geometryGroup.__webGLFaceCount, _gl.UNSIGNED_SHORT, 0
# render lines
else if object instanceof THREE.Line
primitives = if object.type is THREE.LineStrip then _gl.LINE_STRIP else _gl.LINES
_gl.lineWidth material.linewidth
_gl.drawArrays primitives, 0, geometryGroup.__webGLLineCount
# render particles
else if object instanceof THREE.ParticleSystem
_gl.drawArrays _gl.POINTS, 0, geometryGroup.__webGLParticleCount
# render ribbon
else if object instanceof THREE.Ribbon
_gl.drawArrays _gl.TRIANGLE_STRIP, 0, geometryGroup.__webGLVertexCount
setupMorphTargets = (material, geometryGroup, object) ->
# set base
attributes = material.program.attributes
if object.morphTargetBase isnt -1
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLMorphTargetsBuffers[object.morphTargetBase]
_gl.vertexAttribPointer attributes.position, 3, _gl.FLOAT, false, 0, 0
else
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLVertexBuffer
_gl.vertexAttribPointer attributes.position, 3, _gl.FLOAT, false, 0, 0
if object.morphTargetForcedOrder.length
# force order
m = 0
order = object.morphTargetForcedOrder
influences = object.morphTargetInfluences
while m < material.numSupportedMorphTargets and m < order.length
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLMorphTargetsBuffers[order[m]]
_gl.vertexAttribPointer attributes["morphTarget" + m], 3, _gl.FLOAT, false, 0, 0
object.__webGLMorphTargetInfluences[m] = influences[order[m]]
m++
else
# find most influencing
used = []
candidateInfluence = -1
candidate = 0
influences = object.morphTargetInfluences
m = 0
if object.morphTargetBase isnt -1 then used[object.morphTargetBase] = true
while m < material.numSupportedMorphTargets
for i in [0...influences.length]
if !used[i] and influences[i] > candidateInfluence
candidate = i
candidateInfluence = influences[candidate]
_gl.bindBuffer _gl.ARRAY_BUFFER, geometryGroup.__webGLMorphTargetsBuffers[candidate]
_gl.vertexAttribPointer attributes["morphTarget" + m], 3, _gl.FLOAT, false, 0, 0
object.__webGLMorphTargetInfluences[m] = candidateInfluence
used[candidate] = 1
candidateInfluence = -1
m++
_gl.uniform1fv material.program.uniforms.morphTargetInfluences, object.__webGLMorphTargetInfluences
renderBufferImmediate = (object, program) ->
if not object.__webGLVertexBuffer then object.__webGLVertexBuffer = _gl.createBuffer()
if not object.__webGLNormalBuffer then object.__webGLNormalBuffer = _gl.createBuffer()
if object.hasPos
_gl.bindBuffer _gl.ARRAY_BUFFER, object.__webGLVertexBuffer
_gl.bufferData _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW
_gl.enableVertexAttribArray program.attributes.position
_gl.vertexAttribPointer program.attributes.position, 3, _gl.FLOAT, false, 0, 0
if object.hasNormal
_gl.bindBuffer _gl.ARRAY_BUFFER, object.__webGLNormalBuffer
_gl.bufferData _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW
_gl.enableVertexAttribArray program.attributes.normal
_gl.vertexAttribPointer program.attributes.normal, 3, _gl.FLOAT, false, 0, 0
_gl.drawArrays _gl.TRIANGLES, 0, object.count
object.count = 0
setObjectFaces = (object) ->
if _oldDoubleSided isnt object.doubleSided
if object.doubleSided then _gl.disable _gl.CULL_FACE else _gl.enable _gl.CULL_FACE
_oldDoubleSided = object.doubleSided
if _oldFlipSided isnt object.flipSided
if object.flipSided then _gl.frontFace _gl.CW else _gl.frontFace _gl.CCW
_oldFlipSided = object.flipSided
setDepthTest = (test) ->
if _oldDepth isnt test
if test then _gl.enable _gl.DEPTH_TEST else _gl.disable _gl.DEPTH_TEST
_oldDepth = test
computeFrustum = (m) ->
_frustum[0].set m.n41 - m.n11, m.n42 - m.n12, m.n43 - m.n13, m.n44 - m.n14
_frustum[1].set m.n41 + m.n11, m.n42 + m.n12, m.n43 + m.n13, m.n44 + m.n14
_frustum[2].set m.n41 + m.n21, m.n42 + m.n22, m.n43 + m.n23, m.n44 + m.n24
_frustum[3].set m.n41 - m.n21, m.n42 - m.n22, m.n43 - m.n23, m.n44 - m.n24
_frustum[4].set m.n41 - m.n31, m.n42 - m.n32, m.n43 - m.n33, m.n44 - m.n34
_frustum[5].set m.n41 + m.n31, m.n42 + m.n32, m.n43 + m.n33, m.n44 + m.n34
for i in [0...6]
plane = _frustum[i]
plane.divideScalar Math.sqrt(plane.x * plane.x + plane.y * plane.y + plane.z * plane.z)
isInFrustum = (object) ->
distance = null
matrix = object.matrixWorld
radius = -(object.geometry.boundingSphere.radius * Math.max(object.scale.x, Math.max(object.scale.y, object.scale.z)))
for i in [0...6]
distance = _frustum[i].x * matrix.n14 + _frustum[i].y * matrix.n24 + _frustum[i].z * matrix.n34 + _frustum[i].w
if distance <= radius then return false
return true
addToFixedArray = (where, what) ->
where.list[where.count] = what
where.count += 1
unrollImmediateBufferMaterials = (globject) ->
object = globject.object
opaque = globject.opaque
transparent = globject.transparent
transparent.count = 0
opaque.count = 0
for material in object.materials
if (material.opacity and material.opacity < 1.0) or material.blending isnt THREE.NormalBlending
addToFixedArray transparent, material
else
addToFixedArray opaque, material
unrollBufferMaterials = (globject) ->
object = globject.object
buffer = globject.buffer
opaque = globject.opaque
transparent = globject.transparent
transparent.count = 0
opaque.count = 0
for meshMaterial in object.materials
if meshMaterial instanceof THREE.MeshFaceMaterial
for material in buffer.materials
if material
if (material.opacity and material.opacity < 1.0) or material.blending isnt THREE.NormalBlending
addToFixedArray transparent, material
else
addToFixedArray opaque, material
else
material = meshMaterial
if (material.opacity && material.opacity < 1.0) or material.blending isnt THREE.NormalBlending
addToFixedArray transparent, material
else
addToFixedArray opaque, material
painterSort = (a, b) -> b.z - a.z
@render = (scene, camera, renderTarget, forceClear) ->
i = program = opaque = transparent = material = o = ol = oil = webglObject = object = buffer = null
lights = scene.lights
fog = scene.fog
if camera.matrixAutoUpdate then camera.updateMatrix()
scene.update undefined, false, camera
camera.matrixWorldInverse.flattenToArray _viewMatrixArray
camera.projectionMatrix.flattenToArray _projectionMatrixArray
_projScreenMatrix.multiply camera.projectionMatrix, camera.matrixWorldInverse
computeFrustum _projScreenMatrix
this.initWebGLObjects scene
setRenderTarget renderTarget
if @autoClear or forceClear then @clear()
# set matrices
ol = scene.__webglObjects.length
for webglObject in scene.__webglObjects
object = webglObject.object
if object.visible
if !(object instanceof THREE.Mesh) or isInFrustum(object)
object.matrixWorld.flattenToArray object._objectMatrixArray
setupMatrices object, camera
unrollBufferMaterials webglObject
webglObject.render = true
if @sortObjects
_vector3.copy object.position
_projScreenMatrix.multiplyVector3 _vector3
webglObject.z = _vector3.z
else
webglObject.render = false
else
webglObject.render = false
if @sortObjects
scene.__webglObjects.sort painterSort
oil = scene.__webglObjectsImmediate.length
for webglObject in scene.__webglObjectsImmediate
object = webglObject.object
if object.visible
if object.matrixAutoUpdate then object.matrixWorld.flattenToArray object._objectMatrixArray
setupMatrices object, camera
unrollImmediateBufferMaterials webglObject
# opaque pass
setBlending THREE.NormalBlending
for webglObject in scene.__webglObjects
if webglObject.render
object = webglObject.object
buffer = webglObject.buffer
opaque = webglObject.opaque
setObjectFaces object
for material in opaque.list
setDepthTest material.depthTest
renderBuffer camera, lights, fog, material, buffer, object
# opaque pass (immediate simulator)
for webglObject in scene.__webglObjectsImmediate
object = webglObject.object
if object.visible
opaque = webglObject.opaque
setObjectFaces object
for material in opaque.list
setDepthTest material.depthTest
program = setProgram camera, lights, fog, material, object
object.render (object) -> renderBufferImmediate object, program
# transparent pass
for webglObject in scene.__webglObjects
if webglObject.render
object = webglObject.object
buffer = webglObject.buffer
transparent = webglObject.transparent
setObjectFaces object
for material in transparent.list
setBlending material.blending
setDepthTest material.depthTest
renderBuffer camera, lights, fog, material, buffer, object
# transparent pass (immediate simulator)
for webglObject in scene.__webglObjectsImmediate
object = webglObject.object
if object.visible
transparent = webglObject.transparent
setObjectFaces object
for material in transparent.list
setBlending material.blending
setDepthTest material.depthTest
program = setProgram camera, lights, fog, material, object
object.render (object) -> renderBufferImmediate object, program
# Generate mipmap if we're using any kind of mipmap filtering
if renderTarget and renderTarget.minFilter isnt THREE.NearestFilter and renderTarget.minFilter isnt THREE.LinearFilter
updateRenderTargetMipmap renderTarget
setupMatrices = (object, camera) ->
object._modelViewMatrix.multiplyToArray camera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray
THREE.Matrix4.makeInvert3x3(object._modelViewMatrix).transposeIntoArray object._normalMatrixArray
@initWebGLObjects = (scene) ->
if not scene.__webglObjects
scene.__webglObjects = new Array
scene.__webglObjectsImmediate = new Array
while scene.__objectsAdded.length
addObject scene.__objectsAdded[0], scene
scene.__objectsAdded.splice 0, 1
while scene.__objectsRemoved.length
removeObject scene.__objectsRemoved[0], scene
scene.__objectsRemoved.splice 0, 1
# update must be called after objects adding / removal
for webglObject in scene.__webglObjects
updateObject webglObject.object, scene
addObject = (object, scene) ->
g = geometry = geometryGroup = null
if object._modelViewMatrix == undefined
object._modelViewMatrix = new THREE.Matrix4
object._normalMatrixArray = new Float32Array 9
object._modelViewMatrixArray = new Float32Array 16
object._objectMatrixArray = new Float32Array 16
object.matrixWorld.flattenToArray object._objectMatrixArray
if object instanceof THREE.Mesh
geometry = object.geometry
if geometry.geometryGroups == undefined then sortFacesByMaterial geometry
# create separate VBOs per geometry chunk
for key, geometryGroup of geometry.geometryGroups
# initialise VBO on the first access
if not geometryGroup.__webGLVertexBuffer
createMeshBuffers geometryGroup
initMeshBuffers geometryGroup, object
geometry.__dirtyVertices = true
geometry.__dirtyMorphTargets = true
geometry.__dirtyElements = true
geometry.__dirtyUvs = true
geometry.__dirtyNormals = true
geometry.__dirtyTangents = true
geometry.__dirtyColors = true
# create separate wrapper per each use of VBO
addBuffer scene.__webglObjects, geometryGroup, object
else if object instanceof THREE.Ribbon
geometry = object.geometry
if not geometry.__webGLVertexBuffer
createRibbonBuffers geometry
initRibbonBuffers geometry
geometry.__dirtyVertices = true
geometry.__dirtyColors = true
addBuffer scene.__webglObjects, geometry, object
else if object instanceof THREE.Line
geometry = object.geometry
if geometry.__webGLVertexBuffer
createLineBuffers geometry
initLineBuffers geometry
geometry.__dirtyVertices = true
geometry.__dirtyColors = true
addBuffer scene.__webglObjects, geometry, object
else if object instanceof THREE.ParticleSystem
geometry = object.geometry
if not geometry.__webGLVertexBuffer
createParticleBuffers geometry
initParticleBuffers geometry
geometry.__dirtyVertices = true
geometry.__dirtyColors = true
addBuffer scene.__webglObjects, geometry, object
else if THREE.MarchingCubes? and object instanceof THREE.MarchingCubes
addBufferImmediate scene.__webglObjectsImmediate, object
updateObject = (object, scene) ->
if object instanceof THREE.Mesh
geometry = object.geometry
# check all geometry groups
for key, geometryGroup of geometry.geometryGroups
if geometry.__dirtyVertices || geometry.__dirtyMorphTargets || geometry.__dirtyElements || geometry.__dirtyUvs || geometry.__dirtyNormals || geometry.__dirtyColors || geometry.__dirtyTangents
setMeshBuffers geometryGroup, object, _gl.DYNAMIC_DRAW
geometry.__dirtyVertices = false
geometry.__dirtyMorphTargets = false
geometry.__dirtyElements = false
geometry.__dirtyUvs = false
geometry.__dirtyNormals = false
geometry.__dirtyTangents = false
geometry.__dirtyColors = false
else if object instanceof THREE.Ribbon
geometry = object.geometry
if geometry.__dirtyVertices || geometry.__dirtyColors
setRibbonBuffers geometry, _gl.DYNAMIC_DRAW
geometry.__dirtyVertices = false
geometry.__dirtyColors = false
else if object instanceof THREE.Line
geometry = object.geometry
if geometry.__dirtyVertices || geometry.__dirtyColors
setLineBuffers geometry, _gl.DYNAMIC_DRAW
geometry.__dirtyVertices = false
geometry.__dirtyColors = false
else if object instanceof THREE.ParticleSystem
geometry = object.geometry
if geometry.__dirtyVertices || geometry.__dirtyColors || object.sortParticles
setParticleBuffers geometry, _gl.DYNAMIC_DRAW, object
geometry.__dirtyVertices = false
geometry.__dirtyColors = false
removeObject = (object, scene) ->
for o in [0...scene.__webglObjects.length]
zobject = scene.__webglObjects[o].object
if object is zobject then scene.__webglObjects.splice o, 1
sortFacesByMaterial = (geometry) ->
# TODO
# Should optimize by grouping faces with ColorFill / ColorStroke materials
# which could then use vertex color attributes instead of each being
# in its separate VBO
i = l = f = fl = face = material = materials = vertices = mhash = ghash = null
hash_map = {}
numMorphTargets = if geometry.morphTargets isnt undefined then geometry.morphTargets.length else 0
geometry.geometryGroups = new Object
materialHash = (material) ->
hash_array = new Array
for m in material
if m is undefined
hash_array.push "undefined"
else
hash_array.push m.id
return hash_array.join '_'
for f in [0...geometry.faces.length]
face = geometry.faces[f]
materials = face.materials
mhash = materialHash materials
if hash_map[mhash] is undefined then hash_map[mhash] = hash: mhash, counter: 0
ghash = "#{hash_map[mhash].hash}_#{hash_map[mhash].counter}"
if geometry.geometryGroups[ghash] is undefined
geometry.geometryGroups[ghash] = faces: new Array, materials: materials, vertices: 0, numMorphTargets: numMorphTargets
vertices = if face instanceof THREE.Face3 then 3 else 4
if (geometry.geometryGroups[ghash].vertices + vertices) > 65535
hash_map[mhash].counter += 1
ghash = "#{hash_map[mhash].hash}_#{hash_map[mhash].counter}"
if geometry.geometryGroups[ghash] is undefined
geometry.geometryGroups[ghash] = faces: new Array, materials: materials, vertices: 0, numMorphTargets: numMorphTargets
geometry.geometryGroups[ghash].faces.push f
geometry.geometryGroups[ghash].vertices += vertices
addBuffer = (objlist, buffer, object) ->
objlist.push
buffer: buffer
object: object
opaque: {list: new Array, count: 0}
transparent: {list: new Array, count: 0}
addBufferImmediate = (objlist, object) ->
objlist.push
object: object
opaque: {list: new Array, count: 0}
transparent: {list: new Array, count: 0}
@setFaceCulling = (cullFace, frontFace) ->
if cullFace
if !frontFace or frontFace is 'ccw' then _gl.frontFace _gl.CCW else _gl.frontFace _gl.CW
if cullFace is 'back' then _gl.cullFace _gl.BACK
else if cullFace is 'front' then _gl.cullFace _gl.FRONT
else _gl.cullFace _gl.FRONT_AND_BACK
_gl.enable _gl.CULL_FACE
else _gl.disable _gl.CULL_FACE
maxVertexTextures = -> _gl.getParameter _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS
@supportsVertexTextures = -> maxVertexTextures() > 0
buildProgram = (fragmentShader, vertexShader, parameters) ->
program = _gl.createProgram()
prefix_fragment = """
#ifdef GL_ES
precision highp float;
#endif
#define MAX_DIR_LIGHTS #{parameters.maxDirLights}
#define MAX_POINT_LIGHTS #{parameters.maxPointLights}
#{if parameters.fog then '#define USE_FOG' else ''}
#{if parameters.fog instanceof THREE.FogExp2 then '#define FOG_EXP2' else ''}
#{if parameters.map then '#define USE_MAP'else ''}
#{if parameters.envMap then '#define USE_ENVMAP' else ''}
#{if parameters.lightMap then '#define USE_LIGHTMAP' else ''}
#{if parameters.vertexColors then '#define USE_COLOR' else ''}
uniform mat4 viewMatrix;
uniform vec3 cameraPosition;
"""
prefix_vertex = """
#{'#define VERTEX_TEXTURES' if maxVertexTextures() > 0}
#define MAX_DIR_LIGHTS #{parameters.maxDirLights}
#define MAX_POINT_LIGHTS #{parameters.maxPointLights}
#define MAX_BONES #{parameters.maxBones}
#{if parameters.map then '#define USE_MAP' else ''}
#{if parameters.envMap then '#define USE_ENVMAP' else ''}
#{if parameters.lightMap then '#define USE_LIGHTMAP' else ''}
#{if parameters.vertexColors then '#define USE_COLOR' else ''}
#{if parameters.skinning then '#define USE_SKINNING' else ''}
#{if parameters.morphTargets then '#define USE_MORPHTARGETS' else ''}
#{if parameters.sizeAttenuation then '#define USE_SIZEATTENUATION' else ''}
uniform mat4 objectMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat3 normalMatrix;
uniform vec3 cameraPosition;
uniform mat4 cameraInverseMatrix;
attribute vec3 position;
attribute vec3 morphTarget0;
attribute vec3 morphTarget1;
attribute vec3 morphTarget2;
attribute vec3 morphTarget3;
attribute vec3 morphTarget4;
attribute vec3 morphTarget5;
attribute vec3 morphTarget6;
attribute vec3 morphTarget7;
attribute vec3 normal;
attribute vec3 color;
attribute vec2 uv;
attribute vec2 uv2;
attribute vec4 skinVertexA;
attribute vec4 skinVertexB;
attribute vec4 skinIndex;
attribute vec4 skinWeight;
"""
_gl.attachShader program, getShader("fragment", prefix_fragment + fragmentShader)
_gl.attachShader program, getShader("vertex", prefix_vertex + vertexShader)
_gl.linkProgram program
if not _gl.getProgramParameter(program, _gl.LINK_STATUS)
alert """
Could not initialise shaders
VALIDATE_STATUS: #{_gl.getProgramParameter(program, _gl.VALIDATE_STATUS)}
ERROR: #{_gl.getError()}
"""
program.uniforms = new Object
program.attributes = new Object
return program
loadUniformsSkinning = (uniforms, object) ->
_gl.uniformMatrix4fv uniforms.cameraInverseMatrix, false, _viewMatrixArray
_gl.uniformMatrix4fv uniforms.boneGlobalMatrices, false, object.boneMatrices
loadUniformsMatrices = (uniforms, object) ->
_gl.uniformMatrix4fv uniforms.modelViewMatrix, false, object._modelViewMatrixArray
_gl.uniformMatrix3fv uniforms.normalMatrix, false, object._normalMatrixArray
loadUniformsGeneric = (program, uniforms) ->
u = uniform = value = type = location = texture = null
for u, uniform of uniforms
location = program.uniforms[u]
if not location then continue
type = uniform.type
value = uniform.value
switch type
when 'i' then _gl.uniform1i location, value
when 'f' then _gl.uniform1f location, value
when 'fv1' then _gl.uniform1fv location, value
when 'fv' then _gl.uniform3fv location, value
when 'v2' then _gl.uniform2f location, value.x, value.y
when 'v3' then _gl.uniform3f location, value.x, value.y, value.z
when 'c' then _gl.uniform3f location, value.r, value.g, value.b
when 't' then _gl.uniform1i location, value
texture = uniform.texture
if not texture then continue
if texture.image instanceof Array and texture.image.length is 6
setCubeTexture texture, value
else
setTexture texture, value
setBlending = (blending) ->
if blending isnt _oldBlending
switch blending
when THREE.AdditiveBlending
_gl.blendEquation _gl.FUNC_ADD
_gl.blendFunc _gl.ONE, _gl.ONE
when THREE.SubtractiveBlending
# _gl.blendEquation _gl.FUNC_SUBTRACT
_gl.blendFunc _gl.DST_COLOR, _gl.ZERO
when THREE.BillboardBlending
_gl.blendEquation _gl.FUNC_ADD
_gl.blendFunc _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA
when THREE.ReverseSubtractiveBlending:
_gl.blendEquation( _gl.FUNC_REVERSE_SUBTRACT );
_gl.blendFunc( _gl.ONE, _gl.ONE );
else
_gl.blendEquation _gl.FUNC_ADD
_gl.blendFunc _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA
_oldBlending = blending
function setTextureParameters ( textureType, texture, image ) {
if ( isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ) ) {
_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
_gl.generateMipmap( textureType );
} else {
_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
}
};
function setTexture ( texture, slot ) {
if ( texture.needsUpdate ) {
if ( !texture.__wasSetOnce ) {
texture.__webGLTexture = _gl.createTexture();
_gl.bindTexture( _gl.TEXTURE_2D, texture.__webGLTexture );
_gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image );
texture.__wasSetOnce = true;
} else {
_gl.bindTexture( _gl.TEXTURE_2D, texture.__webGLTexture );
_gl.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image );
}
setTextureParameters( _gl.TEXTURE_2D, texture, texture.image );
_gl.bindTexture( _gl.TEXTURE_2D, null );
texture.needsUpdate = false;
}
_gl.activeTexture( _gl.TEXTURE0 + slot );
_gl.bindTexture( _gl.TEXTURE_2D, texture.__webGLTexture );
};
function setCubeTexture ( texture, slot ) {
if ( texture.image.length == 6 ) {
if ( texture.needsUpdate ) {
if ( !texture.__wasSetOnce ) {
texture.image.__webGLTextureCube = _gl.createTexture();
_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webGLTextureCube );
for ( var i = 0; i < 6; ++i ) {
_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image[i] );
}
texture.__wasSetOnce = true;
} else {
_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webGLTextureCube );
for ( var i = 0; i < 6; ++i ) {
_gl.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image[i] );
}
}
setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, texture.image[0] );
_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
texture.needsUpdate = false;
}
_gl.activeTexture( _gl.TEXTURE0 + slot );
_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webGLTextureCube );
}
};
function setRenderTarget ( renderTexture ) {
if ( renderTexture && !renderTexture.__webGLFramebuffer ) {
renderTexture.__webGLFramebuffer = _gl.createFramebuffer();
renderTexture.__webGLRenderbuffer = _gl.createRenderbuffer();
renderTexture.__webGLTexture = _gl.createTexture();
// Setup renderbuffer
_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTexture.__webGLRenderbuffer );
_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTexture.width, renderTexture.height );
// Setup texture
_gl.bindTexture( _gl.TEXTURE_2D, renderTexture.__webGLTexture );
_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, paramThreeToGL( renderTexture.wrapS ) );
_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, paramThreeToGL( renderTexture.wrapT ) );
_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( renderTexture.magFilter ) );
_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( renderTexture.minFilter ) );
_gl.texImage2D( _gl.TEXTURE_2D, 0, paramThreeToGL( renderTexture.format ), renderTexture.width, renderTexture.height, 0, paramThreeToGL( renderTexture.format ), paramThreeToGL( renderTexture.type ), null );
// Setup framebuffer
_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTexture.__webGLFramebuffer );
_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, renderTexture.__webGLTexture, 0 );
_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTexture.__webGLRenderbuffer );
// Release everything
_gl.bindTexture( _gl.TEXTURE_2D, null );
_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
_gl.bindFramebuffer( _gl.FRAMEBUFFER, null);
}
var framebuffer, width, height;
if ( renderTexture ) {
framebuffer = renderTexture.__webGLFramebuffer;
width = renderTexture.width;
height = renderTexture.height;
} else {
framebuffer = null;
width = _viewportWidth;
height = _viewportHeight;
}
if( framebuffer != _oldFramebuffer ) {
_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
_gl.viewport( _viewportX, _viewportY, width, height );
_oldFramebuffer = framebuffer;
}
};
function updateRenderTargetMipmap ( renderTarget ) {
_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webGLTexture );
_gl.generateMipmap( _gl.TEXTURE_2D );
_gl.bindTexture( _gl.TEXTURE_2D, null );
};
function cacheUniformLocations ( program, identifiers ) {
var i, l, id;
for( i = 0, l = identifiers.length; i < l; i++ ) {
id = identifiers[i];
program.uniforms[id] = _gl.getUniformLocation( program, id );
}
};
function cacheAttributeLocations ( program, identifiers ) {
var i, l, id;
for( i = 0, l = identifiers.length; i < l; i++ ) {
id = identifiers[i];
program.attributes[id] = _gl.getAttribLocation( program, id );
}
};
function getShader ( type, string ) {
var shader;
if ( type == "fragment" ) {
shader = _gl.createShader( _gl.FRAGMENT_SHADER );
} else if ( type == "vertex" ) {
shader = _gl.createShader( _gl.VERTEX_SHADER );
}
_gl.shaderSource( shader, string );
_gl.compileShader( shader );
if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
alert( _gl.getShaderInfoLog( shader ) );
return null;
}
return shader;
};
// fallback filters for non-power-of-2 textures
function filterFallback ( f ) {
switch ( f ) {
case THREE.NearestFilter:
case THREE.NearestMipMapNearestFilter:
case THREE.NearestMipMapLinearFilter: return _gl.NEAREST; break;
case THREE.LinearFilter:
case THREE.LinearMipMapNearestFilter:
case THREE.LinearMipMapLinearFilter: return _gl.LINEAR; break;
}
};
function paramThreeToGL ( p ) {
switch ( p ) {
case THREE.RepeatWrapping: return _gl.REPEAT; break;
case THREE.ClampToEdgeWrapping: return _gl.CLAMP_TO_EDGE; break;
case THREE.MirroredRepeatWrapping: return _gl.MIRRORED_REPEAT; break;
case THREE.NearestFilter: return _gl.NEAREST; break;
case THREE.NearestMipMapNearestFilter: return _gl.NEAREST_MIPMAP_NEAREST; break;
case THREE.NearestMipMapLinearFilter: return _gl.NEAREST_MIPMAP_LINEAR; break;
case THREE.LinearFilter: return _gl.LINEAR; break;
case THREE.LinearMipMapNearestFilter: return _gl.LINEAR_MIPMAP_NEAREST; break;
case THREE.LinearMipMapLinearFilter: return _gl.LINEAR_MIPMAP_LINEAR; break;
case THREE.ByteType: return _gl.BYTE; break;
case THREE.UnsignedByteType: return _gl.UNSIGNED_BYTE; break;
case THREE.ShortType: return _gl.SHORT; break;
case THREE.UnsignedShortType: return _gl.UNSIGNED_SHORT; break;
case THREE.IntType: return _gl.INT; break;
case THREE.UnsignedShortType: return _gl.UNSIGNED_INT; break;
case THREE.FloatType: return _gl.FLOAT; break;
case THREE.AlphaFormat: return _gl.ALPHA; break;
case THREE.RGBFormat: return _gl.RGB; break;
case THREE.RGBAFormat: return _gl.RGBA; break;
case THREE.LuminanceFormat: return _gl.LUMINANCE; break;
case THREE.LuminanceAlphaFormat: return _gl.LUMINANCE_ALPHA; break;
}
return 0;
};
function isPowerOfTwo ( value ) {
return ( value & ( value - 1 ) ) == 0;
};
function materialNeedsSmoothNormals ( material ) {
return material && material.shading != undefined && material.shading == THREE.SmoothShading;
};
function bufferNeedsSmoothNormals ( geometryGroup, object ) {
var m, ml, i, l, meshMaterial, needsSmoothNormals = false;
for ( m = 0, ml = object.materials.length; m < ml; m++ ) {
meshMaterial = object.materials[m];
if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
for ( i = 0, l = geometryGroup.materials.length; i < l; i++ ) {
if ( materialNeedsSmoothNormals( geometryGroup.materials[i] ) ) {
needsSmoothNormals = true;
break;
}
}
} else {
if ( materialNeedsSmoothNormals( meshMaterial ) ) {
needsSmoothNormals = true;
break;
}
}
if ( needsSmoothNormals ) break;
}
return needsSmoothNormals;
};
function allocateBones ( object ) {
// default for when object is not specified
// ( for example when prebuilding shader
// to be used with multiple objects )
//
// - leave some extra space for other uniforms
// - limit here is ANGLE's 254 max uniform vectors
// (up to 54 should be safe)
var maxBones = 50;
if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
maxBones = object.bones.length;
}
return maxBones;
};
function allocateLights ( lights, maxLights ) {
var l, ll, light, dirLights, pointLights, maxDirLights, maxPointLights;
dirLights = pointLights = maxDirLights = maxPointLights = 0;
for ( l = 0, ll = lights.length; l < ll; l++ ) {
light = lights[l];
if ( light instanceof THREE.DirectionalLight ) dirLights++;
if ( light instanceof THREE.PointLight ) pointLights++;
}
if ( ( pointLights + dirLights ) <= maxLights ) {
maxDirLights = dirLights;
maxPointLights = pointLights;
} else {
maxDirLights = Math.ceil( maxLights * dirLights / ( pointLights + dirLights ) );
maxPointLights = maxLights - maxDirLights;
}
return { 'directional' : maxDirLights, 'point' : maxPointLights };
};
`
return
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment