Sight vector in OpenGL - opengl

The problem I have is that I cant get "line of sight" vector in OpenGL. I've done some research and found that it should be Z vector after transformations, but it doesn't want to work. I've got this code to retrive velocity of the block( i want it to move foward from "camera"), but all the time it moves irrelevant to camera, but all the time same way compared to rendered world:
GLfloat matrix[16];
glGetFloatv (GL_MODELVIEW_MATRIX, matrix);
GLfloat d = sqrt( matrix[8]*matrix[8] + matrix[9]*matrix[9] + matrix[10]*matrix[10]);
xmov = matrix[8]/d;
ymov = matrix[9]/d;
zmov = matrix[10]/d;
What I've done wrong?

Okay, now after you clarified what you really want to do, I'm pretty sure this is the correct answer:
You are probably used to something called ModelView matrix. Didn't it seem strange for you that it's essentially combined of two parts? Well, it was for me, and after I thought about it for a while, it made sense. The final vertex position is calculated like this:
gl_Position = ProjectionMat * ModelViewMat * VertexPos;
You see, there's no difference for OpenGL whether you move "camera" from origin by [x,y,z] or move objects by [-x,-y,-z] - you'll get the same results. It is however useful to distinguish a "camera" position as something that can be different from the origin.
gl_Position = ProjectionMat * ViewMat * ModelMat * VertexPos;
I think the most natural way to do it is, as I said, split the calculations into two matrices : Model and View. Every object on the scene now has to change the Model matrix, and camera position is set by changing View matrix. Makes sense?
I'll give you an example. If your camera is in [5,0,0] (which corresponds to Translate(-5,0,0)), and your object in [-5,0,0], it will land 10 units from the camera. Now, when you move your camera further away from origin (increasing the first translation distance), distance between "camera" and the object grows.
The object translation is the Model, the camera translation is the View.
So it's not hard to come to conclusion, that if you want to ignore camera position, just strip the View part from the equation; every object will now be drawn without taking camera position into account, thus relative only to your viewport.
gl_Position = ProjectionMat * ModelMat * VertexPos;
Our hypothetical model will now land 5 units along the X axis from the viewport regardless of what you're currently "looking at", and that's, I think, pretty much what you wanted to achieve.
Anyway, you could probably use a nice tutorial about it

Related

Finding world position of element in screen space

I'm attempting to find the world position of an object that exists in screen space. For example in the below screenshot the pistol and hands are rendered without being translated into world space (using only projectionMatrix * modelMatrix), while the other objects in the scene exist in world space (translated via projectionMatrix * viewMatrix * modelMatrix):
I have added a "muzzle" bone to the end of the armature for this pistol, and I am attempting to convert the translation of the muzzle bone into world space so that I can cast a ray starting at this position.
I have this kind of working, but something isn't quite right. For example, note the closest green sphere in the above screenshot. That is the position which I come up with in world space for my muzzle bone. What I am expecting is below:
To obtain this position I am multiplying the position of the muzzle bone by the inverse of the projection and view matrixes of the world camera as follows:
glm::mat4 invMat = glm::inverse(worldStage.getCamera().value().getProjectionMatrix() *
worldStage.getCamera().value().getViewMatrix());
glm::vec4 tmp = this->weapons[this->currentWeapon].actor->getTransform().getMatrix() *
glm::vec4(this->weapons[this->currentWeapon].muzzleBone->translation, 1.0f);
glm::vec4 muzzleWorldTranslation = invMat * tmp;
muzzleWorldTranslation /= muzzleWorldTranslation.w;
It feels like I'm pretty close and there's just something that I'm missing or messed up slightly. If anyone is able to point out what that might be, I would be very grateful!
If you render an object with standard model M, view V and P matrices, you get the P*V*M as the overall transformation. If you draw a model without the view transform, you're placing the object directly in view space. However, conceptually, that will be the same as first placing your object in world space (by applying a modified model matrix M'), and rendering that with the full P*V*M' pipline.
Since V transforms from world to view space, inverse(V) will transform from view space to world space, and therefore M' = inverse(V) * M will get you P*V*M' = P*V*inverse(V)*M = P*M, and M' is exactly the transformation you are looking for. Note that the projection matrix has nothing to do with that at all, and you are not unprojecting any positions back from screen space as the question title suggests.

