private void modifyProjectionMatrix(final Vector4 clipPlane) { // Get the current projection matrix projectionMatrix = cam.getProjectionMatrix().toArray(projectionMatrix); // Get the inverse transpose of the current modelview matrix final ReadOnlyMatrix4 modelViewMatrixInvTrans = tRenderer.getCamera().getModelViewMatrix().invert(tmpMatrix).transposeLocal(); modelViewMatrixInvTrans.applyPre(clipPlane, clipPlane); // Calculate the clip-space corner point opposite the clipping plane // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and // transform it into camera space by multiplying it // by the inverse of the projection matrix cornerPoint.setX((sign(clipPlane.getX()) + projectionMatrix[8]) / projectionMatrix[0]); cornerPoint.setY((sign(clipPlane.getY()) + projectionMatrix[9]) / projectionMatrix[5]); cornerPoint.setZ(-1.0); cornerPoint.setW((1.0 + projectionMatrix[10]) / projectionMatrix[14]); // Calculate the scaled plane vector final Vector4 scaledPlaneVector = clipPlane.multiply((2.0 / clipPlane.dot(cornerPoint)), cornerPoint); // Replace the third row of the projection matrix projectionMatrix[2] = scaledPlaneVector.getX(); projectionMatrix[6] = scaledPlaneVector.getY(); projectionMatrix[10] = scaledPlaneVector.getZ() + 1.0; projectionMatrix[14] = scaledPlaneVector.getW(); // Load it back into OpenGL final Matrix4 newProjectionMatrix = tmpMatrix.fromArray(projectionMatrix); tRenderer.getCamera().setProjectionMatrix(newProjectionMatrix); }
public void updateCamera() { if (isSupported()) { tRenderer .getCamera() .setFrustum( cam.getFrustumNear(), cam.getFrustumFar(), cam.getFrustumLeft(), cam.getFrustumRight(), cam.getFrustumTop(), cam.getFrustumBottom()); } }
/** Render water refraction RTT */ private void renderRefraction(final Vector4 clipPlane) { if (renderList.isEmpty()) { return; } refractionTime += tpf; if (refractionTime < refractionThrottle) { return; } refractionTime = 0; // tRenderer.getCamera().set(cam); tRenderer.getCamera().setLocation(cam.getLocation()); tRenderer.getCamera().setDirection(cam.getDirection()); tRenderer.getCamera().setUp(cam.getUp()); tRenderer.getCamera().setLeft(cam.getLeft()); CullHint cullMode = CullHint.Dynamic; if (skyBox != null) { cullMode = skyBox.getSceneHints().getCullHint(); skyBox.getSceneHints().setCullHint(CullHint.Always); } tRenderer.getCamera().setProjectionMatrix(cam.getProjectionMatrix()); texArray.clear(); texArray.add(textureRefract); texArray.add(textureDepth); tRenderer.getCamera().update(); tRenderer.getCamera().getModelViewMatrix(); tRenderer.getCamera().getProjectionMatrix(); tRenderer.render(renderList, texArray, Renderer.BUFFER_COLOR_AND_DEPTH); if (skyBox != null) { skyBox.getSceneHints().setCullHint(cullMode); } }
/** Render water reflection RTT */ private void renderReflection(final Vector4 clipPlane) { if (renderList.isEmpty()) { return; } reflectionTime += tpf; if (reflectionTime < reflectionThrottle) { return; } reflectionTime = 0; if (aboveWater) { camLocation.set(cam.getLocation()); double planeDistance = waterPlane.pseudoDistance(camLocation); calcVect.set(waterPlane.getNormal()).multiplyLocal(planeDistance * 2.0f); camReflectPos.set(camLocation.subtractLocal(calcVect)); camLocation.set(cam.getLocation()).addLocal(cam.getDirection()); planeDistance = waterPlane.pseudoDistance(camLocation); calcVect.set(waterPlane.getNormal()).multiplyLocal(planeDistance * 2.0f); camReflectDir .set(camLocation.subtractLocal(calcVect)) .subtractLocal(camReflectPos) .normalizeLocal(); camLocation.set(cam.getLocation()).addLocal(cam.getUp()); planeDistance = waterPlane.pseudoDistance(camLocation); calcVect.set(waterPlane.getNormal()).multiplyLocal(planeDistance * 2.0f); camReflectUp .set(camLocation.subtractLocal(calcVect)) .subtractLocal(camReflectPos) .normalizeLocal(); camReflectLeft.set(camReflectUp).crossLocal(camReflectDir).normalizeLocal(); tRenderer.getCamera().setLocation(camReflectPos); tRenderer.getCamera().setDirection(camReflectDir); tRenderer.getCamera().setUp(camReflectUp); tRenderer.getCamera().setLeft(camReflectLeft); } else { tRenderer.getCamera().setLocation(cam.getLocation()); tRenderer.getCamera().setDirection(cam.getDirection()); tRenderer.getCamera().setUp(cam.getUp()); tRenderer.getCamera().setLeft(cam.getLeft()); } if (skyBox != null) { tmpLocation.set(skyBox.getTranslation()); skyBox.setTranslation(tRenderer.getCamera().getLocation()); skyBox.updateGeometricState(0.0f); skyBox.getSceneHints().setCullHint(CullHint.Never); } texArray.clear(); if (doBlurReflection) { texArray.add(textureReflect); } else { texArray.add(textureReflectBlur); } tRenderer.getCamera().setProjectionMode(ProjectionMode.Custom); tRenderer.getCamera().setProjectionMatrix(cam.getProjectionMatrix()); tRenderer.render(skyBox, texArray, Renderer.BUFFER_COLOR_AND_DEPTH); if (skyBox != null) { skyBox.getSceneHints().setCullHint(CullHint.Always); } modifyProjectionMatrix(clipPlane); tRenderer.render(renderList, texArray, Renderer.BUFFER_NONE); if (doBlurReflection) { blurReflectionTexture(); } if (skyBox != null) { skyBox.setTranslation(tmpLocation); skyBox.updateGeometricState(0.0f); skyBox.getSceneHints().setCullHint(CullHint.Never); } }
/** * Initialize texture renderers. Load water textures. Create shaders. * * @param r */ private void initialize(final Renderer r) { if (cam == null || initialized) { return; } initialized = true; final ContextCapabilities caps = ContextManager.getCurrentContext().getCapabilities(); if (useRefraction && useProjectedShader && caps.getNumberOfFragmentTextureUnits() < 6 || useRefraction && caps.getNumberOfFragmentTextureUnits() < 5) { useRefraction = false; logger.info("Not enough textureunits, falling back to non refraction water"); } if (!caps.isGLSLSupported()) { supported = false; } if (!(caps.isPbufferSupported() || caps.isFBOSupported())) { supported = false; } if (isSupported()) { tRenderer = TextureRendererFactory.INSTANCE.createTextureRenderer( // cam.getWidth() / renderScale, // width cam.getHeight() / renderScale, // height 8, // Depth bits... TODO: Make configurable? 0, // Samples... TODO: Make configurable? r, caps); // blurSampleDistance = 1f / ((float) cam.getHeight() / renderScale); tRenderer.setMultipleTargets(true); tRenderer.setBackgroundColor(new ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f)); tRenderer .getCamera() .setFrustum( cam.getFrustumNear(), cam.getFrustumFar(), cam.getFrustumLeft(), cam.getFrustumRight(), cam.getFrustumTop(), cam.getFrustumBottom()); textureState = new TextureState(); textureState.setEnabled(true); setupTextures(); fullScreenQuad = new Quad("FullScreenQuad", cam.getWidth() / 4, cam.getHeight() / 4); fullScreenQuad.setTranslation(cam.getWidth() / 2, cam.getHeight() / 2, 0); fullScreenQuad.getSceneHints().setRenderBucketType(RenderBucketType.Ortho); fullScreenQuad.getSceneHints().setCullHint(CullHint.Never); fullScreenQuad.getSceneHints().setTextureCombineMode(TextureCombineMode.Replace); fullScreenQuad.getSceneHints().setLightCombineMode(LightCombineMode.Off); final TextureState ts = new TextureState(); ts.setTexture(textureReflect); fullScreenQuad.setRenderState(ts); fullScreenQuad.setRenderState(blurShaderVertical); fullScreenQuad.updateWorldRenderStates(false); } if (!isSupported()) { createFallbackData(); } else { noFog = new FogState(); noFog.setEnabled(false); } getSceneHints().setCullHint(CullHint.Never); setWaterEffectOnSpatial(this); }