Why is my GLSL shader lighting moving around the stage with the objects it shines on?

I follow the OpenGL ES 2.0 tutorial and combine it with the GLSL lighting tutorial I found using Utah's handy tea pot from developer.apple.com.

After many exercises and experiments, I have a kettle drawn moderately correctly on the screen, rotating around all three axes with “tone shading” from the working light. As a result, because of me, several failures in the geometry simply draw the entire list of vertices in the form of triangular stripes (if you look in the teapot.h file, there is "-1" where I should start new triangular stripes, but this is only test data and not related to my problem).

I'm a little confused about how to position the light in the scene. In my Objective-C code, I have a float 3 vector that contains {0,1,0} and passes this to the shader to then calculate the light intensity.

Why does light also appear on stage? I mean, the light acts as if it is attached to the teapot with an invisible stick, always pointing to the same side, regardless of the direction the teapot is in.

This is the vertex shader.

attribute vec4 Position; attribute vec4 SourceColor; attribute vec3 Normal; uniform mat4 Projection; uniform mat4 Modelview; varying vec3 normal; void main(void) { normal = Normal; gl_Position = Projection * Modelview * Position; } 

The "position" is set by the Obj-C code and is the vertex for the object, "Normal" is a list of normals from both the vertex array (VBO), "Projection", and "Modelview", calculated as follows:

(A CC3GLMatrix from the Cocos3D library mentioned in the GLES tutorial above)

 CC3GLMatrix *projection = [CC3GLMatrix matrix]; float h = 4.0f * self.frame.size.height / self.frame.size.width; [projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:1 andFar:100]; glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix); CC3GLMatrix *modelView = [CC3GLMatrix matrix]; [modelView populateFromTranslation:CC3VectorMake(0, 0, -7)]; [modelView scaleBy:CC3VectorMake(30, 30, 30)]; _currentRotation += displayLink.duration * 90; [modelView rotateBy:CC3VectorMake(_currentRotation, _currentRotation, _currentRotation)]; glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix); 

And I set the light in the scene by doing

 float lightDir[] = {1,0,1}; glUniform3fv(_lightDirUniform, 1, lightDir); 

The fragment shader is as follows

 varying lowp vec4 DestinationColor; // 1 varying highp vec3 normal; uniform highp vec3 LightDir; void main(void) { highp float intensity; highp vec4 color; intensity = dot(LightDir,normal); if (intensity > 0.95) color = vec4(1.0,0.5,0.5,1.0); else if (intensity > 0.5) color = vec4(0.6,0.3,0.3,1.0); else if (intensity > 0.25) color = vec4(0.4,0.2,0.2,1.0); else color = vec4(0.2,0.1,0.1,1.0); gl_FragColor = color; } 

When trying to deal with this, I come across code that refers to (not existing in GLES) gl_LightSource and gl_NormalMatrix, but I don’t know what to put in equivalents. I need to transfer shaders from my code, Links to "space for space", "outer space", etc. Confused, I know that I probably should convert things between them, but I don’t understand why and how (and where - in the code or in the shader?)

In each frame, do I need to change the light source? The code I have for customization seems too simplistic. I really don’t touch the kettle, I, instead, am I moving the whole scene - the light and everything around?

+4
source share
1 answer

First of all, some definitions:

  • world space: a space in which the whole world is defined. By convention, this is a static space that never moves.

  • viewing camera space / camera space / eye space: the space in which your camera is installed. Usually this position and rotation relative to world space.

  • model space: the space in which your model is defined. Like camera space, usually this position and rotation relative to world space.

  • bright space: same as model space

In simple examples (and, I think, in yours), the model space and the world space are the same. In addition, OpenGL itself does not have a concept of world space, which does not mean that you cannot use it. This is useful when you want several objects to be moved independently in your scene.

Now, what do you do with your object before rendering, a matrix is ​​created that transforms the vertices of the model into a representation space, therefore, "modelViewMatrix".

In the light in this case it is a little different. The calculation of the light in your shader is done in the model space, so you need to convert your light position in each frame into the model space.

This is done by calculating something like:

 _lightDirUniform = inverseMatrix(model) * inverseMatrix(light) * lightPosition; 

The light position is transformed from light to the world, and then to model space. If you do not have world space, just leave the model space transformation and you should be fine.

+5
source

Source: https://habr.com/ru/post/1368981/


All Articles