Per Pixel Lighting
Hey,
I''m playing around with per pixel lighting through dot3 bump mapping, and I''d like to know, how to make specular lighting (like flashlights and pointlights). I can''t seem to figure it out, because the lighting is determinated by the vertices. On a quad with only 4 vertices it can''t be done... Am I right?
My second question is:
Is there another way to do per pixel lighting, that also does flashlights and so on... If yes, how is it done???
quote:Original post by OleKaiwalker
My second question is:
Is there another way to do per pixel lighting, that also does flashlights and so on... If yes, how is it done???
yes, it''s called arb_fragment_program or pixel shader. nvidia has some docs about that
Specular pixel lighting without ARB_fragment_program is quite difficult and slow. But is is possible. The problem here is the power-operation with the shininess. You can easily do dot3 operation in texture environments but no power operation. You have to multiply the dot-result until you reached the shininess. Using ARB_fragment_program can do that in only one pass but requires a new graphic card (GeForceFX, Radeon 9500 or newer).
Here my implementation of bump mapping with specular lighting using 4 texture units, maybe it might help you. (notice that only the specular power operation takes 5 passes when the shininess is 32!!)
VP_Pass1:
!!ARBvp1.0
# Vertex Program vor Diffuse & Specular Bump Mapping
# ARB2 Profile Pass 1
ATTRIB Position = vertex.position;
ATTRIB Normal = vertex.normal;
ATTRIB STangent = vertex.attrib[6];
ATTRIB TTangent = vertex.attrib[7];
ATTRIB TexCoord0 = vertex.texcoord[0];
OUTPUT oPosition = result.position;
OUTPUT oTexCoord0 = result.texcoord[0];
OUTPUT oTexCoord1 = result.texcoord[1];
OUTPUT oTexCoord2 = result.texcoord[2];
PARAM mview[] = { state.matrix.mvp };
PARAM light = state.light[0].position;
PARAM view = program.env[0];
TEMP LightVecObj; # Light Vector in Object Space
TEMP ViewVecObj; # View Vector in Object Space
TEMP H; # Half Vector
TEMP lng;
DP4 oPosition.x, mview[0], Position;
DP4 oPosition.y, mview[1], Position;
DP4 oPosition.z, mview[2], Position;
DP4 oPosition.w, mview[3], Position;
ADD LightVecObj, -Position, light;
ADD ViewVecObj, -Position, view;
DP3 lng, LightVecObj, LightVecObj;
RSQ lng, lng.x;
MUL LightVecObj, lng, LightVecObj;
DP3 lng, ViewVecObj, ViewVecObj;
RSQ lng, lng.x;
MUL ViewVecObj, lng, ViewVecObj;
ADD H, LightVecObj, ViewVecObj;
DP3 oTexCoord0.x, STangent, LightVecObj; #H;
DP3 oTexCoord0.y, TTangent, LightVecObj; #H;
DP3 oTexCoord0.z, Normal, LightVecObj; #H;
DP3 oTexCoord1.x, STangent, ViewVecObj; #H;
DP3 oTexCoord1.y, TTangent, ViewVecObj; #H;
DP3 oTexCoord1.z, Normal, ViewVecObj; #H;
MOV oTexCoord2, TexCoord0;
END
VP_Pass2:
!!ARBvp1.0
# Vertex Program vor Diffuse & Specular Bump Mapping
# ARB2 Profile Pass 2
ATTRIB Position = vertex.position;
ATTRIB Normal = vertex.normal;
ATTRIB STangent = vertex.attrib[6];
ATTRIB TTangent = vertex.attrib[7];
ATTRIB TexCoord0 = vertex.texcoord[0];
ATTRIB Color = vertex.color;
OUTPUT oPosition = result.position;
OUTPUT oTexCoord0 = result.texcoord[0];
OUTPUT oTexCoord1 = result.texcoord[1];
OUTPUT oTexCoord2 = result.texcoord[2];
OUTPUT oColor = result.color;
PARAM mview[] = { state.matrix.mvp };
PARAM light = state.light[0].position;
TEMP LightVecObj; # Light Vector in Object Space
DP4 oPosition.x, mview[0], Position;
DP4 oPosition.y, mview[1], Position;
DP4 oPosition.z, mview[2], Position;
DP4 oPosition.w, mview[3], Position;
ADD LightVecObj, -Position, light;
DP3 oTexCoord0.x, STangent, LightVecObj;
DP3 oTexCoord0.y, TTangent, LightVecObj;
DP3 oTexCoord0.z, Normal, LightVecObj;
MOV oTexCoord1, TexCoord0;
MOV oTexCoord2, TexCoord0;
MOV oColor, Color;
END
PS: The funniest thing I've noticed was that on a GeForce FX 5200 this implimentation is faster than the one-pass fragment program implimentation... :-)
--------------------------------------------------------
"If it looks good, it is good computer graphics"
"If it looks like computer graphics, it is bad computer graphics"
Corrail
corrail@gmx.at
ICQ#59184081
[edited by - Corrail on August 14, 2003 6:59:18 AM]
Here my implementation of bump mapping with specular lighting using 4 texture units, maybe it might help you. (notice that only the specular power operation takes 5 passes when the shininess is 32!!)
glPushAttrib(GL_ALL_ATTRIB_BITS); ToRender->SetArrays(); TheLight->BindPosition(GL_LIGHT0); glPushAttrib(GL_ALL_ATTRIB_BITS); glPolygonOffset(1.0f, 1.0f); glEnable(GL_POLYGON_OFFSET_FILL); VP_Pass1->Bind(); glActiveTextureARB(GL_TEXTURE0); glEnable(GL_TEXTURE_CUBE_MAP); HalfMap->Bind(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glActiveTextureARB(GL_TEXTURE1); glEnable(GL_TEXTURE_CUBE_MAP); HalfMap->Bind(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); glActiveTextureARB(GL_TEXTURE2); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); for (unsigned int j = 0; j < ToRender->NumMeshes; j++) { ToRender->Meshes[j]->SetNormalMap(); ToRender->Meshes[j]->Render(); } glPopAttrib(); glDepthFunc(GL_LEQUAL); glDepthMask(GL_FALSE); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-0.01f, 0.0f); glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_VERTEX_PROGRAM_ARB); glEnable(GL_BLEND); for (unsigned int j = 0; j < ToRender->NumMeshes; j++) { glBlendFunc(GL_ZERO, GL_DST_COLOR); for (unsigned int i = 2; i <= ToRender->Meshes[j]->GetShininess(); i *= 2) { ToRender->Meshes[j]->Render(); } ToRender->Meshes[j]->SetMaterialSpecAsColor(); glBlendFunc(GL_DST_COLOR, GL_ZERO); ToRender->Meshes[j]->Render(); } glPopAttrib(); VP_Pass2->Bind(); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glPushAttrib(GL_ALL_ATTRIB_BITS); glActiveTextureARB(GL_TEXTURE0); glEnable(GL_TEXTURE_CUBE_MAP); NormCubeMap->Bind(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1); glActiveTextureARB(GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR); for (unsigned int j = 0; j < ToRender->NumMeshes; j++) { ToRender->Meshes[j]->SetMaterialDiffAsColor(); glActiveTextureARB(GL_TEXTURE1); ToRender->Meshes[j]->SetNormalMap(); glActiveTextureARB(GL_TEXTURE2); ToRender->Meshes[j]->SetBase(); ToRender->Meshes[j]->Render(); } glPopAttrib(); glBlendFunc(GL_DST_COLOR, GL_ZERO); glDisable(GL_VERTEX_PROGRAM_ARB); glPushAttrib(GL_ALL_ATTRIB_BITS); for (unsigned int j = 0; j < ToRender->NumMeshes; j++) { TheLight->BindColorAsColor(); ToRender->Meshes[j]->Render(); } glPopAttrib(); glBlendFunc(GL_ONE, GL_ONE); glPushAttrib(GL_ALL_ATTRIB_BITS); glActiveTextureARB(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR); for (unsigned int j = 0; j < ToRender->NumMeshes; j++) { ToRender->Meshes[j]->SetMaterialAmbAsColor(); ToRender->Meshes[j]->SetBase(); ToRender->Meshes[j]->Render(); } glPopAttrib();glPopAttrib();
VP_Pass1:
!!ARBvp1.0
# Vertex Program vor Diffuse & Specular Bump Mapping
# ARB2 Profile Pass 1
ATTRIB Position = vertex.position;
ATTRIB Normal = vertex.normal;
ATTRIB STangent = vertex.attrib[6];
ATTRIB TTangent = vertex.attrib[7];
ATTRIB TexCoord0 = vertex.texcoord[0];
OUTPUT oPosition = result.position;
OUTPUT oTexCoord0 = result.texcoord[0];
OUTPUT oTexCoord1 = result.texcoord[1];
OUTPUT oTexCoord2 = result.texcoord[2];
PARAM mview[] = { state.matrix.mvp };
PARAM light = state.light[0].position;
PARAM view = program.env[0];
TEMP LightVecObj; # Light Vector in Object Space
TEMP ViewVecObj; # View Vector in Object Space
TEMP H; # Half Vector
TEMP lng;
DP4 oPosition.x, mview[0], Position;
DP4 oPosition.y, mview[1], Position;
DP4 oPosition.z, mview[2], Position;
DP4 oPosition.w, mview[3], Position;
ADD LightVecObj, -Position, light;
ADD ViewVecObj, -Position, view;
DP3 lng, LightVecObj, LightVecObj;
RSQ lng, lng.x;
MUL LightVecObj, lng, LightVecObj;
DP3 lng, ViewVecObj, ViewVecObj;
RSQ lng, lng.x;
MUL ViewVecObj, lng, ViewVecObj;
ADD H, LightVecObj, ViewVecObj;
DP3 oTexCoord0.x, STangent, LightVecObj; #H;
DP3 oTexCoord0.y, TTangent, LightVecObj; #H;
DP3 oTexCoord0.z, Normal, LightVecObj; #H;
DP3 oTexCoord1.x, STangent, ViewVecObj; #H;
DP3 oTexCoord1.y, TTangent, ViewVecObj; #H;
DP3 oTexCoord1.z, Normal, ViewVecObj; #H;
MOV oTexCoord2, TexCoord0;
END
VP_Pass2:
!!ARBvp1.0
# Vertex Program vor Diffuse & Specular Bump Mapping
# ARB2 Profile Pass 2
ATTRIB Position = vertex.position;
ATTRIB Normal = vertex.normal;
ATTRIB STangent = vertex.attrib[6];
ATTRIB TTangent = vertex.attrib[7];
ATTRIB TexCoord0 = vertex.texcoord[0];
ATTRIB Color = vertex.color;
OUTPUT oPosition = result.position;
OUTPUT oTexCoord0 = result.texcoord[0];
OUTPUT oTexCoord1 = result.texcoord[1];
OUTPUT oTexCoord2 = result.texcoord[2];
OUTPUT oColor = result.color;
PARAM mview[] = { state.matrix.mvp };
PARAM light = state.light[0].position;
TEMP LightVecObj; # Light Vector in Object Space
DP4 oPosition.x, mview[0], Position;
DP4 oPosition.y, mview[1], Position;
DP4 oPosition.z, mview[2], Position;
DP4 oPosition.w, mview[3], Position;
ADD LightVecObj, -Position, light;
DP3 oTexCoord0.x, STangent, LightVecObj;
DP3 oTexCoord0.y, TTangent, LightVecObj;
DP3 oTexCoord0.z, Normal, LightVecObj;
MOV oTexCoord1, TexCoord0;
MOV oTexCoord2, TexCoord0;
MOV oColor, Color;
END
PS: The funniest thing I've noticed was that on a GeForce FX 5200 this implimentation is faster than the one-pass fragment program implimentation... :-)
--------------------------------------------------------
"If it looks good, it is good computer graphics"
"If it looks like computer graphics, it is bad computer graphics"
Corrail
corrail@gmx.at
ICQ#59184081
[edited by - Corrail on August 14, 2003 6:59:18 AM]
Real-Time Per-Pixel Point Lights and Spot Lights in OpenGL
There''s a few other, very nice, tutorials on that page.
There''s a few other, very nice, tutorials on that page.
quote:Original post by Wildfire
Real-Time Per-Pixel Point Lights and Spot Lights in OpenGL
There''s a few other, very nice, tutorials on that page.
The NV register combiners are evil. They only work with nvidia cards and they''re nowhere near as flexible as ARB_FP.
couldn''t you fake spot lights using projective texturing technique? (while rendering the geometry that is to be lit by the spot light from the cameras persepecitve)
quote:Original post by benjamin bunnyquote:Original post by Wildfire
Real-Time Per-Pixel Point Lights and Spot Lights in OpenGL
There''s a few other, very nice, tutorials on that page.
The NV register combiners are evil. They only work with nvidia cards and they''re nowhere near as flexible as ARB_FP.
So what else would you recommend using on a GF3/4?
Death of one is a tragedy, death of a million is just a statistic.
Well.... I learn VERY quick to use fragment_program and do PPL!
Were I learn? Go to humus Site and download the Phong OpenGL Example!
http://esprit.campus.luth.se/~humus/
download the vertex_program(you will not need it, but is same with fragment_program) tutorial from www.devmaster.net
download the ARB_Fragment_program pdf from ATI
also download the: Phong for dummies papper! And you are ready!
This is allo you need to start!
Were I learn? Go to humus Site and download the Phong OpenGL Example!
http://esprit.campus.luth.se/~humus/
download the vertex_program(you will not need it, but is same with fragment_program) tutorial from www.devmaster.net
download the ARB_Fragment_program pdf from ATI
also download the: Phong for dummies papper! And you are ready!
This is allo you need to start!
quote:Original post by python_regiousquote:Original post by benjamin bunnyquote:Original post by Wildfire
Real-Time Per-Pixel Point Lights and Spot Lights in OpenGL
There's a few other, very nice, tutorials on that page.
The NV register combiners are evil. They only work with nvidia cards and they're nowhere near as flexible as ARB_FP.
So what else would you recommend using on a GF3/4?
Death of one is a tragedy, death of a million is just a statistic.
GF3/4 supports nvidia's NV_VP1 and NV_FP1 extensions, which means you can write real shaders; there's no need to bother with the register combiners (which are pre-shader GF1 technology BTW).
Even better, write your shaders with Cg, and use the Cg runtime library to compile them on-the-fly, and you've got hardware independence, and porting to the OGLSL (when it's finally implemented on consumer hardware) should be easy.
[edited by - benjamin bunny on August 16, 2003 10:38:19 PM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement