Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

  • »Wümpftlbrümpftl« ist der Autor dieses Themas

Beiträge: 774

Beruf: Student

  • Private Nachricht senden

1

29.10.2006, 15:20

[HLSL] PerPixel-Directional-Specular-Lighting

Ja also wie der Title sagt, will ich einen Shader für PerPixel Richtungslicht mit Glanzpunkten schreiben ..........

Nunja .... das haut halt nich so hin .....

Das es an falschen Konstanten liegt etc kann ich auschließen. Ich bin leider nicht alzu gut in HLSL. Ohne Specular klappts bereits.
Der momentane Specularshader sieht im Programm genauso aus wie der ohne Specular.
Langer Rede kurzer Sinn: Der Shader da geht nich :cry: :

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Konstanten
float4x4   g_mComboMatrix;
float4x4   g_mWorldMatrix;
TEXTURE    g_Texture;

float3     g_DirLightDir;
float3     g_DirLightAmbient;
float3     g_CamPos;

float4     g_Diffuse;
float3     g_Emissive;
float3     g_Specular;
float1     g_Power;

// Sampler
sampler Texture_Sampler = sampler_state 
{
    texture = <g_Texture>;
};

// Vertexshader Input
struct VS_INPUT
{
    float4 Pos : POSITION;
    float3 Norm : NORMAL;
    float2 Tex0 : TEXCOORD0;
};

// Vertexshader Output
struct VS_OUTPUT
{
    float4 Pos          : POSITION;
    float2 Tex0         : TEXCOORD0;
    float1 LightIntens  : TEXCOORD1;
    float3 Normal       : TEXCOORD2;
    float3 ViewDir      : TEXCOORD3;
};

// Vertexshader
VS_OUTPUT vs_StdDirLightingSpec(VS_INPUT In)
{
    VS_OUTPUT Out;
    
    // Normalenvektor transformieren
    In.Norm = mul(In.Norm, g_mWorldMatrix);

    // Texturkoordinaten übernehmen
    Out.Tex0 = In.Tex0;
    
    // Position
    Out.Pos = mul(In.Pos, g_mComboMatrix);

    // Lichtinensität
    Out.LightIntens = dot(In.Norm, -g_DirLightDir);

    // Vektor zur Kamera
    float3 PosWorld = normalize(mul(In.Pos, g_mWorldMatrix));
    Out.ViewDir = normalize(g_CamPos - PosWorld);

    // Normalenvektor weitergeben
    Out.Normal = In.Norm;
    
    return Out;
}

// Pixelshader
float4 ps_StdDirLightingSpec(VS_OUTPUT In) : COLOR 
{
    // Textur sampeln
    float4 Texture = tex2D(Texture_Sampler, In.Tex0);
    
    // Diffuse, Ambient und Textur 
    float3 Color =  Texture.rgb * 
                   (mul(g_Diffuse.rgb, In.LightIntens) + 
                    g_DirLightAmbient);

    // Emissive hinzufügen
    Color += g_Emissive;

    // Specular hinzufügen
    float3 Reflect = normalize(2 * In.LightIntens * In.Normal - g_DirLightDir);
    Color += pow(dot(Reflect, In.ViewDir), g_Power) * g_Specular;    

    // Zurückgeben
    return float4(Color.rgb, g_Diffuse.a);
}

////////////////////////////////////
TECHNIQUE T0
{
    PASS P0
    {
        VertexShader = compile vs_1_1 vs_StdDirLightingSpec();
        PixelShader = compile ps_2_0 ps_StdDirLightingSpec();
    }
}


Danke an alle die sich meines Problems annehmen oder es zumindest versuchen :)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

29.10.2006, 15:50

ich stell mal ein paar vermutungen auf:

das ganze sieht aus wie der versuch per pixel phong lightning zu implementieren.

Quellcode

1
float3 PosWorld = normalize(mul(In.Pos, g_mWorldMatrix));


der shader wird verwendet um objekte zu rendern, die alle eine eigene weltmatrix haben.

Quellcode

1
Out.LightIntens = dot(In.Norm, -g_DirLightDir);


g_DirLightDir is die richtung AUS der das licht kommt im worldspace.
wenn das objekt über eine eigene weltmatrix verfügt, dann wärs net schlecht den normalvektor auch entsprechend nachzudrehen, also ihn in weltkoordianten umzuwandeln.

