Implementing a unique shader on a sprite using THREE.js

My goal is to apply procedural structures to faces, starting with the task of creating a billboard featuring a nuclear blast in open space. I attempted to create an animated radial gradient for this, and achieved some success.

The key element for each fragment shader is having access to UV as a uniform variable.

It appears that the crucial aspect of rendering sprites is accessing the camera projection matrix in the vertex shader.

Check out this example !

Now I want to display this on the billboard sprite. I tried using THREE.Sprite with THREE.ShaderMaterial, but encountered difficulties. It seems that THREE.SpriteMaterial is the preferred material for sprites, and further investigation revealed why Sprites are drawn in a specific way using plugins.

Before attempting to reinvent the wheel, I wanted to seek advice on how to apply my custom shader to my custom sprite without modifying THREE.js?

Answer №1

After conducting some research and putting in the work, I have come to the conclusion that utilizing the THREE.ShaderMaterial is the optimal choice for completing this particular task. Thanks to the availability of

/extras/renderers/plugins/SpritePlugin
, I was able to grasp the concept of shaping and positioning sprites using vertex shaders. Although I still have a few lingering questions, I am content with the solution I have found.

To start off, I created a basic plane geometry:

 var geometry = new THREE.PlaneGeometry( 1, 1 );

Which I then utilized in a mesh with a ShaderMaterial:

            uniforms = {
                cur_time: {type:"f", value:1.0},
                beg_time:{type:"f", value:1.0},
                scale:{type: "v3", value:new THREE.Vector3()}
            };

            var material = new THREE.ShaderMaterial( {

                uniforms: uniforms,
                vertexShader: document.getElementById( 'vertexShader' ).textContent,
                fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
                transparent: true,
                blending:THREE.AdditiveBlending // Additive blending gives a realistic blast effect!!!

            } );


 var mesh = new THREE.Mesh( geometry, material );

Below are my shader implementations: Vertex shader:

        varying vec2 vUv;
        uniform vec3 scale;

        void main() {
            vUv = uv;
            float rotation = 0.0;

            vec3 alignedPosition = vec3(position.x * scale.x, position.y * scale.y, position.z*scale.z);

            vec2 pos = alignedPosition.xy;

            vec2 rotatedPosition;
            rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;
            rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;

            vec4 finalPosition;

            finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );
            finalPosition.xy += rotatedPosition;
            finalPosition = projectionMatrix * finalPosition;

            gl_Position =  finalPosition;

        }

The vertex shader was adapted from the original Sprite Plugin source code with minor modifications. Interestingly, changing += to = resulted in the sprite sticking to the screen, causing a considerable amount of time to be spent figuring this out.

Followed by the fragment shader:

        uniform float cur_time;
        uniform float beg_time;

        varying vec2 vUv;

        void main() {
            float full_time = 5000.;

            float time_left = cur_time - beg_time;
            float expl_step0 = 0.;
            float expl_step1 = 0.3;
            float expl_max   = 1.;

            float as0 = 0.;
            float as1 = 1.;
            float as2 = 0.;

            float time_perc = clamp( (time_left / full_time), 0., 1. ) ;
            float alphap; 
            alphap = mix(as0,as1, smoothstep(expl_step0, expl_step1, time_perc));
            alphap = mix(alphap,as2, smoothstep(expl_step1, expl_max, time_perc));

            // Rest of the shader code...
            
   }

This example showcases a multipoint gradient that is animated based on time. There is certainly room for optimization and enhancements to make it even more visually appealing. However, the current implementation is close to what I had envisioned.

With further fine-tuning and creativity, this project has the potential to be truly captivating.

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

Importing dynamic NodeJS modules from one module

ModuleA src index.js modules utility.js ModuleB src framework activities activity.js ModuleA serves as the main "runnable" module in this setup, while ModuleB acts as a framework li ...

Retrieving JQuery Results Based on List Items

