Beleuchtung mit glsl Shadern und Irrlicht

badday

Erfahrenes Mitglied
Moin zusammen,

ich beschäftige mich gerade mit Shadern und Beleuchtung, habe dabei aber einige Probleme (ich habe damit zum ersten mal etwas zu tun, daher bitte ich um Nachsicht ;) )

Ich habe hier http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21186 ein Beispiel gefunden, das ich etwas modifiziert angewendet habe, hier der relevante Code:

C++:
class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
public:

 float fLightStrength[4]; //you know I=1/r²**** i changed it to I=1/(r²/fLightStrength) for better results
    vector3df fvLightPosition[4]; //the light positions
    SColorf fvLightColor[4];
    SColorf fvAmbient;     
    float fSpecularPower;   // S=pow(fDiffuseIntensity,fSpecularPower)*fSpecularStrength;
    float fSpecularStrength;// will result in less glossing surfaces
    float fBumpStrength;    //strength of the bumpmapping.. higher values will result in more "bumpy" surfaces
    


        virtual void OnSetConstants(video::IMaterialRendererServices* services,
                        s32 userData)
        {
                video::IVideoDriver* driver = services->getVideoDriver();

                irr::s32 t[] = {0,1,2,3};

                services->setVertexShaderConstant("Texture0", (irr::f32*)&t[0], 1);
                services->setVertexShaderConstant("Texture1", (irr::f32*)&t[1], 1);
                services->setVertexShaderConstant("Texture2", (irr::f32*)&t[2], 1);
                services->setVertexShaderConstant("Texture3", (irr::f32*)&t[3], 1);

				
				int var0=0;
    services->setPixelShaderConstant("baseMap", (float*)(&var0), 1); //the colormap
    int var1=1;
    services->setPixelShaderConstant("bumpMap", (float*)(&var1), 1); //the normalmap
   
    core::matrix4 invWorld = services->getVideoDriver()->getTransform(video::ETS_WORLD);
    invWorld.makeInverse();
    services->setPixelShaderConstant("matWorldInverse", (float*)(&invWorld), 16);
   
    services->setPixelShaderConstant("fLightStrength1", (float*)(&fLightStrength[0]), 1);
    services->setPixelShaderConstant("fLightStrength2", (float*)(&fLightStrength[1]), 1);
    services->setPixelShaderConstant("fLightStrength3", (float*)(&fLightStrength[2]), 1);
    services->setPixelShaderConstant("fLightStrength4", (float*)(&fLightStrength[3]), 1);
   
    services->setPixelShaderConstant("fvLightPosition1", (float*)(&fvLightPosition[0]), 3);
    services->setPixelShaderConstant("fvLightPosition2", (float*)(&fvLightPosition[1]), 3);
    services->setPixelShaderConstant("fvLightPosition3", (float*)(&fvLightPosition[2]), 3);
    services->setPixelShaderConstant("fvLightPosition4", (float*)(&fvLightPosition[3]), 3);
   
    services->setPixelShaderConstant("fvAmbient", (float*)(&fvAmbient), 4);
    services->setPixelShaderConstant("fvLight1Color", (float*)(&fvLightColor[0]), 4);
    services->setPixelShaderConstant("fvLight2Color", (float*)(&fvLightColor[1]), 4);
    services->setPixelShaderConstant("fvLight3Color", (float*)(&fvLightColor[2]), 4);
    services->setPixelShaderConstant("fvLight4Color", (float*)(&fvLightColor[3]), 4);

    services->setPixelShaderConstant("fSpecularPower", (float*)(&fSpecularPower), 1);
    services->setPixelShaderConstant("fSpecularStrength", (float*)(&fSpecularStrength), 1);
    services->setPixelShaderConstant("fBumpStrength", (float*)(&fBumpStrength), 1); 



                irr::core::matrix4 mat = driver->getTransform(irr::video::ETS_WORLD);

                services->setVertexShaderConstant("WORLD", (irr::f32*)mat.pointer(), 16);
        }
};

irr::core::stringc vertexshader =   "varying vec4 pos;"
									"uniform vec3 fvLightPosition1;"
"uniform vec3 fvLightPosition2;"
"uniform vec3 fvLightPosition3;"
"uniform vec3 fvLightPosition4;"
""
"uniform float fLightStrength1;"
"uniform float fLightStrength2;"
"uniform float fLightStrength3;"
"uniform float fLightStrength4;"
""
"uniform mat4 matWorldInverse;"
""
"varying vec2 Texcoord;"
"varying vec3 ViewDirection;"
"varying vec3 LightDirection1;"
"varying vec3 LightDirection2;"
"varying vec3 LightDirection3;"
"varying vec3 LightDirection4;"
"varying vec4 LightDistMultiplier;"
""   
"float getLengthSQR (vec3 vec)"
"{"
"return(vec.x*vec.x+vec.y*vec.y+vec.z*vec.z);"
"}" 
""    
                                    "uniform mat4 WORLD;"
                                    "void main()"
                                    "{"
									
								""   
"   mat4 LightTransform= gl_ModelViewMatrix;"
"   LightTransform=LightTransform*matWorldInverse;"
""     
"   gl_Position = ftransform();"
"   Texcoord    = gl_MultiTexCoord0.xy;"
""   
"   vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;"
"   vec4 fvLightPos1 = LightTransform * vec4(fvLightPosition1,1.0);"
"   vec4 fvLightPos2 = LightTransform * vec4(fvLightPosition2,1.0);"
"   vec4 fvLightPos3 = LightTransform * vec4(fvLightPosition3,1.0);"
"   vec4 fvLightPos4 = LightTransform * vec4(fvLightPosition4,1.0);"
""   
"   vec3 fvViewDirection  =  - fvObjectPosition.xyz;"
""   
"   vec3 fvLightDirection1 = (fvLightPos1.xyz - fvObjectPosition.xyz);"
"   vec3 fvLightDirection2 = (fvLightPos2.xyz - fvObjectPosition.xyz);"
"   vec3 fvLightDirection3 = (fvLightPos3.xyz - fvObjectPosition.xyz);"
"   vec3 fvLightDirection4 = (fvLightPos4.xyz - fvObjectPosition.xyz);"
""   
"   LightDistMultiplier[0]=1.0/(getLengthSQR (fvLightDirection1)/(fLightStrength1*10000.0));"
"   LightDistMultiplier[1]=1.0/(getLengthSQR (fvLightDirection2)/(fLightStrength2*10000.0));"
"   LightDistMultiplier[2]=1.0/(getLengthSQR (fvLightDirection3)/(fLightStrength3*10000.0));"
"   LightDistMultiplier[3]=1.0/(getLengthSQR (fvLightDirection4)/(fLightStrength4*10000.0));"
""     
"   vec3 fvNormal         = gl_NormalMatrix * gl_Normal;"
""   
"   vec3 fvTangent   = -vec3(abs(gl_Normal.y) + abs(gl_Normal.z), abs(gl_Normal.x), 0);"
"   vec3 fvBinormal =cross(fvTangent,gl_Normal);  "
"   fvTangent=gl_NormalMatrix*cross(fvBinormal,gl_Normal);"
"   fvBinormal=gl_NormalMatrix*fvBinormal;"
""
""     
"   ViewDirection.x  = dot( fvTangent, fvViewDirection );"
"   ViewDirection.y  = dot( fvBinormal, fvViewDirection );"
"   ViewDirection.z  = dot( fvNormal, fvViewDirection );"
""   
"   LightDirection1.x  = dot( fvTangent, fvLightDirection1.xyz );"
"   LightDirection1.y  = dot( fvBinormal, fvLightDirection1.xyz );"
"   LightDirection1.z  = dot( fvNormal, fvLightDirection1.xyz );"
""   
"   LightDirection2.x  = dot( fvTangent, fvLightDirection2.xyz );"
"   LightDirection2.y  = dot( fvBinormal, fvLightDirection2.xyz );"
"   LightDirection2.z  = dot( fvNormal, fvLightDirection2.xyz );"
""   
"   LightDirection3.x  = dot( fvTangent, fvLightDirection3.xyz );"
"   LightDirection3.y  = dot( fvBinormal, fvLightDirection3.xyz );"
"   LightDirection3.z  = dot( fvNormal, fvLightDirection3.xyz );"
""   
"   LightDirection4.x  = dot( fvTangent, fvLightDirection4.xyz );"
"   LightDirection4.y  = dot( fvBinormal, fvLightDirection4.xyz );"
"   LightDirection4.z  = dot( fvNormal, fvLightDirection4.xyz );"
""    
	
                                    "   gl_TexCoord[0] = gl_MultiTexCoord0*20;"
                                    "   pos = WORLD * gl_Vertex;"
                                    "   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"
                                    "}"
                                    "";

