How to get a value from vec3 in vertex shader? OpenGL 3.3 - c++

I have the following vertex shader:
#version 330
layout (location = 0) in vec3 Position;
uniform mat4 gWVP;
out vec4 Color;
void main()
{
gl_Position = gWVP * vec4(Position, 1.0);
};
How can I get, for example, the third value of vec3? The first my thought was: "Maybe I can get it by multiplying this vector(Position) on something?" But I am not sure that something like "vertical vector type" exists.
So, what is the best way? I need this value to set the color of the pixel.

There are at least 4 options:
You can access vector components with component names x, y, z, w. This is mostly used for vectors that represent points/vectors. In your example, that would be Position.z.
You can use component names r, g, b, a. This is mostly used for vectors that represent colors. In your example, you could use Position.b, even though that would not be very readable. On the other hand, Color.b would be a good option for the other variable.
You can use component names s, t, p, q. This is mostly used for vectors that represent texture coordinates. In our example, Position.p would also give you the 3rd component.
You can use the subscript notation with 0-based indices. In your example, Position[2] also gives he 3rd element.

Each vector has overloaded access to elements. In this case, using Position.z should work.

Related

Can I access the spare floats in a mat3 in GLSL?

I'm using a mat3 uniform in a GLSL shader.
layout (std140)
struct UNI {
mat3 mat;
} u;
A mat3 is stored as 3 rows of vec4 in GLSL so that means there's 3 unused floats in there.
Is there any way to access those floats? I want to to pack some more data in there.
nb. I tried using u.mat[0][3] but it says "array index out of bounds" when I compile it.
I think you are mixing two things here:
the actual memory layout of the data
the API that GLSL provides you to access the data
When you are using Uniform Buffer Objects (UBO) to back the storage of the mat3 and are using the std140 layout, then yes, a mat3 is layed out in exactly the same way as 3 vec4 values. So, essentially, under std140 layout there is no difference in the memory layout between a mat3x4 (three columns each with 4 rows/elements) and a mat3 or mat3x3.
However, you cannot access the fourth row of each column when using a mat3 as the API type in the GLSL shader.
What you could do instead is simply use the mat3x4 type, which would give you access to the fourth row. And when you need a mat3 you can cast it with mat3(theMat3x4Value).

OpenGL In-shader Vertex Matrix Creation

I am trying to generate up my projection and transform matrix functions inside my vertex shader, e.g. defining my transform, rotation, and perspective matrix functions in terms of GLSL. I am doing this in order to increase readability of my program by bypassing all the loading/importing etc. of matrices into the shader, apart from camera position, rotation and FOV.
My only concern is that the matrix is being calculated each shader call or each vertex calculation.
Which, if either of the two, is what actually happens in the shader?
Is it better to deal with the clutter and import the matrix from my program, or is my short-cut of creating the matrix in-shader acceptable/recommended?
*update with code*
#version 400
in vec4 position;
uniform vec3 camPos;
uniform vec3 camRot;
mat4 calcMatrix(
vec3 pos,
vec3 rot,
) {
float foo=1;
float bar=0;
return mat4(pos.x,pos.y,pos.z,0,
rot.x,rot.y,rot.z,0,
foo,bar,foo,bar,
0,0,0,1);
}
void main()
{
gl_Position = calcMatrix(camPos, camRot) * position;
}
versus:
#version 400
in vec4 position;
uniform mat4 viewMatrix;
void main()
{
gl_Position = viewMatrix * position;
}
Which method is recommended?
Whats wrong with doing
float[16] matrix;
calculate_transform(matrix, args);
glUniformMatrix4fv(mvp, 1, false, matrix);
Or even
set_matrix_uniform_using(mvp, args);
which then does what the previous bit of code does.
If you are worried about clutter then extract a function and give it a good name.
To do this in the shader there are several consequences: you would need multiple varaibles to express what the single matrix expresses, leading to clutter at shader load and uniform upload, shader debugging is much more difficult than making sure your own cope does what it needs to do. If you hardcode the movement code you cannot replace it with a free moving camera without changing the shader.
All that doesn't even touch on performance costs. The GPU is much better at loading a matrix from uniform memory and multiplying a it with a vector than it is at doing the trig function needed for the frustum and rotate.
If you need a different matrix for each vertex, well, fairly do it in the shader. I can't imagine a case where that's needed.
Otherwise, it's much more faster to pass the matrix as a uniform. Don't overload the GPU computing again and again the same matrix.

Acessing VBO/VAO Data in GLSL Shader

