I am writing a shader and I would like to pass a vec3 along to the input.
however everything I could find is always passing either a single float a vec4, texture or number range. Is it possible to send a vanilla vec3 along to a shader in unity?
Properties
{
offset ("formula Offset", Vector) = (0, 0, 0)
}
Doesn't seem to work as I hoped.
To get it to compile I have been doing this:
Properties
{
offset ("formula Offset", Vector) = (0, 0, 0, 0)
}
// offset.xyz //Extract relevant data from vector
this just doesn't feel right. Is there a better way?
Looks like when you mark a property as Vector it has to have 4 components. Even the documentation says: "Vector properties are displayed as four number fields."
This really isn't as bad as it looks, just set the last components to zero.
Note that annoyingly the matching variable is NOT "vector", it's "float4".
Full list:
https://stackoverflow.com/a/37749687/294884
Related
I want to transform data from geometry shaders to feedback buffer,so I set the names of variables like this:
char *Varying[] = {"lColor","lPos","gl_NextBuffer","rColor","rPos"};
then bind two buffers vbos[2] to transformFeedback object Tfb,vbos[0] to bind point 0, and vbos[1] to bind point 2:
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbos[0]);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, vbos[1]);
and set stream number like this:
layout(stream=0) out vec4 lColor;
layout(stream=0) out vec4 lPos;
layout(stream = 2) out rVert
{
vec4 rColor;
vec4 rPos;
};
So I thought lColor and lPos are transformed to vbos[0],rColor and rPos are transformed to vbos[1],but nothing came out,unless I change vbos[1] to bind point 1,and stream number of rvert to 1.
I think there is three variables about indexes for binding geometry shader output and feedback buffers,first is index in glBindBufferBase(target,index,id),second is sequences of names in glTransformFeedbackVaryings(program,count,names,buffermode),third is stream number of variables in geometry shader,what is the relationship of these three parameters?
And I found that no matter what parameters I set the glDrawTransformFeedbackStream ,picture didn't change,Why?
The geometry shader layout qualifier stream has no direct relationship to the TF buffer binding index assignment. There is one caveat here: variables from two different streams can't be assigned to the same buffer binding index. But aside from that, the two have no relationship.
In geometry shader transform feedback, streams are written independently of each other. When you output a vertex/primitive, you say which stream the GS invocation is writing. Only the output variables assigned to that stream are written, and the system keeps track of how much stuff has been written to each stream.
But how the output variables map to feedback buffers is entirely separate (aside from the aforementioned caveat).
In your example, glTransformFeedbackVaryings with {"lColor","lPos","gl_NextBuffer","rColor","rPos"} does the following. It starts with buffer index 0. It assigns lColor and lPos to buffer index 0. gl_NextBuffer causes the system to increment the value of the current buffer index. That value is 0, so incrementing it makes it 1. It then assigns rColor and rPos to buffer 1.
That's why your code doesn't work.
You can skip buffer indices in the TF buffer bindings. To do that, you have to use gl_NextBuffer twice, since each use increments the current buffer index.
Or if your GL version is high enough, you can just assign the buffer bindings and offsets directly in your shader:
layout(stream=0, xfb_offset = 0, xfb_buffer = 0) out vec4 lColor;
layout(stream=0, xfb_offset = 16, xfb_buffer = 0) out vec4 lPos;
layout(stream = 2, xfb_offset = 0, xfb_buffer = 2) out rVert
{
vec4 rColor;
vec4 rPos;
};
I'm trying my hand at shader storage buffer objects (aka Buffer Blocks) and there are a couple of things I don't fully grasp. What I'm trying to do is to store the (simplified) data of an indeterminate number of lights n in them, so my shader can iterate through them and perform calculations.
Let me start by saying that I get the correct results, and no errors from OpenGL. However, it bothers me not to know why it is working.
So, in my shader, I got the following:
struct PointLight {
vec3 pos;
float intensity;
};
layout (std430, binding = 0) buffer PointLights {
PointLight pointLights[];
};
void main() {
PointLight light;
for (int i = 0; i < pointLights.length(); i++) {
light = pointLights[i];
// etc
}
}
and in my application:
struct PointLightData {
glm::vec3 pos;
float intensity;
};
class PointLight {
// ...
PointLightData data;
// ...
};
std::vector<PointLight*> pointLights;
glGenBuffers(1, &BBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, BBO);
glNamedBufferStorage(BBO, n * sizeof(PointLightData), NULL, GL_DYNAMIC_STORAGE_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, BBO);
...
for (unsigned int i = 0; i < pointLights.size(); i++) {
glNamedBufferSubData(BBO, i * sizeof(PointLightData), sizeof(PointLightData), &(pointLights[i]->data));
}
In this last loop I'm storing a PointLightData struct with an offset equal to its size times the number of them I've already stored (so offset 0 for the first one).
So, as I said, everything seems correct. Binding points are correctly set to the zeroeth, I have enough memory allocated for my objects, etc. The graphical results are OK.
Now to my questions. I am using std430 as the layout - in fact, if I change it to std140 as I originally did it breaks. Why is that? My hypothesis is that the layout generated by std430 for the shader's PointLights buffer block happily matches that generated by the compiler for my application's PointLightData struct (as you can see in that loop I'm blindingly storing one after the other). Do you think that's the case?
Now, assuming I'm correct in that assumption, the obvious solution would be to do the mapping for the sizes and offsets myself, querying opengl with glGetUniformIndices and glGetActiveUniformsiv (the latter called with GL_UNIFORM_SIZE and GL_UNIFORM_OFFSET), but I got the sneaking suspicion that these two guys only work with Uniform Blocks and not Buffer Blocks like I'm trying to do. At least, when I do the following OpenGL throws a tantrum, gives me back a 1281 error and returns a very weird number as the indices (something like 3432898282 or whatever):
const char * names[2] = {
"pos", "intensity"
};
GLuint indices[2];
GLint size[2];
GLint offset[2];
glGetUniformIndices(shaderProgram->id, 2, names, indices);
glGetActiveUniformsiv(shaderProgram->id, 2, indices, GL_UNIFORM_SIZE, size);
glGetActiveUniformsiv(shaderProgram->id, 2, indices, GL_UNIFORM_OFFSET, offset);
Am I correct in saying that glGetUniformIndices and glGetActiveUniformsiv do not apply to buffer blocks?
If they do not, or the fact that it's working is like I imagine just a coincidence, how could I do the mapping manually? I checked appendix H of the programming guide and the wording for array of structures is somewhat confusing. If I can't query OpenGL for sizes/offsets for what I'm tryind to do, I guess I could compute them manually (cumbersome as it is) but I'd appreciate some help in there, too.
I'm trying to test colour values and change them if they're greater than 0.5.
I started out with this test which didn't compile:
if(colourIn.b > 0.5){
colourIn.b=0.0;
}
I read through some post on here and found this post which explains relational operators only work on scalar integer and scalar floating-point expressions.
So after finding out a good way to efficiently test frag values and using the built in functions, changed it to:
float mixValue = clamp(ceil(colourIn.b * 2.0) - 1.0, 0.0, 1.0);
if(greaterThan(colourIn.b,0.5)){
colourIn.b = mix(colourIn.b, 0.0, mixValue);}
Unfortunately it still doesn't compile; it gives the following errors:
ERROR: 0:15 error(202) No matching overloaded function found greaterThan
ERROR: 0:16 error(164) 1-value required assigned "colourIn" (can't modify an input)
ERROR: 0:15 error(179) Boolean expression expected
For this I get that the greatThan function is being used wrong? (I can't find an example in similar circumstances) and that the colourIn value cannot be changed?
I may be wrong... Please help me figure this out.
Basically, I want to change any pixels with Blue values greater than 0.5 to white (0.0).
Yes, it is true that relational operators only work on scalars... what on Earth is colourIn declared as (bvec)? Considering boolean colors do not make a lot of sense, usually colourIn.b would be a scalar component from a vecN or ivecN type. Please include the actual body of the shader you are trying to compile.
Additionally, greaterThan (...) does not work on scalar types, only vector. What it returns is a boolean vector containing the result of the test v1 > v2 for each component in v1 and v2.
So for instance consider the following pseudo-code,
vec3 v1 = vec3 (1,2,3);
vec3 v2 = vec3 (3,2,1);
bvec3 gt = greaterThan (v1, v2);
Then the boolean vector gt would have the following form:
gt.x = false;
gt.y = false;
gt.z = true;
However, the biggest problem you have is you are trying to modify an input value. You cannot do this, fragment shader inputs are interpolated from vertex transform (vertex shader, geometry shader, tessellation shader) outputs during rasterization and are read-only. Vertex shader inputs are from your vertex buffer and are also read-only. The only thing shaders are capable of doing is computing the output for the next stage in the pipeline.
In a fragment shader, the next stage would be blending for final pixel output. In a vertex shader it would be tessellation (GL4+) and primitive assembly (geometry shader) and rasterization (fragment shader).
I have a GLSL shader that reads from one of the channels (e.g. R) of an input texture and then writes to the same channel in an output texture. This channel has to be selected by the user.
What I can think of right now is to just use an int uniform and tons of if-statements:
uniform sampler2D uTexture;
uniform int uChannelId;
varying vec2 vUv;
void main() {
//read in data from texture
vec4 t = texture2D(uTexture, vUv);
float data;
if (uChannelId == 0) {
data = t.r;
} else if (uChannelId == 1) {
data = t.g;
} else if (uChannelId == 2) {
data = t.b;
} else {
data = t.a;
}
//process the data...
float result = data * 2; //for example
//write out
if (uChannelId == 0) {
gl_FragColor = vec4(result, t.g, t.b, t.a);
} else if (uChannelId == 1) {
gl_FragColor = vec4(t.r, result, t.b, t.a);
} else if (uChannelId == 2) {
gl_FragColor = vec4(t.r, t.g, result, t.a);
} else {
gl_FragColor = vec4(t.r, t.g, t.b, result);
}
}
Is there any way of doing something like a dictionary access such as t[uChannelId]?
Or perhaps I should have 4 different versions of the same shader, each of which processes a different channel, so that I can avoid all the if-statements?
What is the best way to do this?
EDIT: To be more specific, I am using WebGL (Three.js)
There is such a way, and it is as simple as you actually wrote it in the question. Just use t[channelId]. To quote the GLSL Spec (This is from Version 3.30, Section 5.5, but applies to other versions as well):
Array subscripting syntax can also be applied to vectors to provide numeric indexing. So in
vec4 pos;
pos[2] refers to the third element of pos and is equivalent to pos.z. This allows variable indexing into a
vector, as well as a generic way of accessing components. Any integer expression can be used as the
subscript. The first component is at index zero. Reading from or writing to a vector using a constant
integral expression with a value that is negative or greater than or equal to the size of the vector is illegal.
When indexing with non-constant expressions, behavior is undefined if the index is negative, or greater
than or equal to the size of the vector.
Note that for the first part of your code, you use this to access a specific channel of a texture. You could also use the ARB_texture_swizzle functionality. In that case, you would just use a fxied channel, say r, for access in the shader and what swizzle the actual texture channels so that wahtever channel you want to access becomes r.
Update: as the target platform turned out to be webgl, these suggestions are not available. However, a simple solution would be to use a vec4 uniform in place of uChannelID which is 1.0 for the selected component and 0.0 for all others. Say this variable is called uChannelSel. You could use data=dot(t, uChannelSel) in the first part and gl_FragColor=(vec4(1.0)-uChannelSel) * t + uChannelSel*result for the second part.
as i'm sure you know, branching can be expensive in shaders. however, it sounds like it'll always be the same channel in a pass (yes?), so you might maintain enough cohesion to see good performance.
it's been a good while since i've used GLSL, but if you're using a newer version, maybe you could do some bitwise shifting (<< or >>) magic? you would read the texture into int instead of vec4, then shift it a number of bits depending on which channel you want to read.
My goal was to color the vertexes according to their order
EDIT: long time goal: access to preceding and following vertexes to simulate gravity behavior
i've used following code
#version 120
#extension GL_EXT_geometry_shader4 : enable
void main( void ) {
for( int i = 0 ; i < gl_VerticesIn ; i++ ) {
gl_FrontColor = vec4(float(i)/float(gl_VerticesIn),0.0,0.0,1.0);
gl_Position = gl_PositionIn[i];
EmitVertex();
}
}
but all vertexes are drawn black, it seem that i is always evaluated as 0, am i missing something or doing it wrong?
EDIT: figured the meta-problem out: how to feed all me model geometry into single geometry shader call, so the mainloop iterates over all the vertexes, not for every triangle.
You don't let a single geometry shader invocation iterate over all your vertexes, it is called for every original primitive (point, line, triangle, ...).
The solution is much easier: In the vertex shader (that is actually called for every vertex) you can read the special variable gl_VertexID, which contains the vertex's index. That index is either just a counter incremented for every vertex (if using glDrawArrays) and reset by every draw call, or the index from the index array (if using glDrawElements).
EDIT: Regarding the long time goal. Not directly but you might use a texture buffer for that. This basically enables you to get direct linear array-access to a buffer object (in your case the vertex buffer) which you can then just index with this vertex index. But there might also be other ways to accomplish that, which may suffice for another question.