Create a shader in ThreeJS without the need to include a Geometry in the scene

Currently, I am experimenting with drawing shapes or geometric figures in ThreeJS r128 using only shaders.

The traditional approach in this library involves creating a mesh with a geometry associated with it, and then applying a shader using the ShaderMaterial class. However, I am struggling to figure out how to render the shader directly on the scene without attaching it to an object. In OpenGL Shading Language (GLSL), it is possible to draw shapes on the screen without defining vertices, which is my goal. But it seems I am stuck in the rendering process.

Is it feasible to render solely with shaders in ThreeJS?


As a test, here is a shader function to create a filled circle:

Fragment Shader:

uniform vec2 u_resolution;
float circleShape(vec2 position, float radius){
    return step(radius, length(position));
}
void main(){
    vec2 position = gl_FragCoord.xy / u_resolution;
    float circle = circleShape(position, 0.3);
    vec3 color = vec3(circle);
    gl_FragColor = vec4(color, 1.0);
} 

Here is the Vertex Shader as well:

void main(){
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

Answer №1

Simply create a THREE.PlaneGeometry that covers the entire canvas:

let container, camera, scene, renderer, uniforms;

initialize();
startAnimation();

function initialize() {
    container = document.getElementById('container');
    camera = new THREE.Camera();
    camera.position.z = 1;
    scene = new THREE.Scene();
    let geometry = new THREE.PlaneGeometry(2, 2);

    uniforms = {
        //u_time: { type: "f", value: 1.0 },
        u_resolution: { type: "v2", value: new THREE.Vector2() },
        //u_mouse: { type: "v2", value: new THREE.Vector2() }
    };

    let material = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: document.getElementById('vertexShader').textContent,
        fragmentShader: document.getElementById('fragmentShader').textContent
    });

    let mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    renderer = new THREE.WebGLRenderer();
    renderer.setPixelRatio(window.devicePixelRatio);
    container.appendChild(renderer.domElement);
    adjustWindowSize();
    window.addEventListener('resize', adjustWindowSize, false);
    document.onmousemove = function(e) {
        //uniforms.u_mouse.value.x = e.pageX
        //uniforms.u_mouse.value.y = e.pageY
    }
}

function adjustWindowSize(event) {
    renderer.setSize(window.innerWidth, window.innerHeight);
    uniforms.u_resolution.value.x = renderer.domElement.width;
    uniforms.u_resolution.value.y = renderer.domElement.height;
}

function startAnimation(delta_ms) {
    requestAnimationFrame(startAnimation);
    renderScene(delta_ms);
}

function renderScene(delta_ms) {
    //uniforms.u_time.value = delta_ms;
    renderer.render(scene, camera);
}
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d1b5a9b3a4a4f3b1bfacb5bdb6d7e1bdb1b3">[email protected]</a>/build/three.js"></script>
<div id="container"></div>

<script id="vertexShader" type="x-shader/x-vertex">
void main() {
    gl_Position = vec4( position, 1.0 );
}
</script>

<script id="fragmentShader" type="x-shader/x-fragment">
precision mediump float;

uniform vec2 u_resolution;

float circleShape(vec2 position, float radius){
    return step(radius, length(position));
}

void main(){
    vec2 position = gl_FragCoord.xy / u_resolution;
    float circle = circleShape(position, 0.3);
    vec3 color = vec3(circle);
    gl_FragColor = vec4(color, 1.0);
} 
</script>

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

Determine the data type of a property within a JavaScript object

