What is the angle between the viewing direction and the surface normal?

Dealing with a typical GLSL issue here. Although I grasp the math involved, implementing it at the webGL level is proving to be a challenge. Debugging shaders can be quite tricky.

My current goal is to determine the angle between the view vector and the normal of an object within the GLSL shader. I'm utilizing threejs but creating custom shaders independently.

Below is the crucial segment of the vertex shader:

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

    vec3 nmalInWorld = normalize(normalMatrix * normal);
    vec3 camInWorld = cameraPosition;
    vec4 posInWorld = modelViewMatrix * vec4(position, 1.0);
    posInWorld /= posInWorld[3];
    angle = -dot(normalize(posInWorld - vec4(cameraPosition, 1.0)), normalize(vec4(nmalInWorld,1.0)));
    if(angle > 0.7){
      angle = 1.0;
    }else{
      angle = 0.0;
    }

I've experimented with different versions of this setup, so I apologize for any unnecessary complexity. The output somewhat aligns with my expectations - consistently responding to changes in the camera's perspective. However, it appears off-centered for reasons unknown. The fragment shader simply assigns the angle value to a color field.

https://i.sstatic.net/jGjM0.png

Observing the image, it's evident that the white point isn't accurately centered on the sphere, as intended. I'm puzzled by this discrepancy. Could it possibly require a perspective transformation? I attempted this without success. Moreover, I don't believe the view vector should impact the situation; the sphere's coloration should remain constant regardless of the camera orientation.

Answer №1

positionInWorld, vec4(cameraPosition, 1.0) and vec4(normalInWorld,1.0) are referred to as Homogeneous coordinates.

The Dot product of two Cartesian Unit vectors equals the Cosine of the angle between those vectors.

The "view" vector is a normalized cartesian vector from the vertex's position to the camera's position. After applying the transformation by modelViewMatrix, the result will be a position in view space. The camera's position in view space is at (0, 0, 0) because the origin corresponds to the camera's position.

vec4 posInView = modelViewMatrix * vec4(position, 1.0);
posInView /= posInView[3];

vec3 VInView = normalize(-posInView.xyz); // (0, 0, 0) - posInView

The normalMatrix converts a vector from model space to view space:

vecr NInView = normalize(normalMatrix * normal);

VInView and NInView represent vectors in viewspace. The former points from the vertex towards the camera while the latter indicates the surface's normal vector at the vertex's location.
The dot product of these two vectors calculates the cosine of the angle between them:

float NdotV = dot(NInView, VInView);

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

"Utilizing Material-UI in React to create a textfield input with number validation

I am currently working on an input field that should only accept values within a specified range of min and max. However, I have encountered an issue where manually entering a number bypasses this control mechanism. Is there a way to prevent this from happ ...

Exploring ways to display a controller variable on an AngularJs HTML page

I have created a controller and an HTML page. 'use strict'; angular.module('myApp.view3', ['ngRoute']) .config(['$routeProvider', function($routeProvider) { $routeProvider.when('/view3', { ...

A guide on integrating $http.Get data into a function within an angularjs application

My dilemma arises from fetching data from the server using the $http.Get method. Once I have received this data, I need to utilize it in another function. Any assistance on how to achieve this would be greatly appreciated. var app = angular.module("app", ...

How can I effectively enable the close button on the NbAlertComponent to dismiss an alert?

I have been utilizing the nebular framework in my project and I am struggling to figure out how to make the close button of the NbAlertComponent actually close the alert. When I say close, I mean stop displaying the alert after clicking on the close button ...

Having trouble with my navbar toggler arrow malfunctioning

I have developed a toggler button with an arrow icon that transforms into bars when clicked. However, I am experiencing some issues with the code: 1.) After clicking the toggler for the first time, the arrow icons change to bars successfully. But when I c ...

When should vuex be used for storing data instead of relying on local component data?

Currently I am tackling a complex project that is built using Vue. Our team has opted to use Vuex as our state management system, however there are certain components where the data is not needed elsewhere. Should I follow convention and store this data ...

"Enhance user experience with jQuery's text expansion and collapse

Figuring out how to collapse and expand text with a button click has been challenging for me. I managed to make the text collapse when the button is clicked, but now I also need it to expand back again. The goal is to have the text initially hidden, then e ...

What is the significance of using $timeout in order to activate a watch function?

There is an interesting phenomenon happening with my directive. It watches the height of an element that is being updated by a controller using a factory method to retrieve data. Strangely, unless I include a $timeout in that factory function, my watch doe ...

Is it possible to use jQuery to create a slide-up effect from the

Could I reverse the animation direction of my dropdown menu? Currently, it expands from the top to bottom. Is there a way to make it expand from the bottom to the top? Code snippet: animate({height:'show',opacity:'show'}, ddsmoothmenu ...

Redux export does not complete correctly unless brackets are used

I'm trying to understand why the main JS file is having trouble importing todo from './actions' without brackets, while there are no issues with importing todos from './reducers'. Main js-file: import { createStore } from 'r ...

Retrieve the top-level property name in an object literal when using *ngFor

I am currently utilizing lodash for grouping items by their 'module' property. The code snippet I am using is as follows: _.groupBy(_.flatten(this.postReleaseArr), 'module'); This code returns the following image: https://i.sstatic.ne ...

Executing a Code-Behind function through AJAX without triggering a page refresh

I am looking for a way to directly call a code behind function without going through the PageLoad event in my ajax.aspx.vb file. Currently, I can call the function from the PageLoad event and pass the response using a variable located on the ajax.aspx page ...

Can anyone tell me the best way to access the name attribute of an HTML element in TypeScript?

Currently, my code is utilizing the name attribute to verify whether the user has entered information in a specific field and validating the input. However, I am facing an issue where the submit button remains active even if there are empty fields presen ...

TSDX incorporates Rollup under the hood to bundle CSS Modules, even though they are not referenced

I have recently developed a React library with TSDX and you can find it here: https://github.com/deadcoder0904/react-typical This library utilizes CSS Modules and applies styles to the React components. Although the bundle successfully generates a CSS fi ...

Guide to adjusting a variable with a timer

I am looking to incorporate a timer into the website background to keep track of the time users spend on the site. After 1 minute of being on the website, I would like to add a variable (let's call it "money") with a value of £1. If possible, I would ...

Transforming geographical coordinates to Cartesian coordinates and back again

I've been utilizing this code to convert lonlat to x,y,z, but I'm stuck on how to reverse the process. var phi = (this.lat)*Math.PI/180; var theta = (this.lon-180)*Math.PI/180; x = -(this.R) * Math.cos(phi) * Math.cos(theta); y = -(this.R) * Ma ...

The collapsible tree nodes overlap one another in the D3.js visualization

I'm currently working on integrating a d3 code into Power BI for creating a collapsible tree structure. Each node in the tree is represented by a rectangular box, but I've run into an issue where nodes overlap when their size is large. Below is t ...

Resizing textures for a glTF JSX imported model

I am brand new to this and struggling to figure out how to scale down my seamless texture. The methods related to materials are working fine, but those associated with textures are not having any effect. As a beginner in programming, I find this a bit frus ...

Transferring data packets via WebSocket

Imagine a scenario where you have a string consisting of ones and zeros, for example: "0101101" Now, the question arises - is there a way to transmit only these bits using the WebSocket.prototype.send method? The first step would be to convert these bit ...

Using Javascript to access the index of an element that has been checked and

I am working on a dynamic feature that involves a JavaScript variable called 'options'. This variable is designed to store and update a string with the .innerHTML content of every checkbox checked by the user. For instance, if the user checks Ins ...