besser wärs aber evtl., nicht alle vertices in weltkoordianten umzurechnen, sondern das licht und die kamera in lokale koordinaten zu transformieren, da du ja sowieso einen draw aufruf pro objekt benötigst und die shader konstaten da ohne probleme vorher pro objekt setzen kannst, was dir ein paar (min. 7 denk ich) instructions pro vertex spart.


Zitat

Der momentane Specularshader sieht im Programm genauso aus wie der ohne Specular.


Quellcode

1
float3 Reflect = normalize(2 * In.LightIntens * In.Normal - g_DirLightDir);


möglich dass ich mich irre, aber wenn g_DirLightDir die richtung AUS der das licht kommt is, dann sollte da net - sonder + stehn!?

außerdem gibts in HLSL afaik eine reflect() funktion, und ich weis net ob es so gut is das punktprodukt interpolieren zu lassen und dann zu "recyclen" ;)

evtl. solltest du den interpolierten normalvektor im pixel shader nochmals normalisieren, weils durch das interpolieren passieren kann, dass der weiter weg von den vertices nichtmehr länge 1 hat und es dann in der mitte größerer flächen dunkler wird.

  • »Wümpftlbrümpftl« ist der Autor dieses Themas

Beiträge: 774

Beruf: Student

  • Private Nachricht senden

3

29.10.2006, 16:02

Ich dreh doch den Normalenvektor mit In.Norm = mul(In.Norm, g_mWorldMatrix); am Anfang des Vertexshaders (?).

Zitat

g_DirLightDir is die richtung AUS der das licht kommt im worldspace.

Ja das stimmt. :)

Zitat

interpolierten normalvektor im pixel shader nochmals normalisieren
Sry ich versteh nicht ganz was du meinst.

Zitat

besser wärs aber evtl., nicht alle vertices in weltkoordianten umzurechnen, sondern das licht und die kamera in lokale koordinaten zu transformieren, da du ja sowieso einen draw aufruf pro objekt benötigst.

Hmmm... Also müsste ich im voraus das Licht und Kamera mit der inversen Weltmatrix transformieren (bidde nich haun wenn ich schmarrn red)?

Zitat

möglich dass ich mich irre, aber wenn g_DirLightDir die richtung AUS der das licht kommt is, dann sollte da net - sonder + stehn!?

Hmm da könntest wohl Recht haben. Es ändert sich allerdings leider nichts wenn ich es in + umändere.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

29.10.2006, 16:12

Zitat

Ich dreh doch den Normalenvektor mit In.Norm = mul(In.Norm, g_mWorldMatrix); am Anfang des Vertexshaders (?).


sry, hab ich übersehn. aber hier musst du aufpassen, denn da es sich um einen richtungsvektor handelt musst du ihn nur mit dem 3x3 teil der matrix transformieren und im schlimmsten fall (world matrix ist nicht orthogonal) mit der inversen transponierten der worldmatrix.

warum siehe letzter beitrag hier


Zitat

Zitat

interpolierten normalvektor im pixel shader nochmals normalisieren
Sry ich versteh nicht ganz was du meinst.


du lässt den normalvektor über das dreieck interpolieren. das funzt natürlich net 100% korrekt und kann dazu führen, dass er weiter weg vom rand nicht mehr die länge 1 hat.

Zitat

Zitat

besser wärs aber evtl., nicht alle vertices in weltkoordianten umzurechnen, sondern das licht und die kamera in lokale koordinaten zu transformieren, da du ja sowieso einen draw aufruf pro objekt benötigst.

Hmmm... Also müsste ich im voraus das Licht und Kamera mit der inversen Weltmatrix transformieren (bidde nich haun wenn ich schmarrn red)?


richtig, aber auch hier gilt es wieder aufzupassen, weil die lichtrichtung ein richtungsvektor ist...

ich würds aber auf jeden fall so machen, da es sicher besser ist die CPU für jeden batch *einmal* die vektoren berechnen zu lassen, als die GPU für *jeden* vertex aufs neue...


du berechnest die lichtintensität im vertex shader und den rest im pixel shader.
was hat das für einen sinn? ich denke du willst per pixel lighting und da solltest du die lichtintensität im pixel shader mit dem interpolierten normalvektor berechnen, da du sonst im prinzip auch nix andres als stinknormales gouraud shading wie mit der ffp hast...

  • »Wümpftlbrümpftl« ist der Autor dieses Themas

Beiträge: 774

Beruf: Student

  • Private Nachricht senden

5

30.10.2006, 16:25

