package loon.opengl.d3d;
import loon.LRelease;
import loon.action.camera.BaseCamera;
import loon.opengl.light.Lights;
import loon.utils.Array;
import loon.utils.Pool;
import loon.utils.TArray;
public class ModelBatch implements LRelease{
protected BaseCamera camera;
protected final Pool<Renderable> renderablesPool = new Pool<Renderable>() {
@Override
protected Renderable newObject () {
return new Renderable();
}
@Override
public Renderable obtain () {
Renderable renderable = super.obtain();
renderable.lights = null;
renderable.material = null;
renderable.mesh = null;
renderable.shader = null;
return renderable;
}
};
protected final TArray<Renderable> renderables = new TArray<Renderable>();
protected final Array<Renderable> reuseableRenderables = new Array<Renderable>();
protected final RenderContext context;
protected final ShaderProvider shaderProvider;
protected final RenderableSorter sorter;
public ModelBatch(RenderContext context, ShaderProvider shaderProvider, RenderableSorter sorter) {
this.context = context;
this.shaderProvider = shaderProvider;
this.sorter = sorter;
}
public ModelBatch(ShaderProvider shaderProvider) {
this(new RenderContext(new DefaultTextureBinder(DefaultTextureBinder.ROUNDROBIN, 1)),
shaderProvider,
new DefaultRenderableSorter());
}
public ModelBatch(final String vertexShader, final String fragmentShader) {
this(new DefaultShaderProvider(vertexShader, fragmentShader));
}
public ModelBatch() {
this(new RenderContext(new DefaultTextureBinder(DefaultTextureBinder.ROUNDROBIN, 1)),
new DefaultShaderProvider(),
new DefaultRenderableSorter());
}
public void begin (BaseCamera cam) {
this.camera = cam;
}
public void end () {
sorter.sort(camera, renderables);
context.begin();
Shader currentShader = null;
for (int i = 0; i < renderables.size; i++) {
final Renderable renderable = renderables.get(i);
if (currentShader != renderable.shader) {
if (currentShader != null)
currentShader.end();
currentShader = renderable.shader;
currentShader.begin(camera, context);
}
currentShader.render(renderable);
}
if (currentShader != null)
currentShader.end();
context.end();
renderablesPool.freeAll(reuseableRenderables);
reuseableRenderables.clear();
renderables.clear();
camera = null;
}
public void render(final Renderable renderable) {
renderable.shader = shaderProvider.getShader(renderable);
renderable.mesh.setAutoBind(false);
renderables.add(renderable);
}
public void render(final RenderableProvider renderableProvider) {
render(renderableProvider, null, null);
}
public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders) {
render(renderableProviders, null, null);
}
public void render(final RenderableProvider renderableProvider, final Lights lights) {
render(renderableProvider, lights, null);
}
public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders, final Lights lights) {
render(renderableProviders, lights, null);
}
public void render(final RenderableProvider renderableProvider, final Shader shader) {
render(renderableProvider, null, shader);
}
public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders, final Shader shader) {
render(renderableProviders, null, shader);
}
public void render(final RenderableProvider renderableProvider, final Lights lights, final Shader shader) {
int offset = renderables.size;
renderableProvider.getRenderables(renderables, renderablesPool);
for (int i = offset; i < renderables.size; i++) {
Renderable renderable = renderables.get(i);
renderable.lights = lights;
renderable.shader = shader;
renderable.shader = shaderProvider.getShader(renderable);
reuseableRenderables.add(renderable);
}
}
public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders, final Lights lights, final Shader shader) {
for (final RenderableProvider renderableProvider : renderableProviders)
render(renderableProvider, lights, shader);
}
@Override
public void close () {
shaderProvider.close();
}
}