Tips for rendering objects in webgl without blending when transparency is enabled

My goal is to display two objects using two separate gl.drawArrays calls. I want any transparent parts of the objects to not be visible. Additionally, I want one object to appear on top of the other so that the first drawn object is hidden where it overlaps the second one.

In order to achieve this, I have set up my render loop as follows:

 gl.clearColor(0, 0, 0, 1);
 gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
 gl.enable(gl.BLEND);
 gl.disable(gl.DEPTH_TEST);

I am not entirely sure about the blend functions but I utilize them to enable transparency. However, this causes the two objects to blend and create a yellow color (one object is red and the other is green). My intention is to have the final color be either red or green depending on the order they are drawn in, while still maintaining transparency.

To illustrate the issue, observe the following code snippet:

const fShaderSource2 = `#version 300 es

precision mediump float;

out vec4 outColor;

void main() {
  outColor = vec4(0.0, 1.0, 0.0, 1.0);
}

`;

...

minibatch.push(redText);
minibatch.push(greenText);

Although I draw the red object first and then the green object, the resulting color is yellow instead of the desired outcome. I aim to rectify this discrepancy.

Answer №1

The main issue lies in the improper use of the blend function (blendFunc). Blending essentially combines fragment color outputs with colors already present in the color buffers. The first parameter acts as a factor for the fragment color output, while the second parameter serves as a factor for the existing color in the color buffer. By default, colors are summed due to the standard blend equation being FUNC_ADD.

Thus, the blend function:

gl.blendFunc(gl.SRC_ALPHA, gl.ONE);

can be understood through the formula:

destColor = srcColor * srcAlpha + destColor * 1 

Here, destColor represents the current framebuffer color, and srcColor is the color designated for the fragment (outColor). This approach maintains the color in the framebuffer (multiplied by 1) and incorporates the new color multiplied by the alpha channel. If the current framebuffer color is red (1, 0, 0) and the new color is green (0, 1, 0), then the resulting color is yellow (assuming an alpha channel value of 1):

(0, 1, 0) * 1 + (1, 0, 0) * 1 == (1, 1, 0)    

To resolve this, utilize the following blend function:

gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

This will facilitate a "mixing" effect between the framebuffer color and the new color based on the alpha channel of the latter:

destColor = srcColor * srcAlpha + destColor * (1-srcAlpha)

The fundamental concept of Alpha blending is akin to that of OpenGL (given WebGL's close adherence to OpenGL ES standards), hence additional insights can be gleaned from the OpenGL wiki entry on Blending.

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

Strange Behavior of Json Dataset

I've noticed some unusual behavior when loading JSON data via AJAX with an interval. Initially, the data loads correctly, but after a few intervals, it starts to get scrambled and runs unpredictably between intervals. This issue even leads to crashes ...

What is the most effective method for implementing a fallback image in NextJS?

Lately, I've been immersed in a NextJS project that involves utilizing the YoutubeAPI to retrieve video details, such as thumbnail URLs. When it comes to fetching a full resolution image, the thumbnail URL typically follows this format: https://i.yti ...

html scroll to the flickering page

Why is it that when a user clicks on a link in the list, the browser flickers? This issue becomes especially noticeable if a user clicks on the same 'link' twice. Is there a solution to prevent this from occurring? The problem also seems to aris ...

"Exploring the world of arrays and looping in

Can someone assist me with this issue? I am currently stuck in JS Arrays & Loops and I can't understand why it's not returning "0" when the function is empty. function sumArray (numbers) { // your code var numbers = [1, 2, 3, 4]; if (nu ...

Responsive design issues with Bootstrap 3 box layout

I am currently working on creating a bootstrap4 layout that includes three boxes arranged side by side on a wide screen. However, my goal is to ensure that if the screen size decreases, the red and green boxes always stay adjacent to each other while the b ...

Creating an array of form input names using JavaScript within the HTML input tag

I have a two part question that I'm hoping someone can help me with. There was a similar question asked recently that included information about this particular type of array in PHP, but unfortunately, I can't seem to locate it at the moment. 1. ...

Tips for displaying videos with sound when the autoplay has been successfully implemented, but the audio is not working

I've been working on creating a video player with autoplay functionality, but I'm facing an issue with the sound not playing. Here's what I currently have in my code, but it's not behaving as expected: var myaudio = docum ...

Is there a way to obtain the current URL within the index.html file using Vue.js?

How can I retrieve the current URL in my index.html file using Vue.js? When using pure JavaScript in index.html, I am only able to obtain the URL of the initial page. In order to capture the URL of other pages, I need to refresh the page as the value of ...

Dealing with ASP.NET forms that involve a javascript plugin generating substitute input

I'm facing an issue with my ASP.NET MVC webpage where I submit a form using AJAX in the following way: function ValidateFormAndAjaxSubmit(formId, callingElement) { if (IsNotDblClick(callingElement.id)) { var _form = $("#" + formId); ...

Implementing AngularJS JQuery Datatables Directive for Displaying Multiple Data Tables within a Single View

I have successfully implemented the following directive: angular.module('myApp').directive('jqdatatable', function () { return { restrict: 'A', link: function (scope, element, attrs, ngModelCtrl) { ...

Buttons to maximize, minimize, and close individual sections on a webpage

I am fairly new to front end development and I must say, I am absolutely enjoying every bit of it. Here is a little challenge that came my way. It may seem simple to some but it got me thinking. I have three sections on the right side of my website. I wa ...

Transferring data from an Angular variable to an Express backend using a POST request

req.body seems to be coming up empty for me. I've tried adding content-type headers as json, but it's not making a difference. Can anyone point me in the right direction? Thank you. UPDATE: Just to clarify, my Angular frontend is successfully hi ...

Eliminate unnecessary scrollbar from fancybox iframe

I am trying to display content in an iframe using Fancybox, but I am encountering an issue. Despite all the content being contained within the iframe, horizontal and vertical scroll bars are appearing. When inspecting the element in Firefox, I noticed th ...

Verifying the username's availability through AJAX requests

My registration form utilizing AJAX isn't connecting to the database. It seems like I'm missing something important. Let's focus on validating this particular field: Username:<input type="text" name="user" id="user" maxlength="30"> & ...

Stop the HTML5 video playback within a slider (flickity)

As I add slides to a slider using flickity, I am encountering an issue where the first video pauses when there is a slide change event. However, if I play the video on the next slide and then move back or forward, the video does not pause. This is my curr ...

Webpack configuration for asynchronous loading

I'm having trouble making this work. Can someone please assist? :) (According to the documentation, webpack is capable of handling Promises) Here is what works for me: var compiler = webpack(webpackConfig) However, when I try using a promise, I en ...

Leveraging a single Axios request across various components

My current setup involves making a simple Axios call in this way: .get('https://myAPI.com/') .then(response => { this.info = response.data }) Subsequently, I utilize a v-for array loop on my components to display the retrieved data. ...

Encountering difficulties with the mobile display of a Wordpress theme

I am currently working with the megashop theme on WordPress and I have a few queries that need addressing: Is there a way to modify a specific setting exclusively for views smaller than desktop size, without impacting the desktop view? For example, the m ...

Troubleshooting the issue of "Mismatched transaction number*" in MongoDB and Node.js

While trying to add data, I encountered an issue with modifying two schemas using ACID transactions in MongoDB with Node.js. Upon running the program, an error was displayed: (node:171072) UnhandledPromiseRejectionWarning: MongoError: Given transaction n ...

ul/div element not displaying background color

I am attempting to showcase navigation items horizontally within a blue colored ribbon. Despite my efforts, the background-color property is not being applied to the ul element. I even tried enclosing it in a div element with a blue background, but still n ...