Hello,
The following js-code shows a water flow. It was also made with the HTML function.
$timeout(function() {
//$scope.setShader();
}, 1500);
$scope.setShader = function() {
$scope.view.wdg['3DImage-2']['shader'] = "textMove; time f 0.3";
$scope.view.wdg['3DImage-2']['src'] = "app/resources/Uploaded/Kalt_Pfeil.png?edge=repeat";
$scope.val=0;
$rootScope.$on('modelLoaded', function() {
$scope.setShader();
$interval(function() {
if($scope.val >50) $scope.val =0
else $scope.val +=1
$scope.view.wdg['3DImage-2']['shader'] = "textMove; time f " +$scope.val/-50 + ";"
console.info( "textMove; time f " +$scope.val/100 + ";")
}, 250)
And this code to visible the flow by click on a button:
$scope.buttonClick12 = function()
{
if ($scope.view.wdg['3DImage-2']['visible'] == true)
$scope.view.wdg['3DImage-2']['visible'] = false;
else
$scope.view.wdg['3DImage-2']['visible'] = true;
Now i want to do this like i click on the button the flow is visible first after for example 5 sec.
Then the flow is for example 3 sec visible and then automatically unvisible.
Is there any way to do this so?
Your help will be highly appreciated.
Thanks in advance.
Solved! Go to Solution.
Hi @DenGrz ,
I tested it now more detailed. There are some mistakes in my code , sorry. now it is working in the following code:
$rootScope.$on('modelLoaded',function(){
$scope.setWidgetProp('3DImage-1','src', "app/resources/Uploaded/cvc.jpg?edge=repeat");
$scope.setWidgetProp('3DImage-1','shader', "textMove; time f " +$scope.val);
$scope.$applyAsync()
})
////////////
$scope.app.setShader= function(widgetName,delay,duration)
{
var calldelay =3000; //3 seconds
var callduration=10000;//10secs
var jumpInterval=10;
if(delay !=undefined) calldelay = delay;
if(duration !=undefined) callduration = duration;
$timeout( () => {
$interval(function() {
if($scope.val >50) $scope.val =0
else $scope.val +=1
$scope.setWidgetProp(widgetName,'shader', "textMove; time f " +$scope.val/100);
console.info( "textMove; time f " +$scope.val/100 + ";")
//this console print is a bad idea to have it on run time - only for testing
}, jumpInterval, callduration/jumpInterval)},calldelay);
$timeout( () => {$scope.setWidgetProp(widgetName,'shader',"Default")},calldelay+callduration);
};
Following points:
- the shader float parameter time is actually a moving in x direction ! for better reading of the code we have to pay attention when we use the name- but of course for the functionality is not so relevant. If you require a parameter based on time you can use the tick parameter which is passed to the shader. You need to use the uniform float definition in the frame shader.
-of course, such shader to work depends on the picture size / uv texture coordinates. Therefore the function setShader should be updated according the used picture after some tests.
I attached a demo project where I used an other similar shader mention in the post :How to associate my image texture UV on my 3D Model
The project contains only one button for testing:
I think the mention shader is simple moving a picture (showing water) in particular direction and has not really a water flow shader / only apparitional a picture which has a water texture and it will be moved form A to B with specific speed - parameter f= 0.3
I think with an appropriate water picture we can the shader mention in the article:
For a real water flow you can check this one:
https://threejs.org/examples/webgl_shaders_ocean.html
OK , to be able to understand what you shader is doing I need the definition of the tmlText widget. But… so far, I see the description it is not your question…. The shader seems to work and you want to call it on click for button
So for this simple define a function :
$scope.app.myButtonFunction= function()
{
//here you code
};
And then in the click event of the button write the JavaScript app.myButtonFunction();
To the question how to start it with 3 seconds delay , then playing for 10 seconds and stopping it . Your need the following function definition:
$scope.app.myButtonFunction= function()
{
var calldelay =3000; //3 seconds
var callduration=10000;//5secs
$timeout( () => {
$interval(function() {
if($scope.val >50) $scope.val =0
else $scope.val +=1
$scope.setWidgetProp('3DImage-2','shader', = "textMove; time f " +$scope.val/-50);
console.info( "textMove; time f " +$scope.val/100 + ";")
}, 250, callduration/250)},calldelay);
// reset the shader after 10 secs
$timeout( () => {$scope.setWidgetProp('3DImage-2','shader',"")},callduration);
};
I did not tested the code above but if it does not work then, please, let me know .
Hi @RolandRaytchev ,
i tested it but unfortunately it not working.
The defenition of the tmlText widget i use is:
<script name="textMove" type="x-shader/x-vertex">
attribute vec4 vertexPosition;
attribute vec2 vertexTexCoord;
varying vec2 texcoord;
uniform mat4 modelViewProjectionMatrix;
void main() {
gl_Position=vec4(modelViewProjectionMatrix * vertexPosition);
texcoord = vertexTexCoord ;
}
</script>
<script name="textMove" type="x-shader/x-fragment">
precision mediump float;
const float PI=3.1415926;
varying vec2 texcoord;
// user-provided parameters ---------------------------------
// usage : you can specify shader=image-pinger and it will use the defaults of rings=1,direction=1,rgb=0,1,0,rate=1 (green pulse running outwards)
// you can also specify specific parameters e.g. shader=image-pinger;rate f 10;r f 1;direction f -1 (=red rings, running inwards)
uniform float time;
// system provided values ------------------------------------
uniform sampler2D texSampler2D;
uniform vec4 surfaceColor;
void main() {
// generate a rolling sin wave - velocity (speed, direction) are specified by user
gl_FragColor = texture2D(texSampler2D,vec2(texcoord.x-time ,texcoord.y));
}
</script>
The Js-Code looks like so now:
$scope.app.myButtonFunction = function()
{
$timeout(function() {
//$scope.setShader();
}, 1500);
$scope.setShader = function() {
$scope.view.wdg['3DImage-1']['shader'] = "textMove; time f 0.3";
$scope.view.wdg['3DImage-1']['src'] = "app/resources/Uploaded/Kalt_Pfeil.png?edge=repeat";
}
$scope.val=0;
$rootScope.$on('modelLoaded', function() {
$scope.setShader();
$interval(function() {
if($scope.val >50) $scope.val =0
else $scope.val +=1
$scope.view.wdg['3DImage-1']['shader'] = "textMove; time f " +$scope.val/-50 + ";"
console.info( "textMove; time f " +$scope.val/100 + ";")
}, 250)
})
$scope.buttonClick1 = function()
{
if ($scope.view.wdg['3DImage-1']['visible'] == true)
$scope.view.wdg['3DImage-1']['visible'] = false;
else
$scope.view.wdg['3DImage-1']['visible'] = true;
}
};
$scope.app.myButtonFunction = function()
{
var calldelay =3000; //3 seconds
var callduration=10000;//5secs
$timeout( () => {
$interval(function() {
if($scope.val >50) $scope.val =0
else $scope.val +=1
$scope.setWidgetProp['3DImage-1']['shader'] = "textMove; time f 0,3" +$scope.val/-50;
console.info( "textMove; time f " +$scope.val/100 + ";")
}, 250, callduration/250)},calldelay);
// reset the shader after 10 secs
$timeout( () => {$scope.setWidgetProp('3DImage-1','shader',"")},callduration);
};
Where can my mistake be?
Thanks in advance.
Hi @DenGrz ,
I tested it now more detailed. There are some mistakes in my code , sorry. now it is working in the following code:
$rootScope.$on('modelLoaded',function(){
$scope.setWidgetProp('3DImage-1','src', "app/resources/Uploaded/cvc.jpg?edge=repeat");
$scope.setWidgetProp('3DImage-1','shader', "textMove; time f " +$scope.val);
$scope.$applyAsync()
})
////////////
$scope.app.setShader= function(widgetName,delay,duration)
{
var calldelay =3000; //3 seconds
var callduration=10000;//10secs
var jumpInterval=10;
if(delay !=undefined) calldelay = delay;
if(duration !=undefined) callduration = duration;
$timeout( () => {
$interval(function() {
if($scope.val >50) $scope.val =0
else $scope.val +=1
$scope.setWidgetProp(widgetName,'shader', "textMove; time f " +$scope.val/100);
console.info( "textMove; time f " +$scope.val/100 + ";")
//this console print is a bad idea to have it on run time - only for testing
}, jumpInterval, callduration/jumpInterval)},calldelay);
$timeout( () => {$scope.setWidgetProp(widgetName,'shader',"Default")},calldelay+callduration);
};
Following points:
- the shader float parameter time is actually a moving in x direction ! for better reading of the code we have to pay attention when we use the name- but of course for the functionality is not so relevant. If you require a parameter based on time you can use the tick parameter which is passed to the shader. You need to use the uniform float definition in the frame shader.
-of course, such shader to work depends on the picture size / uv texture coordinates. Therefore the function setShader should be updated according the used picture after some tests.
I attached a demo project where I used an other similar shader mention in the post :How to associate my image texture UV on my 3D Model
The project contains only one button for testing: