Ver código fonte

Merge pull request #1 from beiyang/master

Cubemaps
pull/2/merge
Matthew Petroff 11 anos atrás
pai
commit
31984ac9f6
9 arquivos alterados com 143 adições e 31 exclusões
  1. +10
    -0
      examples/examplecube.htm
  2. BIN
      examples/examplepanocubeXn.jpg
  3. BIN
      examples/examplepanocubeXp.jpg
  4. BIN
      examples/examplepanocubeYn.jpg
  5. BIN
      examples/examplepanocubeYp.jpg
  6. BIN
      examples/examplepanocubeZn.jpg
  7. BIN
      examples/examplepanocubeZp.jpg
  8. +95
    -22
      src/js/libpannellum.js
  9. +38
    -9
      src/js/pannellum.js

+ 10
- 0
examples/examplecube.htm Ver arquivo

@@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html>
<head>
<title>pannellum embed example</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<iframe title="pannellum panorama viewer" width="480" height="390" webkitAllowFullScreen mozallowfullscreen allowFullScreen style="border-style:none;" id="pannellum_JVU18uzhW5" src="../src/pannellum.htm?panorama0=../examples/examplepanocubeXp.jpg&panorama1=../examples/examplepanocubeXn.jpg&panorama2=../examples/examplepanocubeYp.jpg&panorama3=../examples/examplepanocubeYn.jpg&panorama4=../examples/examplepanocubeZp.jpg&panorama5=../examples/examplepanocubeZn.jpg&panotype=cubemap&amp;logo=yes&amp;title=Jordan%20Pond&amp;author=Matthew%20Petroff&amp;license=1&amp;preview=../examples/examplepano-preview.jpg"></iframe>
</body>
</html>

BIN
examples/examplepanocubeXn.jpg Ver arquivo

Antes Depois
Largura: 512  |  Altura: 512  |  Tamanho: 110 KiB

BIN
examples/examplepanocubeXp.jpg Ver arquivo

Antes Depois
Largura: 512  |  Altura: 512  |  Tamanho: 87 KiB

BIN
examples/examplepanocubeYn.jpg Ver arquivo

Antes Depois
Largura: 512  |  Altura: 512  |  Tamanho: 107 KiB

BIN
examples/examplepanocubeYp.jpg Ver arquivo

Antes Depois
Largura: 512  |  Altura: 512  |  Tamanho: 63 KiB

BIN
examples/examplepanocubeZn.jpg Ver arquivo

Antes Depois
Largura: 512  |  Altura: 512  |  Tamanho: 2.9 KiB

BIN
examples/examplepanocubeZp.jpg Ver arquivo

Antes Depois
Largura: 512  |  Altura: 512  |  Tamanho: 3.1 KiB

+ 95
- 22
src/js/libpannellum.js Ver arquivo

@@ -22,21 +22,33 @@
*/

window.libpannellum = (function(window, document, undefined) {
function Renderer(canvas, image) {
/* Image Type argument can be that of "equirectangular", "cubemap"
* If "cubemap" is used, the image argument should be an array of images
* instead of a single image. They should be the order of:
* +x -x +y -y +z -z
*/
function Renderer(canvas, image, imageType) {
this.canvas = canvas;
this.image = image;

//Default argument for image type
this.imageType = "equirectangular";
if( typeof imageType != "undefined" ){
this.imageType = imageType;
}

var program, gl;
this.init = function(haov, vaov, voffset) {
// Enable WebGL on canvas
gl = this.canvas.getContext('experimental-webgl');
var glBindType = gl.TEXTURE_2D;

// Create viewport for entire canvas and clear canvas
gl.viewport(0, 0, this.canvas.width, this.canvas.height);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// Create vertex shader
var vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, v);
@@ -44,7 +56,12 @@ function Renderer(canvas, image) {
// Create fragment shader
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, f);
var fragmentSrc = fragEquirectangular;
if( this.imageType == "cubemap"){
glBindType = gl.TEXTURE_CUBE_MAP
fragmentSrc = fragCube;
}
gl.shaderSource(fs, fragmentSrc);
gl.compileShader(fs);
// Link WebGL program
@@ -90,21 +107,32 @@ function Renderer(canvas, image) {
gl.uniform1f(program.h, haov / (Math.PI * 2.0));
gl.uniform1f(program.v, vaov / Math.PI);
gl.uniform1f(program.vo, voffset / Math.PI);
// Create texture
program.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, program.texture);
gl.bindTexture(glBindType, program.texture);

//upload images to texture depending on type
if( this.imageType == "cubemap" ){
//Load all 6 sides of the cube map
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image[0]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image[1]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image[2]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image[3]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image[4]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image[5]);
}else{
// Upload image to the texture
gl.texImage2D(glBindType, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image);
}

// Set parameters for rendering any size
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
// Upload image to texture
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image);
gl.texParameteri(glBindType, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(glBindType, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(glBindType, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(glBindType, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
}

this.render = function(pitch, yaw, hfov) {
// Calculate focal length from horizontal angle of view
var focal = 1 / Math.tan(hfov / 2);
@@ -117,7 +145,7 @@ function Renderer(canvas, image) {
// Draw using current buffer
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
this.setImage = function(image) {
this.image = image;
this.init();
@@ -144,7 +172,52 @@ var v = [
].join('');

// Fragment shader
var f = [
var fragCube = [
'precision mediump float;',

'uniform float u_aspectRatio;',
'uniform float u_psi;',
'uniform float u_theta;',
'uniform float u_f;',
'uniform float u_h;',
'uniform float u_v;',
'uniform float u_vo;',

'const float PI = 3.14159265358979323846264;',

// Texture
'uniform samplerCube u_image;',

// Coordinates passed in from vertex shader
'varying vec2 v_texCoord;',

'void main() {',
// Find the vector of focal point to view plane
'vec3 planePos = vec3(v_texCoord.xy, 0.0);',
'planePos.x *= u_aspectRatio;',
'vec3 viewVector = planePos - vec3(0.0,0.0,-u_f);',

//rotate vector for psi (yaw) and theta (pitch)
'float sinpsi = sin(-u_psi);',
'float cospsi = cos(-u_psi);',
'float sintheta = sin(u_theta);',
'float costheta = cos(u_theta);',
//now apply the rotations
'vec3 viewVectorTheta = viewVector;',
'viewVectorTheta.z = viewVector.z * costheta - viewVector.y * sintheta;',
'viewVectorTheta.y = viewVector.z * sintheta + viewVector.y * costheta;',
'vec3 viewVectorPsi = viewVectorTheta;',
'viewVectorPsi.x = viewVectorTheta.x * cospsi - viewVectorTheta.z * sinpsi;',
'viewVectorPsi.z = viewVectorTheta.x * sinpsi + viewVectorTheta.z * cospsi;',

//lookup the color
'gl_FragColor = textureCube(u_image, viewVectorPsi);',
'}'
].join('\n');

// Fragment shader
var fragEquirectangular = [
'precision mediump float;',

'uniform float u_aspectRatio;',
@@ -173,7 +246,7 @@ var f = [
'float root = sqrt(x * x + a * a);',
'float lambda = atan(x / root, a / root) + u_psi;',
'float phi = atan((y * costheta + u_f * sintheta) / root);',
// Wrap image
'if(lambda > PI)',
'lambda = lambda - PI * 2.0;',
@@ -193,8 +266,8 @@ var f = [
].join('\n');

return {
renderer: function(canvas, image) {
return new Renderer(canvas, image);
renderer: function(canvas, image, imagetype) {
return new Renderer(canvas, image, imagetype);
}
}



+ 38
- 9
src/js/pannellum.js Ver arquivo

@@ -148,10 +148,20 @@ if(getURLParameter('autorotate') == 'ccw') {
}

function init() {
var panoimage = new Image()
panoimage.onload = function() {
var panotype = getURLParameter('panotype');
if( panotype == '' ) panotype = "equirectangular";
var panoimage;
if( panotype != "cubemap" ){
panoimage = new Image();
}else{
panoimage = new Array();
for( var i=0; i < 6; i++ )panoimage.push( new Image() );
}

function finishloadimage() {
try {
renderer = new libpannellum.renderer(canvas, panoimage);
renderer = new libpannellum.renderer(canvas, panoimage, panotype);
} catch (event) {
// show error message if WebGL is not supported
anError();
@@ -180,11 +190,29 @@ function init() {
renderInit();
var t=setTimeout('isTimedOut = true',500);
setInterval('keyRepeat()',10);
};
panoimage.src = getURLParameter('panorama');
}
//set event handlers
if( panotype != "cubemap" ){
panoimage.onload = finishloadimage;
panoimage.src = getURLParameter('panorama');
}else{
//quick loading counter for syncronous loading
var itemstoload = 6;
function loadCounter(){
itemstoload --;
if( itemstoload == 0 ){
finishloadimage();
}
}
//set the onload and src
for(var i=0; i < panoimage.length; i++){
panoimage[i].onload = loadCounter;
panoimage[i].src = getURLParameter('panorama' + i.toString());
}
}
document.getElementById('page').className = 'grab';
}

@@ -227,9 +255,10 @@ function onDocumentMouseDown(event) {
}

function onDocumentMouseMove(event) {
if (isUserInteracting) {
yaw = (onPointerDownPointerX - event.clientX) * 0.1 + onPointerDownYaw;
pitch = (event.clientY - onPointerDownPointerY) * 0.1 + onPointerDownPitch;
if (isUserInteracting) {
//TODO: This should not only be FOV scaled but scaled to canvas size
yaw = (onPointerDownPointerX - event.clientX) * 0.0029 * hfov + onPointerDownYaw;
pitch = (event.clientY - onPointerDownPointerY) * 0.0029 * hfov + onPointerDownPitch;
animate();
}
}


Carregando…
Cancelar
Salvar