This might be a trivial question.
I am curious about how glsl would synchronize when accessing texture data via a fragment shader.
Say I have a code like below in a fragment shader.
void main() {
vec3 texCoord = in_texCoord;
vec4 out_voxel_intensity = texture(image, vec3(texCoord.x , texCoord.y, texCoord.z));
out_voxel = float(out_voxel_intensity) ;
if(out_voxel <= threshold)
{
out_voxel = 0.0;
return;
}
for(int i = -int(kernalSize); i <= int(kernalSize);++i)
for(int j = -int(kernalSize); j <= int(kernalSize); ++j)
for(int k = -int(kernalSize); k <= int(kernalSize); ++k)
{
float x_o = texCoord.x + i / (imageSize.x);
float y_o = texCoord.y + j / (imageSize.y);
float z_o = texCoord.z + k / (imageSize.z);
if(x_o < 0.0 || x_o > 1.0
|| y_o < 0. || y_o > 1.0
|| z_o < 0. || z_o > 1.0)
continue;
if(float(texture(image, vec3(x_o, y_o, z_o))) <= threshold)
{
out_voxel = 0.0;
return;
}
}
}
as the code above access not only the current texture coordinate, but the values around it with the specified kernel size, how glsl takes care that no other parallel process access the same texture coordinates.
W.r.t that question, does the code above performs efficiently in a fragment shader given it access neighboring texture data or using openCL better?
Thanks
Related
I want to iterate through an array of sampler2DShadow for a shadow map computation (multiple lights), and it looks like the sampler can be accessed only for a constant index. I only show the relevant code for clarity:
smooth in vec4 fShadowTexCoord[5];
uniform sampler2DShadow shadowMapTexSampler[5];
void main() {
for (uint i = 0u; i < 5u; i++) { // light 'i'
float shadowCoeff = 0.0f;
// this line does not work properly
vec2 scale = 2.0f / textureSize(shadowMapTexSampler[i], 0);
float bias = 0.006f;
for (int j = -1; j <= 1; j++)
for (int k = -1; k <= 1; k++)
shadowCoeff += texture(shadowMapTexSampler[i], vec3(fShadowTexCoord[i].xy + vec2(j, k) * scale, fShadowTexCoord[i].z - bias));
shadowCoeff /= 9.0f;
// ...........
}
}
The function 'texture' works as expected, but 'textureSize' function behaves like no texture is bound.
If I replace 'i' with a constant, it works fine, but I didn't found how to cast an 'uint' to a 'const uint' in GLSL.
sorry for the necro post, but this seems to be a limitation of GLSL prior to 4.60 or so?
I do something ugly like this:
#define PCF_LOOP(idx) \
else if (faceIdx == idx) \
{ \
for (int i=0; i<PCF_SAMPLES; i++) \
{ \
...
} \
}
if (false);
PCF_LOOP(0)
PCF_LOOP(1)
PCF_LOOP(2)
PCF_LOOP(3)
PCF_LOOP(4)
PCF_LOOP(5)
it's ugly and (probably) slow, but works even on ancient hw
I'm trying to implement a Fruchterman Reingold simulation using shaders. Before implementing the compute portion in a shader I wrote it in javascript. It works exactly as I expect, as seen here:
http://jaredmcqueen.github.io/gpgpu-force-direction/canvas_app.html
When implementing the compute portion in a shader, I get a stable structure that randomly drifts around the screen. I cannot figure out what repulsion / attraction forces are causing my graphs to float around so unpredictably:
http://jaredmcqueen.github.io/gpgpu-force-direction/gpgpu_app.html
the core of the physics are from the repulsion / attraction functions:
//fr(x) = (k*k)/x;
vec3 addRepulsion(vec3 self, vec3 neighbor){
vec3 diff = self - neighbor;
float x = length( diff );
float f = ( k * k ) / x;
return normalize(diff) * f;
}
//fa(x) = (x*x)/k;
vec3 addAttraction(vec3 self, vec3 neighbor){
vec3 diff = self - neighbor;
float x = length( diff );
float f = ( x * x ) / k;
return normalize(diff) * f;
}
Any insight as to why gpgpu, simulation based shaders would behave seemingly random would be greatly appreciated.
It doesn't seem random, construction stabilizes in seemingly right state and moves out in constant direction.
It looks like you apply force in shader and then update your model's position on CPU side and this global model position should stay constant either should have been updated by another value.
From what i've seen in code i recommend to eliminate floating point comprasions (compareNodePosition.w == -1.0 || 0.0) and continue operator. Please say if it helped. I haven't looked into algorithms logic yet.
It turns out I was iterating through the edges incorrectly. Here's my new edge iteration:
float idx = selfEdgeIndices.x;
float idy = selfEdgeIndices.y;
float idz = selfEdgeIndices.z;
float idw = selfEdgeIndices.w;
float start = idx * 4.0 + idy;
float end = idz * 4.0 + idw;
if(! ( idx == idz && idy == idw ) ){
float edgeIndex = 0.0;
for(float y = 0.0; y < edgesTexWidth; y++){
for(float x = 0.0; x < edgesTexWidth; x++){
vec2 ref = vec2( x + 0.5 , y + 0.5 ) / vec2(edgesTexWidth,edgesTexWidth);
vec4 pixel = texture2D(edgeData,ref);
if (edgeIndex >= start && edgeIndex < end){
nodePosition = getNeighbor(pixel.x);
nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
}
edgeIndex++;
if (edgeIndex >= start && edgeIndex < end){
nodePosition = getNeighbor(pixel.y);
nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
}
edgeIndex++;
if (edgeIndex >= start && edgeIndex < end){
nodePosition = getNeighbor(pixel.z);
nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
}
edgeIndex++;
if (edgeIndex >= start && edgeIndex < end){
nodePosition = getNeighbor(pixel.w);
nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
}
edgeIndex++;
}
}
}
I have an image2DArray in my compute shaders with 7 slices.
I can write in it with the function imageStore without problem and also display these textures.
My problem comes with the initialization, I try to initialize my textures but I can't. Indeed, I make a loop for the initialization :
for(int i=0; i<N; i++){
imageStore( outputTexture , ivec3(texel, i), vec4(0));
}
When N = 7, nothing is displayed but when N < 7 everything works well and my textures initialized.
Is someone can explain me why I can't initialize correctly my image2DArray ?
Edit :
What I test to see that : try to write in all slices of the texture and display it. It works fine but data from the previous frame stay if I don't initialize the texture. So, I initialize all pixels of the slices to 0 but nothing display anymore if N=7.
Some code :
#version 430 compatibility
layout(rgba8) coherent uniform image2DArray outputTexture;
...
void main(){
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
ivec2 outSize = imageSize( outputTexture ).xy;
if( texel.x >= outSize.x || texel.y >= outSize.y )
return;
initializeMeshSet( meshSet );
vec4 pWorld = texelFetch(gBuffer[0],texel,0);
pWorld /= pWorld.w;
vec4 nWorld = texelFetch(gBuffer[1],texel,0);
nWorld /= nWorld.w;
if( length(nWorld.xyz) < 0.1 ){
for(int i=0; i<4; i++){
imageStore( outputTexture , ivec3(texel, i), vec4(0));
}
return;
}
if(nbFrame == 0){
float value = treatment(texel, pWorld, nWorld.xyz, outSize.x);
imageStore( outputTexture, ivec3(texel, 0), vec4(vec3(value),1.0));
imageStore( outputTexture, ivec3(texel, 1), vec4(0.0,0.0,0.0, 1.0));
}
else if(nbFrame == 1){
float value = treatment2(texel, pWorld, nWorld.xyz, outSize.x);
vec3 previousValue = imageLoad(outputTexture, ivec3(texel, 1)).xyz * (nbFrame - 1);
value += previousValue;
value /= nbFrame;
imageStore( outputTexture, ivec3(texel, 1), vec4(vec3(value), 1.0));
}
}
I tried to implement something in glsl to do texture splatting, but the for loop is acting weird and gives different results for code that does exactly the same.
Code 1:
for(int i = 0; i < 5; ++i) {
if(i == 1) {
float fade = texture2D(alphaTextures[i], texCoord.st).r;
vec4 texCol = texture2D(textures[i], texCoord.ba);
texColor = mix(texColor, texCol, fade);
}
}
Code 2:
for(int i = 0; i < 6; ++i) {
if(i == 1) {
float fade = texture2D(alphaTextures[i], texCoord.st).r;
vec4 texCol = texture2D(textures[i], texCoord.ba);
texColor = mix(texColor, texCol, fade);
}
}
The if statement is just for testing purposes so that it should give the same result. The only difference is the loop condition. I really have no idea why only Code 1 gives the correct result. Here are two pictures:
Code1
Code2
The result should be like in picture 1.
According to this answer, you can't iterate over a sampler array. The index alphaTextures[i] is invalid, you can only use alphaTextures[1].
This changes in GLSL 4.00+ (OpenGL 4.0+), where you can have a variable index, but it cannot be from a shader input/derived value.
One reason could be that Graphic processors don't like branched texture fetches.
Try this instead:
for(int i = 0; i < 6; ++i) {
float fade = texture2D(alphaTextures[i], texCoord.st).r;
vec4 texCol = texture2D(textures[i], texCoord.ba);
if(i == 1) {
texColor = mix(texColor, texCol, fade);
}
}
(disclaimer) i am only guessing and this error is really weird.
I am trying to add shading/lighting to my terrain generator. But for some reason my output still looks blocky even after I calculate surface normals.
set<pair<int,int> >::const_iterator it;
for ( it = mRandomPoints.begin(); it != mRandomPoints.end(); ++it )
{
for ( int i = 0; i < GetXSize(); ++i )
{
for ( int j = 0; j < GetZSize(); ++j )
{
float pd = sqrt(pow((*it).first - i,2) + pow((*it).second - j,2))*2 / mCircleSize;
if(fabs(pd) <= 1.0)
{
mMap[i][j][2] += mCircleHeight/2 + cos(pd*3.14)*mCircleHeight/2; ;
}
}
}
}
/*
The three points being considered to compute normals are
(i,j)
(i+1,j)
(i, j+1)
*/
for ( int i = 0; i < GetXSize() -1 ; ++i )
{
for ( int j = 0; j < GetZSize() - 1; ++j )
{
float b[] = {mMap[i+1][j][0]-mMap[i][j][0], mMap[i+1][j][1]-mMap[i][j][1], mMap[i+1][j][2]-mMap[i][j][2] };
float c[] = {mMap[i][j+1][0]-mMap[i][j][0], mMap[i][j+1][1]-mMap[i][j][1], mMap[i][j+1][2]-mMap[i][j][2] };
float a[] = {b[1]*c[2] - b[2]*c[1], b[2]*c[0]-b[0]*c[2], b[0]*c[1]-b[1]*c[0]};
float Vnorm = sqrt(pow(a[0],2) + pow(a[1],2) + pow(a[2],2));
mNormalMap[i][j][0] = a[0]/Vnorm;
mNormalMap[i][j][1] = a[1]/Vnorm;
mNormalMap[i][j][2] = a[2]/Vnorm;
}
}
Then when drawing this I use the following
float*** normal = map->GetNormalMap();
for (int i = 0 ; i < map->GetXSize() - 1; ++i)
{
glBegin(GL_TRIANGLE_STRIP);
for (int j = 0; j < map->GetZSize() - 1; ++j)
{
glNormal3fv(normal[i][j]);
float color = 1 - (terrain[i][j][2]/height);
glColor3f(color,color, color);
glVertex3f(terrain[i][j][0], terrain[i][j][2], terrain[i][j][1]);
glVertex3f(terrain[i+1][j][0], terrain[i+1][j][2], terrain[i+1][j][1]);
glVertex3f(terrain[i][j+1][0], terrain[i][j+1][2], terrain[i][j+1][1]);
glVertex3f(terrain[i+1][j+1][0], terrain[i+1][j+1][2], terrain[i+1][j+1][1]);
}
glEnd();
}
EDIT: Initialization Code
glFrontFace(GL_CCW);
glCullFace(GL_FRONT); // glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
glMatrixMode(GL_PROJECTION);
Am I calculating the Normals Properly?
In addition to what Bovinedragon suggested, namely glShadeModel(GL_SMOOTH);, you should probably use per-vertex normals. This means that each glVertex3f would be preceded by a glNormal3fv call, which would define the average normal of all adjacent faces. To obtain it, you can simply add up these neighbouring normal vectors and normalize the result.
Reference this question: Techniques to smooth face edges in OpenGL
Have you set glShadeModel to GL_SMOOTH?
See: http://www.khronos.org/opengles/documentation/opengles1_0/html/glShadeModel.html
This settings also effects vertex colors in addition to lighting. You seem to say it was blocky even before lighting which makes me think this is the issue.