Can the 'Water Shader Animation' be altered to have a non-spherical shape?

http://codepen.io/Khangeldy/pen/gPJoxJ

JS

// setting up camera, scene, and renderer
var scene, camera, renderer;
scene = new THREE.Scene();
var fov = 75,
        aspect = window.innerWidth / window.innerHeight;
camera = new THREE.PerspectiveCamera(fov, aspect, 0.1, 1000);
camera.position.z = 100;
camera.lookAt(scene.position);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xc4c4c4);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var clock = new THREE.Clock();

// uniform parameters for shader
var tuniform = {
    iGlobalTime: {
        type: 'f',
        value: 0.1
    },
    iResolution: {
        type: 'v2',
        value: new THREE.Vector2()
    },
    iMouse: {
        type: 'v4',
        value: new THREE.Vector2()
    }
};

// capturing mouse position
renderer.domElement.addEventListener('mousedown', function(e) {
    var canvas = renderer.domElement;
    var rect = canvas.getBoundingClientRect();
    tuniform.iMouse.value.x = (e.clientX - rect.left) / window.innerWidth * 2 - 1;
    tuniform.iMouse.value.y = (e.clientY - rect.top) / window.innerHeight * -2 + 1; 
});
renderer.domElement.addEventListener('mouseup', function(e) {
    var canvas = renderer.domElement;
    var rect = canvas.getBoundingClientRect();
    tuniform.iMouse.value.z = (e.clientX - rect.left) / window.innerWidth * 2 - 1;
    tuniform.iMouse.value.w = (e.clientY - rect.top) / window.innerHeight * -2 + 1;
});

// handling window resize
window.addEventListener('resize',function() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

tuniform.iResolution.value.x = window.innerWidth;
tuniform.iResolution.value.y = window.innerHeight;

// creating a flat ocean horizon effect
var material = new THREE.ShaderMaterial({
    uniforms: tuniform,
    vertexShader: document.getElementById('vertex-shader').textContent,
    fragmentShader: document.getElementById('fragment-shader').textContent
});
var mesh = new THREE.Mesh(
    new THREE.PlaneBufferGeometry(window.innerWidth, window.innerHeight, 40), material
);
scene.add(mesh);

// rendering animation with still camera
function render(time) {
    tuniform.iGlobalTime.value += clock.getDelta();
    requestAnimationFrame(render);
    renderer.render(scene, camera);
}
render();

I'm trying to modify this animation to make the horizon appear flat like an ocean horizon and also keep the camera still. Is it achievable? Appreciate any help!

Answer №1

Absolutely, it can be done.

All that's required is some experimentation with the variables.

// Setting up the camera, scene, and renderer
var scene, camera, renderer;
scene = new THREE.Scene();
var fov = 75,
aspect = window.innerWidth / window.innerHeight;
camera = new THREE.PerspectiveCamera(fov, aspect, 0.1, 1000);
camera.position.z = 100;
camera.lookAt(scene.position);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xc4c4c4);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var clock = new THREE.Clock();

var tuniform = {
time: {
type: 'f',
value: 0.1
},
resolution: {
type: 'v2',
value: new THREE.Vector2()
},
mouse: {
type: 'v4',
value: new THREE.Vector2()
}
};

// Calculating mouse position within the canvas
renderer.domElement.addEventListener('mousedown', function(e) {
var canvas = renderer.domElement;
var rect = canvas.getBoundingClientRect();
tuniform.mouse.value.x = (e.clientX - rect.left) / window.innerWidth * 2 - 1;
tuniform.mouse.value.y = (e.clientY - rect.top) / window.innerHeight * -2 + 1; 
});
renderer.domElement.addEventListener('mouseup', function(e) {
var canvas = renderer.domElement;
var rect = canvas.getBoundingClientRect();
tuniform.mouse.value.z = (e.clientX - rect.left) / window.innerWidth * 2 - 1;
tuniform.mouse.value.w = (e.clientY - rect.top) / window.innerHeight * -2 + 1;
});
// Resizing the canvas
window.addEventListener('resize',function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});

tuniform.resolution.value.x = window.innerWidth;
tuniform.resolution.value.y = window.innerHeight;
// Creating a Plane
var material = new THREE.ShaderMaterial({
uniforms: tuniform,
vertexShader: document.getElementById('vertex-shader').textContent,
fragmentShader: document.getElementById('fragment-shader').textContent
});
var mesh = new THREE.Mesh(
new THREE.PlaneBufferGeometry(window.innerWidth, window.innerHeight, 40), material
);
scene.add(mesh);