irr::core::stringc pixelshader =   "varying vec4 pos;"
							
									"uniform vec4 fvAmbient;"
"uniform vec4 fvLight1Color;"
"uniform vec4 fvLight2Color;"
"uniform vec4 fvLight3Color;"
"uniform vec4 fvLight4Color;"

"uniform float fSpecularPower;"
"uniform float fSpecularStrength;"
"uniform float fBumpStrength;"

"uniform sampler2D baseMap;"
"uniform sampler2D bumpMap;"

"varying vec2 Texcoord;"
"varying vec3 ViewDirection;"
"varying vec3 LightDirection1;"
"varying vec3 LightDirection2;"
"varying vec3 LightDirection3;"
"varying vec3 LightDirection4;"
"varying vec4 LightDistMultiplier;" 
                                    "uniform sampler2D Texture0;"
                                    "uniform sampler2D Texture1;"
                                    "uniform sampler2D Texture2;"
                                    "uniform sampler2D Texture3;"
                                    "void main()"
                                    "{"				
								"   vec3  fvLightDirection1 = normalize( LightDirection1 );"
"   vec3  fvLightDirection2 = normalize( LightDirection2 );"
"   vec3  fvLightDirection3 = normalize( LightDirection3 );"
"   vec3  fvLightDirection4 = normalize( LightDirection4 );"
   
"   vec3  fvNormal         = texture2D( bumpMap, Texcoord ).yxz;"
"   fvNormal.xy*=2.0;"
"   fvNormal.xy-=1.0;"
   
"   fvNormal=(vec3(0.0,0.0,1.0)-fvNormal)*fBumpStrength+fvNormal;"
   
"   fvNormal=normalize(fvNormal);"
   
"   float fNDotL1           = max(dot(fvNormal, fvLightDirection1),0.0)-0.1; "
"   float fNDotL2           = max(dot(fvNormal, fvLightDirection2),0.0)-0.1; "
"   float fNDotL3           = max(dot(fvNormal, fvLightDirection3),0.0)-0.1; "
"   float fNDotL4           = max(dot(fvNormal, fvLightDirection4),0.0)-0.1; "
   
"   vec3  fvReflection1     = normalize( ( ( 2.0 * fvNormal )  ) - fvLightDirection1 ); "
"   vec3  fvReflection2     = normalize( ( ( 2.0 * fvNormal )  ) - fvLightDirection2 ); "
"   vec3  fvReflection3     = normalize( ( ( 2.0 * fvNormal )  ) - fvLightDirection3 ); "
"   vec3  fvReflection4     = normalize( ( ( 2.0 * fvNormal )  ) - fvLightDirection4 ); "
   
"   vec3  fvViewDirection  = normalize( ViewDirection );"
   
"   float fRDotV1          = max( 0.0, dot( fvReflection1, fvViewDirection ) );"
"   float fRDotV2          = max( 0.0, dot( fvReflection2, fvViewDirection ) );"
"   float fRDotV3          = max( 0.0, dot( fvReflection3, fvViewDirection ) );"
"   float fRDotV4          = max( 0.0, dot( fvReflection4, fvViewDirection ) );"
   
"   vec4  fvBaseColor      = texture2D( baseMap, Texcoord );"
   
"   vec4  fvTotalAmbient   = fvAmbient * fvBaseColor; "
   
"   vec4  fvTotalDiffuse   = fvLight1Color * fNDotL1* fvBaseColor*LightDistMultiplier[0]; "
"   vec4  fvTotalSpecular  = fNDotL1*fvLight1Color * ( pow( fRDotV1, fSpecularPower ) )*LightDistMultiplier[0];"
   
"         fvTotalDiffuse   += fvLight2Color * fNDotL2* fvBaseColor*LightDistMultiplier[1]; "
"         fvTotalSpecular  += fNDotL2*fvLight2Color * ( pow( fRDotV2, fSpecularPower ) )*LightDistMultiplier[1];  "
   
"         fvTotalDiffuse   += fvLight3Color * fNDotL3* fvBaseColor*LightDistMultiplier[2]; "
"         fvTotalSpecular  += fNDotL3*fvLight3Color * ( pow( fRDotV3, fSpecularPower ) )*LightDistMultiplier[2];  "
         
"         fvTotalDiffuse   += fvLight4Color * fNDotL4* fvBaseColor*LightDistMultiplier[3]; "
"         fvTotalSpecular  += fNDotL4*fvLight4Color * ( pow( fRDotV4, fSpecularPower ) )*LightDistMultiplier[3]; "
   
"   vec4 color=( fvTotalAmbient + fvTotalDiffuse+ (fvTotalSpecular*fSpecularStrength));"
"   if(color.r>1.0){color.gb+=color.r-1.0;}"
"   if(color.g>1.0){color.rb+=color.g-1.0;}"
"   if(color.b>1.0){color.rg+=color.b-1.0;}"

								

                                    "   vec4 col0 = texture2D(Texture0, vec2(gl_TexCoord[0]));"
                                    "   vec4 col1 = texture2D(Texture1, vec2(gl_TexCoord[0]));"
                                    "   vec4 col2 = texture2D(Texture2, vec2(gl_TexCoord[0]));"
                                    "   vec4 col3 = texture2D(Texture3, vec2(gl_TexCoord[0]));"
                                    "  if ( pos.y >= 0 && pos.y < 90)"
									"		gl_FragColor = mix(col0,col1,pos.y*0.011111f);"// Note : 0.111f = 1/90
									"	else if ( pos.y >= 90 && pos.y < 160)"
									"		gl_FragColor = mix(col1,col2,(pos.y-90)*0.014286f);"
									"	else"
									"		gl_FragColor = mix(col2,col3,(pos.y-160)/95.0f);"
									"   gl_FragColor = (gl_FragColor + (color*0.2))/1.2;" 
                                    "}"
                                    "";




//....
//....




	MyShaderCallBack *shader = new MyShaderCallBack;

	shader->fBumpStrength = 4;
	shader->fSpecularPower = 0.8;
	shader->fSpecularPower = 20;


   
   shader->fvAmbient=SColorf(0.22,0.22,0.72);
   
   shader->fLightStrength[0]=1.0;
   shader->fvLightColor[0]=SColorf(0.3,0.3,1.0);
   shader->fvLightPosition[0]=vector3df(100,-10,0);
   
   shader->fLightStrength[1]=1.0;
   shader->fvLightColor[1]=SColorf(0.4,0.4,1.0);
   shader->fvLightPosition[1]=vector3df(-100,10,0); 

    irr::s32 Shader = driver->getGPUProgrammingServices()->addHighLevelShaderMaterial(
		vertexshader.c_str(), "main", irr::video::EVST_VS_3_0,
		pixelshader.c_str(), "main", irr::video::EPST_PS_3_0,
             shader,
             irr::video::EMT_SOLID,
             0);

    terrain->setMaterialType((irr::video::E_MATERIAL_TYPE)Shader);
	

	terrain->setMaterialTexture(0, driver->getTexture(tex_1.c_str()));

    terrain->setMaterialTexture(1, driver->getTexture(tex_2.c_str()));

    terrain->setMaterialTexture(2, driver->getTexture(tex_3.c_str()));
    terrain->setMaterialTexture(3, driver->getTexture(tex_4.c_str()));


terrain->setMaterialFlag(video::EMF_LIGHTING, false);

Allerdings sieht das Resultat wie folgt aus:

black_white.png


Was ich möchte, wäre eine kühle, unwohle Stimmung mit kalten Farben. Ich frage mich, warum hier manche Stellen schwarz und weiß sind...

Die Farbmischung wird gemacht, um beim Terrain weiche Übergänge zwischen den einzelnen Texturen zu erhalten.

Später würde ich gerne die Lichtquelle dynamisch mit der Kamera positionieren, sozusagen als Scheinwerfer an der Kamera, aber zunächst einmal möchte ich eine "normale" Beleuchtung.

Bei Rückfragen, bitte fragen! :)


Vielen Dank & Gruß,

badday


EDIT: Es liegt klar an den fLight´s, nicht am Umgebungslicht. Wenn ich diese alle abschalte, dann habe ich das weiß/schwarz Problem nicht. Aber schon wenn ich auf eine Stärke von 0.01 gehe, ist es vorhanden. Ich kenne mich mit diesen Shadern leider nicht aus, aber für jemanden, der davon Ahnung hat, ist das bestimmt völlig simpel. Gerne auch mit Erklärung oder Link auf ein Tutorial ;)
Danke.
 
Zuletzt bearbeitet:
Zurück