martinlaxenaire / curtainsjs

curtains.js is a lightweight vanilla WebGL javascript library that turns HTML DOM elements into interactive textured planes.
https://www.curtainsjs.com/
MIT License
1.67k stars 111 forks source link

Use more than two images #3

Closed type76 closed 6 years ago

type76 commented 6 years ago

Is there a way to use more than two images? I'd love to make a slideshow using different images and displacement maps if possible, but I don't know if it's possible to do this.

martinlaxenaire commented 6 years ago

Hi @dr-okra,

You could use as many images as you want. You may want to use one or two uniform to keep tracks of the visible slides (like activeSlide and nextSlide) and then mix the textures inside your fragment shader.

AlexisMathewHindle commented 6 years ago

Hi Martin, Love what you've done with curtains.js! Just trying to create, like dr-okra a slideshow using more than two images but struggling... Add other images to html with relevant data-sampler attribute. Then added texture samplers but unfortunately only keep getting two images. Code it below. Any help would be massively appreciated!

`

Click me !
`
martinlaxenaire commented 6 years ago

Hi @AlexisMathewHindle,

here's a link to a codepen that is working : https://codepen.io/martinlaxenaire/full/KeQpLO/ I've commented the code so you should be able to understand how it works.

Let me know if it's ok!

AlexisMathewHindle commented 6 years ago

Hi @martinlaxenaire

You are an absolute legend!Thank you very much! That was a huge help. Unfortunately I haven't got it working yet...

I forgot to mention that I'm using curtains.js in an app that I'm building Angular 6. When I come to to serve it locally I'm getting an error

error TS2304: Cannot find name 'Curtains'.

Even though this is error is occurring I am getting this

screen shot 2018-06-19 at 22 28 17

Which is promising but not quite there... At moment when I place the vertex and shaders in the index.html I get

screen shot 2018-06-19 at 22 30 03

Unable to find the vertex or fragment shader

I'm not sure why this is as they are very much there as I can see them. Instead when I place them in the app.component I get the black screen like in the image above.

Any thoughts would be massively appreciated.

Thanks you very much!

martinlaxenaire commented 6 years ago

Hi @AlexisMathewHindle,

the most important thing here is:

Errors occurred while compiling the shader:
ERROR: 0:3: 'medium' : syntax error

Which means your shader is not compiling. My guess here is that you made a typo and wrote "medium" instead of "mediump". Try with:

#ifdef GL_ES
    precision mediump float;
#endif

However I may add a patch to avoid throwing a js error when the shaders aren't compiling.

AlexisMathewHindle commented 6 years ago

Hi @martinlaxenaire,

Thank you so much for this! Great help! The typo was indeed causing an error but sadly it isn't the main issue. I'm still getting

error TS2304: Cannot find name 'Curtains'.

So therefore only getting the default vertex and fragment shaders which is why I'm getting a black background, right? Is there a way of passing the shaders in the params so that I don't need to have them within script tags in html?

Thank you so much for your help!

martinlaxenaire commented 6 years ago

Hey @AlexisMathewHindle,

looks like an Angular config problem to me, see https://github.com/angular/angular/issues/4902

I was thinking of adding a way to pass shaders via strings anyway so I just pushed an update. You can now pass strings to "vertexShader" and "fragmentShader" params (check the updated documentation).

AlexisMathewHindle commented 6 years ago

Hi @martinlaxenaire,

Amazing! That worked! Thank you very much! One last question - I promise! If I wanted to change the way the direction the displacement images 'fades' in do I have have to amend the effectFactor. I'm trying to get the image to 'fade in' from the right on click.

You've been a HUGE help! Thank you so much!

martinlaxenaire commented 6 years ago

Yep, you'd have to tweak the effectFactor a bit. Remember that the texture coordinates are ranging from 0 (left side) to 1 (right side) on the X axis.

You could try with:

vec2 effectFactor = vec2(textureCoords.x * 0.75, (textureCoords.y - 0.5) * 0.75);

Or even with a constant:

vec2 effectFactor = vec2(2.0, (textureCoords.y - 0.5) * 0.75);

Just play with it (or have a look at how are working other displacement shaders elsewhere)

AlexisMathewHindle commented 6 years ago

Good morning @martinlaxenaire,

Thank you very much for this. Was a massive help. Had a good play and managed to get the effect I was looking for.

Out of curiosity I'm looking to wrap several 'layered' images in a div in order to create a parallax motion effect on mousemove. Do you think this might be possible?

So far I've managed to get it working for one parallax container but can't seem to get it working when I add another one...

`

` Do I need to load each container and push to an array and load like you've done for video and images? Any advice would be massively appreciated. Hope you have an awesome day!
martinlaxenaire commented 6 years ago

Hi @AlexisMathewHindle,

I'm not sure I understand what you want to achieve (and we're going a little bit off topic here.). You could post a jsfiddle/codepen so I can look. Also, data-sampler attributes should be used on img tags.

With something like this you can have a basic parallax layer effect if that's what you're trying to do:

<div class="curtain">
    <img src="images/background.jpg" data-sampler="backgroundTexture" />
    <img src="images/front.png" data-sampler="frontTexture" />
</div>
#ifdef GL_ES
    precision mediump float;
#endif

uniform vec2 uMousePosition;

varying vec3 vVertexPosition;
varying vec2 vTextureCoord;

uniform sampler2D backgroundTexture;
uniform sampler2D frontTexture;

void main( void ) {

    // get our texture coords
    vec2 textureCoords = vec2(vTextureCoord.x, vTextureCoord.y);

    vec2 mouseToTextCoords = vec2((uMousePosition + 1.0) / 8.0);

    // background layer
    vec4 backgroundText = texture2D(backgroundTexture, textureCoords + (uMousePosition / 50.0));
    // front layer (with transparency)
    vec4 frontText = texture2D(frontTexture, textureCoords + (uMousePosition / 30.0));

    // mix both texture based on front texture transparency
    vec4 finalColor = mix(backgroundText, frontText, frontText.a);

    // handling premultiplied alpha (useful if we were using a png with transparency)
    finalColor = vec4(finalColor.rgb * finalColor.a, finalColor.a);

    gl_FragColor = finalColor;
}
type76 commented 6 years ago

I just want to thank you for your efforts Martin. Much respect

rogierhofboer commented 1 month ago

Unfortunatelty this stopped working with the latest version of curtains js. The addPlane() method is not available anymore, and when changing to new Plane() nothing is displayed. Could someone provide an updated example on how to do this. Preferable with both pictures and videos in the same slideshow? (Now .images is hard-coded) Many thanks in advance!