use of org.rajawali3d.extras.LensFlare.FlareInfo in project Rajawali by Rajawali.
the class LensFlarePlugin method render.
@Override
public void render() {
super.render();
int f, i, numLensFlares = mLensFlares.size();
// Calculate world space position to normalized screen space.
double viewportWidth = mRenderer.getViewportWidth(), viewportHeight = mRenderer.getDefaultViewportHeight();
double invAspect = viewportHeight / viewportWidth;
double size;
Vector2 scale = new Vector2();
double halfViewportWidth = viewportWidth / 2;
double halfViewportHeight = viewportHeight / 2;
Vector3 screenPosition = new Vector3();
double screenPositionPixels_x, screenPositionPixels_y;
Camera camera = mRenderer.getCurrentScene().getCamera();
Matrix4 viewMatrix = camera.getViewMatrix().clone(), projMatrix = camera.getProjectionMatrix().clone();
useProgram(mProgram);
// Push the VBOs to the GPU.
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mGeometry.getVertexBufferInfo().bufferHandle);
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glVertexAttribPointer(maPositionHandle, 2, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
// Push texture coordinates to the GPU.
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mGeometry.getTexCoordBufferInfo().bufferHandle);
GLES20.glEnableVertexAttribArray(maTextureCoordHandle);
GLES20.glVertexAttribPointer(maTextureCoordHandle, 2, GLES20.GL_FLOAT, false, 0, 0);
// Push vertex element indices to the GPU.
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mGeometry.getIndexBufferInfo().bufferHandle);
// Set up texture locations.
GLES20.glUniform1i(muOcclusionMapTextureHandle, 0);
GLES20.glUniform1i(muMapTextureHandle, 1);
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glDepthMask(false);
// Calculate camera direction vector.
Vector3 cameraPosition = camera.getPosition().clone();
Vector3 cameraLookAt = camera.getLookAt() != null ? camera.getLookAt().clone() : new Vector3(0, 0, 1);
Vector3 cameraDirection = cameraLookAt.clone().subtract(cameraPosition);
cameraDirection.normalize();
synchronized (mLensFlares) {
for (i = 0; i < numLensFlares; i++) {
size = 16 / viewportHeight;
scale.setX(size * invAspect);
scale.setY(size);
LensFlare lensFlare = mLensFlares.get(i);
// Calculate normalized device coordinates.
screenPosition.setAll(lensFlare.getPosition().clone());
screenPosition.multiply(viewMatrix);
screenPosition.project(projMatrix);
// Calculate actual device coordinates.
screenPositionPixels_x = screenPosition.x * halfViewportWidth + halfViewportWidth;
screenPositionPixels_y = screenPosition.y * halfViewportHeight + halfViewportHeight;
// Calculate the angle between the camera and the light vector.
Vector3 lightToCamDirection = lensFlare.getPosition().clone().subtract(cameraPosition);
lightToCamDirection.normalize();
double angleLightCamera = lightToCamDirection.dot(cameraDirection);
// viewing frustum.
if (mVertexTextureSupported || (angleLightCamera > 0 && screenPositionPixels_x > -64 && screenPositionPixels_x < viewportWidth + 64 && screenPositionPixels_y > -64 && screenPositionPixels_y < viewportHeight + 64)) {
// Bind current framebuffer to texture.
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mMapTexture.getTextureId());
GLES20.glCopyTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, (int) screenPositionPixels_x - 8, (int) screenPositionPixels_y - 8, 16, 16, 0);
// First render pass.
GLES20.glUniform1i(muRenderTypeHandle, 1);
GLES20.glUniform2fv(muScaleHandle, 1, new float[] { (float) scale.getX(), (float) scale.getY() }, 0);
GLES20.glUniform3fv(muScreenPositionHandle, 1, new float[] { (float) screenPosition.x, (float) screenPosition.y, (float) screenPosition.z }, 0);
GLES20.glDisable(GLES20.GL_BLEND);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_INT, 0);
// Copy result to occlusion map.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mOcclusionMapTexture.getTextureId());
GLES20.glCopyTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, (int) screenPositionPixels_x - 8, (int) screenPositionPixels_y - 8, 16, 16, 0);
// Second render pass.
GLES20.glUniform1i(muRenderTypeHandle, 2);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mMapTexture.getTextureId());
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_INT, 0);
// Update the flare's screen positions.
lensFlare.setPositionScreen(screenPosition);
lensFlare.updateLensFlares();
// Third render pass.
GLES20.glUniform1i(muRenderTypeHandle, 3);
GLES20.glEnable(GLES20.GL_BLEND);
for (f = 0; f < lensFlare.getLensFlares().size(); f++) {
FlareInfo sprite = lensFlare.getLensFlares().get(f);
// Don't bother rendering if the sprite's too transparent or too small.
if (sprite.getOpacity() > 0.001 && sprite.getScale() > 0.001) {
screenPosition.setAll(sprite.getScreenPosition());
// Calculate pixel size to normalized size
size = sprite.getSize() * sprite.getScale() / viewportHeight;
scale.setX(size * invAspect);
scale.setY(size);
GLES20.glUniform3fv(muScreenPositionHandle, 1, new float[] { (float) screenPosition.x, (float) screenPosition.y, (float) screenPosition.z }, 0);
GLES20.glUniform2fv(muScaleHandle, 1, new float[] { (float) scale.getX(), (float) scale.getY() }, 0);
GLES20.glUniform1f(muRotationHandle, (float) sprite.getRotation());
GLES20.glUniform1f(muOpacityHandle, (float) sprite.getOpacity());
GLES20.glUniform3fv(muColorHandle, 1, new float[] { (float) sprite.getColor().x, (float) sprite.getColor().y, (float) sprite.getColor().z }, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, sprite.getTexture().getTextureId());
//GLES20.glBlendEquation(GLES20.GL_FUNC_ADD);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE);
// Draw the elements.
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mGeometry.getNumIndices(), GLES20.GL_UNSIGNED_INT, 0);
// Unbind texture.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
}
}
}
}
// Unbind element array.
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthMask(true);
}