package eu.tankernn.gameEngine.renderEngine.entities; import static eu.tankernn.gameEngine.settings.Settings.BLUE; import static eu.tankernn.gameEngine.settings.Settings.GREEN; import static eu.tankernn.gameEngine.settings.Settings.RED; import java.util.List; import java.util.Map; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Matrix4f; import org.lwjgl.util.vector.Vector4f; import eu.tankernn.gameEngine.entities.Entity; import eu.tankernn.gameEngine.entities.Light; import eu.tankernn.gameEngine.loader.models.TexturedModel; import eu.tankernn.gameEngine.loader.textures.ModelTexture; import eu.tankernn.gameEngine.loader.textures.Texture; import eu.tankernn.gameEngine.renderEngine.MasterRenderer; import eu.tankernn.gameEngine.util.ICamera; import eu.tankernn.gameEngine.util.Maths; /** * Renderer for entities. * * @author Frans * */ public class EntityRenderer { private EntityShader shader; /** * Starts shader and loads initial values. * * @param shader * The shader to use when rendering entities * @param projectionMatrix * The projection matrix to use when rendering entities */ public EntityRenderer(Matrix4f projectionMatrix) { this.shader = new EntityShader(); shader.start(); shader.projectionMatrix.loadMatrix(projectionMatrix); shader.connectTextureUnits(); shader.stop(); } /** * Renders entities to the current frame buffer. * * @param entities * The entities to render. * @param toShadowSpace * Transformation matrix to shadow space. Used for applying * shadows. */ public void render(Map> entities, Matrix4f toShadowSpace, ICamera cam, Vector4f clipPlane, List lights, Texture environmentMap) { shader.start(); shader.plane.loadVec4(clipPlane); shader.skyColor.loadVec3(RED, GREEN, BLUE); shader.loadLights(lights); shader.viewMatrix.loadCamera(cam); shader.toShadowMapSpace.loadMatrix(toShadowSpace); shader.cameraPosition.loadVec3(cam.getPosition()); for (TexturedModel model : entities.keySet()) { prepareTexturedModel(model, environmentMap); List batch = entities.get(model); for (Entity entity : batch) { prepareInstance(entity); GL11.glDrawElements(GL11.GL_TRIANGLES, model.getRawModel().getIndexCount(), GL11.GL_UNSIGNED_INT, 0); } unbindTexturedModel(model); } shader.stop(); } public void cleanUp() { shader.cleanUp(); } private void prepareTexturedModel(TexturedModel model, Texture environmentMap) { model.getRawModel().bind(0, 1, 2); ModelTexture texture = model.getModelTexture(); shader.numberOfRows.loadFloat(texture.getNumberOfRows()); if (texture.hasTransparency()) MasterRenderer.disableCulling(); shader.useFakeLighting.loadBoolean(texture.isUseFakeLighting()); shader.shineDamper.loadFloat(texture.getShineDamper()); shader.reflectivity.loadFloat(texture.getReflectivity()); model.getModelTexture().getTexture().bindToUnit(0); shader.usesSpecularMap.loadBoolean(texture.hasSpecularMap()); if (texture.hasSpecularMap()) { texture.getSpecularMap().bindToUnit(1); } bindEnvironmentMap(environmentMap); } private void bindEnvironmentMap(Texture environmentMap) { environmentMap.bindToUnit(10); } private void unbindTexturedModel(TexturedModel model) { MasterRenderer.enableCulling(); model.getRawModel().unbind(0, 1, 2); } private void prepareInstance(Entity entity) { Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(), entity.getRotX(), entity.getRotY(), entity.getRotZ(), entity.getScale()); shader.transformationMatrix.loadMatrix(transformationMatrix); shader.offset.loadVec2(entity.getTextureXOffset(), entity.getTextureYOffset()); } }