Comparing structs in GLSL - opengl

Is it safe to compare two structs of the same type by using the classic equality operator? I haven't found any information about this and there is no option to overload this operator in GLSL. So does GLSL compare two structs component-wise by default?
struct sith
{
int forceLevel;
vec3 saberColor;
};
...
sith vader = sith(100,vec3(1.0,0.0,0.0));
sith anakin = sith(100,vec3(1.0,0.0,0.0));
...
if (vader == anakin)
//is the force strong with this one?

When using the equality operators, two structures are equal if and only if all the fields are
component-wise equal, and two arrays are equal if and only if all the elements are element-wise equal
- GLSL 1.30 Specification, Page 46, Section 5.7 "Structure and Array Operations"

Related

Correct relational operator/function for comparison of vec3 values?

I'm trying to check if vec3 values have the same components.
int same = 0;
vec3 v1 = vec3(1.0f, 0.0f, 0.0f);
vec3 v2 = vec3(0.0f, 0.0f, 0.0f);
if (v1 == v2) // <- this part
{
same = 1;
}
Is == the correct relational operator for vec3 type?
If not, what can I use (operators and functions are also welcome) to compare vec3 values?
The GLSL 4.5 Specification, Section 5.9 states:
The equality operators equal (==), and not equal (!=) operate on all types [...]. They result in a scalar Boolean. [...] For vectors, matrices, structures, and arrays,
all components, members, or elements of one operand must equal the corresponding components,
members, or elements in the other operand for the operands to be considered equal.
To answer your question: Yes, the == operator compares weather two vectors have the same value in all components.

operator overloading VS template function

I want to write a program that multiplies two 2d arrays. Both arrays are instances of the template class( arrays can be int, float, double). Is it better to overload operators * and = , or to write a function that will multiply arrays? What are the advantages and disadvantages of operator overloading? Does overloading affect the performance of the program?
Overloading operators does not have any performance penalty. It translates to a regular function call. The advantage of operator overloading is only that it makes your code shorter. However, in case of array multiplication, I recommend to use a properly named function because there are at least two kinds of multiplication semantics for vectors - there is element-wise multiplication, and there is dot-product a.k.a. scalar multiplication. An overloaded operator* will leave the meaning obscure.

Need some clarification with the concept of vectors in direct3D11

I thought at first that vectors were just arrays that can store multiple values of the same type. But i think direct3d uses a different terminology when it comes to "vectors"
Lets say for example, we create a vector by using the function XMVectorSet()
XMVECTOR myvector;
myvector = XMVectorSet(0.0f, 0.0f, -0.5f, 0.0f);
What exactly did i store inside myvector? did i just store an array of floating point values?
C++'s "vectors" are indeed array-like storage containers.
You're right in that Direct3D is using a different meaning of the term "vectors": their more global mathematical meaning. These vectors are quantities that have direction and size.
Further reading:
https://en.wikipedia.org/wiki/Euclidean_vector
https://en.wikipedia.org/wiki/Column_vector
https://en.wikipedia.org/wiki/Vector_space
In general vectors in Direct3D are an ordered collection of 2 to 4 elements of the same floating-point or integer type. Conceptually they're similar to an array, but more like a structure. The elements are usually referred to by names like x, y, z and w rather than numbers. Depending on the context you may be able to use either C++ structure or an C++ array to represent a Direct3D vector.
However the XMVECTOR type specifically is an ordered collection of 4 elements that simultaneously contains both 32-bit floating-point and 32-bit unsigned integer types. Each element has the value of a floating-point number and an unsigned integer that share the same machine representation. So using your example, the variable myvector has simultaneously holds both the floating-point vector (0.0, 0.0, -0.5, 0.0f) and the unsigned integer vector (0, 0, 0xbf000000, 0).
(If we use the usual XYZW interpretation of the floating-point value of myvector then it would represent a vector of length 0.5 pointing in the direction of the negative Z axis. If we were to use an unusual RGBA interpretation of the unsigned integer value of myvector then it would represent a 100% transparent blue colour.)
Which value gets used depends on the function that the XMVECTOR object is used with. So for example the XMVectorAdd function treats its arguments as two floating point vectors, while XMVectorAndInt treats is argument as two unsigned integer vectors. Most operations that can be preformed with XMVECTOR objects use the floating-point values. The unsigned integer operands are usually used manipulate bits in the machine representation of the floating-points values.
XMVECTOR has an unspecified internal layout:
In the DirectXMath Library, to fully support portability and
optimization, XMVECTOR is, by design, an opaque type. The actual
implementation of XMVECTOR is platform dependent.
So it might be an array with four elements, or it might be a structure with .x, .y, .z and .w members. Or it might be something completely different.

Are conditional expressions in C++ always of bool type?