GLSL Shader - change 'camera' position

I'm trying to create some kind of 'camera' object with OpenGL. By changing its values, you can zoom in/out, and move the camera around. (imagine a 2d world and you're on top of it). This results in the variables center.x, center.y, and center.z.
attribute vec2 in_Position;
attribute vec4 in_Color;
attribute vec2 in_TexCoords;
uniform vec2 uf_Projection;
uniform vec3 center;
varying vec4 var_Color;
varying vec2 var_TexCoords;
void main() {
var_Color = in_Color;
var_TexCoords = in_TexCoords;
gl_Position = vec4(in_Position.x / uf_Projection.x - center.x,
in_Position.y / -uf_Projection.y + center.y,
0, center.z);
}
I'm using uniform vec3 center to manipulate the camera location. (I'm feeling it should be called an attribute, but I don't know for sure; I only know how to manipulate the uniform values. )
uf_Projection has values of half the screen height and width. This was already the case (forking someones code), and I can only assume it's to make sure the values in gl_Position are normalized?
Entering values for i.e. center.x does change the camera angle correctly. However, it does not match the location at which certain things appear to be rendered.
In addition to the question: how bad is the code?, I'm actually asking these concrete questions:
What is in_Position supposed to be? I've seen several code examples use it, but no-one explains it. It's not explicitly defined either; which values does it take?
What values is gl_Position supposed to take? uf_Projection seems to normalize the values, but when adding values (more than 2000) at center.x, it still works (correctly moved the screen).
Is this the correct way to create a kind of "camera" effect? Or is there a better way? (the idea is that things that aren't on the screen, don't have to get rendered)
The questions you ask can only be answered if one considers the bigger picture. In this case, this means we should have a look at the vertex shader and the typical coordinate transformations which are used for rendering.
The purpose of the vertex shader is to calculate a clip space position for each vertex of the object(s) to be drawn.
In this context, an object is just a sequence of geometrical primitives like points, lines or triangles, each specified by some vertices.
These verties typically specify some position with respect to some completely user-defined coorinate frame of reference. The space those vertex positions are defined in is typically called the object space.
Now the vertex shader's job is to transform from object space to clip space using some mathematical or algorithmical way. Typically, these transformation rules also implicitely or explicitetely consist of some "virtual camera", so that the object is transformd as if observed by said camera.
However, what rules are used, and how they are described, and which inputs are needed is completely free.
What is in_Position supposed to be? I've seen several code examples use it, but no-one explains it. It's not explicitly defined either; which values does it take?
So in_Position in your case is just some attribute (meaning it is a value which is specified per vertex). The "meaning" of this attribute depends solely on how it is used. Since you are using it as input for some coordinate transformation, we could interpret it as meaning the object space position of the vertex. In your case, that is a 2D object space.The values it "takes" are completely up to you.
What values is gl_Position supposed to take? uf_Projection seems to normalize the values, but when adding values (more than 2000) at center.x, it still works (correctly moved the screen).
gl_Position is the clip space position of the vertex. Now clip space is a bit hard to describe. The "normalization" you see here has to do with the fact that there is another space, the normalized device coords (NDC). And in the GL, the convention for NDC is such that the viewing volume is represented by the -1 <= x,y,z <=1 cube in NDC.
So if x_ndc is -1, the object will appear at the left border of your viewport, x=1 at the right borde, y=-1 at bottom border and so on. You also have clipping at z, so object which are too far away or are too near of the hypothetical camera position will also not be visible. (Note that the near clipping plane will also exclude everything which is behind the observer.)
The rule to transform from clip space to NDC is by dividing the clip space x,y and z vlaues by the clip space w value.
The rationale for this is that clip space represents a so called projective space, and the clip space coordinates are homogenuous coordinates. It would be far to much to explain the theory behind this in an StackOverflow article.
But what this means is that by setting gl_Position.w to center.z, the GL will later effectively divide gl_Position.xyz by center.z to reach NDC coordinates. Such a division basiaclly creates the perspective effect that points which are farther away appear closer together.
It is unclear to me if this is exactly what you want. Your current solution has the effect that increasing center.z will increase the object space range that is mapped to the viewing volume, so it does give a zoom effect. Let's consider the x coordinate:
x_ndc = (in_Position.x / uf_Projection.x - center.x) / center.z
= in_Position.x / (uf_Projection.x * center.z) - center.x / center.z
To put it the other way around, the object space x range you can see on the screen will be the inverse transformation applied to x_ndc=-1 and x_ndc=1:
x_obj = (x_ndc + center.x/center.z) * (uf_Projection.x * center.z)
= x_ndc * uf_Projection.x * center.z + center.x * uf_Projection.x
= uf_Projection.x * (x_ndc * center.z + center.x);
So basically, the visibile object space range will be center.xy +- uf_Projection.xy * center.z.
Is this the correct way to create a kind of "camera" effect? Or is there a better way? (the idea is that things that aren't on the screen, don't have to get rendered)
Conceptually, the steps are right. Usually, one uses transformation matrices to define the necessary steps. But in your case, directly applying the transformations as some multiplcations and additions is even more efficient (but less flexible).
I'm using uniform vec3 center to manipulate the camera location. (I'm feeling it should be called an attribute, but I don't know for sure.
Actually, using a uniform for this is the right thing to do. Attributes are for values which can change per vertex. Uniforms are for values which are constant during the draw call (hence, are "uniform" for all shader invocations they are accesed by). Your camera specification should be the same for each vertex you are processing. Only the vertex position does vary between vertices, so that each vertex will end up at a different point with respect to some fixed camera location (and parameters).

