Dark Bit Factory & Gravity
GENERAL => Challenges & Competitions => Topic started by: Jim on May 11, 2008
-
Here's my entry - my first real go at glsl shaders! It has perlin noise via a 3D texture, and a 1d texture for the marble and wood. It also has per-pixel specular lighting. Hope it runs on everyone's kit because debugging glsl isn't that much fun :) I have an 8600GT.
Jim
-
Very good...
Runs fine here XPSP2
Nvidea quadro nvs 110m
Cheers eNeRGy
-
On ati x1650 cards you get the objects but no textures, basically the shapes are there but they are grey.
-
It looks great on the screenshot but doesn't even start on my Ati Radeon 9600 Pro. I just click on it and it does nothing. It doesn't need any d3dx dll or anything else, does it?
-
It needs d3dx, an oldish one, but it would tell you about that.
The ATI problem is that it doesn't like the pixel shader - how is anyone supposed to debug this?!
I'll have to make a debug version...
Jim
PS. Here are my shader programs if anyone has any ideas.
//setup for per-pixel lighting
const char *Spider::vsh=
"varying vec4 t;"\
"varying vec4 u;"\
"varying vec3 v;"\
"varying vec4 diffuse, ambient;"\
"varying vec3 normal,lightDir,halfVector;"\
"void main() {"\
"normal = normalize(gl_NormalMatrix * gl_Normal);"\
"lightDir = normalize(vec3(gl_LightSource[0].position));"\
"halfVector = normalize(gl_LightSource[0].halfVector.xyz);"\
"diffuse = gl_LightSource[0].diffuse;"\
"ambient = gl_LightSource[0].ambient;"\
"gl_TexCoord[0] = gl_MultiTexCoord0;"\
"u = gl_Vertex;"\
"v = gl_Vertex.xyz;"\
"gl_Position = t = ftransform();"\
"}";
//marble
const char *Spider::fsh_marble=
"varying vec4 u;"\
"varying vec3 v;"\
"uniform sampler1D tex2;"\
"uniform sampler3D tex3;"\
"uniform float scale;"\
"varying vec4 diffuse,ambient;"\
"varying vec3 normal,lightDir,halfVector;"\
"void main() {"\
"vec3 r = v*scale;"\
"vec3 n0 = texture3D(tex3,r)*0.9;"\
"vec3 n1 = texture3D(tex3,r*2)*0.5;"\
"vec3 n2 = texture3D(tex3,r*4)*0.2;"\
"vec3 n3 = texture3D(tex3,r*8)*0.1;"\
"vec3 q = cos(r+n0+n1+n2+n3);"\
"vec3 n,halfV;"\
"float NdotL,NdotHV;"\
"vec4 color = ambient;"\
"n = normalize(normal);"\
"NdotL = max(dot(n,lightDir),0.0);"\
"if (NdotL > 0.0) {"\
"color += diffuse * NdotL;"\
"halfV = normalize(halfVector);"\
"NdotHV = max(dot(n,halfV),0.0);"\
"color += "\
"gl_LightSource[0].specular * "\
"pow(NdotHV, 10.0);}"\
"gl_FragColor = texture1D(tex2,q.x)*color;"\
"}";
//wood
const char *Spider::fsh_wood=
"varying vec4 u;"\
"varying vec3 v;"\
"uniform sampler1D tex2;"\
"uniform sampler3D tex3;"\
"uniform float scale;"\
"varying vec4 diffuse,ambient;"\
"varying vec3 normal,lightDir,halfVector;"\
"void main() {"\
"vec3 r = v*scale;"\
"vec3 n0 = texture3D(tex3,r)*0.9;"\
"vec3 n1 = texture3D(tex3,r*2)*0.5;"\
"vec3 n2 = texture3D(tex3,r*4)*0.2;"\
"vec3 n3 = texture3D(tex3,r*8)*0.1;"\
"vec3 g = (n0+n1+n2+n3)*20;"\
"g = fract(g);"\
"r.xy*=500;"\
"r.z*=200;"\
"n0 = texture3D(tex3,r)*0.5;"\
"n1 = texture3D(tex3,r*2)*0.3;"\
"n2 = texture3D(tex3,r*4)*0.15;"\
"n3 = texture3D(tex3,r*8)*0.05;"\
"vec3 h=n0+n1+n2+n3+0.5;"\
"h=floor(h)*0.1+1;"\
"vec3 n,halfV;"\
"float NdotL,NdotHV;"\
"vec4 color = ambient;"\
"n = normalize(normal);"\
"NdotL = max(dot(n,lightDir),0.0);"\
"if (NdotL > 0.0) {"\
"color += diffuse * NdotL;"\
"halfV = normalize(halfVector);"\
"NdotHV = max(dot(n,halfV),0.0);"\
"color += "\
"gl_LightSource[0].specular * "\
"pow(NdotHV, 10.0);}"\
"gl_FragColor = texture1D(tex2,g.x)*vec4(h,1)*color;"\
"}";
Thanks to lighthouse3d.com (http://lighthouse3d.com) for the lighting tutorials!
-
Hi Jim,
a texture-lookup returns a vec4 (rgba). when you assign it to a vec3, the ati-shader-compiler wets its' pants while the nvidia-compiler drops the 4th component silently.
Just add a cast:
vec3 n0 = vec3(texture3D(tex3,r)*0.9);
vec3 n1 = vec3(texture3D(tex3,r*2)*0.5);
vec3 n2 = vec3(texture3D(tex3,r*4)*0.2);
vec3 n3 = vec3(texture3D(tex3,r*8)*0.1);
-
It runs here just like the screenies but at a very low frame rate maybe 4 fps
-
Nice one Jim :)
-
Thanks to Hellfire (cheers mate!), I've udpated the texture3D calls to use vec3 and replaced the zip file on the OP.
I've also added a MessageBox to the compiler if it comes up with an error.
Jim
-
Now works perfectly on my Radeon 9600.
I especially like the left material.
But i'm wondering why you need d3dx when using glsl ???
-
Thanks for testing!
The code sits in my framework which has an image loader in it based on d3dx. I should make it more modular so I can take chunks out - there's a whole sprite/font engine in there too!
Jim
-
Works like a charm here Jim, congrats for your first shader program!
-
If no d3dx9_32.dll is found, the application exits without further information.
Just so you know.
-
Good one, Jim!
-
d3dx9_32.dll is ancient history (Dec 06?), so anyone with a well maintained Windows box should have it. If not go here... http://www.microsoft.com/downloads/details.aspx?FamilyID=2da43d38-db71-4c1b-bc6a-9b6652cd92a3&DisplayLang=en (http://www.microsoft.com/downloads/details.aspx?FamilyID=2da43d38-db71-4c1b-bc6a-9b6652cd92a3&DisplayLang=en)...and it will very intelligently work out what you do and don't have, DirectX-wise, and just download a few Mb of updates.
Sorry about the requirement, but any up-to-date games machine will have all these dlls.
Thanks again to Hellfire for helping me fix my PS and thanks to everyone else for the great comments!
Jim
-
Algorithm for the left hand texture. It's just a 1d texture (a scanline of 1024 pixels)
unsigned int blend(unsigned int c0, unsigned int c1)
{
unsigned int r0,g0,b0,a0;
unsigned int r1,g1,b1,a1;
unsigned int r,g,b,a;
a0 = (c0>>24)&0xff;
r0 = (c0>>16)&0xff;
g0 = (c0>>8)&0xff;
b0 = (c0>>0)&0xff;
a1 = (c1>>24)&0xff;
r1 = (c1>>16)&0xff;
g1 = (c1>>8)&0xff;
b1 = (c1>>0)&0xff;
a = (a0+a1)>>1;
r = (r0+r1)>>1;
g = (g0+g1)>>1;
b = (b0+b1)>>1;
return (a<<24)|(r<<16)|(g<<8)|b;
}
void make_marble1d(void)
{
unsigned int marble[1024];
for (int x = 0; x < 1024; x++)
marble[x] = (x/64)*7*0x00010101+0xff7f7f7f;
for (int x = 100; x < 200; x++)
{
double p=0.5*(1.0+sin((x-100.0)*M_PI/100.0));
unsigned int c = 0xff7f7f7f+(unsigned int)(p*0x7f);
marble[x] = blend(marble[x],c);
}
for (int x = 500; x < 700; x++)
{
double p=0.5*(1.0+sin((x-500.0)*M_PI/200.0));
unsigned int c = 0xff7f3f3f+(unsigned int)(p*0x7f);
marble[x] = blend(marble[x],c);
}
for (int x = 600; x < 800; x++)
{
double p=0.5*(1.0+sin((x-600.0)*M_PI/200.0));
unsigned int c = 0xff3f3f3f+((unsigned int)(p*0x5f)<<16);
marble[x] = blend(marble[x],c);
}
for (int x = 900; x < 950; x++)
{
marble[x] = 0xff000000;
}
...
So, it's a 50% grey to 100% gray gradient over 1024 pixels with a pinky red bit added at 100-200pixels, a blue bit between 500-700, a red bit between 600 and 800 and a black bit between 900 and 950. The bilinear filtering deals with the discontinuities in this texture, which is cool.
The really cool bit is in the 3D texture where dozens of blends you'd need to do this on the CPU are replaced by a trilinear filter. Awesome stuff!
Jim
-
It is working like a charm here now :)