Three.js - 鱼眼效果

8
所以,我已经在three.js上进行了一些尝试,效果非常好。唯一让我困惑的是如何制作一个具有真正鱼眼效果的相机。
这可能怎么实现呢?camera.setLens()

你得到答案了吗? - Parth
5个回答

16

可以使用Giliam de Carpentier的透镜畸变着色器实现鱼眼效果。

着色器代码:

function getDistortionShaderDefinition()
{
    return {

        uniforms: {
            "tDiffuse":         { type: "t", value: null },
            "strength":         { type: "f", value: 0 },
            "height":           { type: "f", value: 1 },
            "aspectRatio":      { type: "f", value: 1 },
            "cylindricalRatio": { type: "f", value: 1 }
        },

        vertexShader: [
            "uniform float strength;",          // s: 0 = perspective, 1 = stereographic
            "uniform float height;",            // h: tan(verticalFOVInRadians / 2)
            "uniform float aspectRatio;",       // a: screenWidth / screenHeight
            "uniform float cylindricalRatio;",  // c: cylindrical distortion ratio. 1 = spherical

            "varying vec3 vUV;",                // output to interpolate over screen
            "varying vec2 vUVDot;",             // output to interpolate over screen

            "void main() {",
                "gl_Position = projectionMatrix * (modelViewMatrix * vec4(position, 1.0));",

                "float scaledHeight = strength * height;",
                "float cylAspectRatio = aspectRatio * cylindricalRatio;",
                "float aspectDiagSq = aspectRatio * aspectRatio + 1.0;",
                "float diagSq = scaledHeight * scaledHeight * aspectDiagSq;",
                "vec2 signedUV = (2.0 * uv + vec2(-1.0, -1.0));",

                "float z = 0.5 * sqrt(diagSq + 1.0) + 0.5;",
                "float ny = (z - 1.0) / (cylAspectRatio * cylAspectRatio + 1.0);",

                "vUVDot = sqrt(ny) * vec2(cylAspectRatio, 1.0) * signedUV;",
                "vUV = vec3(0.5, 0.5, 1.0) * z + vec3(-0.5, -0.5, 0.0);",
                "vUV.xy += uv;",
            "}"
        ].join("\n"),

        fragmentShader: [
            "uniform sampler2D tDiffuse;",      // sampler of rendered scene?s render target
            "varying vec3 vUV;",                // interpolated vertex output data
            "varying vec2 vUVDot;",             // interpolated vertex output data

            "void main() {",
                "vec3 uv = dot(vUVDot, vUVDot) * vec3(-0.5, -0.5, -1.0) + vUV;",
                "gl_FragColor = texture2DProj(tDiffuse, uv);",
            "}"
        ].join("\n")

    };
}

通过使用特效合成器设置效果的一种方法(假设已经创建了场景渲染器):
// Create camera
camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 1, 1000000 );
camera.position.z = 800;

// Create effect composer
composer = new THREE.EffectComposer( renderer );
composer.addPass( new THREE.RenderPass( scene, camera ) );

// Add distortion effect to effect composer
var effect = new THREE.ShaderPass( getDistortionShaderDefinition() );
composer.addPass( effect );
effect.renderToScreen = true;

// Setup distortion effect
var horizontalFOV = 140;
var strength = 0.5;
var cylindricalRatio = 2;
var height = Math.tan(THREE.Math.degToRad(horizontalFOV) / 2) / camera.aspect;

camera.fov = Math.atan(height) * 2 * 180 / 3.1415926535;
camera.updateProjectionMatrix();

effect.uniforms[ "strength" ].value = strength;
effect.uniforms[ "height" ].value = height;
effect.uniforms[ "aspectRatio" ].value = camera.aspect;
effect.uniforms[ "cylindricalRatio" ].value = cylindricalRatio;

以下脚本是必需的,可以在three.js GitHub页面等地找到:

<script src="examples/js/postprocessing/EffectComposer.js"></script>
<script src="examples/js/postprocessing/RenderPass.js"></script>
<script src="examples/js/postprocessing/MaskPass.js"></script>
<script src="examples/js/postprocessing/ShaderPass.js"></script>
<script src="examples/js/shaders/CopyShader.js"></script>

链接到Giliam的示例:http://www.decarpentier.nl/downloads/lensdistortion-webgl/lensdistortion-webgl.html

Giliam关于镜头畸变的文章链接:http://www.decarpentier.nl/lens-distortion

我测试使用了镜头畸变效果的图片:

Image


1
将摄像机放入反射球体内。确保球体是双面的。如果想在场景中移动它,请将摄像机和球体绑定在一起。非常好用。

http://tileableart.com/code/NOCosmos/test.html

借自:

http://mrdoob.github.io/three.js/examples/webgl_materials_cubemap_dynamic2.html

cubeCamera = new THREE.CubeCamera( 1, 3000, 1024);
            cubeCamera.renderTarget.minFilter = THREE.LinearMipMapLinearFilter;
scene.add( cubeCamera );
camParent.add(cubeCamera);
var material = new THREE.MeshBasicMaterial( { envMap: cubeCamera.renderTarget } );
material.side = THREE.DoubleSide;
sphere = new THREE.Mesh( new THREE.SphereGeometry( 2, 60, 30 ), material );

0

使用高视场角可以获得鱼眼效果。

            var fishCamera = new THREE.PerspectiveCamera( 110, window.innerWidth / window.innerHeight, 1, 1100 );
            var normalCamera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1100 );

或设置

camera.fov = 110 
camera.updateProjectionMatrix();

这里有一个实时示例: http://mrdoob.github.com/three.js/examples/canvas_geometry_panorama_fisheye.html


0
一种方法是在相机上设置大视野:
new THREE.PerspectiveCamera(140, ... )

这实际上不是鱼眼效果,但可能是您要寻找的效果。

在真正的相机镜头中,想要获得大视野而又没有畸变,很可能会使镜头价格昂贵,但在计算机图形学中,这是简单的方法。

一个真正的鱼眼镜头会扭曲图像,使直线变成弯曲的,就像这张图片:

Fisheye example, CC by Ilveon at Wikipedia

如果你想要使用这种畸变创建真正的鱼眼效果,你需要修改几何形状,就像Three.js的鱼眼示例一样。在那个示例中,几何形状实际上是事先修改的,但对于更高级的场景,你需要使用顶点着色器来动态更新顶点。


我尝试过使用setLens和/或更改透视,但效果不如预期。我将尝试更具体地说明问题,以便请求一个好的答案:因此,我的物理设置如下:投影仪用于在球内投影,真正的鱼眼镜头连接到投影仪上。所需的软件:真正的问题是,我想要投影的图像/3D场景需要显示为鱼眼,以获得满意的效果。例如,Microsoft已经完成了这个示例: http://www.youtube.com/watch?v=-YLdYlN6FhI&feature=related - MrQuiw

0
广角镜头通常具有非常低的焦距。
为了实现极端的广角,我们需要缩短焦距。
请注意,鱼眼镜头是一种极端广角镜头。
要缩短焦距(或实现极端广角),可以通过增加视场角(FOV)来实现,因为FOV与焦距成反比。
例如:
var camera_1 = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );

var camera_2 = new THREE.PerspectiveCamera( 80, width / height, 1, 1000 );

这里的camera_2是一个更广角的设置。

注意

为了达到所需的效果,可能需要调整摄像机的位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接