Why do you use camera space instead of model space for normals?

I am learning OpenGL graphics, and am getting into shadows. The tutorials that I am reading are telling me to transform my normals and light vector to camera space. Why is this? Why can't you just keep the coords in model space?
A follow up question to this is how to handle model transformations. I am unable to find a definitive answer. I currently have this code:
vec3 normCamSpace = normalize(mat3(V) * normal);"
vec3 dirToLight = (V*vec4(lightPos, 0.0)).xyz;"
float cosTheta = clamp(dot(normCamSpace, dirToLight),0,1);"
V is the view matrix, or the camera matrix. I am unsure how to move or edit the light when the model changes in position, rotation, and scale.
The main reason is, that usually your light positions will not be given in model space, but world space. However for illumination to work efficiently all calculations must happen in a common space. In your usual transformation chain, model local coordinates are transformed by the modelview matrix directly into view space
p_view = MV · p_local
Since you normally have only one modelview matrix it would be cumbersome to separate this steap into something like
p_world = M · p_local
p_view = V · p_world
For that you required MV to be separated.
Since the projection transformation traditionally happens as a separate step, view space is the natural "common lower ground" on which illumination calculation to base on. It just involves transforming transforming your light positions from world to view space, and since light positions are not very complex, this is done on the CPU and the pretransformed light positions given as shader.
Note that nothing is stopping you from performing illumination calculations in world space, or model local space. It just takes transforming the light positions correctly.
I am learning OpenGL graphics, and am getting into shadows. The tutorials that I am reading are telling me to transform my normals and light vector to camera space. Why is this? Why can't you just keep the coords in model space?
Actually if you're the one writing the shader, you can use whatever coordinate space you want. IMO calculating lighting in world space feels more "natural", but that's matter of taste.
However, there are two small details:
You cannot "naturally" calculate lighting in object space, if your object is a skinned mesh (character model animated by bones). Such model will require world space or view space. If your object can be only translated and rotated (affine transforms only), then lighting can be easily calculated in model/object space. I think some game engines actualy worked this way.
If you use camera space, you can drop one subtraction when calculating specular highlights. Blinn/phong specular models require vector to(or from) eye to calculate specular factor. In camera space vector from eye to point is equal to point position. This is a very small optimization and it probably isn't worth the effort.

Actually where (or what way ) matrix mode switching takes place in modern opengl 3.x/4.x?

I've read much about vectors, buffer objects etc., and reviewed much of example application implementing old/new opengl operations. My app, including object loading, transformations and vertex/fragment shaders works, in general, I understand how to pass various type of variables to shaders, and how to draw arrays and elements arrays, everything goes fine so far.
But there's one thing I don't understand - final gl_Position matrix used matrix I generated, passed to vertex shader, as some result of some mathematical operations ( actually I use SDL, glew and glm's functions like lookAt, translate, rotate etc. ).
what I do is
shader
#version ...
uniform mvp..
main ..
{
gl_Position = mvp * ...;
}
cpp
load_object_vertices_indexes_etc;
install_shaders;
bind_buffers;
buffer_data;
enable_vertex_array_elements_etc;
mat4 aaa_proj = perspective(persp_params);
mat4 bbb_view = lookAt(look_params);
mat4 ccc_model = translate(translate_params);
mat4 ddd_anim = rotate(rotate_params);
/* then I do matrix multiply */
mat4 some_final = ..proj * ...view * ..model * anim;
glUniformMatrix4fv(location_in_shader, 1, GL_FALSE, ..val_pointer_of_some_final)
glClear(appropriate_bitfield);
glDraw...(spec);
The point is, that, actually, final matrix I can, of course, generate by any combination. Shader calls gl_Position with valid result matrix, no matter how it was generated.
Now, where exactly do I switch from projection to view to model to anim? Of course matrix names doesn't matter, is there a switching somewhere inside perspective, lookAt, translate and rotate? I mean - if the stack contains actually four stages, each one of these stages can be translated, rotated, scaled, etc. As I understand it by now, actions I take would not matter, if there would be only one stage of matrix stack.
Theoretically, inside 3d scene, I should be able to get similar effect if I ( rotate view 45 degrees left, and then rotate model 45 degrees right ), or if I ( rotate view 45 right and then rotate model 45 degress left).
When I stand physically in front of teapot, I can turn it right 45 and walk around the table (translate and rotate myself) to left 45 to see it from the front - or turn it left 45 and walk 45 to right to see it from the front. It will differ for the rest of the world ( I will see left or right room wall behind teapot ), but obviously I will end seeing the front of the pot.
So, to conclude, if I would like to implement two routines - A( obj_turn_left, me_turn_right ) and B (obj_turn_right, me_turn_left), both rotating model first, and myself (eye, camera) later, how do I specify to which matrix mode particular rotation or transformation applies? Should I use glMatrixMode(APPROPRIATE_CONST) to force going a particular stage when I want? glMatrixMode isn't used in my code so far.
There is no switching at all happening. You multiply the whole transformation chain into one single compound matrix.
For the sake of making things easier when it comes to advanced stuff you normally separate the transformation into modelview and projection, so that you can perform e.g. lighting calculations in view space. But this is not a switch it's just an intermediary step.

How to transform back-facing vertices in GLSL when creating a shadow volume

I'm writing a game using OpenGL and I am trying to implement shadow volumes.
I want to construct the shadow volume of a model on the GPU via a vertex shader. To that end, I represent the model with a VBO where:
Vertices are duplicated such that each triangle has its own unique three vertices
Each vertex has the normal of its triangle
For reasons I'm not going to get into, I was actually doing the above two points anyway, so I'm not too worried about the vertex duplication
Degenerate triangles are added to form quads inside the edges between each pair of "regular" triangles
Using this model format, inside the vertex shader I am able to find vertices that are part of triangles that face away from the light and move them back to form the shadow volume.
What I have left to figure out is what transformation exactly I should apply to the back-facing vertices.
I am able to detect when a vertex is facing away from the light, but I am unsure what transformation I should apply to it. This is what my vertex shader looks like so far:
uniform vec3 lightDir; // Parallel light.
// On the CPU this is represented in world
// space. After setting the camera with
// gluLookAt, the light vector is multiplied by
// the inverse of the modelview matrix to get
// it into eye space (I think that's what I'm
// working in :P ) before getting passed to
// this shader.
void main()
{
vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal);
vec3 realLightDir = normalize(lightDir);
float dotprod = dot(eyeNormal, realLightDir);
if (dotprod <= 0.0)
{
// Facing away from the light
// Need to translate the vertex along the light vector to
// stretch the model into a shadow volume
//---------------------------------//
// This is where I'm getting stuck //
//---------------------------------//
// All I know is that I'll probably turn realLightDir into a
// vec4
gl_Position = ???;
}
else
{
gl_Position = ftransform();
}
}
I've tried simply setting gl_position to ftransform() - (vec4(realLightDir, 1.0) * someConstant), but this caused some kind of depth-testing bugs (some faces seemed to be visible behind others when I rendered the volume with colour) and someConstant didn't seem to affect how far the back-faces are extended.
Update - Jan. 22
Just wanted to clear up questions about what space I'm probably in. I must say that keeping track of what space I'm in is the greatest source of my shader headaches.
When rendering the scene, I first set up the camera using gluLookAt. The camera may be fixed or it may move around; it should not matter. I then use translation functions like glTranslated to position my model(s).
In the program (i.e. on the CPU) I represent the light vector in world space (three floats). I've found during development that to get this light vector in the right space of my shader I had to multiply it by the inverse of the modelview matrix after setting the camera and before positioning the models. So, my program code is like this:
Position camera (gluLookAt)
Take light vector, which is in world space, and multiply it by the inverse of the current modelview matrix and pass it to the shader
Transformations to position models
Drawing of models
Does this make anything clearer?
the ftransform result is in clip-space. So this is not the space you want to apply realLightDir in. I'm not sure which space your light is in (your comment confuses me), but what is sure is that you want to add vectors that are in the same space.
On the CPU this is represented in world
space. After setting the camera with
gluLookAt, the light vector is multiplied by
the inverse of the modelview matrix to get
it into eye space (I think that's what I'm
working in :P ) before getting passed to
this shader.
multiplying a vector by the inverse of the mv matrix brings the vector from view space to model space. so you're saying your light-vector (in world space), is applied a transform that does view->model. It makes little sense to me.
We have 4 spaces:
model space: the space where your gl_Vertex is defined in.
world space: a space that GL does not care about in general, that represents an arbitrary space to locate the models in. It's usually what the 3d engine works in (it maps to our general understanding of world coordinates).
view space: a space that corresponds to the referencial of the viewer. 0,0,0 is where the viewer is, looking down Z. Obtained by multiplying gl_Vertex by the modelview
clip space: the magic space that the matrix projection brings us in. result of ftransform is in this space (so is gl_ModelViewProjectionMatrix * gl_Vertex )
Can you clarify exactly which space your light direction is in ?
What you need to do, however, is make the light vector addition in either model, world or view space: Bring all the bits of your operation in the same space. E.g. for model space, just compute the light direction in model space on CPU, and do a:
vec3 vertexTemp = gl_Vertex + lightDirInModelSpace * someConst
then you can bring that new vertex position in clip space with
gl_Position = gl_ModelViewProjectionMatrix * vertexTemp
Last bit, don't try to apply vector additions in clip-space. It won't generally do what you think it should do, as at that point you are necessarily dealing with homogeneous coordinates with non-uniform w.