Last active
May 18, 2017 09:02
-
-
Save kyptov/5aa6aecab2a78a9a21906fe03bbd69ae to your computer and use it in GitHub Desktop.
Babylon js SpriteManager with LogarithmicDepth support
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SpriteManager extends BABYLON.SpriteManager { | |
constructor(...args) { | |
super(...args); | |
if (!BABYLON.Effect.ShadersStore.spritesDepthVertexShader) { | |
SpriteManager.init(); | |
} | |
// Effects | |
this._effectBase = this._scene.getEngine().createEffect("spritesDepth", | |
[BABYLON.VertexBuffer.PositionKind, "options", "cellInfo", BABYLON.VertexBuffer.ColorKind], | |
["view", "projection", "textureInfos", "alphaTest"], | |
["diffuseSampler"], ""); | |
} | |
render() { | |
// Check | |
if (!this._effectBase.isReady() || !this._effectFog.isReady() || !this._spriteTexture || !this._spriteTexture.isReady()) { | |
return; | |
} | |
var engine = this._scene.getEngine(); | |
var baseSize = this._spriteTexture.getBaseSize(); | |
// Sprites | |
var deltaTime = engine.getDeltaTime(); | |
var max = Math.min(this._capacity, this.sprites.length); | |
var rowSize = baseSize.width / this.cellWidth; | |
var offset = 0; | |
for (var index = 0; index < max; index++) { | |
var sprite = this.sprites[index]; | |
if (!sprite) { | |
continue; | |
} | |
sprite._animate(deltaTime); | |
this._appendSpriteVertex(offset++, sprite, 0, 0, rowSize); | |
this._appendSpriteVertex(offset++, sprite, 1, 0, rowSize); | |
this._appendSpriteVertex(offset++, sprite, 1, 1, rowSize); | |
this._appendSpriteVertex(offset++, sprite, 0, 1, rowSize); | |
} | |
this._buffer.update(this._vertexData); | |
// Render | |
var effect = this._effectBase; | |
if (this._scene.fogEnabled && this._scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) { | |
effect = this._effectFog; | |
} | |
engine.enableEffect(effect); | |
var viewMatrix = this._scene.getViewMatrix(); | |
effect.setTexture('diffuseSampler', this._spriteTexture); | |
effect.setMatrix('view', viewMatrix); | |
effect.setMatrix('projection', this._scene.getProjectionMatrix()); | |
effect.setFloat2('textureInfos', this.cellWidth / baseSize.width, this.cellHeight / baseSize.height); | |
// Fog | |
if (this._scene.fogEnabled && this._scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) { | |
effect.setFloat4("vFogInfos", this._scene.fogMode, this._scene.fogStart, this._scene.fogEnd, this._scene.fogDensity); | |
effect.setColor3("vFogColor", this._scene.fogColor); | |
} | |
// Log. depth | |
effect.setFloat('logarithmicDepthConstant', 2.0 / (Math.log(this._scene.activeCamera.maxZ + 1.0) / Math.LN2)); | |
// VBOs | |
engine.bindBuffers(this._vertexBuffers, this._indexBuffer, effect); | |
// Draw order | |
engine.setDepthFunctionToLessOrEqual(); | |
effect.setBool('alphaTest', true); | |
engine.setColorWrite(false); | |
engine.draw(true, 0, max * 6); | |
engine.setColorWrite(true); | |
effect.setBool('alphaTest', false); | |
engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE); | |
engine.draw(true, 0, max * 6); | |
engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE); | |
} | |
// Need to be called once | |
static init() { | |
BABYLON.Effect.ShadersStore.spritesDepthVertexShader = "attribute vec4 position;\nattribute vec4 options;\nattribute vec4 cellInfo;\nattribute vec4 color;\n\nuniform vec2 textureInfos;\nuniform mat4 view;\nuniform mat4 projection;\n\nvarying vec2 vUV;\nvarying vec4 vColor;\n#include<fogVertexDeclaration>\nuniform float logarithmicDepthConstant;\nvarying float vFragmentDepth;\nvoid main(void) { \nvec3 viewPos=(view*vec4(position.xyz,1.0)).xyz; \nvec2 cornerPos;\nfloat angle=position.w;\nvec2 size=vec2(options.x,options.y);\nvec2 offset=options.zw;\nvec2 uvScale=textureInfos.xy;\ncornerPos=vec2(offset.x-0.5,offset.y-0.5)*size;\n\nvec3 rotatedCorner;\nrotatedCorner.x=cornerPos.x*cos(angle)-cornerPos.y*sin(angle);\nrotatedCorner.y=cornerPos.x*sin(angle)+cornerPos.y*cos(angle);\nrotatedCorner.z=0.;\n\nviewPos+=rotatedCorner;\ngl_Position=projection*vec4(viewPos,1.0); \nvFragmentDepth = 1.0 + gl_Position.w;\ngl_Position.z = log2(max(0.000001, vFragmentDepth)) * logarithmicDepthConstant;\n\nvColor=color;\n\nvec2 uvOffset=vec2(abs(offset.x-cellInfo.x),1.0-abs(offset.y-cellInfo.y));\nvUV=(uvOffset+cellInfo.zw)*uvScale;\n\n#ifdef FOG\nvFogDistance=viewPos;\n#endif\n}"; | |
BABYLON.Effect.ShadersStore.spritesDepthPixelShader = "uniform bool alphaTest;\nvarying vec4 vColor;\n#extension GL_EXT_frag_depth : enable\nuniform float logarithmicDepthConstant;\nvarying float vFragmentDepth;\n\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n\n#include<fogFragmentDeclaration>\nvoid main(void) {\nvec4 color=texture2D(diffuseSampler,vUV);\nif (alphaTest) \n{\nif (color.a<0.95)\ndiscard;\n}\ncolor*=vColor;\n#include<fogFragment>\ngl_FragDepthEXT = log2(vFragmentDepth) * logarithmicDepthConstant * 0.5;\ngl_FragColor=color;\n}"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment