The shader on the background plane takes precedence over all other elements in three.js

I'm struggling to achieve a simple setup in my scene where a plane serves as the background with a shader, and a box is placed on top with a lambert material. Despite my efforts, I can't seem to make both the plane and the box appear together. Any suggestions on what I might be misunderstanding or overlooking?

For those who want to take a look, here is the jsfiddle link: http://jsfiddle.net/5zTz3/

Index.html

<html>
  <head>
    <title>The Cube</title>
    <style>
      canvas { width: 100%; height: 100%; }
      body{margin: 0px;}   
    </style>
  </head>
  <body>
    <script id="vertexShader" type="x-shader/x-vertex">
      void main() {
        gl_Position = vec4( position,1);
      }
    </script>
    <script id="fragmentShader" type="x-shader/x-fragment">
      uniform vec2 resolution;
      void main() {
        vec2 coord = gl_FragCoord.xy;
        float xmid = resolution.x/2.0;
        float ymid = resolution.y/2.0;
    float x = (coord.x - xmid)/resolution.x;
        float y = (coord.y-ymid)/resolution.y;
    float r = sqrt(x*x + y*y)+0.5;
        vec4 color = vec4(1.0-vec2(r),1.3-r,1.0);
        gl_FragColor = color;
      }
    </script>
    <script src="https://rawgithub.com/mrdoob/three.js/master/build/three.js"></script>
    <script src="scene.js">
    </script>
  </body>
</html>

scene.js

//Code for scene setup
var scene = new THREE.Scene();
function render() {
    requestAnimationFrame(render);
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
}

//Define camera
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

//Plane material
var uniforms = {
    resolution: { type: "v2", value: new THREE.Vector2(window.innerWidth,window.innerHeight) }
};

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

//Create plane
var geometry = new THREE.PlaneGeometry(1800*2, 1600,1,1);
var plane = new THREE.Mesh(geometry, planeMaterial);
plane.position.z = - 500;
scene.add(plane);

//Create cube
var geometry = new THREE.CubeGeometry(1,1,1);
var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, cubeMaterial );
scene.add( cube );