I am currently working with a javascript object that looks like this: venue = { id: 0, name: '', venueimage_set: [ { imageurl: '', }, ]... At a later point in my code, I need to modify the object ...

I encountered an issue with passing arguments in the invoke function I redesigned

I am currently attempting to replicate the functionality of the .invoke() function. Although I can successfully call the function, I am facing difficulties when it comes to passing arguments. I have made attempts using call and apply, but unfortunately, I ...

Even though my form allows submission of invalid data, my validation process remains effective and accurate

Here is the code I have written: <!doctype html> <html lang="en"> <head> <title>Testing form input</title> <style type="text/css></style> <script type="text/javascript" src="validation.js"></script> &l ...

Ways to show text in a password field

I'm looking to have the password field on a page. I'd like to show the text "Enter password" on the screen before the user starts entering their password, but once they focus on the field to enter their password, it should switch back to password ...

At what point in the lifecycle of my component am I able to begin using this.$refs?

Exploring ways to integrate HTML5 audio events while initializing a Vue.js component that consists of a single file: <template> <audio ref="player" v-bind:src="activeStationUrl" v-if="activeStationUrl" controls autoplay></audio> < ...

Error encountered upon initializing Node-RED due to the presence of an unexpected token while incorporating the NPM module "file-exists" into the

Currently, I'm in the process of developing an application using Node-RED and I'm looking to incorporate some NPM modules into my project. One particular module from James Thom caught my attention, called node-red-contrib-npm, which automates the ...

Set the mesh position in Three.js to the coordinates 0,0,0

I'm currently working on positioning a basic cube at coordinates 0,0,0. When I try to position the cube at 0,0,0, I end up with this outcome: https://i.sstatic.net/S2zom.png However, this is not the desired result. Here is what I am aiming for: http ...

Controller method remains inaccessible despite multiple attempts with Javascript ajax Get call

I've tried numerous solutions for this issue, but I'm still unable to make it work. My goal is to invoke a controller method that accepts a parameter and returns a string based on that parameter. Despite using an ajax GET request, the outcome is ...

Steps to upgrading the React version within a package

Upon executing npm ls react, the following output is displayed: PS > npm ls react ├─┬ @headlessui/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cfbdaaaeacbb8ffee1f8e1fefa">[email protected]</a> │ └ ...

Dealing with React Native text overflowing beyond the screen width when using FlexWrap

I'm currently working on implementing a component in react native that consists of a row containing and components, but I'm struggling to achieve the desired outcome. Here's my current code: <View style={{ flexDirection: ...

Using SailsJS to populate attributes transmitted through socket.io's publishUpdate event

Utilizing the built-in socket capabilities of SailsJS has proved to be quite effective for me so far. However, I've encountered a challenge that I haven't been able to find any information on. In my model, I have set it up to populate certain at ...

What steps can I take to incorporate a user-controlled autoscroll feature into this Carousel?

I am in the process of creating a "slideshow" using text boxes that can be scrolled with arrow buttons. My goal is to have the slideshow automatically scroll only until the user interacts by clicking one of the arrow buttons. Below is the state logic re ...

Utilizing JavaScript For Loops for Code Repetition

Apologies for the ambiguous question title - struggling to articulate this properly. Essentially, I have some JavaScript code that I am looking to streamline by using a for loop. $('.q1').keyup(function () { if ($.inArray($(this).val().toLo ...

Upon running the command "React + $ npm start," an error occurred with the code 'ERR_OSSL_EVP_UNSUPPORTED' related to opensslErrorStack

When running $npm start, an error is being thrown: opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ], library: 'digital envelope routines', reason: 'unsupported', code: 'ERR_OSSL_EVP_ ...

Include more properties to component using a foreach iteration

In my React component, I am receiving a list of photos and have an object structured like this: getItems() { const { gallery } = this.props; const { content_elements: contentElements } = gallery; const items = []; if (contentElements) { ...

React JS - Breaking down the distinction between PublicTheme and PublicTheme

In my React project, I am currently working on creating the admin dashboard and designing the UI area for user interaction. I have encountered an issue where I am unable to separate the admin theme from the PublicTheme. Even when navigating to "/admin/lo ...

Error encountered while executing ExpressJs function that was converted to a promise

Understanding how errors are handled in promises can be a bit tricky, especially for someone new to promises like myself. I'm trying to make the most of them, but I'm not quite there yet. Here is the code snippet I'm working with: app.list ...

Ensure that it is safe to bypass Vue's built-in sanitization on this specific Vue component for the href attribute

I encountered an issue with a .vue file that contains an anchor tag as shown below: <a class="login_class" :href="loginUrl">Use Universal Login</a> When running Sonar, it raises a warning regarding the :href attribute: En ...

Guide to activating animation on one element when hovering over another element?

I am setting up an HTML 5 range element and looking to enhance the user experience. Specifically, I want to implement a feature where when the user hovers over the range, the height and width of the thumb should increase to 12 pixels. CSS .myrange::-webk ...

ng-class remains stagnant as ng-if dynamically updates when tab is no longer in focus

Implementing an interceptor to display a loader while making API calls can come with its challenges. In this case, two API requests are set at intervals of every 60 seconds using $interval. When the page is in focus, the loader functions correctly by showi ...