For example, if I use vertex shader like the following:
#version 400 core
uniform mat4 projM;
uniform mat4 viewM;
uniform mat4 modelM;
in vec4 in_Position;
out vec4 pass_position_model;
void main(void) {
gl_Position = projM * viewM * modelM * in_Position;
pass_position_model = modelM * in_Position;
}
Will it do projM * viewM * modelM
matrix multiplication for each vertex, or it it smart enough to calculate if once and do not recalculate until uniform variables are changed?
If it isn't "smart enough", then is there a way to optimize it other than computing all uniform-dependent values on CPU and send them as uniform variables to GPU?
Also I'm interested in solutions that can be ported to OpenGL ES 2.0 later without problems.
A uniform is a global Shader variable declared with the "uniform" storage qualifier. These act as parameters that the user of a shader program can pass to that program. Their values are stored in a program object.
There are three types of variables in shaders: uniforms, attributes, and varyings: Uniforms are variables that have the same value for all vertices - lighting, fog, and shadow maps are examples of data that would be stored in uniforms. Uniforms can be accessed by both the vertex shader and the fragment shader.
gl_Position is a special variable that holds the position of the vertex in clip space. Since a vertex shader's main output is the position in clip space, it must always set gl_Position. This vertex shader just transforms each vertex position (by the VP matrix).
vec3 is a floating point vector with three components. It can be initialized by: Providing a scalar value for each component. Providing one scalar value. This value is used for all components.
So there is no general answer, as I understand. I did some tests on my hardware, though. I have 2 GPUs in my inventory, Intel HD Graphics 3000
and NVidia GeForce GT 555M
. I tested my program (the program itself is written in java/scala) with matrix multiplication in vertex shader, and then moved multiplication to the CPU program and tested again.
(sphereN - it's a continuously rotating sphere with 2*N^2 quads, drawn with glDrawElements(GL_QUADS,...) with 1 texture and without any lighting/other effects)
matrix multiplication in vertex shader:
intel:
sphere400: 57.17552887364208 fps
sphere40: 128.1394156842645 fps
nvidia:
sphere400: 134.9527665317139 fps
sphere40: 242.0135527589545 fps
matrix multiplication on cpu:
intel:
sphere400: 57.37234652897303 fps
sphere40: 128.2051282051282 fps
nvidia:
sphere400: 142.28799089356858 fps
sphere40: 247.1576866040534 fps
Tests show that multiplicating (uniform) matrices in vertex shader is bad idea, at least on this hardware. So in general one may not rely on corresponding GLSL compiler optimization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With