Ohja du hast Recht ... bisher hab ich nicht wirklcih PerPixellighting gemacht.
Also hab ich jetzt meinen normalen Beleuchtungsshader (also ohne Specularlighting) angepasst.
Allerdings ist das Ergebniss ein wenig ... seltsam. Die Würfel mit dennen ich die Beleuchng teste, haben jetzt so eine Art drehpunkt orthogonal zum Licht. Erst dachte ich, dass liegt daran einfach an den Würfeln, dessen Normalen jetzt ja "rüberinterpolitert" werden ..... bei Kugeln passiert mir allerdings das selbe:

(Link)


Und der Shader dazu:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Globale Konstanten
float4x4   g_mComboMatrix;
float3x3   g_mWorldMatrix;
TEXTURE    g_Texture;

float3     g_DirLightDir;
float3     g_DirLightAmbient;

float4     g_Diffuse;
float3     g_Emissive;


// Sampler
sampler Texture_Sampler = sampler_state 
{
    texture = <g_Texture>;
};

// Vertexdefinitionen
// Vertexshader Input
struct VS_INPUT
{
    float4 Pos : POSITION;
    float3 Norm : NORMAL;
    float2 Tex0 : TEXCOORD0;
};

// Vertexshader Output
struct VS_OUTPUT
{
    float4 Pos : POSITION;
    float2 Tex0 : TEXCOORD0;
    float3 Norm : TEXCOORD1;
};

// Vertexshader
VS_OUTPUT vs_StdDirLighting(VS_INPUT In)
{
    VS_OUTPUT Out;
    
    // Normalenvektor
    Out.Norm = mul(In.Norm, g_mWorldMatrix);

    // Texturkoordinaten übernehmen
    Out.Tex0 = In.Tex0;
    
    // Position
    Out.Pos = mul(In.Pos, g_mComboMatrix);

    return Out;

}

// Pixelshader
float4 ps_StdDirLighting(VS_OUTPUT In) : COLOR 
{
    // Normalisieren, da durch Shading böse geworden
    In.Norm = normalize(In.Norm);

    // Lichtintensität
    float1 LightIntens = dot(In.Norm, -g_DirLightDir);

    // Textur samplen
    float4 Texture = tex2D(Texture_Sampler, In.Tex0);
    
     // Diffuse, Ambient und Textur 
    float3 Color =  Texture.rgb * 
                   (mul(g_Diffuse.rgb, LightIntens) + g_DirLightAmbient);

    // Emissive hinzufügen
    Color += g_Emissive;

    return float4(Color.rgb, g_Diffuse.a+Texture.a-1.0f);
}

////////////////////////////////////
TECHNIQUE T0
{
    PASS P0
    {
        VertexShader = compile vs_1_1 vs_StdDirLighting();
        PixelShader = compile ps_2_0 ps_StdDirLighting();
    }
}


Die Geschichte mit der Normalentransformation müsste eigentlich stimmen. Bei dem Bild ist aber eh weder was gedreht noch skaliert.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

30.10.2006, 18:05

hm, check mal ob die worldmatrix richtig is und achte beim übergeben, ob du sie transponiert übergibst oder net...

aber wie gesagt, ich würd einfach das licht IN den lokalen space transformieren und mir die schweinerei mit den normalen ersparen ;)

  • »Wümpftlbrümpftl« ist der Autor dieses Themas

Beiträge: 774

Beruf: Student

  • Private Nachricht senden

7

30.10.2006, 20:21

Genau das hab ich jetzt versucht ........ Weltmatrix invertieren dann transponiern, Lichtrichtung transformieren mit der neuen und im Pixelshader für die Lichtintentistät das Punktprodukt aus relativer Lichtvektor und unveränderten Normalen bilden .........

sieht genauso wie davor aus :cry:
viel mehr hab ich das Gefühl, dass sich das Licht beim drehn des Objekts jetzt nich "mitdreht" :(

Die Weltmatrix stimmt, weil sonst würd sich das Objekt ja nich dahin bugsieren, wo ich es haben will ;)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

31.10.2006, 12:23

ich meinte eigentlich ob du die matrix im richtigen format an den shader übergibst (gibts da net sowas wie SetMatrix, SetMatrixTranspose...?)

und zum "hinbugsieren" hattest du eine andre matrix als zum transformieren der normalen verwendet ;)


zeig mal ein bisschen code wies jetzt aussieht...

  • »Wümpftlbrümpftl« ist der Autor dieses Themas

Beiträge: 774

Beruf: Student

  • Private Nachricht senden

9

01.11.2006, 16:00

Nunja .... also um den "veränderten" Lichtrichtungsvektor reinzuschieben hab ich folgendes stücklein

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
gve::Matrix mTranspInversWorld = gve::MatrixInvert(pCurEntry->Data->mTransScaleRotMatrix);
mTranspInversWorld = gve::MatrixTranspose(mTranspInversWorld);

gve::Vector3 vRelDirLightDir; // = gve::Vector3TransformNormal(vRelDirLightDir, mTranspInversWorld);

vRelDirLightDir.x = vDirLightDir.x * mTranspInversWorld.m11 + vDirLightDir.y * mTranspInversWorld.m21 + vDirLightDir.z * mTranspInversWorld.m31;
vRelDirLightDir.y = vDirLightDir.x * mTranspInversWorld.m12 + vDirLightDir.y * mTranspInversWorld.m22 + vDirLightDir.z * mTranspInversWorld.m32;
vRelDirLightDir.z = vDirLightDir.x * mTranspInversWorld.m13 + vDirLightDir.y * mTranspInversWorld.m23 + vDirLightDir.z * mTranspInversWorld.m33;
vRelDirLightDir = gve::Vector3Normalize(vRelDirLightDir);           

m_pStdDirLightingShader->GetEffect()->SetVector("g_RelDirLightDir", &D3DXVECTOR4(vRelDirLightDir.x, vRelDirLightDir.y, vRelDirLightDir.z, 1.0f));


Die Mathefunktionen die da verwendet werden sind eigentlich nur Kapslungen den passenden von D3DX.
Wenn ich allerdings die da jetzt ausgeklammert ist hernehm statt des folgenden Blocks, geht gar nichts und nichtmal ungedrehte objekte werden Beleuchtet.

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Globale Konstanten
float4x4   g_mComboMatrix;
TEXTURE    g_Texture;

float3     g_RelDirLightDir;
float3     g_DirLightAmbient;

float4     g_cDiffuse;
float3     g_cEmissive;

// Sampler
sampler Texture_Sampler = sampler_state 
{
    texture = <g_Texture>;
};

// Vertexshader Input
struct VS_INPUT
{
    float4 Pos : POSITION;
    float3 Norm : NORMAL;
    float2 Tex0 : TEXCOORD0;
};

// Vertexshader Output
struct VS_OUTPUT
{
    float4 Pos : POSITION;
    float2 Tex0 : TEXCOORD0;
    float3 Norm : TEXCOORD1;
};

// Vertexshader
VS_OUTPUT vs_StdDirLighting(VS_INPUT In)
{
    VS_OUTPUT Out;
    Out.Norm = In.Norm;
    Out.Tex0 = In.Tex0;
    Out.Pos = mul(In.Pos, g_mComboMatrix);

    return Out;

}

// Pixelshader
float4 ps_StdDirLighting(VS_OUTPUT In) : COLOR 
{
    In.Norm = normalize(In.Norm);
    float1 LightIntens = saturate(dot(In.Norm, -g_RelDirLightDir));
    float4 Texture = tex2D(Texture_Sampler, In.Tex0);
    float3 Color =  Texture.rgb * 
                   (mul(g_cDiffuse.rgb, LightIntens) + g_DirLightAmbient);
    Color += g_cEmissive;

    
    return float4(Color.rgb, g_cDiffuse.a+Texture.a-1.0f);
}

////////////////////////////////////
TECHNIQUE T0
{
    PASS P0
    {
        VertexShader = compile vs_1_1 vs_StdDirLighting();
        PixelShader = compile ps_2_0 ps_StdDirLighting();
    }
}


Naja und das ist der Shader den ich momentan dazuverwende.

  • »Wümpftlbrümpftl« ist der Autor dieses Themas

Beiträge: 774

Beruf: Student

  • Private Nachricht senden

10

05.11.2006, 18:52

Juhuuu!!
Ich hab endlich den Grund für die seltsam anmutende Beleuchtung gefunden. Es lag am Model-Exporter den ich mir für Blender geschrieben hatte. Die Normalen waren nicht gaaanz richtig. :D

Allerdings gehts immernoch nicht, wenn ich gedrehte hab .... :( :(
also ich will ja jetzt den Lichtvektor mitdrehen .... das mach ich so:

C-/C++-Quelltext

1
gve::Vector3 vRelDirLightDir = gve::Vector3TransformNormal(gve::Vector3Normalize(vDirLightDir), gve::MatrixTranspose(gve::MatrixInvert(pCurEntry->Data->mTransScaleRotMatrix)));


wie gesagt, sind die verwendeten Funktionen aus dem Namespace "gve" Kapslungen zur D3DX

Werbeanzeige