In a vertex shader how can a function within the shader be made to access a specific attribute array value after buffering its vertex data to a VBO?
In the shader below the cmp() function is supposed to compare a uniform variable with vertex i.
#version 150 core
in vec2 vertices;
in vec3 color;
out vec3 Color;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform vec2 cmp_vertex; // Vertex to compare
out int isEqual; // Output variable for cmp()
// Comparator
vec2 cmp(){
int i = 3;
return (cmp_vertex == vertices[i]);
}
void main() {
Color = color;
gl_Position = projection * view * model * vec4(vertices, 0.0, 1.0);
isEqual = cmp();
}
Also, can cmp() be modified so that it does the comparison in parallel?
Based on the naming in your shader code, and the wording of your question, it looks like you misunderstood the concept of vertex shaders.
The vertex shader is invoked once for each vertex. So when your vertex shader code executes, it always operates on a single vertex. This means that the name of your in variable is misleading:
in vec2 vertices;
This variable gives you the position of the one and only vertex your shader is working on. So it would probably be clearer if you used a name in singular form:
in vec2 vertex;
Once you realize that you're operating on a single vertex, the rest becomes easy. For the comparison:
bool cmp() {
return (cmp_vertex == vertex);
}
Vertex shaders are typically already invoked in parallel, meaning that many instances can execute at the same time, each one on its own vertex. So there is no need for parallelism within a single shader instance.
You'll probably have more issues achieving what you're after. But I hope that this gets you at least over the initial hurdle.
For example, the following out variable is problematic:
out int isEqual;
out variables of the vertex shader have matching in variables in the fragment shader. By default, the value written by the vertex shader is linearly interpolated across triangles, and the fragment shader gets the interpolated values. This is not supported for variables of type int. They only support flat interpolation:
flat out int isEqual;
But this will probably not give you what you're after, since the value you see in the fragment shader will always be the same across an entire triangle.

Opengl - instanced attributes

I use oglplus - it's a c++ wrapper for OpenGL.
I have a problem with defining instanced data for my particle renderer - positions work fine but something goes wrong when I want to instance a bunch of ints from the same VBO.
I am going to skip some of the implementation details to not make this problem more complicated. Assume that I bind VAO and VBO before described operations.
I have an array of structs (called "Particle") that I upload like this:
glBufferData(GL_ARRAY_BUFFER, sizeof(Particle) * numInstances, newData, GL_DYNAMIC_DRAW);
Definition of the struct:
struct Particle
{
float3 position;
//some more attributes, 9 floats in total
//(...)
int fluidID;
};
I use a helper function to define the OpenGL attributes like this:
void addInstancedAttrib(const InstancedAttribDescriptor& attribDesc, GLSLProgram& program, int offset=0)
{
//binding and some implementation details
//(...)
oglplus::VertexArrayAttrib attrib(program, attribDesc.getName().c_str());
attrib.Pointer(attribDesc.getPerVertVals(), attribDesc.getType(), false, sizeof(Particle), (void*)offset);
attrib.Divisor(1);
attrib.Enable();
}
I add attributes for positions and fluidids like this:
InstancedAttribDescriptor posDesc(3, "InstanceTranslation", oglplus::DataType::Float);
this->instancedData.addInstancedAttrib(posDesc, this->program);
InstancedAttribDescriptor fluidDesc(1, "FluidID", oglplus::DataType::Int);
this->instancedData.addInstancedAttrib(fluidDesc, this->program, (int)offsetof(Particle,fluidID));
Vertex shader code:
uniform vec3 FluidColors[2];
in vec3 InstanceTranslation;
in vec3 VertexPosition;
in vec3 n;
in int FluidID;
out float lightIntensity;
out vec3 sphereColor;
void main()
{
//some typical MVP transformations
//(...)
sphereColor = FluidColors[FluidID];
gl_Position = projection * vertexPosEye;
}
This code as whole produces this output:
As you can see, the particles are arranged in the way I wanted them to be, which means that "InstanceTranslation" property is setup correctly. The group of the particles to the left have FluidID value of 0 and the ones to the right equal to 1. The second set of particles have proper positions but index improperly into FluidColors array.
What I know:
It's not a problem with the way I set up the FluidColors uniform. If I hard-code the color selection in the shader like this:
sphereColor = FluidID == 0? FluidColors[0] : FluidColors1;
I get:
OpenGL returns GL_NO_ERROR from glGetError so there's no problem with the enums/values I provide
It's not a problem with the offsetof macro. I tried using hard-coded values and they didn't work either.
It's not a compatibility issue with GLint, I use simple 32bit Ints (checked this with sizeof(int))
I need to use FluidID as a instanced attrib that indexes into the color array because otherwise, if I were to set the color for a particle group as a simple vec3 uniform, I'd have to batch the same particle types (with the same FluidID) together first which means sorting them and it'd be too costly of an operation.
To me, this seems to be an issue of how you set up the fluidID attribute pointer. Since you use the type int in the shader, you must use glVertexAttribIPointer() to set up the attribute pointer. Attributes you set up with the normal glVertexAttribPointer() function work only for float-based attribute types. They accept integer input, but the data will be converted to float when the shader accesses them.
In oglplus, you apparently have to use VertexArrayAttrib::IPointer() instead of VertexArrayAttrib::Pointer() if you want to work with integer attributes.

OpenGL Shaders - Structuring blocks of data of similar types

I'm having a bit of a structural problem with a shader of mine. Basically I want to be able to handle multiple lights of potentionally different types, but I'm unsure what the best way of implementing this would be. So far I've been using uniform blocks:
layout (std140) uniform LightSourceBlock
{
int type;
vec3 position;
vec4 color;
// Spotlights / Point Lights
float dist;
// Spotlights
vec3 direction;
float cutoffOuter;
float cutoffInner;
float attenuation;
} LightSources[12];
It works, but there are several problems with this:
A light can be one of 3 types (spotlight, point light, directional light), which require different attributes (Which aren't neccessarily required by all types)
Every light needs a sampler2DShadow (samplerCubeShadow for point lights), which can't be used in uniform blocks.
The way I'm doing it works, but surely there must be a better way of handling something like this? How is this usually done?