Once I have obtained the list id from the navigation, my next step is to send the id to a PHP file that will return a JSON list. Below is the jQuery syntax I am using: $("#ul_navigation li").click(function(e) { idsec = this.id; alert(idse ...

Challenges with differentiating between addition and concatenation in Vue computed properties

Recently diving into Vue and came across an intriguing issue, I am curious to know the reason behind it and how to prevent it. <template> <div> <input type="number" v-model="a" style="color: white" /> <input type="number" v- ...

Ensuring grid columns are equal for varying text sizes

I am looking to achieve equal width and spacing for columns without using the width, min-width, max-width properties. Can anyone help me accomplish this using flex or any other method? https://i.sstatic.net/xo56M.png .d-flex { display: flex; } .d-fl ...

My current array is arr=[1,2,3,4]. I recently added an element to it using arr.push(5). Now I want to rearrange the array to be [5,4,3,2,1]. Any suggestions on how to achieve this

I currently have an array in the following format: var arr = [1,2,3,4] // Add another element to the array arr.push(5) // Now, arr = [1,2,3,4,5] I want to print my array as The elements in the array arr are: 5,1,2,3,4 When I use Arr.reverse(), it retu ...

A guide to displaying a DIV element upon clicking a button in ReactJs

While developing a form, I encountered the need to render the same div in the "Active Membership" section whenever the "Add More" button is pressed. Since users can have multiple active memberships, each time the button is clicked, the input section shou ...

Platform designed to simplify integration of high-definition imagery and scalable vector illustrations on websites

In the ever-evolving world of technology, some clients support advanced features like svg while others do not. With the rise of high resolution devices such as iPhone 4+ and iPad 3rd gen., it has become crucial to deliver graphics that can meet these stand ...

I encountered an issue where the data I passed to a component ended up being undefined

So here's the scenario: I'm working on a Next.js project where I have a context for modals. In this context, I store modal details in an array called modalBase. Additionally, I fetch data from another context (toolsContext) to pass it to componen ...

Storing data locally and replacing the current URL with window.location.href

My course mate and I are working on writing a code that saves an order to local storage and redirects to an order page when the order button is clicked. However, we are facing issues where clicking on the order button doesn't register in the applicat ...

Utilizing a third-party API within the next/api endpoint

I've recently started working with NEXTJS and developed a weather application. I'm integrating the openweather API, but I'm unsure how to use it within the next/api. I attempted creating a file named today.js inside the next/api directory an ...

How can I use `app.js` in Zendesk to connect to an external API using the complete URL

As someone new to developing Zendesk apps, I've been following the step-by-step guide available here. To Summarize I'm facing an issue with passing external API URLs to the AJAX call syntax within Zendesk's app.js file. You can find my sim ...

Organizing requests in PHP: What are the best methods?

My attempt to use the code below for queuing requests has not produced the desired results! <?php $Sleep_Time = "10"; if (isset($_POST["String"])){ $File = "Edit_File_Content.txt"; while(file_exists($File . "_L ...

Identifying the Operating System of Your Device: iOS, Android or Desktop

I am in need of displaying different app download links based on the user's operating system. This includes IOS, Android, or both if the user is accessing the page on a Desktop device. I am currently utilizing React and Next.js for this project. Unfor ...

The Ionic search bar will only initiate a search once the keyboard is no longer in view

In my Ionic application, I have implemented a search bar to filter and search through a list. The filtering process is triggered as soon as I start typing in the search bar. However, the updated results are not displayed on the screen until I manually hide ...

What happens if you try to add a member to a Mailchimp list who is already on the list

After following Angela Yu's course for the past few weeks, I attempted to implement the Mailchimp API as she demonstrates. However, I encountered difficulties due to recent changes in Mailchimp. Despite this setback, I was able to find the API referen ...

Seeking particular section of online content in an asynchronous manner

Is there a method for asynchronously requesting a specific portion of a web resource (like the initial 100 bytes) using JavaScript? I believed this could be accomplished through XmlHttpRequest by adjusting its Range header. However, if the server utilizes ...

Encountered a POST Error while attempting to access a backend function from the frontend in a React application, resulting in

I have developed a website using React for the frontend and Node.js Express for the backend. However, I am facing an issue where calling a backend function from the frontend takes around 2 minutes and results in the following error being displayed in the c ...

Issue with CSS transition not displaying ng-show elements properly

I'm currently working on incorporating a fade-in effect for text using the second solution from this source when using ng-show. Here is my HTML setup: <input ng-focus="hasFocus = true" ng-blur="hasFocus = false" type="text" placeholder="Cli ...

Is there a way to shade the entire webpage background in HTML?

Instead of affecting other DOM classes, I tried using another div but it doesn't darken the whole page. This means I have to manually modify each DOM class. Is there a way to overlay the entire document with a semi-transparent gray plane? ...

Unleashing the potential of extracting the value of a subsequent iteration while within the

Currently, I am facing a dilemma as I am unable to comprehend the logic required to design this algorithm. The problem at hand involves a sequence of images with arrows placed alternatively between each image. The structure appears as follows: Image -> ...