//Define Render
var renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize( window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

//Define light
var light = new THREE.PointLight(0xffffff);
light.position.set(0,200,100);
scene.add(light);

//render
render();

As a workaround, changing the plane geometry to another CubeGeometry ( new THREE.CubeGeometry(2,2,2); ) achieves the desired result. However, the underlying issue with the plane not working remains unclear.

Answer №1

To transform the vertex position in the vertex shader, it is important to multiply the modelViewMatrix and projectionMatrix.

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

Check out this fiddle for an example: http://jsfiddle.net/5zTz3/2/

Answer №2

If you're looking to dive into the world of Three.js, I highly suggest checking out the book "Learning three.js". It's a fantastic resource to get started with.

You can find the example code from the book right here: https://github.com/josdirksen/learning-threejs

Specifically, Chapter 1, Section 3 covers the topic you're interested in. Here's an excerpt of the code snippet:

<!DOCTYPE html>
<html>
<head>
    <title>Example 01.03 - Materials and light</title>
    <script type="text/javascript" src="../libs/three.js"></script>
    <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
    <style>
        body{
            /* set margin to 0 and overflow to hidden, to go fullscreen */
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<!-- Div where the Output is Displayed -->
<div id="WebGL-output">
</div>

<!-- The JavaScript code that executes our Three.js examples -->
<script type="text/javascript">

    // When everything is loaded, we start our Three.js operations.
    $(function () {

        // Create a scene to hold objects, cameras, and lights.
        var scene = new THREE.Scene();

        // Set up a camera to determine the perspective.
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        // Create a renderer and define the size.
        var renderer = new THREE.WebGLRenderer();

        renderer.setClearColorHex(0xEEEEEE, 1.0);
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;

        // Create a ground plane
        var planeGeometry = new THREE.PlaneGeometry(60,20);
        var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
        var plane = new THREE.Mesh(planeGeometry,planeMaterial);
        plane.receiveShadow = true;

        // Rotate and position the plane
        plane.rotation.x = -0.5*Math.PI;
        plane.position.x = 15;
        plane.position.y = 0;
        plane.position.z = 0;

        // Add the plane to the scene
        scene.add(plane);

        // Create a cube
        var cubeGeometry = new THREE.CubeGeometry(4,4,4);
        var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.castShadow = true;

        // Position the cube
        cube.position.x = -4;
        cube.position.y = 3;
        cube.position.z = 0;

        // Add the cube to the scene
        scene.add(cube);

        var sphereGeometry = new THREE.SphereGeometry(4,20,20);
        var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
        var sphere = new THREE.Mesh(sphereGeometry,sphereMaterial);

        // Position the sphere
        sphere.position.x = 20;
        sphere.position.y = 4;
        sphere.position.z = 2;
        sphere.castShadow = true;

        // Add the sphere to the scene
        scene.add(sphere);

        // Position and focus the camera on the center of the scene
        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);

        // Add spotlight for shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);

        // Append the renderer output to the html element
        $("#WebGL-output").append(renderer.domElement);

        // Render the scene
        renderer.render(scene, camera);
    });

</script>
</body>
</html>

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

"Dilemma: Why won't the AJAX form post load inside the

Apologies for the simple question, but I'm experiencing an issue where nothing happens when the button is pressed. Any assistance would be greatly appreciated. AJAX $(document).on("ready", function(){ //Form action $("#wbForm").on("submit", function( ...

Encountering an issue while attempting to extract an ACF field in WordPress using JavaScript

When I write the following code, everything works fine: <script> $(document).ready(function(){ var user_id = '<?php echo get_current_user_id(); ?>'; // This is working var subject = "<?php echo the_field('subject ...

Error message: An error occurred while executing the AJAX PHP code due to a TypeError, specifically stating that the property 'status' cannot be

For some reason, I keep receiving an undefined return for my response. The event handler in index.php triggers the following code: $.post("getData.php", onNewPost()); function onNewPost (response){ if (response.status == "OK") { console.log(resp ...

How to create a fresh factory instance in Angular Js

I have implemented a factory in my application to retrieve a list of folders and display it on the front end. Additionally, I have a form on the front end where users can add new folders to the existing list. After adding a folder, I need to refresh my fac ...

Unusual actions observed with that particular button

Currently, I am working on creating a pomodoro clock using Codepen. While I acknowledge that my code isn't flawless yet, I have encountered a peculiar behavior with the Start button. When I click on it once, the timer starts as expected. However, if I ...

Apple Automation: Extract a targeted string from text and transfer it to a different spot within the page

Apologies for my lack of expertise in this area, but I hope to convey my question clearly. I am working on a form where I need to input text in order to copy specific items and paste them elsewhere on the same webpage. For example, if the input text is " ...

Is it possible to use v-model on an input that is being dynamically updated by another script?

How can I retrieve the lat and lng values stored in two input fields when a user changes the marker's position on a Google map? When the user clicks to select a new place, I need to update these inputs accordingly. I attempted using v-model but it onl ...

Best practices for handling errors beyond network problems when using the fetch() function

I am facing a situation where the route of my fetch() call can result in two different responses, each requiring a different action. However, I have noticed that the catch() method only handles network errors as far as I know. Currently, my code looks lik ...

Utilizing regex in jQuery/JavaScript for replacing specific text areas

Can you provide a solution for isolating the currency from the text using jQuery in the following example? We need to remove all other data except the currency. We attempted using JavaScript's replace method as shown below: var symbol = $("div.pri ...

Guide on displaying the marker location on a map when hovering over a div element, similar to the method used by AirBnb

In the left side div of my page, there are items such as images, titles, details, and addresses. On the right side, I have a Leaflet Map that shows markers of these addresses taken from the left side items. What I want is to display the marker locations on ...

How can I use Node.js Express to upload files with Multer?

I am facing an issue while trying to upload a file image using multer in express. The file gets successfully uploaded to the directory, but the name of the file is not being saved in the database. I am utilizing mongodb with express and currently, the file ...

How to completely disable a DIV using Javascript/JQuery

Displayed below is a DIV containing various controls: <div id="buttonrow" class="buttonrow"> <div class="Add" title="Add"> <div class="AddButton"> <input id="images" name="images" title="Add Photos" ...

Display the Image Element in Angular only when the image actually exists

In my HTML code, I have two sibling elements - one is an image and the other is a div. I want to display the image element if the image exists, and show the div element if the image doesn't exist. Here's how my elements are structured: <img ...

Automatically close the multiselect dropdown when the user interacts outside of it (varied scenario)

For those interested, check out this jsfiddle link: http://jsfiddle.net/jaredwilli/vUSPu/ This specific code snippet focuses on creating a multi-select dropdown feature. When a user chooses options from the dropdown and then clicks outside of the menu are ...

Trouble with two dropdown selections in Angular and preset values

I am encountering an issue with a select input in angular 7. The scenario involves having 2 selects where selecting an option in the second select populates the corresponding values in the first select. The first select should display a default placeholder ...

Exploring the use of the "++" operator in Regular

Is there a way to detect the presence of ++, --, // or ** signs in a string? Any help would be greatly appreciated. var str = document.getElementById('screen').innerHTML; var res = str.substring(0, str.length); var patt1 = ++,--,//,**; var resul ...

overlay appears as I reveal the slide-out menu

Struggling with adding an overlay to an expanding navigation bar, similar to Youtube's overlay when the slide-out nav is open. Need help with the implementation. Here is the javascript code for the expanding navigation using jQuery: 'use strict ...

How can HTML and CSS be linked to display images independently?

Check out this code: body{ background-image:url('http://wallpoper.com/images/00/31/33/51/black-background_00313351.jpg'); } div.header{ background-color:#F0F8FF; text-align:center; padding:3px; ...

Leveraging *ngFor to extract HTML content from ion-label

I've encountered an issue while using *ngFor in my HTML like this: <ion-slides #slides [options]="slideOpts"> <ion-slide class="numbers-wrapper" *ngFor="let questionNumber of numbers" (click)="clickQue ...

Animating content to slide into view in the same direction using CSS transitions

My goal is to smoothly slide one of two 'pages', represented as <divs>, into view with a gentle transition that allows the user to see one page sliding out while the other slides in. Eventually, this transition will be triggered from the ba ...