-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added a Method (panorama(img)
) which adds a sphereMapped Background.
#6808
Changes from 2 commits
9d2914b
997db50
71dc723
692ea24
71a32d5
9db3b2e
bc9558c
2c61205
88d251c
242aedd
ae6e257
3c491c4
30844cf
0117abd
47e9a6f
9741865
a063911
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -115,7 +115,7 @@ import p5 from '../core/main'; | |
* @param {p5.Color} color color as a <a href="#/p5.Color">p5.Color</a> | ||
* @chainable | ||
*/ | ||
p5.prototype.ambientLight = function(v1, v2, v3, a) { | ||
p5.prototype.ambientLight = function (v1, v2, v3, a) { | ||
this._assert3d('ambientLight'); | ||
p5._validateParameters('ambientLight', arguments); | ||
const color = this.color(...arguments); | ||
|
@@ -229,7 +229,7 @@ p5.prototype.ambientLight = function(v1, v2, v3, a) { | |
* @param {p5.Color} color color as a <a href="#/p5.Color">p5.Color</a> | ||
* @chainable | ||
*/ | ||
p5.prototype.specularColor = function(v1, v2, v3) { | ||
p5.prototype.specularColor = function (v1, v2, v3) { | ||
this._assert3d('specularColor'); | ||
p5._validateParameters('specularColor', arguments); | ||
const color = this.color(...arguments); | ||
|
@@ -327,7 +327,7 @@ p5.prototype.specularColor = function(v1, v2, v3) { | |
* @param {p5.Vector} direction | ||
* @chainable | ||
*/ | ||
p5.prototype.directionalLight = function(v1, v2, v3, x, y, z) { | ||
p5.prototype.directionalLight = function (v1, v2, v3, x, y, z) { | ||
this._assert3d('directionalLight'); | ||
p5._validateParameters('directionalLight', arguments); | ||
|
||
|
@@ -454,7 +454,7 @@ p5.prototype.directionalLight = function(v1, v2, v3, x, y, z) { | |
* @param {p5.Vector} position | ||
* @chainable | ||
*/ | ||
p5.prototype.pointLight = function(v1, v2, v3, x, y, z) { | ||
p5.prototype.pointLight = function (v1, v2, v3, x, y, z) { | ||
this._assert3d('pointLight'); | ||
p5._validateParameters('pointLight', arguments); | ||
|
||
|
@@ -592,13 +592,63 @@ p5.prototype.pointLight = function(v1, v2, v3, x, y, z) { | |
* @alt | ||
* light with slider having a slider for varying roughness | ||
*/ | ||
p5.prototype.imageLight = function(img){ | ||
p5.prototype.imageLight = function (img) { | ||
// activeImageLight property is checked by _setFillUniforms | ||
// for sending uniforms to the fillshader | ||
this._renderer.activeImageLight = img; | ||
this._renderer._enableLighting = true; | ||
}; | ||
|
||
/** | ||
* Creates a Panorama with given image. | ||
* | ||
* | ||
* `panorama(img)` is a method designed to transform a standard | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we could try to explain what kind of images this is intended to be used with? Possibly mentioning things like maps as a common example of a 360 degree view mapped to a rectangular image, and maybe how HDRIs are also in this format |
||
* image into a 360-degree view. It operates on the concept | ||
* of sphere mapping, where the image is manipulated to | ||
* resemble a sphere by adjusting camera angles. Utilizing | ||
* this method, users can obtain a complete 360-degree view | ||
* of a scene. | ||
* | ||
* Using Panorama is straightforward. Similar to calling a | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than describing what users can do, we can address this directly to users like instructions, e.g. "Similar to calling Also, we generally stay away from calling anything simple or straightforward so that people don't feel bad if they struggle using something. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This section where we describe it as being similar to background is actually maybe a good thing to start this documentation with instead of ending it with it, what do you think? |
||
* `background(color)`, users only need to call the `panorama(img)`, and | ||
* beneath it, anything created will form a 360-degree scene. | ||
* To enable 360-degree viewing, it is essential to invoke | ||
* `orbitControl()`; otherwise, the method will not function as intended. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe instead of saying it's essential, since it still works if you programmatically animate a camera, we can say to either use |
||
* @method panorama | ||
* @param {p5.image} img | ||
perminder-17 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @example | ||
* <div class="notest"> | ||
* <code> | ||
* let img; | ||
* function preload() { | ||
* img = loadImage('assets/outdoor_spheremap.jpg'); | ||
* } | ||
* function setup() { | ||
* createCanvas(100 ,100 ,WEBGL); | ||
* } | ||
* function draw() { | ||
* panorama(img); | ||
* imageMode(CENTER); | ||
* orbitControl(); | ||
* noStroke(); | ||
* push(); | ||
* imageLight(img); | ||
* specularMaterial('green'); | ||
* shininess(200); | ||
* metalness(100); | ||
* sphere(25); | ||
* pop(); | ||
* } | ||
* </code> | ||
* </div> | ||
* @alt | ||
* The image transformed into a panoramic scene. | ||
*/ | ||
p5.prototype.panorama = function (img) { | ||
this.filter(this._renderer._getSphereMapping(img)); | ||
}; | ||
|
||
/** | ||
* Places an ambient and directional light in the scene. | ||
* The lights are set to ambientLight(128, 128, 128) and | ||
|
@@ -634,7 +684,7 @@ p5.prototype.imageLight = function(img){ | |
* @alt | ||
* the light is partially ambient and partially directional | ||
*/ | ||
p5.prototype.lights = function() { | ||
p5.prototype.lights = function () { | ||
this._assert3d('lights'); | ||
// Both specify gray by default. | ||
const grayColor = this.color('rgb(128,128,128)'); | ||
|
@@ -698,7 +748,7 @@ p5.prototype.lights = function() { | |
* @alt | ||
* Two spheres with different falloff values show different intensity of light | ||
*/ | ||
p5.prototype.lightFalloff = function( | ||
p5.prototype.lightFalloff = function ( | ||
constantAttenuation, | ||
linearAttenuation, | ||
quadraticAttenuation | ||
|
@@ -892,7 +942,7 @@ p5.prototype.lightFalloff = function( | |
* @param {Number} [angle] | ||
* @param {Number} [concentration] | ||
*/ | ||
p5.prototype.spotLight = function( | ||
p5.prototype.spotLight = function ( | ||
v1, | ||
v2, | ||
v3, | ||
|
@@ -1153,7 +1203,7 @@ p5.prototype.spotLight = function( | |
* Three white spheres. Each appears as a different | ||
* color due to lighting. | ||
*/ | ||
p5.prototype.noLights = function(...args) { | ||
p5.prototype.noLights = function (...args) { | ||
this._assert3d('noLights'); | ||
p5._validateParameters('noLights', args); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -300,23 +300,32 @@ p5.prototype.createFilterShader = function (fragSrc) { | |
} | ||
`; | ||
let defaultVertV2 = `#version 300 es | ||
uniform mat4 uModelViewMatrix; | ||
uniform mat4 uProjectionMatrix; | ||
uniform mat4 uModelViewMatrix; | ||
uniform mat4 uProjectionMatrix; | ||
|
||
in vec3 aPosition; | ||
in vec2 aTexCoord; | ||
out vec2 vTexCoord; | ||
in vec3 aPosition; | ||
in vec2 aTexCoord; | ||
in vec3 aNormal; | ||
|
||
void main() { | ||
// transferring texcoords for the frag shader | ||
vTexCoord = aTexCoord; | ||
out vec3 faNormal; | ||
out vec3 vNormal; | ||
out vec3 faPosition; | ||
out vec2 vTexCoord; | ||
out vec3 fvNormal; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we don't use these in the shader, we can probably take them out from here |
||
|
||
void main() { | ||
// transferring vectors and texcoords for the frag shader | ||
faNormal = aNormal; | ||
fvNormal = vNormal; | ||
faPosition = aPosition; | ||
vTexCoord = aTexCoord; | ||
|
||
// copy position with a fourth coordinate for projection (1.0 is normal) | ||
vec4 positionVec4 = vec4(aPosition, 1.0); | ||
// copy position with a fourth coordinate for projection (1.0 is normal) | ||
vec4 positionVec4 = vec4(aPosition, 1.0); | ||
|
||
// project to 3D space | ||
gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; | ||
} | ||
// project to 3D space | ||
gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; | ||
} | ||
`; | ||
let vertSrc = fragSrc.includes('#version 300 es') ? defaultVertV2 : defaultVertV1; | ||
const shader = new p5.Shader(this._renderer, vertSrc, fragSrc); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,10 @@ const webgl2CompatibilityShader = readFileSync( | |
); | ||
|
||
const defaultShaders = { | ||
sphereMappingFrag: readFileSync( | ||
join(__dirname, '/shaders/sphereMapping.frag'), | ||
'utf-8' | ||
), | ||
immediateVert: readFileSync( | ||
join(__dirname, '/shaders/immediate.vert'), | ||
'utf-8' | ||
|
@@ -80,6 +84,7 @@ const defaultShaders = { | |
imageLightDiffusedFrag: readFileSync(join(__dirname, '/shaders/imageLightDiffused.frag'), 'utf-8'), | ||
imageLightSpecularFrag: readFileSync(join(__dirname, '/shaders/imageLightSpecular.frag'), 'utf-8') | ||
}; | ||
let sphereMapping = defaultShaders.sphereMappingFrag; | ||
for (const key in defaultShaders) { | ||
defaultShaders[key] = webgl2CompatibilityShader + defaultShaders[key]; | ||
} | ||
|
@@ -559,6 +564,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer { | |
this.executeRotateAndMove = false; | ||
|
||
this.specularShader = undefined; | ||
this.sphereMapping = undefined; | ||
this.diffusedShader = undefined; | ||
this._defaultLightShader = undefined; | ||
this._defaultImmediateModeShader = undefined; | ||
|
@@ -1012,6 +1018,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer { | |
} | ||
filter(...args) { | ||
|
||
this.uNMatrix.inverseTranspose(this.uMVMatrix); | ||
let fbo = this.getFilterLayer(); | ||
|
||
// use internal shader for filter constants BLUR, INVERT, etc | ||
|
@@ -1104,6 +1111,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer { | |
this._pInst.noStroke(); | ||
this._pInst.blendMode(constants.BLEND); | ||
this._pInst.shader(this.filterShader); | ||
this.filterShader.setUniform('uNewNormalMatrix', this.uNMatrix.mat3); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this only is used in the sphere mapping shader, can we do this and the |
||
this.filterShader.setUniform('tex0', target); | ||
this.filterShader.setUniform('texelSize', texelSize); | ||
this.filterShader.setUniform('canvasSize', [target.width, target.height]); | ||
|
@@ -1613,6 +1621,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer { | |
properties.quadraticAttenuation = this.quadraticAttenuation; | ||
|
||
properties._enableLighting = this._enableLighting; | ||
properties.sphereMapping = this.sphereMapping; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the shader doesn't need to be pushed/popped since we can just create it once and then reuse it with different images, so we can probably take this line out |
||
properties._useNormalMaterial = this._useNormalMaterial; | ||
properties._tex = this._tex; | ||
properties.drawMode = this.drawMode; | ||
|
@@ -1676,6 +1685,14 @@ p5.RendererGL = class RendererGL extends p5.Renderer { | |
return this._getImmediateStrokeShader(); | ||
} | ||
|
||
_getSphereMapping(img) { | ||
this.sphereMapping = this._pInst.createFilterShader( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like this is creating a new shader every frame. Maybe you can wrap lines 1689-1691 call in |
||
sphereMapping | ||
); | ||
this.sphereMapping.setUniform('uSampler', img); | ||
return this.sphereMapping; | ||
} | ||
|
||
/* | ||
* selects which fill shader should be used based on renderer state, | ||
* for use with begin/endShape and immediate vertex mode. | ||
|
@@ -2141,9 +2158,9 @@ p5.RendererGL = class RendererGL extends p5.Renderer { | |
} | ||
|
||
/* Binds a buffer to the drawing context | ||
* when passed more than two arguments it also updates or initializes | ||
* the data associated with the buffer | ||
*/ | ||
* when passed more than two arguments it also updates or initializes | ||
* the data associated with the buffer | ||
*/ | ||
_bindBuffer( | ||
buffer, | ||
target, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#version 300 es | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For maximum compatibility, do you think we can do this one in GL ES 100? So, taking out the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh.. you mean There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oops yes you're right, that should be |
||
#define PI 3.141592 | ||
|
||
precision highp float; | ||
|
||
uniform sampler2D uSampler; | ||
uniform mat3 uNewNormalMatrix; | ||
uniform mat3 uCameraRotation; | ||
uniform mat4 uNewModelViewMatrix; | ||
uniform mat4 uModelViewMatrix; | ||
|
||
in vec2 vTexCoord; | ||
in vec3 fvNormal; | ||
in vec3 faNormal; | ||
in vec3 faPosition; | ||
|
||
out vec4 fragColor; | ||
|
||
void main() { | ||
vec4 viewModelPosition = uModelViewMatrix * vec4(faPosition, 1.0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
vec3 vViewPosition = viewModelPosition.xyz; | ||
vec4 newTexColor = texture(uSampler, vTexCoord); | ||
vec3 vGlobalNormal = uNewNormalMatrix * faNormal ; | ||
vec3 n = reflect(vViewPosition.xyz , (vGlobalNormal.xyz)); | ||
n = normalize(n); | ||
vec2 suv; | ||
suv.y = 0.5 + 0.5 * n.y; | ||
suv.x = atan(n.z, n.x) / (2.0 * PI) + 0.5; | ||
newTexColor = texture(uSampler, suv.xy); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice! |
||
vec4 baseColor = newTexColor; | ||
fragColor = baseColor; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably take this line out if we move that last paragraph up to the top, it serves as a pretty good intro.