Hi there. I am a GLSL newbie and I’m building my first serious project- a GPU-driven particle system using multiple FBOs to do physics processing and some other stuff.
I have had all of it working for nearly two weeks now… on nVidia hardware. But I’m having massive problems with HD-series Radeons.
Problems:
- Originally, I wanted to just use GL_POINTS and point-sprites.
This worked just fine on nVidia, but on ATi hardware, it seems to bork. The texture coordinates keep getting lost somehow.
Reading a bit on here, it appears that that this is a problem people are familiar with, so I was hoping maybe somebody knows what fixed-function stuff or GLSL I need to have set up before I submit my display list to the fragment shader to actually have it work as planned, or some magic combination of things I need to do within the vertex shader to pass the correct data to the fragment shader.
- The second problem’s more embarrassing, and I hope people don’t think too badly of me for having this problem, but I am a newbie in a lot of ways, and this problem turned out to be a gotcha.
I wrote an alternative workaround to just use quads instead, and billboard them in the final vertex shader, but I can’t seem to get the final rotation to billboard it right. I’ve read a lot of tutorials and looked at a lot of source, and it’s still not working, the matrix I supply doesn’t result in the right behaviors.
Anyhow, I apologize for the wall of text, but I wanted to make sure people understand what I’m trying to do, and where it’s going wrong. Here’s the full source of the vertex shader, both the point version and the quad version. The rest of it has been repeatedly verified to be operating properly- particle birth, death, motion simulation, etc. is all performed elsewhere in the code.
Point version, final vertex shader as of October 22, 2009. Confirmed working properly on my hardware (nVidia 7800GS) and on other nVidia GPUs, but does not pass working texture coordinates to ATi HD:
uniform sampler2D posTex;
uniform sampler2D dragTex;
uniform vec3 camPos;
varying vec2 losPos;
varying vec2 offset;
uniform float shaderTime;
varying float timePercent;
const float mapSize = ]] .. FloatStr(MaxSizeX) .. [[;
const float dScale = 1000000.0;
void main(void)
{
#extension GL_ARB_pointsize : enable
vec2 texCoord = gl_Vertex.xy;
offset = texCoord;
vec4 posData = vec4(texture2D(posTex, texCoord)); // Get Color Data from sectors
vec4 timeData = vec4(texture2D(dragTex, texCoord)); // get time data
timePercent = ((shaderTime / dScale) - timeData.b) / (timeData.g - timeData.b);
if (posData.r > 0.5)
{
posData.r = float((posData.r - 0.5) * (dScale * -1.0));
} else {
posData.r = float(posData.r * dScale);
}
if (posData.g > 0.5)
{
posData.g = float((posData.g - 0.5) * (dScale * -1.0));
} else {
posData.g = float(posData.g * dScale);
}
if (posData.b > 0.5)
{
posData.b = float((posData.b - 0.5) * (dScale * -1.0));
} else {
posData.b = float(posData.b * dScale);
}
float size = float(posData.w * dScale);
gl_Vertex.x = posData.r;
gl_Vertex.y = posData.g;
gl_Vertex.z = posData.b;
float myLength = distance(gl_Vertex.xyz, camPos.xyz);
gl_PointSize = float((size * 1e4 / myLength) / 2.0);
if (gl_PointSize > 256.0 || gl_PointSize < 1.0)//SAFEGUARD CODE
{
gl_Vertex.xyz = vec3(-100000.0,100000.0,-100000.0);
}
gl_Position = ftransform();
gl_FrontColor.xy = gl_Vertex.xy;
losPos = vec2(gl_Vertex.x/mapSize,gl_Vertex.z/mapSize);
if (losPos.x < 0.0)
{
losPos.x = 0.01;
}
if (losPos.x < 0.0)
{
losPos.x = 0.01;
}
if (losPos.y > 1.0)
{
losPos.y = 0.99;
}
if (losPos.y > 1.0)
{
losPos.y = 0.99;
}
}
Quad version, with a display list of GL_QUADS in the XY plane, draws nothing at all on my hardware (but the shader compiles, and it is using the same FBO / GLSL setup to get to this point, which I have confirmed working on ATi):
uniform sampler2D posTex;
uniform sampler2D dragTex;
uniform vec3 camPos;
varying vec2 losPos;
varying vec2 offset;
uniform float shaderTime;
varying float timePercent;
const float mapSize = ]] .. FloatStr(MaxSizeX) .. [[;
const float dScale = 1000000.0;
void main(void)
{
offset = gl_MultiTexCoord1.xy;
gl_TexCoord[0].st = gl_Vertex.xy;
vec4 posData = vec4(texture2D(posTex, offset)); // Get Color Data from sectors
vec4 timeData = vec4(texture2D(dragTex, offset)); // get time data
timePercent = ((shaderTime / dScale) - timeData.b) / (timeData.g - timeData.b);
if (posData.r > 0.5)
{
posData.r = float((posData.r - 0.5) * (dScale * -1.0));
} else {
posData.r = float(posData.r * dScale);
}
if (posData.g > 0.5)
{
posData.g = float((posData.g - 0.5) * (dScale * -1.0));
} else {
posData.g = float(posData.g * dScale);
}
if (posData.b > 0.5)
{
posData.b = float((posData.b - 0.5) * (dScale * -1.0));
} else {
posData.b = float(posData.b * dScale);
}
float size = float(posData.w * dScale);
float myLength = distance(gl_Vertex.xyz, camPos.xyz);
float finalSize = float((size * 1e4 / myLength) / 2.0);
gl_Position = vec4(posData.xyz,1.0);
// offset vertex from center of the polygon
gl_Vertex *= gl_Vertex * finalSize;
// end
gl_Position = gl_ProjectionMatrix * gl_Vertex;
losPos = vec2(gl_Vertex.x/mapSize,gl_Vertex.z/mapSize);
if (losPos.x < 0.0)
{
losPos.x = 0.01;
}
if (losPos.x < 0.0)
{
losPos.x = 0.01;
}
if (losPos.y > 1.0)
{
losPos.y = 0.99;
}
if (losPos.y > 1.0)
{
losPos.y = 0.99;
}
}
Anyhow, I have posted here as a last resort, hoping somebody can help me out. I know that billboards are considered “simple”, but once I moved to GLSL from fixed-function, I am in over my head.