1
\$\begingroup\$

Sorry for the terrible title, but I really cant think of anything better.. Suggestions welcome.

I am trying to do something like showcased in this video:

http://www.youtube.com/watch?v=CaTI2d0tQME

So basically smoothly change the opacity when looked face-on.

This is my vertex shader so far, the fragment shader is simple as it just multiplies the lightColor with the texture:

#version 430 core

uniform mat4 MV;
uniform mat4 MVP;

layout(location = 0) attribute vec3 vertexPosition;
layout(location = 1) attribute vec2 vertexUV;
layout(location = 2) attribute vec3 vertexNormal;

layout(location = 3) attribute mat4 bufferMatrix; // For per-instance translation

varying  vec2 UV;
varying  vec4 lightColor;
flat varying int InstanceID;

void main(){
    vec4 mcPosition = MV * bufferMatrix * vec4(vertexPosition, 1.0);
    mcPosition = mcPosition / length(mcPosition);

    vec3 mcNormal = vertexNormal;

    vec3 ecNormal = vec3(MV * bufferMatrix * vec4(mcNormal, 0.0));
    ecNormal = ecNormal / length(ecNormal);

    float dotProduct = dot(vec4(mcNormal, 1.0), mcPosition);

    lightColor = vec4(dotProduct);

    gl_Position = MVP * bufferMatrix * vec4(vertexPosition, 1.0);
    UV = vertexUV;
    InstanceID = gl_InstanceID;
}

The base is copied code from a 'phong' shader - that works!.. I have tried everything I could think of, as well as searched google for quite some time.

I think I realize what I need to do mathematically, which is getting the dot-product of the vertex-normal on to the view-to-vertex vector. That is mathematically speaking, another is to do it in GLSL with matrices etc.

I am bad at debugging GLSL code, but right now the lightColor is always 0, no matter where I look at the model from.

Quick Bonus Question: What is the technique in the video actually called - if anything?

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

The easiest think to do is to pass as a uniform the position of the camera in World-Space and calculate the direction from the vertex to the camera and then calculate the dot product between that direction and the vertex normal. The code would be something similar to

#version 430 core

uniform mat4 M;
uniform mat4 M_InvTransp;
uniform mat4 MVP;
uniform vec4 cameraPosition;

layout(location = 0) attribute vec3 vertexPosition;
layout(location = 1) attribute vec2 vertexUV;
layout(location = 2) attribute vec3 vertexNormal;

layout(location = 3) attribute mat4 bufferMatrix; // For per-instance translation

varying  vec2 UV;
varying  vec4 lightColor;
flat varying int InstanceID;

void main(){
    vec4 positionWCS = bufferMatrix * M * vec4(vertexPosition, 1.0);
    vec4 vertexToCamera = cameraPosition - positionWCS;
    vec3 direction = normalize(vertexToCamera.xyz);
    vec4 normalWCS = M_InvTransp * vec4(vertexNormal, 0.0);
    normalWCS.xyz = normalize(normalWCS.xyz);

    // if the face is facing the camera the dotProduct would be 1.0 so to make
    // the face trasparent multiply the texture with 1.0 - dotProduct
    float dotProduct = dot(normalWCS.xyz, direction);
    lightColor = vec4(1.0-dotProduct);

    gl_Position = MVP * bufferMatrix * vec4(vertexPosition, 1.0);
    UV = vertexUV;
    InstanceID = gl_InstanceID;
}

You should multiply the normal with the inverse - transpose Model matrix since if your Model Matrix is not an orthonormal matrix you would get incorrect results if you multiply him with the normal. Also the code will work only if your bufferMatrix contains only translation information and not rotation or scaling.
Keep in mind that a direction in a 3D space is defined by X,Y,Z components, so it is better to have the W component as zero when you normalize or calculating the length of the normal ( or not use it at all as in the code above ), otherwise you will get incorrect results.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .