[GLSL][solved] help needed getting started with shaders

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
user-r3
Posts: 70
Joined: Tue Dec 07, 2010 4:09 pm

[GLSL][solved] help needed getting started with shaders

Post by user-r3 »

First of all:
Sorry for this potentially nooby question, but I just entered the world of shaders (GLSL), which is completely new to me and introduced me to new things like matrices.

I updated this topic as I stumbled from one problem into another :lol:

I now think I got the correct normals

Code: Select all

normal = vec3(mInvWorld * vec4(gl_Normal, 0.0));
normal = normalize(normal);
as it is in the shader in the media folder of irrlichts demos.
(However, I do not know, why this is working and gl_NormalMatrix is not...?)

I think I also managed to get the correct transformations for the light and vertex positions. My test:

Code: Select all

Vertex Shader File:
...
position = vec3(gl_Vertex * mTransWorld);
...
Fragment Shader File:
void main (void)
{
vec3 lightPos = vec3(mTransWorld * vec4(mLightPos, 1.0));
float dist = length(position - lightPos);
float range = 150.0;
float diffusePointLight = float(dist < range);
 
gl_FragColor = vec4(diffusePointLight);
}
 
This seems to work correctly, as the area around the position of my theoretical light source is white :)

However, if I change this to real diffuse lighting:

Code: Select all

 
Fragment Shader File:
void main (void)
{
vec3 lightPos = vec3(mTransWorld * vec4(mLightPos, 1.0));
float dist = length(position - lightPos);
float range = 150.0;
vec3 surf2light = normalize(lightPos  - position);
vec3 norm = normalize(normal);
float diffusePointLight = max(dot(norm, surf2light), 0.0);
 
gl_FragColor = vec4(diffusePointLight);
}
 
This does not seem to work correctly.
The lighting seems to come from about the correct position, but it seems to shine as a spot into a specific direction instead of point lighting everything around... if this makes any sense :lol:

Thanks for anyone reading this and willing to help :)


--------
This is the original post:
--------
Now to my problem.
If I understood correctly (if I did not this whole problem is redundant^^) the normals of faces should be independent from camera position.
In my thinking a face that faces upwards should always have the normal vector (0, 1, 0), correct so far?

If these assumptions are correct I stumbled upon a problem:
The normals in my test program are not.

in my vertex shader I have the following lines:

Code: Select all

 
//...
varying vec3 normal;
//...
normal = normalize(gl_NormalMatrix * gl_Normal);
//...
 
and in my pixel shader the following lines, for testing purposes:

Code: Select all

 
//...
varying vec3 normal;
//...
vec3 norm = normalize(normal);
//...
gl_FragColor = vec4(norm, 1.0);
//...
 
So, again, if I understood correctly, the faces should have the same color as I fly around with my fps camera.
as xyz are converted to rgb, faces pointing upwards should always be completely green, right? But they aren't.
Also completely flat faces have different shades of colors ... and change as I fly around...

Is it me misunderstanding something here, or is it me using something in a wrong way? (or something different even^^)

I appreciate any attempts to help me, and I would gladly post more code, if necessary.

Thanks in advance
user-r3

EDIT:
If this topic belongs in the "beginner's help" section, I apologize, I just think this belongs here because the forum states shaders among the topics for advanced help :)
Last edited by user-r3 on Sun Sep 21, 2014 10:44 am, edited 1 time in total.
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: [GLSL][noob] help needed getting started with shaders

Post by mongoose7 »

Code: Select all

position = vec3(gl_Vertex * mTransWorld);
Are you sure your shader compiles? You can't multiply a 4x1 vector by a 4x4 matrix.

Code: Select all

vec3 lightPos = vec3(mTransWorld * vec4(mLightPos, 1.0));
You would never multiply the light position by the object's world transformation. If you are working in world coordinates, the light position doesn't need to be transformed, but the object's position may need to be. I'm assuming mTransWorld is the world/object transform and not the MVP. So

Code: Select all

normal = vec3(mInvWorld * vec4(gl_Normal, 0.0));
would be putting the object's normal into world coordinates, which would seem to be OK (if there is no asymmetric scaling).
No comment on the fragment shader as the code seems to be incomplete.
user-r3
Posts: 70
Joined: Tue Dec 07, 2010 4:09 pm

Re: [GLSL][noob] help needed getting started with shaders

Post by user-r3 »

Thanks for your reply :)
I want to say that I am really new to matrices too. I read a bit about what they are used for and how you can multiply matrices with each other but I don't really understand what each of the matrices do and which opengl matrices are equal to which irrlicht matrices.

1) I'm pretty sure it does compile. I get no warnings or errors and the result... is not what I would like to see, but the shader is doing something^^

2) If I don't do anything with the light it seems to be in the wrong position, or the world around it is... I don't know really... :/
[EDIT:] had a wrong multiplier in the c++ code, now the light seems to be in the correct position again, but has the same wrong lighting as the first version...

3) I don't plan to do any asymmetrical scalings, but what would be the correct way to do it?
---
Sorry for probably being dumb, but after reading/watching lots of GLSL tutorials online some things are still just not clear to me, being the matrices, but also especially the communication irrLicht-GLSL (as most tuts explain OpenGL-GLSL)

Thanks again :)
---
Here the complete shadercode, with lot's of redundant stuff probably, and the part of the C++ code that is probably relevant:

Code: Select all

#version 120
 
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform vec3 mLightPos;
uniform vec4 mLightColor;
 
varying vec2 texcoord;
 
varying vec3 position;
varying vec3 normal;
 
void main(void)
{
    gl_Position = mWorldViewProj * gl_Vertex;
 
    position = vec3(gl_Vertex * mTransWorld);
 
    normal = vec3(mInvWorld * vec4(gl_Normal, 0.0));
    normal = normalize(normal);
 
    texcoord = gl_MultiTexCoord0.xy;
}
 

Code: Select all

#version 120
 
uniform vec3 mLightPos;
 
uniform sampler2D tex;
varying vec2 texcoord;
 
varying vec3 position;
varying vec3 normal;
 
uniform mat4 mTransWorld;
 
 
void main (void)
{
 
/// Diffuse
    vec3 lightPos = vec3(mTransWorld * vec4(mLightPos, 1.0));
    float dist = length(position - mLightPos);
    float range = 150.0;
    
    vec3 surf2light = normalize(mLightPos  - position); /// lightPos or mLightPos ?????
    vec3 norm = normalize(normal);
    float diffusePointLight = max(dot(norm, surf2light), 0.0);
    
    gl_FragColor = vec4(diffusePointLight);
}
 
The following is mostly what I got from irrLicht tutorial 10.

Code: Select all

void CShaderCallback::OnSetConstants(IMaterialRendererServices* services, s32 userData)
{
    IVideoDriver* driver = services->getVideoDriver();
 
    // set inverted world matrix
 
    core::matrix4 invWorld = driver->getTransform(ETS_WORLD);
    invWorld.makeInverse();
 
    services->setVertexShaderConstant("mInvWorld", invWorld.pointer(), 16);
 
    // set clip matrix
 
    core::matrix4 worldViewProj;
    worldViewProj = driver->getTransform(ETS_PROJECTION);
    worldViewProj *= driver->getTransform(ETS_VIEW);
    worldViewProj *= driver->getTransform(ETS_WORLD);
 
    services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);
 
    // set light position
 
    vector3df  pos = vector3df(-3.f, 2.f, -1.3f)*110.f; 
 
    services->setVertexShaderConstant("mLightPos", reinterpret_cast<f32*>(&pos), 3);
 
    // set light color
 
    SColorf col(0.0f,1.0f,1.0f,0.0f);
 
    services->setVertexShaderConstant("mLightColor", reinterpret_cast<f32*>(&col), 4);
 
    // set transposed world matrix
 
    matrix4 world = driver->getTransform(ETS_WORLD);
    world = world.getTransposed();
 
    services->setVertexShaderConstant("mTransWorld", world.pointer(), 16);
 
    // set texture, for textures you can use both an int and a float setPixelShaderConstant interfaces (You need it only for an OpenGL driver).
    s32 TextureLayerID = 0;
 
    services->setPixelShaderConstant("myTexture", &TextureLayerID, 1);
}
 
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: [GLSL][noob] help needed getting started with shaders

Post by mongoose7 »

1. GLSL is GLSL. It works just like in raw OpenGL. The Irrlicht functions are just wrappers for the OpenGL ones. So go ahead and read the tutorials.
2. Transforming normals is not the same as other transformations. Instead of M you should use the inverse transpose of M. But it doesn't matter if M is composed only of rotations and translations, so you can save yourself the bother of thinking about it.
3. You didn't say what the lighting problem is. You should post a screenshot. Note also that you are not doing per-pixel lighting, so don't expect it to look "natural".
user-r3
Posts: 70
Joined: Tue Dec 07, 2010 4:09 pm

Re: [GLSL][noob] help needed getting started with shaders

Post by user-r3 »

Thanks for your reply :)

1) Could you tell me which irrLicht matrices "link to" the correct GL matrices?
in irrLicht we seem to call for matrices like ETS_VIEW, ETS_WORLD, ETS_PROJECTION, so these are equal to the View, Model(?) and Projection matrices?
:)

2) Thanks for the information :)

3)Sorry, here is a picture hopefully explaining what I mean. The light source is floating in front of the wall and I would think (as I treat it as a point light?!) the wall should be more or less the same in all directions from the light source - but it clearly doesn't look like that... Do you know what I am / could be doing wrong? :)

Image

Thanks again and again in advance, and sorry for my stupidity in this field :oops:
user-r3
Posts: 70
Joined: Tue Dec 07, 2010 4:09 pm

Re: [GLSL][noob] help needed getting started with shaders

Post by user-r3 »

I tried again with a much simpler object and with both the light and the object placed on 0/0/0, to reduce error sources.

I think the explanations on the picture tells you my problem, thanks :)

EDIT: The blue lines pointing inwards on the first picture are the normals of the faces. In case of not being familiar with blender.

Image
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: [GLSL][noob] help needed getting started with shaders

Post by mongoose7 »

You can show normals in Irrlicht with

Code: Select all

node->setDebugDataVisible(scene::EDS_NORMALS);
If simply changing the object changes the lighting, the problem may be with the objects. In any case, you should verify the normals.
user-r3
Posts: 70
Joined: Tue Dec 07, 2010 4:09 pm

Re: [GLSL][noob] help needed getting started with shaders

Post by user-r3 »

THANK YOU!

Pretty much: I'm dumb. :lol:

I thought of the normals as face normals and in this situation everything would be fine.

But I didn't think it through really:
VERTEX Shader gives VERTEX normals for interpolation...

As I have vertices that have 2 (or more) faces (or actually edges) attached to them they cannot have their normals point 90° from each face.
(The picture should show what I mean)

So, could you tell me possible solutions? The only thing that I could think of is splitting all of those faces apart, where I don't want normal interpolation (like I would on a sphere), but solid normals across whole faces?
This solution works, but results in much more vertices than necessary?!

Image

Thanks :D

EDIT: Just for clarification: the lighting difference between b3d and obj is because they (at least in this case) treat normals differently. The B3D has the same normals as the blender screenshot shows. The OBJ tries to put vertex normals normal to the face (thus one face looks like what I want^^)
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: [GLSL][noob] help needed getting started with shaders

Post by hendu »

It is normal to duplicate verts in these cases. It's what the exporters do behind your back when you specify "hard edge" in your modeler.
user-r3
Posts: 70
Joined: Tue Dec 07, 2010 4:09 pm

Re: [GLSL][noob] help needed getting started with shaders

Post by user-r3 »

Thanks guys :D
With split faces it looks more like what I had in mind :)

If you can spot any problems on these screens below please tell me, otherwise I'll mark this topic as solved and proceed in figuring out stuff in shaders :lol:

Image
Post Reply