Can I achieve a black outline effect on my 3D models using three.js?
I'm looking to create graphics similar to Borderlands 2, with toon shading and distinct black outlines.
Can I achieve a black outline effect on my 3D models using three.js?
I'm looking to create graphics similar to Borderlands 2, with toon shading and distinct black outlines.
It seems like I arrived late. Hopefully, this information will be helpful for someone in the future.
Here's a tip: you don't have to render everything twice. By duplicating the mesh and setting the duplicate mesh's material side to "backside", you can avoid the overhead of double rendering. This way, you'll only be rendering two meshes with most of the outline's geometry culled by WebGL's "backface culling".
Here's an example to illustrate this concept:
var scene = new THREE.Scene();
//Create main object
var mesh_geo = new THREE.BoxGeometry(1, 1, 1);
var mesh_mat = new THREE.MeshBasicMaterial({color : 0xff0000});
var mesh = new THREE.Mesh(mesh_geo, mesh_mat);
scene.add(mesh);
//Create outline object
var outline_geo = new THREE.BoxGeometry(1, 1, 1);
//Adjust the material's side property
var outline_mat = new THREE.MeshBasicMaterial({color : 0x00ff00, side: THREE.BackSide});
var outline = new THREE.Mesh(outline_geo, outline_mat);
//Scale the object to create an outline
outline.scale.multiplyScalar(1.5);
scene.add(outline);
If you want more information on backface culling, you can visit: http://en.wikipedia.org/wiki/Back-face_culling
This approach is effective for adding outlines to objects without resorting to toon shading and sacrificing realism.
Toon shading itself supports edge detection. The 'cel' shader in Borderlands was developed for this purpose.
In cel shading, developers can choose between object duplication (usually at a low pipeline level) or using image processing filters for edge detection. This decision involves a performance tradeoff between the two techniques.
For more information on cel shading, you can visit: http://en.wikipedia.org/wiki/Cel_shading
Yes, achieving toon shading in three.js is possible, but it's not a straightforward process. You can find shaders for toon shading in /examples/js/ShaderToon.js.
One common method for creating outlines in three.js is to render in two passes. The first pass renders the models in black at a slightly larger size, while the second pass uses the toon shaders at normal scale. This creates a larger black outline around the models. While not perfect, this method is commonly used for creating outlines in three.js. Another approach you can try is searching for "three.js hidden line rendering" as it uses a similar method to achieve a different look.
Although this question is from a while ago, I'll share what I did in response.
For my CG course, I developed an Outlined Cel-shader. Currently, it requires 3 rendering passes, but I am working on streamlining it to eliminate one pass.
Here's my approach: 1) Generate a NormalDepth image and save it to a texture.
In the vertex shader, convert the position to screen space and the normal to screen space.
In the fragment shader, calculate the depth of the pixel and generate the normal color using the depth as the alpha value.
float ndcDepth = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) / (gl_DepthRange.far - gl_DepthRange.near);
float clipDepth = ndcDepth / gl_FragCoord.w;
2) Render the scene onto a texture with cel-shading. I modified the scene override material for this step.
3) Create a quad and render both textures onto it. Use an orthographic camera to view the quad. The cel-shaded texture is directly rendered on the quad, while the normaldepth shaded texture undergoes edge detection to determine when a pixel should be black (indicating an edge).
What is the reason behind needing Node.js installed before installing TypeScript if we transpile typescript into JavaScript using tsc and run our code in the browser, not locally? ...
Here is a function that deletes people from a list when you click on a certain part of the form: function ParticipantsDeleteClick(model, url) { for (i in model.Participants) { $("#delete" + i).click(function () { $.ajax({ url: url, ...
I am currently working on developing a basic Text Editor using Electron. I am facing an issue with adding a custom title bar where the buttons are not clickable. To try and fix this issue, I have included an onclick tag to the buttons in my code. main.js ...
I am attempting to retrieve the metadata of my Kafka brokers' topics using the kafkajs admin client within my Node.js + express.js server. Here is the content of my index.js file, serving as the main entrypoint for npm: 'use strict'; cons ...
Describing my issue is proving to be challenging, so I have simplified the code. Let me share the code below: main.ts import express from 'express'; let a = 1 console.log ('a in main.ts', a) export let b = a const app = express() let ...
The challenge I am currently working on involves page1.html <a href="/foo"></a> foo.html <select ng-model="ctrl.listvalues"> <option id="{{item.value}}" ng-repeat="item" in ctrl.availableValues" value="{{item.value}}">item.di ...
I have a model called Item with the following structure: {data: String, schedule: DateTime, category: String} I want to create a report that displays the data in a table format like this: <table> <tr> <th>Time Range</th&g ...
Currently, I am in the process of learning how to utilize ReactJS, Spotify API, and Promises. My goal is to retrieve top albums from musicians on Spotify and play a 30-second snippet of their tracks. I have decided to work with a Spotify package known as ...
I am working with the react-to-print library and I have a requirement to print a list of components, with each component on its own separate page. However, when I click on the print button, I encounter an error stating that the argument does not appear to ...
Hello, I've incorporated a Material UI table into one of my projects with a design concept similar to this - https://i.stack.imgur.com/i6Fsj.png I'm aiming to include icons within the tables. Here's the code I've worked on so far - ...
In my current setup, I have implemented an iframe within the main window. The iframe includes a form where users can input data and submit it. Currently, I achieve the submission with the following code: var openURL = '/results/finalpage'; windo ...
Forgive me if I seem clueless. I am a beginner in the world of Javascript and am currently experimenting with loops. At the moment, I am toying around with this particular piece of code: <!DOCTYPE html> <html> <body> <button oncl ...
I'm currently working on creating a regex for a textarea in my Angular 8 application. The goal is to allow all characters but not permit an empty character at the start. I've experimented with 3 different regex patterns, each presenting its own s ...
Creating a custom Selenium getText() method that can retrieve either the node text or the node plus child text of an element is my current challenge. The default behavior of Selenium appears to utilize the Xpath .//string() method which includes the text o ...
Apologies for my poor grasp of English. I am working with HTML and JavaScript. <noindex> <h1>This is h1 in noindex</h1> <div> <h1>This is h1 in noindex and in div</h1> <div> <h1>This is h1 in noindex a ...
Hi there, I'm currently facing an issue. I am trying to generate a triangular number pattern like the one shown below: Output: 1223334444333221 =22333444433322= ===3334444333=== ======4444====== I attempted to write a program for this, however, ...
Is there a way to retrieve the center anchor point position (x, y) of the user's selection relative to the document or window? I have tried using window.getSelection() to get selected nodes, but I am unsure how to obtain their position: See an examp ...
I have the following HTML structure: <div class="container"> <div class="list-wrapper"> <ul> <li class="item-first"> </li> </ul> </div> <div class="description-wrapper"> <d ...
Hey there, how are you doing? I am currently working on a project using Next.js and styled components. I am trying to change a string using props in my layout component, where the main content is dynamic per page. Page 'prueba.js' import React f ...
I am currently facing an issue and seeking feedback on how to resolve it. Below is the JSON data: questions: [ { question: 'lala', answer: 'papa', categories: ['Handla'] }, { question: ...