use of org.terasology.math.geom.Vector3f in project Terasology by MovingBlocks.
the class AmbientOcclusionNode method createSamplesBuffer.
private void createSamplesBuffer() {
ssaoSamples = BufferUtils.createFloatBuffer(SSAO_KERNEL_ELEMENTS * 3);
for (int i = 0; i < SSAO_KERNEL_ELEMENTS; ++i) {
Vector3f vec = new Vector3f();
vec.x = randomGenerator.nextFloat(-1.0f, 1.0f);
vec.y = randomGenerator.nextFloat(-1.0f, 1.0f);
vec.z = randomGenerator.nextFloat();
vec.normalize();
vec.scale(randomGenerator.nextFloat(0.0f, 1.0f));
float scale = i / (float) SSAO_KERNEL_ELEMENTS;
scale = TeraMath.lerp(0.25f, 1.0f, scale * scale);
vec.scale(scale);
ssaoSamples.put(vec.x);
ssaoSamples.put(vec.y);
ssaoSamples.put(vec.z);
}
ssaoSamples.flip();
}
use of org.terasology.math.geom.Vector3f in project Terasology by MovingBlocks.
the class ShadowMapNode method positionShadowMapCamera.
private void positionShadowMapCamera() {
// We begin by setting our light coordinates at the player coordinates, ignoring the player's altitude
// world-space coordinates
Vector3f mainLightPosition = new Vector3f(activeCamera.getPosition().x, 0.0f, activeCamera.getPosition().z);
// The shadow projected onto the ground must move in in light-space texel-steps, to avoid causing flickering.
// That's why we first convert it to the previous frame's light-space coordinates and then back to world-space.
// to light-space
shadowMapCamera.getViewProjectionMatrix().transformPoint(mainLightPosition);
mainLightPosition.set(TeraMath.fastFloor(mainLightPosition.x / texelSize) * texelSize, 0.0f, TeraMath.fastFloor(mainLightPosition.z / texelSize) * texelSize);
// back to world-space
shadowMapCamera.getInverseViewProjectionMatrix().transformPoint(mainLightPosition);
// This is what causes the shadow map to change infrequently, to prevent flickering.
// Notice that this is different from what is done above, which is about spatial steps
// and is related to the player's position and texels.
Vector3f quantizedMainLightDirection = getQuantizedMainLightDirection(STEP_SIZE);
// The shadow map camera is placed away from the player, in the direction of the main light.
Vector3f offsetFromPlayer = new Vector3f(quantizedMainLightDirection);
// these hardcoded numbers are another mystery.
offsetFromPlayer.scale(256.0f + 64.0f);
mainLightPosition.add(offsetFromPlayer);
shadowMapCamera.getPosition().set(mainLightPosition);
// Finally, we adjust the shadow map camera to look toward the player
Vector3f fromLightToPlayerDirection = new Vector3f(quantizedMainLightDirection);
fromLightToPlayerDirection.scale(-1.0f);
shadowMapCamera.getViewingDirection().set(fromLightToPlayerDirection);
shadowMapCamera.update(worldRenderer.getSecondsSinceLastFrame());
}
use of org.terasology.math.geom.Vector3f in project Terasology by MovingBlocks.
the class ShadowMapNode method process.
/**
* Re-positions the shadow map camera to loosely match the position of the main light (sun, moon), then
* writes depth information from that camera into a depth buffer, to be used later to create shadows.
*
* The loose match is to avoid flickering: the shadowmap only moves in steps while the main light actually
* moves continuously.
*
* This method is executed within a NodeTask in the Render Tasklist, but its calculations are executed
* only once per frame. I.e. in VR mode they are executed only when the left eye is processed. This is
* done in the assumption that we do not need to generate and use a shadow map for each eye as it wouldn't
* be noticeable.
*/
@Override
public void process() {
// TODO: remove this IF statement when VR is handled via parallel nodes, one per eye.
if (worldRenderer.isFirstRenderingStageForCurrentFrame()) {
PerformanceMonitor.startActivity("rendering/" + getUri());
// Actual Node Processing
// TODO: extract these calculation into a separate node.
positionShadowMapCamera();
int numberOfRenderedTriangles = 0;
int numberOfChunksThatAreNotReadyYet = 0;
final Vector3f cameraPosition = shadowMapCamera.getPosition();
shadowMapCamera.lookThrough();
// FIXME: storing chunksOpaqueShadow or a mechanism for requesting a chunk queue for nodes which calls renderChunks method?
while (renderQueues.chunksOpaqueShadow.size() > 0) {
RenderableChunk chunk = renderQueues.chunksOpaqueShadow.poll();
if (chunk.hasMesh()) {
final ChunkMesh chunkMesh = chunk.getMesh();
final Vector3f chunkPosition = chunk.getPosition().toVector3f();
numberOfRenderedTriangles += chunkMesh.render(OPAQUE, chunkPosition, cameraPosition);
} else {
numberOfChunksThatAreNotReadyYet++;
}
}
worldRenderer.increaseTrianglesCount(numberOfRenderedTriangles);
worldRenderer.increaseNotReadyChunkCount(numberOfChunksThatAreNotReadyYet);
PerformanceMonitor.endActivity();
}
}
use of org.terasology.math.geom.Vector3f in project Terasology by MovingBlocks.
the class ShadowMapNode method getQuantizedMainLightDirection.
private Vector3f getQuantizedMainLightDirection(float stepSize) {
float mainLightAngle = (float) Math.floor(backdropProvider.getSunPositionAngle() * stepSize) / stepSize + 0.0001f;
Vector3f mainLightDirection = new Vector3f(0.0f, (float) Math.cos(mainLightAngle), (float) Math.sin(mainLightAngle));
// When the sun goes under the horizon we flip the vector, to provide the moon direction, and viceversa.
if (mainLightDirection.y < 0.0f) {
mainLightDirection.scale(-1.0f);
}
return mainLightDirection;
}
use of org.terasology.math.geom.Vector3f in project Terasology by MovingBlocks.
the class WorldReflectionNode method process.
/**
* Renders the landscape, reflected, into the buffers attached to the "engine:sceneReflected" FBO. It is used later,
* to render horizontal reflective surfaces, i.e. water.
*
* Notice that this method -does not- clear the FBO. The rendering takes advantage of the depth buffer to decide
* which pixel is in front of the one already stored in the buffer.
*
* See: https://en.wikipedia.org/wiki/Deep_image_compositing
*/
@Override
public void process() {
PerformanceMonitor.startActivity("rendering/" + getUri());
chunkMaterial.activateFeature(ShaderProgramFeature.FEATURE_USE_FORWARD_LIGHTING);
// Common Shader Parameters
chunkMaterial.setFloat("daylight", backdropProvider.getDaylight(), true);
chunkMaterial.setFloat("time", worldProvider.getTime().getDays(), true);
// Specific Shader Parameters
// TODO: This is necessary right now because activateFeature removes all material parameters.
// TODO: Remove this explicit binding once we get rid of activateFeature, or find a way to retain parameters through it.
chunkMaterial.setInt("textureAtlas", 0, true);
chunkMaterial.setInt("textureEffects", 1, true);
chunkMaterial.setInt("textureLava", 2, true);
if (isNormalMapping) {
chunkMaterial.setInt("textureAtlasNormal", 3, true);
if (isParallaxMapping) {
chunkMaterial.setInt("textureAtlasHeight", 4, true);
chunkMaterial.setFloat4("parallaxProperties", parallaxBias, parallaxScale, 0.0f, 0.0f, true);
}
}
chunkMaterial.setFloat("clip", 0.0f, true);
// Actual Node Processing
int numberOfRenderedTriangles = 0;
int numberOfChunksThatAreNotReadyYet = 0;
final Vector3f cameraPosition = activeCamera.getPosition();
while (renderQueues.chunksOpaqueReflection.size() > 0) {
RenderableChunk chunk = renderQueues.chunksOpaqueReflection.poll();
if (chunk.hasMesh()) {
final ChunkMesh chunkMesh = chunk.getMesh();
final Vector3f chunkPosition = chunk.getPosition().toVector3f();
chunkMesh.updateMaterial(chunkMaterial, chunkPosition, chunk.isAnimated());
numberOfRenderedTriangles += chunkMesh.render(OPAQUE, chunkPosition, cameraPosition);
} else {
numberOfChunksThatAreNotReadyYet++;
}
}
chunkMaterial.deactivateFeature(ShaderProgramFeature.FEATURE_USE_FORWARD_LIGHTING);
worldRenderer.increaseTrianglesCount(numberOfRenderedTriangles);
worldRenderer.increaseNotReadyChunkCount(numberOfChunksThatAreNotReadyYet);
PerformanceMonitor.endActivity();
}
Aggregations