// Animation rendering function
function render(time) {
tuniform.time.value += clock.getDelta();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
body {
overflow: hidden;
margin: 0;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r70/three.min.js"></script>

<!-- THIS is OPENGL Shading language scripts -->
<script id="vertex-shader" type="no-js">
void main(){
gl_Position = vec4( position, 1.0 );
}
</script>

<script id="fragment-shader" type="no-js">
#ifdef GL_ES
precision mediump float;
#endif

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
varying vec2 surfacePosition;

... (Fragment shader code continued)


External Demo

https://jsfiddle.net/nanilab/uz6yo2w3/

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

showcasing a map on an HTML webpage

Seeking advice on integrating a map feature in HTML to mark store locations. Working on an app for a business community and need help with this specific functionality. Your assistance would be greatly appreciated! ...

What is the process for selecting and clicking a specific div with a distinct class name in HTML

Hey there! I'm a beginner at coding with puppeteer and I have a question. How can I make my code click on this image: (image) The current code I have looks like this: const puppeteer = require('puppeteer'); (async () => { const bro ...

Tips for sending a parameter within a JavaScript confirm method?

I currently have the following code snippet in my file: <?php foreach($clients as $client): ?> <tr class="tableContent"> <td onclick="location.href='<?php echo site_url('clients/edit/'.$client->id ) ?>&ap ...

What is the best way to delete comments from the config.js file?

I'm looking for a way to remove comments from my config.js file, which is acting as a JSON file in my project. The config file has both single line comments like this: //comment goes here and multi-line comments like this: /* comments goes here */ ...

Send location data to the PHP server through AJAX and then fetch it in JavaScript once it has been handled

I am looking to transfer coordinates from client-side JavaScript to server-side PHP using Ajax, and then retrieve the processed result back to JavaScript for further use. While I have managed to pass the data to PHP successfully, I am struggling to figure ...

I can't seem to figure out what's causing this error to pop up in my coding setup (Tailwind + Next.js). It

I've been struggling with this problem for a week now and despite my efforts, I haven't been able to find a solution yet. However, I have made some progress in narrowing down the issue. The problem arises when I try to execute the yarn build comm ...

What is the best way to choose the page number using numeric paging in RadGrid?

I have implemented a JavaScript function that binds onchange to onbeforeunload or a confirm box only when there are changes on the grid. My goal is to target the footer paging anchors in order to prevent triggering the confirm or onbeforeunload events. Us ...

Setting up Firebase in Node.js with Express.js is a key step in developing

Setting up a Firebase instance (not firebase-admin) in Node.js. import { initializeApp } from 'firebase/app'; const firebaseConfig = { //... }; const app = initializeApp(firebaseConfig); This method may not be effective as Node.js uses Commo ...

Finding the identifier for resources through excluding external influences

I am currently facing an issue with the full calendar plugin. In my set up, I have 3 resources along with some external events. The problem arises when I try to drop an external event onto the calendar - I want to retrieve the resource id from which the ev ...

Confusion surrounding the purpose of an AngularJS controller function

After experimenting with some basic tutorials in AngularJS, I came across a discrepancy in how controllers are declared and used. For instance, in this JSFiddle link - http://jsfiddle.net/dakra/U3pVM/ - the controller is defined as a function name, which w ...

Compare and contrast JSON files that are constantly changing using JavaScript

I have reviewed the various inquiries on comparing JSON objects and feel confident in my ability to implement a comparison. However, my question pertains to dynamically loading source .json files into JSON objects for comparison. The scope of my project h ...

Change the appearance of the page when it is being displayed within an iframe using CSS

How can I display a webpage differently using CSS if it is within an iframe? I would like to use jQuery or JavaScript to switch to a different stylesheet specifically when the site is being displayed within an iframe. Any suggestions on how to achieve th ...

Is there a way to detect and handle errors triggered by a callback function?

My component has the following code snippet: this.loginService.login(this.user, () => { this.router.navigateByUrl('/'); }); Additionally, my service contains this method: login(credentials, callback) { co ...

Proper usage of a method within another method in a Vue component

Currently, I am extracting GPS data from an image using exifjs. My objective is to convert the latitude and longitude variables into a decimal variable as illustrated below: <template lang="html"> <div class="upload-wrap"> <button cla ...

What is the best way to eliminate the border color on a drop-down menu's bottom border?

I need help removing the border color from a dropdown with the style border-bottom: 1px solid rgba(0, 0, 0, 0.42); After debugging, I discovered that it is originating from the class MuiInput-underline-2593. However, the CSS class MuiInput-underline-2593 ...

The function `open` is not a valid prop for the `Dialog` component

Upon clicking an icon, a dialog box containing a form should appear for either adding a tab or deleting a specific tab. I have utilized reactjs, redux, and material-ui for the components. While I am able to display the dialog box when the icon is clicked, ...

Synchronous loop in Javascript

Is there a method to execute codes asynchronously within a for loop? In this scenario, events ranging from day x to y need to be inserted into the calendar using a for loop. However, the current loop is taking too long, as it has to cover all the days fro ...

Tips for ensuring proper function of bullets in glidejs

I am currently working on implementing glidejs as a slider for a website, but I am facing issues with the bullet navigation. The example on glidejs' website shows the bullets at the bottom of the slider (you can view it here: ). On my site, the bullet ...

Is there a way to display a bootstrap modal when the page is refreshed?

Is there a way to automatically display a Bootstrap modal box without the need for clicking anywhere? I want the modal to appear every time the page is refreshed, rather than requiring a click event. Can anyone provide guidance on achieving this? < ...

Can you tell me if there is a switch available for hover or mouse enter/mouse leave functions?

I have a series of div elements, each containing several nested div elements. I would like to add hover effects to these div elements. However, I am unsure whether to use the hover or mouseenter function. For instance, when hovering over a div, I want it t ...