In C conditional-oriented operators evaluate to either 1 or 0 of type int (even if it does have dedicated _Bool type). Referring to C11 N1570 draft:
C11 §6.5.8/6 Relational operators
Each of the operators < (less than), > (greater than), <= (less than
or equal to), and >= (greater than or equal to) shall yield 1 if the
specified relation is true and 0 if it is false.107) The result has
type int.
C11 §6.5.9/3 Equality operators
The == (equal to) and != (not equal to) operators are analogous to the
relational operators except for their lower precedence.108) Each of
the operators yields 1 if the specified relation is true and 0 if it
is false. The result has type int. For any pair of operands, exactly
one of the relations is true.
C11 6.5.13/3 Logical AND operator
The && operator shall yield 1 if both of its operands compare unequal
to 0; otherwise, it yields 0. The result has type int.
C11 6.5.14/3 Logical OR operator
The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
As I checked C++ seems to be different in this matter, as in following example (see http://ideone.com/u3NxfW):
#include <iostream>
#include <typeinfo>
int main() {
double x = 10.0;
std::cout << typeid(x <= 10.0).name() << std::endl;
return 0;
}
outputs b, which as I guess indicates bool type. Does C++ guarantee that all of these operators always evaluate to bool type (in contrast to C)?
No, because of operator overloading. This has been mentioned before, but I can give the real life example of expression templates. The idea, generally, is to allow writing "lazy" expressions (that is, really, function objects or ASTs) with syntax that is very similar to the normal, eager use of logical operators. Typically, many other operators, in particular arithmetic operators are also, overloaded.
For instance, one design goal of Boost.Lambda was to simplify the use of algorithms:
std::string str;
// ...
std:.string::iterator firstA = std::find_if(str.begin(), str.end(), _1 == 'a' || _1 == 'A');
Previously, in "pure" C++98, it was generally necessary to write numerous named functions or function objects before many standard algorithms could be used effectively.
Since C++11, Boost.Lambda is not as useful any more since lambda expressions have been added to the core language. There are still numerous EDSLs (embedded domain-specific languages) where C++11 lambdas cannot replace expression templates though, e.g. you may want to generate SQL command strings directly from a C++ EDSL in a way similar to LINQ in .NET, but as a portable library solution. Another example: the VexCL library uses expression templates to generate GPU kernels.
This is probably the only legitimate use of non-bool return types for overloaded logical operators, but it's not generally considered esoteric.
Contrary to C, in C++, relational operators, equality operators and logical operators (logical AND, logical OR and logical negation) all yield a value of type bool.
For example:
(C++11, 5.9p1 Relational operators) "[...] The type of the result is bool."
EDIT: for the sake of completeness, all the operators listed above can be overloaded and thus the resulting type can be changed. See Arne Vogel answer for real life example.

OpenGL / GLSL - Uniform block data values incorrect

My shader has a uniform block as such:
layout (std140) uniform LightSourceBlock
{
vec3 test;
vec3 color;
} LightSources;
The data for this block is supposed to come from a buffer object which is created like so:
GLuint buffer;
glGenBuffers(1,&buffer);
GLfloat data[6] = {
0,0,0,
0,0,1
};
glBindBuffer(GL_UNIFORM_BUFFER,buffer);
glBufferData(GL_UNIFORM_BUFFER,sizeof(data),&data[0],GL_DYNAMIC_DRAW);
The buffer is linked to the uniform block before rendering:
unsigned int locLightSourceBlock = glGetUniformBlockIndex(program,"LightSourceBlock");
glUniformBlockBinding(program,locLightSourceBlock,8);
glBindBufferBase(GL_UNIFORM_BUFFER,8,buffer);
From my understanding this should be setting 'color' inside the block in the shader to (0,0,1), but the value I'm getting instead is (0,1,0).
If I remove the 'test' variable from the block and only bind the three floats (0,0,1) to the shader, it works as intended.
What's going on?
As you did specify layout (std140) for your UBO, you must obey the alginment rules defined there. That layout was first specified (in core) in the OpenGL 3.2 core spec, section 2.11.4 "Uniform Variables" in subsection "Standard Uniform Block Layout":
If the member is a scalar consuming N basic machine units, the base alignment is N.
If the member is a two- or four-component vector with components consuming N basic machine units, the base alignment is 2N or 4N,
respectively.
If the member is a three-component vector with components consuming N basic machine units, the base alignment is 4N.
If the member is an array of scalars or vectors, the base alignment and array stride are set to match the base alignment of a single array
element, according to rules (1), (2), and (3), and rounded up to the
base alignment of a vec4. The array may have padding at the end; the
base offset of the member following the array is rounded up to the
next multiple of the base alignment.
If the member is a column-major matrix with C columns and R rows, the matrix is stored identically to an array of C column vectors with
R components each, according to rule (4).
If the member is an array of S column-major matrices with C columns and R rows, the matrix is stored identically to a row of S C column
vectors with R components each, according to rule (4).
If the member is a row-major matrix with C columns and R rows, the matrix is stored identically to an array of R row vectors with C
components each, according to rule (4).
If the member is an array of S row-major matrices with C columns and R rows, the matrix is stored identically to a row of S R row
vectors with C components each, according to rule (4).
If the member is a structure, the base alignment of the structure is N, where N is the largest base alignment value of any of its
members, and rounded up to the base alignment of a vec4. The
individual members of this substructure are then assigned offsets by
applying this set of rules recursively, where the base offset of the
first member of the sub-structure is equal to the aligned offset of
the structure. The structure may have padding at the end; the base
offset of the member following the sub-structure is rounded up to the
next multiple of the base alignment of the structure.
If the member is an array of S structures, the S elements of the array are laid out in order, according to rule (9).
For your case, point 3 applies. So, you need to pad another float before the second vector begins.